Глобальна таблиця конфігурації PrestaShop дозволяє процедурі видалення модуля легко стирати налаштування, що належать зовсім іншим розширенням. Один виклик Configuration::deleteByName('width') може видалити кастомне значення ширини іншого магазину, залишаючи власника в розгубленості, а модуль-винуватець — зовні безневинним.
Чому спільна таблиця конфігурації має значення
PrestaShop зберігає налаштування кожного модуля в одній таблиці, яка містить лише ключ і значення. У таблиці немає стовпця, який би фіксував, який саме модуль створив рядок, і вона не застосовує жодних правил іменування. Як наслідок, два модулі, які випадково використовують один і той самий ключ — наприклад, «width» або «API_DATE_FROM» — читатимуть і записуватимуть один і той самий рядок у базі даних. Перемагає останній запис, а будь-яке подальше видалення видаляє рядок для обох сторін.
Коли код видалення перетворюється на інструмент для стирання даних
Типовий метод видалення виглядає так:
public function uninstall()
{
return Configuration::deleteByName('width');
}
Мета полягає в тому, щоб очистити власну конфігурацію модуля, але оскільки ключ не має простору імен (namespace), ця команда видаляє будь-який рядок під назвою «width». Жодних попереджень не реєструється, жодних винятків не викидається; рядок просто зникає. Інший модуль власника магазину тихо втрачає своє налаштування і може почати поводитися дивно.
Проблема стає особливо гострою під час оновлення версії. Розробник, який переходить з версії 1.0 на 2.0, може почати зберігати значення під ключем із префіксом, наприклад MY_MODULE_WIDTH. Щоб «очистити» старі записи без префікса, вони додають виклик видалення до процедури видалення, вважаючи, що видаляють лише застарілі дані. Насправді вони також видаляють усе, що інші розширення зберігали під тим самим загальним ключем.
Що виявив аудит
Аудит 57 публічних репозиторіїв модулів виявив повторювану закономірність:
- Багато модулів використовують загальні ключі, такі як «width», «height» або «API_DATE_FROM», без будь-якого префікса, похідного від назви модуля.
- Кілька методів видалення містять виклики
Configuration::deleteByName, які націлені на ці загальні ключі. - Проблема не обмежується одним розробником або певним типом модуля; дизайн спільної таблиці робить це системним ризиком.
Аудит не виявив жодних логів або повідомлень про помилки, які б попередили власника магазину про те, що конфігурація іншого модуля була видалена. Єдиним симптомом є раптова втрата налаштувань, яку власник може списати на проблему з кешем або помилку у власному коді.
Більш безпечні практики для розробників модулів
- Використовуйте простір імен для кожного ключа – додавайте технічну назву модуля до кожного ключа конфігурації (наприклад,
my_module_width). Це створює унікальний ідентифікатор, не покладаючись на окремий стовпець власності. - Уникайте видалення старих ключів без префіксів – залишення кількох застарілих рядків у таблиці майже не потребує місця в сховищі та усуває ризик побічної шкоди.
- Перевіряйте власність перед видаленням – якщо видалення дійсно необхідне, спочатку перевірте, чи було значення ключа встановлене вашим власним кодом (наприклад, збережіть маркерне значення, яке відоме лише вашому модулю).
- Аудитуйте методи видалення – шукайте у коді виклики
deleteByName. Кожне входження слід перевірити, щоб підтвердити, що ключ має унікальний простір імен. - Документуйте правила іменування – додайте корослу інструкцію в README модуля, щоб майбутні контриб'ютори розуміли важливість ключів із префіксами.
Тестування на випадкове видалення між модулями
Практичний спосіб виявити помилку до того, як вона потрапить у реальний магазин:
- Наповніть таблицю конфігурації ключем, який належить іншому модулю (наприклад,
other_module_setting=>test). - Запустіть процедуру видалення модуля в контрольованому середовищі.
- Перевірте (Assert), що наповнений ключ все ще існує після завершення видалення.
Автоматизація цієї перевірки в наборі юніт-тестів модуля гарантує, що будь-яка майбутня зміна, яка введе випадковий виклик deleteByName, призведе до провалу тесту, що спонукатиме до перегляду коду.
На що варто звернути увагу власникам магазинів
Власники магазинів рідко бачать внутрішні рядки бази даних, але вони можуть помітити симптом: після вимкнення або видалення модуля інше розширення раптово повертається до налаштувань за замовчуванням. Якщо це сталося, попросіть розробника перевірити, чи враховує код видалення модуля глобальну таблицю конфігурації. Запитайте список усіх ключів конфігурації, які використовує модуль; будь-який ключ без чіткого префікса є тривожним сигналом.
Висновок
Архітектура PrestaShop робить таблицю конфігурації спільним ресурсом, і необережна процедура деінсталяції може безслідно стерти налаштування іншого модуля. Використовуючи простори імен для ключів, уникаючи агресивного очищення та додаючи простий тест, який захищає сторонні записи, розробники можуть запобігти прихованій втраті даних і забезпечити стабільність магазинів продавців. Необхідні зусилля мінімальні, але ціна втраченого налаштування — скарги клієнтів, запити в службу підтримки та пошкоджена репутація — може бути набагато вищою.
