Woocommerce: hide category in shop - php

I have a category with products not visible to everyone.
I already have a script in place, that removes this category from the sidebar widget, when no items in the category are visible to the user.
I created a function that puts the exclude term_id in a global variable.
Now I need something that excludes them from view in the shop.
$GLOBALS['cat_exclude'] = NULL;
function getExcludedCats( ) {
//if( ! is_admin() && (is_product_category() || is_shop())){
$current_tax = get_query_var( 'product_cat' );
$term =get_term_by( 'slug', $current_tax, 'product_cat');
$parentid = $term->term_id;
$args = array(
'hide_empty' => true,
'parent' => $parentid
);
$product_categories = get_terms( 'product_cat', $args );
$exclude = array();
foreach ( $product_categories as $category ) {
$posts = get_posts( array( 'post_type' => 'product', 'posts_per_page' => -1, 'product_cat' => $category->slug, 'fields' => 'ids' ) );
$show_category = false;
foreach ( $posts as $post ) {
$product = new WC_Product( $post );
$visible_product = $product->is_visible();
if ( true === $visible_product ) {
$show_category = true;
break;
}
}
if ( false === $show_category ) {
$exclude[] = $category->term_id;
}
}
if ( ! empty( $exclude ) ) {
$GLOBALS['cat_exclude'] = implode( ',', $exclude );
}
//}
}
add_action('wp_head', 'getExcludedCats');
However, in the shop view itself, the category is still visible. How can I remove it there, when no items in this category are visible to the user.
I have tried:
https://gist.github.com/rynaldos/a9d357b1e3791afd9bea48833ff95994
But it removes the category ALWAYS, in both widget and shop.
Products are being displayed by group membership of the customer:
https://wordpress.org/plugins/groups/

I think I managed to create a script that made this possible:
https://gist.github.com/DarkAllMan/cffb114eb97c6f26882e54793e023587
<?php
/**
Plugin Name: WooCommerce - Hide categories where no products are visible to user
Plugin URI: https://www.randall.nl
Description: Excludes categories with no visible products from the WooCommerce category overview in shop
Version: 0.1
Author: Randall Kam
Author URI: https://www.randall.nl
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if ( !class_exists( 'ExcludeCats' ) ) :
class ExcludeCats {
public $version = '0.1',
$exclude = array();
protected static $_instance = null;
/**
* Main Plugin Instance
*
* Ensures only one instance of plugin is loaded or can be loaded.
*/
public static function instance() {
if ( is_null( self::$_instance ) ) {
self::$_instance = new self();
}
return self::$_instance;
}
/**
* Constructor
*/
public function __construct() {
// CHECK CATEGORIES FOR VISIBLE PRODUCTS
add_action('wp_head', array( $this, 'get_excluded_cats' ), 10, 3 );
// ADD THE WIDGET SIDEBAR FILTER
add_filter( 'woocommerce_product_categories_widget_args', array( $this, 'kfg_exclude_categories_from_widget'), 10, 1 );
// ADD THE SHOP FILTER
add_filter( 'woocommerce_product_subcategories_args', array( $this, 'filter_woocommerce_product_subcategories_args'), 10, 1 );
}
// GET CATEGORIES WITH NO VISIBLE PRODUCTS AND PUT IN GLOBAL IF GLOBAL FALSE
public function get_excluded_cats( $terms, $taxonomies, $args ) {
$current_tax = get_query_var( 'product_cat' );
$term =get_term_by( 'slug', $current_tax, 'product_cat');
$term_id = $term->term_id;
$args = array(
'parent' => $term_id,
'hide_empty' => false,
'hierarchical' => false,
);
$product_categories = get_terms( 'product_cat', $args );
// if a product category and on the shop page
//if ( in_array( 'product_cat', $taxonomies ) && ! is_admin() && is_shop() ) {
if ( ! is_admin() && is_shop() ) {
foreach ( $product_categories as $key => $term ) {
unset($this->exclude);
if($term->taxonomy=='product_cat'){
$posts = get_posts( array( 'post_type' => 'product', 'posts_per_page' => -1, 'product_cat' => $term->slug, 'fields' => 'ids' ) );
$show_category = false;
foreach ( $posts as $post ) {
$product = new WC_Product( $post );
$visible_product = $product->is_visible();
if ( true === $visible_product ) {
$show_category = true;
break;
}
}
}
if ( false === $show_category ) {
$this->exclude[] = $term->term_id;
}
}
}
}
public function get_parent_cats ($cat_termid, $found = array()) {
array_push ($found, $cat_termid);
$term =get_term_by( 'term_id', $cat_termid, 'product_cat');
if($term->parent > 0){
return get_parent_cats($term->parent, $found);
}
return $found;
}
// ADD FILTERS FOR CATEGORIES AND EXCLUDE EMPTY
public function filter_woocommerce_product_subcategories_args( $temp_args = array() ) {
$current_tax = get_query_var( 'product_cat' );
$term =get_term_by( 'slug', $current_tax, 'product_cat');
$term_id = $term->term_id;
$temp_args = array(
'parent' => $term_id,
'menu_order' => 'ASC',
'hide_empty' => 1,
'hierarchical' => 1,
'taxonomy' => 'product_cat',
'pad_counts' => 1,
'include' => NULl,
'exclude' => $this->exclude,
);
return $temp_args;
}
public function kfg_exclude_categories_from_widget( $category_list_args ) {
$current_tax = get_query_var( 'product_cat' );
$term = get_term_by( 'slug', $current_tax, 'product_cat');
$term_id = $term->term_id;
$parents = $this->get_parent_cats($term_id);
$args = array(
'hide_empty' => false,
'hierarchical' => true,
);
$product_categories = get_terms( 'product_cat', $args );
$wexclude = array();
foreach ( $product_categories as $category ) {
$posts = get_posts( array( 'post_type' => 'product', 'posts_per_page' => -1, 'product_cat' => $category->slug, 'fields' => 'ids' ) );
$show_category = false;
foreach ( $posts as $post ) {
$product = new wC_Product( $post );
$visible_product = $product->is_visible();
if ( true === $visible_product ) {
$show_category = true;
break;
}
}
if ( false === $show_category || ( $category->parent > 0 && !in_array($category->parent,$parents) ) ) {
$wexclude[] = $category->term_id;
}
}
if ( ! empty( $wexclude ) ) {
$category_list_args['exclude'] = implode( ',', $wexclude );
unset( $category_list_args['include'] );
}
return $category_list_args;
}
} // class ExcludeCats
endif; // class_exists
/**
* Returns the main instance of the plugin class to prevent the need to use globals.
*
* #since 2.0
* #return WooCommerce_PostcodeAPInu
*/
function ExcludeCats() {
return ExcludeCats::instance();
}
ExcludeCats(); // load plugin

