[ 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   * @phpstan-import-type Block_Style_Properties from WP_Block_Styles_Registry
  18   */
  19  class WP_REST_Block_Types_Controller extends WP_REST_Controller {
  20  
  21      const NAME_PATTERN = '^[a-z][a-z0-9-]*/[a-z][a-z0-9-]*$';
  22  
  23      /**
  24       * Instance of WP_Block_Type_Registry.
  25       *
  26       * @since 5.5.0
  27       * @var WP_Block_Type_Registry
  28       */
  29      protected $block_registry;
  30  
  31      /**
  32       * Instance of WP_Block_Styles_Registry.
  33       *
  34       * @since 5.5.0
  35       * @var WP_Block_Styles_Registry
  36       */
  37      protected $style_registry;
  38  
  39      /**
  40       * Constructor.
  41       *
  42       * @since 5.5.0
  43       */
  44  	public function __construct() {
  45          $this->namespace      = 'wp/v2';
  46          $this->rest_base      = 'block-types';
  47          $this->block_registry = WP_Block_Type_Registry::get_instance();
  48          $this->style_registry = WP_Block_Styles_Registry::get_instance();
  49      }
  50  
  51      /**
  52       * Registers the routes for block types.
  53       *
  54       * @since 5.5.0
  55       *
  56       * @see register_rest_route()
  57       */
  58  	public function register_routes() {
  59  
  60          register_rest_route(
  61              $this->namespace,
  62              '/' . $this->rest_base,
  63              array(
  64                  array(
  65                      'methods'             => WP_REST_Server::READABLE,
  66                      'callback'            => array( $this, 'get_items' ),
  67                      'permission_callback' => array( $this, 'get_items_permissions_check' ),
  68                      'args'                => $this->get_collection_params(),
  69                  ),
  70                  'schema' => array( $this, 'get_public_item_schema' ),
  71              )
  72          );
  73  
  74          register_rest_route(
  75              $this->namespace,
  76              '/' . $this->rest_base . '/(?P<namespace>[a-zA-Z0-9_-]+)',
  77              array(
  78                  array(
  79                      'methods'             => WP_REST_Server::READABLE,
  80                      'callback'            => array( $this, 'get_items' ),
  81                      'permission_callback' => array( $this, 'get_items_permissions_check' ),
  82                      'args'                => $this->get_collection_params(),
  83                  ),
  84                  'schema' => array( $this, 'get_public_item_schema' ),
  85              )
  86          );
  87  
  88          register_rest_route(
  89              $this->namespace,
  90              '/' . $this->rest_base . '/(?P<namespace>[a-zA-Z0-9_-]+)/(?P<name>[a-zA-Z0-9_-]+)',
  91              array(
  92                  'args'   => array(
  93                      'name'      => array(
  94                          'description' => __( 'Block name.' ),
  95                          'type'        => 'string',
  96                      ),
  97                      'namespace' => array(
  98                          'description' => __( 'Block namespace.' ),
  99                          'type'        => 'string',
 100                      ),
 101                  ),
 102                  array(
 103                      'methods'             => WP_REST_Server::READABLE,
 104                      'callback'            => array( $this, 'get_item' ),
 105                      'permission_callback' => array( $this, 'get_item_permissions_check' ),
 106                      'args'                => array(
 107                          'context' => $this->get_context_param( array( 'default' => 'view' ) ),
 108                      ),
 109                  ),
 110                  'schema' => array( $this, 'get_public_item_schema' ),
 111              )
 112          );
 113      }
 114  
 115      /**
 116       * Checks whether a given request has permission to read post block types.
 117       *
 118       * @since 5.5.0
 119       *
 120       * @param WP_REST_Request $request Full details about the request.
 121       * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
 122       */
 123  	public function get_items_permissions_check( $request ) {
 124          return $this->check_read_permission();
 125      }
 126  
 127      /**
 128       * Retrieves all post block types, depending on user context.
 129       *
 130       * @since 5.5.0
 131       *
 132       * @param WP_REST_Request $request Full details about the request.
 133       * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
 134       */
 135  	public function get_items( $request ) {
 136          if ( $request->is_method( 'HEAD' ) ) {
 137              // Return early as this handler doesn't add any response headers.
 138              return new WP_REST_Response( array() );
 139          }
 140  
 141          $data        = array();
 142          $block_types = $this->block_registry->get_all_registered();
 143  
 144          // Retrieve the list of registered collection query parameters.
 145          $registered = $this->get_collection_params();
 146          $namespace  = '';
 147          if ( isset( $registered['namespace'] ) && ! empty( $request['namespace'] ) ) {
 148              $namespace = $request['namespace'];
 149          }
 150  
 151          foreach ( $block_types as $obj ) {
 152              if ( $namespace ) {
 153                  list ( $block_namespace ) = explode( '/', $obj->name );
 154  
 155                  if ( $namespace !== $block_namespace ) {
 156                      continue;
 157                  }
 158              }
 159              $block_type = $this->prepare_item_for_response( $obj, $request );
 160              $data[]     = $this->prepare_response_for_collection( $block_type );
 161          }
 162  
 163          return rest_ensure_response( $data );
 164      }
 165  
 166      /**
 167       * Checks if a given request has access to read a block type.
 168       *
 169       * @since 5.5.0
 170       *
 171       * @param WP_REST_Request $request Full details about the request.
 172       * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise.
 173       */
 174  	public function get_item_permissions_check( $request ) {
 175          $check = $this->check_read_permission();
 176          if ( is_wp_error( $check ) ) {
 177              return $check;
 178          }
 179          $block_name = sprintf( '%s/%s', $request['namespace'], $request['name'] );
 180          $block_type = $this->get_block( $block_name );
 181          if ( is_wp_error( $block_type ) ) {
 182              return $block_type;
 183          }
 184  
 185          return true;
 186      }
 187  
 188      /**
 189       * Checks whether a given block type should be visible.
 190       *
 191       * @since 5.5.0
 192       *
 193       * @return true|WP_Error True if the block type is visible, WP_Error otherwise.
 194       */
 195  	protected function check_read_permission() {
 196          if ( current_user_can( 'edit_posts' ) ) {
 197              return true;
 198          }
 199          foreach ( get_post_types( array( 'show_in_rest' => true ), 'objects' ) as $post_type ) {
 200              if ( current_user_can( $post_type->cap->edit_posts ) ) {
 201                  return true;
 202              }
 203          }
 204  
 205          return new WP_Error( 'rest_block_type_cannot_view', __( 'Sorry, you are not allowed to manage block types.' ), array( 'status' => rest_authorization_required_code() ) );
 206      }
 207  
 208      /**
 209       * Get the block, if the name is valid.
 210       *
 211       * @since 5.5.0
 212       *
 213       * @param string $name Block name.
 214       * @return WP_Block_Type|WP_Error Block type object if name is valid, WP_Error otherwise.
 215       */
 216  	protected function get_block( $name ) {
 217          $block_type = $this->block_registry->get_registered( $name );
 218          if ( empty( $block_type ) ) {
 219              return new WP_Error( 'rest_block_type_invalid', __( 'Invalid block type.' ), array( 'status' => 404 ) );
 220          }
 221  
 222          return $block_type;
 223      }
 224  
 225      /**
 226       * Retrieves a specific block type.
 227       *
 228       * @since 5.5.0
 229       *
 230       * @param WP_REST_Request $request Full details about the request.
 231       * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
 232       */
 233  	public function get_item( $request ) {
 234          $block_name = sprintf( '%s/%s', $request['namespace'], $request['name'] );
 235          $block_type = $this->get_block( $block_name );
 236          if ( is_wp_error( $block_type ) ) {
 237              return $block_type;
 238          }
 239          $data = $this->prepare_item_for_response( $block_type, $request );
 240  
 241          return rest_ensure_response( $data );
 242      }
 243  
 244      /**
 245       * Prepares a block type object for serialization.
 246       *
 247       * @since 5.5.0
 248       * @since 5.9.0 Renamed `$block_type` to `$item` to match parent class for PHP 8 named parameter support.
 249       * @since 6.3.0 Added `selectors` field.
 250       * @since 6.5.0 Added `view_script_module_ids` field.
 251       *
 252       * @param WP_Block_Type   $item    Block type data.
 253       * @param WP_REST_Request $request Full details about the request.
 254       * @return WP_REST_Response Block type data.
 255       */
 256  	public function prepare_item_for_response( $item, $request ) {
 257          // Restores the more descriptive, specific name for use within this method.
 258          $block_type = $item;
 259  
 260          // Don't prepare the response body for HEAD requests.
 261          if ( $request->is_method( 'HEAD' ) ) {
 262              /** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-block-types-controller.php */
 263              return apply_filters( 'rest_prepare_block_type', new WP_REST_Response( array() ), $block_type, $request );
 264          }
 265  
 266          $fields = $this->get_fields_for_response( $request );
 267          $data   = array();
 268  
 269          if ( rest_is_field_included( 'attributes', $fields ) ) {
 270              $data['attributes'] = $block_type->get_attributes();
 271          }
 272  
 273          if ( rest_is_field_included( 'is_dynamic', $fields ) ) {
 274              $data['is_dynamic'] = $block_type->is_dynamic();
 275          }
 276  
 277          $schema = $this->get_item_schema();
 278          // Fields deprecated in WordPress 6.1, but left in the schema for backwards compatibility.
 279          $deprecated_fields = array(
 280              'editor_script',
 281              'script',
 282              'view_script',
 283              'editor_style',
 284              'style',
 285          );
 286          $extra_fields      = array_merge(
 287              array(
 288                  'api_version',
 289                  'name',
 290                  'title',
 291                  'description',
 292                  'icon',
 293                  'category',
 294                  'keywords',
 295                  'parent',
 296                  'ancestor',
 297                  'allowed_blocks',
 298                  'provides_context',
 299                  'uses_context',
 300                  'selectors',
 301                  'supports',
 302                  'styles',
 303                  'textdomain',
 304                  'example',
 305                  'editor_script_handles',
 306                  'script_handles',
 307                  'view_script_handles',
 308                  'view_script_module_ids',
 309                  'editor_style_handles',
 310                  'style_handles',
 311                  'view_style_handles',
 312                  'variations',
 313                  'block_hooks',
 314              ),
 315              $deprecated_fields
 316          );
 317          foreach ( $extra_fields as $extra_field ) {
 318              if ( rest_is_field_included( $extra_field, $fields ) ) {
 319                  if ( isset( $block_type->$extra_field ) ) {
 320                      $field = $block_type->$extra_field;
 321                      if ( in_array( $extra_field, $deprecated_fields, true ) && is_array( $field ) ) {
 322                          // Since the schema only allows strings or null (but no arrays), we return the first array item.
 323                          $field = ! empty( $field ) ? array_shift( $field ) : '';
 324                      }
 325                  } elseif ( array_key_exists( 'default', $schema['properties'][ $extra_field ] ) ) {
 326                      $field = $schema['properties'][ $extra_field ]['default'];
 327                  } else {
 328                      $field = '';
 329                  }
 330                  $data[ $extra_field ] = rest_sanitize_value_from_schema( $field, $schema['properties'][ $extra_field ] );
 331              }
 332          }
 333  
 334          if ( rest_is_field_included( 'styles', $fields ) ) {
 335              $styles = $this->style_registry->get_registered_styles_for_block( $block_type->name );
 336              $styles = array_values( $styles );
 337  
 338              /*
 339               * The loop above assigns this key from rest_sanitize_value_from_schema(), whose
 340               * return is documented as `mixed|WP_Error`, so what the styles came back as has
 341               * to be restated here. A WP_Error is why the value is checked rather than cast.
 342               */
 343              /**
 344               * @var array<string, mixed>[] $block_styles
 345               * @phpstan-var list<Block_Style_Properties> $block_styles
 346               */
 347              $block_styles = isset( $data['styles'] ) && is_array( $data['styles'] ) ? $data['styles'] : array();
 348  
 349              $data['styles'] = array_merge( $block_styles, $styles );
 350              $data['styles'] = array_filter( $data['styles'] );
 351          }
 352  
 353          $context = ! empty( $request['context'] ) ? $request['context'] : 'view';
 354          $data    = $this->add_additional_fields_to_object( $data, $request );
 355          $data    = $this->filter_response_by_context( $data, $context );
 356  
 357          $response = rest_ensure_response( $data );
 358  
 359          if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) {
 360              $response->add_links( $this->prepare_links( $block_type ) );
 361          }
 362  
 363          /**
 364           * Filters a block type returned from the REST API.
 365           *
 366           * Allows modification of the block type data right before it is returned.
 367           *
 368           * @since 5.5.0
 369           *
 370           * @param WP_REST_Response $response   The response object.
 371           * @param WP_Block_Type    $block_type The original block type object.
 372           * @param WP_REST_Request  $request    Request used to generate the response.
 373           */
 374          return apply_filters( 'rest_prepare_block_type', $response, $block_type, $request );
 375      }
 376  
 377      /**
 378       * Prepares links for the request.
 379       *
 380       * @since 5.5.0
 381       *
 382       * @param WP_Block_Type $block_type Block type data.
 383       * @return array Links for the given block type.
 384       */
 385  	protected function prepare_links( $block_type ) {
 386          list( $namespace ) = explode( '/', $block_type->name );
 387  
 388          $links = array(
 389              'collection' => array(
 390                  'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ),
 391              ),
 392              'self'       => array(
 393                  'href' => rest_url( sprintf( '%s/%s/%s', $this->namespace, $this->rest_base, $block_type->name ) ),
 394              ),
 395              'up'         => array(
 396                  'href' => rest_url( sprintf( '%s/%s/%s', $this->namespace, $this->rest_base, $namespace ) ),
 397              ),
 398          );
 399  
 400          if ( $block_type->is_dynamic() ) {
 401              $links['https://api.w.org/render-block'] = array(
 402                  'href' => add_query_arg(
 403                      'context',
 404                      'edit',
 405                      rest_url( sprintf( '%s/%s/%s', 'wp/v2', 'block-renderer', $block_type->name ) )
 406                  ),
 407              );
 408          }
 409  
 410          return $links;
 411      }
 412  
 413      /**
 414       * Retrieves the block type' schema, conforming to JSON Schema.
 415       *
 416       * @since 5.5.0
 417       * @since 6.3.0 Added `selectors` field.
 418       *
 419       * @return array Item schema data.
 420       */
 421  	public function get_item_schema() {
 422          if ( $this->schema ) {
 423              return $this->add_additional_fields_schema( $this->schema );
 424          }
 425  
 426          // rest_validate_value_from_schema doesn't understand $refs, pull out reused definitions for readability.
 427          $inner_blocks_definition = array(
 428              'description' => __( 'The list of inner blocks used in the example.' ),
 429              'type'        => 'array',
 430              'items'       => array(
 431                  'type'       => 'object',
 432                  'properties' => array(
 433                      'name'        => array(
 434                          'description' => __( 'The name of the inner block.' ),
 435                          'type'        => 'string',
 436                          'pattern'     => self::NAME_PATTERN,
 437                          'required'    => true,
 438                      ),
 439                      'attributes'  => array(
 440                          'description' => __( 'The attributes of the inner block.' ),
 441                          'type'        => 'object',
 442                      ),
 443                      'innerBlocks' => array(
 444                          'description' => __( "A list of the inner block's own inner blocks. This is a recursive definition following the parent innerBlocks schema." ),
 445                          'type'        => 'array',
 446                      ),
 447                  ),
 448              ),
 449          );
 450  
 451          $example_definition = array(
 452              'description' => __( 'Block example.' ),
 453              'type'        => array( 'object', 'null' ),
 454              'default'     => null,
 455              'properties'  => array(
 456                  'attributes'  => array(
 457                      'description' => __( 'The attributes used in the example.' ),
 458                      'type'        => 'object',
 459                  ),
 460                  'innerBlocks' => $inner_blocks_definition,
 461              ),
 462              'context'     => array( 'embed', 'view', 'edit' ),
 463              'readonly'    => true,
 464          );
 465  
 466          $keywords_definition = array(
 467              'description' => __( 'Block keywords.' ),
 468              'type'        => 'array',
 469              'items'       => array(
 470                  'type' => 'string',
 471              ),
 472              'default'     => array(),
 473              'context'     => array( 'embed', 'view', 'edit' ),
 474              'readonly'    => true,
 475          );
 476  
 477          $icon_definition = array(
 478              'description' => __( 'Icon of block type.' ),
 479              'type'        => array( 'string', 'null' ),
 480              'default'     => null,
 481              'context'     => array( 'embed', 'view', 'edit' ),
 482              'readonly'    => true,
 483          );
 484  
 485          $category_definition = array(
 486              'description' => __( 'Block category.' ),
 487              'type'        => array( 'string', 'null' ),
 488              'default'     => null,
 489              'context'     => array( 'embed', 'view', 'edit' ),
 490              'readonly'    => true,
 491          );
 492  
 493          $this->schema = array(
 494              '$schema'    => 'http://json-schema.org/draft-04/schema#',
 495              'title'      => 'block-type',
 496              'type'       => 'object',
 497              'properties' => array(
 498                  'api_version'            => array(
 499                      'description' => __( 'Version of block API.' ),
 500                      'type'        => 'integer',
 501                      'default'     => 1,
 502                      'context'     => array( 'embed', 'view', 'edit' ),
 503                      'readonly'    => true,
 504                  ),
 505                  'title'                  => array(
 506                      'description' => __( 'Title of block type.' ),
 507                      'type'        => 'string',
 508                      'default'     => '',
 509                      'context'     => array( 'embed', 'view', 'edit' ),
 510                      'readonly'    => true,
 511                  ),
 512                  'name'                   => array(
 513                      'description' => __( 'Unique name identifying the block type.' ),
 514                      'type'        => 'string',
 515                      'pattern'     => self::NAME_PATTERN,
 516                      'required'    => true,
 517                      'context'     => array( 'embed', 'view', 'edit' ),
 518                      'readonly'    => true,
 519                  ),
 520                  'description'            => array(
 521                      'description' => __( 'Description of block type.' ),
 522                      'type'        => 'string',
 523                      'default'     => '',
 524                      'context'     => array( 'embed', 'view', 'edit' ),
 525                      'readonly'    => true,
 526                  ),
 527                  'icon'                   => $icon_definition,
 528                  'attributes'             => array(
 529                      'description'          => __( 'Block attributes.' ),
 530                      'type'                 => array( 'object', 'null' ),
 531                      'properties'           => array(),
 532                      'default'              => null,
 533                      'additionalProperties' => array(
 534                          'type' => 'object',
 535                      ),
 536                      'context'              => array( 'embed', 'view', 'edit' ),
 537                      'readonly'             => true,
 538                  ),
 539                  'provides_context'       => array(
 540                      'description'          => __( 'Context provided by blocks of this type.' ),
 541                      'type'                 => 'object',
 542                      'properties'           => array(),
 543                      'additionalProperties' => array(
 544                          'type' => 'string',
 545                      ),
 546                      'default'              => array(),
 547                      'context'              => array( 'embed', 'view', 'edit' ),
 548                      'readonly'             => true,
 549                  ),
 550                  'uses_context'           => array(
 551                      'description' => __( 'Context values inherited by blocks of this type.' ),
 552                      'type'        => 'array',
 553                      'default'     => array(),
 554                      'items'       => array(
 555                          'type' => 'string',
 556                      ),
 557                      'context'     => array( 'embed', 'view', 'edit' ),
 558                      'readonly'    => true,
 559                  ),
 560                  'selectors'              => array(
 561                      'description' => __( 'Custom CSS selectors.' ),
 562                      'type'        => 'object',
 563                      'default'     => array(),
 564                      'properties'  => array(),
 565                      'context'     => array( 'embed', 'view', 'edit' ),
 566                      'readonly'    => true,
 567                  ),
 568                  'supports'               => array(
 569                      'description' => __( 'Block supports.' ),
 570                      'type'        => 'object',
 571                      'default'     => array(),
 572                      'properties'  => array(),
 573                      'context'     => array( 'embed', 'view', 'edit' ),
 574                      'readonly'    => true,
 575                  ),
 576                  'category'               => $category_definition,
 577                  'is_dynamic'             => array(
 578                      'description' => __( 'Is the block dynamically rendered.' ),
 579                      'type'        => 'boolean',
 580                      'default'     => false,
 581                      'context'     => array( 'embed', 'view', 'edit' ),
 582                      'readonly'    => true,
 583                  ),
 584                  'editor_script_handles'  => array(
 585                      'description' => __( 'Editor script handles.' ),
 586                      'type'        => array( 'array' ),
 587                      'default'     => array(),
 588                      'items'       => array(
 589                          'type' => 'string',
 590                      ),
 591                      'context'     => array( 'embed', 'view', 'edit' ),
 592                      'readonly'    => true,
 593                  ),
 594                  'script_handles'         => array(
 595                      'description' => __( 'Public facing and editor script handles.' ),
 596                      'type'        => array( 'array' ),
 597                      'default'     => array(),
 598                      'items'       => array(
 599                          'type' => 'string',
 600                      ),
 601                      'context'     => array( 'embed', 'view', 'edit' ),
 602                      'readonly'    => true,
 603                  ),
 604                  'view_script_handles'    => array(
 605                      'description' => __( 'Public facing script handles.' ),
 606                      'type'        => array( 'array' ),
 607                      'default'     => array(),
 608                      'items'       => array(
 609                          'type' => 'string',
 610                      ),
 611                      'context'     => array( 'embed', 'view', 'edit' ),
 612                      'readonly'    => true,
 613                  ),
 614                  'view_script_module_ids' => array(
 615                      'description' => __( 'Public facing script module IDs.' ),
 616                      'type'        => array( 'array' ),
 617                      'default'     => array(),
 618                      'items'       => array(
 619                          'type' => 'string',
 620                      ),
 621                      'context'     => array( 'embed', 'view', 'edit' ),
 622                      'readonly'    => true,
 623                  ),
 624                  'editor_style_handles'   => array(
 625                      'description' => __( 'Editor style handles.' ),
 626                      'type'        => array( 'array' ),
 627                      'default'     => array(),
 628                      'items'       => array(
 629                          'type' => 'string',
 630                      ),
 631                      'context'     => array( 'embed', 'view', 'edit' ),
 632                      'readonly'    => true,
 633                  ),
 634                  'style_handles'          => array(
 635                      'description' => __( 'Public facing and editor style handles.' ),
 636                      'type'        => array( 'array' ),
 637                      'default'     => array(),
 638                      'items'       => array(
 639                          'type' => 'string',
 640                      ),
 641                      'context'     => array( 'embed', 'view', 'edit' ),
 642                      'readonly'    => true,
 643                  ),
 644                  'view_style_handles'     => array(
 645                      'description' => __( 'Public facing style handles.' ),
 646                      'type'        => array( 'array' ),
 647                      'default'     => array(),
 648                      'items'       => array(
 649                          'type' => 'string',
 650                      ),
 651                      'context'     => array( 'embed', 'view', 'edit' ),
 652                      'readonly'    => true,
 653                  ),
 654                  'styles'                 => array(
 655                      'description' => __( 'Block style variations.' ),
 656                      'type'        => 'array',
 657                      'items'       => array(
 658                          'type'       => 'object',
 659                          'properties' => array(
 660                              'name'         => array(
 661                                  'description' => __( 'Unique name identifying the style.' ),
 662                                  'type'        => 'string',
 663                                  'required'    => true,
 664                              ),
 665                              'label'        => array(
 666                                  'description' => __( 'The human-readable label for the style.' ),
 667                                  'type'        => 'string',
 668                              ),
 669                              'inline_style' => array(
 670                                  'description' => __( 'Inline CSS code that registers the CSS class required for the style.' ),
 671                                  'type'        => 'string',
 672                              ),
 673                              'style_handle' => array(
 674                                  'description' => __( 'Contains the handle that defines the block style.' ),
 675                                  'type'        => 'string',
 676                              ),
 677                          ),
 678                      ),
 679                      'default'     => array(),
 680                      'context'     => array( 'embed', 'view', 'edit' ),
 681                      'readonly'    => true,
 682                  ),
 683                  'variations'             => array(
 684                      'description' => __( 'Block variations.' ),
 685                      'type'        => 'array',
 686                      'items'       => array(
 687                          'type'       => 'object',
 688                          'properties' => array(
 689                              'name'        => array(
 690                                  'description' => __( 'The unique and machine-readable name.' ),
 691                                  'type'        => 'string',
 692                                  'required'    => true,
 693                              ),
 694                              'title'       => array(
 695                                  'description' => __( 'A human-readable variation title.' ),
 696                                  'type'        => 'string',
 697                                  'required'    => true,
 698                              ),
 699                              'description' => array(
 700                                  'description' => __( 'A detailed variation description.' ),
 701                                  'type'        => 'string',
 702                                  'required'    => false,
 703                              ),
 704                              'category'    => $category_definition,
 705                              'icon'        => $icon_definition,
 706                              'isDefault'   => array(
 707                                  'description' => __( 'Indicates whether the current variation is the default one.' ),
 708                                  'type'        => 'boolean',
 709                                  'required'    => false,
 710                                  'default'     => false,
 711                              ),
 712                              'attributes'  => array(
 713                                  'description' => __( 'The initial values for attributes.' ),
 714                                  'type'        => 'object',
 715                              ),
 716                              'innerBlocks' => $inner_blocks_definition,
 717                              'example'     => $example_definition,
 718                              'scope'       => array(
 719                                  'description' => __( 'The list of scopes where the variation is applicable. When not provided, it assumes all available scopes.' ),
 720                                  'type'        => array( 'array', 'null' ),
 721                                  'default'     => null,
 722                                  'items'       => array(
 723                                      'type' => 'string',
 724                                      'enum' => array( 'block', 'inserter', 'transform' ),
 725                                  ),
 726                                  'readonly'    => true,
 727                              ),
 728                              'keywords'    => $keywords_definition,
 729                          ),
 730                      ),
 731                      'readonly'    => true,
 732                      'context'     => array( 'embed', 'view', 'edit' ),
 733                      'default'     => null,
 734                  ),
 735                  'textdomain'             => array(
 736                      'description' => __( 'Public text domain.' ),
 737                      'type'        => array( 'string', 'null' ),
 738                      'default'     => null,
 739                      'context'     => array( 'embed', 'view', 'edit' ),
 740                      'readonly'    => true,
 741                  ),
 742                  'parent'                 => array(
 743                      'description' => __( 'Parent blocks.' ),
 744                      'type'        => array( 'array', 'null' ),
 745                      'items'       => array(
 746                          'type'    => 'string',
 747                          'pattern' => self::NAME_PATTERN,
 748                      ),
 749                      'default'     => null,
 750                      'context'     => array( 'embed', 'view', 'edit' ),
 751                      'readonly'    => true,
 752                  ),
 753                  'ancestor'               => array(
 754                      'description' => __( 'Ancestor blocks.' ),
 755                      'type'        => array( 'array', 'null' ),
 756                      'items'       => array(
 757                          'type'    => 'string',
 758                          'pattern' => self::NAME_PATTERN,
 759                      ),
 760                      'default'     => null,
 761                      'context'     => array( 'embed', 'view', 'edit' ),
 762                      'readonly'    => true,
 763                  ),
 764                  'allowed_blocks'         => array(
 765                      'description' => __( 'Allowed child block types.' ),
 766                      'type'        => array( 'array', 'null' ),
 767                      'items'       => array(
 768                          'type'    => 'string',
 769                          'pattern' => self::NAME_PATTERN,
 770                      ),
 771                      'default'     => null,
 772                      'context'     => array( 'embed', 'view', 'edit' ),
 773                      'readonly'    => true,
 774                  ),
 775                  'keywords'               => $keywords_definition,
 776                  'example'                => $example_definition,
 777                  'block_hooks'            => array(
 778                      'description'       => __( 'This block is automatically inserted near any occurrence of the block types used as keys of this map, into a relative position given by the corresponding value.' ),
 779                      'type'              => 'object',
 780                      'patternProperties' => array(
 781                          self::NAME_PATTERN => array(
 782                              'type' => 'string',
 783                              'enum' => array( 'before', 'after', 'first_child', 'last_child' ),
 784                          ),
 785                      ),
 786                      'default'           => array(),
 787                      'context'           => array( 'embed', 'view', 'edit' ),
 788                      'readonly'          => true,
 789                  ),
 790              ),
 791          );
 792  
 793          // Properties deprecated in WordPress 6.1, but left in the schema for backwards compatibility.
 794          $deprecated_properties      = array(
 795              'editor_script' => array(
 796                  'description' => __( 'Editor script handle. DEPRECATED: Use `editor_script_handles` instead.' ),
 797                  'type'        => array( 'string', 'null' ),
 798                  'default'     => null,
 799                  'context'     => array( 'embed', 'view', 'edit' ),
 800                  'readonly'    => true,
 801              ),
 802              'script'        => array(
 803                  'description' => __( 'Public facing and editor script handle. DEPRECATED: Use `script_handles` instead.' ),
 804                  'type'        => array( 'string', 'null' ),
 805                  'default'     => null,
 806                  'context'     => array( 'embed', 'view', 'edit' ),
 807                  'readonly'    => true,
 808              ),
 809              'view_script'   => array(
 810                  'description' => __( 'Public facing script handle. DEPRECATED: Use `view_script_handles` instead.' ),
 811                  'type'        => array( 'string', 'null' ),
 812                  'default'     => null,
 813                  'context'     => array( 'embed', 'view', 'edit' ),
 814                  'readonly'    => true,
 815              ),
 816              'editor_style'  => array(
 817                  'description' => __( 'Editor style handle. DEPRECATED: Use `editor_style_handles` instead.' ),
 818                  'type'        => array( 'string', 'null' ),
 819                  'default'     => null,
 820                  'context'     => array( 'embed', 'view', 'edit' ),
 821                  'readonly'    => true,
 822              ),
 823              'style'         => array(
 824                  'description' => __( 'Public facing and editor style handle. DEPRECATED: Use `style_handles` instead.' ),
 825                  'type'        => array( 'string', 'null' ),
 826                  'default'     => null,
 827                  'context'     => array( 'embed', 'view', 'edit' ),
 828                  'readonly'    => true,
 829              ),
 830          );
 831          $this->schema['properties'] = array_merge( $this->schema['properties'], $deprecated_properties );
 832  
 833          return $this->add_additional_fields_schema( $this->schema );
 834      }
 835  
 836      /**
 837       * Retrieves the query params for collections.
 838       *
 839       * @since 5.5.0
 840       *
 841       * @return array Collection parameters.
 842       */
 843  	public function get_collection_params() {
 844          return array(
 845              'context'   => $this->get_context_param( array( 'default' => 'view' ) ),
 846              'namespace' => array(
 847                  'description' => __( 'Block namespace.' ),
 848                  'type'        => 'string',
 849              ),
 850          );
 851      }
 852  }


Generated : Thu Nov 12 08:20:02 2026 Cross-referenced by PHPXref