Адаптация существующих модулей и тем под CS-Cart 4.21.1

Изменения в ядре

Предстоящие изменения требований к версии PHP

Мы планируем повысить минимальную поддерживаемую версию PHP в ближайших релизах:

  • Поддержка PHP 7 будет полностью прекращена. Минимальной поддерживаемой версией вероятнее всего станет PHP 8.0 (именно до этой версии необходимо повысить системные требования).
  • Тем не менее, мы рекомендуем уже сейчас перейти на PHP 8.3. Это последняя версия PHP, которая в настоящее время поддерживается CS-Cart (поддержка была добавлена в версии 4.19.1).
  • Одновременно с прекращением поддержки PHP 7 будет добавлена поддержка более новых версий PHP, включая PHP 8.5.
  • Мы ожидаем, что после выхода версии CS-Cart с поддержкой PHP 8.5 многие владельцы магазинов захотят обновиться до этой версии PHP. Пожалуйста, учитывайте это при планировании разработки и развертывания своих решений.

Новый опциональный интерфейс для shipping-сервисов, предоставляющих возможность выбора ПВЗ

Добавлен новый интерфейс TyghShippingsIPickupPointsService. Вы можете реализовать его в своем shipping-сервисе, если хотите привести данные ПВЗ (пунктов выдачи заказов) к единому формату, описанному в классе TyghShippingsPickupPointsDtoPickupPoint.

Раньше shipping-сервисы, которые предоставляют возможность выбора ПВЗ, должны были реализовывать интерфейс TyghShippingsIPickupService. Так как изменение его методов сломало бы уже существующие сервисы, параллельно с ним добавлен новый интерфейс.

Зачем? Возникла необходимость унифицировать данные ПВЗ, что дает возможность:

  1. Не плодить большое количество шаблонов и контроллеров под каждый сервис доставки.
  2. Отображать все ПВЗ всех способов доставки в одном списке и на одной карте.
  3. Хранить полученные ПВЗ в одной таблице кэша, а не в сессии, как было ранее в некоторых сервисах (например, СДЭК и Самовывоз). Это дает большой прирост к производительности страниц, использующих список ПВЗ, в первую очередь - страницы оформления заказа.

По этим причинам создан новый интерфейс TyghShippingsIPickupPointsService, при этом старый остался для сохранения обратной совместимости.

Как работает новый интерфейс?

  1. Он требует реализовать в shipping-сервисе метод getPickupPointsLoader(): IPickupPointsLoaderByLocation, который должен вернуть объект класса-loader вашего shipping-сервиса, реализующего интерфейс TyghShippingsPickupPointsLoaderByLocationIPickupPointsLoaderByLocation.
  2. Интерфейс IPickupPointsLoaderByLocation, в свою очередь, предполагает, что в классе-loader вашего сервиса будет метод getPickupPointsByLocation(): PickupPoint[], который обязан вернуть список ПВЗ, каждый из которых является объектом класса TyghShippingsPickupPointsDtoPickupPoint.
  3. Дальше ядро само определяет, реализует ли ваш сервис новый интерфейс и, в зависимости от этого, принимает решение по какой логике получать список ПВЗ (старой или новой).

В целом, на этом все. Вы реализовываете метод, который может вернуть список ПВЗ в унифицированном виде, таким образом далее для работы со списком и его отображения можно использовать глобальные шаблоны. Например, если в будущем будет реализована карта с пунктами выдачи всех доступных способов доставки, ваши ПВЗ также попадут на эту карту. В противном случае - нет.

Из чего состоит объект PickupPoint?

Объект класса TyghShippingsPickupPointsDtoPickupPoint состоит из базовых полей ПВЗ, необходимых для отображения (город, адрес, координаты, время работы и т.п.). Также для хранения всей информации о ПВЗ, которую предоставляет API сервиса, предусмотрено отдельное поле $shipping_extra, туда в качестве массива нужно передавать все данные целиком.

Как кэшируется список ПВЗ?

Для кэширования предусмотрена таблица shipping_pickup_points. Она содержит столбцы, соответствующие полям в классе PickupPoint. На данный момент реализовано так, что каждый сервис реализует кеширование сам в своем loader-классе.

Функции для работы с таблицами кэширования находятся в TyghShippingsPickupPointsRepository.

  1. Перед запросом в API сервиса на получение списка ПВЗ из параметров запроса формируется cache_key, который равен hash(‘sha256’, implode(‘,’, $params)). Предварительно params должны быть отсортированы.
  2. С помощью метода findFreshPickupPointsSyncStates($provider, $cache_key) проверяется, есть ли свежеполученные ПВЗ. Свежими считаются те, что получены в течение текущих суток.
  3. Если есть, то список ПВЗ получаем методом findPickupPointsByProviderAndCacheKey($provider, $cache_key).
  4. Если нет, то: * Получаем список ПВЗ из API. * Циклом каждый элемент списка приводим к объекту PickupPoint. То есть создаем объект и записываем в него сеттерами все параметры. * Полученный список объектов PickupPoint записываем в таблицу кэша методом setPickupPointsByCacheKey($pickup_points, $cache_key). * Также в таблицу текущего состояния записываем новые данные с помощью метода setPickupPointSyncState.

Новые функции

  • fn_get_storefront_theme_manifest_features - Раздел “features” файла manifest.json активной темы витрины (кэшируется в рамках запроса).
  • fn_is_storefront_theme_manifest_feature_enabled($feature) - Проверяет, включена ли булева возможность из раздела “features” файла manifest.json темы (значение свойства в JSON должно быть строго true).

Изменения в хуках

Новые хуки

  • fn_set_hook('get_pickup_points_for_checkout_pre', $cart, $pickup_points); - Выполняется перед получением списка ПВЗ для оформления заказа. Позволяет предотвратить дальнейшее выполнение кода, задав собственный список ПВЗ.
  • fn_set_hook('get_pickup_points_for_checkout_post', $cart, $pickup_points); - Выполняется после получения списка ПВЗ для оформления заказа. Позволяет изменить данные в списке ПВЗ.
  • fn_set_hook('get_checkout_pickup_points_loader_pre', $cart, $loader); - Выполняется перед получением загрузчика ПВЗ для оформления заказа. Позволяет использовать собственный загрузчик.
  • fn_set_hook('get_checkout_pickup_points_loader_post', $cart, $loader); - Выполняется после получения загрузчика ПВЗ для оформления заказа. Позволяет изменить данные загрузчика.
  • fn_set_hook('get_pickup_points_for_order_management_pre', $cart, $pickup_points); - Выполняется перед получением списка ПВЗ для управления заказом. Позволяет предотвратить дальнейшее выполнение кода, задав собственный список ПВЗ.
  • fn_set_hook('get_pickup_points_for_order_management_post', $cart, $pickup_points); - Выполняется после получения списка ПВЗ для управления заказом. Позволяет изменить данные в списке ПВЗ.
  • fn_set_hook('get_order_management_pickup_points_loader_pre', $cart, $loader); - Выполняется перед получением загрузчика ПВЗ для управления заказом. Позволяет использовать собственный загрузчик.
  • fn_set_hook('get_order_management_pickup_points_loader_post', $cart, $loader); - Выполняется после получения загрузчика ПВЗ для управления заказом. Позволяет изменить данные загрузчика.
  • fn_set_hook('get_pickup_points_for_order_pre', $order_info, $pickup_points); - Выполняется перед получением списка ПВЗ для заказа. Позволяет предотвратить дальнейшее выполнение кода, задав собственный список ПВЗ.
  • fn_set_hook('get_pickup_points_for_order_post', $order_info, $pickup_points); - Выполняется после получения списка ПВЗ для заказа. Позволяет изменить данные в списке ПВЗ.
  • fn_set_hook('get_order_pickup_points_loader_pre', $order_info, $loader); - Выполняется перед получением загрузчика ПВЗ для заказа. Позволяет использовать собственный загрузчик.
  • fn_set_hook('get_order_pickup_points_loader_post', $order_info, $loader); - Выполняется после получения загрузчика ПВЗ для заказа. Позволяет изменить данные загрузчика.
  • fn_set_hook('get_storefront_theme_manifest_features_post', $features); - Выполняется после загрузки раздела features файла manifest.json активной темы витрины.

