Skip to content

Commit

Permalink
Moves resolution of file paths back to theme_json resolver
Browse files Browse the repository at this point in the history
  • Loading branch information
ramonjd committed May 7, 2024
1 parent 415da7c commit 444bbc6
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 75 deletions.
31 changes: 0 additions & 31 deletions lib/class-wp-theme-json-gutenberg.php
Expand Up @@ -4085,35 +4085,4 @@ protected static function get_valid_block_style_variations() {

return $valid_variations;
}

/**
* Resolves relative paths in theme.json styles to theme absolute paths.
*
* @since 6.6.0
*
* @return WP_Theme_JSON_Gutenberg The current instance of $this.
*/
public function resolve_theme_file_uris() {
if ( empty( $this->theme_json ) ) {
return $this;
}

/*
* Styles backgrounds.
* Where a URL is not absolute (has no host fragment), it is assumed to be relative to the theme directory.
* Blocks, elements, and block variations are not yet supported.
*/
if (
isset( $this->theme_json['styles']['background']['backgroundImage']['url'] ) &&
is_string( $this->theme_json['styles']['background']['backgroundImage']['url'] ) &&
! isset( wp_parse_url( $this->theme_json['styles']['background']['backgroundImage']['url'] )['host'] ) ) {
_wp_array_set(
$this->theme_json,
array( 'styles', 'background', 'backgroundImage', 'url' ),
esc_url( get_theme_file_uri( $this->theme_json['styles']['background']['backgroundImage']['url'] ) )
);
}

return $this;
}
}
49 changes: 44 additions & 5 deletions lib/class-wp-theme-json-resolver-gutenberg.php
Expand Up @@ -604,7 +604,7 @@ public static function get_merged_data( $origin = 'custom' ) {
$result->merge( static::get_core_data() );
if ( 'default' === $origin ) {
$result->set_spacing_sizes();
$result->resolve_theme_file_uris();
$result = static::resolve_theme_file_uris( $result );
return $result;
}

Expand All @@ -616,13 +616,13 @@ public static function get_merged_data( $origin = 'custom' ) {
$result->merge( static::get_theme_data() );
if ( 'theme' === $origin ) {
$result->set_spacing_sizes();
$result->resolve_theme_file_uris();
$result = static::resolve_theme_file_uris( $result );
return $result;
}

$result->merge( static::get_user_data() );
$result->set_spacing_sizes();
$result->resolve_theme_file_uris();
$result = static::resolve_theme_file_uris( $result );
return $result;
}

Expand Down Expand Up @@ -753,8 +753,9 @@ public static function get_style_variations() {
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_Gutenberg( $translated ) )->resolve_theme_file_uris()->get_raw_data();
$translated = static::translate( $decoded_file, wp_get_theme()->get( 'TextDomain' ) );
$with_resolved_paths = static::resolve_theme_file_uris( new WP_Theme_JSON_Gutenberg( $translated ) );
$variation = $with_resolved_paths->get_raw_data();
if ( empty( $variation['title'] ) ) {
$variation['title'] = basename( $path, '.json' );
}
Expand All @@ -763,4 +764,42 @@ public static function get_style_variations() {
}
return $variations;
}


/**
* Resolves relative paths in theme.json styles to theme absolute paths.
*
* @since 6.6.0
*
* @param WP_Theme_JSON_Gutenberg $theme_json A theme json instance.
* @return WP_Theme_JSON_Gutenberg The theme json instance with merged resolved paths.
*/
protected static function resolve_theme_file_uris( $theme_json ) {
if ( ! $theme_json instanceof WP_Theme_JSON_Gutenberg ) {
return $theme_json;
}

$theme_json_data = $theme_json->get_raw_data();
$resolved_theme_json_data = array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
);

/*
* Styles backgrounds.
* Where a URL is not absolute (has no host fragment), it is assumed to be relative to the theme directory.
* Blocks, elements, and block variations are not yet supported.
*/
if (
isset( $theme_json_data['styles']['background']['backgroundImage']['url'] ) &&
is_string( $theme_json_data['styles']['background']['backgroundImage']['url'] ) &&
! isset( wp_parse_url( $theme_json_data['styles']['background']['backgroundImage']['url'] )['host'] ) ) {
$resolved_theme_json_data['styles']['background']['backgroundImage']['url'] = esc_url( get_theme_file_uri( $theme_json_data['styles']['background']['backgroundImage']['url'] ) );
}

if ( ! empty( $resolved_theme_json_data ) ) {
$theme_json->merge( new WP_Theme_JSON_Gutenberg( $resolved_theme_json_data ) );
}

