new

MiniShop3

Современный компонент интернет-магазина для MODX3
Бесплатно
Загрузите дополнение из админки вашего сайта.
Как загрузить?
Автор дополнения
Николай Савин
Пакетов
20
Закачек
33 504
Автор дополнения
Пакетов
20
Закачек
33 504
Версия 1.14.3-beta1
Дата выпуска 19.10.2026
Загрузки 731
Просмотры 4 530
Внимание, этот компонент требует PHP 8.2 или выше!
Внимание, этот компонент требует MODX 3 или выше.
MiniShop3 разработан специально для MODX Revolution 3.x и использует все преимущества новой версии:

  • PHP 8.2+ — современный синтаксис, типизация, атрибуты
  • Namespaces — все классы организованы в пространстве имён MiniShop3\
  • PSR-4 автозагрузка — через Composer
  • Миграции Phinx — версионирование структуры БД

Улучшенная архитектура

  • REST API — полноценный API для headless-интеграций
  • Service Container — зависимости через DI-контейнер MODX
  • Vue 3 + PrimeVue — современный интерфейс админки через VueTools
  • Современный фронтенд — без jQuery, нативный JavaScript

Совместимость

MiniShop3 сохраняет обратную совместимость с miniShop2 на уровне:

  • Имена сниппетов (msProducts, msCart, msOrder и др.)
  • Структура чанков и плейсхолдеров
  • Параметры сниппетов

Системные требования
  • MODX Revolution | 3.0.0+
  • PHP | 8.1+
  • MySQL | 5.7+ / MariaDB 10.3+

Зависимости MODX

  • pdoTools 3.x — для работы сниппетов и шаблонизатора Fenom
  • VueTools — Vue 3 и PrimeVue для административного интерфейса
  • Scheduler (опционально) — для фоновых задач (импорт, уведомления, очистка)

MiniShop3 использует Vue 3 для современного интерфейса админки. Пакет VueTools должен быть установлен до или вместе с MiniShop3. При отсутствии пакета будет показано сообщение с инструкцией по установке.

Composer библиотеки
MiniShop3 использует следующие PHP библиотеки (включены в пакет):
nikic | ^1.3 | Маршрутизация REST API
rakit/validation | ^1.4 | Валидация данных форм и API
intervention/image | ^3.0 | Обработка изображений (ресайз, водяные знаки)
robmorgan/phinx | ^0.16 | Миграции базы данных
ramsey/uuid | ^4.7 | Генерация UUID для токенов

Октябрь 2026

[2026-10-19] Версия 1.14.3-beta1

Тип релиза: PATCH (beta) — закрытие уязвимостей, найденных при аудите, и исправления расчётов.

Безопасность

