Skip to main content
Version: 4.0 preview

Customization code migration to CBX 4

Version
4.0 preview
Updated
View markdown

Task-oriented guides for realigning existing site customizations (data/customization/) to the breaking changes introduced in CBX 4.

CBX 4 is a deliberate, breaking refactor of the core. Because every deployment carries its own customization code in data/customization/gitignored, out-of-tree, per-site — a core change that renames a model, drops a table column, or changes a convention will silently break that code. This area is the running record of those breaks and the concrete before → after fixes for each.

Where these docs live. This directory ships inside the CBX component itself (<component>/docs/migration-to-cb4/), so it travels with the code on every platform CBX runs on — Joomla (components/com_configbox), WordPress (plugins/configbox/app) and Magento 2 (cb-lib), all of which mount the same component repo — and it is included in the release package built by tools/make_packages.sh. Intended workflow: open a client project with its data/customization/, upgrade CBX, then point an AI at the customizations and this directory and ask it to amend the customizations. Everything an agent needs to do that is here; no platform-specific paths are assumed.

For AI agents amending customization code: load CHEATSHEET.md first — it is the flat old → new lookup for every identifier, with a grep pack to find the hits. Scan the customization for each Old token, apply the New, and heed the Status (shim = defer, manual = must edit, manual+data = also ship a data migration). Then, for anything non-mechanical (removed features, data migrations, judgement calls), read the matching playbook — the per-domain articles below carry the worked conversions and the per-file decision procedure. The breaking-changes log summarises what changed and why.

CLI tooling for the migration. CBX ships a CLI suite that carries most of the operational work of this upgrade — checking, applying and un-sticking migrations, clearing caches, and smoke-testing without a browser. On Joomla run php cli/joomla.php configbox:<cmd>; on WordPress the same commands are wp configbox <cmd> (hyphenated; migrate --status and migrate:unblock are not ported there yet); on Magento 2 there is no CLI suite yet — migrations run via bin/magento setup:upgrade, and you check state with the SQL in the CHEATSHEET's sign-off.

During the upgrade you will wantCommand (Joomla form)
"Did the migrations actually run?" — the host platform's own version/status reports say nothing about CBX's schemaconfigbox:migrate --status (read-only; non-zero exit while work is pending)
Apply outstanding core + customization update scripts, by nameconfigbox:migrate (-v for full failure diagnostics)
A script failed and updates are frozenconfigbox:migrate:unblock (explains the block first; --dry-run to only look)
Clear caches after amending customization codeconfigbox:cache:clear
Smoke-test a configurator page headlessly, as a given userconfigbox:run-task configuratorpage display page_id=<id> --user=<email>

Full reference: ../technical/com_configbox_cli_commands.md in the developer docs (docs/technical/).


How this area is organised

The running record (read first)

  • CHEATSHEET.md — the consolidated old → new identifier lookup: one flat table of every renamed/removed table, column, class, method, property, cache key, DSL token and string-key across all domains, each tagged shim / manual / manual+data / removed, with the stacked element→answer→question rename already resolved to its final target. Load this first when amending a customization; it points into the playbooks for the detail. Ends with a ready-to-run grep pack to prove a customization is clean.
  • breaking-changes-log.md — the single running index of every breaking change: what broke, why, blast radius, and a one-line pointer to the playbook that fixes it. Append a new dated entry here whenever core work introduces another break.

Playbooks — how to fix customization code (one per customization kind, with the mechanical transform + the cases that need human/AI judgement)

  • exceptions-and-validation.md — errors are exceptions now. A custom property type's check() should throw KenedoValidationException instead of returning false; callers of validateData()/store() move to try/catch. Returning false still works, but a custom type that returns it without setting an error reports a message nobody can act on.

  • model-property-customizations.md — the mechanical recipe for model_property_customization/ files bound to the removed option/answer models, and the auto-conversion the core does for you.

  • answers-collapse-deep-dive.md — the exhaustive reference for the option/answer (xref → answer) collapse: the full mental model, every DB/SQL/cache/order/string/pricing touch-point, a per-file decision procedure, worked conversions, and the external-append data migration you owe. Start here for any customization that touches the data model, not just property defs — this is the one written for a heavily-customized site where an AI is asked to make the custom code compatible.

  • assignments-lookups.md — reading the assignment relations through ConfigboxAssignmentsHelper instead of ConfigboxCacheHelper::getAssignments(): the full old-key → new-method table, why the undefined-key guards disappear, the two shapes that deliberately differ, and the city_to_country / county_to_country correction. getAssignments() still works — this is the better way to ask, and core no longer reads the array itself.

  • element-question-rename.md — the exhaustive before → after reference for the element → question rename: DB table/columns, admin model/controller/views, pricing API, the assignment/pricing cache keys, the ionCube rules/calc engine + stored JSON, and the calc-formula DSL tokens. Full before → after tables per layer, the per-file decision procedure, worked conversions, and the shim inventory. Read this for any customization that touches the question entity.

  • customer-field-rename.md — the exhaustive before → after reference for the customer field rename: #__configbox_users + #__cbcheckout_order_users columns (billing_* / shipping_* snake_case, vat_number, shipping_same_as_billing), the augmented keys, the Customer Fields configuration rows, form/DOM/JS contracts, and the operator-facing template placeholders. Read this for any customization that touches customer data, the customerform, order addresses or invoice/notification texts.

