fix(product): сохранение Data и extra fields в процессорах Create/Update#298
Conversation
|
Спасибо за PR — закрывает реальный гэп в processor-флоу для msProductData и сделано архитектурно правильно (trait, whitelist, разделение Create/Update, alias-классы). Прошёлся по коду, PHPStan прогнал — есть три вещи, которые лучше доделать до мержа. Корректность диагнозаПодтверждаю: АрхитектураДелю на сильные стороны и проблемы. Хорошо
🔴 Блокер 1 — PHPStanПрогнал по файлам PR (
Решение: либо уточнить тип в 🔴 Блокер 2 — discarded return value в
|
78f1724 to
0edef3c
Compare
- Annotate msProduct::getDataFieldsNames() as list<string> for PHPStan - Treat empty msProductData payload as noop success in trait - Log ERROR when Create fails to persist msProductData after resource insert - Log WARN when Data JSON payload is malformed
|
@biz87 можно смотреть повторно |
|
Спасибо за фиксы — закрыто всё содержательное из первого ревью. Прогнал PHPStan на актуальной версии, осталось две мелочи перед мержем. ✅ Что закрыто1. Discarded return value в if (!$this->persistProductDataPayload()) {
$this->modx->log(modX::LOG_LEVEL_ERROR,
'[msProduct/Create] failed to persist msProductData for resource id '
. $this->object->get('id'));
}Плюс в трейте 2. Лог при malformed JSON $this->modx->log(modX::LOG_LEVEL_WARN,
'[msProduct] malformed Data JSON payload: ' . json_last_error_msg());3. PHPStan typing на /**
* @return list<string>
*/
public function getDataFieldsNames(): arrayЗакрыли в источнике — это правильнее, чем правка в потребителе. 🟡 Осталось — две мелочиPHPStan ещё ругается на traitПосле уточнения Docblock в трейте остался от предыдущей итерации ( Один из вариантов: a) Поправить docblock на корректный тип: /**
* @return array<string, int<0, max>>
*/
private function getAllowedProductDataFieldNames(): arrayb) Заменить $fields = array_fill_keys($this->object->getDataFieldsNames(), true);
unset($fields['id']);
return $fields;Я бы выбрал (b) — читается как «список разрешённых ключей», и 🔴 Conflicting — нужен rebase
Правки концептуально аддитивные:
Take-both в обеих секциях после РезюмеСодержательно PR готов. До мержа:
После этого — мержим без оговорок. |
MODX Resource processors call fromArray() without ignoreInvalid, so extra fields and flat msProductData keys were dropped. Add Data payload support and apply allowed fields in beforeSave() after loadMap(). Closes #297
Move product data payload application to afterSave on Create so price and extra fields save once the resource id exists; add MODX resolver aliases for Resource Create/Update and JSON-decoded Data payloads.
- Annotate msProduct::getDataFieldsNames() as list<string> for PHPStan - Treat empty msProductData payload as noop success in trait - Log ERROR when Create fails to persist msProductData after resource insert - Log WARN when Data JSON payload is malformed
8984282 to
796f121
Compare
|
Закрыто всё:
Плюс ранее уже было закрыто:
Мержим. |
Описание
Исправляет #297: поля
msProductData(включая Object Extension / extra fields, напримерext_id) не сохранялись при вызовеrunProcessorс блокомDataили плоскими ключами (price, …).Причина (две части):
Resource\Create|Updateвызывают$object->fromArray($properties)безignoreInvalid— колонкиmsProductDataне попадают на объект.Dataтребуетidресурса; запись вbeforeSave()не гарантирует persistpriceи extra fields.Решение:
ProductDataPayloadTrait: захватDataвbeforeSet(), whitelist черезgetDataFieldsNames(),loadMap()для extra fields.applyProductDataPayload()вbeforeSave().persistProductDataPayload()вafterSave()после insert ресурса.msProductCreateProcessor/msProductUpdateProcessorдля резолвераResource\Create|Update::getInstance()(импорт CSV, интеграции).Поддерживаются плоские ключи в корне payload и явный блок
Data(при конфликте побеждаетData).Тип изменений
Связанные Issues
Closes #297
Как это было протестировано?
Конфигурация тестирования:
php -lдля изменённых PHP-файлов (OK)Сценарии для ревьюера:
MiniShop3\Processors\Product\Create+Data=>['price' => 5200, 'ext_id' => '…']— значения вms3_products.MODX\Revolution\Processors\Resource\Create+class_key = msProduct— тот же результат (alias-процессор).Updateс блокомData— поля обновляются.price/ext_idв корне payload.options-*).Пример
runProcessor:Скриншоты (если применимо)
price/ extra fields не сохранялись черезrunProcessorна CreateDataи плоские ключи послеafterSave()Чеклист
Дополнительные заметки
Code review (clean-code / pre-merge)
Сильные стороны:
capture/apply/persist).getDataFieldsNames()+array_intersect_key— безопаснее произвольного merge.fromArray(..., true, true)сignoreInvalid— корректный контракт для extra fields.afterSave+ explicitsave) / Update (beforeSave) задокументировано в docblock trait.Model\— минимальный diff, без дублирования логики.Замечания (не блокеры, follow-up):
persistProductDataPayload()возвращаетfalseи при «нет полей для записи», и при ошибке$productData->save()— вCreate::afterSave()результат не проверяется; при сбое save клиент может получить success. Имеет смысл различать noop / failure или проверять return при непустом payload.Dataиз connector молча игнорируется — для отладки можно log или validation error (низкий приоритет).Затронутые файлы:
Processors/Product/ProductDataPayloadTrait.php(новый)Processors/Product/Create.php,Update.phpModel/msProductCreateProcessor.php,msProductUpdateProcessor.php(новые)