How to change the modified time of a wordpress post? - wordpress

We are able to make use of ajax to update our post_meta as we wanted. However, it does not change the modified_time of the post.
We depend on the get_modified_time to show users when the post was last updated. (The newer the better)
I have searched around, and I don't see anyone using this technique yet.
Does anyone have an answer?
Thanks!

I used wpdb::query() to do this:
global $wpdb;
//eg. time one year ago..
$time = time() - DAY_IN_SECONDS * 365;
$mysql_time_format= "Y-m-d H:i:s";
$post_modified = gmdate( $mysql_time_format, $time );
$post_modified_gmt = gmdate( $mysql_time_format, ( $time + get_option( 'gmt_offset' ) * HOUR_IN_SECONDS ) );
$post_id = /*the post id*/;
$wpdb->query("UPDATE $wpdb->posts SET post_modified = '{$post_modified}', post_modified_gmt = '{$post_modified_gmt}' WHERE ID = {$post_id}" );
Note: You can't use wp_update_post() if you want to explicity set the modified date(s) on the post, because it calls wp_insert_post(), which determines that the post exists and sets the post_modified and post_modified variables to the current date.

Very simple in PHP, where 80 is the post number:
// update post_modified and post_modified_gmt `datetime` on a post
$update = array( 'ID' => 80 );
wp_update_post( $update );

If you want to change for set of posts, better use Query Loop to get each post id.

Assuming that you have previously collected the post ID from your ajax request you can then update post_modified and post_modified_gmt using the regular wp_update_post function:
$date = current_time('mysql');
wp_update_post(array(
'ID' => $post_id,
'post_modified' => $date,
'post_modified_gmt' => get_gmt_from_date($date),
));
Resources
https://developer.wordpress.org/reference/functions/wp_update_post/

Related

A Wordpress cronjob to cancel WC orders for a product that was deleted?

