phpjquerywordpresswoocommerceproduct-variations

Adding a custom link to products stop variations being added to cart in WooCommerce


I have an issue with some basic code on my WooCommerce project. I want to automatically add a link to a related demo product, to notify the customer. I am adding that link using woocommerce_after_add_to_cart_button action hook, so it's displayed exactly where I want. It works fine on simple product pages, but on variable products, I can no longer add the variation to the cart. Any ideas?

The following code checks for the related product demo based on the SKU and if it exists and is in stock, it displays the related product demo link:

add_action( 'woocommerce_after_add_to_cart_button', 'find_rf_link_products_function2' );

function find_rf_link_products_function2(){ 
    global $product;
    
    $product_rf = $product->get_sku();
    $product_rf = $product_rf."RF";
    $product_id = wc_get_product_id_by_sku( ''.$product_rf.'' );
    $linktorf   = get_permalink($product_id);

    if( $product_id ) {
        $product  = wc_get_product( $product_id );
        $amountRF = $product->get_stock_quantity();
    }
    
    if ( $amountRF > 0 ) {
        $box = "<span class='box'><a href='".$linktorf."'>EX-DEMO AVAILABLE</a></span>";
        echo $box;  
    } else {
        // do nothing
    }
}

Solution

  • Handling variable products and the live selected variation should solve your issue: It requires a bit of JavaScript and some more things, to extend your code for the live selected variation on variable products.

    Note that in your current code, you should check that the demo product object is not null, before using get_stock_quantity() method. Also, some other optimizations should help.

    Try the following:

    // Display the demo link
    add_action( 'woocommerce_after_add_to_cart_button', 'display_product_demo_link' );
    function display_product_demo_link(){ 
        global $product;
        
        // Get the related demo product ID from the prepended product SKU
        $product_demo_id = wc_get_product_id_by_sku( $product->get_sku() . 'RF' );
    
        // On variable products (display a hidden empty demo link)
        if ( $product->is_type('variable') ) {
            printf('<span class="box demo-link" style="display:none;"><a href="#">%s</a></span>', esc_html__('EX-DEMO AVAILABLE') );
        } 
        // For other product types (display the demo link if available)
        elseif ( !$product->is_type('variable') && $product_demo_id ) {
            $product_demo = wc_get_product( $product_demo_id );
    
            if ( $product_demo && $product_demo->is_in_stock() ) {
                printf('<span class="box"><a href="%s">%s</a></span>', $product_demo->get_permalink(), esc_html__('EX-DEMO AVAILABLE') );
            }
        }
    }
    
    // Variable product: add each variation demo link to the form data
    add_filter( 'woocommerce_available_variation', 'define_variation_demo_link', 10, 3 );
    function define_variation_demo_link( $data_variation, $product, $variation ) {
        // Get the related demo variation ID from the prepended variation SKU
        $variation_demo_id = wc_get_product_id_by_sku( $variation->get_sku() . 'RF' );
    
        if ( $variation_demo_id ) {
            $variation_demo = wc_get_product( $variation_demo_id );
    
            if ( $variation_demo && $variation_demo->is_type('variation') && $variation_demo->is_in_stock() ) {
                $data_variation['demo_link'] = $variation_demo->get_permalink();
            }
        }
        return $data_variation;
    }
    
    // Variable product: Display dynamically the selected variation demo link when available
    add_action('woocommerce_single_variation', 'variable_product_jquery_demo_link_script', 5);
    function variable_product_jquery_demo_link_script() {
        // Enqueued JavaScript
        wc_enqueue_js( "$('form.variations_form').on('show_variation', function(event, data){ 
            if( data.demo_link ) {
                $('span.demo-link > a').prop('href', data.demo_link);
                $('span.demo-link').show();
            } else {
                $('span.demo-link > a').prop('href', '');
                $('span.demo-link').hide();
            }
        }).on('hide_variation', function(){
            $('span.demo-link > a').prop('href', '');
            $('span.demo-link').hide();
        });" );
    }
    

    It should work as you expect.