<?php /** * @package VikBooking * @subpackage com_vikbooking * @author Alessio Gaggii - E4J srl * @copyright Copyright (C) 2022 E4J srl. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE * @link https://vikwp.com */ defined('ABSPATH') or die('No script kiddies please!'); /** * Class handler for admin widget "currency converter". * * @since 1.15.4 (J) - 1.5.10 (WP) */ class VikBookingAdminWidgetCurrencyConverter extends VikBookingAdminWidget { /** * The instance counter of this widget. * * @var int */ protected static $instance_counter = -1; /** * Class constructor will define the widget name and identifier. */ public function __construct() { // call parent constructor parent::__construct(); $this->widgetName = JText::translate('VBO_W_CURRCONV_TITLE'); $this->widgetDescr = JText::translate('VBO_W_CURRCONV_DESCR'); $this->widgetId = basename(__FILE__, '.php'); // define widget and icon and style name $this->widgetIcon = '<i class="' . VikBookingIcons::i('funnel-dollar') . '"></i>'; $this->widgetStyleName = 'violet'; // load widget's settings $this->widgetSettings = $this->loadSettings(); if (!is_object($this->widgetSettings)) { $this->widgetSettings = new stdClass; } } /** * Custom method for this widget only to exchange the rates between currencies. * The method is called by the admin controller through an AJAX request. * The visibility should be public, it should not exit the process, and * any content sent to output will be returned to the AJAX response. * In this case we return an array because this method requires "return":1. * * It's the actual rendering of the widget. */ public function exchangeRates() { $wrapper = VikRequest::getString('wrapper', '', 'request'); $from_currency = VikRequest::getString('from_currency', '', 'request'); $to_currency = VikRequest::getString('to_currency', '', 'request'); $amount = VikRequest::getFloat('amount', 1, 'request'); if (empty($from_currency) || empty($to_currency)) { // use the website default currency $from_currency = VikBooking::getCurrencyName($iso = true); // use the default to currency $to_currency = !strcasecmp($from_currency, 'EUR') ? 'USD' : 'EUR'; } if ($amount <= 0) { $amount = 1; } // import currency converter class VikBooking::import('currencyconverter'); // get numbering format data $format = VikBooking::getNumberFormatData(); // get the instance of the converter object $converter = new VboCurrencyConverter($from_currency, $to_currency, [$amount], explode(':', $format)); // collect values $converter_error = null; $exchanged = null; $exchange_rate = null; // make sure from currency is supported for conversion if (!$converter->currencyExists($from_currency)) { $converter_error = sprintf('Currency %s is not supported', $from_currency); } elseif (!$converter->currencyExists($to_currency)) { $converter_error = sprintf('Currency %s is not supported', $to_currency); } if (!$converter_error) { // exchange the given rates $exchanged = $converter->convert($get_floats = true); } if (!$converter_error && (!is_array($exchanged) || !count($exchanged))) { // something went wrong during the conversion $converter_error = $converter->getError(); $converter_error = empty($converter_error) ? 'Error while converting rates' : $converter_error; } else { // get the conversion rate $exchange_rate = $converter->getConversionRate(); // update widget's settings with the lastly used currencies $this->widgetSettings->from_currency = $from_currency; $this->widgetSettings->to_currency = $to_currency; $this->updateSettings(json_encode($this->widgetSettings)); } // start output buffering ob_start(); ?> <div class="vbo-widget-currconv-result-data"> <?php if ($converter_error || empty($exchanged)) { ?> <p class="err"><?php echo $converter_error; ?></p> <?php } else { ?> <p class="info"><?php echo JText::sprintf('VBO_CONV_RES_OTA_CURRENCY_EXC', $from_currency . ' ' . $amount, $to_currency . ' ' . $exchanged[0]); ?></p> <p class="info"><?php echo JText::translate('VBO_CONV_RATE'); ?> <span class="badge badge-primary"><?php echo $exchange_rate; ?></span></p> <?php } ?> </div> <?php // get the HTML buffer $html_content = ob_get_contents(); ob_end_clean(); // return an associative array of values return [ 'html' => $html_content, 'exchanged' => $exchanged, 'exchange_rate' => $exchange_rate, ]; } /** * Preload the necessary CSS/JS assets. * * @return void */ public function preload() { // load assets $this->vbo_app->loadSelect2(); } public function render(?VBOMultitaskData $data = null) { // increase widget's instance counter static::$instance_counter++; // check whether the widget is being rendered via AJAX when adding it through the customizer $is_ajax = $this->isAjaxRendering(); // generate a unique ID for the sticky notes wrapper instance $wrapper_instance = !$is_ajax ? static::$instance_counter : rand(); $wrapper_id = 'vbo-widget-currconv-' . $wrapper_instance; // import currency converter class if (!VikBooking::import('currencyconverter')) { // display nothing return; } // the website default currency $def_currency = !empty($this->widgetSettings->from_currency) ? $this->widgetSettings->from_currency : VikBooking::getCurrencyName($iso = true); // the default to currency $def_to_currency = !strcasecmp($def_currency, 'EUR') ? 'USD' : 'EUR'; if (!empty($this->widgetSettings->to_currency)) { $def_to_currency = $this->widgetSettings->to_currency; } // get numbering format data $format = VikBooking::getNumberFormatData(); // get the instance of the converter object $converter = new VboCurrencyConverter($def_currency, $def_to_currency, [1], explode(':', $format)); // grab all currency names $all_currencies = $converter->getCurrencyNames(); ?> <div class="vbo-admin-widget-wrapper"> <div class="vbo-admin-widget-head"> <h4><?php echo $this->widgetIcon; ?> <span><?php echo $this->widgetName; ?></span></h4> </div> <div id="<?php echo $wrapper_id; ?>" class="vbo-widget-currconv-wrap" data-instance="<?php echo $wrapper_instance; ?>"> <div class="vbo-widget-currconv-filters"> <div class="vbo-widget-currconv-filters-main"> <div class="vbo-widget-currconv-filter vbo-widget-currconv-filter-from"> <label for="vbo-widget-currconv-from-<?php echo $wrapper_instance; ?>"><?php echo JText::translate('VBO_CONV_FROM'); ?></label> <select id="vbo-widget-currconv-from-<?php echo $wrapper_instance; ?>" class="vbo-widget-currconv-sel vbo-widget-currconv-from"> <?php foreach ($all_currencies as $code => $name) { ?> <option value="<?php echo $code; ?>"<?php echo !strcasecmp($def_currency, $code) ? ' selected="selected"' : ''; ?>><?php echo $name; ?></option> <?php } ?> </select> </div> <div class="vbo-widget-currconv-filter vbo-widget-currconv-filter-amount"> <label for="vbo-widget-currconv-amount-<?php echo $wrapper_instance; ?>"><?php echo JText::translate('VBPSHOWSEASONSFOUR'); ?></label> <input type="number" id="vbo-widget-currconv-amount-<?php echo $wrapper_instance; ?>" class="vbo-widget-currconv-amount" min="0.01" step="any" value="1" /> </div> </div> <div class="vbo-widget-currconv-filters-secondary"> <div class="vbo-widget-currconv-filter vbo-widget-currconv-filter-to"> <label for="vbo-widget-currconv-to-<?php echo $wrapper_instance; ?>"><?php echo JText::translate('VBO_CONV_TO'); ?></label> <select id="vbo-widget-currconv-to-<?php echo $wrapper_instance; ?>" class="vbo-widget-currconv-sel vbo-widget-currconv-to"> <?php foreach ($all_currencies as $code => $name) { ?> <option value="<?php echo $code; ?>"<?php echo !strcasecmp($def_to_currency, $code) ? ' selected="selected"' : ''; ?>><?php echo $name; ?></option> <?php } ?> </select> </div> </div> <div class="vbo-widget-currconv-filters-submit"> <div class="vbo-widget-currconv-filter vbo-widget-currconv-filter-submit"> <button type="button" class="btn vbo-config-btn" onclick="vboWidgetCurrConvCalc('<?php echo $wrapper_id; ?>');"><?php VikBookingIcons::e('exchange-alt'); ?><?php echo JText::translate('VBRATESOVWRATESCALCULATORCALC'); ?></button> </div> </div> </div> <div class="vbo-widget-currconv-result"></div> </div> </div> <?php if (static::$instance_counter === 0 || $is_ajax) { /** * Print the JS code only once for all instances of this widget. * The real rendering is made through AJAX, not when the page loads. */ ?> <script type="text/javascript"> /** * Perform the request to exchange rates. */ function vboWidgetCurrConvExchange(wrapper) { var widget_instance = jQuery('#' + wrapper); if (!widget_instance.length) { return false; } // get vars for making the request var from_currency = widget_instance.find('.vbo-widget-currconv-from').val(); var to_currency = widget_instance.find('.vbo-widget-currconv-to').val(); var amount = widget_instance.find('.vbo-widget-currconv-amount').val(); // the widget method to call var call_method = 'exchangeRates'; // make a request to load the available room rates VBOCore.doAjax( "<?php echo $this->getExecWidgetAjaxUri(); ?>", { widget_id: "<?php echo $this->getIdentifier(); ?>", call: call_method, return: 1, from_currency: from_currency, to_currency: to_currency, amount: amount, tmpl: "component" }, function(response) { try { var obj_res = typeof response === 'string' ? JSON.parse(response) : response; if (!obj_res.hasOwnProperty(call_method) || !obj_res[call_method]) { console.error('Unexpected JSON response', obj_res); return false; } // replace HTML with exchange rates widget_instance.find('.vbo-widget-currconv-result').html(obj_res[call_method]['html']); } catch(err) { console.error('could not parse JSON response', err, response); } }, function(error) { // empty result container widget_instance.find('.vbo-widget-currconv-result').html(''); console.error(error); } ); } /** * Calculate the exchange rates. */ function vboWidgetCurrConvCalc(wrapper) { var widget_instance = jQuery('#' + wrapper); if (!widget_instance.length) { return false; } // show loading spinner widget_instance.find('.vbo-widget-currconv-result').html('<p style="text-align: center;"><?php VikBookingIcons::e('circle-notch', 'fa-spin fa-fw'); ?></p>'); // load data vboWidgetCurrConvExchange(wrapper); } </script> <?php } ?> <script type="text/javascript"> jQuery(function() { // render select2 jQuery('#<?php echo $wrapper_id; ?>').find('.vbo-widget-currconv-sel').select2({ width: "200px", }); }); </script> <?php } }