Link to home
Start Free TrialLog in
Avatar of sharingsunshine
sharingsunshineFlag for United States of America

asked on

Need "Sale To Date" On Woo Commerce Category Page

I want to add the "sale to date" on my on-sale category page for each product.  I have put together this function but it doesn't seem to be getting any values so please tell me what is wrong.  My Woo Commerce version is 3.4.4

add_filter( 'get_date_on_sale_to', 'custom_price_html', 100, 2 );
function custom_price_html( $price, $product )
{
    global $post;
    $sales_price_to = get_post_meta($post->ID, $data['date_on_sale_to'], true);
    if(is_product_category( 'on-sale' ) && ($sales_price_to != ""))
    {
        $sales_price_date_to = date("j M y", $sales_price_to);
        return str_replace( '</ins>', ' </ins> <b>(Offer till '.$sales_price_date_to.')</b>', $price );
    }
    else
    {
        return apply_filters( 'woocommerce_get_price', $price );
    }
}

Open in new window

Avatar of Adrian Thompson
Adrian Thompson
Flag of United Kingdom of Great Britain and Northern Ireland image

Your code on line 5 is not correct:
$sales_price_to = get_post_meta($post->ID, $data['date_on_sale_to'], true);

Open in new window


The $data array seems to be added in error (it is not defined) and the function "get_post_meta" expects a STRING value as the 2nd argument. Therefore, change the above line of code to:
$sales_price_to = get_post_meta($post->ID, 'date_on_sale_to', true);

Open in new window


This assumes that you have a custom field with the name:
date_on_sale_to
Let me know if this works. If it does not work, I will show you how to troubleshoot in order to find the incorrect code.
Avatar of sharingsunshine

ASKER

that didn't work and it isn't a custom field.  Please see screenshot

https://gyazo.com/88d817384008aa2938e04b6cb5594bbe
I found this code but it won't output on the category page even trying to change the hook.

This will show the code on the single page
add_filter( 'woocommerce_get_price_html', 'custom_price_html', 100, 2 );
function custom_price_html( $price, $product )
{
    global $post;
    $sales_price_to = get_post_meta($post->ID, '_sale_price_dates_to', true);
    if(is_single() && $sales_price_to != "")
    {
        $sales_price_date_to = date("j M y", $sales_price_to);
        return str_replace( '</ins>', ' </ins> <b>(Offer till '.$sales_price_date_to.')</b>', $price );
    }
    else
    {
        return apply_filters( 'woocommerce_get_price', $price );
    }
}

Open in new window

I need it to output on the category page and the single page.
Hello,

You say "This will show the code on the single page" and that is because you have the following code on line 6:

 if(is_single() && $sales_price_to != "")

Open in new window


You need to remove the is_single() condition from your if statement. So Just change that line of code to:

 if($sales_price_to != "")

Open in new window

Thanks for your help.  However, when I make that change I get this error:

Fatal error: Uncaught ArgumentCountError: Too few arguments to function custom_price_html(), 1 passed in C:\xampp\apps\wordpress\htdocs\wp-includes\class-wp-hook.php on line 286 and exactly 2 expected in C:\xampp\apps\wordpress\htdocs\wp-content\themes\flatsome-child\functions.php:5 Stack trace: #0 C:\xampp\apps\wordpress\htdocs\wp-includes\class-wp-hook.php(286): custom_price_html('') #1 C:\xampp\apps\wordpress\htdocs\wp-includes\class-wp-hook.php(310): WP_Hook->apply_filters('', Array) #2 C:\xampp\apps\wordpress\htdocs\wp-includes\plugin.php(453): WP_Hook->do_action(Array) #3 C:\xampp\apps\wordpress\htdocs\wp-content\themes\flatsome\woocommerce\content-product.php(87): do_action('woocommerce_aft...') #4 C:\xampp\apps\wordpress\htdocs\wp-includes\template.php(690): require('C:\\xampp\\apps\\w...') #5 C:\xampp\apps\wordpress\htdocs\wp-content\plugins\woocommerce\includes\wc-core-functions.php(179): load_template('C:\\xampp\\apps\\w...', false) #6 C:\xampp\apps\wordpress\htdocs\wp-content\themes\flatsome\woocommerce\layout in C:\xampp\apps\wordpress\htdocs\wp-content\themes\flatsome-child\functions.php on line 5

