Skip to content
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Block Hooks: Add apply_block_hooks_to_content_from_post_object
  • Loading branch information
ockham committed Feb 17, 2025
commit 44c7524ea8acaea2831c3c01e96b5e6c43ba5a6b
68 changes: 68 additions & 0 deletions src/wp-includes/blocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -1140,6 +1140,74 @@ function apply_block_hooks_to_content( $content, $context = null, $callback = 'i
return $content;
}

/**
* Run the Block Hooks algorithm on a post object's content.
*
* This function is different from `apply_block_hooks_to_content` in that
* it takes ignored hooked block information from the post's metadata into
* account. This ensures that any blocks hooked as first or last child
* of the block that corresponds to the post type are handled correctly.
*
* @since 6.8.0
* @access private
*
* @param string $content Serialized content.
* @param WP_Post|null $post A post object that the content belongs to. If set to `null`,
* `get_post()` will be called to use the current post as context.
* Default: `null`.
* @param callable $callback A function that will be called for each block to generate
* the markup for a given list of blocks that are hooked to it.
* Default: 'insert_hooked_blocks'.
* @return string The serialized markup.
*/
function apply_block_hooks_to_content_from_post_object( $content, WP_Post $post = null, $callback = 'insert_hooked_blocks' ) {
// Default to the current post if no context is provided.
if ( null === $post ) {
$post = get_post();
}

if ( ! $post instanceof WP_Post ) {
return apply_block_hooks_to_content( $content, $post, $callback );
}

$attributes = array();

// If context is a post object, `ignoredHookedBlocks` information is stored in its post meta.
$ignored_hooked_blocks = get_post_meta( $post->ID, '_wp_ignored_hooked_blocks', true );
if ( ! empty( $ignored_hooked_blocks ) ) {
$ignored_hooked_blocks = json_decode( $ignored_hooked_blocks, true );
$attributes['metadata'] = array(
'ignoredHookedBlocks' => $ignored_hooked_blocks,
);
}

// We need to wrap the content in a temporary wrapper block with that metadata
// so the Block Hooks algorithm can insert blocks that are hooked as first or last child
// of the wrapper block.
// To that end, we need to determine the wrapper block type based on the post type.
if ( 'wp_navigation' === $post->post_type ) {
$wrapper_block_type = 'core/navigation';
} elseif ( 'wp_block' === $post->post_type ) {
$wrapper_block_type = 'core/block';
} else {
$wrapper_block_type = 'core/post-content';
}

$content = get_comment_delimited_block_content(
$wrapper_block_type,
$attributes,
$content
);

// Apply Block Hooks.
$content = apply_block_hooks_to_content( $content, $post, $callback );

// Finally, we need to remove the temporary wrapper block.
$content = remove_serialized_parent_block( $content );

return $content;
}

/**
* Accepts the serialized markup of a block and its inner blocks, and returns serialized markup of the inner blocks.
*
Expand Down