I'm using WordPress and Elementor. There are 2 post types named "albums" and "clips". The clips post type stores video clips for specific album under albums post type. A custom Elementor query displays all albums under which user has uploaded the clips.
When the queries are tested on a testing page, it works fine. But when included under Elementor custom query, it doesn't work. Here is the code,
function user_contributed( $query ) {
// initialize array
$albums[] = '';
// Get logged in user id
$user_id = get_current_user_id();
if(isset($user_id) && !empty($user_id)){
$user_info = get_userdata($user_id);
// Get user email ID
$user_email = $user_info->user_email;
// Get the user contributed clips from "clips" post type
$args = array( 'post_type' => 'clips', 'posts_per_page' => -1,
'meta_query' => array( array( 'key' => 'user_email', 'value' => $user_email, 'compare' => '=' ), 'relation' => 'AND', array( 'key' => 'clip_status', 'value' => 'ready', 'compare' => '=' ) ),
);
$contributed_query = new WP_Query( $args );
if($contributed_query->have_posts()) {
if($contributed_query->post_count > 0){
while($contributed_query->have_posts() ) {
$contributed_query->the_post(); $postid = get_the_ID();
// Get album ID from ACF field
$albumid = get_field( "album_id", $postid );
if(!in_array($albumid, $albums)){ $albums[] = $albumid; }
}
}
}
// Get all albums from "album" post type, where logged-in user has contributed
$query->set( 'post_type', [ 'albums' ] );
$query->set( 'post__in', $albums );
}
}
add_action( 'elementor/query/user_contributed', 'user_contributed' );
I think the first query is overwriting or conflicting with the main query. I tried wp_reset_postdata, wp_reset_query and pre_get_posts but didn't work. The Elementor custom query documentation wasn't helpful. Is it possible to execute a query before the main query?
I tried wp_reset_postdata, wp_reset_query and pre_get_posts but didn't work.
Related
I have created a custom post similar to WordPress posts that I want to delete automatically every time (for example, every day or every week).
Is there a function for this?
I know that you can delete trash posts with the following function
define('EMPTY_TRASH_DAYS', 10 );
But what about custom created posts?
Thanks for your help
I think, this code will full fill your requirements.
// Define the custom post type that you want to delete automatically
$custom_post_type = 'your_custom_post_type';
// Function to delete the custom post type posts
function delete_custom_post_type_posts() {
// Get all published posts of the custom post type
$current_date = current_time('Y-m-d');
$yesterday_date = date('Y-m-d', strtotime('-1 day', strtotime($current_date)));
$args = array(
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => -1,
'date_query' => array(
'after' => $yesterday_date,
'before' => $current_date,
'inclusive' => true
)
);
$my_posts = get_posts( $args );
// Loop through the posts and delete them
foreach ( $my_posts as $my_post ) {
wp_delete_post( $my_post->ID, true );
}
}
// Schedule the event to run every week
if ( ! wp_next_scheduled( 'delete_custom_post_type_posts_event' ) ) {
wp_schedule_event( time(), 'twicedaily', 'delete_custom_post_type_posts_event' );
}
// Hook the function to the scheduled event
add_action( 'delete_custom_post_type_posts_event', 'delete_custom_post_type_posts' );```
You can delete published posts every week by setting up a wp_schedule_event
Hope this code helps
// Define the custom post type that you want to delete automatically
$custom_post_type = 'your_custom_post_type';
// Function to delete the custom post type posts
function delete_custom_post_type_posts() {
// Get all published posts of the custom post type
$current_date = current_time('Y-m-d');
$last_week_date = date('Y-m-d', strtotime('-1 week', strtotime($current_date)));
$args = array(
'post_type' => 'post',
'post_status' => 'publish',
'posts_per_page' => -1,
'date_query' => array(
'after' => $last_week_date,
'before' => $current_date,
'inclusive' => true
)
);
$posts = get_posts( $args );
// Loop through the posts and delete them
foreach ( $posts as $post ) {
wp_delete_post( $post->ID, true );
}
}
// Schedule the event to run every week
if ( ! wp_next_scheduled( 'delete_custom_post_type_posts_event' ) ) {
wp_schedule_event( time(), 'weekly', 'delete_custom_post_type_posts_event' );
}
// Hook the function to the scheduled event
add_action( 'delete_custom_post_type_posts_event', 'delete_custom_post_type_posts' );
I have a custom post type called 'movie' and custom taxonomy called 'genre'.
The genre custom taxonomy has several categories, such as 'western', 'action', animation' etc.
What I am trying to do is check if a post already exists in one of the custom categories, before running this function...
wp_insert_post( $args);
So for example, if I go to create a new movie post called Terminator and want to put it in the 'action' custom category, I need a condition that checks if a post called Terminator already exists in that 'action' category before running the wp_insert_post() function.
I know about this...
$post_id = post_exists( 'Terminator' );
if (!$post_id) {
//
}
...but that only checks for a duplicate post across all posts, and so isn't very helpful.
Can this even be done in WordPress?
You can use WP_Query to search in previous CTPs:
$post_args = array(
'post_type' => 'movie',
'post_title' => 'terminator',
'tax_query' => array(
array(
'taxonomy' => 'genre',
'field' => 'slug',
'terms' => 'action',
),
),
);
$query = new WP_Query( $post_args );
if( ! $query->have_posts() ) {
$args = array(
.......
);
wp_insert_post( $args);
}
I'm using a plugin that already count product views and store it in a table called 'mwb_wpr_data'.
The query to list the product views is:
SELECT DISTINCT('productid') FROM 'mwb_wpr_data' WHERE 'action' = 'view'
The productid field is a FK to Woocomerce products.
How can I modify the Woocommerce default sorting, so it will display products by order of most views based in the table 'mwb_wpr_data'?
Current code using the plugin Post View Counter:
add_action( 'pre_get_posts', 'my_view_filter' );
function my_view_filter($query){
if (
$query->is_main_query() &&
( $query->is_home() || $query->is_archive() || $query->is_search() )
) {
$query->set('suppress_filters', 'false');
$query->set('orderby', 'post_views');
$query->set('order', 'DESC');
}
}
According to me you have set the correct pre_get_post but problem is in your if condition.
You have set the current_user_can which not correct filter is for every user so if you are not login in with administrator role than your query will not work.
current_user_can('administrator')
Remove this above one from the condition.
add_action( 'pre_get_posts', 'my_view_filter' );
function my_view_filter($query){
if ($query->is_main_query() && ( $query->is_home() || $query->is_archive() || $query->is_search() )
) {
$query->set('suppress_filters', 'false');
$query->set('orderby', 'post_views');
$query->set('order', 'DESC');
}
}
Ok, so the RIGHT way to do this would be
Change how your post view counts are stored, so that they are stored as postmeta of each product (post) in a field like _post_views_count.
Use meta_key & orderby in wp_query like this
$args = array(
'meta_key' => '_post_views_count',
'orderby' => 'meta_value_num',
'order' => 'ASC'
);
< EDIT >
IF you want to use the same plugin for recording your product views, I'd set up a function that fires every time a post view is added to the table that updates a postmeta field of the product.
Is it elegant? No.
Will it work? Yes.
Not sure about the plugin you're using (it would be great if you give additional info about it) but I've been using Post Views Counter for years and it works really well.
It even has a query parameter for WP_Query (to query posts by post views):
EDIT: This query parameter won't work without the Post Views Counter plugin as it's not a WordPress default parameter.
More info about this plugin API here:
https://dfactory.eu/docs/post-views-counter/developers-api/
$query_args = array(
'posts_per_page' => 12,
'order' => 'DESC',
'suppress_filters' => false, //required param
'orderby' => 'post_views', //required param
);
$query = new WP_Query( $query_args );
if ( $query->have_posts() ):
while ( $query->have_posts() ): $query->the_post();
//Post content here
echo get_the_title();
endwhile;
endif;
I hope this helps,
Cheers!
According to the plugins documentation you are required to pass the post_type as well in order for this to work, i.e.
$args = array(
'order' => 'asc',
'post_type' => 'event',
// required by PVC
'suppress_filters' => false,
'orderby' => 'post_views',
'fields' => ''
);
$most_viewed = get_posts( $args );
That code is in the post that #Marounm linked to in comment higher up.
Try passing the post_type arg as well i.e.
$query->set('post_type', 'product');
If you want to showing the the products which was most viewed , so you can follow these below steps .
Steps :1 I have add menu in admin panel using (add_menu_page) function. in function file
function admin_manage_users22(){
add_menu_page('My Page Title', 'MVP', 'manage_options', 'MVP_backend_view',
'MVP_backend_view' );
}
add_action('admin_menu', 'admin_manage_users22');
Step :2 Get product details after user view product it's +1 counter value in wp_postmeta with post id. default value set 1
function MVP_product_details($product ) {
$post_id = get_the_ID();
$count_key = 'AK_product_view_count';
$count = get_post_meta( $post_id, $count_key, true );
if ( empty( $count ) ) {
delete_post_meta( $post_id, $count_key );
update_post_meta( $post_id, $count_key, '1' );
echo "count null";
}else{
$count ++;
update_post_meta( $post_id, $count_key, (string) $count );
}
}
add_filter( 'woocommerce_quantity_input_args', 'MVP_product_details', 10, 2 );
Step :3 Now you can get most viewed product details simply using below code.
function MVP_backend_view(){
$count_key = 'AK_product_view_count';
$query_args = array(
'posts_per_page' => 3,
'no_found_rows' => 1,
'post_status' => 'publish',
'post_type' => 'product',
'orderby' => 'meta_value',
'order' => 'DESC',
'meta_key' => $count_key,
);
$query_args['meta_query'] = array(
array(
'key' => $count_key,
'value' => '0',
'type' => 'numeric',
'compare' => '>',
),
);
$zwcmvp_query = new WP_Query( $query_args );
I am trying to setup a cron job for a custom post type (Job Listings), that contains two ACF custom fields.
Datepicker – User can choose closing date of the job ( ‘job_listing_closing_date’ )
Radio field – Open & Closed choices. ( ‘job_listing_status’ )
I need the radio field to change from ‘Open’ to ‘Closed’ in the backend post edit screen if the job_listing_closing_date has passed. Here is my code at the moment which is located within ‘/wp-content/themes/themename/assets/functions/cpt-job-listings.php file.
I’ve added the below to code to the website but nothing happens.
Maybe the query is wrong or the ACF fields aren’t available in the file I have coded in?
// Create a cron job in order to check the custom field of 'job_listing_closing_date' against today's date. If the date has passed, set the job status to 'closed' and display different content on front-end.
// Scheduled Action Hook
function check_job_end_date( ) {
// WP_Query arguments
$listings = array (
'post_type' => 'job_listings',
'posts_per_page' => -1,
'meta_key' => 'job_listing_closing_date',
'meta_query' => array(
'key' => 'job_listing_closing_date',
'value' => date( 'Ymd' ),
'compare' => '<',
'type' => 'NUMERIC',
)
);
global $post;
if ($listings->have_posts()) {
while ($listings->have_post()) {
$listings->the_post();
update_field('job_listing_job_status', 'Closed');
//update_post_meta($post->ID, 'job_listing_job_status', 'Closed');
}
wp_reset_postdata();
}
}
// Schedule Cron Job Event
function job_listing_cron_job() {
if ( ! wp_next_scheduled( 'check_job_end_date' ) ) {
wp_schedule_event( date( 'Ymd' ), 'daily', 'check_job_end_date' );
}
}
I ended up rewriting most of the code and this is what worked:
// Create a cron job in order to check the custom field of 'job_listing_closing_date' against today's date. If the date has passed, set the job status to 'closed' and display different content on front-end.
// Scheduled Action Hook
function check_job_end_date( ) {
global $post;
$args = array(
'post_type' => 'job_listings',
'posts_per_page' => -1,
);
$listings = get_posts( $args );
foreach($listings as $post) : setup_postdata($post);
$today = date( 'Ymd' );
$expire = get_field( 'job_listing_closing_date', false, false );
$status = get_field( 'job_listing_job_status' );
if ( $expire < $today ) :
$status = 'Closed';
update_field( 'job_listing_job_status', $status );
endif;
endforeach;
}
// Schedule Cron Job Event
if ( ! wp_next_scheduled( 'job_listing_cron_job' ) ) {
wp_schedule_event( date( 'Ymd' ), 'daily', 'job_listing_cron_job' );
}
add_action( 'job_listing_cron_job', 'check_job_end_date' );
Try this:
$listings = array (
'post_type' => 'job_listings',
'posts_per_page' => -1,
'meta_key' => 'job_listing_closing_date',
'meta_query' => array(
'key' => 'job_listing_closing_date',
'value' => date( 'Ymd' ),
'compare' => '<',
'type' => 'DATE',
)
);
And sure is the correct date format date( 'Ymd' )
I added this to my function.php for saving the post:
function my_pre_save_post( $post_id )
{
// check if this is to be a new post
if( $post_id != 'new' )
{
return $post_id;
}
// Create a new post
$post = array(
'post_status' => 'draft' ,
'post_title' => 'A title, maybe a $_POST variable' ,
'post_type' => 'post' ,
);
// insert the post
$post_id = wp_insert_post( $post );
// update $_POST['return']
$_POST['return'] = add_query_arg( array('post_id' => $post_id), $_POST['return'] );
// return the new ID
return $post_id;
}
add_filter('acf/pre_save_post' , 'my_pre_save_post' );
And on the page.php I've got this code:
$postid = get_the_ID();
if($postid ==50){ //50 is a Page I created for the Form
$options = array(
'post_id' => 'new',//$post->ID, // post id to get field groups from and save data to
'field_groups' => array(46), // this will find the field groups for this post (post ID's of the acf post objects)
'form' => true, // set this to false to prevent the <form> tag from being created
'form_attributes' => array( // attributes will be added to the form element
'id' => 'post',
'class' => '',
'action' => '',
'method' => 'post',
),
'return' => add_query_arg( 'updated', 'true', get_permalink() ), // return url
'html_before_fields' => '', // html inside form before fields
'html_after_fields' => '', // html inside form after fields
'submit_value' => 'Update', // value for submit field
'updated_message' => 'Post updated.', // default updated message. Can be false to show no message
);
acf_form( $options );
}
Now, I think the saving was successfull, how do I get the whole Posts that have been created with this Form?
I tried this (on page with ID 51), but I get nothing:
$posts = get_posts(array(
'post_type' => 'event',
'posts_per_page' => -1,
'meta_key' => 'location',
'meta_value' => 'melbourne'
));
if($posts)
{
foreach($posts as $post)
{
the_field('titel');
}
}
The ACF Plugin for Wordpress is very well documented, but I couldnt solve my problem.
http://www.advancedcustomfields.com/resources
according to the ACF form field documentation https://www.advancedcustomfields.com/resources/acf_form/
the "return" field has 2 dynamic placeholders
"(String) The URL to be redirected to after the form is submitted.
Defaults to the current URL with a GET parameter ‘?updated=true’. A
special placeholder ‘%post_url%’ will be converted to post’s
permalink. A special placeholder ‘%post_id%’ will be converted to
post’s ID."
if you add 'return' => '?newpost=%post_id%', for example, you get back your original page with the new post id as URL parameter that you can handle with PHP in your page template
The documentation says you've to set the post_id value inside your $options array to new_post instead of new if you want to create a new post. Also you've to use the new_post array key with an array with data for the new post as value for the key.
Check out the acf_form documentation. This is what I basically mean:
$options = array(
'post_id' = 'new_post',
'new_post' = array(
//new post data
)
);