Skip to content

Icons: Fix collection unregister not removing icons after core added its own registry - #80292

Merged
t-hamano merged 5 commits into
trunkfrom
fix/icons-registry-shared-singleton
Jul 15, 2026
Merged

Icons: Fix collection unregister not removing icons after core added its own registry#80292
t-hamano merged 5 commits into
trunkfrom
fix/icons-registry-shared-singleton

Conversation

@t-hamano

@t-hamano t-hamano commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

What?

Fixes the icon registry so that unregistering an icon collection also removes its icons, which stopped working after WordPress core added its own icon registry.

Why?

WordPress core now ships its own icon registry classes (WP_Icons_Registry and WP_Icon_Collections_Registry). When core has them, Gutenberg's compatibility copies are skipped, and core's versions are used.

Gutenberg uses a subclass, WP_Icons_Registry_Gutenberg, and it kept its own separate singleton instance. Core's unregister a collection() logic looks up icons through the base class instance, but the rest of the code held a different instance. So the two sides no longer pointed at the same registry, and icons were not removed when their collection was unregistered.

This broke a unit test (WP_Test_Icon_Collections_Registry::test_unregister_collection_cascades_to_icons).

How?

Stop giving the subclass its own instance. By not redefining the $instance slot, the subclass and the base class share a single instance, so WP_Icons_Registry::get_instance() and WP_Icons_Registry_Gutenberg::get_instance() always return the same object.

get_instance() now upgrades an already-created base registry in place (keeping any non-core/ icons). This also let us drop the old reflection-based override.

Testing Instructions

To ensure this PR works on older WordPress versions, I have temporarily disabled the unit test exclusion rule. Once all CI checks pass, I will revert the matrix to its previous state before merging.

Use of AI Tools

This PR was written with the help of Claude Code (Anthropic). The investigation, fix, and description were reviewed and verified by the author.

t-hamano and others added 2 commits July 15, 2026 14:58
Core now ships WP_Icons_Registry and WP_Icon_Collections_Registry, so the
Gutenberg compat classes are skipped. Core's collection unregister cascade
calls WP_Icons_Registry::get_instance(), but WP_Icons_Registry_Gutenberg
redefined its own static $instance, splitting the singleton into two slots.
The cascade then operated on a different instance than the one callers held,
so icons were not removed when their collection was unregistered.

Stop redefining $instance so the subclass shares the base slot; both
WP_Icons_Registry::get_instance() and WP_Icons_Registry_Gutenberg::get_instance()
now resolve to the same object. get_instance() upgrades an existing base
registry in place, replaying non-core icons, which also removes the need for
the reflection-based override.

Co-Authored-By: Claude <noreply@anthropic.com>
Temporarily disable the test-php exclude matrix so PRs run against all PHP
versions and both the current and previous major WordPress versions. The
previous major WP lacks the core icon registry, exercising the Gutenberg
shim path this change must keep working. Revert before merge.

Co-Authored-By: Claude <noreply@anthropic.com>
@t-hamano t-hamano self-assigned this Jul 15, 2026
@t-hamano t-hamano added Gutenberg Plugin Issues or PRs related to Gutenberg Plugin management related efforts Backwards Compatibility Issues or PRs that impact backwards compatability [Type] Code Quality Issues or PRs that relate to code quality No Core Sync Required Indicates that any changes do not need to be synced to WordPress Core labels Jul 15, 2026
@t-hamano

Copy link
Copy Markdown
Contributor Author

Since the same error is occurring on the wp/7.1 branch, I will backport this to wp/7.1 as well.

@t-hamano t-hamano added the Backport to WP 7.1 Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta label Jul 15, 2026
Now that WP_Icons_Registry_Gutenberg shares the base singleton slot, resetting
the singleton in another suite's tear_down wipes the default icons that `init`
only registers once. The REST controller tests depend on those defaults, so
they failed with an empty registry when run after such a suite.

Mirror WordPress core's Tests_REST_WpRestIconsController::set_up() by
re-registering the default collection and icons when the registry is empty,
using the Gutenberg registration functions. Core already does this; the
Gutenberg test previously got away without it because the old dual-slot design
shielded the base registry from those resets.