Open in new window


Here is my code that I have in functions.php in the child theme.

<?php
// Add custom Theme Functions here
//add_filter( 'woocommerce_get_price_html', 'custom_price_html', 100, 2 );
add_filter( 'woocommerce_after_shop_loop_item', 'custom_price_html', 100, 2 );
function custom_price_html( $price, $product )
{
    global $post;
    $sales_price_to = get_post_meta($post->ID, '_sale_price_dates_to', true);
    //if(is_single() && $sales_price_to != "")
	if($sales_price_to != "")
	
    {
        $sales_price_date_to = date("m/d/y", $sales_price_to);
        return str_replace( '</ins>', ' </ins> <b>(Expires '.$sales_price_date_to.')</b>', $price );
    }
    else
    {
        return apply_filters( 'woocommerce_get_price', $price );
    }
}

Open in new window

Your error "Too few arguments to function custom_price_html(), 1 passed" means you have this line of code somewhere:
custom_price_html(myprice)

The error message tells you this is happening in C:\xampp\apps\wordpress\htdocs\wp-includes\class-wp-hook.php on line 286

This is wrong because your function requires two arguments:
custom_price_html(myprice, myproduct)

You can fix this by redefining your function OR by setting DEFAULT VALUES. At the moment your function is not referencing $product so it would be best practice to remove this from your function declaration.

Therefore change this line of code:
function custom_price_html( $price, $product )

Open in new window


to the following declaration with one parameter:
function custom_price_html( $price)

Open in new window


If that gives you a similar error message, try using this declaration with two parameters using default values:
function custom_price_html( $price=0, $product=0)

Open in new window


If you need to use default values that means somewhere  in your code is calling the function with one parameter and somewhere else in your code it is calling the function with two parameters so your code is inconsistent. It would be best to make everything consistent... but default values will fix the error.
I made the changes as you suggested and the error goes away but it doesn't put the date on the category page like I need.  Looking over the Woo Commerce classes it seems it would be better to use the Product class I just don't know how to access what is needed.

https://gyazo.com/8d9121236447cb6ca5ba6b4a1009c521
This seems to be a more direct approach to get the date for each product.

this seems to be more information - https://gyazo.com/f7c113bbe539d82d68e6b46d804c2707

I really want to learn how to grab this data like I did using your sql function for the QV.  So, if you can get me going that way I would appreciate it.
You say "but it doesn't put the date on the category page like I need". Please can you explain?

For example, what is the current output? Is it the wrong date, a number, bad formatting or something else?

I can help you with an SQL statement but using the built in function get_post_meta is usually the most efficient way to go.
I'm sorry not to be more specific.  It actually doesn't have any output on the category page.
The first task in debugging would be to make sure you are able to actually output something to the page.

can you remove all your code and replace with this just to make sure the output is visible:

<?php
add_filter( 'woocommerce_after_shop_loop_item', 'custom_price_html', 100, 2 );
function custom_price_html( $price=0, $product=0)
{
     return "hello! output is working with product ".$product." and price ".$price;
}

Open in new window


You need to check that "hello! the output is working" appears where you want it (i.e. on your product page AND your category page). If this is working fine, then we can move on with confidence that all we need to do is acquire the correct "sale to date" for you.
I edited my comment above to include the $price and $product in the output. Please reply here to let me know what the output is. For example, if the output is "hello! output is working with product 0 and price 0" then the parameters are missing in your function calls.
Using your edited content, nothing is showing on the category or the single product page.  I also commented out every function in functions.php to test it too.
This shows the problem is not with getting the date. Rather, the problem is with the output of your function.

Please can you confirm that you only commented out your functions in functions.php? If you also commented out other functions used by your theme, that can cause it to stop working.
my theme doesn't have anything in it but custom functions.  Here is my code:

