Wordpress - Include data from new column in the search query - wordpress

I added a new column to Woocommerce orders's screen, that indicates who is the order's creator (in that site, service representatives have the ability to create order for customer's in the backend).The problem is that when I search for that data in the orders screen, I can't find any.
The order's creator is set to the order with add_post_meta()
So I tried something like this:
function include_search( $query ) {
if ( is_admin() && $query->is_search() && $query->query['post_type'] == 'shop_order' ) {
$query->set( 'meta_query', array('key' => 'representative', 'value' => $query->query['s'], 'compare' => '=') );
}
}
add_action( 'pre_get_posts', 'include_search' );
But it doesn't work.
For example, If an order created by "Ben X", then I can see his name appears in the right column in the orders screen, but if I search for "Ben X" in the search box, I don't find that order.
Any help with that?
Thanks!

If anyone need help with that, I found the answer:
function filter_woocommerce_shop_order_search_fields( $array ) {
$array[] = 'representative'; //The order meta key that needs to be include in the search
return $array;
};
add_filter( 'woocommerce_shop_order_search_fields', 'filter_woocommerce_shop_order_search_fields', 10, 1 );

Related

Wordpress - Hide Category from Posts

So our Wordpress site's backend is horribly slow due to the HUGE amount of posts we have. There are three categories in particular that we shouldn't need to edit, so I am hoping to not even load them in the back end. I have seen plugins that restrict who can edit what categories of posts, but it doesn't seem to speed it up much. I'm not sure if this is because it is still pulling those posts and just filtering them out when displaying?
I am wondering if _get_list_table( 'WP_Posts_List_Table' ) has a hook of some sort where I can make it so those three categories are not even pulled from the database.
Is this possible? Would it help speed up the backend?
Thanks!
Edit:
Kinda want something like this, but set() does not allow modifiers on = or !=
function exclude_category_posts( $query ) {
if ( $query->is_main_query() && is_admin()) {
//$query->set( 'cat', '-187460' );
$query = new WP_Query( array( 'category__not_in' => array( 187460, 187460, 182149 ) ) );
}
return $query;
}
add_filter( 'pre_get_posts', 'exclude_category_posts' );
The commented out method only works with one category. The new query doesn't filter anything ):
PHP code to exclude WordPress category from blog
function exclude_category($query) {
if ( $query->is_home() ) {
$query->set('cat', '-xx');
}
return $query;
}
add_filter('pre_get_posts', 'exclude_category');
The trick is to add the minus sign in front of your category ID (the xx in the example above). Try that, it should work.
Use this notation $query->set( 'cat', '-60, -61' ); to exclude multiple categories.
Alternative
You can also use the category__not_in parameter
$query = new WP_Query( array( 'category__not_in' => array( 2, 6 ) ) );
source

How to restrict media library grid view to only display files from categories current role has access to

I am building a plugin where users can only see Media files from categories which are accessible by User role assigned to him.
I have been able to filter out the result in media list view mode, when it first loads by hooking a function to pre_get_posts action, but don't know how to do the same for grid view mode.
This is what happening:
User-A is assigned to Role-A which has access to categories Cat-A and Cat-B.
When User-A logs in to the admin and navigates to Media list view page, correct media files are coming up, i.e. only from Cat-A and Cat-B. But on Media grid view mode, all media files are coming up, while I want medias only from above two categories to appear.
I searched the web and looked into some posts in Stack Overflow but did not find what I am exactly looking for.
Edit
After more searching I have found this:
Reference: https://codex.wordpress.org/Plugin_API/Filter_Reference/ajax_query_attachments_args
add_filter( 'ajax_query_attachments_args', array( $this, 'load_media_library_by_category_access' ), 10, 1 );
function load_media_library_by_category_access( $query = array() ) {
$user_id = get_current_user_id();
if( $user_id ) {
$query['author'] = $user_id;
}
return $query;
}
Since the above is possible, is this also possible to find categories attached to each media item and then create a filtered array consisting of media items associated with given categories?
Something like:
function load_media_library_by_category_access( $query = array() ) {
// Get an array of category ids, which I already have
$cat_array = get_category_array_by_role();
// Modify $query to filter media items by given categories (array may be?)
return $query;
}
Is this possible?
According to this post it's not possible for the Grid View. You can only manipulate the media results for the list view.
I got this to work finally. This is how I did it:
function load_media_library_by_category_access( $query = array() ) {
$cats = $this->get_accessible_categories();
$tax_query = array(
array(
'taxonomy' => 'category',
'field' => 'id',
'terms' => $cats,
),
);
if( !current_user_can( 'update_core' ) ) {
$query['tax_query'] = $tax_query;
}
return $query;
}
add_filter('ajax_query_attachments_args', array($this, 'load_media_library_by_category_access'), 10, 1);
Now my media grid view filters out correct media items based on categories that current user role has access to.
Since administrator does not need to be restricted I put the following check before actually injecting the $tax_query filter into original query.
if( !current_user_can( 'update_core' ) ) {
$query['tax_query'] = $tax_query;
}
Thought this might be helpful for others.
add_filter( 'ajax_query_attachments_args', 'show_current_user_attachments', 10, 1 );
function show_current_user_attachments( $query = array() ) {
//echo "<pre>";
//print_r($query);
$user_id = get_current_user_id();
if( $user_id ) {
//$query['author'] = $user_id;
}
$query['post_mime_type'] = 'image';
return $query;
}

Expand woocommerce single product page functionality with html

I know it's possible to add checkboxes and other via html to a woocommerce single product description / brief description of product (done that). Is it possible / what are the hooks, in order to save given customer selections and pass the information on to the cart? Customers are able to make choices but unfortunately no information is passed on by woocommerce.
thanks
Yes you may add your own HTML and then can use these data to the cart, these hints can be useful for you.
You may use an action
"add_filter( 'woocommerce_add_cart_item_data', 'Your_own_function', 10, 2);"
function Your_own_function($cart_data,$pro_id){
if(isset($_POST['your_checkbox_value'])){
$item_meta['your_meta_key'] = $_POST['your_checkbox_value'];
$cart_data ['product_meta'] = array('meta_data' => $item_meta);
}
return $cart_data;
}
and then you may retrieve these cart item data by using
"add_filter( 'woocommerce_get_item_data', "custom_get_item_data", 10, 2 );"
function custom_get_item_data($item_meta, $existing_item_meta){
foreach ($existing_item_meta['product_meta'] ['meta_data'] as $key => $val )
{
if($key == 'your_meta_key'){
$item_meta [] = array (
'name' => __('Custom Name','Text Domain'),
'value' => stripslashes( $val ),
);
}
}
return $item_meta;
}

woocommerce conditional products/categories on user role

Looking for a plugin that helps me to restrict woocommerce products or product categories based on role.
Let's say that I only want to sell bulk products to whole sale buyers.
Any help is awesome, thanks!
Here is how I managed to hide products based on role:
First, I have added a checkbox in the product options inventory section to enable admins to hide the products based on their selection:
add_action( 'woocommerce_product_options_stock_status', 'hide_if_available_to_user_role' );
function hide_if_available_to_user_role(){
woocommerce_wp_checkbox( array( 'id' => '_hide_from_users', 'wrapper_class' => 'show_if_simple show_if_variable', 'label' => __( 'Hide this product from specific roles?', 'customhideplugin' ) ) );
}
I then saved this selection in the actual post when a post is updated.
add_action( 'woocommerce_process_product_meta', 'hide_save_product_meta' );
function hide_save_product_meta( $post_id ){
if( isset( $_POST['_hide_from_users'] ) ) {
update_post_meta( $post_id, '_hide_from_users', 'yes' );
} else {
delete_post_meta( $post_id, '_hide_from_users' );
}
}
This is how I got current user's role.
function getCurrentUserRole( $user = null ) {
$user = $user ? new WP_User( $user ) : wp_get_current_user();
return $user->roles ? $user->roles[0] : false;
}
Now query products. If the current user role matches the roles below, show the products as usual.
Otherwise, set the query based on the code above...
add_action( 'woocommerce_product_query', 'hide_product_query' );
function hide_product_query( $q ){
if((getCurrentUserRole() == 'editor' ) || (getCurrentUserRole() == 'administrator' )){
return false;
} else {
$meta_query = $q->get( 'meta_query' );
if ( get_option( 'woocommerce_hide_out_of_stock_items' ) == 'no' ) {
$meta_query[] = array(
'key' => '_hide_from_users',
'compare' => 'NOT EXISTS'
);
}
$q->set( 'meta_query', $meta_query );
}
}
To achieve this you can use the Free Groups plugin. But for that you must add all the wholesalers to one group say wholesale group 1. Then while editing any product you get an option to access to, add the wholesaler group 1 there. The product will now be only seen by the user who is in wholesalers group 1.
I tried a few different plugins to try to achieve that. I finally chose this one because it's easy to understand and can show/hide depending on procucts, tags, categories and custom taxonomies. WooCommerce Products Visibility

Get WooCommerce products on sale with WC_Query

I know there are plenty of solutions on the internet about how to get WooCommerce products on sale, by doing a WP_Query. However, WooCommerce doesn't seem to work fully if it's WC_Query object is not populated. For example: filter or sorting
Both these templates call:
woocommerce_products_will_display()
Which check's to see if the page is a taxonomy page (obvious false if you're using your own custom template):
if ( ! is_product_taxonomy() ) return false;
This is an example of a simple solution if you just want the products: WooCommerce: Display ONLY on-sale products in Shop
So, I there seems to be a couple of issues I need to solve here:
1) How to tell WC that my "Sale" page is a taxonomy page? Is there some sort of trick I need to do to force it into a taxonomy?
2) How do I get get WC_Query filled with the sales query (rather than just the WP_Query)
I have plugins that depend on:
$woocommerce->query->layered_nav_product_ids
being populated.
Any help is appreciated!
Thanks!!!
Well woocommerce_products_will_display() is pluggable, meaning you can define it in your own functions.php (or site-specific plugin) and alter it, having it return true for your specific template/page.
I think it could stand for some tweaking and a filter.
EDIT
I played around with this a bit more. Typically changing the posts that you want to retrieve is done in the pre_get_posts hook. I took a look at what WooCommerce is doing. They are adding something to the pre_get_posts hook and calling their special query stuff from there.
But their special query stuff dies if you aren't on a WooCommerce page. So, it made me thing that maybe we could just call it ourselves from our own function. I put this together and coupled with a special page template for a page called "on-sale" (basically just a copy of the shop template), seems to show just the for sale items with proper sorting and pagination.
Your mileage may vary, but I hope it helps.
function kia_pre_get_posts( $q ){
// We only want to affect the main query
if ( ! $q->is_main_query() ) {
return;
}
// Fix for verbose page rules
if ( is_page('on-sale') ) {
$q->set( 'post_type', 'product' );
$q->set( 'page_id', '' );
$q->set( 'page', '' );
$q->set( 'pagename', '' );
$meta_query = array( array(
'key' => '_sale_price',
'value' => 0,
'compare' => '>'
) );
$q->set( 'meta_query', $meta_query );
if ( isset( $q->query['paged'] ) ) {
$q->set( 'paged', $q->query['paged'] );
}
// Fix conditional Functions
$q->is_archive = true;
$q->is_post_type_archive = true;
$q->is_singular = false;
$q->is_page = false;
}
$wc_query = WC()->query;
$wc_query->product_query( $q );
if ( is_search() ) {
add_filter( 'posts_where', array( $wc_query, 'search_post_excerpt' ) );
add_filter( 'wp', array( $wc_query, 'remove_posts_where' ) );
}
add_filter( 'posts_where', array( $wc_query, 'exclude_protected_products' ) );
// We're on a shop page so queue the woocommerce_get_products_in_view function
add_action( 'wp', array( $wc_query, 'get_products_in_view' ), 2);
// And remove the pre_get_posts hook
$wc_query->remove_product_query();
}
add_action( 'pre_get_posts', 'kia_pre_get_posts' );

Resources