1

I have added a custom field (checkbox) to product variations with the following code:

/**
* Create new fields for variations
*
*/
function variation_settings_fields( $loop, $variation_data, $variation ) {

woocommerce_wp_checkbox( 
array( 
    'id'            => '_wholesale_checkbox[' . $variation->ID . ']', 
    'label'         => 'Visa endast för företagskunder', 
    'description'   => '',
    'value'         => get_post_meta( $variation->ID, '_wholesale_checkbox', true ), 
    )
);

}
/**
 * Save new fields for variations
 *
*/
function save_variation_settings_fields( $post_id ) {

// Checkbox
$checkbox = isset( $_POST['_wholesale_checkbox'][ $post_id ] ) ? 'yes' : 'no';
update_post_meta( $post_id, '_wholesale_checkbox', $checkbox );

}

add_action( 'woocommerce_variation_options', 'variation_settings_fields', 10, 3 );
add_action( 'woocommerce_save_product_variation', 'save_variation_settings_fields', 10, 2 );

It adds the checkbox as desired as seen in the screenshot.

enter image description here

Now I want to conditionally hide or show the product variation in the frontend based on this field. The problem is I have some custom variation list in place (not my work) and I couldn't figure out how to get hold of the _wholesale_checkbox field to skip the variation (for which the checkbox is checked) in the loop that is outputting the list. See code for outputting the custom variation list below:

/**
 * Convert WooCommerce variation dropdown to radio buttons.
 *
 * @param string $html Original dropdown html.
 * @param array  $args Arguments.
 */
function ac_variation_radio_buttons( $html, $args ) {
$options   = $args['options'];
$product   = $args['product'];
$attribute = $args['attribute'];
$name      = $args['name'] ? $args['name'] : 'attribute_' . sanitize_title( $attribute );
$id        = $args['id'] ? $args['id'] : sanitize_title( $attribute );

if ( empty( $options ) && ! empty( $product ) && ! empty( $attribute ) ) {
    $attributes = $product->get_variation_attributes();
    $options    = $attributes[ $attribute ];
}

// Output original dropdown element.
echo $html;

/* Create custom radio input list */
$html = '<section for="' . esc_attr( $id ) . '" class="ac_variation_list_block">';

if ( ! empty( $options ) ) {
    if ( $product && taxonomy_exists( $attribute ) ) {
        // Get terms if this is a taxonomy - ordered. We need the names too.
        $terms = wc_get_product_terms( $product->get_id(), $attribute, [
            'fields' => 'all',
        ] );
        // var_dump($options);
        foreach ( $terms as $term ) {
            /*
            if (**CUSTOM_FIELD is checked** )) {
                continue;
            }
            */
            if ( in_array( $term->slug, $options, true ) ) {
                $html .= '<section class="ac_variation_option">';
                $html .= '<input id="' . esc_attr( $term->slug ) . '_v" type="radio" name="' . esc_attr( $name ) . '_g" value="' . esc_attr( $term->slug ) . '" ' . checked( sanitize_title( $args['selected'] ), $term->slug, false ) . '/>';
                $html .= '<label for="' . esc_attr( $term->slug ) . '_v"><span></span>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name ) ) . '</label>';
                $html .= '</section>';
            }
        }
    }
}

$html .= '</section>';

echo $html;
}

add_filter( 'woocommerce_dropdown_variation_attribute_options_html', 'ac_variation_radio_buttons', 10, 2 );

2 Answers 2

1

I ultimately solved this by manipulating the $options array. See full code below for conditionally hiding a product variation by a custom field, and display variations as radio buttons. Solution marked with comments

/**
* Convert WooCommerce variation dropdown to radio buttons.
*
* @param string $html Original dropdown html.
* @param array  $args Arguments.
*/
function ac_variation_radio_buttons( $html, $args ) {
$options   = $args['options'];
$product   = $args['product'];
$attribute = $args['attribute'];
$name      = $args['name'] ? $args['name'] : 'attribute_' . sanitize_title( $attribute );
$id        = $args['id'] ? $args['id'] : sanitize_title( $attribute );

if ( empty( $options ) && ! empty( $product ) && ! empty( $attribute ) ) {
    $attributes = $product->get_variation_attributes();
    $options    = $attributes[ $attribute ];
}

// Output original dropdown element.
echo $html;

/**** ADDED CODE *****/
//Remove wholesale products for regular users
if($product->is_type( 'variable' )){
    $user = wp_get_current_user();
    if(!in_array('fretagskund', $user->roles)){
        foreach ( $product->get_children() as $child_id ) {
            $variation = wc_get_product( $child_id );

            if ( ! $variation || ! $variation->exists() ) {
                continue;
            }

            if(get_post_meta($variation->get_id(), '_wholesale_checkbox', true) === "yes" ){
                $attribute_name = get_post_meta($variation->get_id(), 'attribute_pa_storlek', true);

                if ( in_array( $attribute_name, $options, true ) ) {
                    $options = array_diff($options, array($attribute_name));
                }

            }

        }
    }
}

/* Create custom radio input list */
$html = '<section for="' . esc_attr( $id ) . '" class="ac_variation_list_block">';

if ( ! empty( $options ) ) {
    if ( $product && taxonomy_exists( $attribute ) ) {
        // Get terms if this is a taxonomy - ordered. We need the names too.
        $terms = wc_get_product_terms( $product->get_id(), $attribute, [
            'fields' => 'all',
        ] );

        foreach ( $terms as $term ) {
            if ( in_array( $term->slug, $options, true ) ) {
                $html .= '<section class="ac_variation_option">';
                $html .= '<input id="' . esc_attr( $term->slug ) . '_v" type="radio" name="' . esc_attr( $name ) . '_g" value="' . esc_attr( $term->slug ) . '" ' . checked( sanitize_title( $args['selected'] ), $term->slug, false ) . '/>';
                $html .= '<label for="' . esc_attr( $term->slug ) . '_v"><span></span>' . esc_html( apply_filters( 'woocommerce_variation_option_name', $term->name ) ) . '</label>';
                $html .= '</section>';
            }
        }
    }
}

$html .= '</section>';

echo $html;
}


