You are here:  » Currency Dropdown List and Price Filter


Currency Dropdown List and Price Filter

Submitted by chessyb on Sat, 2015-09-12 11:02 in

Hi,

I pull in feeds at the moment that have GBP as price, is there a simple way of adding a dropdown list so users on the site can select either GBP, USD or Euros that will change the display price to the currency selected and that the currency selected will be remembered across all pages and work with a price filter?

Thanks,

- Quentin

Submitted by support on Sat, 2015-09-12 11:20

Hello Quentin,

Apologies for the delay in your post appearing I do moderate all forum topics / replies before publishing in order to protect customers information / site links etc.

I know you have been running the script for several years now - can you let me know what distribution you are running (displayed on /admin/ > Support Info)?

Thanks!

David.
--
PriceTapestry.com

Submitted by chessyb on Sat, 2015-09-12 14:29

Hi David,

No problems, it's version 14/06A.

Thanks,

- Quentin

Submitted by support on Sat, 2015-09-12 15:42

Thanks Quentin,

That makes it much easier to document with the centralised tapestry_price() function used to display prices throughout the site. I'll compile the changes and post the mods as soon as I'm back online properly on Monday.

Cheers,
David.
--
PriceTapestry.com

Submitted by support on Mon, 2015-09-14 09:17

(edit: updated for 18/06A)

Hello Quentin,

Much of the data source and conversion code is already in place for this by way of the Currency Conversion Filter so this can be used as a base. First of all, set-up a new Automation Tool job to fetch the ECB currency feed to your /feeds/ folder using the following URL:

https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml

And a Filename to Save As... of:

eurofxref-daily.xml

With that in place, there are 3 sections of code to add to handle a drop-down for the currency display form, the form itself, and the modification to display prices in the selected currency.

Firstly, the handling code for the form needs to go before any output has been generated, so that can be placed in html/user_header_before.php. This file is called by html/header.php (if exists) so if you don't currently have that file, create a new file containing the code as follows;

html/user_header_before.php:

<?php
  
if (isset($_POST["currency"]))
  {
    
setcookie("currency",$_POST["currency"],strtotime("+90 days"),"/");
    
header("Location: ".$_SERVER["REQUEST_URI"]);
    exit();
  }
  
$currencyDefault "GBP";
  
$currency = (isset($_COOKIE["currency"])?$_COOKIE["currency"]:$currencyDefault)
?>

This code checks for a currency code being submitted via the form and sets a cookie if present, redirecting the same page as the form was submitted from (using $_SERVER["REQUEST_URI"]). Finally, it sets the default currency (GBP in this case) and sets a $currency variable for use by the rest of the mod.

Next, the form to change currency which you can include anywhere within your template according to your layout, so presumably somehwere in html/header.php, html/footer.php or any other script that is included on every page:

<?php
  $currencyOptions 
= array("GBP","EUR","USD");
  print 
"<form method='POST'>";
  print 
"Show me prices in ";
  print 
"<select name='currency' style='width:auto;' onChange='JavaScript:this.form.submit();'>";
  foreach(
$currencyOptions as $currencyOption)
  {
    
$selected = ($currency==$currencyOption?"selected='selected'":"");
    print 
"<option ".$selected." value='".$currencyOption."'>".$currencyOption."</option>";
  }
  print 
"</select>";
  print 
"</label>";
  print 
"</form>";
?>

Notice how this code uses the current value of $currency to make sure the drop-down is pre-selected with the chosen currency.

Finally, to display converted prices, edit includes/tapestry.php and look for the tapestry_price() function at line 300 (18/06A)

  function tapestry_price($price)
  {
    global $config_currencyHTML;
    global $config_currencySeparator;
    global $config_currencyHTMLAfter;
    $price = str_replace(".",$config_currencySeparator,$price);
    return ($config_currencyHTMLAfter?$price.$config_currencyHTML:$config_currencyHTML.$price);
  }

