/** * Helper class to allow 3rd party plugins to implement multi-currency * capabilities. The class was designed to work with the Aelia Currency Switcher, * but it's generic enough to be adapted to other solutions. * * Need a consultation? Find us on Codeable: https://bit.ly/aelia_codeable * * @author Aelia * @link https://aelia.co * @link https://aelia.co/shop/currency-switcher-woocommerce/ */ class Advanced_CurrencySwitcher_Integration { // @var string Shop's base currency. Used for caching. protected static $_base_currency; /** * Returns shop's base currency. This method implements some simple caching, * to avoid calling get_option() too many times. * * @return string Shop's base currency. */ protected static function shop_base_currency() { if(empty(self::$_base_currency)) { self::$_base_currency = get_option('woocommerce_currency'); } return self::$_base_currency; } /** * Returns the list of the currencies enabled in the Aelia Currency Switcher. * If the Currency Switcher is not installed, or active, then the list will * only contain the shop base currency. * * @return array An array of currency codes. */ public static function enabled_currencies() { return apply_filters('wc_aelia_cs_enabled_currencies', array(self::shop_base_currency())); } /** * Returns a product's base currency. A product's base currency is the point * of reference to calculate other prices, and it can differ from shop's base * currency. * For example, if a shop's base currency is USD, a product's base currency * can be EUR. In such case, product prices in other currencies can be * calculated automatically, as long as the EUR one is entered. * * @param int product_id A product ID. * @param string default_currency The default currency to use if the product * doesn't have a base currency. * @return string A currency code. */ public static function get_product_base_currency($product_id, $default_currency = null) { if(empty($default_currency)) { $default_currency = self::shop_base_currency(); } return apply_filters('wc_aelia_cs_product_base_currency', $default_currency, $product_id); } /** * Advanced integration with WooCommerce Currency Switcher, developed by Aelia * (https://aelia.co). This method can be used by any 3rd party plugin to * return prices in the active currency. * * @param double price The source price. * @param string to_currency The target currency. If empty, the active currency * is taken. * @param string from_currency The source currency. If empty, WooCommerce base * currency is taken. * @return double The price converted from source to destination currency. */ public static function get_price_in_currency($price, $to_currency = null, $from_currency = null) { if(empty($from_currency)) { $from_currency = self::shop_base_currency(); } if(empty($to_currency)) { $to_currency = get_woocommerce_currency(); } return self::convert($price, $to_currency, $from_currency); } /** * Converts an amount from one currency to another, using exchange rates. * * @param float amount The amount to convert. * @param string to_currency The destination currency. * @param string from_currency The source currency. * @return float The amount converted to the target destination currency. */ public static function convert($amount, $to_currency, $from_currency = null) { return apply_filters('wc_aelia_cs_convert', $amount, $from_currency, $to_currency); } /** * Returns a list of prices that should be a applied to a product for each currency. * This is a example of how the fixed-price logic could be implemented. The * actual implementation depends on the specifics of the product being proceseed, * on how the prices were stored, and so on. * * @param WC_Product product The product for which the prices should be retrieved. * @param string currency The currency for which the product prices will be retrieved. * @return array An array of prices. */ protected function get_product_prices_for_currency($product, $currency) { // Load the custom prices in the specified currency $prices = array( 'my_custom_price' => get_post_meta($product->id, '_my_custom_price_' . $currency, true), 'my_other_custom_price' => get_post_meta($product->id, 'my_other_custom_price_' . $currency, true), ); return $prices; } /** * Performs a simple test conversion of an arbitrary value, using exchange * rates. */ public function test() { $price = 123; // Just call the get_price_in_currency() method. This will use automatic conversion return self::get_price_in_currency($price); } /** * Alter the callbacks used by the Currency Switcher, replacing the callback * for a "my_custom_product" type with a custon one. * * @param callable convert_callback The original callback. * @param WC_Product product The callback being converted. * @return callable The callback that will convert the product's prices. */ public function wc_aelia_currencyswitcher_product_convert_callback($convert_callback, $product) { if($product->product_type === 'my_custom_product') { $convert_callback = array($this, 'convert_my_custom_product'); } return $convert_callback; } /** * Converts the prices of a custom product to the specified currency. * * @param WC_Product product A variable product. * @param string currency A currency code. * @return WC_Product The product with converted prices. */ public function convert_my_custom_product($product, $currency) { /* Here you can implement your custom logic to convert the prices. * The two lines below are just an example. Here you can do anything you * want with the product, to ensure that its prices are converted correctly. */ // Load the product prices that were entered manually for the specified currency $product_prices_for_currency = $this->get_product_prices_for_currency($product, $currency); // If prices were entered manually, then they will be used as they are. If not, // product's price in base currency will be converted using exchange rates $product->my_custom_price = isset($product_prices_for_currency['my_custom_price']) ? $product_prices_for_currency['my_custom_price'] : self::get_price_in_currency($product->my_custom_price); $product->my_other_custom_price = isset($product_prices_for_currency['my_other_custom_price']) ? $product_prices_for_currency['my_other_custom_price'] : self::get_price_in_currency($product->my_other_custom_price); return $product; } public function __construct() { add_filter('wc_aelia_currencyswitcher_product_convert_callback', array($this, 'wc_aelia_currencyswitcher_product_convert_callback'), 10, 2); } }