Skip to content

Export menu category links as url_path - #15

Merged
gregor-RW merged 2 commits into
mainfrom
menu-category-paths
Aug 19, 2026
Merged

gregor-RW merged 2 commits into
mainfrom
menu-category-paths

Conversation

@gregor-RW

Copy link
Copy Markdown
Contributor

Follow-up to #14. A menu addresses a CMS page by identifier and a product by SKU, both portable. A category link was the exception: it stores the entity id, so an exported menu pointed at whatever category held that id on the target.

CategoryLinkMapper swaps the id for url_path on export and back on import, covering both a category link and the category_ids list of hyva_menu_category_tree.

Why url_path

Measured on a real 288-category catalog:

key rows distinct
name 288 247
url_key 287 287
url_path 286 (1 null) 285

name collides 41 times, so it is unusable. url_key is unique on that catalog by luck — Magento only enforces it between siblings, so two branches can each hold envelopes. url_path is the concatenation of the ancestor url keys, unique by construction and still readable in a diff.

Paths are read at the default store scope, which is what every store inherits unless overridden.

Failure handling

Anything that does not resolve is reported and left as it stands, matching how a missing block or theme is already handled: the import completes and the warning says what will not render.

A category tree list is rewritten whole or not at all, so a partial failure cannot silently drop entries from a tree.

Scope

Menus only. Pages and blocks can carry the same links, but they keep the behaviour they shipped with until that is asked for.

Verification

Against a real install, with a category link (id 147) and a category tree (148,149) added to a live menu:

  • export wrote product-category/amsive-miamisburg and product-category/state-wisconsin-employee-trust,product-category/state-wisconsin-uw-green-bay
  • import resolved them back to 147 and 148,149
  • a hand-broken path produced category path "product-category/does-not-exist-here" does not exist on this install, left as it is and the import completed

Integration tests cover the round trip for a link and for a tree, an unknown path, a non-category link passing through untouched, and empty or non-json content.

Gregor Pollak added 2 commits August 19, 2026 11:48
A menu addresses a CMS page by identifier and a product by SKU, both of which
mean the same thing on every install. A category link was the exception: it
stores the entity id, so an exported menu pointed at whatever category held
that id on the target.

CategoryLinkMapper swaps the id for url_path on export and back on import,
covering both a category link and the category_ids list of
hyva_menu_category_tree.

url_path rather than name or url_key. Names collide freely, and Magento only
enforces url_key uniqueness between siblings, so two branches can each hold
"envelopes". url_path is the concatenation of the ancestor url keys, so it is
unique by construction and still readable in a diff. Paths are read at the
default store scope, which is what every store inherits unless overridden.

Anything that does not resolve is reported and left as it stands, matching how
a missing block or theme is already handled: the import completes, and the
warning says what will not render. A category tree list is rewritten whole or
not at all, so a partial failure cannot silently drop entries.

Menus only. Pages and blocks can carry the same links, but they keep the
behaviour they shipped with until that is asked for.
Setting url_path explicitly does not stick: the url path autogenerator
derives it from the category name on save, so the fixture category came back
as category-1 and the assertion compared against a value that never existed.
@gregor-RW
gregor-RW merged commit 5d8f80c into main Aug 19, 2026
1 of 2 checks passed
@gregor-RW
gregor-RW deleted the menu-category-paths branch August 19, 2026 10:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant