103 */ |
113 */ |
104 public function prepare_item_for_response( $theme, $request ) { |
114 public function prepare_item_for_response( $theme, $request ) { |
105 $data = array(); |
115 $data = array(); |
106 $fields = $this->get_fields_for_response( $request ); |
116 $fields = $this->get_fields_for_response( $request ); |
107 |
117 |
108 if ( in_array( 'theme_supports', $fields, true ) ) { |
118 if ( rest_is_field_included( 'stylesheet', $fields ) ) { |
109 $formats = get_theme_support( 'post-formats' ); |
119 $data['stylesheet'] = $theme->get_stylesheet(); |
110 $formats = is_array( $formats ) ? array_values( $formats[0] ) : array(); |
120 } |
111 $formats = array_merge( array( 'standard' ), $formats ); |
121 |
112 $data['theme_supports']['formats'] = $formats; |
122 if ( rest_is_field_included( 'template', $fields ) ) { |
113 |
123 /** |
114 $data['theme_supports']['post-thumbnails'] = false; |
124 * Use the get_template() method, not the 'Template' header, for finding the template. |
115 $data['theme_supports']['responsive-embeds'] = (bool) get_theme_support( 'responsive-embeds' ); |
125 * The 'Template' header is only good for what was written in the style.css, while |
116 $post_thumbnails = get_theme_support( 'post-thumbnails' ); |
126 * get_template() takes into account where WordPress actually located the theme and |
117 |
127 * whether it is actually valid. |
118 if ( $post_thumbnails ) { |
128 */ |
119 // $post_thumbnails can contain a nested array of post types. |
129 $data['template'] = $theme->get_template(); |
120 // e.g. array( array( 'post', 'page' ) ). |
130 } |
121 $data['theme_supports']['post-thumbnails'] = is_array( $post_thumbnails ) ? $post_thumbnails[0] : true; |
131 |
|
132 $plain_field_mappings = array( |
|
133 'requires_php' => 'RequiresPHP', |
|
134 'requires_wp' => 'RequiresWP', |
|
135 'textdomain' => 'TextDomain', |
|
136 'version' => 'Version', |
|
137 ); |
|
138 |
|
139 foreach ( $plain_field_mappings as $field => $header ) { |
|
140 if ( rest_is_field_included( $field, $fields ) ) { |
|
141 $data[ $field ] = $theme->get( $header ); |
|
142 } |
|
143 } |
|
144 |
|
145 if ( rest_is_field_included( 'screenshot', $fields ) ) { |
|
146 // Using $theme->get_screenshot() with no args to get absolute URL. |
|
147 $data['screenshot'] = $theme->get_screenshot() ? $theme->get_screenshot() : ''; |
|
148 } |
|
149 |
|
150 $rich_field_mappings = array( |
|
151 'author' => 'Author', |
|
152 'author_uri' => 'AuthorURI', |
|
153 'description' => 'Description', |
|
154 'name' => 'Name', |
|
155 'tags' => 'Tags', |
|
156 'theme_uri' => 'ThemeURI', |
|
157 ); |
|
158 |
|
159 foreach ( $rich_field_mappings as $field => $header ) { |
|
160 if ( rest_is_field_included( "{$field}.raw", $fields ) ) { |
|
161 $data[ $field ]['raw'] = $theme->display( $header, false, true ); |
|
162 } |
|
163 |
|
164 if ( rest_is_field_included( "{$field}.rendered", $fields ) ) { |
|
165 $data[ $field ]['rendered'] = $theme->display( $header ); |
|
166 } |
|
167 } |
|
168 |
|
169 if ( rest_is_field_included( 'theme_supports', $fields ) ) { |
|
170 foreach ( get_registered_theme_features() as $feature => $config ) { |
|
171 if ( ! is_array( $config['show_in_rest'] ) ) { |
|
172 continue; |
|
173 } |
|
174 |
|
175 $name = $config['show_in_rest']['name']; |
|
176 |
|
177 if ( ! rest_is_field_included( "theme_supports.{$name}", $fields ) ) { |
|
178 continue; |
|
179 } |
|
180 |
|
181 if ( ! current_theme_supports( $feature ) ) { |
|
182 $data['theme_supports'][ $name ] = $config['show_in_rest']['schema']['default']; |
|
183 continue; |
|
184 } |
|
185 |
|
186 $support = get_theme_support( $feature ); |
|
187 |
|
188 if ( isset( $config['show_in_rest']['prepare_callback'] ) ) { |
|
189 $prepare = $config['show_in_rest']['prepare_callback']; |
|
190 } else { |
|
191 $prepare = array( $this, 'prepare_theme_support' ); |
|
192 } |
|
193 |
|
194 $prepared = $prepare( $support, $config, $feature, $request ); |
|
195 |
|
196 if ( is_wp_error( $prepared ) ) { |
|
197 continue; |
|
198 } |
|
199 |
|
200 $data['theme_supports'][ $name ] = $prepared; |
122 } |
201 } |
123 } |
202 } |
124 |
203 |
125 $data = $this->add_additional_fields_to_object( $data, $request ); |
204 $data = $this->add_additional_fields_to_object( $data, $request ); |
126 |
205 |
138 */ |
217 */ |
139 return apply_filters( 'rest_prepare_theme', $response, $theme, $request ); |
218 return apply_filters( 'rest_prepare_theme', $response, $theme, $request ); |
140 } |
219 } |
141 |
220 |
142 /** |
221 /** |
|
222 * Prepares the theme support value for inclusion in the REST API response. |
|
223 * |
|
224 * @since 5.5.0 |
|
225 * |
|
226 * @param mixed $support The raw value from get_theme_support(). |
|
227 * @param array $args The feature's registration args. |
|
228 * @param string $feature The feature name. |
|
229 * @param WP_REST_Request $request The request object. |
|
230 * @return mixed The prepared support value. |
|
231 */ |
|
232 protected function prepare_theme_support( $support, $args, $feature, $request ) { |
|
233 $schema = $args['show_in_rest']['schema']; |
|
234 |
|
235 if ( 'boolean' === $schema['type'] ) { |
|
236 return true; |
|
237 } |
|
238 |
|
239 if ( is_array( $support ) && ! $args['variadic'] ) { |
|
240 $support = $support[0]; |
|
241 } |
|
242 |
|
243 return rest_sanitize_value_from_schema( $support, $schema ); |
|
244 } |
|
245 |
|
246 /** |
143 * Retrieves the theme's schema, conforming to JSON Schema. |
247 * Retrieves the theme's schema, conforming to JSON Schema. |
144 * |
248 * |
145 * @since 5.0.0 |
249 * @since 5.0.0 |
146 * |
250 * |
147 * @return array Item schema data. |
251 * @return array Item schema data. |
148 */ |
252 */ |
149 public function get_item_schema() { |
253 public function get_item_schema() { |
|
254 if ( $this->schema ) { |
|
255 return $this->add_additional_fields_schema( $this->schema ); |
|
256 } |
|
257 |
150 $schema = array( |
258 $schema = array( |
151 '$schema' => 'http://json-schema.org/draft-04/schema#', |
259 '$schema' => 'http://json-schema.org/draft-04/schema#', |
152 'title' => 'theme', |
260 'title' => 'theme', |
153 'type' => 'object', |
261 'type' => 'object', |
154 'properties' => array( |
262 'properties' => array( |
|
263 'stylesheet' => array( |
|
264 'description' => __( 'The theme\'s stylesheet. This uniquely identifies the theme.' ), |
|
265 'type' => 'string', |
|
266 'readonly' => true, |
|
267 ), |
|
268 'template' => array( |
|
269 'description' => __( 'The theme\'s template. If this is a child theme, this refers to the parent theme, otherwise this is the same as the theme\'s stylesheet.' ), |
|
270 'type' => 'string', |
|
271 'readonly' => true, |
|
272 ), |
|
273 'author' => array( |
|
274 'description' => __( 'The theme author.' ), |
|
275 'type' => 'object', |
|
276 'readonly' => true, |
|
277 'properties' => array( |
|
278 'raw' => array( |
|
279 'description' => __( 'The theme author\'s name, as found in the theme header.' ), |
|
280 'type' => 'string', |
|
281 ), |
|
282 'rendered' => array( |
|
283 'description' => __( 'HTML for the theme author, transformed for display.' ), |
|
284 'type' => 'string', |
|
285 ), |
|
286 ), |
|
287 ), |
|
288 'author_uri' => array( |
|
289 'description' => __( 'The website of the theme author.' ), |
|
290 'type' => 'object', |
|
291 'readonly' => true, |
|
292 'properties' => array( |
|
293 'raw' => array( |
|
294 'description' => __( 'The website of the theme author, as found in the theme header.' ), |
|
295 'type' => 'string', |
|
296 'format' => 'uri', |
|
297 ), |
|
298 'rendered' => array( |
|
299 'description' => __( 'The website of the theme author, transformed for display.' ), |
|
300 'type' => 'string', |
|
301 'format' => 'uri', |
|
302 ), |
|
303 ), |
|
304 ), |
|
305 'description' => array( |
|
306 'description' => __( 'A description of the theme.' ), |
|
307 'type' => 'object', |
|
308 'readonly' => true, |
|
309 'properties' => array( |
|
310 'raw' => array( |
|
311 'description' => __( 'The theme description, as found in the theme header.' ), |
|
312 'type' => 'string', |
|
313 ), |
|
314 'rendered' => array( |
|
315 'description' => __( 'The theme description, transformed for display.' ), |
|
316 'type' => 'string', |
|
317 ), |
|
318 ), |
|
319 ), |
|
320 'name' => array( |
|
321 'description' => __( 'The name of the theme.' ), |
|
322 'type' => 'object', |
|
323 'readonly' => true, |
|
324 'properties' => array( |
|
325 'raw' => array( |
|
326 'description' => __( 'The theme name, as found in the theme header.' ), |
|
327 'type' => 'string', |
|
328 ), |
|
329 'rendered' => array( |
|
330 'description' => __( 'The theme name, transformed for display.' ), |
|
331 'type' => 'string', |
|
332 ), |
|
333 ), |
|
334 ), |
|
335 'requires_php' => array( |
|
336 'description' => __( 'The minimum PHP version required for the theme to work.' ), |
|
337 'type' => 'string', |
|
338 'readonly' => true, |
|
339 ), |
|
340 'requires_wp' => array( |
|
341 'description' => __( 'The minimum WordPress version required for the theme to work.' ), |
|
342 'type' => 'string', |
|
343 'readonly' => true, |
|
344 ), |
|
345 'screenshot' => array( |
|
346 'description' => __( 'The theme\'s screenshot URL.' ), |
|
347 'type' => 'string', |
|
348 'format' => 'uri', |
|
349 'readonly' => true, |
|
350 ), |
|
351 'tags' => array( |
|
352 'description' => __( 'Tags indicating styles and features of the theme.' ), |
|
353 'type' => 'object', |
|
354 'readonly' => true, |
|
355 'properties' => array( |
|
356 'raw' => array( |
|
357 'description' => __( 'The theme tags, as found in the theme header.' ), |
|
358 'type' => 'array', |
|
359 'items' => array( |
|
360 'type' => 'string', |
|
361 ), |
|
362 ), |
|
363 'rendered' => array( |
|
364 'description' => __( 'The theme tags, transformed for display.' ), |
|
365 'type' => 'string', |
|
366 ), |
|
367 ), |
|
368 ), |
|
369 'textdomain' => array( |
|
370 'description' => __( 'The theme\'s text domain.' ), |
|
371 'type' => 'string', |
|
372 'readonly' => true, |
|
373 ), |
155 'theme_supports' => array( |
374 'theme_supports' => array( |
156 'description' => __( 'Features supported by this theme.' ), |
375 'description' => __( 'Features supported by this theme.' ), |
157 'type' => 'array', |
376 'type' => 'object', |
158 'readonly' => true, |
377 'readonly' => true, |
159 'properties' => array( |
378 'properties' => array(), |
160 'formats' => array( |
379 ), |
161 'description' => __( 'Post formats supported.' ), |
380 'theme_uri' => array( |
162 'type' => 'array', |
381 'description' => __( 'The URI of the theme\'s webpage.' ), |
163 'readonly' => true, |
382 'type' => 'object', |
164 ), |
383 'readonly' => true, |
165 'post-thumbnails' => array( |
384 'properties' => array( |
166 'description' => __( 'Whether the theme supports post thumbnails.' ), |
385 'raw' => array( |
167 'type' => array( 'array', 'bool' ), |
386 'description' => __( 'The URI of the theme\'s webpage, as found in the theme header.' ), |
168 'readonly' => true, |
387 'type' => 'string', |
169 ), |
388 'format' => 'uri', |
170 'responsive-embeds' => array( |
389 ), |
171 'description' => __( 'Whether the theme supports responsive embedded content.' ), |
390 'rendered' => array( |
172 'type' => 'bool', |
391 'description' => __( 'The URI of the theme\'s webpage, transformed for display.' ), |
173 'readonly' => true, |
392 'type' => 'string', |
174 ), |
393 'format' => 'uri', |
175 ), |
394 ), |
|
395 ), |
|
396 ), |
|
397 'version' => array( |
|
398 'description' => __( 'The theme\'s current version.' ), |
|
399 'type' => 'string', |
|
400 'readonly' => true, |
176 ), |
401 ), |
177 ), |
402 ), |
178 ); |
403 ); |
179 |
404 |
180 return $this->add_additional_fields_schema( $schema ); |
405 foreach ( get_registered_theme_features() as $feature => $config ) { |
|
406 if ( ! is_array( $config['show_in_rest'] ) ) { |
|
407 continue; |
|
408 } |
|
409 |
|
410 $name = $config['show_in_rest']['name']; |
|
411 |
|
412 $schema['properties']['theme_supports']['properties'][ $name ] = $config['show_in_rest']['schema']; |
|
413 } |
|
414 |
|
415 $this->schema = $schema; |
|
416 |
|
417 return $this->add_additional_fields_schema( $this->schema ); |
181 } |
418 } |
182 |
419 |
183 /** |
420 /** |
184 * Retrieves the search params for the themes collection. |
421 * Retrieves the search params for the themes collection. |
185 * |
422 * |
204 /** |
441 /** |
205 * Filter collection parameters for the themes controller. |
442 * Filter collection parameters for the themes controller. |
206 * |
443 * |
207 * @since 5.0.0 |
444 * @since 5.0.0 |
208 * |
445 * |
209 * @param array $query_params JSON Schema-formatted collection parameters. |
446 * @param array $query_params JSON Schema-formatted collection parameters. |
210 */ |
447 */ |
211 return apply_filters( 'rest_themes_collection_params', $query_params ); |
448 return apply_filters( 'rest_themes_collection_params', $query_params ); |
212 } |
449 } |
213 |
450 |
214 /** |
451 /** |
215 * Sanitizes and validates the list of theme status. |
452 * Sanitizes and validates the list of theme status. |
216 * |
453 * |
217 * @since 5.0.0 |
454 * @since 5.0.0 |
218 * |
455 * |
219 * @param string|array $statuses One or more theme statuses. |
456 * @param string|array $statuses One or more theme statuses. |
220 * @param WP_REST_Request $request Full details about the request. |
457 * @param WP_REST_Request $request Full details about the request. |
221 * @param string $parameter Additional parameter to pass to validation. |
458 * @param string $parameter Additional parameter to pass to validation. |
222 * @return array|WP_Error A list of valid statuses, otherwise WP_Error object. |
459 * @return array|WP_Error A list of valid statuses, otherwise WP_Error object. |
223 */ |
460 */ |
224 public function sanitize_theme_status( $statuses, $request, $parameter ) { |
461 public function sanitize_theme_status( $statuses, $request, $parameter ) { |
225 $statuses = wp_parse_slug_list( $statuses ); |
462 $statuses = wp_parse_slug_list( $statuses ); |
226 |
463 |