[ Index ] |
PHP Cross Reference of WordPress |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * REST API: WP_REST_Templates_Controller class 4 * 5 * @package WordPress 6 * @subpackage REST_API 7 * @since 5.8.0 8 */ 9 10 /** 11 * Base Templates REST API Controller. 12 * 13 * @since 5.8.0 14 * 15 * @see WP_REST_Controller 16 */ 17 class WP_REST_Templates_Controller extends WP_REST_Controller { 18 19 /** 20 * Post type. 21 * 22 * @since 5.8.0 23 * @var string 24 */ 25 protected $post_type; 26 27 /** 28 * Constructor. 29 * 30 * @since 5.8.0 31 * 32 * @param string $post_type Post type. 33 */ 34 public function __construct( $post_type ) { 35 $this->post_type = $post_type; 36 $obj = get_post_type_object( $post_type ); 37 $this->rest_base = ! empty( $obj->rest_base ) ? $obj->rest_base : $obj->name; 38 $this->namespace = ! empty( $obj->rest_namespace ) ? $obj->rest_namespace : 'wp/v2'; 39 } 40 41 /** 42 * Registers the controllers routes. 43 * 44 * @since 5.8.0 45 */ 46 public function register_routes() { 47 // Lists all templates. 48 register_rest_route( 49 $this->namespace, 50 '/' . $this->rest_base, 51 array( 52 array( 53 'methods' => WP_REST_Server::READABLE, 54 'callback' => array( $this, 'get_items' ), 55 'permission_callback' => array( $this, 'get_items_permissions_check' ), 56 'args' => $this->get_collection_params(), 57 ), 58 array( 59 'methods' => WP_REST_Server::CREATABLE, 60 'callback' => array( $this, 'create_item' ), 61 'permission_callback' => array( $this, 'create_item_permissions_check' ), 62 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ), 63 ), 64 'schema' => array( $this, 'get_public_item_schema' ), 65 ) 66 ); 67 68 // Lists/updates a single template based on the given id. 69 register_rest_route( 70 $this->namespace, 71 // The route. 72 sprintf( 73 '/%s/(?P<id>%s%s)', 74 $this->rest_base, 75 // Matches theme's directory: `/themes/<subdirectory>/<theme>/` or `/themes/<theme>/`. 76 // Excludes invalid directory name characters: `/:<>*?"|`. 77 '([^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?)', 78 // Matches the template name. 79 '[\/\w-]+' 80 ), 81 array( 82 'args' => array( 83 'id' => array( 84 'description' => __( 'The id of a template' ), 85 'type' => 'string', 86 'sanitize_callback' => array( $this, '_sanitize_template_id' ), 87 ), 88 ), 89 array( 90 'methods' => WP_REST_Server::READABLE, 91 'callback' => array( $this, 'get_item' ), 92 'permission_callback' => array( $this, 'get_item_permissions_check' ), 93 'args' => array( 94 'context' => $this->get_context_param( array( 'default' => 'view' ) ), 95 ), 96 ), 97 array( 98 'methods' => WP_REST_Server::EDITABLE, 99 'callback' => array( $this, 'update_item' ), 100 'permission_callback' => array( $this, 'update_item_permissions_check' ), 101 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ), 102 ), 103 array( 104 'methods' => WP_REST_Server::DELETABLE, 105 'callback' => array( $this, 'delete_item' ), 106 'permission_callback' => array( $this, 'delete_item_permissions_check' ), 107 'args' => array( 108 'force' => array( 109 'type' => 'boolean', 110 'default' => false, 111 'description' => __( 'Whether to bypass Trash and force deletion.' ), 112 ), 113 ), 114 ), 115 'schema' => array( $this, 'get_public_item_schema' ), 116 ) 117 ); 118 } 119 120 /** 121 * Checks if the user has permissions to make the request. 122 * 123 * @since 5.8.0 124 * 125 * @param WP_REST_Request $request Full details about the request. 126 * @return true|WP_Error True if the request has read access, WP_Error object otherwise. 127 */ 128 protected function permissions_check( $request ) { 129 // Verify if the current user has edit_theme_options capability. 130 // This capability is required to edit/view/delete templates. 131 if ( ! current_user_can( 'edit_theme_options' ) ) { 132 return new WP_Error( 133 'rest_cannot_manage_templates', 134 __( 'Sorry, you are not allowed to access the templates on this site.' ), 135 array( 136 'status' => rest_authorization_required_code(), 137 ) 138 ); 139 } 140 141 return true; 142 } 143 144 /** 145 * Requesting this endpoint for a template like 'twentytwentytwo//home' 146 * requires using a path like /wp/v2/templates/twentytwentytwo//home. There 147 * are special cases when WordPress routing corrects the name to contain 148 * only a single slash like 'twentytwentytwo/home'. 149 * 150 * This method doubles the last slash if it's not already doubled. It relies 151 * on the template ID format {theme_name}//{template_slug} and the fact that 152 * slugs cannot contain slashes. 153 * 154 * @since 5.9.0 155 * @see https://core.trac.wordpress.org/ticket/54507 156 * 157 * @param string $id Template ID. 158 * @return string Sanitized template ID. 159 */ 160 public function _sanitize_template_id( $id ) { 161 $id = urldecode( $id ); 162 163 $last_slash_pos = strrpos( $id, '/' ); 164 if ( false === $last_slash_pos ) { 165 return $id; 166 } 167 168 $is_double_slashed = substr( $id, $last_slash_pos - 1, 1 ) === '/'; 169 if ( $is_double_slashed ) { 170 return $id; 171 } 172 return ( 173 substr( $id, 0, $last_slash_pos ) 174 . '/' 175 . substr( $id, $last_slash_pos ) 176 ); 177 } 178 179 /** 180 * Checks if a given request has access to read templates. 181 * 182 * @since 5.8.0 183 * 184 * @param WP_REST_Request $request Full details about the request. 185 * @return true|WP_Error True if the request has read access, WP_Error object otherwise. 186 */ 187 public function get_items_permissions_check( $request ) { 188 return $this->permissions_check( $request ); 189 } 190 191 /** 192 * Returns a list of templates. 193 * 194 * @since 5.8.0 195 * 196 * @param WP_REST_Request $request The request instance. 197 * @return WP_REST_Response 198 */ 199 public function get_items( $request ) { 200 $query = array(); 201 if ( isset( $request['wp_id'] ) ) { 202 $query['wp_id'] = $request['wp_id']; 203 } 204 if ( isset( $request['area'] ) ) { 205 $query['area'] = $request['area']; 206 } 207 if ( isset( $request['post_type'] ) ) { 208 $query['post_type'] = $request['post_type']; 209 } 210 211 $templates = array(); 212 foreach ( get_block_templates( $query, $this->post_type ) as $template ) { 213 $data = $this->prepare_item_for_response( $template, $request ); 214 $templates[] = $this->prepare_response_for_collection( $data ); 215 } 216 217 return rest_ensure_response( $templates ); 218 } 219 220 /** 221 * Checks if a given request has access to read a single template. 222 * 223 * @since 5.8.0 224 * 225 * @param WP_REST_Request $request Full details about the request. 226 * @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise. 227 */ 228 public function get_item_permissions_check( $request ) { 229 return $this->permissions_check( $request ); 230 } 231 232 /** 233 * Returns the given template 234 * 235 * @since 5.8.0 236 * 237 * @param WP_REST_Request $request The request instance. 238 * @return WP_REST_Response|WP_Error 239 */ 240 public function get_item( $request ) { 241 if ( isset( $request['source'] ) && 'theme' === $request['source'] ) { 242 $template = get_block_file_template( $request['id'], $this->post_type ); 243 } else { 244 $template = get_block_template( $request['id'], $this->post_type ); 245 } 246 247 if ( ! $template ) { 248 return new WP_Error( 'rest_template_not_found', __( 'No templates exist with that id.' ), array( 'status' => 404 ) ); 249 } 250 251 return $this->prepare_item_for_response( $template, $request ); 252 } 253 254 /** 255 * Checks if a given request has access to write a single template. 256 * 257 * @since 5.8.0 258 * 259 * @param WP_REST_Request $request Full details about the request. 260 * @return true|WP_Error True if the request has write access for the item, WP_Error object otherwise. 261 */ 262 public function update_item_permissions_check( $request ) { 263 return $this->permissions_check( $request ); 264 } 265 266 /** 267 * Updates a single template. 268 * 269 * @since 5.8.0 270 * 271 * @param WP_REST_Request $request Full details about the request. 272 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. 273 */ 274 public function update_item( $request ) { 275 $template = get_block_template( $request['id'], $this->post_type ); 276 if ( ! $template ) { 277 return new WP_Error( 'rest_template_not_found', __( 'No templates exist with that id.' ), array( 'status' => 404 ) ); 278 } 279 280 $post_before = get_post( $template->wp_id ); 281 282 if ( isset( $request['source'] ) && 'theme' === $request['source'] ) { 283 wp_delete_post( $template->wp_id, true ); 284 $request->set_param( 'context', 'edit' ); 285 286 $template = get_block_template( $request['id'], $this->post_type ); 287 $response = $this->prepare_item_for_response( $template, $request ); 288 289 return rest_ensure_response( $response ); 290 } 291 292 $changes = $this->prepare_item_for_database( $request ); 293 294 if ( is_wp_error( $changes ) ) { 295 return $changes; 296 } 297 298 if ( 'custom' === $template->source ) { 299 $update = true; 300 $result = wp_update_post( wp_slash( (array) $changes ), false ); 301 } else { 302 $update = false; 303 $post_before = null; 304 $result = wp_insert_post( wp_slash( (array) $changes ), false ); 305 } 306 307 if ( is_wp_error( $result ) ) { 308 if ( 'db_update_error' === $result->get_error_code() ) { 309 $result->add_data( array( 'status' => 500 ) ); 310 } else { 311 $result->add_data( array( 'status' => 400 ) ); 312 } 313 return $result; 314 } 315 316 $template = get_block_template( $request['id'], $this->post_type ); 317 $fields_update = $this->update_additional_fields_for_object( $template, $request ); 318 if ( is_wp_error( $fields_update ) ) { 319 return $fields_update; 320 } 321 322 $request->set_param( 'context', 'edit' ); 323 324 $post = get_post( $template->wp_id ); 325 /** This action is documented in wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php */ 326 do_action( "rest_after_insert_{$this->post_type}", $post, $request, false ); 327 328 wp_after_insert_post( $post, $update, $post_before ); 329 330 $response = $this->prepare_item_for_response( $template, $request ); 331 332 return rest_ensure_response( $response ); 333 } 334 335 /** 336 * Checks if a given request has access to create a template. 337 * 338 * @since 5.8.0 339 * 340 * @param WP_REST_Request $request Full details about the request. 341 * @return true|WP_Error True if the request has access to create items, WP_Error object otherwise. 342 */ 343 public function create_item_permissions_check( $request ) { 344 return $this->permissions_check( $request ); 345 } 346 347 /** 348 * Creates a single template. 349 * 350 * @since 5.8.0 351 * 352 * @param WP_REST_Request $request Full details about the request. 353 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. 354 */ 355 public function create_item( $request ) { 356 $prepared_post = $this->prepare_item_for_database( $request ); 357 358 if ( is_wp_error( $prepared_post ) ) { 359 return $prepared_post; 360 } 361 362 $prepared_post->post_name = $request['slug']; 363 $post_id = wp_insert_post( wp_slash( (array) $prepared_post ), true ); 364 if ( is_wp_error( $post_id ) ) { 365 if ( 'db_insert_error' === $post_id->get_error_code() ) { 366 $post_id->add_data( array( 'status' => 500 ) ); 367 } else { 368 $post_id->add_data( array( 'status' => 400 ) ); 369 } 370 371 return $post_id; 372 } 373 $posts = get_block_templates( array( 'wp_id' => $post_id ), $this->post_type ); 374 if ( ! count( $posts ) ) { 375 return new WP_Error( 'rest_template_insert_error', __( 'No templates exist with that id.' ), array( 'status' => 400 ) ); 376 } 377 $id = $posts[0]->id; 378 $post = get_post( $post_id ); 379 $template = get_block_template( $id, $this->post_type ); 380 $fields_update = $this->update_additional_fields_for_object( $template, $request ); 381 if ( is_wp_error( $fields_update ) ) { 382 return $fields_update; 383 } 384 385 /** This action is documented in wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php */ 386 do_action( "rest_after_insert_{$this->post_type}", $post, $request, true ); 387 388 wp_after_insert_post( $post, false, null ); 389 390 $response = $this->prepare_item_for_response( $template, $request ); 391 $response = rest_ensure_response( $response ); 392 393 $response->set_status( 201 ); 394 $response->header( 'Location', rest_url( sprintf( '%s/%s/%s', $this->namespace, $this->rest_base, $template->id ) ) ); 395 396 return $response; 397 } 398 399 /** 400 * Checks if a given request has access to delete a single template. 401 * 402 * @since 5.8.0 403 * 404 * @param WP_REST_Request $request Full details about the request. 405 * @return true|WP_Error True if the request has delete access for the item, WP_Error object otherwise. 406 */ 407 public function delete_item_permissions_check( $request ) { 408 return $this->permissions_check( $request ); 409 } 410 411 /** 412 * Deletes a single template. 413 * 414 * @since 5.8.0 415 * 416 * @param WP_REST_Request $request Full details about the request. 417 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. 418 */ 419 public function delete_item( $request ) { 420 $template = get_block_template( $request['id'], $this->post_type ); 421 if ( ! $template ) { 422 return new WP_Error( 'rest_template_not_found', __( 'No templates exist with that id.' ), array( 'status' => 404 ) ); 423 } 424 if ( 'custom' !== $template->source ) { 425 return new WP_Error( 'rest_invalid_template', __( 'Templates based on theme files can\'t be removed.' ), array( 'status' => 400 ) ); 426 } 427 428 $id = $template->wp_id; 429 $force = (bool) $request['force']; 430 431 $request->set_param( 'context', 'edit' ); 432 433 // If we're forcing, then delete permanently. 434 if ( $force ) { 435 $previous = $this->prepare_item_for_response( $template, $request ); 436 $result = wp_delete_post( $id, true ); 437 $response = new WP_REST_Response(); 438 $response->set_data( 439 array( 440 'deleted' => true, 441 'previous' => $previous->get_data(), 442 ) 443 ); 444 } else { 445 // Otherwise, only trash if we haven't already. 446 if ( 'trash' === $template->status ) { 447 return new WP_Error( 448 'rest_template_already_trashed', 449 __( 'The template has already been deleted.' ), 450 array( 'status' => 410 ) 451 ); 452 } 453 454 // (Note that internally this falls through to `wp_delete_post()` 455 // if the Trash is disabled.) 456 $result = wp_trash_post( $id ); 457 $template->status = 'trash'; 458 $response = $this->prepare_item_for_response( $template, $request ); 459 } 460 461 if ( ! $result ) { 462 return new WP_Error( 463 'rest_cannot_delete', 464 __( 'The template cannot be deleted.' ), 465 array( 'status' => 500 ) 466 ); 467 } 468 469 return $response; 470 } 471 472 /** 473 * Prepares a single template for create or update. 474 * 475 * @since 5.8.0 476 * 477 * @param WP_REST_Request $request Request object. 478 * @return stdClass Changes to pass to wp_update_post. 479 */ 480 protected function prepare_item_for_database( $request ) { 481 $template = $request['id'] ? get_block_template( $request['id'], $this->post_type ) : null; 482 $changes = new stdClass(); 483 if ( null === $template ) { 484 $changes->post_type = $this->post_type; 485 $changes->post_status = 'publish'; 486 $changes->tax_input = array( 487 'wp_theme' => isset( $request['theme'] ) ? $request['theme'] : wp_get_theme()->get_stylesheet(), 488 ); 489 } elseif ( 'custom' !== $template->source ) { 490 $changes->post_name = $template->slug; 491 $changes->post_type = $this->post_type; 492 $changes->post_status = 'publish'; 493 $changes->tax_input = array( 494 'wp_theme' => $template->theme, 495 ); 496 $changes->meta_input = array( 497 'origin' => $template->source, 498 ); 499 } else { 500 $changes->post_name = $template->slug; 501 $changes->ID = $template->wp_id; 502 $changes->post_status = 'publish'; 503 } 504 if ( isset( $request['content'] ) ) { 505 if ( is_string( $request['content'] ) ) { 506 $changes->post_content = $request['content']; 507 } elseif ( isset( $request['content']['raw'] ) ) { 508 $changes->post_content = $request['content']['raw']; 509 } 510 } elseif ( null !== $template && 'custom' !== $template->source ) { 511 $changes->post_content = $template->content; 512 } 513 if ( isset( $request['title'] ) ) { 514 if ( is_string( $request['title'] ) ) { 515 $changes->post_title = $request['title']; 516 } elseif ( ! empty( $request['title']['raw'] ) ) { 517 $changes->post_title = $request['title']['raw']; 518 } 519 } elseif ( null !== $template && 'custom' !== $template->source ) { 520 $changes->post_title = $template->title; 521 } 522 if ( isset( $request['description'] ) ) { 523 $changes->post_excerpt = $request['description']; 524 } elseif ( null !== $template && 'custom' !== $template->source ) { 525 $changes->post_excerpt = $template->description; 526 } 527 528 if ( 'wp_template_part' === $this->post_type ) { 529 if ( isset( $request['area'] ) ) { 530 $changes->tax_input['wp_template_part_area'] = _filter_block_template_part_area( $request['area'] ); 531 } elseif ( null !== $template && 'custom' !== $template->source && $template->area ) { 532 $changes->tax_input['wp_template_part_area'] = _filter_block_template_part_area( $template->area ); 533 } elseif ( ! $template->area ) { 534 $changes->tax_input['wp_template_part_area'] = WP_TEMPLATE_PART_AREA_UNCATEGORIZED; 535 } 536 } 537 538 if ( ! empty( $request['author'] ) ) { 539 $post_author = (int) $request['author']; 540 541 if ( get_current_user_id() !== $post_author ) { 542 $user_obj = get_userdata( $post_author ); 543 544 if ( ! $user_obj ) { 545 return new WP_Error( 546 'rest_invalid_author', 547 __( 'Invalid author ID.' ), 548 array( 'status' => 400 ) 549 ); 550 } 551 } 552 553 $changes->post_author = $post_author; 554 } 555 556 return $changes; 557 } 558 559 /** 560 * Prepare a single template output for response 561 * 562 * @since 5.8.0 563 * @since 5.9.0 Renamed `$template` to `$item` to match parent class for PHP 8 named parameter support. 564 * 565 * @param WP_Block_Template $item Template instance. 566 * @param WP_REST_Request $request Request object. 567 * @return WP_REST_Response Response object. 568 */ 569 public function prepare_item_for_response( $item, $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable 570 // Restores the more descriptive, specific name for use within this method. 571 $template = $item; 572 573 $fields = $this->get_fields_for_response( $request ); 574 575 // Base fields for every template. 576 $data = array(); 577 578 if ( rest_is_field_included( 'id', $fields ) ) { 579 $data['id'] = $template->id; 580 } 581 582 if ( rest_is_field_included( 'theme', $fields ) ) { 583 $data['theme'] = $template->theme; 584 } 585 586 if ( rest_is_field_included( 'content', $fields ) ) { 587 $data['content'] = array(); 588 } 589 if ( rest_is_field_included( 'content.raw', $fields ) ) { 590 $data['content']['raw'] = $template->content; 591 } 592 593 if ( rest_is_field_included( 'content.block_version', $fields ) ) { 594 $data['content']['block_version'] = block_version( $template->content ); 595 } 596 597 if ( rest_is_field_included( 'slug', $fields ) ) { 598 $data['slug'] = $template->slug; 599 } 600 601 if ( rest_is_field_included( 'source', $fields ) ) { 602 $data['source'] = $template->source; 603 } 604 605 if ( rest_is_field_included( 'origin', $fields ) ) { 606 $data['origin'] = $template->origin; 607 } 608 609 if ( rest_is_field_included( 'type', $fields ) ) { 610 $data['type'] = $template->type; 611 } 612 613 if ( rest_is_field_included( 'description', $fields ) ) { 614 $data['description'] = $template->description; 615 } 616 617 if ( rest_is_field_included( 'title', $fields ) ) { 618 $data['title'] = array(); 619 } 620 621 if ( rest_is_field_included( 'title.raw', $fields ) ) { 622 $data['title']['raw'] = $template->title; 623 } 624 625 if ( rest_is_field_included( 'title.rendered', $fields ) ) { 626 if ( $template->wp_id ) { 627 /** This filter is documented in wp-includes/post-template.php */ 628 $data['title']['rendered'] = apply_filters( 'the_title', $template->title, $template->wp_id ); 629 } else { 630 $data['title']['rendered'] = $template->title; 631 } 632 } 633 634 if ( rest_is_field_included( 'status', $fields ) ) { 635 $data['status'] = $template->status; 636 } 637 638 if ( rest_is_field_included( 'wp_id', $fields ) ) { 639 $data['wp_id'] = (int) $template->wp_id; 640 } 641 642 if ( rest_is_field_included( 'has_theme_file', $fields ) ) { 643 $data['has_theme_file'] = (bool) $template->has_theme_file; 644 } 645 646 if ( rest_is_field_included( 'is_custom', $fields ) && 'wp_template' === $template->type ) { 647 $data['is_custom'] = $template->is_custom; 648 } 649 650 if ( rest_is_field_included( 'author', $fields ) ) { 651 $data['author'] = (int) $template->author; 652 } 653 654 if ( rest_is_field_included( 'area', $fields ) && 'wp_template_part' === $template->type ) { 655 $data['area'] = $template->area; 656 } 657 658 $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; 659 $data = $this->add_additional_fields_to_object( $data, $request ); 660 $data = $this->filter_response_by_context( $data, $context ); 661 662 // Wrap the data in a response object. 663 $response = rest_ensure_response( $data ); 664 665 $links = $this->prepare_links( $template->id ); 666 $response->add_links( $links ); 667 if ( ! empty( $links['self']['href'] ) ) { 668 $actions = $this->get_available_actions(); 669 $self = $links['self']['href']; 670 foreach ( $actions as $rel ) { 671 $response->add_link( $rel, $self ); 672 } 673 } 674 675 return $response; 676 } 677 678 679 /** 680 * Prepares links for the request. 681 * 682 * @since 5.8.0 683 * 684 * @param integer $id ID. 685 * @return array Links for the given post. 686 */ 687 protected function prepare_links( $id ) { 688 $base = sprintf( '%s/%s', $this->namespace, $this->rest_base ); 689 690 $links = array( 691 'self' => array( 692 'href' => rest_url( trailingslashit( $base ) . $id ), 693 ), 694 'collection' => array( 695 'href' => rest_url( $base ), 696 ), 697 'about' => array( 698 'href' => rest_url( 'wp/v2/types/' . $this->post_type ), 699 ), 700 ); 701 702 return $links; 703 } 704 705 /** 706 * Get the link relations available for the post and current user. 707 * 708 * @since 5.8.0 709 * 710 * @return string[] List of link relations. 711 */ 712 protected function get_available_actions() { 713 $rels = array(); 714 715 $post_type = get_post_type_object( $this->post_type ); 716 717 if ( current_user_can( $post_type->cap->publish_posts ) ) { 718 $rels[] = 'https://api.w.org/action-publish'; 719 } 720 721 if ( current_user_can( 'unfiltered_html' ) ) { 722 $rels[] = 'https://api.w.org/action-unfiltered-html'; 723 } 724 725 return $rels; 726 } 727 728 /** 729 * Retrieves the query params for the posts collection. 730 * 731 * @since 5.8.0 732 * @since 5.9.0 Added `'area'` and `'post_type'`. 733 * 734 * @return array Collection parameters. 735 */ 736 public function get_collection_params() { 737 return array( 738 'context' => $this->get_context_param( array( 'default' => 'view' ) ), 739 'wp_id' => array( 740 'description' => __( 'Limit to the specified post id.' ), 741 'type' => 'integer', 742 ), 743 'area' => array( 744 'description' => __( 'Limit to the specified template part area.' ), 745 'type' => 'string', 746 ), 747 'post_type' => array( 748 'description' => __( 'Post type to get the templates for.' ), 749 'type' => 'string', 750 ), 751 ); 752 } 753 754 /** 755 * Retrieves the block type' schema, conforming to JSON Schema. 756 * 757 * @since 5.8.0 758 * @since 5.9.0 Added `'area'`. 759 * 760 * @return array Item schema data. 761 */ 762 public function get_item_schema() { 763 if ( $this->schema ) { 764 return $this->add_additional_fields_schema( $this->schema ); 765 } 766 767 $schema = array( 768 '$schema' => 'http://json-schema.org/draft-04/schema#', 769 'title' => $this->post_type, 770 'type' => 'object', 771 'properties' => array( 772 'id' => array( 773 'description' => __( 'ID of template.' ), 774 'type' => 'string', 775 'context' => array( 'embed', 'view', 'edit' ), 776 'readonly' => true, 777 ), 778 'slug' => array( 779 'description' => __( 'Unique slug identifying the template.' ), 780 'type' => 'string', 781 'context' => array( 'embed', 'view', 'edit' ), 782 'required' => true, 783 'minLength' => 1, 784 'pattern' => '[a-zA-Z0-9_\-]+', 785 ), 786 'theme' => array( 787 'description' => __( 'Theme identifier for the template.' ), 788 'type' => 'string', 789 'context' => array( 'embed', 'view', 'edit' ), 790 ), 791 'type' => array( 792 'description' => __( 'Type of template.' ), 793 'type' => 'string', 794 'context' => array( 'embed', 'view', 'edit' ), 795 ), 796 'source' => array( 797 'description' => __( 'Source of template' ), 798 'type' => 'string', 799 'context' => array( 'embed', 'view', 'edit' ), 800 'readonly' => true, 801 ), 802 'origin' => array( 803 'description' => __( 'Source of a customized template' ), 804 'type' => 'string', 805 'context' => array( 'embed', 'view', 'edit' ), 806 'readonly' => true, 807 ), 808 'content' => array( 809 'description' => __( 'Content of template.' ), 810 'type' => array( 'object', 'string' ), 811 'default' => '', 812 'context' => array( 'embed', 'view', 'edit' ), 813 'properties' => array( 814 'raw' => array( 815 'description' => __( 'Content for the template, as it exists in the database.' ), 816 'type' => 'string', 817 'context' => array( 'view', 'edit' ), 818 ), 819 'block_version' => array( 820 'description' => __( 'Version of the content block format used by the template.' ), 821 'type' => 'integer', 822 'context' => array( 'edit' ), 823 'readonly' => true, 824 ), 825 ), 826 ), 827 'title' => array( 828 'description' => __( 'Title of template.' ), 829 'type' => array( 'object', 'string' ), 830 'default' => '', 831 'context' => array( 'embed', 'view', 'edit' ), 832 'properties' => array( 833 'raw' => array( 834 'description' => __( 'Title for the template, as it exists in the database.' ), 835 'type' => 'string', 836 'context' => array( 'view', 'edit', 'embed' ), 837 ), 838 'rendered' => array( 839 'description' => __( 'HTML title for the template, transformed for display.' ), 840 'type' => 'string', 841 'context' => array( 'view', 'edit', 'embed' ), 842 'readonly' => true, 843 ), 844 ), 845 ), 846 'description' => array( 847 'description' => __( 'Description of template.' ), 848 'type' => 'string', 849 'default' => '', 850 'context' => array( 'embed', 'view', 'edit' ), 851 ), 852 'status' => array( 853 'description' => __( 'Status of template.' ), 854 'type' => 'string', 855 'enum' => array_keys( get_post_stati( array( 'internal' => false ) ) ), 856 'default' => 'publish', 857 'context' => array( 'embed', 'view', 'edit' ), 858 ), 859 'wp_id' => array( 860 'description' => __( 'Post ID.' ), 861 'type' => 'integer', 862 'context' => array( 'embed', 'view', 'edit' ), 863 'readonly' => true, 864 ), 865 'has_theme_file' => array( 866 'description' => __( 'Theme file exists.' ), 867 'type' => 'bool', 868 'context' => array( 'embed', 'view', 'edit' ), 869 'readonly' => true, 870 ), 871 'author' => array( 872 'description' => __( 'The ID for the author of the template.' ), 873 'type' => 'integer', 874 'context' => array( 'view', 'edit', 'embed' ), 875 ), 876 ), 877 ); 878 879 if ( 'wp_template' === $this->post_type ) { 880 $schema['properties']['is_custom'] = array( 881 'description' => __( 'Whether a template is a custom template.' ), 882 'type' => 'bool', 883 'context' => array( 'embed', 'view', 'edit' ), 884 'readonly' => true, 885 ); 886 } 887 888 if ( 'wp_template_part' === $this->post_type ) { 889 $schema['properties']['area'] = array( 890 'description' => __( 'Where the template part is intended for use (header, footer, etc.)' ), 891 'type' => 'string', 892 'context' => array( 'embed', 'view', 'edit' ), 893 ); 894 } 895 896 $this->schema = $schema; 897 898 return $this->add_additional_fields_schema( $this->schema ); 899 } 900 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Nov 21 01:00:03 2024 | Cross-referenced by PHPXref 0.7.1 |