Changeset 58394
- Timestamp:
- 06/12/2024 07:15:06 AM (4 months ago)
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/block-supports/block-style-variations.php
r58264 r58394 214 214 /** 215 215 * Collects block style variation data for merging with theme.json data. 216 * As each block style variation is processed it is registered if it hasn't217 * been already. This registration is required for later sanitization of218 * theme.json data.219 216 * 220 217 * @since 6.6.0 … … 225 222 * @return array Block variations data to be merged under `styles.blocks`. 226 223 */ 227 function wp_resolve_ and_register_block_style_variations( $variations ) {224 function wp_resolve_block_style_variations( $variations ) { 228 225 $variations_data = array(); 229 226 230 227 if ( empty( $variations ) ) { 231 228 return $variations_data; 229 } 230 231 $have_named_variations = ! wp_is_numeric_array( $variations ); 232 233 foreach ( $variations as $key => $variation ) { 234 $supported_blocks = $variation['blockTypes'] ?? array(); 235 236 /* 237 * Standalone theme.json partial files for block style variations 238 * will have their styles under a top-level property by the same name. 239 * Variations defined within an existing theme.json or theme style 240 * variation will themselves already be the required styles data. 241 */ 242 $variation_data = $variation['styles'] ?? $variation; 243 244 if ( empty( $variation_data ) ) { 245 continue; 246 } 247 248 /* 249 * Block style variations read in via standalone theme.json partials 250 * need to have their name set to the kebab case version of their title. 251 */ 252 $variation_name = $have_named_variations ? $key : _wp_to_kebab_case( $variation['title'] ); 253 254 foreach ( $supported_blocks as $block_type ) { 255 // Add block style variation data under current block type. 256 $path = array( $block_type, 'variations', $variation_name ); 257 _wp_array_set( $variations_data, $path, $variation_data ); 258 } 259 } 260 261 return $variations_data; 262 } 263 264 /** 265 * Merges variations data with existing theme.json data ensuring that the 266 * current theme.json data values take precedence. 267 * 268 * @since 6.6.0 269 * @access private 270 * 271 * @param array $variations_data Block style variations data keyed by block type. 272 * @param WP_Theme_JSON_Data $theme_json Current theme.json data. 273 * @param string $origin Origin for the theme.json data. 274 * 275 * @return WP_Theme_JSON The merged theme.json data. 276 */ 277 function wp_merge_block_style_variations_data( $variations_data, $theme_json, $origin = 'theme' ) { 278 if ( empty( $variations_data ) ) { 279 return $theme_json; 280 } 281 282 $variations_theme_json_data = array( 283 'version' => WP_Theme_JSON::LATEST_SCHEMA, 284 'styles' => array( 'blocks' => $variations_data ), 285 ); 286 287 $variations_theme_json = new WP_Theme_JSON_Data( $variations_theme_json_data, $origin ); 288 289 /* 290 * Merge the current theme.json data over shared variation data so that 291 * any explicit per block variation values take precedence. 292 */ 293 return $variations_theme_json->update_with( $theme_json->get_data() ); 294 } 295 296 /** 297 * Merges any shared block style variation definitions from a theme style 298 * variation into their appropriate block type within theme json styles. Any 299 * custom user selections already made will take precedence over the shared 300 * style variation value. 301 * 302 * @since 6.6.0 303 * @access private 304 * 305 * @param WP_Theme_JSON_Data $theme_json Current theme.json data. 306 * 307 * @return WP_Theme_JSON_Data 308 */ 309 function wp_resolve_block_style_variations_from_theme_style_variation( $theme_json ) { 310 $theme_json_data = $theme_json->get_data(); 311 $shared_variations = $theme_json_data['styles']['blocks']['variations'] ?? array(); 312 $variations_data = wp_resolve_block_style_variations( $shared_variations ); 313 314 return wp_merge_block_style_variations_data( $variations_data, $theme_json, 'user' ); 315 } 316 317 /** 318 * Merges block style variation data sourced from standalone partial 319 * theme.json files. 320 * 321 * @since 6.6.0 322 * @access private 323 * 324 * @param WP_Theme_JSON_Data $theme_json Current theme.json data. 325 * 326 * @return WP_Theme_JSON_Data 327 */ 328 function wp_resolve_block_style_variations_from_theme_json_partials( $theme_json ) { 329 $block_style_variations = WP_Theme_JSON_Resolver::get_style_variations( 'block' ); 330 $variations_data = wp_resolve_block_style_variations( $block_style_variations ); 331 332 return wp_merge_block_style_variations_data( $variations_data, $theme_json ); 333 } 334 335 /** 336 * Merges shared block style variations registered within the 337 * `styles.blocks.variations` property of the primary theme.json file. 338 * 339 * @since 6.6.0 340 * @access private 341 * 342 * @param WP_Theme_JSON_Data $theme_json Current theme.json data. 343 * 344 * @return WP_Theme_JSON_Data 345 */ 346 function wp_resolve_block_style_variations_from_primary_theme_json( $theme_json ) { 347 $theme_json_data = $theme_json->get_data(); 348 $block_style_variations = $theme_json_data['styles']['blocks']['variations'] ?? array(); 349 $variations_data = wp_resolve_block_style_variations( $block_style_variations ); 350 351 return wp_merge_block_style_variations_data( $variations_data, $theme_json ); 352 } 353 354 /** 355 * Merges block style variations registered via the block styles registry with a 356 * style object, under their appropriate block types within theme.json styles. 357 * Any variation values defined within the theme.json specific to a block type 358 * will take precedence over these shared definitions. 359 * 360 * @since 6.6.0 361 * @access private 362 * 363 * @param WP_Theme_JSON_Data $theme_json Current theme.json data. 364 * 365 * @return WP_Theme_JSON_Data 366 */ 367 function wp_resolve_block_style_variations_from_styles_registry( $theme_json ) { 368 $registry = WP_Block_Styles_Registry::get_instance(); 369 $styles = $registry->get_all_registered(); 370 $variations_data = array(); 371 372 foreach ( $styles as $block_type => $variations ) { 373 foreach ( $variations as $variation_name => $variation ) { 374 if ( ! empty( $variation['style_data'] ) ) { 375 $path = array( $block_type, 'variations', $variation_name ); 376 _wp_array_set( $variations_data, $path, $variation['style_data'] ); 377 } 378 } 379 } 380 381 return wp_merge_block_style_variations_data( $variations_data, $theme_json ); 382 } 383 384 /** 385 * Enqueues styles for block style variations. 386 * 387 * @since 6.6.0 388 * @access private 389 */ 390 function wp_enqueue_block_style_variation_styles() { 391 wp_enqueue_style( 'block-style-variation-styles' ); 392 } 393 394 // Register the block support. 395 WP_Block_Supports::get_instance()->register( 'block-style-variation', array() ); 396 397 add_filter( 'render_block_data', 'wp_render_block_style_variation_support_styles', 10, 2 ); 398 add_filter( 'render_block', 'wp_render_block_style_variation_class_name', 10, 2 ); 399 add_action( 'wp_enqueue_scripts', 'wp_enqueue_block_style_variation_styles', 1 ); 400 401 // Resolve block style variations from all their potential sources. The order here is deliberate. 402 add_filter( 'wp_theme_json_data_theme', 'wp_resolve_block_style_variations_from_primary_theme_json', 10, 1 ); 403 add_filter( 'wp_theme_json_data_theme', 'wp_resolve_block_style_variations_from_theme_json_partials', 10, 1 ); 404 add_filter( 'wp_theme_json_data_theme', 'wp_resolve_block_style_variations_from_styles_registry', 10, 1 ); 405 406 add_filter( 'wp_theme_json_data_user', 'wp_resolve_block_style_variations_from_theme_style_variation', 10, 1 ); 407 408 /** 409 * Registers any block style variations contained within the provided 410 * theme.json data. 411 * 412 * @since 6.6.0 413 * @access private 414 * 415 * @param array $variations Shared block style variations. 416 */ 417 function wp_register_block_style_variations_from_theme_json_data( $variations ) { 418 if ( empty( $variations ) ) { 419 return $variations; 232 420 } 233 421 … … 270 458 ); 271 459 } 272 273 // Add block style variation data under current block type.274 $path = array( $block_type, 'variations', $variation_name );275 _wp_array_set( $variations_data, $path, $variation_data );276 460 } 277 461 } 278 279 return $variations_data; 280 } 281 282 /** 283 * Merges variations data with existing theme.json data ensuring that the 284 * current theme.json data values take precedence. 285 * 286 * @since 6.6.0 287 * @access private 288 * 289 * @param array $variations_data Block style variations data keyed by block type. 290 * @param WP_Theme_JSON_Data $theme_json Current theme.json data. 291 * @param string $origin Origin for the theme.json data. 292 * 293 * @return WP_Theme_JSON The merged theme.json data. 294 */ 295 function wp_merge_block_style_variations_data( $variations_data, $theme_json, $origin = 'theme' ) { 296 if ( empty( $variations_data ) ) { 297 return $theme_json; 298 } 299 300 $variations_theme_json_data = array( 301 'version' => WP_Theme_JSON::LATEST_SCHEMA, 302 'styles' => array( 'blocks' => $variations_data ), 303 ); 304 305 $variations_theme_json = new WP_Theme_JSON_Data( $variations_theme_json_data, $origin ); 462 } 463 464 /** 465 * Register shared block style variations defined by the theme. 466 * 467 * These can come in three forms: 468 * - the theme's theme.json 469 * - the theme's partials (standalone files in `/styles` that only define block style variations) 470 * - the user's theme.json (for example, theme style variations the user selected) 471 * 472 * @since 6.6.0 473 * @access private 474 */ 475 function wp_register_block_style_variations_from_theme() { 476 // Partials from `/styles`. 477 $variations_partials = WP_Theme_JSON_Resolver::get_style_variations( 'block' ); 478 wp_register_block_style_variations_from_theme_json_data( $variations_partials ); 306 479 307 480 /* 308 * Merge the current theme.json data over shared variation data so that 309 * any explicit per block variation values take precedence. 481 * Pull the data from the specific origin instead of the merged data. 482 * This is because, for 6.6, we only support registering block style variations 483 * for the 'theme' and 'custom' origins but not for 'default' (core theme.json) 484 * or 'custom' (theme.json in a block). 485 * 486 * When/If we add support for every origin, we should switch to using the public API 487 * instead, e.g.: wp_get_global_styles( array( 'blocks', 'variations' ) ). 310 488 */ 311 return $variations_theme_json->update_with( $theme_json->get_data() ); 312 } 313 314 /** 315 * Merges any shared block style variation definitions from a theme style 316 * variation into their appropriate block type within theme json styles. Any 317 * custom user selections already made will take precedence over the shared 318 * style variation value. 319 * 320 * @since 6.6.0 321 * @access private 322 * 323 * @param WP_Theme_JSON_Data $theme_json Current theme.json data. 324 * 325 * @return WP_Theme_JSON_Data 326 */ 327 function wp_resolve_block_style_variations_from_theme_style_variation( $theme_json ) { 328 $theme_json_data = $theme_json->get_data(); 329 $shared_variations = $theme_json_data['styles']['blocks']['variations'] ?? array(); 330 $variations_data = wp_resolve_and_register_block_style_variations( $shared_variations ); 331 332 return wp_merge_block_style_variations_data( $variations_data, $theme_json, 'user' ); 333 } 334 335 /** 336 * Merges block style variation data sourced from standalone partial 337 * theme.json files. 338 * 339 * @since 6.6.0 340 * @access private 341 * 342 * @param WP_Theme_JSON_Data $theme_json Current theme.json data. 343 * 344 * @return WP_Theme_JSON_Data 345 */ 346 function wp_resolve_block_style_variations_from_theme_json_partials( $theme_json ) { 347 $block_style_variations = WP_Theme_JSON_Resolver::get_style_variations( 'block' ); 348 $variations_data = wp_resolve_and_register_block_style_variations( $block_style_variations ); 349 350 return wp_merge_block_style_variations_data( $variations_data, $theme_json ); 351 } 352 353 /** 354 * Merges shared block style variations registered within the 355 * `styles.blocks.variations` property of the primary theme.json file. 356 * 357 * @since 6.6.0 358 * @access private 359 * 360 * @param WP_Theme_JSON_Data $theme_json Current theme.json data. 361 * 362 * @return WP_Theme_JSON_Data 363 */ 364 function wp_resolve_block_style_variations_from_primary_theme_json( $theme_json ) { 365 $theme_json_data = $theme_json->get_data(); 366 $block_style_variations = $theme_json_data['styles']['blocks']['variations'] ?? array(); 367 $variations_data = wp_resolve_and_register_block_style_variations( $block_style_variations ); 368 369 return wp_merge_block_style_variations_data( $variations_data, $theme_json ); 370 } 371 372 /** 373 * Merges block style variations registered via the block styles registry with a 374 * style object, under their appropriate block types within theme.json styles. 375 * Any variation values defined within the theme.json specific to a block type 376 * will take precedence over these shared definitions. 377 * 378 * @since 6.6.0 379 * @access private 380 * 381 * @param WP_Theme_JSON_Data $theme_json Current theme.json data. 382 * 383 * @return WP_Theme_JSON_Data 384 */ 385 function wp_resolve_block_style_variations_from_styles_registry( $theme_json ) { 386 $registry = WP_Block_Styles_Registry::get_instance(); 387 $styles = $registry->get_all_registered(); 388 $variations_data = array(); 389 390 foreach ( $styles as $block_type => $variations ) { 391 foreach ( $variations as $variation_name => $variation ) { 392 if ( ! empty( $variation['style_data'] ) ) { 393 $path = array( $block_type, 'variations', $variation_name ); 394 _wp_array_set( $variations_data, $path, $variation['style_data'] ); 395 } 396 } 397 } 398 399 return wp_merge_block_style_variations_data( $variations_data, $theme_json ); 400 } 401 402 /** 403 * Enqueues styles for block style variations. 404 * 405 * @since 6.6.0 406 * @access private 407 */ 408 function wp_enqueue_block_style_variation_styles() { 409 wp_enqueue_style( 'block-style-variation-styles' ); 410 } 411 412 // Register the block support. 413 WP_Block_Supports::get_instance()->register( 'block-style-variation', array() ); 414 415 add_filter( 'render_block_data', 'wp_render_block_style_variation_support_styles', 10, 2 ); 416 add_filter( 'render_block', 'wp_render_block_style_variation_class_name', 10, 2 ); 417 add_action( 'wp_enqueue_scripts', 'wp_enqueue_block_style_variation_styles', 1 ); 418 419 // Resolve block style variations from all their potential sources. The order here is deliberate. 420 add_filter( 'wp_theme_json_data_theme', 'wp_resolve_block_style_variations_from_primary_theme_json', 10, 1 ); 421 add_filter( 'wp_theme_json_data_theme', 'wp_resolve_block_style_variations_from_theme_json_partials', 10, 1 ); 422 add_filter( 'wp_theme_json_data_theme', 'wp_resolve_block_style_variations_from_styles_registry', 10, 1 ); 423 424 add_filter( 'wp_theme_json_data_user', 'wp_resolve_block_style_variations_from_theme_style_variation', 10, 1 ); 489 490 // theme.json of the theme. 491 $theme_json_theme = WP_Theme_JSON_Resolver::get_theme_data(); 492 $variations_theme = $theme_json_theme->get_data()['styles']['blocks']['variations'] ?? array(); 493 wp_register_block_style_variations_from_theme_json_data( $variations_theme ); 494 495 // User data linked for this theme. 496 $theme_json_user = WP_Theme_JSON_Resolver::get_user_data(); 497 $variations_user = $theme_json_user->get_data()['styles']['blocks']['variations'] ?? array(); 498 wp_register_block_style_variations_from_theme_json_data( $variations_user ); 499 } 500 add_action( 'init', 'wp_register_block_style_variations_from_theme' ); -
trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-global-styles-controller.php
r58262 r58394 232 232 * @since 5.9.0 233 233 * @since 6.2.0 Added validation of styles.css property. 234 * @since 6.6.0 Added registration of newly created style variations provided by the user. 234 235 * 235 236 * @param WP_REST_Request $request Request object. … … 264 265 $config['styles'] = $existing_config['styles']; 265 266 } 267 268 /* 269 * If the incoming request is going to create a new variation 270 * that is not yet registered, we register it here. 271 * This is because the variations are registered on init, 272 * but we want this endpoint to return the new variation immediately: 273 * if we don't register it, it'll be stripped out of the response 274 * just in this request (subsequent ones will be ok). 275 * Take the variations defined in styles.blocks.variations from the incoming request 276 * that are not part of the $exsting_config. 277 */ 278 if ( isset( $request['styles']['blocks']['variations'] ) ) { 279 $existing_variations = isset( $existing_config['styles']['blocks']['variations'] ) ? $existing_config['styles']['blocks']['variations'] : array(); 280 $new_variations = array_diff_key( $request['styles']['blocks']['variations'], $existing_variations ); 281 if ( ! empty( $new_variations ) ) { 282 wp_register_block_style_variations_from_theme_json_data( $new_variations ); 283 } 284 } 285 266 286 if ( isset( $request['settings'] ) ) { 267 287 $config['settings'] = $request['settings']; -
trunk/tests/phpunit/tests/block-supports/block-style-variations.php
r58264 r58394 66 66 switch_theme( 'block-theme' ); 67 67 68 /* 69 * Trigger block style registration that occurs on `init` action. 70 * do_action( 'init' ) could be used here however this direct call 71 * means only the updates being tested are performed. 72 */ 73 wp_register_block_style_variations_from_theme(); 74 68 75 $variation_styles_data = array( 69 76 'color' => array( -
trunk/tests/phpunit/tests/rest-api/rest-global-styles-controller.php
r58328 r58394 604 604 605 605 /** 606 * Tests the submission of a custom block style variation that was defined 607 * within a theme style variation and wouldn't be registered at the time 608 * of saving via the API. 609 * 610 * @covers WP_REST_Global_Styles_Controller_Gutenberg::update_item 611 * @ticket 61312 612 */ 613 public function test_update_item_with_custom_block_style_variations() { 614 wp_set_current_user( self::$admin_id ); 615 if ( is_multisite() ) { 616 grant_super_admin( self::$admin_id ); 617 } 618 619 $group_variations = array( 620 'fromThemeStyleVariation' => array( 621 'color' => array( 622 'background' => '#ffffff', 623 'text' => '#000000', 624 ), 625 ), 626 ); 627 628 $request = new WP_REST_Request( 'PUT', '/wp/v2/global-styles/' . self::$global_styles_id ); 629 $request->set_body_params( 630 array( 631 'styles' => array( 632 'blocks' => array( 633 'variations' => array( 634 'fromThemeStyleVariation' => array( 635 'blockTypes' => array( 'core/group', 'core/columns' ), 636 'color' => array( 637 'background' => '#000000', 638 'text' => '#ffffff', 639 ), 640 ), 641 ), 642 'core/group' => array( 643 'variations' => $group_variations, 644 ), 645 ), 646 ), 647 ) 648 ); 649 $response = rest_get_server()->dispatch( $request ); 650 $data = $response->get_data(); 651 $this->assertSame( $group_variations, $data['styles']['blocks']['core/group']['variations'] ); 652 } 653 654 /** 606 655 * @doesNotPerformAssertions 607 656 */
Note: See TracChangeset
for help on using the changeset viewer.