| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * REST API: WP_REST_Icons_Controller class 5 * 6 * @package WordPress 7 * @subpackage REST_API 8 * @since 7.0.0 9 */ 10 11 /** 12 * Controller which provides a REST endpoint for the editor to read registered 13 * icons. Icons are grouped into collections (the default one being `core`). 14 * 15 * @since 7.0.0 16 * 17 * @see WP_REST_Controller 18 */ 19 class WP_REST_Icons_Controller extends WP_REST_Controller { 20 21 /** 22 * Constructs the controller. 23 * 24 * @since 7.0.0 25 */ 26 public function __construct() { 27 $this->namespace = 'wp/v2'; 28 $this->rest_base = 'icons'; 29 } 30 31 /** 32 * Registers the routes for the objects of the controller. 33 * 34 * @since 7.0.0 35 * @since 7.1.0 Added the `/icons/<collection>` collection-scoped route. 36 */ 37 public function register_routes() { 38 register_rest_route( 39 $this->namespace, 40 '/' . $this->rest_base, 41 array( 42 array( 43 'methods' => WP_REST_Server::READABLE, 44 'callback' => array( $this, 'get_items' ), 45 'permission_callback' => array( $this, 'get_items_permissions_check' ), 46 'args' => $this->get_collection_params(), 47 ), 48 'schema' => array( $this, 'get_public_item_schema' ), 49 ) 50 ); 51 52 register_rest_route( 53 $this->namespace, 54 '/' . $this->rest_base . '/(?P<collection>[a-z0-9](?:[a-z0-9_-]*[a-z0-9])?)', 55 array( 56 'args' => array( 57 'collection' => array( 58 'description' => __( 'Icon collection slug.' ), 59 'type' => 'string', 60 ), 61 ), 62 array( 63 'methods' => WP_REST_Server::READABLE, 64 'callback' => array( $this, 'get_items' ), 65 'permission_callback' => array( $this, 'get_items_permissions_check' ), 66 'args' => $this->get_collection_params(), 67 ), 68 'schema' => array( $this, 'get_public_item_schema' ), 69 ) 70 ); 71 72 register_rest_route( 73 $this->namespace, 74 '/' . $this->rest_base . '/(?P<name>[a-z0-9](?:[a-z0-9_-]*[a-z0-9])?/[a-z0-9](?:[a-z0-9_-]*[a-z0-9])?)', 75 array( 76 'args' => array( 77 'name' => array( 78 'description' => __( 'Icon name.' ), 79 'type' => 'string', 80 ), 81 ), 82 array( 83 'methods' => WP_REST_Server::READABLE, 84 'callback' => array( $this, 'get_item' ), 85 'permission_callback' => array( $this, 'get_item_permissions_check' ), 86 'args' => array( 87 'context' => $this->get_context_param( array( 'default' => 'view' ) ), 88 ), 89 ), 90 'schema' => array( $this, 'get_public_item_schema' ), 91 ) 92 ); 93 } 94 95 /** 96 * Checks whether a given request has permission to read icons. 97 * 98 * @since 7.0.0 99 * 100 * @param WP_REST_Request $request Full details about the request. 101 * @return true|WP_Error True if the request has read access, WP_Error object otherwise. 102 */ 103 public function get_items_permissions_check( 104 // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable 105 $request 106 ) { 107 if ( current_user_can( 'edit_posts' ) ) { 108 return true; 109 } 110 111 foreach ( get_post_types( array( 'show_in_rest' => true ), 'objects' ) as $post_type ) { 112 if ( current_user_can( $post_type->cap->edit_posts ) ) { 113 return true; 114 } 115 } 116 117 return new WP_Error( 118 'rest_cannot_view', 119 __( 'Sorry, you are not allowed to view the registered icons.' ), 120 array( 'status' => rest_authorization_required_code() ) 121 ); 122 } 123 124 /** 125 * Checks if a given request has access to read a specific icon. 126 * 127 * @since 7.0.0 128 * 129 * @param WP_REST_Request $request Full details about the request. 130 * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise. 131 */ 132 public function get_item_permissions_check( $request ) { 133 $check = $this->get_items_permissions_check( $request ); 134 if ( is_wp_error( $check ) ) { 135 return $check; 136 } 137 138 return true; 139 } 140 141 /** 142 * Retrieves all icons, optionally scoped to a collection. 143 * 144 * @since 7.0.0 145 * @since 7.1.0 Supports filtering by collection. 146 * @since 7.2.0 Icons belonging to non-public collections are omitted. 147 * 148 * @param WP_REST_Request $request Full details about the request. 149 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. 150 */ 151 public function get_items( $request ) { 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; 155 156 if ( null !== $collection && ( null === $registered_collection || ! $registered_collection['public'] ) ) { 157 return new WP_Error( 158 'rest_icon_collection_not_found', 159 sprintf( 160 /* translators: %s: Icon collection slug. */ 161 __( 'Icon collection not found: "%s".' ), 162 $collection 163 ), 164 array( 'status' => 404 ) 165 ); 166 } 167 168 $response = array(); 169 $search = $request->get_param( 'search' ); 170 $icons = WP_Icons_Registry::get_instance()->get_registered_icons( $search ); 171 172 foreach ( $icons as $icon ) { 173 if ( null !== $collection && ( ! isset( $icon['collection'] ) || $icon['collection'] !== $collection ) ) { 174 continue; 175 } 176 $icon_collection = isset( $icon['collection'] ) ? $collections_registry->get_registered( $icon['collection'] ) : null; 177 if ( null === $icon_collection || ! $icon_collection['public'] ) { 178 continue; 179 } 180 $prepared_icon = $this->prepare_item_for_response( $icon, $request ); 181 $response[] = $this->prepare_response_for_collection( $prepared_icon ); 182 } 183 return rest_ensure_response( $response ); 184 } 185 186 /** 187 * Retrieves a specific icon. 188 * 189 * @since 7.0.0 190 * 191 * @param WP_REST_Request $request Full details about the request. 192 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. 193 */ 194 public function get_item( $request ) { 195 $icon = $this->get_icon( $request['name'] ); 196 if ( is_wp_error( $icon ) ) { 197 return $icon; 198 } 199 200 $data = $this->prepare_item_for_response( $icon, $request ); 201 return rest_ensure_response( $data ); 202 } 203 204 /** 205 * Retrieves a specific icon from the registry. 206 * 207 * @since 7.0.0 208 * @since 7.2.0 Icons belonging to non-public collections are reported as not found. 209 * 210 * @param string $name Icon name. 211 * @return array|WP_Error Icon data on success, or WP_Error object on failure. 212 */ 213 public function get_icon( $name ) { 214 $registry = WP_Icons_Registry::get_instance(); 215 $icon = $registry->get_registered_icon( $name ); 216 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'] ) { 222 return new WP_Error( 223 'rest_icon_not_found', 224 sprintf( 225 // translators: %s is the name of any user-provided name 226 __( 'Icon not found: "%s".' ), 227 $name 228 ), 229 array( 'status' => 404 ) 230 ); 231 } 232 233 return $icon; 234 } 235 236 /** 237 * Prepare a raw icon before it gets output in a REST API response. 238 * 239 * Adds `collection` and `keywords` fields to the base response while keeping 240 * the namespaced icon name (e.g. `core/arrow-left`) as the `name` field. 241 * 242 * @since 7.0.0 243 * @since 7.1.0 Added the `collection` field. 244 * @since 7.2.0 Added the `keywords` field. 245 * 246 * @param array $item Raw icon as registered, before any changes. 247 * @param WP_REST_Request $request Request object. 248 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. 249 */ 250 public function prepare_item_for_response( $item, $request ) { 251 $fields = $this->get_fields_for_response( $request ); 252 $keys = array( 253 'name' => 'name', 254 'label' => 'label', 255 'content' => 'content', 256 'collection' => 'collection', 257 ); 258 $data = array(); 259 foreach ( $keys as $item_key => $rest_key ) { 260 if ( isset( $item[ $item_key ] ) && rest_is_field_included( $rest_key, $fields ) ) { 261 $data[ $rest_key ] = $item[ $item_key ]; 262 } 263 } 264 265 /* 266 * Keywords are optional at registration time, but the field is always 267 * present in the response so consumers do not have to handle its absence. 268 */ 269 if ( rest_is_field_included( 'keywords', $fields ) ) { 270 $data['keywords'] = isset( $item['keywords'] ) ? array_values( $item['keywords'] ) : array(); 271 } 272 273 $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; 274 $data = $this->add_additional_fields_to_object( $data, $request ); 275 $data = $this->filter_response_by_context( $data, $context ); 276 return rest_ensure_response( $data ); 277 } 278 279 /** 280 * Retrieves the icon schema, conforming to JSON Schema. 281 * 282 * @since 7.0.0 283 * @since 7.1.0 Added the `collection` property. 284 * @since 7.2.0 Added the `keywords` property. 285 * 286 * @return array Item schema data. 287 */ 288 public function get_item_schema() { 289 if ( $this->schema ) { 290 return $this->add_additional_fields_schema( $this->schema ); 291 } 292 293 $schema = array( 294 '$schema' => 'http://json-schema.org/draft-04/schema#', 295 'title' => 'icon', 296 'type' => 'object', 297 'properties' => array( 298 'name' => array( 299 'description' => __( 'The icon name.' ), 300 'type' => 'string', 301 'readonly' => true, 302 'context' => array( 'view', 'edit', 'embed' ), 303 ), 304 'label' => array( 305 'description' => __( 'The icon label.' ), 306 'type' => 'string', 307 'readonly' => true, 308 'context' => array( 'view', 'edit', 'embed' ), 309 ), 310 'content' => array( 311 'description' => __( 'The icon content (SVG markup).' ), 312 'type' => 'string', 313 'readonly' => true, 314 'context' => array( 'view', 'edit', 'embed' ), 315 ), 316 'collection' => array( 317 'description' => __( 'The slug of the collection this icon belongs to.' ), 318 'type' => 'string', 319 'readonly' => true, 320 'context' => array( 'view', 'edit', 'embed' ), 321 ), 322 'keywords' => array( 323 'description' => __( 'Additional search terms for the icon.' ), 324 'type' => 'array', 325 'items' => array( 326 'type' => 'string', 327 ), 328 'readonly' => true, 329 'context' => array( 'view', 'edit', 'embed' ), 330 ), 331 ), 332 ); 333 334 $this->schema = $schema; 335 336 return $this->add_additional_fields_schema( $this->schema ); 337 } 338 339 /** 340 * Retrieves the query params for the icons collection. 341 * 342 * @since 7.0.0 343 * @since 7.1.0 Added the `collection` parameter. 344 * 345 * @return array Collection parameters. 346 */ 347 public function get_collection_params() { 348 $query_params = parent::get_collection_params(); 349 $query_params['context']['default'] = 'view'; 350 $query_params['collection'] = array( 351 'description' => __( 'Limit results to icons belonging to the given collection slug.' ), 352 'type' => 'string', 353 'pattern' => '^[a-z0-9]([a-z0-9_-]*[a-z0-9])?$', 354 ); 355 return $query_params; 356 } 357 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Tue Oct 13 08:20:33 2026 | Cross-referenced by PHPXref |