WCML_Exchange_Rates

The WooCommerce Multilingual WCML Exchange Rates class.

Defined (1)

The class is defined in the following location(s).

/inc/currencies/class-wcml-exchange-rates.php  
  1. class WCML_Exchange_Rates{ 
  2.  
  3. /** 
  4. * @var woocommerce_wpml 
  5. */ 
  6. private $woocommerce_wpml; 
  7.  
  8. /** 
  9. * @var array 
  10. */ 
  11. private $services = array(); 
  12.  
  13. /** 
  14. * @var array 
  15. */ 
  16. private $settings; 
  17.  
  18. const cronjob_event = 'wcml_exchange_rates_update'; 
  19.  
  20. function __construct( $woocommerce_wpml ) { 
  21.  
  22. $this->woocommerce_wpml =& $woocommerce_wpml; 
  23.  
  24. $this->initialize_settings(); 
  25.  
  26. // Load built in services 
  27. $this->services['yahoo'] = new WCML_Exchange_Rates_YahooFinance(); 
  28. $this->services['fixierio'] = new WCML_Exchange_Rates_Fixierio(); 
  29. $this->services['currencylayer'] = new WCML_Exchange_Rates_Currencylayer(); 
  30.  
  31. if( is_admin() ) { 
  32. add_action( 'wcml_saved_mc_options', array($this, 'update_exchange_rate_options' ) ); //before init 
  33.  
  34. add_action( 'init', array( $this, 'init' ) ); 
  35.  
  36.  
  37. public function init() { 
  38.  
  39. if( $this->woocommerce_wpml->multi_currency->get_currencies() ) { 
  40.  
  41. if( is_admin() ) { 
  42. add_action( 'wp_ajax_wcml_update_exchange_rates', array( $this, 'update_exchange_rates_ajax') ); 
  43.  
  44. add_filter( 'cron_schedules', array( $this, 'cron_schedules' ) ); 
  45. add_action( self::cronjob_event, array( $this, 'update_exchange_rates' ) ); 
  46.  
  47.  
  48.  
  49. private function initialize_settings() { 
  50.  
  51. if( !isset( $this->woocommerce_wpml->settings['multi_currency']['exchange_rates'] ) ) { 
  52.  
  53. $this->settings = array( 
  54. 'automatic' => 0,  
  55. 'service' => 'yahoo',  
  56. 'lifting_charge' => 0,  
  57. 'schedule' => 'manual',  
  58. 'week_day' => 1,  
  59. 'month_day' => 1 
  60. ); 
  61.  
  62. $this->save_settings(); 
  63.  
  64. } else { 
  65. $this->settings =& $this->woocommerce_wpml->settings['multi_currency']['exchange_rates']; 
  66.  
  67.  
  68. public function get_services() { 
  69. return $this->services; 
  70.  
  71. /** 
  72. * @param $service_id string 
  73. * @param $service WCML_Exchange_Rate_Service 
  74. */ 
  75. public function add_service( $service_id, $service ) { 
  76. $this->services[ $service_id ] = $service; 
  77.  
  78. public function get_settings() { 
  79. return $this->settings; 
  80.  
  81. public function get_setting( $key ) { 
  82. return isset( $this->settings[$key] ) ? $this->settings[$key] : null; 
  83.  
  84. public function save_settings() { 
  85.  
  86. $this->woocommerce_wpml->settings['multi_currency']['exchange_rates'] = $this->settings; 
  87. $this->woocommerce_wpml->update_settings(); 
  88.  
  89. public function save_setting( $key, $value ) { 
  90. $this->settings[$key] = $value; 
  91. $this->save_settings(); 
  92.  
  93. public function update_exchange_rates_ajax() { 
  94.  
  95. $response = array(); 
  96.  
  97. if( wp_create_nonce( 'update-exchange-rates' ) == $_POST['wcml_nonce'] ) { 
  98.  
  99. try { 
  100.  
  101. $rates = $this->update_exchange_rates(); 
  102. $response['success'] = 1; 
  103. $response['last_updated'] = date_i18n( 'F j, Y g:i a', $this->settings['last_updated'] ); 
  104. $response['rates'] = $rates; 
  105.  
  106. } catch ( Exception $e ) { 
  107.  
  108. $response['success'] = 0; 
  109. $response['error'] = $e->getMessage(); 
  110. $response['service'] = $this->settings['service']; 
  111.  
  112.  
  113. } else { 
  114.  
  115. $response['success'] = 0; 
  116. $response['error'] = 'Invalid nonce'; 
  117.  
  118.  
  119. wp_send_json( $response ); 
  120.  
  121. public function update_exchange_rates() { 
  122.  
  123. if( isset( $this->services[ $this->settings['service'] ]) ) { 
  124. $service =& $this->services[ $this->settings['service'] ]; 
  125.  
  126. $currencies = $this->woocommerce_wpml->multi_currency->get_currency_codes(); 
  127. $default_currency = get_option( 'woocommerce_currency' ); 
  128. $secondary_currencies = array_diff( $currencies, array( $default_currency ) ); 
  129.  
  130. try{ 
  131. $rates = $service->get_rates( $default_currency, $secondary_currencies ); 
  132. } catch (Exception $e) { 
  133. if( defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ) { 
  134. error_log( "Exchange rates update error (" . $this->settings['service'] . "): " . $e->getMessage() ); 
  135. throw new Exception( $e->getMessage() ); 
  136. return; 
  137.  
  138. $this->apply_lifting_charge( $rates ); 
  139.  
  140. foreach( $rates as $to => $rate ) { 
  141. if( $rate && is_numeric( $rate ) ) { 
  142. $this->save_exchage_rate( $to, $rate ); 
  143.  
  144. $this->settings['last_updated'] = current_time( 'timestamp' ); 
  145. $this->save_settings(); 
  146.  
  147. return $rates; 
  148.  
  149. public function apply_lifting_charge( &$rates ) { 
  150. foreach( $rates as $k => $rate ) { 
  151. $rates[$k] = round( $rate * ( 1 + $this->settings['lifting_charge'] / 100 ), 4 ); 
  152.  
  153. private function save_exchage_rate( $currency, $rate ) { 
  154.  
  155. $this->woocommerce_wpml->settings['currency_options'][$currency]['previous_rate'] = 
  156. $this->woocommerce_wpml->settings['currency_options'][$currency]['rate']; 
  157. $this->woocommerce_wpml->settings['currency_options'][$currency]['rate'] = $rate; 
  158. $this->woocommerce_wpml->update_settings(); 
  159.  
  160.  
  161. public function get_currency_rate( $currency ) { 
  162. return $this->woocommerce_wpml->settings['currency_options'][$currency]['rate']; 
  163.  
  164. public function update_exchange_rate_options( $post_data ) { 
  165.  
  166. if( isset( $post_data['exchange-rates-automatic'] ) && $post_data['exchange-rates-automatic'] ) { 
  167.  
  168. $this->settings['automatic'] = intval($post_data['exchange-rates-automatic']); 
  169.  
  170. if ( isset($post_data['exchange-rates-service']) ) { 
  171.  
  172. // clear errors for replaced service 
  173. if( $post_data['exchange-rates-service'] != $this->settings['service'] ) { 
  174. $this->services[$this->settings['service']]->clear_last_error(); 
  175.  
  176. $this->settings['service'] = sanitize_text_field( $post_data['exchange-rates-service'] ); 
  177.  
  178.  
  179. if ( isset($post_data['services']) ) { 
  180.  
  181. foreach ( $post_data['services'] as $service_id => $service_data ) { 
  182. foreach( $service_data as $key => $value ) { 
  183. $this->services[$service_id]->save_setting( 'api-key', $value ); 
  184.  
  185.  
  186. $this->settings['lifting_charge'] = is_numeric( $post_data['lifting_charge'] ) ? $post_data['lifting_charge'] : 0; 
  187.  
  188. if ( isset($post_data['update-schedule']) ) { 
  189. $this->settings['schedule'] = sanitize_text_field( $post_data['update-schedule'] ); 
  190.  
  191. if ( isset($post_data['update-time']) ) { 
  192. $this->settings['time'] = sanitize_text_field( $post_data['update-time'] ); 
  193.  
  194. if ( isset($post_data['update-weekly-day']) ) { 
  195. $this->settings['week_day'] = sanitize_text_field( $post_data['update-weekly-day'] ); 
  196.  
  197. if ( isset($post_data['update-monthly-day']) ) { 
  198. $this->settings['month_day'] = sanitize_text_field( $post_data['update-monthly-day'] ); 
  199.  
  200. if ( $this->settings['schedule'] === 'manual' ) { 
  201. $this->delete_update_cronjob(); 
  202. } else { 
  203. $this->enable_update_cronjob(); 
  204.  
  205. } else { 
  206. $this->settings['automatic'] = 0; 
  207. $this->delete_update_cronjob(); 
  208.  
  209. $this->save_settings(); 
  210.  
  211.  
  212.  
  213. public function enable_update_cronjob() { 
  214.  
  215. $schedule = wp_get_schedule( self::cronjob_event ); 
  216.  
  217. if( $schedule != $this->settings['schedule'] ) { 
  218. $this->delete_update_cronjob(); 
  219.  
  220.  
  221. if( $this->settings['schedule'] == 'monthly' ) { 
  222. $current_day = date('j'); 
  223. $days_in_current_month = cal_days_in_month( CAL_GREGORIAN, date('n'), date('Y') ); 
  224.  
  225. if( $this->settings['month_day'] >= $current_day && $this->settings['month_day'] <= $days_in_current_month ) { 
  226. $days = $this->settings['month_day'] - $current_day; 
  227. }else{ 
  228. $days = $days_in_current_month - $current_day + $this->settings['month_day']; 
  229.  
  230. $time_offset = time() + $days * 86400; 
  231. $schedule = 'wcml_' . $this->settings['schedule'] . '_on_' . $this->settings['month_day']; 
  232.  
  233. }elseif( $this->settings['schedule'] == 'weekly' ) { 
  234. $current_day = date('w'); 
  235. if( $this->settings['week_day'] >= $current_day ) { 
  236. $days = $this->settings['week_day'] - $current_day; 
  237. }else{ 
  238. $days = 7 - $current_day + $this->settings['week_day']; 
  239.  
  240. $time_offset = time() + $days * 86400; 
  241. $schedule = 'wcml_' . $this->settings['schedule'] . '_on_' . $this->settings['week_day']; 
  242.  
  243. }else{ 
  244. $time_offset = time(); 
  245. $schedule = $this->settings['schedule']; 
  246.  
  247.  
  248. if( !wp_next_scheduled ( self::cronjob_event ) ) { 
  249. wp_schedule_event( $time_offset, $schedule, self::cronjob_event ); 
  250.  
  251.  
  252. public function delete_update_cronjob() { 
  253.  
  254. wp_clear_scheduled_hook( self::cronjob_event ); 
  255.  
  256.  
  257. public function cron_schedules( $schedules ) { 
  258.  
  259. if( $this->settings['schedule'] == 'monthly' ) { 
  260.  
  261. $month_day = $this->settings['month_day']; 
  262. switch( $month_day ) { 
  263. case 1: $month_day .= 'st'; break; 
  264. case 2: $month_day .= 'nd'; break; 
  265. case 3: $month_day .= 'rd'; break; 
  266. default: $month_day .= 'th'; break; 
  267.  
  268. $current_month = date('n'); 
  269. $days_in_current_month = cal_days_in_month( CAL_GREGORIAN, $current_month, date('Y') ); 
  270. if( $this->settings['month_day'] >= date('j') && $this->settings['month_day'] <= $days_in_current_month ) { 
  271. $interval = 3600 * 24 * $days_in_current_month; 
  272. }else{ 
  273. $month_number = $current_month == 12 ? 1 : $current_month + 1; 
  274. $year_number = $current_month == 12 ? date('Y') + 1 : date('Y'); 
  275. $interval = 3600 * 24 * cal_days_in_month( CAL_GREGORIAN, $month_number, $year_number ); 
  276.  
  277. $schedules['wcml_monthly_on_' . $this->settings['month_day']] = array( 
  278. 'interval' => $interval,  
  279. 'display' => sprintf( __( 'Monthly on the %s', 'woocommerce-multilingual' ), $month_day ),  
  280. ); 
  281.  
  282. } elseif( $this->settings['schedule'] == 'weekly' ) { 
  283.  
  284. global $wp_locale; 
  285. $week_day = $wp_locale->get_weekday( $this->settings['week_day'] ); 
  286. $schedules['wcml_weekly_on_' . $this->settings['week_day']] = array( 
  287. 'interval' => 604800,  
  288. 'display' => sprintf( __( 'Weekly on %s', 'woocommerce-multilingual' ), $week_day ),  
  289. ); 
  290.  
  291.  
  292. return $schedules; 
  293.