1 <?php
  2 
  3 if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
  4 
  5 /**
  6  * Flat Rate Shipping Method
  7  *
  8  * A simple shipping method for a flat fee per item or per order
  9  *
 10  * @class       WC_Shipping_Flat_Rate
 11  * @version     2.0.0
 12  * @package     WooCommerce/Classes/Shipping
 13  * @author      WooThemes
 14  */
 15 class WC_Shipping_Flat_Rate extends WC_Shipping_Method {
 16 
 17     /**
 18      * __construct function.
 19      *
 20      * @access public
 21      * @return void
 22      */
 23     function __construct() {
 24         $this->id                       = 'flat_rate';
 25         $this->method_title             = __( 'Flat Rate', 'woocommerce' );
 26         $this->flat_rate_option         = 'woocommerce_flat_rates';
 27         $this->method_description       = __( 'Flat rates let you define a standard rate per item, or per order.', 'woocommerce' );
 28 
 29         add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_admin_options' ) );
 30         add_action( 'woocommerce_update_options_shipping_' . $this->id, array( $this, 'process_flat_rates' ) );
 31         add_filter( 'woocommerce_settings_api_sanitized_fields_' . $this->id, array( $this, 'save_default_costs' ) );
 32 
 33         $this->init();
 34     }
 35 
 36     /**
 37      * init function.
 38      *
 39      * @access public
 40      * @return void
 41      */
 42     function init() {
 43 
 44         // Load the settings.
 45         $this->init_form_fields();
 46         $this->init_settings();
 47 
 48         // Define user set variables
 49         $this->title          = $this->get_option( 'title' );
 50         $this->availability   = $this->get_option( 'availability' );
 51         $this->countries      = $this->get_option( 'countries' );
 52         $this->type           = $this->get_option( 'type' );
 53         $this->tax_status     = $this->get_option( 'tax_status' );
 54         $this->cost           = $this->get_option( 'cost' );
 55         $this->cost_per_order = $this->get_option( 'cost_per_order' );
 56         $this->fee            = $this->get_option( 'fee' );
 57         $this->minimum_fee    = $this->get_option( 'minimum_fee' );
 58         $this->options        = (array) explode( "\n", $this->get_option( 'options' ) );
 59 
 60         // Load Flat rates
 61         $this->get_flat_rates();
 62     }
 63 
 64 
 65     /**
 66      * Initialise Gateway Settings Form Fields
 67      *
 68      * @access public
 69      * @return void
 70      */
 71     function init_form_fields() {
 72 
 73         $this->form_fields = array(
 74             'enabled' => array(
 75                             'title'         => __( 'Enable/Disable', 'woocommerce' ),
 76                             'type'          => 'checkbox',
 77                             'label'         => __( 'Enable this shipping method', 'woocommerce' ),
 78                             'default'       => 'no',
 79                         ),
 80             'title' => array(
 81                             'title'         => __( 'Method Title', 'woocommerce' ),
 82                             'type'          => 'text',
 83                             'description'   => __( 'This controls the title which the user sees during checkout.', 'woocommerce' ),
 84                             'default'       => __( 'Flat Rate', 'woocommerce' ),
 85                             'desc_tip'      => true
 86                         ),
 87             'availability' => array(
 88                             'title'         => __( 'Availability', 'woocommerce' ),
 89                             'type'          => 'select',
 90                             'default'       => 'all',
 91                             'class'         => 'availability',
 92                             'options'       => array(
 93                                 'all'       => __( 'All allowed countries', 'woocommerce' ),
 94                                 'specific'  => __( 'Specific Countries', 'woocommerce' ),
 95                             ),
 96                         ),
 97             'countries' => array(
 98                             'title'         => __( 'Specific Countries', 'woocommerce' ),
 99                             'type'          => 'multiselect',
100                             'class'         => 'chosen_select',
101                             'css'           => 'width: 450px;',
102                             'default'       => '',
103                             'options'       => WC()->countries->get_shipping_countries(),
104                             'custom_attributes' => array(
105                                 'data-placeholder' => __( 'Select some countries', 'woocommerce' )
106                             )
107                         ),
108             'tax_status' => array(
109                             'title'         => __( 'Tax Status', 'woocommerce' ),
110                             'type'          => 'select',
111                             'default'       => 'taxable',
112                             'options'       => array(
113                                 'taxable'   => __( 'Taxable', 'woocommerce' ),
114                                 'none'      => _x( 'None', 'Tax status', 'woocommerce' )
115                             ),
116                         ),
117             'cost_per_order' => array(
118                             'title'         => __( 'Cost per order', 'woocommerce' ),
119                             'type'          => 'price',
120                             'placeholder'   => wc_format_localized_price( 0 ),
121                             'description'   => __( 'Enter a cost (excluding tax) per order, e.g. 5.00. Default is 0.', 'woocommerce' ),
122                             'default'       => '',
123                             'desc_tip'      => true
124                         ),
125             'options' => array(
126                             'title'         => __( 'Additional Rates', 'woocommerce' ),
127                             'type'          => 'textarea',
128                             'description'   => __( 'Optional extra shipping options with additional costs (one per line): Option Name | Additional Cost [+- Percents] | Per Cost Type (order, class, or item) Example: <code>Priority Mail | 6.95 [+ 0.2%] | order</code>.', 'woocommerce' ),
129                             'default'       => '',
130                             'desc_tip'      => true,
131                             'placeholder'   => __( 'Option Name | Additional Cost [+- Percents%] | Per Cost Type (order, class, or item)', 'woocommerce' )
132                         ),
133             'additional_costs' => array(
134                             'title'         => __( 'Additional Costs', 'woocommerce' ),
135                             'type'          => 'title',
136                             'description'   => __( 'Additional costs can be added below - these will all be added to the per-order cost above.', 'woocommerce' )
137                         ),
138             'type' => array(
139                             'title'         => __( 'Costs Added...', 'woocommerce' ),
140                             'type'          => 'select',
141                             'default'       => 'order',
142                             'options'       => array(
143                                 'order'     => __( 'Per Order - charge shipping for the entire order as a whole', 'woocommerce' ),
144                                 'item'      => __( 'Per Item - charge shipping for each item individually', 'woocommerce' ),
145                                 'class'     => __( 'Per Class - charge shipping for each shipping class in an order', 'woocommerce' ),
146                             ),
147                         ),
148             'additional_costs_table' => array(
149                         'type'              => 'additional_costs_table'
150                         ),
151             'minimum_fee' => array(
152                             'title'         => __( 'Minimum Handling Fee', 'woocommerce' ),
153                             'type'          => 'price',
154                             'placeholder'   => wc_format_localized_price( 0 ),
155                             'description'   => __( 'Enter a minimum fee amount. Fee\'s less than this will be increased. Leave blank to disable.', 'woocommerce' ),
156                             'default'       => '',
157                             'desc_tip'      => true
158                         ),
159             );
160 
161     }
162 
163 
164     /**
165      * calculate_shipping function.
166      *
167      * @access public
168      * @param array $package (default: array())
169      * @return void
170      */
171     function calculate_shipping( $package = array() ) {
172 
173         $this->rates        = array();
174         $cost_per_order     = ( isset( $this->cost_per_order ) && ! empty( $this->cost_per_order ) ) ? $this->cost_per_order : 0;
175 
176         if ( $this->type == 'order' ) {
177 
178             $shipping_total = $this->order_shipping( $package );
179 
180             if ( ! is_null( $shipping_total ) || $cost_per_order > 0 ) {
181                 $rate = array(
182                     'id'    => $this->id,
183                     'label' => $this->title,
184                     'cost'  => $shipping_total + $cost_per_order,
185                 );
186             }
187 
188         } elseif ( $this->type == 'class' ) {
189 
190             $shipping_total = $this->class_shipping( $package );
191 
192             if ( ! is_null( $shipping_total ) || $cost_per_order > 0 ) {
193                 $rate = array(
194                     'id'    => $this->id,
195                     'label' => $this->title,
196                     'cost'  => $shipping_total + $cost_per_order,
197                 );
198             }
199 
200         } elseif ( $this->type == 'item' ) {
201 
202             $costs = $this->item_shipping( $package );
203 
204             if ( ! is_null( $costs ) || $cost_per_order > 0 ) {
205 
206                 if ( ! is_array( $costs ) ) {
207                     $costs = array();
208                 }
209 
210                 $costs['order'] = $cost_per_order;
211 
212                 $rate = array(
213                     'id'        => $this->id,
214                     'label'     => $this->title,
215                     'cost'      => $costs,
216                     'calc_tax'  => 'per_item',
217                 );
218 
219             }
220         }
221 
222         if ( isset( $rate ) ) {
223             $this->add_rate( $rate );
224         }
225 
226         // Add any extra rates
227         if ( sizeof( $this->options ) > 0) {
228 
229             if ( ! isset( $rate ) ) {
230                 $rate = array(
231                     'id'    => $this->id,
232                     'label' => $this->title,
233                     'cost'  => 0,
234                 );
235             }
236 
237             // Get item qty
238             $total_quantity = 0;
239 
240             foreach ( $package['contents'] as $item_id => $values ) {
241                 if ( $values['quantity'] > 0 && $values['data']->needs_shipping() ) {
242                     $total_quantity += $values['quantity'];
243                 }
244             }
245 
246             // Loop options
247             foreach ( $this->options as $option ) {
248 
249                 $this_option = array_map( 'trim', explode( WC_DELIMITER, $option ) );
250 
251                 if ( sizeof( $this_option ) !== 3 ) continue;
252 
253                 $extra_rate = $rate;
254 
255                 $extra_rate['id']    = $this->id . ':' . urldecode( sanitize_title( $this_option[0] ) );
256                 $extra_rate['label'] = $this_option[0];
257                 $this_cost           = $this_option[1];
258                 $this_cost_percents  = '';
259 
260                 $pattern =
261                     '/' .           // start regex
262                     '(\d+\.?\d*)' . // capture digits, optionally capture a `.` and more digits
263                     '\s*' .         // match whitespace
264                     '(\+|-)' .      // capture the operand
265                     '\s*'.          // match whitespace
266                     '(\d+\.?\d*)'.  // capture digits, optionally capture a `.` and more digits
267                     '\%/';          // match the percent sign & end regex
268                 if ( preg_match( $pattern, $this_cost, $this_cost_matches ) ) {
269                     $this_cost_mathop = $this_cost_matches[2];
270                     $this_cost_percents = $this_cost_matches[3] / 100;
271                     $this_cost = $this_cost_matches[1];
272                     unset( $this_cost_matches );
273                 }
274 
275                 // Backwards compat with yes and no
276                 if ( $this_option[2] == 'yes' ) {
277                     $this_type = 'order';
278                 } elseif ( $this_option[2] == 'no' ) {
279                     $this_type = $this->type;
280                 } else {
281                     $this_type = $this_option[2];
282                 }
283 
284                 switch ( $this_type ) {
285                     case 'class' :
286                         $this_cost = $this_cost * sizeof( $this->find_shipping_classes( $package ) );
287 
288                         // Factor $this_cost by the percentage if provided.
289                         if ( $this_cost_percents ) {
290                             foreach ( $this->find_shipping_classes( $package ) as $shipping_class => $items ){
291                                 foreach ( $items as $item_id => $values ) {
292                                     if ($this_cost_mathop == '+') {
293                                         $this_cost += $this_cost_percents * $values['line_total'];
294                                     }
295                                     else {
296                                         $this_cost -= $this_cost_percents * $values['line_total'];
297                                     }
298                                 }
299                             }
300                         }
301                     break;
302                     case 'item' :
303                         $this_cost = $this_cost * $total_quantity;
304 
305                         // Factor $this_cost by the percentage if provided.
306                         if ( $this_cost_percents ) {
307                             foreach ( $package['contents'] as $item_id => $values ) {
308                                 if ($this_cost_mathop == '+') {
309                                     $this_cost += $this_cost_percents * $values['line_total'];
310                                 } else {
311                                     $this_cost -= $this_cost_percents * $values['line_total'];
312                                 }
313                             }
314                         }
315                     break;
316                     case  'order' :
317                         // Factor $this_cost by the percentage if provided.
318                         if ( $this_cost_percents ) {
319                             if ($this_cost_mathop == '+') {
320                                 $this_cost += $this_cost_percents * $package['contents_cost'];
321                             } else {
322                                 $this_cost -= $this_cost_percents * $package['contents_cost'];
323                             }
324                         }
325                     break;
326                 }
327 
328                 // Per item rates
329                 if ( is_array( $extra_rate['cost'] ) ) $extra_rate['cost']['order'] = $extra_rate['cost']['order'] + $this_cost;
330 
331                 // Per order or class rates
332                 else $extra_rate['cost'] = $extra_rate['cost'] + $this_cost;
333 
334                 $this->add_rate( $extra_rate );
335             }
336         }
337     }
338 
339 
340     /**
341      * order_shipping function.
342      *
343      * @access public
344      * @param array $package
345      * @return float
346      */
347     function order_shipping( $package ) {
348         $cost   = null;
349         $fee    = null;
350 
351         if ( sizeof( $this->flat_rates ) > 0 ) {
352 
353             $found_shipping_classes = $this->find_shipping_classes( $package );
354 
355             // Find most expensive class (if found)
356             foreach ( $found_shipping_classes as $shipping_class => $products ) {
357                 if ( isset( $this->flat_rates[ $shipping_class ] ) ) {
358                     if ( $this->flat_rates[ $shipping_class ]['cost'] > $cost ) {
359                         $cost   = $this->flat_rates[ $shipping_class ]['cost'];
360                         $fee    = $this->flat_rates[ $shipping_class ]['fee'];
361                     }
362                 } else {
363                     // No matching classes so use defaults
364                     if ( ! empty( $this->cost ) && $this->cost > $cost ) {
365                         $cost   = $this->cost;
366                         $fee    = $this->fee;
367                     }
368                 }
369             }
370 
371         }
372 
373         // Default rates if set
374         if ( is_null( $cost ) && $this->cost !== '' ) {
375             $cost   = $this->cost;
376             $fee    = $this->fee;
377         } elseif ( is_null( $cost ) ) {
378             // Set rates to 0 if nothing is set by the user
379             $cost   = 0;
380             $fee    = 0;
381         }
382 
383         // Shipping for whole order
384         return $cost + $this->get_fee( $fee, $package['contents_cost'] );
385     }
386 
387 
388     /**
389      * class_shipping function.
390      *
391      * @access public
392      * @param array $package
393      * @return float
394      */
395     function class_shipping( $package ) {
396         $cost   = null;
397         $fee    = null;
398         $matched = false;
399 
400         if ( sizeof( $this->flat_rates ) > 0 || $this->cost !== '' ) {
401 
402             // Find shipping classes for products in the cart.
403             $found_shipping_classes = $this->find_shipping_classes( $package );
404 
405             //  Store prices too, so we can calc a fee for the class.
406             $found_shipping_classes_values = array();
407 
408             foreach ( $found_shipping_classes as $shipping_class => $products ) {
409                 if ( ! isset( $found_shipping_classes_values[ $shipping_class ] ) ) {
410                     $found_shipping_classes_values[ $shipping_class ] = 0;
411                 }
412 
413                 foreach ( $products as $product ) {
414                     $found_shipping_classes_values[ $shipping_class ] += $product['data']->get_price() * $product['quantity'];
415                 }
416             }
417 
418             // For each found class, add up the costs and fees
419             foreach ( $found_shipping_classes_values as $shipping_class => $class_price ) {
420                 if ( isset( $this->flat_rates[ $shipping_class ] ) ) {
421                     $cost   += $this->flat_rates[ $shipping_class ]['cost'];
422                     $fee    += $this->get_fee( $this->flat_rates[ $shipping_class ]['fee'], $class_price );
423                     $matched = true;
424                 } elseif ( $this->cost !== '' ) {
425                     // Class not set so we use default rate if its set
426                     $cost   += $this->cost;
427                     $fee    += $this->get_fee( $this->fee, $class_price );
428                     $matched = true;
429                 }
430             }
431         }
432 
433         // Total
434         if ( $matched ) {
435             return $cost + $fee;
436         } else {
437             return null;
438         }
439     }
440 
441 
442     /**
443      * item_shipping function.
444      *
445      * @access public
446      * @param array $package
447      * @return array
448      */
449     function item_shipping( $package ) {
450         // Per item shipping so we pass an array of costs (per item) instead of a single value
451         $costs = array();
452 
453         $matched = false;
454 
455         // Shipping per item
456         foreach ( $package['contents'] as $item_id => $values ) {
457             $_product = $values['data'];
458 
459             if ( $values['quantity'] > 0 && $_product->needs_shipping() ) {
460                 $shipping_class = $_product->get_shipping_class();
461 
462                 $fee = $cost = 0;
463 
464                 if ( isset( $this->flat_rates[ $shipping_class ] ) ) {
465                     $cost   = $this->flat_rates[ $shipping_class ]['cost'];
466                     $fee    = $this->get_fee( $this->flat_rates[ $shipping_class ]['fee'], $_product->get_price() );
467                     $matched = true;
468                 } elseif ( $this->cost !== '' ) {
469                     $cost   = $this->cost;
470                     $fee    = $this->get_fee( $this->fee, $_product->get_price() );
471                     $matched = true;
472                 }
473 
474                 $costs[ $item_id ] = ( ( $cost + $fee ) * $values['quantity'] );
475             }
476         }
477 
478         if ( $matched ) {
479             return $costs;
480         } else {
481             return null;
482         }
483     }
484 
485     /**
486      * Finds and returns shipping classes and the products with said class.
487      *
488      * @access public
489      * @param mixed $package
490      * @return array
491      */
492     public function find_shipping_classes( $package ) {
493         $found_shipping_classes = array();
494 
495         // Find shipping classes for products in the cart
496         if ( sizeof( $package['contents'] ) > 0 ) {
497             foreach ( $package['contents'] as $item_id => $values ) {
498                 if ( $values['data']->needs_shipping() ) {
499                     $found_class = $values['data']->get_shipping_class();
500                     if ( ! isset( $found_shipping_classes[ $found_class ] ) ) {
501                         $found_shipping_classes[ $found_class ] = array();
502                     }
503 
504                     $found_shipping_classes[ $found_class ][ $item_id ] = $values;
505                 }
506             }
507         }
508 
509         return $found_shipping_classes;
510     }
511 
512     /**
513      * validate_additional_costs_field function.
514      *
515      * @access public
516      * @param mixed $key
517      * @return bool
518      */
519     function validate_additional_costs_table_field( $key ) {
520         return false;
521     }
522 
523     /**
524      * generate_additional_costs_html function.
525      *
526      * @access public
527      * @return string
528      */
529     function generate_additional_costs_table_html() {
530         ob_start();
531         ?>
532         <tr valign="top">
533             <th scope="row" class="titledesc"><?php _e( 'Costs', 'woocommerce' ); ?>:</th>
534             <td class="forminp" id="<?php echo $this->id; ?>_flat_rates">
535                 <table class="shippingrows widefat" cellspacing="0">
536                     <thead>
537                         <tr>
538                             <th class="check-column"><input type="checkbox"></th>
539                             <th class="shipping_class"><?php _e( 'Shipping Class', 'woocommerce' ); ?></th>
540                             <th><?php _e( 'Cost', 'woocommerce' ); ?> <a class="tips" data-tip="<?php _e( 'Cost, excluding tax.', 'woocommerce' ); ?>">[?]</a></th>
541                             <th><?php _e( 'Handling Fee', 'woocommerce' ); ?> <a class="tips" data-tip="<?php _e( 'Fee excluding tax. Enter an amount, e.g. 2.50, or a percentage, e.g. 5%.', 'woocommerce' ); ?>">[?]</a></th>
542                         </tr>
543                     </thead>
544                     <tfoot>
545                         <tr>
546                             <th colspan="4"><a href="#" class="add button"><?php _e( 'Add Cost', 'woocommerce' ); ?></a> <a href="#" class="remove button"><?php _e( 'Delete selected costs', 'woocommerce' ); ?></a></th>
547                         </tr>
548                     </tfoot>
549                     <tbody class="flat_rates">
550                         <tr>
551                             <td></td>
552                             <td class="flat_rate_class"><?php _e( 'Any class', 'woocommerce' ); ?></td>
553                             <td><input type="text" value="<?php echo esc_attr( wc_format_localized_price( $this->cost ) ); ?>" name="default_cost" placeholder="<?php _e( 'N/A', 'woocommerce' ); ?>" size="4" class="wc_input_price" /></td>
554                             <td><input type="text" value="<?php echo esc_attr( wc_format_localized_price( $this->fee ) ); ?>" name="default_fee" placeholder="<?php _e( 'N/A', 'woocommerce' ); ?>" size="4" class="wc_input_price" /></td>
555                         </tr>
556                         <?php
557                         $i = -1;
558                         if ( $this->flat_rates ) {
559                             foreach ( $this->flat_rates as $class => $rate ) {
560                                 $i++;
561 
562                                 echo '<tr class="flat_rate">
563                                     <th class="check-column"><input type="checkbox" name="select" /></th>
564                                     <td class="flat_rate_class">
565                                             <select name="' . esc_attr( $this->id . '_class[' . $i . ']' ) . '" class="select">';
566 
567                                 if ( WC()->shipping->get_shipping_classes() ) {
568                                     foreach ( WC()->shipping->get_shipping_classes() as $shipping_class ) {
569                                         echo '<option value="' . esc_attr( $shipping_class->slug ) . '" '.selected($shipping_class->slug, $class, false).'>'.$shipping_class->name.'</option>';
570                                     }
571                                 } else {
572                                     echo '<option value="">'.__( 'Select a class&hellip;', 'woocommerce' ).'</option>';
573                                 }
574 
575                                 echo '</select>
576                                     </td>
577                                     <td><input type="text" value="' . esc_attr( $rate['cost'] ) . '" name="' . esc_attr( $this->id .'_cost[' . $i . ']' ) . '" placeholder="' . wc_format_localized_price( 0 ) . '" size="4" class="wc_input_price" /></td>
578                                     <td><input type="text" value="' . esc_attr( $rate['fee'] ) . '" name="' . esc_attr( $this->id .'_fee[' . $i . ']' ) . '" placeholder="' . wc_format_localized_price( 0 ) . '" size="4" class="wc_input_price" /></td>
579                                 </tr>';
580                             }
581                         }
582                         ?>
583                     </tbody>
584                 </table>
585                 <script type="text/javascript">
586                     jQuery(function() {
587 
588                         jQuery('#<?php echo $this->id; ?>_flat_rates').on( 'click', 'a.add', function(){
589 
590                             var size = jQuery('#<?php echo $this->id; ?>_flat_rates tbody .flat_rate').size();
591 
592                             jQuery('<tr class="flat_rate">\
593                                 <th class="check-column"><input type="checkbox" name="select" /></th>\
594                                 <td class="flat_rate_class">\
595                                     <select name="<?php echo $this->id; ?>_class[' + size + ']" class="select">\
596                                         <?php
597                                         if (WC()->shipping->get_shipping_classes()) :
598                                             foreach (WC()->shipping->get_shipping_classes() as $class) :
599                                                 echo '<option value="' . esc_attr( $class->slug ) . '">' . esc_js( $class->name ) . '</option>';
600                                             endforeach;
601                                         else :
602                                             echo '<option value="">'.__( 'Select a class&hellip;', 'woocommerce' ).'</option>';
603                                         endif;
604                                         ?>\
605                                     </select>\
606                                 </td>\
607                                 <td><input type="text" name="<?php echo $this->id; ?>_cost[' + size + ']" placeholder="<?php echo wc_format_localized_price( 0 ); ?>" size="4" class="wc_input_price" /></td>\
608                                 <td><input type="text" name="<?php echo $this->id; ?>_fee[' + size + ']" placeholder="<?php echo wc_format_localized_price( 0 ); ?>" size="4" class="wc_input_price" /></td>\
609                             </tr>').appendTo('#<?php echo $this->id; ?>_flat_rates table tbody');
610 
611                             return false;
612                         });
613 
614                         // Remove row
615                         jQuery('#<?php echo $this->id; ?>_flat_rates').on( 'click', 'a.remove', function(){
616                             var answer = confirm("<?php _e( 'Delete the selected rates?', 'woocommerce' ); ?>");
617                             if (answer) {
618                                 jQuery('#<?php echo $this->id; ?>_flat_rates table tbody tr th.check-column input:checked').each(function(i, el){
619                                     jQuery(el).closest('tr').remove();
620                                 });
621                             }
622                             return false;
623                         });
624 
625                     });
626                 </script>
627             </td>
628         </tr>
629         <?php
630         return ob_get_clean();
631     }
632 
633     /**
634      * process_flat_rates function.
635      *
636      * @access public
637      * @return void
638      */
639     function process_flat_rates() {
640         // Save the rates
641         $flat_rate_class = array();
642         $flat_rate_cost = array();
643         $flat_rate_fee = array();
644         $flat_rates = array();
645 
646         if ( isset( $_POST[ $this->id . '_class'] ) ) $flat_rate_class = array_map( 'wc_clean', $_POST[ $this->id . '_class'] );
647         if ( isset( $_POST[ $this->id . '_cost'] ) )  $flat_rate_cost  = array_map( 'stripslashes', $_POST[ $this->id . '_cost'] );
648         if ( isset( $_POST[ $this->id . '_fee'] ) )   $flat_rate_fee   = array_map( 'stripslashes', $_POST[ $this->id . '_fee'] );
649 
650         // Get max key
651         $values = $flat_rate_class;
652         ksort( $values );
653         $value = end( $values );
654         $key = key( $values );
655 
656         for ( $i = 0; $i <= $key; $i++ ) {
657             if ( ! empty( $flat_rate_class[ $i ] ) && isset( $flat_rate_cost[ $i ] ) && isset( $flat_rate_fee[ $i ] ) ) {
658 
659                 $flat_rate_cost[ $i ] = wc_format_decimal( $flat_rate_cost[$i] );
660 
661                 if ( ! strstr( $flat_rate_fee[$i], '%' ) ) {
662                     $flat_rate_fee[ $i ] = wc_format_decimal( $flat_rate_fee[$i] );
663                 } else {
664                     $flat_rate_fee[ $i ] = wc_clean( $flat_rate_fee[$i] );
665                 }
666 
667                 // Add to flat rates array
668                 $flat_rates[ urldecode( sanitize_title( $flat_rate_class[ $i ] ) ) ] = array(
669                     'cost' => $flat_rate_cost[ $i ],
670                     'fee'  => $flat_rate_fee[ $i ],
671                 );
672             }
673         }
674 
675         update_option( $this->flat_rate_option, $flat_rates );
676 
677         $this->get_flat_rates();
678     }
679 
680     /**
681      * save_default_costs function.
682      *
683      * @access public
684      * @param array $fields
685      * @return array
686      */
687     function save_default_costs( $fields ) {
688         $default_cost = ( $_POST['default_cost'] === '' ) ? '' : wc_format_decimal( $_POST['default_cost'] );
689 
690         if ( ! strstr( $_POST['default_fee'], '%' ) ) {
691             $default_fee  = ( $_POST['default_fee'] === '' ) ? '' : wc_format_decimal( $_POST['default_fee'] );
692         } else {
693             $default_fee = wc_clean( $_POST['default_fee'] );
694         }
695 
696         $fields['cost'] = $default_cost;
697         $fields['fee']  = $default_fee;
698 
699         return $fields;
700     }
701 
702 
703     /**
704      * get_flat_rates function.
705      *
706      * @access public
707      * @return void
708      */
709     function get_flat_rates() {
710         $this->flat_rates = array_filter( (array) get_option( $this->flat_rate_option ) );
711     }
712 
713 }
714 
WooCommerce API documentation generated by ApiGen 2.8.0