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 am looking for solution to auto delete images of old posts in WordPress site. I want to hold images of current 50 posts, others should be deleted automatically. It can be function to delete on time interval, or function to hold only images of last 50 posts. Does anyone know function or some plugin which can do this or similar things, to automatically delete older images? I believe that setting a cron job will be needed.

Someone posted this function in stackoverflow but I don't see any mention of time.


function delete_post_media( $post_id ) {

    $attachments = get_posts( array(
        'post_type'      => 'attachment',
        'posts_per_page' => -1,
        'post_status'    => 'any',
        'post_parent'    => $post_id
    ) );

    foreach ( $attachments as $attachment ) {
        if ( false === wp_delete_attachment( $attachment->ID ) ) {
            // Log failure to delete attachment.
        }
    }
}

share|improve this question
    
+1 a very interesting question. –  kaiser Mar 5 at 10:37

1 Answer 1

If you need to retain only images for last 50 posts, I don't think that a cron job or a WP cron is the best thing you can do, in WordPress you can know when a post is published, and you can run a routine everytime it happen, deleting images for the post pubblished 50 posts ago.

That's easy, better performing (you do nothing if you have nothing to do, a cron job runs regardless you have something to delete or not).

The workflow is pretty easy:

  1. Everytime a post is published get the 51th post id (ordered by publish date)
  2. delete all images having that id as post parent

the code:

add_action( 'save_post', 'cleanup_old_post_images', 10, 3 );

function cleanup_old_post_images( $post_ID, $post, $update ) {
  if ( $update ) return; // do nothing on update
  $postid51th = get51th_postid(); // see below
  if ( ! empty( $postid51th ) && is_numeric( $postid51th ) ) {
    delete_post_media( $postid51th ); // see below, function in OP
  }
}

function get51th_postid() {
  return $GLOBALS['wpdb']->get_var(
    "SELECT ID FROM " . $GLOBALS['wpdb']->posts .
    " WHERE post_type = 'post' AND post_status = 'publish' ORDER BY post_date DESC
    LIMIT 50, 1"
  ); 
}

function delete_post_media( $post_id ) {
  $attachments = get_posts( array(
    'post_type'      => 'attachment',
    'nopaging'       => TRUE,
    'post_parent'    => $post_id
  ) );
  if ( empty( $attachments ) ) return; // added this line to prevent errors
  foreach ( $attachments as $attachment ) {
    if ( false === wp_delete_attachment( $attachment->ID ) ) {
      // Log failure to delete attachment.
    }
  }
}

This works for posts published after you put the code in the site, but you can write a run-once function to delete images for older posts

add_action( 'shutdown', 'delete_older_attachments' );

function delete_older_attachments() {

  // run only on admin and use a transient to run once
  if ( ! is_admin() || get_transient('get_older_postids') ) return;     

  // the query to exclude last 50 posts
  $latest_query = "SELECT ID FROM " . $GLOBALS['wpdb']->posts .
    " WHERE post_type = 'post' AND post_status = 'publish' ORDER BY post_date DESC
    LIMIT 50"
  );

  // get older posts ids
  $older_ids = $GLOBALS['wpdb']->get_row(
    "SELECT ID FROM " . $GLOBALS['wpdb']->posts . 
    " WHERE post_type = 'post' AND post_status = 'publish'
    AND ID NOT IN (" . $latest_query . ")"
  );

  // get attachments for older posts
  if ( ! empty( $older_ids ) && is_array( $older_ids )  ) {
    $attachments = $GLOBALS['wpdb']->get_row(
      "SELECT ID FROM " . $GLOBALS['wpdb']->posts . 
      " WHERE post_type = 'attachments'
      AND post_parent IN (" . implode( ',', $older_ids ) . ")"
    );
  }

  if ( isset($attachments) && ! empty( $attachments ) && is_array( $attachments )  ) {
    foreach ( $attachments as $attachment ) {
      if ( false === wp_delete_attachment( $attachment ) ) {
        // Log failure to delete attachment.
      }
    }
    // set the transient to assure run once
    set_transient( 'get_older_postids', 1 );
  }
}
share|improve this answer
    
My mind immediately went to chron job, but this is very slick. +1. –  helgatheviking Mar 5 at 15:25
    
Thanks @helgatheviking I don't see +1 on answer maybe because I got the 200 rep cap today :) –  G. M. Mar 5 at 15:31
    
Facepalm! I just thought the +1 in my mind apparently. I don't know why the website didn't register that as a click. –  helgatheviking Mar 5 at 15:32
    
@helgatheviking :D –  G. M. Mar 5 at 15:33
1  
@helgatheviking if the published time is the discriminant, then yes, I think so. –  G. M. Apr 1 at 7:55

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.