add_filter( 'woocommerce_dropdown_variation_attribute_options_html', 'ac_variation_radio_buttons', 10, 2 );
1
  • You should make a woocommerce plugin from this solution: "Show/Hide Product variation in the front end" Oct 21, 2020 at 0:16
0

Code to hide these variations from the standard WC dropdown:

Notes - 1. I'm using "b2bcustomer" role name, change as needed, 2. "gewicht" is my attribute slug, change as needed.

function hide_b2b_variations( $html, $args ) {
$options   = $args['options'];
$product   = $args['product'];
$attribute = $args['attribute'];
$name      = $args['name'] ? $args['name'] : 'attribute_' . sanitize_title( $attribute );
$id        = $args['id'] ? $args['id'] : sanitize_title( $attribute );

if ( empty( $options ) && ! empty( $product ) && ! empty( $attribute ) ) {
    $attributes = $product->get_variation_attributes();
    $options    = $attributes[ $attribute ];
}

if($product->is_type( 'variable' )){
    $user = wp_get_current_user();
    if(in_array('b2bcustomer', $user->roles)){
        foreach ( $product->get_children() as $child_id ) {
            $variation = wc_get_product( $child_id );

            if ( ! $variation || ! $variation->exists() ) {
                continue;
            }

            if(get_post_meta($variation->get_id(), '_wholesale_checkbox', true) === "yes" ){
                $attribute_name = get_post_meta($variation->get_id(), 'attribute_pa_gewicht', true);
                if ( in_array( $attribute_name, $options, true ) ) {
                    $options = array_diff($options, array($attribute_name));
                }

            }

        }
    }
}
    

$html = '<select id="' . esc_attr( $id ) .'1'. '" class name="attribute_pa_gewicht" data-attribute_name="attribute_pa_gewicht" data-show_option_none="yes"> ';

if ( ! empty( $options ) ) {
    if ( $product && taxonomy_exists( $attribute ) ) {

        $terms = wc_get_product_terms( $product->get_id(), $attribute, [
            'fields' => 'all',
        ] );
    $html .='<option value>Choose an option</option>';
        foreach ( $terms as $term ) {
            if ( in_array( $term->slug, $options, true ) ) {
                $html .= '<option value="' .esc_attr( $term->slug) .'" class="attached enabled">' .esc_attr( $term->name) .'</option>';

            }
        }
    }
}

$html .= '</select>';

echo $html;


}

add_filter( 'woocommerce_dropdown_variation_attribute_options_html', 'hide_b2b_variations', 10, 2 );

Also code for showing the new lowest price when hiding variations, or when showing all variations: Note - I'm using "von" for the prefix, change it to "From" or something if needed

function variable_price_format( $price, $product ) {

$prefix = 'von ';

    $user = wp_get_current_user();
    if(in_array('b2bcustomer', $user->roles)){
    $min_price_regular = 1000;
    $min_price_sale = 0;
        foreach ( $product->get_children() as $child_id ) {
            $variation = wc_get_product( $child_id );

            if ( ! $variation || ! $variation->exists() ) {
                continue;
            }

            if(get_post_meta($variation->get_id(), '_wholesale_checkbox', true) === "no" ){
                $attribute_name = get_post_meta($variation->get_id(), 'attribute_pa_gewicht', true);
                    $price_regular = get_post_meta($variation->get_id(), '_regular_price', true);
                    $price_sale = get_post_meta($variation->get_id(), '_sale_price', true);

                if (($price_regular <= $min_price_regular)){
                    $min_price_regular = $price_regular;                
                }
                if (($price_sale > $min_price_sale)){
                 $min_price_sale = $price_sale;
                }
            }
        }

        if ($min_price_regular > $min_price_sale){
            return sprintf('%s%s', $prefix, wc_price($min_price_regular));
        }
        else return sprintf('%s%s', $prefix, wc_price($min_price_sale));
    }
    
    else 
    {
        $min_price_regular = $product->get_variation_regular_price( 'min', true );
        $min_price_sale = $product->get_variation_sale_price( 'min', true );
        $max_price = $product->get_variation_price( 'max', true );
        $min_price = $product->get_variation_price( 'min', true );


        $price = ( $min_price_sale == $min_price_regular ) ?
    
        wc_price( $min_price_regular ) :
        '' . wc_price( $min_price_regular ) . '' . '' . wc_price( $min_price_sale ) . '';
        return ( $min_price == $max_price ) ?
        $price :
        sprintf('%s%s', $prefix, $price);
    }
}

add_filter( 'woocommerce_variable_sale_price_html', 'variable_price_format', 10, 2 );
add_filter( 'woocommerce_variable_price_html', 'variable_price_format', 10, 2 );
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.