From a51f22e45cdc42459468ace6bd895b993d851137 Mon Sep 17 00:00:00 2001 From: Aki Hamano Date: Thu, 11 Jun 2026 15:42:48 +0900 Subject: [PATCH 1/2] Icons: Use snake_case file_path internally in the icon registry. 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 --- src/wp-includes/class-wp-icons-registry.php | 24 ++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/wp-includes/class-wp-icons-registry.php b/src/wp-includes/class-wp-icons-registry.php index f82739fc5d91d..a442a2f99af94 100644 --- a/src/wp-includes/class-wp-icons-registry.php +++ b/src/wp-includes/class-wp-icons-registry.php @@ -81,8 +81,8 @@ protected function __construct() { $this->register( 'core/' . $icon_name, array( - 'label' => $icon_data['label'], - 'filePath' => $icons_directory . $icon_data['filePath'], + 'label' => $icon_data['label'], + 'file_path' => $icons_directory . $icon_data['filePath'], ) ); } @@ -97,11 +97,11 @@ protected function __construct() { * @param array $icon_properties { * List of properties for the icon. * - * @type string $label Required. A human-readable label for the icon. - * @type string $content Optional. SVG markup for the icon. - * If not provided, the content will be retrieved from the `filePath` if set. - * If both `content` and `filePath` are not set, the icon will not be registered. - * @type string $filePath Optional. The full path to the file containing the icon content. + * @type string $label Required. A human-readable label for the icon. + * @type string $content Optional. SVG markup for the icon. + * 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. * } * @return bool True if the icon was registered with success and false otherwise. */ @@ -115,7 +115,7 @@ protected function register( $icon_name, $icon_properties ) { return false; } - $allowed_keys = array_fill_keys( array( 'label', 'content', 'filePath' ), 1 ); + $allowed_keys = array_fill_keys( array( 'label', 'content', 'file_path' ), 1 ); foreach ( array_keys( $icon_properties ) as $key ) { if ( ! array_key_exists( $key, $allowed_keys ) ) { _doing_it_wrong( @@ -141,12 +141,12 @@ protected function register( $icon_name, $icon_properties ) { } if ( - ( ! isset( $icon_properties['content'] ) && ! isset( $icon_properties['filePath'] ) ) || - ( isset( $icon_properties['content'] ) && isset( $icon_properties['filePath'] ) ) + ( ! isset( $icon_properties['content'] ) && ! isset( $icon_properties['file_path'] ) ) || + ( isset( $icon_properties['content'] ) && isset( $icon_properties['file_path'] ) ) ) { _doing_it_wrong( __METHOD__, - __( 'Icons must provide either `content` or `filePath`.' ), + __( 'Icons must provide either `content` or `file_path`.' ), '7.0.0' ); return false; @@ -234,7 +234,7 @@ protected function sanitize_icon_content( $icon_content ) { protected function get_content( $icon_name ) { if ( ! isset( $this->registered_icons[ $icon_name ]['content'] ) ) { $content = file_get_contents( - $this->registered_icons[ $icon_name ]['filePath'] + $this->registered_icons[ $icon_name ]['file_path'] ); $content = $this->sanitize_icon_content( $content ); From d4988e37ec9cc65b57cf8b34e8efda8031d00357 Mon Sep 17 00:00:00 2001 From: Aki Hamano Date: Thu, 11 Jun 2026 11:47:04 +0900 Subject: [PATCH 2/2] Icons: Add show_in_rest support to gate REST API exposure Co-Authored-By: Claude --- src/wp-includes/class-wp-icons-registry.php | 23 ++++++++++++++----- .../class-wp-rest-icons-controller.php | 5 +++- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/wp-includes/class-wp-icons-registry.php b/src/wp-includes/class-wp-icons-registry.php index a442a2f99af94..bafd50826c8e4 100644 --- a/src/wp-includes/class-wp-icons-registry.php +++ b/src/wp-includes/class-wp-icons-registry.php @@ -83,6 +83,7 @@ protected function __construct() { array( 'label' => $icon_data['label'], 'file_path' => $icons_directory . $icon_data['filePath'], + 'show_in_rest' => ! empty( $icon_data['show_in_rest'] ), ) ); } @@ -97,11 +98,12 @@ protected function __construct() { * @param array $icon_properties { * List of properties for the icon. * - * @type string $label Required. A human-readable label for the icon. - * @type string $content Optional. SVG markup for the icon. - * 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 string $label Required. A human-readable label for the icon. + * @type string $content Optional. SVG markup for the icon. + * 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 $show_in_rest Optional. Whether the icon is available via the REST API. Default false. * } * @return bool True if the icon was registered with success and false otherwise. */ @@ -115,7 +117,7 @@ protected function register( $icon_name, $icon_properties ) { return false; } - $allowed_keys = array_fill_keys( array( 'label', 'content', 'file_path' ), 1 ); + $allowed_keys = array_fill_keys( array( 'label', 'content', 'file_path', 'show_in_rest' ), 1 ); foreach ( array_keys( $icon_properties ) as $key ) { if ( ! array_key_exists( $key, $allowed_keys ) ) { _doing_it_wrong( @@ -140,6 +142,15 @@ protected function register( $icon_name, $icon_properties ) { return false; } + if ( isset( $icon_properties['show_in_rest'] ) && ! is_bool( $icon_properties['show_in_rest'] ) ) { + _doing_it_wrong( + __METHOD__, + __( 'Icon "show_in_rest" property must be a boolean.' ), + '7.0.0' + ); + return false; + } + if ( ( ! isset( $icon_properties['content'] ) && ! isset( $icon_properties['file_path'] ) ) || ( isset( $icon_properties['content'] ) && isset( $icon_properties['file_path'] ) ) diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-icons-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-icons-controller.php index 91126b498d338..6fcdd3128d1d0 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-icons-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-icons-controller.php @@ -131,6 +131,9 @@ public function get_items( $request ) { $search = $request->get_param( 'search' ); $icons = WP_Icons_Registry::get_instance()->get_registered_icons( $search ); foreach ( $icons as $icon ) { + if ( empty( $icon['show_in_rest'] ) ) { + continue; + } $prepared_icon = $this->prepare_item_for_response( $icon, $request ); $response[] = $this->prepare_response_for_collection( $prepared_icon ); } @@ -167,7 +170,7 @@ public function get_icon( $name ) { $registry = WP_Icons_Registry::get_instance(); $icon = $registry->get_registered_icon( $name ); - if ( null === $icon ) { + if ( null === $icon || empty( $icon['show_in_rest'] ) ) { return new WP_Error( 'rest_icon_not_found', sprintf(