Tag: PHP

  • 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";
        }
    }
  • Quick Script to Count Block Usage

    Here’s a quick script to determine what blocks a site is using and how often they use them:

    <?php
    
    require_once __DIR__ . '/wp-load.php';
    
    $sql = 'select * from wp_posts where post_content like "%<!-- wp:%"';
    
    $results = $wpdb->get_results($sql);
    $blocks = [];
    
    // Loop through each post and get a list of all blocks used in gutenberg post_content
    foreach ($results as $post) {
        $matches = [];
        preg_match_all('/<!-- wp:(.*?) -->/', $post->post_content, $matches);
        if ( !empty($matches) ) {
            $block_names = $matches[1];
    
            foreach ( $block_names as $block_name ) {
                $name = explode(' ', $block_name);
                $name = $name[0] ?? $block_name;
    
                if ( !isset($blocks[$name]) ) {
                    $blocks[$name] = 0;
                }
                ++$blocks[$name];
            }
        }
    }
    
    print_r($blocks);