Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

I have a big WordPress installation more than 200K posts, with auto publish posts features. My post content is contained "some HTML tags, some text, some <img> tags". I need to remove all <img> tags from post content from the specific posts. So I have this function to do this job:

function remove_images_form_past_posts() {
    if ( get_transient('images_removed_from_past') )
        return;
    $args = array( 
                'post_type' => 'post', 
                'year' => 2013, 
                'monthnum' => 1, 
                'day' =>28,     
                'post_status' =>'publish',
                'category' => 30,
                'post_author' => 3,
                'nopaging' => 1
            );
    $posts = get_posts( $args );    
        if ( $posts ) {
            foreach ( $posts as $post ); setup_postdata( $post ); {
                $newcontent = preg_replace('/<img[^>]+\>/i', '', $post->post_content);
                $newpost = array(
                               'ID' => $post->ID, 
                               'post_content' => $newcontent
                           );
                wp_update_post($newpost);
                wp_reset_postdata();
            }
            set_transient('images_removed_from_past', 60 * 60 * 24);
        }
    }
add_action('admin_init','remove_images_form_past_posts');

The code above is perfect & do the job but have one problem: this code is unfortunately update 1 post only although the $args is matching 9 posts.

I have tested the get_posts alone & it is working perfectly & executing 9 posts. I have stopped the WP_super_cache plugin & also no way. I have tried to change "set_transient $value from 1 to 9 with no way.

Any ideas!

share|improve this question
    
Where does the variable $images_removed_from_past come from? –  ialocin Oct 5 '13 at 11:42
    
please see the first line of the code, came from the sqme function –  adnan Oct 5 '13 at 12:11
    
Sorry, I'm not quite sure what you mean. –  ialocin Oct 5 '13 at 12:19
    
ok, iam here because iam not a developer, not a wordpress expert, so please if you see any mistakes in the code tell me the true , i explained my goal & specified every thing, help me please by posting an answer for my question not by posting a new question –  adnan Oct 5 '13 at 12:22
    
Believe it or not, to help you is what I'm trying to do. –  ialocin Oct 5 '13 at 12:35
show 2 more comments

2 Answers 2

up vote 0 down vote accepted

If what you want is for this function to run once a day and loop through all matching posts (removing img tags), I think this should do the trick:

<?php
function remove_images_form_past_posts() {
        if ( get_transient('images_removed_from_past') )
            return;
        $args = array( 
                    'post_type' => 'post', 
                    'year' => 2013, 
                    'monthnum' => 1, 
                    'day' =>28,     
                    'post_status' =>'publish',
                    'category' => 30,
                    'post_author' => 3,
                    'nopaging' => 1
                );
        $posts = get_posts( $args );    
            if ( $posts ) {
                foreach ( $posts as $post ) {
                    $newcontent = preg_replace('/<img[^>]+\>/i', '', $post->post_content);
                    $newpost = array(
                                   'ID' => $post->ID, 
                                   'post_content' => $newcontent
                               );
                    wp_update_post($newpost);
                }
                set_transient('images_removed_from_past',true, 60 * 60 * 24);
            }
        }
add_action('admin_init','remove_images_form_past_posts');
share|improve this answer
1  
Isn't that just about what I suggested.. :D I wouldn't wp_reset _postdata() on every loop though. And @adnan the set_transient() is still kind of useless, because now it's set with the seconds for day as value and expiration set to 0, which means it won't expire. BTW when you are testing be sure that the transient isn't set, otherwise the piece of code you want to test won't execute. Just to clear that too. –  ialocin Oct 5 '13 at 15:24
    
setup_postdata( $post ); must be available see this please codex.wordpress.org/Template_Tags/… –  adnan Oct 5 '13 at 15:27
    
@ialocin it's pretty darn close to what you suggested. His use of set_transient is very confusing to me as well, I actually meant to change that set_transient() call. Will make an edit now. And @adnan, setup_postdata really just allows you to use template tags, and you're not using them. If you var_dump($post) before you set $newcontent you'll see that what you need is available. –  murdaugh Oct 5 '13 at 15:31
1  
No, read again, it's really just needed if you want to use template tags like the_content(). –  ialocin Oct 5 '13 at 15:32
    
ok, i have excuted delete_transient to clear it, changed the function & transient name, tested it –  adnan Oct 5 '13 at 15:37
show 16 more comments

The syntax of your foreach-loop is wrong, you are breaking it by putting a ; behind it. This is the reason why you only update one post. Just do it like this:

        foreach ( $posts as $post ) { //remove the »;«
            setup_postdata( $post ); //move this inside the loop
            $newcontent = preg_replace('#(<[/]?img.*>)#U', '', $post->post_content);
            $newpost = array(
                           'ID' => $post->ID, 
                           'post_content' => $newcontent
                       );
            wp_update_post($newpost);
        }
        wp_reset_postdata(); //do not forget to reset postdata after the loop

I changed the regex too, might not be absolutely necessary, but this one is working pretty good for me.

Additionally add:

global $post;

at the begin of your function. You don't have to do it see @murdaugh comment, but if you setup and reset postdata correct there is no harm. In fact there are some cases you have to do it, but that's not pertinent here. I just suggested it for failsafe reasons.





Disclaimer:
This second part isn't part of the answer to the question. It's just an extended consideration of the raised problem.
Other notes:

  • I'm guessing you want your transient to reflect which posts are already cleaned up. Which makes absolutely sense if you are having 200k posts. In this case you should make sure your transient name is reflecting which set of post you already cleaned up. A generic one like in your function won't cut it. The transient name should reflect all the changing parameters of your $args. A stripped-down code snippet:

        //make your parameters variables
        $ay = '2013'; //year
        $am = '1'; //month
        $ad = '28'; //day
        $ac = '30'; //category
        $aa = '3'; //author
    
        //get your transient based on the set of variables
        if (get_transient('rm_img_'.$ay.'_'.$am.'_'.$ad.'_'.$ac.'_'.$aa.'') )
            return;
    
        //use the variables in your args
        $args = array( 
            'post_type' => 'post', 
            'year' => $ay, 
            'monthnum' => $am, 
            'day' => $ad,     
            'post_status' =>'publish',
            'category' => $ac,
            'post_author' => $aa,
            'nopaging' => 1
        );
    
        //get your transient based on the set of variables
        set_transient('rm_img_'.$ay.'_'.$am.'_'.$ad.'_'.$ac.'_'.$aa.'', true, 0);
    
  • This isn't working as it is! Just to make that very clear.

  • It's just an idea on how to make use of the transient, for you or anybody else interested.
  • Of course there are some other steps, for example:
    • What you probably really want is that the function takes those parameters as arguments.
    • Besides that one would probably want way more possibilities for automated looping an iterating.

Ok, I'm going to break this here, before it's getting out of hand.

share|improve this answer
    
ok i will update the q with last one i have used & please see it –  adnan Oct 5 '13 at 13:22
    
unfortunately after moved setup_postdata( $post ); inside loop.. no way –  adnan Oct 5 '13 at 13:35
    
global $post; add this after the line function remove_images_form_past_posts() { ... also no way –  adnan Oct 5 '13 at 14:07
    
I agree that the structure foreach loop is an issue, but because he's populating $post with the contents of the $posts object in that foreach loop, there's no reason to add global $post; anywhere. That really could just foul things up. One could also argue that he shouldn't be using $post as a variable name because it causes readability issues. –  murdaugh Oct 5 '13 at 14:19
    
@murdaugh please post a complete code to test it –  adnan Oct 5 '13 at 14:24
show 5 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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