Make WordPress Core

Changeset 58398

Timestamp:
06/13/2024 08:55:47 AM (8 weeks ago)
Author:
audrasjb
Message:

HTML API: Revert using regex in block bindings HTML replacement logic.

This changeset reverts part of the changes made in [58298] to avoid using regex that can cause potential bugs. It is indeed safer to revert these changes for now and do the refactoring once the HTML API supports CSS selectors and provides a way to set inner content.

It also adds a unit test to cover the regression experienced in https://github.com/WordPress/gutenberg/issues/62347.

Follow-up to [58298].

Props santosguillamot, gziolo.
Fixes #61385.
See #61351.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-block.php

    r58298 r58398  
    334334            case 'html':
    335335            case 'rich-text':
    336                 // Hardcode the selectors and processing until the HTML API is able to read CSS selectors and replace inner HTML.
    337                 // TODO: Use the HTML API instead.
    338                 if ( 'core/paragraph' === $this->name && 'content' === $attribute_name ) {
    339                     $selector = 'p';
    340                 }
    341                 if ( 'core/heading' === $this->name && 'content' === $attribute_name ) {
    342                     $selector = 'h[1-6]';
    343                 }
    344                 if ( 'core/button' === $this->name && 'text' === $attribute_name ) {
    345                     // Check if it is a <button> or <a> tag.
    346                     if ( preg_match( '/<button[^>]*>.*?<\/button>/', $block_content ) ) {
    347                         $selector = 'button';
    348                     } else {
    349                         $selector = 'a';
     336                $block_reader = new WP_HTML_Tag_Processor( $block_content );
     337
     338                // TODO: Support for CSS selectors whenever they are ready in the HTML API.
     339                // In the meantime, support comma-separated selectors by exploding them into an array.
     340                $selectors = explode( ',', $block_type->attributes[ $attribute_name ]['selector'] );
     341                // Add a bookmark to the first tag to be able to iterate over the selectors.
     342                $block_reader->next_tag();
     343                $block_reader->set_bookmark( 'iterate-selectors' );
     344
     345                // TODO: This shouldn't be needed when the `set_inner_html` function is ready.
     346                // Store the parent tag and its attributes to be able to restore them later in the button.
     347                // The button block has a wrapper while the paragraph and heading blocks don't.
     348                if ( 'core/button' === $this->name ) {
     349                    $button_wrapper                 = $block_reader->get_tag();
     350                    $button_wrapper_attribute_names = $block_reader->get_attribute_names_with_prefix( '' );
     351                    $button_wrapper_attrs           = array();
     352                    foreach ( $button_wrapper_attribute_names as $name ) {
     353                        $button_wrapper_attrs[ $name ] = $block_reader->get_attribute( $name );
    350354                    }
    351355                }
    352                 if ( empty( $selector ) ) {
    353                     return $block_content;
     356
     357                foreach ( $selectors as $selector ) {
     358                    // If the parent tag, or any of its children, matches the selector, replace the HTML.
     359                    if ( strcasecmp( $block_reader->get_tag( $selector ), $selector ) === 0 || $block_reader->next_tag(
     360                        array(
     361                            'tag_name' => $selector,
     362                        )
     363                    ) ) {
     364                        $block_reader->release_bookmark( 'iterate-selectors' );
     365
     366                        // TODO: Use `set_inner_html` method whenever it's ready in the HTML API.
     367                        // Until then, it is hardcoded for the paragraph, heading, and button blocks.
     368                        // Store the tag and its attributes to be able to restore them later.
     369                        $selector_attribute_names = $block_reader->get_attribute_names_with_prefix( '' );
     370                        $selector_attrs           = array();
     371                        foreach ( $selector_attribute_names as $name ) {
     372                            $selector_attrs[ $name ] = $block_reader->get_attribute( $name );
     373                        }
     374                        $selector_markup = "<$selector>" . wp_kses_post( $source_value ) . "</$selector>";
     375                        $amended_content = new WP_HTML_Tag_Processor( $selector_markup );
     376                        $amended_content->next_tag();
     377                        foreach ( $selector_attrs as $attribute_key => $attribute_value ) {
     378                            $amended_content->set_attribute( $attribute_key, $attribute_value );
     379                        }
     380                        if ( 'core/paragraph' === $this->name || 'core/heading' === $this->name ) {
     381                            return $amended_content->get_updated_html();
     382                        }
     383                        if ( 'core/button' === $this->name ) {
     384                            $button_markup  = "<$button_wrapper>{$amended_content->get_updated_html()}</$button_wrapper>";
     385                            $amended_button = new WP_HTML_Tag_Processor( $button_markup );
     386                            $amended_button->next_tag();
     387                            foreach ( $button_wrapper_attrs as $attribute_key => $attribute_value ) {
     388                                $amended_button->set_attribute( $attribute_key, $attribute_value );
     389                            }
     390                            return $amended_button->get_updated_html();
     391                        }
     392                    } else {
     393                        $block_reader->seek( 'iterate-selectors' );
     394                    }
    354395                }
    355                 $pattern = '/(<' . $selector . '[^>]*>).*?(<\/' . $selector . '>)/i';
    356                 return preg_replace( $pattern, '$1' . wp_kses_post( $source_value ) . '$2', $block_content );
     396                $;
     397                return ;
    357398
    358399            case 'attribute':
  • trunk/tests/phpunit/tests/block-bindings/render.php

    r58289 r58398  
    237237
    238238    /**
     239
     240
     241
     242
     243
     244
     245
     246
     247
     248
     249
     250
     251
     252
     253
     254
     255
     256
     257
     258
     259
     260
     261
     262
     263
     264
     265
     266
     267
     268
     269
     270
     271
     272
     273
     274
    239275     * Tests if the `__default` attribute is replaced with real attribues for
    240276     * pattern overrides.
Note: See TracChangeset for help on using the changeset viewer.