Icons: Add APIs for collection and icon registration#11559
Conversation
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
|
I am encountering the following error. This issue will likely be resolved once the Gutenberg ref is updated in wordpress-develop.
|
Align the icon registry's internal property with WordPress core's snake_case array-key convention by renaming the registered icon property from filePath to file_path. The conversion now happens only at the registration/mapping boundary in the constructor: the generated manifest keeps the upstream camelCase `filePath` key (as produced by Gutenberg), which is read and mapped to the internal `file_path` property when each icon is registered. This updates the registry validation, allowed property keys, `get_content()` lookup, and the related docblocks and error messages, while leaving the manifest and the copy:icon-library-manifest Grunt task untouched. Co-Authored-By: Claude <noreply@anthropic.com>
Add the public icon collection and icon registration APIs on top of the snake_case icon registry. Introduces WP_Icon_Collections_Registry, icons.php (wp_register_icon/wp_unregister_icon/wp_register_icon_collection and the default registration callbacks), the collection-scoped REST routes, and the related tests. Icon properties use the internal snake_case `file_path` key established in the icon registry; the Gutenberg manifest's upstream camelCase `filePath` key is read and mapped to `file_path` at the registration boundary. Co-Authored-By: Claude <noreply@anthropic.com>
de545bf to
d08cbfa
Compare
The icon registries warn via _doing_it_wrong() when a collection or icon is already registered. Because tests such as the Customize widgets suite fire `do_action( 'init' )` again after bootstrap, the default icon registration runs twice and triggers those notices, failing unrelated tests. Match the existing pattern used for font and connector registration by unhooking `_wp_register_default_icon_collections` and `_wp_register_default_icons` from `init` after the first run. Co-Authored-By: Claude <noreply@anthropic.com>
The REST icons controller now registers a per-collection route, `/wp/v2/icons/(?P<namespace>[a-z][a-z-]*)`. Add it to the expected routes list so test_expected_routes_in_schema reflects the registered routes. Co-Authored-By: Claude <noreply@anthropic.com>
The icons controller now exposes a `namespace` argument on the collection endpoint and a new per-collection route. Regenerate the QUnit fixtures so `git diff --exit-code` passes in CI. Co-Authored-By: Claude <noreply@anthropic.com>
|
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 Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Custom icons can be registered with a `file_path`, but the path was never checked before `file_get_contents()`, so a missing, unreadable, non-SVG, or non-string path emitted a raw PHP warning and a misleading "invalid SVG markup" error. Guard `get_content()` by resolving the path via `realpath()`, then requiring an `.svg` extension, a regular file, and readability, returning null with a clear message otherwise. Add tests covering valid and invalid file paths. Co-Authored-By: Claude <noreply@anthropic.com>
The collection slug pattern required a leading lowercase letter and rejected digits, which excluded legitimate plugin slugs such as `a8c` or vendor names containing numbers. Relax the validation to accept any combination of lowercase alphanumeric characters and hyphens, and update the error message and tests to match. Co-Authored-By: Claude <noreply@anthropic.com>
…tag. Several @SInCE 7.0.0 tags were accidentally dropped from properties and internal methods while reworking the Icons API, leaving docblocks without a version per the inline documentation standards. Restore them. Also remove the stray blank line after the opening PHP tag to match the rest of the core class files. Co-Authored-By: Claude <noreply@anthropic.com>
Derive the collection from the icon name instead of passing it separately, so an icon is always identified by a single namespaced name. The collection prefix is now required; a non-namespaced name is rejected via _doing_it_wrong(). This drops the $collection parameter from wp_register_icon()/wp_unregister_icon() and the "collection" icon property, and simplifies the cascade unregister when a collection is removed. The "core" collection is reserved for WordPress core icons. Co-Authored-By: Claude <noreply@anthropic.com>
# Conflicts: # src/wp-includes/class-wp-icons-registry.php # tests/phpunit/tests/icons/wpIconsRegistry.php
|
Update: The Gutenberg PR has been approved. This PR includes all changes for Gutenberg, but please let me know if there are any other points that need to be fixed. |
The REST controller tests depend on the default core icons, but those are registered only once on `init` and the registration is then unhooked, so once another suite resets the `WP_Icons_Registry` singleton in teardown the core icons are gone. The affected tests were therefore skipped. Re-register the default icons in `set_up()` when the registry is empty so the tests run deterministically regardless of execution order, and drop the `markTestSkipped()` guards. Co-Authored-By: Claude <noreply@anthropic.com>
Relax the icon slug validation so names can start with a lowercase letter or digit and contain lowercase letters, digits, hyphens, and underscores. Many real-world icon sets use digits (e.g. html5, 500px, w3c) and some consumers want underscores, which the previous regex rejected. Co-Authored-By: Claude <noreply@anthropic.com>
Port the equivalent of WordPress/gutenberg#79686 to core: - Add WP_REST_Icon_Collections_Controller exposing /wp/v2/icon-collections and /wp/v2/icon-collections/<slug> so the editor can group icons by collection in the icon picker. - Unify the naming rules for icon controllers and the collection registry on /^[a-z0-9]([a-z0-9_-]*[a-z0-9])?$/, allowing leading digits and underscores while still requiring alphanumeric boundaries. This fixes requests such as /wp/v2/icons/bootstrap-icons/0-circle-fill that previously 404'd. - Add unit tests for the new collection controller and extend the collection registry tests to cover the updated slug rules. Co-Authored-By: Claude <noreply@anthropic.com>
Replace the legacy false === strpos() idiom with str_contains(), which expresses the intent more clearly and avoids the loose/strict comparison pitfalls of the strpos()-against-false pattern. WordPress polyfills str_contains() in wp-includes/compat.php, so it is safe on PHP 7.4. Co-Authored-By: Claude <noreply@anthropic.com>
|
88f1834 is the improvements made in WordPress/gutenberg#79927. See https://github.com/WordPress/gutenberg/pull/79927/changes#r3534498017 for more details. |
| add_action( 'init', '_wp_register_default_font_collections' ); | ||
|
|
||
| // Icons. | ||
| add_action( 'init', '_wp_register_default_icon_collections', 0 ); |
There was a problem hiding this comment.
Why priority 0? I see this commit message:
Default icon collection registration runs at init priority 0 so collections exist before the Gutenberg registry override replays registered icons.
If this is still the motivation, shouldn't it be made very clear here?
There was a problem hiding this comment.
Apologies, that comment was not accurate. A priority 0 is intended to ensure the core collection is registered before all other icon collections. I believe a similar approach is being taken by create_initial_post_types and create_initial_taxonomies.
| ); | ||
| $content = $this->sanitize_icon_content( $content ); | ||
| $file_path = $this->registered_icons[ $icon_name ]['file_path'] ?? ''; | ||
| $is_stringy = is_string( $file_path ) || ( is_object( $file_path ) && method_exists( $file_path, '__toString' ) ); |
There was a problem hiding this comment.
The commit message in the original dev branch doesn't explain it, so:
What was the motivation for also accepting Stringable objects? The possibility of lazy evaluation?
There was a problem hiding this comment.
When I implemented the initial version in #77260, I based it on the block pattern registry implementation. The purpose was to prevent critical errors, as consumers can inject any type into the file_path parameter of wp_register_icon.
| $defaults = array( | ||
| 'description' => '', | ||
| ); |
There was a problem hiding this comment.
We're missing type validation for description, no?
| '/wp/v2/icons/(?P<namespace>[a-z][a-z-]*)', | ||
| '/wp/v2/icons/(?P<name>[a-z][a-z0-9-]*/[a-z][a-z0-9-]*)', |
There was a problem hiding this comment.
Looks like we'll need to update the regexes here?
There was a problem hiding this comment.
Nice catch, added the missing routes in 60bb86a.
| '/' . $this->rest_base . '/(?P<slug>[a-z0-9](?:[a-z0-9_-]*[a-z0-9])?)', | ||
| array( | ||
| 'args' => array( | ||
| 'slug' => array( |
There was a problem hiding this comment.
This concept is called "namespace" in the icons list route param, the icon field is called collection and here we call it slug. Should we be consistent with this?
There was a problem hiding this comment.
I believe unifying it under "collection" would be the most precise approach. Fixed in 8034efa
There was a problem hiding this comment.
I've already left a note in the other PR, but I'm cross-posting here so that we don't miss it:
As of WordPress/gutenberg#79681, we have a consumer using namespace:
The collection label was already type-checked, but the optional description was merged into the collection unvalidated, allowing non-string values to violate the documented @type string contract. Reject a non-string description with _doing_it_wrong() for consistency. Co-Authored-By: Claude <noreply@anthropic.com>
The icon name/namespace regexes were tightened and an icon-collections controller was added, but the expected route list in the schema test was not updated to match, causing the full-set comparison to fail. Co-Authored-By: Claude <noreply@anthropic.com>
The collection-scoped icons route used a `namespace` URL param whose value is actually a collection slug, which both collided with the REST API namespace concept and diverged from the icon `collection` field that names the same relationship. Rename it to `collection` so the same concept reads consistently across the icons endpoints. Co-Authored-By: Claude <noreply@anthropic.com>
|
Please note that the CI check will fail in this PR because a critical error occurs when the Gutenberg plugin is enabled. This is because, in Gutenberg 23.5, This CI error should be resolved if the Gutenberg ref is updated to version 23.6. |
What can we do to mitigate the problem? We wouldn't want to break WP trunk for Gutenberg users. It also means that users that for some reason are stuck on Gutenberg 23.5 (and several older versions) by the time that WP 7.1 comes are at risk of fatals, right? |
Yes. I think this error occurs if Gutenberg version 23.5 or lower is enabled on the WP trunk that includes this PR.
Another approach is to release a Gutenberg 23.5 minor version immediately, making the In any case, users need to use the latest Gutenberg to prevent critical errors. Do you have any other good ideas? Update: We plan to release Gutenberg 23.5.2 on Monday, July 13th. |
|
I would be fine with a minor release for this. FWIW I've been considering whether to have one for WordPress/gutenberg#79894 so let's add that to the minor, too, if possible. |
Rejects registering an icon collection when a non-string `description` is provided, matching the WordPress core validation. Refs WordPress/wordpress-develop#11559. Co-Authored-By: Claude <noreply@anthropic.com>
Aligns the Gutenberg icons REST controller with the WordPress core rename of the collection-scoping route param from `namespace` to `collection`. Refs WordPress/wordpress-develop#11559. Co-Authored-By: Claude <noreply@anthropic.com>
Rejects registering an icon collection when a non-string `description` is provided, matching the WordPress core validation. Refs WordPress/wordpress-develop#11559. Co-Authored-By: Claude <noreply@anthropic.com>
…ate description (#80113) * Icons: Rename the collection-scoping route param to `collection` Aligns the Gutenberg icons REST controller with the WordPress core rename of the collection-scoping route param from `namespace` to `collection`. Refs WordPress/wordpress-develop#11559. Co-Authored-By: Claude <noreply@anthropic.com> * Icons: Validate that the collection description is a string Rejects registering an icon collection when a non-string `description` is provided, matching the WordPress core validation. Refs WordPress/wordpress-develop#11559. Co-Authored-By: Claude <noreply@anthropic.com> * Icons: Use `collection` query param in the icon picker Follows the route param rename so the icon picker keeps filtering by collection once the core rename lands. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: mcsf <mcsf@git.wordpress.org>
…ate description (#80113) * Icons: Rename the collection-scoping route param to `collection` Aligns the Gutenberg icons REST controller with the WordPress core rename of the collection-scoping route param from `namespace` to `collection`. Refs WordPress/wordpress-develop#11559. Co-Authored-By: Claude <noreply@anthropic.com> * Icons: Validate that the collection description is a string Rejects registering an icon collection when a non-string `description` is provided, matching the WordPress core validation. Refs WordPress/wordpress-develop#11559. Co-Authored-By: Claude <noreply@anthropic.com> * Icons: Use `collection` query param in the icon picker Follows the route param rename so the icon picker keeps filtering by collection once the core rename lands. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: t-hamano <wildworks@git.wordpress.org> Co-authored-by: mcsf <mcsf@git.wordpress.org> Source: WordPress/gutenberg@800096f
|
Ditto—totally happy with a minor release. |
The icon REST routes changed on this branch: the collection-scoping route param was renamed from `namespace` to `collection`, the slug pattern was relaxed, and the `/wp/v2/icon-collections` route was added. The generated fixture was left stale, so the PHPUnit job regenerated it and failed the "version-controlled files are not modified" check. Co-Authored-By: Claude <noreply@anthropic.com>
file_pathkey in icon registry #12149Use of AI Tools
Claude Opus 4.6 (1M context)