Make WordPress Core

Changeset 56557


Ignore:
Timestamp:
09/12/2023 01:00:32 PM (7 months ago)
Author:
Bernhard Reiter
Message:

General: Add optional callback argument to serialize_block(s).

Allow passing a function callback to serialize_block(s) that is invoked on each node in the tree of parsed blocks as it is traversed for serialization.

A function argument was chosen for passing the callback function as it reflects a pattern familiar from other algorithms that apply a given callback function while traversing a data structure -- most notably PHP's own array_map().

Introducing a filter was considered as an alternative but ultimately dismissed. For a fairly low-level and general-purpose function such as serialize_block(), using a filter to pass the callback seemed risky, as it also requires removing that filter after usage in order to prevent the callback from being accidentally applied when serialize_block() is called in an entirely different context.

Introducing a separate function for applying a given operation during tree traversal (i.e. independently of serialization) was also considered but dismissed, as it would unnecessarily duplicate tree traversal.

Props dlh, gziolo.
Fixes #59327. See #59313.

Location:
trunk
Files:
2 edited

Legend:

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

    r56527 r56557  
    795795 *
    796796 * @since 5.3.1
    797  *
    798  * @param array $block A representative array of a single parsed block object. See WP_Block_Parser_Block.
     797 * @since 6.4.0 The `$callback` parameter was added.
     798 *
     799 * @param array         $block    A representative array of a single parsed block object. See WP_Block_Parser_Block.
     800 * @param callable|null $callback Optional. Callback to run on each block in the tree before serialization. Default null.
    799801 * @return string String of rendered HTML.
    800802 */
    801 function serialize_block( $block ) {
     803function serialize_block( $block, $callback = null ) {
     804    if ( is_callable( $callback ) ) {
     805        $block = call_user_func( $callback, $block );
     806    }
     807
    802808    $block_content = '';
    803809
    804810    $index = 0;
    805811    foreach ( $block['innerContent'] as $chunk ) {
    806         $block_content .= is_string( $chunk ) ? $chunk : serialize_block( $block['innerBlocks'][ $index++ ] );
     812        $block_content .= is_string( $chunk ) ? $chunk : serialize_block( $block['innerBlocks'][ $index++ ], $callback );
    807813    }
    808814
     
    823829 *
    824830 * @since 5.3.1
    825  *
    826  * @param array[] $blocks An array of representative arrays of parsed block objects. See serialize_block().
     831 * @since 6.4.0 The `$callback` parameter was added.
     832 *
     833 * @param array[]       $blocks   An array of representative arrays of parsed block objects. See serialize_block().
     834 * @param callable|null $callback Optional. Callback to run on each block in the tree before serialization. Default null.
    827835 * @return string String of rendered HTML.
    828836 */
    829 function serialize_blocks( $blocks ) {
    830     return implode( '', array_map( 'serialize_block', $blocks ) );
     837function serialize_blocks( $blocks, $callback = null ) {
     838    $result = '';
     839    foreach ( $blocks as $block ) {
     840        $result .= serialize_block( $block, $callback );
     841    };
     842    return $result;
    831843}
    832844
  • trunk/tests/phpunit/tests/blocks/serialize.php

    r56547 r56557  
    5555        $this->assertSame( 'plugin/example', strip_core_block_namespace( 'plugin/example' ) );
    5656    }
     57
     58    /**
     59     * @ticket 59327
     60     *
     61     * @covers ::serialize_blocks
     62     */
     63    public function test_callback_argument() {
     64        $markup = "<!-- wp:outer --><!-- wp:inner {\"key\":\"value\"} -->Example.<!-- /wp:inner -->\n\nExample.\n\n<!-- wp:void /--><!-- /wp:outer -->";
     65        $blocks = parse_blocks( $markup );
     66
     67        $actual = serialize_blocks( $blocks, array( __CLASS__, 'add_attribute_to_inner_block' ) );
     68
     69        $this->assertSame(
     70            "<!-- wp:outer --><!-- wp:inner {\"key\":\"value\",\"myattr\":\"myvalue\"} -->Example.<!-- /wp:inner -->\n\nExample.\n\n<!-- wp:void /--><!-- /wp:outer -->",
     71            $actual
     72        );
     73    }
     74
     75    public static function add_attribute_to_inner_block( $block ) {
     76        if ( 'core/inner' === $block['blockName'] ) {
     77            $block['attrs']['myattr'] = 'myvalue';
     78        }
     79        return $block;
     80    }
    5781}
Note: See TracChangeset for help on using the changeset viewer.