Co-Authored-By: Claude <noreply@anthropic.com>
Comment on lines +27 to +40
public function set_up() {
parent::set_up();

/*
* Other suites reset the `WP_Icons_Registry` singleton, wiping the core icons that
* `init` only registers once. Re-register them when empty so order-dependent tests pass.
*/
if ( ! WP_Icon_Collections_Registry::get_instance()->is_registered( 'core' ) ) {
gutenberg_register_default_icon_collections();
}
if ( empty( WP_Icons_Registry::get_instance()->get_registered_icons() ) ) {
gutenberg_register_default_icons();
}
}

@t-hamano t-hamano Jul 15, 2026

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.

Same root cause as the REST controller test: sharing the base registry
singleton means another suite's tear_down reset wipes the default icons that
`init` registers only once. Because Gutenberg's test files sort
`class-wp-icon-collections-registry-test.php` (which resets the singleton)
before `class-wp-icon-test.php`, wp_get_icon() ran against an empty registry
and returned '' for every icon.

Add the same set_up() repopulation used by the REST controller test so these
tests are order-independent. In core the equivalent wpGetIcon test happens to
run before the resetting suite, so it needs no such guard; Gutenberg's file
naming reverses that order.

Co-Authored-By: Claude <noreply@anthropic.com>
@t-hamano

Copy link
Copy Markdown
Contributor Author

All unit tests have passed. I will revert the matrix and merge this once all CI checks are complete.

Revert the temporary full-matrix change now that CI has verified icon registry
compatibility across all PHP versions and both the current and previous major
WordPress versions. PRs go back to the reduced matrix (PHP 7.4/8.5, single
site, latest WP).

Co-Authored-By: Claude <noreply@anthropic.com>
@t-hamano
t-hamano marked this pull request as ready for review July 15, 2026 07:15
@t-hamano
t-hamano requested a review from spacedmonkey as a code owner July 15, 2026 07:15
@github-actions

Copy link
Copy Markdown

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: t-hamano <wildworks@git.wordpress.org>

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

