I'm trying to add product category to the email notification. The custom fields (Time and Date) work but the product category is displaying as an "Array".
function render_product_description($item_id, $item, $order){
$_product = $order->get_product_from_item( $item );
echo "<br>" . $_product->post->post_content;
echo "<br>";
echo '<p><strong>Time:</strong><br />';
echo get_post_meta($_product->id, 'time', true) .'</p>';
echo '<p><strong>Category:</strong><br />';
echo wp_get_post_terms($_product->id, 'product_cat', true) .'</p>';
echo '<p><strong>Date:</strong><br />';
echo get_post_meta($_product->id, 'date', true) .'</p>';
}
add_action('woocommerce_order_item_meta_end', 'render_product_description',10,3);
You can use implode() function that join array values in a string.
I also added an extra check for empty values
function render_product_description( $item_id, $item, $order, $plain_text ) {
// Get product id
$product_id = $item->get_product_id();
// Get product
$product = $item->get_product();
// Product content
$product_content = $product->post->post_content;
// NOT empty
if ( ! empty ( $product_content ) ) {
echo '<p>' . $product_content . '</p>';
}
// Get post meta
$time = get_post_meta( $product_id, 'time', true );
// NOT empty
if ( ! empty ( $time ) ) {
echo '<p><strong>Date:</strong><br />' . $time . '</p>';
}
// Get terms
$term_names = wp_get_post_terms( $product_id, 'product_cat', ['fields' => 'names'] );
// NOT empty
if ( ! empty ( $term_names ) ) {
echo '<p><strong>Categories:</strong><br />' . implode( ", ", $term_names ) . '</p>';
}
// Get post meta
$date = get_post_meta( $product_id, 'date', true );
// NOT empty
if ( ! empty ( $date ) ) {
echo '<p><strong>Date:</strong><br />' . $date . '</p>';
}
}
add_action( 'woocommerce_order_item_meta_end', 'render_product_description', 10, 4 );
Related
I'm looking to add the attribute data of simple products in the infobox (cart/checkout/email). I am currently doing this with the following code:
function sm_woo_cart_attributes($cart_item, $cart_item_key){
$item_data = $cart_item_key['data'];
$attributes = $item_data->get_attributes();
if ( ! $attributes ) {
return $cart_item;
}
$out = $cart_item . '<br />';
foreach ( $attributes as $attribute ) {
if ( $attribute['is_taxonomy'] ) {
// skip variations
if ( $attribute['is_variation'] ) {
continue;
}
// backwards compatibility for attributes which are registered as taxonomies
$product_id = $item_data->id;
$terms = wp_get_post_terms( $product_id, $attribute['name'], 'all' );
// get the taxonomy
$tax = $terms[0]->taxonomy;
// get the tax object
$tax_object = get_taxonomy($tax);
// get tax label
if ( isset ($tax_object->labels->name) ) {
$tax_label = $tax_object->labels->name;
} elseif ( isset( $tax_object->label ) ) {
$tax_label = $tax_object->label;
}
foreach ( $terms as $term ) {
$out .= $tax_label . ': ';
$out .= $term->name . '<br />';
}
} else {
// not a taxonomy
$out .= $attribute['name'] . ': ';
$out .= $attribute['value'] . '<br />';
}
}
echo $out;
}
add_filter( 'woocommerce_cart_item_name', 'sm_woo_cart_attributes', 10, 2 );
This lists all of the attribute data, but above the product, shown in this screenshot. Is there any way to move the attribute data under the product image?
What I'm trying to accomplish is adding term meta from a custom taxonomy that is attached to a product and display it on the cart/checkout/ order details/email notification. I'm not the greatest at this but know enough to get by.
What I'm using is the 'Perfect Brands WooCommerce' plugin that adds in the "pwb-brand". I've also added in my own terms so we can show ETA leads times based on the brand. What I'm trying to have show up is like the following:
/**
* Add ETA for builder for
* Better user experience
*/
public function product_eta($eta) {
global $product;
$brands = wp_get_object_terms($product->get_id(), 'pwb-brand');
ob_start();
?>
<?php
if ( is_product() ) {
foreach ($brands as $brand) :
?>
<?php
$brand_eta_txt = get_option('wc_pwb_admin_tab_brand_single_product_eta_txt');
$eta_start = get_term_meta($brand->term_id, 'pwb_brand_eta_start', true);
$eta_end = get_term_meta($brand->term_id, 'pwb_brand_eta_end', true);
$eta_txt = get_term_meta($brand->term_id, 'pwb_brand_eta_txt', true);
?>
<div id="pwb-eta-content">
<?php
echo '<span class="avail"><strong>Availability: </strong> Estimated '.$eta_start.'-'.$eta_end.' weeks (' . date('m/d', strtotime('+'.$eta_start.' weeks')). '-' . date('m/d', strtotime('+'.$eta_end.' weeks')) . ')');
?>
</div>
<?php
endforeach;
}
?>
<?php
echo ob_get_clean();
return $eta;
}
This is a stripped down version of what we display on our product pages (https://25e62027b7.nxcli.net/shop/dining/extend-a-bench/brooklyn-extend-a-bench/). I'm trying to add the availability time that I added to the pwb-brand to each product item. I have the following in our functions.php at the moment:
add_filter( 'woocommerce_cart_item_name', function( $link_text, $cart_item, $cart_item_key ) {
$_product = $cart_item['data'];
$brands = implode(', ', wp_get_post_terms( $_product->get_id(), 'pwb-brand', ['fields' => 'names'] ) );
$link_text = '<div>' . __( 'Brand', 'perfect-woocommerce-brands' ) . ': ' . $brands . '</div>';
$product_permalink = apply_filters( 'woocommerce_cart_item_permalink', $_product->is_visible() ? $_product->get_permalink( $cart_item ) : '', $cart_item, $cart_item_key );
if ( ! $product_permalink ) {
$link_text .= $_product->get_name();
} else {
$link_text .= sprintf( '%s', esc_url( $product_permalink ), $_product->get_name() );
}
return $link_text;
}, 10, 3 );
// Display order items product brands (Orders on front end and emails)
add_action( 'woocommerce_order_item_meta_end', 'display_custom_data_in_emails', 10, 4 );
function display_custom_data_in_emails( $item_id, $item, $order, $bool ) {
// Get the product brands for this item
$terms = wp_get_post_terms( $item->get_product_id(), 'pwb-brand', array( 'fields' => 'names' ) );
// Output a coma separated string of product brand names
echo "<br><small>" . implode(', ', $terms) . "</small>";
}
// Display order items product brands in admin order edit pages
add_action( 'woocommerce_after_order_itemmeta', 'custom_admin_order_itemmeta', 15, 3 );
function custom_admin_order_itemmeta( $item_id, $item, $product ){
//if( ! is_admin() ) return; // only backend
// Target order "line items" only to avoid errors
if( $item->is_type( 'line_item' ) ){
// Get the product brands for this item
$terms = wp_get_post_terms( $item->get_product_id(), 'pwb-brand', array( 'fields' => 'names' ) );
// Output a coma separated string of product brands names
echo "<br><small>" . implode(', ', $terms) . "</small>";
}
}
I found these snippets while trying to figure this out and it's close to what I'm after however since it uses the "wp_get_post_terms" to pull I can not get anything past the name or id. Is there a way to pull the term meta from the 'pwb-brand' and have it displayed for each cart item in the cart/checkout/order details/email notification?
Try this for cart
add_filter( 'woocommerce_cart_item_name', function( $link_text, $cart_item, $cart_item_key ) {
$brands = wp_get_object_terms($cart_item['product_id'], 'pwb-brand');
$term_id = $terms[0]->term_id;
$eta_start = get_term_meta($term_id, 'pwb_brand_eta_start', true);
$eta_end = get_term_meta($term_id, 'pwb_brand_eta_end', true);
$eta_txt = get_term_meta($term_id, 'pwb_brand_eta_txt', true);
if ( $eta_start != "" ){
$link_text .= ' <br><span class="avail"><strong>Availability: </strong> Estimated '.$eta_start.'-'.$eta_end.' weeks (' . date('m/d', strtotime('+'.$eta_start.' weeks')). '-' . date('m/d', strtotime('+'.$eta_end.' weeks')) . ')';
}
return $link_text;
}, 10, 3 );
And this for email
add_action( 'woocommerce_order_item_meta_end', 'display_custom_data_in_emails', 10, 4 );
function display_custom_data_in_emails( $item_id, $item, $order, $bool ) {
// Get the product brands for this item
$terms = wp_get_post_terms( $item->get_product_id(), 'pwb-brand', array( 'fields' => 'names' ) );
$brands = wp_get_object_terms($cart_item['product_id'], 'pwb-brand');
$term_id = $terms[0]->term_id;
$eta_start = get_term_meta($term_id, 'pwb_brand_eta_start', true);
$eta_end = get_term_meta($term_id, 'pwb_brand_eta_end', true);
$eta_txt = get_term_meta($term_id, 'pwb_brand_eta_txt', true);
if ( $eta_start != "" ){
echo ' <br><span class="avail"><strong>Availability: </strong> Estimated '.$eta_start.'-'.$eta_end.' weeks (' . date('m/d', strtotime('+'.$eta_start.' weeks')). '-' . date('m/d', strtotime('+'.$eta_end.' weeks')) . ')';
}
}
Based on Get product custom attributes to display them in WooCommerce product loop answer code.
I am displaying specific product attributes on the single product page with this:
add_action('woocommerce_single_product_summary', 'display_custom_attributes', 36 );
function display_custom_attributes() {
global $product;
$attributes_names = array('Brand', 'Color', 'Size');
$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 '<h4>Details</h4><ul><li>' . implode( '</li><li>', $attributes_data ) . '</ul>';
}
Now I also need to add two custom meta fields ('Serial_Number' and 'MPN') to this list.
How can I add these?
To add two custom meta fields:
Serial_Number
MPN
to this list, you can use:
function action_woocommerce_single_product_summary() {
global $product;
$attributes_names = array( 'Brand', 'Color', 'Size' );
$attributes_data = array();
foreach ( $attributes_names as $attribute_name ) {
if ( $value = $product->get_attribute($attribute_name) ) {
$attributes_data[] = $attribute_name . ': ' . $value;
}
}
// NOT empty
if ( ! empty($attributes_data) ) {
echo '<h4>' . __( 'Details', 'woocommerce' ) . '</h4><ul><li>' . implode( '</li><li>', $attributes_data );
}
// Get meta
$sn = $product->get_meta( 'Serial_Number' );
$mpn = $product->get_meta( 'MPN' );
// NOT empty
if ( ! empty ( $sn ) ) {
echo '<li>' . __( 'My label 1: ', 'woocommerce' ) . $sn . '</li>';
}
// NOT empty
if ( ! empty ( $mpn ) ) {
echo '<li>' . __( 'My label 2: ', 'woocommerce' ) . $mpn . '</li>';
}
echo '</ul>';
}
add_action( 'woocommerce_single_product_summary', 'action_woocommerce_single_product_summary', 36, 0 );
Add this code on the function.php theme file
function call_product_meta_data()
{
global $post;
if ($post) {
$post_meta_value = get_post_meta($post->ID, 'post_meta_key', true);
if ($post_meta_value != null) {
echo "<div class='pr-meta'><p><strong>Meta Title</strong>: $post_meta_value</p></div>";
} else {
echo "<div class='pr-meta'><p><strong>Meta Title</strong>: N/A</p></div>";
}
}
}
add_action('woocommerce_single_variation', 'call_product_meta_data');
This code shows how to display custom product attributes for without variations. I wish to display all the variations too in the typical dropdown select menu. How do I do that?
P/S: I can't post the code here because this site says I have too much code and too little details.
UPDATED:
/**
* Show all product attributes on the product page
*/
function isa_woocommerce_all_pa(){
global $product;
$attributes = $product->get_attributes();
if ( ! $attributes ) {
return;
}
$out = '';
foreach ( $attributes as $attribute ) {
// skip variations
if ( $attribute->get_variation() ) {
continue;
}
$name = $attribute->get_name();
if ( $attribute->is_taxonomy() ) {
$terms = wp_get_post_terms( $product->get_id(), $name, 'all' );
// get the taxonomy
$tax = $terms[0]->taxonomy;
// get the tax object
$tax_object = get_taxonomy($tax);
// get tax label
if ( isset ($tax_object->labels->singular_name) ) {
$tax_label = $tax_object->labels->singular_name;
} elseif ( isset( $tax_object->label ) ) {
$tax_label = $tax_object->label;
// Trim label prefix since WC 3.0
if ( 0 === strpos( $tax_label, 'Product ' ) ) {
$tax_label = substr( $tax_label, 8 );
}
}
$out .= $tax_label . ': ';
$tax_terms = array();
foreach ( $terms as $term ) {
$single_term = esc_html( $term->name );
array_push( $tax_terms, $single_term );
}
$out .= implode(', ', $tax_terms) . '<br />';
} else {
$out .= $name . ': ';
$out .= esc_html( implode( ', ', $attribute->get_options() ) ) . '<br />';
}
}
echo $out;
}
add_action('woocommerce_single_product_summary', 'isa_woocommerce_all_pa', 25);
I want to make some modification of my site, but for some reason, can get it. i tryed to use this function that found into this thread of Stack :
add_filter( 'woocommerce_variation_option_name',
'customizing_variations_terms_name', 10, 1 );
function customizing_variations_terms_name( $term_name ){
if(is_admin())
return $term_name;
global $product;
$second_loop_stoped = false;
// Get available product variations
$product_variations = $product->get_available_variations();
// Iterating through each available product variation
foreach($product_variations as $variation){
$variation_id = $variation['variation_id'];
$variation_obj = new WC_Product_Variation( $variation_id );
## WOOCOMMERCE RETRO COMPATIBILITY ##
if ( version_compare( WC_VERSION, '3.0', '<' ) ) # BEFORE Version 3 (older)
{
$stock_status = $variation_obj->stock_status;
$stock_qty = intval($variation_obj->stock);
// The attributes WC slug key and slug value for this variation
$attributes_arr = $variation_obj->get_variation_attributes();
}
else # For newest verions: 3.0+ (and Up)
{
$stock_status = $variation_obj->get_stock_status();
$stock_qty = $variation_obj->get_stock_quantity();
// The attributes taxonomy key and slug value for this variation
$attributes_arr = $variation_obj->get_attributes();
}
if(count($attributes_arr) != 1) // Works only for 1 attribute set in the product
return $term_name;
// Get the terms for this attribute
foreach( $attributes_arr as $attr_key => $term_slug){
// Get the attribute taxonomy
$term_key = str_replace('attribute_', '', $attr_key );
// get the corresponding term object
$term_obj = get_term_by( 'slug', $term_slug, $term_key );
if( $term_obj->name == $term_name ){ // If the term name matches we stop the loops
$second_loop_stoped = true;
break;
}
}
if($second_loop_stoped)
break;
}
if( $stock_qty>0 )
return $term_name .= ' - ' . $stock_status . ' ('.$stock_qty.')';
else
return $term_name .= ' - ' . $stock_status;
}
but for some reason when insert into functions, show me "outofstock" next to every variation. I dont use standard Woocommerce dropdown variation style, and use WC Variations Radio Buttons to show radio buttons next to each variation, instead of dropdown. The problem is that i want to show only "Out Of Stock" , next to each variation. not "In Stock", so customer will know that wanted variation is not in stock before press Add to Cart button. SO seems that issue is this code:
if( $stock_qty>0 )
return $term_name .= ' - ' . $stock_status . ' ('.$stock_qty.')';
else
return $term_name .= ' - ' . $stock_status;
}
function looks like return
return $term_name .= ' - ' . $stock_status;
all the time. Any help ? Preview from my issue can be seen here. Thanks.
EDIT: This is the code from variable.php Radio Button Plugin where print variations as radio buttons:
<td class="value">
<?php
if ( ! empty( $options ) ) {
if ( taxonomy_exists( $name ) ) {
// Get terms if this is a taxonomy - ordered. We need the names too.
$terms = wc_get_product_terms( $product->get_id(), $name, array( 'fields' => 'all' ) );
foreach ( $terms as $term ) {
if ( ! in_array( $term->slug, $options ) ) {
continue;
}
print_attribute_radio( $checked_value, $term->slug, $term->name, $sanitized_name );
}
} else {
foreach ( $options as $option ) {
print_attribute_radio( $checked_value, $option, $option, $sanitized_name );
}
}
}
echo end( $attribute_keys ) === $name ?
apply_filters( 'woocommerce_reset_variations_link', '<a
class="reset_variations" href="#">' . __( 'Clear', 'woocommerce' ) . '</a>'
) : '';
?>
</td>
Maybe need to update something there to show properly?
do this instead
if( $stock_qty>0 )
//return $term_name .= ' - ' . $stock_status . ' ('.$stock_qty.')';
return $term_name;
else
//return $term_name .= ' - ' . $stock_status;
return $term_name .= ' - Out Of Stock';