[ 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 WP_Error|bool 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_Error|WP_REST_Response 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 WP_Error|bool 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 WP_Error|bool 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_Error|WP_REST_Response 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              'name',
 260              'title',
 261              'description',
 262              'icon',
 263              'category',
 264              'keywords',
 265              'parent',
 266              'provides_context',
 267              'uses_context',
 268              'supports',
 269              'styles',
 270              'textdomain',
 271              'example',
 272              'editor_script',
 273              'script',
 274              'editor_style',
 275              'style',
 276          );
 277          foreach ( $extra_fields as $extra_field ) {
 278              if ( rest_is_field_included( $extra_field, $fields ) ) {
 279                  if ( isset( $block_type->$extra_field ) ) {
 280                      $field = $block_type->$extra_field;
 281                  } elseif ( array_key_exists( 'default', $schema['properties'][ $extra_field ] ) ) {
 282                      $field = $schema['properties'][ $extra_field ]['default'];
 283                  } else {
 284                      $field = '';
 285                  }
 286                  $data[ $extra_field ] = rest_sanitize_value_from_schema( $field, $schema['properties'][ $extra_field ] );
 287              }
 288          }
 289  
 290          if ( rest_is_field_included( 'styles', $fields ) ) {
 291              $styles         = $this->style_registry->get_registered_styles_for_block( $block_type->name );
 292              $styles         = array_values( $styles );
 293              $data['styles'] = wp_parse_args( $styles, $data['styles'] );
 294              $data['styles'] = array_filter( $data['styles'] );
 295          }
 296  
 297          $context = ! empty( $request['context'] ) ? $request['context'] : 'view';
 298          $data    = $this->add_additional_fields_to_object( $data, $request );
 299          $data    = $this->filter_response_by_context( $data, $context );
 300  
 301          $response = rest_ensure_response( $data );
 302  
 303          $response->add_links( $this->prepare_links( $block_type ) );
 304  
 305          /**
 306           * Filters a block type returned from the REST API.
 307           *
 308           * Allows modification of the block type data right before it is returned.
 309           *
 310           * @since 5.5.0
 311           *
 312           * @param WP_REST_Response $response   The response object.
 313           * @param WP_Block_Type    $block_type The original block type object.
 314           * @param WP_REST_Request  $request    Request used to generate the response.
 315           */
 316          return apply_filters( 'rest_prepare_block_type', $response, $block_type, $request );
 317      }
 318  
 319      /**
 320       * Prepares links for the request.
 321       *
 322       * @since 5.5.0
 323       *
 324       * @param WP_Block_Type $block_type Block type data.
 325       * @return array Links for the given block type.
 326       */
 327  	protected function prepare_links( $block_type ) {
 328          list( $namespace ) = explode( '/', $block_type->name );
 329  
 330          $links = array(
 331              'collection' => array(
 332                  'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ),
 333              ),
 334              'self'       => array(
 335                  'href' => rest_url( sprintf( '%s/%s/%s', $this->namespace, $this->rest_base, $block_type->name ) ),
 336              ),
 337              'up'         => array(
 338                  'href' => rest_url( sprintf( '%s/%s/%s', $this->namespace, $this->rest_base, $namespace ) ),
 339              ),
 340          );
 341  
 342          if ( $block_type->is_dynamic() ) {
 343              $links['https://api.w.org/render-block'] = array(
 344                  'href' => add_query_arg( 'context', 'edit', rest_url( sprintf( '%s/%s/%s', 'wp/v2', 'block-renderer', $block_type->name ) ) ),
 345              );
 346          }
 347  
 348          return $links;
 349      }
 350  
 351      /**
 352       * Retrieves the block type' schema, conforming to JSON Schema.
 353       *
 354       * @since 5.5.0
 355       *
 356       * @return array Item schema data.
 357       */
 358  	public function get_item_schema() {
 359          if ( $this->schema ) {
 360              return $this->add_additional_fields_schema( $this->schema );
 361          }
 362  
 363          $schema = array(
 364              '$schema'    => 'http://json-schema.org/draft-04/schema#',
 365              'title'      => 'block-type',
 366              'type'       => 'object',
 367              'properties' => array(
 368                  'title'            => array(
 369                      'description' => __( 'Title of block type.' ),
 370                      'type'        => 'string',
 371                      'default'     => '',
 372                      'context'     => array( 'embed', 'view', 'edit' ),
 373                      'readonly'    => true,
 374                  ),
 375                  'name'             => array(
 376                      'description' => __( 'Unique name identifying the block type.' ),
 377                      'type'        => 'string',
 378                      'default'     => '',
 379                      'context'     => array( 'embed', 'view', 'edit' ),
 380                      'readonly'    => true,
 381                  ),
 382                  'description'      => array(
 383                      'description' => __( 'Description of block type.' ),
 384                      'type'        => 'string',
 385                      'default'     => '',
 386                      'context'     => array( 'embed', 'view', 'edit' ),
 387                      'readonly'    => true,
 388                  ),
 389                  'icon'             => array(
 390                      'description' => __( 'Icon of block type.' ),
 391                      'type'        => array( 'string', 'null' ),
 392                      'default'     => null,
 393                      'context'     => array( 'embed', 'view', 'edit' ),
 394                      'readonly'    => true,
 395                  ),
 396                  'attributes'       => array(
 397                      'description'          => __( 'Block attributes.' ),
 398                      'type'                 => array( 'object', 'null' ),
 399                      'properties'           => array(),
 400                      'default'              => null,
 401                      'additionalProperties' => array(
 402                          'type' => 'object',
 403                      ),
 404                      'context'              => array( 'embed', 'view', 'edit' ),
 405                      'readonly'             => true,
 406                  ),
 407                  'provides_context' => array(
 408                      'description'          => __( 'Context provided by blocks of this type.' ),
 409                      'type'                 => 'object',
 410                      'properties'           => array(),
 411                      'additionalProperties' => array(
 412                          'type' => 'string',
 413                      ),
 414                      'default'              => array(),
 415                      'context'              => array( 'embed', 'view', 'edit' ),
 416                      'readonly'             => true,
 417                  ),
 418                  'uses_context'     => array(
 419                      'description' => __( 'Context values inherited by blocks of this type.' ),
 420                      'type'        => 'array',
 421                      'default'     => array(),
 422                      'items'       => array(
 423                          'type' => 'string',
 424                      ),
 425                      'context'     => array( 'embed', 'view', 'edit' ),
 426                      'readonly'    => true,
 427                  ),
 428                  'supports'         => array(
 429                      'description' => __( 'Block supports.' ),
 430                      'type'        => 'object',
 431                      'default'     => array(),
 432                      'properties'  => array(),
 433                      'context'     => array( 'embed', 'view', 'edit' ),
 434                      'readonly'    => true,
 435                  ),
 436                  'category'         => array(
 437                      'description' => __( 'Block category.' ),
 438                      'type'        => array( 'string', 'null' ),
 439                      'default'     => null,
 440                      'context'     => array( 'embed', 'view', 'edit' ),
 441                      'readonly'    => true,
 442                  ),
 443                  'is_dynamic'       => array(
 444                      'description' => __( 'Is the block dynamically rendered.' ),
 445                      'type'        => 'boolean',
 446                      'default'     => false,
 447                      'context'     => array( 'embed', 'view', 'edit' ),
 448                      'readonly'    => true,
 449                  ),
 450                  'editor_script'    => array(
 451                      'description' => __( 'Editor script handle.' ),
 452                      'type'        => array( 'string', 'null' ),
 453                      'default'     => null,
 454                      'context'     => array( 'embed', 'view', 'edit' ),
 455                      'readonly'    => true,
 456                  ),
 457                  'script'           => array(
 458                      'description' => __( 'Public facing script handle.' ),
 459                      'type'        => array( 'string', 'null' ),
 460                      'default'     => null,
 461                      'context'     => array( 'embed', 'view', 'edit' ),
 462                      'readonly'    => true,
 463                  ),
 464                  'editor_style'     => array(
 465                      'description' => __( 'Editor style handle.' ),
 466                      'type'        => array( 'string', 'null' ),
 467                      'default'     => null,
 468                      'context'     => array( 'embed', 'view', 'edit' ),
 469                      'readonly'    => true,
 470                  ),
 471                  'style'            => array(
 472                      'description' => __( 'Public facing style handle.' ),
 473                      'type'        => array( 'string', 'null' ),
 474                      'default'     => null,
 475                      'context'     => array( 'embed', 'view', 'edit' ),
 476                      'readonly'    => true,
 477                  ),
 478                  'styles'           => array(
 479                      'description' => __( 'Block style variations.' ),
 480                      'type'        => 'array',
 481                      'items'       => array(
 482                          'type'       => 'object',
 483                          'properties' => array(
 484                              'name'         => array(
 485                                  'description' => __( 'Unique name identifying the style.' ),
 486                                  'type'        => 'string',
 487                                  'required'    => true,
 488                              ),
 489                              'label'        => array(
 490                                  'description' => __( 'The human-readable label for the style.' ),
 491                                  'type'        => 'string',
 492                              ),
 493                              'inline_style' => array(
 494                                  'description' => __( 'Inline CSS code that registers the CSS class required for the style.' ),
 495                                  'type'        => 'string',
 496                              ),
 497                              'style_handle' => array(
 498                                  'description' => __( 'Contains the handle that defines the block style.' ),
 499                                  'type'        => 'string',
 500                              ),
 501                          ),
 502                      ),
 503                      'default'     => array(),
 504                      'context'     => array( 'embed', 'view', 'edit' ),
 505                      'readonly'    => true,
 506                  ),
 507                  'textdomain'       => array(
 508                      'description' => __( 'Public text domain.' ),
 509                      'type'        => array( 'string', 'null' ),
 510                      'default'     => null,
 511                      'context'     => array( 'embed', 'view', 'edit' ),
 512                      'readonly'    => true,
 513                  ),
 514                  'parent'           => array(
 515                      'description' => __( 'Parent blocks.' ),
 516                      'type'        => array( 'array', 'null' ),
 517                      'items'       => array(
 518                          'type' => 'string',
 519                      ),
 520                      'default'     => null,
 521                      'context'     => array( 'embed', 'view', 'edit' ),
 522                      'readonly'    => true,
 523                  ),
 524                  'keywords'         => array(
 525                      'description' => __( 'Block keywords.' ),
 526                      'type'        => 'array',
 527                      'items'       => array(
 528                          'type' => 'string',
 529                      ),
 530                      'default'     => array(),
 531                      'context'     => array( 'embed', 'view', 'edit' ),
 532                      'readonly'    => true,
 533                  ),
 534                  'example'          => array(
 535                      'description' => __( 'Block example.' ),
 536                      'type'        => array( 'object', 'null' ),
 537                      'default'     => null,
 538                      'properties'  => array(
 539                          'attributes'  => array(
 540                              'description' => __( 'The attributes used in the example.' ),
 541                              'type'        => 'object',
 542                          ),
 543                          'innerBlocks' => array(
 544                              'description' => __( 'The list of inner blocks used in the example.' ),
 545                              'type'        => 'array',
 546                              'items'       => array(
 547                                  'type'       => 'object',
 548                                  'properties' => array(
 549                                      'name'        => array(
 550                                          'description' => __( 'The name of the inner block.' ),
 551                                          'type'        => 'string',
 552                                      ),
 553                                      'attributes'  => array(
 554                                          'description' => __( 'The attributes of the inner block.' ),
 555                                          'type'        => 'object',
 556                                      ),
 557                                      'innerBlocks' => array(
 558                                          'description' => __( "A list of the inner block's own inner blocks. This is a recursive definition following the parent innerBlocks schema." ),
 559                                          'type'        => 'array',
 560                                      ),
 561                                  ),
 562                              ),
 563                          ),
 564                      ),
 565                      'context'     => array( 'embed', 'view', 'edit' ),
 566                      'readonly'    => true,
 567                  ),
 568              ),
 569          );
 570  
 571          $this->schema = $schema;
 572  
 573          return $this->add_additional_fields_schema( $this->schema );
 574      }
 575  
 576      /**
 577       * Retrieves the query params for collections.
 578       *
 579       * @since 5.5.0
 580       *
 581       * @return array Collection parameters.
 582       */
 583  	public function get_collection_params() {
 584          return array(
 585              'context'   => $this->get_context_param( array( 'default' => 'view' ) ),
 586              'namespace' => array(
 587                  'description' => __( 'Block namespace.' ),
 588                  'type'        => 'string',
 589              ),
 590          );
 591      }
 592  
 593  }


Generated: Wed Aug 12 01:00:03 2020 Cross-referenced by PHPXref 0.7.1