WordPress 4.7.2
[autoinstalls/wordpress.git] / wp-includes / rest-api / endpoints / class-wp-rest-posts-controller.php
index 872a6607cbf89867b325a6cf6ca2d14ae778ec7c..7b27f60decfc16b77de460095fb942b47de30810 100644 (file)
@@ -77,18 +77,28 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
                        'schema' => array( $this, 'get_public_item_schema' ),
                ) );
 
+               $schema = $this->get_item_schema();
+               $get_item_args = array(
+                       'context'  => $this->get_context_param( array( 'default' => 'view' ) ),
+               );
+               if ( isset( $schema['properties']['password'] ) ) {
+                       $get_item_args['password'] = array(
+                               'description' => __( 'The password for the post if it is password protected.' ),
+                               'type'        => 'string',
+                       );
+               }
                register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<id>[\d]+)', array(
+                       'args' => array(
+                               'id' => array(
+                                       'description' => __( 'Unique identifier for the object.' ),
+                                       'type'        => 'integer',
+                               ),
+                       ),
                        array(
                                'methods'             => WP_REST_Server::READABLE,
                                'callback'            => array( $this, 'get_item' ),
                                'permission_callback' => array( $this, 'get_item_permissions_check' ),
-                               'args'                => array(
-                                       'context'  => $this->get_context_param( array( 'default' => 'view' ) ),
-                                       'password' => array(
-                                               'description' => __( 'The password for the post if it is password protected.' ),
-                                               'type'        => 'string',
-                                       ),
-                               ),
+                               'args'                => $get_item_args,
                        ),
                        array(
                                'methods'             => WP_REST_Server::EDITABLE,
@@ -345,6 +355,28 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
                return $response;
        }
 
