[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/rest-api/endpoints/ -> class-wp-rest-view-config-controller.php (source)

   1  <?php
   2  /**
   3   * REST API: WP_REST_View_Config_Controller class
   4   *
   5   * @package    WordPress
   6   * @subpackage REST_API
   7   * @since      7.1.0
   8   */
   9  
  10  /**
  11   * Controller which provides a REST endpoint for retrieving the default
  12   * view configuration for a given entity type.
  13   *
  14   * @since 7.1.0
  15   *
  16   * @see WP_REST_Controller
  17   */
  18  class WP_REST_View_Config_Controller extends WP_REST_Controller {
  19  
  20      /**
  21       * Constructor.
  22       *
  23       * @since 7.1.0
  24       */
  25  	public function __construct() {
  26          $this->namespace = 'wp/v2';
  27          $this->rest_base = 'view-config';
  28      }
  29  
  30      /**
  31       * Registers the routes for the controller.
  32       *
  33       * @since 7.1.0
  34       */
  35  	public function register_routes() {
  36          register_rest_route(
  37              $this->namespace,
  38              '/' . $this->rest_base,
  39              array(
  40                  array(
  41                      'methods'             => WP_REST_Server::READABLE,
  42                      'callback'            => array( $this, 'get_items' ),
  43                      'permission_callback' => array( $this, 'get_items_permissions_check' ),
  44                      'args'                => array(
  45                          'kind' => array(
  46                              'description' => __( 'Entity kind.' ),
  47                              'type'        => 'string',
  48                              'required'    => true,
  49                          ),
  50                          'name' => array(
  51                              'description' => __( 'Entity name.' ),
  52                              'type'        => 'string',
  53                              'required'    => true,
  54                          ),
  55                      ),
  56                  ),
  57                  'schema' => array( $this, 'get_public_item_schema' ),
  58              )
  59          );
  60      }
  61  
  62      /**
  63       * Checks if a given request has access to read view config.
  64       *
  65       * @since 7.1.0
  66       *
  67       * @param WP_REST_Request $request Full details about the request.
  68       * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
  69       */
  70  	public function get_items_permissions_check( $request ) {
  71          $kind = $request->get_param( 'kind' );
  72          $name = $request->get_param( 'name' );
  73  
  74          $capability = $this->get_required_capability( $kind, $name );
  75  
  76          if ( null === $capability ) {
  77              return new WP_Error(
  78                  'rest_view_config_invalid_entity',
  79                  __( 'Invalid entity kind or name.' ),
  80                  array( 'status' => 404 )
  81              );
  82          }
  83  
  84          if ( ! current_user_can( $capability ) ) {
  85              return new WP_Error(
  86                  'rest_cannot_read',
  87                  __( 'Sorry, you are not allowed to read view config.' ),
  88                  array( 'status' => rest_authorization_required_code() )
  89              );
  90          }
  91  
  92          return true;
  93      }
  94  
  95      /**
  96       * Resolves the capability required to read the view config for an entity.
  97       *
  98       * Known kinds map to the capability that gates managing that entity's list:
  99       * post types use their own `edit_posts` capability (which honors custom
 100       * `capability_type` registrations), taxonomies use `manage_terms`, and
 101       * root-level entities use `manage_options`. A post type or taxonomy that is
 102       * not registered, or not exposed to the REST API, resolves to `null` so the
 103       * request is treated as referencing an unknown entity.
 104       *
 105       * Any other kind falls back to `edit_posts`. This keeps entities registered
 106       * through the `get_entity_view_config_{$kind}_{$name}` filter readable behind
 107       * a baseline capability.
 108       *
 109       * @since 7.1.0
 110       *
 111       * @param string $kind The entity kind (e.g. `postType`).
 112       * @param string $name The entity name (e.g. `page`).
 113       * @return string|null Capability required to read the config, or null if the
 114       *                     entity is not registered.
 115       */
 116  	protected function get_required_capability( $kind, $name ) {
 117          switch ( $kind ) {
 118              case 'postType':
 119                  $post_type = get_post_type_object( $name );
 120                  if ( $post_type && $post_type->show_in_rest ) {
 121                      return $post_type->cap->edit_posts;
 122                  }
 123                  return null;
 124  
 125              case 'taxonomy':
 126                  $taxonomy = get_taxonomy( $name );
 127                  if ( $taxonomy && $taxonomy->show_in_rest ) {
 128                      return $taxonomy->cap->manage_terms;
 129                  }
 130                  return null;
 131  
 132              case 'root':
 133                  return 'manage_options';
 134          }
 135  
 136          return 'edit_posts';
 137      }
 138  
 139      /**
 140       * Returns the default view configuration for the given entity type.
 141       *
 142       * @since 7.1.0
 143       *
 144       * @param WP_REST_Request $request Full details about the request.
 145       * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
 146       */
 147  	public function get_items( $request ) {
 148          $kind = $request->get_param( 'kind' );
 149          $name = $request->get_param( 'name' );
 150  
 151          $config = wp_get_entity_view_config( $kind, $name );
 152          $schema = $this->get_item_schema();
 153  
 154          $response = array(
 155              'kind'            => $kind,
 156              'name'            => $name,
 157              'default_view'    => $this->cast_empty_objects( $config['default_view'], $schema['properties']['default_view'] ),
 158              'default_layouts' => $this->cast_empty_objects( $config['default_layouts'], $schema['properties']['default_layouts'] ),
 159              'view_list'       => $this->cast_empty_objects( $config['view_list'], $schema['properties']['view_list'] ),
 160              'form'            => $this->cast_empty_objects( $config['form'], $schema['properties']['form'] ),
 161          );
 162  
 163          return rest_ensure_response( $response );
 164      }
 165  
 166      /**
 167       * Recursively casts empty arrays to objects where the schema types them as
 168       * objects.
 169       *
 170       * PHP cannot distinguish an empty associative array from an empty list, so
 171       * `json_encode()` always serializes `array()` as a JSON array (`[]`). The
 172       * REST schema, however, types several values as objects, which must encode
 173       * as `{}`. This walks the value against its schema and casts any empty,
 174       * object-typed array to an object. Non-empty associative arrays already
 175       * encode as objects, so they are left as arrays and only recursed into to
 176       * fix any nested empty objects.
 177       *
 178       * Union schemas (`oneOf`/`anyOf`) are handled only for the empty-array case:
 179       * an empty value is cast to an object when any branch allows an object. Such
 180       * values are not recursed into, which is sufficient for the form schema
 181       * where they never contain empty nested objects.
 182       *
 183       * @since 7.1.0
 184       *
 185       * @param mixed $value  The value to normalize.
 186       * @param array $schema The schema node describing the value.
 187       * @return mixed The normalized value, with empty object-typed arrays cast to objects.
 188       */
 189  	protected function cast_empty_objects( $value, $schema ) {
 190          if ( ! is_array( $value ) || ! is_array( $schema ) ) {
 191              return $value;
 192          }
 193  
 194          if ( isset( $schema['oneOf'] ) || isset( $schema['anyOf'] ) ) {
 195              $branches = isset( $schema['oneOf'] ) ? $schema['oneOf'] : $schema['anyOf'];
 196              if ( array() === $value ) {
 197                  foreach ( $branches as $branch ) {
 198                      if ( is_array( $branch ) && in_array( 'object', (array) ( isset( $branch['type'] ) ? $branch['type'] : array() ), true ) ) {
 199                          return (object) array();
 200                      }
 201                  }
 202              }
 203              return $value;
 204          }
 205  
 206          $types = (array) ( isset( $schema['type'] ) ? $schema['type'] : array() );
 207  
 208          if ( in_array( 'array', $types, true ) && isset( $schema['items'] ) ) {
 209              foreach ( $value as $index => $item ) {
 210                  $value[ $index ] = $this->cast_empty_objects( $item, $schema['items'] );
 211              }
 212              return $value;
 213          }
 214  
 215          if ( in_array( 'object', $types, true ) ) {
 216              if ( isset( $schema['properties'] ) ) {
 217                  foreach ( $schema['properties'] as $property => $property_schema ) {
 218                      if ( array_key_exists( $property, $value ) ) {
 219                          $value[ $property ] = $this->cast_empty_objects( $value[ $property ], $property_schema );
 220                      }
 221                  }
 222              }
 223              if ( isset( $schema['additionalProperties'] ) && is_array( $schema['additionalProperties'] ) ) {
 224                  foreach ( $value as $key => $item ) {
 225                      if ( isset( $schema['properties'][ $key ] ) ) {
 226                          continue;
 227                      }
 228                      $value[ $key ] = $this->cast_empty_objects( $item, $schema['additionalProperties'] );
 229                  }
 230              }
 231  
 232              // Empty object-typed arrays must serialize as {} to match the schema.
 233              if ( array() === $value ) {
 234                  return (object) array();
 235              }
 236          }
 237  
 238          return $value;
 239      }
 240  
 241      /**
 242       * Retrieves the item's schema, conforming to JSON Schema.
 243       *
 244       * @since 7.1.0
 245       *
 246       * @return array Item schema data.
 247       */
 248  	public function get_item_schema() {
 249          if ( $this->schema ) {
 250              return $this->add_additional_fields_schema( $this->schema );
 251          }
 252  
 253          $view_base_properties = $this->get_view_base_schema();
 254  
 255          $this->schema = array(
 256              '$schema'    => 'http://json-schema.org/draft-04/schema#',
 257              'title'      => 'view-config',
 258              'type'       => 'object',
 259              'properties' => array(
 260                  'kind'            => array(
 261                      'description' => __( 'Entity kind.' ),
 262                      'type'        => 'string',
 263                      'readonly'    => true,
 264                  ),
 265                  'name'            => array(
 266                      'description' => __( 'Entity name.' ),
 267                      'type'        => 'string',
 268                      'readonly'    => true,
 269                  ),
 270                  'default_view'    => array(
 271                      'description' => __( 'Default view configuration.' ),
 272                      'type'        => 'object',
 273                      'readonly'    => true,
 274                      'properties'  => array_merge(
 275                          array(
 276                              'type'   => array(
 277                                  'type' => 'string',
 278                              ),
 279                              'layout' => $this->get_combined_layout_schema(),
 280                          ),
 281                          $view_base_properties
 282                      ),
 283                  ),
 284                  'default_layouts' => array(
 285                      'description' => __( 'Default layout configurations.' ),
 286                      'type'        => 'object',
 287                      'readonly'    => true,
 288                      'properties'  => array(
 289                          'table'       => array(
 290                              'type'       => 'object',
 291                              'properties' => array_merge(
 292                                  $view_base_properties,
 293                                  array(
 294                                      'layout' => $this->get_table_layout_schema(),
 295                                  )
 296                              ),
 297                          ),
 298                          'list'        => array(
 299                              'type'       => 'object',
 300                              'properties' => array_merge(
 301                                  $view_base_properties,
 302                                  array(
 303                                      'layout' => $this->get_list_layout_schema(),
 304                                  )
 305                              ),
 306                          ),
 307                          'grid'        => array(
 308                              'type'       => 'object',
 309                              'properties' => array_merge(
 310                                  $view_base_properties,
 311                                  array(
 312                                      'layout' => $this->get_grid_layout_schema(),
 313                                  )
 314                              ),
 315                          ),
 316                          'activity'    => array(
 317                              'type'       => 'object',
 318                              'properties' => array_merge(
 319                                  $view_base_properties,
 320                                  array(
 321                                      'layout' => $this->get_list_layout_schema(),
 322                                  )
 323                              ),
 324                          ),
 325                          'pickerGrid'  => array(
 326                              'type'       => 'object',
 327                              'properties' => array_merge(
 328                                  $view_base_properties,
 329                                  array(
 330                                      'layout' => $this->get_grid_layout_schema(),
 331                                  )
 332                              ),
 333                          ),
 334                          'pickerTable' => array(
 335                              'type'       => 'object',
 336                              'properties' => array_merge(
 337                                  $view_base_properties,
 338                                  array(
 339                                      'layout' => $this->get_table_layout_schema(),
 340                                  )
 341                              ),
 342                          ),
 343                      ),
 344                  ),
 345                  'view_list'       => array(
 346                      'description' => __( 'List of default views.' ),
 347                      'type'        => 'array',
 348                      'readonly'    => true,
 349                      'items'       => array(
 350                          'type'       => 'object',
 351                          'properties' => array(
 352                              'title' => array(
 353                                  'type' => 'string',
 354                              ),
 355                              'slug'  => array(
 356                                  'type' => 'string',
 357                              ),
 358                              'view'  => array(
 359                                  'type'       => 'object',
 360                                  'properties' => array_merge(
 361                                      array(
 362                                          'type'   => array(
 363                                              'type' => 'string',
 364                                          ),
 365                                          'layout' => $this->get_combined_layout_schema(),
 366                                      ),
 367                                      $view_base_properties
 368                                  ),
 369                              ),
 370                          ),
 371                      ),
 372                  ),
 373                  'form'            => array(
 374                      'description' => __( 'Default form configuration.' ),
 375                      'type'        => 'object',
 376                      'readonly'    => true,
 377                      'properties'  => $this->get_form_schema(),
 378                  ),
 379              ),
 380          );
 381  
 382          return $this->add_additional_fields_schema( $this->schema );
 383      }
 384  
 385      /**
 386       * Returns the schema properties shared by all view types (ViewBase), excluding 'type'.
 387       *
 388       * @since 7.1.0
 389       *
 390       * @return array Schema properties for the base view configuration.
 391       */
 392  	protected function get_view_base_schema() {
 393          return array(
 394              'search'                => array(
 395                  'type' => 'string',
 396              ),
 397              'filters'               => array(
 398                  'type'  => 'array',
 399                  'items' => array(
 400                      'type'       => 'object',
 401                      'properties' => array(
 402                          'field'    => array(
 403                              'type' => 'string',
 404                          ),
 405                          'operator' => array(
 406                              'type' => 'string',
 407                              'enum' => array(
 408                                  'is',
 409                                  'isNot',
 410                                  'isAny',
 411                                  'isNone',
 412                                  'isAll',
 413                                  'isNotAll',
 414                                  'lessThan',
 415                                  'greaterThan',
 416                                  'lessThanOrEqual',
 417                                  'greaterThanOrEqual',
 418                                  'before',
 419                                  'after',
 420                              ),
 421                          ),
 422                          'value'    => array(),
 423                          'isLocked' => array(
 424                              'type' => 'boolean',
 425                          ),
 426                      ),
 427                  ),
 428              ),
 429              'sort'                  => array(
 430                  'type'       => 'object',
 431                  'properties' => array(
 432                      'field'     => array(
 433                          'type' => 'string',
 434                      ),
 435                      'direction' => array(
 436                          'type' => 'string',
 437                          'enum' => array( 'asc', 'desc' ),
 438                      ),
 439                  ),
 440              ),
 441              'page'                  => array(
 442                  'type' => 'integer',
 443              ),
 444              'perPage'               => array(
 445                  'type' => 'integer',
 446              ),
 447              'fields'                => array(
 448                  'type'  => 'array',
 449                  'items' => array(
 450                      'type' => 'string',
 451                  ),
 452              ),
 453              'titleField'            => array(
 454                  'type' => 'string',
 455              ),
 456              'mediaField'            => array(
 457                  'type' => 'string',
 458              ),
 459              'descriptionField'      => array(
 460                  'type' => 'string',
 461              ),
 462              'showTitle'             => array(
 463                  'type' => 'boolean',
 464              ),
 465              'showMedia'             => array(
 466                  'type' => 'boolean',
 467              ),
 468              'showDescription'       => array(
 469                  'type' => 'boolean',
 470              ),
 471              'showLevels'            => array(
 472                  'type' => 'boolean',
 473              ),
 474              'groupBy'               => array(
 475                  'type'       => 'object',
 476                  'properties' => array(
 477                      'field'     => array(
 478                          'type' => 'string',
 479                      ),
 480                      'direction' => array(
 481                          'type' => 'string',
 482                          'enum' => array( 'asc', 'desc' ),
 483                      ),
 484                      'showLabel' => array(
 485                          'type'    => 'boolean',
 486                          'default' => true,
 487                      ),
 488                  ),
 489              ),
 490              'infiniteScrollEnabled' => array(
 491                  'type' => 'boolean',
 492              ),
 493          );
 494      }
 495  
 496      /**
 497       * Returns the schema for the ColumnStyle type.
 498       *
 499       * @since 7.1.0
 500       *
 501       * @return array Schema for a column style object.
 502       */
 503  	protected function get_column_style_schema() {
 504          return array(
 505              'type'       => 'object',
 506              'properties' => array(
 507                  'width'    => array(
 508                      'type' => array( 'string', 'number' ),
 509                  ),
 510                  'maxWidth' => array(
 511                      'type' => array( 'string', 'number' ),
 512                  ),
 513                  'minWidth' => array(
 514                      'type' => array( 'string', 'number' ),
 515                  ),
 516                  'align'    => array(
 517                      'type' => 'string',
 518                      'enum' => array( 'start', 'center', 'end' ),
 519                  ),
 520              ),
 521          );
 522      }
 523  
 524      /**
 525       * Returns the layout schema for table-type views (ViewTable, ViewPickerTable).
 526       *
 527       * @since 7.1.0
 528       *
 529       * @return array Schema for a table layout object.
 530       */
 531  	protected function get_table_layout_schema() {
 532          return array(
 533              'type'       => 'object',
 534              'properties' => array(
 535                  'styles'       => array(
 536                      'type'                 => 'object',
 537                      'additionalProperties' => $this->get_column_style_schema(),
 538                  ),
 539                  'density'      => array(
 540                      'type' => 'string',
 541                      'enum' => array( 'compact', 'balanced', 'comfortable' ),
 542                  ),
 543                  'enableMoving' => array(
 544                      'type' => 'boolean',
 545                  ),
 546              ),
 547          );
 548      }
 549  
 550      /**
 551       * Returns the layout schema for list-type views (ViewList, ViewActivity).
 552       *
 553       * @since 7.1.0
 554       *
 555       * @return array Schema for a list layout object.
 556       */
 557  	protected function get_list_layout_schema() {
 558          return array(
 559              'type'       => 'object',
 560              'properties' => array(
 561                  'density' => array(
 562                      'type' => 'string',
 563                      'enum' => array( 'compact', 'balanced', 'comfortable' ),
 564                  ),
 565              ),
 566          );
 567      }
 568  
 569      /**
 570       * Returns a combined layout schema that accepts properties from all view types.
 571       *
 572       * This is useful for contexts where the view type is not known ahead of time
 573       * (e.g. the `view` override in a view list item), so all possible layout
 574       * properties must be accepted.
 575       *
 576       * @since 7.1.0
 577       *
 578       * @return array Schema for a combined layout object.
 579       */
 580  	protected function get_combined_layout_schema() {
 581          return array(
 582              'type'       => 'object',
 583              'properties' => array_merge(
 584                  $this->get_table_layout_schema()['properties'],
 585                  $this->get_grid_layout_schema()['properties'],
 586                  $this->get_list_layout_schema()['properties']
 587              ),
 588          );
 589      }
 590  
 591      /**
 592       * Returns the layout schema for grid-type views (ViewGrid, ViewPickerGrid).
 593       *
 594       * @since 7.1.0
 595       *
 596       * @return array Schema for a grid layout object.
 597       */
 598  	protected function get_grid_layout_schema() {
 599          return array(
 600              'type'       => 'object',
 601              'properties' => array(
 602                  'badgeFields' => array(
 603                      'type'  => 'array',
 604                      'items' => array(
 605                          'type' => 'string',
 606                      ),
 607                  ),
 608                  'previewSize' => array(
 609                      'type' => 'number',
 610                  ),
 611                  'density'     => array(
 612                      'type' => 'string',
 613                      'enum' => array( 'compact', 'balanced', 'comfortable' ),
 614                  ),
 615              ),
 616          );
 617      }
 618  
 619      /**
 620       * Returns the schema for a form layout object as a discriminated union.
 621       *
 622       * Each variant is discriminated by a single-value enum on its `type` property,
 623       * matching the TypeScript Layout union in dataviews/src/types/dataform.ts.
 624       *
 625       * @since 7.1.0
 626       *
 627       * @return array Schema for a form layout object.
 628       */
 629  	protected function get_form_layout_schema() {
 630          return array(
 631              'oneOf' => array(
 632                  // RegularLayout.
 633                  array(
 634                      'type'       => 'object',
 635                      'properties' => array(
 636                          'type'          => array(
 637                              'type' => 'string',
 638                              'enum' => array( 'regular' ),
 639                          ),
 640                          'labelPosition' => array(
 641                              'type' => 'string',
 642                              'enum' => array( 'top', 'side', 'none' ),
 643                          ),
 644                      ),
 645                  ),
 646                  // PanelLayout.
 647                  array(
 648                      'type'       => 'object',
 649                      'properties' => array(
 650                          'type'           => array(
 651                              'type' => 'string',
 652                              'enum' => array( 'panel' ),
 653                          ),
 654                          'labelPosition'  => array(
 655                              'type' => 'string',
 656                              'enum' => array( 'top', 'side', 'none' ),
 657                          ),
 658                          'openAs'         => array(
 659                              'oneOf' => array(
 660                                  array(
 661                                      'type' => 'string',
 662                                      'enum' => array( 'dropdown', 'modal' ),
 663                                  ),
 664                                  array(
 665                                      'type'       => 'object',
 666                                      'properties' => array(
 667                                          'type'        => array(
 668                                              'type' => 'string',
 669                                              'enum' => array( 'dropdown', 'modal' ),
 670                                          ),
 671                                          'applyLabel'  => array(
 672                                              'type' => 'string',
 673                                          ),
 674                                          'cancelLabel' => array(
 675                                              'type' => 'string',
 676                                          ),
 677                                      ),
 678                                  ),
 679                              ),
 680                          ),
 681                          'summary'        => array(
 682                              'oneOf' => array(
 683                                  array( 'type' => 'string' ),
 684                                  array(
 685                                      'type'  => 'array',
 686                                      'items' => array(
 687                                          'type' => 'string',
 688                                      ),
 689                                  ),
 690                              ),
 691                          ),
 692                          'editVisibility' => array(
 693                              'type' => 'string',
 694                              'enum' => array( 'always', 'on-hover' ),
 695                          ),
 696                      ),
 697                  ),
 698                  // CardLayout.
 699                  array(
 700                      'type'       => 'object',
 701                      'properties' => array(
 702                          'type'          => array(
 703                              'type' => 'string',
 704                              'enum' => array( 'card' ),
 705                          ),
 706                          'withHeader'    => array(
 707                              'type' => 'boolean',
 708                          ),
 709                          'isOpened'      => array(
 710                              'type' => 'boolean',
 711                          ),
 712                          'isCollapsible' => array(
 713                              'type' => 'boolean',
 714                          ),
 715                          'summary'       => array(
 716                              'oneOf' => array(
 717                                  array( 'type' => 'string' ),
 718                                  array(
 719                                      'type'  => 'array',
 720                                      'items' => array(
 721                                          'oneOf' => array(
 722                                              array( 'type' => 'string' ),
 723                                              array(
 724                                                  'type' => 'object',
 725                                                  'properties' => array(
 726                                                      'id' => array(
 727                                                          'type' => 'string',
 728                                                      ),
 729                                                      'visibility' => array(
 730                                                          'type' => 'string',
 731                                                          'enum' => array( 'always', 'when-collapsed' ),
 732                                                      ),
 733                                                  ),
 734                                              ),
 735                                          ),
 736                                      ),
 737                                  ),
 738                              ),
 739                          ),
 740                      ),
 741                  ),
 742                  // RowLayout.
 743                  array(
 744                      'type'       => 'object',
 745                      'properties' => array(
 746                          'type'      => array(
 747                              'type' => 'string',
 748                              'enum' => array( 'row' ),
 749                          ),
 750                          'alignment' => array(
 751                              'type' => 'string',
 752                              'enum' => array( 'start', 'center', 'end' ),
 753                          ),
 754                          'styles'    => array(
 755                              'type'                 => 'object',
 756                              'additionalProperties' => array(
 757                                  'type'       => 'object',
 758                                  'properties' => array(
 759                                      'flex' => array(
 760                                          'type' => array( 'string', 'number' ),
 761                                      ),
 762                                  ),
 763                              ),
 764                          ),
 765                      ),
 766                  ),
 767                  // DetailsLayout.
 768                  array(
 769                      'type'       => 'object',
 770                      'properties' => array(
 771                          'type'    => array(
 772                              'type' => 'string',
 773                              'enum' => array( 'details' ),
 774                          ),
 775                          'summary' => array(
 776                              'type' => 'string',
 777                          ),
 778                      ),
 779                  ),
 780              ),
 781          );
 782      }
 783  
 784      /**
 785       * Returns the schema for a form field item (string or object).
 786       *
 787       * @since 7.1.0
 788       *
 789       * @return array Schema for a form field.
 790       */
 791  	protected function get_form_field_schema() {
 792          return array(
 793              'oneOf' => array(
 794                  array( 'type' => 'string' ),
 795                  array(
 796                      'type'       => 'object',
 797                      'properties' => array(
 798                          'id'          => array(
 799                              'type' => 'string',
 800                          ),
 801                          'label'       => array(
 802                              'type' => 'string',
 803                          ),
 804                          'description' => array(
 805                              'type' => 'string',
 806                          ),
 807                          'layout'      => $this->get_form_layout_schema(),
 808                          'children'    => array(
 809                              'type'  => 'array',
 810                              'items' => array(
 811                                  'oneOf' => array(
 812                                      array( 'type' => 'string' ),
 813                                      // This object can have the shape of a form field itself,
 814                                      // allowing for recursive nesting of form fields.
 815                                      // There's no easy way to codify this recursion via the JSON Schema draft-04
 816                                      // supported by the REST API.
 817                                      array( 'type' => 'object' ),
 818                                  ),
 819                              ),
 820                          ),
 821                      ),
 822                  ),
 823              ),
 824          );
 825      }
 826  
 827      /**
 828       * Returns the schema for the form configuration object.
 829       *
 830       * @since 7.1.0
 831       *
 832       * @return array Schema properties for the form configuration.
 833       */
 834  	protected function get_form_schema() {
 835          return array(
 836              'layout' => $this->get_form_layout_schema(),
 837              'fields' => array(
 838                  'type'  => 'array',
 839                  'items' => $this->get_form_field_schema(),
 840              ),
 841          );
 842      }
 843  }


Generated : Wed Jun 24 08:20:11 2026 Cross-referenced by PHPXref