3

I have around 2,500+ posts on my site where I've inserted images using the traditional method into the post content itself.

In upgrading to a different theme, the single post page now displays the featured image as well before the title (which I want to keep), but I now would like to remove the first image from the_content to prevent duplicate images from showing up.

I know that it can be done with this filter, but is there are way to permanently remove the first images from my old posts other than manually going through each one?

function remove_first_image ($content) {
if (!is_page() && !is_feed() && !is_feed() && !is_home()) {
$content = preg_replace("/<img[^>]+\>/i", "", $content, 1);
} return $content;
}
add_filter('the_content', 'remove_first_image');

I feel as if this filter might be resource intensive and be very unflexible for things I might wish to do in future within posts.

Another thread mentioned "Export your database tables to your desktop.than you can remove all unwanted tags by using any text editor such as notepad++." but I'm not familiar with how to do that.

Any help is appreciated. Thanks

1
  • Very similar code in a loop could remove the image and resave the post content.
    – s_ha_dum
    Commented Apr 26, 2014 at 1:05

2 Answers 2

6

Just as @s_ha_dum suggests, you can loop through all of your posts and update the content of each one.

The following gives you the idea but is untested:

$posts = get_posts( array( 
    'post_type'      => 'post', 
    'posts_per_page' => 500, 
    'offset'         => 0, 
) );

foreach( $posts as $post ):
    // Update each post with your reg-ex content filter:
    $pid = wp_update_post( array( 
        'ID'           => $post->ID,
        'post_content' => preg_replace( "/<img[^>]+\>/i", "", $post->post_content, 1 )
    ) );
    // Show the update process:
    printf( '<p>Post with ID: %d was %s updated</p>', 
        $post->ID, 
        ( 0 < $pid ) ? '' : 'NOT' 
    );     
endforeach;

To avoid PHP timeout, I added a finite number of posts to update with a given offset. You can adjust this to your needs. It's best to try it first on a single post while you're testing it.

But remember to backup your database before testing this!

Demo Plugin - First Image Remover

Here's a demo plugin with a custom admin page:

Admin page

and it's own admin menu item:

Admin menu

You can create a plugin file /wp-content/plugins/first-image-remover/first-image-remover.php with the following code:

<?php
/**
 * Plugin Name: First Image Remover
 * Description: Remove the first image from the post content
 * Plugin URI:  http://wordpress.stackexchange.com/a/142494/26350 
 * Version:     0.0.1
 */

/**
 * Create the 'First Image Remover' admin menu
 */

function wpse_142494_create_menu()
{
    // Create new top-level menu:
    add_menu_page( 
        'First Image Remover', 
        'First Image Remover', 
        'manage_options', 
        'wpse_142494_settings_page', 
        'wpse_142494_settings_page'
    );
}

add_action('admin_menu', 'wpse_142494_create_menu');

/**
 * Create the 'Image Replacer' settings pge
 */
function wpse_142494_settings_page()
{ 
?>
    <div class="wrap">
        <h2>First Image Remover</h2>
        <p>Remove the first image of each post in the selected loop.</p>


        <h3>Help:</h3>
        <p>Avialable GET parameters: 
        <pre>
wpse_ppp - Posts Per Page (int), 
wpse_offset - Offset (int),
wpse_update - Update mode (boolean) 

Update Example for 5 posts with offset 10:

/wp-admin/admin.php?page=wpse_142494_settings_page&wpse_offset=10&wpse_ppp=5&wpse_update=yes
        </pre>
        <h3>Loop:</h3>
        <?php wpse_142494_loop(); ?>
    </div>
<?php
}

/**
 * Fetch posts based on user input
 */
function wpse_142494_loop()
{
    // Only site admin can update posts:
    if( ! current_user_can( 'manage_options' ) ) return;

    // Get user input:
    $params = filter_input_array( INPUT_GET, array( 
        'wpse_offset'  => FILTER_SANITIZE_NUMBER_INT,
        'wpse_ppp'     => FILTER_SANITIZE_NUMBER_INT, 
        'wpse_update'  => FILTER_VALIDATE_BOOLEAN, 
    ) );

    // Fetch posts to update:   
    $posts = get_posts( array( 
        'post_type'      => 'post', 
        'posts_per_page' => ( ! empty( $params['wpse_ppp'] ) )    ? $params['wpse_ppp']    : 10 , 
        'offset'         => ( ! empty( $params['wpse_offset'] ) ) ? $params['wpse_offset'] : 0, 
    ) );

    // Loop through posts:
    $li = '';
    foreach( $posts as $post ):

        if( $params['wpse_update'] ):           
            // Update each post with your reg-ex content filter:
            $pid = wp_update_post( array( 
                'ID'           => $post->ID,
                'post_content' => preg_replace( "/<img[^>]+\>/i", "", $post->post_content, 1 )
            ) );

            // Show the update process:
            $li .= sprintf( '<li>%d - <strong>%s</strong> - was %s updated</li>', 
                $post->ID, 
                $post->post_title,
                ( 0 < $pid ) ? '' : 'NOT' 
            );
        else:
            // Show the post list that will be updated
            $li .= sprintf( '<li>%d - <strong>%s</strong> - will be updated</li>', 
                $post->ID,
                $post->post_title
            );
        endif;

    endforeach;

    // Output:
    printf( '<strong>Settings:</strong> Posts: %d - Offset: %d - Update: %s <ul>%s</ul>', 
        $params['wpse_ppp'], 
        $params['wpse_offset'], 
        $params['wpse_update'] ? 'ON' : 'OFF', 
        $li 
    );
}

where you can access it from:

/wp-admin/admin.php?page=wpse_142494_settings_page

You can then adjust it to your needs with the following GET parameters:

/wp-admin/admin.php?page=wpse_142494_settings_page&wpse_offset=10&wpse_ppp=5&wpse_update=no

When you run it in the update mode (wpse_update=yes) you will get something like:

Update mode

You can then hopefully extend this and adjust to your needs.

16
  • thanks @birgire ! I understand what posts_per_page does but could you please explain the offset number? Do I copy this code into functions.php? Commented Apr 26, 2014 at 4:16
  • @user2803938 I udpated the answer with a demo plugin I created for you. The offset is like paging. Just let me know if you need any assistance to setup the plugin.
    – birgire
    Commented Apr 26, 2014 at 10:38
  • Thanks @birgire! Thats absolutely fantastic. I'll run it on a development server first to see if it does what I want. Thanks for all of your help and all the detail! Commented Apr 27, 2014 at 2:06
  • Thanks for this, unfortunately when i run the plugin it deletes all of the post content complete. Commented Jan 10, 2015 at 5:02
  • Thanks for this @birgire , unfortunately when i run the plugin it deletes all of the post content completey rather than just the image. I've changed it to include the following 'post_content' => preg_replace( "<a href[^>]+\><img[^>]+\></a>", "", $content, 1) Commented Jan 10, 2015 at 5:12
1

Search RegEx is a good plugin to be able to search and replace (optionally with grep) and save through all posts, pages, excerpts, comments, titles and meta.

3
  • Thanks @Songdogtech but I don't want to replace the first image in each post, will this plugin allow that? Commented Apr 26, 2014 at 3:16
  • You can replace with nothing, if you want to delete images and links. Use grep to find the image link and replace with ''. Commented Apr 26, 2014 at 3:18
  • sorry I should've said I just** want to replace the first image in each post. Commented Apr 26, 2014 at 4:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.