[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

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              '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  }


Generated : Sat Oct 31 08:20:01 2020 Cross-referenced by PHPXref