wp_schedule_event is planned but function not firing - php

I have some trouble with the wp_schedule_event function and I was not able to find any solution here so far.
The event is triggert, atleast I see the next planned when calling wp_next_scheduled( 'update_expired_events_hourly' ), but when the time is reached, nothing is happening.
Also the function is working fine when I call it manually. I tried to fire the event by calling /wp-cron.php?doing_wp_cron, but that had no effect either.
The following code is in my themes functions.php
Any suggestions how to fix that?
Thank you in advance!
add_action( 'wp', 'expired_activation' );
add_action( 'update_expired_events_hourly', 'update_expired_events' );
function expired_activation(){
if ( !wp_next_scheduled( 'update_expired_events_hourly' ) ) {
wp_schedule_event(time(), 'hourly', 'update_expired_events_hourly');
}
}
function update_expired_events(){
// events query
$args = array(
'post_type' => 'espresso_events',
'post_status' => array('publish', 'pending', 'draft', 'auto-draft', 'future', 'private', 'inherit', 'trash'),
'post_per_page' => -1,
'tax_query' => array(
array(
'taxonomy' => 'espresso_event_categories',
'field' => 'slug',
'terms' => 'ee_exp', // the expired category slug
'operator' => 'NOT IN',
),
)
);
$events = new WP_QUERY($args);
$today = strtotime(current_time( "Y-m-d H:i:s", $gmt =0 )); // get current date
if ( $events->have_posts() ){
while ( $events->have_posts() ){
$events->the_post();
//get event end date
$event_end = strtotime( espresso_event_end_date( 'Y-m-d', 'H:i:s', false, false ) ); // get event end date
if( $event_end - (60*60*24) < $today ){
wp_set_object_terms( get_the_ID(), 'ee_exp', 'espresso_event_categories', true); // Add post to expired category
}
}
}
}
I forgot to mention, that define('DISABLE_WP_CRON'); is set to false in my config.php
---------------------- EDIT ----------------------
The code above is working. Apparently the only thing not working was firing the event via URL (/wp-cron.php?doing_wp_cron). Sorry for that and thx for your help!

I think you shouldn't disable wp_cron I suggest you use wp_schedule_single_event it worked well for me
wp_schedule_single_event( time() + 3600, 'update_expired_events_hourly' );

Related

Automatically draft WordPress Posts older than 30 days using CRON

I have a WordPress site with 1000s of posts. I'd like to set all posts older than 30 days to draft automatically when it reaches the specified date.
Been staring myself blind at the following code - triggering the CRON manually has now effect:
<?php
/**
* Function that will draft specific posts on specific conditions
*
* #param \WP_Post $_post
*/
function tgs_maybe_draft_the_post( $_post ) {
$publish_date = get_the_date( 'd M Y', $_post->ID);
// Bail if no publish date set for some reason.
if ( ! $publish_date ) {
return;
}
// Set status to draft if older than 30 days.
if (strtotime($publish_date) < strtotime('-30 days')) {
wp_update_post( array(
'ID' => $_post->ID,
'post_status' => 'draft'
) );
}
}
/**
* Register cron event on init action
*/
function tgs_cron_schedule_draft_posts() {
$timestamp = wp_next_scheduled( 'tgs_draft_posts' );
if ( $timestamp == false ) {
wp_schedule_event( time(), 'hourly', 'tgs_draft_posts' );
}
}
add_action( 'init', 'tgs_cron_schedule_draft_posts' );
/**
* Handle deletion of posts periodically.
* - Loop through the posts and call the tgs_maybe_draft_the_post function.
*/
function tgs_draft_posts_handler() {
$posts = get_posts( array(
'posts_per_page' => - 1,
'post_type' => 'post',
'post_status' => 'publish',
'suppress_filters' => true,
) );
foreach ( $posts as $_post ) {
tgs_maybe_draft_the_post( $_post );
}
}
add_action( 'tgs_draft_posts', 'tgs_draft_posts_handler' );
What am I doing wrong?
You can troubleshoot your logic (change status to draft) by running that logic directly during a page view rather than from cron. Try using the wp_footer action, something like this.
add_action( 'wp_footer', 'tgs_draft_posts_handler')
You can then include print_r(); debugging code and it will show up on your rendered page: ugly but useful. You could do print_r('about to do get_posts'); for example.
You can search for posts with date criteria. That way you don't need a separate check for the posts' age. With thousands of posts this is a significant time saver.
$posts = get_posts( array(
'posts_per_page' => - 1,
'post_type' => 'post',
'post_status' => 'publish',
'suppress_filters' => true,
'date_query' => array(
array(
'column' => 'post_date_gmt',
'before' => '30 days ago'
)
),
) );
Once your basic logic works, you can get it working under cron.
And, turn on the WordPress debugging stuff. It helps a lot.
When it all works, don't forget to remove the print_r() statements (duh, obviously).