@t-hamano
t-hamano merged commit d8d80b2 into trunk Jul 15, 2026
46 checks passed
@t-hamano
t-hamano deleted the fix/icons-registry-shared-singleton branch July 15, 2026 07:31
@github-actions github-actions Bot added this to the Gutenberg 23.7 milestone Jul 15, 2026
@github-actions github-actions Bot removed the Backport to WP 7.1 Beta/RC Pull request that needs to be backported to the WordPress major release that's currently in beta label Jul 15, 2026
gutenbergplugin pushed a commit that referenced this pull request Jul 15, 2026
…its own registry (#80292)

* Icons: Share the base registry singleton in WP_Icons_Registry_Gutenberg

Core now ships WP_Icons_Registry and WP_Icon_Collections_Registry, so the
Gutenberg compat classes are skipped. Core's collection unregister cascade
calls WP_Icons_Registry::get_instance(), but WP_Icons_Registry_Gutenberg
redefined its own static $instance, splitting the singleton into two slots.
The cascade then operated on a different instance than the one callers held,
so icons were not removed when their collection was unregistered.

Stop redefining $instance so the subclass shares the base slot; both
WP_Icons_Registry::get_instance() and WP_Icons_Registry_Gutenberg::get_instance()
now resolve to the same object. get_instance() upgrades an existing base
registry in place, replaying non-core icons, which also removes the need for
the reflection-based override.

Co-Authored-By: Claude <noreply@anthropic.com>

* [TEMP] CI: Run full unit-test matrix to verify icon registry WP compat

Temporarily disable the test-php exclude matrix so PRs run against all PHP
versions and both the current and previous major WordPress versions. The
previous major WP lacks the core icon registry, exercising the Gutenberg
shim path this change must keep working. Revert before merge.

Co-Authored-By: Claude <noreply@anthropic.com>

* Icons: Repopulate default icons in REST controller test set_up

Now that WP_Icons_Registry_Gutenberg shares the base singleton slot, resetting
the singleton in another suite's tear_down wipes the default icons that `init`
only registers once. The REST controller tests depend on those defaults, so
they failed with an empty registry when run after such a suite.

Mirror WordPress core's Tests_REST_WpRestIconsController::set_up() by
re-registering the default collection and icons when the registry is empty,
using the Gutenberg registration functions. Core already does this; the
Gutenberg test previously got away without it because the old dual-slot design
shielded the base registry from those resets.

Co-Authored-By: Claude <noreply@anthropic.com>

* Icons: Repopulate default icons in wp_get_icon() test set_up

Same root cause as the REST controller test: sharing the base registry
singleton means another suite's tear_down reset wipes the default icons that
`init` registers only once. Because Gutenberg's test files sort
`class-wp-icon-collections-registry-test.php` (which resets the singleton)
before `class-wp-icon-test.php`, wp_get_icon() ran against an empty registry
and returned '' for every icon.

Add the same set_up() repopulation used by the REST controller test so these
tests are order-independent. In core the equivalent wpGetIcon test happens to
run before the resetting suite, so it needs no such guard; Gutenberg's file
naming reverses that order.

Co-Authored-By: Claude <noreply@anthropic.com>

* CI: Restore test-php exclude matrix

Revert the temporary full-matrix change now that CI has verified icon registry
compatibility across all PHP versions and both the current and previous major
WordPress versions. PRs go back to the reduced matrix (PHP 7.4/8.5, single
site, latest WP).

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: t-hamano <wildworks@git.wordpress.org>
@github-actions github-actions Bot added the Backported to WP Core Pull request that has been successfully merged into WP Core label Jul 15, 2026
@github-actions

Copy link
Copy Markdown

I just cherry-picked this PR to the wp/7.1 branch to get it included in the next release: 54d2fe8

@t-hamano t-hamano added the Backport to Gutenberg RC Pull request that needs to be backported to a Gutenberg release candidate (RC) label Jul 15, 2026
pento pushed a commit to WordPress/wordpress-develop that referenced this pull request Jul 15, 2026
This updates the pinned commit hash of the Gutenberg repository from `2872d71cde528d82675f14862a1b84e2b8abbaea` to `e73c3c481db0650183f092af157f6e42efe9ee2d`.

A full list of changes included in this commit can be found on GitHub: 
WordPress/gutenberg@2872d71...e73c3c4

- Icon block: Show text and background color controls by default. (WordPress/gutenberg#80251)
- fix: set dataviews popover hover text color (WordPress/gutenberg#80105)
- DataViews: Fix the unintended gap between `list` layout items when `groupBy` is set (WordPress/gutenberg#80254)
- DataViews: Fix the `list` layout ignoring some settings when `groupBy` is set (WordPress/gutenberg#80255)
- DataViews: Add shift-click range selection (WordPress/gutenberg#80046)
- Responsive Editing: support editing pattern styles (WordPress/gutenberg#80233)
- Tab List: Add toolbar buttons to reorder tabs (WordPress/gutenberg#80107)
- Hide color controls for Navigation and Social Icons when viewport states are active (WordPress/gutenberg#80289)
- Icons: Fix collection unregister not removing icons after core added its own registry (WordPress/gutenberg#80292)
- Notes: increase contrast between avatar border colors (WordPress/gutenberg#80285)
- Playlist: Fix track insertion (WordPress/gutenberg#80200)
- Fix: Allow icon labels to wrap with word breaks and no ellipsis (WordPress/gutenberg#80309)
- Core Abilities: Restore the ready promise and lazy-load via dynamic import (WordPress/gutenberg#79155)

Props wildworks.
See #65529.

git-svn-id: https://develop.svn.wordpress.org/trunk@62757 602fd350-edb4-49c9-b593-d223f7449a82
markjaquith pushed a commit to markjaquith/WordPress that referenced this pull request Jul 15, 2026
This updates the pinned commit hash of the Gutenberg repository from `2872d71cde528d82675f14862a1b84e2b8abbaea` to `e73c3c481db0650183f092af157f6e42efe9ee2d`.

A full list of changes included in this commit can be found on GitHub: 
WordPress/gutenberg@2872d71...e73c3c4

- Icon block: Show text and background color controls by default. (WordPress/gutenberg#80251)
- fix: set dataviews popover hover text color (WordPress/gutenberg#80105)
- DataViews: Fix the unintended gap between `list` layout items when `groupBy` is set (WordPress/gutenberg#80254)
- DataViews: Fix the `list` layout ignoring some settings when `groupBy` is set (WordPress/gutenberg#80255)
- DataViews: Add shift-click range selection (WordPress/gutenberg#80046)
- Responsive Editing: support editing pattern styles (WordPress/gutenberg#80233)
- Tab List: Add toolbar buttons to reorder tabs (WordPress/gutenberg#80107)
- Hide color controls for Navigation and Social Icons when viewport states are active (WordPress/gutenberg#80289)
- Icons: Fix collection unregister not removing icons after core added its own registry (WordPress/gutenberg#80292)
- Notes: increase contrast between avatar border colors (WordPress/gutenberg#80285)
- Playlist: Fix track insertion (WordPress/gutenberg#80200)
- Fix: Allow icon labels to wrap with word breaks and no ellipsis (WordPress/gutenberg#80309)
- Core Abilities: Restore the ready promise and lazy-load via dynamic import (WordPress/gutenberg#79155)

Props wildworks.
See #65529.
Built from https://develop.svn.wordpress.org/trunk@62757


git-svn-id: http://core.svn.wordpress.org/trunk@62041 1a063a9b-81f0-0310-95a4-ce76da25c4cd
t-hamano added a commit that referenced this pull request Jul 21, 2026
…its own registry (#80292)

* Icons: Share the base registry singleton in WP_Icons_Registry_Gutenberg

Core now ships WP_Icons_Registry and WP_Icon_Collections_Registry, so the
Gutenberg compat classes are skipped. Core's collection unregister cascade
calls WP_Icons_Registry::get_instance(), but WP_Icons_Registry_Gutenberg
redefined its own static $instance, splitting the singleton into two slots.
The cascade then operated on a different instance than the one callers held,
so icons were not removed when their collection was unregistered.

Stop redefining $instance so the subclass shares the base slot; both
WP_Icons_Registry::get_instance() and WP_Icons_Registry_Gutenberg::get_instance()
now resolve to the same object. get_instance() upgrades an existing base
registry in place, replaying non-core icons, which also removes the need for
the reflection-based override.

Co-Authored-By: Claude <noreply@anthropic.com>

* [TEMP] CI: Run full unit-test matrix to verify icon registry WP compat

Temporarily disable the test-php exclude matrix so PRs run against all PHP
versions and both the current and previous major WordPress versions. The
previous major WP lacks the core icon registry, exercising the Gutenberg
shim path this change must keep working. Revert before merge.

Co-Authored-By: Claude <noreply@anthropic.com>

* Icons: Repopulate default icons in REST controller test set_up

Now that WP_Icons_Registry_Gutenberg shares the base singleton slot, resetting
the singleton in another suite's tear_down wipes the default icons that `init`
only registers once. The REST controller tests depend on those defaults, so
they failed with an empty registry when run after such a suite.

Mirror WordPress core's Tests_REST_WpRestIconsController::set_up() by
re-registering the default collection and icons when the registry is empty,
using the Gutenberg registration functions. Core already does this; the
Gutenberg test previously got away without it because the old dual-slot design
shielded the base registry from those resets.

Co-Authored-By: Claude <noreply@anthropic.com>

* Icons: Repopulate default icons in wp_get_icon() test set_up

Same root cause as the REST controller test: sharing the base registry
singleton means another suite's tear_down reset wipes the default icons that
`init` registers only once. Because Gutenberg's test files sort
`class-wp-icon-collections-registry-test.php` (which resets the singleton)
before `class-wp-icon-test.php`, wp_get_icon() ran against an empty registry
and returned '' for every icon.

Add the same set_up() repopulation used by the REST controller test so these
tests are order-independent. In core the equivalent wpGetIcon test happens to
run before the resetting suite, so it needs no such guard; Gutenberg's file
naming reverses that order.

Co-Authored-By: Claude <noreply@anthropic.com>

* CI: Restore test-php exclude matrix

Revert the temporary full-matrix change now that CI has verified icon registry
compatibility across all PHP versions and both the current and previous major
WordPress versions. PRs go back to the reduced matrix (PHP 7.4/8.5, single
site, latest WP).

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: t-hamano <wildworks@git.wordpress.org>
@t-hamano

Copy link
Copy Markdown
Contributor Author

I just cherry-picked this PR to the release/23.6 branch to get it included in the next release: a62d375

@t-hamano t-hamano removed the Backport to Gutenberg RC Pull request that needs to be backported to a Gutenberg release candidate (RC) label Jul 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Backported to WP Core Pull request that has been successfully merged into WP Core Backwards Compatibility Issues or PRs that impact backwards compatability Gutenberg Plugin Issues or PRs related to Gutenberg Plugin management related efforts No Core Sync Required Indicates that any changes do not need to be synced to WordPress Core [Type] Code Quality Issues or PRs that relate to code quality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Sponsor
SponsoredKunjungi sekarang
Promo