Skip to content

Commit

Permalink
Editor: resolve patterns server side.
Browse files Browse the repository at this point in the history
See WordPress/gutenberg#60349.
See WordPress/gutenberg#61757.
See WordPress/wordpress-develop#6673.

Fixes #61228.

Props ellatrix, antonvlasenko.


Built from https://develop.svn.wordpress.org/trunk@58303


git-svn-id: http://core.svn.wordpress.org/trunk@57760 1a063a9b-81f0-0310-95a4-ce76da25c4cd
  • Loading branch information
ellatrix committed Jun 3, 2024
1 parent c6d62b1 commit db68e46
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 1 deletion.
77 changes: 77 additions & 0 deletions wp-includes/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -1518,6 +1518,83 @@ function traverse_and_serialize_block( $block, $pre_callback = null, $post_callb
);
}

/**
* Replaces patterns in a block tree with their content.
*
* @since 6.6.0
*
* @param array $blocks An array blocks.
*
* @return array An array of blocks with patterns replaced by their content.
*/
function resolve_pattern_blocks( $blocks ) {
static $inner_content;
// Keep track of seen references to avoid infinite loops.
static $seen_refs = array();
$i = 0;
while ( $i < count( $blocks ) ) {
if ( 'core/pattern' === $blocks[ $i ]['blockName'] ) {
$attrs = $blocks[ $i ]['attrs'];

if ( empty( $attrs['slug'] ) ) {
++$i;
continue;
}

$slug = $attrs['slug'];

if ( isset( $seen_refs[ $slug ] ) ) {
// Skip recursive patterns.
array_splice( $blocks, $i, 1 );
continue;
}

$registry = WP_Block_Patterns_Registry::get_instance();
$pattern = $registry->get_registered( $slug );

// Skip unknown patterns.
if ( ! $pattern ) {
++$i;
continue;
}

$blocks_to_insert = parse_blocks( $pattern['content'] );
$seen_refs[ $slug ] = true;
$prev_inner_content = $inner_content;
$inner_content = null;
$blocks_to_insert = resolve_pattern_blocks( $blocks_to_insert );
$inner_content = $prev_inner_content;
unset( $seen_refs[ $slug ] );
array_splice( $blocks, $i, 1, $blocks_to_insert );

// If we have inner content, we need to insert nulls in the
// inner content array, otherwise serialize_blocks will skip
// blocks.
if ( $inner_content ) {
$null_indices = array_keys( $inner_content, null, true );
$content_index = $null_indices[ $i ];
$nulls = array_fill( 0, count( $blocks_to_insert ), null );
array_splice( $inner_content, $content_index, 1, $nulls );
}

// Skip inserted blocks.
$i += count( $blocks_to_insert );
} else {
if ( ! empty( $blocks[ $i ]['innerBlocks'] ) ) {
$prev_inner_content = $inner_content;
$inner_content = $blocks[ $i ]['innerContent'];
$blocks[ $i ]['innerBlocks'] = resolve_pattern_blocks(
$blocks[ $i ]['innerBlocks']
);
$blocks[ $i ]['innerContent'] = $inner_content;
$inner_content = $prev_inner_content;
}
++$i;
}
}
return $blocks;
}

/**
* Given an array of parsed block trees, applies callbacks before and after serializing them and
* returns their concatenated output.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,12 @@ protected function migrate_pattern_categories( $pattern ) {
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
*/
public function prepare_item_for_response( $item, $request ) {
// Resolve pattern blocks so they don't need to be resolved client-side
// in the editor, improving performance.
$blocks = parse_blocks( $item['content'] );
$blocks = resolve_pattern_blocks( $blocks );
$item['content'] = serialize_blocks( $blocks );

$fields = $this->get_fields_for_response( $request );
$keys = array(
'name' => 'name',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,12 @@ protected function prepare_item_for_database( $request ) {
* @return WP_REST_Response Response object.
*/
public function prepare_item_for_response( $item, $request ) {
// Resolve pattern blocks so they don't need to be resolved client-side
// in the editor, improving performance.
$blocks = parse_blocks( $item->content );
$blocks = resolve_pattern_blocks( $blocks );
$item->content = serialize_blocks( $blocks );

// Restores the more descriptive, specific name for use within this method.
$template = $item;

Expand Down
2 changes: 1 addition & 1 deletion wp-includes/version.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
*
* @global string $wp_version
*/
$wp_version = '6.6-alpha-58299';
$wp_version = '6.6-alpha-58303';

/**
* Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.
Expand Down

0 comments on commit db68e46

Please sign in to comment.