Commit bb56ae22a6 for wordpress.org
commit bb56ae22a634316c5605c2fcc55ee76ee8666847
Author: wildworks <wildworks@git.wordpress.org>
Date: Wed Oct 7 06:46:00 2026 +0000
Icons: Move `public` to collections and add `core-admin` collection.
Visibility is now controlled per icon collection instead of per icon. Icons in a non-public collection are not exposed through the REST API or selectable in the Icon block, but remain available to server-side rendering.
Adds a non-public `core-admin` collection for the icons used by the admin interface, so that a plugin unregistering the `core` collection to hide the default icons from the Icon block no longer removes the icons rendered in the dashboard.
Developed in: https://github.com/WordPress/wordpress-develop/pull/13625
Follow-up to [63625].
Props mcsf, peterwilsoncc, wildworks.
Fixes #66114.
Built from https://develop.svn.wordpress.org/trunk@64224
git-svn-id: http://core.svn.wordpress.org/trunk@63375 1a063a9b-81f0-0310-95a4-ce76da25c4cd
diff --git a/wp-includes/class-wp-icon-collections-registry.php b/wp-includes/class-wp-icon-collections-registry.php
index 0c59011977..dcfe842285 100644
--- a/wp-includes/class-wp-icon-collections-registry.php
+++ b/wp-includes/class-wp-icon-collections-registry.php
@@ -37,6 +37,7 @@ class WP_Icon_Collections_Registry {
* Registers an icon collection.
*
* @since 7.1.0
+ * @since 7.2.0 Added the `public` property.
*
* @param string $collection_slug Icon collection slug.
* @param array $collection_properties {
@@ -44,6 +45,10 @@ class WP_Icon_Collections_Registry {
*
* @type string $label Required. A human-readable label for the icon collection.
* @type string $description Optional. A human-readable description for the icon collection.
+ * @type bool $public Optional. Whether the collection and its icons are exposed through
+ * the REST API, and therefore selectable in the editor's icon picker.
+ * Icons in non-public collections stay available to server-side code
+ * via {@see wp_get_icon()}. Default true.
* }
* @return bool True if the collection was registered successfully, false otherwise.
*/
@@ -84,7 +89,7 @@ class WP_Icon_Collections_Registry {
return false;
}
- $allowed_keys = array_fill_keys( array( 'label', 'description' ), 1 );
+ $allowed_keys = array_fill_keys( array( 'label', 'description', 'public' ), 1 );
foreach ( array_keys( $collection_properties ) as $key ) {
if ( ! array_key_exists( $key, $allowed_keys ) ) {
_doing_it_wrong(
@@ -118,8 +123,18 @@ class WP_Icon_Collections_Registry {
return false;
}
+ if ( array_key_exists( 'public', $collection_properties ) && ! is_bool( $collection_properties['public'] ) ) {
+ _doing_it_wrong(
+ __METHOD__,
+ __( 'Icon collection public property must be a boolean.' ),
+ '7.2.0'
+ );
+ return false;
+ }
+
$defaults = array(
'description' => '',
+ 'public' => true,
);
$collection = array_merge(
diff --git a/wp-includes/class-wp-icons-registry.php b/wp-includes/class-wp-icons-registry.php
index 745e369e7c..361506a67e 100644
--- a/wp-includes/class-wp-icons-registry.php
+++ b/wp-includes/class-wp-icons-registry.php
@@ -46,7 +46,7 @@ class WP_Icons_Registry {
*
* @since 7.0.0
* @since 7.1.0 The icon name must be namespaced in the form "collection/icon-name".
- * @since 7.2.0 Added the `public` and `keywords` properties.
+ * @since 7.2.0 Added the `keywords` property.
*
* @param string $icon_name Namespaced icon name in the form "collection/icon-name"
* (e.g. "core/arrow-left").
@@ -58,10 +58,6 @@ class WP_Icons_Registry {
* If not provided, the content will be retrieved from the `file_path` if set.
* If both `content` and `file_path` are not set, the icon will not be registered.
* @type string $file_path Optional. The full path to the file containing the icon content.
- * @type bool $public Optional. Whether the icon is exposed through the REST API, and
- * therefore selectable in the editor's icon picker. Non-public icons
- * stay available to server-side code via {@see wp_get_icon()}.
- * Default true.
* @type string[] $keywords Optional. Additional search terms for the icon, matched by
* `get_registered_icons()` alongside the name and label.
* }
@@ -108,7 +104,7 @@ class WP_Icons_Registry {
return false;
}
- $allowed_keys = array_fill_keys( array( 'label', 'content', 'file_path', 'public', 'keywords' ), 1 );
+ $allowed_keys = array_fill_keys( array( 'label', 'content', 'file_path', 'keywords' ), 1 );
foreach ( array_keys( $icon_properties ) as $key ) {
if ( ! array_key_exists( $key, $allowed_keys ) ) {
_doing_it_wrong(
@@ -146,15 +142,6 @@ class WP_Icons_Registry {
return false;
}
- if ( isset( $icon_properties['public'] ) && ! is_bool( $icon_properties['public'] ) ) {
- _doing_it_wrong(
- __METHOD__,
- __( 'Icon public property must be a boolean.' ),
- '7.2.0'
- );
- return false;
- }
-
if ( array_key_exists( 'keywords', $icon_properties ) ) {
if ( ! is_array( $icon_properties['keywords'] ) ) {
_doing_it_wrong(
diff --git a/wp-includes/icons.php b/wp-includes/icons.php
index e6916aaed1..05588c3cf4 100644
--- a/wp-includes/icons.php
+++ b/wp-includes/icons.php
@@ -11,6 +11,7 @@
* Registers a new icon collection.
*
* @since 7.1.0
+ * @since 7.2.0 Added the `public` property.
*
* @param string $slug Icon collection slug.
* @param array $args {
@@ -18,6 +19,10 @@
*
* @type string $label Required. A human-readable label for the icon collection.
* @type string $description Optional. A human-readable description for the icon collection.
+ * @type bool $public Optional. Whether the collection and its icons are exposed through
+ * the REST API, and therefore selectable in the editor's icon picker.
+ * Icons in non-public collections stay available to server-side code
+ * via {@see wp_get_icon()}. Default true.
* }
* @return bool True if the icon collection was registered successfully, else false.
*/
@@ -41,13 +46,13 @@ function wp_unregister_icon_collection( $slug ) {
* Registers a new icon.
*
* @since 7.1.0
- * @since 7.2.0 Added the `public` and `keywords` properties.
+ * @since 7.2.0 Added the `keywords` property.
*
* @param string $icon_name Namespaced icon name in the form "collection/icon-name"
- * (e.g. "my-plugin/arrow-left"). The "core" collection is
- * reserved for WordPress core icons; third-party code should
- * register icons under its own collection rather than the
- * "core" collection.
+ * (e.g. "my-plugin/arrow-left"). The "core" and "core-admin"
+ * collections are reserved for WordPress core icons; third-party
+ * code should register icons under its own collection rather than
+ * a reserved one.
* @param array $args {
* List of properties for the icon.
*
@@ -56,10 +61,6 @@ function wp_unregister_icon_collection( $slug ) {
* If not provided, the content will be retrieved from the `file_path` if set.
* If both `content` and `file_path` are not set, the icon will not be registered.
* @type string $file_path Optional. The full path to the file containing the icon content.
- * @type bool $public Optional. Whether the icon is exposed through the REST API, and
- * therefore selectable in the editor's icon picker. Non-public icons
- * stay available to server-side code via {@see wp_get_icon()}.
- * Default true.
* @type string[] $keywords Optional. Additional search terms for the icon, matched by
* `get_registered_icons()` alongside the name and label.
* }
@@ -96,10 +97,18 @@ function _wp_register_default_icon_collections() {
'description' => __( 'Default icon collection.' ),
)
);
+ wp_register_icon_collection(
+ 'core-admin',
+ array(
+ 'label' => __( 'WordPress Admin' ),
+ 'description' => __( 'Icon collection used by the WordPress admin interface.' ),
+ 'public' => false,
+ )
+ );
}
/**
- * Registers the default core icons from the manifest.
+ * Registers the default core and core-admin icons from the manifest.
*
* @since 7.1.0
* @access private
@@ -139,20 +148,27 @@ function _wp_register_default_icons() {
return;
}
+ if ( empty( $icon_data['collections'] ) || ! is_array( $icon_data['collections'] ) ) {
+ _doing_it_wrong(
+ __FUNCTION__,
+ __( 'Core icon collection manifest must provide a non-empty "collections" array for each icon.' ),
+ '7.2.0'
+ );
+ return;
+ }
+
$icon_args = array(
'label' => $icon_data['label'],
'file_path' => $icons_directory . $icon_data['filePath'],
);
- if ( isset( $icon_data['public'] ) ) {
- $icon_args['public'] = $icon_data['public'];
- }
-
if ( isset( $icon_data['keywords'] ) ) {
$icon_args['keywords'] = $icon_data['keywords'];
}
- wp_register_icon( 'core/' . $icon_name, $icon_args );
+ foreach ( $icon_data['collections'] as $collection_slug ) {
+ wp_register_icon( $collection_slug . '/' . $icon_name, $icon_args );
+ }
}
}
diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-icon-collections-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-icon-collections-controller.php
index 9e8a935b94..ab6c83f2ea 100644
--- a/wp-includes/rest-api/endpoints/class-wp-rest-icon-collections-controller.php
+++ b/wp-includes/rest-api/endpoints/class-wp-rest-icon-collections-controller.php
@@ -120,6 +120,7 @@ class WP_REST_Icon_Collections_Controller extends WP_REST_Controller {
* Retrieves all icon collections.
*
* @since 7.1.0
+ * @since 7.2.0 Non-public collections are omitted.
*
* @param WP_REST_Request $request Full details about the request.
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
@@ -128,6 +129,9 @@ class WP_REST_Icon_Collections_Controller extends WP_REST_Controller {
$response = array();
$collections = WP_Icon_Collections_Registry::get_instance()->get_all_registered();
foreach ( $collections as $collection ) {
+ if ( ! $collection['public'] ) {
+ continue;
+ }
$prepared_collection = $this->prepare_item_for_response( $collection, $request );
$response[] = $this->prepare_response_for_collection( $prepared_collection );
}
@@ -156,6 +160,7 @@ class WP_REST_Icon_Collections_Controller extends WP_REST_Controller {
* Retrieves a specific icon collection from the registry.
*
* @since 7.1.0
+ * @since 7.2.0 Non-public collections are reported as not found.
*
* @param string $slug Icon collection slug.
* @return array|WP_Error Icon collection data on success, or WP_Error object on failure.
@@ -164,7 +169,7 @@ class WP_REST_Icon_Collections_Controller extends WP_REST_Controller {
$registry = WP_Icon_Collections_Registry::get_instance();
$collection = $registry->get_registered( $slug );
- if ( null === $collection ) {
+ if ( null === $collection || ! $collection['public'] ) {
return new WP_Error(
'rest_icon_collection_not_found',
sprintf(
diff --git a/wp-includes/rest-api/endpoints/class-wp-rest-icons-controller.php b/wp-includes/rest-api/endpoints/class-wp-rest-icons-controller.php
index 610cc58230..afcf80f4b2 100644
--- a/wp-includes/rest-api/endpoints/class-wp-rest-icons-controller.php
+++ b/wp-includes/rest-api/endpoints/class-wp-rest-icons-controller.php
@@ -143,15 +143,17 @@ class WP_REST_Icons_Controller extends WP_REST_Controller {
*
* @since 7.0.0
* @since 7.1.0 Supports filtering by collection.
- * @since 7.2.0 Icons registered as non-public are omitted.
+ * @since 7.2.0 Icons belonging to non-public collections are omitted.
*
* @param WP_REST_Request $request Full details about the request.
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
*/
public function get_items( $request ) {
- $collection = $request->get_param( 'collection' );
+ $collection = $request->get_param( 'collection' );
+ $collections_registry = WP_Icon_Collections_Registry::get_instance();
+ $registered_collection = null !== $collection ? $collections_registry->get_registered( $collection ) : null;
- if ( null !== $collection && ! WP_Icon_Collections_Registry::get_instance()->is_registered( $collection ) ) {
+ if ( null !== $collection && ( null === $registered_collection || ! $registered_collection['public'] ) ) {
return new WP_Error(
'rest_icon_collection_not_found',
sprintf(
@@ -168,10 +170,11 @@ class WP_REST_Icons_Controller extends WP_REST_Controller {
$icons = WP_Icons_Registry::get_instance()->get_registered_icons( $search );
foreach ( $icons as $icon ) {
- if ( false === ( $icon['public'] ?? true ) ) {
+ if ( null !== $collection && ( ! isset( $icon['collection'] ) || $icon['collection'] !== $collection ) ) {
continue;
}
- if ( null !== $collection && ( ! isset( $icon['collection'] ) || $icon['collection'] !== $collection ) ) {
+ $icon_collection = isset( $icon['collection'] ) ? $collections_registry->get_registered( $icon['collection'] ) : null;
+ if ( null === $icon_collection || ! $icon_collection['public'] ) {
continue;
}
$prepared_icon = $this->prepare_item_for_response( $icon, $request );
@@ -202,7 +205,7 @@ class WP_REST_Icons_Controller extends WP_REST_Controller {
* Retrieves a specific icon from the registry.
*
* @since 7.0.0
- * @since 7.2.0 Icons registered as non-public are reported as not found.
+ * @since 7.2.0 Icons belonging to non-public collections are reported as not found.
*
* @param string $name Icon name.
* @return array|WP_Error Icon data on success, or WP_Error object on failure.
@@ -211,7 +214,11 @@ class WP_REST_Icons_Controller extends WP_REST_Controller {
$registry = WP_Icons_Registry::get_instance();
$icon = $registry->get_registered_icon( $name );
- if ( null === $icon || false === ( $icon['public'] ?? true ) ) {
+ $collection = null !== $icon && isset( $icon['collection'] )
+ ? WP_Icon_Collections_Registry::get_instance()->get_registered( $icon['collection'] )
+ : null;
+
+ if ( null === $icon || null === $collection || ! $collection['public'] ) {
return new WP_Error(
'rest_icon_not_found',
sprintf(
diff --git a/wp-includes/version.php b/wp-includes/version.php
index 9ca6b49545..fec9d394b2 100644
--- a/wp-includes/version.php
+++ b/wp-includes/version.php
@@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
-$wp_version = '7.2-alpha-64223';
+$wp_version = '7.2-alpha-64224';
/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.