PageRenderTime 39ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/wp-content/plugins/woocommerce/includes/shipping/legacy-flat-rate/class-wc-shipping-legacy-flat-rate.php

https://gitlab.com/hunt9310/ras
PHP | 379 lines | 219 code | 48 blank | 112 comment | 29 complexity | b273f65f03b1aa8a8cf0f0a4ec7a4125 MD5 | raw file
  1. <?php
  2. if ( ! defined( 'ABSPATH' ) ) {
  3. exit;
  4. }
  5. /**
  6. * Flat Rate Shipping Method.
  7. *
  8. * This class is here for backwards commpatility for methods existing before zones existed.
  9. *
  10. * @deprecated 2.6.0
  11. * @version 2.4.0
  12. * @package WooCommerce/Classes/Shipping
  13. * @author WooThemes
  14. */
  15. class WC_Shipping_Legacy_Flat_Rate extends WC_Shipping_Method {
  16. /** @var string cost passed to [fee] shortcode */
  17. protected $fee_cost = '';
  18. /**
  19. * Constructor.
  20. */
  21. public function __construct() {
  22. $this->id = 'legacy_flat_rate';
  23. $this->method_title = __( 'Flat Rate (Legacy)', 'woocommerce' );
  24. $this->method_description = sprintf( __( '<strong>This method is deprecated in 2.6.0 and will be removed in future versions - we recommend disabling it and instead setting up a new rate within your <a href="%s">Shipping Zones</a>.</strong>', 'woocommerce' ), admin_url( 'admin.php?page=wc-settings&tab=shipping' ) );
  25. $this->init();
  26. add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
  27. add_action( 'woocommerce_flat_rate_shipping_add_rate', array( $this, 'calculate_extra_shipping' ), 10, 2 );
  28. }
  29. /**
  30. * Process and redirect if disabled.
  31. */
  32. public function process_admin_options() {
  33. parent::process_admin_options();
  34. if ( 'no' === $this->settings[ 'enabled' ] ) {
  35. wp_redirect( admin_url( 'admin.php?page=wc-settings&tab=shipping&section=options' ) );
  36. exit;
  37. }
  38. }
  39. /**
  40. * Return the name of the option in the WP DB.
  41. * @since 2.6.0
  42. * @return string
  43. */
  44. public function get_option_key() {
  45. return $this->plugin_id . 'flat_rate' . '_settings';
  46. }
  47. /**
  48. * init function.
  49. */
  50. public function init() {
  51. // Load the settings.
  52. $this->init_form_fields();
  53. $this->init_settings();
  54. // Define user set variables
  55. $this->title = $this->get_option( 'title' );
  56. $this->availability = $this->get_option( 'availability' );
  57. $this->countries = $this->get_option( 'countries' );
  58. $this->tax_status = $this->get_option( 'tax_status' );
  59. $this->cost = $this->get_option( 'cost' );
  60. $this->type = $this->get_option( 'type', 'class' );
  61. $this->options = $this->get_option( 'options', false ); // @deprecated in 2.4.0
  62. }
  63. /**
  64. * Initialise Settings Form Fields.
  65. */
  66. public function init_form_fields() {
  67. $this->form_fields = include( 'includes/settings-flat-rate.php' );
  68. }
  69. /**
  70. * Evaluate a cost from a sum/string.
  71. * @param string $sum
  72. * @param array $args
  73. * @return string
  74. */
  75. protected function evaluate_cost( $sum, $args = array() ) {
  76. include_once( WC()->plugin_path() . '/includes/libraries/class-wc-eval-math.php' );
  77. $locale = localeconv();
  78. $decimals = array( wc_get_price_decimal_separator(), $locale['decimal_point'], $locale['mon_decimal_point'] );
  79. $this->fee_cost = $args['cost'];
  80. // Expand shortcodes
  81. add_shortcode( 'fee', array( $this, 'fee' ) );
  82. $sum = do_shortcode( str_replace(
  83. array(
  84. '[qty]',
  85. '[cost]'
  86. ),
  87. array(
  88. $args['qty'],
  89. $args['cost']
  90. ),
  91. $sum
  92. ) );
  93. remove_shortcode( 'fee', array( $this, 'fee' ) );
  94. // Remove whitespace from string
  95. $sum = preg_replace( '/\s+/', '', $sum );
  96. // Remove locale from string
  97. $sum = str_replace( $decimals, '.', $sum );
  98. // Trim invalid start/end characters
  99. $sum = rtrim( ltrim( $sum, "\t\n\r\0\x0B+*/" ), "\t\n\r\0\x0B+-*/" );
  100. // Do the math
  101. return $sum ? WC_Eval_Math::evaluate( $sum ) : 0;
  102. }
  103. /**
  104. * Work out fee (shortcode).
  105. * @param array $atts
  106. * @return string
  107. */
  108. public function fee( $atts ) {
  109. $atts = shortcode_atts( array(
  110. 'percent' => '',
  111. 'min_fee' => ''
  112. ), $atts );
  113. $calculated_fee = 0;
  114. if ( $atts['percent'] ) {
  115. $calculated_fee = $this->fee_cost * ( floatval( $atts['percent'] ) / 100 );
  116. }
  117. if ( $atts['min_fee'] && $calculated_fee < $atts['min_fee'] ) {
  118. $calculated_fee = $atts['min_fee'];
  119. }
  120. return $calculated_fee;
  121. }
  122. /**
  123. * calculate_shipping function.
  124. *
  125. * @param array $package (default: array())
  126. */
  127. public function calculate_shipping( $package = array() ) {
  128. $rate = array(
  129. 'id' => $this->id,
  130. 'label' => $this->title,
  131. 'cost' => 0,
  132. 'package' => $package,
  133. );
  134. // Calculate the costs
  135. $has_costs = false; // True when a cost is set. False if all costs are blank strings.
  136. $cost = $this->get_option( 'cost' );
  137. if ( $cost !== '' ) {
  138. $has_costs = true;
  139. $rate['cost'] = $this->evaluate_cost( $cost, array(
  140. 'qty' => $this->get_package_item_qty( $package ),
  141. 'cost' => $package['contents_cost']
  142. ) );
  143. }
  144. // Add shipping class costs
  145. $found_shipping_classes = $this->find_shipping_classes( $package );
  146. $highest_class_cost = 0;
  147. foreach ( $found_shipping_classes as $shipping_class => $products ) {
  148. // Also handles BW compatibility when slugs were used instead of ids
  149. $shipping_class_term = get_term_by( 'slug', $shipping_class, 'product_shipping_class' );
  150. $class_cost_string = $shipping_class_term && $shipping_class_term->term_id ? $this->get_option( 'class_cost_' . $shipping_class_term->term_id, $this->get_option( 'class_cost_' . $shipping_class, '' ) ) : $this->get_option( 'no_class_cost', '' );
  151. if ( $class_cost_string === '' ) {
  152. continue;
  153. }
  154. $has_costs = true;
  155. $class_cost = $this->evaluate_cost( $class_cost_string, array(
  156. 'qty' => array_sum( wp_list_pluck( $products, 'quantity' ) ),
  157. 'cost' => array_sum( wp_list_pluck( $products, 'line_total' ) )
  158. ) );
  159. if ( $this->type === 'class' ) {
  160. $rate['cost'] += $class_cost;
  161. } else {
  162. $highest_class_cost = $class_cost > $highest_class_cost ? $class_cost : $highest_class_cost;
  163. }
  164. }
  165. if ( $this->type === 'order' && $highest_class_cost ) {
  166. $rate['cost'] += $highest_class_cost;
  167. }
  168. $rate['package'] = $package;
  169. // Add the rate
  170. if ( $has_costs ) {
  171. $this->add_rate( $rate );
  172. }
  173. /**
  174. * Developers can add additional flat rates based on this one via this action since @version 2.4.
  175. *
  176. * Previously there were (overly complex) options to add additional rates however this was not user.
  177. * friendly and goes against what Flat Rate Shipping was originally intended for.
  178. *
  179. * This example shows how you can add an extra rate based on this flat rate via custom function:
  180. *
  181. * add_action( 'woocommerce_flat_rate_shipping_add_rate', 'add_another_custom_flat_rate', 10, 2 );
  182. *
  183. * function add_another_custom_flat_rate( $method, $rate ) {
  184. * $new_rate = $rate;
  185. * $new_rate['id'] .= ':' . 'custom_rate_name'; // Append a custom ID.
  186. * $new_rate['label'] = 'Rushed Shipping'; // Rename to 'Rushed Shipping'.
  187. * $new_rate['cost'] += 2; // Add $2 to the cost.
  188. *
  189. * // Add it to WC.
  190. * $method->add_rate( $new_rate );
  191. * }.
  192. */
  193. do_action( 'woocommerce_flat_rate_shipping_add_rate', $this, $rate );
  194. }
  195. /**
  196. * Get items in package.
  197. * @param array $package
  198. * @return int
  199. */
  200. public function get_package_item_qty( $package ) {
  201. $total_quantity = 0;
  202. foreach ( $package['contents'] as $item_id => $values ) {
  203. if ( $values['quantity'] > 0 && $values['data']->needs_shipping() ) {
  204. $total_quantity += $values['quantity'];
  205. }
  206. }
  207. return $total_quantity;
  208. }
  209. /**
  210. * Finds and returns shipping classes and the products with said class.
  211. * @param mixed $package
  212. * @return array
  213. */
  214. public function find_shipping_classes( $package ) {
  215. $found_shipping_classes = array();
  216. foreach ( $package['contents'] as $item_id => $values ) {
  217. if ( $values['data']->needs_shipping() ) {
  218. $found_class = $values['data']->get_shipping_class();
  219. if ( ! isset( $found_shipping_classes[ $found_class ] ) ) {
  220. $found_shipping_classes[ $found_class ] = array();
  221. }
  222. $found_shipping_classes[ $found_class ][ $item_id ] = $values;
  223. }
  224. }
  225. return $found_shipping_classes;
  226. }
  227. /**
  228. * Adds extra calculated flat rates.
  229. *
  230. * @deprecated 2.4.0
  231. *
  232. * Additonal rates defined like this:
  233. * Option Name | Additional Cost [+- Percents%] | Per Cost Type (order, class, or item).
  234. */
  235. public function calculate_extra_shipping( $method, $rate ) {
  236. if ( $this->options ) {
  237. $options = array_filter( (array) explode( "\n", $this->options ) );
  238. foreach ( $options as $option ) {
  239. $this_option = array_map( 'trim', explode( WC_DELIMITER, $option ) );
  240. if ( sizeof( $this_option ) !== 3 ) {
  241. continue;
  242. }
  243. $extra_rate = $rate;
  244. $extra_rate['id'] = $this->id . ':' . urldecode( sanitize_title( $this_option[0] ) );
  245. $extra_rate['label'] = $this_option[0];
  246. $extra_cost = $this->get_extra_cost( $this_option[1], $this_option[2], $rate['package'] );
  247. if ( is_array( $extra_rate['cost'] ) ) {
  248. $extra_rate['cost']['order'] = $extra_rate['cost']['order'] + $extra_cost;
  249. } else {
  250. $extra_rate['cost'] += $extra_cost;
  251. }
  252. $this->add_rate( $extra_rate );
  253. }
  254. }
  255. }
  256. /**
  257. * Calculate the percentage adjustment for each shipping rate.
  258. *
  259. * @deprecated 2.4.0
  260. * @param float $cost
  261. * @param float $percent_adjustment
  262. * @param string $percent_operator
  263. * @param float $base_price
  264. * @return float
  265. */
  266. public function calc_percentage_adjustment( $cost, $percent_adjustment, $percent_operator, $base_price ) {
  267. if ( '+' == $percent_operator ) {
  268. $cost += $percent_adjustment * $base_price;
  269. } else {
  270. $cost -= $percent_adjustment * $base_price;
  271. }
  272. return $cost;
  273. }
  274. /**
  275. * Get extra cost.
  276. *
  277. * @deprecated 2.4.0
  278. * @param string $cost_string
  279. * @param string $type
  280. * @param array $package
  281. * @return float
  282. */
  283. public function get_extra_cost( $cost_string, $type, $package ) {
  284. $cost = $cost_string;
  285. $cost_percent = false;
  286. $pattern =
  287. '/' . // start regex
  288. '(\d+\.?\d*)' . // capture digits, optionally capture a `.` and more digits
  289. '\s*' . // match whitespace
  290. '(\+|-)' . // capture the operand
  291. '\s*'. // match whitespace
  292. '(\d+\.?\d*)'. // capture digits, optionally capture a `.` and more digits
  293. '\%/'; // match the percent sign & end regex
  294. if ( preg_match( $pattern, $cost_string, $this_cost_matches ) ) {
  295. $cost_operator = $this_cost_matches[2];
  296. $cost_percent = $this_cost_matches[3] / 100;
  297. $cost = $this_cost_matches[1];
  298. }
  299. switch ( $type ) {
  300. case 'class' :
  301. $cost = $cost * sizeof( $this->find_shipping_classes( $package ) );
  302. break;
  303. case 'item' :
  304. $cost = $cost * $this->get_package_item_qty( $package );
  305. break;
  306. }
  307. if ( $cost_percent ) {
  308. switch ( $type ) {
  309. case 'class' :
  310. $shipping_classes = $this->find_shipping_classes( $package );
  311. foreach ( $shipping_classes as $shipping_class => $items ){
  312. foreach ( $items as $item_id => $values ) {
  313. $cost = $this->calc_percentage_adjustment( $cost, $cost_percent, $cost_operator, $values['line_total'] );
  314. }
  315. }
  316. break;
  317. case 'item' :
  318. foreach ( $package['contents'] as $item_id => $values ) {
  319. if ( $values['data']->needs_shipping() ) {
  320. $cost = $this->calc_percentage_adjustment( $cost, $cost_percent, $cost_operator, $values['line_total'] );
  321. }
  322. }
  323. break;
  324. case 'order' :
  325. $cost = $this->calc_percentage_adjustment( $cost, $cost_percent, $cost_operator, $package['contents_cost'] );
  326. break;
  327. }
  328. }
  329. return $cost;
  330. }
  331. }