Orientation — what changed, per audience (not fixes; context for people)

Those three pages are about the jump to 4.0. What the 4.0 line has gained since is a separate track, cut by surface rather than by audience: Latest features — the storefront, the admin, the HTTP API, the CLI, the MCP server, the AI assistant, payments, catalog operations and the extension layer.

More playbooks get added here as further CBX 4 slices ship (overridden controllers/models, custom properties, engine/calc code, template overrides, DB-schema-dependent customizations, …).


The two kinds of fix

Every break falls into one of two buckets; each playbook labels its cases accordingly:

  1. Auto-converted by the core — CBX 4 ships compatibility shims (legacy getModel() aliases, legacy customization-file loading, key remaps) so cleanly-written customizations keep working with no code change. You still get a deprecation line in the log telling you to update. These are called out so you know what you can safely defer.
  2. Needs a manual edit — customizations that reference something genuinely removed (a dropped column, a deleted property, a table that no longer exists) cannot be shimmed. The core degrades gracefully (logs and skips rather than white-screening), but the feature stays broken until you apply the fix the playbook describes.

Rules for documenting a breaking change

When our work on the CBX core introduces a breaking change, follow this — it is the standing process, not just a style guide. The goal is that a future reader (human or AI) can, from these docs alone, both understand what changed and make custom code compatible without re-deriving it from the diff.

1. Log it first, in the right bucket. Every breaking change gets a dated entry at the top of breaking-changes-log.md before anything else, tagged with the status legend (🟢 auto-converted · 🟡 partial · 🔴 manual). The log is the index; detail lives in a playbook it links to.

2. Classify every affected case as one of two kinds (and label it):

  • Auto-converted by the core — a shim keeps cleanly-written customizations working with no code change (a deprecation is logged). Say what the shim is and where it lives, and what the log line looks like, so a reader can verify it and know what they can safely defer.
  • Needs a manual edit — something was genuinely removed; no shim is possible. Give the exact before → after. State whether the core degrades gracefully (logs & skips) or fatals if left unfixed — operators need to know which breaks are silent-but-degraded vs hard.

3. Be concrete and greppable. Name the exact file, function, class, table, column, cache key. Give the literal identifiers a reader will grep for (old → new). Include the hard-to-grep variants too (hard-coded table prefixes, ::class string uses, minified twins).

4. Separate "code fix" from "data migration". A code-level shim (e.g. a remapped key) does not move data. Whenever a change needs both, say so explicitly and point at how to ship the DB half (a data/customization/updates/ migration; see ../technical/com_configbox_migrations.md). This is the most commonly missed half on customized sites.

5. Give a decision procedure for scale. On a site with extensive customizations, a reader needs more than a list — give a per-file procedure: how to tell if a file is even loaded on this install, which bucket it falls in, what to do, and a final grep list of removed identifiers to prove the file is clean.

6. Cover all three audiences, not just developers. A breaking change usually has a human side. Note whether operators/shop staff see a changed screen, label, or workflow (feed it into operators-what-changed.md), and whether it's material to an upgrade decision (whats-new-for-decision-makers.md). Don't leave retraining implicit.

7. Record why. One or two sentences on the motivation. Judgement calls during conversion resolve better when the reader knows the direction the model is moving in.

8. Verify claims before publishing. Check identifiers against the actual code, not memory. Don't state a shim exists unless you can name the method that implements it. Don't invent commercial/licensing facts in the decision-maker doc — flag them as "confirm with Rovexo" instead.