WooCommerce: Change order status based on custom Meta Value

I'm trying to run the following function daily, to auto-complete all processing order older than 10 days and who have a specific custom meta value.
I'm using the following snippet, however this will simply not work. Any idea as to why?
function autoComplete(){
$orders = wc_get_orders( array(
'status' => 'wc-processing',
'date_created' => '<' . ( time() - 10 * DAY_IN_SECONDS ),
'meta_key' => 'status_us',
'meta_compare' => '=',
'meta_value' => 'Sent to USA',
) );
foreach ($orders as $order){
$order->update_status( 'completed' );
}
}
if ( ! wp_next_scheduled( 'autoComplete' ) ) {
wp_schedule_event( time(), 'daily', 'autoComplete' );
}
Is there any error I've missed? Thanks for your help!
You did a good attempt but you made a few mistakes.
The following code goes inside your functions.php.
add_action( 'wp_loaded','start_custom_code' );
// Once everything theme and plugins are loaded we register our cron job.
function start_custom_code() {
if ( ! wp_next_scheduled( 'bks_mark_processing_order_complete_if_sent_to_usa' ) ) {
wp_schedule_event( time(), 'daily', 'bks_mark_processing_order_complete_if_sent_to_usa' );
}
}
add_action( 'bks_mark_processing_order_complete_if_sent_to_usa', 'bks_mark_processing_order_complete_if_sent_to_usa' );
Your function has minor errors bks_mark_processing_order_complete_if_sent_to_usa()
function bks_mark_processing_order_complete_if_sent_to_usa(){
$args = array(
'status' => array( 'wc-processing'),
'limit' => -1,
'date_created' => '>' . ( time() - 864000 ), // your mistake 1
'status_us' => 'Sent to USA', // your mistake 2
);
$orders = wc_get_orders( $args );
foreach ($orders as $order){
$order->update_status( 'completed' );
$order->save(); // your mistake 3
}
};
Mistake Explanations
While your attempt was in right direction but 'date_created' => '<' . ( time() - 10 * DAY_IN_SECONDS ), you had to use > instead of < also you didn't acutally set DAY_IN_SECONDS You had to replace it with 86400. So the correct value would be '>' . ( time() - 864000 ). For 10 days 10 * 86400 = 864000. You can read about this explanation here in the WooCommerce documentation.
Here I have created new custom variable for you which is set using woocommerce_order_data_store_cpt_get_orders_query and then queried. Code that needs to be added.
function handle_custom_query_var( $query, $query_vars ) {
if ( ! empty( $query_vars['status_us'] ) ) {
$query['meta_query'][] = array(
'key' => 'status_us',
'value' => esc_attr( $query_vars['status_us'] ),
);
}
return $query;
}
add_filter( 'woocommerce_order_data_store_cpt_get_orders_query', 'handle_custom_query_var', 10, 2 );
You updated the status but you forgot to save it. $order->save();
So to summarise you have to add the following code in your functions.php
add_action( 'wp_loaded','start_custom_code' );
add_action( 'bks_mark_processing_order_complete_if_sent_to_usa', 'bks_mark_processing_order_complete_if_sent_to_usa' );
function start_custom_code() {
if ( ! wp_next_scheduled( 'bks_mark_processing_order_complete_if_sent_to_usa' ) ) {
wp_schedule_event( time(), 'daily', 'bks_mark_processing_order_complete_if_sent_to_usa' );
}
}
function bks_mark_processing_order_complete_if_sent_to_usa(){
$args = array(
'status' => array( 'wc-processing'),
'limit' => -1,
'date_created' => '>' . ( time() - 864000 ),
'status_us' => 'Sent to USA',
);
$orders = wc_get_orders( $args );
foreach ($orders as $order){
$order->update_status( 'completed' );
$order->save();
}
};
function handle_custom_query_var( $query, $query_vars ) {
if ( ! empty( $query_vars['status_us'] ) ) {
$query['meta_query'][] = array(
'key' => 'status_us',
'value' => esc_attr( $query_vars['status_us'] ),
);
}
return $query;
}
add_filter( 'woocommerce_order_data_store_cpt_get_orders_query', 'handle_custom_query_var', 10, 2 );
The above code is TESTED and WORKS.
Proof:
Install WP CRON plugin to check your cron. See above screenshot. You can test by hitting Run Now.
Caveat :
WP Cron runs, when somebody visits your website. Thus if nobody visits, ?>the cron never runs.
Read this : https://wordpress.stackexchange.com/a/179774/204925
Here is what I do to validate orders based on a CRON task.
$order->payment_complete('transaction ID string'); //validate payment
wc_reduce_stock_levels($order->get_id()); //reduce stock
$woocommerce->cart->empty_cart(); //empty cart
$order->update_status('completed', 'A order note string'); //change order statyus
I believe that you don't need the "wc-" prefix.
Are you sure that your scheduled event is working? and that $orders is filled? Please test your method without the schedule first.

