Extending the feed for WooCommerce for PureClarity [duplicate] - wordpress

We want to show a section called "complete the look" in WooCommerce. We are using PureClarity to do that.
PureClarity asked us to extend the WooCommerce feed by adding a code snippet in functions.php to add related peoducts SKUs under RelatedProducts.
We used the following code:
function product_callbackk($data, $product) {
$data['RelatedProducts'] = $product->get_sku() ?? null;
return $data;
}
add_filter( 'pureclarity_feed_get_product_data', 'product_callbackk', 10, 2 );
But it showing only the current product SKU and not the related products SKUs. Any advice?

I don't use PureClarity so I added an example based on a default hook in WooCommerce.
In this I use wc_get_related_products() which allow to obtain related products based on the current product ID.
The product SKU per product can then be obtained via a foreach loop.
So you get:
function action_woocommerce_single_product_summary() {
// Get the global product object
global $product;
// Is a WC product
if ( is_a( $product, 'WC_Product' ) ) {
// Initialize
$skus = array();
// Get product ID
$product_id = $product->get_id();
// Get related products based on product category and tags || second argument = limit of results, default = 5
$related_products = wc_get_related_products( $product_id, 10 );
// Loop through
foreach ( $related_products as $related_product ) {
// Get product
$product = wc_get_product( $related_product );
// Get product SKU
$product_sku = $product->get_sku();
// NOT empty
if ( ! empty( $product_sku ) ) {
// Push to array
$skus[] = $product_sku;
}
}
// Output
echo '<pre>', print_r( $skus, 1 ), '</pre>';
}
}
add_action( 'woocommerce_single_product_summary', 'action_woocommerce_single_product_summary', 10 );
Or in your specific case:
/**
* #param mixed[] $data - the array of data that will be sent to PureClarity
* #param WC_Product $product - the WooCommerce product object
* #return mixed
*/
function filter_pureclarity_feed_get_product_data( $data, $product ) {
// Is a WC product
if ( is_a( $product, 'WC_Product' ) ) {
// Initialize
$skus = array();
// Get product ID
$product_id = $product->get_id();
// Get related products based on product category and tags || second argument = limit of results, default = 5
$related_products = wc_get_related_products( $product_id, 10 );
// Loop through
foreach ( $related_products as $related_product ) {
// Get product
$product = wc_get_product( $related_product );
// Get product SKU
$product_sku = $product->get_sku();
// NOT empty
if ( ! empty( $product_sku ) ) {
// Push to array
$skus[] = $product_sku;
}
}
$data['RelatedProducts'] = $skus;
}
return $data;
}
add_filter( 'pureclarity_feed_get_product_data', 'filter_pureclarity_feed_get_product_data', 10, 2 );

Related

Woocommerce restricted cart based on multiple product ID (problem with variations ID product)

I have problem to restrict cart based on multiple product ID, to be exact, with the variables product. I found the code online and try it out. The solutions seem to be okay with simple product.
The only problem is, how to include variations ID in product array? For example, I have two product ID, 1669 and 1694. 1694 is variable products, where it have 4 variations ID; 1769,1770, 1771 and 1772 while 1669 is simple product. When I click 1669(simple product) and add to cart, I cannot add 1694(variables product). I want to make it enable for ID 1694.
However, when i add to cart the variable product first (1694), then the 1669 can be add to cart. below is the code :
function aelia_get_cart_contents() {
$cart_contents = array();
/**
* Load the cart object. This defaults to the persistant cart if null.
*/
$cart = WC()->session->get( 'cart', null );
if ( is_null( $cart ) && ( $saved_cart = get_user_meta( get_current_user_id(), '_woocommerce_persistent_cart_' . get_current_blog_id(), true ) ) ) { // #codingStandardsIgnoreLine
$cart = $saved_cart['cart'];
}
elseif ( is_null( $cart ) ) {
$cart = array();
}
elseif ( is_array( $cart ) && ( $saved_cart = get_user_meta( get_current_user_id(), '_woocommerce_persistent_cart_' . get_current_blog_id(), true ) ) ) { // #codingStandardsIgnoreLine
$cart = array_merge( $saved_cart['cart'], $cart );
}
if ( is_array( $cart ) ) {
foreach ( $cart as $key => $values ) {
$_product = wc_get_product( $values['variation_id'] ? $values['variation_id'] : $values['product_id'] );
if ( ! empty( $_product ) && $_product->exists() && $values['quantity'] > 0 ) {
if ( $_product->is_purchasable() ) {
// Put session data into array. Run through filter so other plugins can load their own session data
$session_data = array_merge( $values, array( 'data' => $_product ) );
$cart_contents[ $key ] = apply_filters( 'woocommerce_get_cart_item_from_session', $session_data, $values, $key );
}
}
}
}
return $cart_contents;
}
// Step 1 - Keep track of cart contents
add_action('wp_loaded', function() {
// If there is no session, then we don't have a cart and we should not take
// any action
if(!is_object(WC()->session)) {
return;
}
global $allowed_cart_items;
global $restricted_cart_items;
$restricted_cart_items = array( 1669,1694) ;
// 1669 is simple product, 1694 is variable product
// "Snoop" into the cart contents, without actually loading the whole cart
foreach(aelia_get_cart_contents() as $item) {
if(in_array($item['data']->get_id(), $restricted_cart_items)) {
$allowed_cart_items[] = $item['data']->get_id();
// If you need to allow MULTIPLE restricted items in the cart, comment
// the line below
break;
}
}
// Step 2 - Make disallowed products "not purchasable"
add_filter('woocommerce_is_purchasable', function($is_purchasable, $product) {
global $restricted_cart_items;
global $allowed_cart_items;
// If any of the restricted products is in the cart, any other must be made
// "not purchasable"
if(!empty($allowed_cart_items)) {
// To allow MULTIPLE products from the restricted ones, use the line below
$is_purchasable = in_array($product->id, $allowed_cart_items) || in_array($product->id, $restricted_cart_items);
// To allow a SINGLE products from the restricted ones, use the line below
// $is_purchasable = in_array($product->get_id(), $allowed_cart_items);
}
return $is_purchasable;
}, 10, 2);
}, 10);
hope you guys can help me. thank you
to make sure those product (simple and variable products) can be add to cart together.

