Woocommerce conditional is_product() from functions.php - php

I want to check if is single product page, but this has no effect on single product page:
if (! is_admin() && is_product() ) {
var_dump('is product'); // this has no effect in single product page
}
Is there a limitation to use is_product() in functions.php? How can I achieve this?
EDIT:
In order to avoid var_dump issues, this is the final code I'm trying. It try to add product type (simple/variable) to body class:
add_action( 'woocommerce_after_single_product', function () {
if (! is_admin() && is_product() ) {
add_filter( 'body_class', function( $classes ) {
global $post;
$product = wc_get_product( $post->ID );
$tipo = $product->get_type();
return array_merge( $classes, array( $tipo ) );
});
}
}, 100 );

You can not use this function directly without a hook since your functions.php file is included before every other file - mostly. To make this thing work you need to work with hooks every time like this:
add_action( 'template_redirect', 'template_redirect_action' );
function template_redirect_action() {
if ( ! is_admin() && is_product() ) {
add_filter( 'body_class', function ( $classes ) {
global $post;
$product = wc_get_product( $post->ID );
$tipo = $product->get_type();
return array_merge( $classes, array( $tipo ) );
} );
}
}
Visit a product page and check your body classes.
By using the template_redirect hook you can be sure it's executed on every page. Otherwise your check would not make any sense when using a product hook which only gets executed on product pages.
Tested an works.

Related

Plugin with option to disable itself on certain products

I'm creating a plugin that makes a few changes to the product pages in woocommerce and i'd like to add a checkbox if the user wants to disable it for certain products.
I managed to insert the checkbox on the product edit page, but it's possible to verify if it's checked before loading the plugin?
I tried like this, but nothing happens:
global $product;
if ($product) {
$customAttributes = get_post_meta( $product->get_id(), 'custom_attributes', true );
if ( isset($customAttributes['disabled']) && $customAttributes['disabled'] == 1 ) {
return;
}
}
I searched a lot and tried other things, but i couldn't find a solution.
I always create a plugin and put it in the mu-plugins folder so you can do the check before any plugin is loaded.
Could you try the option_active_plugins hook?
add_filter( 'option_active_plugins', function( $plugins ){
global $product;
if ( $product ) {
$customAttributes = get_post_meta( $product->get_id(), 'custom_attributes', true );
if ( isset( $customAttributes['disabled'] ) && $customAttributes['disabled'] == 1 ) {
$unload_plugins[] = "my-plugins/my-plugin.php";
$plugins = array_diff( $plugins, $unload_plugins );
}
}
return $plugins;
} );
If needed, maybe wrap it in a wp or init action, but get_post_meta should work there.

How to run script only once when a product added to the cart in WooCommerce?

When a product is added to the cart, the page goes to the checkout page.
Here on the checkout page, I want to add a script to the footer only once when a product from a certain category is added. I mean when to reload the page it will not show up.
If I use wc_add_notice it shows a message once and when reloading the page it does not show up. Just like I want but add_action( 'wp_footer'); does not work.
add_filter('woocommerce_add_to_cart', 'my_woocommerce_add_to_cart', 8, 6);
function my_woocommerce_add_to_cart( $cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data ){
global $woocommerce;
$clearstorage_cat = 30;
$_categorie = get_the_terms($product_id, 'product_cat');
if ($_categorie) {
$in_cart = false;
foreach ($_categorie as $_cat) {
$_lacats = $_cat->term_id;
if ($_lacats === $clearstorage_cat ){
$in_cart = true;
}
}
}
if ( $in_cart ) {
function clearlocals(){
?>
<script type="text/javascript">localStorage.clear();</script>
<?php
add_action( 'wp_footer', 'clearlocals' );
}
}
}
If I add a message, it works just as I want.
if ( $in_cart ) {
wc_add_notice('Some texts','success');
}
In this case, a message shows up on the checkout page only once when added.
I want to clear the local storage when a product is added to the cart.
You can use the same notice concept. WooCommerce Sessions.
Set a session value in "AddToCart" action hook.
add_action('woocommerce_add_to_cart', 'my_woocommerce_add_to_cart', 8, 6);
function my_woocommerce_add_to_cart( $cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data ){
global $woocommerce;
$clearstorage_cat = 30;
$_categorie = get_the_terms($product_id, 'product_cat');
if ($_categorie) {
$in_cart = false;
foreach ($_categorie as $_cat) {
$_lacats = $_cat->term_id;
if ($_lacats === $clearstorage_cat ){
WC()->session->set( 'clear_locals, true );
}
}
}
Then check inside the wp_footer action hook if it's the checkout page and session variable is set.
add_action( 'wp_footer', 'checkout_clear_locals_script' );
function checkout_clear_locals_script() {
// Check if checkout page and session variable is set.
if ( is_checkout() && ! is_null( WC()->session->get( 'clear_locals', null ) ) ) {
// Clear the session variable and print the script in footer.
WC()->session->set( 'clear_locals', null );
?>
<script type="text/javascript">localStorage.clear();</script>
<?php
}
}

Add CSS to WooCommerce product pages only if product is not on sale

I need to add some CSS to hide some elements/classes on the page if the product is NOT on sale.
From another function I have, I am assuming I can check if $args['meta_key'] = '_sale_price'; is blank and if it then adds the CSS.
How can I use this in my functions.php?
add_action( 'wp', 'add_cssif_product_not_onsale' );
function add_cssif_product_not_onsale() {
if ( is_product() ) {
global $post;
$product = wc_get_product( $post );
if ( !$product->is_on_sale() )
echo "<style>body{display:none}</style>";
}
}

Display product data with custom shortcodes in Woocommerce single product pages

In Woocommerce, I use 3 different shortcode functions that are displaying:
The product categories list,
The product SKU
Values for a specific attribute.
My 3 function looks like this:
function display_woo_sku() {
global $product;
return $product->get_sku();
}
add_shortcode( 'woo_sku', 'display_woo_sku' );
function display_woo_farve() {
global $product;
return $product->get_attribute( 'farve' );
}
add_shortcode( 'woo_farve', 'display_woo_farve' );
function display_woo_style() {
global $post, $product;
$categ = $product->get_categories();
return $categ;
}
add_shortcode( 'woo_style', 'display_woo_style' );
This actually works, but throws errors when updating products and make issues with Facebook Pixel add ons.
I can't see What is wrong with my code, but there must be something wrong since it conflicting with plugins and third party pixel tools.
Any help is appreciated.
Your code is making some errors for many reasons… Try this instead:
function display_woo_sku() {
if( ! is_admin() && ! is_product() ) return;
global $post;
// Get an instance of the WC_Product Object
$product = wc_get_product( $post->ID );
return $product->get_sku();
}
add_shortcode( 'woo_sku', 'display_woo_sku' );
function display_woo_attr_farve() {
if( ! is_admin() && ! is_product() ) return;
global $post;
// Get an instance of the WC_Product Object
$product = wc_get_product( $post->ID );
return $product->get_attribute( 'farve' );
}
add_shortcode( 'woo_farve', 'display_woo_attr_farve' );
function display_woo_cats() {
if( ! is_admin() && ! is_product() ) return;
global $post;
// $categ = $product->get_categories(); // <== <== <== <== IS DEPRECATED
return wc_get_product_category_list( $post->ID );
}
add_shortcode( 'woo_cats', 'display_woo_cats' );
This code goes on function.php file of your active child theme (or theme). Tested and works.
It should solve your issue…

Woocommerce delivery&payment options - What´s wrong with my php code?

I am trying to hide some payment options in Woocommerce in case of specific delivery option. I tried to put this to my functions.php but It´s not working and I don´t know why.
Can you help me please?
function payment_gateway_disable_country( $available_gateways, $available_methods )
{
global $woocommerce;
if ( isset( $available_methods['local_delivery'] ) ){
unset( $available_gateways['paypal'] );
}
return $available_gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'payment_gateway_disable_country' );
My research:
link 1
link 2
link 3
link 4
The available delivery methods do not get passed as a parameter in the filter woocommerce_available_payment_gateways - you need to load them in and check them.
The code below should remove the paypal payment option one if the user selects local delivery. If your checkout page is the AJAX based one then as the user changes the delivery method, the available payment options should also change.
function payment_gateway_disable_country($available_gateways) {
global $woocommerce;
$packages = $woocommerce->shipping->get_packages();
foreach ( $packages as $i => $package ) {
$chosen_method = isset( $woocommerce->session->chosen_shipping_methods[ $i ] ) ?
$woocommerce->session->chosen_shipping_methods[ $i ] : '';
if ('local_delivery' == $chosen_method) {
unset($available_gateways['paypal']);
break;
}
}
return $available_gateways;
}
add_filter(
'woocommerce_available_payment_gateways',
'payment_gateway_disable_country'
);
Let me know if you have any issues with the code; I did not have a chance to test it with woocommerce.
$available_methods will not be accessible inside your function. So first define it globally & access as global variable inside function, somewhat like this:
global $available_methods;
$available_methods = array( 'local_delivery' => 'yes' );
function payment_gateway_disable_country( $available_gateways )
{
global $woocommerce, $available_methods;
if ( isset( $available_methods['local_delivery'] ) ){
unset( $available_gateways['paypal'] );
}
return $available_gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'payment_gateway_disable_country' );

Categories