0fe91ee4322397d2e7601be88d398d61a96b9ae4
[autoinstalls/wordpress.git] / wp-includes / rest-api / endpoints / class-wp-rest-taxonomies-controller.php
1 <?php
2 /**
3  * REST API: WP_REST_Taxonomies_Controller class
4  *
5  * @package WordPress
6  * @subpackage REST_API
7  * @since 4.7.0
8  */
9
10 /**
11  * Core class used to manage taxonomies via the REST API.
12  *
13  * @since 4.7.0
14  *
15  * @see WP_REST_Controller
16  */
17 class WP_REST_Taxonomies_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 = 'taxonomies';
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<taxonomy>[\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 taxonomies.
65          *
66          * @since 4.7.0
67          * @access public
68          *
69          * @param WP_REST_Request $request Full details about the request.
70          * @return true|WP_Error 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                         if ( ! empty( $request['type'] ) ) {
75                                 $taxonomies = get_object_taxonomies( $request['type'], 'objects' );
76                         } else {
77                                 $taxonomies = get_taxonomies( '', 'objects' );
78                         }
79                         foreach ( $taxonomies as $taxonomy ) {
80                                 if ( ! empty( $taxonomy->show_in_rest ) && current_user_can( $taxonomy->cap->manage_terms ) ) {
81                                         return true;
82                                 }
83                         }
84                         return new WP_Error( 'rest_cannot_view', __( 'Sorry, you are not allowed to manage terms in this taxonomy.' ), array( 'status' => rest_authorization_required_code() ) );
85                 }
86                 return true;
87         }
88
89         /**
90          * Retrieves all public taxonomies.
91          *
92          * @since 4.7.0
93          * @access public
94          *
95          * @param WP_REST_Request $request Full details about the request.
96          * @return WP_REST_Response Response object on success, or WP_Error object on failure.
97          */
98         public function get_items( $request ) {
99
100                 // Retrieve the list of registered collection query parameters.
101                 $registered = $this->get_collection_params();
102
103                 if ( isset( $registered['type'] ) && ! empty( $request['type'] ) ) {
104                         $taxonomies = get_object_taxonomies( $request['type'], 'objects' );
105                 } else {
106                         $taxonomies = get_taxonomies( '', 'objects' );
107                 }
108                 $data = array();
109                 foreach ( $taxonomies as $tax_type => $value ) {
110                         if ( empty( $value->show_in_rest ) || ( 'edit' === $request['context'] && ! current_user_can( $value->cap->manage_terms ) ) ) {
111                                 continue;
112                         }
113                         $tax = $this->prepare_item_for_response( $value, $request );
114                         $tax = $this->prepare_response_for_collection( $tax );
115                         $data[ $tax_type ] = $tax;
116                 }
117
118                 if ( empty( $data ) ) {
119                         // Response should still be returned as a JSON object when it is empty.
120                         $data = (object) $data;
121                 }
122
123                 return rest_ensure_response( $data );
124         }
125
126         /**
127          * Checks if a given request has access to a taxonomy.
128          *
129          * @since 4.7.0
130          * @access public
131          *
132          * @param  WP_REST_Request $request Full details about the request.
133          * @return true|WP_Error True if the request has read access for the item, otherwise false or WP_Error object.
134          */
135         public function get_item_permissions_check( $request ) {
136
137                 $tax_obj = get_taxonomy( $request['taxonomy'] );
138
139                 if ( $tax_obj ) {
140                         if ( empty( $tax_obj->show_in_rest ) ) {
141                                 return false;
142                         }
143                         if ( 'edit' === $request['context'] && ! current_user_can( $tax_obj->cap->manage_terms ) ) {
144                                 return new WP_Error( 'rest_forbidden_context', __( 'Sorry, you are not allowed to manage terms in this taxonomy.' ), array( 'status' => rest_authorization_required_code() ) );
145                         }
146                 }
147
148                 return true;
149         }
150
151         /**
152          * Retrieves a specific taxonomy.
153          *
154          * @since 4.7.0
155          * @access public
156          *
157          * @param WP_REST_Request $request Full details about the request.
158          * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
159          */
160         public function get_item( $request ) {
161                 $tax_obj = get_taxonomy( $request['taxonomy'] );
162                 if ( empty( $tax_obj ) ) {
163                         return new WP_Error( 'rest_taxonomy_invalid', __( 'Invalid taxonomy.' ), array( 'status' => 404 ) );
164                 }
165                 $data = $this->prepare_item_for_response( $tax_obj, $request );
166                 return rest_ensure_response( $data );
167         }
168
169         /**
170          * Prepares a taxonomy object for serialization.
171          *
172          * @since 4.7.0
173          * @access public
174          *
175          * @param stdClass        $taxonomy Taxonomy data.
176          * @param WP_REST_Request $request  Full details about the request.
177          * @return WP_REST_Response Response object.
178          */
179         public function prepare_item_for_response( $taxonomy, $request ) {
180                 $base = ! empty( $taxonomy->rest_base ) ? $taxonomy->rest_base : $taxonomy->name;
181                 $data = array(
182                         'name'         => $taxonomy->label,
183                         'slug'         => $taxonomy->name,
184                         'capabilities' => $taxonomy->cap,
185                         'description'  => $taxonomy->description,
186                         'labels'       => $taxonomy->labels,
187                         'types'        => $taxonomy->object_type,
188                         'show_cloud'   => $taxonomy->show_tagcloud,
189                         'hierarchical' => $taxonomy->hierarchical,
190                         'rest_base'    => $base,
191                 );
192
193                 $context = ! empty( $request['context'] ) ? $request['context'] : 'view';
194                 $data = $this->add_additional_fields_to_object( $data, $request );
195                 $data = $this->filter_response_by_context( $data, $context );
196
197                 // Wrap the data in a response object.
198                 $response = rest_ensure_response( $data );
199
200                 $response->add_links( array(
201                         'collection'                => array(
202                                 'href'                  => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ),
203                         ),
204                         'https://api.w.org/items'   => array(
205                                 'href'                  => rest_url( sprintf( 'wp/v2/%s', $base ) ),
206                         ),
207                 ) );
208
209                 /**
210                  * Filters a taxonomy returned from the REST API.
211                  *
212                  * Allows modification of the taxonomy data right before it is returned.
213                  *
214                  * @since 4.7.0
215                  *
216                  * @param WP_REST_Response $response The response object.
217                  * @param object           $item     The original taxonomy object.
218                  * @param WP_REST_Request  $request  Request used to generate the response.
219                  */
220                 return apply_filters( 'rest_prepare_taxonomy', $response, $taxonomy, $request );
221         }
222
223         /**
224          * Retrieves the taxonomy's schema, conforming to JSON Schema.
225          *
226          * @since 4.7.0
227          * @access public
228          *
229          * @return array Item schema data.
230          */
231         public function get_item_schema() {
232                 $schema = array(
233                         '$schema'              => 'http://json-schema.org/schema#',
234                         'title'                => 'taxonomy',
235                         'type'                 => 'object',
236                         'properties'           => array(
237                                 'capabilities'     => array(
238                                         'description'  => __( 'All capabilities used by the taxonomy.' ),
239                                         'type'         => 'object',
240                                         'context'      => array( 'edit' ),
241                                         'readonly'     => true,
242                                 ),
243                                 'description'      => array(
244                                         'description'  => __( 'A human-readable description of the taxonomy.' ),
245                                         'type'         => 'string',
246                                         'context'      => array( 'view', 'edit' ),
247                                         'readonly'     => true,
248                                 ),
249                                 'hierarchical'     => array(
250                                         'description'  => __( 'Whether or not the taxonomy should have children.' ),
251                                         'type'         => 'boolean',
252                                         'context'      => array( 'view', 'edit' ),
253                                         'readonly'     => true,
254                                 ),
255                                 'labels'           => array(
256                                         'description'  => __( 'Human-readable labels for the taxonomy for various contexts.' ),
257                                         'type'         => 'object',
258                                         'context'      => array( 'edit' ),
259                                         'readonly'     => true,
260                                 ),
261                                 'name'             => array(
262                                         'description'  => __( 'The title for the taxonomy.' ),
263                                         'type'         => 'string',
264                                         'context'      => array( 'view', 'edit', 'embed' ),
265                                         'readonly'     => true,
266                                 ),
267                                 'slug'             => array(
268                                         'description'  => __( 'An alphanumeric identifier for the taxonomy.' ),
269                                         'type'         => 'string',
270                                         'context'      => array( 'view', 'edit', 'embed' ),
271                                         'readonly'     => true,
272                                 ),
273                                 'show_cloud'       => array(
274                                         'description'  => __( 'Whether or not the term cloud should be displayed.' ),
275                                         'type'         => 'boolean',
276                                         'context'      => array( 'edit' ),
277                                         'readonly'     => true,
278                                 ),
279                                 'types'            => array(
280                                         'description'  => __( 'Types associated with the taxonomy.' ),
281                                         'type'         => 'array',
282                                         'items'        => array(
283                                                 'type' => 'string',
284                                         ),
285                                         'context'      => array( 'view', 'edit' ),
286                                         'readonly'     => true,
287                                 ),
288                                 'rest_base'            => array(
289                                         'description'  => __( 'REST base route for the taxonomy.' ),
290                                         'type'         => 'string',
291                                         'context'      => array( 'view', 'edit', 'embed' ),
292                                         'readonly'     => true,
293                                 ),
294                         ),
295                 );
296                 return $this->add_additional_fields_schema( $schema );
297         }
298
299         /**
300          * Retrieves the query params for collections.
301          *
302          * @since 4.7.0
303          * @access public
304          *
305          * @return array Collection parameters.
306          */
307         public function get_collection_params() {
308                 $new_params = array();
309                 $new_params['context'] = $this->get_context_param( array( 'default' => 'view' ) );
310                 $new_params['type'] = array(
311                         'description'  => __( 'Limit results to taxonomies associated with a specific post type.' ),
312                         'type'         => 'string',
313                 );
314                 return $new_params;
315         }
316
317 }