diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php index 8413627207996c..e01a3c60ce927a 100644 --- a/lib/block-supports/layout.php +++ b/lib/block-supports/layout.php @@ -138,8 +138,8 @@ function gutenberg_render_layout_support_flag( $block_content, $block ) { return $block_content; } - $block_gap = wp_get_global_settings( array( 'spacing', 'blockGap' ) ); - $default_layout = wp_get_global_settings( array( 'layout' ) ); + $block_gap = gutenberg_get_global_settings( array( 'spacing', 'blockGap' ) ); + $default_layout = gutenberg_get_global_settings( array( 'layout' ) ); $has_block_gap_support = isset( $block_gap ) ? null !== $block_gap : false; $default_block_layout = _wp_array_get( $block_type->supports, array( '__experimentalLayout', 'default' ), array() ); $used_layout = isset( $block['attrs']['layout'] ) ? $block['attrs']['layout'] : $default_block_layout; diff --git a/lib/compat/wordpress-5.9/get-global-styles-and-settings.php b/lib/compat/wordpress-5.9/get-global-styles-and-settings.php deleted file mode 100644 index 0ac1456bd2e423..00000000000000 --- a/lib/compat/wordpress-5.9/get-global-styles-and-settings.php +++ /dev/null @@ -1,194 +0,0 @@ -get_settings(); - - return _wp_array_get( $settings, $path, $settings ); - } -} - -if ( ! function_exists( 'wp_get_global_styles' ) ) { - /** - * Function to get the styles resulting of merging core, theme, and user data. - * - * @param array $path Path to the specific style to retrieve. Optional. - * If empty, will return all styles. - * @param array $context { - * Metadata to know where to retrieve the $path from. Optional. - * - * @type string $block_name Which block to retrieve the styles from. - * If empty, it'll return the styles for the global context. - * @type string $origin Which origin to take data from. - * Valid values are 'all' (core, theme, and user) or 'base' (core and theme). - * If empty or unknown, 'all' is used. - * } - * - * @return array The styles to retrieve. - */ - function wp_get_global_styles( $path = array(), $context = array() ) { - if ( ! empty( $context['block_name'] ) ) { - $path = array_merge( array( 'blocks', $context['block_name'] ), $path ); - } - - $origin = 'custom'; - if ( isset( $context['origin'] ) && 'base' === $context['origin'] ) { - $origin = 'theme'; - } - - $styles = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data( $origin )->get_raw_data()['styles']; - - return _wp_array_get( $styles, $path, $styles ); - } -} - -if ( ! function_exists( 'wp_get_global_stylesheet' ) ) { - /** - * Returns the stylesheet resulting of merging core, theme, and user data. - * - * @param array $types Types of styles to load. Optional. - * It accepts 'variables', 'styles', 'presets' as values. - * If empty, it'll load all for themes with theme.json support - * and only [ 'variables', 'presets' ] for themes without theme.json support. - * - * @return string Stylesheet. - */ - function wp_get_global_stylesheet( $types = array() ) { - // Return cached value if it can be used and exists. - // It's cached by theme to make sure that theme switching clears the cache. - $can_use_cached = ( - ( empty( $types ) ) && - ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) && - ( ! defined( 'SCRIPT_DEBUG' ) || ! SCRIPT_DEBUG ) && - ( ! defined( 'REST_REQUEST' ) || ! REST_REQUEST ) && - ! is_admin() - ); - $transient_name = 'gutenberg_global_styles_' . get_stylesheet(); - if ( $can_use_cached ) { - $cached = get_transient( $transient_name ); - if ( $cached ) { - return $cached; - } - } - - $tree = WP_Theme_JSON_Resolver::get_merged_data(); - - $supports_theme_json = WP_Theme_JSON_Resolver::theme_has_support(); - if ( empty( $types ) && ! $supports_theme_json ) { - $types = array( 'variables', 'presets' ); - } elseif ( empty( $types ) ) { - $types = array( 'variables', 'styles', 'presets' ); - } - - /* - * If variables are part of the stylesheet, - * we add them for all origins (default, theme, user). - * This is so themes without a theme.json still work as before 5.9: - * they can override the default presets. - * See https://core.trac.wordpress.org/ticket/54782 - */ - $styles_variables = ''; - if ( in_array( 'variables', $types, true ) ) { - $styles_variables = $tree->get_stylesheet( array( 'variables' ) ); - $types = array_diff( $types, array( 'variables' ) ); - } - - /* - * For the remaining types (presets, styles), we do consider origins: - * - * - themes without theme.json: only the classes for the presets defined by core - * - themes with theme.json: the presets and styles classes, both from core and the theme - */ - $styles_rest = ''; - if ( ! empty( $types ) ) { - $origins = array( 'default', 'theme', 'custom' ); - if ( ! $supports_theme_json ) { - $origins = array( 'default' ); - } - $styles_rest = $tree->get_stylesheet( $types, $origins ); - } - - $stylesheet = $styles_variables . $styles_rest; - - if ( $can_use_cached ) { - // Cache for a minute. - // This cache doesn't need to be any longer, we only want to avoid spikes on high-traffic sites. - set_transient( $transient_name, $stylesheet, MINUTE_IN_SECONDS ); - } - - return $stylesheet; - } -} - -if ( ! function_exists( 'wp_get_global_styles_svg_filters' ) ) { - /** - * Returns a string containing the SVGs to be referenced as filters (duotone). - * - * @return string - */ - function wp_get_global_styles_svg_filters() { - // Return cached value if it can be used and exists. - // It's cached by theme to make sure that theme switching clears the cache. - $transient_name = 'gutenberg_global_styles_svg_filters_' . get_stylesheet(); - $can_use_cached = ( - ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) && - ( ! defined( 'SCRIPT_DEBUG' ) || ! SCRIPT_DEBUG ) && - ( ! defined( 'REST_REQUEST' ) || ! REST_REQUEST ) && - ! is_admin() - ); - if ( $can_use_cached ) { - $cached = get_transient( $transient_name ); - if ( $cached ) { - return $cached; - } - } - - $supports_theme_json = WP_Theme_JSON_Resolver_Gutenberg::theme_has_support(); - - $origins = array( 'default', 'theme', 'custom' ); - if ( ! $supports_theme_json ) { - $origins = array( 'default' ); - } - - $tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data(); - $svgs = $tree->get_svg_filters( $origins ); - - if ( $can_use_cached ) { - // Cache for a minute, same as gutenberg_get_global_stylesheet. - set_transient( $transient_name, $svgs, MINUTE_IN_SECONDS ); - } - - return $svgs; - } -} diff --git a/lib/compat/wordpress-5.9/global-styles-css-custom-properties.php b/lib/compat/wordpress-5.9/global-styles-css-custom-properties.php index 990f551a625ca7..bcc30c1411700a 100644 --- a/lib/compat/wordpress-5.9/global-styles-css-custom-properties.php +++ b/lib/compat/wordpress-5.9/global-styles-css-custom-properties.php @@ -13,7 +13,7 @@ */ function wp_enqueue_global_styles_css_custom_properties() { wp_register_style( 'global-styles-css-custom-properties', false, array(), true, true ); - wp_add_inline_style( 'global-styles-css-custom-properties', wp_get_global_stylesheet( array( 'variables' ) ) ); + wp_add_inline_style( 'global-styles-css-custom-properties', gutenberg_get_global_stylesheet( array( 'variables' ) ) ); wp_enqueue_style( 'global-styles-css-custom-properties' ); } add_filter( 'enqueue_block_editor_assets', 'wp_enqueue_global_styles_css_custom_properties' ); diff --git a/lib/compat/wordpress-5.9/script-loader.php b/lib/compat/wordpress-5.9/script-loader.php index 36f44f41c4a921..b88cdc65ee63b6 100644 --- a/lib/compat/wordpress-5.9/script-loader.php +++ b/lib/compat/wordpress-5.9/script-loader.php @@ -28,7 +28,7 @@ function gutenberg_enqueue_global_styles_assets() { return; } - $stylesheet = wp_get_global_stylesheet(); + $stylesheet = gutenberg_get_global_stylesheet(); if ( empty( $stylesheet ) ) { return; diff --git a/lib/compat/wordpress-6.0/class-gutenberg-rest-global-styles-controller.php b/lib/compat/wordpress-6.0/class-gutenberg-rest-global-styles-controller.php index a18c5a61531a0a..94f9f85d53b452 100644 --- a/lib/compat/wordpress-6.0/class-gutenberg-rest-global-styles-controller.php +++ b/lib/compat/wordpress-6.0/class-gutenberg-rest-global-styles-controller.php @@ -38,6 +38,54 @@ public function register_routes() { parent::register_routes(); } + /** + * Returns the given theme global styles config. + * + * @since 5.9.0 + * + * @param WP_REST_Request $request The request instance. + * @return WP_REST_Response|WP_Error + */ + public function get_theme_item( $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 ) + ); + } + + $theme = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data( 'theme' ); + $data = array(); + $fields = $this->get_fields_for_response( $request ); + + if ( rest_is_field_included( 'settings', $fields ) ) { + $data['settings'] = $theme->get_settings(); + } + + if ( rest_is_field_included( 'styles', $fields ) ) { + $raw_data = $theme->get_raw_data(); + $data['styles'] = isset( $raw_data['styles'] ) ? $raw_data['styles'] : array(); + } + + $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; + $data = $this->add_additional_fields_to_object( $data, $request ); + $data = $this->filter_response_by_context( $data, $context ); + + $response = rest_ensure_response( $data ); + + $links = array( + 'self' => array( + 'href' => rest_url( sprintf( '%s/%s/themes/%s', $this->namespace, $this->rest_base, $request['stylesheet'] ) ), + ), + ); + + $response->add_links( $links ); + + return $response; + } + /** * Checks if a given request has access to read a single theme global styles config. * diff --git a/lib/compat/wordpress-6.0/get-global-styles-and-settings.php b/lib/compat/wordpress-6.0/get-global-styles-and-settings.php new file mode 100644 index 00000000000000..5e78029d0d1915 --- /dev/null +++ b/lib/compat/wordpress-6.0/get-global-styles-and-settings.php @@ -0,0 +1,177 @@ +get_settings(); + return _wp_array_get( $settings, $path, $settings ); +} + +/** + * Function to get the styles resulting of merging core, theme, and user data. + * + * @param array $path Path to the specific style to retrieve. Optional. + * If empty, will return all styles. + * @param array $context { + * Metadata to know where to retrieve the $path from. Optional. + * + * @type string $block_name Which block to retrieve the styles from. + * If empty, it'll return the styles for the global context. + * @type string $origin Which origin to take data from. + * Valid values are 'all' (core, theme, and user) or 'base' (core and theme). + * If empty or unknown, 'all' is used. + * } + * + * @return array The styles to retrieve. + */ +function gutenberg_get_global_styles( $path = array(), $context = array() ) { + if ( ! empty( $context['block_name'] ) ) { + $path = array_merge( array( 'blocks', $context['block_name'] ), $path ); + } + $origin = 'custom'; + if ( isset( $context['origin'] ) && 'base' === $context['origin'] ) { + $origin = 'theme'; + } + $styles = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data( $origin )->get_raw_data()['styles']; + return _wp_array_get( $styles, $path, $styles ); +} + +/** + * Returns the stylesheet resulting of merging core, theme, and user data. + * + * @param array $types Types of styles to load. Optional. + * It accepts 'variables', 'styles', 'presets' as values. + * If empty, it'll load all for themes with theme.json support + * and only [ 'variables', 'presets' ] for themes without theme.json support. + * + * @return string Stylesheet. + */ +function gutenberg_get_global_stylesheet( $types = array() ) { + // Return cached value if it can be used and exists. + // It's cached by theme to make sure that theme switching clears the cache. + $can_use_cached = ( + ( empty( $types ) ) && + ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) && + ( ! defined( 'SCRIPT_DEBUG' ) || ! SCRIPT_DEBUG ) && + ( ! defined( 'REST_REQUEST' ) || ! REST_REQUEST ) && + ! is_admin() + ); + $transient_name = 'gutenberg_global_styles_' . get_stylesheet(); + if ( $can_use_cached ) { + $cached = get_transient( $transient_name ); + if ( $cached ) { + return $cached; + } + } + $tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data(); + $supports_theme_json = WP_Theme_JSON_Resolver_Gutenberg::theme_has_support(); + if ( empty( $types ) && ! $supports_theme_json ) { + $types = array( 'variables', 'presets' ); + } elseif ( empty( $types ) ) { + $types = array( 'variables', 'styles', 'presets' ); + } + + /* + * If variables are part of the stylesheet, + * we add them for all origins (default, theme, user). + * This is so themes without a theme.json still work as before 5.9: + * they can override the default presets. + * See https://core.trac.wordpress.org/ticket/54782 + */ + $styles_variables = ''; + if ( in_array( 'variables', $types, true ) ) { + $styles_variables = $tree->get_stylesheet( array( 'variables' ) ); + $types = array_diff( $types, array( 'variables' ) ); + } + + /* + * For the remaining types (presets, styles), we do consider origins: + * + * - themes without theme.json: only the classes for the presets defined by core + * - themes with theme.json: the presets and styles classes, both from core and the theme + */ + $styles_rest = ''; + if ( ! empty( $types ) ) { + $origins = array( 'default', 'theme', 'custom' ); + if ( ! $supports_theme_json ) { + $origins = array( 'default' ); + } + $styles_rest = $tree->get_stylesheet( $types, $origins ); + } + $stylesheet = $styles_variables . $styles_rest; + if ( $can_use_cached ) { + // Cache for a minute. + // This cache doesn't need to be any longer, we only want to avoid spikes on high-traffic sites. + set_transient( $transient_name, $stylesheet, MINUTE_IN_SECONDS ); + } + return $stylesheet; +} + +if ( ! function_exists( 'wp_get_global_styles_svg_filters' ) ) { + /** + * Returns a string containing the SVGs to be referenced as filters (duotone). + * + * @return string + */ + function wp_get_global_styles_svg_filters() { + // Return cached value if it can be used and exists. + // It's cached by theme to make sure that theme switching clears the cache. + $transient_name = 'gutenberg_global_styles_svg_filters_' . get_stylesheet(); + $can_use_cached = ( + ( ! defined( 'WP_DEBUG' ) || ! WP_DEBUG ) && + ( ! defined( 'SCRIPT_DEBUG' ) || ! SCRIPT_DEBUG ) && + ( ! defined( 'REST_REQUEST' ) || ! REST_REQUEST ) && + ! is_admin() + ); + if ( $can_use_cached ) { + $cached = get_transient( $transient_name ); + if ( $cached ) { + return $cached; + } + } + + $supports_theme_json = WP_Theme_JSON_Resolver_Gutenberg::theme_has_support(); + + $origins = array( 'default', 'theme', 'custom' ); + if ( ! $supports_theme_json ) { + $origins = array( 'default' ); + } + + $tree = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data(); + $svgs = $tree->get_svg_filters( $origins ); + + if ( $can_use_cached ) { + // Cache for a minute, same as gutenberg_get_global_stylesheet. + set_transient( $transient_name, $svgs, MINUTE_IN_SECONDS ); + } + + return $svgs; + } +} diff --git a/lib/global-styles.php b/lib/global-styles.php index a54373288421a4..4f5555a0285074 100644 --- a/lib/global-styles.php +++ b/lib/global-styles.php @@ -33,7 +33,7 @@ function_exists( 'gutenberg_is_edit_site_page' ) && } if ( 'mobile' === $context && WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() ) { - $settings['__experimentalStyles'] = wp_get_global_styles(); + $settings['__experimentalStyles'] = gutenberg_get_global_styles(); } if ( 'other' === $context ) { @@ -53,7 +53,7 @@ function_exists( 'gutenberg_is_edit_site_page' ) && $new_global_styles = array(); - $css_variables = wp_get_global_stylesheet( array( 'variables' ) ); + $css_variables = gutenberg_get_global_stylesheet( array( 'variables' ) ); if ( '' !== $css_variables ) { $new_global_styles[] = array( 'css' => $css_variables, @@ -61,7 +61,7 @@ function_exists( 'gutenberg_is_edit_site_page' ) && ); } - $css_presets = wp_get_global_stylesheet( array( 'presets' ) ); + $css_presets = gutenberg_get_global_stylesheet( array( 'presets' ) ); if ( '' !== $css_presets ) { $new_global_styles[] = array( 'css' => $css_presets, @@ -70,7 +70,7 @@ function_exists( 'gutenberg_is_edit_site_page' ) && } if ( WP_Theme_JSON_Resolver_Gutenberg::theme_has_support() ) { - $css_blocks = wp_get_global_stylesheet( array( 'styles' ) ); + $css_blocks = gutenberg_get_global_stylesheet( array( 'styles' ) ); if ( '' !== $css_blocks ) { $new_global_styles[] = array( 'css' => $css_blocks, @@ -83,7 +83,7 @@ function_exists( 'gutenberg_is_edit_site_page' ) && } // Copied from get_block_editor_settings() at wordpress-develop/block-editor.php. - $settings['__experimentalFeatures'] = wp_get_global_settings(); + $settings['__experimentalFeatures'] = gutenberg_get_global_settings(); if ( isset( $settings['__experimentalFeatures']['color']['palette'] ) ) { $colors_by_origin = $settings['__experimentalFeatures']['color']['palette']; diff --git a/lib/load.php b/lib/load.php index 8c309c2848b543..14861d63d74adf 100644 --- a/lib/load.php +++ b/lib/load.php @@ -74,7 +74,7 @@ function gutenberg_is_experiment_enabled( $name ) { // If it loads after, that function will always be present at that point // and the global styles assets won't be loaded. require __DIR__ . '/compat/wordpress-5.9/script-loader.php'; -require __DIR__ . '/compat/wordpress-5.9/get-global-styles-and-settings.php'; +require __DIR__ . '/compat/wordpress-6.0/get-global-styles-and-settings.php'; require __DIR__ . '/compat/wordpress-5.9/render-svg-filters.php'; require __DIR__ . '/compat/wordpress-5.9/json-file-decode.php'; require __DIR__ . '/compat/wordpress-5.9/translate-settings-using-i18n-schema.php';