parsing nested blocks (in columns, etc) via PHP

I’m checking posts for a custom block and trying to render the content of those blocks elsewhere in the site via PHP. My method for doing that looks like this:

      if ( has_block( 'custom/block' ) ) {
        global $post;

        $blocks = parse_blocks( $post->post_content );
        foreach ( $blocks as $block ) {
          if ( 'custom/block' === $block['blockName'] ) {
              echo "<div>";
              echo apply_filters( 'the_content', render_block( $block ) );
              echo "</div>";
              break;
          } 
      }

So I basically check the post for a specific block, when I find it I output its contents, then break the loop because I only care about the first one. The problem is that when you put the ‘custom/block’ in a column block (or anything similar I’m assuming) then this loop will miss it. I’m not sure how to effectively investigate a block’s innerblocks to solve this problem, other than something like iterating over all possible parent blocks and checking their guts like so:

      if ( has_block( 'custom/block' ) ) {
        global $post;

        $blocks = parse_blocks( $post->post_content );
        foreach ( $blocks as $block ) {
          if ( 'custom/block' === $block['blockName'] ) {
              echo "<div>";
              echo apply_filters( 'the_content', render_block( $block ) );
              echo "</div>";
              break;
          } elseif ( 'core/columns' === $block['blockName'] ) {
            $column = apply_filters( 'the_content', render_block( $block ) );
            // mess around with the $column here to get the appropriate equivalent output
          }
          // elseif iterate through other potential parent blocks
      }

Any suggestions to make this less messy?

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

If I understand it correctly, you can use a recursive function which loops through inner blocks to find the specific block. Example:

/* Sample usage, assuming $post is defined properly:

    $blocks = parse_blocks( $post->post_content );
    wpse_387661( $blocks );
*/
function wpse_387661( $blocks ) {
    foreach ( $blocks as $block ) {
        if ( ! empty( $block['innerBlocks'] ) ) {
             wpse_387661( $block['innerBlocks'] );
        } elseif ( 'custom/block' === $block['blockName'] ) {
            echo apply_filters( 'the_content', render_block( $block ) );
            break; // this could mean that inner blocks were never looped
        }
    }
}


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

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x