Описание проблемы
OrderStatusTransitionPolicy::resolve() разбирает CSV и JSON по-разному. Для CSV есть защита от конфигурации, из которой не вышло ни одной валидной пары, — для JSON её нет. В результате JSON-значение без пригодных пар включает белый список, в котором не разрешено ничего, и смена статуса заказа перестаёт работать целиком.
Где
core/components/minishop3/src/Services/Order/OrderStatusTransitionPolicy.php
JSON-ветка возвращает MODE_ON сразу после fromPairList(), не проверяя результат:
if (str_starts_with($value, '[')) {
$decoded = json_decode($value, true);
if (!is_array($decoded)) {
return ['mode' => self::MODE_INVALID, 'edges' => []];
}
return ['mode' => self::MODE_ON, 'edges' => self::fromPairList($decoded)];
}
CSV-ветка ниже такую проверку делает:
$edges = self::fromPairList($pairs);
if ($edges === []) {
return ['mode' => self::MODE_INVALID, 'edges' => []];
}
fromPairList() молча отбрасывает пары, где $from < 1 || $to < 1, то есть нечисловые и нулевые идентификаторы.
Воспроизведение
Записать в системную настройку ms3_order_status_transitions любое из:
[]
[[0,0]]
[["a","b"]]
[[3]]
Затем попытаться сменить статус любого заказа.
Ожидается: сообщение о неверной настройке (ms3_err_status_transitions_invalid), как для битого CSV.
Фактически: MODE_ON с пустым списком рёбер. validateStatusTransition() отклоняет любой переход с сообщением ms3_err_status_transition — «переход не разрешён».
Почему это стоит починить
Сообщение уводит в сторону. Человек видит «переход запрещён» и идёт искать причину в статусах и правах, а не в системной настройке, которую правил полчаса назад. Магазин при этом стоит: ни один заказ не двигается ни в оплату, ни в отмену.
Сценарий не экзотический. В описании настройки предлагаются два формата, включая JSON, и [] — это первое, что пишет человек, желающий «обнулить» список, не стирая строку целиком. Пустая строка обрабатывается правильно (MODE_OFF), а пустой массив — нет, хотя намерение то же самое.
Предлагаемое решение
Сделать JSON-ветку симметричной CSV: если fromPairList() вернул пустой массив, возвращать MODE_INVALID.
Открытый вопрос — трактовать ли [] как «выключено» вместо «неверно». Аргумент за MODE_INVALID: пустой список переходов не может быть осмысленным намерением, а явный способ выключить проверку уже есть — пустая строка. Аргумент за MODE_OFF: намерение человека очевидно. Считаю, что первый вариант честнее — он показывает, что настройка не сработала, вместо того чтобы молча её игнорировать.
Тест: resolve() на [], [[0,0]], [["a","b"]] и [[3]] должен давать тот же режим, что resolve() на соответствующем битом CSV.
Связанное
Описание проблемы
OrderStatusTransitionPolicy::resolve()разбирает CSV и JSON по-разному. Для CSV есть защита от конфигурации, из которой не вышло ни одной валидной пары, — для JSON её нет. В результате JSON-значение без пригодных пар включает белый список, в котором не разрешено ничего, и смена статуса заказа перестаёт работать целиком.Где
core/components/minishop3/src/Services/Order/OrderStatusTransitionPolicy.phpJSON-ветка возвращает
MODE_ONсразу послеfromPairList(), не проверяя результат:CSV-ветка ниже такую проверку делает:
fromPairList()молча отбрасывает пары, где$from < 1 || $to < 1, то есть нечисловые и нулевые идентификаторы.Воспроизведение
Записать в системную настройку
ms3_order_status_transitionsлюбое из:[][[0,0]][["a","b"]][[3]]Затем попытаться сменить статус любого заказа.
Ожидается: сообщение о неверной настройке (
ms3_err_status_transitions_invalid), как для битого CSV.Фактически:
MODE_ONс пустым списком рёбер.validateStatusTransition()отклоняет любой переход с сообщениемms3_err_status_transition— «переход не разрешён».Почему это стоит починить
Сообщение уводит в сторону. Человек видит «переход запрещён» и идёт искать причину в статусах и правах, а не в системной настройке, которую правил полчаса назад. Магазин при этом стоит: ни один заказ не двигается ни в оплату, ни в отмену.
Сценарий не экзотический. В описании настройки предлагаются два формата, включая JSON, и
[]— это первое, что пишет человек, желающий «обнулить» список, не стирая строку целиком. Пустая строка обрабатывается правильно (MODE_OFF), а пустой массив — нет, хотя намерение то же самое.Предлагаемое решение
Сделать JSON-ветку симметричной CSV: если
fromPairList()вернул пустой массив, возвращатьMODE_INVALID.Открытый вопрос — трактовать ли
[]как «выключено» вместо «неверно». Аргумент заMODE_INVALID: пустой список переходов не может быть осмысленным намерением, а явный способ выключить проверку уже есть — пустая строка. Аргумент заMODE_OFF: намерение человека очевидно. Считаю, что первый вариант честнее — он показывает, что настройка не сработала, вместо того чтобы молча её игнорировать.Тест:
resolve()на[],[[0,0]],[["a","b"]]и[[3]]должен давать тот же режим, чтоresolve()на соответствующем битом CSV.Связанное