Get related products SKUs in WooCommerce

We want to show a section called "complete the look" in WooCommerce. We are using PureClarity to do that.
PureClarity asked us to extend the WooCommerce feed by adding a code snippet in functions.php to add related peoducts SKUs under RelatedProducts.
We used the following code:
function product_callbackk($data, $product) {
$data['RelatedProducts'] = $product->get_sku() ?? null;
return $data;
}
add_filter( 'pureclarity_feed_get_product_data', 'product_callbackk', 10, 2 );
But it showing only the current product SKU and not the related products SKUs. Any advice?
I don't use PureClarity so I added an example based on a default hook in WooCommerce.
In this I use wc_get_related_products() which allow to obtain related products based on the current product ID.
The product SKU per product can then be obtained via a foreach loop.
So you get:
function action_woocommerce_single_product_summary() {
// Get the global product object
global $product;
// Is a WC product
if ( is_a( $product, 'WC_Product' ) ) {
// Initialize
$skus = array();
// Get product ID
$product_id = $product->get_id();
// Get related products based on product category and tags || second argument = limit of results, default = 5
$related_products = wc_get_related_products( $product_id, 10 );
// Loop through
foreach ( $related_products as $related_product ) {
// Get product
$product = wc_get_product( $related_product );
// Get product SKU
$product_sku = $product->get_sku();
// NOT empty
if ( ! empty( $product_sku ) ) {
// Push to array
$skus[] = $product_sku;
}
}
// Output
echo '<pre>', print_r( $skus, 1 ), '</pre>';
}
}
add_action( 'woocommerce_single_product_summary', 'action_woocommerce_single_product_summary', 10 );
Or in your specific case:
/**
* #param mixed[] $data - the array of data that will be sent to PureClarity
* #param WC_Product $product - the WooCommerce product object
* #return mixed
*/
function filter_pureclarity_feed_get_product_data( $data, $product ) {
// Is a WC product
if ( is_a( $product, 'WC_Product' ) ) {
// Initialize
$skus = array();
// Get product ID
$product_id = $product->get_id();
// Get related products based on product category and tags || second argument = limit of results, default = 5
$related_products = wc_get_related_products( $product_id, 10 );
// Loop through
foreach ( $related_products as $related_product ) {
// Get product
$product = wc_get_product( $related_product );
// Get product SKU
$product_sku = $product->get_sku();
// NOT empty
if ( ! empty( $product_sku ) ) {
// Push to array
$skus[] = $product_sku;
}
}
$data['RelatedProducts'] = $skus;
}
return $data;
}
add_filter( 'pureclarity_feed_get_product_data', 'filter_pureclarity_feed_get_product_data', 10, 2 );

Woocommerce product with custom price based on custom fields [duplicate]

