Exclude category from woocommerce query - woocommerce

I'm trying to list categories but i need to exclude couple. How can I add exclude category to the following?
$size = sizeof( get_the_terms( $post->ID, 'product_cat' ) );
echo $product->get_categories('<p>' . _n( '', '', $size, 'woocommerce' ) . '</p>' );
Many thanks!

Please take a look at:
http://codex.wordpress.org/Plugin_API/Action_Reference/pre_get_posts
the below example uses is_home. But you can also use the is_page() function to check for the page you are using and then apply the pre_get_posts.
function exclude_category( $query ) {
if ( $query->is_home() && $query->is_main_query() ) {
$query->set( 'cat', '-1,-1347' );
}
}
add_action( 'pre_get_posts', 'exclude_category' );

Related

Make ONLY one URL to a Wordpress post accessible which has child category

Let say a post have parent-category 'Recipes', child-category 'Baking' and post name 'My post title'
Apparently, the post can be accessible via 2 link:
https://example.com/recipes/baking/my-post-title/
https://example.com/recipes/my-post-title/
I just want the post to be accessible via the first link, not the latter. Is it possible?
Many thanks!
FYI, I used /%category%/%postname%/ as custom structure for permalinks
you can use both post_link hook and a custom rewrite rule.
custom rewrite function:
function post_add_rewrite_rule(){
$posts = get_posts( array( 'numberposts' => -1) );
if( $posts ){
foreach($posts as $post ){
$post_terms = wp_get_object_terms( $post->ID, 'recipes' );
if( $post_terms ){
add_rewrite_rule( "^recipes/" . array_pop($post_terms)->slug . "/([^/]+)/?$", 'index.php?post_type=post&name=$matches[1]', 'top' );
}
}
}
}
add_action('init', 'post_add_rewrite_rule');
post link hook:
function post_custom_permalink( $url, $post, $leavename=false ) {
if ( $post->post_type == 'post' ) {
$post_terms = wp_get_object_terms( $post->ID, 'recipes' );
if( !empty($post_terms) ){
$url = home_url( '/recipes/' . array_pop($post_terms)->slug . '/' . $post->post_name );
}
else{
$url = home_url( '/recipes/' . $post->post_name );
}
}
return $url;
}
add_filter( 'post_link', 'post_custom_permalink', 10, 3 );
and finally set up your permalink structure to custom structure:
/recipes/%postname%/

Wordpress: Limit Tag Links in Post Content

I really frustrated, I am a novice in wordpress I am trying to Limit Maximum Numbers of Tag Links to appear within post content article. Below is my code. I don't know how to fix it up.
function link_words( $text ) {
$replace = array();
$tags = get_tags();
$count=0;
if ( $tags ) {
foreach ( $tags as $tag ) {
$count++;
$replace[ $tag->name ] = sprintf( '%s', esc_url( get_term_link( $tag ) ), esc_html( $tag->name ) );
if( $count > 2 ) break;
}
}
$text = str_replace( array_keys($replace), $replace, $text );
return $text;
}
add_filter( 'the_content', 'link_words' );
If your tags are comma-separated, this might work for you:
function limit_tags($tags) {
$tags = substr($tags, 0, strpos($tags, ',', strpos($tags, ',')+1));
return $tags;
}
add_filter('the_tags','limit_tags');
The $tags variable is actually a string...
You mention your function works the way you want it to (linking tags) so I won't mess with that. If you look at the docs for get_tags(), you'll see it accepts a few arguments including number which will limit it. This way you won't have a $counter type variable to mess with.
You can also just check to see if the $tags variable gets set to a truthy value, you don't need to define it first.
Your str_replace is also occurring whether or not $tags is defined, which can cause issues if none are found, so you should move that up into the if statement.
For semantic clarity, I've also changed the $text variable to $content since you're using the_content filter.
add_filter( 'the_content', 'link_tags_in_content' );
function link_tags_in_content( $content ){
if( $tags = get_tags( array( 'number' => 2 ) ) ){
foreach( $tags as $tag ){
$tag_link = sprintf( '%s', esc_url( get_term_link( $tag ) ), esc_html( $tag->name ) );
$content = str_replace( $tag->name, $tag_link, $content );
}
}
return $content;
}
Ok, so I think I understand what you want better now...
function link_words( $text ) {
$tags = get_tags();
if ( $tags ) {
foreach ( $tags as $tag ) {
$from = '!<h2>[^<>]*<\/h2>(*SKIP)(*F)|<b>[^<>]*<\/b>(*SKIP)(*F)|<a\b[^>]*>.*?</a>(*SKIP)(*F)|(\b'.$tag->name.'\b)(?=[^>]*(?:<|$))!';
$to = sprintf( ' %s ', esc_url( get_term_link( $tag ) ), esc_html( $tag->name ) );
$text = preg_replace($from, $to , $text, 2);
}
}
return $text;
}
add_filter( 'the_content', 'link_words' );
Because of the limit on preg_replace (2), and it being inside the tag-loop, this replaces two instances of a tag name in the text for every tag... Is this along the lines of what you want? Be aware that this is not case-insensitive, so it will not match if your tag is the first word in a sentence, and is capitalized. To do something like that, maybe take a look at this thread:
PHP preg_replace: Case insensitive match with case sensitive replacement

