Navigation Link block: taxonomy terms added via the Navigation builder are saved with kind:"post-type", then get_url() resolves the term ID as a post ID and renders a wrong URL on the front end
Environment
- Kadence Blocks 3.7.9.1 (also confirmed in current trunk)
- Kadence Blocks Pro 2.8.17, Kadence Theme, WooCommerce
- WordPress 7.1, PHP 8.2.33
Summary
Product category links added through the Advanced Navigation builder's "select existing items" browser render broken URLs on the front end (for example /144/ or /?p=94 instead of /product-category/accessories/), while the editor shows the correct URL. Two separate issues combine to cause this.
Steps to reproduce
- WooCommerce site with product categories. Note a category's term ID (for example Accessories, term ID 144).
- Add an Advanced Navigation block (or edit a navigation in the builder). Use the "select existing items" browser to add that product category as a nav item.
- Check the saved block markup. The item is stored as:
{"label":"Accessories","id":144,"url":"https://example.com/product-category/accessories/","kind":"post-type"}
Note: kind is post-type for a taxonomy term, and there is no type attribute.
- View any page that renders this navigation on the front end while a post row with ID 144 exists in an odd state (drafts, auto-drafts of CPTs such as
kadence_navigation itself, etc. - on our site the colliding IDs were Kadence's own auto-draft navigation posts).
- The rendered href is not the stored URL. We observed
/144/, /?p=94, /?p=20, and a wrong page URL, all 404s.
Root cause
Issue 1 (save side): In blocks-navigation.js (src for dist/blocks-navigation.js), the "add existing items" handlers create nav-link blocks with kind: "post-type" hardcoded. The taxonomy variant maps terms as:
createBlock('kadence/navigation-link', {
label: e.name,
url: e.link,
id: e.id, // term ID
type: e.type, // terms have no .type, so this is undefined and gets dropped
kind: 'post-type' // hardcoded, wrong for terms
});
So a term is stored with its term ID labelled as a post-type link, with no type.
Issue 2 (render side): includes/blocks/class-kadence-blocks-navigation-link-block.php, get_url() (around line 871): when kind === 'post-type' and id is set (disableLink defaults to false), it calls get_permalink( $attributes['id'] ) and returns it whenever truthy, silently replacing the stored URL. There is no get_term_link() branch anywhere in the file, and no check that the ID belongs to a real, published post. A term ID therefore resolves against whatever unrelated post row shares that number.
Navigation Link block: taxonomy terms added via the Navigation builder are saved with
kind:"post-type", thenget_url()resolves the term ID as a post ID and renders a wrong URL on the front endEnvironment
Summary
Product category links added through the Advanced Navigation builder's "select existing items" browser render broken URLs on the front end (for example
/144/or/?p=94instead of/product-category/accessories/), while the editor shows the correct URL. Two separate issues combine to cause this.Steps to reproduce
{"label":"Accessories","id":144,"url":"https://example.com/product-category/accessories/","kind":"post-type"}Note:
kindispost-typefor a taxonomy term, and there is notypeattribute.kadence_navigationitself, etc. - on our site the colliding IDs were Kadence's own auto-draft navigation posts)./144/,/?p=94,/?p=20, and a wrong page URL, all 404s.Root cause
Issue 1 (save side): In
blocks-navigation.js(src fordist/blocks-navigation.js), the "add existing items" handlers create nav-link blocks withkind: "post-type"hardcoded. The taxonomy variant maps terms as:So a term is stored with its term ID labelled as a post-type link, with no
type.Issue 2 (render side):
includes/blocks/class-kadence-blocks-navigation-link-block.php,get_url()(around line 871): whenkind === 'post-type'andidis set (disableLinkdefaults to false), it callsget_permalink( $attributes['id'] )and returns it whenever truthy, silently replacing the stored URL. There is noget_term_link()branch anywhere in the file, and no check that the ID belongs to a real, published post. A term ID therefore resolves against whatever unrelated post row shares that number.