<?php
// Add custom Theme Functions here
//add_filter( 'woocommerce_get_price_html', 'custom_price_html', 100, 2 );
//add_filter( 'woocommerce_after_shop_loop_item', 'custom_price_html', 100, 2 );
//function custom_price_html( $price, $product )
/*function custom_price_html( $price)
{
    global $post;
    $sales_price_to = get_post_meta($post->ID, '_sale_price_dates_to', true);
    //if(is_single() && $sales_price_to != "")
	if($sales_price_to != "")
	
	
    {
        $sales_price_date_to = date("m/d/y", $sales_price_to);
        return str_replace( '</ins>', ' </ins> <b>(Expires '.$sales_price_date_to.')</b>', $price );
    }
    else
    {
        return apply_filters( 'woocommerce_get_price', $price );
    }
}

add_action ('woocommerce_before_order_notes', 'member_note', 10); 
function member_note (){
$code = <<< EOT
<button style= "background-color:green; color:white;" onclick="myFunctionMember()">MEMBERSHIP</button>
<script>
function myFunctionMember() {
    document.getElementById("order_comments").innerHTML = "I want membership";
}
</script>
EOT;
echo $code;
}

add_action ('woocommerce_review_order_after_cart_contents', 'display_item_qv', 10);



function display_item_qv () {

        if ( ! is_ajax() ) {


        global $wpdb;

        //$wpdb->show_errors = TRUE;
//$wpdb->suppress_errors = FALSE;

        $val = 0;

        foreach( WC()->cart->get_cart() as $cart_item ) {

   $product_in_cart = $cart_item['product_id'];


$item_qv = $wpdb->get_row("

SELECT DISTINCT
    p.id AS 'Product ID',
    p.post_title AS 'Product Name',
    t.name AS 'QV'
FROM
        wp_posts AS p
INNER JOIN
    wp_term_relationships AS tr ON p.id = tr.object_id
INNER JOIN
        wp_term_taxonomy AS tt ON tt.term_taxonomy_id = tr.term_taxonomy_id
INNER JOIN
    wp_terms AS t ON t.term_id = tt.term_id
WHERE
        tt.taxonomy='pa_qv'
AND
        p.post_type = 'product'

AND id=$product_in_cart", ARRAY_N);



$val += $item_qv[2] * $cart_item['quantity'];
        //echo $item_qv[2];
        //echo "<pre>";
        //print_r($item_qv);
        //echo "</pre>";

        }
//echo "The total is ". $val;

include_once "qv_contest.php";

        //print_r($item}
}

}
*/

add_filter( 'woocommerce_after_shop_loop_item', 'custom_price_html', 100, 2 );
function custom_price_html( $price=0, $product=0)
{
     return "hello! output is working with product ".$product." and price ".$price;
}

Open in new window

great. okay, please delete the 5 lines I gave you and replace with this. let me know if you get an output:

function custom_price_html()
{
     echo "hello! output is working";
}
add_action('woocommerce_after_shop_loop_item','custom_price_html',10,0);

Open in new window

I get output on every product in the category and nothing on the single page.
excellent. that is what the function is supposed to do because you are hooking into "woocommerce_after_shop_loop_item"

The "loop_item" is referring to the products that are listed (looped) in your category page so this will never show on your single page. I will take a look and see if we can now find a more suitable hook from the list:
https://docs.woocommerce.com/wc-apidocs/hook-docs.html
got it! delete the code I gave you last time and replace with this:

function custom_price_html_single()
{
     echo "<h3>### OUTPUT FOR SINGLE PRODUCT ###</h3>";
}
add_action('woocommerce_after_single_product_summary','custom_price_html_single',10,0);

function custom_price_html_category()
{
     echo "<h3>### OUTPUT FOR CATEGORY PRODUCT ###</h3>";
}
add_action('woocommerce_after_shop_loop_item','custom_price_html_category',10,0);

Open in new window

if you are happy with the location of each output on both the category page and the single product page, all that is left to do is change the lines of code starting "echo ...." to show the end of sale date instead of our debug text
it's not showing on the single product page but it is the category page.
are you sure? because this is very basic code that should always work and I even have it running in my test site right now. It may be lower down the page on your single product page. try scrolling down or try doing a search for  ### OUTPUT in your source code as maybe the font is white on white. In other words, it may be difficult to find or even invisible due to font colour but it should be there.
You are correct, it was much further down.  As far as changing it, that is where I get hung up.  Looking at this code

$sales_price_date_to = date("j M y", $sales_price_to);
        return str_replace( '</ins>', ' </ins> <b>(Offer till '.$sales_price_date_to.')</b>', $price );

Open in new window


It is used to output the date but this comes up blank because I need to access a class to get this answer don't I?
ASKER CERTIFIED SOLUTION
Avatar of Adrian Thompson
Adrian Thompson
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
That is perfect. Thanks so much.
Glad to help! Have a nice day