[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/rest-api/endpoints/ -> class-wp-rest-block-types-controller.php (source)

   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              'variations',
 278          );
 279          foreach ( $extra_fields as $extra_field ) {
 280              if ( rest_is_field_included( $extra_field, $fields ) ) {
 281                  if ( isset( $block_type->$extra_field ) ) {
 282                      $field = $block_type->$extra_field;
 283                  } elseif ( array_key_exists( 'default', $schema['properties'][ $extra_field ] ) ) {
 284                      $field = $schema['properties'][ $extra_field ]['default'];
 285                  } else {
 286                      $field = '';
 287                  }
 288                  $data[ $extra_field ] = rest_sanitize_value_from_schema( $field, $schema['properties'][ $extra_field ] );
 289              }
 290          }
 291  
 292          if ( rest_is_field_included( 'styles', $fields ) ) {
 293              $styles         = $this->style_registry->get_registered_styles_for_block( $block_type->name );
 294              $styles         = array_values( $styles );
 295              $data['styles'] = wp_parse_args( $styles, $data['styles'] );
 296              $data['styles'] = array_filter( $data['styles'] );
 297          }
 298  
 299          $context = ! empty( $request['context'] ) ? $request['context'] : 'view';
 300          $data    = $this->add_additional_fields_to_object( $data, $request );
 301          $data    = $this->filter_response_by_context( $data, $context );
 302  
 303          $response = rest_ensure_response( $data );
 304  
 305          $response->add_links( $this->prepare_links( $block_type ) );
 306  
 307          /**
 308           * Filters a block type returned from the REST API.
 309           *
 310           * Allows modification of the block type data right before it is returned.
 311           *
 312           * @since 5.5.0
 313           *
 314           * @param WP_REST_Response $response   The response object.
 315           * @param WP_Block_Type    $block_type The original block type object.
 316           * @param WP_REST_Request  $request    Request used to generate the response.
 317           */
 318          return apply_filters( 'rest_prepare_block_type', $response, $block_type, $request );
 319      }
 320  
 321      /**
 322       * Prepares links for the request.
 323       *
 324       * @since 5.5.0
 325       *
 326       * @param WP_Block_Type $block_type Block type data.
 327       * @return array Links for the given block type.
 328       */
 329  	protected function prepare_links( $block_type ) {
 330          list( $namespace ) = explode( '/', $block_type->name );
 331  
 332          $links = array(
 333              'collection' => array(
 334                  'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ),
 335              ),
 336              'self'       => array(
 337                  'href' => rest_url( sprintf( '%s/%s/%s', $this->namespace, $this->rest_base, $block_type->name ) ),
 338              ),
 339              'up'         => array(
 340                  'href' => rest_url( sprintf( '%s/%s/%s', $this->namespace, $this->rest_base, $namespace ) ),
 341              ),
 342          );
 343  
 344          if ( $block_type->is_dynamic() ) {
 345              $links['https://api.w.org/render-block'] = array(
 346                  'href' => add_query_arg( 'context', 'edit', rest_url( sprintf( '%s/%s/%s', 'wp/v2', 'block-renderer', $block_type->name ) ) ),
 347              );
 348          }
 349  
 350          return $links;
 351      }
 352  
 353      /**
 354       * Retrieves the block type' schema, conforming to JSON Schema.
 355       *
 356       * @since 5.5.0
 357       *
 358       * @return array Item schema data.
 359       */
 360  	public function get_item_schema() {
 361          if ( $this->schema ) {
 362              return $this->add_additional_fields_schema( $this->schema );
 363          }
 364  
 365          // rest_validate_value_from_schema doesn't understand $refs, pull out reused definitions for readability.
 366          $inner_blocks_definition = array(
 367              'description' => __( 'The list of inner blocks used in the example.' ),
 368              'type'        => 'array',
 369              'items'       => array(
 370                  'type'       => 'object',
 371                  'properties' => array(
 372                      'name'        => array(
 373                          'description' => __( 'The name of the inner block.' ),
 374                          'type'        => 'string',
 375                      ),
 376                      'attributes'  => array(
 377                          'description' => __( 'The attributes of the inner block.' ),
 378                          'type'        => 'object',
 379                      ),
 380                      'innerBlocks' => array(
 381                          'description' => __( "A list of the inner block's own inner blocks. This is a recursive definition following the parent innerBlocks schema." ),
 382                          'type'        => 'array',
 383                      ),
 384                  ),
 385              ),
 386          );
 387  
 388          $example_definition = array(
 389              'description' => __( 'Block example.' ),
 390              'type'        => array( 'object', 'null' ),
 391              'default'     => null,
 392              'properties'  => array(
 393                  'attributes'  => array(
 394                      'description' => __( 'The attributes used in the example.' ),
 395                      'type'        => 'object',
 396                  ),
 397                  'innerBlocks' => $inner_blocks_definition,
 398              ),
 399              'context'     => array( 'embed', 'view', 'edit' ),
 400              'readonly'    => true,
 401          );
 402  
 403          $keywords_definition = array(
 404              'description' => __( 'Block keywords.' ),
 405              'type'        => 'array',
 406              'items'       => array(
 407                  'type' => 'string',
 408              ),
 409              'default'     => array(),
 410              'context'     => array( 'embed', 'view', 'edit' ),
 411              'readonly'    => true,
 412          );
 413  
 414          $icon_definition = array(
 415              'description' => __( 'Icon of block type.' ),
 416              'type'        => array( 'string', 'null' ),
 417              'default'     => null,
 418              'context'     => array( 'embed', 'view', 'edit' ),
 419              'readonly'    => true,
 420          );
 421  
 422          $category_definition = array(
 423              'description' => __( 'Block category.' ),
 424              'type'        => array( 'string', 'null' ),
 425              'default'     => null,
 426              'context'     => array( 'embed', 'view', 'edit' ),
 427              'readonly'    => true,
 428          );
 429  
 430          $schema = array(
 431              '$schema'    => 'http://json-schema.org/draft-04/schema#',
 432              'title'      => 'block-type',
 433              'type'       => 'object',
 434              'properties' => array(
 435                  'api_version'      => array(
 436                      'description' => __( 'Version of block API.' ),
 437                      'type'        => 'integer',
 438                      'default'     => 1,
 439                      'context'     => array( 'embed', 'view', 'edit' ),
 440                      'readonly'    => true,
 441                  ),
 442                  'title'            => array(
 443                      'description' => __( 'Title of block type.' ),
 444                      'type'        => 'string',
 445                      'default'     => '',
 446                      'context'     => array( 'embed', 'view', 'edit' ),
 447                      'readonly'    => true,
 448                  ),
 449                  'name'             => array(
 450                      'description' => __( 'Unique name identifying the block type.' ),
 451                      'type'        => 'string',
 452                      'default'     => '',
 453                      'context'     => array( 'embed', 'view', 'edit' ),
 454                      'readonly'    => true,
 455                  ),
 456                  'description'      => array(
 457                      'description' => __( 'Description of block type.' ),
 458                      'type'        => 'string',
 459                      'default'     => '',
 460                      'context'     => array( 'embed', 'view', 'edit' ),
 461                      'readonly'    => true,
 462                  ),
 463                  'icon'             => $icon_definition,
 464                  'attributes'       => array(
 465                      'description'          => __( 'Block attributes.' ),
 466                      'type'                 => array( 'object', 'null' ),
 467                      'properties'           => array(),
 468                      'default'              => null,
 469                      'additionalProperties' => array(
 470                          'type' => 'object',
 471                      ),
 472                      'context'              => array( 'embed', 'view', 'edit' ),
 473                      'readonly'             => true,
 474                  ),
 475                  'provides_context' => array(
 476                      'description'          => __( 'Context provided by blocks of this type.' ),
 477                      'type'                 => 'object',
 478                      'properties'           => array(),
 479                      'additionalProperties' => array(
 480                          'type' => 'string',
 481                      ),
 482                      'default'              => array(),
 483                      'context'              => array( 'embed', 'view', 'edit' ),
 484                      'readonly'             => true,
 485                  ),
 486                  'uses_context'     => array(
 487                      'description' => __( 'Context values inherited by blocks of this type.' ),
 488                      'type'        => 'array',
 489                      'default'     => array(),
 490                      'items'       => array(
 491                          'type' => 'string',
 492                      ),
 493                      'context'     => array( 'embed', 'view', 'edit' ),
 494                      'readonly'    => true,
 495                  ),
 496                  'supports'         => array(
 497                      'description' => __( 'Block supports.' ),
 498                      'type'        => 'object',
 499                      'default'     => array(),
 500                      'properties'  => array(),
 501                      'context'     => array( 'embed', 'view', 'edit' ),
 502                      'readonly'    => true,
 503                  ),
 504                  'category'         => $category_definition,
 505                  'is_dynamic'       => array(
 506                      'description' => __( 'Is the block dynamically rendered.' ),
 507                      'type'        => 'boolean',
 508                      'default'     => false,
 509                      'context'     => array( 'embed', 'view', 'edit' ),
 510                      'readonly'    => true,
 511                  ),
 512                  'editor_script'    => array(
 513                      'description' => __( 'Editor script handle.' ),
 514                      'type'        => array( 'string', 'null' ),
 515                      'default'     => null,
 516                      'context'     => array( 'embed', 'view', 'edit' ),
 517                      'readonly'    => true,
 518                  ),
 519                  'script'           => array(
 520                      'description' => __( 'Public facing script handle.' ),
 521                      'type'        => array( 'string', 'null' ),
 522                      'default'     => null,
 523                      'context'     => array( 'embed', 'view', 'edit' ),
 524                      'readonly'    => true,
 525                  ),
 526                  'editor_style'     => array(
 527                      'description' => __( 'Editor style handle.' ),
 528                      'type'        => array( 'string', 'null' ),
 529                      'default'     => null,
 530                      'context'     => array( 'embed', 'view', 'edit' ),
 531                      'readonly'    => true,
 532                  ),
 533                  'style'            => array(
 534                      'description' => __( 'Public facing style handle.' ),
 535                      'type'        => array( 'string', 'null' ),
 536                      'default'     => null,
 537                      'context'     => array( 'embed', 'view', 'edit' ),
 538                      'readonly'    => true,
 539                  ),
 540                  'styles'           => array(
 541                      'description' => __( 'Block style variations.' ),
 542                      'type'        => 'array',
 543                      'items'       => array(
 544                          'type'       => 'object',
 545                          'properties' => array(
 546                              'name'         => array(
 547                                  'description' => __( 'Unique name identifying the style.' ),
 548                                  'type'        => 'string',
 549                                  'required'    => true,
 550                              ),
 551                              'label'        => array(
 552                                  'description' => __( 'The human-readable label for the style.' ),
 553                                  'type'        => 'string',
 554                              ),
 555                              'inline_style' => array(
 556                                  'description' => __( 'Inline CSS code that registers the CSS class required for the style.' ),
 557                                  'type'        => 'string',
 558                              ),
 559                              'style_handle' => array(
 560                                  'description' => __( 'Contains the handle that defines the block style.' ),
 561                                  'type'        => 'string',
 562                              ),
 563                          ),
 564                      ),
 565                      'default'     => array(),
 566                      'context'     => array( 'embed', 'view', 'edit' ),
 567                      'readonly'    => true,
 568                  ),
 569                  'variations'       => array(
 570                      'description' => __( 'Block variations.' ),
 571                      'type'        => 'array',
 572                      'items'       => array(
 573                          'type'       => 'object',
 574                          'properties' => array(
 575                              'name'        => array(
 576                                  'description' => __( 'The unique and machine-readable name.' ),
 577                                  'type'        => 'string',
 578                                  'required'    => true,
 579                              ),
 580                              'title'       => array(
 581                                  'description' => __( 'A human-readable variation title.' ),
 582                                  'type'        => 'string',
 583                                  'required'    => true,
 584                              ),
 585                              'description' => array(
 586                                  'description' => __( 'A detailed variation description.' ),
 587                                  'type'        => 'string',
 588                                  'required'    => false,
 589                              ),
 590                              'category'    => $category_definition,
 591                              'icon'        => $icon_definition,
 592                              'isDefault'   => array(
 593                                  'description' => __( 'Indicates whether the current variation is the default one.' ),
 594                                  'type'        => 'boolean',
 595                                  'required'    => false,
 596                                  'default'     => false,
 597                              ),
 598                              'attributes'  => array(
 599                                  'description' => __( 'The initial values for attributes.' ),
 600                                  'type'        => 'object',
 601                              ),
 602                              'innerBlocks' => $inner_blocks_definition,
 603                              'example'     => $example_definition,
 604                              'scope'       => array(
 605                                  'description' => __( 'The list of scopes where the variation is applicable. When not provided, it assumes all available scopes.' ),
 606                                  'type'        => array( 'array', 'null' ),
 607                                  'default'     => null,
 608                                  'items'       => array(
 609                                      'type' => 'string',
 610                                      'enum' => array( 'block', 'inserter', 'transform' ),
 611                                  ),
 612                                  'readonly'    => true,
 613                              ),
 614                              'keywords'    => $keywords_definition,
 615                          ),
 616                      ),
 617                      'readonly'    => true,
 618                      'context'     => array( 'embed', 'view', 'edit' ),
 619                      'default'     => null,
 620                  ),
 621                  'textdomain'       => array(
 622                      'description' => __( 'Public text domain.' ),
 623                      'type'        => array( 'string', 'null' ),
 624                      'default'     => null,
 625                      'context'     => array( 'embed', 'view', 'edit' ),
 626                      'readonly'    => true,
 627                  ),
 628                  'parent'           => array(
 629                      'description' => __( 'Parent blocks.' ),
 630                      'type'        => array( 'array', 'null' ),
 631                      'items'       => array(
 632                          'type' => 'string',
 633                      ),
 634                      'default'     => null,
 635                      'context'     => array( 'embed', 'view', 'edit' ),
 636                      'readonly'    => true,
 637                  ),
 638                  'keywords'         => $keywords_definition,
 639                  'example'          => $example_definition,
 640              ),
 641          );
 642  
 643          $this->schema = $schema;
 644  
 645          return $this->add_additional_fields_schema( $this->schema );
 646      }
 647  
 648      /**
 649       * Retrieves the query params for collections.
 650       *
 651       * @since 5.5.0
 652       *
 653       * @return array Collection parameters.
 654       */
 655  	public function get_collection_params() {
 656          return array(
 657              'context'   => $this->get_context_param( array( 'default' => 'view' ) ),
 658              'namespace' => array(
 659                  'description' => __( 'Block namespace.' ),
 660                  'type'        => 'string',
 661              ),
 662          );
 663      }
 664  
 665  }


Generated: Mon Apr 19 01:00:04 2021 Cross-referenced by PHPXref 0.7.1