函数文档

resolve_pattern_blocks()

💡 云策文档标注

概述

resolve_pattern_blocks() 是一个 WordPress 函数,用于递归遍历块树,将注册的模式(patterns)替换为其实际内容。它处理嵌套块和内部内容,避免无限循环。

关键要点

  • 函数接收一个块数组作为参数,返回替换模式后的块数组。
  • 使用静态变量跟踪已见引用以防止无限递归。
  • 通过 WP_Block_Patterns_Registry 获取注册的模式,跳过未知模式。
  • 递归处理 innerBlocks 以替换嵌套块中的模式。
  • 在替换时调整 innerContent 数组,确保序列化正确。
  • 首次引入于 WordPress 6.6.0 版本。

代码示例

function resolve_pattern_blocks( $blocks ) {
    static $inner_content;
    static $seen_refs = array();
    $i = 0;
    while ( $i < count( $blocks ) ) {
        $block = &$blocks[$i];
        if ( isset( $block['blockName'] ) && 'core/pattern' === $block['blockName'] ) {
            $slug = $block['attrs']['slug'];
            if ( isset( $seen_refs[$slug] ) ) {
                ++$i;
                continue;
            }
            $pattern = WP_Block_Patterns_Registry::get_instance()->get_registered( $slug );
            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 ( $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 );
            }
            $i += count( $blocks_to_insert );
        } else {
            if ( ! empty( $block['innerBlocks'] ) ) {
                $prev_inner_content = $inner_content;
                $inner_content = $block['innerContent'];
                $block['innerBlocks'] = resolve_pattern_blocks( $block['innerBlocks'] );
                $block['innerContent'] = $inner_content;
                $inner_content = $prev_inner_content;
            }
            ++$i;
        }
    }
    return $blocks;
}

注意事项

  • 函数是递归的,需注意性能影响,特别是在处理大型块树时。
  • 依赖 WP_Block_Patterns_Registry 来获取模式,确保模式已正确注册。
  • 内部使用静态变量,可能影响多线程环境或并发调用。

📄 原文内容

Replaces patterns in a block tree with their content.

Parameters

$blocksarrayrequired
An array blocks.

Return

array An array of blocks with patterns replaced by their content.

Source

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;
}

Changelog

Version Description
6.6.0 Introduced.