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?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
parse_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 );
Method 2
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));
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0