Related

Relating Wordpress Users with Order Export

We are using Advanced Custom Fields, WP All Export Pro, and WordPress with Woocommerce.
I have an ACF field created for our accountant in users area of WordPress called "traverse_customer_id". This is for her to know what customer this order is for.
I have this ACF field showing in the orders export but the data comes back blank on each export. I think it's because I'm not relating the order with the customer or user ID. I've attempted to use a code snippet from WP All Exports' support without any luck. Could anyone with knowledge help me see what I'm doing wrong?
This is what I have in the "Custom export field" area: (I think this is running the function on each line of the import.)
[sf_helper_meta_query_lookup("traverse_customer_id",{Customer User ID},"user")]
Then I have this below in the Function Editor:
function sf_helper_meta_query_lookup( $meta_key = '', $meta_value = '', $object_type = 'post', $taxonomy = '', $return_field = 'ID', $compare = '=', $custom_args = array() ) {
if ( empty( $object_type ) || empty( $meta_key ) || empty( $meta_value ) ) return;
$func = 'get_posts';
switch ( $object_type ) {
case 'user':
$func = 'get_users';
break;
case 'term':
$func = 'get_terms';
if ( $return_field == 'ID' ) {
$return_field = 'term_id';
}
break;
default:
$func = 'get_posts';
break;
}
if ( ! empty( $custom_args ) ) {
$objects = $func( $custom_args );
if ( ! empty( $objects ) ) {
return $objects[0]->$return_field;
} else {
return false;
}
}
$args = array();
$meta_query = array( array(
'key' => $meta_key,
'value' => $meta_value,
'compare' => $compare
) );
if ( $func == 'get_terms' ) {
$args = array(
'taxonomy' => $taxonomy,
'hide_empty' => false,
'meta_query' => $meta_query
);
} elseif ( $func == 'get_users' ) {
$args = array(
'meta_query' => $meta_query
);
} else {
$args = array(
'post_type' => $object_type,
'meta_query' => $meta_query
);
}
if ( $objects = $func( $args ) ) {
return $objects[0]->$return_field;
} else {
return false;
}
}
Any help would be greatly appreciated!

How do I set custom product meta on a new product using WooCommerce Core?

