Exclude posts with set custom-field (meta) from search results - php

I have a condition that sets a custom field (hide_search = yes) when some posts are used. I have done this successfully, but I now want these posts to not appear under search, or not be indexed.
This is the code that I've come across, but I can't get it to work with my intended functionality.
/** Hide all posts that have the Custom Field hide_search=yes set */
function hide_posts( $query ) {
// If a search query is done from a non-admin
if ( $query->is_search && !is_admin() ){
// Get all posts with meta value {key = hide_search && value = yes}
// Identify their Post Category and set it to negative value
// Set Category with ID to -ID
$query->set( 'cat', -1 );
return $query;
}
return $query;
}
add_filter( 'pre_get_posts', 'hide_posts' );
Any help would be appreciated. Open to other solutions, if they are better.

It seems that I've found the answer to my question
here:
The code mentioned in the article is this:
function exclude_nonadvertorial_search($query) {
//only run for the main query and don't run on admin pages
if (!is_admin() && $query->is_main_query()) {
//now check to see if you are on a search results page
if ($query->is_search) {
//get sponsor posts that are NOT advertorials, so we can exclude their IDs from search
$args = array(
//get posts of the custom post type sponsor_post
'post_type' => 'sponsor_post',
//get all posts
'posts_per_page' => -1,
//return an array of post IDs
'fields' => 'ids',
//now check for posts that have a sponsor_post_type that is not 'advertorial'
'meta_query' => array(
'relation' => 'OR',
array(
'key' => 'sponsor_post_type',
'value' => 'advertorial',
'compare' => '!='
),
//some posts don't have a sponsor_post_type meta field set, so check for those too
array(
'key' => 'sponsor_post_type',
'compare' => 'NOT EXISTS'
)
)
);
//now get the posts
$excluded_ids = get_posts($args);
//add these post IDs to the 'post__not_in' query parameter
$query->set('post__not_in', $excluded_ids);
}
}
}
add_action('pre_get_posts', 'exclude_nonadvertorial_search');

Related

Code to display all successful purchases in WooCommerce

I want to display the total number of purchases made on my site to my site users; Previously, I wrote the code that displayed the total number of products published on my site, and now I want the code to display the total number of successful purchases from my site to the user.
The code I wrote to display the number of products on my site is as follows:
function product_count_shortcode() {
$count_posts = wp_count_posts( 'product' );
return $count_posts->publish;
}
add_shortcode( 'product_counthalsho', 'product_count_shortcode' );
You will basically have to show the number of orders that have the status completed. Just create a function that will query the order post_type and with the status completed.
You can simply use get_posts and use the php function count the check how many results you have, or use WP_Query that already has a property in the return object that tells you how many orders you have with that status.
Later Edit:
function mrc_total_completed_orders() {
$args = array(
'post_type' => 'order',
'posts_per_page' => -1,
'post_status' => 'completed',
);
$orders = get_posts( $args );
return count( $orders ); }
Or you can use the WC_Order_Query
function mrc_mrc_total_completed_Orders() {
$query = new WC_Order_Query( array(
'limit' => 99999,
'status' => array( 'completed' ),
'return' => 'ids',
) );
$orders = $query->get_orders();
return count( $orders ); }
Also some documentation here
Note that I haven't tested these solutions, but its enough to get you started :)
Usage:
echo mrc_mrc_total_completed_Orders();

Woocommerce show only categories that have products with certain meta value

I am developing b2b section in my Woocommerce shop. I have managed to filter woocommerce_product_query_meta_query to display only products that have been enabled for b2b section for b2b users.
However I cannot find a way to hide product categories that shows 0 results (because no product enabled for b2b section is in that category) in Woocommerce category widget.
I was thinking about overriding default Woocommerce widget code and for each category (and subcategory) run wp query that returns number of products in this category that are enabled for b2b. But with large number of products and categories it seems very inefficient.
Is there a way to hide categories from Woocommerce category widget that are "empty" (no product in this category is enabled for b2b)?
Thanks for any suggestions.
Edit
To clarify my question: here is the function I use to filter product query to display only products that have _eda_display_in_b2b meta set to yes:
function show_only_b2b_products( $meta_query, $query ) {
if ( is_admin() || ! is_user_logged_in() || ! is_b2b_user() ) {
return $meta_query;
}
$meta_query[] = array(
'key' => '_eda_display_in_b2b',
'value' => 'yes',
'compare' => '='
);
return $meta_query;
}
add_filter( 'woocommerce_product_query_meta_query', 'show_only_b2b_products', 10, 2 );
Exaple:
https://klon.vozikyprozivot.cz/kategorie-produktu/pridavne-pohony/
This category is not empty for regular customers and not logged in users. But for b2b customers there is no product to show. So I need to hide this category from the widget for b2b customers.
If you are referring to the product categories widget, there is a setting for hiding empty categories:
If you are referring to something different, could you please share an example page URL as well as your site’s System Status? You can find it via WooCommerce > Status. Select “Get system report” and then “Copy for support”. Once you’ve done that, paste it here in your response.
Hope this will help you.
======Edit======
I think for the above issue you can use the wc category hook and remove the category. Please check the below code
//* Used when the widget is displayed as a dropdown
add_filter( 'woocommerce_product_categories_widget_dropdown_args', 'rv_exclude_wc_widget_categories' );
//* Used when the widget is displayed as a list
add_filter( 'woocommerce_product_categories_widget_args', 'rv_exclude_wc_widget_categories' );
function rv_exclude_wc_widget_categories( $cat_args ) {
//add the logic to check the category have product or not and make the array of ID and replace the below array with that.
$cat_args['exclude'] = array('55','68'); // Insert the product category IDs you wish to exclude
return $cat_args;
}
In the above code I think you can make logic and check if the category have the products or not and make the array of id for the non-product category.
In this way you can exclude the category from the list and dropdown.
How this will help you.
With a big help from Harshit Vaid I have managed to solve it:
add_filter( 'woocommerce_product_categories_widget_dropdown_args', 'eda_exclude_wc_widget_categories' );
add_filter( 'woocommerce_product_categories_widget_args', 'eda_exclude_wc_widget_categories' );
function eda_exclude_wc_widget_categories( $cat_args ) {
$args = array(
'taxonomy' => 'product_cat',
'hide_empty' => 0
);
$all_categories = get_categories( $args );
$category_exclude_list = array();
foreach ( $all_categories as $cat ) {
if ( $cat->category_parent == 0 ) {
$category_id = $cat->term_id;
$product_args = array(
'posts_per_page' => - 1,
'post_type' => 'product',
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'terms' => $category_id,
'field' => 'term_id',
'operator' => 'IN'
)
),
'meta_query' => array(
array(
'key' => '_eda_display_in_b2b',
'value' => 'yes'
)
)
);
$query = new WP_Query( $product_args );
$count = $query->post_count;
if ( $count == 0 ) {
array_push( $category_exclude_list, $category_id );
}
}
}
$cat_args['exclude'] = $category_exclude_list;
return $cat_args;
}

