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

Performance: Skip iteration in block supports elements when not necessary. #5411

123 changes: 55 additions & 68 deletions src/wp-includes/block-supports/elements.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,90 +31,77 @@ function wp_get_elements_class_name( $block ) {
* @return string Filtered block content.
*/
function wp_render_elements_support( $block_content, $block ) {
if ( ! $block_content || empty( $block['attrs'] ) ) {
if ( ! $block_content || ! isset( $block['attrs']['style']['elements'] ) ) {
return $block_content;
}

$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
$style_attributes = $block['attrs']['style']['elements'];

Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if( ! $block_type ){
return $block_content;
}

Should we do this as well?

$element_color_properties = array(
'button' => array(
'skip' => wp_should_skip_block_supports_serialization( $block_type, 'color', 'button' ),
'paths' => array(
'style.elements.button.color.text',
'style.elements.button.color.background',
'style.elements.button.color.gradient',
),
),
'link' => array(
'skip' => wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' ),
'paths' => array(
'style.elements.link.color.text',
'style.elements.link.:hover.color.text',
),
),
'heading' => array(
'skip' => wp_should_skip_block_supports_serialization( $block_type, 'color', 'heading' ),
'paths' => array(
'style.elements.heading.color.text',
'style.elements.heading.color.background',
'style.elements.heading.color.gradient',
'style.elements.h1.color.text',
'style.elements.h1.color.background',
'style.elements.h1.color.gradient',
'style.elements.h2.color.text',
'style.elements.h2.color.background',
'style.elements.h2.color.gradient',
'style.elements.h3.color.text',
'style.elements.h3.color.background',
'style.elements.h3.color.gradient',
'style.elements.h4.color.text',
'style.elements.h4.color.background',
'style.elements.h4.color.gradient',
'style.elements.h5.color.text',
'style.elements.h5.color.background',
'style.elements.h5.color.gradient',
'style.elements.h6.color.text',
'style.elements.h6.color.background',
'style.elements.h6.color.gradient',
),
),
);
// Button element support.
$supports_button = ! wp_should_skip_block_supports_serialization( $block_type, 'color', 'button' );
$has_button_attrs = isset( $style_attributes['button']['color'] );

$skip_all_element_color_serialization = $element_color_properties['button']['skip'] &&
$element_color_properties['link']['skip'] &&
$element_color_properties['heading']['skip'];
if ( $supports_button && $has_button_attrs ) {
$button_attributes = $style_attributes['button']['color'];

if ( $skip_all_element_color_serialization ) {
return $block_content;
}

$element_colors_set = 0;
if (
isset( $button_attributes['text'] ) ||
isset( $button_attributes['background'] ) ||
isset( $button_attributes['gradient'] )
) {
$tags = new WP_HTML_Tag_Processor( $block_content );
if ( $tags->next_tag() ) {
$tags->add_class( wp_get_elements_class_name( $block ) );
}

foreach ( $element_color_properties as $element_config ) {
if ( $element_config['skip'] ) {
continue;
return $tags->get_updated_html();
}
}

foreach ( $element_config['paths'] as $path ) {
if ( null !== _wp_array_get( $block['attrs'], explode( '.', $path ), null ) ) {
++$element_colors_set;
// Link element support.
$supports_link = ! wp_should_skip_block_supports_serialization( $block_type, 'color', 'link' );
$has_link_attrs = isset( $style_attributes['link'] );

if ( $supports_link && $has_link_attrs ) {
if (
isset( $style_attributes['link']['color']['text'] ) ||
isset( $style_attributes['link'][':hover']['color']['text'] )
) {
$tags = new WP_HTML_Tag_Processor( $block_content );
if ( $tags->next_tag() ) {
$tags->add_class( wp_get_elements_class_name( $block ) );
}

return $tags->get_updated_html();
}
}

if ( ! $element_colors_set ) {
return $block_content;
}
// Heading element support.
$supports_heading = ! wp_should_skip_block_supports_serialization( $block_type, 'color', 'heading' );
if ( $supports_heading ) {
foreach ( array( 'heading', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' ) as $element_name ) {
if ( ! isset( $style_attributes[ $element_name ]['color'] ) ) {
continue;
}

$heading_attributes = $style_attributes[ $element_name ]['color'];
if (
isset( $heading_attributes['text'] ) ||
isset( $heading_attributes['background'] ) ||
isset( $heading_attributes['gradient'] )
) {
$tags = new WP_HTML_Tag_Processor( $block_content );
if ( $tags->next_tag() ) {
$tags->add_class( wp_get_elements_class_name( $block ) );
Copy link
Contributor

@costdev costdev Oct 5, 2023

Choose a reason for hiding this comment

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

Since $block doesn't change per iteration, we can avoid calling wp_get_elements_class_name() (and therefore md5() and serialize()) for each iteration by storing this above the foreach on line 94.

$elements_class_name = wp_get_elements_class_name( $block );

Copy link
Member Author

Choose a reason for hiding this comment

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

this was something I thought at first too but there's actually no iteration here so it only gets called once. once it realized it needs the class name, it finds the first opening HTML tag, adds the class, and then returns from the function.

}

// Like the layout hook this assumes the hook only applies to blocks with a single wrapper.
// Add the class name to the first element, presuming it's the wrapper, if it exists.
$tags = new WP_HTML_Tag_Processor( $block_content );
if ( $tags->next_tag() ) {
$tags->add_class( wp_get_elements_class_name( $block ) );
return $tags->get_updated_html();
}
}
}

return $tags->get_updated_html();
return $block_content;
}

/**
Expand Down