...and REPLACE with the following:

  function tapestry_price($price)
  {
    global $currencyDefault;
    global $currency;
    global $config_currencySeparator;
    $currencyHTML["GBP"] = "&pound;";
    $currencyHTML["EUR"] = "&euro;";
    $currencyHTML["USD"] = "&dollar;";
    if ($currency != $currencyDefault)
    {
      $price = tapestry_priceConvert($price,$currencyDefault,$currency);
    }
    $price = str_replace(".",$config_currencySeparator,$price);
    return $currencyHTML[$currency].$price;
    return ($config_currencyHTMLAfter?$price.$currencyHTML[$currency]:$currencyHTML[$currency].$price);
  }
  function tapestry_priceConvert($price,$currencyDefault,$currency)
  {
    global $tapestry_priceRates;
    if (!isset($tapestry_priceRates))
    {
      $filename = "feeds/eurofxref-daily.xml";
      $parser = xml_parser_create();
      xml_set_element_handler($parser, "tapestry_priceConvertXMLElement", "");
      $xml = file_get_contents($filename);
      $tapestry_priceRates = array();
      $tapestry_priceRates["EUR"] = "1";
      xml_parse($parser,$xml,TRUE);
    }
    $EUR = $price * (1/$tapestry_priceRates[$currencyDefault]);
    return tapestry_decimalise($EUR * $tapestry_priceRates[$currency]);
  }
  function tapestry_priceConvertXMLElement($parser,$name,$attribs)
  {
    global $tapestry_priceRates;
    if (isset($attribs["CURRENCY"]))
    {
      $tapestry_priceRates[$attribs["CURRENCY"]] = $attribs["RATE"];
    }
  }

Although the above code involves parsing the exchange rate feed, this is only done once per page regardless of how many prices there are to convert.

Hope this helps!

Cheers,
David.
--
PriceTapestry.com

Submitted by chessyb on Mon, 2015-09-14 11:27

Hi David,

Thanks for the code, I updated my site to include everything above and I can see the cookie being set and page refreshing, but the prices are still displayed as GPB no matter what I select.

I currently use on the search results page to display prices:

<?php if ($product["normalprice"] =="0.00" || $product["normalprice"]=="") { ?>
<span style="float: left; margin-left: 5px; color: #231F20;"><strong><?php print $config_currencyHTML.$product["price"]; ?></strong></span>
<?php }elseif ($product["normalprice"] > $product["price"]) { ?>
<span style="float: left; margin-left: 5px; color: #231F20; text-decoration: line-through;"><strong><?php print $config_currencyHTML.$product["normalprice"]; ?></strong></span><span style="float: left; margin-left: 5px; color: #ff0000;"><strong><?php print $config_currencyHTML.$product["price"]; ?></strong></span><?php ?>

This is a slight change for the 'display sale price mod' you posted up in another thread. Could this be the reason why the prices do not change?

Thanks,

- Quentin

Submitted by support on Mon, 2015-09-14 12:03

Hi Quentin,

You just need to convert your code to use the tapestry_price() function instead of displaying the price values directly - have a go with:

<?php if ($product["normalprice"] =="0.00" || $product["normalprice"]=="") { ?>
<span style="float: left; margin-left: 5px; color: #231F20;"><strong><?php print tapestry_price($product["price"]); ?></strong></span>
<?php }elseif ($product["normalprice"] > $product["price"]) { ?>
<span style="float: left; margin-left: 5px; color: #231F20; text-decoration: line-through;"><strong><?php print tapestry_price($product["normalprice"]); ?></strong></span><span style="float: left; margin-left: 5px; color: #ff0000;"><strong><?php print tapestry_price($product["price"]); ?></strong></span><?php ?>

Cheers,
David.
--
PriceTapestry.com

Submitted by chessyb on Mon, 2015-09-14 13:29

Hi David,

Yes, that did the trick and made it work fine. Thank you very much for sorting this for me and hopefully other people can make of it as well.

Thanks,

- Quentin

Submitted by chessyb on Thu, 2015-09-17 15:19

Hi David,

Is it possible to get this mod to work with the filter mod which I took from another thread please as at the moment if tries to filter price results based on GBP only and doesn't take into account the currency being used.

Here is my filter code that appears on search results:

{code saved}

Thanks,

- Quentin

Submitted by support on Thu, 2015-09-17 16:13

Hi Quentin,

Sure - it requires the reverse of the currency conversion when creating the filter SQL, but also a mod to your filter script to display the selected currency value of the filter rather than the converted version.

Firstly however, the code to populate $currency and handle the form submission previously added to html/user_header_before.php now needs to occur earlier in the script, since the the filter SQL etc. is created before the header is included. So remove the code from html/user_header_before.php (or just delete the file if you were not already using it) and instead paste into the end of includes/common.php. Make sure that there is no white space or new lines between the existing PHP code in includes/common.php and the new code.

Next, in search.php look for the following code around line 24:

    $minPrice = sprintf("%.2f",$_GET["minPrice"]);

...and REPLACE with:

    $minPrice = sprintf("%.2f",$_GET["minPrice"]);
    if ($currency != $currencyDefault)
    {
      $minPrice = tapestry_priceConvert($minPrice,$currency,$currencyDefault);
    }

And similarly for maxPrice, look for the following code around line 32:

    $maxPrice = sprintf("%.2f",$_GET["maxPrice"]);

...and REPLACE with:

    $maxPrice = sprintf("%.2f",$_GET["maxPrice"]);
    if ($currency != $currencyDefault)
    {
      $maxPrice = tapestry_priceConvert($maxPrice,$currency,$currencyDefault);
    }

Finally, in your filter code look, SEARCH and REPLACE as follows:

Search:
$minPrice
Replace:
$_GET["minPrice"]

and

Search:
$maxPrice
Replace:
$_GET["maxPrice"]

Hope this helps!

Cheers,
David.
--
PriceTapestry.com

Submitted by chessyb on Fri, 2015-09-18 09:01

Hi David,

Works perfectly as always! Thanks for your help.

- Quentin

Submitted by shaunmac on Mon, 2016-12-19 02:06

I have done the above and when i go to change the currency the page go blank. see link i have the test code on. {link saved}
just above the logo

Submitted by support on Mon, 2016-12-19 10:52

Hello Shaun,

Your page is generating some output before the form handler in html/user_header_before.php is being processed, meaning that the header() call cannot set the Location header in order to redirect the user back to the page they were on.

If you submit the change currency form and then and use your browser's View > Source function you'll see the output - I think it's part of a Facebook widget, and then check where this being output , it may be at the very top of html/header.php before html/user_header_before.php is included. Once located, move the code inside your main header as currently it looks like it is being output before the opening <html> tag on all pages...

Hope this helps!

Cheers,
David.
--
PriceTapestry.com

Submitted by shaunmac on Mon, 2016-12-19 14:43

Ok I looked at the page source I seen the Facebook code causing the error. I moved the code to right before the closing as well as removed it altogether. Now it does the same thing (blank page) but this time if I check the source code it is blank. It does this with or without the facebook code.
Thanks,
Shaun

Submitted by support on Mon, 2016-12-19 14:59

Hi Shaun,

When this happens, i.e. form handling code does not redirect because of output already having been generated, it is normally down to one of two things;

i) White space (spaces or new lines) accidentally appearing in top level or included files, in other words, anything outside of the opening <?php and closing ?> tags. To check this, open each .php file into your text editor and make sure that there is nothing visible before the opening <?php at the top of the file, and the closing ?> at the end. To make absolutely sure, move your cursor to the end of the file and if you are able to edit beyond the closing ?> use DELETE until the closing ?>, then Save.

ii) UTF-8 Byte Order Markers inserted by your text editor at the top of the file. Check this at the same time as the above. When checking the first file for any white space, use your text editor's Save As... instead of Save function, and on the Save As... dialog, look for a Character Encoding drop-down. If you see options including "UTF-8", and "UTF-8 NO-BOM", ensure that the "NO-BOM" option is selected, as byte order marking should not be included in source files (they are intended for human readable documents).

