close
Skip to content

Navigation: Restore block_core_navigation_submenu_render_submenu_icon() as deprecated shim#78484

Merged
talldan merged 4 commits into
WordPress:trunkfrom
ecairol:fix/65287-deprecate-navigation-submenu-render-submenu-icon
May 22, 2026
Merged

Navigation: Restore block_core_navigation_submenu_render_submenu_icon() as deprecated shim#78484
talldan merged 4 commits into
WordPress:trunkfrom
ecairol:fix/65287-deprecate-navigation-submenu-render-submenu-icon

Conversation

@ecairol
Copy link
Copy Markdown
Contributor

@ecairol ecairol commented May 21, 2026

What

Restores block_core_navigation_submenu_render_submenu_icon() as a deprecation shim and removes the backwards-incompatibility introduced by #74853.

Why

In #74853 the function was removed from packages/block-library/src/navigation-submenu/index.php as part of consolidating submenu icon rendering into the new shared helper block_core_shared_navigation_render_submenu_icon(). The removal landed without a _deprecated_function() notice or a backwards-compatible alias.

Once that change synced into Core (wordpress-develop #10865, scheduled for WordPress 7.0), any theme or plugin that called the function — for example from a render_block_core/navigation-submenu filter to customise the dropdown chevron — started triggering a fatal PHP error.

Trac ticket: https://core.trac.wordpress.org/ticket/65287

How

  • Adds the shim to packages/block-library/src/navigation-submenu/index.php — the same file the original was first deleted from. Wrapped in a function_exists guard so a future Core sync that brings the shim back to Core itself doesn't double-declare.
  • The shim triggers _deprecated_function() so callers see actionable guidance to migrate to the new shared helper, and returns the new helper's output to preserve the rendered markup.
  • Adds a phpunit test asserting the deprecation notice fires and that the return value matches the new helper. The test exercises the gutenberg_-prefixed name (matching the build's plugin output and the existing block-navigation-link-variations-test.php convention).

Notes for reviewers

The build's gutenberg_ prefix transform (packages/wp-build/lib/build.mjs:413-422) applies to plugin builds but is skipped for Core (IS_WORDPRESS_CORE branch at L392-397). That means:

  • Core 7.0+ (after sync): receives block_core_navigation_submenu_render_submenu_icon() unprefixed — fixes the fatal on standalone Core installs.
  • Gutenberg plugin builds: the function becomes gutenberg_block_core_navigation_submenu_render_submenu_icon(). On WP 7.0+ + plugin, theme calls to the unprefixed name resolve to Core's shim (once synced), so the bug is fixed there too.

Testing Instructions

  1. On a site running WordPress 7.0 (or trunk after the Gutenberg → Core sync), apply this change.
  2. Add a theme/plugin snippet that calls block_core_navigation_submenu_render_submenu_icon() (e.g. inside a render_block_core/navigation-submenu filter).
  3. Load a page containing a Navigation block with a submenu.
  4. Expected: the page renders without a fatal error, and a deprecation notice points to block_core_shared_navigation_render_submenu_icon().
  5. Before this PR: the page fatals with "Call to undefined function block_core_navigation_submenu_render_submenu_icon()".

Also runnable: phpunit --filter Block_Core_Navigation_Submenu_Render_Submenu_Icon_Test.

Screenshots or screencast

N/A — backend-only change with no UI impact.

Types of changes

Bug fix (backwards-compatible).

Checklist

  • My code is tested.
  • My code follows the WordPress code style.
  • My code has proper inline documentation.
  • I've included developer documentation if appropriate — N/A, function is deprecated.
  • I've updated all React Native files affected by the changes — N/A, PHP only.
  • I've tested the changes on Android and iOS — N/A, PHP only.

…() as deprecated shim

In WordPress#74853 the function was removed from packages/block-library/src/navigation-submenu/index.php
without a _deprecated_function() notice. Once that change synced into Core
(wordpress-develop WordPress#10865, scheduled for WP 7.0), themes and plugins that called
the function — for example from a render_block_core/navigation-submenu filter —
started fatal-erroring.

This restores it as a thin wrapper that triggers _deprecated_function() and
returns block_core_shared_navigation_render_submenu_icon(), the new shared
helper that replaced it. Adding it to the shared file means it's available
wherever the original was previously rendered.

A phpunit test asserts the deprecation notice fires and the return value
matches the new helper.

Trac ticket: https://core.trac.wordpress.org/ticket/65287
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 21, 2026

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: ecairol <ecairol@git.wordpress.org>
Co-authored-by: ramonjd <ramonopoly@git.wordpress.org>
Co-authored-by: t-hamano <wildworks@git.wordpress.org>
Co-authored-by: tyxla <tyxla@git.wordpress.org>
Co-authored-by: aaronjorbin <jorbin@git.wordpress.org>
Co-authored-by: talldan <talldanwp@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@github-actions github-actions Bot added [Package] Block library /packages/block-library First-time Contributor Pull request opened by a first-time contributor to Gutenberg repository labels May 21, 2026
@github-actions
Copy link
Copy Markdown

👋 Thanks for your first Pull Request and for helping build the future of Gutenberg and WordPress, @ecairol! In case you missed it, we'd love to have you join us in our Slack community.

If you want to learn more about WordPress development in general, check out the Core Handbook full of helpful information.

PHPCS in packages/block-library/src/navigation-link/shared/ enforces a
function-name prefix of block_core_shared*, which forbids the deprecation
shim's name. Move the shim into navigation-submenu/index.php (where the
function originally lived and block_core_navigation_submenu_* is allowed),
guarded by function_exists so a future Core sync that brings the shim back
into Core doesn't double-declare.

Drop the require_once in the test — its path resolution differed from the
plugin's own init load and was triggering "Cannot redeclare" fatals against
the already-loaded block_core_shared_navigation_render_submenu_icon().
Normal plugin boot loads navigation-submenu/index.php during block
registration, so the shim is available to the test without an explicit require.
@ramonjd ramonjd added the [Type] Regression Related to a regression in the latest release label May 21, 2026
The build prefixes packages/block-library functions with gutenberg_ before
the plugin loads them, so in the plugin test env the shim exists as
gutenberg_block_core_navigation_submenu_render_submenu_icon, not the
unprefixed Core name. Match the existing block-navigation-link-variations
test convention of asserting on the prefixed name with setExpectedDeprecated().
*
* @return string SVG markup for the submenu icon.
*/
function block_core_navigation_submenu_render_submenu_icon() {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just checking something... the PR description says it should live in packages/block-library/src/navigation-link/shared/render-submenu-icon.php.

To be clear, packages/block-library/src/navigation-submenu/index.php is fine since it was first deleted here:

https://github.com/WordPress/gutenberg/pull/74853/changes#diff-a22b96046ab15d77ae0b88e24a4cf01e5dbfea45c5bb8e489db9204c134026bfL87

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, thank you — you're right that the description was stale. I started with the shim in render-submenu-icon.php (commit 1), then moved it into navigation-submenu/index.php (commit 2) because PHPCS in the navigation-link/shared/ directory only accepts function names matching the block_core_shared* prefix. I just updated the PR description to match the code, and linked to the same L87 deletion you pointed at as the justification for the placement. Appreciate the review!

@ramonjd
Copy link
Copy Markdown
Member

ramonjd commented May 21, 2026

LGTM thanks for the quick patch @ecairol 🙇🏻

@scruffian @getdave do you think this is worth a point release? if so, we might need to coordinate with @ellatrix or someone in the release squad.

require_once __DIR__ . '/navigation-link/shared/render-submenu-icon.php';
require_once __DIR__ . '/navigation-link/shared/build-css-font-sizes.php';

if ( ! function_exists( 'block_core_navigation_submenu_render_submenu_icon' ) ) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrapped in a function_exists guard so a future Core sync that brings the shim back to Core itself doesn't double-declare.

I don't think a double declaration can occur, so we can remove this function existence check.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. The only way that comes to mind would be if a theme/plugin declares it after seeing it doesn't exist in 7.0, but it's as rare an edge case as using the function in a theme/plugin in the first place.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! This has been removed (84e2c4a)

@t-hamano t-hamano added the Backwards Compatibility Issues or PRs that impact backwards compatability label May 21, 2026
@github-project-automation github-project-automation Bot moved this to 🔎 Needs Review in WordPress 7.0 Editor Tasks May 21, 2026
@t-hamano t-hamano moved this from 🔎 Needs Review to 🐛 Punted to 7.0.1 in WordPress 7.0 Editor Tasks May 21, 2026
@t-hamano t-hamano moved this from 🐛 Punted to 7.0.1 to 🔎 Needs Review in WordPress 7.0 Editor Tasks May 21, 2026
/**
* @group blocks
*/
class Block_Core_Navigation_Submenu_Render_Submenu_Icon_Test extends WP_UnitTestCase {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The existence test for a deprecated function felt a bit like overkill to me. Is it really necessary? I'm generally fine with regression tests, but I don't see a good need for that, unless it's actually used somewhere.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, removed. (84e2c4a)

require_once __DIR__ . '/navigation-link/shared/render-submenu-icon.php';
require_once __DIR__ . '/navigation-link/shared/build-css-font-sizes.php';

if ( ! function_exists( 'block_core_navigation_submenu_render_submenu_icon' ) ) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. The only way that comes to mind would be if a theme/plugin declares it after seeing it doesn't exist in 7.0, but it's as rare an edge case as using the function in a theme/plugin in the first place.

* Renders the submenu icon SVG for the Navigation Submenu block.
*
* @since 5.9.0
* @deprecated 7.0.0 Use block_core_shared_navigation_render_submenu_icon() instead.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to confirm, it's intended to land in a patch version?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is confirmed yet. The last thing I know is @ramonjd asked if this is worth a point release.

I'll leave it like this for now, but happy to bump the version string if needed.

Comment on lines +5 to +8
* In Gutenberg plugin builds, the function name is prefixed with `gutenberg_`
* by the build system to avoid colliding with the WordPress Core version. These
* tests therefore exercise the prefixed name; the unprefixed counterpart is the
* one Core ships once the change syncs back.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this really true for this function? I see no prefixing happening with that function at all.

Copy link
Copy Markdown
Contributor Author

@ecairol ecairol May 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies. This was AI adding unnecessary comments. Apparently, there's an automatic prefixing at build that prepends gutenberg_:

The build genuinely rewrites function NAME( → function gutenberg_NAME( for everything under packages/block-library/src/**/*.php

However, the comment was pure noise, and it's been removed now (84e2c4a)

@ecairol ecairol requested review from ramonjd, t-hamano and tyxla May 21, 2026 13:56
@talldan talldan added the Backport to WP Minor Release Pull request that needs to be backported to a WordPress minor release label May 22, 2026
@talldan
Copy link
Copy Markdown
Contributor

talldan commented May 22, 2026

Added the label to backport this to the next minor WP release, as that seems like the likeliest thing that will happen.

@talldan talldan added the props-bot Manually triggers Props Bot to ensure the list of props is up to date. label May 22, 2026
@github-actions github-actions Bot removed the props-bot Manually triggers Props Bot to ensure the list of props is up to date. label May 22, 2026
@talldan talldan merged commit f59cc26 into WordPress:trunk May 22, 2026
54 of 58 checks passed
@github-project-automation github-project-automation Bot moved this from 🔎 Needs Review to ✅ Done in WordPress 7.0 Editor Tasks May 22, 2026
@github-actions github-actions Bot added this to the Gutenberg 23.3 milestone May 22, 2026
@talldan
Copy link
Copy Markdown
Contributor

talldan commented May 22, 2026

Looks like the PHP test caused a CI failure on trunk, I expect it might need to be gated by WordPress version or something. I can follow up on it.

@ramonjd
Copy link
Copy Markdown
Member

ramonjd commented May 22, 2026

Ah, block_core_shared_navigation_render_submenu_icon doesn't exist in older versions of WP in the test matrix of multiple WordPress versions.

I don't think that matrix runs on PRs.

I guess we could guard the test so it only runs when the shared core helper exists. I dunno.

		if ( ! function_exists( 'block_core_shared_navigation_render_submenu_icon' ) ) {
			$this->markTestSkipped( 'block_core_shared_navigation_render_submenu_icon() is not available in this WordPress version.' );
		}

@talldan
Copy link
Copy Markdown
Contributor

talldan commented May 22, 2026

It should be fixed via d8688b2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Backport to WP Minor Release Pull request that needs to be backported to a WordPress minor release Backwards Compatibility Issues or PRs that impact backwards compatability First-time Contributor Pull request opened by a first-time contributor to Gutenberg repository [Package] Block library /packages/block-library [Type] Regression Related to a regression in the latest release

Projects

Development

Successfully merging this pull request may close these issues.

6 participants