diff --git a/src/wp-includes/class-wp-theme-json-resolver.php b/src/wp-includes/class-wp-theme-json-resolver.php index 53abd0e0be08e..d74cce2a4a5e1 100644 --- a/src/wp-includes/class-wp-theme-json-resolver.php +++ b/src/wp-includes/class-wp-theme-json-resolver.php @@ -664,33 +664,61 @@ public static function clean_cached_data() { static::$i18n_schema = null; } + /** + * Returns an array of all nested json files within a given directory. + * + * @since 6.2.0 + * + * @param string $dir The directory to recursively iterate and list files of. + * @return array The merged array. + */ + private static function recursively_iterate_json( $dir ) { + $nested_files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir ) ); + $nested_json_files = iterator_to_array( new RegexIterator( $nested_files, '/^.+\.json$/i', RecursiveRegexIterator::GET_MATCH ) ); + return $nested_json_files; + } + + /** * Returns the style variations defined by the theme. * * @since 6.0.0 + * @since 6.2.0 Returns parent theme variations if theme is a child. * * @return array */ public static function get_style_variations() { - $variations = array(); - $base_directory = get_stylesheet_directory() . '/styles'; + $variation_files = array(); + $variations = array(); + $base_directory = get_stylesheet_directory() . '/styles'; + $template_directory = get_template_directory() . '/styles'; if ( is_dir( $base_directory ) ) { - $nested_files = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $base_directory ) ); - $nested_html_files = iterator_to_array( new RegexIterator( $nested_files, '/^.+\.json$/i', RecursiveRegexIterator::GET_MATCH ) ); - ksort( $nested_html_files ); - foreach ( $nested_html_files as $path => $file ) { - $decoded_file = wp_json_file_decode( $path, array( 'associative' => true ) ); - if ( is_array( $decoded_file ) ) { - $translated = static::translate( $decoded_file, wp_get_theme()->get( 'TextDomain' ) ); - $variation = ( new WP_Theme_JSON( $translated ) )->get_raw_data(); - if ( empty( $variation['title'] ) ) { - $variation['title'] = basename( $path, '.json' ); + $variation_files = static::recursively_iterate_json( $base_directory ); + } + if ( is_dir( $template_directory ) && $template_directory !== $base_directory ) { + $variation_files_parent = static::recursively_iterate_json( $template_directory ); + // If the child and parent variation file basename are the same, only include the child theme's. + foreach ( $variation_files_parent as $parent_path => $parent ) { + foreach ( $variation_files as $child_path => $child ) { + if ( basename( $parent_path ) === basename( $child_path ) ) { + unset( $variation_files_parent[ $parent_path ] ); } - $variations[] = $variation; } } + $variation_files = array_merge( $variation_files, $variation_files_parent ); + } + ksort( $variation_files ); + foreach ( $variation_files as $path => $file ) { + $decoded_file = wp_json_file_decode( $path, array( 'associative' => true ) ); + if ( is_array( $decoded_file ) ) { + $translated = static::translate( $decoded_file, wp_get_theme()->get( 'TextDomain' ) ); + $variation = ( new WP_Theme_JSON( $translated ) )->get_raw_data(); + if ( empty( $variation['title'] ) ) { + $variation['title'] = basename( $path, '.json' ); + } + $variations[] = $variation; + } } return $variations; } - } diff --git a/tests/phpunit/data/themedir1/block-theme-child/styles/variation-b.json b/tests/phpunit/data/themedir1/block-theme-child/styles/variation-b.json new file mode 100644 index 0000000000000..0a8a4fcab99f6 --- /dev/null +++ b/tests/phpunit/data/themedir1/block-theme-child/styles/variation-b.json @@ -0,0 +1,18 @@ +{ + "version": 2, + "settings": { + "blocks": { + "core/post-title": { + "color": { + "palette": [ + { + "slug": "dark", + "name": "Dark", + "color": "#010101" + } + ] + } + } + } + } +} diff --git a/tests/phpunit/data/themedir1/block-theme/styles/variation-b.json b/tests/phpunit/data/themedir1/block-theme/styles/variation-b.json new file mode 100644 index 0000000000000..340198ffe0b65 --- /dev/null +++ b/tests/phpunit/data/themedir1/block-theme/styles/variation-b.json @@ -0,0 +1,18 @@ +{ + "version": 2, + "settings": { + "blocks": { + "core/post-title": { + "color": { + "palette": [ + { + "slug": "light", + "name": "Light", + "color": "#f1f1f1" + } + ] + } + } + } + } +} diff --git a/tests/phpunit/data/themedir1/block-theme/theme.json b/tests/phpunit/data/themedir1/block-theme/theme.json index d023faec53125..76d075aab7d28 100644 --- a/tests/phpunit/data/themedir1/block-theme/theme.json +++ b/tests/phpunit/data/themedir1/block-theme/theme.json @@ -124,4 +124,4 @@ "area": "header" } ] -} \ No newline at end of file +} diff --git a/tests/phpunit/tests/theme/wpThemeJsonResolver.php b/tests/phpunit/tests/theme/wpThemeJsonResolver.php index 363c756170ed2..ca96a8c6c9683 100644 --- a/tests/phpunit/tests/theme/wpThemeJsonResolver.php +++ b/tests/phpunit/tests/theme/wpThemeJsonResolver.php @@ -235,7 +235,7 @@ public function test_translations_are_applied() { ); $this->assertSame( 'Wariant motywu blokowego', - $style_variations[0]['title'] + $style_variations[1]['title'] ); } @@ -920,10 +920,10 @@ public function test_get_style_variations_returns_all_variations() { $expected_settings = array( array( 'version' => 2, - 'title' => 'variation-a', + 'title' => 'variation-b', 'settings' => array( 'blocks' => array( - 'core/paragraph' => array( + 'core/post-title' => array( 'color' => array( 'palette' => array( 'theme' => array( @@ -941,20 +941,25 @@ public function test_get_style_variations_returns_all_variations() { ), array( 'version' => 2, - 'title' => 'variation-b', + 'title' => 'Block theme variation', 'settings' => array( + 'color' => array( + 'palette' => array( + 'theme' => array( + array( + 'slug' => 'foreground', + 'name' => 'Foreground', + 'color' => '#3F67C6', + ), + ), + ), + ), + ), + 'styles' => array( 'blocks' => array( 'core/post-title' => array( - 'color' => array( - 'palette' => array( - 'theme' => array( - array( - 'slug' => 'light', - 'name' => 'Light', - 'color' => '#f1f1f1', - ), - ), - ), + 'typography' => array( + 'fontWeight' => '700', ), ), ),