I have in the Wordpress functions.php the next code that changes the main_query when posts are sorted using a form. The question is: how to exclude from the main_query the second array of the meta_query when the $country variable is empty?
if ( $query->is_main_query() && ( $orderby || $order || $country ) ) {
if ( in_array( $orderby, array( 'event_start_date' ) ) ) {
$query->set( 'orderby', 'meta_value' );
$query->set( 'order', $order );
$query->set( 'meta_query', array( // WordPress has all the results, now, return only the events after today's date
array(
'key' => 'event_start_date', // Check the start date field
'value' => date_i18n("Y-m-d"), // Set today's date (note the similar format)
'compare' => '>=', // Return the ones greater than or equal to today's date
'type' => 'DATE' // Let WordPress know we're working with date
),
array(
'key' => 'venue_country',
'value' => $country,
)
) );
}
}
UPDATE
A suggestion how to solve this I found here.
The problem was solved in this way:
if ( $query->is_main_query() && ( $orderby || $order || $country ) ) {
if ( in_array( $orderby, array( 'event_start_date' ) ) ) {
$query->set( 'orderby', 'meta_value' );
$query->set( 'order', $order );
if( !empty( $_GET['country'] ) ) {
$query->set( 'meta_query', $metaquery1 );
} else {
$query->set( 'meta_query', $metaquery2 );
}
}
}
Related
I used a big part of this code to add a meta_query in the WooCommerce product query. I don't get any errors, but the products are NOT getting filtered by the meta. It still shows all products.
function yl_custom_product_query( $query ) {
// check if the user is requesting an admin page
// or current query is not the main query
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
global $product;
$blog_id = get_current_blog_id();
if ($blog_id == '1') {
$subsite = '_visibility_3rdmillennium';
} elseif ($blog_id == '2') {
$subsite = '_visibility_fight2win';
} elseif ($blog_id == '3') {
$subsite = '_visibility_muaythai';
} elseif ($blog_id == '4') {
$subsite = '_visibility_taekwondo';
} elseif ($blog_id == '5') {
$subsite = '_visibility_xprtfightgear';
} elseif ($blog_id == '6') {
$subsite = '_visibility_hayabusashop';
} elseif ($blog_id == '7') {
$subsite = '_visibility_kmushop';
}
$meta_query = array();
// add meta_query elements
if ( !empty( get_query_var( $subsite ) ) ) {
$meta_query[] = array( 'key' => $subsite, 'value' => get_query_var( 'yes' ), 'compare' => 'LIKE' );
}
// unused meta_query for now
if ( !empty( get_query_var( 'key2' ) ) ) {
$meta_query[] = array( 'key' => 'key2', 'value' => get_query_var( 'key2' ), 'compare' => 'LIKE' );
}
if ( count( $meta_query ) > 1 ) {
$meta_query['relation'] = 'AND';
}
if ( count( $meta_query ) > 0 ) {
$query->set( 'meta_query', $meta_query );
}
}
add_action( 'pre_get_posts', 'yl_custom_product_query' );
But, when I change:
// add meta_query elements
if ( !empty( get_query_var( $subsite ) ) ) {
$meta_query[] = array( 'key' => $subsite, 'value' => get_query_var( 'yes' ), 'compare' => 'LIKE' );
}
to
// add meta_query elements
if ( !empty( $subsite ) ) {
$meta_query[] = array( 'key' => $subsite, 'value' => 'yes', 'compare' => 'LIKE' );
}
(so removing get_query_var twice) the meta_query works great but all static pages suddenly become unreachable...
What am I missing here?
I need to be able to filter WooCommerce products according to the values from an ACF field with a series of checkboxes e.g. Apples, Bananas, Grapes etc. Ideally I'd like to be able to do this with a URL query e.g. https://example.com/shop/?fruit=apples
I've been trying something along these lines with no success:
function product_initial_filter( $query ) {
if( !is_admin() ) {
if( isset($query->query_vars['post_type']) && $query->query_vars['post_type'] == 'product' ) {
if( isset($GET['fruit']) ) {
$query->set('meta_value', $GET['fruit']);
$query->set('meta_key', 'fruits');
$query->set('meta_compare', 'IN');
}
}
}
// return
return $query;
}
add_action('pre_get_posts', 'product_initial_filter');
You can pass meta argument in meta_query. and also if you are 'compare' => 'IN', the value must be an array. check the below code.
Using WP pre_get_posts action hook.
function product_initial_filter( $query ) {
if( !is_admin() && $q->is_main_query() ) {
if( $query->get('post_type') == 'product' && isset( $GET['fruit'] ) && $GET['fruit'] != '' ) {
$meta_query = array(
array(
'key' => 'fruits',
'value' => array( $GET['fruit'] ),
'compare' => 'IN',
),
);
$query->set( 'meta_query', $meta_query );
}
}
}
add_action('pre_get_posts', 'product_initial_filter');
OR
Using WC woocommerce_product_query action hook.
function product_initial_filter( $query ) {
if( !is_admin() && $q->is_main_query() ) {
if( $query->get('post_type') == 'product' && isset( $GET['fruit'] ) && $GET['fruit'] != '' ) {
$meta_query = array(
array(
'key' => 'fruits',
'value' => array( $GET['fruit'] ),
'compare' => 'IN',
),
);
$query->set( 'meta_query', $meta_query );
}
}
}
add_action('woocommerce_product_query', 'product_initial_filter');
USEFUL LINKS.
pre_get_posts
woocommerce_product_query
meta_query
I've been working with this function and for some reason, I cannot seem to figure out the issue here.
I have a function that I want to affect the search results to change the number of posts_per_page of the query to be unlimited.
For whatever reason, $query->set('posts_per_page', -1) and $query->set('post__in', $post__in) appear to do nothing while $query->set('tax_query', $tax_query) does work.
Any ideas would be much appreciated!
function fp_search_query_mod( $query ) {
if ( $query->is_search && $query->is_main_query() && !is_admin() ) :
$cats = ( isset($_GET['cats'] ) ? $_GET['cats'] : null );
$post__in = array();
if ( !empty( $cats ) ) :
$cats = explode( ',', $cats );
$tax_query = array(
'relation' => 'AND',
array(
'taxonomy' => 'product_type',
'field' => 'slug',
'terms' => array( 'simple', 'variable' )
),
array(
'taxonomy' => 'product_cat',
'field' => 'id',
'terms' => $cats,
)
);
$query->set( 'tax_query', $tax_query );
if ( in_array( 'favs', $cats ) ) :
$fp_favs = get_user_meta( get_current_user_id(), 'fp_favs', true );
if ( !empty( $fp_favs ) ) {
$post__in = $fp_favs;
}
endif;
if ( in_array( 'purchases', $cats ) ) :
// $purchased = get_customer_purchased_products();
$purchased = get_user_meta( get_current_user_id(), 'fp_purchases', true );
if ( !empty( $post__in ) ) {
$post__in = array_merge( $post__in, $purchased );
$post__in = array_unique( $post__in );
} else {
$post__in = $purchased;
}
endif;
endif;
if ( !empty( $post__in ) ) :
$query->set( 'post__in', $post__in );
endif;
$query->set( 'posts_per_page', -1 );
endif;
}
add_action( 'pre_get_posts', 'fp_search_query_mod', 2 );
Here's the page on which the resuls are displayed: https://filmpacdev.wpengine.com/?s=beaches&post_type=product
I've set up a custom post type called clientarea, and set up several custom columns for it in the admin area - the custom columns are all custom meta fields, as you can see from my code. I'd like to sort by 'Appointment Date' descending by default.
All of the columns work fine, and can be sorted manually as expected, but I can't get the default sort order to work.
If I change the default sort field to a standard field (e.g. 'title') it works as expected; it only seems not to work when I'm trying to set a custom column as the default sort order. The order works (i.e. I can change between asc and desc by default even with a custom column), but it's not picking up the orderby so is reverting back to sorting by the date the custom post was published.
What am I missing?
My code is as follows:
add_action( 'manage_posts_custom_column' , 'custom_columns', 10, 2 );
function custom_columns( $column, $post_id ) {
global $wpdb;
switch ( $column ) {
case 'extranet_case_office':
$get_office_ID = get_post_meta( $post_id, 'extranet_case_office', true );
$get_office_name = $wpdb->get_results('SELECT post_title FROM `cn_bf_posts` WHERE `ID` = '.$get_office_ID);
echo $get_office_name[0]->post_title;
break;
case 'extranet_appointment_date':
echo date('d/m/Y',strtotime(get_post_meta( $post_id, 'extranet_appointment_date', true )));
break;
case 'extranet_appointment_type':
echo get_post_meta( $post_id, 'extranet_appointment_type', true );
break;
case 'extranet_insolvency_practioner':
$get_person_ID = get_post_meta( $post_id, 'extranet_insolvency_practioner', true );
$get_person_name = $wpdb->get_results('SELECT post_title FROM `cn_bf_posts` WHERE `ID` = '.$get_person_ID);
echo $get_person_name[0]->post_title;
break;
default:
break;
}
}
add_filter( 'manage_edit-clientarea_sortable_columns', 'my_sortable_clientarea_columns' );
function my_sortable_clientarea_columns( $columns ) {
$columns['extranet_case_office'] = 'extranet_sort_office';
$columns['extranet_appointment_date'] = 'extranet_sort_date';
$columns['extranet_appointment_type'] = 'extranet_sort_type';
$columns['extranet_insolvency_practioner'] = 'extranet_sort_IP';
return $columns;
}
add_action( 'pre_get_posts', 'extranet_orderby' );
function extranet_orderby( $query ) {
if( ! is_admin() )
return;
$orderby = $query->get( 'orderby');
switch ( $orderby ) {
case 'extranet_sort_office':
$query->set('meta_key','extranet_case_office');
$query->set('orderby','meta_value_num');
break;
case 'extranet_sort_date':
$query->set('meta_key','extranet_appointment_date');
$query->set('orderby','meta_value');
break;
case 'extranet_sort_type':
$query->set('meta_key','extranet_appointment_type');
$query->set('orderby','meta_value');
break;
case 'extranet_sort_IP':
$query->set('meta_key','extranet_insolvency_practioner');
$query->set('orderby','meta_value_num');
break;
default:
break;
}
}
add_action('pre_get_posts','clientarea_default_order');
function clientarea_default_order( $query ){
if( $query->get('post_type')=='clientarea' ){
if( $query->get('orderby') == '' )
$query->set('orderby','extranet_sort_date');
if( $query->get('order') == '' )
$query->set('order','desc');
}
}
The problem is that you run the clientarea_default_order callback too late.
To fix that you only have to change the priority from the default one that's 10:
add_action( 'pre_get_posts','clientarea_default_order');
to the priority of 9:
add_action( 'pre_get_posts','clientarea_default_order', 9 );
But you don't actually need two pre_get_posts callbacks.
You can combine them:
Example #1
is_admin() && add_action( 'pre_get_posts', 'extranet_orderby' );
function extranet_orderby( $query )
{
// Nothing to do:
if( ! $query->is_main_query() || 'clientarea' != $query->get( 'post_type' ) )
return;
//-------------------------------------------
// Modify the 'orderby' and 'meta_key' parts
//-------------------------------------------
$orderby = $query->get( 'orderby');
switch ( $orderby )
{
case 'extranet_sort_office':
$query->set( 'meta_key', 'extranet_case_office' );
$query->set( 'orderby', 'meta_value_num' );
break;
case 'extranet_sort_date':
$query->set( 'meta_key', 'extranet_appointment_date' );
$query->set( 'orderby', 'meta_value' );
break;
case '': // <-- The default empty case
$query->set( 'meta_key', 'extranet_appointment_date' );
$query->set( 'orderby', 'meta_value' );
break;
case 'extranet_sort_type':
$query->set( 'meta_key', 'extranet_appointment_type' );
$query->set( 'orderby', 'meta_value' );
break;
case 'extranet_sort_IP':
$query->set( 'meta_key', 'extranet_insolvency_practioner' );
$query->set( 'orderby', 'meta_value_num' );
break;
default:
break;
}
}
where we added a main query check and an empty switch case.
Example #2
Here's another approach, without the switch part (PHP 5.4+):
is_admin() && add_action( 'pre_get_posts', 'extranet_orderby' );
function extranet_orderby( $query )
{
// Nothing to do
if( ! $query->is_main_query() || 'clientarea' != $query->get( 'post_type' ) )
return;
//-------------------------------------------
// Modify the 'orderby' and 'meta_key' parts
//-------------------------------------------
$orderby = strtolower( $query->get( 'orderby') );
$mods = [
'office' => [ 'meta_key' => 'extranet_sort_office', 'orderby' => 'meta_value_num' ],
'date' => [ 'meta_key' => 'extranet_appointment_date', 'orderby' => 'meta_value' ],
'' => [ 'meta_key' => 'extranet_appointment_date', 'orderby' => 'meta_value' ],
'type' => [ 'meta_key' => 'extranet_sort_type', 'orderby' => 'meta_value_num' ],
'ip' => [ 'meta_key' => 'extranet_insolvency_practioner', 'orderby' => 'meta_value_num' ],
];
$key = 'extranet_sort_' . $orderby;
if( isset( $mods[$key] ) )
{
$query->set( 'meta_key', $mods[$key]['meta_key'] );
$query->set( 'orderby', $mods[$key]['orderby'] );
}
}
Try change clientarea_default_order action & function for this:
add_action('pre_get_posts', 'clientarea_default_order', 99);
function clientarea_default_order($query) {
if ($query->get('post_type') == 'clientarea') {
if ($query->get('orderby') == '') {
$query->set('orderby', 'extranet_sort_date');
$query->set('meta_key', 'extranet_appointment_date');
}
if ($query->get('order') == '') {
$query->set('order', 'DESC');
}
}
}
im new posting in the forum, but here i found answers without ask, just searching, thanks about that.
Here go my questions:
I have a custom post type called 'publicacion' and there the next custom WP_Query:
$query_args = array(
's' => mysql_real_escape_string( $_GET['s'] ),
'post_type' => 'publicacion',
'meta_key' => 'meta-box-fp'
);
if( $_GET['autor'] != '' ) {
$query_args['tax_query'] = array(
array(
'taxonomy' => 'autores',
'field' => 'slug',
'terms' => mysql_real_escape_string( $_GET['autor'] )
)
);
}
if( trim( $_GET['fini'] ) != '' || trim( $_GET['ffin'] ) != '' ) {
$query_args['meta_query'] = array (
array(
'key' => 'meta-box-fp',
'value' => array( mysql_real_escape_string( $_GET['fini'] ) . '-00-00', mysql_real_escape_string( $_GET['ffin'] ) . '-00-00' ),
'type' => 'DATE',
'compare' => 'BETWEEN' )
);
}
if( isset( $_GET['ord_by'] ) ) {
$ordby = mysql_real_escape_string( $_GET['ord_by'] ) == 'year' ? 'meta_value' : mysql_real_escape_string( $_GET['ord_by'] );
$query_args['orderby'] = $ordby;//mysql_escape_string( $_GET['ord_by'] );
$query_args['order'] = 'DESC';//mysql_escape_string( $_GET['ord'] );
}
$query = new WP_Query( $query_args );
The 's' parameter redirects to the search page, but i need do the search in the archive-publicacion.php file, and i need the 's' parameter, search for excerpt instead content.
It is possible to do that? Thanks and i hope be clear in my question and excuse me my english.
well.. i've resolved my issue by adding the query parameters in functions.php from theme instead from archive.php and changing the 's' to 'str' from the url for not redirect the query when wordpress reads the url.
This looks something like this functions.php:
add_action( 'pre_get_posts', 'my_custom_search' );
function my_custom_search( $query ) {
if( !is_admin() && $query->is_main_query() && $query->get('post_type') == 'publicacion' ) {
if( isset( $_GET['str'] ) && !empty( $_GET['str'] ) ) {
$query->set( 's', mysql_real_escape_string( $_GET['str'] ) );
}
if( ( isset( $_GET['fini'] ) && !empty( $_GET['fini'] ) ) && ( isset( $_GET['ffin'] ) && !empty( $_GET['ffin'] ) ) ) {
$fini = !empty( $_GET['fini'] ) ? mysql_real_escape_string( $_GET['fini'] ) . '-00-00' : '1900-00-00';
$ffin = !empty( $_GET['ffin'] ) ? mysql_real_escape_string( $_GET['ffin'] ) . '-00-00' : date( 'Y' ) . '-00-00';
$args_meta_query = array(
array(
'key' => 'meta-box-fp',
'value' => array( $fini, $ffin ),
'type' => 'DATE',
'compare' => 'BETWEEN'
)
);
$query->set( 'meta_query', $args_meta_query );
}
if( isset( $_GET['autor'] ) && !empty( $_GET['autor'] ) ) {
$args_tax_query = array(
array(
'taxonomy' => 'autores',
'field' => 'slug',
'terms' => mysql_real_escape_string( $_GET['autor'] )
)
);
$query->set( 'tax_query', $args_tax_query );
}
if( isset( $_GET['ordby'] ) && $_GET['ordby'] != 'fecha' ) {
$ordby = mysql_real_escape_string( $_GET['ordby'] );
$query->set( 'orderby', $ordby );
$query->set( 'order', strtoupper( mysql_real_escape_string( $_GET['ord'] ) ) );
}else {
$ord = isset( $_GET['ord'] ) && !empty( $_GET['ord'] ) ? strtoupper( mysql_real_escape_string( $_GET['ord'] ) ) : 'DESC';
$query->set( 'orderby', 'meta_value_num' );
$query->set( 'meta_key', 'meta-box-fp' );
$query->set( 'order', $ord );
}
}
}
I hope this help somebody and excuse me my english again.
Bye.