Using Parse and Serialize Blocks

Here’s a script we used to update all of the first heading tags to h1’s if they weren’t already, but I think you can see the potential of this technique:

<?php

/*
This site has post content (just pages for now) that all start with h2 tags. This script updates all those h2 tags to h1 tags for SEO purposes.

The first thing we need to do is loop through all posts and grab the post content.
Then we need to search for the first instance of an h2 tag and replace it with an h1 tag.
Finally, we need to update the post content with the new content.

An example of one of the headings looks like this:
<!-- wp:heading {"className":"hero-heading","style":{"spacing":{"margin":{"top":"0","bottom":"0"}},"elements":{"link":{"color":{"text":"var:preset|color|secondary"}}}},"textColor":"secondary"} -->
<h2 class="wp-block-heading hero-heading has-secondary-color has-text-color has-link-color" style="margin-top:0;margin-bottom:0">Explore the Wonders of Germany Tour</h2>
<!-- /wp:heading -->

Since it's gutenberg content, we need to make sure we only replace the h2 tag within the wp:heading block, and specify the level of the heading tag to be 1 instead of 2 (or not specified).
*/

require_once __DIR__ . '/wp-load.php';

// Get all posts
$all_posts = get_posts(array(
    'numberposts' => -1, // Get all posts
    'post_type'   => 'page', // Change this if you want to target a
    'post_status' => 'any', // Include all post statuses
));

foreach ($all_posts as $post) {
    // Get the post content
    $content = $post->post_content;

    // Here we use parse_blocks to parse the content into blocks and manage them properly
    $blocks = parse_blocks($content);
    $updated = false;
    foreach ($blocks as &$block) {
        if ($block['blockName'] === 'core/heading') {
            // Check if the heading level is 2
            if (isset($block['attrs']['level']) && $block['attrs']['level'] == 2) {
                // Change it to level 1
                $block['attrs']['level'] = 1;
                $block['innerHTML'] = str_replace('h2', 'h1', $block['innerHTML']);
                $block['innerContent'] = str_replace('h2', 'h1', $block['innerContent']);
                $updated = true;
            } elseif (!isset($block['attrs']['level'])) {
                // If level is not set, it defaults to 2, so we change it to 1
                $block['attrs']['level'] = 1;
                $block['innerHTML'] = str_replace('h2', 'h1', $block['innerHTML']);
                $block['innerContent'] = str_replace('h2', 'h1', $block['innerContent']);
                $updated = true;
            }
        }

        if ($updated) {
            // We only want to change the first heading we find
            break;
        }
    }

    if ($updated) {
        // Convert blocks back to content
        $new_content = serialize_blocks($blocks);

        // Update the post content
        wp_update_post(array(
            'ID'           => $post->ID,
            'post_content' => $new_content,
        ));

        echo "Updated post ID " . $post->ID . "\n";
    } else {
        echo "No changes for post ID " . $post->ID . "\n";
    }
}

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *