Skip to content
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

[Global Styles]: Add REST API endpoint to fetch variations #38124

Merged
merged 6 commits into from
Jan 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

588 changes: 588 additions & 0 deletions lib/compat/wordpress-5.9/class-wp-rest-global-styles-controller.php

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php
/**
* REST API: Gutenberg_REST_Global_Styles_Controller class
*
* @package Gutenberg
* @subpackage REST_API
*/

/**
* Base Global Styles REST API Controller.
*/
class Gutenberg_REST_Global_Styles_Controller extends WP_REST_Global_Styles_Controller {
/**
* Registers the controllers routes.
*
* @return void
*/
public function register_routes() {
// List themes global styles.
register_rest_route(
$this->namespace,
'/' . $this->rest_base . '/themes/(?P<stylesheet>[\/\s%\w\.\(\)\[\]\@_\-]+)/variations',
array(
array(
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_theme_items' ),
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should rename get_theme_items to get_theme_variations or change the endpoint to be theme-items. This all comes down to whether we want to support more things from this endpoint other than fetching the variations.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will merge this into WP_REST_Global_Styles_Controller in the future, right? In that case using get_theme_variations or get_variation_items make sense.

'permission_callback' => array( $this, 'get_theme_items_permissions_check' ),
'args' => array(
'stylesheet' => array(
'description' => __( 'The theme identifier', 'gutenberg' ),
'type' => 'string',
),
),
),
)
);

parent::register_routes();
}

/**
* Checks if a given request has access to read a single theme global styles config.
*
* @param WP_REST_Request $request Full details about the request.
* @return true|WP_Error True if the request has read access for the item, WP_Error object otherwise.
*/
public function get_theme_items_permissions_check( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
// Verify if the current user has edit_theme_options capability.
// This capability is required to edit/view/delete templates.
if ( ! current_user_can( 'edit_theme_options' ) ) {
return new WP_Error(
'rest_cannot_manage_global_styles',
__( 'Sorry, you are not allowed to access the global styles on this site.', 'gutenberg' ),
array(
'status' => rest_authorization_required_code(),
)
);
}

return true;
}

/**
* Returns the given theme global styles variations.
*
* @param WP_REST_Request $request The request instance.
*
* @return WP_REST_Response|WP_Error
*/
public function get_theme_items( $request ) {
if ( wp_get_theme()->get_stylesheet() !== $request['stylesheet'] ) {
// This endpoint only supports the active theme for now.
return new WP_Error(
'rest_theme_not_found',
__( 'Theme not found.', 'gutenberg' ),
array( 'status' => 404 )
);
}

$variations = array();
$base_directory = get_stylesheet_directory() . '/styles';
if ( is_dir( $base_directory ) ) {
$nested_files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $base_directory ) );
$nested_html_files = new RegexIterator( $nested_files, '/^.+\.json$/i', RecursiveRegexIterator::GET_MATCH );
foreach ( $nested_html_files as $path => $file ) {
$decoded_file = wp_json_file_decode( $path, array( 'associative' => true ) );
if ( is_array( $decoded_file ) ) {
$variations[] = ( new WP_Theme_JSON_Gutenberg( $decoded_file ) )->get_raw_data();
}
}
}
$response = rest_ensure_response( $variations );

return $response;
}
}
15 changes: 15 additions & 0 deletions lib/compat/wordpress-6.0/rest-api.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php
/**
* Overrides Core's wp-includes/rest-api.php and registers the new endpoint for WP 6.0.
*
* @package gutenberg
*/

