The brick/math package (v0.10.2) was added to the core composer.json.
The floorToPrecision() and ceilToPrecision() methods were refactored to use Brick\Math\BigDecimal instead of native PHP floating-point arithmetic, fixing precision errors when rounding numbers to a given step (e.g. prices to 0.01, filter ranges to 0.1). If BigDecimal operations fail, both methods fall back to the previous native PHP implementation. Method signatures remain unchanged, but the returned values may differ in edge cases (e.g. 299.99 with precision 0.01, 11.225 with precision 0.01).
If your add-on duplicates price rounding logic using the sprintf() with round((double) $price + 0.00000000001, $decimals) workaround, consider replacing it with Tygh\Tools\Math::roundToPrecisionString().
We plan to raise the minimal supported PHP version in the releases that come after 4.21.1:
A new interface Tygh\Shippings\IPickupPointsService has been introduced. You can implement it in your shipping service if you want to normalize pickup point data into the unified format defined by the Tygh\Shippings\PickupPoints\Dto\PickupPoint class.
Previously, shipping services with pickup point selection had to implement the Tygh\Shippings\IPickupService interface. As changing its methods would break existing integrations, the new interface has been introduced alongside the old one.
We did this to standardize pickup point data and to:
For these reasons, the new Tygh\Shippings\IPickupPointsService interface was introduced, while the old interface remains available for backward compatibility.
getPickupPointsLoader(): IPickupPointsLoaderByLocation method, which should return a loader object implementing the Tygh\Shippings\PickupPoints\LoaderByLocation\IPickupPointsLoaderByLocation interface.getPickupPointsByLocation(): PickupPoint[] method. This method must return a list of pickup points, where each pickup point is represented by the Tygh\Shippings\PickupPoints\Dto\PickupPoint object.By implementing a method that returns pickup points in a standardized format, you enable the core to use shared templates for displaying and working with the pickup point list. For example, if a unified map displaying pickup points for all available shipping methods is introduced in the future, your pickup points will automatically be included.
The Tygh\Shippings\PickupPoints\Dto\PickupPoint class contains the basic fields for pickup point information required for display, such as the city, address, coordinates, business hours, and similar properties. To store all additional data returned by the shipping provider’s API, the class also includes a dedicated $shipping_extra field, to which all the data should be passed as an array.
Pickup points are cached in the shipping_pickup_points table. Its columns correspond to the fields of the PickupPoint class. At the moment, each shipping service is responsible for implementing its own caching logic within its loader class.
Functions to work with the cache tables are available in Tygh\Shippings\PickupPoints\Repository.
hash('sha256', implode(',', $params)). Before generating the hash, the params must be sorted.findFreshPickupPointsSyncStates($provider, $cache_key) to check whether fresh pickup points already exist. Pickup points are considered fresh if they were fetched on the current day.findPickupPointsByProviderAndCacheKey($provider, $cache_key) method.setPickupPointsByCacheKey($pickup_points, $cache_key) method.setPickupPointSyncState() method.Tygh\Tools\Math::roundToPrecisionString($x, $decimals) — rounds the given number to the specified number of decimal places and returns the result as a string.Tygh\Tools\Math::floorFallback($x, $precision) — floors the given number to the given precision using native PHP arithmetic (fallback implementation).Tygh\Tools\Math::ceilFallback($x, $precision) — ceils the given number to the given precision using native PHP arithmetic (fallback implementation).fn_get_storefront_theme_manifest_features — returns theme manifest “features” for the active storefront theme (cached per request).fn_is_storefront_theme_manifest_feature_enabled($feature) — checks whether a boolean feature under theme manifest.json “features” is enabled (strict JSON true).- function fn_set_storage_data($key, $data = '', $allow_empty = false)
+ function fn_set_storage_data($key, $data = '', $allow_empty = false, $expires_at = null)
fn_set_hook('apply_emails_and_documents_logo_thumbnails_pre', $logos, $width, $height, $keep_original_format); - Executes before emails and documents logo thumbnails are applied. Allows modifying the original logos list and thumbnail settings.fn_set_hook('apply_emails_and_documents_logo_thumbnails_post', $width, $height, $keep_original_format, $logos, $thumbnail_logos); - Executes after emails and documents logo thumbnails are applied. Allows modifying the original logos list and the logos list with thumbnails.fn_set_hook('apply_emails_and_documents_logo_thumbnail_to_image_pre', $image, $width, $height, $keep_original_format, $thumbnail_path); - Executes before a single emails and documents logo thumbnail is generated. Allows modifying the original image data, thumbnail settings, and thumbnail path.fn_set_hook('apply_emails_and_documents_logo_thumbnail_to_image_post', $width, $height, $keep_original_format, $thumbnail_path, $image, $thumbnail_image); - Executes after a single emails and documents logo thumbnail is generated. Allows modifying the original image data and the image data with thumbnail.fn_set_hook('get_pickup_points_for_checkout_pre', $cart, $pickup_points); — Executes before fetching pickup points for checkout. Allows preventing following script by setting your own list of pickup points.fn_set_hook('get_pickup_points_for_checkout_post', $cart, $pickup_points); — Executes after fetching pickup points for checkout. Allows changing data in pickup points list.fn_set_hook('get_checkout_pickup_points_loader_pre', $cart, $loader); — Executes before getting pickup points loader for checkout. Allows setting your own loader.fn_set_hook('get_checkout_pickup_points_loader_post', $cart, $loader); — Executes after getting pickup points loader for checkout. Allows changing loader data.fn_set_hook('get_pickup_points_for_order_management_pre', $cart, $pickup_points); — Executes before fetching pickup points for order management. Allows preventing following script by setting your own list of pickup points.fn_set_hook('get_pickup_points_for_order_management_post', $cart, $pickup_points); — Executes after fetching pickup points for order management. Allows changing data in pickup points list.fn_set_hook('get_order_management_pickup_points_loader_pre', $cart, $loader); — Executes before getting pickup points loader for order management. Allows setting your own loader.fn_set_hook('get_order_management_pickup_points_loader_post', $cart, $loader); — Executes after getting pickup points loader for order management. Allows changing loader data.fn_set_hook('get_pickup_points_for_order_pre', $order_info, $pickup_points); — Executes before fetching pickup points for order. Allows preventing following script by setting your own list of pickup points.fn_set_hook('get_pickup_points_for_order_post', $order_info, $pickup_points); — Executes after fetching pickup points for order. Allows changing data in pickup points list.fn_set_hook('get_order_pickup_points_loader_pre', $order_info, $loader); — Executes before getting pickup points loader for order. Allows setting your own loader.fn_set_hook('get_order_pickup_points_loader_post', $order_info, $loader); — Executes after getting pickup points loader for order. Allows changing loader data.fn_set_hook('pickup_points_filter_by_q_get_searchable_fields_pre', $searchable_fields); - Executes before filtering pickup points by search query in API. Allows extending the list of searchable fields.fn_set_hook('pickup_points_filter_points_by_q_post', $points, $q, $match); - Executes after filtering a flat list of pickup points by search query in API. Allows changing filtered pickup points data.fn_set_hook('pickup_points_paginate_pre', $pickup_points, $page, $items_per_page); - Executes before paginating pickup points in API. Allows reordering or filtering the list and adjusting pagination params.fn_set_hook('pickup_points_paginate_post', $pickup_points, $page, $items_per_page, $total_items, $total_pages, $items, $params); - Executes after paginating pickup points in API. Allows changing the page slice or pagination metadata.fn_set_hook('get_storefront_theme_manifest_features_post', $features); — Executes after manifest “features” are loaded for the active storefront theme.- fn_set_hook('get_store_locations_for_shipping_before_select', $destination_id, $fields, $joins, $conditions, \Tygh\Shippings\Services\StoreLocator $this);
+ fn_set_hook('get_store_locations_for_shipping_before_select', $destination_id, $fields, $joins, $conditions, \Tygh\Shippings\PickupPoints\StoreLocatorPickupPointsByLocationLoader $this);
fn_set_hook('seo_get_schema_org_organization_markup_post', $storefront, $extra, $organization); — Executes when building Organization Schema.org JSON-LD for the storefront homepage, before filtering in the caller.fn_set_hook('seo_get_schema_org_breadcrumb_list_markup_post', $breadcrumbs, $markup); — Executes when building BreadcrumbList JSON-LD from storefront breadcrumbs, before filtering and output.A new Image Panel component is available for placing buttons and other elements on top of a product image. These buttons are now displayed in the top-right corner of the product image by default. Use the Image Panel when you need to add your own buttons or controls on a product image.
Image Panel uses a data-driven API: you describe elements as items in a Smarty array instead of writing overlay HTML by hand. The component handles layout, positioning, sorting, and rendering.
common/product_data.tpl captures Image Panel output when show_image_panel is enabled.views/products/components/image_panel_data.tpl builds the $image_panel_items array and exposes the products:image_panel hook for extensions.views/products/components/image_panel_process.tpl sorts items within each corner.views/products/components/image_panel.tpl renders the panel.Each item is placed in one of four corners:
top_lefttop_rightbottom_leftbottom_rightAdd items to $image_panel_items in the products:image_panel template hook.
Example
design/themes/responsive/templates/addons/wishlist/hooks/products/image_panel.post.tpl
{strip}
{if !$hide_wishlist_button && $show_wishlist_button_on_image_panel}
{$image_panel_items.top_right.add_to_wishlist = [
type => "a",
insert_before_id => "add_to_compare",
id => "button_wishlist_`$obj_prefix``$product.product_id`",
class => "ty-btn ty-btn__tertiary ty-btn-icon ty-add-to-wish cm-submit",
title => __("add_to_wishlist"),
icon => "ty-icon-heart",
element_attrs => [
"data-ca-dispatch" => "dispatch[wishlist.add..`$product.product_id`]"
]
]}
{/if}
{$image_panel_items = $image_panel_items scope=parent}
{/strip}
Important
{$image_panel_items = $image_panel_items scope=parent}.add_to_wishlist). This key is used for ordering and CSS class generation.$show_wishlist_button_on_image_panel and $hide_wishlist_button before adding an item.Add items to $image_panel_items using corner keys. Each corner contains an associative array of items.
Common fields
| Field | Description |
|---|---|
type |
Element type: button, a, or div. If omitted, a is used when href is set; otherwise div is used. |
id |
HTML id attribute. |
name |
HTML name attribute. |
title |
HTML title attribute. |
href |
Link URL. Processed through fn_url. |
class |
CSS classes for the element. |
text |
Text content inside the element. |
icon |
Icon name passed to common/icon.tpl. |
icon_class |
Additional icon CSS classes. |
icon_id |
Icon id attribute. |
icon_title |
Icon title attribute. |
icon_text |
Icon text content. |
icon_data |
Additional icon data array. |
ajax |
When true, adds the cm-ajax class. |
full_render |
When true, adds the cm-ajax-full-render class. |
element_attrs |
Associative array of extra HTML attributes (rel, data-ca-target-id, etc.). |
wrapper_attrs |
Associative array of attributes for the item wrapper. |
content |
HTML content. |
insert_before_id |
Item key to insert this item before. |
insert_after_id |
Item key to insert this item after. |
file |
Custom template file path. When set, the component includes this file instead of rendering the item automatically. |
Custom template rendering
If an item needs non-standard markup, set the file parameter and create a template that receives $item and $item_id:
{$image_panel_items.top_left.my_addon_button = [
file => "addons/my_addon/views/products/components/my_image_panel_button.tpl"
]}
design/themes/responsive/templates/addons/my_addon/views/products/components/my_image_panel_button.tpl
{* $item and $item_id are provided by Image Panel *}
<div class="my-addon-image-panel-button">
{* custom markup *}
</div>
Questions & Feedback
Have any questions that weren't answered here? Need help with solving a problem in your online store? Want to report a bug in our software? Find out how to contact us.