Woocommerce add attribute value names as class - php

I'm trying to set the attribute value names of a product attribute as classname for each <span> item.
So I can set eg material as product attribute. And then attach values like stone, paper etc.
How can I set stone and paper as a classname? Normally values are printed like -> Material: stone, paper. I want to set a classname so I can change stone and paper to a small image.
So in woocommerce/single-product/add-to-cart/simple.php I have added this:
<?php
if ( $attribute['is_taxonomy'] ) {
$values = wc_get_product_terms( $product->id, $attribute['name'], array( 'fields' => 'names' ) );
///////////////this is added//////////////////////////
if($attribute['name'] == 'pa_material'){ // I only want to set a classname if attribute name == material
foreach($values as $value){
$value_classname = $value; // how can I get the value name??
}
echo apply_filters( 'woocommerce_attribute', wpautop( wptexturize('<span class="lbl ' . $value_classname . '">'. implode( '</span><span class="lbl ' . $value . '">', $values ).'</span>' ) ), $attribute, $values );
////////////////////////////////////////////
} else{
echo apply_filters( 'woocommerce_attribute', wpautop( wptexturize( implode( ', ', $values ) ) ), $attribute, $values );
}
} else {
// Convert pipes to commas and display values
$values = array_map( 'trim', explode( WC_DELIMITER, $attribute['value'] ) );
echo apply_filters( 'woocommerce_attribute', wpautop( wptexturize( implode( ', ', $values ) ) ), $attribute, $values );
}
?>
Right now the classname returns blank obviously.

To get the attribute values assigned to the product for just the material attribute:
global $product;
//this will get the names
$values = wc_get_product_terms($product->id, 'pa_material', array( 'fields' => 'names' ) );

Related

Displaying Woocommerce attribute value description instead of value name

I have this code to display product attributes
add_action('woocommerce_single_product_summary', 'attributes', 30 );
function attributes() {
global $product;
$attributes_names = array('Size', 'Color', 'Material', 'Pieces');
$attributes_data = array();
foreach ( $attributes_names as $attribute_name ) {
if ( $value = $product->get_attribute($attribute_name) ) {
$attributes_data[] = $attribute_name . ': ' . $value;
}
}
if ( ! empty($attributes_data) ) {
echo '<div><p>' . implode( '</p>', $attributes_data ) . '</div>';
}
}
Instead of displaying the attribute's value, I want to display their description, so something like
$attributes_data[] = $attribute_name . ': ' . $term_description;
How can this be done?
You can use wc_get_product_terms to retrieve the terms for a product (including its attributes). The parameters of the function are the product ID, the taxonomy and the query args.
For example, you could do something like this:
function attributes() {
global $product;
$attributes_names = array( 'Size', 'Color', 'Material', 'Pieces' );
$attributes_data = array();
foreach ( $product->get_attributes() as $attribute => $value ) {
$attribute_name = wc_get_attribute( $value->get_id() )->name;
if ( ! in_array( $attribute_name, $attributes_names, true ) ) {
continue;
}
$values = wc_get_product_terms( $product->get_id(), $attribute, array( 'fields' => 'all' ) );
if ( $values ) {
$attribute_descriptions = array();
foreach ( $values as $term ) {
$attribute_descriptions[] = term_description( $term->term_id, $term->taxonomy );
}
$attributes_data[] = $attribute_name . ': ' . implode( ',', $attribute_descriptions );
}
}
if ( ! empty( $attributes_data ) ) {
echo '<div><p>' . implode( '</p>', $attributes_data ) . '</div>';
}
}
To note that the attribute description includes any HTML tags, line breaks, etc. That's why in my example above I stripped those, but of course it might not be necessary.

Get WooCommerce specific product attribute terms sorted by "menu order"