I'm adding new products (car listings) to my WooCommerce shop in bulk in PHP. I'm looping through rows in a custom data table and adding them as WooCommerce products.
I'm able to save each product and add the default meta (ie. description, price, sku, visibility, etc). However, I am not able to set custom product meta. Am I doing this in the wrong order?
Below is the code in my FOREACH loop that saves each row (but the "set_meta_data" is not working).
foreach ( $cars as $car ) {
set_time_limit(60);
$product = new WC_Product_Simple();
$product->set_name( $car->heading );
$product->set_status( 'publish' );
$product->set_slug( $car->heading . '-' . uniqid() );
$product->set_description( $car->seller_comments );
$product->set_regular_price( $car->price );
$product->set_sku( $car->vehicle_id );
$product->set_virtual( true );
$product->set_meta_data( array(
'neg_miles' => $car->miles,
'neg_year' => $car->year,
'neg_trim' => $car->trim,
'neg_drivetrain' => $car->drivetrain,
'neg_fueltype' => $car->fuel_type,
'neg_transmission' => $car->transmission,
'neg_doors' => $car->doors,
'neg_cylinders' => $car->cylinders,
'neg_color_ext' => $car->color,
'neg_color_int' => $car->interior_color,
'neg_is_certified' => $car->is_certified,
'neg_single_owner' => $car->carfax_1_owner,
'neg_engine' => $car->engine,
'neg_latitude' => $car->latitude,
'neg_longitude' => $car->longitude
) );
$product->save();
$product_id = $product->get_id();
if( !term_exists( $car->make, 'product_cat' ) ) {
$make = wp_insert_term( $car->make, 'product_cat' );
$model = wp_insert_term( $car->model, 'product_cat', array( 'parent' => $make['term_id'] ) );
} else {
$make = term_exists( $car->make, 'product_cat' );
if( !term_exists( $car->model, 'product_cat' ) ) {
$model = wp_insert_term( $car->model, 'product_cat', array( 'parent' => $make['term_id'] ) );
} else {
$model = term_exists( $car->model, 'product_cat' );
}
}
wp_set_object_terms( $product_id, array( intval($make['term_id']), intval($model['term_id']) ), 'product_cat' );
if( !empty( $car->body_type ) ) {
if( !term_exists( $car->body_type, 'neg_body_style' ) ) {
$body = wp_insert_term( $car->body_type, 'neg_body_style' );
} else {
$body = term_exists( $car->body_type, 'neg_body_style' );
}
wp_set_object_terms( $product_id, array( intval($body['term_id']) ), 'neg_body_style' );
}
$last_id = $car->ID;
}
set_meta_data method require another piece of meta structure (with id).
I think is better use update_meta_data method in loop:
$product->update_meta_data('neg_miles', $car->miles);

Automatically assign products to categories based on their product tags in Woocommerce

I currently have a function which successfully adds products to Woocommerce using wp_insert_post().
I'm now trying to assign products to relevant categories based on their product tags. For example, if the product is added with the product tags 'ring' or 'necklace' then it is auto assigned to the 'Jewellery' category.
Using the following function, I'm able to achieve the correct functionality on posts, but have had no luck in attempting to make this work for the products post type used in woocommerce.
Works for posts:
function auto_add_category ($post_id = 0) {
if (!$post_id) return;
$tag_categories = array (
'ring' => 'Jewellery',
'necklace' => 'Jewellery',
'dress' => 'Clothing',
);
$post_tags = get_the_tags($post_id);
foreach ($post_tags as $tag) {
if ($tag_categories[$tag->name] ) {
$cat_id = get_cat_ID($tag_categories[$tag->name]);
if ($cat_id) {
$result = wp_set_post_terms( $post_id, $tags = $cat_id, $taxonomy = 'category', $append = true );
}
}
}
}
add_action('publish_post','auto_add_category');
I've tried to repurpose the code to work for products as follows:
function auto_add_category ($product_id = 0) {
if (!$product_id) return;
$tag_categories = array (
'ring' => 'Jewellery'
'necklace' => 'Jewellery',
'dress' => 'Clothing',
);
$product_tags = get_terms( array( 'taxonomy' => 'product_tag') );
foreach ($product_tags as $tag) {
if ($tag_categories[$tag->name] ) {
$cat = get_term_by( 'name', $tag_categories[$tag->name], 'product_cat' );
$cat_id = $cat->term_id;
if ($cat_id) {
$result = wp_set_post_terms( $product_id, $tags = $cat_id, $taxonomy = 'product_cat', $append = true );
}
}
}
}
add_action('publish_product','auto_add_category');
However, it doesn't assign the relevant categories upon product creation. Any assistance would be greatly appreciated by this novice coder muddling his way through wordpress!
Try this code:
function auto_add_category ($product_id = 0) {
if (!$product_id) return;
// because we use save_post action, let's check post type here
$post_type = get_post_type($post_id);
if ( "product" != $post_type ) return;
$tag_categories = array (
'ring' => 'Jewellery'
'necklace' => 'Jewellery',
'dress' => 'Clothing',
);
// get_terms returns ALL terms, so we have to add object_ids param to get terms to a specific product
$product_tags = get_terms( array( 'taxonomy' => 'product_tag', 'object_ids' => $product_id ) );
foreach ($product_tags as $term) {
if ($tag_categories[$term->slug] ) {
$cat = get_term_by( 'name', $tag_categories[$term->slug], 'product_cat' );
$cat_id = $cat->term_id;
if ($cat_id) {
$result = wp_set_post_terms( $product_id, $cat_id, 'product_cat', true );
}
}
}
}
add_action('save_post','auto_add_category');

