admin管理员组

文章数量:1125734

I have a block, say, elseloop/this-block, that was turned into a pattern on one page that it was included on. It is always displayed in an odd spot in the layout, so I want to pull it out of the content and then place it programmatically within the template. To do this, I was doing something like this (roughly based on this):

function elseloop_remove_blocks($post) {
  if ( ! has_blocks( $post ) ) {
    return $post;
  }

  if ( 'elseloop/this-block' === $block['blockName'] ) {
    continue;
  } else {
    echo apply_filters( 'the_content', render_block( $block ) );
  }
}

add_filter( 'the_content', 'elseloop_remove_blocks');

Then to call it, I'd do something like

function elseloop_get_that_block($post_id) {
  $post = get_post($post_id);
  $blocks = parse_blocks( $post->post_content );

  foreach( $blocks as $block ) {
    if( 'elseloop/this-block' !== $block['blockName'] ) {
      continue;
     }

      echo apply_filters( 'the_content', render_block( $block ) );
      break;
  }
}

and call that function in my template. It was working fine. Then once the block was turned into a pattern it no longer shows up in the blocks array passed to the_content or even in the_content() call.

Is this expected behavior? And if so, how would a similar process happen with patterns? There don't seem to be comparable filters for them.

EDIT: it does seem to appear in the array passed to the_content, but it is no longer wp:elseloop/this-block but instead wp:block {"ref":5728}. I’m definitely unsure what to do with that now. Is the ref consistent?

I have a block, say, elseloop/this-block, that was turned into a pattern on one page that it was included on. It is always displayed in an odd spot in the layout, so I want to pull it out of the content and then place it programmatically within the template. To do this, I was doing something like this (roughly based on this):

function elseloop_remove_blocks($post) {
  if ( ! has_blocks( $post ) ) {
    return $post;
  }

  if ( 'elseloop/this-block' === $block['blockName'] ) {
    continue;
  } else {
    echo apply_filters( 'the_content', render_block( $block ) );
  }
}

add_filter( 'the_content', 'elseloop_remove_blocks');

Then to call it, I'd do something like

function elseloop_get_that_block($post_id) {
  $post = get_post($post_id);
  $blocks = parse_blocks( $post->post_content );

  foreach( $blocks as $block ) {
    if( 'elseloop/this-block' !== $block['blockName'] ) {
      continue;
     }

      echo apply_filters( 'the_content', render_block( $block ) );
      break;
  }
}

and call that function in my template. It was working fine. Then once the block was turned into a pattern it no longer shows up in the blocks array passed to the_content or even in the_content() call.

Is this expected behavior? And if so, how would a similar process happen with patterns? There don't seem to be comparable filters for them.

EDIT: it does seem to appear in the array passed to the_content, but it is no longer wp:elseloop/this-block but instead wp:block {"ref":5728}. I’m definitely unsure what to do with that now. Is the ref consistent?

Share Improve this question edited Jan 26, 2024 at 19:15 elseloop asked Jan 26, 2024 at 19:05 elseloopelseloop 13 bronze badges 3
  • Not sure about the described approach here. Otherwise the ref number is the post ID of the wp_block post type storing the "reusable" block's content if I recall correctly. Try fetch that post from your $block['attrs']['ref'] ? – birgire Commented Jan 26, 2024 at 19:46
  • Thank you, @birgire! This set me on the right path. I wound up going in a completely different direction (using WP_Query to grab the pattern using its registered title and then hiding the first instance with CSS. I didn't realize they were there own post type until your answer though, so thanks! – elseloop Commented Jan 27, 2024 at 4:39
  • Glad to hear it helped. Please accept/mark your answer to close the question. – birgire Commented Jan 29, 2024 at 17:43
Add a comment  | 

1 Answer 1

Reset to default 0

Turns out the answer to my question appears to be yes, patterns are no longer filterable through the_content. At least not directly in a way where you can filter them out of the content easily like you can a standard block.

For anyone looking, I wound up querying for the pattern directly then including in the partial I needed it in. Because I couldn't filter it out of the content, this resulted in two instances of the block on the page. After trial and error, I wound up just hiding the fist (incorrectly placed) instance using a slightly involved sibling selector. All of this looked like this:

defining the function to query for the pattern by title:

// $block_title is the registered display title of the block
function elseloop_get_this_block($block_title = 'This Block') {
  // query for post_type 'wp_block'
  $query = new WP_Query(
    array(
        'post_type'              => 'wp_block',
        'title'                  => $block_title,
        'post_status'            => 'published',
        'posts_per_page'         => 1,
    )
  );

  // if there's content, run it through 'the_content' and return it
  if (!empty($query->post)) {
    $reusable_block = $query->post;
    $reusable_block_content = apply_filters('the_content', $reusable_block->post_content);
    return $reusable_block_content;
  } else {
    return '';
  }
}

using it in my template partial:

<div class="partial__this-block">
<?php elseloop_get_this_block('This Block'); ?>
</div>

and finally CSS to hide the first instance:

/* selects the first instance by ensuring it has a known sibling the second instance would never have */
.partial__this-block:has(~ .known-sibling) {
    display: none;
  }

本文标签: filtersAre blocks that are converted to patterns no longer filterable through thecontent