Delete Page after plugin deactivation code not working

I am trying to delete page after plugin deactivate.The code is not working for delete page.
register_activation_hook( __FILE__, 'insert_page' );
function insert_page(){
// Create post object
$my_post = array(
'post_title' => 'Menu',
'post_content' => 'Short Code',
'post_status' => 'publish',
'post_author' => get_current_user_id(),
'post_type' => 'page',
);
// Insert the post into the database
wp_insert_post( $my_post, '' );
$newvalue = wp_insert_post( $post, false );
update_option( 'Menu', $newvalue );
}
register_deactivation_hook( __FILE__, 'deactivate_plugin' );
function deactivate_plugin() {
$page = get_page_by_title('Menu');
wp_delete_post($page);
}
I have even tried wp_delete_post($page, true);. It is also not working. Help me where i am wrong.
I'm going to address a few things if you don't mind:
First of all, you should work on your code indentation/formatting. Future you thanks you!
Second of all you're calling the wp_insert_post() function twice, but it's only working once. You can also check to see if wp_insert_post() returns a truthy value before calling update_option().
Third, be careful with "common" function names, as you risk having redeclaration errors! Try and use namespaces, classes or at the very least prefix your functions names to avoid future headaches.
Fourth, you don't need to set the $error parameter to false on wp_insert_post() as that is its default value.
Lastly, to answer your question (finally!) it's not working because wp_delete_post() requires a Post ID and you're passing a Post Object. Instead you'll want to use $page->ID. Here's your code with the changes I outlined above:
register_activation_hook( __FILE__, 'so_50960355_insert_page' );
function so_50960355_insert_page(){
// Define my page arguments
$page = array(
'post_title' => 'Menu',
'post_content' => 'Short Code',
'post_status' => 'publish',
'post_author' => get_current_user_id(),
'post_type' => 'page',
);
if( $page_id = wp_insert_post( $page ) ){
// Only update this option if `wp_insert_post()` was successful
update_option( 'my_menu_page_id', $page_id );
}
}
register_deactivation_hook( __FILE__, 'so_50960355_delete_page' );
function so_50960355_delete_page(){
$page_id = intval( get_option( 'my_menu_page_id' ) );
// Force delete this so the Title/slug "Menu" can be used again.
wp_delete_post( $page_id, true );
}

WordPress: Trash Custom Post Type after 30 days