I have a project where a user can actually delete their own virtual product they have put up for sale and there may actually be some active orders on that product at the time of its deletion. I figured the best solution would be to add a cronjob that runs every 10 minutes, using a real cron, via crontab, rather than the Wordpress virtual cron, which I have already enacted - but the question is, how do I get all of the orders for a product and then change the status of all of those products to cancelled rather than deleting them, for posterity.
Any help will be appreciated, thank you.
So, worked it out... safer and just generally better way of doing this. Rather than a cronjob, you hook on post deletion and when a product is actually deleted you perform the query required. You find all the attached orders that are not already complete and you cancel those upcoming / pending orders.
function get_order_ids_by_product_id( $product_id, $order_status = array( 'wc-completed' ) ){
global $wpdb;
$results = $wpdb->get_col("
SELECT order_items.order_id
FROM {$wpdb->prefix}woocommerce_order_items as order_items
LEFT JOIN {$wpdb->prefix}woocommerce_order_itemmeta as order_item_meta ON order_items.order_item_id = order_item_meta.order_item_id
LEFT JOIN {$wpdb->posts} AS posts ON order_items.order_id = posts.ID
WHERE posts.post_type = 'shop_order'
AND posts.post_status NOT IN ( '" . implode( "','", $order_status ) . "' )
AND order_items.order_item_type = 'line_item'
AND order_item_meta.meta_key = '_product_id'
AND order_item_meta.meta_value = '$product_id'
");
return $results;
}
add_action( 'before_delete_post', 'check_for_active_orders' );
function check_for_active_orders($post_id){
$WC_Product = wc_get_product( $post_id );
$orders_ids = get_order_ids_by_product_id( $post_id );
if(count($orders_ids) > 0){
foreach($orders_ids as $oid){
$order = new WC_Order($oid);
$order->update_status('cancelled', 'This product has been removed.');
}
}
}
Hopefully it'll help someone else in the near future.

Custom post type archive in sidebar widget of post

This works fine. I see custom post type archive in dropdown but when I select any month, I see all custom posts on that archive page. While there is only one post in every month, for e.g. I have 1 post in month of July and 1 in August, the dropdown counter shows correct but when I select them I see all custom posts instead of just one. Is there any solution for this?
add_filter( 'getarchives_where', 'custom_getarchives_where' );
function custom_getarchives_where( $where ){
$where = str_replace( "post_type = 'post'", "post_type IN ( 'post', 'fruits' )", $where );
return $where;
}
add_action( 'pre_get_posts', 'add_podcasts_to_archive' );
function add_podcasts_to_archive( $query ) {
if ( $query->is_main_query() && $query->is_archive() && !is_admin() )
$query->set( 'post_type', array( 'post', 'fruits' ) );
return $query;
}
The code in your question works. I truely suspect that your problem lies in your archive.php template.
Here are my thoughts
you have replaced the main query with a custom query. An improper custom query on any archive page is disasterous. This is the only reason I can think of given the reason that you get all post from your custom post tytpe
My solution would be, delete your custom query, replace it with the default loop, and if you need any more customization, add it with pre_get_posts.
EDIT
For extra reading that might you lots in future
When to use a custom query and when not

How to get meta value by meta id

Example, I have a post's meta_key is 'name', meta_value is 'Jason',
and this meta_id in MySQL is 128
How can I get this meta_value by meta_id ?
The best way to do this is to use WordPress's built-in function, get_metadata_by_mid().
So in your case:
$value = get_metadata_by_mid( 'post', 128 );
I found this which might help you.
It describes How to get the Meta ID by Meta Key, so it is not exactly what you need but quite similar. Maybe all that is required is to modify that query a little.
get_metadata_by_mid( $meta_type, $meta_key ) will work for most situations. It returns an object with all the postmeta data.
$jason = get_metadata_by_mid( 'post', 128 );
echo 'Meta Value = ' . $jason->meta_value;
echo 'Post ID = ' . $jason->post_id;
// Results
Meta Value = Jason
Post ID = 123
If you need to do something a bit more custom such as get stock status of product using the meta id. You can use this.
global $wpdb;
$meta_id = 128;
$postmeta_post_id = $wpdb->get_var( $wpdb->prepare("SELECT post_id FROM {$wpdb->prefix}postmeta WHERE meta_id = %d", $meta_id) );
$stock_status = get_post_meta( $postmeta_post_id, '_stock_status', single );
echo 'Product status: ' . $stock_status;
//results
Product status: outofstock

Wordpress Queries to count updates post per day in specific categories

Anyone know how to count updates post per day (example: in this day/date) in specific categories with wordpress query ?
Thanks a lot.
I don't know if I fully understand your question, do you want a count of posts in a specific category posted on a specific day/date?
In this case, you can just create an instance of WP_Query and pass in the time parameters and categories you want you look at.
Something like,
<?php
$today = getdate();
$args = array('year' => $today["year"], 'monthnum' => $today["mon"], 'day' => $today["mday"], 'category_name' => 'Uncategorized');
$search = new WP_Query($args);
$count = $search->found_posts;
?>
If you want to return posts based on the modified date (you state count updates post per day, which I don't understand), then you need to add a 'posts_where' filter instead of the time parameters of args.
See the time parameters link above for sample code and explanations on using this - but in slightly modifying one of their examples you can create something like this.
// Create a new filtering function that will add our where clause to the query
function filter_where( $where = '' ) {
$where .= " AND post_modified >= '2010-03-01' AND post_modified < '2010-03-16'";
return $where;
}
add_filter( 'posts_where', 'filter_where' );
$query = new WP_Query( $query_string );
remove_filter( 'posts_where', 'filter_where' );

How to exclude password protected posts in WordPress loop

I have a custom post type that supports password protected entries. In a custom loop using a new WP_Query object, I want to exclude those password protected posts from the results. What arguments do I need set in order to do this? I am using the latest trunk version of WordPress 3.2.1.
I come up to this question where I was looking for the same. However, I read WP_Query document line by line then found very simple solution and that is just to add 'has_password' => false argument to the query $args
So the code will be as below...
$args = [
'post_type' => [ 'post', 'page' ],
'posts_per_page' => 3,
'post__not_in' => get_option( 'sticky_posts' ),
'has_password' => FALSE
];
Here you can see I have excluded Sticky and Password Protected posts.
I really like Kevin's approach, but I adjusted it slightly:
// Create a new filtering function that will add our where clause to the query
function my_password_post_filter( $where = '' ) {
// Make sure this only applies to loops / feeds on the frontend
if (!is_single() && !is_admin()) {
// exclude password protected
$where .= " AND post_password = ''";
}
return $where;
}
add_filter( 'posts_where', 'my_password_post_filter' );
Did you take a look at the post_status argument of WP_Query?
"Protected" seems like a good candidate to exclude.
Edit: Okay, it seems like you'll have to modify the where clause to achieve what you want:
// Create a new filtering function that will add our where clause to the query
function filter_where( $where = '' ) {
// exclude password protected
$where .= " AND post_password = ''";
return $where;
}
if (!is_single()) { add_filter( 'posts_where', 'filter_where' ); }
$query = new WP_Query( $query_string );
remove_filter( 'posts_where', 'filter_where' );
After a bit of playing about, I found the posts_where filter a bit too intrusive for what I wanted to do, so I came up with an alternative. As part of the 'save_post' action that I attached for my custom post type, I added the following logic;
$visibility = isset($_POST['visibility']) ? $_POST['visibility'] : '';
$protected = get_option('__protected_posts', array());
if ($visibility === 'password' && !in_array($post->ID, $protected)) {
array_push($protected, $post->ID);
}
if ($visibility === 'public' && in_array($post->ID, $protected)) {
$i = array_search($post->ID, $protected);
unset($protected[$i]);
}
update_option('__protected_posts', $protected);
What this does is hold an array of post id's in the options table where the post is protected by a password. Then in a custom query I simply passed this array as part of the post__not_in option e.g.
$query = new WP_Query(array(
'post_type' => 'my_custom_post_type',
'post__not_in' => get_option('__protected_posts'),
));
This way I could exclude the protected posts from an archive page but still allow a user to land on the password protected page to enter the password.
In addition to #Peter Chester's answer:
You may also want to exclude password-protected posts from the Previous Post and Next Post links, if you have those at the bottom of your post page.
To do so you can add the exclusion to the get_previous_post_where and get_next_post_where hooks.
add_filter( 'get_previous_post_where', 'my_theme_mod_adjacent' );
add_filter( 'get_next_post_where', 'my_theme_mod_adjacent' );
function my_theme_mod_adjacent( $where ) {
return $where . " AND p.post_password = ''";
}

Resources