Hide specific category in listings - wordpress

I'm working on a Wordpress theme. The theme is Classifieds theme from premiumpress. The theme has a shortcode to list all the listings. The corresponding shortcode is [LISTINGS].
The function for the shortcode is as follows
/* =============================================================================
[LISTINGS] - SHORTCODE
========================================================================== */
function wlt_page_listings( $atts, $content = null ) {
global $userdata, $wpdb, $CORE; $STRING = ""; $extra=""; $i=1; $stopcount = 4;
extract( shortcode_atts( array( 'query' => '', 'show' => '', 'type' => '', 'cat' => '', 'orderby' => '', 'order' => '', 'grid' => "no", 'featuredonly' => "no"), $atts ) );
// SETUP DEFAULTS
if(!isset($atts['show']) || (isset($atts['show']) && $atts['show'] == "") ){ $atts['show'] = 5; }
if($atts['type'] == ""){ $atts['type'] = THEME_TAXONOMY.'_type'; }
if($atts['orderby'] == ""){ $atts['orderby'] = "post_title"; }
if($atts['order'] == ""){ $atts['order'] = "desc"; }
// DEFAULT FOR LIST STYLE
if($grid == "yes"){
$sstyle = "grid_style";
$STRING .= '<script language="javascript">jQuery(window).load(function() { equalheight(\'.grid_style .item .thumbnail\');});</script>';
}else{
$sstyle = "list_style";
}
$query= str_replace("#038;","&",$query);
if(strlen($query) > 1){
// ADD ON POST TYPE FOR THOSE WHO FORGET
if(strpos($query,'post_type') == false){
$args = $query ."&post_type=".THEME_TAXONOMY."_type";
}else{
$args = $query;
}
}elseif($featuredonly == "yes"){
$args = array('posts_per_page' => $atts['show'],
'post_type' => $atts['type'], 'orderby' => $atts['orderby'], 'order' => $atts['order'],
'meta_query' => array (
array (
'key' => 'featured',
'value' => 'yes',
)
)
);
}else{
/*** default string ***/
$args = array('posts_per_page' => $atts['show'], 'post_type' => $atts['type'], 'orderby' => $atts['orderby'], 'order' => $atts['order'] );
}
/*** custom category ***/
if(strlen($atts['cat']) > 1){
$args = array('tax_query' => array( array( 'taxonomy' => str_replace("_type","",$atts['type']) ,'field' => 'term_id','terms' => array( $atts['cat'] ))), 'posts_per_page' => $atts['show'] );
}
// BUILD QUERY
$the_query = new WP_Query( hook_custom_queries($args) );
if ( $the_query->have_posts() ) {
$STRING .= '<div class="_searchresultsdata"><div class="wlt_search_results row '.$sstyle.'">';
while ( $the_query->have_posts() ) { $the_query->the_post(); $post = get_post();
$STRING .= '<div class="item '.hook_gallerypage_item_class('col-md-4').$CORE->FEATURED($post->ID).'">'.hook_item_cleanup(hook_gallerypage_item($CORE->ITEM_CONTENT($post))).'</div>';
}
$STRING .= '</div></div><div class="clearfix"></div>';
}
// END QUERY
wp_reset_postdata();
return $STRING;
}
add_shortcode( 'LISTINGS', array($this,'wlt_page_listings') );
The shortcode does not have an attribute to hide certain categories. I need to display all listings, except the ones in wedding category, which is a custom taxonomy. Is there any way to do that with the above code?
Will something like this work?
if ( is_tax( 'listing', 'wedding' ) ) {
do not display the wedding listings and display the rest}
Any suggestions?
EDITS:
This my online site url : http://webzer.comxa.com/
The main page shows the all the products.I like to have all but not one that is from wedding category coz i have separate page to list wedding category.
i have tried this where 51 is the page id of my home store page
if ( is_page( 51 ) && is_tax( 'listing', 'wedding' ) ) {
?><style>.caption {display:none!important;}</style>
<?php } ?>
this also didn't work

