Changeset 54493
- Timestamp:
- 10/11/2022 05:15:11 PM (2 years ago)
- Location:
- trunk
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/class-wp-theme-json-resolver.php
r54491 r54493 22 22 23 23 /** 24 * Container for keep track of registered blocks. 25 * 26 * @since 6.1.0 27 * @var array 28 */ 29 protected static $blocks_cache = array( 30 'core' => array(), 31 'blocks' => array(), 32 'theme' => array(), 33 'user' => array(), 34 ); 35 36 /** 24 37 * Container for data coming from core. 25 38 * … … 28 41 */ 29 42 protected static $core = null; 43 44 /** 45 * Container for data coming from the blocks. 46 * 47 * @since 6.1.0 48 * @var WP_Theme_JSON 49 */ 50 protected static $blocks = null; 30 51 31 52 /** … … 146 167 */ 147 168 public static function get_core_data() { 169 if ( null !== static::$core && static::has_same_registered_blocks( 'core' ) ) { 170 return static::$core; 171 } 172 148 173 $config = static::read_json_file( __DIR__ . '/theme.json' ); 149 174 $config = static::translate( $config ); … … 164 189 165 190 /** 191 * Checks whether the registered blocks were already processed for this origin. 192 * 193 * @since 6.1.0 194 * 195 * @param string $origin Data source for which to cache the blocks. 196 * Valid values are 'core', 'blocks', 'theme', and 'user'. 197 * @return bool True on success, false otherwise. 198 */ 199 protected static function has_same_registered_blocks( $origin ) { 200 // Bail out if the origin is invalid. 201 if ( ! isset( static::$blocks_cache[ $origin ] ) ) { 202 return false; 203 } 204 205 $registry = WP_Block_Type_Registry::get_instance(); 206 $blocks = $registry->get_all_registered(); 207 208 // Is there metadata for all currently registered blocks? 209 $block_diff = array_diff_key( $blocks, static::$blocks_cache[ $origin ] ); 210 if ( empty( $block_diff ) ) { 211 return true; 212 } 213 214 foreach ( $blocks as $block_name => $block_type ) { 215 static::$blocks_cache[ $origin ][ $block_name ] = true; 216 } 217 218 return false; 219 } 220 221 /** 166 222 * Returns the theme's data. 167 223 * … … 190 246 $options = wp_parse_args( $options, array( 'with_supports' => true ) ); 191 247 192 $theme_json_data = static::read_json_file( static::get_file_path_from_theme( 'theme.json' ) ); 193 $theme_json_data = static::translate( $theme_json_data, wp_get_theme()->get( 'TextDomain' ) ); 194 195 /** 196 * Filters the data provided by the theme for global styles and settings. 197 * 198 * @since 6.1.0 199 * 200 * @param WP_Theme_JSON_Data Class to access and update the underlying data. 201 */ 202 $theme_json = apply_filters( 'theme_json_theme', new WP_Theme_JSON_Data( $theme_json_data, 'theme' ) ); 203 $theme_json_data = $theme_json->get_data(); 204 static::$theme = new WP_Theme_JSON( $theme_json_data ); 248 if ( null === static::$theme || ! static::has_same_registered_blocks( 'theme' ) ) { 249 $theme_json_data = static::read_json_file( static::get_file_path_from_theme( 'theme.json' ) ); 250 $theme_json_data = static::translate( $theme_json_data, wp_get_theme()->get( 'TextDomain' ) ); 251 252 /** 253 * Filters the data provided by the theme for global styles and settings. 254 * 255 * @since 6.1.0 256 * 257 * @param WP_Theme_JSON_Data Class to access and update the underlying data. 258 */ 259 $theme_json = apply_filters( 'theme_json_theme', new WP_Theme_JSON_Data( $theme_json_data, 'theme' ) ); 260 $theme_json_data = $theme_json->get_data(); 261 static::$theme = new WP_Theme_JSON( $theme_json_data ); 262 } 205 263 206 264 if ( wp_get_theme()->parent() ) { … … 259 317 $with_theme_supports = new WP_Theme_JSON( $theme_support_data ); 260 318 $with_theme_supports->merge( static::$theme ); 261 262 319 return $with_theme_supports; 263 320 } … … 273 330 $registry = WP_Block_Type_Registry::get_instance(); 274 331 $blocks = $registry->get_all_registered(); 275 $config = array( 'version' => 2 ); 332 333 if ( null !== static::$blocks && static::has_same_registered_blocks( 'blocks' ) ) { 334 return static::$blocks; 335 } 336 337 $config = array( 'version' => 2 ); 276 338 foreach ( $blocks as $block_name => $block_type ) { 277 339 if ( isset( $block_type->supports['__experimentalStyle'] ) ) { … … 299 361 $config = $theme_json->get_data(); 300 362 301 return new WP_Theme_JSON( $config, 'blocks' ); 363 static::$blocks = new WP_Theme_JSON( $config, 'blocks' ); 364 return static::$blocks; 302 365 } 303 366 … … 408 471 */ 409 472 public static function get_user_data() { 473 if ( null !== static::$user && static::has_same_registered_blocks( 'user' ) ) { 474 return static::$user; 475 } 476 410 477 $config = array(); 411 478 $user_cpt = static::get_user_data_from_wp_global_styles( wp_get_theme() ); … … 563 630 * @since 5.9.0 Added the `$user`, `$user_custom_post_type_id`, 564 631 * and `$i18n_schema` variables to reset. 632 * @since 6.1.0 Added the `$blocks` and `$blocks_cache` variables 633 * to reset. 565 634 */ 566 635 public static function clean_cached_data() { 567 636 static::$core = null; 637 static::$blocks = null; 638 static::$blocks_cache = array( 639 'core' => array(), 640 'blocks' => array(), 641 'theme' => array(), 642 'user' => array(), 643 ); 568 644 static::$theme = null; 569 645 static::$user = null; -
trunk/tests/phpunit/tests/theme/wpThemeJsonResolver.php
r54446 r54493 34 34 private $queries = array(); 35 35 36 /** 37 * WP_Theme_JSON_Resolver::$blocks_cache property. 38 * 39 * @var ReflectionProperty 40 */ 41 private static $property_blocks_cache; 42 43 /** 44 * Original value of the WP_Theme_JSON_Resolver::$blocks_cache property. 45 * 46 * @var array 47 */ 48 private static $property_blocks_cache_orig_value; 49 50 /** 51 * WP_Theme_JSON_Resolver::$core property. 52 * 53 * @var ReflectionProperty 54 */ 55 private static $property_core; 56 57 /** 58 * Original value of the WP_Theme_JSON_Resolver::$core property. 59 * 60 * @var WP_Theme_JSON 61 */ 62 private static $property_core_orig_value; 63 64 public static function set_up_before_class() { 65 parent::set_up_before_class(); 66 67 static::$property_blocks_cache = new ReflectionProperty( WP_Theme_JSON_Resolver::class, 'blocks_cache' ); 68 static::$property_blocks_cache->setAccessible( true ); 69 static::$property_blocks_cache_orig_value = static::$property_blocks_cache->getValue(); 70 71 static::$property_core = new ReflectionProperty( WP_Theme_JSON_Resolver::class, 'core' ); 72 static::$property_core->setAccessible( true ); 73 static::$property_core_orig_value = static::$property_core->getValue(); 74 } 75 76 public static function tear_down_after_class() { 77 static::$property_blocks_cache->setValue( WP_Theme_JSON_Resolver::class, static::$property_blocks_cache_orig_value ); 78 static::$property_core->setValue( WP_Theme_JSON_Resolver::class, static::$property_core_orig_value ); 79 parent::tear_down_after_class(); 80 } 81 36 82 public function set_up() { 37 83 parent::set_up(); … … 56 102 wp_clean_themes_cache(); 57 103 unset( $GLOBALS['wp_themes'] ); 104 105 // Reset data between tests. 106 WP_Theme_JSON_Resolver::clean_cached_data(); 58 107 parent::tear_down(); 59 108 } … … 191 240 } 192 241 242 private function get_registered_block_names( $hard_reset = false ) { 243 static $expected_block_names; 244 245 if ( ! $hard_reset && ! empty( $expected_block_names ) ) { 246 return $expected_block_names; 247 } 248 249 $expected_block_names = array(); 250 $resolver = WP_Block_Type_Registry::get_instance(); 251 $blocks = $resolver->get_all_registered(); 252 foreach ( array_keys( $blocks ) as $block_name ) { 253 $expected_block_names[ $block_name ] = true; 254 } 255 256 return $expected_block_names; 257 } 258 259 /** 260 * Tests when WP_Theme_JSON_Resolver::$blocks_cache is empty or does not match 261 * the all registered blocks. 262 * 263 * Though this is a non-public method, it is vital to other functionality. 264 * Therefore, tests are provided to validate it functions as expected. 265 * 266 * @dataProvider data_has_same_registered_blocks_when_all_blocks_not_cached 267 * @ticket 56467 268 * 269 * @param string $origin The origin to test. 270 */ 271 public function test_has_same_registered_blocks_when_all_blocks_not_cached( $origin, array $cache = array() ) { 272 $has_same_registered_blocks = new ReflectionMethod( WP_Theme_JSON_Resolver::class, 'has_same_registered_blocks' ); 273 $has_same_registered_blocks->setAccessible( true ); 274 $expected_cache = $this->get_registered_block_names(); 275 276 // Set up the blocks cache for the origin. 277 $blocks_cache = static::$property_blocks_cache->getValue(); 278 $blocks_cache[ $origin ] = $cache; 279 static::$property_blocks_cache->setValue( null, $blocks_cache ); 280 281 $this->assertFalse( $has_same_registered_blocks->invoke( null, $origin ), 'WP_Theme_JSON_Resolver::has_same_registered_blocks() should return false when same blocks are not cached' ); 282 $blocks_cache = static::$property_blocks_cache->getValue(); 283 $this->assertSameSets( $expected_cache, $blocks_cache[ $origin ], 'WP_Theme_JSON_Resolver::$blocks_cache should contain all expected block names for the given origin' ); 284 } 285 286 /** 287 * Data provider. 288 * 289 * @return array 290 */ 291 public function data_has_same_registered_blocks_when_all_blocks_not_cached() { 292 return array( 293 'origin: core; cache: empty' => array( 294 'origin' => 'core', 295 ), 296 'origin: blocks; cache: empty' => array( 297 'origin' => 'blocks', 298 ), 299 'origin: theme; cache: empty' => array( 300 'origin' => 'theme', 301 ), 302 'origin: user; cache: empty' => array( 303 'origin' => 'user', 304 ), 305 'origin: core; cache: not empty' => array( 306 'origin' => 'core', 307 'cache' => array( 308 'core/block' => true, 309 ), 310 ), 311 'origin: blocks; cache: not empty' => array( 312 'origin' => 'blocks', 313 'cache' => array( 314 'core/block' => true, 315 'core/comments' => true, 316 ), 317 ), 318 'origin: theme; cache: not empty' => array( 319 'origin' => 'theme', 320 'cache' => array( 321 'core/cover' => true, 322 ), 323 ), 324 'origin: user; cache: not empty' => array( 325 'origin' => 'user', 326 'cache' => array( 327 'core/gallery' => true, 328 ), 329 ), 330 ); 331 } 332 333 /** 334 * Tests when WP_Theme_JSON_Resolver::$blocks_cache is empty or does not match 335 * the all registered blocks. 336 * 337 * Though this is a non-public method, it is vital to other functionality. 338 * Therefore, tests are provided to validate it functions as expected. 339 * 340 * @dataProvider data_has_same_registered_blocks_when_all_blocks_are_cached 341 * @ticket 56467 342 * 343 * @param string $origin The origin to test. 344 */ 345 public function test_has_same_registered_blocks_when_all_blocks_are_cached( $origin ) { 346 $has_same_registered_blocks = new ReflectionMethod( WP_Theme_JSON_Resolver::class, 'has_same_registered_blocks' ); 347 $has_same_registered_blocks->setAccessible( true ); 348 $expected_cache = $this->get_registered_block_names(); 349 350 // Set up the cache with all registered blocks. 351 $blocks_cache = static::$property_blocks_cache->getValue(); 352 $blocks_cache[ $origin ] = $this->get_registered_block_names(); 353 static::$property_blocks_cache->setValue( null, $blocks_cache ); 354 355 $this->assertTrue( $has_same_registered_blocks->invoke( null, $origin ), 'WP_Theme_JSON_Resolver::has_same_registered_blocks() should return true when using the cache' ); 356 $this->assertSameSets( $expected_cache, $blocks_cache[ $origin ], 'WP_Theme_JSON_Resolver::$blocks_cache should contain all expected block names for the given origin' ); 357 } 358 359 /** 360 * Data provider. 361 * 362 * @return array 363 */ 364 public function data_has_same_registered_blocks_when_all_blocks_are_cached() { 365 return array( 366 'core' => array( 'core' ), 367 'blocks' => array( 'blocks' ), 368 'theme' => array( 'theme' ), 369 'user' => array( 'user' ), 370 ); 371 } 372 373 /** 374 * @dataProvider data_get_core_data 375 * @covers WP_Theme_JSON_Resolver::get_core_data 376 * @ticket 56467 377 */ 378 public function test_get_core_data( $should_fire_filter, $core_is_cached, $blocks_are_cached ) { 379 WP_Theme_JSON_Resolver::clean_cached_data(); 380 381 // If should cache core, then fire the method to cache it before running the tests. 382 if ( $core_is_cached ) { 383 WP_Theme_JSON_Resolver::get_core_data(); 384 } 385 386 // If should cache registered blocks, then set them up before running the tests. 387 if ( $blocks_are_cached ) { 388 $blocks_cache = static::$property_blocks_cache->getValue(); 389 $blocks_cache['core'] = $this->get_registered_block_names(); 390 static::$property_blocks_cache->setValue( null, $blocks_cache ); 391 } 392 393 $expected_filter_count = did_filter( 'theme_json_default' ); 394 $actual = WP_Theme_JSON_Resolver::get_core_data(); 395 if ( $should_fire_filter ) { 396 $expected_filter_count++; 397 } 398 399 $this->assertSame( $expected_filter_count, did_filter( 'theme_json_default' ), 'The filter "theme_json_default" should fire the given number of times' ); 400 $this->assertInstanceOf( WP_Theme_JSON::class, $actual, 'WP_Theme_JSON_Resolver::get_core_data() should return instance of WP_Theme_JSON' ); 401 $this->assertSame( static::$property_core->getValue(), $actual, 'WP_Theme_JSON_Resolver::$core property should be the same object as returned from WP_Theme_JSON_Resolver::get_core_data()' ); 402 } 403 404 /** 405 * Data provider. 406 * 407 * @return array 408 */ 409 public function data_get_core_data() { 410 return array( 411 'When both caches are empty' => array( 412 'should_fire_filter' => true, 413 'core_is_cached' => false, 414 'blocks_are_cached' => false, 415 ), 416 'When the blocks_cache is not empty and matches' => array( 417 'should_fire_filter' => true, 418 'core_is_cached' => false, 419 'blocks_are_cached' => true, 420 ), 421 'When blocks_cache is empty but core cache is not' => array( 422 'should_fire_filter' => true, 423 'core_is_cached' => true, 424 'blocks_are_cached' => false, 425 ), 426 'When both caches are not empty' => array( 427 'should_fire_filter' => true, 428 'core_is_cached' => true, 429 'blocks_are_cached' => false, 430 ), 431 ); 432 } 433 193 434 /** 194 435 * @ticket 52991
Note: See TracChangeset
for help on using the changeset viewer.