PluginProbe
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster / trunk
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster vtrunk
2.6.0 trunk 1.1.0 1.1.4 1.2.1 1.2.2 1.2.3 1.2.5 1.2.9 1.3.1 1.3.2 1.5.0 1.5.1 1.5.4 1.5.7 1.5.8 1.5.9 1.6.2 1.6.5 1.6.8 1.7.2 1.7.4 1.7.5 1.7.9 1.8.1 All 42 releases
sellkit / includes / block-editor / blocks / smart-coupon / helper.php

helper.php in SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster trunk, at includes/block-editor/blocks/smart-coupon/helper.php

401 lines 13.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Sellkit\Blocks\Helpers\Smart_Coupon;
3
4 defined( 'ABSPATH' ) || die();
5
6 /**
7 * Smart Coupon block helper class.
8 *
9 * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
10 * @SuppressWarnings(PHPMD.NPathComplexity)
11 * @since 2.3.0
12 */
13 class Helper {
14 /**
15 * Class constructor.
16 *
17 * @since 2.3.0
18 */
19 public function __construct() {
20 add_action( 'wp_ajax_sellkit_block_check_smart_coupon', [ $this, 'check_coupon' ] );
21 add_action( 'wp_ajax_nopriv_sellkit_block_check_smart_coupon', [ $this, 'check_coupon' ] );
22 add_action( 'wp_ajax_sellkit_block_get_smart_coupon', [ $this, 'get_coupon' ] );
23 add_action( 'wp_ajax_nopriv_sellkit_block_get_smart_coupon', [ $this, 'get_coupon' ] );
24 }
25
26 /**
27 * Create Coupons.
28 *
29 * @SuppressWarnings(PHPMD.CyclomaticComplexity)
30 * @since 2.3.0
31 * @param string $display_type Display type.
32 */
33 public function create_coupons( $display_type ) {
34 $rule = $this->get_rule_by_conditions( $display_type );
35
36 $coupon_meta = get_post_meta( $rule );
37 $filters = get_post_meta( $rule, 'filters', true );
38 $coupon_type = ! empty( $coupon_meta['sellkit_type'][0] ) ? $coupon_meta['sellkit_type'][0] : 'percent';
39 $coupon_amount = ! empty( $coupon_meta['value'][0] ) ? $coupon_meta['value'][0] : 0;
40 $use_with_others = ! empty( $coupon_meta['use_with_other_coupon'][0] ) ? $coupon_meta['use_with_other_coupon'][0] : false;
41 $apply_to_on_sale = ! empty( $coupon_meta['apply_onsale_product'][0] ) ? $coupon_meta['apply_onsale_product'][0] : false;
42 $minimum_subtotal = ! empty( $coupon_meta['minimum_subtotal_count'][0] ) ? $coupon_meta['minimum_subtotal_count'][0] : '';
43 $coupon_limitation = ! empty( $coupon_meta['can_use_count_total'][0] ) ? $coupon_meta['can_use_count_total'][0] : '';
44 $expiration_number = ! empty( $coupon_meta['sellkit_expiration_date_number'][0] ) ? $coupon_meta['sellkit_expiration_date_number'][0] : '';
45 $expiration_type = ! empty( $coupon_meta['sellkit_expiration_date_type'][0] ) ? $coupon_meta['sellkit_expiration_date_type'][0] : '';
46 $is_individual = ! empty( $coupon_meta['sellkit_can_use'][0] ) ? $coupon_meta['sellkit_can_use'][0] : false;
47 $coupon_limit_per_user = ! empty( $coupon_meta['sellkit_can_use_count'][0] ) ? $coupon_meta['sellkit_can_use_count'][0] : '';
48 $expiration_time = $this->get_expiration_time( $expiration_number, $expiration_type );
49
50 $coupon = new \WC_Coupon();
51
52 // Generate a non existing coupon code name.
53 $coupon_code = self::generate_coupon_code();
54
55 // Set the necessary coupon data.
56 $coupon->set_code( $coupon_code );
57
58 if ( empty( $filters ) ) {
59 $filters = [];
60 }
61
62 foreach ( $filters as $filter ) {
63 if ( 'products' === $filter['subject'] && 'is' === $filter['operator'] ) {
64 $coupon->set_product_ids( sellkit_get_multi_select_values( $filter['value'] ) );
65 }
66
67 if ( 'products' === $filter['subject'] && 'is_not' === $filter['operator'] ) {
68 $coupon->set_excluded_product_ids( sellkit_get_multi_select_values( $filter['value'] ) );
69 }
70
71 if ( 'categories' === $filter['subject'] && 'is_not' === $filter['operator'] ) {
72 $coupon->set_excluded_product_categories( sellkit_get_multi_select_values( $filter['value'] ) );
73 }
74
75 if ( 'categories' === $filter['subject'] && 'is' === $filter['operator'] ) {
76 $coupon->set_product_categories( sellkit_get_multi_select_values( $filter['value'] ) );
77 }
78 }
79
80 if ( 'percent' === $coupon_type && $coupon_amount > 100 ) {
81 $coupon_amount = 100;
82 }
83
84 if ( empty( $coupon_amount ) ) {
85 return;
86 }
87
88 $coupon->set_discount_type( $coupon_type );
89 $coupon->set_amount( floatval( $coupon_amount ) );
90 $coupon->set_individual_use( ! $use_with_others );
91 $coupon->set_exclude_sale_items( ! $apply_to_on_sale );
92 $coupon->set_minimum_amount( $minimum_subtotal );
93 $coupon->set_usage_limit( $coupon_limitation );
94 $coupon->set_usage_limit_per_user( $coupon_limit_per_user );
95
96 $coupon->add_meta_data( 'sellkit_personalised_coupon_rule', $rule );
97
98 if ( ! empty( $expiration_time ) ) {
99 $coupon->set_date_expires( $expiration_time );
100 }
101
102 if ( $is_individual && ! empty( wp_get_current_user()->user_email ) ) {
103 $coupon->set_email_restrictions( wp_get_current_user()->user_email );
104 }
105
106 // Create, publish and save coupon (data).
107 $coupon->save();
108
109 return [
110 'code' => $coupon_code,
111 'amount' => $coupon_amount,
112 'type' => $coupon_type,
113 'expiration_date' => empty( $expiration_time ) ? '' : get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $expiration_time ), 'Y/m/d h:i A' ),
114 'display_type' => $display_type,
115 'rule_id' => $rule,
116 'coupon_id' => $coupon->get_id(),
117 ];
118 }
119
120 /**
121 * Coupons generator.
122 *
123 * @since 2.3.0
124 * @return string
125 */
126 public static function generate_coupon_code() {
127 return strtolower( wp_generate_password( 10, false ) );
128 }
129
130 /**
131 * Gets expiration time.
132 *
133 * @since 2.3.0
134 * @param string $number Number of type.
135 * @param string $type The type of time.
136 */
137 private function get_expiration_time( $number, $type ) {
138 if ( empty( $number ) || empty( $type ) ) {
139 return false;
140 }
141
142 $type_days = 1;
143
144 if ( 'weeks' === $type ) {
145 $type_days = 7;
146 }
147
148 if ( 'months' === $type ) {
149 $type_days = 30;
150 }
151
152 return time() + ( ( intval( $number ) * $type_days ) * ( 60 * 60 * 24 ) );
153 }
154
155 /**
156 * Gets coupons.
157 *
158 * @since 2.3.0
159 */
160 public function get_coupon() {
161 check_ajax_referer( 'sellkit_smart_coupon_code', 'nonce' );
162
163 $display_type = sellkit_htmlspecialchars( INPUT_GET, 'display_type' );
164 $coupon = $this->create_coupons( $display_type );
165
166 if ( ! empty( $coupon ) ) {
167 setcookie( 'sellkit_personalised_coupon', wp_json_encode( $coupon ), time() + 86400, '/' );
168 }
169
170 wp_send_json_success( $coupon );
171 }
172
173 /**
174 * Gets rules by conditions.
175 *
176 * @SuppressWarnings(PHPMD.NPathComplexity)
177 * @since 2.3.0
178 * @return string
179 * @param string $display_type Display Type.
180 */
181 private function get_rule_by_conditions( $display_type ) {
182 $args = [
183 'post_type' => 'sellkit-coupon',
184 'post_status' => 'publish',
185 'posts_per_page' => -1,
186 'orderby' => [ 'meta_value_num' => 'ASC' ],
187 'meta_key' => 'sellkit_usage_limit', // phpcs:ignore
188 ];
189
190 if ( 'add-to-content' === $display_type ) {
191 $args['meta_query'] = [ // phpcs:ignore
192 'relation' => 'AND',
193 [
194 'key' => 'sellkit_add_content_page_post',
195 'value' => 'true',
196 ],
197 ];
198 }
199
200 $query = new \WP_Query( $args );
201
202 foreach ( $query->posts as $post ) {
203 $conditions = get_post_meta( $post->ID, 'conditions', true );
204 $is_valid = true;
205 $condition_type = ! empty( $conditions[1]['type'] ) ? $conditions[1]['type'] : 'and';
206
207 if ( 'or' === $condition_type ) {
208 $is_valid = false;
209 }
210
211 if ( ! is_array( $conditions ) ) {
212 continue;
213 }
214
215 foreach ( $conditions as $condition ) {
216 if ( is_array( $condition['condition_value'] ) && ! empty( $condition['condition_value'][0]['value'] ) ) {
217 $condition['condition_value'] = sellkit_get_multi_select_values( $condition['condition_value'] );
218 }
219
220 $result = sellkit_condition_match( $condition['condition_subject'], $condition['condition_operator'], $condition['condition_value'] );
221
222 if ( is_wp_error( $result ) ) {
223 continue;
224 }
225
226 if ( ! $result ) {
227 $is_valid = false;
228 }
229
230 if ( $result && 'or' === $condition_type ) {
231 $is_valid = true;
232 break;
233 }
234 }
235
236 if ( true === $is_valid ) {
237 return $post->ID;
238 }
239 }
240 }
241
242 /**
243 * Checks the cookie coupon.
244 *
245 * @since 2.3.0
246 */
247 public function check_coupon() {
248 check_ajax_referer( 'sellkit_smart_coupon_code', 'nonce' );
249
250 $rule_id = sellkit_htmlspecialchars( INPUT_GET, 'rule_id' );
251 $coupon_id = sellkit_htmlspecialchars( INPUT_GET, 'coupon_id' );
252 $display_type = sellkit_htmlspecialchars( INPUT_GET, 'display_type' );
253 $conditions = get_post_meta( $rule_id, 'conditions', true );
254
255 if ( $coupon_id ) {
256 $this->maybe_update_coupon( $display_type, $coupon_id );
257 }
258
259 if ( sellkit_conditions_validation( $conditions ) ) {
260 wp_send_json_success( [ 'coupon_is_valid' => true ] );
261 }
262
263 wp_send_json_success( [ 'coupon_is_valid' => false ] );
264 }
265
266 /**
267 * Update Coupon if needed.
268 *
269 * @SuppressWarnings(PHPMD.CyclomaticComplexity)
270 * @SuppressWarnings(PHPMD.NPathComplexity)
271 * @since 2.3.0
272 * @param string $display_type Display Type.
273 * @param integer $coupon_id Coupon ID.
274 */
275 public function maybe_update_coupon( $display_type, $coupon_id ) {
276 $rule = $this->get_rule_by_conditions( $display_type );
277
278 $coupon_meta = get_post_meta( $rule );
279 $filters = get_post_meta( $rule, 'filters', true );
280 $coupon_type = ! empty( $coupon_meta['sellkit_type'][0] ) ? $coupon_meta['sellkit_type'][0] : 'percent';
281 $coupon_amount = ! empty( $coupon_meta['value'][0] ) ? $coupon_meta['value'][0] : 0;
282 $use_with_others = ! empty( $coupon_meta['use_with_other_coupon'][0] ) ? $coupon_meta['use_with_other_coupon'][0] : false;
283 $apply_to_on_sale = ! empty( $coupon_meta['apply_onsale_product'][0] ) ? $coupon_meta['apply_onsale_product'][0] : false;
284 $minimum_subtotal = ! empty( $coupon_meta['minimum_subtotal_count'][0] ) ? $coupon_meta['minimum_subtotal_count'][0] : '';
285 $coupon_limitation = ! empty( $coupon_meta['can_use_count_total'][0] ) ? $coupon_meta['can_use_count_total'][0] : '';
286 $expiration_number = ! empty( $coupon_meta['sellkit_expiration_date_number'][0] ) ? $coupon_meta['sellkit_expiration_date_number'][0] : '';
287 $expiration_type = ! empty( $coupon_meta['sellkit_expiration_date_type'][0] ) ? $coupon_meta['sellkit_expiration_date_type'][0] : '';
288 $is_individual = ! empty( $coupon_meta['sellkit_can_use'][0] ) ? $coupon_meta['sellkit_can_use'][0] : false;
289 $coupon_limit_per_user = ! empty( $coupon_meta['sellkit_can_use_count'][0] ) ? $coupon_meta['sellkit_can_use_count'][0] : '';
290 $expiration_time = $this->get_expiration_time( $expiration_number, $expiration_type );
291 $has_changed = true;
292
293 $coupon = new \WC_Coupon( $coupon_id );
294
295 if ( empty( $filters ) ) {
296 $filters = [];
297 }
298
299 foreach ( $filters as $filter ) {
300 if ( 'products' === $filter['subject'] && 'is' === $filter['operator'] && sellkit_get_multi_select_values( $filter['value'] ) !== $coupon->get_product_ids() ) {
301 $coupon->set_product_ids( sellkit_get_multi_select_values( $filter['value'] ) );
302 $has_changed = true;
303 }
304
305 if ( 'products' === $filter['subject'] && 'is_not' === $filter['operator'] && sellkit_get_multi_select_values( $filter['value'] ) !== $coupon->set_excluded_product_ids() ) {
306 $coupon->set_excluded_product_ids( sellkit_get_multi_select_values( $filter['value'] ) );
307 $has_changed = true;
308 }
309
310 if ( 'categories' === $filter['subject'] && 'is_not' === $filter['operator'] && sellkit_get_multi_select_values( $filter['value'] ) !== $coupon->set_excluded_product_categories() ) {
311 $coupon->set_excluded_product_categories( sellkit_get_multi_select_values( $filter['value'] ) );
312 $has_changed = true;
313 }
314
315 if ( 'categories' === $filter['subject'] && 'is' === $filter['operator'] && sellkit_get_multi_select_values( $filter['value'] ) !== $coupon->set_product_categories() ) {
316 $coupon->set_product_categories( sellkit_get_multi_select_values( $filter['value'] ) );
317 $has_changed = true;
318 }
319 }
320
321 if ( 'percent' === $coupon_type && $coupon_amount > 100 ) {
322 $coupon_amount = 100;
323 }
324
325 if ( empty( $coupon_amount ) ) {
326 return;
327 }
328
329 if ( $coupon_type !== $coupon->get_discount_type() ) {
330 $coupon->set_discount_type( $coupon_type );
331 $has_changed = true;
332 }
333
334 if ( floatval( $coupon_amount ) !== $coupon->get_amount() ) {
335 $coupon->set_amount( floatval( $coupon_amount ) );
336 $has_changed = true;
337 }
338
339 if ( ! $use_with_others !== $coupon->get_individual_use() ) {
340 $coupon->set_individual_use( ! $use_with_others );
341 $has_changed = true;
342 }
343
344 if ( ! $apply_to_on_sale !== $coupon->get_exclude_sale_items() ) {
345 $coupon->set_exclude_sale_items( ! $apply_to_on_sale );
346 $has_changed = true;
347 }
348
349 if ( $minimum_subtotal !== $coupon->get_minimum_amount() ) {
350 $coupon->set_minimum_amount( $minimum_subtotal );
351 $has_changed = true;
352 }
353
354 if ( $coupon_limitation !== $coupon->get_usage_limit() ) {
355 $coupon->set_usage_limit( $coupon_limitation );
356 $has_changed = true;
357 }
358
359 if ( $coupon_limit_per_user !== $coupon->get_usage_limit_per_user() ) {
360 $coupon->set_usage_limit_per_user( $coupon_limit_per_user );
361 $has_changed = true;
362 }
363
364 if ( ! empty( $expiration_time ) && $expiration_time !== $coupon->get_date_expires() ) {
365 $coupon->set_date_expires( $expiration_time );
366 $has_changed = true;
367 }
368
369 if ( $is_individual && ! empty( wp_get_current_user()->user_email ) && wp_get_current_user()->user_email !== $coupon->get_email_restrictions() ) {
370 $coupon->set_email_restrictions( wp_get_current_user()->user_email );
371 $has_changed = true;
372 }
373
374 if ( $is_individual && 'anyone' !== $is_individual && '' !== $coupon->get_usage_limit_per_user() ) {
375 $coupon->set_usage_limit_per_user( '' );
376 $has_changed = true;
377 }
378
379 if ( $is_individual && 'anyone' === $is_individual && '' !== $coupon->get_email_restrictions() ) {
380 $coupon->set_email_restrictions( '' );
381 $has_changed = true;
382 }
383
384 if ( $has_changed ) {
385 $coupon->save();
386
387 $coupon_data = [
388 'code' => $coupon->get_code(),
389 'amount' => $coupon_amount,
390 'type' => $coupon_type,
391 'expiration_date' => empty( $expiration_time ) ? '' : get_date_from_gmt( gmdate( 'Y-m-d H:i:s', $expiration_time ), 'Y/m/d h:i A' ),
392 'display_type' => $display_type,
393 'rule_id' => $rule,
394 'coupon_id' => $coupon->get_id(),
395 ];
396
397 setcookie( 'sellkit_personalised_coupon', wp_json_encode( $coupon_data ), time() + 86400, '/' );
398 }
399 }
400 }
401