I struggle with columns block in my plugin. I try to filter all blocks of the type "heading":
$post = get_post();
$blocks = parse_blocks($post->post_content);
$headings = array_values(array_filter($blocks, function ($block) {
return $block['blockName'] === 'core/heading';
}));
This returns an array of all heading block. But if the post contains columns the array $blocks is a nested multidimensional array. array_filter does not select blocks nested like this:
}
[1]=>
array(5) {
["blockName"]=>
string(11) "core/column"
["attrs"]=>
array(0) {
}
["innerBlocks"]=>
array(4) {
[0]=>
array(5) {
["blockName"]=>
string(12) "core/heading"
["attrs"]=>
array(0) {
}
["innerBlocks"]=>
array(0) {
}
["innerHTML"]=>
string(26) "
<h2>HEADING.COLUMN1</h2>
"
["innerContent"]=>
array(1) {
[0]=>
string(26) "
<h2>HEADING.COLUMN1</h2>
"
}
}
Is there a way to select only heading blocks with parse_blocks or some other clever way?
I struggle with columns block in my plugin. I try to filter all blocks of the type "heading":
$post = get_post();
$blocks = parse_blocks($post->post_content);
$headings = array_values(array_filter($blocks, function ($block) {
return $block['blockName'] === 'core/heading';
}));
This returns an array of all heading block. But if the post contains columns the array $blocks is a nested multidimensional array. array_filter does not select blocks nested like this:
}
[1]=>
array(5) {
["blockName"]=>
string(11) "core/column"
["attrs"]=>
array(0) {
}
["innerBlocks"]=>
array(4) {
[0]=>
array(5) {
["blockName"]=>
string(12) "core/heading"
["attrs"]=>
array(0) {
}
["innerBlocks"]=>
array(0) {
}
["innerHTML"]=>
string(26) "
<h2>HEADING.COLUMN1</h2>
"
["innerContent"]=>
array(1) {
[0]=>
string(26) "
<h2>HEADING.COLUMN1</h2>
"
}
}
Is there a way to select only heading blocks with parse_blocks or some other clever way?
Share Improve this question edited Feb 18, 2021 at 20:03 Marc asked Feb 18, 2021 at 19:18 MarcMarc 6979 silver badges28 bronze badges2 Answers
Reset to default 4parse_blocks()
simply returns all blocks found in the post content, so for what you're trying to get, you could use a function which calls itself recursively like so:
function my_find_heading_blocks( $blocks ) {
$list = array();
foreach ( $blocks as $block ) {
if ( 'core/heading' === $block['blockName'] ) {
// add current item, if it's a heading block
$list[] = $block;
} elseif ( ! empty( $block['innerBlocks'] ) ) {
// or call the function recursively, to find heading blocks in inner blocks
$list = array_merge( $list, my_find_heading_blocks( $block['innerBlocks'] ) );
}
}
return $list;
}
// Sample usage:
$post = get_post();
$blocks = parse_blocks( $post->post_content );
$headings = my_find_heading_blocks( $blocks );
I used this:
function recurse($blocks) {
$arr = array();
foreach ($blocks as $block => $innerBlock) {
if (is_array($innerBlock) ) {
$arr = array_merge(recurse($innerBlock),$arr);
} else {
if ( isset($blocks['blockName']) && $blocks['blockName'] === 'core/heading' && $innerBlock !== 'core/heading') {
$arr[] = $innerBlock;
}
}
}
return $arr;
}
$headings = array_reverse(recurse($blocks));