I want to sort get_the_terms by menu_order of the curent product and till now i have this code:
$colors='';
$terms = get_the_terms( get_the_ID(), 'pa_colors' );
foreach ( $terms as $term ) {
$colors='<pre>'.$term->name.'</pre>';
}
echo $colors;
There is 2 ways to get the product attribute term names sorted by menu order (for a defined product):
1). Using wp_get_post_terms() function (WordPress way)
The WordPress function get_the_terms() doesn't allow to alter the WP_Term_Query…
So instead you will use similar wp_get_post_terms() that allows WP_Term_Query tuning.
$taxonomy = 'pa_color'; // The taxonomy
$query_args = array(
'fields' => 'names',
'orderby' => 'meta_value_num',
'meta_query' => array( array(
'key' => 'order_' . $taxonomy,
'type' => 'NUMERIC'
) )
);
$term_names = wp_get_post_terms( get_the_ID(), $taxonomy, $query_args );
if ( ! empty( $term_names ) ) {
// Output
echo '<pre>' . implode( '</pre><pre>', $term_names ) . '</pre>';
}
2). Simply using WC_Product method get_attribute() (WooCommerce way)
$product = wc_get_product( get_the_ID() ); // The WC_product Object
$taxonomy = 'pa_color'; // The taxonomy
$names_string = $product->get_attribute('color');
if ( ! empty( $names_string ) ) {
$names_array = explode( ', ', $names_string ); // Converting the string to an array of term names
// Output
echo '<pre>' . implode( '</pre><pre>', $names_array ) . '</pre>';
}
Both ways work.

Woocommerce print simple product attributes on cart and checkout, like variable attributes

I want to show attibutes from a simple product, in cart and checkout. Just like variable products does, but there is only one attibute. See image below:
Is this possible to achive with PHP?
I was thinking about something like using echo $product->get_attributes()
Add the follows code snippets to achieve your above task -
function modify_woocommerce_get_item_data( $item_data, $cart_item ) {
if( $item_data || $cart_item['data']->is_type( 'variation' ) ) return $item_data;
if ( $cart_item['data']->is_type( 'simple' ) ) {
$attributes = array_filter( $cart_item['data']->get_attributes(), 'wc_attributes_array_filter_visible' );
foreach ( $attributes as $attribute ) {
$values = array();
if ( $attribute->is_taxonomy() ) {
$attribute_taxonomy = $attribute->get_taxonomy_object();
$attribute_values = wc_get_product_terms( $cart_item['data']->get_id(), $attribute->get_name(), array( 'fields' => 'all' ) );
foreach ( $attribute_values as $attribute_value ) {
$value_name = esc_html( $attribute_value->name );
if ( $attribute_taxonomy->attribute_public ) {
$values[] = '' . $value_name . '';
} else {
$values[] = $value_name;
}
}
} else {
$values = $attribute->get_options();
foreach ( $values as &$value ) {
$value = make_clickable( esc_html( $value ) );
}
}
$item_data[] = array(
'key' => wc_attribute_label( $attribute->get_name() ),
'value' => apply_filters( 'woocommerce_attribute', wpautop( wptexturize( implode( ', ', $values ) ) ), $attribute, $values ),
);
}
}
return $item_data;
}
add_filter( 'woocommerce_get_item_data', 'modify_woocommerce_get_item_data', 99, 2 );
Codes goes to your active theme's functions.php
Yes you can. Please try adding a filter as bellow,
add_filter('woocommerce_cart_item_name', function($name, $cart_item) {
//has attributes
if ($cart_item['data']->is_type( 'simple' ) && $attributes = $cart_item['data']->get_attributes()) {
$name .= " - ";
foreach ($attributes as $att)
$name .= $att->get_name() . " : " . implode(',', $att->get_options());
}
return $name;
}, 10, 2);

Woocommerce - Display more attributes on the cart

