Display SKU in Woocommerce single product page with OceanWP theme - php

I want to display the SKU field of each product in its signle product page. The woocommerce plugin's settings does not have that option in wordpress.
I already followed the instructions here:
https://wordpress.stackexchange.com/questions/219410/how-to-show-product-sku-on-product-page/219427#219427
I tried adding to my functions.php file this code:
add_action( 'woocommerce_single_product_summary', 'dev_designs_show_sku', 5 );
function dev_designs_show_sku(){
global $product;
echo 'SKU: ' . $product->get_sku();
}
And also tried to add this code to the theme's single product content file:
if ( 'sku' === $element ) {
woocommerce_template_single_sku();
}
file name is owp-single-product.php:
<?php
/**
* Single product template.
*
* #package OceanWP WordPress theme
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
// Get price conditional display state.
$ocean_woo_single_cond = get_theme_mod( 'ocean_woo_single_conditional', false );
// Conditional vars.
$show_woo_single = '';
$show_woo_single = ( is_user_logged_in() && $ocean_woo_single_cond === true );
/**
* Display Single Product template
*
*/
// Get elements.
$elements = oceanwp_woo_summary_elements_positioning();
// Loop through elements.
foreach ( $elements as $element ) {
do_action( 'ocean_before_single_product_' . $element );
// Title.
if ( 'title' === $element ) {
woocommerce_template_single_title();
}
// Sku.
if ( 'sku' === $element ) {
woocommerce_template_single_sku();
}
// Rating.
if ( 'rating' === $element ) {
woocommerce_template_single_rating();
}
// Price.
if ( 'price' === $element ) {
if ( false === $ocean_woo_single_cond || $show_woo_single ) {
woocommerce_template_single_price();
}
}
// Excerpt.
if ( 'excerpt' === $element ) {
woocommerce_template_single_excerpt();
}
// Quantity & Add to cart button.
if ( 'quantity-button' === $element ) {
if ( false === $ocean_woo_single_cond || $show_woo_single ) {
woocommerce_template_single_add_to_cart();
} else {
// Get Add to Cart button message display state.
$ocean_woo_single_msg = get_theme_mod( 'ocean_woo_single_cond_msg', 'yes' );
if ( 'yes' === $ocean_woo_single_msg ) {
// Get Add to Cart button replacement message.
$ocean_woo_single_msg_txt = get_theme_mod( 'ocean_woo_single_cond_msg_text' );
$ocean_woo_single_msg_txt = $ocean_woo_single_msg_txt ? $ocean_woo_single_msg_txt : esc_html__( 'Log in to view price and purchase', 'oceanwp' );
$woo_single_myaccunt_link = get_theme_mod( 'ocean_single_add_myaccount_link', false );
echo '<div class="owp-woo-single-cond-notice">';
if ( false === $woo_single_myaccunt_link ) {
echo '<span>'. $ocean_woo_single_msg_txt .'</span>';
} else {
echo '' . $ocean_woo_single_msg_txt . '';
}
echo '</div>';
}
}
}
// Meta.
if ( 'meta' === $element ) {
woocommerce_template_single_meta();
}
do_action( 'ocean_after_single_product_' . $element );
}
Did not work! What do I do?

You can try this to show the sku after product title
add_action( 'ocean_after_single_product_title', 'show_product_sku', 5 );
function show_product_sku(){
global $product;
echo 'SKU: ' . $product->get_sku();
}

Related

WooCommerce show on-sale badge only for logged in users

