WordPress 4.7.2
[autoinstalls/wordpress.git] / wp-includes / rest-api / endpoints / class-wp-rest-post-statuses-controller.php
1 <?php
2 /**
3  * REST API: WP_REST_Post_Statuses_Controller class
4  *
5  * @package WordPress
6  * @subpackage REST_API
7  * @since 4.7.0
8  */
9
10 /**
11  * Core class used to access post statuses via the REST API.
12  *
13  * @since 4.7.0
14  *
15  * @see WP_REST_Controller
16  */
17 class WP_REST_Post_Statuses_Controller extends WP_REST_Controller {
18
19         /**
20          * Constructor.
21          *
22          * @since 4.7.0
23          * @access public
24          */
25         public function __construct() {
26                 $this->namespace = 'wp/v2';
27                 $this->rest_base = 'statuses';
28         }
29
30         /**
31          * Registers the routes for the objects of the controller.
32          *
33          * @since 4.7.0
34          * @access public
35          *
36          * @see register_rest_route()
37          */
38         public function register_routes() {
39
40                 register_rest_route( $this->namespace, '/' . $this->rest_base, array(
41                         array(
42                                 'methods'             => WP_REST_Server::READABLE,
43                                 'callback'            => array( $this, 'get_items' ),
44                                 'permission_callback' => array( $this, 'get_items_permissions_check' ),
45                                 'args'                => $this->get_collection_params(),
46                         ),
47                         'schema' => array( $this, 'get_public_item_schema' ),
48                 ) );
49
50                 register_rest_route( $this->namespace, '/' . $this->rest_base . '/(?P<status>[\w-]+)', array(
51                         'args' => array(
52                                 'status' => array(
53                                         'description' => __( 'An alphanumeric identifier for the status.' ),
54                                         'type'        => 'string',
55                                 ),
56                         ),
57                         array(
58                                 'methods'             => WP_REST_Server::READABLE,
59                                 'callback'            => array( $this, 'get_item' ),
60                                 'permission_callback' => array( $this, 'get_item_permissions_check' ),
61                                 'args'                => array(
62                                         'context' => $this->get_context_param( array( 'default' => 'view' ) ),
63                                 ),
64                         ),
65                         'schema' => array( $this, 'get_public_item_schema' ),
66                 ) );
67         }
68
69         /**
70          * Checks whether a given request has permission to read post statuses.
71          *
72          * @since 4.7.0
73          * @access public
74          *
75          * @param WP_REST_Request $request Full details about the request.
76          * @return WP_Error|bool True if the request has read access, WP_Error object otherwise.
77          */
78         public function get_items_permissions_check( $request ) {
79                 if ( 'edit' === $request['context'] ) {
80                         $types = get_post_types( array( 'show_in_rest' => true ), 'objects' );
81
82                         foreach ( $types as $type ) {
83                                 if ( current_user_can( $type->cap->edit_posts ) ) {
84                                         return true;
85                                 }
86                         }
87                         return new WP_Error( 'rest_cannot_view', __( 'Sorry, you are not allowed to edit posts in this post type.' ), array( 'status' => rest_authorization_required_code() ) );
88                 }
89
90                 return true;
91         }
92
93         /**
94          * Retrieves all post statuses, depending on user context.
95          *
96          * @since 4.7.0
97          * @access public
98          *
99          * @param WP_REST_Request $request Full details about the request.
100          * @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure.
101          */
102         public function get_items( $request ) {
103                 $data = array();
104                 $statuses = get_post_stati( array( 'internal' => false ), 'object' );
105                 $statuses['trash'] = get_post_status_object( 'trash' );
106
107                 foreach ( $statuses as $slug => $obj ) {
108                         $ret = $this->check_read_permission( $obj );
109
110                         if ( ! $ret ) {
111                                 continue;
112                         }
113
114                         $status = $this->prepare_item_for_response( $obj, $request );
115                         $data[ $obj->name ] = $this->prepare_response_for_collection( $status );
116                 }
117
118                 return rest_ensure_response( $data );
119         }
120
121         /**
122          * Checks if a given request has access to read a post status.
123          *
124          * @since 4.7.0
125          * @access public
126          *
127          * @param WP_REST_Request $request Full details about the request.
128          * @return WP_Error|bool True if the request has read access for the item, WP_Error object otherwise.
129          */
130         public function get_item_permissions_check( $request ) {
131                 $status = get_post_status_object( $request['status'] );
132
133                 if ( empty( $status ) ) {
134                         return new WP_Error( 'rest_status_invalid', __( 'Invalid status.' ), array( 'status' => 404 ) );
135                 }
136
137                 $check = $this->check_read_permission( $status );
138
139                 if ( ! $check ) {
140                         return new WP_Error( 'rest_cannot_read_status', __( 'Cannot view status.' ), array( 'status' => rest_authorization_required_code() ) );
141                 }
142
143                 return true;
144         }
145
146         /**
147          * Checks whether a given post status should be visible.
148          *
149          * @since 4.7.0
150          * @access protected
151          *
152          * @param object $status Post status.
153          * @return bool True if the post status is visible, otherwise false.
154          */
155         protected function check_read_permission( $status ) {
156                 if ( true === $status->public ) {
157                         return true;
158                 }
159
160                 if ( false === $status->internal || 'trash' === $status->name ) {
161                         $types = get_post_types( array( 'show_in_rest' => true ), 'objects' );
162
163                         foreach ( $types as $type ) {
164                                 if ( current_user_can( $type->cap->edit_posts ) ) {
165                                         return true;
166                                 }
167                         }
168                 }
169
170                 return false;
171         }
172
173         /**
174          * Retrieves a specific post status.
175          *
176          * @since 4.7.0
177          * @access public
178          *
179          * @param WP_REST_Request $request Full details about the request.
180          * @return WP_Error|WP_REST_Response Response object on success, or WP_Error object on failure.
181          */
182         public function get_item( $request ) {
183                 $obj = get_post_status_object( $request['status'] );
184
185                 if ( empty( $obj ) ) {
186                         return new WP_Error( 'rest_status_invalid', __( 'Invalid status.' ), array( 'status' => 404 ) );
187                 }
188
189                 $data = $this->prepare_item_for_response( $obj, $request );
190
191                 return rest_ensure_response( $data );
192         }
193
194         /**
195          * Prepares a post status object for serialization.
196          *
197          * @since 4.7.0
198          * @access public
199          *
200          * @param stdClass        $status  Post status data.
201          * @param WP_REST_Request $request Full details about the request.
202          * @return WP_REST_Response Post status data.
203          */
204         public function prepare_item_for_response( $status, $request ) {
205
206                 $data = array(
207                         'name'         => $status->label,
208                         'private'      => (bool) $status->private,
209                         'protected'    => (bool) $status->protected,
210                         'public'       => (bool) $status->public,
211                         'queryable'    => (bool) $status->publicly_queryable,
212                         'show_in_list' => (bool) $status->show_in_admin_all_list,
213                         'slug'         => $status->name,
214                 );
215
216                 $context = ! empty( $request['context'] ) ? $request['context'] : 'view';
217                 $data = $this->add_additional_fields_to_object( $data, $request );
218                 $data = $this->filter_response_by_context( $data, $context );
219
220                 $response = rest_ensure_response( $data );
221
222                 if ( 'publish' === $status->name ) {
223                         $response->add_link( 'archives', rest_url( 'wp/v2/posts' ) );
224                 } else {
225                         $response->add_link( 'archives', add_query_arg( 'status', $status->name, rest_url( 'wp/v2/posts' ) ) );
226                 }
227
228                 /**
229                  * Filters a status returned from the REST API.
230                  *
231                  * Allows modification of the status data right before it is returned.
232                  *
233                  * @since 4.7.0
234                  *
235                  * @param WP_REST_Response $response The response object.
236                  * @param object           $status   The original status object.
237                  * @param WP_REST_Request  $request  Request used to generate the response.
238                  */
239                 return apply_filters( 'rest_prepare_status', $response, $status, $request );
240         }
241
242         /**
243          * Retrieves the post status' schema, conforming to JSON Schema.
244          *
245          * @since 4.7.0
246          * @access public
247          *
248          * @return array Item schema data.
249          */
250         public function get_item_schema() {
251                 $schema = array(
252                         '$schema'              => 'http://json-schema.org/schema#',
253                         'title'                => 'status',
254                         'type'                 => 'object',
255                         'properties'           => array(
256                                 'name'             => array(
257                                         'description'  => __( 'The title for the status.' ),
258                                         'type'         => 'string',
259                                         'context'      => array( 'embed', 'view', 'edit' ),
260                                         'readonly'     => true,
261                                 ),
262                                 'private'          => array(
263                                         'description'  => __( 'Whether posts with this status should be private.' ),
264                                         'type'         => 'boolean',
265                                         'context'      => array( 'edit' ),
266                                         'readonly'     => true,
267                                 ),
268                                 'protected'        => array(
269                                         'description'  => __( 'Whether posts with this status should be protected.' ),
270                                         'type'         => 'boolean',
271                                         'context'      => array( 'edit' ),
272                                         'readonly'     => true,
273                                 ),
274                                 'public'           => array(
275                                         'description'  => __( 'Whether posts of this status should be shown in the front end of the site.' ),
276                                         'type'         => 'boolean',
277                                         'context'      => array( 'view', 'edit' ),
278                                         'readonly'     => true,
279                                 ),
280                                 'queryable'        => array(
281                                         'description'  => __( 'Whether posts with this status should be publicly-queryable.' ),
282                                         'type'         => 'boolean',
283                                         'context'      => array( 'view', 'edit' ),
284                                         'readonly'     => true,
285                                 ),
286                                 'show_in_list'     => array(
287                                         'description'  => __( 'Whether to include posts in the edit listing for their post type.' ),
288                                         'type'         => 'boolean',
289                                         'context'      => array( 'edit' ),
290                                         'readonly'     => true,
291                                 ),
292                                 'slug'             => array(
293                                         'description'  => __( 'An alphanumeric identifier for the status.' ),
294                                         'type'         => 'string',
295                                         'context'      => array( 'embed', 'view', 'edit' ),
296                                         'readonly'     => true,
297                                 ),
298                         ),
299                 );
300
301                 return $this->add_additional_fields_schema( $schema );
302         }
303
304         /**
305          * Retrieves the query params for collections.
306          *
307          * @since 4.7.0
308          * @access public
309          *
310          * @return array Collection parameters.
311          */
312         public function get_collection_params() {
313                 return array(
314                         'context' => $this->get_context_param( array( 'default' => 'view' ) ),
315                 );
316         }
317
318 }