I have Woocommerce and Woocommerce Bookings. I want to add some more info on the cart, after a user added it there.
At the moment, I have the starting date of the booking and the duration, with a label.
<dl class="variation">
<dt class="variation-Booking"><font><font class="">Booking Date:</font></font></dt>
<dd class="variation-Booking"><p><font><font class="">August 11, 2015</font></font></p></dd>
<dt class="variation-Duration"><font><font>Duration:</font></font></dt>
<dd class="variation-Duration"><p><font><font>4 days</font></font></p></dd>
</dl>
I try to find where this code is created on the PHP files of Woocommerce, so I can either add more attributes that are available on the database (like ending date and SKU for example) and also change the HTML output.
In the cart.php file, there is this part of the code:
// Meta data
echo WC()->cart->get_item_data( $cart_item );
Then on class-wc-cart.php the above function:
public function get_item_data( $cart_item, $flat = false ) {
$item_data = array();
// Variation data
if ( ! empty( $cart_item['data']->variation_id ) && is_array( $cart_item['variation'] ) ) {
foreach ( $cart_item['variation'] as $name => $value ) {
if ( '' === $value )
continue;
$taxonomy = wc_attribute_taxonomy_name( str_replace( 'attribute_pa_', '', urldecode( $name ) ) );
// If this is a term slug, get the term's nice name
if ( taxonomy_exists( $taxonomy ) ) {
$term = get_term_by( 'slug', $value, $taxonomy );
if ( ! is_wp_error( $term ) && $term && $term->name ) {
$value = $term->name;
}
$label = wc_attribute_label( $taxonomy );
// If this is a custom option slug, get the options name
} else {
$value = apply_filters( 'woocommerce_variation_option_name', $value );
$product_attributes = $cart_item['data']->get_attributes();
if ( isset( $product_attributes[ str_replace( 'attribute_', '', $name ) ] ) ) {
$label = wc_attribute_label( $product_attributes[ str_replace( 'attribute_', '', $name ) ]['name'] );
} else {
$label = $name;
}
}
$item_data[] = array(
'key' => $label,
'value' => $value
);
}
}
// Other data - returned as array with name/value values
$other_data = apply_filters( 'woocommerce_get_item_data', array(), $cart_item );
if ( $other_data && is_array( $other_data ) && sizeof( $other_data ) > 0 ) {
foreach ( $other_data as $data ) {
// Set hidden to true to not display meta on cart.
if ( empty( $data['hidden'] ) ) {
$display_value = ! empty( $data['display'] ) ? $data['display'] : $data['value'];
$item_data[] = array(
'key' => $data['name'],
'value' => $display_value
);
}
}
}
// Output flat or in list format
if ( sizeof( $item_data ) > 0 ) {
ob_start();
if ( $flat ) {
foreach ( $item_data as $data ) {
echo esc_html( $data['key'] ) . ': ' . wp_kses_post( $data['value'] ) . "\n";
}
} else {
wc_get_template( 'cart/cart-item-data.php', array( 'item_data' => $item_data ) );
}
return ob_get_clean();
}
return '';
}
And the cart-item-data.php that is called above:
<dl class="variation">
<?php
foreach ( $item_data as $data ) :
$key = sanitize_text_field( $data['key'] );
?>
<dt class="variation-<?php echo sanitize_html_class( $key ); ?>"><?php echo wp_kses_post( $data['key'] ); ?>:</dt>
<dd class="variation-<?php echo sanitize_html_class( $key ); ?>"><?php echo wp_kses_post( wpautop( $data['value'] ) ); ?></dd>
<?php endforeach; ?>
</dl>
However, I am still unaware of how I can change the layout and add specific attributes from the database.
add_filter( 'woocommerce_get_item_data', 'wc_add_address_to_cart', 10, 2 );
function wc_add_address_to_cart( $other_data, $cart_item ) {
$post_data = get_post( $cart_item['product_id'] );
$post_data->post_author;
$vendor_id = $post_data->post_author;
echo '<br>';
$Add = 'Address: ';
$city = 'City: ';
$tel = 'Phone: ';
echo $test;
$user_id = $vendor_id;
// Get all user meta data for $user_id
$meta = get_user_meta( $user_id );
// Filter out empty meta data
$meta = array_filter( array_map( function( $a ) {
return $a[0];
}, $meta ) );
echo $Add;
print_r( $meta ['_vendor_address_1'] );
echo '<br>';
echo $city;
print_r( $meta['_vendor_city'] );
echo '<br>';
echo $tel;
print_r( $meta['_vendor_phone'] );
return $other_data;
}
Add this to the functions.php file in your theme. it will display the Address of each vendor on the products. you can customize it to what ever you want.

