Этот файл содержит хронологическую историю всех значительных изменений в проекте.
- Текущий месяц: Апрель 2026 (ниже)
- Предыдущий месяц: Март 2026 (ниже)
- Ещё раньше: Февраль 2026, Январь 2026 (ниже)
- Архив по месяцам:
Тип релиза: PATCH (beta) — точечные исправления и восстановление контракта событий
Manager API — события жизненного цикла позиции заказа (#208, closes #207):
- Vue-админка дёргает
msOnBefore/Create/Update/Remove OrderProductчерезUtils::invokeEventпри добавлении/изменении/удалении позиций заказа — раньше события были зарегистрированы вevents.php, ноOrdersControllerих не вызывал, и сторонние подписчики (ms3PromoCode и т.п.) не срабатывали. - Before-hooks могут заблокировать операцию через
Response::error(400). After-hooks логируются на WARN-уровне с маркером(persistence already done)— ошибка плагина послеsave()/remove()не возвращается клиенту как 4xx, потому что persistence уже произошёл.
Опции товара — переключение групп больше не сбрасывает значения (#230):
ProductOptionsTab.vueрендерит все группы сразу сv-showвместоv-if-style монтирования только активной — локальныеvalue = ref(...)и hidden inputs сохраняются между переключениями вкладок.- Раньше значения, введённые в неактивной группе, терялись и не доезжали на бэкенд (MODX/ExtJS
BasicForm.getValues()собирает только инпуты, физически присутствующие в DOM на момент сабмита).
Опции товара — висячие modcategory_id после удаления категории (#228):
- Плагин
MiniShop3подписан наOnCategoryRemove— обнуляетmsOption.modcategory_idдля всех опций, ссылавшихся на удалённуюmodCategory. Зеркалит штатный паттерн MODX, гдеmodCategory::remove()сбрасываетcategoryуmodChunk/modPlugin/modSnippet/modTemplate/modTemplateVar. - Без фикса в карточке товара мог появиться второй таб «Без группы» с разными мёртвыми
modcategory_id.
OrderFinalizeService вызывал несуществующие события (#217):
msOnBeforeFinalizeOrder/msOnFinalizeOrderнигде не были зарегистрированы какmodEvent, подписать плагин через UI было нельзя. Заменены наmsOnBeforeMgrCreateOrder/msOnMgrCreateOrder— уже существовали в билдере, но никем не вызывались.
Импорт товаров — неправильный ключ system setting для дефолтного шаблона (#210):
Processors\Utilities\Import\Fields::getTvFields()использовал несуществующий ключms3_product_default_template. Корректный ключ —ms3_template_product_default(используется вcontrollers/product/create.class.php). Из-за опечатки на экране импорта блок «TV-поля» перечислял все TV вместо только привязанных к шаблону-дефолту.
Cart API — отсутствующий лексикон (#223, closes #222):
- Добавлен ключ
ms3_cart_get_successвlexicon/{ru,en}/cart.inc.php— ключ использовался вCart::get(), но без перевода MODX писал в логLanguage string not found.
ServiceRegistry — лишний debug-шум в логах (#225, closes #224):
- На штатной установке без кастомизации сервисов
loadMainConfig()/loadAddonConfigs()писали DEBUG про отсутствие дефолтных override-путей. Теперь логирование срабатывает только если оператор явно задалms3_services_config/ms3_services_addons_dirчерез system settings, а файла/папки по этому пути нет.
_build/elements/plugins.php
core/components/minishop3/elements/plugins/minishop3.php
core/components/minishop3/lexicon/en/cart.inc.php
core/components/minishop3/lexicon/ru/cart.inc.php
core/components/minishop3/src/Controllers/Api/Manager/OrdersController.php
core/components/minishop3/src/Processors/Utilities/Import/Fields.php
core/components/minishop3/src/ServiceRegistry.php
core/components/minishop3/src/Services/Order/OrderFinalizeService.php
vueManager/src/components/product/ProductOptionsTab.vue
Тип релиза: MINOR (beta) — полный перевод управления опциями с ExtJS на Vue, рефакторинг карточки заказа, self-heal миграция
Управление опциями товара полностью на Vue (#205, в т.ч. #200, #203):
Настройки → Опции— грид (DataTable), дерево категорий MODX (PrimeVue Tree) с независимыми чекбоксами и контекстным меню (обновить / развернуть / свернуть / выделить все вложенные / снять все), диалог создания-редактирования с формой и деревом категорий для привязки, редактор значений дляcombobox/comboMultiple/comboColors(drag-drop сортировка черезvuedraggable,PrimeVue ColorPickerдля цветов)Категория товара → вкладка Опции— Vue-грид привязок: drag-drop сортировка (rowReorder), inline-редактор поля «Значение по умолчанию», массовые действия (активировать / деактивировать / обязательная / необязательная / удалить), диалоги «Добавить опцию» и «Копировать опции из другой категории»Карточка товара → вкладка Опции товара— универсальный рендер всех 10 типов (textfield, numberfield, textarea, checkbox, comboBoolean, combobox, comboMultiple, comboColors, comboOptions, datefield);comboOptionsработает как чипы (PrimeVueInputChips) с автодобавлением по Enter / запятой / blur + клик-подсказки под полем из/api/mgr/options/suggestions- Per-category caption/description override в
ms3_category_options(#200): при непустом значении показывается вместо глобальногоmsOption.caption/descriptionи на витрине, и в админке; inline-редактор в гриде категории + поля в диалоге «Добавить опцию»; пакетная подгрузка без N+1 дляloadForProducts - REST API
/api/mgr/options/*и/api/mgr/categories/{id}/options/*заменил legacyProcessors/Settings/Option/*иProcessors/Category/Option/* - Декларативный schema API в
msOptionType::getSchema()— backend отдаёт декларативное описание типа вместо ExtJS JS-строк
Self-heal миграция msOrder / msOrderAddress (#201): если seed ms3_model_fields / ms3_model_field_sections частично не применился (админка показывала ms3_model_fields_empty), миграция 20260420120000_repair_order_model_fields_if_missing добавляет только отсутствующие записи — пользовательские настройки секций/ширин не затирает (update ограничен WHERE section_id IS NULL).
- Опции: удалены 7 ExtJS-файлов (
settings/option/*,category/option.*) и 22 PHP-процессора (~2600 строк устаревшего кода) - Карточка заказа — provide/inject вместо props-цепочки (#196, #204):
provide(ORDER_CONTEXT_KEY)вOrderView, composablesuseOrderFormatters,useOrderFieldHelpers,useOrderLogFormatters; вкладки получают только специфичные данные через props; безопасныйinjectдо деструктуризации OptionLoaderService::convertPreloadedValue— case-insensitive матч типов; multi-значения теперь корректно восстанавливаются при reload дляcomboMultiple,comboColors,comboOptions(раньше возвращалось только первое)- Multi-value опции товара отправляются одним hidden input с JSON-массивом + декодирование на сервере через
Utils::decodeOptionValue()— обход ограниченияExtJS BasicForm.getValues(), который читал только последний input при нескольких hidden с одинаковым name ProductTabs.vue— вкладка опций больше не монтируетExt.create('modx-vtabs')+ms3.utils.getExtField(), всё рендерится Vue-компонентомProductOptionsTabс вертикальными группами поmodcategory_id
- Удалённая опция товара снова появлялась после сохранения (#199, #202): при сохранении из полей
options-*теперь используетсяremoveOther=true— ключи, которых нет в POST (после ручного удаления или копирования), удаляются изmsProductOption. Автосинхронизация только JSON-полей по-прежнему черезsaveOptions(null)с принудительнымremoveOther=false, чтобы не повторить регрессию #153/#158. - Checkbox-опции товара
boolean/modx-combo-boolean/combo-booleanотображались узкой полоской («V|») приlabelAlign: 'top'— регрессияanchor: '25%'изms3.utils.js; старый путь удалён вместе с ExtJS UI, опции теперь рендерятся через PrimeVue - Дерево категорий в старом ExtJS-диалоге опций выводило все resource'ы и ориентировалось на
isfolder— в Vue-дереве точный фильтрclass_key = MiniShop3\\Model\\msCategoryи leaf поCOUNT(Child.id) - Множественный выбор в
comboMultiple/comboColorsв старом коде терял все значения кроме последнего при сохранении товара modcategory_idопции можно очистить (null коэрсится в 0, поле больше не обязательно)- DatePicker для
datefieldотправлял UTC-сдвиг (toISOString()давал дату на день раньше в TZ восточнее UTC) — теперь формат черезgetFullYear/getMonth/getDate
Тип релиза: MINOR (beta) — vendor extra fields, ms3_cart status sync, рефакторинг опций и заказа
Сниппет ms3_cart — синхронизация итогов со статусом (#197):
- После
msOnGetStatusCartитоги в чанке/return=dataвыравниваются со всеми числовыми полями статуса (total_cost,total_count,total_weight,total_discount,total_positions) - Синхронизация работает и на ранних выходах при пустой корзине
cost_formatted/weight_formattedсчитаются от финального$totalбез мутации$outputData- В чанк и
return=dataдобавлен ключstatus— доступ к{$status.total_cost}и т.д.
Vendor extra fields — DynamicField для формы вендора (#198):
VendorsGridзаменена ручная цепочкаv-if(3 типа) на компонентDynamicField(13+ типов полей, включая checkbox)VendorsController: загрузка xPDO map для extra fields, динамическийallowedFields,toArray()вformatVendorExtraFieldsService: созданиеmsProductFieldтолько дляmsProductData(не для msVendor и других моделей)DynamicField: поддержка FileBrowser для файловых полей,w-fullна всех инпутах,fluidна InputNumber, propidPrefixдля label/id accessibility
- Удалённая опция товара в админке снова появлялась после сохранения (#199): при сохранении из полей
options-*использовалсяremoveOther=false, из‑за чего строки вmsProductOptionдля ключей, которых больше нет в POST (после удаления опции в форме, в т.ч. после копирования товара), не удалялись — для явного массива опций из процессора теперьremoveOther=true; автосинхронизация только JSON-полей по-прежнему черезsaveOptions(null)с принудительнымremoveOther=false(#153, #158) - Manager API затирал
msOrder.propertiesданными адреса (#191):array_merge($order->toArray(), $address->toArray())перезаписывалpropertiesзаказа значениемnullизmsOrderAddress— выделенmergeAddressIntoOrderData()с исключением конфликтующих полей - В форме заказа manager UI показывались raw lexicon keys (#193):
GET /api/mgr/model-fields/visible/msOrderзагружал толькоminishop3:vue, из-за чегоcomboOptionsне переводили значения изminishop3:defaultиminishop3:manager; дополнительно исправлены order-form dropdown routes для статусов и активных доставок - Удаление клиента из грида не работало (#179): DELETE-запрос выполнялся только после подтверждения в диалоге, но сетевой запрос не отправлялся
- AuthUI.initTabSupport() сбрасывала все вкладки Bootstrap (#180): fallback без Bootstrap JS ограничен областью блока логина/регистрации, сброс
.nav-linkи.tab-paneтолько внутри своей группы - Фильтр групп опций дублировал категории (#186): dedupe список modCategory в фильтре, увеличен page size комбобокса
- Массовое назначение опций категориям (#187): исправлен bulk assign processor и логика select-all в дереве категорий
- Вкладки групп опций в карточке товара (#188): опции группируются по
modcategory_id, нормализация id, guard для пустыхoption_fields - msPayment type hints в Payment Sort процессоре (#177): заменены устаревшие type hints на msPayment
- Экран заказа — provide/inject вместо props-цепочки (#196):
provide(ORDER_CONTEXT_KEY)вOrderView, composablesuseOrderFormatters,useOrderFieldHelpers,useOrderLogFormatters; вкладки получают только данные вкладки через props; безопасныйinjectдо деструктуризации - OrderView разбит на подкомпоненты (#176): монолитный
OrderView.vueразделён наOrderInfoTab,OrderProductsTab,OrderAddressTab,OrderHistoryTab+ вынесенorderFieldsLayout.css - Опции товара: Map по
modcategory_idдля вкладок, именованный page size комбобокса подms3.grid, документирован GROUP BY - PHPStan (#174): исправлено 109 ошибок, baseline уменьшен с 277 до 168
- OptionsChips: стили вынесены из scoped в non-scoped с
.vueAppпрефиксом (фикс несовпадения Vite scoped хешей между чанками) - Prettier: форматирование 25 Vue-компонентов
lodash4.17.23 → 4.18.1vite6.4.1 → 6.4.2
Тип релиза: MINOR (beta) — Order Tabs Registry, модульные роуты аддонов, баг-фиксы
MS3OrderTabsRegistry — кастомные вкладки в окне заказа (#166, #167):
window.MS3OrderTabsRegistry.register()— регистрация Vue и ExtJS вкладок на странице заказа без правки ядра- Pre-mount очередь: плагины через
msOnManagerCustomCssJsмогут регистрировать табы до маунта Vue - Общие пропсы для плагин-табов:
orderId,order,config,isCreateMode hideOnCreate— скрытие вкладки в режиме создания заказа- Защита reserved keys (info, products, address, history), валидация конфига, snapshot очереди
- Ленивый маунт ExtJS-панелей при первом открытии вкладки, cleanup в
onBeforeUnmount - Утилита
orderPluginTab.js— валидация и нормализация конфига
Модульная регистрация роутов для аддонов — core/config/ms3.routes.d/ (#169):
- Загрузка фрагментов
*.phpизms3.routes.d/web/иms3.routes.d/manager/(алфавитный порядок) после системных и custom-файлов, доbuild(); переопределение по ключуMETHOD:PATTERN - Метод
Router::loadRoutesFromDirectory(), путьRouter::coreAddonRoutesDirectory('manager'|'web')с проверкой аргумента;api.phpиProcessors\Api\Indexгрузят web-фрагменты;Processors\Api\Router(встроенная админка) — только manager-фрагменты - Resolver создаёт каталоги при установке; примеры
example-addon.php.distв компоненте для копирования вcore/config/
- Пустая строка в decimal/int Extra Fields ломала сохранение товара (#170): пустое значение кастомного поля (например
wholesale_price) вызывало MySQL ошибкуIncorrect decimal value,save()возвращалfalseи категории/опции/ссылки молча не сохранялись — хардкод кастаprice/old_price/weightзаменён на универсальный цикл по_fieldMetaдля всехfloat,integerиbooleanполей - Чекбокс «Скрыть дочерние ресурсы» не сохранялся в категориях (#161, #160):
hide_children_in_treeне обрабатывался вhandleCheckBoxes()процессоровCategory/UpdateиCategory/Create— unchecked-состояние не передавалось в POST и значение сбрасывалось publish_documentпередавался как bool вместо int в контроллерах (#160):canPublishне приводился к(int)в массиве JS-конфига — MODX JS использует строгое сравнение=== 1, из-за чего флаг мог не срабатывать. Исправлено во всех 4 контроллерах- Кнопки «Дублировать» и «Опубликовать» не отображались в гриде товаров категории (#143, #163): миграция обновляет конфиг колонки
actionsвms3_grid_fields— добавлены действияduplicateиpublish(логика уже была в Vue-компоненте)
Тип релиза: MINOR (beta) — inline-edit, форматированные плейсхолдеры, миграция галереи на Vue, баг-фиксы
Удаление неиспользуемой настройки ms3_category_grid_fields (#145, #146):
- Удалена логика
ms3_category_grid_fields,grid_fields,option_fields,product_fieldsиз контроллераcategory/update - Удалён неиспользуемый процессор
Processors\Category\GetList - Из
Processors\Product\GetListубрана мёртвая ветка с опциями (процессор вызывается только сcombo: true)
Упрощение Product\GetList — удаление non-combo логики (#151, #152):
- Удалена non-combo ветка из
prepareArray()(actions, preview_url, cls, category_name, округление price/weight) - Удалены non-combo ветки из
prepareQueryBeforeCount()(full select, parent-фильтрация, nested products, join msCategoryMember) - Добавлена валидация
combo: trueвinitialize()
Миграция галереи товара с ExtJS на Vue (#112, #150):
- ExtJS прослойка (gallery.panel, toolbar, view, window, ext.ddview) заменена чистыми Vue-компонентами
- Новая архитектура:
ProductGallery(оркестратор) →ProductGalleryGrid(vuedraggable + ContextMenu + поиск + пагинация) +ProductGalleryToolbar(выбор source + bulk actions) +ProductGalleryEditDialog useGalleryApicomposable — все API-вызовы к Gallery процессорам через коннектор- Новый процессор
Product\UpdateSource— смена media source без сохранения всей формы GalleryUploader(Uppy) встроен вproduct-tabsбандл, отдельный entry pointgallery-uploaderудалён- Удалено 6 ExtJS-файлов (~900 строк), добавлено 5 Vue-компонентов + composable (~1300 строк)
Inline-редактирование в таблице товаров категории (#116, #134):
- Двойной клик по ячейке → редактирование прямо в таблице (text, number, boolean/checkbox)
- Настройка редактируемых полей и типа редактора в «Утилиты → Поля таблицы» для грида «Товары категории»
- Бэкенд: whitelist полей в
ProductDataService, валидация, проверка прав, корректные HTTP-коды ошибок - Поле
publishedобновляет ресурс msProduct с вызовом событийOnDocPublished/OnDocUnPublished
Форматированные плейсхолдеры валюты и веса (#144, #147):
- Системные настройки (
ms3_currency_symbol,ms3_currency_position, новаяms3_weight_unit) — единый источник истины для отображения валюты и единиц веса - Новые
*_formattedплейсхолдеры во всех сниппетах и чанках:price_formatted,cost_formatted,old_price_formatted,old_cost_formatted,weight_formatted,discount_price_formatted,discount_cost_formatted Format::weightWithUnit(),Format::getWeightUnit()— форматирование веса с единицей измерения- Лексиконы
ms3_frontend_currencyиms3_frontend_weight_unitсохранены, но core-чанки их больше не используют
Поддержка кастомных полей в валидации заказа (#135):
- Кастомные поля из правил валидации доставки (например, чекбокс
agreementс правиломrequired|accepted) сохраняются вdraft->properties['_validated']междуorder/addиorder/submit - При создании заказа кастомные поля передаются в события
msOnBeforeCreateOrder/msOnCreateOrderчерез параметрcustomFields, после чего очищаются - Чекбоксы на фронтенде отправляют состояние
input.checked('1'/'0') вместо статического атрибутаvalue
- Не удалялись опции товара в админке (#148, #149): форма отправляла
options-color[], ноsubstr($key, 8)давал ключcolor[]вместоcolor— опция не матчилась и не удалялась. Парсинг вынесен вUtils::extractOptionKey()сrtrim('[]'). Также исправлена обработка пустого массива опций вOptionSyncService - Визуальный редактор (TinyMCE) не работал в категории товаров (#156):
item_j.value = "<p></p>"выполнялся безусловно, перезатирая контент при редактировании. Блокmodx-resource-contentбыл исключён из формы,loadRichTextEditor()закомментирован — всё восстановлено - Удаление кастомных опций категорий при сохранении товара (#153, #158):
saveOptions(null, true)при автосборе только JSON-полей вызывалremoveUnusedOptionsи удалял кастомные опции категорий (proizvoditel, brend и т.п.) — приoptions=nullтеперь принудительноremoveOther=false - Пропажа пункта «создать Документ» в контекстном меню категории (#153, #158): Form Customization не всегда выставлял CSS-класс
pnew_modDocumentна узле дерева — добавлен fallback на общий классpnewдля ядровых типов ресурсов. Убран дебагconsole.log - Кнопки «Дублировать» и «Удалить» не отображались у товаров и категорий (#128, #133): MODX JS использует строгое сравнение
=== 1для permission-флагов, аjson_encode(true)даётtrueвместо1— добавлен(int)cast дляcanDuplicate,canDelete,canCreateRootв контроллерах update empty('0')в OrderFieldManager::add() (#135): значение'0'больше не считается пустым — фикс PHP-ловушкиempty('0') === true- Return type
OrderAddressManager::saveToCustomerAddresses()(#135): метод возвращалbool, но был объявлен как?msCustomerAddress— исправлен наbool save_addressпри снятии чекбокса (#135): раньше снятие чекбокса игнорировалось (значение'0'не заходило в обработчик), теперь корректно удаляет ключ из properties- Табличный префикс в relation-полях grid config (#136): при указании прямого имени таблицы (например
ms3_orders) в конфигурации связанного поля не добавлялся префикс MODX — агрегатные значения (COUNT, SUM и др.) возвращали нули - Сортировка и серверная пагинация в таблице клиентов (#137): клик по заголовку сортируемой колонки менял иконку, но данные не сортировались —
getIterator()получал параметры сортировки/пагинации как$cacheFlagвместо xPDO-запроса - Статус заказа не отображался в истории заказов клиента (#139): ad-hoc поля из LEFT JOIN (
status_name,status_color) не гидрировались в xPDO-объекты (hydrate_adhoc_fieldsвыключен по умолчанию) — заменено на предзагрузку статусов в map. Та же проблема исправлена для данных товаров в деталях заказа (pagetitle,article,old_price). Добавлен#к CSS-цветам в чанках - Некорректные URL в ЛК заказов клиента (#141): кнопка «Сбросить» фильтра и ссылки пагинации вели на корень сайта (
/?) из-за<base href>в шаблоне MODX — URL формируются server-side черезmakeUrl()+http_build_query(), пагинация сохраняет фильтр по статусу. Добавлены недостающие SVG-иконки в спрайт (icon-arrow-left,icon-truck,icon-credit-card,icon-message), исправленfill→strokeдля Feather-иконок в деталях заказа - Некорректные URL и хардкод английских сообщений в ЛК адресов (#142): кнопки «Добавить адрес», «Редактировать», «Отмена» вели на корень сайта — URL формируются server-side через
makeUrl()+http_build_query(). API-контроллерCustomerAddressControllerсодержал хардкод английских строк вместо лексиконов — все сообщения заменены на$this->modx->lexicon(), добавлено 7 ключей в ru/en лексиконы - Отсутствие ключа
descв свойствах сниппетов и источников при сборке пакета (#127): добавлена инициализацияdescпустой строкой если ключ отсутствует в определении свойства — устраняет warning/ошибку вresolver_04_sourcesиresolver_08_snippet_properties
cost_formattedвключает символ валюты (#147):cost_formattedв списке заказов ЛК теперь включает символ валюты — кастомные чанки, добавляющие валюту вручную, получат двойной символ
Тип релиза: MINOR (beta) — httpOnly cookie auth, отмена заказов, community PRs
Интеграция standalone ЛК-модулей в архитектуру ms3 (#126):
- Три standalone модуля (
order-cancel.js,customer-addresses.js,auth-forms.js) заменены на UI-классы в единой архитектуре (API → UI → hooks → message) - Новый
AuthUI— класс для форм авторизации/регистрации с хукамиbeforeLogin/afterLogin,beforeRegister/afterRegister CustomerUIрасширен: отмена заказов, управление адресами (set default, delete) с хукамиCustomerAPIрасширен: +4 метода (login,register,setDefaultAddress,cancelOrder)- 6 новых селекторов в
Selectors.jsдля ЛК-компонентов
Promise-based confirm dialog (#126):
- Новый модуль
confirm.js— Bootstrap Modal с fallback на nativeconfirm() - i18n кнопок по атрибуту
<html lang>(ru/en), переопределение черезms3Lexiconили параметры - Декларативная привязка через
data-ms3-confirmатрибут на любом элементе - Заменяет все
confirm()в ЛК: отмена заказа, удаление адреса, выход
UUID в URL заказов (#126):
- Ссылки на детали заказа используют
uuidвместо integerid— безопаснее, не раскрывает количество заказов - Валидация формата UUID из
$_GETперед запросом к БД
Отмена заказа покупателем (#119, Issue #117):
- API endpoint
POST /api/v1/customer/orders/{id}/cancelс авторизацией - Кнопка «Отменить заказ» в списке заказов и на странице деталей
- Настройка
ms3_customer_cancel_allowed_statuses— разрешённые статусы для отмены (по умолчанию: новый, оплаченный)
Запоминание активной вкладки товара (#120, Issue #111):
- При переключении вкладки ключ сохраняется в
localStorage, при перезагрузке восстанавливается - Настройка
ms3_product_remember_tabs(по умолчанию включена)
- httpOnly cookie token architecture (#124): единый httpOnly cookie
ms3_tokenвместо 4 несинхронизированных хранилищ (localStorage,$_SESSION,ms3_customer_tokens,msCustomer.token). Middleware injection ($_COOKIE→$_REQUEST) для обратной совместимости. Корзина сохраняется при логине/регистрации. - Корректное отображение кнопки «Сохранить» для товаров и категорий в MODX 3.2 (#118) — явное вычисление
canSave/lockedс учётомsave_document, компонентных permissions иcheckPolicy('save') - Формат
dataв политиках доступа для совместимости с апгрейдом MODX (#107, Issue #100) — устранено двойное JSON-кодирование при сборке пакета
- Register.php response format (#124): поле
tokenизменено с объекта{token, expires_at}на строку.expires_atвынесен на верхний уровень ответа. Кастомные темы, обращающиеся кresult.object.token.token, потребуют обновления.
Тип релиза: MINOR (beta) — селекторы, обработка ошибок, community PRs
Централизация селекторов (Issue #18):
- Новый модуль
Selectors.jsс дефолтными селекторами для всех UI-компонентов - Переопределение через
ms3Config.selectors— частичное слияние с дефолтами - UI-классы (CartUI, OrderUI, QuantityUI, CustomerUI, ProductCardUI) используют селекторы из конфига
- Миграция для добавления
Selectors.jsвms3_frontend_assets
Обработка отсутствия сервиса ms3 (Issue #68):
ServiceCheckMiddleware— проверкаhas('ms3')на уровне роутера для всех/api/v1маршрутов- Проверка
has('ms3')в точках входа (api.php, connector.php), плагине и всех сниппетах - 503 + лог вместо необработанного Exception при отсутствии сервиса
data- атрибуты как основные селекторы (Issue #17):*
data-ms3-form,data-ms3-qty,data-ms3-cart-options,data-ms3-product-cardи др.- CSS-классы сохранены как fallback для обратной совместимости
Пагинация и количество строк в гриде заказов (Issue #78):
- Выбор количества строк на странице
- Кнопки перехода в начало/конец списка
- Хеш-параметры в чанках
Устойчивость к обрыву MySQL-соединения при установке:
- Reconnect-функция в
resolver_02_migrations.php— проверка и восстановление соединения - Покрывает gap после скачивания пакетов (resolver_01, до 180s) и после выполнения Phinx-миграций
- Защищает от
MySQL server has gone awayна хостингах с короткимwait_timeout
Прочее:
- Событие
ms3:cart:updatedпри успешном оформлении заказа (#96) - Параметр
formatPricesв сниппетеmsOrderTotal - Сортировка в таблице списка заказов (Vue)
- Исправлены неточности в лексиконах (Issue #21)
- Удалён
actionиз конфигурации меню miniShop3 (#94) - Очистка EAV-опций из формы товара
- Пустой список заказов из-за лишнего
GROUP BY - Идемпотентность seed-миграций грид-конфигурации
Response::errorтеперь включает корректный HTTP-код (code) в JSON-ответCartController::change()/remove()— исправлен тип возвращаемого значения (array вместо Response)- Корректные дефолтные ID статусов заказов с fallback для нулевых значений
getIteratorдля msProduct/msCategory — добавленclass_keyв критерии
- Удалены избыточные проверки прав в
initialize()процессоров (#95) CustomerAddressController::getAuthorizedCustomer()упрощён (middleware гарантирует сервис)- Убран fallback-регистрация сервиса в
api.php— при сбое bootstrap возвращается 503
Тип релиза: MINOR (beta) — Notification Center, улучшения msOrder
Notification Center — Email уведомления:
- Email-уведомления при смене статуса заказа
- Поддержка получателей:
managerиcustomer - Настраиваемые шаблоны через чанки (поддержка
@FILEсинтаксиса) - Миграция для seed-конфигурации уведомлений
- Лексиконы для email-сообщений (ru/en)
Notification Center — Telegram уведомления:
- Telegram-уведомления для менеджеров при смене статуса заказа
- Системные настройки:
ms3_telegram_bot_token,ms3_telegram_manager_chat_id - Локализованные сообщения с информацией о заказе
- Поддержка кастомных шаблонов через чанки
Сниппет msOrder — параметр customerFields:
- Новый параметр для маппинга полей msCustomer на поля заказа
- Формат: JSON
{"order_field": "customer_field"} - Автозаполнение данных авторизованного клиента
Сниппет msOrder — выбор источника данных:
- При
ms3_customer_sync_enabled = true: данные берутся из modUserProfile - При
ms3_customer_sync_enabled = false: данные берутся из msCustomer - Исключает конфликт между двумя источниками
События для интеграции внешних пакетов:
msOnProductsLoad— bulk-загрузка данных для списка товаровmsOnProductPrepare— обогащение данных отдельного товара- Параметр
usePackagesдля активации (ms3Variants, msBrands и др.)
Страница "Помощь и поддержка":
- Переведена на Vue 3 + PrimeVue для унификации UI
- Карточки ресурсов с hover-эффектами
- Быстрые ссылки на разделы админки
Конвертация ресурса в товар:
- При смене
class_keyобычного ресурса наmsProduct:- Автоматически создаётся запись
msProductData - Товар скрывается из дерева согласно настройке
ms3_product_show_in_tree_default
- Автоматически создаётся запись
- Логика в сервисе
ProductService::handleConversion()
Централизация сервисов:
- Все 41 сервис MiniShop3 теперь в ServiceRegistry
- bootstrap.php содержит только основной
ms3сервис - Добавлен
ms3_filter_configв ServiceRegistry
Сниппет msOrder:
- Удалён мёртвый код валидации POST (валидация в OrderSubmitHandler)
- Удалены неиспользуемые CSS-классы ошибок из чанка
ms3_order.tpl
Доступ к ms3.config в Vue компонентах:
- Исправлен доступ к глобальной переменной
ms3 - Добавлена утилита
getMs3Config()вutils/modx.js
Синхронизация XML схемы и PHP моделей:
- Поле
stockв моделиmsProductData - Поле
default_valueв моделиmsExtraField - Модель
msGridFieldв XML схему
Стили вкладки Options:
- Исправлены стили компонента ProductOptions.vue
- Удалён deprecated CSS код
Очистка неиспользуемых файлов:
misc/plupload/— библиотека Pluploadmodel-fields/model-fields.wrapper.jsutilities/gallery/panel.jsproduct.grid.js— грид товаров полностью на Vuehelp.css— стили теперь в Vue компоненте- Лексиконы Plupload
- Неиспользуемые процессоры уведомлений
Эти изменения вошли в релиз 1.4.0-beta1 (07.02.2026)
Админка — Редактирование товара:
- Вложенные вкладки товара: верхний уровень (ExtJS) — Document, Товар, Page Settings, Access Permissions; вложенный уровень (Vue) — Properties, Gallery, Categories, Links, Options
- Plugin Registry API для сторонних компонентов:
window.MS3ProductTabsRegistry.register({ key, title, type, xtype/component }) - Новый компонент ProductTabs.vue с PrimeVue TabView
Кастомные поля:
- Новый тип поля «Выпадающий список» (xtype:
ms3-combo-select) для Extra Fields - UI для настройки опций в утилитах «Свои поля» (формат:
value==label) - Рендеринг PrimeVue Dropdown в форме редактирования товара
Фронтенд:
- Динамическое обновление виджета msOrderTotal при изменении корзины
- Новый чанк
tpl.msOrderTotalс дефолтной разметкой - CSS стили для виджета
.ms3-order-total
Сниппет msProducts:
- Поддержка msCategoryMember для вывода товаров из дополнительных категорий
- Собственная обработка parents (включения и исключения) как воркараунд для pdoTools
- Оптимизированный поиск дочерних категорий (только msCategory, не все ресурсы)
- События для интеграции внешних пакетов:
msOnProductsLoadиmsOnProductPrepare - Параметр
usePackages— активация загрузки данных из внешних пакетов (ms3Variants, msBrands и др.) - Bulk-загрузка дополнительных данных одним запросом (избежание проблемы N+1)
Админка — Настройки:
- Подсказки к полям названия способов доставки и оплаты (можно указать ключ лексикона)
Установка:
- VueTools добавлен в зависимости — устанавливается автоматически при отсутствии
Авторизация:
- Унифицирована авторизация в CustomerAddressController — теперь поддерживает и API-токен, и session customer_id
Миграции:
- Добавлена миграция для колонки
select_optionsв таблицеms3_extra_fields
Тип релиза: PATCH (beta) — улучшения и исправления
Админка — Vue Manager:
- Локализация PrimeVue через
@vuetools/usePrimeVueLocaleво всех Vue-приложениях (заказы, товары, клиенты, доставки, оплаты, производители, связи, статусы, уведомления, категории товаров, галерея, импорт, поля и т.д.) usePrimeVueLocaleдобавлен в vuetoolsComposables в vite.config.js- Унифицирован импорт темы Aura:
@primeuix/themes/auraво всех entry points - Добавлен
cultureKeyв мок MODx в api-test.html - Зависимость темы:
@primevue/themesзаменена на@primeuix/themes(PrimeVue 4.x)
ESLint:
- Удалён неиспользуемый параметр
mutationsв MutationObserver (entry points) - Удалён неиспользуемый параметр
prefixToIgnoreв vite.config.js (postcss-prefix-selector) - Добавлены глобальные переменные MODX (
Ext,MODx,ms3) в eslint.config.js - Откачено правило
no-unused-varsсargsIgnorePattern/varsIgnorePattern/caughtErrorsIgnorePattern— исправления через удаление неиспользуемого кода и optional catch binding
OrderView.vue:
- Согласована сигнатура
onOptionTypeChange(row)и вызов в шаблоне (удалён лишний аргументindex)
vueManager/src/entries/api-test.js
vueManager/src/entries/category-products.js
vueManager/src/entries/customers.js
vueManager/src/entries/deliveries.js
vueManager/src/entries/extra-fields.js
vueManager/src/entries/fields-management.js
vueManager/src/entries/grid-fields-config.js
vueManager/src/entries/import.js
vueManager/src/entries/links.js
vueManager/src/entries/model-fields.js
vueManager/src/entries/notifications.js
vueManager/src/entries/order.js
vueManager/src/entries/orders.js
vueManager/src/entries/payments.js
vueManager/src/entries/product-tabs.js
vueManager/src/entries/statuses.js
vueManager/src/entries/utilities-gallery.js
vueManager/src/entries/vendors.js
vueManager/vite.config.js
vueManager/api-test.html
vueManager/package.json
vueManager/eslint.config.js
vueManager/src/components/OrderView.vue
Подробная история изменений по месяцам:
Полная история: См. архивные файлы для детальной информации по предыдущим месяцам.