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.
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. |