Changeset 39026
- Timestamp:
- 10/30/2016 05:36:15 PM (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php
r38968 r39026 1 1 <?php 2 2 /** 3 * REST API: WP_REST_Posts_Controller class 4 * 5 * @package WordPress 6 * @subpackage REST_API 7 * @since 4.7.0 8 */ 9 10 /** 11 * Core class to access posts via the REST API. 12 * 13 * @since 4.7.0 14 * 15 * @see WP_REST_Controller 16 */ 3 17 class WP_REST_Posts_Controller extends WP_REST_Controller { 4 18 … … 6 20 * Post type. 7 21 * 22 * @since 4.7.0 8 23 * @access protected 9 24 * @var string … … 14 29 * Instance of a post meta fields object. 15 30 * 31 * @since 4.7.0 16 32 * @access protected 17 33 * @var WP_REST_Post_Meta_Fields … … 21 37 /** 22 38 * Constructor. 39 * 40 * @since 4.7.0 41 * @access public 23 42 * 24 43 * @param string $post_type Post type. … … 34 53 35 54 /** 36 * Register the routes for the objects of the controller. 55 * Registers the routes for the objects of the controller. 56 * 57 * @since 4.7.0 58 * @access public 59 * 60 * @see register_rest_route() 37 61 */ 38 62 public function register_routes() { … … 40 64 register_rest_route( $this->namespace, '/' . $this->rest_base, array( 41 65 array( 42 'methods' => WP_REST_Server::READABLE,43 'callback' => array( $this, 'get_items' ),66 'methods' => WP_REST_Server::READABLE, 67 'callback' => array( $this, 'get_items' ), 44 68 'permission_callback' => array( $this, 'get_items_permissions_check' ), 45 'args' => $this->get_collection_params(),69 'args' => $this->get_collection_params(), 46 70 ), 47 71 array( 48 'methods' => WP_REST_Server::CREATABLE,49 'callback' => array( $this, 'create_item' ),72 'methods' => WP_REST_Server::CREATABLE, 73 'callback' => array( $this, 'create_item' ), 50 74 'permission_callback' => array( $this, 'create_item_permissions_check' ), 51 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ),75 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ), 52 76 ), 53 77 'schema' => array( $this, 'get_public_item_schema' ), 54 78 ) ); 79 55 80 register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array( 56 81 array( 57 'methods' => WP_REST_Server::READABLE,58 'callback' => array( $this, 'get_item' ),82 'methods' => WP_REST_Server::READABLE, 83 'callback' => array( $this, 'get_item' ), 59 84 'permission_callback' => array( $this, 'get_item_permissions_check' ), 60 'args' => array(85 'args' => array( 61 86 'context' => $this->get_context_param( array( 'default' => 'view' ) ), 62 87 'password' => array( … … 66 91 ), 67 92 array( 68 'methods' => WP_REST_Server::EDITABLE,69 'callback' => array( $this, 'update_item' ),93 'methods' => WP_REST_Server::EDITABLE, 94 'callback' => array( $this, 'update_item' ), 70 95 'permission_callback' => array( $this, 'update_item_permissions_check' ), 71 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ),96 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::EDITABLE ), 72 97 ), 73 98 array( 74 'methods' => WP_REST_Server::DELETABLE,75 'callback' => array( $this, 'delete_item' ),99 'methods' => WP_REST_Server::DELETABLE, 100 'callback' => array( $this, 'delete_item' ), 76 101 'permission_callback' => array( $this, 'delete_item_permissions_check' ), 77 'args' => array(78 'force' 79 'default' 80 'description' 102 'args' => array( 103 'force' => array( 104 'default' => false, 105 'description' => __( 'Whether to bypass trash and force deletion.' ), 81 106 ), 82 107 ), … … 87 112 88 113 /** 89 * Check if a given request has access to read /posts. 114 * Checks if a given request has access to read posts. 115 * 116 * @since 4.7.0 117 * @access public 90 118 * 91 119 * @param WP_REST_Request $request Full details about the request. 92 * @return WP_Error|boolean120 * @return true|WP_Error True if the request has read access, WP_Error object otherwise. 93 121 */ 94 122 public function get_items_permissions_check( $request ) { … … 104 132 105 133 /** 106 * Get a collection of posts. 134 * Retrieves a collection of posts. 135 * 136 * @since 4.7.0 137 * @access public 107 138 * 108 139 * @param WP_REST_Request $request Full details about the request. 109 * @return WP_ Error|WP_REST_Response140 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. 110 141 */ 111 142 public function get_items( $request ) { 112 143 113 // Makesure a search string is set in case the orderby is set to 'relevance'.144 // Ensure a search string is set in case the orderby is set to 'relevance'. 114 145 if ( ! empty( $request['orderby'] ) && 'relevance' === $request['orderby'] && empty( $request['search'] ) ) { 115 146 return new WP_Error( 'rest_no_search_term_defined', __( 'You need to define a search term to order by relevance.' ), array( 'status' => 400 ) ); … … 120 151 $args = array(); 121 152 122 // This array defines mappings between public API query parameters whose 123 // values are accepted as-passed, and their internal WP_Query parameter 124 // name equivalents (some are the same). Only values which are also 125 // present in $registered will be set. 153 /* 154 * This array defines mappings between public API query parameters whose 155 * values are accepted as-passed, and their internal WP_Query parameter 156 * name equivalents (some are the same). Only values which are also 157 * present in $registered will be set. 158 */ 126 159 $parameter_mappings = array( 127 160 'author' => 'author__in', … … 141 174 ); 142 175 143 // For each known parameter which is both registered and present in the request, 144 // set the parameter's value on the query $args. 176 /* 177 * For each known parameter which is both registered and present in the request, 178 * set the parameter's value on the query $args. 179 */ 145 180 foreach ( $parameter_mappings as $api_param => $wp_param ) { 146 181 if ( isset( $registered[ $api_param ], $request[ $api_param ] ) ) { … … 150 185 151 186 // Check for & assign any parameters which require special handling or setting. 152 153 187 $args['date_query'] = array(); 188 154 189 // Set before into date query. Date query must be specified as an array of an array. 155 190 if ( isset( $registered['before'], $request['before'] ) ) { … … 170 205 $sticky_posts = get_option( 'sticky_posts', array() ); 171 206 if ( $sticky_posts && $request['sticky'] ) { 172 // As post__in will be used to only get sticky posts, 173 // we have to support the case where post__in was already 174 // specified. 207 /* 208 * As post__in will be used to only get sticky posts, 209 * we have to support the case where post__in was already 210 * specified. 211 */ 175 212 $args['post__in'] = $args['post__in'] ? array_intersect( $sticky_posts, $args['post__in'] ) : $sticky_posts; 176 213 177 // If we intersected, but there are no post ids in common, 178 // WP_Query won't return "no posts" for `post__in = array()` 179 // so we have to fake it a bit. 214 /* 215 * If we intersected, but there are no post ids in common, 216 * WP_Query won't return "no posts" for post__in = array() 217 * so we have to fake it a bit. 218 */ 180 219 if ( ! $args['post__in'] ) { 181 220 $args['post__in'] = array( -1 ); 182 221 } 183 222 } elseif ( $sticky_posts ) { 184 // As post___not_in will be used to only get posts that 185 // are not sticky, we have to support the case where post__not_in 186 // was already specified. 223 /* 224 * As post___not_in will be used to only get posts that 225 * are not sticky, we have to support the case where post__not_in 226 * was already specified. 227 */ 187 228 $args['post__not_in'] = array_merge( $args['post__not_in'], $sticky_posts ); 188 229 } … … 193 234 194 235 /** 195 * Filter the query arguments for a request. 196 * 197 * Enables adding extra arguments or setting defaults for a post 198 * collection request. 199 * 200 * @see https://developer.wordpress.org/reference/classes/wp_query/ 236 * Filters the query arguments for a request. 237 * 238 * Enables adding extra arguments or setting defaults for a post collection request. 239 * 240 * @since 4.7.0 241 * 242 * @link https://developer.wordpress.org/reference/classes/wp_query/ 201 243 * 202 244 * @param array $args Key value array of query var to query value. … … 207 249 208 250 $taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) ); 251 209 252 foreach ( $taxonomies as $taxonomy ) { 210 253 $base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name; … … 231 274 } 232 275 233 $posts_query = new WP_Query();276 $posts_query = new WP_Query(); 234 277 $query_result = $posts_query->query( $query_args ); 235 278 … … 240 283 241 284 $posts = array(); 285 242 286 foreach ( $query_result as $post ) { 243 287 if ( ! $this->check_read_permission( $post ) ) { … … 245 289 } 246 290 247 $data = $this->prepare_item_for_response( $post, $request );291 $data = $this->prepare_item_for_response( $post, $request ); 248 292 $posts[] = $this->prepare_response_for_collection( $data ); 249 293 } … … 260 304 // Out-of-bounds, run the query again without LIMIT for total count. 261 305 unset( $query_args['paged'] ); 306 262 307 $count_query = new WP_Query(); 263 308 $count_query->query( $query_args ); … … 266 311 267 312 $max_pages = ceil( $total_posts / (int) $posts_query->query_vars['posts_per_page'] ); 268 269 $response = rest_ensure_response( $posts ); 313 $response = rest_ensure_response( $posts ); 314 270 315 $response->header( 'X-WP-Total', (int) $total_posts ); 271 316 $response->header( 'X-WP-TotalPages', (int) $max_pages ); … … 276 321 if ( $page > 1 ) { 277 322 $prev_page = $page - 1; 323 278 324 if ( $prev_page > $max_pages ) { 279 325 $prev_page = $max_pages; 280 326 } 327 281 328 $prev_link = add_query_arg( 'page', $prev_page, $base ); 282 329 $response->link_header( 'prev', $prev_link ); … … 285 332 $next_page = $page + 1; 286 333 $next_link = add_query_arg( 'page', $next_page, $base ); 334 287 335 $response->link_header( 'next', $next_link ); 288 336 } … … 292 340 293 341 /** 294 * Check if a given request has access to read a post. 295 * 296 * @param WP_REST_Request $request Full details about the request. 297 * @return WP_Error|boolean 342 * Checks if a given request has access to read a post. 343 * 344 * @since 4.7.0 345 * @access public 346 * 347 * @param WP_REST_Request $request Full details about the request. 348 * @return bool|WP_Error True if the request has read access for the item, WP_Error object otherwise. 298 349 */ 299 350 public function get_item_permissions_check( $request ) { … … 325 376 326 377 /** 327 * C an the user access password-protected content?378 * Checks if the user can access password-protected content. 328 379 * 329 380 * This method determines whether we need to override the regular password 330 381 * check in core with a filter. 331 382 * 383 * @since 4.7.0 384 * @access protected 385 * 332 386 * @param WP_Post $post Post to check against. 333 387 * @param WP_REST_Request $request Request data to check. 334 * @return bool True if the user can access password-protected content, false otherwise.388 * @return bool True if the user can access password-protected content, otherwise false. 335 389 */ 336 390 protected function can_access_password_content( $post, $request ) { … … 355 409 356 410 /** 357 * Get a single post. 411 * Retrieves a single post. 412 * 413 * @since 4.7.0 414 * @access public 358 415 * 359 416 * @param WP_REST_Request $request Full details about the request. 360 * @return WP_ Error|WP_REST_Response417 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. 361 418 */ 362 419 public function get_item( $request ) { 363 $id = (int) $request['id'];420 $id = (int) $request['id']; 364 421 $post = $this->get_post( $id ); 365 422 … … 368 425 } 369 426 370 $data = $this->prepare_item_for_response( $post, $request );427 $data = $this->prepare_item_for_response( $post, $request ); 371 428 $response = rest_ensure_response( $data ); 372 429 … … 379 436 380 437 /** 381 * Check if a given request has access to create a post. 382 * 383 * @param WP_REST_Request $request Full details about the request. 384 * @return WP_Error|boolean 438 * Checks if a given request has access to create a post. 439 * 440 * @since 4.7.0 441 * @access public 442 * 443 * @param WP_REST_Request $request Full details about the request. 444 * @return true|WP_Error True if the request has access to create items, WP_Error object otherwise. 385 445 */ 386 446 public function create_item_permissions_check( $request ) { … … 399 459 return new WP_Error( 'rest_cannot_create', __( 'Sorry, you are not allowed to create new posts.' ), array( 'status' => rest_authorization_required_code() ) ); 400 460 } 461 401 462 return true; 402 463 } 403 464 404 465 /** 405 * Create a single post. 466 * Creates a single post. 467 * 468 * @since 4.7.0 469 * @access public 406 470 * 407 471 * @param WP_REST_Request $request Full details about the request. 408 * @return WP_ Error|WP_REST_Response472 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. 409 473 */ 410 474 public function create_item( $request ) { … … 414 478 415 479 $post = $this->prepare_item_for_database( $request ); 480 416 481 if ( is_wp_error( $post ) ) { 417 482 return $post; … … 419 484 420 485 $post->post_type = $this->post_type; 421 $post_id = wp_insert_post( $post, true );486 $post_id = wp_insert_post( $post, true ); 422 487 423 488 if ( is_wp_error( $post_id ) ) { … … 428 493 $post_id->add_data( array( 'status' => 400 ) ); 429 494 } 495 430 496 return $post_id; 431 497 } 498 432 499 $post->ID = $post_id; 433 500 … … 453 520 $this->handle_template( $request['template'], $post->ID ); 454 521 } 522 455 523 $terms_update = $this->handle_terms( $post->ID, $request ); 524 456 525 if ( is_wp_error( $terms_update ) ) { 457 526 return $terms_update; … … 459 528 460 529 $post = $this->get_post( $post_id ); 530 461 531 if ( ! empty( $schema['properties']['meta'] ) && isset( $request['meta'] ) ) { 462 532 $meta_update = $this->meta->update_value( $request['meta'], (int) $request['id'] ); 533 463 534 if ( is_wp_error( $meta_update ) ) { 464 535 return $meta_update; … … 467 538 468 539 $fields_update = $this->update_additional_fields_for_object( $post, $request ); 540 469 541 if ( is_wp_error( $fields_update ) ) { 470 542 return $fields_update; … … 474 546 * Fires after a single post is created or updated via the REST API. 475 547 * 476 * @param object $post Inserted Post object (not a WP_Post object). 477 * @param WP_REST_Request $request Request object. 478 * @param boolean $creating True when creating post, false when updating. 548 * The dynamic portion of the hook name, `$this->post_type`, refers to the post type slug. 549 * 550 * @since 4.7.0 551 * 552 * @param object $post Inserted Post object (not a WP_Post object). 553 * @param WP_REST_Request $request Request object. 554 * @param bool $creating True when creating post, false when updating. 479 555 */ 480 556 do_action( "rest_insert_{$this->post_type}", $post, $request, true ); 481 557 482 558 $request->set_param( 'context', 'edit' ); 559 483 560 $response = $this->prepare_item_for_response( $post, $request ); 484 561 $response = rest_ensure_response( $response ); 562 485 563 $response->set_status( 201 ); 486 564 $response->header( 'Location', rest_url( sprintf( '%s/%s/%d', $this->namespace, $this->rest_base, $post_id ) ) ); … … 490 568 491 569 /** 492 * Check if a given request has access to update a post. 493 * 494 * @param WP_REST_Request $request Full details about the request. 495 * @return WP_Error|boolean 570 * Checks if a given request has access to update a post. 571 * 572 * @since 4.7.0 573 * @access public 574 * 575 * @param WP_REST_Request $request Full details about the request. 576 * @return true|WP_Error True if the request has access to update the item, WP_Error object otherwise. 496 577 */ 497 578 public function update_item_permissions_check( $request ) { … … 516 597 517 598 /** 518 * Update a single post. 599 * Updates a single post. 600 * 601 * @since 4.7.0 602 * @access public 519 603 * 520 604 * @param WP_REST_Request $request Full details about the request. 521 * @return WP_ Error|WP_REST_Response605 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. 522 606 */ 523 607 public function update_item( $request ) { 524 $id = (int) $request['id'];608 $id = (int) $request['id']; 525 609 $post = $this->get_post( $id ); 526 610 … … 530 614 531 615 $post = $this->prepare_item_for_database( $request ); 616 532 617 if ( is_wp_error( $post ) ) { 533 618 return $post; 534 619 } 620 535 621 // convert the post object to an array, otherwise wp_update_post will expect non-escaped input. 536 622 $post_id = wp_update_post( (array) $post, true ); 623 537 624 if ( is_wp_error( $post_id ) ) { 538 625 if ( 'db_update_error' === $post_id->get_error_code() ) { … … 567 654 568 655 $terms_update = $this->handle_terms( $post->ID, $request ); 656 569 657 if ( is_wp_error( $terms_update ) ) { 570 658 return $terms_update; … … 575 663 if ( ! empty( $schema['properties']['meta'] ) && isset( $request['meta'] ) ) { 576 664 $meta_update = $this->meta->update_value( $request['meta'], $post->ID ); 665 577 666 if ( is_wp_error( $meta_update ) ) { 578 667 return $meta_update; … … 581 670 582 671 $fields_update = $this->update_additional_fields_for_object( $post, $request ); 672 583 673 if ( is_wp_error( $fields_update ) ) { 584 674 return $fields_update; … … 589 679 590 680 $request->set_param( 'context', 'edit' ); 681 591 682 $response = $this->prepare_item_for_response( $post, $request ); 683 592 684 return rest_ensure_response( $response ); 593 685 } 594 686 595 687 /** 596 * Check if a given request has access to delete a post. 597 * 598 * @param WP_REST_Request $request Full details about the request. 599 * @return bool|WP_Error 688 * Checks if a given request has access to delete a post. 689 * 690 * @since 4.7.0 691 * @access public 692 * 693 * @param WP_REST_Request $request Full details about the request. 694 * @return true|WP_Error True if the request has access to delete the item, WP_Error object otherwise. 600 695 */ 601 696 public function delete_item_permissions_check( $request ) { … … 611 706 612 707 /** 613 * Delete a single post. 708 * Deletes a single post. 709 * 710 * @since 4.7.0 711 * @access public 614 712 * 615 713 * @param WP_REST_Request $request Full details about the request. 616 * @return WP_REST_Response|WP_Error 714 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. 617 715 */ 618 716 public function delete_item( $request ) { 619 $id = (int) $request['id'];717 $id = (int) $request['id']; 620 718 $force = (bool) $request['force']; 621 719 … … 627 725 628 726 $supports_trash = ( EMPTY_TRASH_DAYS > 0 ); 727 629 728 if ( 'attachment' === $post->post_type ) { 630 729 $supports_trash = $supports_trash && MEDIA_TRASH; … … 632 731 633 732 /** 634 * Filter whether a post is trashable. 635 * 636 * Return false to disable trash support for the post. 637 * 638 * @param boolean $supports_trash Whether the post type support trashing. 733 * Filters whether a post is trashable. 734 * 735 * The dynamic portion of the hook name, `$this->post_type`, refers to the post type slug. 736 * 737 * Pass false to disable trash support for the post. 738 * 739 * @since 4.7.0 740 * 741 * @param bool $supports_trash Whether the post type support trashing. 639 742 * @param WP_Post $post The Post object being considered for trashing support. 640 743 */ … … 646 749 647 750 $request->set_param( 'context', 'edit' ); 751 648 752 $response = $this->prepare_item_for_response( $post, $request ); 649 753 … … 672 776 673 777 /** 674 * Fires after a single post is deleted or trashed via the REST API. 778 * Fires immediately after a single post is deleted or trashed via the REST API. 779 * 780 * They dynamic portion of the hook name, `$this->post_type`, refers to the post type slug. 781 * 782 * @since 4.7.0 675 783 * 676 784 * @param object $post The deleted or trashed post. … … 684 792 685 793 /** 686 * Determine the allowed query_vars for a get_items() response and 687 * prepare for WP_Query. 688 * 689 * @param array $prepared_args Prepared WP_Query arguments. 690 * @param WP_REST_Request $request Full details about the request. 691 * @return array $query_args 794 * Determines the allowed query_vars for a get_items() response and prepares 795 * them for WP_Query. 796 * 797 * @since 4.7.0 798 * @access protected 799 * 800 * @param array $prepared_args Optional. Prepared WP_Query arguments. Default empty array. 801 * @param WP_REST_Request $request Optional. Full details about the request. 802 * @return array Items query arguments. 692 803 */ 693 804 protected function prepare_items_query( $prepared_args = array(), $request = null ) { … … 695 806 $valid_vars = array_flip( $this->get_allowed_query_vars( $request ) ); 696 807 $query_args = array(); 808 697 809 foreach ( $valid_vars as $var => $index ) { 698 810 if ( isset( $prepared_args[ $var ] ) ) { 699 811 /** 700 * Filter the query_vars used in `get_items`for the constructed query.812 * Filters the query_vars used in get_items() for the constructed query. 701 813 * 702 * The dynamic portion of the hook name, $var, refers to the query_var key.814 * The dynamic portion of the hook name, `$var`, refers to the query_var key. 703 815 * 704 * @param mixed $prepared_args[ $var ] The query_var value. 816 * @since 4.7.0 817 * 818 * @param string $var The query_var value. 705 819 */ 706 820 $query_args[ $var ] = apply_filters( "rest_query_var-{$var}", $prepared_args[ $var ] ); … … 720 834 721 835 /** 722 * Get all the WP Query vars that are allowed for the API request. 723 * 724 * @param WP_REST_Request $request Full details about the request. 725 * @return array 836 * Retrieves all of the WP Query vars that are allowed for the REST API request. 837 * 838 * @since 4.7.0 839 * @access protected 840 * 841 * @param WP_REST_Request $request Optional. Full details about the request. 842 * @return array Allowed query variables. 726 843 */ 727 844 protected function get_allowed_query_vars( $request = null ) { … … 729 846 730 847 /** 731 * Filter the publicly allowed query vars.848 * Filters the publicly allowed query vars. 732 849 * 733 850 * Allows adjusting of the default query vars that are made public. 851 * 852 * @since 4.7.0 734 853 * 735 854 * @param array Array of allowed WP_Query query vars. … … 740 859 if ( current_user_can( $post_type_obj->cap->edit_posts ) ) { 741 860 /** 742 * Filter the allowed 'private' query vars for authorized users.861 * Filters the allowed 'private' query vars for authorized users. 743 862 * 744 863 * If the user has the `edit_posts` capability, we also allow use of … … 749 868 * `add_filter( 'rest_private_query_vars', '__return_empty_array' );` 750 869 * 870 * @since 4.7.0 871 * 751 872 * @param array $private_query_vars Array of allowed query vars for authorized users. 752 * }753 873 */ 754 874 $private = apply_filters( 'rest_private_query_vars', $wp->private_query_vars ); 875 755 876 $valid_vars = array_merge( $valid_vars, $private ); 756 877 } 878 757 879 // Define our own in addition to WP's normal vars. 758 880 $rest_valid = array( … … 770 892 'date_query', 771 893 ); 894 772 895 $valid_vars = array_merge( $valid_vars, $rest_valid ); 773 896 774 897 /** 775 * Filter allowed query vars for the REST API.898 * Filters allowed query vars for the REST API. 776 899 * 777 900 * This filter allows you to add or remove query vars from the final allowed 778 901 * list for all requests, including unauthenticated ones. To alter the 779 * vars for editors only, {@see rest_private_query_vars}. 902 * vars for editors only, see {@see 'rest_private_query_vars'}. 903 * 904 * @since 4.7.0 780 905 * 781 906 * @param array { 782 907 * Array of allowed WP_Query query vars. 783 908 * 784 * @param string $allowed_query_var The query var to allow.785 * @param WP_REST_Request $request Request object.909 * @param string $allowed_query_var The query var to allow. 910 * @param WP_REST_Request $request Request object. 786 911 * } 787 912 */ … … 792 917 793 918 /** 794 * Check the post_date_gmt or modified_gmt and prepare any post or919 * Checks the post_date_gmt or modified_gmt and prepare any post or 795 920 * modified date for single post output. 796 921 * 922 * @since 4.7.0 923 * @access protected 924 * 797 925 * @param string $date_gmt GMT publication time. 798 * @param string|null $date Optional , default is null. Local publication time.926 * @param string|null $date Optional. Local publication time. Default null. 799 927 * @return string|null ISO8601/RFC3339 formatted datetime. 800 928 */ … … 815 943 816 944 /** 817 * Prepare a single post for create or update. 945 * Prepares a single post for create or update. 946 * 947 * @since 4.7.0 948 * @access protected 818 949 * 819 950 * @param WP_REST_Request $request Request object. 820 * @return WP_Error|stdClass $prepared_post Post object.951 * @return stdClass|WP_Error Post object or WP_Error. 821 952 */ 822 953 protected function prepare_item_for_database( $request ) { 823 954 $prepared_post = new stdClass; 824 955 825 // ID.956 // Post ID. 826 957 if ( isset( $request['id'] ) ) { 827 958 $prepared_post->ID = absint( $request['id'] ); … … 865 996 $prepared_post->post_type = get_post_type( $request['id'] ); 866 997 } 998 867 999 $post_type = get_post_type_object( $prepared_post->post_type ); 868 1000 … … 870 1002 if ( ! empty( $schema['properties']['status'] ) && isset( $request['status'] ) ) { 871 1003 $status = $this->handle_status_param( $request['status'], $post_type ); 1004 872 1005 if ( is_wp_error( $status ) ) { 873 1006 return $status; … … 891 1024 } 892 1025 } 1026 893 1027 // Post slug. 894 1028 if ( ! empty( $schema['properties']['slug'] ) && isset( $request['slug'] ) ) { … … 899 1033 if ( ! empty( $schema['properties']['author'] ) && ! empty( $request['author'] ) ) { 900 1034 $post_author = (int) $request['author']; 1035 901 1036 if ( get_current_user_id() !== $post_author ) { 902 1037 $user_obj = get_userdata( $post_author ); 1038 903 1039 if ( ! $user_obj ) { 904 1040 return new WP_Error( 'rest_invalid_author', __( 'Invalid author id.' ), array( 'status' => 400 ) ); 905 1041 } 906 1042 } 1043 907 1044 $prepared_post->post_author = $post_author; 908 1045 } … … 930 1067 if ( ! empty( $schema['properties']['parent'] ) && ! empty( $request['parent'] ) ) { 931 1068 $parent = $this->get_post( (int) $request['parent'] ); 1069 932 1070 if ( empty( $parent ) ) { 933 1071 return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post parent id.' ), array( 'status' => 400 ) ); … … 951 1089 $prepared_post->ping_status = $request['ping_status']; 952 1090 } 1091 953 1092 /** 954 * Filter a post before it is inserted via the REST API. 955 * 956 * The dynamic portion of the hook name, $this->post_type, refers to post_type of the post being 957 * prepared for insertion. 1093 * Filters a post before it is inserted via the REST API. 1094 * 1095 * The dynamic portion of the hook name, `$this->post_type`, refers to the post type slug. 1096 * 1097 * @since 4.7.0 958 1098 * 959 1099 * @param stdClass $prepared_post An object representing a single post prepared … … 966 1106 967 1107 /** 968 * Determine validity and normalize provided status param. 1108 * Determines validity and normalizes the given status parameter. 1109 * 1110 * @since 4.7.0 1111 * @access protected 969 1112 * 970 1113 * @param string $post_status Post status. 971 1114 * @param object $post_type Post type. 972 * @return WP_Error|string $post_status1115 * @return string|WP_Error Post status or WP_Error if lacking the proper permission. 973 1116 */ 974 1117 protected function handle_status_param( $post_status, $post_type ) { … … 1000 1143 1001 1144 /** 1002 * Determine the featured media based on a request param. 1145 * Determines the featured media based on a request param. 1146 * 1147 * @since 4.7.0 1148 * @access protected 1003 1149 * 1004 1150 * @param int $featured_media Featured Media ID. 1005 1151 * @param int $post_id Post ID. 1006 * @return bool|WP_Error 1152 * @return bool|WP_Error Whether the post thumbnail was successfully deleted, otherwise WP_Error. 1007 1153 */ 1008 1154 protected function handle_featured_media( $featured_media, $post_id ) { … … 1023 1169 1024 1170 /** 1025 * Set the template for a page. 1171 * Sets the template for a page. 1172 * 1173 * @since 4.7.0 1174 * @access public 1026 1175 * 1027 1176 * @param string $template Page template filename. … … 1037 1186 1038 1187 /** 1039 * Update the post's terms from a REST request. 1040 * 1041 * @param int $post_id The post ID to update the terms form. 1042 * @param WP_REST_Request $request The request object with post and terms data. 1043 * @return null|WP_Error WP_Error on an error assigning any of the terms. 1188 * Updates the post's terms from a REST request. 1189 * 1190 * @since 4.7.0 1191 * @access protected 1192 * 1193 * @param int $post_id The post ID to update the terms form. 1194 * @param WP_REST_Request $request The request object with post and terms data. 1195 * @return null|WP_Error WP_Error on an error assigning any of the terms, otherwise null. 1044 1196 */ 1045 1197 protected function handle_terms( $post_id, $request ) { 1046 1198 $taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) ); 1199 1047 1200 foreach ( $taxonomies as $taxonomy ) { 1048 1201 $base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name; … … 1051 1204 continue; 1052 1205 } 1053 $terms = array_map( 'absint', $request[ $base ] ); 1206 1207 $terms = array_map( 'absint', $request[ $base ] ); 1054 1208 $result = wp_set_object_terms( $post_id, $terms, $taxonomy->name ); 1209 1055 1210 if ( is_wp_error( $result ) ) { 1056 1211 return $result; … … 1060 1215 1061 1216 /** 1062 * Check if a given post type should be viewed or managed. 1217 * Checks if a given post type can be viewed or managed. 1218 * 1219 * @since 4.7.0 1220 * @access protected 1063 1221 * 1064 1222 * @param object|string $post_type Post type name or object. 1065 * @return bool ean Is post type allowed?1223 * @return bool Whether the post type is allowed in REST. 1066 1224 */ 1067 1225 protected function check_is_post_type_allowed( $post_type ) { … … 1078 1236 1079 1237 /** 1080 * Check if we can read a post.1238 * Checks if a post can be read. 1081 1239 * 1082 1240 * Correctly handles posts with the inherit status. 1083 1241 * 1242 * @since 4.7.0 1243 * @access public 1244 * 1084 1245 * @param object $post Post object. 1085 * @return bool ean Can we read it?1246 * @return bool Whether the post can be read. 1086 1247 */ 1087 1248 public function check_read_permission( $post ) { … … 1091 1252 } 1092 1253 1093 // Can we read the post?1254 // Is the post readable? 1094 1255 if ( 'publish' === $post->post_status || current_user_can( $post_type->cap->read_post, $post->ID ) ) { 1095 1256 return true; … … 1107 1268 } 1108 1269 1109 // If we don't have a parent, but the status is set to inherit, assume 1110 // it's published (as per get_post_status()). 1270 /* 1271 * If there isn't a parent, but the status is set to inherit, assume 1272 * it's published (as per get_post_status()). 1273 */ 1111 1274 if ( 'inherit' === $post->post_status ) { 1112 1275 return true; … … 1117 1280 1118 1281 /** 1119 * Check if we can edit a post. 1282 * Checks if a post can be edited. 1283 * 1284 * @since 4.7.0 1285 * @access protected 1120 1286 * 1121 1287 * @param object $post Post object. 1122 * @return bool ean Can we edit it?1288 * @return bool Whether the post can be edited. 1123 1289 */ 1124 1290 protected function check_update_permission( $post ) { … … 1133 1299 1134 1300 /** 1135 * Check if we can create a post. 1301 * Checks if a post can be created. 1302 * 1303 * @since 4.7.0 1304 * @access protected 1136 1305 * 1137 1306 * @param object $post Post object. 1138 * @return bool ean Can we create it?.1307 * @return bool Whether the post can be created. 1139 1308 */ 1140 1309 protected function check_create_permission( $post ) { … … 1149 1318 1150 1319 /** 1151 * Check if we can delete a post. 1320 * Checks if a post can be deleted. 1321 * 1322 * @since 4.7.0 1323 * @access protected 1152 1324 * 1153 1325 * @param object $post Post object. 1154 * @return bool ean Can we delete it?1326 * @return bool Whether the post can be deleted. 1155 1327 */ 1156 1328 protected function check_delete_permission( $post ) { … … 1165 1337 1166 1338 /** 1167 * Prepare a single post output for response. 1339 * Prepares a single post output for response. 1340 * 1341 * @since 4.7.0 1342 * @access public 1168 1343 * 1169 1344 * @param WP_Post $post Post object. 1170 1345 * @param WP_REST_Request $request Request object. 1171 * @return WP_REST_Response $data1346 * @return WP_REST_Response Response object. 1172 1347 */ 1173 1348 public function prepare_item_for_response( $post, $request ) { 1174 1349 $GLOBALS['post'] = $post; 1350 1175 1351 setup_postdata( $post ); 1176 1352 … … 1230 1406 if ( ! empty( $schema['properties']['title'] ) ) { 1231 1407 add_filter( 'protected_title_format', array( $this, 'protected_title_format' ) ); 1408 1232 1409 $data['title'] = array( 1233 1410 'raw' => $post->post_title, 1234 1411 'rendered' => get_the_title( $post->ID ), 1235 1412 ); 1413 1236 1414 remove_filter( 'protected_title_format', array( $this, 'protected_title_format' ) ); 1237 1415 } 1238 1416 1239 1417 $has_password_filter = false; 1418 1240 1419 if ( $this->can_access_password_content( $post, $request ) ) { 1241 1420 // Allow access to the post, permissions already checked before. 1242 1421 add_filter( 'post_password_required', '__return_false' ); 1422 1243 1423 $has_password_filter = true; 1244 1424 } … … 1306 1486 if ( ! empty( $schema['properties']['format'] ) ) { 1307 1487 $data['format'] = get_post_format( $post->ID ); 1488 1308 1489 // Fill in blank post format. 1309 1490 if ( empty( $data['format'] ) ) { … … 1317 1498 1318 1499 $taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) ); 1500 1319 1501 foreach ( $taxonomies as $taxonomy ) { 1320 1502 $base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name; 1503 1321 1504 if ( ! empty( $schema['properties'][ $base ] ) ) { 1322 1505 $terms = get_the_terms( $post, $taxonomy->name ); … … 1326 1509 1327 1510 $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; 1328 $data = $this->add_additional_fields_to_object( $data, $request );1329 $data = $this->filter_response_by_context( $data, $context );1511 $data = $this->add_additional_fields_to_object( $data, $request ); 1512 $data = $this->filter_response_by_context( $data, $context ); 1330 1513 1331 1514 // Wrap the data in a response object. … … 1335 1518 1336 1519 /** 1337 * Filter the post data for a response. 1338 * 1339 * The dynamic portion of the hook name, $this->post_type, refers to post_type of the post being 1340 * prepared for the response. 1341 * 1342 * @param WP_REST_Response $response The response object. 1343 * @param WP_Post $post Post object. 1344 * @param WP_REST_Request $request Request object. 1520 * Filters the post data for a response. 1521 * 1522 * The dynamic portion of the hook name, `$this->post_type`, refers to the post type slug. 1523 * 1524 * @since 4.7.0 1525 * 1526 * @param WP_REST_Response $response The response object. 1527 * @param WP_Post $post Post object. 1528 * @param WP_REST_Request $request Request object. 1345 1529 */ 1346 1530 return apply_filters( "rest_prepare_{$this->post_type}", $response, $post, $request ); … … 1348 1532 1349 1533 /** 1350 * Overwrite the default protected title format.1351 * 1352 * By default WordPress will show password protected posts with a title of1534 * Overwrites the default protected title format. 1535 * 1536 * By default, WordPress will show password protected posts with a title of 1353 1537 * "Protected: %s", as the REST API communicates the protected status of a post 1354 1538 * in a machine readable format, we remove the "Protected: " prefix. 1355 1539 * 1356 * @return string 1540 * @return string Protected title format. 1357 1541 */ 1358 1542 public function protected_title_format() { … … 1361 1545 1362 1546 /** 1363 * Prepare links for the request. 1547 * Prepares links for the request. 1548 * 1549 * @since 4.7.0 1550 * @access protected 1364 1551 * 1365 1552 * @param WP_Post $post Post object. … … 1393 1580 $replies_url = rest_url( 'wp/v2/comments' ); 1394 1581 $replies_url = add_query_arg( 'post', $post->ID, $replies_url ); 1582 1395 1583 $links['replies'] = array( 1396 'href' 1397 'embeddable' 1584 'href' => $replies_url, 1585 'embeddable' => true, 1398 1586 ); 1399 1587 } … … 1404 1592 ); 1405 1593 } 1594 1406 1595 $post_type_obj = get_post_type_object( $post->post_type ); 1596 1407 1597 if ( $post_type_obj->hierarchical && ! empty( $post->post_parent ) ) { 1408 1598 $links['up'] = array( … … 1415 1605 if ( $featured_media = get_post_thumbnail_id( $post->ID ) ) { 1416 1606 $image_url = rest_url( 'wp/v2/media/' . $featured_media ); 1607 1417 1608 $links['https://api.w.org/featuredmedia'] = array( 1418 1609 'href' => $image_url, … … 1420 1611 ); 1421 1612 } 1613 1422 1614 if ( ! in_array( $post->post_type, array( 'attachment', 'nav_menu_item', 'revision' ), true ) ) { 1423 1615 $attachments_url = rest_url( 'wp/v2/media' ); 1424 1616 $attachments_url = add_query_arg( 'parent', $post->ID, $attachments_url ); 1617 1425 1618 $links['https://api.w.org/attachment'] = array( 1426 'href' 1619 'href' => $attachments_url, 1427 1620 ); 1428 1621 } 1429 1622 1430 1623 $taxonomies = get_object_taxonomies( $post->post_type ); 1624 1431 1625 if ( ! empty( $taxonomies ) ) { 1432 1626 $links['https://api.w.org/term'] = array(); … … 1434 1628 foreach ( $taxonomies as $tax ) { 1435 1629 $taxonomy_obj = get_taxonomy( $tax ); 1630 1436 1631 // Skip taxonomies that are not public. 1437 1632 if ( empty( $taxonomy_obj->show_in_rest ) ) { … … 1440 1635 1441 1636 $tax_base = ! empty( $taxonomy_obj->rest_base ) ? $taxonomy_obj->rest_base : $tax; 1637 1442 1638 $terms_url = add_query_arg( 1443 1639 'post', … … 1458 1654 1459 1655 /** 1460 * Get the Post's schema, conforming to JSON Schema. 1461 * 1462 * @return array 1656 * Retrieves the post's schema, conforming to JSON Schema. 1657 * 1658 * @since 4.7.0 1659 * @access public 1660 * 1661 * @return array Item schema data. 1463 1662 */ 1464 1663 public function get_item_schema() { … … 1468 1667 'title' => $this->post_type, 1469 1668 'type' => 'object', 1470 /* 1471 * Base properties for every Post. 1472 */ 1669 // Base properties for every Post. 1473 1670 'properties' => array( 1474 1671 'date' => array( … … 1555 1752 1556 1753 $post_type_obj = get_post_type_object( $this->post_type ); 1754 1557 1755 if ( $post_type_obj->hierarchical ) { 1558 1756 $schema['properties']['parent'] = array( … … 1787 1985 1788 1986 /** 1789 * Get the query params for collections of attachments. 1790 * 1791 * @return array 1987 * Retrieves the query params for the posts collection. 1988 * 1989 * @since 4.7.0 1990 * @access public 1991 * 1992 * @return array Collection parameters. 1792 1993 */ 1793 1994 public function get_collection_params() { … … 1802 2003 'validate_callback' => 'rest_validate_request_arg', 1803 2004 ); 2005 1804 2006 if ( post_type_supports( $this->post_type, 'author' ) ) { 1805 2007 $params['author'] = array( … … 1816 2018 ); 1817 2019 } 2020 1818 2021 $params['before'] = array( 1819 2022 'description' => __( 'Limit response to resources published before a given ISO8601 compliant date.' ), … … 1822 2025 'validate_callback' => 'rest_validate_request_arg', 1823 2026 ); 2027 1824 2028 $params['exclude'] = array( 1825 2029 'description' => __( 'Ensure result set excludes specific ids.' ), … … 1828 2032 'sanitize_callback' => 'wp_parse_id_list', 1829 2033 ); 2034 1830 2035 $params['include'] = array( 1831 2036 'description' => __( 'Limit result set to specific ids.' ), … … 1834 2039 'sanitize_callback' => 'wp_parse_id_list', 1835 2040 ); 2041 1836 2042 if ( 'page' === $this->post_type || post_type_supports( $this->post_type, 'page-attributes' ) ) { 1837 2043 $params['menu_order'] = array( … … 1842 2048 ); 1843 2049 } 2050 1844 2051 $params['offset'] = array( 1845 2052 'description' => __( 'Offset the result set by a specific number of items.' ), … … 1848 2055 'validate_callback' => 'rest_validate_request_arg', 1849 2056 ); 2057 1850 2058 $params['order'] = array( 1851 2059 'description' => __( 'Order sort attribute ascending or descending.' ), … … 1855 2063 'validate_callback' => 'rest_validate_request_arg', 1856 2064 ); 2065 1857 2066 $params['orderby'] = array( 1858 2067 'description' => __( 'Sort collection by object attribute.' ), … … 1869 2078 'validate_callback' => 'rest_validate_request_arg', 1870 2079 ); 2080 1871 2081 if ( 'page' === $this->post_type || post_type_supports( $this->post_type, 'page-attributes' ) ) { 1872 2082 $params['orderby']['enum'][] = 'menu_order'; … … 1874 2084 1875 2085 $post_type_obj = get_post_type_object( $this->post_type ); 2086 1876 2087 if ( $post_type_obj->hierarchical || 'attachment' === $this->post_type ) { 1877 2088 $params['parent'] = array( … … 1894 2105 'validate_callback' => 'rest_validate_request_arg', 1895 2106 ); 2107 1896 2108 $params['status'] = array( 1897 2109 'default' => 'publish', … … 1904 2116 1905 2117 $taxonomies = wp_list_filter( get_object_taxonomies( $this->post_type, 'objects' ), array( 'show_in_rest' => true ) ); 2118 1906 2119 foreach ( $taxonomies as $taxonomy ) { 1907 2120 $base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name; … … 1927 2140 1928 2141 /** 1929 * Validate whether the user can query private statuses. 2142 * Validates whether the user can query private statuses. 2143 * 2144 * @since 4.7.0 2145 * @access public 1930 2146 * 1931 2147 * @param mixed $value Post status. 1932 2148 * @param WP_REST_Request $request Full details about the request. 1933 * @param string $parameter 1934 * @return WP_Error|boolean2149 * @param string $parameter Additional parameter to pass to validation. 2150 * @return bool|WP_Error Whether the request can query private statuses, otherwise WP_Error object. 1935 2151 */ 1936 2152 public function validate_user_can_query_private_statuses( $value, $request, $parameter ) { … … 1938 2154 return rest_validate_request_arg( $value, $request, $parameter ); 1939 2155 } 2156 1940 2157 $post_type_obj = get_post_type_object( $this->post_type ); 2158 1941 2159 if ( current_user_can( $post_type_obj->cap->edit_posts ) ) { 1942 2160 return rest_validate_request_arg( $value, $request, $parameter ); 1943 2161 } 2162 1944 2163 return new WP_Error( 'rest_forbidden_status', __( 'Status is forbidden.' ), array( 'status' => rest_authorization_required_code() ) ); 1945 2164 }
Note: See TracChangeset
for help on using the changeset viewer.