Adding conditional div class to Genesis shortcode entry-header

I am desperately trying to find a solution to add a conditional div class to individual categories when using the Genesis shortcode [post_categories] in the entry-header.
I want to apply unique colors to category titles in the entry header for articles on the home page and on individual posts. www.mic.com has this affect. You will notice that articles under the "World" category have the category text one color, while articles under the "News" category have the category text displayed as a different color.
For example, if the category is "Infrastructure", I'd like there to be a class that wraps around the existing entry-categories class.
I want it to look like this:
<div class="infrastructure section"><span class="entry-categories"></span></div>
If the category is "Elections", I'd like it to show:
<div class="elections section"><span class="entry-categories"></span></div>
The code I need to edit to get this effect is listed below.
add_shortcode( 'post_categories', 'genesis_post_categories_shortcode' );
/**
* Produces the category links list.
*
* Supported shortcode attributes are:
* after (output after link, default is empty string),
* before (output before link, default is 'Tagged With: '),
* sep (separator string between tags, default is ', ').
*
* Output passes through 'genesis_post_categories_shortcode' filter before returning.
*
* #since 1.1.0
*
* #param array|string $atts Shortcode attributes. Empty string if no attributes.
* #return string Shortcode output
*/
function genesis_post_categories_shortcode( $atts ) {
$defaults = array(
'sep' => ', ',
'before' => __( 'Filed Under: ', 'genesis' ),
'after' => '',
);
$atts = shortcode_atts( $defaults, $atts, 'post_categories' );
$cats = get_the_category_list( trim( $atts['sep'] ) . ' ' );
if ( genesis_html5() )
$output = sprintf( '<span %s>', genesis_attr( 'entry-categories' ) ) . $atts['before'] . $cats . $atts['after'] . '</span>';
else
$output = '<span class="categories">' . $atts['before'] . $cats . $atts['after'] . '</span>';
return apply_filters( 'genesis_post_categories_shortcode', $output, $atts );
}
I have tried using the get_the_category_list function to conditionally create the class names, but the command is not completing an action. When viewing my site through firebug, the new class shows the command as text.
$cats = get_the_category_list( trim( $atts['sep'] ) . ' ' );
if ( genesis_html5() )
$output = sprintf( '<div class="<?php echo $cats[0]->cat_name; ?> section"><span %s>', genesis_attr( 'entry-categories' ) ) . $atts['before'] . $cats . $atts['after'] . '</span></div>';
Any ideas on how to achieve this affect?
Thanks so much!
Something like this should work ( but only for html5 ):
function custom_terms_shortcode( $atts ) {
$defaults = array(
'after' => '',
'before' => __( 'Filed Under: ', 'genesis' ),
'sep' => ', ',
'taxonomy' => 'category',
);
$atts = shortcode_atts( $defaults, $atts, 'custom_terms' );
$terms = get_the_terms( get_the_ID(), $atts['taxonomy'] );
if ( is_wp_error( $terms ) )
return;
if ( empty( $terms ) )
return;
if ( genesis_html5() ){
$output .= '<span class="entry-terms">';
$output .= $atts['before'];
foreach ($terms as $term) {
$output = '<div class="'. $term->name .'">';
$output .= ''.$term->name.''.$atts['sep'];
$output .= '</div>';
}
$output = substr($output, 0, -2);
$output .= $atts['after'];
$output .= '</span>';
}
return apply_filters( 'genesis_post_terms_shortcode', $output, $terms, $atts );
}

Categories