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