From b48dd4ed8224e07a2c008ecd86e1eed09c48fcc2 Mon Sep 17 00:00:00 2001 From: Ramon Date: Thu, 31 Oct 2024 12:48:17 +1100 Subject: [PATCH] Global styles: preload user global styles based on user caps (#66541) This commit preloads '/wp/v2/global-styles/' . $global_styles_id with a context corresponding to user caps, that is, edit for users that can edit global styles, and view for everyone else. Preloading the global styles endpoint according to role context means that admins and non admins, e.g., editors, avoid clientside requests. Co-authored-by: ramonjd Co-authored-by: ellatrix Co-authored-by: aaronrobertshaw --- backport-changelog/6.8/7681.md | 3 ++ lib/compat/wordpress-6.7/rest-api.php | 2 +- lib/compat/wordpress-6.8/preload.php | 32 +++++++++++++++++++ .../global-styles-provider/index.js | 28 +++++++++++----- 4 files changed, 56 insertions(+), 9 deletions(-) create mode 100644 backport-changelog/6.8/7681.md diff --git a/backport-changelog/6.8/7681.md b/backport-changelog/6.8/7681.md new file mode 100644 index 00000000000000..b8cffc70c68561 --- /dev/null +++ b/backport-changelog/6.8/7681.md @@ -0,0 +1,3 @@ +https://github.com/WordPress/wordpress-develop/pull/7681 + +* https://github.com/WordPress/gutenberg/pull/66541 diff --git a/lib/compat/wordpress-6.7/rest-api.php b/lib/compat/wordpress-6.7/rest-api.php index 89efdc4c4219d2..741d0ad1805e07 100644 --- a/lib/compat/wordpress-6.7/rest-api.php +++ b/lib/compat/wordpress-6.7/rest-api.php @@ -51,7 +51,6 @@ function gutenberg_block_editor_preload_paths_6_7( $paths, $context ) { } // Preload theme and global styles paths. - $excluded_paths = array(); if ( 'core/edit-site' === $context->name || 'core/edit-post' === $context->name ) { $active_theme = get_stylesheet(); $global_styles_id = WP_Theme_JSON_Resolver_Gutenberg::get_user_global_styles_post_id(); @@ -60,6 +59,7 @@ function gutenberg_block_editor_preload_paths_6_7( $paths, $context ) { $paths[] = array( '/wp/v2/global-styles/' . $global_styles_id, 'OPTIONS' ); // Remove duplicate or unnecessary global styles paths. + $excluded_paths = array(); $excluded_paths[] = '/wp/v2/global-styles/themes/' . $active_theme; $excluded_paths[] = '/wp/v2/global-styles/' . $global_styles_id; foreach ( $paths as $key => $path ) { diff --git a/lib/compat/wordpress-6.8/preload.php b/lib/compat/wordpress-6.8/preload.php index 5ba613e22033d4..0805ace4233d59 100644 --- a/lib/compat/wordpress-6.8/preload.php +++ b/lib/compat/wordpress-6.8/preload.php @@ -29,6 +29,38 @@ function gutenberg_block_editor_preload_paths_6_8( $paths, $context ) { ) ); } + + // Preload theme and global styles paths. + if ( 'core/edit-site' === $context->name || 'core/edit-post' === $context->name ) { + $global_styles_id = WP_Theme_JSON_Resolver_Gutenberg::get_user_global_styles_post_id(); + $excluded_paths = array(); + /* + * Removes any edit or view context paths originating from Core, + * or elsewhere, e.g., gutenberg_block_editor_preload_paths_6_6(). + * Aside from not preloading unnecessary contexts, it also ensures there no duplicates, + * leading to a small optimization: block_editor_rest_api_preload() does not dedupe, + * and will fire off a WP_REST_Request for every path. In the case of + * `/wp/v2/global-styles/*` this will create a new WP_Theme_JSON() instance. + */ + $excluded_paths[] = '/wp/v2/global-styles/' . $global_styles_id . '?context=view'; + // Removes any edit context path originating from gutenberg_block_editor_preload_paths_6_6(). + $excluded_paths[] = '/wp/v2/global-styles/' . $global_styles_id . '?context=edit'; + foreach ( $paths as $key => $path ) { + if ( in_array( $path, $excluded_paths, true ) ) { + unset( $paths[ $key ] ); + } + } + + /* + * Preload the global styles path with the correct context based on user caps. + * NOTE: There is an equivalent conditional check in the client-side code to fetch + * the global styles entity using the appropriate context value. + * See the call to `canUser()`, under `useGlobalStylesUserConfig()` in `packages/edit-site/src/components/use-global-styles-user-config/index.js`. + * Please ensure that the equivalent check is kept in sync with this preload path. + */ + $context = current_user_can( 'edit_theme_options' ) ? 'edit' : 'view'; + $paths[] = "/wp/v2/global-styles/$global_styles_id?context=$context"; + } return $paths; } add_filter( 'block_editor_rest_api_preload_paths', 'gutenberg_block_editor_preload_paths_6_8', 10, 2 ); diff --git a/packages/editor/src/components/global-styles-provider/index.js b/packages/editor/src/components/global-styles-provider/index.js index 3f3a3389801eb6..74fbed5f000624 100644 --- a/packages/editor/src/components/global-styles-provider/index.js +++ b/packages/editor/src/components/global-styles-provider/index.js @@ -57,11 +57,13 @@ function useGlobalStylesUserConfig() { let record; - // We want the global styles ID request to finish before triggering - // the OPTIONS request for user capabilities, otherwise it will - // fetch `/wp/v2/global-styles` instead of - // `/wp/v2/global-styles/{id}`! - // Please adjust the preloaded requests if this changes! + /* + * Ensure that the global styles ID request is complete by testing `_globalStylesId`, + * before firing off the `canUser` OPTIONS request for user capabilities, otherwise it will + * fetch `/wp/v2/global-styles` instead of `/wp/v2/global-styles/{id}`. + * NOTE: Please keep in sync any preload paths sent to `block_editor_rest_api_preload()`, + * or set using the `block_editor_rest_api_preload_paths` filter, if this changes. + */ const userCanEditGlobalStyles = _globalStylesId ? canUser( 'update', { kind: 'root', @@ -72,11 +74,21 @@ function useGlobalStylesUserConfig() { if ( _globalStylesId && - // We want the OPTIONS request for user capabilities to finish - // before getting the records, otherwise we'll fetch both! + /* + * Test that the OPTIONS request for user capabilities is complete + * before fetching the global styles entity record. + * This is to avoid fetching the global styles entity unnecessarily. + */ typeof userCanEditGlobalStyles === 'boolean' ) { - // Please adjust the preloaded requests if this changes! + /* + * Fetch the global styles entity record based on the user's capabilities. + * The default context is `edit` for users who can edit global styles. + * Otherwise, the context is `view`. + * NOTE: There is an equivalent conditional check using `current_user_can()` in the backend + * to preload the global styles entity. Please keep in sync any preload paths sent to `block_editor_rest_api_preload()`, + * or set using `block_editor_rest_api_preload_paths` filter, if this changes. + */ if ( userCanEditGlobalStyles ) { record = getEditedEntityRecord( 'root',