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
Related
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;
}
On my current project I have three post categories (Column, Pickup and News) and use Jetpack Publicize to share any new post on both Facebook and Twitter.
For the "News" category, I'd like to only publicize on Twitter (so somehow deactivating Facebook sharing for this category exclusively).
I have been looking at the Jetpack documentation and adjusted their recommended code:
add_filter( 'wpas_submit_post?', 'news_twitter_submit_post', 10, 4 );
function news_twitter_submit_post( $ret, $post_id, $name, $connection ) {
// $categories = get_the_terms( $post_id, 'category' );
$categories = wp_get_post_categories( $post->slug );
if ( 'facebook' == $name ) {
if ( is_array( $categories ) )
$categories = wp_list_pluck( $categories, 'slug' );
if ( !empty( $categories ) && in_array( 'news', $categories ) ){
$ret = false;
}
}
return $ret; }
Except, the post still is getting published on Facebook.
I have also been looking at the publicize_should_publicize_published_post hook but can't get it to work.
Any way I could achieve this?
So I played a little bit more with Jetpack then decided to switch to another plugin.
Some notes:
I played a little bit with publicize_should_publicize_published_post and it's basically a big ON/OFF switch for the whole Publicize plugin. Can't get it to turn off only one channel (Facebook)
No matter how I expressed the if-else conditions, Facebook posting still went through, eventhough I did check the output of the function was correct.
Still interested in knowing if anyone has a clean solution for that problem, but let's close the question.
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 );
In a plugin for displaying recent posts in your sidebar widget, how can we apply a filter to the plugin's functions.php so that it won't include the current page/post in the display?
The plugin author replied, before he entered a long silence: "You can add custom parameter to the rpwe_default_query_arguments filter. Just add exclude => get_the_ID() to the filter."
Is it here, that we add it?
// Allow plugins/themes developer to filter the default query.
$query = apply_filters( 'rpwe_default_query_arguments', $query );
How?
This is the plugin: https://wordpress.org/plugins/recent-posts-widget-extended/
I found some guidance that appears to be quite simple
but then it results in errors in my site (localhost) while trying to correct the syntax. => seems to be not correctly used.
This is what I have so far:
add_filter( 'rpwe_default_query_arguments', 'rpwe_exclude_current' );
function rpwe_exclude_current ( $query ) {
'exclude' => get_the_ID()
$posts = new WP_Query( $query );
return $posts;
}
Here is the answer that worked in my situation:
add_filter( 'rpwe_default_query_arguments', 'my_function_name' );
function my_function_name( $args ) {
if( is_singular() && !isset( $args['post__in'] ) )
$args['post__not_in'] = array( get_the_ID() );
return $args;
}
Here is the site where I found it.
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' );