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

Improve caching for theme.json processing #3418

Closed
wants to merge 16 commits into from
Closed
105 changes: 91 additions & 14 deletions src/wp-includes/class-wp-theme-json-resolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,19 @@
#[AllowDynamicProperties]
class WP_Theme_JSON_Resolver {

/**
* Container for keep track of registered blocks.
*
* @since 6.1.0
* @var array
oandregal marked this conversation as resolved.
Show resolved Hide resolved
*/
protected static $blocks_cache = array(
'core' => array(),
'blocks' => array(),
'theme' => array(),
'user' => array(),
);

/**
* Container for data coming from core.
*
Expand All @@ -28,6 +41,14 @@ class WP_Theme_JSON_Resolver {
*/
protected static $core = null;

/**
* Container for data coming from the blocks.
*
* @since 6.1.0
* @var WP_Theme_JSON
*/
protected static $blocks = null;

/**
* Container for data coming from the theme.
*
Expand Down Expand Up @@ -145,6 +166,10 @@ protected static function translate( $theme_json, $domain = 'default' ) {
* @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;
}

$config = static::read_json_file( __DIR__ . '/theme.json' );
$config = static::translate( $config );

Expand All @@ -162,6 +187,37 @@ public static function get_core_data() {
return static::$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.
*/
protected static function has_same_registered_blocks( $origin ) {
// Bail out if the origin is invalid.
if ( ! isset( static::$blocks_cache[ $origin ] ) ) {
return false;
}

$registry = WP_Block_Type_Registry::get_instance();
$blocks = $registry->get_all_registered();

// Is there metadata for all currently registered blocks?
$block_diff = array_diff_key( $blocks, static::$blocks_cache[ $origin ] );
if ( empty( $block_diff ) ) {
return true;
}

foreach ( $blocks as $block_name => $block_type ) {
static::$blocks_cache[ $origin ][ $block_name ] = true;
}

return false;
}

/**
* Returns the theme's data.
*
Expand Down Expand Up @@ -189,19 +245,21 @@ public static function get_theme_data( $deprecated = array(), $options = array()

$options = wp_parse_args( $options, array( 'with_supports' => true ) );

$theme_json_data = static::read_json_file( static::get_file_path_from_theme( 'theme.json' ) );
$theme_json_data = static::translate( $theme_json_data, wp_get_theme()->get( 'TextDomain' ) );
if ( null === static::$theme || ! static::has_same_registered_blocks( 'theme' ) ) {
Copy link
Member Author

@oandregal oandregal Oct 11, 2022

Choose a reason for hiding this comment

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

The only change here is running this code conditionally. The code within has not changed, it's only tabbed.

$theme_json_data = static::read_json_file( static::get_file_path_from_theme( 'theme.json' ) );
$theme_json_data = static::translate( $theme_json_data, wp_get_theme()->get( 'TextDomain' ) );

/**
* Filters the data provided by the theme for global styles and settings.
*
* @since 6.1.0
*
* @param WP_Theme_JSON_Data Class to access and update the underlying data.
*/
$theme_json = apply_filters( 'theme_json_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 );
/**
* Filters the data provided by the theme for global styles and settings.
*
* @since 6.1.0
*
* @param WP_Theme_JSON_Data Class to access and update the underlying data.
*/
$theme_json = apply_filters( 'theme_json_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 );
}

if ( wp_get_theme()->parent() ) {
// Get parent theme.json.
Expand Down Expand Up @@ -258,7 +316,6 @@ public static function get_theme_data( $deprecated = array(), $options = array()
}
$with_theme_supports = new WP_Theme_JSON( $theme_support_data );
$with_theme_supports->merge( static::$theme );

return $with_theme_supports;
}

Expand All @@ -272,7 +329,13 @@ public static function get_theme_data( $deprecated = array(), $options = array()
public static 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;
}

$config = array( 'version' => 2 );
Copy link
Member

Choose a reason for hiding this comment

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

Can you explain this change?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is a bug I found while working in this PR. I can prepare a different PR if that's preferred but thought it was so minor it didn't merit one.

This sets the version of the theme.json schema used by the data stored in the blocks. We introduced version 2 in WordPress 5.9 and blocks only gained this functionality in this release, so we should be using the latest. In practice, because we're using the version 2 to store data in the blocks, probably we won't notice anything. Though this is still a dormant bug waiting to happen, and I rather do the right thing now. See docs.


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'] );
Expand All @@ -298,7 +361,8 @@ public static function get_block_data() {
$theme_json = apply_filters( 'theme_json_blocks', new WP_Theme_JSON_Data( $config, 'blocks' ) );
$config = $theme_json->get_data();

return new WP_Theme_JSON( $config, 'blocks' );
static::$blocks = new WP_Theme_JSON( $config, 'blocks' );
return static::$blocks;
}

/**
Expand Down Expand Up @@ -407,6 +471,10 @@ public static function get_user_data_from_wp_global_styles( $theme, $create_post
* @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;
}

$config = array();
$user_cpt = static::get_user_data_from_wp_global_styles( wp_get_theme() );

Expand Down Expand Up @@ -562,9 +630,18 @@ protected static function get_file_path_from_theme( $file_name, $template = fals
* @since 5.8.0
* @since 5.9.0 Added the `$user`, `$user_custom_post_type_id`,
* and `$i18n_schema` variables to reset.
* @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(
oandregal marked this conversation as resolved.
Show resolved Hide resolved
'core' => array(),
'blocks' => array(),
'theme' => array(),
'user' => array(),
);
static::$theme = null;
static::$user = null;
static::$user_custom_post_type_id = null;
Expand Down
Loading