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

Fix wp_head performance regression for classic themes #3536

Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
15 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 32 additions & 16 deletions src/wp-includes/class-wp-theme-json-resolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,14 @@ public static function get_core_data() {
return static::$core;
}

$config = static::read_json_file( __DIR__ . '/theme.json' );
$config = static::translate( $config );
// TODO: Generate 'theme-json.php' at build time which returns fully parsed and translation-ready 'theme.json'
// as a PHP associative array.
if ( file_exists( __DIR__ . '/theme-json.php' ) ) {
$config = require __DIR__ . '/theme-json.php';
} else {
$config = static::read_json_file( __DIR__ . '/theme.json' );
$config = static::translate( $config );
}

/**
* Filters the default data provided by WordPress for global styles & settings.
Expand Down Expand Up @@ -246,8 +252,12 @@ public static function get_theme_data( $deprecated = array(), $options = array()
$options = wp_parse_args( $options, array( 'with_supports' => true ) );

if ( null === static::$theme || ! static::has_same_registered_blocks( 'theme' ) ) {
$theme_json_data = static::read_json_file( static::get_file_path_from_theme( 'theme.json' ) );
$theme_json_data = static::translate( $theme_json_data, wp_get_theme()->get( 'TextDomain' ) );
if ( static::theme_has_support() ) {
$theme_json_data = static::read_json_file( static::get_file_path_from_theme( 'theme.json' ) );
$theme_json_data = static::translate( $theme_json_data, wp_get_theme()->get( 'TextDomain' ) );
} else {
$theme_json_data = array();
}

/**
* Filters the data provided by the theme for global styles and settings.
Expand All @@ -263,16 +273,19 @@ public static function get_theme_data( $deprecated = array(), $options = array()

if ( wp_get_theme()->parent() ) {
// Get parent theme.json.
$parent_theme_json_data = static::read_json_file( static::get_file_path_from_theme( 'theme.json', true ) );
$parent_theme_json_data = static::translate( $parent_theme_json_data, wp_get_theme()->parent()->get( 'TextDomain' ) );
$parent_theme = new WP_Theme_JSON( $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( static::$theme );
static::$theme = $parent_theme;
$parent_theme_json_file = static::get_file_path_from_theme( 'theme.json', true );
if ( $parent_theme_json_file !== '' ) {
desrosj marked this conversation as resolved.
Show resolved Hide resolved
$parent_theme_json_data = static::read_json_file( $parent_theme_json_file );
$parent_theme_json_data = static::translate( $parent_theme_json_data, wp_get_theme()->parent()->get( 'TextDomain' ) );
$parent_theme = new WP_Theme_JSON( $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( static::$theme );
static::$theme = $parent_theme;
}
}

if ( ! $options['with_supports'] ) {
Expand Down Expand Up @@ -400,6 +413,9 @@ private static function remove_json_comments( $array ) {
* @return array Custom Post Type for the user's origin config.
*/
public static function get_user_data_from_wp_global_styles( $theme, $create_post = false, $post_status_filter = array( 'publish' ) ) {
if ( ! static::theme_has_support() ) {
Copy link
Member

Choose a reason for hiding this comment

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

The only edge case I can think of is a theme that uses theme.json and removes it in a later version. In that case, this changes the behavior: the code will now ignore user data while it was used before.

Copy link
Member

Choose a reason for hiding this comment

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

YES! Love this change.

Copy link
Member Author

Choose a reason for hiding this comment

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

That's a fair point. However, I would consider this indeed an edge-case which I don't think is worth addressing here. If a theme removed its theme.json it would come with a whole lot of other behavioral changes anyway - I don't think realistically any theme author is going to change a block theme to become a classic theme.

return array();
}
peterwilsoncc marked this conversation as resolved.
Show resolved Hide resolved
if ( ! $theme instanceof WP_Theme ) {
$theme = wp_get_theme();
}
Expand Down Expand Up @@ -582,8 +598,8 @@ public static function get_user_global_styles_post_id() {
public static function theme_has_support() {
if ( ! isset( static::$theme_has_support ) ) {
static::$theme_has_support = (
is_readable( static::get_file_path_from_theme( 'theme.json' ) ) ||
is_readable( static::get_file_path_from_theme( 'theme.json', true ) )
static::get_file_path_from_theme( '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.

This is nice, get_file_path_from_theme already calls is_readable.

static::get_file_path_from_theme( 'theme.json', true ) !== ''
Comment on lines +605 to +606
Copy link
Contributor

Choose a reason for hiding this comment

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

Yoda

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't think this is needed here. Yoda conditions are only required around variable to value comparisons, not with functions (since setting a function to another value would result in an error anyway).

);
}

Expand Down
3 changes: 2 additions & 1 deletion src/wp-includes/class-wp-theme-json.php
Original file line number Diff line number Diff line change
Expand Up @@ -2934,7 +2934,8 @@ public function get_data() {
public function set_spacing_sizes() {
$spacing_scale = _wp_array_get( $this->theme_json, array( 'settings', 'spacing', 'spacingScale' ), array() );

if ( ! is_numeric( $spacing_scale['steps'] )
if ( ! isset( $spacing_scale['steps'] )
|| ! is_numeric( $spacing_scale['steps'] )
spacedmonkey marked this conversation as resolved.
Show resolved Hide resolved
|| ! isset( $spacing_scale['mediumStep'] )
|| ! isset( $spacing_scale['unit'] )
|| ! isset( $spacing_scale['operator'] )
Expand Down
12 changes: 12 additions & 0 deletions src/wp-includes/theme-json.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php
/**
* Parsed version of WordPress's theme.json file.
*
* TODO: This file should be auto-generated.
*
* @package WordPress
*/

// TODO: Auto-generate this. For now, this was just created using `var_export()` on the parsed `theme.json` data,
// and then manually adding i18n functions around the relevant strings based on `theme-i18n.json`.
return array ( 'version' => 2, 'settings' => array ( 'appearanceTools' => false, 'useRootPaddingAwareAlignments' => false, 'border' => array ( 'color' => false, 'radius' => false, 'style' => false, 'width' => false, ), 'color' => array ( 'background' => true, 'custom' => true, 'customDuotone' => true, 'customGradient' => true, 'defaultDuotone' => true, 'defaultGradients' => true, 'defaultPalette' => true, 'duotone' => array ( 0 => array ( 'name' => _x( 'Dark grayscale', 'Duotone name' ), 'colors' => array ( 0 => '#000000', 1 => '#7f7f7f', ), 'slug' => 'dark-grayscale', ), 1 => array ( 'name' => _x( 'Grayscale', 'Duotone name' ), 'colors' => array ( 0 => '#000000', 1 => '#ffffff', ), 'slug' => 'grayscale', ), 2 => array ( 'name' => _x( 'Purple and yellow', 'Duotone name' ), 'colors' => array ( 0 => '#8c00b7', 1 => '#fcff41', ), 'slug' => 'purple-yellow', ), 3 => array ( 'name' => _x( 'Blue and red', 'Duotone name' ), 'colors' => array ( 0 => '#000097', 1 => '#ff4747', ), 'slug' => 'blue-red', ), 4 => array ( 'name' => _x( 'Midnight', 'Duotone name' ), 'colors' => array ( 0 => '#000000', 1 => '#00a5ff', ), 'slug' => 'midnight', ), 5 => array ( 'name' => _x( 'Magenta and yellow', 'Duotone name' ), 'colors' => array ( 0 => '#c7005a', 1 => '#fff278', ), 'slug' => 'magenta-yellow', ), 6 => array ( 'name' => _x( 'Purple and green' , 'Duotone name' ), 'colors' => array ( 0 => '#a60072', 1 => '#67ff66', ), 'slug' => 'purple-green', ), 7 => array ( 'name' => _x( 'Blue and orange', 'Duotone name' ), 'colors' => array ( 0 => '#1900d8', 1 => '#ffa96b', ), 'slug' => 'blue-orange', ), ), 'gradients' => array ( 0 => array ( 'name' => _x( 'Vivid cyan blue to vivid purple', 'Gradient name' ), 'gradient' => 'linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)', 'slug' => 'vivid-cyan-blue-to-vivid-purple', ), 1 => array ( 'name' => _x( 'Light green cyan to vivid green cyan', 'Gradient name' ), 'gradient' => 'linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%)', 'slug' => 'light-green-cyan-to-vivid-green-cyan', ), 2 => array ( 'name' => _x( 'Luminous vivid amber to luminous vivid orange', 'Gradient name' ), 'gradient' => 'linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%)', 'slug' => 'luminous-vivid-amber-to-luminous-vivid-orange', ), 3 => array ( 'name' => _x( 'Luminous vivid orange to vivid red', 'Gradient name' ), 'gradient' => 'linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%)', 'slug' => 'luminous-vivid-orange-to-vivid-red', ), 4 => array ( 'name' => _x( 'Very light gray to cyan bluish gray', 'Gradient name' ), 'gradient' => 'linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%)', 'slug' => 'very-light-gray-to-cyan-bluish-gray', ), 5 => array ( 'name' => _x( 'Cool to warm spectrum', 'Gradient name' ), 'gradient' => 'linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%)', 'slug' => 'cool-to-warm-spectrum', ), 6 => array ( 'name' => _x( 'Blush light purple', 'Gradient name' ), 'gradient' => 'linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%)', 'slug' => 'blush-light-purple', ), 7 => array ( 'name' => _x( 'Blush bordeaux', 'Gradient name' ), 'gradient' => 'linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%)', 'slug' => 'blush-bordeaux', ), 8 => array ( 'name' => _x( 'Luminous dusk', 'Gradient name' ), 'gradient' => 'linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%)', 'slug' => 'luminous-dusk', ), 9 => array ( 'name' => _x( 'Pale ocean', 'Gradient name' ), 'gradient' => 'linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%)', 'slug' => 'pale-ocean', ), 10 => array ( 'name' => _x( 'Electric grass', 'Gradient name' ), 'gradient' => 'linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%)', 'slug' => 'electric-grass', ), 11 => array ( 'name' => _x( 'Midnight', 'Gradient name' ), 'gradient' => 'linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%)', 'slug' => 'midnight', ), ), 'link' => false, 'palette' => array ( 0 => array ( 'name' => _x( 'Black', 'Color name' ), 'slug' => 'black', 'color' => '#000000', ), 1 => array ( 'name' => _x( 'Cyan bluish gray', 'Color name' ), 'slug' => 'cyan-bluish-gray', 'color' => '#abb8c3', ), 2 => array ( 'name' => _x( 'White', 'Color name' ), 'slug' => 'white', 'color' => '#ffffff', ), 3 => array ( 'name' => _x( 'Pale pink', 'Color name' ), 'slug' => 'pale-pink', 'color' => '#f78da7', ), 4 => array ( 'name' => _x( 'Vivid red', 'Color name' ), 'slug' => 'vivid-red', 'color' => '#cf2e2e', ), 5 => array ( 'name' => _x( 'Luminous vivid orange', 'Color name' ), 'slug' => 'luminous-vivid-orange', 'color' => '#ff6900', ), 6 => array ( 'name' => _x( 'Luminous vivid amber', 'Color name' ), 'slug' => 'luminous-vivid-amber', 'color' => '#fcb900', ), 7 => array ( 'name' => _x( 'Light green cyan', 'Color name' ), 'slug' => 'light-green-cyan', 'color' => '#7bdcb5', ), 8 => array ( 'name' => _x( 'Vivid green cyan', 'Color name' ), 'slug' => 'vivid-green-cyan', 'color' => '#00d084', ), 9 => array ( 'name' => _x( 'Pale cyan blue', 'Color name' ), 'slug' => 'pale-cyan-blue', 'color' => '#8ed1fc', ), 10 => array ( 'name' => _x( 'Vivid cyan blue', 'Color name' ), 'slug' => 'vivid-cyan-blue', 'color' => '#0693e3', ), 11 => array ( 'name' => _x( 'Vivid purple', 'Color name' ), 'slug' => 'vivid-purple', 'color' => '#9b51e0', ), ), 'text' => true, ), 'layout' => array ( 'definitions' => array ( 'default' => array ( 'name' => 'default', 'slug' => 'flow', 'className' => 'is-layout-flow', 'baseStyles' => array ( 0 => array ( 'selector' => ' > .alignleft', 'rules' => array ( 'float' => 'left', 'margin-inline-start' => '0', 'margin-inline-end' => '2em', ), ), 1 => array ( 'selector' => ' > .alignright', 'rules' => array ( 'float' => 'right', 'margin-inline-start' => '2em', 'margin-inline-end' => '0', ), ), 2 => array ( 'selector' => ' > .aligncenter', 'rules' => array ( 'margin-left' => 'auto !important', 'margin-right' => 'auto !important', ), ), ), 'spacingStyles' => array ( 0 => array ( 'selector' => ' > *', 'rules' => array ( 'margin-block-start' => '0', 'margin-block-end' => '0', ), ), 1 => array ( 'selector' => ' > * + *', 'rules' => array ( 'margin-block-start' => NULL, 'margin-block-end' => '0', ), ), ), ), 'constrained' => array ( 'name' => 'constrained', 'slug' => 'constrained', 'className' => 'is-layout-constrained', 'baseStyles' => array ( 0 => array ( 'selector' => ' > .alignleft', 'rules' => array ( 'float' => 'left', 'margin-inline-start' => '0', 'margin-inline-end' => '2em', ), ), 1 => array ( 'selector' => ' > .alignright', 'rules' => array ( 'float' => 'right', 'margin-inline-start' => '2em', 'margin-inline-end' => '0', ), ), 2 => array ( 'selector' => ' > .aligncenter', 'rules' => array ( 'margin-left' => 'auto !important', 'margin-right' => 'auto !important', ), ), 3 => array ( 'selector' => ' > :where(:not(.alignleft):not(.alignright):not(.alignfull))', 'rules' => array ( 'max-width' => 'var(--wp--style--global--content-size)', 'margin-left' => 'auto !important', 'margin-right' => 'auto !important', ), ), 4 => array ( 'selector' => ' > .alignwide', 'rules' => array ( 'max-width' => 'var(--wp--style--global--wide-size)', ), ), ), 'spacingStyles' => array ( 0 => array ( 'selector' => ' > *', 'rules' => array ( 'margin-block-start' => '0', 'margin-block-end' => '0', ), ), 1 => array ( 'selector' => ' > * + *', 'rules' => array ( 'margin-block-start' => NULL, 'margin-block-end' => '0', ), ), ), ), 'flex' => array ( 'name' => 'flex', 'slug' => 'flex', 'className' => 'is-layout-flex', 'displayMode' => 'flex', 'baseStyles' => array ( 0 => array ( 'selector' => '', 'rules' => array ( 'flex-wrap' => 'wrap', 'align-items' => 'center', ), ), 1 => array ( 'selector' => ' > *', 'rules' => array ( 'margin' => '0', ), ), ), 'spacingStyles' => array ( 0 => array ( 'selector' => '', 'rules' => array ( 'gap' => NULL, ), ), ), ), ), ), 'spacing' => array ( 'blockGap' => NULL, 'margin' => false, 'padding' => false, 'customSpacingSize' => true, 'units' => array ( 0 => 'px', 1 => 'em', 2 => 'rem', 3 => 'vh', 4 => 'vw', 5 => '%', ), 'spacingScale' => array ( 'operator' => '*', 'increment' => 1.5, 'steps' => 7, 'mediumStep' => 1.5, 'unit' => 'rem', ), ), 'typography' => array ( 'customFontSize' => true, 'dropCap' => true, 'fontSizes' => array ( 0 => array ( 'name' => _x( 'Small', 'Font size name' ), 'slug' => 'small', 'size' => '13px', ), 1 => array ( 'name' => _x( 'Medium', 'Font size name' ), 'slug' => 'medium', 'size' => '20px', ), 2 => array ( 'name' => _x( 'Large', 'Font size name' ), 'slug' => 'large', 'size' => '36px', ), 3 => array ( 'name' => _x( 'Extra Large', 'Font size name' ), 'slug' => 'x-large', 'size' => '42px', ), ), 'fontStyle' => true, 'fontWeight' => true, 'letterSpacing' => true, 'lineHeight' => false, 'textDecoration' => true, 'textTransform' => true, ), 'blocks' => array ( 'core/button' => array ( 'border' => array ( 'radius' => true, ), ), 'core/pullquote' => array ( 'border' => array ( 'color' => true, 'radius' => true, 'style' => true, 'width' => true, ), ), ), ), 'styles' => array ( 'elements' => array ( 'button' => array ( 'color' => array ( 'text' => '#fff', 'background' => '#32373c', ), 'spacing' => array ( 'padding' => 'calc(0.667em + 2px) calc(1.333em + 2px)', ), 'typography' => array ( 'fontSize' => 'inherit', 'fontFamily' => 'inherit', 'lineHeight' => 'inherit', 'textDecoration' => 'none', ), 'border' => array ( 'width' => '0', ), ), 'link' => array ( 'typography' => array ( 'textDecoration' => 'underline', ), ), ), 'spacing' => array ( 'blockGap' => '24px', 'padding' => array ( 'top' => '0px', 'right' => '0px', 'bottom' => '0px', 'left' => '0px', ), ), ), );