1 <?php
  2 /**
  3  * WooCommerce coupons
  4  *
  5  * The WooCommerce coupons class gets coupon data from storage and checks coupon validity
  6  *
  7  * @class       WC_Coupon
  8  * @package     WooCommerce/Classes
  9  * @category    Class
 10  * @author      WooThemes
 11  */
 12 class WC_Coupon {
 13 
 14     // Coupon message codes
 15     const E_WC_COUPON_INVALID_FILTERED               = 100;
 16     const E_WC_COUPON_INVALID_REMOVED                = 101;
 17     const E_WC_COUPON_NOT_YOURS_REMOVED              = 102;
 18     const E_WC_COUPON_ALREADY_APPLIED                = 103;
 19     const E_WC_COUPON_ALREADY_APPLIED_INDIV_USE_ONLY = 104;
 20     const E_WC_COUPON_NOT_EXIST                      = 105;
 21     const E_WC_COUPON_USAGE_LIMIT_REACHED            = 106;
 22     const E_WC_COUPON_EXPIRED                        = 107;
 23     const E_WC_COUPON_MIN_SPEND_LIMIT_NOT_MET        = 108;
 24     const E_WC_COUPON_NOT_APPLICABLE                 = 109;
 25     const E_WC_COUPON_NOT_VALID_SALE_ITEMS           = 110;
 26     const E_WC_COUPON_PLEASE_ENTER                   = 111;
 27     const WC_COUPON_SUCCESS                          = 200;
 28     const WC_COUPON_REMOVED                          = 201;
 29 
 30     /** @public string Coupon code. */
 31     public $code;
 32 
 33     /** @public int Coupon ID. */
 34     public $id;
 35 
 36     /** @public string Type of discount. */
 37     public $type;
 38 
 39     /** @public string Type of discount (alias). */
 40     public $discount_type;
 41 
 42     /** @public string Coupon amount. */
 43     public $amount;
 44 
 45     /** @public string "Yes" if for individual use. */
 46     public $individual_use;
 47 
 48     /** @public array Array of product IDs. */
 49     public $product_ids;
 50 
 51     /** @public int Coupon usage limit. */
 52     public $usage_limit;
 53 
 54     /** @public int Coupon usage limit per user. */
 55     public $usage_limit_per_user;
 56 
 57     /** @public int Coupon usage limit per item. */
 58     public $limit_usage_to_x_items;
 59 
 60     /** @public int Coupon usage count. */
 61     public $usage_count;
 62 
 63     /** @public string Expiry date. */
 64     public $expiry_date;
 65 
 66     /** @public string "yes" if applied before tax. */
 67     public $apply_before_tax;
 68 
 69     /** @public string "yes" if coupon grants free shipping. */
 70     public $free_shipping;
 71 
 72     /** @public array Array of category ids. */
 73     public $product_categories;
 74 
 75     /** @public array Array of category ids. */
 76     public $exclude_product_categories;
 77 
 78     /** @public string "yes" if coupon does NOT apply to items on sale. */
 79     public $exclude_sale_items;
 80 
 81     /** @public string Minimum cart amount. */
 82     public $minimum_amount;
 83 
 84     /** @public string Coupon owner's email. */
 85     public $customer_email;
 86 
 87     /** @public array Post meta. */
 88     public $coupon_custom_fields;
 89 
 90     /** @public string How much the coupon is worth. */
 91     public $coupon_amount;
 92 
 93     /** @public string Error message. */
 94     public $error_message;
 95 
 96     /**
 97      * Coupon constructor. Loads coupon data.
 98      *
 99      * @access public
100      * @param mixed $code code of the coupon to load
101      */
102     public function __construct( $code ) {
103         global $wpdb;
104 
105         $this->code  = apply_filters( 'woocommerce_coupon_code', $code );
106 
107         // Coupon data lets developers create coupons through code
108         $coupon_data = apply_filters( 'woocommerce_get_shop_coupon_data', false, $code );
109 
110         if ( $coupon_data ) {
111 
112             $this->id                         = absint( $coupon_data['id'] );
113             $this->type                       = esc_html( $coupon_data['type'] );
114             $this->amount                     = esc_html( $coupon_data['amount'] );
115             $this->individual_use             = esc_html( $coupon_data['individual_use'] );
116             $this->product_ids                = is_array( $coupon_data['product_ids'] ) ? $coupon_data['product_ids'] : array();
117             $this->exclude_product_ids        = is_array( $coupon_data['exclude_product_ids'] ) ? $coupon_data['exclude_product_ids'] : array();
118             $this->usage_limit                = absint( $coupon_data['usage_limit'] );
119             $this->usage_limit_per_user       = isset( $coupon_data['usage_limit_per_user'] ) ? absint( $coupon_data['usage_limit_per_user'] ) : 0;
120             $this->limit_usage_to_x_items     = isset( $coupon_data['limit_usage_to_x_items'] ) ? absint( $coupon_data['limit_usage_to_x_items'] ) : '';
121             $this->usage_count                = absint( $coupon_data['usage_count'] );
122             $this->expiry_date                = esc_html( $coupon_data['expiry_date'] );
123             $this->apply_before_tax           = esc_html( $coupon_data['apply_before_tax'] );
124             $this->free_shipping              = esc_html( $coupon_data['free_shipping'] );
125             $this->product_categories         = is_array( $coupon_data['product_categories'] ) ? $coupon_data['product_categories'] : array();
126             $this->exclude_product_categories = is_array( $coupon_data['exclude_product_categories'] ) ? $coupon_data['exclude_product_categories'] : array();
127             $this->exclude_sale_items         = esc_html( $coupon_data['exclude_sale_items'] );
128             $this->minimum_amount             = esc_html( $coupon_data['minimum_amount'] );
129             $this->customer_email             = esc_html( $coupon_data['customer_email'] );
130 
131         } else {
132 
133             $coupon_id  = $wpdb->get_var( $wpdb->prepare( apply_filters( 'woocommerce_coupon_code_query', "SELECT ID FROM $wpdb->posts WHERE post_title = %s AND post_type = 'shop_coupon' AND post_status = 'publish'" ), $this->code ) );
134 
135             if ( ! $coupon_id )
136                 return;
137 
138             $coupon             = get_post( $coupon_id );
139             $this->post_title   = apply_filters( 'woocommerce_coupon_code', $coupon->post_title );
140 
141             if ( empty( $coupon ) || $this->code !== $this->post_title )
142                 return;
143 
144             $this->id                   = $coupon->ID;
145             $this->coupon_custom_fields = get_post_meta( $this->id );
146 
147             $load_data = array(
148                 'discount_type'              => 'fixed_cart',
149                 'coupon_amount'              => 0,
150                 'individual_use'             => 'no',
151                 'product_ids'                => '',
152                 'exclude_product_ids'        => '',
153                 'usage_limit'                => '',
154                 'usage_limit_per_user'       => '',
155                 'limit_usage_to_x_items'     => '',
156                 'usage_count'                => '',
157                 'expiry_date'                => '',
158                 'apply_before_tax'           => 'yes',
159                 'free_shipping'              => 'no',
160                 'product_categories'         => array(),
161                 'exclude_product_categories' => array(),
162                 'exclude_sale_items'         => 'no',
163                 'minimum_amount'             => '',
164                 'customer_email'             => array()
165             );
166 
167             foreach ( $load_data as $key => $default )
168                 $this->$key = isset( $this->coupon_custom_fields[ $key ][0] ) && $this->coupon_custom_fields[ $key ][0] !== '' ? $this->coupon_custom_fields[ $key ][0] : $default;
169 
170             // Alias
171             $this->type                    = $this->discount_type;
172             $this->amount                  = $this->coupon_amount;
173 
174             // Formatting
175             $this->product_ids                = array_filter( array_map( 'trim', explode( ',', $this->product_ids ) ) );
176             $this->exclude_product_ids        = array_filter( array_map( 'trim', explode( ',', $this->exclude_product_ids ) ) );
177             $this->expiry_date                = $this->expiry_date ? strtotime( $this->expiry_date ) : '';
178             $this->product_categories         = array_filter( array_map( 'trim', (array) maybe_unserialize( $this->product_categories ) ) );
179             $this->exclude_product_categories = array_filter( array_map( 'trim', (array) maybe_unserialize( $this->exclude_product_categories ) ) );
180             $this->customer_email             = array_filter( array_map( 'trim', array_map( 'strtolower', (array) maybe_unserialize( $this->customer_email ) ) ) );
181         }
182 
183         do_action( 'woocommerce_coupon_loaded', $this );
184     }
185 
186 
187     /**
188      * Check if coupon needs applying before tax.
189      *
190      * @access public
191      * @return bool
192      */
193     public function apply_before_tax() {
194         return $this->apply_before_tax == 'yes' ? true : false;
195     }
196 
197 
198     /**
199      * Check if a coupon enables free shipping.
200      *
201      * @access public
202      * @return bool
203      */
204     public function enable_free_shipping() {
205         return $this->free_shipping == 'yes' ? true : false;
206     }
207 
208 
209     /**
210      * Check if a coupon excludes sale items.
211      *
212      * @access public
213      * @return bool
214      */
215     public function exclude_sale_items() {
216         return $this->exclude_sale_items == 'yes' ? true : false;
217     }
218 
219 
220 
221     /**
222      * Increase usage count fo current coupon.
223      *
224      * @access public
225      * @param  string $used_by Either user ID or billing email
226      * @return void
227      */
228     public function inc_usage_count( $used_by = '' ) {
229         $this->usage_count++;
230         update_post_meta( $this->id, 'usage_count', $this->usage_count );
231 
232         if ( $used_by ) {
233             add_post_meta( $this->id, '_used_by', strtolower( $used_by ) );
234         }
235     }
236 
237 
238     /**
239      * Decrease usage count fo current coupon.
240      *
241      * @access public
242      * @param  string $used_by Either user ID or billing email
243      * @return void
244      */
245     public function dcr_usage_count( $used_by = '' ) {
246         global $wpdb;
247 
248         $this->usage_count--;
249         update_post_meta( $this->id, 'usage_count', $this->usage_count );
250 
251         // Delete 1 used by meta
252         $meta_id = $wpdb->get_var( $wpdb->prepare( "SELECT meta_id FROM $wpdb->postmeta WHERE meta_key = '_used_by' AND meta_value = %s AND post_id = %d LIMIT 1;", $used_by, $this->id ) );
253         if ( $meta_id ) {
254             delete_metadata_by_mid( 'post', $meta_id );
255         }
256     }
257 
258     /**
259      * Returns the error_message string
260      *
261      * @access public
262      * @return string
263      */
264     public function get_error_message() {
265         return $this->error_message;
266     }
267 
268     /**
269      * is_valid function.
270      *
271      * Check if a coupon is valid. Return a reason code if invalid. Reason codes:
272      *
273      * @access public
274      * @return bool|WP_Error validity or a WP_Error if not valid
275      */
276     public function is_valid() {
277 
278         $error_code = null;
279         $valid      = true;
280         $error      = false;
281 
282         if ( $this->id ) {
283 
284             // Usage Limit
285             if ( $this->usage_limit > 0 ) {
286                 if ( $this->usage_count >= $this->usage_limit ) {
287                     $valid = false;
288                     $error_code = self::E_WC_COUPON_USAGE_LIMIT_REACHED;
289                 }
290             }
291 
292             // Per user usage limit - check here if user is logged in (against user IDs)
293             // Checked again for emails later on in WC_Cart::check_customer_coupons()
294             if ( $this->usage_limit_per_user > 0 && is_user_logged_in() ) {
295                 $used_by     = (array) get_post_meta( $this->id, '_used_by' );
296                 $usage_count = sizeof( array_keys( $used_by, get_current_user_id() ) );
297 
298                 if ( $usage_count >= $this->usage_limit_per_user ) {
299                     $valid = false;
300                     $error_code = self::E_WC_COUPON_USAGE_LIMIT_REACHED;
301                 }
302             }
303 
304             // Expired
305             if ( $this->expiry_date ) {
306                 if ( current_time( 'timestamp' ) > $this->expiry_date ) {
307                     $valid = false;
308                     $error_code = self::E_WC_COUPON_EXPIRED;
309                 }
310             }
311 
312             // Minimum spend
313             if ( $this->minimum_amount > 0 ) {
314                 if ( $this->minimum_amount > WC()->cart->subtotal ) {
315                     $valid = false;
316                     $error_code = self::E_WC_COUPON_MIN_SPEND_LIMIT_NOT_MET;
317                 }
318             }
319 
320             // Product ids - If a product included is found in the cart then its valid
321             if ( sizeof( $this->product_ids ) > 0 ) {
322                 $valid_for_cart = false;
323                 if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
324                     foreach( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
325 
326                         if ( in_array( $cart_item['product_id'], $this->product_ids ) || in_array( $cart_item['variation_id'], $this->product_ids ) || in_array( $cart_item['data']->get_parent(), $this->product_ids ) )
327                             $valid_for_cart = true;
328                     }
329                 }
330                 if ( ! $valid_for_cart ) {
331                     $valid = false;
332                     $error_code = self::E_WC_COUPON_NOT_APPLICABLE;
333                 }
334             }
335 
336             // Category ids - If a product included is found in the cart then its valid
337             if ( sizeof( $this->product_categories ) > 0 ) {
338                 $valid_for_cart = false;
339                 if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
340                     foreach( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
341 
342                         $product_cats = wp_get_post_terms($cart_item['product_id'], 'product_cat', array("fields" => "ids"));
343 
344                         if ( sizeof( array_intersect( $product_cats, $this->product_categories ) ) > 0 )
345                             $valid_for_cart = true;
346                     }
347                 }
348                 if ( ! $valid_for_cart ) {
349                     $valid = false;
350                     $error_code = self::E_WC_COUPON_NOT_APPLICABLE;
351                 }
352             }
353 
354             // Cart discounts cannot be added if non-eligble product is found in cart
355             if ( $this->type != 'fixed_product' && $this->type != 'percent_product' ) {
356 
357                 // Exclude Products
358                 if ( sizeof( $this->exclude_product_ids ) > 0 ) {
359                     $valid_for_cart = true;
360                     if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
361                         foreach( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
362                             if ( in_array( $cart_item['product_id'], $this->exclude_product_ids ) || in_array( $cart_item['variation_id'], $this->exclude_product_ids ) || in_array( $cart_item['data']->get_parent(), $this->exclude_product_ids ) ) {
363                                 $valid_for_cart = false;
364                             }
365                         }
366                     }
367                     if ( ! $valid_for_cart ) {
368                         $valid = false;
369                         $error_code = self::E_WC_COUPON_NOT_APPLICABLE;
370                     }
371                 }
372 
373                 // Exclude Sale Items
374                 if ( $this->exclude_sale_items == 'yes' ) {
375                     $valid_for_cart = true;
376                     $product_ids_on_sale = wc_get_product_ids_on_sale();
377                     if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
378                         foreach( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
379                             if ( in_array( $cart_item['product_id'], $product_ids_on_sale, true ) || in_array( $cart_item['variation_id'], $product_ids_on_sale, true ) || in_array( $cart_item['data']->get_parent(), $product_ids_on_sale, true ) ) {
380                                 $valid_for_cart = false;
381                             }
382                         }
383                     }
384                     if ( ! $valid_for_cart ) {
385                         $valid = false;
386                         $error_code = self::E_WC_COUPON_NOT_VALID_SALE_ITEMS;
387                     }
388                 }
389 
390                 // Exclude Categories
391                 if ( sizeof( $this->exclude_product_categories ) > 0 ) {
392                     $valid_for_cart = true;
393                     if ( sizeof( WC()->cart->get_cart() ) > 0 ) {
394                         foreach( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
395 
396                             $product_cats = wp_get_post_terms( $cart_item['product_id'], 'product_cat', array( "fields" => "ids" ) );
397 
398                             if ( sizeof( array_intersect( $product_cats, $this->exclude_product_categories ) ) > 0 )
399                                 $valid_for_cart = false;
400                         }
401                     }
402                     if ( ! $valid_for_cart ) {
403                         $valid = false;
404                         $error_code = self::E_WC_COUPON_NOT_APPLICABLE;
405                     }
406                 }
407             }
408 
409             $valid = apply_filters( 'woocommerce_coupon_is_valid', $valid, $this );
410 
411             if ( $valid ) {
412                 return true;
413             } else {
414                 if ( is_null( $error_code ) )
415                     $error_code = self::E_WC_COUPON_INVALID_FILTERED;
416             }
417 
418         } else {
419             $error_code = self::E_WC_COUPON_NOT_EXIST;
420         }
421 
422         if ( $error_code )
423             $this->error_message = $this->get_coupon_error( $error_code );
424 
425         return false;
426     }
427 
428     /**
429      * Check if a coupon is valid
430      *
431      * @return bool
432      */
433     public function is_valid_for_cart() {
434         if ( $this->type != 'fixed_cart' && $this->type != 'percent' )
435             return false;
436         else
437             return true;
438     }
439 
440     /**
441      * Check if a coupon is valid for a product
442      * 
443      * @param  WC_Product  $product
444      * @return boolean
445      */
446     public function is_valid_for_product( $product ) {
447         if ( $this->type != 'fixed_product' && $this->type != 'percent_product' )
448             return false;
449 
450         $valid        = false;
451         $product_cats = wp_get_post_terms( $product->id, 'product_cat', array( "fields" => "ids" ) );
452 
453         // Specific products get the discount
454         if ( sizeof( $this->product_ids ) > 0 ) {
455 
456             if ( in_array( $product->id, $this->product_ids ) || ( isset( $product->variation_id ) && in_array( $product->variation_id, $this->product_ids ) ) || in_array( $product->get_parent(), $this->product_ids ) )
457                 $valid = true;
458 
459         // Category discounts
460         } elseif ( sizeof( $this->product_categories ) > 0 ) {
461 
462             if ( sizeof( array_intersect( $product_cats, $this->product_categories ) ) > 0 )
463                 $valid = true;
464 
465         } else {
466             // No product ids - all items discounted
467             $valid = true;
468         }
469 
470         // Specific product ID's excluded from the discount
471         if ( sizeof( $this->exclude_product_ids ) > 0 )
472             if ( in_array( $product->id, $this->exclude_product_ids ) || ( isset( $product->variation_id ) && in_array( $product->variation_id, $this->exclude_product_ids ) ) || in_array( $product->get_parent(), $this->exclude_product_ids ) )
473                 $valid = false;
474 
475         // Specific categories excluded from the discount
476         if ( sizeof( $this->exclude_product_categories ) > 0 )
477             if ( sizeof( array_intersect( $product_cats, $this->exclude_product_categories ) ) > 0 )
478                 $valid = false;
479 
480         // Sale Items excluded from discount
481         if ( $this->exclude_sale_items == 'yes' ) {
482             $product_ids_on_sale = wc_get_product_ids_on_sale();
483 
484             if ( in_array( $product->id, $product_ids_on_sale, true ) || ( isset( $product->variation_id ) && in_array( $product->variation_id, $product_ids_on_sale, true ) ) || in_array( $product->get_parent(), $product_ids_on_sale, true ) )
485                 $valid = false;
486         }
487 
488         return apply_filters( 'woocommerce_coupon_is_valid_for_product', $valid, $product, $this );
489     }
490 
491     /**
492      * Get discount amount for a cart item
493      * 
494      * @param  float $discounting_amount Amount the coupon is being applied to
495      * @param  array|null $cart_item Cart item being discounted if applicable
496      * @param  boolean $single True if discounting a single qty item, false if its the line
497      * @return float Amount this coupon has discounted
498      */
499     public function get_discount_amount( $discounting_amount, $cart_item = null, $single = false ) {
500         $discount = 0;
501 
502         if ( $this->type == 'fixed_product') {
503 
504             $discount = $discounting_amount < $this->amount ? $discounting_amount : $this->amount;
505 
506             // If dealing with a line and not a single item, we need to multiple fixed discount by cart item qty.
507             if ( ! $single && ! is_null( $cart_item ) ) {
508                 // Discount for the line.
509                 $discount = $discount * $cart_item['quantity'];
510             }
511 
512         } elseif ( $this->type == 'percent_product' || $this->type == 'percent' ) {
513 
514             $discount = round( ( $discounting_amount / 100 ) * $this->amount, WC()->cart->dp );
515 
516         } elseif ( $this->type == 'fixed_cart' ) {
517             if ( ! is_null( $cart_item ) ) {
518                 /**
519                  * This is the most complex discount - we need to divide the discount between rows based on their price in
520                  * proportion to the subtotal. This is so rows with different tax rates get a fair discount, and so rows
521                  * with no price (free) don't get discounted.
522                  *
523                  * Get item discount by dividing item cost by subtotal to get a %
524                  */
525                 $discount_percent = 0;
526 
527                 if ( WC()->cart->subtotal_ex_tax ) {
528                     $discount_percent = ( $cart_item['data']->get_price_excluding_tax() * $cart_item['quantity'] ) / WC()->cart->subtotal_ex_tax;
529                 }
530                     
531                 $discount = min( ( $this->amount * $discount_percent ) / $cart_item['quantity'], $discounting_amount );
532             } else {
533                 $discount = min( $this->amount, $discounting_amount );
534             }
535         }
536 
537         // Handle the limit_usage_to_x_items option
538         if ( in_array( $this->type, array( 'percent_product', 'fixed_product' ) ) && ! is_null( $cart_item ) ) {
539             $qty = empty( $this->limit_usage_to_x_items ) ? $cart_item['quantity'] : min( $this->limit_usage_to_x_items, $cart_item['quantity'] );
540 
541             if ( $single ) {
542                 $discount = ( $discount * $qty ) / $cart_item['quantity'];
543             } else {
544                 $discount = ( $discount / $cart_item['quantity'] ) * $qty;
545             }
546         }
547 
548         return apply_filters( 'woocommerce_coupon_get_discount_amount', $discount, $discounting_amount, $cart_item, $single, $this );
549     }
550 
551     /**
552      * Converts one of the WC_Coupon message/error codes to a message string and
553      * displays the message/error.
554      *
555      * @access public
556      * @param int $msg_code Message/error code.
557      * @return void
558      */
559     public function add_coupon_message( $msg_code ) {
560 
561         if ( $msg_code < 200 )
562             wc_add_notice( $this->get_coupon_error( $msg_code ), 'error' );
563         else
564             wc_add_notice( $this->get_coupon_message( $msg_code ) );
565     }
566 
567     /**
568      * Map one of the WC_Coupon message codes to a message string
569      *
570      * @access public
571      * @param mixed $msg_code
572      * @return string| Message/error string
573      */
574     public function get_coupon_message( $msg_code ) {
575 
576         switch ( $msg_code ) {
577             case self::WC_COUPON_SUCCESS :
578                 $msg = __( 'Coupon code applied successfully.', 'woocommerce' );
579             break;
580             case self::WC_COUPON_REMOVED :
581                 $msg = __( 'Coupon code removed successfully.', 'woocommerce' );
582             break;
583             default:
584                 $msg = '';
585             break;
586         }
587 
588         return apply_filters( 'woocommerce_coupon_message', $msg, $msg_code, $this );
589     }
590 
591     /**
592      * Map one of the WC_Coupon error codes to a message string
593      *
594      * @access public
595      * @param int $err_code Message/error code.
596      * @return string| Message/error string
597      */
598     public function get_coupon_error( $err_code ) {
599 
600         switch ( $err_code ) {
601             case self::E_WC_COUPON_INVALID_FILTERED:
602                 $err = __( 'Coupon is not valid.', 'woocommerce' );
603             break;
604             case self::E_WC_COUPON_NOT_EXIST:
605                 $err = __( 'Coupon does not exist!', 'woocommerce' );
606             break;
607             case self::E_WC_COUPON_INVALID_REMOVED:
608                 $err = sprintf( __( 'Sorry, it seems the coupon "%s" is invalid - it has now been removed from your order.', 'woocommerce' ), $this->code );
609             break;
610             case self::E_WC_COUPON_NOT_YOURS_REMOVED:
611                 $err = sprintf( __( 'Sorry, it seems the coupon "%s" is not yours - it has now been removed from your order.', 'woocommerce' ), $this->code );
612             break;
613             case self::E_WC_COUPON_ALREADY_APPLIED:
614                 $err = __( 'Coupon code already applied!', 'woocommerce' );
615             break;
616             case self::E_WC_COUPON_ALREADY_APPLIED_INDIV_USE_ONLY:
617                 $err = sprintf( __( 'Sorry, coupon "%s" has already been applied and cannot be used in conjunction with other coupons.', 'woocommerce' ), $this->code );
618             break;
619             case self::E_WC_COUPON_USAGE_LIMIT_REACHED:
620                 $err = __( 'Coupon usage limit has been reached.', 'woocommerce' );
621             break;
622             case self::E_WC_COUPON_EXPIRED:
623                 $err = __( 'This coupon has expired.', 'woocommerce' );
624             break;
625             case self::E_WC_COUPON_MIN_SPEND_LIMIT_NOT_MET:
626                 $err = sprintf( __( 'The minimum spend for this coupon is %s.', 'woocommerce' ), wc_price( $this->minimum_amount ) );
627             break;
628             case self::E_WC_COUPON_NOT_APPLICABLE:
629                 $err = __( 'Sorry, this coupon is not applicable to your cart contents.', 'woocommerce' );
630             break;
631             case self::E_WC_COUPON_NOT_VALID_SALE_ITEMS:
632                 $err = __( 'Sorry, this coupon is not valid for sale items.', 'woocommerce' );
633             break;
634             default:
635                 $err = '';
636             break;
637         }
638 
639         return apply_filters( 'woocommerce_coupon_error', $err, $err_code, $this );
640     }
641 
642     /**
643      * Map one of the WC_Coupon error codes to an error string
644      * No coupon instance will be available where a coupon does not exist,
645      * so this static method exists.
646      *
647      * @access public
648      * @param int $err_code Error code
649      * @return string| Error string
650      */
651     public static function get_generic_coupon_error( $err_code ) {
652 
653         switch ( $err_code ) {
654             case self::E_WC_COUPON_NOT_EXIST:
655                 $err = __( 'Coupon does not exist!', 'woocommerce' );
656             break;
657             case self::E_WC_COUPON_PLEASE_ENTER:
658                 $err = __( 'Please enter a coupon code.', 'woocommerce' );
659             break;
660             default:
661                 $err = '';
662             break;
663         }
664 
665         // When using this static method, there is no $this to pass to filter
666         return apply_filters( 'woocommerce_coupon_error', $err, $err_code, null );
667     }
668 
669 }
670 
WooCommerce API documentation generated by ApiGen 2.8.0