I want to trash (not force delete) a Custom Post Type after 30 days.
To do this, I've found a nice solution from #pieter-goosen to delete posts after a number of days: https://wordpress.stackexchange.com/questions/209046/delete-expired-posts-after-a-number-of-days-after-they-expired
My problem is, that the function deletes all the posts of this Custom Post Type and doesn't use the trash.
My code looks like this:
function get_exired_posts_to_delete()
{
/**
* If you need posts that expired more than a week ago, we would need to
* get the unix time stamp of the day a week ago. You can adjust the relative
* date and time formats as needed.
* #see http://php.net/manual/en/function.strtotime.php
* #see http://php.net/manual/en/datetime.formats.php
*/
// As example, we need to get posts that has expired more than 7days ago
$past = strtotime( "- 1 week" );
// Set our query arguments
$args = [
'fields' => 'ids', // Only get post ID's to improve performance
'post_type' => 'job',
'post_status' => 'publish',
'posts_per_page' => -1,
'date_query' => array(
'column' => 'post_date_gmt',
'before' => '30 days'
)
];
$q = get_posts( $args );
// Check if we have posts to delete, if not, return false
if ( !$q )
return false;
// OK, we have posts to delete, lets delete them
foreach ( $q as $id )
wp_delete_post( $id );
}
// expired_post_delete hook fires when the Cron is executed
add_action( 'expired_post_delete', 'get_exired_posts_to_delete' );
// Add function to register event to wp
add_action( 'wp', 'register_daily_post_delete_event');
function register_daily_post_delete_event() {
// Make sure this event hasn't been scheduled
if( !wp_next_scheduled( 'expired_post_delete' ) ) {
// Schedule the event
wp_schedule_event( time(), 'daily', 'expired_post_delete' );
}
}
Is there anythin wrong with the date query?
And is there a better solution to use the server cron instead the WP cron?
I found a solution for my question.
For the problem with the trash, I've changed the argument wp_delete_post() to wp_trash_post() because wp_delete_post() only applies to native posts, pages, and attachments. Great answer from #rarst here: https://wordpress.stackexchange.com/questions/281877/error-after-deleting-custom-post-type-with-a-function-no-trash-used/281888#281888
Here is my code:
function get_delete_old_jobs() {
// Set our query arguments
$args = [
'fields' => 'ids', // Only get post ID's to improve performance
'post_type' => 'job',
'post_status' => 'publish',
'posts_per_page' => -1,
'date_query' => array(
'before' => date('Y-m-d', strtotime('-30 days'))
)
];
$q = get_posts( $args );
// Check if we have posts to delete, if not, return false
if ( !$q )
return false;
// OK, we have posts to delete, lets delete them
foreach ( $q as $id )
wp_trash_post( $id );
}
// expired_post_delete hook fires when the Cron is executed
add_action( 'old_job_delete', 'get_delete_old_jobs' );
// Add function to register event to wp
add_action( 'wp', 'register_daily_jobs_delete_event');
function register_daily_jobs_delete_event() {
// Make sure this event hasn't been scheduled
if( !wp_next_scheduled( 'old_job_delete' ) ) {
// Schedule the event
wp_schedule_event( time(), 'hourly', 'old_job_delete' );
}
}

Wordpress Plugin - Delete a Page Created when deactivating

I tried to make a custom post type plugin for my own use, and managed to make a function that creates the page for it so far. What I want to do is to delete the said page when the plugin is activated. How should the code be?
This is my code for creating the said page upon plugin activation:
function create_video_pages() {
$post = array(
'comment_status' => 'open',
'ping_status' => 'closed' ,
'post_date' => date('Y-m-d H:i:s'),
'post_name' => 'videos',
'post_status' => 'publish' ,
'post_title' => 'Videos',
'post_type' => 'page',
);
$newvalue = wp_insert_post( $post, false );
update_option( 'vidpage', $newvalue );
}
Get the post_id from your vidpage option.
Then use it to delete that post.
function deactivate_plugin() {
$page_id = get_option('vidpage');
wp_delete_post($page_id);
}
register_deactivation_hook( __FILE__, 'deactivate_plugin' );
You can do this using register_deactivation_hook and function wp_delete_post which deletes post with everything that is tied to it.
What about this?
function on_deactivating_your_plugin() {
$page = get_page_by_path( 'about' );
wp_delete_post($page->ID);
}
register_deactivation_hook( __FILE__, 'on_deactivating_your_plugin' );

Categories