• Resolved ctmartin2020

    (@ctmartin2020)


    Hi. I want to change cart item pricing but (I’m guessing this is due to AJAX handling?) I cannot seem to be able to use the action “woocommerce_before_calculate_totals” to iterate through the cart items to find the product whose price I’d like to adjust, and then set_price() on the line item with the new price.

    I have constants defined with the special sale price (‘FITSALEPRICE’) and product id (‘FITPID’). Here’s what I’m trying to do, but this does not seem to work with the sidecart:

    
    add_action( 'woocommerce_before_calculate_totals', 'pricecartvariations', 99 );
    
    function pricecartvariations( $cart ) {	
    	if (defined('FITSALEPRICE') && defined('FITPID')) {
    		foreach ($cart->get_cart() as $key=>$value) {
    			if ( $value['product_id'] == FITPID ) {
             			$value['data']->set_price(FITSALEPRICE);
            		}
    		}
    	}
    }
    

    It seems like this action never gets called, so when WC Side Cart writes $product_price with WC->cart->get_product_price() only the original price shows in the cart – not the special sale price defined by FITSALEPRICE.

    Any help would be GREATLY appreciated. This is driving me mad.

    • This topic was modified 2 years, 10 months ago by ctmartin2020.
Viewing 11 replies - 1 through 11 (of 11 total)
  • Thread Starter ctmartin2020

    (@ctmartin2020)

    P.S. I have even tried to change the price in the $product object before the add-to-cart even happens using $product->set_sale_price(<<MY NEW PRICE>>) but this does not seem to have any effect on the side cart — the value that shows in the cart is the original product price. Makes no sense. Hopefully I’m doing something stupid that can be easily fixed.

    Thread Starter ctmartin2020

    (@ctmartin2020)

    Update: I’ve now tried using $GLOBALS for the sale price and ID to pass into the action. Still doesn’t work. Here’s what DOES work:

    add_action( 'woocommerce_before_calculate_totals', 'pricecartvariations', 1000, 1 );
    function pricecartvariations( $cart ) {	
       $pr = 500;
       // $pr = $GLOBALS['fit_sale_price']   DOES NOT WORK
       $pid = 1234;
       // $pid = $GLOBALS['fit_pid']    DOES NOT WORK
    
    	foreach ($cart->get_cart() as $key=>$value) {
                if ($value['product_id'] == $pid) {
    		$value['data']->set_price( $pr );
                }
    	}
    }

    Obviously this is not what I want — to set the price of an items in the cart to $500 — but this is the ONLY thing that works.

    So I guess the question now is, why are my $GLOBALS not coming through? Isn’t this a valid way to pass additional parameters into a filter or action?

    Thread Starter ctmartin2020

    (@ctmartin2020)

    Any help? The filter “woocommerce_add_cart_item_data” does not work either to relay new price info to the action “woocommerce_before_calculate_totals”.

    So is this a case of the AJAX call for the side cart effectively being a new session, so none of this works? Is there a way? If not, just let me know and I will look for another plugin for the cart!

    Plugin Author xootix

    (@xootix)

    Hello,

    The hook woocommerce_before_calculate_totals works fine with side cart. I have tested the below code.

    define('MYCONSTANT', 20);
    
    add_action( 'woocommerce_before_calculate_totals', 'pricecartvariations', 99 );
    
    function pricecartvariations( $cart ) {	
    
    	foreach ($cart->get_cart() as $key=>$value) {
    		
     		$value['data']->set_price(MYCONSTANT);
        	
    	}
    	
    }

    Constants are different from $GLOBALS, if you have used function define() then you cannot use $GLOBALS to fetch it.
    Now if you are still not able to get the constant value inside filter that means your constant is declared too late, after the filter is called.
    Ajax is no different than the normal request.

    Also to make sure some other filter is not overriding yours, use priority PHP_INT_MAX instead of 99

    • This reply was modified 2 years, 10 months ago by xootix.
    Thread Starter ctmartin2020

    (@ctmartin2020)

    I will try the PHP_INT_MAX.

    Of course, I’m not confusing globals with constants. I have tried both, neither work. My constants are being set before the user even “adds to cart”. But when I get into this filter, I cannot echo anything to see what is set but I suspect the constant values are reset based on the logic not executing. I have no idea why.

    Thread Starter ctmartin2020

    (@ctmartin2020)

    Also, if I do introduce caching, is there a particular endpoint URL I should exclude from the cache?

    Plugin Author xootix

    (@xootix)

    Ajax requests do not get cached, so you have nothing to worry about caching.

    Also make sure the hook/place you’re using to define constant is available globally & is being executed. I am saying this because you have mentioned “My constants are being set before the user even “adds to cart”
    The filter woocommerce_before_calculate_totals has nothing to do with “add to cart” functionality, it is for changing price in cart directly.
    If you’re setting constants during “add to cart” event then it will not work.

    Thread Starter ctmartin2020

    (@ctmartin2020)

    Thank you!

    Ok, I set the action to priority “PHP_MAX_INT” but still didn’t help.

    But if the constants are getting set after this action runs, I don’t understand how that could be the case. My constants are being set from within a filter function for Yoast SEO which runs at a priority of 10 (versus this action which has priority PHP_INT_MAX).

    Here’s the trace:

    #0 wp-content/themes/oem/functions.php(2032): quickfit(Array, 84693) 
    #1 wp-includes/class-wp-hook.php(294): oem_yoast_meta_and_opengraph_description('Dirt Bike Front...') 
    #2 wp-includes/plugin.php(212): WP_Hook->apply_filters('Dirt Bike Front...', Array) 
    #3 wp-content/plugins/wordpress-seo/src/presenters/meta-description-presenter.php(59): apply_filters('wpseo_metadesc', 'Dirt Bike Front...', Object(Yoast\WP\SEO\Presentations\Indexable_Post_Type_Presentation)) 
    #4 wp-content/plugins/wordpress-seo/src/presenters/abstract-indexable-tag-presenter.php(30): Yoast\WP\SEO\Presenters\Meta_Description_Presenter->get() 
    #5 wp-content/plugins/wordpress-seo/src/presenters/meta-description-presenter.php(25): Yoast\WP\SEO\Presenters\Abstract_Indexable_Tag_Presenter->present() 
    #6 wp-content/plugins/wordpress-seo/src/integrations/front-end-integration.php(299): Yoast\WP\SEO\Presenters\Meta_Description_Presenter->present() 
    #7 wp-includes/class-wp-hook.php(292): Yoast\WP\SEO\Integrations\Front_End_Integration->present_head('') 
    #8 wp-includes/class-wp-hook.php(316): WP_Hook->apply_filters('', Array) 
    #9 wp-includes/plugin.php(484): WP_Hook->do_action(Array) 
    #10 wp-content/plugins/wordpress-seo/src/integrations/front-end-integration.php(273): do_action('wpseo_head') 
    #11 wp-includes/class-wp-hook.php(292): Yoast\WP\SEO\Integrations\Front_End_Integration->call_wpseo_head('') 
    #12 wp-includes/class-wp-hook.php(316): WP_Hook->apply_filters(NULL, Array) 
    #13 wp-includes/plugin.php(484): WP_Hook->do_action(Array) 
    #14 wp-includes/general-template.php(3009): do_action('wp_head') 
    #15 wp-content/themes/oem/header.php(28): wp_head() 
    #16 wp-includes/template.php(730): require_once('/chroot/home/ad...') 
    #17 wp-includes/template.php(676): load_template('/chroot/home/ad...', true, Array) 
    #18 wp-includes/general-template.php(48): locate_template(Array, true, true, Array) 
    #19 wp-content/plugins/elementor/modules/page-templates/templates/header-footer.php(9): get_header() 
    #20 wp-includes/template-loader.php(106): include('/chroot/home/ad...') 
    #21 wp-blog-header.php(19): require_once('/chroot/home/ad...') 
    #22 index.php(17): require('/chroot/home/ad...') 
    #23 {main}

    #0 shows call to function in functions.php “quickfit” which is exactly where the constants are set — and I can echo them back from there to confirm it.

    To further test this, I actually put the call to quickfit() (which sets the constants if they’re not already set) INTO the woocommerce_before_calculate_totals action function, and still I cannot get this working.

    So can you tell me if there is another action or filter I can use for my purposes?

    Thread Starter ctmartin2020

    (@ctmartin2020)

    DUH, wait, I’m reading this wrong. #0 is actually the last place in the queue. So I need to find a way to define these constants sooner. However, I do not understand why they are not being set when I run the code from within the action function itself!

    Regardless, I don’t see any specific call to action woocommerce_before_calculate_totals but maybe that’s in an do_action array?

    Another thing that makes it nearly impossible for me to figure out what is going on is whenever there is an “echo” or print of any sort in the action function, the add-to-cart spins and spins in an endless loop and not only does the side cart not open but I get no output from my echo or print_r etc.

    • This reply was modified 2 years, 10 months ago by ctmartin2020.
    • This reply was modified 2 years, 10 months ago by ctmartin2020.
    Thread Starter ctmartin2020

    (@ctmartin2020)

    OK, I’m at the end of my rope here. It seems like woocommerce_before_calculate_totals — which seems like the most reasonable place to do this repricing — is running before I can set constants or globals to the values I need them to contain.

    Since I can’t use echo or print_r directly within the action function without crashing the page, I’m piping the output of my trace to a text file. So here’s what is happening (in reverse order) from the action function:

    #0 wp-includes/class-wp-hook.php(292): pricecartvariations(Object(WC_Cart))
    #1 wp-includes/class-wp-hook.php(316): WP_Hook->apply_filters(NULL, Array)
    #2 wp-includes/plugin.php(484): WP_Hook->do_action(Array)
    #3 wp-content/plugins/woocommerce/includes/class-wc-cart.php(1367): do_action('woocommerce_bef...', Object(WC_Cart))
    #4 wp-content/plugins/side-cart-woocommerce/public/class-xoo-wsc-cart-data.php(71): WC_Cart->calculate_totals()
    #5 wp-includes/class-wp-hook.php(292): xoo_wsc_Cart_Data->set_ajax_fragments(Array)
    #6 wp-includes/plugin.php(212): WP_Hook->apply_filters(Array, Array)
    #7 wp-content/plugins/woocommerce/includes/class-wc-ajax.php(195): apply_filters('woocommerce_add...', Array)
    #8 wp-includes/class-wp-hook.php(292): WC_AJAX::get_refreshed_fragments('')
    #9 wp-includes/class-wp-hook.php(316): WP_Hook->apply_filters('', Array)
    #10 wp-includes/plugin.php(484): WP_Hook->do_action(Array)
    #11 wp-content/plugins/woocommerce/includes/class-wc-ajax.php(90): do_action('wc_ajax_get_ref...')
    #12 wp-includes/class-wp-hook.php(292): WC_AJAX::do_wc_ajax('')
    #13 wp-includes/class-wp-hook.php(316): WP_Hook->apply_filters(false, Array)
    #14 wp-includes/plugin.php(484): WP_Hook->do_action(Array)
    #15 wp-includes/template-loader.php(13): do_action('template_redire...')
    #16 wp-blog-header.php(19): require_once('/chroot/home/ad...')
    #17 index.php(17): require('/chroot/home/ad...')
    #18 {main}

    I need to (1) check if this is a product page, (2) get the product id, then (3) lookup the pricing for the specific model the user is looking for (and apply that special pricing to the item added to the cart). It’s in this function quickfit() that I’m setting these constants I want to pull into the woocommerce_before_calculate_totals action… but when that gets called, they haven’t been defined yet (even though the priority is as high as it can possibly get!!!!).

    I’ve then tried to do this in an action like template_redirect (which is #15 in the list above, i.e. well before the woocommerce_before_calculate_totals action) but I get a fatal error as global $product; $product->get_id(); isn’t recognized (yet).

    Then I tried doing this in a filter like woocommerce_add_to_cart_fragments (#7 on the list above — also well before the woocommerce_before_calculate_totals action). I simply returned the $fragments parameter but before that inserted my logic to (1) check if is_product() and if so (2) get the product id and (3) lookup the pricing and set the constants etc. It never gets past the is_product() check, so it looks like this is happening before woocommerce even knows this is a product.

    The info I need for my lookup is stored in the url. When I look at $_SERVER['REQUEST_URI'] I do not see my own data… I only see the AJAX endpoint for the side cart.

    SO… where/how exactly can I pass the values that I need to change the pricing in the cart??? I’m really thinking this plugin is just not something a developer can work with as there don’t appear to be any hooks where I can modify the cart items.

    • This reply was modified 2 years, 10 months ago by ctmartin2020.
    • This reply was modified 2 years, 10 months ago by ctmartin2020.
    Thread Starter ctmartin2020

    (@ctmartin2020)

    SOLUTION: for those who encounter the same issue (…then good luck LOL!), there is a solution that appears to work. Set a session with an array of the data you want to pass into the woocommerce_before_calculate_totals action function when you’re dealing with an AJAX situation.

    Set it like this (substitute “_your_session_name” with whatever you like):

    WC()->session->set( '_your_session_name', $data );

    …where $data is an array of whatever data you want to store. You retrieve it like this:

    $data = (array)WC()->session->get( '_your_session_name' );

Viewing 11 replies - 1 through 11 (of 11 total)
  • The topic ‘Trying to change cart pricing’ is closed to new replies.