Download Count on WooCommerce Free Product

I provide freebies using WooCommerce plugin.
I want to ask, is it possible to determine the number of downloads on the freebies on the product detail page downloads?
Use this code:
add_action( 'woocommerce_single_product_summary', 'show_number_of_downloads' );
function show_number_of_downloads() {
global $wpdb, $product;
if ( empty( $product->id ) ) return;
if ( $product->product_type == 'variable' ) {
$product_ids = $product->get_children();
} else {
$product_ids = array( $product->id );
}
$query = "SELECT SUM( download_count ) AS count
FROM {$wpdb->prefix}woocommerce_downloadable_product_permissions
WHERE product_id IN (".implode( ',', $product_ids ).")";
$count = $wpdb->get_var( $query );
if ( ! empty( $count ) ) {
echo '<p><strong>' . __( 'Total downloads' ) . '</strong>: ' . $count . '</p>';
}
}
Keep this code either in your theme's function.php file or any custom plugin such that you don't loose this code after upgrade of either WordPress, plugins or theme.
The result:

Getting the Product Attribute Term Permalink in WordPress / WooCommerce

I'm using WooCommerce with WordPress to build a store of Antique Photos.
I'm using the WooCommerce product attributes feature to store information about an item photographer.
See here for an example, photographer attribute is pulled out in the box on the left http://bit.ly/1Dp999O
The code that pulls out the attribute looks like this:
if($attribute['is_taxonomy']) {
$values=wc_get_product_terms($product->id, $attribute['name'], array('fields' => 'names'));
echo apply_filters('woocommerce_attribute', wpautop(wptexturize(implode(', ', $values))), $attribute, $values);
}
$values looks like this:
Array ( [0] => Photographer 1 )
The problem is, how do I get to the permalink for the Photographer which is automatically generated by WordPress and WooCommerce:
http://bit.ly/1JtwBna
I can't find any documentation for this within WooCommerce, and this seems to be a taxonomy within a taxonomy which goes a bit further than stabdard WordPress, but I'm assuming this is a fairly standard requirement. Any pointers appreciated.
Once you have the attribute term (in this case the photographer's name) you can use get_term_link() to get the URL. Because the $product id isn't passed to the woocommerce_attribute folder, I couldn't filter that, but instead create an override of the product-attributes.php template. And modified the relevant section to be the following:
if ( $attribute['is_taxonomy'] ) {
$terms = wc_get_product_terms( $product->id, $attribute['name'], array( 'fields' => 'all' ) );
$html = '';
$counter = 1;
$total = count( $terms );
foreach( $terms as $term ){
$html .= sprintf( '%s',
esc_url( get_term_link( $term ) ),
esc_attr( $term->name ),
wptexturize( $term->name )
);
if( $counter < $total ){
$html .= ', ';
}
$counter++;
}
echo wpautop( $html );
}
For some reason, the URL isn't a pretty permalink. It's late and I can't tell if this has to do with my configuration or what exactly, but it is a start.
This basically does what I require:
$terms = get_the_terms($product->id, $attribute['name']);
foreach ($terms as $term){
echo ''.$term->name.'';
}
But could do with a bit of refinement for sure.

Add current_cat class on wp_list_categories when I'm on single with custom taxonomy

I search all the web for that answer. I use wp_list_categories to make a submenu with custom taxonomy, It works well, and puts current-cat when I browse those categories.
The thing is, when I browse single posts with this menu, the highlight no more works.
For the blog part of that site, I use the following code to highlight current category on wp_list_categories():
function sgr_show_current_cat_on_single($output) {
global $post;
if( is_single() ) {
$categories = wp_get_post_categories($post->ID);
foreach( $categories as $catid ) {
$cat = get_category($catid);
if(preg_match('#cat-item-' . $cat->cat_ID . '#', $output)) {
$output = str_replace('cat-item-'.$cat->cat_ID, 'cat-item-'.$cat->cat_ID . ' current-cat', $output);
}
}
}
return $output;
}
add_filter('wp_list_categories', 'sgr_show_current_cat_on_single');
But as far as I tried, can't make it work for single posts that are ordered by custom taxonomy. :/ > I don't know how to custom it.
Is it even possible ?
You need to use get_the_terms( $id, $taxonomy ); instead of wp_get_post_categories(); for getting custom taxonomy term IDs.
You can hardcode taxonomy name into the functon or get it from the $args you passed into wp_list_categories( $args );.
Final code:
add_filter( 'wp_list_categories', 'sgr_show_current_cat_on_single', 10, 2 );
function sgr_show_current_cat_on_single( $output, $args ) {
if ( is_single() ) :
global $post;
$terms = get_the_terms( $post->ID, $args['taxonomy'] );
foreach( $terms as $term ) {
if ( preg_match( '#cat-item-' . $term ->term_id . '#', $output ) ) {
$output = str_replace('cat-item-'.$term ->term_id, 'cat-item-'.$term ->term_id . ' current-cat', $output);
}
}
endif;
return $output;
}

Resources