/classes/class.wc-pf.php

  1. <?php 
  2. /** 
  3. * WooCommerce Payment Fees 
  4. * Copyright (C) 2014 Pinch Of Code. All rights reserved. 
  5. * 
  6. * This program is free software; you can redistribute it and/or 
  7. * modify it under the terms of the GNU General Public License 
  8. * as published by the Free Software Foundation; either version 2 
  9. * of the License, or (at your option) any later version. 
  10.   
  11. * This program is distributed in the hope that it will be useful,  
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of 
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
  14. * GNU General Public License for more details. 
  15.   
  16. * You should have received a copy of the GNU General Public License 
  17. * along with this program; if not, write to the Free Software 
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 
  19. * 
  20. * Contact the author at info@pinchofcode.com 
  21. */ 
  22.  
  23. /** 
  24. * Main plugin class 
  25. */ 
  26.  
  27. if( !class_exists( 'WooCommerce_Payment_Fees' ) ) : 
  28. class WooCommerce_Payment_Fees { 
  29. /** 
  30. * @var string 
  31. */ 
  32. public $version; 
  33.  
  34. /** 
  35. * @var string 
  36. */ 
  37. public $suffix; 
  38.  
  39. /** 
  40. * @var string 
  41. */ 
  42. public $plugin_url; 
  43.  
  44. /** 
  45. * @var string 
  46. */ 
  47. public $plugin_path; 
  48.  
  49. /** 
  50. * @var array 
  51. */ 
  52. public $gateways; 
  53.  
  54. /** 
  55. * @var object 
  56. */ 
  57. public $current_gateway; 
  58.  
  59. /** 
  60. * @var string 
  61. */ 
  62. public $current_extra_charge_type; 
  63.  
  64. /** 
  65. * @var double 
  66. */ 
  67. public $current_extra_charge_amount; 
  68.  
  69. /** 
  70. * Constructor 
  71. * 
  72. * @param string $id Order id 
  73. */ 
  74. public function __construct() { 
  75. global $pagenow; 
  76.  
  77. $this->version = '1.5'; 
  78. $this->suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; 
  79. $this->plugin_url = $this->plugin_url(); 
  80. $this->plugin_path = $this->plugin_path(); 
  81. $this->gateways = WC()->payment_gateways->payment_gateways(); 
  82. $this->current_gateway = null; 
  83. $this->current_extra_charge_type = ''; 
  84. $this->current_extra_charge_amount = 0; 
  85. $this->current_extra_charge_max_cart_value = 0; 
  86.  
  87. //Load plugin languages 
  88. load_plugin_textdomain( 'wc_pf', false, dirname( dirname( plugin_basename( __FILE__ ) ) ) . '/i18n/' ); 
  89.  
  90. //Hooks & Filters 
  91. add_action( 'woocommerce_cart_calculate_fees', array( $this, 'calculate_order_totals' ) ); 
  92. add_action( 'wp_enqueue_scripts' , array( $this, 'enqueue_scripts_frontend' ) ); 
  93.  
  94. if( is_admin() ) { 
  95. add_action( 'admin_head', array( $this, 'manage_form_fields' ) ); 
  96.  
  97. public function enqueue_scripts_frontend() { 
  98. $min = !defined( 'SCRIPT_DEBUG' ) || !SCRIPT_DEBUG ? '.min' : ''; 
  99.  
  100. if( !is_checkout() ) { return; } 
  101.  
  102. wp_enqueue_script( 'wc-pf-checkout', $this->plugin_url . '/assets/js/checkout' . $min . '.js', array( 'jquery' ), $this->version, true ); 
  103.  
  104. /** 
  105. * Manage gateways form fields 
  106. * 
  107. * @return string 
  108. */ 
  109. public function manage_form_fields() { 
  110. $current_tab = !isset( $_GET['tab'] ) || empty( $_GET['tab'] ) ? '' : sanitize_text_field( urldecode( $_GET['tab'] ) ); 
  111. $current_section = !isset( $_GET['section'] ) || empty( $_GET['section'] ) ? '' : sanitize_text_field( urldecode( $_GET['section'] ) ); 
  112. $current_gateway = ''; 
  113. $charge_amount = 0.00; 
  114. $charge_type = 'fixed'; 
  115. $max_cart_value = 0.00; 
  116.  
  117. if( $current_tab == 'checkout' && !empty( $current_section ) ) { 
  118. foreach( $this->gateways as $gateway ) { 
  119. if( strtolower( get_class( $gateway ) ) == $current_section ) { 
  120. $current_gateway = $gateway->id; 
  121. break; 
  122.  
  123. $html = $this->manage_form_fields_for_basic_gateways( $current_gateway ); 
  124. $html = str_replace( array( "\r", "\n" ) , '', trim( $html ) ); 
  125. $html = str_replace( "'", '"', $html ); 
  126.  
  127. wc_enqueue_js( "$( '.form-table:last' ).after( '" . $html . "' );" ); 
  128.  
  129. /** 
  130. * Prints fees form on the gateways settings page for all the gateways NOT USING credit/debit cards. 
  131. * 
  132. * @param string $current_gateway 
  133. * @return string 
  134. */ 
  135. public function manage_form_fields_for_basic_gateways( $current_gateway ) { 
  136. if( isset( $_REQUEST['save'] ) ) { 
  137. update_option( $this->get_option_id( $current_gateway, 'name' ), $_REQUEST[ $this->get_option_id( $current_gateway, 'name' ) ] ); 
  138. update_option( $this->get_option_id( $current_gateway, 'amount' ), $_REQUEST[ $this->get_option_id( $current_gateway, 'amount' ) ] ); 
  139. update_option( $this->get_option_id( $current_gateway, 'type' ), $_REQUEST[ $this->get_option_id( $current_gateway, 'type' ) ] ); 
  140. update_option( $this->get_option_id( $current_gateway, 'max_cart_value' ), $_REQUEST[ $this->get_option_id( $current_gateway, 'max_cart_value' ) ] ); 
  141. update_option( $this->get_option_id( $current_gateway, 'calc_taxes' ), $_REQUEST[ $this->get_option_id( $current_gateway, 'calc_taxes' ) ] ); 
  142.  
  143. $fee_name = get_option( $this->get_option_id( $current_gateway, 'name' ) ); 
  144. $charge_amount = get_option( $this->get_option_id( $current_gateway, 'amount' ) ); 
  145. $charge_type = get_option( $this->get_option_id( $current_gateway, 'type' ) ); 
  146. $max_cart_value = get_option( $this->get_option_id( $current_gateway, 'max_cart_value' ) ); 
  147. $calc_taxes = get_option( $this->get_option_id( $current_gateway, 'calc_taxes' ) ); 
  148.  
  149. ob_start() ?> 
  150. <h3><?php _e( 'Extra charge for this payment method', 'wc_pf' ) ?></h3> 
  151. <p><?php _e( 'Optionally add extra charge fixed/percentage amount to this payment method.', 'wc_pf' ) ?></p> 
  152. <table class="form-table"> 
  153. <tbody> 
  154. <tr valign="top"> 
  155. <th scope="row" class="titledesc"><label for="woocommerce_<?php echo $current_gateway ?>_extra_charge_name"><?php _e( 'Fee name', 'wc_pf' ) ?></label></th> 
  156. <td class="forminp"> 
  157. <fieldset> 
  158. <legend class="screen-reader-text"><span><?php _e( 'Fee name', 'wc_pf' ) ?></span></legend> 
  159. <input class="input-text regular-input " type="text" name="woocommerce_<?php echo $current_gateway ?>_extra_charge_name" id="woocommerce_<?php echo $current_gateway ?>_extra_charge_name" value="<?php echo $fee_name ?>" placeholder="<?php _e( 'Payment method fee', 'wc_pf' ) ?>"> 
  160. </fieldset> 
  161. </td> 
  162. </tr> 
  163. <tr valign="top"> 
  164. <th scope="row" class="titledesc"><label for="woocommerce_<?php echo $current_gateway ?>_extra_charge_amount"><?php _e( 'Extra charge amount', 'wc_pf' ) ?></label></th> 
  165. <td class="forminp"> 
  166. <fieldset> 
  167. <legend class="screen-reader-text"><span><?php _e( 'Extra charge amount', 'wc_pf' ) ?></span></legend> 
  168. <input class="input-text regular-input " type="number" name="woocommerce_<?php echo $current_gateway ?>_extra_charge_amount" id="woocommerce_<?php echo $current_gateway ?>_extra_charge_amount" style="width:70px" value="<?php echo $charge_amount ?>" placeholder="0.00" min="0" step="0.01"> 
  169. </fieldset> 
  170. </td> 
  171. </tr> 
  172. <tr valign="top"> 
  173. <th scope="row" class="titledesc"><label for="woocommerce_<?php echo $current_gateway ?>_extra_charge_type"><?php _e( 'Fee type', 'wc_pf' ) ?></label></th> 
  174. <td class="forminp"> 
  175. <fieldset> 
  176. <legend class="screen-reader-text"><span><?php _e( 'Extra charge type', 'wc_pf' ) ?></span></legend> 
  177. <select name="woocommerce_<?php echo $current_gateway ?>_extra_charge_type" id="woocommerce_<?php echo $current_gateway ?>_extra_charge_type" style="" class="select "> 
  178. <option value="fixed" <?php selected( $charge_type, 'fixed' ) ?>><?php _e( 'Fixed', 'wc_pf' ) ?></option> 
  179. <option value="percentage"<?php selected( $charge_type, 'percentage' ) ?>><?php _e( 'Percentage', 'wc_pf' ) ?></option> 
  180. </select> 
  181. </fieldset> 
  182. </td> 
  183. </tr> 
  184. <tr valign="top"> 
  185. <th scope="row" class="titledesc"><label for="woocommerce_<?php echo $current_gateway ?>_extra_charge_max_cart_value"><?php _e( 'Maximum cart value to which adding fee:', 'wc_pf' ) ?></label></th> 
  186. <td class="forminp"> 
  187. <fieldset> 
  188. <legend class="screen-reader-text"><span><?php _e( 'Maximum cart value for adding fee:', 'wc_pf' ) ?></span></legend> 
  189. <input class="input-text regular-input " type="number" name="woocommerce_<?php echo $current_gateway ?>_extra_charge_max_cart_value" id="woocommerce_<?php echo $current_gateway ?>_extra_charge_max_cart_value" style="width:70px" value="<?php echo $max_cart_value ?>" placeholder="0.00" min="0" step="0.01"> 
  190. </fieldset> 
  191. </td> 
  192. </tr> 
  193. <tr valign="top"> 
  194. <th scope="row" class="titledesc"><?php _e( 'Includes taxes', 'wc_pf' ) ?></th> 
  195. <td class="forminp"> 
  196. <fieldset> 
  197. <legend class="screen-reader-text"><span><?php _e( 'Calculate taxes on this fee', 'wc_pf' ) ?></span></legend> 
  198. <select name="woocommerce_<?php echo $current_gateway ?>_extra_charge_calc_taxes" id="woocommerce_<?php echo $current_gateway ?>_extra_charge_calc_taxes" style="" class="select"> 
  199. <option value="no-tax" <?php selected( 'no-tax', $calc_taxes ) ?>><?php _e( 'Do not calculate taxes', 'wc_pf' ) ?></option> 
  200. <option value="tax-incl" <?php selected( 'tax-incl', $calc_taxes ) ?>><?php _e( 'The fee is taxes included', 'wc_pf' ) ?></option> 
  201. <option value="tax-excl" <?php selected( 'tax-excl', $calc_taxes ) ?>><?php _e( 'The fee is taxes excluded', 'wc_pf' ) ?></option> 
  202. </select> 
  203. </fieldset> 
  204. </td> 
  205. </tr> 
  206. </tbody> 
  207. </table> 
  208. <?php 
  209.  
  210. return ob_get_clean(); 
  211.  
  212. /** 
  213. * Add extra charge to cart totals 
  214. * 
  215. * @param double $totals 
  216. * return double 
  217. */ 
  218. public function calculate_order_totals( $cart ) { 
  219. if( !defined( 'WOOCOMMERCE_CHECKOUT' ) ) { return; } 
  220.  
  221. $available_gateways = WC()->payment_gateways->get_available_payment_gateways(); 
  222. $current_gateway = WC()->session->chosen_payment_method; 
  223. $subtotal = $cart->cart_contents_total; 
  224.  
  225. if( !empty( $available_gateways ) ) { 
  226. //Get the current gateway 
  227. if ( isset( $current_gateway ) && isset( $available_gateways[ $current_gateway ] ) ) { 
  228. $current_gateway = $available_gateways[ $current_gateway ]; 
  229. } elseif ( isset( $available_gateways[ get_option( 'woocommerce_default_gateway' ) ] ) ) { 
  230. $current_gateway = $available_gateways[ get_option( 'woocommerce_default_gateway' ) ]; 
  231. } else { 
  232. $current_gateway = current( $available_gateways ); 
  233.  
  234. $this->current_gateway = $current_gateway; //Note: this is an object 
  235. $extra_charge_max_cart_value = get_option( $this->get_option_id( $current_gateway->id, 'max_cart_value' ) ); 
  236.  
  237. //Add charges to cart totals 
  238. if( !empty( $current_gateway ) && ( empty( $extra_charge_max_cart_value ) || $extra_charge_max_cart_value >= $subtotal ) ) { 
  239.  
  240. $extra_charge_name = get_option( $this->get_option_id( $current_gateway->id, 'name' ) ); 
  241. $extra_charge_amount = get_option( $this->get_option_id( $current_gateway->id, 'amount' ) ); 
  242. $extra_charge_type = get_option( $this->get_option_id( $current_gateway->id, 'type' ) ); 
  243. $calc_taxes = get_option( $this->get_option_id( $current_gateway->id, 'calc_taxes' ) ); 
  244.  
  245. $decimal_sep = wp_specialchars_decode( stripslashes( get_option( 'woocommerce_price_decimal_sep' ) ), ENT_QUOTES ); 
  246. $thousands_sep = wp_specialchars_decode( stripslashes( get_option( 'woocommerce_price_thousand_sep' ) ), ENT_QUOTES ); 
  247.  
  248. if( $extra_charge_type == 'percentage' ) { 
  249. $extra_charge_amount = number_format( $subtotal * $extra_charge_amount / 100 , 2 ); 
  250.  
  251. $taxable = false; 
  252. $taxes = 0; 
  253. if( $calc_taxes != 'no-tax' ) { 
  254. $taxable = true; 
  255. $tax = new WC_Tax(); 
  256. $base_rate = $tax->get_shop_base_rate(); 
  257. $taxrates = array_shift( $base_rate ); 
  258. $taxrate = floatval( $taxrates['rate'] ) / 100; 
  259. if( $calc_taxes == 'tax-incl' ) { 
  260. $taxes = $extra_charge_amount - ( $extra_charge_amount / ( 1 + $taxrate ) ); 
  261. $extra_charge_amount -= $taxes; 
  262. } else { 
  263. $taxes = $extra_charge_amount * $taxrate; 
  264.  
  265. $extra_charge_amount = apply_filters( 'woocommerce_wc_pf_' . $current_gateway->id . '_amount' , $extra_charge_amount , $subtotal , $current_gateway ); 
  266. $do_apply = $extra_charge_amount != 0; 
  267. $do_apply = apply_filters( 'woocommerce_wc_pf_apply' , $do_apply , $extra_charge_amount , $subtotal , $current_gateway ); 
  268. $do_apply = apply_filters( 'woocommerce_wc_pf_apply_for_' . $current_gateway->id , $do_apply , $extra_charge_amount , $subtotal , $current_gateway ); 
  269.  
  270. if ( $do_apply ) { 
  271.  
  272. $already_exists = false; 
  273. $fees = $cart->get_fees(); 
  274. for( $i = 0; $i < count( $fees ); $i++ ) { 
  275. if( $fees[$i]->id == 'payment-method-fee' ) { 
  276. $already_exists = true; 
  277. $fee_id = $i; 
  278.  
  279. if( !$already_exists ) { 
  280. $cart->add_fee( $extra_charge_name, $extra_charge_amount, $taxable ); 
  281. } else { 
  282. $fees[$fee_id]->amount = $extra_charge_amount; 
  283.  
  284. $this->current_extra_charge_amount = $extra_charge_amount; 
  285. $this->current_extra_charge_type = $extra_charge_type; 
  286.  
  287. /** 
  288. * Return formatted name of the option 
  289. * 
  290. * @param string $payment_gateway 
  291. * @param string $option 
  292. * @return string 
  293. */ 
  294. public function get_option_id( $payment_gateway, $option ) { 
  295. return 'woocommerce_' . $payment_gateway . '_extra_charge_' . $option; 
  296.  
  297. /** 
  298. * Get the plugin url. 
  299. * 
  300. * @return string 
  301. */ 
  302. public function plugin_url() { 
  303. if ( $this->plugin_url ) return $this->plugin_url; 
  304. return $this->plugin_url = untrailingslashit( plugins_url( '/', dirname( __FILE__ ) ) ); 
  305.  
  306.  
  307. /** 
  308. * Get the plugin path. 
  309. * 
  310. * @return string 
  311. */ 
  312. public function plugin_path() { 
  313. if ( $this->plugin_path ) return $this->plugin_path; 
  314.  
  315. return $this->plugin_path = untrailingslashit( dirname( plugin_dir_path( __FILE__ ) ) ); 
  316. endif; 
.