Wordpress - pre_get_posts filtering by the count of dynamic keys

I have created a new sortable column in my custom post type called offers_made.
I now want to sort by the amount of dynamic keys each post_id has within its meta.
For example:
Each post could have a dynamic key such as _kf_offers_1, _kf_offers_9, _kf_offers_12.
So I want to return the value of 3 on my column header. Here is what I have so far, but I dont think I'm going to achieve it this way because I dont think pre_get_posts works this way?
When I click 'sort ASC' in the column header - The values of each key are being displayed but just not sorting.
function sortable_offers_orderby( $query ) {
if( ! is_admin() )
return;
$orderby = $query->get( 'orderby');
if( 'offers_made' == $orderby ) {
$meta_query = array(
'relation' => 'OR',
array(
'key' => '_kf_offers_',
'compare_key' => 'LIKE',
),
array(
'key' => '_kf_offers_',
'compare' => 'NOT EXISTS',
),
);
$query->set( 'meta_query', $meta_query );
}
}
add_action( 'pre_get_posts', 'sortable_offers_orderby' );
Hope this makes sense,
Thanks in advance.

WooCommerce Memberships: How to adjust query to account for delayed content/content drip?

I'm trying to build a query that shows the latest post a member has access to, but I cannot find what parameters to add so that posts that they have access to in the future are removed from this list.
Does anyone know how to do this?
If not, can wc_memberships_is_post_content_restricted( ) be adapted into a custom loop?
EDIT
I tried adding the code suggested, but instead of getting the latest post a user has access to, it outputs the oldest page on the site. Am I adding it to the wrong place?
`<?php
// Query Test
$args = array(
'post_type' => 'premium',
'posts_per_page' => 1,
'tax_query' => array(
array(
'taxonomy' => 'notebook',
'field' => 'term_id',
'terms' => 425,
),
),
);
$query4 = new WP_Query( $args );
if ( $query4->have_posts() ) {
// The Loop
while ( $query4->have_posts() ) {
$query4->the_post();
foreach ( $posts as $post ) {
if( !wc_memberships_is_post_content_restricted($post->ID)){
echo the_title();
}
}
} wp_reset_postdata(); } ?>`
To remove restricted post titles select "Hide Completely" on Settings -> "Content Restriction Mode."
If you select "Hide Content" post titles will continue to show up on post navigation and lists.
Once I did this both loops (mine and mujuonly's) worked.
foreach ( $posts as $post ) {
if( wc_memberships_is_post_content_restricted($post->ID)){
// do the coding here for the restricted contents
}else{
// do the coding here for the non-restricted contents
}
}
Try this code

How to filter query based on page meta keys and/or title?

I am using Beaver Builder with WordPress and am using Advanced Posts to display my custom post types. I have 6 teams and about 30 players that belong to each team. I want to display the team's roster on the team page but can't filter by team when selecting players to show.
I found this method: https://www.ultimatebeaver.com/docs/filter-query-parameters-advanced-posts/
But I am having trouble comparing the meta keys between players and teams and don't know where to begin.
This is what I have so far:
global $post;
$current_team = $post->post_name;
if ( $settings->id == 'team-roster' ) {
$args['meta_key'] = 'team';
$args['posts_per_page'] = '30';
$args['meta_query'] =
array(
'key' => 'team',
'value' => '$current_team',
'compare' => '=',
);
}
return $args;
I am trying to compare to the page slug, which is the same as the values stored in the meta_key.
I would like each team page to show the players on the team as well as use this same module on the players page to show the rest of the players. Open to other ideas as well if this isn't the right method.
Ended up using categories to filter instead of the relationship meta_key field. Found out that the relationship field is stored as an array so it wasn't comparing correctly. Here's my solution:
global $post;
$current_team = $post->post_name;
if ( $settings->id == 'team-roster' ) {
$args['posts_per_page'] = '50';
$args['tax_query'] =
array(
array(
'taxonomy' => 'category',
'terms' => $current_team,
'field' => 'slug',
)
);
}
return $args;

Categories