Skip to content

[Bug] JSON-значение без валидных пар включает белый список переходов, где запрещено всё #786

Description

@biz87

Описание проблемы

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.

Связанное

Activity

  1. self-assigned this
    on Sep 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions