[ Index ] |
PHP Cross Reference of WordPress |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * REST API: WP_REST_Block_Types_Controller class 4 * 5 * @package WordPress 6 * @subpackage REST_API 7 * @since 5.5.0 8 */ 9 10 /** 11 * Core class used to access block types via the REST API. 12 * 13 * @since 5.5.0 14 * 15 * @see WP_REST_Controller 16 */ 17 class WP_REST_Block_Types_Controller extends WP_REST_Controller { 18 19 /** 20 * Instance of WP_Block_Type_Registry. 21 * 22 * @since 5.5.0 23 * @var WP_Block_Type_Registry 24 */ 25 protected $block_registry; 26 27 /** 28 * Instance of WP_Block_Styles_Registry. 29 * 30 * @since 5.5.0 31 * @var WP_Block_Styles_Registry 32 */ 33 protected $style_registry; 34 35 /** 36 * Constructor. 37 * 38 * @since 5.5.0 39 */ 40 public function __construct() { 41 $this->namespace = 'wp/v2'; 42 $this->rest_base = 'block-types'; 43 $this->block_registry = WP_Block_Type_Registry::get_instance(); 44 $this->style_registry = WP_Block_Styles_Registry::get_instance(); 45 } 46 47 /** 48 * Registers the routes for the objects of the controller. 49 * 50 * @since 5.5.0 51 * 52 * @see register_rest_route() 53 */ 54 public function register_routes() { 55 56 register_rest_route( 57 $this->namespace, 58 '/' . $this->rest_base, 59 array( 60 array( 61 'methods' => WP_REST_Server::READABLE, 62 'callback' => array( $this, 'get_items' ), 63 'permission_callback' => array( $this, 'get_items_permissions_check' ), 64 'args' => $this->get_collection_params(), 65 ), 66 'schema' => array( $this, 'get_public_item_schema' ), 67 ) 68 ); 69 70 register_rest_route( 71 $this->namespace, 72 '/' . $this->rest_base . '/(?P<namespace>[a-zA-Z0-9_-]+)', 73 array( 74 array( 75 'methods' => WP_REST_Server::READABLE, 76 'callback' => array( $this, 'get_items' ), 77 'permission_callback' => array( $this, 'get_items_permissions_check' ), 78 'args' => $this->get_collection_params(), 79 ), 80 'schema' => array( $this, 'get_public_item_schema' ), 81 ) 82 ); 83 84 register_rest_route( 85 $this->namespace, 86 '/' . $this->rest_base . '/(?P<namespace>[a-zA-Z0-9_-]+)/(?P<name>[a-zA-Z0-9_-]+)', 87 array( 88 'args' => array( 89 'name' => array( 90 'description' => __( 'Block name.' ), 91 'type' => 'string', 92 ), 93 'namespace' => array( 94 'description' => __( 'Block namespace.' ), 95 'type' => 'string', 96 ), 97 ), 98 array( 99 'methods' => WP_REST_Server::READABLE, 100 'callback' => array( $this, 'get_item' ), 101 'permission_callback' => array( $this, 'get_item_permissions_check' ), 102 'args' => array( 103 'context' => $this->get_context_param( array( 'default' => 'view' ) ), 104 ), 105 ), 106 'schema' => array( $this, 'get_public_item_schema' ), 107 ) 108 ); 109 } 110 111 /** 112 * Checks whether a given request has permission to read post block types. 113 * 114 * @since 5.5.0 115 * 116 * @param WP_REST_Request $request Full details about the request. 117 * @return true|WP_Error True if the request has read access, WP_Error object otherwise. 118 */ 119 public function get_items_permissions_check( $request ) { 120 return $this->check_read_permission(); 121 } 122 123 /** 124 * Retrieves all post block types, depending on user context. 125 * 126 * @since 5.5.0 127 * 128 * @param WP_REST_Request $request Full details about the request. 129 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. 130 */ 131 public function get_items( $request ) { 132 $data = array(); 133 $block_types = $this->block_registry->get_all_registered(); 134 135 // Retrieve the list of registered collection query parameters. 136 $registered = $this->get_collection_params(); 137 $namespace = ''; 138 if ( isset( $registered['namespace'] ) && ! empty( $request['namespace'] ) ) { 139 $namespace = $request['namespace']; 140 } 141 142 foreach ( $block_types as $slug => $obj ) { 143 if ( $namespace ) { 144 list ( $block_namespace ) = explode( '/', $obj->name ); 145 146 if ( $namespace !== $block_namespace ) { 147 continue; 148 } 149 } 150 $block_type = $this->prepare_item_for_response( $obj, $request ); 151 $data[] = $this->prepare_response_for_collection( $block_type ); 152 } 153 154 return rest_ensure_response( $data ); 155 } 156 157 /** 158 * Checks if a given request has access to read a block type. 159 * 160 * @since 5.5.0 161 * 162 * @param WP_REST_Request $request Full details about the request. 163 * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise. 164 */ 165 public function get_item_permissions_check( $request ) { 166 $check = $this->check_read_permission(); 167 if ( is_wp_error( $check ) ) { 168 return $check; 169 } 170 $block_name = sprintf( '%s/%s', $request['namespace'], $request['name'] ); 171 $block_type = $this->get_block( $block_name ); 172 if ( is_wp_error( $block_type ) ) { 173 return $block_type; 174 } 175 176 return true; 177 } 178 179 /** 180 * Checks whether a given block type should be visible. 181 * 182 * @since 5.5.0 183 * 184 * @return true|WP_Error True if the block type is visible, WP_Error otherwise. 185 */ 186 protected function check_read_permission() { 187 if ( current_user_can( 'edit_posts' ) ) { 188 return true; 189 } 190 foreach ( get_post_types( array( 'show_in_rest' => true ), 'objects' ) as $post_type ) { 191 if ( current_user_can( $post_type->cap->edit_posts ) ) { 192 return true; 193 } 194 } 195 196 return new WP_Error( 'rest_block_type_cannot_view', __( 'Sorry, you are not allowed to manage block types.' ), array( 'status' => rest_authorization_required_code() ) ); 197 } 198 199 /** 200 * Get the block, if the name is valid. 201 * 202 * @since 5.5.0 203 * 204 * @param string $name Block name. 205 * @return WP_Block_Type|WP_Error Block type object if name is valid, WP_Error otherwise. 206 */ 207 protected function get_block( $name ) { 208 $block_type = $this->block_registry->get_registered( $name ); 209 if ( empty( $block_type ) ) { 210 return new WP_Error( 'rest_block_type_invalid', __( 'Invalid block type.' ), array( 'status' => 404 ) ); 211 } 212 213 return $block_type; 214 } 215 216 /** 217 * Retrieves a specific block type. 218 * 219 * @since 5.5.0 220 * 221 * @param WP_REST_Request $request Full details about the request. 222 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. 223 */ 224 public function get_item( $request ) { 225 $block_name = sprintf( '%s/%s', $request['namespace'], $request['name'] ); 226 $block_type = $this->get_block( $block_name ); 227 if ( is_wp_error( $block_type ) ) { 228 return $block_type; 229 } 230 $data = $this->prepare_item_for_response( $block_type, $request ); 231 232 return rest_ensure_response( $data ); 233 } 234 235 /** 236 * Prepares a block type object for serialization. 237 * 238 * @since 5.5.0 239 * 240 * @param WP_Block_Type $block_type Block type data. 241 * @param WP_REST_Request $request Full details about the request. 242 * @return WP_REST_Response Block type data. 243 */ 244 public function prepare_item_for_response( $block_type, $request ) { 245 246 $fields = $this->get_fields_for_response( $request ); 247 $data = array(); 248 249 if ( rest_is_field_included( 'attributes', $fields ) ) { 250 $data['attributes'] = $block_type->get_attributes(); 251 } 252 253 if ( rest_is_field_included( 'is_dynamic', $fields ) ) { 254 $data['is_dynamic'] = $block_type->is_dynamic(); 255 } 256 257 $schema = $this->get_item_schema(); 258 $extra_fields = array( 259 'api_version', 260 'name', 261 'title', 262 'description', 263 'icon', 264 'category', 265 'keywords', 266 'parent', 267 'provides_context', 268 'uses_context', 269 'supports', 270 'styles', 271 'textdomain', 272 'example', 273 'editor_script', 274 'script', 275 'editor_style', 276 'style', 277 ); 278 foreach ( $extra_fields as $extra_field ) { 279 if ( rest_is_field_included( $extra_field, $fields ) ) { 280 if ( isset( $block_type->$extra_field ) ) { 281 $field = $block_type->$extra_field; 282 } elseif ( array_key_exists( 'default', $schema['properties'][ $extra_field ] ) ) { 283 $field = $schema['properties'][ $extra_field ]['default']; 284 } else { 285 $field = ''; 286 } 287 $data[ $extra_field ] = rest_sanitize_value_from_schema( $field, $schema['properties'][ $extra_field ] ); 288 } 289 } 290 291 if ( rest_is_field_included( 'styles', $fields ) ) { 292 $styles = $this->style_registry->get_registered_styles_for_block( $block_type->name ); 293 $styles = array_values( $styles ); 294 $data['styles'] = wp_parse_args( $styles, $data['styles'] ); 295 $data['styles'] = array_filter( $data['styles'] ); 296 } 297 298 $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; 299 $data = $this->add_additional_fields_to_object( $data, $request ); 300 $data = $this->filter_response_by_context( $data, $context ); 301 302 $response = rest_ensure_response( $data ); 303 304 $response->add_links( $this->prepare_links( $block_type ) ); 305 306 /** 307 * Filters a block type returned from the REST API. 308 * 309 * Allows modification of the block type data right before it is returned. 310 * 311 * @since 5.5.0 312 * 313 * @param WP_REST_Response $response The response object. 314 * @param WP_Block_Type $block_type The original block type object. 315 * @param WP_REST_Request $request Request used to generate the response. 316 */ 317 return apply_filters( 'rest_prepare_block_type', $response, $block_type, $request ); 318 } 319 320 /** 321 * Prepares links for the request. 322 * 323 * @since 5.5.0 324 * 325 * @param WP_Block_Type $block_type Block type data. 326 * @return array Links for the given block type. 327 */ 328 protected function prepare_links( $block_type ) { 329 list( $namespace ) = explode( '/', $block_type->name ); 330 331 $links = array( 332 'collection' => array( 333 'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ), 334 ), 335 'self' => array( 336 'href' => rest_url( sprintf( '%s/%s/%s', $this->namespace, $this->rest_base, $block_type->name ) ), 337 ), 338 'up' => array( 339 'href' => rest_url( sprintf( '%s/%s/%s', $this->namespace, $this->rest_base, $namespace ) ), 340 ), 341 ); 342 343 if ( $block_type->is_dynamic() ) { 344 $links['https://api.w.org/render-block'] = array( 345 'href' => add_query_arg( 'context', 'edit', rest_url( sprintf( '%s/%s/%s', 'wp/v2', 'block-renderer', $block_type->name ) ) ), 346 ); 347 } 348 349 return $links; 350 } 351 352 /** 353 * Retrieves the block type' schema, conforming to JSON Schema. 354 * 355 * @since 5.5.0 356 * 357 * @return array Item schema data. 358 */ 359 public function get_item_schema() { 360 if ( $this->schema ) { 361 return $this->add_additional_fields_schema( $this->schema ); 362 } 363 364 $schema = array( 365 '$schema' => 'http://json-schema.org/draft-04/schema#', 366 'title' => 'block-type', 367 'type' => 'object', 368 'properties' => array( 369 'api_version' => array( 370 'description' => __( 'Version of block API.' ), 371 'type' => 'integer', 372 'default' => 1, 373 'context' => array( 'embed', 'view', 'edit' ), 374 'readonly' => true, 375 ), 376 'title' => array( 377 'description' => __( 'Title of block type.' ), 378 'type' => 'string', 379 'default' => '', 380 'context' => array( 'embed', 'view', 'edit' ), 381 'readonly' => true, 382 ), 383 'name' => array( 384 'description' => __( 'Unique name identifying the block type.' ), 385 'type' => 'string', 386 'default' => '', 387 'context' => array( 'embed', 'view', 'edit' ), 388 'readonly' => true, 389 ), 390 'description' => array( 391 'description' => __( 'Description of block type.' ), 392 'type' => 'string', 393 'default' => '', 394 'context' => array( 'embed', 'view', 'edit' ), 395 'readonly' => true, 396 ), 397 'icon' => array( 398 'description' => __( 'Icon of block type.' ), 399 'type' => array( 'string', 'null' ), 400 'default' => null, 401 'context' => array( 'embed', 'view', 'edit' ), 402 'readonly' => true, 403 ), 404 'attributes' => array( 405 'description' => __( 'Block attributes.' ), 406 'type' => array( 'object', 'null' ), 407 'properties' => array(), 408 'default' => null, 409 'additionalProperties' => array( 410 'type' => 'object', 411 ), 412 'context' => array( 'embed', 'view', 'edit' ), 413 'readonly' => true, 414 ), 415 'provides_context' => array( 416 'description' => __( 'Context provided by blocks of this type.' ), 417 'type' => 'object', 418 'properties' => array(), 419 'additionalProperties' => array( 420 'type' => 'string', 421 ), 422 'default' => array(), 423 'context' => array( 'embed', 'view', 'edit' ), 424 'readonly' => true, 425 ), 426 'uses_context' => array( 427 'description' => __( 'Context values inherited by blocks of this type.' ), 428 'type' => 'array', 429 'default' => array(), 430 'items' => array( 431 'type' => 'string', 432 ), 433 'context' => array( 'embed', 'view', 'edit' ), 434 'readonly' => true, 435 ), 436 'supports' => array( 437 'description' => __( 'Block supports.' ), 438 'type' => 'object', 439 'default' => array(), 440 'properties' => array(), 441 'context' => array( 'embed', 'view', 'edit' ), 442 'readonly' => true, 443 ), 444 'category' => array( 445 'description' => __( 'Block category.' ), 446 'type' => array( 'string', 'null' ), 447 'default' => null, 448 'context' => array( 'embed', 'view', 'edit' ), 449 'readonly' => true, 450 ), 451 'is_dynamic' => array( 452 'description' => __( 'Is the block dynamically rendered.' ), 453 'type' => 'boolean', 454 'default' => false, 455 'context' => array( 'embed', 'view', 'edit' ), 456 'readonly' => true, 457 ), 458 'editor_script' => array( 459 'description' => __( 'Editor script handle.' ), 460 'type' => array( 'string', 'null' ), 461 'default' => null, 462 'context' => array( 'embed', 'view', 'edit' ), 463 'readonly' => true, 464 ), 465 'script' => array( 466 'description' => __( 'Public facing script handle.' ), 467 'type' => array( 'string', 'null' ), 468 'default' => null, 469 'context' => array( 'embed', 'view', 'edit' ), 470 'readonly' => true, 471 ), 472 'editor_style' => array( 473 'description' => __( 'Editor style handle.' ), 474 'type' => array( 'string', 'null' ), 475 'default' => null, 476 'context' => array( 'embed', 'view', 'edit' ), 477 'readonly' => true, 478 ), 479 'style' => array( 480 'description' => __( 'Public facing style handle.' ), 481 'type' => array( 'string', 'null' ), 482 'default' => null, 483 'context' => array( 'embed', 'view', 'edit' ), 484 'readonly' => true, 485 ), 486 'styles' => array( 487 'description' => __( 'Block style variations.' ), 488 'type' => 'array', 489 'items' => array( 490 'type' => 'object', 491 'properties' => array( 492 'name' => array( 493 'description' => __( 'Unique name identifying the style.' ), 494 'type' => 'string', 495 'required' => true, 496 ), 497 'label' => array( 498 'description' => __( 'The human-readable label for the style.' ), 499 'type' => 'string', 500 ), 501 'inline_style' => array( 502 'description' => __( 'Inline CSS code that registers the CSS class required for the style.' ), 503 'type' => 'string', 504 ), 505 'style_handle' => array( 506 'description' => __( 'Contains the handle that defines the block style.' ), 507 'type' => 'string', 508 ), 509 ), 510 ), 511 'default' => array(), 512 'context' => array( 'embed', 'view', 'edit' ), 513 'readonly' => true, 514 ), 515 'textdomain' => array( 516 'description' => __( 'Public text domain.' ), 517 'type' => array( 'string', 'null' ), 518 'default' => null, 519 'context' => array( 'embed', 'view', 'edit' ), 520 'readonly' => true, 521 ), 522 'parent' => array( 523 'description' => __( 'Parent blocks.' ), 524 'type' => array( 'array', 'null' ), 525 'items' => array( 526 'type' => 'string', 527 ), 528 'default' => null, 529 'context' => array( 'embed', 'view', 'edit' ), 530 'readonly' => true, 531 ), 532 'keywords' => array( 533 'description' => __( 'Block keywords.' ), 534 'type' => 'array', 535 'items' => array( 536 'type' => 'string', 537 ), 538 'default' => array(), 539 'context' => array( 'embed', 'view', 'edit' ), 540 'readonly' => true, 541 ), 542 'example' => array( 543 'description' => __( 'Block example.' ), 544 'type' => array( 'object', 'null' ), 545 'default' => null, 546 'properties' => array( 547 'attributes' => array( 548 'description' => __( 'The attributes used in the example.' ), 549 'type' => 'object', 550 ), 551 'innerBlocks' => array( 552 'description' => __( 'The list of inner blocks used in the example.' ), 553 'type' => 'array', 554 'items' => array( 555 'type' => 'object', 556 'properties' => array( 557 'name' => array( 558 'description' => __( 'The name of the inner block.' ), 559 'type' => 'string', 560 ), 561 'attributes' => array( 562 'description' => __( 'The attributes of the inner block.' ), 563 'type' => 'object', 564 ), 565 'innerBlocks' => array( 566 'description' => __( "A list of the inner block's own inner blocks. This is a recursive definition following the parent innerBlocks schema." ), 567 'type' => 'array', 568 ), 569 ), 570 ), 571 ), 572 ), 573 'context' => array( 'embed', 'view', 'edit' ), 574 'readonly' => true, 575 ), 576 ), 577 ); 578 579 $this->schema = $schema; 580 581 return $this->add_additional_fields_schema( $this->schema ); 582 } 583 584 /** 585 * Retrieves the query params for collections. 586 * 587 * @since 5.5.0 588 * 589 * @return array Collection parameters. 590 */ 591 public function get_collection_params() { 592 return array( 593 'context' => $this->get_context_param( array( 'default' => 'view' ) ), 594 'namespace' => array( 595 'description' => __( 'Block namespace.' ), 596 'type' => 'string', 597 ), 598 ); 599 } 600 601 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Tue Jan 19 01:00:03 2021 | Cross-referenced by PHPXref 0.7.1 |