Измененные хуки

- 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);

Измененные функции

- 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('seo_get_schema_org_organization_markup_post', $storefront, $extra, $organization); - Выполняется при формировании JSON-LD-разметки Organization Schema.org для главной страницы витрины, до ее фильтрации в вызывающем коде.
  • fn_set_hook('seo_get_schema_org_breadcrumb_list_markup_post', $breadcrumbs, $markup); - Выполняется при формировании JSON-LD-разметки BreadcrumbList Schema.org на основе хлебных крошек витрины, до ее фильтрации и вывода.

Витрина

Компонент Image Panel для размещения элементов на изображениях товаров

Новый компонент Image Panel предназначен для размещения кнопок и других элементов поверх изображения товара. По умолчанию такие кнопки отображаются в правом верхнем углу изображения товара. Используйте Image Panel, если вам необходимо добавить собственные кнопки или другие элементы управления поверх изображения товара.

Как это работает

Image Panel использует API, управляемый данными (data-driven API): вместо того чтобы вручную писать HTML для элементов поверх изображения, вы описываете их в виде элементов массива Smarty. Компонент самостоятельно отвечает за компоновку, позиционирование, сортировку и отрисовку.

  1. common/product_data.tpl перехватывает вывод Image Panel, если включен параметр show_image_panel.
  2. views/products/components/image_panel_data.tpl` формирует массив ``$image_panel_items и предоставляет шаблонный хук products:image_panel для расширений.
  3. views/products/components/image_panel_process.tpl сортирует элементы внутри каждого угла.
  4. views/products/components/image_panel.tpl выполняет отрисовку панели.

Каждый элемент размещается в одном из четырех углов:

  • top_left
  • top_right
  • bottom_left
  • bottom_right

Расширение Image Panel в модуле

Добавьте элементы в массив $image_panel_items в шаблонном хуке products:image_panel.

Пример

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}

Важно

  • После изменения массива обязательно экспортируйте его обратно в родительскую область видимости: {$image_panel_items = $image_panel_items scope=parent}.
  • Используйте уникальный ключ элемента (например, add_to_wishlist). Этот ключ используется для определения порядка отображения элемента и формирования CSS-классов.
  • Перед добавлением элемента проверяйте флаги видимости, такие как $show_wishlist_button_on_image_panel и $hide_wishlist_button.

Структура данных элемента

Добавляйте элементы в массив $image_panel_items, используя ключи, соответствующие углам. Для каждого угла используется ассоциативный массив элементов.

Общие поля

Поле Описание
type Тип элемента: button, a или div. Если поле не указано, используется a при наличии href; иначе - div.
id HTML-атрибут id.
name HTML-атрибут name.
title HTML-атрибут title.
href URL ссылки. Обрабатывается функцией fn_url.
class CSS-классы элемента.
text Текстовое содержимое элемента.
icon Имя иконки, передаваемое в шаблон common/icon.tpl.
icon_class Дополнительные CSS-классы иконки.
icon_id HTML-атрибут id иконки.
icon_title HTML-атрибут title иконки.
icon_text Текстовое содержимое иконки.
icon_data Массив дополнительных данных иконки.
ajax Если значение равно true, элементу добавляется CSS-класс cm-ajax.
full_render Если значение равно true, элементу добавляется CSS-класс cm-ajax-full-render.
element_attrs Ассоциативный массив дополнительных HTML-атрибутов элемента (rel, data-ca-target-id, и т.д.).
wrapper_attrs Ассоциативный массив HTML-атрибутов контейнера элемента.
content HTML-содержимое элемента.
insert_before_id Ключ элемента, перед которым необходимо разместить текущий элемент.
insert_after_id Ключ элемента, после которого необходимо разместить текущий элемент.
file Путь к пользовательскому шаблону. Если указан, компонент подключает этот шаблон вместо автоматической отрисовки элемента.

Отрисовка с использованием пользовательского шаблона

Если для элемента требуется нестандартная разметка, задайте параметр file и создайте шаблон, которому будут переданы переменные $item и $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>