1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
if ( ! defined( 'ABSPATH' ) ) { |
4
|
|
|
exit; // Exit if accessed directly |
5
|
|
|
} |
6
|
|
|
|
7
|
|
|
/** |
8
|
|
|
* Cart Coupons. |
9
|
|
|
* |
10
|
|
|
* @class WC_Cart_Coupons |
11
|
|
|
* @version 2.7.0 |
12
|
|
|
* @package WooCommerce/Classes |
13
|
|
|
* @category Class |
14
|
|
|
* @author WooThemes |
15
|
|
|
*/ |
16
|
|
|
class WC_Cart_Coupons { |
17
|
|
|
|
18
|
|
|
/** |
19
|
|
|
* An array of coupon objects. |
20
|
|
|
* @var object[] |
21
|
|
|
*/ |
22
|
|
|
private $coupons = array(); |
23
|
|
|
|
24
|
|
|
/** |
25
|
|
|
* Constructor. |
26
|
|
|
*/ |
27
|
|
|
public function __construct() { |
28
|
|
|
add_action( 'woocommerce_check_cart_items', array( $this, 'check_coupons' ), 1 ); |
29
|
|
|
add_action( 'woocommerce_after_checkout_validation', array( $this, 'check_customer_restriction' ), 1 ); |
30
|
|
|
add_action( 'woocommerce_after_checkout_validation', array( $this, 'check_customer_limits' ), 1 ); |
31
|
|
|
add_action( 'woocommerce_applied_coupon', array( $this, 'applied_coupon' ), 10, 2 ); |
32
|
|
|
} |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* Get coupons. |
36
|
|
|
* @return array |
37
|
|
|
*/ |
38
|
|
|
public function get_coupons() { |
39
|
|
|
return $this->coupons; |
40
|
|
|
} |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* Set coupons. |
44
|
|
|
* @param array $set |
45
|
|
|
*/ |
46
|
|
|
public function set_coupons( $set ) { |
47
|
|
|
$set = array_filter( (array) $set ); |
48
|
|
|
$this->coupons = array(); |
49
|
|
|
|
50
|
|
|
foreach ( $set as $code => $coupon ) { |
51
|
|
|
if ( is_object( $coupon ) ) { |
52
|
|
|
$this->coupons[ $code ] = $coupon; |
53
|
|
|
} else { |
54
|
|
|
$this->coupons[ $coupon ] = new WC_Coupon( $coupon ); |
55
|
|
|
} |
56
|
|
|
} |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* Remove a single coupon by code. |
61
|
|
|
* @param string $coupon_code Code of the coupon to remove |
62
|
|
|
*/ |
63
|
|
|
public function remove_coupon( $coupon_code ) { |
64
|
|
|
$coupon_code = wc_format_coupon_code( $coupon_code ); |
65
|
|
|
unset( $this->coupons[ $coupon_code ] ); |
66
|
|
|
do_action( 'woocommerce_removed_coupon', $coupon_code ); |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* Check cart coupons for errors. |
71
|
|
|
*/ |
72
|
|
|
public function check_coupons() { |
73
|
|
|
foreach ( $this->coupons as $code => $coupon ) { |
74
|
|
View Code Duplication |
if ( ! $coupon->is_valid() ) { |
|
|
|
|
75
|
|
|
$coupon->add_coupon_message( WC_Coupon::E_WC_COUPON_INVALID_REMOVED ); |
76
|
|
|
$this->remove_coupon( $code ); |
77
|
|
|
WC()->session->set( 'refresh_totals', true ); |
78
|
|
|
} |
79
|
|
|
} |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* Check for user coupons (now that we have billing email). If a coupon is invalid, add an error. |
84
|
|
|
* @param array $posted |
85
|
|
|
*/ |
86
|
|
|
public function check_customer_restriction( $posted ) { |
87
|
|
|
foreach ( $this->coupons as $code => $coupon ) { |
88
|
|
|
if ( sizeof( $coupon->get_email_restrictions() ) > 0 ) { |
89
|
|
|
$check_emails = array( |
90
|
|
|
$posted['billing_email'] |
91
|
|
|
); |
92
|
|
|
if ( is_user_logged_in() ) { |
93
|
|
|
$current_user = wp_get_current_user(); |
94
|
|
|
$check_emails[] = $current_user->user_email; |
95
|
|
|
} |
96
|
|
|
$check_emails = array_map( 'sanitize_email', array_map( 'strtolower', $check_emails ) ); |
97
|
|
|
|
98
|
|
|
if ( 0 == sizeof( array_intersect( $check_emails, $coupon->get_email_restrictions() ) ) ) { |
99
|
|
|
$coupon->add_coupon_message( WC_Coupon::E_WC_COUPON_NOT_YOURS_REMOVED ); |
100
|
|
|
$this->remove_coupon( $code ); |
101
|
|
|
WC()->session->set( 'refresh_totals', true ); |
102
|
|
|
} |
103
|
|
|
} |
104
|
|
|
} |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* Check for user coupons (now that we have billing email). If a coupon is invalid, add an error. |
109
|
|
|
* @param array $posted |
110
|
|
|
*/ |
111
|
|
|
public function check_customer_limits( $posted ) { |
112
|
|
|
foreach ( $this->coupons as $code => $coupon ) { |
113
|
|
|
// Usage limits per user - check against billing and user email and user ID |
114
|
|
|
if ( $coupon->get_usage_limit_per_user() > 0 ) { |
115
|
|
|
$check_emails = array(); |
116
|
|
|
$used_by = $coupon->get_used_by(); |
117
|
|
|
|
118
|
|
|
if ( is_user_logged_in() ) { |
119
|
|
|
$current_user = wp_get_current_user(); |
120
|
|
|
$check_emails[] = sanitize_email( $current_user->user_email ); |
121
|
|
|
$usage_count = sizeof( array_keys( $used_by, get_current_user_id() ) ); |
122
|
|
|
} else { |
123
|
|
|
$check_emails[] = sanitize_email( $posted['billing_email'] ); |
124
|
|
|
$user = get_user_by( 'email', $posted['billing_email'] ); |
125
|
|
|
if ( $user ) { |
126
|
|
|
$usage_count = sizeof( array_keys( $used_by, $user->ID ) ); |
127
|
|
|
} else { |
128
|
|
|
$usage_count = 0; |
129
|
|
|
} |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
foreach ( $check_emails as $check_email ) { |
133
|
|
|
$usage_count = $usage_count + sizeof( array_keys( $used_by, $check_email ) ); |
134
|
|
|
} |
135
|
|
|
|
136
|
|
View Code Duplication |
if ( $usage_count >= $coupon->get_usage_limit_per_user() ) { |
|
|
|
|
137
|
|
|
$coupon->add_coupon_message( WC_Coupon::E_WC_COUPON_USAGE_LIMIT_REACHED ); |
138
|
|
|
$this->remove_coupon( $code ); |
139
|
|
|
WC()->session->set( 'refresh_totals', true ); |
140
|
|
|
} |
141
|
|
|
} |
142
|
|
|
} |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* Add a message for the applied coupon. |
147
|
|
|
* @param string $code |
148
|
|
|
* @param WC_Coupon $coupon |
149
|
|
|
*/ |
150
|
|
|
public function applied_coupon( $code, $coupon ) { |
151
|
|
|
$coupon->add_coupon_message( WC_Coupon::WC_COUPON_SUCCESS ); |
152
|
|
|
if ( $coupon->get_free_shipping() ) { |
153
|
|
|
WC()->session->set( 'chosen_shipping_methods', null ); |
154
|
|
|
} |
155
|
|
|
} |
156
|
|
|
} |
157
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.