Skip Navigation

[Resolved] CRON Job to manage post expiry across all CPTs via their individual data

This support ticket is created 6 years, 4 months ago. There's a good chance that you are reading advice that it now obsolete.

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

Sun Mon Tue Wed Thu Fri Sat
8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 - -
13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 13:00 – 17:00 - -

Supporter timezone: America/New_York (GMT-04:00)

This topic contains 12 replies, has 3 voices.

Last updated by Christian Cox 6 years, 3 months ago.

Assisted by: Christian Cox.

Author
Posts
#1089319

For all of my CPTs I have set up a checkbox field as below…
• If Post is still relevant, Value should be 0
• If Post has expired, Value should be 1

Each CPT has a different cause for expiry based on its unique data (such as event dates being in the past or product being out of stock), and some CPTs do not expire. I do not want to unpublish posts if expired, I simply want to update the checkbox field value so that it can be used to filter all views across my site whilst mixing different CPTs within the same views.

To do this, I'd like to set a CRON job to loop through the following CPTs and manage this checkbox field based on each CPT and each Posts individual data…

Expiry of these CPTs is optional:
• Posts: Expire IF ( 'Post Expiry Date' ne ' ' AND IS gte 'PAST_DAY()' )
• Charter Packages: Expire IF ( 'Charter Package Available Until' ne ' ' AND IS gte 'PAST_DAY()' ) OR 'Booking Stock Status' eq 'OutOfStock'

Expiry of these CPTs is based on post field values:
• Events: 'Event End Date' gte 'PAST_DAY()'
• Series: 'Series End Date' gte 'PAST_DAY()'
• Opportunities: 'Applications Closing Date' gte 'PAST_DAY()'
• Charter Opportunities: 'Opportunity End Date' gte 'PAST_DAY()' OR 'Booking Stock Status' eq 'OutOfStock'
• Appearances: 'Appearance Expiry Date' gte 'PAST_DAY()'
• Voyages: 'Voyage Embarkation Date' gte 'NOW()' OR 'Booking Stock Status' eq 'OutOfStock'
⁃ Price Options: Expire based on parent Voyage Expiry

Some CPTs (Organisations and Vessels) do not expire so I would likely just set the value in the first CRON job then remove it and have the field value set via CRED from then on.

Are you able to help with setting this up in php?

For reference, I'm running Types 2.2.22, Views 2.5.2 and CRED 1.9.5
I'm unlikely to be able to update easily due to the site already being live.

Thanks in Advance!

#1089545

I do not want to unpublish posts if expired, I simply want to update the checkbox field value so that it can be used to filter all views across my site whilst mixing different CPTs within the same views.
Please read the information here about using "save 0 when unchecked" and searches: https://toolset.com/errata/checkboxes-that-save-0-are-interpreted-as-checked-by-views/
It is best not to save "0" to indicate an unchecked checkbox. Instead, don't save this field key or any value at all. If you want to store two different values to indicate yes/no, consider using a radio button input with values 1 and 2.

Are you able to help with setting this up in php?
I can show you how to get any information you need from Types custom fields and I can give you advice, but the bulk of this code will be your responsibility. Setting up the code to run on a CRON may require assistance from your host.

Looping over posts from multiple post types in PHP: https://codex.wordpress.org/Class_Reference/WP_Query#Type_Parameters

$query_args = array(
  'post_type'   => array('post', 'charter-package', 'event'),
);
$query = new WP_Query( $query_args );
if ( $query->have_posts() ) {
  foreach ( $query->posts as $post ) {
    switch( $post->post_type) {
      case 'post':
        // validate each post here
        break;

      case 'charter-package':
        // validate each charter package post here
        break;

      case 'event':
        // validate each event post here
        break;

      default:
        break;
    }
  }
}

Set a checkbox field value of "1" on an expired post:

update_post_meta( $post->ID, 'wpcf-checkboxslug', 1);

Get a custom field value from a parent post:

$parent_id = get_post_meta( $post->ID, '_wpcf_belongs_parentslug_id' );
$parent_field = get_post_meta( $parent_id, 'wpcf-parentfieldslug', true);

To get a Unix timestamp date from a Types date custom field:

$timestamp = get_post_meta( $post->ID, 'wpcf-datefieldslug', true);

PHP Time functions:
http://php.net/manual/en/function.time.php
http://php.net/manual/en/function.mktime.php

#1096936

Hi Christian,

I'm almost there, using the code below, though it only seems to loop though a limited number of posts for each type. In this instance it runs through 2 organisations and around 10 vessels, but I actually have 80+ published vessel posts and around 15 organisation posts.

Can you advise on what may be the issue?

// CRON Job to update content relevance fields for post types specified
add_action( 'update_relevance_expiry_cron_hook', 'update_content_relevance' );

if ( ! wp_next_scheduled( 'update_relevance_expiry_cron_hook' ) ) {
    wp_schedule_event( time(), 'daily', 'update_relevance_expiry_cron_hook' );
}


function update_content_relevance()
 {
 
  $query_args = array(
    'post_type'   => array('post', 'organisations', 'vessels'),
  );

  $query = new WP_Query( $query_args );

  if ( $query->have_posts() ) 
    {

    foreach ( $query->posts as $post ) 
      {

      switch( $post->post_type) 
	{

        case 'organisations':

	   update_post_meta( $post->ID, 'wpcf-content-relevance', 1);
      	   $currentid = $post->ID;
	   $orelevant = 'Organisation Marked Relevant';
	   error_log(print_r($currentid, true));
	   error_log(print_r($orelevant, true));

        break;
 

        case 'vessels':

	   update_post_meta( $post->ID, 'wpcf-content-relevance', 1);
	   $currentid = $post->ID;
	   $vrelevant = 'Vessel Marked Relevant';
	   error_log(print_r($currentid, true));
	   error_log(print_r($vrelevant, true));


        break;


        case 'post':

	   update_post_meta( $post->ID, 'wpcf-content-relevance', 1);
	   $currentid = $post->ID;
	   $prelevant = 'Post Marked Relevant';
	   error_log(print_r($currentid, true));
	   error_log(print_r($prelevant, true));

 
        break;


        default:
          break;
	
      }
    }
  }
}

