Skip to content

Commit 6f89b39

Browse files
authored
Merge branch 'trunk' into feat/icon-block-pattern-overrides
2 parents fd64cc0 + da76470 commit 6f89b39

10 files changed

Lines changed: 387 additions & 105 deletions

‎src/wp-includes/class-wp-icon-collections-registry.php‎

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,18 @@ class WP_Icon_Collections_Registry {
3737
* Registers an icon collection.
3838
*
3939
* @since 7.1.0
40+
* @since 7.2.0 Added the `public` property.
4041
*
4142
* @param string $collection_slug Icon collection slug.
4243
* @param array $collection_properties {
4344
* List of properties for the icon collection.
4445
*
4546
* @type string $label Required. A human-readable label for the icon collection.
4647
* @type string $description Optional. A human-readable description for the icon collection.
48+
* @type bool $public Optional. Whether the collection and its icons are exposed through
49+
* the REST API, and therefore selectable in the editor's icon picker.
50+
* Icons in non-public collections stay available to server-side code
51+
* via {@see wp_get_icon()}. Default true.
4752
* }
4853
* @return bool True if the collection was registered successfully, false otherwise.
4954
*/
@@ -84,7 +89,7 @@ public function register( $collection_slug, $collection_properties ) {
8489
return false;
8590
}
8691

87-
$allowed_keys = array_fill_keys( array( 'label', 'description' ), 1 );
92+
$allowed_keys = array_fill_keys( array( 'label', 'description', 'public' ), 1 );
8893
foreach ( array_keys( $collection_properties ) as $key ) {
8994
if ( ! array_key_exists( $key, $allowed_keys ) ) {
9095
_doing_it_wrong(
@@ -118,8 +123,18 @@ public function register( $collection_slug, $collection_properties ) {
118123
return false;
119124
}
120125

126+
if ( array_key_exists( 'public', $collection_properties ) && ! is_bool( $collection_properties['public'] ) ) {
127+
_doing_it_wrong(
128+
__METHOD__,
129+
__( 'Icon collection public property must be a boolean.' ),
130+
'7.2.0'
131+
);
132+
return false;
133+
}
134+
121135
$defaults = array(
122136
'description' => '',
137+
'public' => true,
123138
);
124139

125140
$collection = array_merge(

‎src/wp-includes/class-wp-icons-registry.php‎

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ protected function __construct() {}
4646
*
4747
* @since 7.0.0
4848
* @since 7.1.0 The icon name must be namespaced in the form "collection/icon-name".
49-
* @since 7.2.0 Added the `public` and `keywords` properties.
49+
* @since 7.2.0 Added the `keywords` property.
5050
*
5151
* @param string $icon_name Namespaced icon name in the form "collection/icon-name"
5252
* (e.g. "core/arrow-left").
@@ -58,10 +58,6 @@ protected function __construct() {}
5858
* If not provided, the content will be retrieved from the `file_path` if set.
5959
* If both `content` and `file_path` are not set, the icon will not be registered.
6060
* @type string $file_path Optional. The full path to the file containing the icon content.
61-
* @type bool $public Optional. Whether the icon is exposed through the REST API, and
62-
* therefore selectable in the editor's icon picker. Non-public icons
63-
* stay available to server-side code via {@see wp_get_icon()}.
64-
* Default true.
6561
* @type string[] $keywords Optional. Additional search terms for the icon, matched by
6662
* `get_registered_icons()` alongside the name and label.
6763
* }
@@ -108,7 +104,7 @@ public function register( $icon_name, $icon_properties ) {
108104
return false;
109105
}
110106

111-
$allowed_keys = array_fill_keys( array( 'label', 'content', 'file_path', 'public', 'keywords' ), 1 );
107+
$allowed_keys = array_fill_keys( array( 'label', 'content', 'file_path', 'keywords' ), 1 );
112108
foreach ( array_keys( $icon_properties ) as $key ) {
113109
if ( ! array_key_exists( $key, $allowed_keys ) ) {
114110
_doing_it_wrong(
@@ -146,15 +142,6 @@ public function register( $icon_name, $icon_properties ) {
146142
return false;
147143
}
148144

149-
if ( isset( $icon_properties['public'] ) && ! is_bool( $icon_properties['public'] ) ) {
150-
_doing_it_wrong(
151-
__METHOD__,
152-
__( 'Icon public property must be a boolean.' ),
153-
'7.2.0'
154-
);
155-
return false;
156-
}
157-
158145
if ( array_key_exists( 'keywords', $icon_properties ) ) {
159146
if ( ! is_array( $icon_properties['keywords'] ) ) {
160147
_doing_it_wrong(

‎src/wp-includes/icons.php‎

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,18 @@
1111
* Registers a new icon collection.
1212
*
1313
* @since 7.1.0
14+
* @since 7.2.0 Added the `public` property.
1415
*
1516
* @param string $slug Icon collection slug.
1617
* @param array $args {
1718
* Arguments for registering an icon collection.
1819
*
1920
* @type string $label Required. A human-readable label for the icon collection.
2021
* @type string $description Optional. A human-readable description for the icon collection.
22+
* @type bool $public Optional. Whether the collection and its icons are exposed through
23+
* the REST API, and therefore selectable in the editor's icon picker.
24+
* Icons in non-public collections stay available to server-side code
25+
* via {@see wp_get_icon()}. Default true.
2126
* }
2227
* @return bool True if the icon collection was registered successfully, else false.
2328
*/
@@ -41,13 +46,13 @@ function wp_unregister_icon_collection( $slug ) {
4146
* Registers a new icon.
4247
*
4348
* @since 7.1.0
44-
* @since 7.2.0 Added the `public` and `keywords` properties.
49+
* @since 7.2.0 Added the `keywords` property.
4550
*
4651
* @param string $icon_name Namespaced icon name in the form "collection/icon-name"
47-
* (e.g. "my-plugin/arrow-left"). The "core" collection is
48-
* reserved for WordPress core icons; third-party code should
49-
* register icons under its own collection rather than the
50-
* "core" collection.
52+
* (e.g. "my-plugin/arrow-left"). The "core" and "core-admin"
53+
* collections are reserved for WordPress core icons; third-party
54+
* code should register icons under its own collection rather than
55+
* a reserved one.
5156
* @param array $args {
5257
* List of properties for the icon.
5358
*
@@ -56,10 +61,6 @@ function wp_unregister_icon_collection( $slug ) {
5661
* If not provided, the content will be retrieved from the `file_path` if set.
5762
* If both `content` and `file_path` are not set, the icon will not be registered.
5863
* @type string $file_path Optional. The full path to the file containing the icon content.
59-
* @type bool $public Optional. Whether the icon is exposed through the REST API, and
60-
* therefore selectable in the editor's icon picker. Non-public icons
61-
* stay available to server-side code via {@see wp_get_icon()}.
62-
* Default true.
6364
* @type string[] $keywords Optional. Additional search terms for the icon, matched by
6465
* `get_registered_icons()` alongside the name and label.
6566
* }
@@ -96,10 +97,18 @@ function _wp_register_default_icon_collections() {
9697
'description' => __( 'Default icon collection.' ),
9798
)
9899
);
100+
wp_register_icon_collection(
101+
'core-admin',
102+
array(
103+
'label' => __( 'WordPress Admin' ),
104+
'description' => __( 'Icon collection used by the WordPress admin interface.' ),
105+
'public' => false,
106+
)
107+
);
99108
}
100109

101110
/**
102-
* Registers the default core icons from the manifest.
111+
* Registers the default core and core-admin icons from the manifest.
103112
*
104113
* @since 7.1.0
105114
* @access private
@@ -139,20 +148,27 @@ function _wp_register_default_icons() {
139148
return;
140149
}
141150

151+
if ( empty( $icon_data['collections'] ) || ! is_array( $icon_data['collections'] ) ) {
152+
_doing_it_wrong(
153+
__FUNCTION__,
154+
__( 'Core icon collection manifest must provide a non-empty "collections" array for each icon.' ),
155+
'7.2.0'
156+
);
157+
return;
158+
}
159+
142160
$icon_args = array(
143161
'label' => $icon_data['label'],
144162
'file_path' => $icons_directory . $icon_data['filePath'],
145163
);
146164

147-
if ( isset( $icon_data['public'] ) ) {
148-
$icon_args['public'] = $icon_data['public'];
149-
}
150-
151165
if ( isset( $icon_data['keywords'] ) ) {
152166
$icon_args['keywords'] = $icon_data['keywords'];
153167
}
154168

155-
wp_register_icon( 'core/' . $icon_name, $icon_args );
169+
foreach ( $icon_data['collections'] as $collection_slug ) {
170+
wp_register_icon( $collection_slug . '/' . $icon_name, $icon_args );
171+
}
156172
}
157173
}
158174

‎src/wp-includes/rest-api/endpoints/class-wp-rest-icon-collections-controller.php‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ public function get_item_permissions_check( $request ) {
120120
* Retrieves all icon collections.
121121
*
122122
* @since 7.1.0
123+
* @since 7.2.0 Non-public collections are omitted.
123124
*
124125
* @param WP_REST_Request $request Full details about the request.
125126
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
@@ -128,6 +129,9 @@ public function get_items( $request ) {
128129
$response = array();
129130
$collections = WP_Icon_Collections_Registry::get_instance()->get_all_registered();
130131
foreach ( $collections as $collection ) {
132+
if ( ! $collection['public'] ) {
133+
continue;
134+
}
131135
$prepared_collection = $this->prepare_item_for_response( $collection, $request );
132136
$response[] = $this->prepare_response_for_collection( $prepared_collection );
133137
}
@@ -156,6 +160,7 @@ public function get_item( $request ) {
156160
* Retrieves a specific icon collection from the registry.
157161
*
158162
* @since 7.1.0
163+
* @since 7.2.0 Non-public collections are reported as not found.
159164
*
160165
* @param string $slug Icon collection slug.
161166
* @return array|WP_Error Icon collection data on success, or WP_Error object on failure.
@@ -164,7 +169,7 @@ public function get_icon_collection( $slug ) {
164169
$registry = WP_Icon_Collections_Registry::get_instance();
165170
$collection = $registry->get_registered( $slug );
166171

167-
if ( null === $collection ) {
172+
if ( null === $collection || ! $collection['public'] ) {
168173
return new WP_Error(
169174
'rest_icon_collection_not_found',
170175
sprintf(

‎src/wp-includes/rest-api/endpoints/class-wp-rest-icons-controller.php‎

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -143,15 +143,17 @@ public function get_item_permissions_check( $request ) {
143143
*
144144
* @since 7.0.0
145145
* @since 7.1.0 Supports filtering by collection.
146-
* @since 7.2.0 Icons registered as non-public are omitted.
146+
* @since 7.2.0 Icons belonging to non-public collections are omitted.
147147
*
148148
* @param WP_REST_Request $request Full details about the request.
149149
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
150150
*/
151151
public function get_items( $request ) {
152-
$collection = $request->get_param( 'collection' );
152+
$collection = $request->get_param( 'collection' );
153+
$collections_registry = WP_Icon_Collections_Registry::get_instance();
154+
$registered_collection = null !== $collection ? $collections_registry->get_registered( $collection ) : null;
153155

154-
if ( null !== $collection && ! WP_Icon_Collections_Registry::get_instance()->is_registered( $collection ) ) {
156+
if ( null !== $collection && ( null === $registered_collection || ! $registered_collection['public'] ) ) {
155157
return new WP_Error(
156158
'rest_icon_collection_not_found',
157159
sprintf(
@@ -168,10 +170,11 @@ public function get_items( $request ) {
168170
$icons = WP_Icons_Registry::get_instance()->get_registered_icons( $search );
169171

170172
foreach ( $icons as $icon ) {
171-
if ( false === ( $icon['public'] ?? true ) ) {
173+
if ( null !== $collection && ( ! isset( $icon['collection'] ) || $icon['collection'] !== $collection ) ) {
172174
continue;
173175
}
174-
if ( null !== $collection && ( ! isset( $icon['collection'] ) || $icon['collection'] !== $collection ) ) {
176+
$icon_collection = isset( $icon['collection'] ) ? $collections_registry->get_registered( $icon['collection'] ) : null;
177+
if ( null === $icon_collection || ! $icon_collection['public'] ) {
175178
continue;
176179
}
177180
$prepared_icon = $this->prepare_item_for_response( $icon, $request );
@@ -202,7 +205,7 @@ public function get_item( $request ) {
202205
* Retrieves a specific icon from the registry.
203206
*
204207
* @since 7.0.0
205-
* @since 7.2.0 Icons registered as non-public are reported as not found.
208+
* @since 7.2.0 Icons belonging to non-public collections are reported as not found.
206209
*
207210
* @param string $name Icon name.
208211
* @return array|WP_Error Icon data on success, or WP_Error object on failure.
@@ -211,7 +214,11 @@ public function get_icon( $name ) {
211214
$registry = WP_Icons_Registry::get_instance();
212215
$icon = $registry->get_registered_icon( $name );
213216

214-
if ( null === $icon || false === ( $icon['public'] ?? true ) ) {
217+
$collection = null !== $icon && isset( $icon['collection'] )
218+
? WP_Icon_Collections_Registry::get_instance()->get_registered( $icon['collection'] )
219+
: null;
220+
221+
if ( null === $icon || null === $collection || ! $collection['public'] ) {
215222
return new WP_Error(
216223
'rest_icon_not_found',
217224
sprintf(

‎tests/phpunit/tests/icons/wpIconCollectionsRegistry.php‎

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,4 +201,93 @@ public function test_unregister_collection_cascades_to_icons() {
201201
public function test_unregister_unknown_collection() {
202202
$this->assertFalse( $this->collections->unregister( 'ghost' ) );
203203
}
204+
205+
/**
206+
* Should register collections as public by default.
207+
*
208+
* @ticket 66087
209+
*
210+
* @covers ::register
211+
*/
212+
public function test_register_collection_defaults_to_public() {
213+
$this->collections->register( 'my-collection', array( 'label' => 'My Collection' ) );
214+
215+
$this->assertTrue( $this->collections->get_registered( 'my-collection' )['public'] );
216+
}
217+
218+
/**
219+
* Should preserve explicitly configured collection visibility.
220+
*
221+
* @ticket 66087
222+
*
223+
* @dataProvider data_boolean_public_properties
224+
*
225+
* @covers ::register
226+
*
227+
* @param bool $is_public Whether the collection is public.
228+
*/
229+
public function test_register_collection_accepts_boolean_public_property( $is_public ) {
230+
$result = $this->collections->register(
231+
'my-collection',
232+
array(
233+
'label' => 'My Collection',
234+
'public' => $is_public,
235+
)
236+
);
237+
238+
$this->assertTrue( $result );
239+
$this->assertSame( $is_public, $this->collections->get_registered( 'my-collection' )['public'] );
240+
}
241+
242+
/**
243+
* Data provider for supported collection visibility values.
244+
*
245+
* @return array[]
246+
*/
247+
public function data_boolean_public_properties() {
248+
return array(
249+
'public collection' => array( true ),
250+
'non-public collection' => array( false ),
251+
);
252+
}
253+
254+
/**
255+
* Should reject collection visibility values that are not booleans.
256+
*
257+
* @ticket 66087
258+
*
259+
* @dataProvider data_non_boolean_public_properties
260+
*
261+
* @covers ::register
262+
*
263+
* @expectedIncorrectUsage WP_Icon_Collections_Registry::register
264+
*
265+
* @param mixed $is_public Invalid collection visibility value.
266+
*/
267+
public function test_register_collection_rejects_non_boolean_public_property( $is_public ) {
268+
$result = $this->collections->register(
269+
'my-collection',
270+
array(
271+
'label' => 'My Collection',
272+
'public' => $is_public,
273+
)
274+
);
275+
276+
$this->assertFalse( $result );
277+
$this->assertFalse( $this->collections->is_registered( 'my-collection' ) );
278+
}
279+
280+
/**
281+
* Data provider for unsupported collection visibility values.
282+
*
283+
* @return array[]
284+
*/
285+
public function data_non_boolean_public_properties() {
286+
return array(
287+
'string' => array( 'false' ),
288+
'integer' => array( 0 ),
289+
'array' => array( array() ),
290+
'null' => array( null ),
291+
);
292+
}
204293
}

0 commit comments

Comments
 (0)