Last active
September 27, 2021 18:24
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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 ) ) ? ' — ' . implode( ', ', $name_output ) : ''; // Add variation(s) if not null. | |
$added_text = sprintf( __( '"%s" 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 ); |
Updated the add to cart message to use the proper attribute name.
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
I should add a way for the options to be removed if the theme is removed, or move it to a plugin.