In Woocommerce, I used jQuery to calculate a custom price on a single product pages, and now need to pass this value to the cart.
The desired behavior is to pass the new price retrieved from the hidden field to the cart item price.
Here is my actual code:
// Hidden input field in single product page
add_action( 'woocommerce_before_add_to_cart_button', 'custom_hidden_product_field', 11, 0 );
function custom_hidden_product_field() {
echo '<input type="hidden" id="hidden_field" name="custom_price" class="custom_price" value="">';
}
// The code to pass this data to the cart:
add_action( 'woocommerce_add_cart_item_data', 'save_custom_fields_data_to_cart', 10, 2 );
function save_custom_fields_data_to_cart( $cart_item_data, $product_id ) {
if( ! empty( $_REQUEST['custom_price'] ) ) {
// Set the custom data in the cart item
$cart_item_data['custom_data']['custom_price'] = $_REQUEST['custom_price'];
$data = array( 'custom_price' => $_REQUEST['custom_price'] );
// below statement make sure every add to cart action as unique line item
$cart_item_data['custom_data']['unique_key'] = md5( microtime().rand() );
WC()->session->set( 'custom_data', $data );
}
return $cart_item_data;
}
And check both $data and $cart_item_data to see that they both return the custom_price data that is calculated on the page.
However, I go to view cart, and the value of the line item is still 0.
I set a var equal to the WC()->session->set( 'custom_data', $data ); and then var_dump to check it, but this returns NULL which might just be what it returns, I'm not entirely sure because I've never used it.
I should also add that I have the regular_price in the product backend set to 0. When I erase this (and leave it blank) I get back the error:
Warning: A non-numeric value encountered in
C:\xampp\htdocs\my-transfer-source\wp-content\plugins\woocommerce\includes\class-wc-discounts.php on line 85
I'm wondering if I've missed something here, and if someone could lend some light onto this? Thanks
Update 2021 - Handling custom price item in mini cart
First for testing purpose we add a price in the hidden input field as you don't give the code that calculate the price:
// Add a hidden input field (With a value of 20 for testing purpose)
add_action( 'woocommerce_before_add_to_cart_button', 'custom_hidden_product_field', 11 );
function custom_hidden_product_field() {
echo '<input type="hidden" id="hidden_field" name="custom_price" class="custom_price" value="20">'; // Price is 20 for testing
}
Then you will use the following to change the cart item price (WC_Session is not needed):
// Save custom calculated price as custom cart item data
add_filter( 'woocommerce_add_cart_item_data', 'save_custom_fields_data_to_cart', 10, 2 );
function save_custom_fields_data_to_cart( $cart_item_data, $product_id ) {
if( isset( $_POST['custom_price'] ) && ! empty( $_POST['custom_price'] ) ) {
// Set the custom data in the cart item
$cart_item_data['custom_price'] = (float) sanitize_text_field( $_POST['custom_price'] );
// Make each item as a unique separated cart item
$cart_item_data['unique_key'] = md5( microtime().rand() );
}
return $cart_item_data;
}
// For mini cart
add_action( 'woocommerce_cart_item_price', 'filter_cart_item_price', 10, 2 );
function filter_cart_item_price( $price, $cart_item ) {
if ( isset($cart_item['custom_price']) ) {
$args = array( 'price' => floatval( $cart_item['custom_price'] ) );
if ( WC()->cart->display_prices_including_tax() ) {
$product_price = wc_get_price_including_tax( $cart_item['data'], $args );
} else {
$product_price = wc_get_price_excluding_tax( $cart_item['data'], $args );
}
return wc_price( $product_price );
}
return $price;
}
// Updating cart item price
add_action( 'woocommerce_before_calculate_totals', 'change_cart_item_price', 30, 1 );
function change_cart_item_price( $cart ) {
if ( ( is_admin() && ! defined( 'DOING_AJAX' ) ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
// Set the new price
if( isset($cart_item['custom_price']) ){
$cart_item['data']->set_price($cart_item['custom_price']);
}
}
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.

Auto update product custom field based on WooCommerce product stock

I have an ACF field "DeliverySpeed" attached to Products with the values 'Fast' and 'Slow'
I would like to update this field to change to value 'Slow' every time the product stock is zero or less (product on backorder)
I am still learning PHP so far this is what I got to but I am sure different things are missing, I just don't know in which direction to go:
based on acf update field documentation
function automatically_change_delivery( ) {
global $product;
$fieldkey = "DeliverySpeed";
$valueslow = "Slow";
if($product->get_stock_quantity()<0) { update_field( $field_key, $valueslow, $post_id );
} }
Thank you in advance for the attention and advice.
The following code will update automatically your product custom field once order has reduced product stock levels. So when product has stock the custom field value will be 'Fast' otherwise 'Slow'.
The code:
add_action( 'woocommerce_payment_complete', 'update_product_custom_field_after_reduced_stock_levels', 20, 2 );
add_action( 'woocommerce_order_status_completed', 'update_product_custom_field_after_reduced_stock_levels', 20, 2 );
add_action( 'woocommerce_order_status_processing', 'update_product_custom_field_after_reduced_stock_levels', 20, 2 );
add_action( 'woocommerce_order_status_on-hold', 'update_product_custom_field_after_reduced_stock_levels', 20, 2 );
function update_product_custom_field_( $order_id, $order = '' ) {
// Continue only when order has reduced product stock levels
if ( wc_string_to_bool( get_post_meta( $order_id, '_order_stock_reduced', true ) ) )
return $order_id; // Exit
if( ! $order || ! is_a( $order, 'WC_Order') ) {
$order = wc_get_order( $order_id ); // Get the WC_Order object if it's empty
}
$field_key = 'DeliverySpeed';
// Loop through order items
foreach ( $order->get_items() as $item ) {
$product = $cart_item['data'];
$product_id = $product->get_id();
$stock_qty = $product->get_stock_quantity();
$field_value = get_field( $field_key, $product_id ); // Get ACF field value
if ( $stock_qty <= 0 && $field_value === 'Fast' ) {
update_field( $field_key, 'Slow', $product_id );
}
elseif ( $stock_qty > 0 && $field_value === 'Slow' ) {
update_field( $field_key, 'Fast', $product_id );
}
}
}
Code goes in functions.php file of the active child theme (or active theme). It should works.

Woocommerce product custom price is not accepted by woocommerce coupon

In our woocommerce shop , customer can enter the custom width and height of the product and product price calculated based on this details .
For example if the initial price for a product is 50 . And customer add width =2, height=3 , then the price for this product is going to 50*2*3=300
for this we are using following code
// Save custom field value in cart item as custom data
add_filter( 'woocommerce_add_cart_item', 'calculate_custom_cart_item_prices', 30, 3 );
function calculate_custom_cart_item_prices( $cart_item_data, $product_id, $variation_id ) {
if ( isset($_POST['width']) && isset($_POST['height']) ) {
// Get the correct Id to be used (compatible with product variations)
$the_id = $variation_id > 0 ? $variation_id : $product_id;
$product = wc_get_product( $the_id ); // Get the WC_Product object
$product_price = (float) $product->get_price(); // Get the product price
// Get the posted data
$width = (float) sanitize_text_field( $_POST['width'] );
$height = (float) sanitize_text_field( $_POST['height'] );
$new_price = $width * $height * $product_price; // Calculated price
$cart_item_data['calculated-price'] = $new_price; // Save this price as custom data
}
return $cart_item_data;
}
// Set custom calculated price in cart item price
add_action( 'woocommerce_before_calculate_totals', 'set_calculated_cart_item_price', 20, 1 );
function set_calculated_cart_item_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ){
if( ! empty( $cart_item['calculated-price'] ) ){
// Set the calculated item price (if there is one)
$cart_item['data']->set_price( $cart_item['calculated-price'] );
}
}
And it is wormking , but the problem is:
when customer apply a 50% coupon code for this product then the
discount is coming as 25 , because it calculating based on 50*(50/100)=25;
But actually product new price is 300, so the discount should be
300*(50/100)=150;
Try updating your 'calculate_custom_cart_item_prices' function to something like this and see if that helps.
add_filter( 'woocommerce_add_cart_item', 'calculate_custom_cart_item_prices', 30, 2 );
function calculate_custom_cart_item_prices( $cart_item_data, $cart_item_key ) {
if ( isset($_POST['width']) && isset($_POST['height']) ) {
// Get the correct Id to be used (compatible with product variations)
$the_id = $cart_item_data['variation_id'] > 0 ? $cart_item_data['variation_id'] : $cart_item_data['product_id'];
$product = wc_get_product( $the_id ); // Get the WC_Product object
$product_price = (float) $product->get_price(); // Get the product price
// Get the posted data
$width = (float) sanitize_text_field( $_POST['width'] );
$height = (float) sanitize_text_field( $_POST['height'] );
$new_price = $width * $height * $product_price; // Calculated price
$cart_item_data['calculated-price'] = $new_price; // Save this price as custom data
}
return $cart_item_data;
}
My guess as to what is happening is a change in Woocommerce has changed the way the 'woocommerce_add_cart_item' filter works and so you need to update this function.

Resources