BRD-1216: custom product fields support in PrestaShopAdapterV2 - #77
Conversation
|
@claude please review this PR |
|
Claude finished @GantasG's task in 2m 56s —— View job Review complete ✅Todos
SummaryThe change adds Findings
Not verifiedI don't have permission to run VerdictNo blocking issues. The two notes above (custom field name sanitization, missing |
transformCustomFields() inlined the localized-values loop instead of reusing addLocalizedField(), and the scalar branch never sanitized at all, so custom fields indexed raw HTML unlike every other localized field (name, description, brand).
|
@claude please review this PR again. The earlier review ran against an older head. Since then: fixes from the branch code review were applied. Current head: |
|
Claude finished @GantasG's task in 1m 28s —— View job Re-review complete ✅
SummaryTwo commits landed since the last review, both addressing the earlier feedback:
Verification
Not verifiedSame limitation as the previous run: VerdictThe fix commit directly and correctly resolves the substantive point from the first review. No new issues found. Approve-able pending your own CI confirmation. |
|
@claude please review this PR. The head is unchanged since your last review, so this is a fresh full-PR look rather than a delta. Worth attacking: whether |
|
Claude finished @GantasG's task in 2m 20s —— View job Review complete ✅Todos
SummaryThis is a fresh full-PR look at the unchanged head ( Findings1. Sanitization is correct and consistent across both branches.
2. A malformed or partial 3. One real gap: non-scalar 4. Previously-noted items remain unchanged (informational only, not blocking):
Not verifiedSame limitation as both previous review rounds: no permission to run VerdictNo blockers. Finding #3 (non-scalar value guard) is the one substantive new observation from this pass — a real but non-fatal gap, worth a small follow-up but not required to merge given it mirrors a pre-existing pattern in |
…ingifying them A custom field whose value arrived as an array was cast with (string), which emits an Array to string conversion warning and stores the literal Array — silent data corruption in the index. An object value would have thrown outright, failing the whole product transform rather than one field. Guards both paths a custom field can take. The localized branch routes through addLocalizedField(), which is shared with name/description/brand/features, so the guard there also removes the same corruption path for core fields; skipping is strictly better than storing Array and no caller can want the old behaviour. Both tests fail without the guards, emitting the conversion warning.
ReviewSmall diff, no SQL, no BC break on constructors/interfaces. Field naming ( Blocking
Important
Nits
Note on merge orderThe PS module vendors its own Verdict: approve after the |
The previous commit tightened addLocalizedField()'s guard from `$value === null` to `!is_scalar($value)` to stop arrays being stringified into the index. That also silently dropped Stringable objects, which used to work via `(string) $value`, on name/description/descriptionShort/brand as well as on localized custom fields. Route every value through stringifyFieldValue(): scalars and Stringable are accepted, arrays and non-stringable objects stay rejected.
Two defects in one path: strip_tags() drops everything from an unmatched `<` to the end of the string. Custom columns hold codes, size ranges and numeric notes, not HTML bodies, so "30<x<40" was silently indexed as "30", "S<M<L" as "S" and "5<3" as "5". Non-text values were stripped at all, and the emptiness check ran on the raw value instead of the cleaned one, so a text value that cleaned down to '' was still written. brad-app maps non-text custom fields as integer/double/date and an empty string on one of those makes the backend reject the whole product. Now: HTML removal applies to text-typed values only, it no longer truncates at a literal `<` (literal angle brackets are parked behind a sentinel while strip_tags removes real markup), values are trimmed - char(32) columns arrive space-padded - and anything empty after cleaning is skipped. Core localized fields (name/description/descriptionShort/brand/features) keep their existing always-strip behaviour: the type awareness is passed in from transformCustomFields and defaults to off.
A nullable DATE/DATETIME column hands out '0000-00-00 00:00:00' rather than NULL. brad-app maps a date-typed custom field as an ES date, which rejects that value, and one rejected field fails the whole product document. The PrestaShop module already normalizes the zero date away for the core createdAt/updatedAt fields but not for custom columns, so filter it here. Only date-typed fields are affected: a text column may legitimately contain '0000-00-00' as literal content.
…paths
The name came straight off the network payload and was concatenated into a
search field name. A `.` in it becomes an object path in the index, and an
over-long name is rejected by the backend. Hold names to the module's own
column-name rule, /^[a-zA-Z0-9_]{1,64}$/, and skip the entry otherwise; this
also subsumes the previous empty-name check.
…try shape The `custom_` literal is repeated across three repos, so publish it as PrestaShopAdapterV2::CUSTOM_FIELD_PREFIX and use it internally. The field name shapes (custom_<name>, custom_<name>_<locale>) are unchanged. Also document the accepted entry shape on transformCustomFields, the way transformFeatures documents its own: this is a wire contract between the PrestaShop module, this SDK and brad-app.
Re-review (fix commits d0b5300..61ec66a)Friday's blocker is properly fixed: Blocking — new bug introduced by the fix roundBoolean custom fields are broken both ways. Routing values through
Fix: normalise Small
Verdict: fix the boolean handling, then good to merge and tag v4.15.0. |
- real PHP booleans become 'true'/'false' instead of '1'/dropped - name pattern anchored with the D modifier so a trailing newline is rejected - tests for booleans, trailing newline, duplicate names and map-shaped input - document the custom field entry shape on transformCustomFields() Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
@claude review |
|
Claude finished @PauliusInvertus's task in 3m 39s —— View job Re-review complete (head
|
* releases/2026.05 * BRD-1225: stop dropping products and variants with an empty SKU (#78) Shops do not require a SKU (PrestaShop reference, Shopify sku are optional), so products without one were skipped in sync and missing from search. Product, ProductVariant and ProductBuilder now accept an empty sku. The PrestaShop adapters read a null or missing sku as '' instead of throwing. id stays required. * BRD-1053: carry Shopify variant image into variant imageUrl (#79) * BRD-1053: carry Shopify variant image into variant imageUrl Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * BRD-1053: read variant image from media, not the deprecated image field Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * BRD-1216: custom product fields support in PrestaShopAdapterV2 (#77) * feat(prestashop): map merchant custom product fields into additionalFields * style(prestashop): strip development comments * fix(prestashop): sanitize custom field values with strip_tags transformCustomFields() inlined the localized-values loop instead of reusing addLocalizedField(), and the scalar branch never sanitized at all, so custom fields indexed raw HTML unlike every other localized field (name, description, brand). * fix(customfields): skip non-scalar custom field values instead of stringifying them A custom field whose value arrived as an array was cast with (string), which emits an Array to string conversion warning and stores the literal Array — silent data corruption in the index. An object value would have thrown outright, failing the whole product transform rather than one field. Guards both paths a custom field can take. The localized branch routes through addLocalizedField(), which is shared with name/description/brand/features, so the guard there also removes the same corruption path for core fields; skipping is strictly better than storing Array and no caller can want the old behaviour. Both tests fail without the guards, emitting the conversion warning. * fix(prestashop): keep accepting Stringable localized field values The previous commit tightened addLocalizedField()'s guard from `$value === null` to `!is_scalar($value)` to stop arrays being stringified into the index. That also silently dropped Stringable objects, which used to work via `(string) $value`, on name/description/descriptionShort/brand as well as on localized custom fields. Route every value through stringifyFieldValue(): scalars and Stringable are accepted, arrays and non-stringable objects stay rejected. * fix(customfields): stop strip_tags corrupting custom field values Two defects in one path: strip_tags() drops everything from an unmatched `<` to the end of the string. Custom columns hold codes, size ranges and numeric notes, not HTML bodies, so "30<x<40" was silently indexed as "30", "S<M<L" as "S" and "5<3" as "5". Non-text values were stripped at all, and the emptiness check ran on the raw value instead of the cleaned one, so a text value that cleaned down to '' was still written. brad-app maps non-text custom fields as integer/double/date and an empty string on one of those makes the backend reject the whole product. Now: HTML removal applies to text-typed values only, it no longer truncates at a literal `<` (literal angle brackets are parked behind a sentinel while strip_tags removes real markup), values are trimmed - char(32) columns arrive space-padded - and anything empty after cleaning is skipped. Core localized fields (name/description/descriptionShort/brand/features) keep their existing always-strip behaviour: the type awareness is passed in from transformCustomFields and defaults to off. * fix(customfields): skip MySQL zero dates on date-typed custom fields A nullable DATE/DATETIME column hands out '0000-00-00 00:00:00' rather than NULL. brad-app maps a date-typed custom field as an ES date, which rejects that value, and one rejected field fails the whole product document. The PrestaShop module already normalizes the zero date away for the core createdAt/updatedAt fields but not for custom columns, so filter it here. Only date-typed fields are affected: a text column may legitimately contain '0000-00-00' as literal content. * fix(customfields): validate custom field names before building field paths The name came straight off the network payload and was concatenated into a search field name. A `.` in it becomes an object path in the index, and an over-long name is rejected by the backend. Hold names to the module's own column-name rule, /^[a-zA-Z0-9_]{1,64}$/, and skip the entry otherwise; this also subsumes the previous empty-name check. * refactor(customfields): expose the custom_ prefix and document the entry shape The `custom_` literal is repeated across three repos, so publish it as PrestaShopAdapterV2::CUSTOM_FIELD_PREFIX and use it internally. The field name shapes (custom_<name>, custom_<name>_<locale>) are unchanged. Also document the accepted entry shape on transformCustomFields, the way transformFeatures documents its own: this is a wire contract between the PrestaShop module, this SDK and brad-app. * docs(customfields): cut the added prose to the non-obvious why * docs: drop the explanatory comments from the custom-field fixes * BRD-1216: normalise boolean custom fields and tighten the name pattern - real PHP booleans become 'true'/'false' instead of '1'/dropped - name pattern anchored with the D modifier so a trailing newline is rejected - tests for booleans, trailing newline, duplicate names and map-shaped input - document the custom field entry shape on transformCustomFields() Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Paulius Stukšys <paulius.stuksys@invertus.eu> Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: GantasG <gantas.grigalionis@invertus.eu>
Summary
Adds custom product field handling to
PrestaShopAdapterV2socustom_*values coming from the PrestaShop module's product payloads are transformed and forwarded to the engine (both plain and per-locale suffixed names).Testing
Merge order / release
brad-appneeds itscomposer.jsonbumped fromv4.14.0to consume this.Jira: BRD-1216