return $theme_json;
}
}
49 changes: 49 additions & 0 deletions phpunit/class-wp-theme-json-resolver-test.php
Expand Up @@ -1139,4 +1139,53 @@ public function test_shadow_default_presets_value_for_block_and_classic_themes()
$default_presets_for_block = $theme_json->get_settings()['shadow']['defaultPresets'];
$this->assertTrue( $default_presets_for_block );
}

/**
* Tests that classic themes still get core default settings such as color palette and duotone.
*/
public function test_resolve_theme_file_uris() {
$theme_json_resolver = new ReflectionClass( 'WP_Theme_JSON_Resolver_Gutenberg' );
$func = $theme_json_resolver->getMethod( 'resolve_theme_file_uris' );

$func->setAccessible( true );

$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'styles' => array(
'background' => array(
'backgroundImage' => array(
'url' => 'example/img/image.png',
),
),
),
)
);

$expected_data = array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'styles' => array(
'background' => array(
'backgroundImage' => array(
'url' => 'https://example.org/wp-content/themes/example-theme/example/img/image.png',
),
),
),
);

/*
* This filter callback normalizes the return value from `get_theme_file_uri`
* to guard against changes in test environments.
* The test suite otherwise returns full system dir path, e.g.,
* /wordpress-phpunit/includes/../data/themedir1/default/example/img/image.png
*/
$filter_theme_file_uri_callback = function ( $file ) {
return 'https://example.org/wp-content/themes/example-theme/example/' . explode( 'example/', $file )[1];
};
add_filter( 'theme_file_uri', $filter_theme_file_uri_callback );
$actual = $func->invoke( null, $theme_json );
remove_filter( 'theme_file_uri', $filter_theme_file_uri_callback );

$this->assertSame( $expected_data, $actual->get_raw_data() );
}
}
39 changes: 0 additions & 39 deletions phpunit/class-wp-theme-json-test.php
Expand Up @@ -4855,45 +4855,6 @@ public function test_get_top_level_background_image_styles() {

$expected_styles = ":where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}:where(body){background-image: url('http://example.org/image.png');background-position: center center;background-repeat: no-repeat;background-size: contain;}";
$this->assertSame( $expected_styles, $theme_json->get_stylesheet(), 'Styles returned from "::get_stylesheet()" with top-level background image as string type does not match expectations' );

$theme_json = new WP_Theme_JSON_Gutenberg(
array(
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
'styles' => array(
'background' => array(
'backgroundImage' => array(
'url' => 'example/img/image.png',
),
),
),
)
);
$expected_data = array(
'styles' => array(
'background' => array(
'backgroundImage' => array(
'url' => 'https://example.org/wp-content/themes/example-theme/example/img/image.png',
),
),
),
'version' => WP_Theme_JSON_Gutenberg::LATEST_SCHEMA,
);
$expected_styles = ":where(body) { margin: 0; }.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}.is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}.is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}.is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){margin-left: auto !important;margin-right: auto !important;}body .is-layout-flex{display: flex;}.is-layout-flex{flex-wrap: wrap;align-items: center;}.is-layout-flex > :is(*, div){margin: 0;}body .is-layout-grid{display: grid;}.is-layout-grid > :is(*, div){margin: 0;}html{min-height: calc(100% - var(--wp-admin--admin-bar--height, 0px));}:where(body){background-image: url('https://example.org/wp-content/themes/example-theme/example/img/image.png');}";

/*
* This filter callback normalizes the return value from `get_theme_file_uri`
* to guard against changes in test environments.
* The test suite otherwise returns full system dir path, e.g.,
* /wordpress-phpunit/includes/../data/themedir1/default/example/img/image.png
*/
$filter_theme_file_uri_callback = function ( $file ) {
return 'https://example.org/wp-content/themes/example-theme/example/' . explode( 'example/', $file )[1];
};
add_filter( 'theme_file_uri', $filter_theme_file_uri_callback );
$this->assertSame( $expected_styles, $theme_json->resolve_theme_file_uris()->get_stylesheet(), 'Styles returned from "::resolve_theme_file_uris()->get_stylesheet()" with resolved top-level theme background images do not match expected string' );
remove_filter( 'theme_file_uri', $filter_theme_file_uri_callback );

$this->assertSame( $expected_data, $theme_json->get_data(), 'Styles returned from "::get_data()" with resolved top-level theme background images do not match expected array' );
}

public function test_get_custom_css_handles_global_custom_css() {
Expand Down

0 comments on commit 444bbc6

Please sign in to comment.