Сбрасываются настройки модуля для витрин при обновлении модуля в "опасном" режиме(cscart ultimate 4.13.2 - 4.14.1.sp1)

Давно мучал баг со сбросом настроек у модулей при их обновлении, наконец появилось время разобраться. Итак начиная с cscart 4.13.2 в app\Tygh\Settings.php(updateValueById) появился такой вот код

if ($this->isRootMode() && $storefront_id) {
    $this->db->query('DELETE FROM ?:settings_vendor_values WHERE object_id = ?i AND storefront_id = ?i', $object_id, $storefront_id);
}

В итоге при обновлении настроек модуля для витрин насколько я понимаю происходит следующее

//Обновляем настройки в settings_vendor_values
$this->db->replaceInto($table, $data);
// Маназин в рут режиме и обновляются настройки например storefront_id 2
// В итоге тут мы удаляем только что обновленные настройки
if ($this->isRootMode() && $storefront_id) {
$this->db->query(‘DELETE FROM ?:settings_vendor_values WHERE object_id = ?i AND storefront_id = ?i’, $object_id, $storefront_id);
}

2 лайка

Кажется, что Вы правы. Хотел спросить почему вы создали рут инстанс изначально :slight_smile:
Потом понял, что это код из ядра :wink:

Добрый день! Спасибо вам за обращение и приношу извинения за задержку.

Пожалуйста опишите поэтапно как вы воспроизвели данную проблему. Скриншоты будут крайне полезны. Так же рекомендую попробовать воспроизвести данную проблему на нашем демо: https://dev.demo.mv.cs-cart.com/ Заранее спасибо.

С Уважением, Серж
Специалист поддержки CS-Cart

Сделал видео чтобы было понятно. Если пошагово то:

  • Настраиваем модуль под разные витрины
  • Обновляем модуль
  • Вместо настроек что были у витрин, получаем настройки что были по умолчанию(заданы для всех витрин изначально)

bandicam 2022-04-12 14-42-46-525.zip (2,5 МБ)

1 лайк

Благодарю вас за данную информацию и видео!

Я изучил ваше видео, шаги воспроизведения и связался с нашими разработчиками. Они подтвердили, что данное поведение является нормальным. Так же они указали, что удаление настроек производится следующей функцией:

function fn_update_addon_settings($addon_scheme, $execute_functions = true, $values = array(), $vendor_values = array())
{
$section = Settings::instance()->getSectionByName($addon_scheme->getId(), Settings::ADDON_SECTION);

if (isset($section['section_id'])) {
    Settings::instance()->removeSection($section['section_id']); //вот тут
}

В случае если данный принцип работы приносит трудности в ваш рабочий процесс, я рекомендую вам обратиться в нашу службу тех. поддержки Helpdesk. Мои коллеги изучат вашу ситуацию и, в случае необходимости, либо предложат вам решение, либо сформируют запрос разработчикам о добавлении данной функциональности на основании вашего запроса.

С Уважением, Серж
Специалист поддержки CS-Cart

Я конечно извиняюсь, но ваши разработчики не вникли в суть проблемы. У себя каждый раз исправляю, но все же хотелось бы чтобы было исправлено в ядре. Итак:

  1. Действительно за обновление настроек отвечает fn_update_addon_settings в которую в качестве четвертого аргумента передается $vendor_values
  2. Далее для обновления настроек витрин страбатывает вот этот код
                    if (
                        !empty($vendor_values[$setting['id']])
                        && Settings::instance()->areOverriddenValuesSupportedByEdition($setting['edition_type'])
                    ) {
                        foreach ($vendor_values[$setting['id']] as $company_id => $vendor_setting_value) {
                            if ($setting_value != $vendor_setting_value) {
                                Settings::instance()->updateValueById($setting_id, $vendor_setting_value, $company_id, $execute_functions);
                            }
                        }
                    }

В итоге мы переходим к Settings::instance()->updateValueById(), где и доходим до изначально указанного мной кода

$this->db->replaceInto($table, $data);

if ($this->isRootMode() && $storefront_id) {
    $this->db->query('DELETE FROM ?:settings_vendor_values WHERE object_id = ?i AND storefront_id = ?i', $object_id, $storefront_id);
}

Теперь смотрим скриншот дебаггера

И видим что срабатывает
Записываем в таблицу settings_vendor_values правильные настройки что были у обновляемого модуля для витрины 3

    $this->db->replaceInto("settings_vendor_values", ['object_id' => 6377, 'value' => 3, 'company_id' => 3, 'storefront_id' => 3]);

Удаляем только что записанные настройки витрины 3

    \\isRootMode = true    storefront_id=3
    if ($this->isRootMode() && $storefront_id) {
        $this->db->query('DELETE FROM ?:settings_vendor_values WHERE object_id = 6377 AND storefront_id = 3');
    }

До 4.13.2 кода удаления не было и все работало корректно(старые настройки сохранялись). Ну и логики работы я тут не вижу - нужно либо удалять старые настройки и ничего не записывать. Либо удалять старые настройки, а потом записывать новые. Либо как раньше просто был код db->replaceInto и все работало прекрасно. А вот записывать новые настройки и тут же удалять ну как то странно, хотя может так и задумано.

3 лайка

Благодарю вас за дополнительную информацию!

Вариант с переустановкой модуля действительно не учтен в данном случае. Однако этот код решает другую проблемы с некорректной работой настроек.

К сожалению, мы не можем гарантировать корректную работу модуля и сохранение настроек в случае использования опасного метода переустановки модуля, поскольку могут быть добавлены новые настройки или область их видимости. В этом случае их необходимо будет перезаписать.

Я создал запрос нашим разработчикам на исследования данного вопроса. Они определят есть ли возможность сохранять настройки модуля на нескольких витринах при переустановке не безопасным методом. На данном этапе я не могу дать каких либо гарантий и сроков внедрения - это зависит от результата их исследования.

С Уважением, Серж
Специалист поддержки CS-Cart