diff --git a/src/wp-admin/edit-form-blocks.php b/src/wp-admin/edit-form-blocks.php index f43c835168c1d..b0c3f41846511 100644 --- a/src/wp-admin/edit-form-blocks.php +++ b/src/wp-admin/edit-form-blocks.php @@ -20,7 +20,7 @@ * @global string $title * @global array $wp_meta_boxes */ -global $post_type, $post_type_object, $post, $title, $wp_meta_boxes; +global $post_type, $post_type_object, $post, $title, $wp_meta_boxes, $wp_theme_json_resolver; $block_editor_context = new WP_Block_Editor_Context( array( 'post' => $post ) ); @@ -203,7 +203,7 @@ static function( $classes ) { 'unlockNonce' => wp_create_nonce( 'update-post_' . $post->ID ), 'ajaxUrl' => admin_url( 'admin-ajax.php' ), ), - 'supportsLayout' => WP_Theme_JSON_Resolver::theme_has_support(), + 'supportsLayout' => $wp_theme_json_resolver->theme_has_support(), 'supportsTemplateMode' => current_theme_supports( 'block-templates' ), // Whether or not to load the 'postcustom' meta box is stored as a user meta diff --git a/src/wp-admin/site-editor.php b/src/wp-admin/site-editor.php index a8b43b52af768..09ade1d1c221a 100644 --- a/src/wp-admin/site-editor.php +++ b/src/wp-admin/site-editor.php @@ -6,7 +6,7 @@ * @subpackage Administration */ -global $editor_styles; +global $editor_styles, $wp_theme_json_resolver; /** WordPress Administration Bootstrap */ require_once __DIR__ . '/admin.php'; @@ -74,7 +74,7 @@ static function( $classes ) { 'styles' => get_block_editor_theme_styles(), 'defaultTemplateTypes' => $indexed_template_types, 'defaultTemplatePartAreas' => get_allowed_block_template_part_areas(), - 'supportsLayout' => WP_Theme_JSON_Resolver::theme_has_support(), + 'supportsLayout' => $wp_theme_json_resolver->theme_has_support(), 'supportsTemplatePartsMode' => ! wp_is_block_theme() && current_theme_supports( 'block-template-parts' ), '__unstableHomeTemplate' => $home_template, ); @@ -100,7 +100,7 @@ static function( $classes ) { } } -$active_global_styles_id = WP_Theme_JSON_Resolver::get_user_global_styles_post_id(); +$active_global_styles_id = $wp_theme_json_resolver->get_user_global_styles_post_id(); $active_theme = get_stylesheet(); $preload_paths = array( array( '/wp/v2/media', 'OPTIONS' ), diff --git a/src/wp-includes/block-editor.php b/src/wp-includes/block-editor.php index 7af9f2a90062a..a43d7fd4010a7 100644 --- a/src/wp-includes/block-editor.php +++ b/src/wp-includes/block-editor.php @@ -387,6 +387,7 @@ function _wp_get_iframed_editor_assets() { * @return array The contextualized block editor settings. */ function get_block_editor_settings( array $custom_settings, $block_editor_context ) { + global $wp_theme_json_resolver; $editor_settings = array_merge( get_default_block_editor_settings(), array( @@ -417,7 +418,7 @@ function get_block_editor_settings( array $custom_settings, $block_editor_contex } } - if ( WP_Theme_JSON_Resolver::theme_has_support() ) { + if ( $wp_theme_json_resolver->theme_has_support() ) { $block_classes = array( 'css' => 'styles', '__unstableType' => 'theme', diff --git a/src/wp-includes/block-patterns.php b/src/wp-includes/block-patterns.php index 074ed33c84b44..22f5ef3707d9d 100644 --- a/src/wp-includes/block-patterns.php +++ b/src/wp-includes/block-patterns.php @@ -134,16 +134,17 @@ function _load_remote_featured_patterns() { * @access private */ function _register_remote_theme_patterns() { + global $wp_theme_json_resolver; /** This filter is documented in wp-includes/block-patterns.php */ if ( ! apply_filters( 'should_load_remote_block_patterns', true ) ) { return; } - if ( ! WP_Theme_JSON_Resolver::theme_has_support() ) { + if ( ! $wp_theme_json_resolver->theme_has_support() ) { return; } - $pattern_settings = WP_Theme_JSON_Resolver::get_theme_data()->get_patterns(); + $pattern_settings = $wp_theme_json_resolver->get_theme_data()->get_patterns(); if ( empty( $pattern_settings ) ) { return; } diff --git a/src/wp-includes/block-supports/layout.php b/src/wp-includes/block-supports/layout.php index 7a882a9bab386..8c765a29985e3 100644 --- a/src/wp-includes/block-supports/layout.php +++ b/src/wp-includes/block-supports/layout.php @@ -457,6 +457,7 @@ function wp_render_layout_support_flag( $block_content, $block ) { * @return string Filtered block content. */ function wp_restore_group_inner_container( $block_content, $block ) { + global $wp_theme_json_resolver; $tag_name = isset( $block['attrs']['tagName'] ) ? $block['attrs']['tagName'] : 'div'; $group_with_inner_container_regex = sprintf( '/(^\s*<%1$s\b[^>]*wp-block-group(\s|")[^>]*>)(\s*]*wp-block-group__inner-container(\s|")[^>]*>)((.|\S|\s)*)/U', @@ -464,7 +465,7 @@ function wp_restore_group_inner_container( $block_content, $block ) { ); if ( - WP_Theme_JSON_Resolver::theme_has_support() || + $wp_theme_json_resolver->theme_has_support() || 1 === preg_match( $group_with_inner_container_regex, $block_content ) || ( isset( $block['attrs']['layout']['type'] ) && 'flex' === $block['attrs']['layout']['type'] ) ) { @@ -500,6 +501,7 @@ static function( $matches ) { * @return string Filtered block content. */ function wp_restore_image_outer_container( $block_content, $block ) { + global $wp_theme_json_resolver; $image_with_align = " /# 1) everything up to the class attribute contents ( @@ -527,7 +529,7 @@ function wp_restore_image_outer_container( $block_content, $block ) { )/iUx"; if ( - WP_Theme_JSON_Resolver::theme_has_support() || + $wp_theme_json_resolver->theme_has_support() || 0 === preg_match( $image_with_align, $block_content, $matches ) ) { return $block_content; diff --git a/src/wp-includes/block-template-utils.php b/src/wp-includes/block-template-utils.php index f4958050c6593..207e8ac3ec371 100644 --- a/src/wp-includes/block-template-utils.php +++ b/src/wp-includes/block-template-utils.php @@ -347,11 +347,12 @@ function _get_block_templates_files( $template_type ) { * @return array Template item. */ function _add_block_template_info( $template_item ) { - if ( ! WP_Theme_JSON_Resolver::theme_has_support() ) { + global $wp_theme_json_resolver; + if ( ! $wp_theme_json_resolver->theme_has_support() ) { return $template_item; } - $theme_data = WP_Theme_JSON_Resolver::get_theme_data()->get_custom_templates(); + $theme_data = $wp_theme_json_resolver->get_theme_data()->get_custom_templates(); if ( isset( $theme_data[ $template_item['slug'] ] ) ) { $template_item['title'] = $theme_data[ $template_item['slug'] ]['title']; $template_item['postTypes'] = $theme_data[ $template_item['slug'] ]['postTypes']; @@ -370,8 +371,9 @@ function _add_block_template_info( $template_item ) { * @return array Template info. */ function _add_block_template_part_area_info( $template_info ) { - if ( WP_Theme_JSON_Resolver::theme_has_support() ) { - $theme_data = WP_Theme_JSON_Resolver::get_theme_data()->get_template_parts(); + global $wp_theme_json_resolver; + if ( $wp_theme_json_resolver->theme_has_support() ) { + $theme_data = $wp_theme_json_resolver->get_theme_data()->get_template_parts(); } if ( isset( $theme_data[ $template_info['slug'] ]['area'] ) ) { @@ -1205,8 +1207,8 @@ function wp_is_theme_directory_ignored( $path ) { * @return WP_Error|string Path of the ZIP file or error on failure. */ function wp_generate_block_templates_export_file() { - global $wp_version; - + global $wp_theme_json_resolver, $wp_version; + if ( ! class_exists( 'ZipArchive' ) ) { return new WP_Error( 'missing_zip_package', __( 'Zip Export not supported.' ) ); } @@ -1267,9 +1269,9 @@ function wp_generate_block_templates_export_file() { } // Load theme.json into the zip file. - $tree = WP_Theme_JSON_Resolver::get_theme_data( array(), array( 'with_supports' => false ) ); + $tree = $wp_theme_json_resolver->get_theme_data( array(), array( 'with_supports' => false ) ); // Merge with user data. - $tree->merge( WP_Theme_JSON_Resolver::get_user_data() ); + $tree->merge( $wp_theme_json_resolver->get_user_data() ); $theme_json_raw = $tree->get_data(); // If a version is defined, add a schema. diff --git a/src/wp-includes/class-wp-theme-json-resolver.php b/src/wp-includes/class-wp-theme-json-resolver.php index b1f15897b1af5..50e595c35b06a 100644 --- a/src/wp-includes/class-wp-theme-json-resolver.php +++ b/src/wp-includes/class-wp-theme-json-resolver.php @@ -26,7 +26,7 @@ class WP_Theme_JSON_Resolver { * @since 6.1.0 * @var array */ - protected static $blocks_cache = array( + protected $blocks_cache = array( 'core' => array(), 'blocks' => array(), 'theme' => array(), @@ -39,7 +39,7 @@ class WP_Theme_JSON_Resolver { * @since 5.8.0 * @var WP_Theme_JSON */ - protected static $core = null; + protected $core = null; /** * Container for data coming from the blocks. @@ -47,7 +47,7 @@ class WP_Theme_JSON_Resolver { * @since 6.1.0 * @var WP_Theme_JSON */ - protected static $blocks = null; + protected $blocks = null; /** * Container for data coming from the theme. @@ -55,7 +55,8 @@ class WP_Theme_JSON_Resolver { * @since 5.8.0 * @var WP_Theme_JSON */ - protected static $theme = null; + protected $theme = null; + protected $data = null; /** * Whether or not the theme supports theme.json. @@ -63,7 +64,7 @@ class WP_Theme_JSON_Resolver { * @since 5.8.0 * @var bool */ - protected static $theme_has_support = null; + protected $theme_has_support = null; /** * Container for data coming from the user. @@ -71,7 +72,7 @@ class WP_Theme_JSON_Resolver { * @since 5.9.0 * @var WP_Theme_JSON */ - protected static $user = null; + protected $user = null; /** * Stores the ID of the custom post type @@ -80,7 +81,7 @@ class WP_Theme_JSON_Resolver { * @since 5.9.0 * @var int */ - protected static $user_custom_post_type_id = null; + protected $user_custom_post_type_id = null; /** * Container to keep loaded i18n schema for `theme.json`. @@ -89,7 +90,7 @@ class WP_Theme_JSON_Resolver { * @since 5.9.0 Renamed from `$theme_json_i18n` to `$i18n_schema`. * @var array */ - protected static $i18n_schema = null; + protected $i18n_schema = null; /** * `theme.json` file cache. @@ -97,28 +98,30 @@ class WP_Theme_JSON_Resolver { * @since 6.1.0 * @var array */ - protected static $theme_json_file_cache = array(); + protected $theme_json_file_cache = array(); /** * Processes a file that adheres to the theme.json schema * and returns an array with its contents, or a void array if none found. * + * @param string $file_path Path to file. Empty if no file. + * + * @return array Contents that adhere to the theme.json schema. * @since 5.8.0 * @since 6.1.0 Added caching. * - * @param string $file_path Path to file. Empty if no file. - * @return array Contents that adhere to the theme.json schema. */ - protected static function read_json_file( $file_path ) { + protected function read_json_file( $file_path ) { if ( $file_path ) { - if ( array_key_exists( $file_path, static::$theme_json_file_cache ) ) { - return static::$theme_json_file_cache[ $file_path ]; + if ( array_key_exists( $file_path, $this->theme_json_file_cache ) ) { + return $this->theme_json_file_cache[ $file_path ]; } $decoded_file = wp_json_file_decode( $file_path, array( 'associative' => true ) ); if ( is_array( $decoded_file ) ) { - static::$theme_json_file_cache[ $file_path ] = $decoded_file; - return static::$theme_json_file_cache[ $file_path ]; + $this->theme_json_file_cache[ $file_path ] = $decoded_file; + + return $this->theme_json_file_cache[ $file_path ]; } } @@ -128,13 +131,14 @@ protected static function read_json_file( $file_path ) { /** * Returns a data structure used in theme.json translation. * - * @since 5.8.0 + * @return array An array of theme.json fields that are translatable and the keys that are translatable. * @deprecated 5.9.0 * - * @return array An array of theme.json fields that are translatable and the keys that are translatable. + * @since 5.8.0 */ - public static function get_fields_to_translate() { + public function get_fields_to_translate() { _deprecated_function( __METHOD__, '5.9.0' ); + return array(); } @@ -142,63 +146,66 @@ public static function get_fields_to_translate() { * Given a theme.json structure modifies it in place to update certain values * by its translated strings according to the language set by the user. * - * @since 5.8.0 - * - * @param array $theme_json The theme.json to translate. - * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. + * @param array $theme_json The theme.json to translate. + * @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings. * Default 'default'. + * * @return array Returns the modified $theme_json_structure. + * @since 5.8.0 + * */ - protected static function translate( $theme_json, $domain = 'default' ) { - if ( null === static::$i18n_schema ) { - $i18n_schema = wp_json_file_decode( __DIR__ . '/theme-i18n.json' ); - static::$i18n_schema = null === $i18n_schema ? array() : $i18n_schema; + protected function translate( $theme_json, $domain = 'default' ) { + if ( null === $this->i18n_schema ) { + $i18n_schema = wp_json_file_decode( __DIR__ . '/theme-i18n.json' ); + $this->i18n_schema = null === $i18n_schema ? array() : $i18n_schema; } - return translate_settings_using_i18n_schema( static::$i18n_schema, $theme_json, $domain ); + return translate_settings_using_i18n_schema( $this->i18n_schema, $theme_json, $domain ); } /** * Returns core's origin config. * + * @return WP_Theme_JSON Entity that holds core data. * @since 5.8.0 * - * @return WP_Theme_JSON Entity that holds core data. */ - public static function get_core_data() { - if ( null !== static::$core && static::has_same_registered_blocks( 'core' ) ) { - return static::$core; + public function get_core_data() { + if ( null !== $this->core && $this->has_same_registered_blocks( 'core' ) ) { + return $this->core; } - $config = static::read_json_file( __DIR__ . '/theme.json' ); - $config = static::translate( $config ); + $config = $this->read_json_file( __DIR__ . '/theme.json' ); + $config = $this->translate( $config ); /** * Filters the default data provided by WordPress for global styles & settings. * + * @param WP_Theme_JSON_Data Class to access and update the underlying data. + * * @since 6.1.0 * - * @param WP_Theme_JSON_Data Class to access and update the underlying data. */ - $theme_json = apply_filters( 'wp_theme_json_data_default', new WP_Theme_JSON_Data( $config, 'default' ) ); - $config = $theme_json->get_data(); - static::$core = new WP_Theme_JSON( $config, 'default' ); + $theme_json = apply_filters( 'wp_theme_json_data_default', new WP_Theme_JSON_Data( $config, 'default' ) ); + $config = $theme_json->get_data(); + $this->core = new WP_Theme_JSON( $config, 'default' ); - return static::$core; + return $this->core; } /** * Checks whether the registered blocks were already processed for this origin. * - * @since 6.1.0 - * * @param string $origin Data source for which to cache the blocks. * Valid values are 'core', 'blocks', 'theme', and 'user'. + * * @return bool True on success, false otherwise. + * @since 6.1.0 + * */ - protected static function has_same_registered_blocks( $origin ) { + protected function has_same_registered_blocks( $origin ) { // Bail out if the origin is invalid. - if ( ! isset( static::$blocks_cache[ $origin ] ) ) { + if ( ! isset( $this->blocks_cache[ $origin ] ) ) { return false; } @@ -206,13 +213,13 @@ protected static function has_same_registered_blocks( $origin ) { $blocks = $registry->get_all_registered(); // Is there metadata for all currently registered blocks? - $block_diff = array_diff_key( $blocks, static::$blocks_cache[ $origin ] ); + $block_diff = array_diff_key( $blocks, $this->blocks_cache[ $origin ] ); if ( empty( $block_diff ) ) { return true; } foreach ( $blocks as $block_name => $block_type ) { - static::$blocks_cache[ $origin ][ $block_name ] = true; + $this->blocks_cache[ $origin ][ $block_name ] = true; } return false; @@ -226,31 +233,31 @@ protected static function has_same_registered_blocks( $origin ) { * is present in theme.json and in theme supports, * the theme.json takes precedence. * - * @since 5.8.0 - * @since 5.9.0 Theme supports have been inlined and the `$theme_support_data` argument removed. - * @since 6.0.0 Added an `$options` parameter to allow the theme data to be returned without theme supports. - * * @param array $deprecated Deprecated. Not used. * @param array $options { * Options arguments. * - * @type bool $with_supports Whether to include theme supports in the data. Default true. + * @type bool $with_supports Whether to include theme supports in the data. Default true. * } * @return WP_Theme_JSON Entity that holds theme data. + * @since 5.8.0 + * @since 5.9.0 Theme supports have been inlined and the `$theme_support_data` argument removed. + * @since 6.0.0 Added an `$options` parameter to allow the theme data to be returned without theme supports. + * */ - public static function get_theme_data( $deprecated = array(), $options = array() ) { + public function get_theme_data( $deprecated = array(), $options = array() ) { if ( ! empty( $deprecated ) ) { _deprecated_argument( __METHOD__, '5.9.0' ); } $options = wp_parse_args( $options, array( 'with_supports' => true ) ); - if ( null === static::$theme || ! static::has_same_registered_blocks( 'theme' ) ) { - $theme_json_file = static::get_file_path_from_theme( 'theme.json' ); + if ( null === $this->theme || ! $this->has_same_registered_blocks( 'theme' ) ) { + $theme_json_file = $this->get_file_path_from_theme( 'theme.json' ); $wp_theme = wp_get_theme(); if ( '' !== $theme_json_file ) { - $theme_json_data = static::read_json_file( $theme_json_file ); - $theme_json_data = static::translate( $theme_json_data, $wp_theme->get( 'TextDomain' ) ); + $theme_json_data = $this->read_json_file( $theme_json_file ); + $theme_json_data = $this->translate( $theme_json_data, $wp_theme->get( 'TextDomain' ) ); } else { $theme_json_data = array(); } @@ -258,20 +265,21 @@ public static function get_theme_data( $deprecated = array(), $options = array() /** * Filters the data provided by the theme for global styles and settings. * + * @param WP_Theme_JSON_Data Class to access and update the underlying data. + * * @since 6.1.0 * - * @param WP_Theme_JSON_Data Class to access and update the underlying data. */ $theme_json = apply_filters( 'wp_theme_json_data_theme', new WP_Theme_JSON_Data( $theme_json_data, 'theme' ) ); $theme_json_data = $theme_json->get_data(); - static::$theme = new WP_Theme_JSON( $theme_json_data ); + $this->theme = new WP_Theme_JSON( $theme_json_data ); if ( $wp_theme->parent() ) { // Get parent theme.json. - $parent_theme_json_file = static::get_file_path_from_theme( 'theme.json', true ); + $parent_theme_json_file = $this->get_file_path_from_theme( 'theme.json', true ); if ( '' !== $parent_theme_json_file ) { - $parent_theme_json_data = static::read_json_file( $parent_theme_json_file ); - $parent_theme_json_data = static::translate( $parent_theme_json_data, $wp_theme->parent()->get( 'TextDomain' ) ); + $parent_theme_json_data = $this->read_json_file( $parent_theme_json_file ); + $parent_theme_json_data = $this->translate( $parent_theme_json_data, $wp_theme->parent()->get( 'TextDomain' ) ); $parent_theme = new WP_Theme_JSON( $parent_theme_json_data ); /* @@ -279,23 +287,23 @@ public static function get_theme_data( $deprecated = array(), $options = array() * The child theme takes precedence over the parent. */ $parent_theme->merge( static::$theme ); - static::$theme = $parent_theme; + $this->theme = $parent_theme; } } } if ( ! $options['with_supports'] ) { - return static::$theme; + return $this->theme; } /* * We want the presets and settings declared in theme.json * to override the ones declared via theme supports. * So we take theme supports, transform it to theme.json shape - * and merge the static::$theme upon that. + * and merge the $this->theme upon that. */ $theme_support_data = WP_Theme_JSON::get_from_editor_settings( get_default_block_editor_settings() ); - if ( ! static::theme_has_support() ) { + if ( ! $this->theme_has_support() ) { if ( ! isset( $theme_support_data['settings']['color'] ) ) { $theme_support_data['settings']['color'] = array(); } @@ -324,29 +332,30 @@ public static function get_theme_data( $deprecated = array(), $options = array() $theme_support_data['settings']['color']['defaultDuotone'] = false; } $with_theme_supports = new WP_Theme_JSON( $theme_support_data ); - $with_theme_supports->merge( static::$theme ); + $with_theme_supports->merge( $this->theme ); + return $with_theme_supports; } /** * Gets the styles for blocks from the block.json file. * + * @return WP_Theme_JSON * @since 6.1.0 * - * @return WP_Theme_JSON */ - public static function get_block_data() { + public function get_block_data() { $registry = WP_Block_Type_Registry::get_instance(); $blocks = $registry->get_all_registered(); - if ( null !== static::$blocks && static::has_same_registered_blocks( 'blocks' ) ) { - return static::$blocks; + if ( null !== $this->blocks && $this->has_same_registered_blocks( 'blocks' ) ) { + return $this->blocks; } $config = array( 'version' => 2 ); foreach ( $blocks as $block_name => $block_type ) { if ( isset( $block_type->supports['__experimentalStyle'] ) ) { - $config['styles']['blocks'][ $block_name ] = static::remove_json_comments( $block_type->supports['__experimentalStyle'] ); + $config['styles']['blocks'][ $block_name ] = $this->remove_json_comments( $block_type->supports['__experimentalStyle'] ); } if ( @@ -362,28 +371,31 @@ public static function get_block_data() { /** * Filters the data provided by the blocks for global styles & settings. * + * @param WP_Theme_JSON_Data Class to access and update the underlying data. + * * @since 6.1.0 * - * @param WP_Theme_JSON_Data Class to access and update the underlying data. */ $theme_json = apply_filters( 'wp_theme_json_data_blocks', new WP_Theme_JSON_Data( $config, 'blocks' ) ); $config = $theme_json->get_data(); - static::$blocks = new WP_Theme_JSON( $config, 'blocks' ); - return static::$blocks; + $this->blocks = new WP_Theme_JSON( $config, 'blocks' ); + + return $this->blocks; } /** * When given an array, this will remove any keys with the name `//`. * * @param array $array The array to filter. + * * @return array The filtered array. */ - private static function remove_json_comments( $array ) { + private function remove_json_comments( $array ) { unset( $array['//'] ); foreach ( $array as $k => $v ) { if ( is_array( $v ) ) { - $array[ $k ] = static::remove_json_comments( $v ); + $array[ $k ] = $this->remove_json_comments( $v ); } } @@ -396,19 +408,20 @@ private static function remove_json_comments( $array ) { * * This can also create and return a new draft custom post type. * - * @since 5.9.0 - * - * @param WP_Theme $theme The theme object. If empty, it + * @param WP_Theme $theme The theme object. If empty, it * defaults to the active theme. - * @param bool $create_post Optional. Whether a new custom post + * @param bool $create_post Optional. Whether a new custom post * type should be created if none are * found. Default false. - * @param array $post_status_filter Optional. Filter custom post type by + * @param array $post_status_filter Optional. Filter custom post type by * post status. Default `array( 'publish' )`, * so it only fetches published posts. + * * @return array Custom Post Type for the user's origin config. + * @since 5.9.0 + * */ - public static function get_user_data_from_wp_global_styles( $theme, $create_post = false, $post_status_filter = array( 'publish' ) ) { + public function get_user_data_from_wp_global_styles( $theme, $create_post = false, $post_status_filter = array( 'publish' ) ) { if ( ! $theme instanceof WP_Theme ) { $theme = wp_get_theme(); } @@ -453,7 +466,8 @@ public static function get_user_data_from_wp_global_styles( $theme, $create_post array( 'post_content' => '{"version": ' . WP_Theme_JSON::LATEST_SCHEMA . ', "isGlobalStylesUserThemeJSON": true }', 'post_status' => 'publish', - 'post_title' => 'Custom Styles', // Do not make string translatable, see https://core.trac.wordpress.org/ticket/54518. + 'post_title' => 'Custom Styles', + // Do not make string translatable, see https://core.trac.wordpress.org/ticket/54518. 'post_type' => $post_type_filter, 'post_name' => sprintf( 'wp-global-styles-%s', urlencode( $stylesheet ) ), 'tax_input' => array( @@ -473,17 +487,17 @@ public static function get_user_data_from_wp_global_styles( $theme, $create_post /** * Returns the user's origin config. * + * @return WP_Theme_JSON Entity that holds styles for user data. * @since 5.9.0 * - * @return WP_Theme_JSON Entity that holds styles for user data. */ - public static function get_user_data() { - if ( null !== static::$user && static::has_same_registered_blocks( 'user' ) ) { - return static::$user; + public function get_user_data() { + if ( null !== $this->user && $this->has_same_registered_blocks( 'user' ) ) { + return $this->user; } $config = array(); - $user_cpt = static::get_user_data_from_wp_global_styles( wp_get_theme() ); + $user_cpt = $this->get_user_data_from_wp_global_styles( wp_get_theme() ); if ( array_key_exists( 'post_content', $user_cpt ) ) { $decoded_data = json_decode( $user_cpt['post_content'], true ); @@ -494,12 +508,14 @@ public static function get_user_data() { /** * Filters the data provided by the user for global styles & settings. * + * @param WP_Theme_JSON_Data Class to access and update the underlying data. + * * @since 6.1.0 * - * @param WP_Theme_JSON_Data Class to access and update the underlying data. */ $theme_json = apply_filters( 'wp_theme_json_data_user', new WP_Theme_JSON_Data( $config, 'custom' ) ); $config = $theme_json->get_data(); + return new WP_Theme_JSON( $config, 'custom' ); } @@ -516,11 +532,11 @@ public static function get_user_data() { } /** This filter is documented in wp-includes/class-wp-theme-json-resolver.php */ - $theme_json = apply_filters( 'wp_theme_json_data_user', new WP_Theme_JSON_Data( $config, 'custom' ) ); - $config = $theme_json->get_data(); - static::$user = new WP_Theme_JSON( $config, 'custom' ); + $theme_json = apply_filters( 'wp_theme_json_data_user', new WP_Theme_JSON_Data( $config, 'custom' ) ); + $config = $theme_json->get_data(); + $this->user = new WP_Theme_JSON( $config, 'custom' ); - return static::$user; + return $this->user; } /** @@ -542,73 +558,75 @@ public static function get_user_data() { * for the paragraph block, and the theme has done it as well, * the user preference wins. * - * @since 5.8.0 - * @since 5.9.0 Added user data, removed the `$settings` parameter, - * added the `$origin` parameter. - * @since 6.1.0 Added block data and generation of spacingSizes array. - * * @param string $origin Optional. To what level should we merge data. * Valid values are 'theme' or 'custom'. Default 'custom'. + * * @return WP_Theme_JSON + * @since 6.1.0 Added block data and generation of spacingSizes array. + * + * @since 5.8.0 + * @since 5.9.0 Added user data, removed the `$settings` parameter, + * added the `$origin` parameter. */ - public static function get_merged_data( $origin = 'custom' ) { + public function get_merged_data( $origin = 'custom' ) { if ( is_array( $origin ) ) { _deprecated_argument( __FUNCTION__, '5.9.0' ); } - $result = static::get_core_data(); - $result->merge( static::get_block_data() ); - $result->merge( static::get_theme_data() ); - - if ( 'custom' === $origin ) { - $result->merge( static::get_user_data() ); + if( $this->data ){ + return $this->data; } + $this->data = $this->get_core_data(); + $this->data->merge( $this->get_block_data() ); + $this->data->merge( $this->get_theme_data() ); + $this->data->merge( $this->get_user_data() ); + // Generate the default spacingSizes array based on the merged spacingScale settings. - $result->set_spacing_sizes(); + $this->data->set_spacing_sizes(); - return $result; + return $this->data; } /** * Returns the ID of the custom post type * that stores user data. * + * @return integer|null * @since 5.9.0 * - * @return integer|null */ - public static function get_user_global_styles_post_id() { - if ( null !== static::$user_custom_post_type_id ) { - return static::$user_custom_post_type_id; + public function get_user_global_styles_post_id() { + if ( null !== $this->user_custom_post_type_id ) { + return $this->user_custom_post_type_id; } - $user_cpt = static::get_user_data_from_wp_global_styles( wp_get_theme(), true ); + $user_cpt = $this->get_user_data_from_wp_global_styles( wp_get_theme(), true ); if ( array_key_exists( 'ID', $user_cpt ) ) { - static::$user_custom_post_type_id = $user_cpt['ID']; + $this->user_custom_post_type_id = $user_cpt['ID']; } - return static::$user_custom_post_type_id; + return $this->user_custom_post_type_id; } /** * Determines whether the active theme has a theme.json file. * - * @since 5.8.0 + * @return bool * @since 5.9.0 Added a check in the parent theme. * - * @return bool + * @since 5.8.0 */ - public static function theme_has_support() { - if ( ! isset( static::$theme_has_support ) ) { - static::$theme_has_support = ( - static::get_file_path_from_theme( 'theme.json' ) !== '' || - static::get_file_path_from_theme( 'theme.json', true ) !== '' + public function theme_has_support() { + if ( ! isset( $this->theme_has_support ) ) { + $this->theme_has_support = ( + is_readable( $this->get_file_path_from_theme( 'theme.json' ) ) || + is_readable( $this->get_file_path_from_theme( 'theme.json', true ) ) ); } - return static::$theme_has_support; + return $this->theme_has_support; } /** @@ -616,14 +634,15 @@ public static function theme_has_support() { * * If it isn't, returns an empty string, otherwise returns the whole file path. * - * @since 5.8.0 - * @since 5.9.0 Adapted to work with child themes, added the `$template` argument. - * * @param string $file_name Name of the file. - * @param bool $template Optional. Use template theme directory. Default false. + * @param bool $template Optional. Use template theme directory. Default false. + * * @return string The whole file path or empty if the file doesn't exist. + * @since 5.9.0 Adapted to work with child themes, added the `$template` argument. + * + * @since 5.8.0 */ - protected static function get_file_path_from_theme( $file_name, $template = false ) { + protected function get_file_path_from_theme( $file_name, $template = false ) { $path = $template ? get_template_directory() : get_stylesheet_directory(); $candidate = $path . '/' . $file_name; @@ -639,30 +658,31 @@ protected static function get_file_path_from_theme( $file_name, $template = fals * @since 6.1.0 Added the `$blocks` and `$blocks_cache` variables * to reset. */ - public static function clean_cached_data() { - static::$core = null; - static::$blocks = null; - static::$blocks_cache = array( + public function clean_cached_data() { + $this->core = null; + $this->data = null; + $this->blocks = null; + $this->blocks_cache = array( 'core' => array(), 'blocks' => array(), 'theme' => array(), 'user' => array(), ); - static::$theme = null; - static::$user = null; - static::$user_custom_post_type_id = null; - static::$theme_has_support = null; - static::$i18n_schema = null; + $this->theme = null; + $this->user = null; + $this->user_custom_post_type_id = null; + $this->theme_has_support = null; + $this->i18n_schema = null; } /** * Returns the style variations defined by the theme. * + * @return array * @since 6.0.0 * - * @return array */ - public static function get_style_variations() { + public function get_style_variations() { $variations = array(); $base_directory = get_stylesheet_directory() . '/styles'; if ( is_dir( $base_directory ) ) { @@ -672,7 +692,7 @@ public static function get_style_variations() { foreach ( $nested_html_files as $path => $file ) { $decoded_file = wp_json_file_decode( $path, array( 'associative' => true ) ); if ( is_array( $decoded_file ) ) { - $translated = static::translate( $decoded_file, wp_get_theme()->get( 'TextDomain' ) ); + $translated = $this->translate( $decoded_file, wp_get_theme()->get( 'TextDomain' ) ); $variation = ( new WP_Theme_JSON( $translated ) )->get_raw_data(); if ( empty( $variation['title'] ) ) { $variation['title'] = basename( $path, '.json' ); @@ -681,6 +701,7 @@ public static function get_style_variations() { } } } + return $variations; } diff --git a/src/wp-includes/default-filters.php b/src/wp-includes/default-filters.php index e9ca31f5f7908..47a39db93842c 100644 --- a/src/wp-includes/default-filters.php +++ b/src/wp-includes/default-filters.php @@ -346,8 +346,13 @@ add_action( 'init', '_register_core_block_patterns_and_categories' ); add_action( 'init', 'check_theme_switched', 99 ); add_action( 'init', array( 'WP_Block_Supports', 'init' ), 22 ); -add_action( 'switch_theme', array( 'WP_Theme_JSON_Resolver', 'clean_cached_data' ) ); -add_action( 'start_previewing_theme', array( 'WP_Theme_JSON_Resolver', 'clean_cached_data' ) ); + +global $wp_theme_json_resolver; + +if( $wp_theme_json_resolver ) { + add_action( 'switch_theme', array( $wp_theme_json_resolver, 'clean_cached_data' ) ); + add_action( 'start_previewing_theme', array( $wp_theme_json_resolver, 'clean_cached_data' ) ); +} add_action( 'after_switch_theme', '_wp_menus_changed' ); add_action( 'after_switch_theme', '_wp_sidebars_changed' ); add_action( 'wp_print_styles', 'print_emoji_styles' ); diff --git a/src/wp-includes/global-styles-and-settings.php b/src/wp-includes/global-styles-and-settings.php index b6c8c91b464c0..93e711bc7cfc3 100644 --- a/src/wp-includes/global-styles-and-settings.php +++ b/src/wp-includes/global-styles-and-settings.php @@ -24,6 +24,7 @@ * @return array The settings to retrieve. */ function wp_get_global_settings( $path = array(), $context = array() ) { + global $wp_theme_json_resolver; if ( ! empty( $context['block_name'] ) ) { $path = array_merge( array( 'blocks', $context['block_name'] ), $path ); } @@ -33,7 +34,7 @@ function wp_get_global_settings( $path = array(), $context = array() ) { $origin = 'theme'; } - $settings = WP_Theme_JSON_Resolver::get_merged_data( $origin )->get_settings(); + $settings = $wp_theme_json_resolver->get_merged_data( $origin )->get_settings(); return _wp_array_get( $settings, $path, $settings ); } @@ -57,6 +58,7 @@ function wp_get_global_settings( $path = array(), $context = array() ) { * @return array The styles to retrieve. */ function wp_get_global_styles( $path = array(), $context = array() ) { + global $wp_theme_json_resolver; if ( ! empty( $context['block_name'] ) ) { $path = array_merge( array( 'blocks', $context['block_name'] ), $path ); } @@ -66,7 +68,7 @@ function wp_get_global_styles( $path = array(), $context = array() ) { $origin = 'theme'; } - $styles = WP_Theme_JSON_Resolver::get_merged_data( $origin )->get_raw_data()['styles']; + $styles = $wp_theme_json_resolver->get_merged_data( $origin )->get_raw_data()['styles']; return _wp_array_get( $styles, $path, $styles ); } @@ -83,6 +85,7 @@ function wp_get_global_styles( $path = array(), $context = array() ) { * @return string Stylesheet. */ function wp_get_global_stylesheet( $types = array() ) { + global $wp_theme_json_resolver; // 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 = ( @@ -100,9 +103,9 @@ function wp_get_global_stylesheet( $types = array() ) { } } - $tree = WP_Theme_JSON_Resolver::get_merged_data(); + $tree = $wp_theme_json_resolver->get_merged_data(); - $supports_theme_json = WP_Theme_JSON_Resolver::theme_has_support(); + $supports_theme_json = $wp_theme_json_resolver->theme_has_support(); if ( empty( $types ) && ! $supports_theme_json ) { $types = array( 'variables', 'presets', 'base-layout-styles' ); } elseif ( empty( $types ) ) { @@ -168,6 +171,7 @@ function wp_get_global_stylesheet( $types = array() ) { * @return string */ function wp_get_global_styles_svg_filters() { + global $wp_theme_json_resolver; // 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 = ( @@ -184,14 +188,14 @@ function wp_get_global_styles_svg_filters() { } } - $supports_theme_json = WP_Theme_JSON_Resolver::theme_has_support(); + $supports_theme_json = $wp_theme_json_resolver->theme_has_support(); $origins = array( 'default', 'theme', 'custom' ); if ( ! $supports_theme_json ) { $origins = array( 'default' ); } - $tree = WP_Theme_JSON_Resolver::get_merged_data(); + $tree = $wp_theme_json_resolver->get_merged_data(); $svgs = $tree->get_svg_filters( $origins ); if ( $can_use_cached ) { @@ -208,7 +212,8 @@ function wp_get_global_styles_svg_filters() { * @since 6.1.0 */ function wp_add_global_styles_for_blocks() { - $tree = WP_Theme_JSON_Resolver::get_merged_data(); + global $wp_theme_json_resolver; + $tree = $wp_theme_json_resolver->get_merged_data(); $block_nodes = $tree->get_styles_block_nodes(); foreach ( $block_nodes as $metadata ) { $block_css = $tree->get_styles_for_block( $metadata ); diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-controller.php index 9ce931398f383..701657fe20bc2 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-controller.php @@ -564,6 +564,8 @@ public function get_theme_item_permissions_check( $request ) { * @return WP_REST_Response|WP_Error */ public function get_theme_item( $request ) { + global $wp_theme_json_resolver; + if ( get_stylesheet() !== $request['stylesheet'] ) { // This endpoint only supports the active theme for now. return new WP_Error( @@ -573,7 +575,7 @@ public function get_theme_item( $request ) { ); } - $theme = WP_Theme_JSON_Resolver::get_merged_data( 'theme' ); + $theme = $wp_theme_json_resolver->get_merged_data( 'theme' ); $data = array(); $fields = $this->get_fields_for_response( $request ); @@ -638,6 +640,8 @@ public function get_theme_items_permissions_check( $request ) { // phpcs:ignore * @return WP_REST_Response|WP_Error */ public function get_theme_items( $request ) { + global $wp_theme_json_resolver; + if ( get_stylesheet() !== $request['stylesheet'] ) { // This endpoint only supports the active theme for now. return new WP_Error( @@ -647,7 +651,7 @@ public function get_theme_items( $request ) { ); } - $variations = WP_Theme_JSON_Resolver::get_style_variations(); + $variations = $wp_theme_json_resolver->get_style_variations(); $response = rest_ensure_response( $variations ); return $response; diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php index 71dbcb61931f8..4ab08b250bfa7 100644 --- a/src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php +++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-themes-controller.php @@ -356,6 +356,7 @@ public function prepare_item_for_response( $item, $request ) { * @return array Links for the given block type. */ protected function prepare_links( $theme ) { + global $wp_theme_json_resolver; $links = array( 'self' => array( 'href' => rest_url( sprintf( '%s/%s/%s', $this->namespace, $this->rest_base, $theme->get_stylesheet() ) ), @@ -367,9 +368,9 @@ protected function prepare_links( $theme ) { if ( $this->is_same_theme( $theme, wp_get_theme() ) ) { // This creates a record for the active theme if not existent. - $id = WP_Theme_JSON_Resolver::get_user_global_styles_post_id(); + $id = $wp_theme_json_resolver->get_user_global_styles_post_id(); } else { - $user_cpt = WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme ); + $user_cpt = $wp_theme_json_resolver->get_user_data_from_wp_global_styles( $theme ); $id = isset( $user_cpt['ID'] ) ? $user_cpt['ID'] : null; } diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php index 27defd0659460..32b128a6b8520 100644 --- a/src/wp-includes/script-loader.php +++ b/src/wp-includes/script-loader.php @@ -1468,7 +1468,7 @@ function wp_default_scripts( $scripts ) { * @param WP_Styles $styles */ function wp_default_styles( $styles ) { - global $editor_styles; + global $editor_styles, $wp_theme_json_resolver; // Include an unmodified $wp_version. require ABSPATH . WPINC . '/version.php'; @@ -1618,7 +1618,7 @@ function wp_default_styles( $styles ) { ); // Only load the default layout and margin styles for themes without theme.json file. - if ( ! WP_Theme_JSON_Resolver::theme_has_support() ) { + if ( ! $wp_theme_json_resolver->theme_has_support() ) { $wp_edit_blocks_dependencies[] = 'wp-editor-classic-layout-styles'; } @@ -3201,12 +3201,13 @@ function _wp_theme_json_webfonts_handler() { * @return array Array of defined webfonts. */ $fn_get_webfonts_from_theme_json = static function() { + global $wp_theme_json_resolver; // Get settings from theme.json. - $settings = WP_Theme_JSON_Resolver::get_merged_data()->get_settings(); + $settings = $wp_theme_json_resolver->get_merged_data()->get_settings(); // If in the editor, add webfonts defined in variations. if ( is_admin() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) { - $variations = WP_Theme_JSON_Resolver::get_style_variations(); + $variations = $wp_theme_json_resolver->get_style_variations(); foreach ( $variations as $variation ) { // Skip if fontFamilies are not defined in the variation. if ( empty( $variation['settings']['typography']['fontFamilies'] ) ) { @@ -3665,7 +3666,8 @@ function _wp_theme_json_webfonts_handler() { * @since 6.1.0 */ function wp_enqueue_classic_theme_styles() { - if ( ! WP_Theme_JSON_Resolver::theme_has_support() ) { + global $wp_theme_json_resolver; + if ( ! $wp_theme_json_resolver->theme_has_support() ) { $suffix = wp_scripts_get_suffix(); wp_register_style( 'classic-theme-styles', '/' . WPINC . "/css/classic-themes$suffix.css", array(), true ); wp_enqueue_style( 'classic-theme-styles' ); @@ -3683,7 +3685,8 @@ function wp_enqueue_classic_theme_styles() { * @return array A filtered array of editor settings. */ function wp_add_editor_classic_theme_styles( $editor_settings ) { - if ( WP_Theme_JSON_Resolver::theme_has_support() ) { + global $wp_theme_json_resolver; + if ( $wp_theme_json_resolver->theme_has_support() ) { return $editor_settings; } diff --git a/src/wp-includes/theme-templates.php b/src/wp-includes/theme-templates.php index 7ef010eea5ffd..7392ffbf3177d 100644 --- a/src/wp-includes/theme-templates.php +++ b/src/wp-includes/theme-templates.php @@ -209,7 +209,8 @@ function the_block_template_skip_link() { * @since 5.8.0 */ function wp_enable_block_templates() { - if ( wp_is_block_theme() || WP_Theme_JSON_Resolver::theme_has_support() ) { + global $wp_theme_json_resolver; + if ( wp_is_block_theme() || $wp_theme_json_resolver->theme_has_support() ) { add_theme_support( 'block-templates' ); } } diff --git a/src/wp-settings.php b/src/wp-settings.php index d80d79bb82d6b..1ef0d2a8c9705 100644 --- a/src/wp-settings.php +++ b/src/wp-settings.php @@ -525,6 +525,14 @@ */ $GLOBALS['wp'] = new WP(); +/** + * WordPress Object + * + * @global WP_Theme_JSON_Resolver $wp_theme_json_resolver Current WordPress environment instance. + * @since 2.0.0 + */ +$GLOBALS['wp_theme_json_resolver'] = new WP_Theme_JSON_Resolver(); + /** * WordPress Widget Factory Object *