Skip to content
Advertisement

Editing this Snippet to Run One Time Only

We have thousands of custom posts where we need to update the_excerpt using this PHP snippet (which works great when a single post is saved). Is there a way to tweak this code so that we can run it one time (like when we load a page) and then delete it? We’re trying to update each post’s excerpt based on this code without manually editing each post.

// This saves the Short Description ACF field as the post excerpt.

add_action('acf/save_post', function($post_id) {
    
    $post_type = get_post_type( $post->ID );
    if ($post_type == "ultratech_product") {

  $post_excerpt   = get_field( 'short_description', $post_id );
        
        if ( '' != $post_excerpt ) {
        $post_excerpt = strip_shortcodes( $post_excerpt );
        $post_excerpt = apply_filters('the_content', $post_excerpt);
        $post_excerpt = str_replace(']]>', ']]>', $post_excerpt);
        $excerpt_length = 250; // 250 words
        $excerpt_more = apply_filters('excerpt_more', " " . '[...]');
        $post_excerpt = wp_trim_words( $post_excerpt, $excerpt_length, $excerpt_more );
    }

    // Update post options array
    $update_post_excerpt_args = array(
      'ID'          => $post_id,
      'post_excerpt'    => $post_excerpt,
    );

    wp_update_post( $update_post_excerpt_args );

    }
    }, 40);

Advertisement

Answer

First, please make sure to read through everything here. If you don’t feel comfortable with anything, I would recommend contacting a developer to have them inspect and run this on your behalf. It should be a small price to pay to make sure thousands of posts get updated correctly.

Second, take a full backup and make sure you can restore it.

Third, keep that backup somewhere for access in the future, just in case there is a flaw in this logic that you don’t find for a while.

There’s a couple ways to do this. Personally, I would build a CLI version because I like progress bars and verbose status messages, but that’s just me. You could also make a plugin, use a query string to trigger special PHP code, use magic pages or page templates, and for this code, I’m going to use the last option, a page template.

Place the following into a new PHP file in the root of your theme. Technically the file name doesn’t really matter, but by convention I prefix my templates with tpl, so I recommend calling this new file tpl-update.php. Paste the below code into that file, but make sure to keep reading after the code block.

<?php

/**
 * Template Name: Excerpt Updater
 */

die('Remove me when ready');

// Turn on full error reporting
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);

// Disable PHP timeouts
set_time_limit(0);

// Grab all products
$allProducts = get_posts(
    [
        'post_type' => 'ultratech_product',
        'posts_per_page' => -1,
    ]
);

foreach ($allProducts as $product) {
    echo 'Processing post ' . $product->ID . ';' . PHP_EOL;
    // We're guaranteed to only have our products, so we don't need to check the type anymore

    // Get the ACF field
    $post_excerpt = get_field('short_description', $product->ID);

    // If it has anything in it, apply the logic (which was untested)
    if ($post_excerpt) {
        $post_excerpt = strip_shortcodes($post_excerpt);
        $post_excerpt = apply_filters('the_content', $post_excerpt);
        $post_excerpt = str_replace(']]>', ']]>', $post_excerpt);
        $excerpt_length = 250; // 250 words
        $excerpt_more = apply_filters('excerpt_more', " " . '[...]');
        $post_excerpt = wp_trim_words($post_excerpt, $excerpt_length, $excerpt_more);

        // Only update the post if we made a change above

        // Update post options array
        $update_post_excerpt_args = array(
            'ID' => $product->ID,
            'post_excerpt' => $post_excerpt,
        );

        wp_update_post($update_post_excerpt_args);
    }
}

echo 'Done';

In WordPress, create a new page and assign it the Excerpt Updater Template: Screenshot of WordPress Page Attributes area.

The code above explicitly has a die statement as the first line of logic so that you can test that WordPress is using the template. To be clear, you can publish and view the page and all you will see is Remove me when ready, no work will be done.

Once you see that message, you can comment out that line in the template code and it will process everything. This might take a while so I’ve tried to disable any PHP timeouts, however it is possible the server or something else might cancel the script.

But before you run the live code, I would also recommend that you change the value of posts_per_page to a low number like 5 so that you can make sure things work. The code will echo out the ID of the product so that you can inspect it in the backend.

Once you’ve confirmed it is working as expected, you can change posts_per_page back to -1 again which means “all posts” (of the given post type).

One last thing, I didn’t really vet the logic for updating the excerpt itself, I’m assuming that you did that already, but at a quick glance it appears that it is correct.

Okay, one more last thing. Usually when I do something like this, I create a new ACF field called something like “excerpt version” which will be empty by default. Then, I run my loop and say “if the excerpt version is not v2, update the excerpt and set the version to v2“. By doing this, I can guarantee that the logic only ever runs once. You don’t have to do this, but it can be helpful if you want to run the code in batches, like 10 at a time to test things. It also helps if you think that someday you might have to change the excerpt again.

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement