Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FSE: Allow child theme.json to be merged with parent theme.json #35459

Merged
merged 9 commits into from Oct 18, 2021
27 changes: 19 additions & 8 deletions lib/class-wp-theme-json-resolver-gutenberg.php
Expand Up @@ -274,6 +274,18 @@ public static function get_theme_data( $theme_support_data = array() ) {
$theme_json_data = self::read_json_file( self::get_file_path_from_theme( 'theme.json' ) );
$theme_json_data = self::translate( $theme_json_data, wp_get_theme()->get( 'TextDomain' ) );
self::$theme = new WP_Theme_JSON_Gutenberg( $theme_json_data );

if ( wp_get_theme()->parent() ) {
// Get parent theme.json.
$parent_theme_json_data = self::read_json_file( self::get_file_path_from_theme( 'theme.json', true ) );
$parent_theme_json_data = self::translate( $parent_theme_json_data, wp_get_theme()->parent()->get( 'TextDomain' ) );
$parent_theme = new WP_Theme_JSON_Gutenberg( $parent_theme_json_data );

// Merge the child theme.json into the parent theme.json.
// The child theme takes precedence over the parent.
$parent_theme->merge( self::$theme );
self::$theme = $parent_theme;
}
}

if ( empty( $theme_support_data ) ) {
Expand Down Expand Up @@ -476,7 +488,7 @@ public static function get_user_custom_post_type_id() {
*/
public static function theme_has_support() {
if ( ! isset( self::$theme_has_support ) ) {
self::$theme_has_support = (bool) self::get_file_path_from_theme( 'theme.json' );
self::$theme_has_support = is_readable( get_theme_file_path( 'theme.json' ) );
}

return self::$theme_has_support;
Expand All @@ -490,15 +502,14 @@ public static function theme_has_support() {
* otherwise returns the whole file path.
*
* @param string $file_name Name of the file.
* @param bool $template Use template theme directroy. Default: false.
* @return string The whole file path or empty if the file doesn't exist.
*/
private static function get_file_path_from_theme( $file_name ) {
$located = '';
$candidate = get_theme_file_path( $file_name );
if ( is_readable( $candidate ) ) {
$located = $candidate;
}
return $located;
private static function get_file_path_from_theme( $file_name, $template = false ) {
$path = $template ? get_template_directory() : get_stylesheet_directory();
$candidate = $path . '/' . $file_name;

return is_readable( $candidate ) ? $candidate : '';
aristath marked this conversation as resolved.
Show resolved Hide resolved
}

/**
Expand Down
59 changes: 59 additions & 0 deletions phpunit/class-wp-theme-json-resolver-test.php
Expand Up @@ -255,4 +255,63 @@ function test_add_theme_supports_are_loaded_for_themes_without_theme_json() {
$this->assertSame( $color_palette, $settings['color']['palette']['theme'] );
}

function test_merges_child_theme_json_into_parent_theme_json() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In #35759 I tweak a bit the test so that we test that single parts can be updated by the child while the untouched parent sections remain the same (the current tests checks that all the child sections override the parent).

switch_theme( 'fse-child' );

$actual = WP_Theme_JSON_Resolver_Gutenberg::get_theme_data();

// Should merge settings.
$this->assertSame(
array(
'color' => array(
'palette' => array(
'theme' => array(
array(
'slug' => 'light',
'name' => 'Light',
'color' => '#f3f4f6',
),
array(
'slug' => 'primary',
'name' => 'Primary',
'color' => '#3858e9',
),
array(
'slug' => 'dark',
'name' => 'Dark',
'color' => '#111827',
),
),
),
'custom' => true,
),
'blocks' => array(
'core/paragraph' => array(
'color' => array(
'palette' => array(
'theme' => array(
array(
'slug' => 'light',
'name' => 'Light',
'color' => '#f3f4f6',
),
),
),
),
),
),
),
$actual->get_settings()
);

$this->assertSame(
$actual->get_custom_templates(),
array(
'page-home' => array(
'title' => 'Homepage',
'postTypes' => array( 'page' ),
),
)
);
}
}
8 changes: 8 additions & 0 deletions phpunit/data/themedir1/fse-child/style.css
@@ -0,0 +1,8 @@
/*
Theme Name: FSE Child Theme
Theme URI: https://wordpress.org/
Description: For testing purposes only.
Template: fse
Version: 1.0.0
Text Domain: fse-child
*/
51 changes: 51 additions & 0 deletions phpunit/data/themedir1/fse-child/theme.json
@@ -0,0 +1,51 @@
{
"version": 1,
"settings": {
"color": {
"palette": [
{
"slug": "light",
"name": "Light",
"color": "#f3f4f6"
},
{
"slug": "primary",
"name": "Primary",
"color": "#3858e9"
},
{
"slug": "dark",
"name": "Dark",
"color": "#111827"
}
],
"custom": true
},
"blocks": {
"core/paragraph": {
"color": {
"palette": [
{
"slug": "light",
"name": "Light",
"color": "#f3f4f6"
}
]
}
}
}
},
"customTemplates": [
{
"name": "page-home",
"title": "Homepage"
}
],
"templateParts": [
{
"name": "small-header",
"title": "Small Header",
"area": "header"
}
]
}