Add product description to cart items in Woocommerce - php

I'm struggling to find a simple solution to this problem I'm having with One-page-checkout plugin for Woocommerce.
My client would like to add the product description next to the product title in cart items.
Any thoughts on how I can manipulate the code to show the description?
This is what I have actually:
I would think that this plugin would just be hiding the description somewhere but I can't locate it anywhere in the code.

There is 2 ways to do it (making work for products and product variations):
1). With custom function hooked in woocommerce_get_item_data action hook (The best way):
add_filter( 'woocommerce_get_item_data', 'customizing_cart_item_data', 10, 2 );
function customizing_cart_item_data( $cart_data, $cart_item ) {
$description = $cart_item['data']->get_description(); // Get the product description
// For product variations when description is empty
if( $cart_item['variation_id'] > 0 && empty( $description ) ){
// Get the parent variable product object
$parent_product = wc_get_product( $cart_item['product_id'] );
// Get the variable product description
$description = $parent_product->get_description();
}
// If product or variation description exists we display it
if( ! empty( $description ) ){
$cart_data[] = array(
'key' => __( 'Description', 'woocommerce' ),
'value' => $description,
'display' => $description,
);
}
return $cart_data;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
… or …
2). With custom function hooked in woocommerce_cart_item_name filter hook:
WooCommerce: Display also product variation description on cart items

You could try this code in your functions.php located in your root of your theme folder. Not sure if it still works as I'm not active in Wordpress development anymore. [untested]
Updated: this should probably work for WooCommerce 3+
Using woocommerce_cart_item_name hook:
add_filter( 'woocommerce_cart_item_name', 'cart_description', 20, 3);
function cart_description( $name, $cart_item, $cart_item_key ) {
// Get the corresponding WC_Product
$product_item = $cart_item['data'];
if(!empty($product_item)) {
// WC 3+ compatibility
$description = $product_item->get_description();
$result = __( 'Description: ', 'woocommerce' ) . $description;
return $name . '<br>' . $result;
} else
return $name;
}
}

Related

Hide product price and disable add to cart for specific product categories in Woocommerce

