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


Generated : Sat Sep 12 08:20:32 2026 Cross-referenced by PHPXref