Подстановка sort и dir в SQL у списка товаров (#919). Legacy-процессор Product/GetList отдавал оба параметра в ORDER BY как есть. Встроенная защита xPDO отсекает только ;, union, sleep() и benchmark(), поэтому запятая и подзапрос проходили: выражение исполнялось, и по порядку строк можно было читать произвольные таблицы базы, включая хеши паролей менеджеров. Своего права у процессора нет, так что хватало любой сессии в админке. Теперь направление сортировки принимает только ASC или DESC, имя поля берётся из фиксированного списка колонок и экранируется, а всё остальное сводится к сортировке по menuindex и в запрос не попадает.

То же в листинге «Товары категории» (#918). Неизвестное значение sort уходило в ORDER BY как msProduct.{sort}. Для эксплуатации хватало права view_document, которое есть у редактора контента. Сортировка теперь собирается только из колонок опций и связей грида, собственных полей msProductData с корректным именем и фиксированной карты встроенных колонок. Попутно починена сортировка по new, popular и favorite: эти поля лежат в данных товара, а уходили с чужим алиасом и без экранирования, из-за чего new (зарезервированное слово MySQL) ломал запрос и грид отдавал пустую страницу.

Данные товара выводились без экранирования (#920). В гриде «Товары категории» значения подставлялись в HTML-шаблон колонки и выводились через v-html, в утилите галереи так же выводилось имя медиа-источника, а штатный чанк витрины печатал название, описание, производителя и артикул без фильтра. Название товара с разметкой исполнялось в браузере — в админке это атака на пользователя с более высокими правами. Значения в гриде теперь экранируются, разметка самого шаблона колонки сохраняется; в утилите галереи HTML убран из строки лексикона, подписи выводятся обычным текстом, а ссылка на источник собирается из числового идентификатора; в чанке витрины поля проходят через |e, в том числе внутри атрибутов.

Теги покупателя исполнялись в уведомлениях Telegram и SMS (#929). Защита, добавленная для писем в 1.14.2-beta1, на эти каналы не распространялась: шаблон рендерился вместе с данными покупателя напрямую. Комментарий к заказу с [[++setting]] раскрывал системные настройки — в канале для покупателя их видел сам отправитель. Вход при этом открыт неаутентифицированному посетителю: достаточно оформить заказ. Маскировка тегов вынесена в общий TemplateTagGuard, которым теперь пользуются все каналы; для Telegram значения дополнительно экранируются под parse_mode=HTML, так что незакрытый тег в комментарии больше не ломает доставку сообщения менеджеру.

Хеш пароля и токен уходили из процессоров покупателя и пользователя (#908). Customer\GetListCombobox и System\User\GetList ограничивали набор полей только в ветке combo, а без этого параметра отдавали строку целиком. У Customer\GetList — страницы грида — фильтровать было негде вовсе, то есть хеши и токены всех покупателей уходили разом; Customer\Update возвращал полную строку через ядро, и пустое обновление работало как способ прочитать хеш пароля любого покупателя. Все пять процессоров переведены на белый список полей: колонка, добавленная в таблицу позже, в ответ не попадёт, пока её не разрешат явно. Собственные поля покупателя, зарегистрированные через «Свои поля», по-прежнему приходят. Учётные колонки вдобавок исключены из запроса, то есть не читаются из базы вовсе.

Исправлено

Доставка по весу не учитывалась при оформлении (#810). Delivery::getCost() брал вес из контроллера корзины под проверкой empty($this->ms3->cart), но у MiniShop3 свойство отдаётся через __get() без __isset(), поэтому условие всегда было истинным и вес оставался нулевым. Покупатель платил за доставку без веса, а пересчёт в админке давал другую сумму. Теперь вес считается по позициям самого заказа, как это уже делал пересчёт в менеджере. Для доставки «390 + 60 за кг» и корзины в 0,4 кг стоимость стала 414 вместо 390.

Свои поля и остаток не работали в гриде «Товары категории» (#914). Колонка, настроенная на собственное поле msProductData, оставалась пустой, а правка через таблицу терялась, хотя интерфейс показывал успешное сохранение. Чтение и запись держали независимые списки колонок, и ни один не знал про «Свои поля»; из-за расхождения списков между собой то же происходило со штатным полем stock — колонка пустая, при этом правка в неё доходила до базы. Оба списка заменены общей политикой, построенной от карты модели.

Резерв склада не сверялся при правке состава заказа (#829). Добавление, изменение количества и удаление позиции в админке не трогали журнал резерва, поэтому оплата и отмена списывали количество, которое было в заказе до правки. Теперь резерв приводится к итоговому количеству по каждому товару, остаток двигается на разницу, а при нехватке строка не сохраняется.

Ссылка «Выйти» не работала без дружественных адресов (#850). Адрес собирался как [[~[[*id]]]]?action=logout, и при выключенных ЧПУ получалось index.php?id=47?action=logout — страница открывалась с ошибкой 404. Параметр передаётся через сам тег ссылки, MODX сам ставит нужный разделитель.

Шум в логе обновления (#782). Резолвер свойств сниппетов читал их методом, который обращается к описанию параметра без проверки, и на каждом обновлении в лог уходило по предупреждению на каждый параметр — семь десятков строк, выглядящих как ошибки установки.

Важно для обновляющихся

Новое право msorder_inventory_override. Позволяет править состав заказа в обход нехватки остатка. Право создаётся при обновлении, но в политике по умолчанию не выдано: если на вашем магазине менеджеры уводили остаток в минус, выдайте его явно. Пользователям с sudo оно доступно автоматически.

Подменённый складской сервис. Если ms3_inventory заменён собственной реализацией, не поддерживающей новый интерфейс AdjustableInventoryInterface, правка заказа, который уже держит остаток, будет отклоняться. Реализуйте интерфейс либо отключите учёт остатков на время доработки.

Сортировка combo-списка товаров. Сортировка по полям данных товара (например, по артикулу) в legacy-процессоре Product/GetList сведена к сортировке по умолчанию. Combo-список отдаёт только идентификатор, название и контекст, поэтому на интерфейс это не влияет.

[2026-10-16] Версия 1.14.2-beta1

Тип релиза: PATCH (beta) — закрытие уязвимостей и блокирующей проблемы с правами.

Безопасность

Витрина могла писать служебные колонки черновика заказа (#860). POST /api/v1/order/add принимал произвольный key и писал его в черновик, если такая колонка есть у заказа или адреса. Посетитель с токеном своей корзины подставлял чужой customer_id — при оформлении он уже не перезаписывается, и заказ уезжал в чужой личный кабинет. Тем же путём открывались cost, status_id, num, token и properties. Теперь OrderFieldManager отклоняет служебные колонки на всех витринных путях записи: order/add, order/set, order/remove и ключи в data у order/submit. Поля формы (delivery_id, payment_id, order_comment, колонки адреса) и собственные колонки магазина, добавленные через дополнительные поля, писать можно по-прежнему; ключи вне моделей, как и раньше, уходят в properties['_validated'].

Там же исправлена запись в две таблицы: updateField() писал ключ и в заказ, и в адрес, если колонка есть в обеих, из-за чего свойства адреса затирались свойствами заказа — в том числе при обычном выборе сохранённого адреса.

Теги из данных покупателя исполнялись при сборке письма (#888). Тело письма собирается Fenom-чанком вместе с полями заказа, а затем прогонялось через разбор тегов. При установленном pdoTools $modx->getParser() — это Fenom, а не разбор MODX-тегов, поэтому из комментария покупателя исполнялись и [[++setting]], и {$_modx->runSnippet(...)}: в Fenom pdoTools через $_modx доступны runSnippet() и runProcessor(). Второй путь — тема письма: данные подставлялись в строку темы до компиляции, и тема вида Заказ {num}: {order_comment} исполняла код из комментария.

Теперь данные уходят в рендер с подменёнными открывающими последовательностями тегов и возвращаются к исходному виду уже после разбора. Свои чанки писем работают как раньше — в самом шаблоне по-прежнему доступны и Fenom, и MODX-настройки, лексикон, кэшируемые и некэшируемые сниппеты. Поля покупателя в штатных чанках писем выводятся экранированными: скрипты в письме не исполняются, но ссылка и картинка работают, то есть покупатель мог подсунуть менеджеру ссылку или трекинг-пиксель.

Шаблон письма видел секреты заказа, покупателя и доставки (#889). В плейсхолдеры уведомления уходил полный toArray(): token заказа (тот же, которым витрина правит черновик и которым покупатель авторизует запросы к Web API), password и token покупателя, properties способа доставки с ключами интеграций. Оплату в том же методе уже резал PaymentPublicFields. Теперь заказ отдаётся без token и idempotency_key, покупатель — через CustomerPublicDto (дополнительные поля проходят, поэтому telegram_chat_id работает), доставка — через новый DeliveryPublicFields. Получатель уведомления, который уходит в плагины и шаблоны каналов, тоже отдаётся публичным набором.

Хеш пароля и токен покупателя уходили в чанки кабинета (#840, #848). Страницы профиля, заказов и адресов вызывали сырой $this->customer->toArray(), поэтому в чанки Fenom попадали bcrypt-хеш пароля, активный API-токен, IP согласия с политикой и счётчики попыток входа. Из массива заказа чанкам отдавались token и idempotency_key. Все страницы кабинета переведены на CustomerPublicDto.

Кабинет отдавал ключи интеграций способа доставки (#889). Страница заказа в кабинете продолжала класть в шаблон полный массив доставки — с properties, class и validation_rules, хотя оплату рядом уже резал PaymentPublicFields. Теперь и доставка идёт через публичный набор. Штатный чанк печатает только название и описание, поэтому вид страницы не меняется.

id склеивался с SQL в combo-списках покупателя и пользователя (#882). Customer\GetListCombobox и System\User\GetList ставят выбранную строку первой через ORDER BY FIELD(id, …) и собирали выражение строкой, подставляя параметр запроса как есть. Вход — пользователь с доступом в админку. Значение теперь нормализуется в список положительных целых; мусор отбрасывается целиком, и при пустом списке сортировка просто не добавляется.

Исправлено

Администратор без sudo не мог сохранить товар или категорию (#893). Права компонента лежали только в политике miniShopManagerPolicy, а она не была назначена ни одной группе, поэтому любой администратор без sudo упирался в «Access denied. Required permission: msproduct_save». Первый администратор сайта проблемы не видел: sudo обходит проверки. В miniShop2 это делал resolve.policy.php, при переносе в MiniShop3 часть потерялась.

Установка и обновление теперь выдают политику магазина всем группам, у которых уже есть доступ к контексту mgr, добавочной записью с authority 9999 — чужие политики не меняются, активным сессиям права перечитываются без перелогина. Важно: группа, созданная после установки, политику не получит — ей нужно выдать её вручную или повторить обновление пакета.

Изменено

Листинг товаров категории в админке снова постраничный (#473). Проверка прав уровня документа, добавленная в #473, заменила прямые LIMIT/OFFSET сканированием: политику можно проверить только по загруженному объекту, поэтому на каждый запрос страницы вычитывалась вся категория — для подсчёта всегда, плюс от начала до смещения для самой страницы. На категории с 2114 товарами это 18 запросов и 953 мс на первой странице и 33 запроса с 1350 мс на дальних.

Видимость ресурса ограничивает только группа ресурсов с записью доступа, поэтому, когда таких записей нет (или выключена access_resource_group_enabled, или пользователь sudo), построчная проверка заведомо никого не отбрасывает — и страницу снова отдают один SELECT с LIMIT и один COUNT. На той же категории это 1 запрос и 24–31 мс, причём время больше не растёт с номером страницы. Если группы ресурсов настроены, сохраняется прежнее поведение: права важнее скорости.

Важно для обновляющихся

Токен покупателя по умолчанию живёт сутки, а не неделю (#848). В настройках пакета ms3_customer_token_ttl всегда был 86400, но при отсутствии настройки в базе код подставлял 604800. Теперь фолбэк совпадает с настройкой. На сайтах, где настройки в базе нет, покупатели станут входить заново через сутки, а не через семь дней.

Витрина больше не может писать служебные колонки заказа (#860). Если собственный фронт выставлял через order/add поля вроде delivery_cost, он получит ошибку — именно через это посетитель мог обнулить себе доставку. Стоимость доставки считают DeliveryService и OrderCostCalculator.

Из плейсхолдеров письма и чанков кабинета ушли поля (#889, #840). Шаблоны, которые печатали {$customer.password}, {$order.token} или {$delivery.properties}, получат пустое значение. У способа доставки в письме и кабинете остались id, name, description, price и logo — если шаблон использовал weight_price, distance_price или free_delivery_amount, их нужно получать иначе.

Utils::sendEmail() больше не разбирает теги в переданном теле (#888). Метод получает тело уже собранным, а прогон разбора по нему исполнял теги из данных покупателя. Внутри компонента метод не используется; дополнения, которые передавали в него тело с MODX-тегами, должны разбирать его сами — до того, как в строке появится чужой текст.


Сентябрь 2026

[2026-09-25] Версия 1.14.1-beta2

Тип релиза: PATCH (beta) — ускорение установки и обновления.

Изменено

Файлы компонента больше не архивируются при установке (#783). core и assets переехали в собственные vehicle, и .preserved.zip при обновлении больше не создаётся — раньше на каждое обновление зиповалось 4248 файлов установленного компонента. Обновление ускорилось с 3,1 до 2,2 секунды на прогретом кэше файловой системы; на медленных дисках выигрыш заметно больше, и именно там архивация упирала установку в таймаут веб-сервера.

Плата за это — режим «Восстановить» при деинсталляции больше не откатывает файлы MiniShop3: архива нет, восстанавливать нечего, поэтому объекты категории вернутся к прежней версии, а файлы будут удалены. Режимы «Сохранение» (по умолчанию) и «Деинсталлировать» работают как прежде — они и раньше удаляли файлы. Полным откат всё равно не был: Phinx-миграции не откатываются.


[2026-09-24] Версия 1.14.1-beta1

Тип релиза: PATCH (beta) — экстренный фикс: 1.14.0-beta1 не устанавливался поверх предыдущих версий.

Исправлено

Обновление падало с Class "ComposerAutoloaderInit…" not found (#779). bootstrap.php подключает vendor/autoload.php на каждом запросе MODX, поэтому при обновлении в памяти уже лежит composer/autoload_real.php предыдущей версии. Транспорт распаковывает новый vendor/ поверх, резолвер миграций делает require vendor/autoload.php, но его require_once на неизменившийся путь composer/autoload_real.php — no-op, и вызов уходит в необъявленный класс. Composer выводит имя этого класса из состава пакетов, а в 1.14.0-beta1 состав изменился (в require-dev добавился modxkit/testbench), поэтому старое имя перестало совпадать с новым. Теперь ms3PhinxEnsureAutoloaderInit() вычитывает имя класса из нового autoload.php и, если оно не объявлено, требует composer/autoload_real.php напрямую, в обход кэша require_once. Обновление проходит с любой прошлой версии.

Имя класса автолоадера закреплено (#779). В composer.json добавлен config.autoloader-suffix: "MiniShop3" — суффикс больше не зависит от состава пакетов, поэтому такой рассинхрон не повторится на будущих обновлениях.

Сборка больше не пакует dev-зависимости (#779). _build/vendor_guard.php проверяет vendor/composer/installed.json и отказывается собирать транспортный пакет, пока в vendor/ лежат пакеты из require-dev. В 1.14.0-beta1 в пакет уехали PHPUnit, PHPStan и testbench — 45 МБ вместо примерно семи.


[2026-09-23] Версия 1.14.0-beta1

Тип релиза: MINOR (beta) — коммерческий жизненный цикл заказа: складской учёт, попытки оплаты и отгрузки, доменные события с исходящими вебхуками; ACL групп ресурсов на всей витрине; закалка сортировки в msProducts.

Добавлено

Складской учёт, выключенный по умолчанию (#589, #603, #763). При включённой настройке ms3_inventory_enabled остаток резервируется на статусе «Новый», фиксируется на «Оплачен» и освобождается на «Отменён», если заказ ещё не был оплачен. Журнал резервов лежит в ms3_inventory_reservations, переходы состояния атомарны (условный UPDATE ... WHERE state = ...), так что параллельные запросы не спишут остаток дважды. Доступность проверяется до выдачи номера заказа. Шесть событий msOnBeforeInventoryReserve / msOnInventoryReserve / Commit / Release позволяют подключить внешнюю систему; события выпускаются только после фиксации транзакции, поэтому подписчик не получит уведомление о резерве, которого нет в базе. NULL в stock считается нулём — перед включением заполните остатки. Внешний склад подключается подменой сервиса ms3_inventory.

Жизненный цикл оплаты (#590, #604, #626). Появились таблицы ms3_payment_attempts и ms3_payment_attempt_events, публичный эндпойнт POST /api/v1/payment/webhook/{payment_method_id} и защита от повторной обработки: уникальный provider_event_id не даст применить один и тот же вебхук дважды. Платёжный шлюз подключается через PaymentWebhookHandlerInterface — проверка подписи и разбор тела остаются на стороне дополнения.

Жизненный цикл отгрузки (#591, #605, #606, #607). Таблицы ms3_shipments и ms3_shipment_events, вебхук службы доставки, трек-номера и синхронизация со статусом заказа. В менеджере — GET|PUT /orders/{id}/shipment, в витрине — плейсхолдер {$shipments} у msGetOrder. Выключено по умолчанию (ms3_shipment_enabled).

Управляемая смена статуса заказа (#592, #596). Переходы проверяются по правилам final / fixed и необязательному списку ms3_order_status_transitions. Доменные шаги, которые могут запретить переход, выполняются внутри одной транзакции со сменой status_id; после фиксации компенсирующих записей нет. ensure() идемпотентен и безопасен при гонке двух параллельных вызовов. Ошибка плагина на msOnChangeOrderStatus возвращается вызывающему, но статус не откатывает.

Доменные события и контракт исходящих вебхуков (#593, #764, #772, #774). Ядро собирает событие order.status_changed, в полезной нагрузке только идентификаторы и суммы — персональные данные покупателя наружу не уходят. Подпись — HMAC-SHA256 по строке {timestamp}.{rawBody}, заголовки X-MS3-Signature и X-MS3-Timestamp, окно 300 секунд. По умолчанию стоит NullWebhookDispatcher, то есть без дополнения наружу ничего не отправляется. Дополнение подключает HTTP-доставку подменой ms3_webhook_dispatcher, а внутренних слушателей регистрирует через $modx->services->get('ms3_domain_events')->addListener(...).

ACL групп ресурсов на всей витрине (#659, #666, #677, #681, #757). Публичный каталог, Fenom-сниппеты и корзина учитывают группы ресурсов MODX. Залогиненный покупатель, чья группа клиентов привязана к группе пользователей MODX, видит member-каталог — для этого появилась модель msCustomerGroup и CRUD в менеджере. Для member-запросов текущему ресурсу проставляется cacheable = 0, поэтому на кэшируемых страницах вызывайте сниппеты некэшированно: [[!msProducts]].

Публичный Web API (#578, #580, #586, #597, #598, #644). Category API (list / get / tree), расширенные фильтры product/list, фасеты product/filters, публичные delivery/list и payment/list, галерея товара product/{id}/images, резолв каталога по alias или uri.

SEO-блок публичного каталога (#599, #715). title, description, canonical, robots и Open Graph; карта TV через ms3_public_seo_tv_map; robots выводится из поля searchable; правки через событие msOnGetPublicSeo.

Текстовый водяной знак в превью Media Source (#731, #769) рядом с уже существующим наложением картинки. Путь к шрифту ограничен корнем сайта, ошибки пишутся в журнал, превью создаётся в любом случае.

Индивидуальный порядок товаров в дополнительных категориях (#625, #627) — и в гриде менеджера, и при сортировке по menuindex в msProducts.

Живые тесты на настоящем MODX (#687, #698, #699, #712) через modxkit/testbench на версиях 3.1.2-pl, 3.2.3-pl и 3.2.4-pl: схема поднимается из Phinx-миграций, проверяются права процессоров.

Изменено

Vue-менеджер выглядит как MODX 3 (#621, #702, #738, #760, #761, #765, #768). Тема берётся из VueTools через getActiveTheme(): по умолчанию Aura, vuetools.theme=modx переключает на вид менеджера. Высоты кнопок, полей и списков в тулбарах выровнены, размеры кнопок приведены к единому виду по всем экранам; кнопки действий внутри строк таблиц остались компактными, чтобы гриды не раздувались.

msProducts проверяет строковый sortby по белому списку (#741, #742, #757). Поля ресурса и товара получают префикс таблицы, объявленные TV, поля производителя и ключи sortbyOptions проходят как есть, функции RAND(), FIELD(), IFNULL(), COALESCE() и CAST() разрешены с проверенными аргументами. Остальное отбрасывается и пишется в журнал. Это закрывает передачу произвольного SQL в ORDER BY через параметр сниппета.

Неуспешная оплата больше не отменяет заказ по умолчанию (#754, #756). Настройка ms3_payment_on_failed_status теперь по умолчанию 0, поэтому покупатель может повторить оплату без ошибки 409. При включённом складском учёте резерв остаётся за заказом до отмены — чтобы остаток освобождался автоматически, укажите в настройке статус отмены.

Уведомления отправляются даже при ошибке плагина на msOnChangeOrderStatus (#754, #756) — статус уже зафиксирован, и покупатель не должен оставаться без письма из-за сбоя интеграции.

Обновление пакета убирает устаревшие файлы (#690, #709, #726, #728) из core и assets, не трогая то, что перечислено в ms3_frontend_assets; миграции всегда выполняются на собственном Phinx MiniShop3, а не на копии из другого дополнения.

CORS-preflight обрабатывается до стека middleware (#637, #708, #725, #727) — без обращения к сессии MODX и без порчи кэша.

Исправлено

  • Блокировки покупателей (#734, #747, #748). Временная блокировка по числу неудачных попыток больше не мешает восстановить пароль, перманентная отзывает токены, счётчик сбрасывается после истечения блокировки.
  • Молчаливые ошибки записи попыток оплаты (#752, #753). На соединении MODX (ERRMODE_SILENT) неудачные запросы возвращали false и терялись; теперь дубли распознаются честно, а сбой поднимает исключение.
  • Расхождение статуса заказа с отгрузкой (#754, #756). Повторный вебхук долечивает статус, не переэмитируя события.
  • Пустые подсказки значений опций в менеджере (#745, #746).
  • Битый UTF-8 в ответах коннектора (#618, #662, #676, #691) — больше не отдаётся ни повреждённый JSON, ни пустое тело.
  • Права на сортировку галереи и товаров (#614, #661, #675) проверяются по msproductfile_save и msproduct_save, ACL полей заказа следует miniShopManagerPolicy.
  • Кэш фасетов и страниц (#735) сбрасывается при изменении ACL групп ресурсов, членства и привязки группы клиентов.
  • Опции в корзине (#633, #638) принимаются в виде JSON-строки в cart/add и cart/change-option.
  • Английские вкладки товара при русском менеджере (#758, #759, #767, #771). Отравленный кэш лексикона лечится один раз после установки или обновления.
  • Сортировка по опциям и полям производителя (#776). Ключ sortbyOptions, совпадающий с именем колонки (weight, color, size), больше не ломает запрос; sortby=vendor_name работает при дефолтных параметрах вызова.

Примечание

Документация по складскому учёту, отгрузкам и попыткам оплаты в docs.modx.pro пока отсутствует — выйдет отдельным обновлением.

Последние обсуждения в сообществе MODX.pro