In WordPress, I have created "Dealer" and "Wholesale" user roles.
I want to hide specific WooCommerce product variation if the user role has a "Dealer" role for specific product variations based on a custom setting field. I have added a checkbox to the product variation to selectively hide or display the variation.
Partially based on this answer thread I have the following code:
// Here is where I add my custom user roles- Wholesaler and Dealer
function add_custom_roles() {
add_role(
'wholesaler',
__( 'Wholesaler' ),
get_role( 'customer' )->capabilities
);
add_role(
'dealer',
__( 'Dealer' ),
get_role( 'customer' )->capabilities
);
}
add_action( 'init', 'add_custom_roles' );
// Here i add custom fields to product variations
add_action( 'woocommerce_variation_options', 'add_custom_fields_to_variations', 10, 3 );
function add_custom_fields_to_variations( $loop, $variation_data, $variation ) {
woocommerce_wp_checkbox(
array(
'id' => '_hide_variation_dealer',
'wrapper_class' => 'show_if_variation',
'label' => __('Hide for dealers', 'woocommerce' ),
'description' => '',
'value' => get_post_meta( $variation->ID, '_hide_variation_dealer', true ) ? 'yes' : 'no',
)
);
}
// Saving custom fields for product variations
add_action( 'woocommerce_save_product_variation', 'save_custom_fields_for_variations', 10, 2 );
function save_custom_fields_for_variations( $variation_id, $i ) {
$hide_variation_dealer = isset( $_POST['_hide_variation_dealer'][$i] ) ? 'yes' : 'no';
update_post_meta( $variation_id, '_hide_variation_dealer', $hide_variation_dealer );
}
// Here I filtering function to read custom field values - logged in and dealer.
add_filter( 'woocommerce_variation_is_visible', 'hide_specific_product_variation', 10, 4 );
function hide_specific_product_variation( $is_visible, $variation_id, $variable_product, $variation ) {
// Check if user is logged in and has dealer role
if( is_user_logged_in() ) {
$user = wp_get_current_user();
if ( in_array( 'dealer', (array) $user->roles ) ) {
// For dealer user role, hide variations with the custom field set to 'yes'
$hide_variation_dealer = get_post_meta( $variation->ID, '_hide_variation_dealer', true );
if ( $hide_variation_dealer === 'yes' ) {
return false;
}
}
}
return $is_visible;
}
But the variation is not hidden. I am not able to find why it doesn't work. Any help is appreciated.
The main issue comes from $variation->ID
in your last function as $variation
function argument is not a WP_Post
object but a WC_Product_Variation
object (you should have used $variation_id
argument directly).
Now, as WooCommerce is migrating progressively to custom tables, you should avoid using WordPress post meta functions, when it's possible. Instead, always try to use available getter or setter methods introduced in WooCommerce 3.
Use the following code replacement that will hide specific variation from specific user role based on a custom field (checkbox in variation settings):
// Conditional function: Check if the user is from specific user role
function is_user_role( $role ) {
global $current_user;
return in_array( $role, $current_user->roles );
}
// Add a custom setting field to product variation
add_action( 'woocommerce_variation_options', 'add_variation_setting_field', 10, 3 );
function add_variation_setting_field( $loop, $variation_data, $variation ) {
$field_key = '_hide_variation_dealer';
woocommerce_wp_checkbox( array(
'id' => $field_key,
'label' => __('Hide for dealers', 'woocommerce' ),
'value' => get_post_meta( $variation->ID, $field_key, true ) ? 'yes' : 'no',
) );
}
// Save product variation custom setting field value
add_action('woocommerce_admin_process_variation_object', 'save_variation_setting_field', 10, 2 );
function save_variation_setting_field($variation, $i) {
$field_key = '_hide_variation_dealer';
$variation->update_meta_data($field_key, isset($_POST[$field_key][$i]));
}
// Hide variation based on user role and custom field
add_filter( 'woocommerce_variation_is_visible', 'hide_conditionally_product_variation', 10, 4 );
function hide_conditionally_product_variation( $is_visible, $variation_id, $product_id, $variation ) {
$field_key = '_hide_variation_dealer';
if ( is_user_role('dealer') && $variation->get_meta($field_key) ) {
return false;
}
return $is_visible;
}
Code goes on functions.php file of your child theme (or in a plugin). Tested and works.