Here's what shows in the Error Log after running the CRON Job twice...

[31-Aug-2018 13:17:57 UTC] Vessel Marked Relevant
[31-Aug-2018 13:20:36 UTC] 3367
[31-Aug-2018 13:20:36 UTC] Organisation Marked Relevant
[31-Aug-2018 13:20:36 UTC] 3356
[31-Aug-2018 13:20:36 UTC] Vessel Marked Relevant
[31-Aug-2018 13:20:36 UTC] 3329
[31-Aug-2018 13:20:36 UTC] Organisation Marked Relevant
[31-Aug-2018 13:20:36 UTC] 3332
[31-Aug-2018 13:20:36 UTC] Vessel Marked Relevant
[31-Aug-2018 13:20:36 UTC] 3330
[31-Aug-2018 13:20:36 UTC] Vessel Marked Relevant
[31-Aug-2018 13:20:36 UTC] 2962
[31-Aug-2018 13:20:36 UTC] Vessel Marked Relevant
[31-Aug-2018 13:20:36 UTC] 2959
[31-Aug-2018 13:20:36 UTC] Vessel Marked Relevant
[31-Aug-2018 13:20:36 UTC] 2950
[31-Aug-2018 13:20:36 UTC] Vessel Marked Relevant
[31-Aug-2018 13:20:36 UTC] 2947
[31-Aug-2018 13:20:36 UTC] Vessel Marked Relevant
[31-Aug-2018 13:20:36 UTC] 2944
/* Second run starts here and runs through the same posts again */
[31-Aug-2018 13:20:36 UTC] Vessel Marked Relevant
[31-Aug-2018 13:22:05 UTC] 3367
[31-Aug-2018 13:22:05 UTC] Organisation Marked Relevant
[31-Aug-2018 13:22:05 UTC] 3356
[31-Aug-2018 13:22:05 UTC] Vessel Marked Relevant
[31-Aug-2018 13:22:05 UTC] 3329
[31-Aug-2018 13:22:05 UTC] Organisation Marked Relevant
[31-Aug-2018 13:22:05 UTC] 3332
[31-Aug-2018 13:22:05 UTC] Vessel Marked Relevant
[31-Aug-2018 13:22:05 UTC] 3330
[31-Aug-2018 13:22:05 UTC] Vessel Marked Relevant
[31-Aug-2018 13:22:05 UTC] 2962
[31-Aug-2018 13:22:05 UTC] Vessel Marked Relevant
[31-Aug-2018 13:22:05 UTC] 2959
[31-Aug-2018 13:22:05 UTC] Vessel Marked Relevant
[31-Aug-2018 13:22:05 UTC] 2950
[31-Aug-2018 13:22:05 UTC] Vessel Marked Relevant
[31-Aug-2018 13:22:05 UTC] 2947
[31-Aug-2018 13:22:05 UTC] Vessel Marked Relevant
[31-Aug-2018 13:22:05 UTC] 2944
[31-Aug-2018 13:22:05 UTC] Vessel Marked Relevant
#1097910

Okay great, you should add a parameter to the query that sets the number of posts to -1. Otherwise the default value(s) may be applied.

$query_args = array(
    'post_type'   => array('post', 'organisations', 'vessels'),
    'numberposts' => -1,
  );

More details about that here:
https://developer.wordpress.org/reference/functions/get_posts/

#1098497

Hi Christian,

I have made this adjustment and I'm unfortunately still getting the same result, could there be something else restricting this?

#1098810

Shane
Supporter

Languages: English (English )

Timezone: America/Jamaica (GMT-05:00)

Hi Jon,

Christian is currently on a public holiday today but he will be back tomorrow to continue helping here.

Thanks,
Shane

#1099549

Ok, no problem.

For refefnce I have been in touch with my host to try increasing php timeouts and memory limits but these did not fix the issue.

#1099717

There could be another plugin or theme file causing interference in the query, or it could be something else going on. Are the missing vessels and organizations private? Are they scheduled to be published in the future? Any other reason they would be inaccessible to a query?

Try creating a custom shortcode that calls the same update_content_relevance function:

add_shortcode("test-relevance", "update_content_relevance");

Then test the shortcode on your site to eliminate problems with the CRON:

[test-relevance]
#1101347

Hi Christian,

Calling the function via the shortcode delivered the same result so I'll begin deactivating plugins to see if one of these is causing the conflict.

Whilst there are a few draft posts, the vast majority are publicly published and not appearing in the results.

#1101699

Okay I'll stand by for your update.

#1104443

Hi Christian,

I have tried disabling everything except for the Toolset Plugins and can still see the issue appearing.

I avoided disabling Toolset plugins because it's a live site.
Is it possible you could test deactivating the Toolset plugins on a duplicate site?

#1104740

Sure, if you want to set up a duplicate site for me that's fine, or you can give me login credentials to the live site and I can create a clone using the Duplicator plugin. I will activate private reply fields here so you can share either credentials here.

#1109067

Okay I think this query is performing correctly on my local test site:

 $query_args = array(
    'post_type'   => array('post', 'organisations', 'vessels'),
    'posts_per_page' => -1,
  );

Please try this correction on your live site and let me know if it's not finding all the posts as expected.