Skip to content

Instantly share code, notes, and snippets.

@TimBHowe
Last active September 27, 2021 18:24
Show Gist options
  • Save TimBHowe/e5a0b99d0a6f92823ec6 to your computer and use it in GitHub Desktop.
Save TimBHowe/e5a0b99d0a6f92823ec6 to your computer and use it in GitHub Desktop.
Include this in your theme to allow WooCommerce variable products to be displayed in a grid format with each variation having there own quantity and add to cart button, rather then the drop-down options. This should be include in your themes function file.
<?php
/**
* Woocommerce Custom Variation Output
*
* The following function allow for the theme to display product variations in a grid format.
* This code could be moved to a plugin but is in the theme function file as it used the
* themes grid system.
*
* @package WooGrid
* @since WooGrid 1.2
* @reference: http://www.eggplantstudios.ca/woocommerce-product-variation-add-cart-grid/
*/
/**
* Add option to allow the variations to be displayed in a grid or default layout
*
* @since WooGrid 1.0
*/
function variation_grid_advanced_fields() {
global $woocommerce, $post;
echo '<div class="options_group show_if_variable">';
$variation_grid_view = get_post_meta( $post->ID, 'variation_grid_view', true );
woocommerce_wp_checkbox(
array(
'id' => 'variation_grid_view',
'wrapper_class' => 'show_if_variable',
'label' => __( 'Show Variations in Grid' ),
'description' => __( 'Enable' ),
'cbvalue' => true,
)
);
echo '</div>';
}
add_action( 'woocommerce_product_options_general_product_data', 'variation_grid_advanced_fields' );
/**
* Save option if the variation is in grid layout
*
* @param int $post_id the post id of the current product.
*
* @since WooGrid 1.0
*/
function variation_grid_advanced_fields_save( $post_id ) {
// Save checkbox options.
if ( ! empty( $_POST['variation_grid_view'] ) ) { // TODO: add nonce.
update_post_meta( $post_id, 'variation_grid_view', true );
} else {
update_post_meta( $post_id, 'variation_grid_view', false );
}
}
add_action( 'woocommerce_process_product_meta', 'variation_grid_advanced_fields_save' );
/**
* Display in grid format by overwriting woocommerce template
*
* @since WooGrid 1.0
*/
function variation_grid_variable_add_to_cart() {
global $product, $post, $woocommerce;
$variations = find_valid_variations();
$attributes = $product->get_attributes();
// Check if the special 'variation_grid_view' meta is set to false, load the default template.
if ( ! get_post_meta( $post->ID, 'variation_grid_view', true ) ) {
// Enqueue variation scripts.
wp_enqueue_script( 'wc-add-to-cart-variation' );
// Load the template.
wc_get_template( 'single-product/add-to-cart/variable.php', array(
'available_variations' => $product->get_available_variations(),
'attributes' => $product->get_variation_attributes(),
'selected_attributes' => $product->get_variation_default_attributes(),
) );
return;
}
?>
<div class="variations variations-grid clearfix">
<?php // Loop through visible variations.
foreach ( $variations as $key => $value ) :
if ( ! $value['variation_is_visible'] ) { continue;
} ?>
<div itemprop="offers" itemscope itemtype="http://schema.org/Offer" class="clearfix">
<?php // Loop through and print the attribute names.
$name_output = null;
foreach ( $value['attributes'] as $key => $val ) {
$key = str_replace( 'attribute_', '', $key ); // Clean the attribute name.
$attribute = $attributes[ $key ]; // Get the attribute data.
// Check for variation description first.
if ( isset( $value['variation_description'] ) && ! empty( $value['variation_description'] ) ) {
$description = wptexturize( strip_tags( $value['variation_description'] ) );
$name_output[] = '<span class="variation-titles attr var-description">' . $description . '</span>';
break; // Since there is a variation description set we can exit the loop.
} else {
// Check if the attribute is a taxonomy.
if ( $attribute['is_taxonomy'] ) {
// Get the taxonomy name.
$attr_name = get_term_by( 'slug', $val, $key, 'ARRAY_A' );
$attr_name = $attr_name['name'];
} else {
$attr_name = ucwords( $val ); // Clean up the custom attribute name.
}
$name_output[] = '<span class="variation-titles attr attr-' . $key . '">' . $attr_name . '</span>';
}
$i++;
}
?>
<div class="variation-meta">
<?php // Dump the output.
echo implode( '', (array) $name_output );
// Add sku if we have one.
if ( ! empty( $value['sku'] ) ) {
echo '<span class="sku">' . $value['sku'] . '</span>';
}
// Force the price to always print.
if ( empty( $value['price_html'] ) ) {
$price = '<span class="price">' . wc_price( $value['display_price'] ) . '</span>';
} else {
$price = $value['price_html'];
}
// Print the availability message.
// echo $value['availability_html'];
?>
<?php // Make sure there is more than 1 variation.
if ( count( $variations ) > 1 ) : ?>
<span itemprop="price" class="variation-price"><?php echo $price; ?></span>
<?php endif; ?>
<?php
$availability_html = $value['availability_html'];
if ( ! empty( $availability_html ) && $value['backorders_allowed'] ) {
echo apply_filters( 'woocommerce_stock_html', $availability_html );
}
?>
</div>
<?php if ( $value['is_in_stock'] ) : ?>
<form class="cart" action="<?php echo esc_url( $product->add_to_cart_url() ); ?>" method="post" enctype='multipart/form-data'>
<?php if ( ! $product->is_sold_individually() ) : ?>
<?php woocommerce_quantity_input( array( 'input_value' => isset( $_POST['quantity'] ) ? wc_stock_amount( $_POST['quantity'] ) : 1 ) ); ?>
<?php endif; ?>
<?php // Run through the attributes and print them in hidden inputs.
if ( ! empty( $value['attributes'] ) ) {
foreach ( $value['attributes'] as $attr_key => $attr_value ) { ?>
<input type="hidden" name="<?php echo $attr_key?>" value="<?php echo $attr_value?>">
<?php
}
} ?>
<button type="submit" class="single_add_to_cart_button button alt">Add to cart</button>
<input type="hidden" name="variation_id" value="<?php echo $value['variation_id']?>" />
<input type="hidden" name="product_id" value="<?php echo esc_attr( $post->ID ); ?>" />
<input type="hidden" name="add-to-cart" value="<?php echo esc_attr( $post->ID ); ?>" />
</form>
<?php else : // Out of Stock. ?>
<div class="stock-message">
<p class="stock out-of-stock"><?php _e( 'Out of Stock', 'woocommerce' ); ?></p>
</div>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
<?php
}
add_action( 'woocommerce_variable-subscription_add_to_cart', 'variation_grid_variable_add_to_cart' );
remove_action( 'woocommerce_variable-subscription_add_to_cart', array( 'WC_Subscriptions', 'variable_subscription_add_to_cart' ), 30 );
/**
* Collect all the variations of a product and add them in a new array to use for displaying them in the grid
*
* @since WooGrid 1.0
*/
function find_valid_variations() {
global $product;
$variations = $product->get_available_variations();
$attributes = $product->get_attributes();
$new_variants = array();
// Loop through all variations
foreach ( $variations as $variation ) {
// Peruse the attributes.
// 1. If both are explicitly set, this is a valid variation
// 2. If one is not set, that means any, and we must 'create' the rest.
$valid = true; // so far
foreach ( $attributes as $slug => $args ) {
if ( array_key_exists( "attribute_$slug", $variation['attributes'] ) && ! empty( $variation['attributes'][ "attribute_$slug" ] ) ) {
// Exists
} else {
// Not exists, create.
$valid = false; // it contains 'anys'.
// loop through all options for the 'ANY' attribute, and add each.
foreach ( explode( '|', $attributes[ $slug ]['value'] ) as $attribute ) {
$attribute = trim( $attribute );
$new_variant = $variation;
$new_variant['attributes'][ "attribute_$slug" ] = $attribute;
$new_variants[] = $new_variant;
}
}
}
// This contains ALL set attributes, and is itself a 'valid' variation.
if ( $valid ) {
$new_variants[] = $variation;
}
}
return $new_variants;
}
/**
* Custom Add To Cart Messages
*
* @param string $message the message to update.
* @param int $product_id the post id of the current product.
*
* @since WooGrid 1.0
*/
function custom_add_to_cart_message( $message, $product_id ) {
// Collect the variation if is exists.
$variation_id = isset( $_REQUEST['variation_id'] ) ? $_REQUEST['variation_id'] : null;
$name_output = array();
if ( is_array( $product_id ) ) { // Multiple item added to cart - Grouped Product.
$titles = array();
foreach ( $product_id as $id ) {
$titles[] = get_the_title( $id );
}
$added_text = sprintf( __( 'Added %s to your cart.', 'woocommerce' ), wc_format_list_of_items( $titles ) );
} else { // One item added to cart.
// Add variation name to the product title.
$added_text = '';
if ( ! empty( $variation_id ) ) {
// Check for variation description first and use that if available.
$description = get_post_meta( $variation_id, '_variation_description', true );
if ( ! empty( $description ) ) {
if ( ! in_array( $attr_name, $name_output ) ) {
$name_output[] = strip_tags( $description );
}
} else {
// Collect the product, product variations and attributes.
$var_product = get_product( $variation_id );
$variations = $var_product->get_variation_attributes();
$attributes = $var_product->get_attributes();
if ( is_array( $variations ) ) {
foreach ( $variations as $key => $value ) {
$key = str_replace( 'attribute_', '', $key ); // Clean the attribute name.
$attribute = $attributes[ $key ]; // Get the attribute data.
// Check if the attribute is a taxonomy.
if ( $attribute['is_taxonomy'] ) {
// Get the taxonomy name.
$attr_name = get_term_by( 'slug', $value, $key, 'ARRAY_A' );
$attr_name = $attr_name['name'];
} else {
$attr_name = ucwords( $value ); // Clean up the custom attribute name.
}
if ( ! in_array( $attr_name, $name_output ) ) {
$name_output[] = $attr_name; // Load them into an array to be imploded.
}
}
}
}
}
$product_title = get_the_title( $product_id ); // Get the main product title.
$product_title .= ( ! empty( $name_output ) ) ? ' &mdash; ' . implode( ', ', $name_output ) : ''; // Add variation(s) if not null.
$added_text = sprintf( __( '&quot;%s&quot; was successfully added to your cart.', 'woocommerce' ), $product_title );
}
// Output success messages.
if ( get_option( 'woocommerce_cart_redirect_after_add' ) == 'yes' ) :
$return_to = apply_filters( 'woocommerce_continue_shopping_redirect', wp_get_referer() ? wp_get_referer() : home_url() );
$message = sprintf( '<a href="%s" class="button wc-forward">%s</a> %s', $return_to, __( 'Continue Shopping', 'woocommerce' ), $added_text );
else :
$message = sprintf( '<a href="%s" class="button wc-forward">%s</a> %s', wc_get_page_permalink( 'cart' ), __( 'View Cart', 'woocommerce' ), $added_text );
endif;
return $message;
}
add_filter( 'wc_add_to_cart_message', 'custom_add_to_cart_message', 10, 2 );
@johnnny-bravoo
Copy link

Many thanks @TimBHowe . Is there any way to add all(bulk) variations at once to the cart. Something like this http://www.eggplantstudios.ca/eggplant/wp-content/uploads/2015/02/Woocommerce-variations-layout-4.jpg

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment