0

I have a local WordPress website installment. I have custom post type "tours" and a custom taxonomy connected to it called "active-past". This taxonomy has two terms "active1" and "past1". Connected to this custom post type I have a custom post field "datum_polaska" in a date format. I would like to be able to automatically change the term "active1" to "past1" if "datum_polaska" is older than the current date. How can I accomplish this? I want this to be checked for each post containing the term "active1" only once per day. It's important that the event is triggered automatically on a time base. I found this answer, but I don't get how to implement it for my case. I tinkered around with chatGPT (sorry if this insults someone here) and I got these two codes:

function update_tour_status() {
// Get all posts with the "active1" term
$args = array(
    'post_type' => 'tours',
    'tax_query' => array(
        array(
            'taxonomy' => 'active-past',
            'field' => 'slug',
            'terms' => 'active1'
        )
    ),
    'posts_per_page' => -1 // Retrieve all posts
);
$query = new WP_Query($args);

// Loop through each post and update the term if needed
while ($query->have_posts()) {
    $query->the_post();
    $datum_polaska = get_post_meta(get_the_ID(), 'datum_polaska', true);
    if ($datum_polaska && strtotime($datum_polaska) < time()) {
        wp_set_post_terms(get_the_ID(), 'past1', 'active-past', false);
    }
}

wp_reset_postdata();

}

and this

// Schedule the event to run every 5 minutes for testing purposes
add_action('wp', 'my_custom_cronjob');
function my_custom_cronjob() {
    if (! wp_next_scheduled('update_tour_status')) {
        wp_schedule_event(time(), '5min', 'update_tour_status');
    }
}

I tried using them as 2 separate code snippets but they don't do anything. Does anyone have any idea what's wrong with the code? Please bear in mind that I'm not a developer and that I barely understand the concepts in the code. If someone has a suggestion on how to deal with this in some other way I'm happy to hear it.

1 Answer 1

0

This is pretty straight forward and easy to do with $wpdb and SQL statement

the relationship between any post type (custom or not) and taxonomy term (custom or not ) are stored wp_term_relationships table which has object_id and term_id

all you have to do is query the record that has the term_id for active1 term and update that to term_id of past1 term, if the postmeta value with meta key datum_polaska of the object_id is greater than the current time.

Here is a function to do that (untested)

function _update_tours_post_type_terms() {
    
    // Added additional condition to terminate the function when called many times per day
    $tsKey = '_update_tours_post_type_terms_last_run';
    $lastRun = get_transient( $tsKey ); // get the transient data
    
    /* Un-comment the line below if you want to;
     * stop execution if the last time it was called is < 12 hour ( 12 hr = 43200 seconds )
    */

    //if (  $lastRun + 43200 > time() )
        //return;
    
    global $wpdb;

    $activeTermID = 1; // set the active1 term ID   
    $pastTermID = 2; // set the past1 term ID
    $currentDate =  date('Y-m-d'); // get current date and make sure it matches the format you stored in postmeta

    /*
        Next code explains below per line
        -run update statement on term_relationships table on all rows matching all if condition below
        -set the term_taxonomy_id to $pastTermID
        -load the postmeta where meta post_id = object_id and meta_key is datum_polaska
        -if the current term_taxonomy_id value is $activeTermID
        -if datum_polaska is less than $currentDate
    */
    $wpdb->query($wpdb->prepare("
        UPDATE $wpdb->term_relationships tr         

        SET tr.term_taxonomy_id = $pastTermID

        INNER JOIN $wpdb->postmeta dp ON dp.post_id = tr.object_id AND dp.meta_key = 'datum_polaska'        

        WHERE tr.term_taxonomy_id = $activeTermID

        AND dp.meta_value < '$currentDate'

    "));

    // Update transient to current time if the function runs
    set_transient( $tsKey, time() );

}

and thats it, no need for query or looping, this just need the post type to to have the active1 term set while past1 should not be assign, otherwise it wont work as this simply update/replaces the record already present in the database.

All you have to do is call that function in your wp_schedule_event

Optional setting up cron from your server instead of using wordpress event scheduler

You may also set-up a cron directly from your server that runs every day. all you have to do is set a url param and call the function when the param is present in the request.

e.i

add_action('init', function() {
    
    //terminate if update_tours_post_type_terms is not present in url parameter or if its value is not equal to 1
    if ( !isset( $_REQUEST['update_tours_post_type_terms'] ) || !$_REQUEST['update_tours_post_type_terms'] === '1' )
        return;
    
    _update_tours_post_type_terms();
    
});

Then you can simply open the URL to run that function

https://yoursite.com/?update_tours_post_type_terms=1

and setup a daily cron on your server to ping that URL every day at 1AM

0 1 * * * wget -O - https://yoursite.com/?update_tours_post_type_terms=1 >/dev/null 2>&1

EDIT

If you want to test the function, first make sure the code below is commented (I already edited the function above which disable those lines

if (  $lastRun + 43200 > time() )
    return;

Second, you can implement the init hook above then simply open the example url I mentioned

OR just hook the function direclty on init (this should not be done unless you are just testing)

e.i.

add_action('init', '_update_tours_post_type_terms');

then wherever you browse your site (front-end or back-end) that function will run,

you can simply assign an active1 term with a past date meta, and it should update itself to past1 once you hit save

5
  • Wow! Thanks for this great explanation and code!
    – Trombolo
    Feb 18, 2023 at 16:45
  • I have to say that I'm struggling to implement this code. I want to test it out without waiting for 12h period. I'm using a code snippet for this. I asked chatGPT how to achieve this, and it told me to use another snippet with this code: function manually_trigger_update_tours_post_type_terms() { _update_tours_post_type_terms(); } add_action( 'init', 'manually_trigger_update_tours_post_type_terms' ); It's supposed to trigger your function once I activate this code snippet. Sadly it did not work. What am I doing wrong?
    – Trombolo
    Feb 18, 2023 at 17:02
  • I'm not sure if your code is not working properly or if I'm just not triggering the function _update_tours_post_type_terms().
    – Trombolo
    Feb 18, 2023 at 17:03
  • I edited my answer,
    – silver
    Feb 18, 2023 at 17:16
  • I think the best thing would be to ask chatGPT to explain the whole function code per line to you, so you have better understanding as it appears you are not aware with if and return statement :) although Im not sure how accurate would be the explanation
    – silver
    Feb 18, 2023 at 17:25

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.