Delete a Gutenberg Block Programmatically?

For the original approach – when you delete a forum post, search the database and remove any blocks that refer to that specific post – it looks like the only way to accomplish this would be with a regular expression, which could break in future updates.

You could hook into the delete_post hook, verify that the deleted post is a “forum” post, then get all posts that could contain the forum block, loop through them and parse_blocks() so you could check whether the current post contains a forum block with the forum post ID as an attribute.

But, where this process breaks down is, we don’t currently have a serialize_blocks() function to convert the blocks back into HTML comments. (They’re discussing adding one in Trac but it’s not ready yet.) So, even though you could identify all of the posts that contain the block you’re looking for, you would then have to create a regular expression to update the actual post_content of those posts.

For what it’s worth, here is the code as far as it goes:

<?php
add_action('delete_post', 'wpse_delete_forum_blocks', 10, 1);
// The forum post ID is the only argument
function wpse_delete_forum_blocks($post_id) {
    $post_type = get_post_type($post_id);
    // Only run this code if the deleted post was a "forum" CPT
    if($post_type == 'forum') {
        // Get all posts that may contain the forum block
        // Arguments are up to you - perhaps only a specific post type can contain it
        $check_posts = get_posts(
            array(
                // Get all posts
                'numberpost' => -1
                // Get "post" post type / adjust as needed
                'post_type' => 'post'
            )
        );
        // Loop through all the posts
        foreach($check_posts as $post) {
            // If the post has blocks
            if(has_blocks($post->post_content)) {
                // Parse the blocks
                $blocks = parse_blocks($post->post_content);
                // Loop through the blocks
                foreach($blocks as $block) {
                    // If this is a "forum" block, and its "post_id" attribute matches the id we're looking for
                    // (make sure to change this to your applicable namespace and block name)
                    if($block['blockName'] === 'stmu/icon-heading' && $block['attrs']['post_id'] === $post_id) {
                        // This is where you need to create a regular expression to remove just this block.
                    }
                }
            }
        }
    }
}
?>

In the meantime, server-side rendering would allow you to show either the post if found, or nothing if it’s gone.