Make WordPress Core

Changeset 57574


Ignore:
Timestamp:
02/09/2024 10:38:38 AM (3 years ago)
Author:
gziolo
Message:

Editor: Refactor block binding processing and attribute computation

Refactors the processing of block bindings into steps:

  • Gets the value for each "bound" attribute from the respective source.
  • Returns the computer attributes with values from the sources.
  • The computed attributes get injected into block's content.
  • The render_callback gets the updated list of attributes and processeded block content.

Fixes #60282.
Props czapla, gziolo, andraganescu, santosguillamot.

Location:
trunk
Files:
2 edited

Legend:

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

    r57565 r57574  
    193193
    194194        /**
    195          * Processes the block bindings in block's attributes.
     195         * Processes the block bindings and updates the block attributes with the values from the sources.
    196196         *
    197197         * A block might contain bindings in its attributes. Bindings are mappings
    … …  
    200200         * retrieve a value from outside the block, e.g. from post meta.
    201201         *
    202          * This function will process those bindings and replace the HTML with the value of the binding.
    203          * The value is retrieved from the source of the binding.
     202         * This function will process those bindings and update the block's attributes
     203         * with the values coming from the bindings.
    204204         *
    205205         * ### Example
    … …  
    229229         * @since 6.5.0
    230230         *
    231          * @param string $block_content Block content.
    232          * @param array  $block         The full block, including name and attributes.
    233          * @return string The modified block content.
    234          */
    235         private function process_block_bindings( $block_content ) {
     231         * @return array The computed block attributes for the provided block bindings.
     232         */
     233        private function process_block_bindings() {
    236234                $parsed_block = $this->parsed_block;
     235
     236                $computed_attributes = array();
    237237
    238238                // Allowed blocks that support block bindings.
    … …  
    252252                        ! is_array( $parsed_block['attrs']['metadata']['bindings'] )
    253253                ) {
    254                         return $block_content;
    255                 }
    256 
    257                 $modified_block_content = $block_content;
     254                        return $computed_attributes;
     255                }
     256
    258257                foreach ( $parsed_block['attrs']['metadata']['bindings'] as $attribute_name => $block_binding ) {
    259258                        // If the attribute is not in the allowed list, process next attribute.
    … …  
    276275                        // If the value is not null, process the HTML based on the block and the attribute.
    277276                        if ( ! is_null( $source_value ) ) {
    278                                 $modified_block_content = $this->replace_html( $modified_block_content, $attribute_name, $source_value );
    279                         }
    280                 }
    281 
    282                 return $modified_block_content;
     277                                $computed_attributes[ $attribute_name ] = $source_value;
     278                        }
     279                }
     280
     281                return $computed_attributes;
    283282        }
    284283
    … …  
    392391         *
    393392         * @since 5.5.0
     393         * @since 6.5.0 Added block bindings processing.
    394394         *
    395395         * @global WP_Post $post Global post object.
    … …  
    411411                );
    412412
     413                // Process the block bindings and get attributes updated with the values from the sources.
     414                $computed_attributes = $this->process_block_bindings();
     415                if ( ! empty( $computed_attributes ) ) {
     416                        // Merge the computed attributes with the original attributes
     417                        $this->attributes = array_merge( $this->attributes, $computed_attributes );
     418                }
     419
    413420                $is_dynamic    = $options['dynamic'] && $this->name && null !== $this->block_type && $this->block_type->is_dynamic();
    414421                $block_content = '';
    … …  
    446453                }
    447454
     455                if ( ! empty( $computed_attributes ) && ! empty( $block_content ) ) {
     456                        foreach ( $computed_attributes as $attribute_name => $source_value ) {
     457                                $block_content = $this->replace_html( $block_content, $attribute_name, $source_value );
     458                        }
     459                }
     460
    448461                if ( $is_dynamic ) {
    449462                        $global_post = $post;
    … …  
    488501                        }
    489502                }
    490 
    491                 // Process the block bindings for this block, if any are registered. This
    492                 // will replace the block content with the value from a registered binding source.
    493                 $block_content = $this->process_block_bindings( $block_content );
    494503
    495504                /**
  • trunk/tests/phpunit/tests/block-bindings/render.php

    r57526 r57574  
    5353
    5454                $block_content = <<<HTML
    55 <!-- wp:paragraph {"metadata":{"bindings":{"content":{"source":"test/source"}}}} --><p>This should not appear</p><!-- /wp:paragraph -->
     55<!-- wp:paragraph {"metadata":{"bindings":{"content":{"source":"test/source"}}}} -->
     56<p>This should not appear</p>
     57<!-- /wp:paragraph -->
    5658HTML;
    57 
    5859                $parsed_blocks = parse_blocks( $block_content );
    5960                $block         = new WP_Block( $parsed_blocks[0] );
     61                $result        = $block->render();
    6062
    61                 $expected = '<p>test source value</p>';
    62                 $result   = $block->render();
    63 
    64                 $this->assertEquals( $expected, $result, 'The block content should be updated with the value returned by the source.' );
     63                $this->assertSame(
     64                        'test source value',
     65                        $block->attributes['content'],
     66                        "The 'content' attribute should be updated with the value returned by the source."
     67                );
     68                $this->assertSame(
     69                        '<p>test source value</p>',
     70                        trim( $result ),
     71                        'The block content should be updated with the value returned by the source.'
     72                );
    6573        }
    6674
    … …  
    8694                );
    8795
    88                 $value         = 'test';
    8996                $block_content = <<<HTML
    90 <!-- wp:paragraph {"metadata":{"bindings":{"content":{"source":"test/source", "args": {"key": "$value"}}}}} --><p>This should not appear</p><!-- /wp:paragraph -->
     97<!-- wp:paragraph {"metadata":{"bindings":{"content":{"source":"test/source", "args": {"key": "test"}}}}} -->
     98<p>This should not appear</p>
     99<!-- /wp:paragraph -->
    91100HTML;
    92 
    93101                $parsed_blocks = parse_blocks( $block_content );
    94102                $block         = new WP_Block( $parsed_blocks[0] );
     103                $result        = $block->render();
    95104
    96                 $expected = "<p>The attribute name is 'content' and its binding has argument 'key' with value '$value'.</p>";
    97                 $result   = $block->render();
     105                $this->assertSame(
     106                        "The attribute name is 'content' and its binding has argument 'key' with value 'test'.",
     107                        $block->attributes['content'],
     108                        "The 'content' attribute should be updated with the value returned by the source."
     109                );
     110                $this->assertSame(
     111                        "<p>The attribute name is 'content' and its binding has argument 'key' with value 'test'.</p>",
     112                        trim( $result ),
     113                        'The block content should be updated with the value returned by the source.'
     114                );
     115        }
    98116
    99                 $this->assertEquals( $expected, $result, 'The block content should be updated with the value returned by the source.' );
     117        /**
     118         * Tests if the block content is updated with the value returned by the source
     119         * for the Image block in the placeholder state.
     120         *
     121         * @ticket 60282
     122         *
     123         * @covers ::register_block_bindings_source
     124         */
     125        public function test_update_block_with_value_from_source_image_placeholder() {
     126                $get_value_callback = function () {
     127                        return 'https://example.com/image.jpg';
     128                };
     129
     130                register_block_bindings_source(
     131                        self::SOURCE_NAME,
     132                        array(
     133                                'label'              => self::SOURCE_LABEL,
     134                                'get_value_callback' => $get_value_callback,
     135                        )
     136                );
     137
     138                $block_content = <<<HTML
     139<!-- wp:image {"metadata":{"bindings":{"url":{"source":"test/source"}}}} -->
     140<figure class="wp-block-image"><img alt=""/></figure>
     141<!-- /wp:image -->
     142HTML;
     143                $parsed_blocks = parse_blocks( $block_content );
     144                $block         = new WP_Block( $parsed_blocks[0] );
     145                $result        = $block->render();
     146
     147                $this->assertSame(
     148                        'https://example.com/image.jpg',
     149                        $block->attributes['url'],
     150                        "The 'url' attribute should be updated with the value returned by the source."
     151                );
     152                $this->assertSame(
     153                        '<figure class="wp-block-image"><img src="https://example.com/image.jpg" alt=""/></figure>',
     154                        trim( $result ),
     155                        'The block content should be updated with the value returned by the source.'
     156                );
    100157        }
    101158}
Note: See TracChangeset for help on using the changeset viewer.