I’ve built a little event calendar category that uses custom fields to allow the site’s admin to place a starting/ending date and time to posts. Part of my hope for this setup is to automatically expire posts that have gone past their ending date field.
I found this topic on the setup but it haven’t had much luck getting it to work.
I’m running the following code in my template:
<?php
if (!wp_next_scheduled('expire_posts')){
wp_schedule_event(time(), 'hourly', 'expire_posts'); // running hourly for testing purposes
}
add_action('expire_posts', 'expire_posts_function');
function expire_posts_function() {
$today = time('l, F j, Y'); // matches the output of my custom field
$args = array(
'post_type' => array('post'), // array of the post types you want to check
'category' => 'events',
'posts_per_page' => -1 // get all the posts
);
$posts = get_posts($args);
foreach($posts as $p){
if(get_field('event_ending_date', $p->ID) > $today){
$postdata = array(
'ID' => $p->ID,
'post_status' => 'draft'
);
wp_update_post($postdata);
}
}
}
?>
Am I on the right track with this type of code? Any suggestions on what may get this working?
Hi @karks88
Almost..
But I would say there’s no need for you to query all posts and then do the check when you can just query all past posts directly and change their statuses..
if (!wp_next_scheduled('expire_posts')){
wp_schedule_event(time(), 'hourly', 'expire_posts'); // running hourly for testing purposes
}
add_action('expire_posts', 'expire_posts_function');
function expire_posts_function() {
$today = time('Ymd'); // matches the date in DB
$args = array(
'post_type' => array('post'), // array of the post types you want to check
'posts_per_page' => 200 // get all the posts but don't set it t o -1 since its a risk of overloading the server
'category' => 'events',
'post_status' => 'publish',
'meta_query' => array(
array(
'key' => 'event_ending_date',
'value' => $today,
'compare' => '<' // you might have to switch this out for >
)
)
);
$post_query = new WP_Query($args);
if( $posts->have_posts() ){
while( $post_query->have_posts() ){
$post_query->the_post();
wp_transition_post_status('draft', 'publish', $post);
}
wp_reset_postdata();
}
}
Might could streamline the code a bit, but this is working for me. Hope it helps.
// Expire events
if ($expireTransient = get_transient($post->ID) === false) {
set_transient($post->ID, 'set for 1 minutes', 1 * MINUTE_IN_SECONDS );
$today = date('Y-m-d H:i:s', current_time('timestamp', 0));
$args = array(
'post_type' => 'events',
'posts_per_page' => 200,
'post_status' => 'publish',
'meta_query' => array(
array(
'key' => 'end_date_time',
'value' => $today,
'compare' => '<='
)
)
);
$posts = get_posts($args);
foreach( $posts as $post ) {
if(get_field('end_date_time', $post->ID)) {
$postdata = array(
'ID' => $post->ID,
'post_status' => 'draft'
);
wp_update_post($postdata);
}
}
}
Thank’s for your example too. It’s pretty much the same as mine except you also run a transient check so as to avoid running it more than once a minute (I’m guessing?).
A few key differences tho I think worth mentioning is:
1. Always use WP_Query if you can. get_posts() is a wrapper for WP_Query which excludes filters. It’s just good practice tho, don’t think it has any real impact on load times.
2. By using wp_transition_post_status
instead of wp_update_post
we only update the status column in wp_posts table. The benefit of this is that it only handles the status so it’s faster and also it wont trigger any save_post
hooked functions.
Hey Gents,
I’ve attempted to use both code snippets provided by @jonathan & @precisioncreations but without much luck. I’ve added both to my functions file (at different times) with the only difference being my post type and key value based on my client’s setup.
I can confirm the meta_value shows as a previous date of “20161130” in the database, yet the posts remain in a published state.
When first attempting to force the cron job manually through BackupBuddy’s server tools, I received the following error message from the method @jonathan provided:
“Fatal error: Call to a member function have_posts() on a non-object in /path/functions/custom.php on line 220″
Line 220 is:
if( $posts->have_posts() ){
I removed the if call from the code altogether and was able to manually run the cron job, but still with the same result of no posts updating.
Below is the code I’m using in the site’s functions file:
// Expire Post Settings
if (!wp_next_scheduled('expire_posts')){
wp_schedule_event(time(), 'hourly', 'expire_posts');
}
add_action('expire_posts', 'expire_posts_function');
function expire_posts_function() {
$today = time('Ymd');
$args = array(
'post_type' => 'ivy_event',
'posts_per_page' => 200,
'post_status' => 'publish',
'meta_query' => array(
array(
'key' => 'expire_post_date',
'value' => $today,
'compare' => '<='
)
)
);
$post_query = new WP_Query($args);
while( $post_query->have_posts() ){
$post_query->the_post();
wp_transition_post_status('draft', 'publish', $post);
}
wp_reset_postdata();
}
Any help here would be greatly appreciated. I’m sure it’s something simple, but I’m on the tail end of a week where 14 hour shifts have been the norm.
The topic ‘Expire Posts on Datepicker Field’ is closed to new replies.
Welcome to the Advanced Custom Fields community forum.
Browse through ideas, snippets of code, questions and answers between fellow ACF users
Helping others is a great way to earn karma, gain badges and help ACF development!
We use cookies to offer you a better browsing experience, analyze site traffic and personalize content. Read about how we use cookies and how you can control them in our Privacy Policy. If you continue to use this site, you consent to our use of cookies.