Skip to content
Open
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
8 changes: 4 additions & 4 deletions src/wp-includes/class-wp-theme-json-resolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ 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' ) ) {
if ( static::has_same_registered_blocks( 'core' ) && null !== static::$core ) {
return static::$core;
}

Expand Down Expand Up @@ -262,7 +262,7 @@ public static function get_theme_data( $deprecated = array(), $options = array()

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

if ( null === static::$theme || ! static::has_same_registered_blocks( 'theme' ) ) {
if ( ! static::has_same_registered_blocks( 'theme' ) || null === static::$theme ) {
$wp_theme = wp_get_theme();
$theme_json_file = $wp_theme->get_file_path( 'theme.json' );
if ( is_readable( $theme_json_file ) ) {
Expand Down Expand Up @@ -407,7 +407,7 @@ 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' ) ) {
if ( static::has_same_registered_blocks( 'blocks' ) && null !== static::$blocks ) {
return static::$blocks;
}

Expand Down Expand Up @@ -555,7 +555,7 @@ 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' ) ) {
if ( static::has_same_registered_blocks( 'user' ) && null !== static::$user ) {
return static::$user;
}

Expand Down
68 changes: 60 additions & 8 deletions tests/phpunit/tests/theme/wpThemeJsonResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,10 @@ public function tear_down() {
unset( $GLOBALS['wp_themes'] );
remove_filter( 'theme_file_uri', array( $this, 'filter_theme_file_uri' ) );

if ( WP_Block_Type_Registry::get_instance()->is_registered( 'test/seeded' ) ) {
unregister_block_type( 'test/seeded' );
}

// Reset data between tests.
wp_clean_theme_json_cache();
parent::tear_down();
Expand Down Expand Up @@ -433,12 +437,10 @@ public function test_get_core_data( $should_fire_filter, $core_is_cached, $block
WP_Theme_JSON_Resolver::get_core_data();
}

// If should cache registered blocks, then set them up before running the tests.
if ( $blocks_are_cached ) {
$blocks_cache = static::$property_blocks_cache->getValue();
$blocks_cache['core'] = $this->get_registered_block_names();
static::$property_blocks_cache->setValue( null, $blocks_cache );
}
// Set the blocks cache to the registered blocks, or empty it: caching core also fills it.
$blocks_cache = static::$property_blocks_cache->getValue();
$blocks_cache['core'] = $blocks_are_cached ? $this->get_registered_block_names() : array();
static::$property_blocks_cache->setValue( null, $blocks_cache );

$expected_filter_count = did_filter( 'wp_theme_json_data_default' );
$actual = WP_Theme_JSON_Resolver::get_core_data();
Expand Down Expand Up @@ -474,13 +476,63 @@ public static function data_get_core_data() {
'blocks_are_cached' => false,
),
'When both caches are not empty' => array(
'should_fire_filter' => true,
'should_fire_filter' => false,
'core_is_cached' => true,
'blocks_are_cached' => false,
'blocks_are_cached' => true,
),
);
}

/**
* The first call to an origin getter should record the registered blocks,
* so the second call reuses the data instead of rebuilding it.
*
* @ticket 62249
*
* @dataProvider data_origin_getters
*
* @covers WP_Theme_JSON_Resolver::get_core_data
* @covers WP_Theme_JSON_Resolver::get_block_data
* @covers WP_Theme_JSON_Resolver::get_theme_data
* @covers WP_Theme_JSON_Resolver::get_user_data
*
* @param string $getter Resolver method name.
* @param list<mixed> $args Arguments for the method.
* @param string $filter Filter the method applies when it builds the data.
*/
public function test_origin_data_is_built_once_while_registered_blocks_are_unchanged( string $getter, array $args, string $filter ): void {
wp_clean_theme_json_cache();
$callback = array( WP_Theme_JSON_Resolver::class, $getter );
$filter_count = did_filter( $filter );

$first = call_user_func_array( $callback, $args );
$this->assertSame( $filter_count + 1, did_filter( $filter ), 'The first call should build the data' );

$second = call_user_func_array( $callback, $args );
$this->assertSame( $filter_count + 1, did_filter( $filter ), 'The second call should not rebuild the data' );
$this->assertSame( $first, $second, 'The second call should return the same object' );

register_block_type( 'test/seeded' );

$third = call_user_func_array( $callback, $args );
$this->assertSame( $filter_count + 2, did_filter( $filter ), 'Registering a block type should rebuild the data' );
$this->assertNotSame( $first, $third, 'The rebuilt data should be a new object' );
}

/**
* Data provider.
*
* @return array<string, array{0: string, 1: list<mixed>, 2: string}>
*/
public static function data_origin_getters(): array {
return array(
'core' => array( 'get_core_data', array(), 'wp_theme_json_data_default' ),
'blocks' => array( 'get_block_data', array(), 'wp_theme_json_data_blocks' ),
'theme' => array( 'get_theme_data', array( array(), array( 'with_supports' => false ) ), 'wp_theme_json_data_theme' ),
'user' => array( 'get_user_data', array(), 'wp_theme_json_data_user' ),
);
}

/**
* @ticket 54336
* @ticket 60118
Expand Down
Loading