I want to display sale bubble in WooCommerce only for logged in users.
I have a function which hides sale-bubble for unlogged users but if I log in there is showing only value "1" instead of sale-bubble.
I know why, because I am returning a true, but I cant figure out how to return sale-bubble instead of true..
WooCommerce
add_filter('woocommerce_sale_flash', 'woo_custom_hide_sales_flash');
function woo_custom_hide_sales_flash()
{
if ( is_user_logged_in() ) {
return true;
}
return false;
}
You are not using this filter hook in the right way. Try the following:
add_filter( 'woocommerce_sale_flash', 'filter_sales_flash_callback', 100, 3 );
function filter_sales_flash_callback( $output_html, $post, $product )
{
if ( ! is_user_logged_in() ) {
$output_html = false;
}
return $output_html;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
function sales_badge() {
global $product;
if ( ! $product->is_on_sale() ) return;
if ( $product->is_type( 'simple' ) ) {
$max_percentage = ( ( $product->get_regular_price() - $product->get_sale_price() ) / $product->get_regular_price() ) * 100;
} elseif ( $product->is_type( 'variable' ) ) {
$max_percentage = 0;
foreach ( $product->get_children() as $child_id ) {
$variation = wc_get_product( $child_id );
$price = $variation->get_regular_price();
$sale = $variation->get_sale_price();
if ( $price != 0 && ! empty( $sale ) ) $percentage = ( $price - $sale ) / $price * 100;
if ( $percentage > $max_percentage ) {
$max_percentage = $percentage;
}
}
}
if ( $max_percentage > 0 ) { ?>
<span class="prinjal-sale-badge"><?php echo round($max_percentage) . "%"; ?></span>
<?php
}
}
// use shortcode instead of action and then use shortcode anywhere you want to ouptut it
add_shortcode( 'custom_sales_badge', 'sales_badge' );
my problem solve using this code you can place any ware you want to display sale badge
function sales_markup() {
if(!is_admin()) {
if(is_user_logged_in()) {
// Instead of outputting add the markup that you want to show
$output = '<div class="Sales_markup_here">
</div>';
return $output;
}
}
}
// use shortcode instead of action and then use shortcode anywhere you want to ouptut it
add_shortcode( 'sales_markup', 'sales_markup' );
Use the shortcode where you want to output the bubble. You can add the css in the global css file.

Update a custom field on "Update Cart" click in WooCommerce Cart

I added a custom <select> field to each product in cart page to be able to update variation, but when I change it's value and click "Update Cart", nothing updates unless quantity field has also been changed.
Is there a way to avoid this?
My code:
functions.php file:
add_filter( 'woocommerce_update_cart_action_cart_updated', 'on_action_cart_updated', 20, 1 );
function on_action_cart_updated( $cart_updated ){
if ($cart_updated) {
$cart_content = WC()->cart->get_cart_contents();
$update_cart = false;
$cart_totals = isset( $_POST['cart'] ) ? wp_unslash( $_POST['cart'] ) : '';
if ( ! empty( $cart_content ) && is_array( $cart_totals ) ) {
foreach ($cart_content as $key => $item) {
$lease_period = $cart_totals[$key]['lease'];
if ( ! empty( $lease_period )) {
$cart_content[$key]['variation']['attribute_pa_lease-period'] = $lease_period;
$update_cart = true;
}
}
if ($update_cart) {
WC()->cart->set_cart_contents($cart_content);
}
}
}
}
cart.php file:
<td class="product-lease-period" data-title="<?php esc_attr_e( 'Lease Period', 'woocommerce' ); ?>">
<div class="product-lease-period-select">
<select name="cart[<?php echo $cart_item_key ?>][lease]">
<?php
$lease_periods = ['6-months'=> '6 Months',
'12-months' => '12 Months',
'18-months' => '18 Months',
'24-months' => '24 Months'];
foreach ($lease_periods as $key => $period) {
$selected = '';
if ($cart_item['variation']['attribute_pa_lease-period'] == $key) {
$selected = 'selected="selected"';
}
echo "<option value=" . $key . " $selected>" . $period . "</option>";
}
?>
</select>
</div>
</td>
My conclusions so far:
I believe it's because of these pieces of code inside the class-wc-form-handler.php :
// Skip product if no updated quantity was posted.
if ( ! isset( $cart_totals[ $cart_item_key ] ) || ! isset( $cart_totals[ $cart_item_key ]['qty'] ) ) {
continue;
}
and a bit below:
if ( '' === $quantity || $quantity === $values['quantity'] ) {
continue;
}
I extended the WC_Form_Handler class in my functions.php file, copied a method I needed and edited it, and gave it higher hook priority in my extended class than it's in the original class:
class WC_Form_Handler_Ext extends WC_Form_Handler {
/**
* Hook in method.
*/
public static function init() {
add_action( 'wp_loaded', array( __CLASS__, 'update_cart_action' ), 30 );
}
/**
* Remove from cart/update.
*/
public static function update_cart_action() {
// method content edited
}
}
WC_Form_Handler_Ext::init();
UPDATE:
To make price change after variation value in cart is updated, this function needs to be added to the functions.php
function find_matching_product_variation_id($product_id, $attributes)
{
return (new WC_Product_Data_Store_CPT())->find_matching_product_variation(
new WC_Product($product_id),
$attributes
);
}
And it should be called from the loop in functions.php I mentioned in my question this way:
$attributes = $cart_content[$key]['variation'];
$variation_id = find_matching_product_variation_id($product_id, $attributes);
$price = get_post_meta($variation_id, '_price', true);
$item['data']->set_price($price);

Conditional function that check if products are already in cart in Woocommerce 3

Hi solution provided here WooCommerce - Check if item's are already in cart working perfect. This is the function code:
function woo_in_cart($arr_product_id) {
global $woocommerce;
$cartarray=array();
foreach($woocommerce->cart->get_cart() as $key => $val ) {
$_product = $val['product_id'];
array_push($cartarray,$_product);
}
if (!empty($cartarray)) {
$result = array_intersect($cartarray,$arr_product_id);
}
if (!empty($result)) {
return true;
} else {
return false;
};
}
Usage
$my_products_ids_array = array(22,23,465);
if (woo_in_cart($my_products_ids_array)) {
echo 'ohh yeah there some of that products in!';
}else {
echo 'no matching products :(';
}
But I need use as if(in_array) but no luck so far. What i doing wrong?
$my_products_ids_array = array("69286", "69287",);
if (in_array("69286", $my_products_ids_array)) {
echo '<p>' . the_field ( 'cart_field', 'option' ) . '</p>';
}
if (in_array("69287", $my_products_ids_array)) {
echo '<p>' . the_field ( 'cart_field-1', 'option' ) . '</p>';
}
Thank you
Your main function code is outdated.
For Advanced custom fields (ACF):
you need to use get_field() (that return the field value) instead of the_field() (that echo the field value).
You may need to add a product ID as 2nd argument in get_field('the_slug', $product_id ).
So try:
function is_in_cart( $ids ) {
// Initialise
$found = false;
// Loop Through cart items
foreach( WC()->cart->get_cart() as $cart_item ) {
// For an array of product IDS
if( is_array($ids) && ( in_array( $cart_item['product_id'], $ids ) || in_array( $cart_item['variation_id'], $ids ) ) ){
$found = true;
break;
}
// For a unique product ID (integer or string value)
elseif( ! is_array($ids) && ( $ids == $cart_item['product_id'] || $ids == $cart_item['variation_id'] ) ){
$found = true;
break;
}
}
return $found;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
The custom conditional function is_in_cart( $ids ) accept a string (a unique product Id) or an array of product Ids.
Your revisited usage (ACF get_field may need a post ID (product ID)):
if ( is_in_cart( "69286" ) ) {
echo '<p>' . get_field ( 'cart_field' ) . '</p>'; // or get_field ( 'cart_field', "69286" )
}
if ( is_in_cart( "69287" ) ) {
echo '<p>' . get_field ( 'cart_field-1' ) . '</p>'; // or get_field ( 'cart_field', "69287" )
}

Remove "Shop" from BreadCrumb in WooCommerce

How to Remove Shop Text from Bread Crumb in woo commerce?[Home-->Shop-->Pink Himalayan Salt]
I want to Set Bread crumb as per my Navigation menu in m WordPress site.[Home-->Products-->Salt-->Pink Himalayan Salt]
I have used some Pages, Custom Links, Categories & Products to My main Menu.
See screenshot.
Bredcrumb -
Menu -
You can override WooCommerce templates via the theme (read the following official documentation):
Template Structure + Overriding Templates via a Theme
Once you have copied the file from plugins/woocommerce/templates/global/breadcrumb.php
to: themes/yourtheme/woocommerce/global/breadcrumb.php, you will be able to change the code by replacing it with the following:
<?php
/**
* Shop breadcrumb
*
* This template can be overridden by copying it to yourtheme/woocommerce/global/breadcrumb.php.
*
* HOWEVER, on occasion WooCommerce will need to update template files and you
* (the theme developer) will need to copy the new files to your theme to
* maintain compatibility. We try to do this as little as possible, but it does
* happen. When this occurs the version of the template file will be bumped and
* the readme will list any important changes.
*
* #see https://docs.woocommerce.com/document/template-structure/
* #author WooThemes
* #package WooCommerce/Templates
* #version 2.3.0
* #see woocommerce_breadcrumb()
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! empty( $breadcrumb ) ) {
$breadcrumb0 = $breadcrumb[0];
$shop_txt = __( 'Shop', 'woocommerce' );
$products_txt = __( 'Products', 'woocommerce' );
$products_url = home_url( '/products/' );
$breadcrumb10 = array( $products_txt );
$breadcrumb11 = array( $products_txt, $products_url );
if(is_product() || is_shop() || is_product_category() || is_product_tag() ){
if( $breadcrumb[1][0] == $shop_txt ){
if( ! empty( $breadcrumb[1][1] ) )
$breadcrumb[1] = $breadcrumb11;
else
$breadcrumb[1] = $breadcrumb10;
} else {
unset($breadcrumb[0]);
array_unshift($breadcrumb, $breadcrumb0, $breadcrumb11);
}
}
echo $wrap_before;
foreach ( $breadcrumb as $key => $crumb ) {
echo $before;
if ( ! empty( $crumb[1] ) && sizeof( $breadcrumb ) !== $key + 1 ) {
echo '' . esc_html( $crumb[0] ) . '';
} else {
echo esc_html( $crumb[0] );
}
echo $after;
if ( sizeof( $breadcrumb ) !== $key + 1 ) {
echo $delimiter;
}
}
echo $wrap_after;
}
This will:
Replace "Shop" by "Products"
Add "Products" just after "Home" when "Shop" doesn't exits.
So your breadcrumps will always start with: Home > Products on shop, archives and single product pages…
This might be solved with CSS, but cannot help unless you post a link to your shop.
Try like this:
Add this line to your custom CSS
ul.breadcrumbs li:nth-of-type(2) {display:none}
If it does not work, might also need !important
ul.breadcrumbs li:nth-of-type(2) {display:none!important}
I cannot comment that is why I had to answer. please provide the link of your site. I'll update my answer with exact CSS.
Inspired by LoicTheAztec, here is a solution for a similar but slightly different requirement. Let's say you just wanted to remove the Shop link completely:
Copy the file: plugins/woocommerce/templates/global/breadcrumb.php
to: themes/yourtheme/woocommerce/global/breadcrumb.php
In the new file, look for the line
foreach ( $breadcrumb as $key => $crumb ) {
and after that line, add this line:
if (trim(strip_tags($crumb[0])) == 'Shop') { continue; }
So the final code will look like this:
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! empty( $breadcrumb ) ) {
echo $wrap_before;
foreach ( $breadcrumb as $key => $crumb ) {
if (trim(strip_tags($crumb[0])) == 'Shop') { continue; }
echo $before;
if ( ! empty( $crumb[1] ) && sizeof( $breadcrumb ) !== $key + 1 ) {
echo '' . esc_html( $crumb[0] ) . '';
} else {
echo esc_html( $crumb[0] );
}
echo $after;
if ( sizeof( $breadcrumb ) !== $key + 1 ) {
echo $delimiter;
}
}
echo $wrap_after;
}
I have Got the answer by doing changes on functions.php
https://www.screencast.com/t/U42lqPduY707
if (get_post_type() == 'product')
{
echo sprintf($link, '#', esc_html__('Products', 'thegem'));
//echo sprintf($link, get_permalink(get_option ('woocommerce_shop_page_id' , 0 )), esc_html__('Product', 'thegem'));
$taxonomy = 'product_cat';
$terms = get_the_terms( $post->ID, $taxonomy );
foreach ( $terms as $c ) {
$c->term_id;
// echo '' . ($c->name ) . '';
if($c->term_id=='36') {
echo $delimiter;
echo sprintf($link, get_permalink( 106 ), esc_html__($c->name, 'thegem'));
}
}
}
else {
$slug = $post_type->rewrite;
printf($link, $home_link . '/' . $slug['slug'] . '/', $post_type->labels->singular_name);
}

Woocommerce Is_Purchasable cause ajax error

I'm using the code below to modify the WooCommerce Is_Purchasable option so that, item Y is purchasable if item X is added to the cart.
But it gives ajax error when trying to add item Y to the cart.
Here's 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', true ) ) ) {
$cart = $saved_cart['cart'];
} elseif ( is_null( $cart ) ) {
$cart = array();
}
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;
}
// Product Y
global $y_cart_items;
$y_cart_items = 2986;
//Product X
global $x_cart_items;
$x_cart_items = array(
'297'
);
// Step 2
add_filter('woocommerce_is_purchasable', function($is_purchasable, $product) {
global $y_cart_items;
global $x_cart_items;
if( $product->id == $y_cart_items ) {
// make it false
$is_purchasable = false;
// get the cart items object
foreach ( aelia_get_cart_contents() as $key => $item ) {
// do your condition
if( in_array( $item['product_id'], $x_cart_items ) ) {
// Eligible product found on the cart
$is_purchasable = true;
break;
}
}
}
return $is_purchasable;
}, 10, 2);
}, 10);
// Step 3 - Explain customers why they can't add some products to the cart
add_filter('woocommerce_get_price_html', function($price_html, $product) {
if(!$product->is_purchasable() && is_product()) {
$price_html .= '<p>' . __('Add Product X to be able to purchase Product Y.', 'woocommerce') . '</p>';
}
return $price_html;
}, 10, 2);
How do I fix this? Thank you.

Categories