I'm looking for the right code that hides the prices for some specific categories in Woocommerce.
I already have the code to hide the prices on de single product page:
add_action( 'wp', 'remove_prices_based_on_category' );
function remove_prices_based_on_category() {
// On product single pages
if ( is_product() ) {
remove_product_price( get_the_ID() );
}
}
function return_custom_price( $price, $instance ) {
$price = '<span style="color:red; font-size:12px;">Call our office <strong>516.695.3110</strong> for prices.</span>';
return $price;
}
add_action( 'woocommerce_before_shop_loop_item', 'remove_product_price', 5, 1 ); // for each product on product listing page/shop page.
function remove_product_price( $product_id ) {
$product_id = get_the_ID();
$hidden_price_category_ids = array( '27419','27421' ); // Add Product Category IDs for which the product price should be hidden.
$product_cat_ids = get_the_terms( $product_id, 'product_cat' ); // Getting all categories for this product.
$cat_ids = wp_list_pluck( $product_cat_ids, 'term_id' ); // Getting all category ids for this product.
$result = array_intersect( $hidden_price_category_ids, $cat_ids ); // Will match hidden price categories with product categories and the cat id in the array.
// If a hidden price category is found
if( !empty($result) ) {
add_filter( 'woocommerce_get_price_html', 'return_custom_price', 10, 2 );
remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart' );
} else {
remove_filter( 'woocommerce_get_price_html', 'return_custom_price', 10, 2 );
add_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
add_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart' );
}
}
How can I do it for WooCommerce archive pages?
Your existing code is complicated, uncompleted and not really convenient. Try the following instead that will work for single product pages and archives pages too (as shop page).
It handles any kind of product, including variable products and their variations.
For defined product categories, it replace the price and disable add to cart button on related products.
The code:
// Custom conditional function that check for specific product categories
function check_for_defined_product_categories( $product_id ) {
// HERE your Product Categories where the product price need to be hidden.
$targeted_terms = array( '27419','27421' ); // Can be term names, slugs or Ids
return has_term( $targeted_terms, 'product_cat', $product_id );
}
// Custom function that replace the price by a text
function product_price_replacement(){
return '<span style="color:red; font-size:12px;">' . sprintf( __( "Call our office %s for prices."), '<strong>516.695.3110</strong>' ) . '</span>';
}
// Replace price by a text (conditionally)
add_filter( 'woocommerce_get_price_html', 'filter_get_price_html_callback', 10, 2 );
function filter_get_price_html_callback( $price, $product ){
if( check_for_defined_product_categories( $product->get_id() ) ) {
$price = product_price_replacement();
}
return $price;
}
// Hide prices and availiability on product variations (conditionally)
add_filter( 'woocommerce_available_variation', 'filter_available_variation_callback', 10, 3 ); // for Variations
function filter_available_variation_callback( $args, $product, $variation ) {
if( check_for_defined_product_categories( $product->get_id() ) ) {
$args['price_html'] = '';
$args['availability_html'] = '';
}
return $args;
}
// Disable add to cart button (conditionally)
add_filter( 'woocommerce_variation_is_purchasable', 'woocommerce_is_purchasable_filter_callback', 10, 2 );
add_filter('woocommerce_is_purchasable', 'woocommerce_is_purchasable_filter_callback', 10, 2 );
function woocommerce_is_purchasable_filter_callback( $purchasable, $product ) {
$product_id = $product->get_parent_id() > 0 ? $product->get_parent_id() : $product->get_id();
if( check_for_defined_product_categories( $product_id ) ) {
$purchasable = false;
}
return $purchasable;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and work.

Display a product custom field value in WooCommerce cart and checkout table

In WooCommerce and I have added a custom field "description" for each product.
I was able to find a way to show both, the label name and the value:
add_filter( 'woocommerce_add_cart_item_data', 'save_days_field', 10, 2 );
function save_days_field( $cart_item_data, $product_id ) {
$special_item = get_post_meta( $product_id , 'description',true );
if(!empty($special_item)) {
$cart_item_data[ 'description' ] = $special_item;
// below statement make sure every add to cart action as unique line item
$cart_item_data['unique_key'] = md5( microtime().rand() );
WC()->session->set( 'description', $special_item );
}
return $cart_item_data;
}
// Render meta on cart and checkout
add_filter( 'woocommerce_get_item_data','rendering_meta_field_on_cart_and_checkout', 10, 2 );
function rendering_meta_field_on_cart_and_checkout( $cart_item_data, $cart_item ) {
if( isset( $cart_item['description'] ) ) {
$cart_item_data[] = array( "name" => __( "Description", "woocommerce" ), "value" => $cart_item['description'] );
}
return $cart_item_data;
}
Now I need to display ONLY the value (not the label name "Description") of this custom field in the cart and checkout table. I need to display with <small>, like the attribute I am displaying with this code:
add_filter('woocommerce_cart_item_name', 'wp_woo_cart_attributes', 10, 2);
function wp_woo_cart_attributes($cart_item, $cart_item_key){
$productId = $cart_item_key['product_id'];
$product = wc_get_product($productId);
$taxonomy = 'pa_color';
$value = $product->get_attribute($taxonomy);
if ($value) {
$label = get_taxonomy($taxonomy)->labels->singular_name;
$cart_item .= "<small>$value</small>";
}
return $cart_item;
}
How can I make it for this custom field, displaying the value only?
You don't need to include a product custom field as custom cart item data, as it's directly accessible from the product object (or the product ID).
Note: On a cart item variable $cart_item, the WC_Product Object is included and available using $cart_item['data'].
Try the following to add a custom field after the item name in cart and checkout pages:
// Display in cart and checkout pages
add_filter( 'woocommerce_cart_item_name', 'customizing_cart_item_name', 10, 3 );
function customizing_cart_item_name( $product_name, $cart_item, $cart_item_key ) {
$product = $cart_item['data']; // Get the WC_Product Object
if ( $value = $product->get_meta('description') ) {
$product_name .= '<small>'.$value.'</small>';
}
return $product_name;
}
To display it on orders and email notifications use:
// Display in orders and email notifications
add_filter( 'woocommerce_order_item_name', 'customizing_order_item_name', 10, 2 );
function customizing_order_item_name( $product_name, $item ) {
$product = $item->get_product(); // Get the WC_Product Object
if ( $value = $product->get_meta('description') ) {
$product_name .= '<small>'.$value.'</small>';
}
return $product_name;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

Editing breadcrumb for product tag archive pages only in Woocommerce

I have found where in WooCommerce (WC) I can edit directly to get my desired result, which is editing the following function: https://github.com/woocommerce/woocommerce/blob/master/includes/class-wc-breadcrumb.php#L222
private function add_crumbs_product_tag() {
$current_term = $GLOBALS['wp_query']->get_queried_object();
$this->prepend_shop_page();
/* translators: %s: product tag */
$this->add_crumb( sprintf( __( 'My Edit: %s', 'woocommerce' ), $current_term->name ), get_term_link( $current_term, 'product_tag' ) );
}
Now I know that it is bad practice to directly edit the WC plugin, so I am looking for an alternative, so that when WC updates, the changes aren't overwritten.
Override Attempt
I have tried to add my edited class to my child theme (mytheme-child/woocommerce/includes/class-wc-breadcrumb.php) but this doesn't seem to work.
What can I do?
Try the following instead using the specific woocommerce_get_breadcrumb filter hook:
add_filter( 'woocommerce_get_breadcrumb', 'custom_product_tag_crumb', 20, 2 );
function custom_product_tag_crumb( $crumbs, $breadcrumb ){
// Targetting product tags
$current_taxonomy = 'product_tag';
$current_term = $GLOBALS['wp_query']->get_queried_object();
$current_key_index = sizeof($crumbs) - 1;
// Only product tags
if( is_a($current_term, 'WP_Term') && term_exists( $current_term->term_id, $current_taxonomy ) ) {
// The label term name
$crumbs[$current_key_index][0] = sprintf( __( 'My Edit: %s', 'woocommerce' ), $current_term->name );
// The term link (not really necessary as we are already on the page)
$crumbs[$current_key_index][1] = get_term_link( $current_term, $current_taxonomy );
}
return $crumbs;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.

woocommerce add to cart button on single product page

On WooCommerce, I would like a custom add to cart button redirection for specific categories to contact us page (when customer click on the add to cart button in single product pages).
This is my code:
add_filter( 'woocommerce_add_to_cart_redirect', 'rv_redirect_to_url' );
function rv_redirect_to_url() {
global $woocommerce, $post;
$product_id = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $_REQUEST['add-to-cart'] ) );
$rv_woo_redirect_url = get_post_meta( $product_id, '_rv_woo_product_custom_redirect_url', true );
if ( ! empty( $rv_woo_redirect_url ) ) {
wp_redirect( esc_url( $rv_woo_redirect_url ) ); exit;
}
}
How can I change my code to get it working only for defined product categories?
Updated (the right custom url when it's a defined product category)
Using a custom function hooked in woocommerce_add_to_cart_redirect filter hook, that will redirect customer when a product is added to cart (for defined product category(ies)):
add_filter( 'woocommerce_add_to_cart_redirect', 'conditional_add_to_cart_redirection', 99, 1 );
function conditional_add_to_cart_redirection( $url ) {
// ==> HERE define your product category or categories in the array
$category = array( 'clothing', 'music' );
if ( ! isset( $_REQUEST['add-to-cart'] ) ) return $url; // Very important!
// When it's available (on add to cart click), get the product ID
$product_id = absint( $_REQUEST['add-to-cart'] );
// Get the custom url from product post meta data
$custom_url = get_post_meta( $product_id, '_rv_woo_product_custom_redirect_url', true );
// Exit to normal, If the custom URL redirection is not set in the product
if( empty( $custom_url ) ) return $url;
// Custom redirection only for your defined product category(ies)
if( has_term( $category, 'product_cat', $product_id ) ){
// Clear add to cart notice (with the cart link).
wc_clear_notices();
$url = $custom_url; // Updated here
}
return $url;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Code is tested on Woocommerce 3+ and works
Add to cart redirection will not work with ajax add to cart on shop and archives pages. So you will have to choose between that 2 options for shop and archives pages:
Disable ajax add-to-cart on shop and archives pages ( WC settings > Products > Display ).
Add the following code to replace the add to cart button, by a button linked to the product:
This 2nd option seems to be the best (as this is conditional on some products only):
// Conditionally changing add to cart button link and text on shop and archives
add_filter( 'woocommerce_loop_add_to_cart_link', 'replacing_add_to_cart_button', 10, 2 );
function replacing_add_to_cart_button( $button, $product ) {
if( $product->is_type( 'variable-subscription' ) || $product->is_type( 'variable' ) ) return $button;
// ==> HERE define your product category or categories in the array
$category = array( 'clothing', 'music' );
// Check that the custom url from product post meta data is not empty
$custom_url = get_post_meta( $post->ID, '_rv_woo_product_custom_redirect_url', true );
if( empty( $custom_url ) ) return $button;
// Check if the current product has a defined product category(ies)
if( ! has_term( $category, 'product_cat', $post->ID ) ) return $button;
$button_text = __( 'View product', 'woocommerce' );
$button = '<a class="button" href="' . $product->get_permalink() . '">' . $button_text . '</a>';
return $button;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Code is tested on Woocommerce 3+ and works
If the product is not meant to be purchased outright, then I would filter woocommerce_is_purchasable and replace the add to cart button with a button-styled link to your contact form.
function so_46395830_not_purchasable( $is_purchasable, $product ) {
$rv_woo_redirect_url = $product->get_meta( '_rv_woo_product_custom_redirect_url', true );
if ( ! empty( $rv_woo_redirect_url ) ) {
add_action( 'woocommerce_single_product_summary', 'so_46395830_redirect_to_contact' );
}
return $is_purchasable;
}
add_filter( 'woocommerce_is_purchasable', 'so_46395830_not_purchasable', 10, 2 );
function so_46395830_redirect_to_contact( $url ) {
global $product;
$rv_woo_redirect_url = $product->get_meta( '_rv_woo_product_custom_redirect_url', true );
echo sprintf( '<a class="button" href="%s">%s</a>', esc_url( $rv_woo_redirect_url ), __( 'Contact Us for Info', 'your-plugin-textdomain' ) );
}

Override External Product URL to "Add to Cart" product button

I work on site that use External products from Amazon, but want instead pointing users to that external URL, first to add to cart that product. I have this function, that change Default Button text for each product, to Add to cart.
function sv_wc_external_product_button( $button_text, $product ) {
if ( 'external' === $product->get_type() ) {
// enter the default text for external products
return $product->button_text ? $product->button_text : 'Add To Cart';
}
return $button_text;
}
add_filter( 'woocommerce_product_single_add_to_cart_text',
'sv_wc_external_product_button', 10, 2 );
But this function not add product to cart.
How to make this function to Add selected product to cart?
Thanks.
Updated 2020
This is a complete different way with simple products and a custom field external link.
In this answer we will use simple products instead of external products.
We add an "External URL" custom field in product option settings and we save the data.
Add a custom field on general product option settings for simple products only :
add_action( 'woocommerce_product_options_general_product_data', 'simple_product_with_external_url' );
function simple_product_with_external_url() {
global $product_object;
echo '<div class="options_group show_if_simple hidden">';
// External Url
woocommerce_wp_text_input( array(
'id' => '_ext_url_cust',
'label' => 'External Url',
'description' => 'Custom external URL',
'desc_tip' => 'true',
'placeholder' => 'Enter here your custom external URL'
) );
echo '</div>';
}
Save the custom field data if it's a simple product and not empty:
add_action( 'woocommerce_admin_process_product_object', 'save_simple_product_with_external_url' );
function save_simple_product_with_external_url( $product ) {
if( $product->is_type('simple') && isset($_POST['_ext_url_cust']) ) {
$product->update_meta_data( '_ext_url_cust', sanitize_url($_POST['_ext_url_cust']) );
}
}
2) This will not work on shop pages and archives pages, if we don't set in WooCommerce the cart redirection when adding a product to cart.
So we will replace add-to-cart button (just for our simple products with a custom link redirection) on shop pages and archives pages by a linked custom button to single product pages.
Replacing add-to-cart button in shop pages and archives pages (for simple products with custom external url):
add_filter( 'woocommerce_loop_add_to_cart_link', 'quantity_inputs_for_woocommerce_loop_add_to_cart_link', 10, 2 );
function quantity_inputs_for_woocommerce_loop_add_to_cart_link( $html, $product ) {
$external_url = $product->get_meta('_ext_url_cust');
if ( ! empty($external_url) ) {
$html = sprintf( '%s', $product->get_permalink(), __("Read More", "woocommerce") );
}
return $html;
}
3) If the custom field value is not empty, the product is added to cart first and then redirected to the external URL (our custom field value in single product pages)
External URL redirection after adding to cart (when custom field is not empty in simple products):
add_filter( 'woocommerce_add_to_cart_redirect', 'redirect_simple_product_with_external_url' );
function redirect_simple_product_with_external_url( $url ) {
if( isset($_REQUEST['add-to-cart']) && absint( $_REQUEST['add-to-cart'] ) > 0 )
return get_post_meta( absint( $_REQUEST['add-to-cart'] ), '_ext_url_cust', true );
return $url;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works on WooCommerce version 3+
Use https://stackoverflow.com/a/44036965/3730754 instead.
You should try to use woocommerce_product_add_to_cart_url filter hook to change the add-to-cart link (here for grouped products), this way:
add_filter( 'woocommerce_product_add_to_cart_url', 'override_external_product_url', 10, 2 );
function override_external_product_url( $url, $product ){
if ( 'external' === $product->get_type() ) {
//Get product ID -- WooCommerce compatibility
if ( method_exists( $product, 'get_id' ) ) {
$product_id = $product->get_id();
} else {
$product_id = $product->id;
}
// custom add to cart url example
$url = home_url( "/product/?add-to-cart=$product_id");
}
return $url;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Update: But this will not add to cart this external product before redirecting to an external url even if it works displaying the add-to-cart url (as add-to-cart is ajax driven).
I fixed myself. For External products, to replace default "Buy This Product" with other generic text, add this functions into functions.php file into theme:
add_filter( 'woocommerce_product_add_to_cart_text' ,
'wpf_custom_add_cart_text_archive',11);
function wpf_custom_add_cart_text_archive() {
global $product;
$product_type = $product->product_type;
switch ( $product_type ) {
case 'external':
return __( 'Add to Cart', 'woocommerce' );
break;
case 'grouped':
return __( 'View products', 'woocommerce' );
break;
case 'simple':
return __( 'Add to cart', 'woocommerce' );
break;
case 'variable':
return __( 'Select options', 'woocommerce' );
break;
default:
return __( 'Read more', 'woocommerce' );
}
}
add_filter( 'woocommerce_product_single_add_to_cart_text',
'wpf_custom_add_cart_text',11);
and this one:
function wpf_custom_add_cart_text() {
return __( 'Add to Cart', 'woocommerce' );
}
to replace text everywhere.

Categories