To minimise the number of files you need to check, test on a product page, check products.php first, followed by each of the files in the includes/ folder, and then html/user_header_before.php / html/header.php which should cover it.

Hope this helps!

Cheers,
David.
--
PriceTapestry.com

Submitted by shaunmac on Thu, 2016-12-22 14:15

Ok I believe I have found and fixed the issue with a blank page being displayed but now I am having the same issue as Quentin above. If I change the currency it does not change the price.
{link saved}
Thanks,
Shaun

Submitted by shaunmac on Thu, 2016-12-22 14:28

Ok I got it fixed to show the current price but for some reason I no longer have a . between my numbers. they show as 1234 instead of 12.34

Submitted by shaunmac on Thu, 2016-12-22 14:36

Maybe I spoke to soon. The currency converter seems to work on the search pages but my product page is still not changing.
Search that seems to work. {link saved}
Product page that does not. {link saved}
I believe it is because I am using a 3rd party theme the price tapestry prices change but the other prices do not. So would there be a way to change the product page price? I also have a custom field called price each would I be able to get this to change with it?

Submitted by support on Tue, 2016-12-27 08:47

Hello Shaun,

Regarding the missing decimal point, I noticed a missing global declaration (for $config_currencySeparator) in the modified tapestry_price() function, corrected in this comment above.

With that in place, your search results converted prices should then appear correctly.

Regarding the product page, what it will be is that your 3rd party template is generating the price output directly instead of using the tapestry_price() function. In your html/prices.php, search for the following:

$config_currencyHTML.$product["price"];

...and REPLACE with:

tapestry_price($product["price"]);

That should be all it is!

Cheers,
David.
--
PriceTapestry.com