/**
* Registers the Global Styles REST API routes.
*/
function gutenberg_register_global_styles_endpoints() {
$editor_settings = new Gutenberg_REST_Global_Styles_Controller();
$editor_settings->register_routes();
}
add_action( 'rest_api_init', 'gutenberg_register_global_styles_endpoints' );
4 changes: 3 additions & 1 deletion lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,13 @@ function gutenberg_is_experiment_enabled( $name ) {
require __DIR__ . '/compat/wordpress-5.9/block-template.php';
require __DIR__ . '/compat/wordpress-5.9/wp-theme-get-post-templates.php';
require __DIR__ . '/compat/wordpress-5.9/default-theme-supports.php';
require __DIR__ . '/compat/wordpress-5.9/class-gutenberg-rest-global-styles-controller.php';
require __DIR__ . '/compat/wordpress-5.9/class-wp-rest-global-styles-controller.php';
require __DIR__ . '/compat/wordpress-5.9/rest-active-global-styles.php';
require __DIR__ . '/compat/wordpress-5.9/move-theme-editor-menu-item.php';
require __DIR__ . '/compat/wordpress-6.0/post-lock.php';
require __DIR__ . '/compat/wordpress-6.0/blocks.php';
require __DIR__ . '/compat/wordpress-6.0/class-gutenberg-rest-global-styles-controller.php';
require __DIR__ . '/compat/wordpress-6.0/rest-api.php';
require __DIR__ . '/compat/experimental/blocks.php';

require __DIR__ . '/blocks.php';
Expand Down
9 changes: 0 additions & 9 deletions lib/rest-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -234,15 +234,6 @@ function gutenberg_rest_user_collection_params_has_published_posts( $query_param
}
add_filter( 'rest_user_collection_params', 'gutenberg_rest_user_collection_params_has_published_posts' );

/**
* Registers the Global Styles REST API routes.
*/
function gutenberg_register_global_styles_endpoints() {
$editor_settings = new Gutenberg_REST_Global_Styles_Controller();
$editor_settings->register_routes();
}
add_action( 'rest_api_init', 'gutenberg_register_global_styles_endpoints' );

/**
* Registers the Edit Site's Export REST API routes.
*
Expand Down
46 changes: 44 additions & 2 deletions phpunit/class-gutenberg-rest-global-styles-controller-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,25 +54,67 @@ public static function wpSetupBeforeClass( $factory ) {
);
}


public function test_register_routes() {
$routes = rest_get_server()->get_routes();
$this->assertArrayHasKey(
'/wp/v2/global-styles/(?P<id>[\/\s%\w\.\(\)\[\]\@_\-]+)',
// '/wp/v2/global-styles/(?P<id>[\/\s%\w\.\(\)\[\]\@_\-]+)',
'/wp/v2/global-styles/(?P<id>[\/\w-]+)',
$routes,
'Single global style based on the given ID route does not exist'
);
$this->assertArrayHasKey(
'/wp/v2/global-styles/themes/(?P<stylesheet>[\/\s%\w\.\(\)\[\]\@_\-]+)',
'/wp/v2/global-styles/themes/(?P<stylesheet>[^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?)',
$routes,
'Theme global styles route does not exist'
);
$this->assertArrayHasKey(
'/wp/v2/global-styles/themes/(?P<stylesheet>[\/\s%\w\.\(\)\[\]\@_\-]+)/variations',
$routes,
'Theme global styles variations route does not exist'
);
}

public function test_context_param() {
// TODO: Implement test_context_param() method.
$this->markTestIncomplete();
}

public function test_get_theme_items() {
wp_set_current_user( self::$admin_id );
$request = new WP_REST_Request( 'GET', '/wp/v2/global-styles/themes/emptytheme/variations' );
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$expected = array(
array(
'version' => 2,
'settings' => array(
'color' => array(
'palette' => array(
'theme' => array(
array(
'slug' => 'foreground',
'color' => '#3F67C6',
'name' => 'Foreground',
),
),
),
),
),
'styles' => array(
'blocks' => array(
'core/post-title' => array(
'typography' => array(
'fontWeight' => '700',
),
),
),
),
),
);
$this->assertSameSetsWithIndex( $data, $expected );
}

public function test_get_items() {
$this->markTestIncomplete();
}
Expand Down
23 changes: 23 additions & 0 deletions test/emptytheme/styles/variation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I wonder if we should try to make the variation more "meaningful". For instance add a "dark" variation to the empty theme.

Copy link
Contributor Author

@ntsekouras ntsekouras Jan 21, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can do it an a follow up to unblock the remaining functionality from landing. I'd appreciate if some theme dev could provide a minimal dark theme.json for empty theme. --cc @kjellr 🙏

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. So this would be just for the emptytheme version bundled here with Gutenberg, right? For the canonical version over in theme-experiments, I don't think adding a style makes sense since it's positioned primarily as an ultra-minimal starting point.

It doesn't even specify a color palette, so making a dark mode version of it is a bit unexpected. 😄

"version": 2,
"settings": {
"color": {
"palette": [
{
"slug": "foreground",
"color": "#3F67C6",
"name": "Foreground"
}
]
}
},
"styles": {
"blocks": {
"core/post-title": {
"typography": {
"fontWeight": "700"
}
}
}
}
}