+       /**
+        * Get the post, if the ID is valid.
+        *
+        * @since 4.7.2
+        *
+        * @param int $id Supplied ID.
+        * @return WP_Post|WP_Error Post object if ID is valid, WP_Error otherwise.
+        */
+       protected function get_post( $id ) {
+               $error = new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
+               if ( (int) $id <= 0 ) {
+                       return $error;
+               }
+
+               $post = get_post( (int) $id );
+               if ( empty( $post ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
+                       return $error;
+               }
+
+               return $post;
+       }
+
        /**
         * Checks if a given request has access to read a post.
         *
@@ -355,8 +387,10 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
         * @return bool|WP_Error True if the request has read access for the item, WP_Error object otherwise.
         */
        public function get_item_permissions_check( $request ) {
-
-               $post = get_post( (int) $request['id'] );
+               $post = $this->get_post( $request['id'] );
+               if ( is_wp_error( $post ) ) {
+                       return $post;
+               }
 
                if ( 'edit' === $request['context'] && $post && ! $this->check_update_permission( $post ) ) {
                        return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to edit this post.' ), array( 'status' => rest_authorization_required_code() ) );
@@ -424,18 +458,16 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
         * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
         */
        public function get_item( $request ) {
-               $id   = (int) $request['id'];
-               $post = get_post( $id );
-
-               if ( empty( $id ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
-                       return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
+               $post = $this->get_post( $request['id'] );
+               if ( is_wp_error( $post ) ) {
+                       return $post;
                }
 
                $data     = $this->prepare_item_for_response( $post, $request );
                $response = rest_ensure_response( $data );
 
                if ( is_post_type_viewable( get_post_type_object( $post->post_type ) ) ) {
-                       $response->link_header( 'alternate',  get_permalink( $id ), array( 'type' => 'text/html' ) );
+                       $response->link_header( 'alternate',  get_permalink( $post->ID ), array( 'type' => 'text/html' ) );
                }
 
                return $response;
@@ -451,6 +483,9 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
         * @return true|WP_Error True if the request has access to create items, WP_Error object otherwise.
         */
        public function create_item_permissions_check( $request ) {
+               if ( ! empty( $request['id'] ) ) {
+                       return new WP_Error( 'rest_post_exists', __( 'Cannot create existing post.' ), array( 'status' => 400 ) );
+               }
 
                $post_type = get_post_type_object( $this->post_type );
 
@@ -587,8 +622,11 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
         * @return true|WP_Error True if the request has access to update the item, WP_Error object otherwise.
         */
        public function update_item_permissions_check( $request ) {
+               $post = $this->get_post( $request['id'] );
+               if ( is_wp_error( $post ) ) {
+                       return $post;
+               }
 
-               $post = get_post( $request['id'] );
                $post_type = get_post_type_object( $this->post_type );
 
                if ( $post && ! $this->check_update_permission( $post ) ) {
@@ -620,11 +658,9 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
         * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
         */
        public function update_item( $request ) {
-               $id   = (int) $request['id'];
-               $post = get_post( $id );
-
-               if ( empty( $id ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
-                       return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
+               $valid_check = $this->get_post( $request['id'] );
+               if ( is_wp_error( $valid_check ) ) {
+                       return $valid_check;
                }
 
                $post = $this->prepare_item_for_database( $request );
@@ -710,8 +746,10 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
         * @return true|WP_Error True if the request has access to delete the item, WP_Error object otherwise.
         */
        public function delete_item_permissions_check( $request ) {
-
-               $post = get_post( $request['id'] );
+               $post = $this->get_post( $request['id'] );
+               if ( is_wp_error( $post ) ) {
+                       return $post;
+               }
 
                if ( $post && ! $this->check_delete_permission( $post ) ) {
                        return new WP_Error( 'rest_cannot_delete', __( 'Sorry, you are not allowed to delete this post.' ), array( 'status' => rest_authorization_required_code() ) );
@@ -730,15 +768,14 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
         * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
         */
        public function delete_item( $request ) {
-               $id    = (int) $request['id'];
-               $force = (bool) $request['force'];
-
-               $post = get_post( $id );
-
-               if ( empty( $id ) || empty( $post->ID ) || $this->post_type !== $post->post_type ) {
-                       return new WP_Error( 'rest_post_invalid_id', __( 'Invalid post ID.' ), array( 'status' => 404 ) );
+               $post = $this->get_post( $request['id'] );
+               if ( is_wp_error( $post ) ) {
+                       return $post;
                }
 
+               $id    = $post->ID;
+               $force = (bool) $request['force'];
+
                $supports_trash = ( EMPTY_TRASH_DAYS > 0 );
 
                if ( 'attachment' === $post->post_type ) {
@@ -897,7 +934,12 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
 
                // Post ID.
                if ( isset( $request['id'] ) ) {
-                       $prepared_post->ID = absint( $request['id'] );
+                       $existing_post = $this->get_post( $request['id'] );
+                       if ( is_wp_error( $existing_post ) ) {
+                               return $existing_post;
+                       }
+
+                       $prepared_post->ID = $existing_post->ID;
                }
 
                $schema = $this->get_item_schema();
@@ -1919,10 +1961,16 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
 
                                case 'post-formats':
                                        $supports_formats = get_theme_support( 'post-formats' );
+
+                                       // Force to an array. Supports formats can return true even if empty in some cases.
+                                       $supports_formats = is_array( $supports_formats ) ? array_values( $supports_formats[0] ) : array();
+
+                                       $supported_formats = array_merge( array( 'standard' ), $supports_formats );
+
                                        $schema['properties']['format'] = array(
                                                'description' => __( 'The format for the object.' ),
                                                'type'        => 'string',
-                                               'enum'        => array_merge( array( 'standard' ), $supports_formats ? array_values( $supports_formats[0] ) : array() ),
+                                               'enum'        => $supported_formats,
                                                'context'     => array( 'view', 'edit' ),
                                        );
                                        break;
@@ -1975,18 +2023,18 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
         * @return array Collection parameters.
         */
        public function get_collection_params() {
-               $params = parent::get_collection_params();
+               $query_params = parent::get_collection_params();
 
-               $params['context']['default'] = 'view';
+               $query_params['context']['default'] = 'view';
 
-               $params['after'] = array(
+               $query_params['after'] = array(
                        'description'        => __( 'Limit response to posts published after a given ISO8601 compliant date.' ),
                        'type'               => 'string',
                        'format'             => 'date-time',
                );
 
                if ( post_type_supports( $this->post_type, 'author' ) ) {
-                       $params['author'] = array(
+                       $query_params['author'] = array(
                                'description'         => __( 'Limit result set to posts assigned to specific authors.' ),
                                'type'                => 'array',
                                'items'               => array(
@@ -1994,7 +2042,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
                                ),
                                'default'             => array(),
                        );
-                       $params['author_exclude'] = array(
+                       $query_params['author_exclude'] = array(
                                'description'         => __( 'Ensure result set excludes posts assigned to specific authors.' ),
                                'type'                => 'array',
                                'items'               => array(
@@ -2004,13 +2052,13 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
                        );
                }
 
-               $params['before'] = array(
+               $query_params['before'] = array(
                        'description'        => __( 'Limit response to posts published before a given ISO8601 compliant date.' ),
                        'type'               => 'string',
                        'format'             => 'date-time',
                );
 
-               $params['exclude'] = array(
+               $query_params['exclude'] = array(
                        'description'        => __( 'Ensure result set excludes specific IDs.' ),
                        'type'               => 'array',
                        'items'              => array(
@@ -2019,7 +2067,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
                        'default'            => array(),
                );
 
-               $params['include'] = array(
+               $query_params['include'] = array(
                        'description'        => __( 'Limit result set to specific IDs.' ),
                        'type'               => 'array',
                        'items'              => array(
@@ -2029,25 +2077,25 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
                );
 
                if ( 'page' === $this->post_type || post_type_supports( $this->post_type, 'page-attributes' ) ) {
-                       $params['menu_order'] = array(
+                       $query_params['menu_order'] = array(
                                'description'        => __( 'Limit result set to posts with a specific menu_order value.' ),
                                'type'               => 'integer',
                        );
                }
 
-               $params['offset'] = array(
+               $query_params['offset'] = array(
                        'description'        => __( 'Offset the result set by a specific number of items.' ),
                        'type'               => 'integer',
                );
 
-               $params['order'] = array(
+               $query_params['order'] = array(
                        'description'        => __( 'Order sort attribute ascending or descending.' ),
                        'type'               => 'string',
                        'default'            => 'desc',
                        'enum'               => array( 'asc', 'desc' ),
                );
 
-               $params['orderby'] = array(
+               $query_params['orderby'] = array(
                        'description'        => __( 'Sort collection by object attribute.' ),
                        'type'               => 'string',
                        'default'            => 'date',
@@ -2062,13 +2110,13 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
                );
 
                if ( 'page' === $this->post_type || post_type_supports( $this->post_type, 'page-attributes' ) ) {
-                       $params['orderby']['enum'][] = 'menu_order';
+                       $query_params['orderby']['enum'][] = 'menu_order';
                }
 
-               $post_type_obj = get_post_type_object( $this->post_type );
+               $post_type = get_post_type_object( $this->post_type );
 
-               if ( $post_type_obj->hierarchical || 'attachment' === $this->post_type ) {
-                       $params['parent'] = array(
+               if ( $post_type->hierarchical || 'attachment' === $this->post_type ) {
+                       $query_params['parent'] = array(
                                'description'       => __( 'Limit result set to those of particular parent IDs.' ),
                                'type'              => 'array',
                                'items'             => array(
@@ -2076,7 +2124,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
                                ),
                                'default'           => array(),
                        );
-                       $params['parent_exclude'] = array(
+                       $query_params['parent_exclude'] = array(
                                'description'       => __( 'Limit result set to all items except those of a particular parent ID.' ),
                                'type'              => 'array',
                                'items'             => array(
@@ -2086,7 +2134,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
                        );
                }
 
-               $params['slug'] = array(
+               $query_params['slug'] = array(
                        'description'       => __( 'Limit result set to posts with one or more specific slugs.' ),
                        'type'              => 'array',
                        'items'             => array(
@@ -2095,7 +2143,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
                        'sanitize_callback' => 'wp_parse_slug_list',
                );
 
-               $params['status'] = array(
+               $query_params['status'] = array(
                        'default'           => 'publish',
                        'description'       => __( 'Limit result set to posts assigned one or more statuses.' ),
                        'type'              => 'array',
@@ -2111,7 +2159,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
                foreach ( $taxonomies as $taxonomy ) {
                        $base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;
 
-                       $params[ $base ] = array(
+                       $query_params[ $base ] = array(
                                /* translators: %s: taxonomy name */
                                'description'       => sprintf( __( 'Limit result set to all items that have the specified term assigned in the %s taxonomy.' ), $base ),
                                'type'              => 'array',
@@ -2121,7 +2169,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
                                'default'           => array(),
                        );
 
-                       $params[ $base . '_exclude' ] = array(
+                       $query_params[ $base . '_exclude' ] = array(
                                /* translators: %s: taxonomy name */
                                'description' => sprintf( __( 'Limit result set to all items except those that have the specified term assigned in the %s taxonomy.' ), $base ),
                                'type'        => 'array',
@@ -2133,7 +2181,7 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
                }
 
                if ( 'post' === $this->post_type ) {
-                       $params['sticky'] = array(
+                       $query_params['sticky'] = array(
                                'description'       => __( 'Limit result set to items that are sticky.' ),
                                'type'              => 'boolean',
                        );
@@ -2151,10 +2199,10 @@ class WP_REST_Posts_Controller extends WP_REST_Controller {
                 *
                 * @since 4.7.0
                 *
-                * @param $params JSON Schema-formatted collection parameters.
-                * @param WP_Post_Type $post_type_obj Post type object.
+                * @param array        $query_params JSON Schema-formatted collection parameters.
+                * @param WP_Post_Type $post_type    Post type object.
                 */
-               return apply_filters( "rest_{$this->post_type}_collection_params", $params, $post_type_obj );
+               return apply_filters( "rest_{$this->post_type}_collection_params", $query_params, $post_type );
        }
 
        /**