I have an options page in my wordpress theme, it's to select a number of categories from a custom taxonomy.
$terms_obj = get_option('shop_features')
This returns an array with $key being the category-name and $value being either 1 or empty depending if the category was checked.
I need to grab a list of the checked categories to use in an array in another function:
add_action( 'pre_get_posts', 'custom_pre_get_posts_query' );
function custom_pre_get_posts_query( $q ) {
if ( ! $q->is_main_query() ) return;
if ( ! $q->is_post_type_archive() ) return;
if ( ! is_admin() && is_shop() ) {
$q->set( 'tax_query', array(array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => array( 'knives' ), // Don't display products in the knives category on the shop page
'operator' => 'NOT IN'
)));
}
remove_action( 'pre_get_posts', 'custom_pre_get_posts_query' );
}
Where I need to insert my category-names contained in a variable $terms to replace the 'terms' => array('knives') with 'terms' => array ( $terms )
Except it doesn't work by just doing that!
Here is how I've tried to accomplish that:
function custom_pre_get_posts_query( $q ) {
if ( ! $q->is_main_query() ) return;
if ( ! $q->is_post_type_archive() ) return;
if ( ! is_admin() && is_shop() ) {
$terms_obj = of_get_option( 'eco_shop_features', $default );
foreach ( $terms_obj as $slug => $checked ) { //$key ==> value
if ( $checked > 0 )
$terms .= '\'' . $slug . '\', ';
}
$terms = rtrim( $terms, ', ' );
$q->set( 'tax_query', array(array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => array( "$terms" ), // Don't display products in the knives category on the shop page
'operator' => 'NOT IN'
)));
}
remove_action( 'pre_get_posts', 'custom_pre_get_posts_query' );
}
I'm stuck of how to insert just the list of category names in to the terms field so it works as an array.
The right way seems to be commented out by you, below should work
foreach ( $terms_obj as $slug => $checked ) { //$key ==> value
if ( $checked > 0 )
$terms[] = $slug;
}
$q->set( 'tax_query', array(array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => $terms,
'operator' => 'NOT IN'
)));
To get your array of category names you can do :
$terms_obj = get_option('shop_features');
$category_name_array = array_keys($terms_obj, 1);
The array_keys($terms_obj, 1) function will extract in an array all the keys of the $terms_obj for witch the value match 1.
More info : http://php.net/manual/en/function.array-keys.php
Just prepare an array in the loop
$terms[] = $slug
And assign to term
'terms' => $terms,
Related
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 am excluding from Wordpress search results any posts or custom posts with custom taxonomies set to specific terms. I want to be able to add more taxonomies and terms simply (like in an array) without having the duplicate the function, and ensure I'm doing it efficiently.
Can anyone suggest a cleaner function that accommodates this?
/* Exclude from WordPress Search using custom taxonomy */
add_action( 'pre_get_posts', function ( $query ) {
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
// Exclude Terms by ID from Search and Archive Listings
if ( is_search() || is_tax( 'marque' ) ) {
$tax_query = array([
'taxonomy' => 'site_search',
'field' => 'term_id',
'terms' => [ exclude_page ],
'operator' => 'NOT IN',
]);
$query->set( 'tax_query', $tax_query );
}
}, 11, 1 );
/* Exclude from WordPress Search using custom taxonomy */
add_action( 'pre_get_posts', function ( $query ) {
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
// Exclude Terms by ID from Search and Archive Listings
if ( is_search() || is_tax( 'marque' ) ) {
$tax_query = array([
'taxonomy' => 'job_status',
'field' => 'term_id',
'terms' => [ closed ],
'operator' => 'NOT IN',
]);
$query->set( 'tax_query', $tax_query );
}
}, 11, 1 );
You could try first to define all your data in an array first as taxonomies / terms pairs (I have embedded the array in an external function, but it can be added directly in the hooked function). This way you can add or remove data easily.
Then we use a foreach loop to read and set the data in the tax query. So your code will be something like:
// HERE set in the array your taxonomies / terms pairs
function get_custom_search_data(){
return [
'site_search' => [ 'exclude_page' ],
'job_status' => [ 'closed' ],
];
}
/* Exclude from WordPress Search using custom taxonomy */
add_action( 'pre_get_posts', 'multiple_taxonomy_search', 33, 1 );
function multiple_taxonomy_search( $query ) {
if ( is_admin() || ! $query->is_main_query() ) {
return;
}
// Exclude Terms by ID from Search and Archive Listings
if ( is_search() || is_tax( 'marque' ) ) {
// Set the "relation" argument if the array has more than 1 custom taxonomy
if( sizeof( get_custom_search_data() ) > 1 ){
$tax_query['relation'] = 'AND'; // or 'OR'
}
// Loop through taxonomies / terms pairs and add the data in the tax query
foreach( get_custom_search_data() as $taxonomy => $terms ){
$tax_query[] = [
'taxonomy' => $taxonomy,
'field' => 'slug', // <== Terms slug seems to be used
'terms' => $terms,
'operator' => 'NOT IN',
];
}
// Set the defined tax query
$query->set( 'tax_query', $tax_query );
}
}
Code goes in function.php file of your active child theme (or active theme). Untested, it should work.
In WooCommerce I have checked the option "Visibility out of stock", but I need that some product category stay visible, even if that option is checked.
On the other hand, the main store doesn't show that category. For that I used this code:
add_action( 'pre_get_posts', 'custom_pre_get_posts_query' );
function custom_pre_get_posts_query( $q ) {
if ( ! $q->is_main_query() ) return;
if ( ! $q->is_post_type_archive() ) return;
if ( ! is_admin() && is_shop() ) {
$q->set( 'tax_query', array(array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => array( 'MYCATEGORY' ), // Don't show this category.
'operator' => 'NOT IN'
)));
}
remove_action( 'pre_get_posts', 'custom_pre_get_posts_query' );
}
As it would be possible to do this?
Thank you!
This is just a quick guess, not tested but could you try starting with something like:
global $product;
$terms = wp_get_post_terms( $post->ID, 'product_cat' );
foreach ( $terms as $term ) $categories[] = $term->slug;
$category_to_show = ‘MYCATEGORY’;
if( $categories ) {
if( in_array( $category_to_show, $categories ) && !$product->is_in_stock() ) {
apply_filters( 'woocommerce_product_is_visible', true, $product->id );
}
}
The code below with the 19 is working correctly as it is copied from the woocommerce website. Unfortunate I can't get it working to replace the 19 with $producten so that $producten contains an array with all categories.
$producten contains multiple categories that need to be hidden and are defined in the database. Is it possible what I want to do and how?
$userid = get_current_user_id();
$result = mysql_query("SELECT productID FROM bestellingen WHERE userID='$userid'");
$producten = array();
while($row = mysql_fetch_array($result)){
array_push($producten, $row['productID']);
}
add_action( 'pre_get_posts', 'custom_pre_get_posts_query' );
function custom_pre_get_posts_query( $q ) {
if ( ! $q->is_main_query() ) return;
if ( ! $q->is_post_type_archive() ) return;
if ( ! is_admin() && is_shop() ) {
$q->set( 'tax_query', array(array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => array( 19 ), // de categorienummers
'operator' => 'NOT IN'
)));
}
remove_action( 'pre_get_posts', 'custom_pre_get_posts_query' );
}
Thanks in advance!
It is solved using a session like:
$result = mysql_query("SELECT productID FROM bestellingen WHERE userID='$userid'");
$producten = array();
while($row = mysql_fetch_array($result)){
array_push($producten, $row['productID']);
}
$_SESSION['PRODUCTEN'] = $producten;
add_action( 'pre_get_posts', 'custom_pre_get_posts_query' );
function custom_pre_get_posts_query( $q ) {
if ( ! $q->is_main_query() ) return;
if ( ! $q->is_post_type_archive() ) return;
if ( ! is_admin() && is_shop() ) {
$q->set( 'tax_query', array(array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => $_SESSION['PRODUCTEN'], // Don't display products in the knives category on the shop page
'operator' => 'NOT IN'
)));
}
unset($_SESSION['PRODUCTEN']);
remove_action( 'pre_get_posts', 'custom_pre_get_posts_query' );
}
I've been trying to hide a specific category from SHOP page. I found this code:
add_filter( 'pre_get_posts', 'custom_pre_get_posts_query' );
function custom_pre_get_posts_query( $q ) {
if ( ! $q->is_main_query() ) return;
if ( ! $q->is_post_type_archive() ) return;
$q->set( 'tax_query', array(array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => array( 'CATEGORY TO HIDE' ),
'operator' => 'NOT IN'
)));
remove_filter( 'pre_get_posts', 'custom_pre_get_posts_query' );
}
I've pasted this code in my theme function.php file but I'm not achieving the result...
Can anybody help me please?
I know this is a bit late, but had this problem myself and solved it with the following function:
add_filter( 'get_terms', 'get_subcategory_terms', 10, 3 );
function get_subcategory_terms( $terms, $taxonomies, $args ) {
$new_terms = array();
// if a product category and on the shop page
if ( in_array( 'product_cat', $taxonomies ) && ! is_admin() && is_shop() ) {
foreach ( $terms as $key => $term ) {
if ( ! in_array( $term->slug, array( '**CATEGORY-HERE**' ) ) ) {
$new_terms[] = $term;
}
}
$terms = $new_terms;
}
return $terms;
}
The following snippet it works fine for me:
add_action( 'pre_get_posts', 'custom_pre_get_posts_query' );
function custom_pre_get_posts_query( $q ) {
if ( ! $q->is_main_query() ) return;
if ( ! $q->is_post_type_archive() ) return;
if ( ! is_admin() && is_shop() ) {
$q->set( 'tax_query', array(array(
'taxonomy' => 'product_cat',
'field' => 'slug',
'terms' => array( 'your category slug' ), // Don't display products in the knives category on the shop page
'operator' => 'NOT IN'
)));
}
remove_action( 'pre_get_posts', 'custom_pre_get_posts_query' );
}
I'm wondering how can I achieve the same for the products excluded within the category to be searchable via product search, while using the snippet those products gets totally hidden.
Simple way to hide a category from everything except the admin backend:
In functions.php:
add_filter( 'get_terms', 'hide_category', 10, 1 );
function hide_category( $terms ) {
$new_terms = array();
foreach ( $terms as $term ) {
if ( $term->slug !== 'secret_category' ) {
$new_terms[] = $term;
} else if ( $term->taxonomy !== 'product_cat' || is_admin() ) {
$new_terms[] = $term;
}
}
return $new_terms;
}
If you want to only hide it from the shop, add || !is_shop() to the else if condition.
If you want to hide some categories in your theme you can just pass exclude argument in the wp_list_categories function:
wp_list_categories( array(
'taxonomy' => 'product_cat',
'hide_empty' => 1,
'use_desc_for_title' => 0,
'title_li' => ' ',
'show_count' => 0,
'exclude' => '63' // <-- Hidden) );