-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Expose theme_supports data through a minimial theme controller #10518
Changes from 8 commits
049f30f
9187617
e013653
08eb03d
5b5675d
3af33f2
f18a663
7a1c75e
06fb8cf
2ff2fb4
2bbd6ba
f593169
6e8abc1
c972f4a
d3dbb6f
9693640
b1fe1b7
f7cd0a5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,233 @@ | ||
<?php | ||
/** | ||
* REST API: WP_REST_Themes_Controller class | ||
* | ||
* @package WordPress | ||
* @subpackage REST_API | ||
* @since 5.0.0 | ||
*/ | ||
|
||
/** | ||
* Core class used to manage themes via the REST API. | ||
* | ||
* @since 5.0.0 | ||
* | ||
* @see WP_REST_Controller | ||
*/ | ||
class WP_REST_Themes_Controller extends WP_REST_Controller { | ||
|
||
/** | ||
* Constructor. | ||
* | ||
* @since 5.0.0 | ||
*/ | ||
public function __construct() { | ||
$this->namespace = 'wp/v2'; | ||
$this->rest_base = 'themes'; | ||
} | ||
|
||
/** | ||
* Registers the routes for the objects of the controller. | ||
* | ||
* @since 5.0.0 | ||
* | ||
* @see register_rest_route() | ||
*/ | ||
public function register_routes() { | ||
register_rest_route( | ||
$this->namespace, | ||
'/' . $this->rest_base . '/active', | ||
array( | ||
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' => 'edit' ) ), | ||
), | ||
), | ||
'schema' => array( $this, 'get_item_schema' ), | ||
) | ||
); | ||
} | ||
|
||
/** | ||
* Checks if a given request has access to read the theme. | ||
* | ||
* @since 5.0.0 | ||
* | ||
* @param WP_REST_Request $request Full details about the request. | ||
* @return true|WP_Error True if the request has read access for the item, otherwise WP_Error object. | ||
*/ | ||
public function get_item_permissions_check( $request ) { | ||
if ( ! is_user_logged_in() || ! current_user_can( 'edit_posts' ) ) { | ||
return new WP_Error( 'rest_user_cannot_view', __( 'Sorry, you are not allowed to view themes.', 'gutenberg' ), array( 'status' => rest_authorization_required_code() ) ); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
/** | ||
* Retrieves the active theme. | ||
* | ||
* @since 5.0.0 | ||
* | ||
* @param WP_REST_Request $request Full details about the request. | ||
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. | ||
*/ | ||
public function get_item( $request ) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Per the comment about |
||
$theme = wp_get_theme(); | ||
|
||
$response = $this->prepare_item_for_response( $theme, $request ); | ||
$response = rest_ensure_response( $response ); | ||
|
||
return $response; | ||
} | ||
|
||
/** | ||
* Prepares a single theme output for response. | ||
* | ||
* @since 5.0.0 | ||
* | ||
* @param WP_Theme $theme Theme object. | ||
* @param WP_REST_Request $request Request object. | ||
* @return WP_REST_Response Response object. | ||
*/ | ||
public function prepare_item_for_response( $theme, $request ) { | ||
$data = array(); | ||
$fields = $this->get_fields_for_response( $request ); | ||
|
||
if ( in_array( 'name', $fields, true ) ) { | ||
$data['name'] = $theme->__get( 'name' ); | ||
} | ||
|
||
if ( in_array( 'stylesheet', $fields, true ) ) { | ||
$data['stylesheet'] = $theme->__get( 'stylesheet' ); | ||
} | ||
|
||
if ( in_array( 'version', $fields, true ) ) { | ||
$data['version'] = $theme->__get( 'version' ); | ||
} | ||
|
||
if ( in_array( 'template', $fields, true ) ) { | ||
$data['template'] = $theme->__get( 'template' ); | ||
} | ||
|
||
if ( in_array( 'theme_supports', $fields, true ) ) { | ||
$formats = get_theme_support( 'post-formats' ); | ||
$formats = is_array( $formats ) ? array_values( $formats[0] ) : array(); | ||
$formats = array_merge( array( 'standard' ), $formats ); | ||
$data['theme_supports']['formats'] = $formats; | ||
|
||
$post_thumbnails = get_theme_support( 'post-thumbnails' ); | ||
|
||
if ( $post_thumbnails ) { | ||
desrosj marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// $post_thumbnails can contain a nested array of post types. | ||
// e.g. array( array( 'post', 'page' ) ). | ||
$data['theme_supports']['post-thumbnails'] = is_array( $post_thumbnails ) ? $post_thumbnails[0] : true; | ||
} | ||
} | ||
|
||
$context = ! empty( $request['context'] ) ? $request['context'] : 'edit'; | ||
|
||
$data = $this->add_additional_fields_to_object( $data, $request ); | ||
$data = $this->filter_response_by_context( $data, $context ); | ||
|
||
// Wrap the data in a response object. | ||
$response = rest_ensure_response( $data ); | ||
|
||
$response->add_links( $this->prepare_links( $theme ) ); | ||
|
||
/** | ||
* Filters theme data returned from the REST API. | ||
* | ||
* @since 5.0.0 | ||
* | ||
* @param WP_REST_Response $response The response object. | ||
* @param WP_Theme $theme Theme object used to create response. | ||
* @param WP_REST_Request $request Request object. | ||
*/ | ||
return apply_filters( 'rest_prepare_theme', $response, $theme, $request ); | ||
} | ||
|
||
/** | ||
* Prepares links for the theme request. | ||
* | ||
* @since 5.0.0 | ||
* | ||
* @param WP_Theme $theme Theme object. | ||
* @return array Links for the given theme. | ||
*/ | ||
protected function prepare_links( $theme ) { | ||
$links = array( | ||
'self' => array( | ||
'href' => rest_url( sprintf( '%s/%s/active', $this->namespace, $this->rest_base ) ), | ||
), | ||
); | ||
|
||
return $links; | ||
} | ||
|
||
/** | ||
* Retrieves the theme's schema, conforming to JSON Schema. | ||
* | ||
* @since 5.0.0 | ||
* | ||
* @return array Item schema data. | ||
*/ | ||
public function get_item_schema() { | ||
$schema = array( | ||
'$schema' => 'http://json-schema.org/draft-04/schema#', | ||
'title' => 'theme', | ||
'type' => 'object', | ||
'properties' => array( | ||
'name' => array( | ||
'description' => __( 'Theme name', 'gutenberg' ), | ||
'type' => 'string', | ||
'context' => array( 'edit' ), | ||
'readonly' => true, | ||
), | ||
'stylesheet' => array( | ||
'description' => __( 'The directory name of the theme.', 'gutenberg' ), | ||
'type' => 'string', | ||
'context' => array( 'edit' ), | ||
'readonly' => true, | ||
), | ||
'version' => array( | ||
'description' => __( 'Theme version', 'gutenberg' ), | ||
'type' => 'string', | ||
'context' => array( 'edit' ), | ||
'readonly' => true, | ||
), | ||
'template' => array( | ||
'description' => __( 'The theme template', 'gutenberg' ), | ||
'type' => 'string', | ||
'context' => array( 'edit' ), | ||
'readonly' => true, | ||
), | ||
'theme_supports' => array( | ||
'description' => __( 'A list of features this theme supports.', 'gutenberg' ), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Language tweak: |
||
'type' => 'array', | ||
'context' => array( 'edit' ), | ||
'readonly' => true, | ||
'properties' => array( | ||
'formats' => array( | ||
'description' => __( 'Post formats supported.', 'gutenberg' ), | ||
'type' => 'array', | ||
'context' => array( 'edit' ), | ||
'readonly' => true, | ||
), | ||
'post-thumbnails' => array( | ||
'description' => __( 'Whether the theme supports post thumbnails.', 'gutenberg' ), | ||
'type' => array( 'array', 'bool' ), | ||
'context' => array( 'edit' ), | ||
'readonly' => true, | ||
), | ||
), | ||
), | ||
), | ||
); | ||
danielbachhuber marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
return $this->add_additional_fields_schema( $schema ); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ | |
require dirname( __FILE__ ) . '/class-wp-rest-blocks-controller.php'; | ||
require dirname( __FILE__ ) . '/class-wp-rest-autosaves-controller.php'; | ||
require dirname( __FILE__ ) . '/class-wp-rest-block-renderer-controller.php'; | ||
require dirname( __FILE__ ) . '/class-wp-rest-themes-controller.php'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We need to wrap this with a |
||
require dirname( __FILE__ ) . '/class-wp-rest-search-controller.php'; | ||
require dirname( __FILE__ ) . '/class-wp-rest-search-handler.php'; | ||
require dirname( __FILE__ ) . '/class-wp-rest-post-search-handler.php'; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,7 +14,7 @@ import { addQueryArgs } from '@wordpress/url'; | |
import { | ||
receiveUserQuery, | ||
receiveEntityRecords, | ||
receiveThemeSupportsFromIndex, | ||
receiveThemeSupports, | ||
receiveEmbedPreview, | ||
} from './actions'; | ||
import { getKindEntities } from './entities'; | ||
|
@@ -70,8 +70,8 @@ export function* getEntityRecords( kind, name, query = {} ) { | |
* Requests theme supports data from the index. | ||
*/ | ||
export function* getThemeSupports() { | ||
const index = yield apiFetch( { path: '/' } ); | ||
yield receiveThemeSupportsFromIndex( index ); | ||
const currentTheme = yield apiFetch( { path: '/wp/v2/themes/active' } ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we can preload this API endpoint here https://github.com/WordPress/gutenberg/blob/master/lib/client-assets.php#L1303 ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added this endpoint to that list. It correctly prevents the Featured Image editor from flashing onto the screen like it was. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool, do we need to pass the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That I am not sure of. The default context is now There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Context was removed entirely per the discussion in #core-restapi. |
||
yield receiveThemeSupports( currentTheme.theme_supports ); | ||
} | ||
|
||
/** | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per discussion in Slack, we should use the following structure for querying this information:
/wp/v2/themes?status=active
will return an array containing the object representing the capabilities of the active theme.status
will be anenum
parameter with one option,active
, and that parameter will be required./active
,/~active
, etc, which has unfolded mostly in slack). Any of these approaches might be found to be limiting down the road as we add support for theme management, multi-site, etcetera, while a query parameter likestatus
is unlikely to conflict with any future plans.Long-term I imagine we'd update the active theme by PUT'ing a theme slug to the settings endpoint, or a hypothetical new site endpoint. Figuring all that out is out of scope and not necessary for Gutenberg in terms of 5.0.