Consider this :
change
function wlt_page_listings( $atts, $content = null ) {
to
function wlt_page_listings( $atts, $content = null, $exclude=array(99) ) { // 99 is wedding cat id
where $exclude is an optional array of excluded cat names (99 in there for ease of testing/use)
Then in the
while ( $the_query->have_posts() ) {
add something like this:
$post = get_post(); // get post obj, will use the ID attr
$cats = wp_get_post_categories( $post->ID )); // returns array of IDs for all cats
foreach($exclude as $x){ // loop on the excluded cat ids
if(in_array($x, $cats))continue; // if excluded skip
}
http://codex.wordpress.org/Function_Reference/wp_get_post_categories
I think this will work or at least got you close.
display:none is bad mojo as the content will still be in your source code for others to see.
I hope I addressed the problem correctly for you, cheers.

Related

Woocommerce sync grouped product attributes with childrens

To achieve this, i have written 2 functions one for grouped product save and another for child product save.
1 - Adding all child attributes to the grouped product on grouped product save:
add_action('woocommerce_after_product_object_save', 'nd_update_group_product_attributes_before_save_func', 9993, 2);
function nd_update_group_product_attributes_before_save_func($product, $data_store) {
// echo 'has category <pre>';var_dump($product); echo '</pre>';die;
// exit if not the target post type
if ('product' !== $product->post_type) {
return;
}
// $product_type = $product->get_type();
$product_type = $product->post_type;
if ($product->is_type('grouped')) {
$group_product_id = $product->get_id();
nd_sync_child_attribute_to_group($group_product_id, 'pa_bedrooms');
}
}
function nd_sync_child_attribute_to_group($group_product_id, $attribute_slug){
$group_product = wc_get_product($group_product_id);
$child_product_ids = $group_product->get_children();
$all_child_attributes = array();
if($child_product_ids){
foreach ($child_product_ids as $child_product_id) {
$child_product = wc_get_product($child_product_id);
$child_attributes = wc_get_product_terms( $child_product_id, $attribute_slug, array( 'fields' => 'names' ) );
$all_child_attributes = array_unique(array_merge($all_child_attributes, $child_attributes));
}
}
if ($all_child_attributes) {
$group_attributes = wc_get_product_terms( $group_product_id, $attribute_slug, array( 'fields' => 'names' ) );
if($group_attributes){
wp_remove_object_terms( $group_product_id, $group_attributes, $attribute_slug );
}
foreach ($all_child_attributes as $attr) {
wp_set_object_terms($group_product_id, $attr, $attribute_slug, true);
}
}
}
2 - Adding all child attributes to the grouped product on child product save by triggering grouped product save.
add_action('woocommerce_update_product', 'nd_update_group_product_attributes_on_child_update', 1002, 2);
function nd_update_group_product_attributes_on_child_update($product_id) {
$product = wc_get_product( $product_id );
// exit if not the target post type
if ( !$product->is_type('simple') || !has_term( 'home-design-floor-plans', 'product_cat' , $product_id )) {
return;
}
if ( $product->is_type('simple') ) {
$children_id = $product->get_id();
$group_args = array(
'post_type' => 'product',
'meta_query' => array(
array(
'key' => '_children',
'value' => 'i:' . $product->get_id() . ';',
'compare' => 'LIKE',
)
),
'fields' => 'ids' // THIS LINE FILTERS THE SELECT SQL
);
$parent_ids = get_posts( $group_args );
if($parent_ids){
foreach ($parent_ids as $parent_grouped_id){
if($parent_grouped_id){
$parent_product = wc_get_product( $parent_grouped_id );
if($parent_product){
$parent_product->save();
}
}
}
}
}
}
I have an issue with this once I add an attribute value to a grouped product, it was not showing on the admin area group product edit > attributes.
Is there anything I missed or is there any better way to achieve this?
All I want is to sync child product attributes to parent i.e. group product.

Wordpress seo silo category/term-tree for sidebar

I created a sidebar for the dynamic WordPress category pages.
Example Url: https://example.com/category/firstcategory/secondcategory/othercategories/
SEO Silo:
Info about SEO Silos: What is a content silo and how does it benefit for SEO?
An imaginary company offers books, films and toys. And so the following categories are usually formed:
Company category:
* company
** books
** movies
** games
They have subcategories.
* company
** books
*** drama
*** comedy
** movies
*** drama
*** comedy
*** romance
** games
*** actions
*** for kids
*** click and point
The subcategories in turn have entries.
If I now come to the books category, only everything about books may appear in the category tree and not movies and games as well. Ideally not even the upper category, like that:
* company
** books
*** drama
---- drama Book1
---- drama Book2
If I'm in the drama category for books, I dont want to see the others like comedy in the books category too.
If I'm in the Company category, its okay to see the first subcategories like:
* company
** books
** movies
** games
If I'm in the books category:
* company
** books
*** drama
*** comedy
Problem:
The code isn't optimized yet, because I'm just trying out a lot.
Active Category level 2 already works (apart from the indentation).
When calling up the second category, sometimes not all (existing) sub-categories appear.
Probably the smallest problem is that the categories are not indented as a list.
// Manual: https://stackoverflow.com/questions/9225920/how-to-check-which-level-category-it-is-for-wordpress
function get_the_level($id, $type = 'category') {
return count(get_ancestors($id, $type));
}
function children_sidebar_shortcode($atts) {
global $post;
if (!is_category()) {
return false;
}
$returnval = "";
$category = get_queried_object();
$category_id = $category->term_id;
$n = 0;
$item_cat_level = 0;
// Active Category is level 2 and more
if (get_the_level($category_id) >= 2) {
$returnval .= "<h2>Active Category is level 2 and more</h2>";
$args = array(
'type' => 'post',
'child_of' => 0,
'parent' => '',
'orderby' => 'term_group', //'name',
'order' => 'ASC',
'hide_empty' => 0,
'hierarchical' => 1,
'exclude' => '',
'include' => '',
'number' => '',
'taxonomy' => 'category',
'pad_counts' => false
);
} else {
$returnval .= "<h2>Active Category is level 1 or less</h2>";
$args = array(
'type' => 'post',
'child_of' => $category_id,
'parent' => '', // set here same category as you want to fetch only their 1st level category on in depth child
'orderby' => 'term_group', //'name',
'order' => 'ASC',
'hide_empty' => 0,
'hierarchical' => 1,
'exclude' => '',
'include' => '',
'number' => '',
'taxonomy' => 'category',
'pad_counts' => false
);
}
$categories = get_categories($args);
if (count($categories) > 0) {
// show the category description
//$returnval .= category_description();
$returnval .= "<ul>";
foreach ($categories as $category) {
$item_cat_level = get_the_level($category->term_id);
// Active Category is level 2 and more
if (get_the_level($category_id) >= 2) {
if (
// Category is part of the parent Categories/Terms
cat_is_ancestor_of($category->term_id, $category_id)
// SubLevel Category 2
|| $item_cat_level >= 2
// Active Category (same)
|| $category->term_id === $category_id
) {
$category_link = sprintf(
'%3$s',
esc_url(get_category_link($category->term_id)),
esc_attr($category->name),
esc_html($category->name)
);
$returnval .= sprintf("<li class='cat-item cat-item-%d %s'>%s", $category_id, ($category->term_id === $category_id) ? 'current-cat-ancestor' : '', $category_link);
}
} else {
if (
// Category is part of the parent Categories/Terms
//cat_is_ancestor_of($category->term_id, $category_id)
// SubLevel Category 2
//||
$item_cat_level <= 1
// Active Category (same)
//|| $category->term_id === $category_id
) {
$category_link = sprintf(
'%3$s',
esc_url(get_category_link($category->term_id)),
esc_attr($category->name),
esc_html($category->name)
);
$returnval .= sprintf("<li class='cat-item cat-item-%d %s'>%s", $category_id, ($category->term_id === $category_id) ? 'current-cat-ancestor' : '', $category_link);
}
}
}
$returnval .= "</ul>";
}
// Attributes
$atts = shortcode_atts(
array(
'name' => '',
),
$atts,
''
);
return $returnval;
}
add_shortcode('children_sidebar', 'children_sidebar_shortcode');
So looking at the edited question, I think what you are really looking for is, a category tree having only the (immediate) children or siblings of the current category (i.e. the queried object/term on a category archive page), right?
If so, then this should work for you:
function children_sidebar_shortcode( $atts ) {
// Do nothing if we're not on a category archive.
if ( ! is_category() ) {
return '';
}
// Parse the shortcode's parameters.
$atts = shortcode_atts( array(
'show_parent' => 1,
), $atts );
// Get the queried category object and ID.
$current_cat = get_queried_object();
$current_cat_id = $current_cat->term_id;
// Get the category's immediate children, if any.
$parent_cat_id = $current_cat_id;
$categories = get_categories( array(
'parent' => $parent_cat_id,
'hide_empty' => 1,
) );
// If none, get its siblings.
// .. which means it's the last level.
if ( empty( $categories ) ) {
$parent_cat_id = $current_cat->parent;
$categories = get_categories( array(
'parent' => $parent_cat_id,
'hide_empty' => 1,
) );
}
$heading = '';
$list = '<ul class="cat-list">';
foreach ( $categories as $term ) {
$class = 'cat-item';
// If it's the current category, show the name only.
if ( $current_cat_id === $term->term_id ) {
$class .= ' current-cat';
$cat_name = '<span>' . esc_html( $term->name ) . '</span>';
// If it's not the current category, add a link to view the category
// archive.
} else {
$cat_name = '<a href="' . esc_url( get_category_link( $term ) ) . '">' .
esc_html( $term->name ) . '</a>';
}
$list .= "<li class='$class'>$cat_name</li>";
}
$list .= '</ul>';
if ( $parent_cat_id && $atts['show_parent'] ) {
$term = get_category( $parent_cat_id );
$heading = '<h3>' . esc_html( $term->name ) . '</h3>';
}
return "$heading $list";
}
Note regarding the shortcode parameters: I added show_parent, which if true or 1, then the immediate parent category will always be added to the output. So for example, on the Books category page, the shortcode would output something like this: (the "Books" is not a link)
Books
● Comedy
● Drama
And BTW, using a custom function to manually generate the categories list (i.e. the <li> tags) will give you full control over the HTML markup, but just so that you know, you could also use wp_list_categories() like so:
Just replace the entire foreach above with this:
$list .= wp_list_categories( array(
'current_category' => $current_cat_id,
'parent' => $parent_cat_id,
'hide_empty' => 1,
'title_li' => '',
'echo' => 0,
) );
Last but not least, you can style the current category/<li> using the current-cat class. :)
The answer is only a temporary solution:
I tried indenting with the query for a level change. Until then set an optical (but not semantic) indentation by a margin-left-0 to 2. With classes ml-%d (0,1,2).
// Manual: https://stackoverflow.com/questions/9225920/how-to-check-which-level-category-it-is-for-wordpress
function get_the_level($id, $type = 'category') {
return count(get_ancestors($id, $type));
}
function children_sidebar_shortcode($atts) {
global $post;
if (!is_category()) {
return false;
}
$returnval = "";
$category = get_queried_object();
$category_id = $category->term_id;
$item_cat_level_last = 0;
$item_cat_level = 0;
// Active Category is level 2 and more
if (get_the_level($category_id) >= 2) {
//$returnval .= "<h2>Active Category is level 2 and more</h2>";
$args = array(
'type' => 'post',
'child_of' => 0,
'parent' => '',
'orderby' => 'term_group', //'name',
'order' => 'ASC',
'hide_empty' => 1,
'hierarchical' => 1,
'exclude' => '',
'include' => '',
'number' => '',
'taxonomy' => 'category',
'pad_counts' => false
);
} else {
//$returnval .= "<h2>Active Category is level 1 or less</h2>";
$args = array(
'type' => 'post',
'child_of' => $category_id,
'parent' => '', // set here same category as you want to fetch only their 1st level category on in depth child
'orderby' => 'term_group', //'name',
'order' => 'ASC',
'hide_empty' => 1,
'hierarchical' => 1,
'exclude' => '',
'include' => '',
'number' => '',
'taxonomy' => 'category',
'pad_counts' => false
);
}
$categories = get_categories($args);
if (count($categories) > 0) {
// show the category description
//$returnval .= category_description();
$returnval .= "<ul>";
foreach ($categories as $category) {
$item_cat_level = get_the_level($category->term_id);
// Active Category is level 2 and more
if (get_the_level($category_id) >= 2) {
if (
// Category is part of the parent Categories/Terms
cat_is_ancestor_of($category->term_id, $category_id)
// SubLevel Category 2
|| $item_cat_level >= 2
// Active Category (same)
|| $category->term_id === $category_id
) {
if ($item_cat_level >= 2) {
$category_link = sprintf(
'%3$s',
esc_url(get_category_link($category->term_id)),
esc_attr($category->name),
esc_html($category->name)
);
}else{
$category_link = esc_html($category->name);
}
$returnval .= sprintf("<li class='cat-item ml-%d cat-item-%d %s'>%s", $item_cat_level, $category_id, ($category->term_id === $category_id) ? 'current-cat-ancestor' : '', $category_link);
}
} else {
if (
// Category is part of the parent Categories/Terms
//cat_is_ancestor_of($category->term_id, $category_id)
// SubLevel Category 2
//||
$item_cat_level <= 1
// Active Category (same)
//|| $category->term_id === $category_id
) {
/*$category_link = sprintf(
'%3$s',
esc_url(get_category_link($category->term_id)),
esc_attr($category->name),
esc_html($category->name)
);*/
$category_link = esc_attr($category->name);
$returnval .= sprintf("<li class='cat-item ml-%d cat-item-%d %s'>%s", $item_cat_level, $category_id, ($category->term_id === $category_id) ? 'current-cat-ancestor' : '', $category_link);
}
}
/*if ($item_cat_level > $item_cat_level_last){
$item_cat_level_last = $item_cat_level;
$returnval .= "<ul class='children'></ul>";
}*/
$returnval .= "</li>";
}
$returnval .= "</ul>";
}
// Attributes
$atts = shortcode_atts(
array(
'name' => '',
),
$atts,
''
);
return $returnval;
}
add_shortcode('children_sidebar', 'children_sidebar_shortcode');
I didn't link the first two category levels where the output doesn't work yet, until the code optimization.
With a direct call, a 301 (permanent) redirect, which is removed again when the code is optimized.
<IfModule mod_rewrite.c>
RewriteEngine On
RedirectMatch 301 ^/category/firstcategory/secondcategory/?$ https://example.com/firstcategory/secondcategory-page/
</IfModule>

Show posts of a specific category first in WordPress loop

I'd like to show posts from a category first in the homepage and then continue the default order of WordPress posts.
Is it even possible?
I've tried using 2 loops and filter the first one with the category that I want however I don't think that the pagination will work as expected.
Try this (untested code, though).
$total_posts_to_display = 10; // Change accordingly
$id_of_category_1 = 4; // Change accordingly
$filtered_posts = array(); // Array to be filled in with all posts, ordered by "category 1" first
$posts_in_category_1 = get_posts( array(
'numberposts' => $total_posts_to_display,
'category' => $id_of_category_1
) );
$ramaining_posts_number = $total_posts_to_display - count( $posts_in_category_1 );
if ( $ramaining_posts_number > 1 ) {
$excluded_post_ids = array();
foreach( $posts_in_category_1 as $ep ) {
array_push( $excluded_post_ids, $ep->ID );
}
$remaining_posts = get_posts( array(
'numberposts' => $ramaining_posts_number,
'exclude' => $excluded_post_ids
) );
} else {
$remaining_posts = array();
}
$filtered_posts = array_merge( $posts_in_category_1, $remaining_posts );
I have a more sophisticated solution that will support pagination too! You will need to place it in functions.php:
add_action( 'pre_get_posts', 'my_custom_home_post_ordering' );
function my_custom_home_post_ordering( $query ) {
if ( ! is_home() ) {
return;
}
if ( ! $query->is_main_query() ) {
return;
}
$posts_in_category_1 = get_posts( array(
'posts_per_page' => -1,
'category' => 4 // Change accordingly. You may also use 'category_name', instead.
'fields' => 'ids'
) );
$query->set( 'post__in', $posts_in_category_1 );
$query->set( 'orderby', 'post__in' );
}

WooCommerce REST API : query products by multiple attributes

According to the API : http://woocommerce.github.io/woocommerce-rest-api-docs/#list-all-products we can filter products by a single attribute. But Is it impossible to search by multiple attributes through API ?
Example : "I want red shirts". Here attribute is color and attribute term is red. To accomplish the search, the query string goes like this : products?category=17&attribute=pa_color&attribute_term=22&
And we get the red shirts only.
But for "I want red medium shirts" , here an additional size attribute with value medium is encountered. And according to the API there is no way to associate both the color and the size attributes in the query string. So the query -
products?category=17&attribute=pa_color&attribute_term=22&attribute=pa_size&attribute_term=24&
returns all products from the store
Is there any workaround ?
I have written custom query that does it all :D
This is a callback function. All you need to do is create new endpoint with this callback:
Here is a documentation:
category - string (category slug) - filter by products category.
per_page - int (default - from admin) - show items on one page.
offset - int (default - 1) - show page number.
order - string (ASC/DESC, default: desc) - order products ascending or descending.
orderby - string (name, price, default: name) - order products by key.
filter - array
[pa_attribute_name (string) ] = array of ID's.
[min_price (string) ] = int.
[max_price (string) ] = int.
Example:
/wp-json/go/v1/products/?category=smartphones&filter[pa_brand]=87,88&filter[pa_colour]=17&filter[min_price]=1&filter[max_price]=50&per_page=10&offset=1&order=DESC&orderby=price
Here is a function:
public function get_products_list_callback( \WP_REST_Request $request ) {
$params = $request->get_params();
$category = General_Helper::get_array_value( 'category', $params );
$filters = General_Helper::get_array_value( 'filter', $params );
$per_page = General_Helper::get_array_value( 'per_page', $params );
$offset = General_Helper::get_array_value( 'offset', $params );
$order = General_Helper::get_array_value( 'order', $params );
$orderby = General_Helper::get_array_value( 'orderby', $params );
$output = [];
// Use default arguments.
$args = [
'post_type' => Config::POST_TYPE_SLUG_PRODUCT,
'posts_per_page' => get_option( 'posts_per_page' ),
'post_status' => 'publish',
'paged' => 1,
];
// Posts per page.
if ( ! empty( $per_page ) ) {
$args['posts_per_page'] = $per_page;
}
// Pagination, starts from 1.
if ( ! empty( $offset ) ) {
$args['paged'] = $offset;
}
// Order condition. ASC/DESC.
if ( ! empty( $order ) ) {
$args['order'] = $order;
}
// Orderby condition. Name/Price.
if ( ! empty( $orderby ) ) {
if ( $orderby === 'price' ) {
$args['orderby'] = 'meta_value_num';
} else {
$args['orderby'] = $orderby;
}
}
// If filter buy category or attributes.
if ( ! empty( $category ) || ! empty( $filters ) ) {
$args['tax_query']['relation'] = 'AND';
// Category filter.
if ( ! empty( $category ) ) {
$args['tax_query'][] = [
'taxonomy' => Config::TAXONOMY_SLUG_PRODUCT,
'field' => 'slug',
'terms' => [ $category ],
];
}
// Attributes filter.
if ( ! empty( $filters ) ) {
foreach ( $filters as $filter_key => $filter_value ) {
if ( $filter_key === 'min_price' || $filter_key === 'max_price' ) {
continue;
}
$args['tax_query'][] = [
'taxonomy' => $filter_key,
'field' => 'term_id',
'terms' => \explode( ',', $filter_value ),
];
}
}
// Min / Max price filter.
if ( isset( $filters['min_price'] ) || isset( $filters['max_price'] ) ) {
$price_request = [];
if ( isset( $filters['min_price'] ) ) {
$price_request['min_price'] = $filters['min_price'];
}
if ( isset( $filters['max_price'] ) ) {
$price_request['max_price'] = $filters['max_price'];
}
$args['meta_query'][] = \wc_get_min_max_price_meta_query( $price_request );
}
}
$the_query = new \WP_Query( $args );
if ( ! $the_query->have_posts() ) {
return $output;
}
while ( $the_query->have_posts() ) {
$the_query->the_post();
$output[] = get_the_title();
}
wp_reset_postdata();
return $output;
}
Hope it helps
Try to request like this:
products?attribute=pa_color&attribute_term=51,50&per_page=100
Its worked for me.
Latest woocommerce-api wc/v2!
after test on WooRest API v3, you can pass multiple term taxonomy IDs.
You have to pass a string with ids separated by comma, this will be parsed as an array by WooRest API v3.
Like this :
/wp-json/wc/v3/products/?category=1,2,3,4
Don't forget to encode query parameter or use Automattic\WooCommerce package
Enjoy,
I just looked into the woocommerce rest api implementation at
plugins/woocommerce/includes/api/class-wc-rest-products-controller.php
file but unfortunately their codes doesn't support multiple attributes.
But you can write your own query to achieve your goal.
$args = array(
'post_type' => 'product',
'tax_query' => array(
array(
'relation' => 'AND',
array(
'taxonomy' => 'pa_color',
'field' => 'term_id',
'terms' => array( 'red' ),
),
array(
'taxonomy' => 'pa_size',
'field' => 'term_id',
'terms' => array( 'Long' ),
),
),
),
);
$products = new WP_Query( $args );
print_r($products);

List authors that have written certain number of posts in category/tags in Wordpress

I'm struggling to get the list of authors on the category page. I need to list the authors who have written at least 5 articles in that category.
I need something like this in tags also.
Any idea how to do this in wordpress?
Its only possible with a custom SQL query so here is a simple function which should return an array with user id's of users with at least $n posts in the current term archive, which means it should work in categories, tags and custom taxonomies
function get_authors_with($num = 5){
global $wpdb;
$term_slug = get_query_var( 'term' );
$taxonomyName = get_query_var( 'taxonomy' );
$current_term = get_term_by( 'slug', $term_slug, $taxonomyName );
$sub_q = $wpdb->prepare("SELECT * FROM $wpdb->posts
INNER JOIN $wpdb->term_relationships ON ($wpdb->posts.ID = $wpdb->term_relationships.object_id)
INNER JOIN $wpdb->term_taxonomy ON ($wpdb->term_relationships.term_taxonomy_id = $wpdb->term_taxonomy.term_taxonomy_id)
WHERE ($wpdb->term_taxonomy.term_id = %s
AND $wpdb->term_taxonomy.taxonomy = '%s'
AND $wpdb->posts.post_type = 'post'
AND $wpdb->posts.post_status = 'publish')",
$current_term->term_id,
$taxonomyName
);
$sql = $wpdb->prepare("SELECT $wpdb->posts.post_author, FROM (%s)
GROUP BY $wpdb->posts.post_author
HAVING count(*) > %s",
$sub_q,
$num
);
return $wpdb->get_results($sql);
}
Try this.
function list_author_in_this_cat ($with) {
if (is_category()) {
$current_category = get_query_var('cat');
$args = array(
'numberposts' => -1,
'category' => $current_category,
'orderby' => 'author',
'order' => 'ASC'
);
} else {
$tag_id = get_query_var('tag_id');
$args = array(
'numberposts' => -1,
'tag__in' => $tag_id,
'orderby' => 'author',
'order' => 'ASC'
);
}
$cat_posts = get_posts($args);
$author_id_array = array();
$user_posts = array();
foreach( $cat_posts as $cat_post ):
$user_posts[$cat_post->post_author][] = $cat_post->ID;
endforeach;
foreach( $user_posts as $key => $user_post ):
$user_post = array_unique($user_post);
$count_user_posts[$key] = count($user_post);
if ($count_user_posts[$key] >= $with) {
$author_id_array[] = $key;
}
endforeach;
return $author_id_array; }
In your theme files, place this code wherever you want the list of authors to be displayed:
if (is_category() || is_tag()) {
$at_least = 5; // at least 5 articles in current category or tags
$author_array = list_author_in_this_cat ($at_least);
foreach (array_slice($author_array, 0, 4) as $author) : // limit 4 results
$name = get_userdata($author)->display_name;
$link = get_userdata($author)->user_login;
echo "<a href='/author/".$link."'>".$name."</a>\n";
endforeach;
}
Add the following code to your theme's function.php
function get_authors_in_category ( $category_id, $min_posts ) {
$posts = get_posts( array( 'numberposts' => 1000, 'category' => $category_id ) );
$author_count = array();
foreach ($posts as $post) {
if( array_key_exists( get_the_author_meta( 'display_name', $post->post_author ), $author_count ) ) {
$author_count[get_the_author_meta( 'display_name', $post->post_author )]++;
} else { $author_count[get_the_author_meta( 'display_name', $post->post_author )] = 1; }
}
$authors = array();
foreach ( $author_count as $author_name => $count ) {
if ( $min_posts <= $count ) {
$authors[] = $author_name;
}
return $authors;
}
This function as you can see returns an array of authors who have a minimum number of posts in a category. Category ID has to be passed, this can be obtained using the wordpress function get_cat_ID.
You can call this function from any where in the theme and display the authors as you wish.
Note: This is a more resource intensive than the custom SQL functions. Also this function might have some errors, I typed it here and didn't test it.
I did some simple coding with query post method.,
<?php
$cur_cat_id = get_cat_id(single_cat_title("",false));
$posts=query_posts("cat=$cur_cat_id&order=ASC");
foreach($posts as $post){
$number_of_posts = number_format_i18n(get_the_author_posts($post->post_author));
if($number_of_posts>5)
{
echo the_author_meta('user_nicename',$post->post_author)."(".number_format_i18n(get_the_author_posts($post->post_author)).")<br>";
}
}
?>
I think this may help you to resolve your problem.

Resources