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 );

1 Answer 1

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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