Skip to content

Commit

Permalink
Add shared block style variations #57787
Browse files Browse the repository at this point in the history
  • Loading branch information
aaronrobertshaw committed Feb 6, 2024
1 parent cde41e7 commit 8a1ac2c
Show file tree
Hide file tree
Showing 9 changed files with 305 additions and 62 deletions.
1 change: 1 addition & 0 deletions lib/class-wp-theme-json-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,7 @@ class WP_Theme_JSON_Gutenberg {
'patterns',
'settings',
'styles',
'supportedBlockTypes',
'templateParts',
'title',
'version',
Expand Down
55 changes: 51 additions & 4 deletions lib/class-wp-theme-json-resolver-gutenberg.php
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,8 @@ protected static function has_same_registered_blocks( $origin ) {
* @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.
* @since 6.5.0 Theme data will now also include block style variations that were registered with a style object.
* @since 6.5.0 Theme data will now also include block style variations that
* were registered with a style object or included via a standalone file.
*
* @param array $deprecated Deprecated. Not used.
* @param array $options {
Expand Down Expand Up @@ -370,9 +371,53 @@ public static function get_theme_data( $deprecated = array(), $options = array()
$with_theme_supports = new WP_Theme_JSON_Gutenberg( $theme_support_data );

if ( $options['with_block_style_variations'] ) {
// Absorb block style variations that were registered with a style object.
$block_style_variations_data = WP_Theme_JSON_Gutenberg::get_from_block_styles_registry();
$with_block_style_variations = new WP_Theme_JSON_Gutenberg( $block_style_variations_data );
$with_theme_supports->merge( $with_block_style_variations );

// Resolve shared block style variations that were bundled in the
// theme via standalone theme.json files.
$shared_block_style_variations = static::get_style_variations( '/block-styles' );
$variations_data = array();
$registry = WP_Block_Styles_Registry::get_instance();

foreach ( $shared_block_style_variations as $variation ) {
if ( empty( $variation['supportedBlockTypes'] ) || empty( $variation['styles'] ) ) {
continue;
}

$variation_slug = _wp_to_kebab_case( $variation['title'] );

// If it proves desirable, block style variations could include
// custom settings which can be included here.
foreach ( $variation['supportedBlockTypes'] as $block_type ) {
// Automatically register the block style variation if it
// hasn't been already.
$registered_styles = $registry->get_registered_styles_for_block( $block_type );
if ( ! array_key_exists( $variation_slug, $registered_styles ) ) {
gutenberg_register_block_style(
$block_type,
array(
'name' => $variation_slug,
'label' => $variation['title'],
)
);
}

$path = array( $block_type, 'variations', $variation_slug );
_wp_array_set( $variations_data, $path, $variation['styles'] );
}
}

if ( ! empty( $variations_data ) ) {
$variations_theme_json_data = array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'styles' => array( 'blocks' => $variations_data ),
);
$with_shared_variations = new WP_Theme_JSON_Gutenberg( $variations_theme_json_data );
$with_theme_supports->merge( $with_shared_variations );
}
}

$with_theme_supports->merge( static::$theme );
Expand Down Expand Up @@ -740,14 +785,16 @@ private static function recursively_iterate_json( $dir ) {
* Returns the style variations defined by the theme (parent and child).
*
* @since 6.2.0 Returns parent theme variations if theme is a child.
* @since 6.5.0 Added configurable directory to allow block style variations
* to reside in a different directory to theme style variations.
*
* @return array
*/
public static function get_style_variations() {
public static function get_style_variations( $dir = 'styles' ) {
$variation_files = array();
$variations = array();
$base_directory = get_stylesheet_directory() . '/styles';
$template_directory = get_template_directory() . '/styles';
$base_directory = get_stylesheet_directory() . '/' . $dir;
$template_directory = get_template_directory() . '/' . $dir;
if ( is_dir( $base_directory ) ) {
$variation_files = static::recursively_iterate_json( $base_directory );
}
Expand Down
262 changes: 204 additions & 58 deletions phpunit/class-wp-theme-json-resolver-test.php
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,104 @@ public function test_add_theme_supports_are_loaded_for_themes_without_theme_json
$this->assertTrue( $settings['border']['color'], 'Support for "appearance-tools" was not added.' );
}

/**
* Tests that block style variations registered via either
* `gutenberg_register_block_style` with a style object, or a standalone
* block style variation file within `/block-styles`, are added to the
* theme data.
*/
public function test_add_registered_block_styles_to_theme_data() {
switch_theme( 'block-theme' );

$variation_styles_data = array(
'color' => array(
'background' => 'darkslateblue',
'text' => 'lavender',
),
'blocks' => array(
'core/heading' => array(
'color' => array(
'text' => 'violet',
),
),
),
'elements' => array(
'link' => array(
'color' => array(
'text' => 'fuchsia',
),
':hover' => array(
'color' => array(
'text' => 'deeppink',
),
),
),
),
);

register_block_style(
'core/group',
array(
'name' => 'my-variation',
'style_data' => $variation_styles_data,
)
);

$theme_json = WP_Theme_JSON_Resolver_Gutenberg::get_theme_data()->get_raw_data();
$group_styles = $theme_json['styles']['blocks']['core/group'] ?? array();
$expected = array(
'variations' => array(
'my-variation' => $variation_styles_data,
// The following variations are registered automatically from
// their respective JSON files within the theme's `block-styles`
// directory.
'block-style-variation-a' => array(
'color' => array(
'background' => 'indigo',
'text' => 'plum',
),
),
'block-style-variation-b' => array(
'color' => array(
'background' => 'midnightblue',
'text' => 'lightblue',
),
),
),
);

unregister_block_style( 'core/group', 'my-variation' );

$this->assertSameSetsWithIndex( $group_styles, $expected );
}

public function test_registered_block_styles_not_added_to_theme_data_when_option_is_false() {
switch_theme( 'block-theme' );

$variation_styles_data = array(
'color' => array(
'background' => 'darkslateblue',
'text' => 'lavender',
),
);

register_block_style(
'core/group',
array(
'name' => 'my-variation',
'style_data' => $variation_styles_data,
)
);

$options = array( 'with_block_style_variations' => false );
$theme_json = WP_Theme_JSON_Resolver_Gutenberg::get_theme_data( null, $options )->get_raw_data();
$group_styles = $theme_json['styles']['blocks']['core/group'] ?? array();

unregister_block_style( 'core/group', 'my-variation' );

$this->assertArrayNotHasKey( 'variations', $group_styles );
}

/**
* Tests that classic themes still get core default settings such as color palette and duotone.
*/
Expand Down Expand Up @@ -949,94 +1047,142 @@ public function data_get_merged_data_returns_origin() {
}

/**
* Tests that get_style_variations returns all variations, including parent theme variations if the theme is a child,
* and that the child variation overwrites the parent variation of the same name.
* Tests that `get_style_variations` returns all the appropriate variations,
* including parent variations if the theme is a child, and that the child
* variation overwrites the parent variation of the same name.
*
* Note: This covers both theme style variations (`/styles`) and block style
* variations (`/block-styles`).
*
* @covers WP_Theme_JSON_Resolver::get_style_variations
*
* @covers WP_Theme_JSON_Resolver_Gutenberg::get_style_variations
* @dataProvider data_get_style_variations
*
* @param string $theme Name of the theme to use.
* @param string $dir The directory to retrieve variation json files from.
* @param array $expected_variations Collection of expected variations.
*/
public function test_get_style_variations_returns_all_variations() {
// Switch to a child theme.
switch_theme( 'block-theme-child' );
public function test_get_style_variations( $theme, $dir, $expected_variations ) {
switch_theme( $theme );
wp_set_current_user( self::$administrator_id );

$actual_settings = WP_Theme_JSON_Resolver_Gutenberg::get_style_variations();
$expected_settings = array(
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'title' => 'variation-a',
'settings' => array(
'blocks' => array(
'core/paragraph' => array(
'color' => array(
'palette' => array(
'theme' => array(
array(
'slug' => 'dark',
'name' => 'Dark',
'color' => '#010101',
$actual_variations = WP_Theme_JSON_Resolver_Gutenberg::get_style_variations( $dir );

wp_recursive_ksort( $actual_variations );
wp_recursive_ksort( $expected_variations );

$this->assertSame( $expected_variations, $actual_variations );
}

/**
* Data provider for test_get_style_variations
*
* @return array
*/
public function data_get_style_variations() {
return array(
'theme_style_variations' => array(
'theme' => 'block-theme-child',
'dir' => 'styles',
'expected_variations' => array(
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'title' => 'variation-a',
'settings' => array(
'blocks' => array(
'core/paragraph' => array(
'color' => array(
'palette' => array(
'theme' => array(
array(
'slug' => 'dark',
'name' => 'Dark',
'color' => '#010101',
),
),
),
),
),
),
),
),
),
),
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'title' => 'variation-b',
'settings' => array(
'blocks' => array(
'core/post-title' => array(
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'title' => 'variation-b',
'settings' => array(
'blocks' => array(
'core/post-title' => array(
'color' => array(
'palette' => array(
'theme' => array(
array(
'slug' => 'dark',
'name' => 'Dark',
'color' => '#010101',
),
),
),
),
),
),
),
),
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'title' => 'Block theme variation',
'settings' => array(
'color' => array(
'palette' => array(
'theme' => array(
array(
'slug' => 'dark',
'name' => 'Dark',
'color' => '#010101',
'slug' => 'foreground',
'name' => 'Foreground',
'color' => '#3F67C6',
),
),
),
),
),
'styles' => array(
'blocks' => array(
'core/post-title' => array(
'typography' => array(
'fontWeight' => '700',
),
),
),
),
),
),
),
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'title' => 'Block theme variation',
'settings' => array(
'color' => array(
'palette' => array(
'theme' => array(
array(
'slug' => 'foreground',
'name' => 'Foreground',
'color' => '#3F67C6',
),
'block_style_variations' => array(
'theme' => 'block-theme-child-with-block-style-variations',
'dir' => 'block-styles',
'expected_variations' => array(
array(
'supportedBlockTypes' => array( 'core/group', 'core/columns', 'core/media-text' ),
'version' => 2,
'title' => 'block-style-variation-a',
'styles' => array(
'color' => array(
'background' => 'darkcyan',
'text' => 'aliceblue',
),
),
),
),
'styles' => array(
'blocks' => array(
'core/post-title' => array(
'typography' => array(
'fontWeight' => '700',
array(
'supportedBlockTypes' => array( 'core/group', 'core/columns' ),
'version' => 2,
'title' => 'block-style-variation-b',
'styles' => array(
'color' => array(
'background' => 'midnightblue',
'text' => 'lightblue',
),
),
),
),
),
);

wp_recursive_ksort( $actual_settings );
wp_recursive_ksort( $expected_settings );

$this->assertSame(
$expected_settings,
$actual_settings
);
}
}
Loading

0 comments on commit 8a1ac2c

Please sign in to comment.