How to exclude a term from a taxonomy post count function

I have a function that displays the post count of any terms for its taxonomy anywhere i want to show it and it works great but i would like to change this up a bit to completely exclude the post count of any post that has a certain term added to it, let's call that "state". So if a post has "state" added to it, i would like the function to not include the count of that post in any terms within the taxonomy.
function get_city_count( $taxonomy = 'countries', $term = '', $args = [] )
{
if ( !$term )
return false;
if ( $term !== 'all' ) {
if ( !is_array( $term ) ) {
$term = filter_var( $term, FILTER_VALIDATE_INT );
} else {
$term = filter_var_array( $term, FILTER_VALIDATE_INT );
}
}
if ( $taxonomy !== 'countries' ) { $taxonomy = filter_var( $taxonomy, FILTER_SANITIZE_STRING );
if ( !taxonomy_exists( $taxonomy ) ) return false;
}
if ( $args ) { if ( !is_array ) return false; } $defaults = [ 'posts_per_page' => 1, 'fields' => 'ids' ];
if ( $term !== 'all' ) { $defaults['tax_query'] = [ [ 'taxonomy' => $taxonomy, 'terms' => $term ] ]; }
$combined_args = wp_parse_args( $args, $defaults );
$q = new WP_Query( $combined_args );
return $q->found_posts;
}

Filter categories in wordpress

I want to add a filter to get_categories function.
I tried this:
function wpr_cat_filter($args) {
$args['include'] = '37';
return $args;
}
add_filter('get_categories','wpr_cat_filter');
but it doesn't seem to be working. Any ides of what is wrong?
The filter doesn't actually seems to be applied.
If you check the "get_categories" function (in wp-includes/category.php), there's no "get_categories" filter applied:
function &get_categories( $args = '' ) {
$defaults = array( 'taxonomy' => 'category' );
$args = wp_parse_args( $args, $defaults );
$taxonomy = apply_filters( 'get_categories_taxonomy', $args['taxonomy'], $args );
// Back compat
if ( isset($args['type']) && 'link' == $args['type'] ) {
_deprecated_argument( __FUNCTION__, '3.0', '' );
$taxonomy = $args['taxonomy'] = 'link_category';
}
$categories = (array) get_terms( $taxonomy, $args );
foreach ( array_keys( $categories ) as $k )
_make_cat_compat( $categories[$k] );
return $categories;
}
Also, if you check the source:
wordpress$ grep -Ri "apply_filters" * | grep get_categories
wp-includes/default-widgets.php: wp_dropdown_categories(apply_filters('widget_categories_dropdown_args', $cat_args));
wp-includes/default-widgets.php: wp_list_categories(apply_filters('widget_categories_args', $cat_args));
wp-includes/category.php: $taxonomy = apply_filters( 'get_categories_taxonomy', $args['taxonomy'], $args );
Perhaps it is just a placeholder for a filter that you can add yourself or might be added later.
If you want that filter, change the get_category function:
function &get_categories( $args = '' ) {
$defaults = array( 'taxonomy' => 'category' );
$args = wp_parse_args( $args, $defaults );
$args = apply_filters( 'get_categories', $args );
$taxonomy = apply_filters( 'get_categories_taxonomy', $args['taxonomy'], $args );
// Back compat
if ( isset($args['type']) && 'link' == $args['type'] ) {
_deprecated_argument( __FUNCTION__, '3.0', '' );
$taxonomy = $args['taxonomy'] = 'link_category';
}
$categories = (array) get_terms( $taxonomy, $args );
foreach ( array_keys( $categories ) as $k )
_make_cat_compat( $categories[$k] );
return $categories;
}
You might want to file a bug with wordpress or ask on their mailing list to find out why this filter isn't being applied!

Categories