Is it possible to Schedule Attachments in WordPress?

My idea is that you can setup a post date for the attachments. This can be done using attachment_fields_to_edit to show the UI (is possible use the touch_time internal function).

After that, you can filter all the attachments query to show only the attachments with a past or current date.

So

add_action('load-post.php', 'setup_attachment_fields');

function setup_attachment_fields() {
  $scr = get_current_screen();
  if ( $scr->post_type === 'attachment' ) {
    add_filter("attachment_fields_to_edit", "add_date_to_attachments", null, 2);
  }
}

function add_date_to_attachments( $form_fields, $post = NULL ) {    
  printf('<label for="content"><strong>%s</strong></label>', __('Date'));
  touch_time( 1, 1, 0, 1 );
  return $form_fields;
}

Now on the attachment page you’ll see something like:

Attachments date

Now let’s set post date on attachment save:

add_filter("attachment_fields_to_save", "save_date_to_attachments");

function save_date_to_attachments( $post ) {
  foreach ( array('mm', 'jj', 'aa', 'hh', 'mn') as $f ) {
    $$f = (int) filter_input(INPUT_POST, $f, FILTER_SANITIZE_NUMBER_INT);
  }
  if ( ! checkdate ( $mm, $jj, $aa ) ) return; // bad data, man
  if ( ($hh < 0 || $hh > 24) ) $hh = 0;
  if ( ($mn < 0 || $mn > 60) ) $mn = 0;
  $ts = mktime($hh, $mn, 0, $mm, $jj, $aa);
  $date = date( 'Y-m-d H:i:s', $ts );
  $date_gmt = date( 'Y-m-d H:i:s', ( $ts + ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) ) );
  $modified = current_time( 'mysql');
  $modified_gmt = current_time( 'mysql', true);
  global $wpdb;
  $data = array(
    'post_date' => $date,
    'post_date_gmt' => $date_gmt,
    'post_modified' => $modified,
    'post_modified_gmt' => $modified_gmt,
  );
   $wpdb->update( $wpdb->posts, $data, array( 'ID' => $post['ID'] ), '%s', '%d' );
}

When attachment is saved, the post date is set to whatever you set on date fields.

However, attachments are all visible, no matter the date, because WordPress does not check the date on attachments queries. Let’s add a filter to where clause for that:

add_filter( 'posts_where', 'not_future_attachment', 9999, 2 );

function not_future_attachment( $where, $query ) {
  if ( is_admin() ) return $where;
  if ( $query->get('post_type') === 'attachment' ) {
    global $wpdb;
    $where .= $wpdb->prepare(
      " AND ($wpdb->posts.post_date <= %s)", current_time( 'mysql')
    );
  }
  return $where;
}

Now in a shortcode for gallery (or wherever you want) be sure to use WP_Query setting up the post type argument to 'attachment'.

On standard shortcode this will not work because it uses get_children where query filters are suppressed, so you have to create a custom shortcode or overwrite the default.

Leave a Comment