PluginProbe
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO / 1.1.9
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO v1.1.9
1.4.15 1.4.14 1.4.13 1.4.12 1.4.11 1.4.10 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.54 1.3.53 1.3.52 1.3.51 1.3.50 1.3.49 1.3.48 1.3.47 1.3.46 All 178 releases
disco / app / Utility / Conditions.php

Conditions.php in Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO 1.1.9, at app/Utility/Conditions.php

505 lines 13.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Condition Utility
5 *
6 * @package Disco
7 * @subpackage App\Utility
8 * @since 1.0.0
9 * @category Utility
10 */
11
12 namespace Disco\App\Utility;
13
14 use Disco\App\Attributes\AttributeFactory;
15
16 /**
17 * Class Filter
18 *
19 * @package Disco
20 * @subpackage App\Utility
21 * @author Ohidul Islam <wahid0003@gmail.com>
22 * @link https://webappick.com
23 * @license https://opensource.org/licenses/gpl-license.php GNU Public License
24 * @category Utility
25 */
26 class Conditions {
27
28 /**
29 * @var array $product Product Info.
30 */
31 private $product;
32
33 /**
34 * Contains the conditions array.
35 *
36 * @var array $conditions Filter object.
37 */
38 private $conditions;
39
40 /**
41 * Conditions constructor.
42 *
43 * @param \Disco\App\Utility\Config $config Campaign configuration.
44 * @param array $product Product Object.
45 */
46 public function __construct( $config, $product ) {
47 $this->conditions = $config->get_conditions();
48 $this->product = $product;
49 }
50
51 /**
52 * Check if the product is passed the filter
53 *
54 * @return bool
55 */
56 public function is_passed() {
57 if ( ! empty( $this->conditions ) ) {
58 return $this->check_all_conditions( $this->conditions );
59 }
60
61 return true;
62 }
63
64 /**
65 * Check if the product is passed the filter
66 *
67 * @param array $filters Filter array.
68 * array(
69 * array(
70 * 'base_operator' => 'and',
71 * 'base_filters' => array(
72 * 0 => array(
73 * 'filter' => 'id',
74 * 'operator' => 'and',
75 * 'condition' => 'between',
76 * 'compare' => array( 1, 100 ),
77 * ),
78 * 1 => array(
79 * 'filter' => 'Hat Wizard',
80 * 'operator' => 'and',
81 * 'condition' => 'contain',
82 * 'compare' => 'Hat',
83 * ),
84 * ),
85 * ),
86 * array(
87 * 'base_operator' => 'or',
88 * 'base_filters' => array(
89 * 0 => array(
90 * 'filter' => 'total_sold',
91 * 'operator' => 'and',
92 * 'condition' => 'greater_tan',
93 * 'compare' => 2000,
94 * ),
95 * 1 => array(
96 * 'filter' => 'total_order_name',
97 * 'operator' => 'or',
98 * 'condition' => 'equal',
99 * 'compare' => '100',
100 * ),
101 * ),
102 * array(
103 * 'base_operator' => 'and',
104 * 'base_filters' => array(
105 * 0 => array(
106 * 'filter' => 'total_sold',
107 * 'operator' => 'and',
108 * 'condition' => 'greater_tan',
109 * 'compare' => 2000,
110 * ),
111 * 2 => array(
112 * 'filter' => 'title',
113 * 'operator' => 'and',
114 * 'condition' => 'not_equal',
115 * 'compare' => '',
116 * ),
117 * ),
118 * ),
119 * ),.
120 * @return bool
121 */
122 public function check_group_conditions( $filters ) {// phpcs:ignore
123
124 $result = true;
125 // Start with true, will be updated based on conditions
126 $first = true;
127
128 foreach ( $filters as $filter ) {
129 if ( is_array( $filter ) ) {
130 $filter = (object) $filter;
131 }
132
133 if ( strtolower( $filter->operator ) ) {
134 $operator = strtolower( $filter->operator );
135 } else {
136 $operator = 'and';
137 }
138
139 $condition = $this->compare_value( $filter );
140
141 // Apply the operator
142 if ( $first ) {
143 $result = $condition;
144 $first = false;
145 } elseif ( $operator === 'and' ) {
146 $result = $result && $condition;// phpcs:ignore
147 } elseif ( $operator === 'or' ) {
148 $result = $result || $condition;// phpcs:ignore
149 }
150 }//end foreach
151
152 return $result;
153 }
154
155 /**
156 * Compare value based on a type
157 *
158 * @param object $filter Filter object.
159 * @return bool
160 */
161 public function compare_value( $filter ) {// phpcs:ignore
162
163 // Filter should be an object. If not, return false
164 if ( ! is_object( $filter ) ) {
165 return false;
166 }
167
168 if ( ! is_object( $filter ) || ! isset( $filter->condition, $filter->compare ) ) {
169 return false;
170 }
171
172 $condition = $filter->condition;
173 $compare = $filter->compare;
174
175 $type = $this->get_type( $compare, $condition );
176
177 // Compare value based on a type.
178 switch ( $type ) {
179 case 'date':
180 return $this->date_compare( $filter );
181
182 case 'array':
183 return $this->array_compare( $filter );
184
185 case 'double':
186 case 'integer':
187 return $this->number_compare( $filter );
188
189 default:
190 return $this->string_compare( $filter );
191 }
192 }
193
194 /**
195 * Get the type of the compare value
196 *
197 * @param mixed $compare Compare value.
198 * @param string $condition Condition.
199 * @return string
200 */
201 public function get_type( $compare, $condition ) { // phpcs:ignore
202 // Get $compare variable value type
203 $type = 'string';
204
205 // If $compare is a number, check if it is an integer or double
206 if ( is_numeric( $compare ) ) {
207 $type = 'integer';
208 }
209
210 // If $compare is a date, check if it is a valid date
211 if ( !is_numeric( $compare ) && is_string( $compare ) && strtotime( $compare ) ) {
212 $type = 'date';
213 }
214
215 // If $condition is an array, check if it is an array of strings
216 if ( in_array( $condition, array( 'in_list', 'not_in_list' ), true ) ) {
217 $type = 'array';
218 }
219
220 // If $compare is an array, check if it is a number range. Only for between condition.
221 if ( $condition === 'between' && is_array( $compare ) && count( $compare ) === 2 ) {
222 $type = 'integer';
223 }
224
225 // If $compare is an array, check if it is a date range. Only for date between condition.
226 if ( $condition === 'date_between'
227 && is_array( $compare )
228 && count( $compare ) === 2
229 && strtotime( $compare[0] )
230 && strtotime( $compare[1] )
231 ) {
232 $type = 'date';
233 }
234
235 if ( is_bool( $compare ) ) {
236 $type = 'boolean';
237 }
238
239 return $type;
240 }
241
242 /**
243 * Compare value for a date type.
244 *
245 * @param object $filter Filter object.
246 * @return bool
247 */
248 public function date_compare( $filter ) {
249 if ( ! is_object( $filter ) || ! isset( $filter->condition, $filter->compare, $filter->compare_with ) ) {
250 return false;
251 }
252
253 $condition = $filter->condition;
254 $compare = $filter->compare;
255 $compare_with = AttributeFactory::get_value( $filter->compare_with, $this->product );
256
257 switch ( $condition ) {
258 case 'equal':
259 return $compare === $compare_with;
260
261 case 'not_equal':
262 return $compare !== $compare_with;
263
264 case 'greater':
265 return $compare_with > $compare;
266
267 case 'greater_equal':
268 return $compare_with >= $compare;
269
270 case 'lesser':
271 return $compare_with < $compare;
272
273 case 'lesser_equal':
274 return $compare_with <= $compare;
275
276 case 'date_between':
277 return $compare_with >= $compare[0] && $compare_with <= $compare[1];
278
279 default:
280 return false;
281 }//end switch
282 }
283
284 /**
285 * Compare value for an array type.
286 *
287 * @param object $filter Filter object.
288 * @return bool
289 */
290 public function array_compare( $filter ) {// phpcs:ignore
291 if ( ! is_object( $filter ) || ! isset( $filter->condition, $filter->compare, $filter->compare_with ) ) {
292 return false;
293 }
294
295 $condition = $filter->condition;
296 $compare = $filter->compare;
297
298 // Is compare_with needs to be compared with id or name
299 $column = $this->get_array_compare_column( $filter->compare_with );
300
301 if ( isset( $compare[0] ) && is_object( $compare[0] ) ) {
302 $compare = array_column( (array) $compare, $column );
303 } elseif ( isset( $compare[0] ) && is_array( $compare[0] ) ) {
304 $compare = array_column( $compare, $column );
305 }
306
307 $compare_with = AttributeFactory::get_value( $filter->compare_with, $this->product );
308
309 switch ( $condition ) {
310 case 'not_in_list':
311 if ( is_array( $compare ) && is_array( $compare_with ) ) {
312 // Check if there are no common elements between the two arrays
313 return !count( array_intersect( $compare, $compare_with ) );
314 }
315
316 if ( is_array( $compare_with ) ) {
317 // Check if a scalar $compare is not in the array $compare_with
318 return !in_array( $compare, $compare_with, true );
319 }
320
321 if ( is_array( $compare ) && is_string( $compare_with ) ) {
322 // Check if a string $compare_with is not in the array $compare
323 return !in_array( $compare_with, $compare, true );
324 }
325
326 return false;
327
328 case 'in_list':
329 // return $compare;
330 // Ensure $compare[0] is an array before calling array_intersect
331 if ( is_array( $compare ) && is_array( $compare_with ) ) {
332 // Extract IDs from $compare if $compare_with is an array of IDs
333 return (bool) count( array_intersect( $compare, $compare_with ) );
334 }
335
336 if ( is_array( $compare_with ) && is_string( $compare ) ) {
337 // Check if a scalar $compare is in the array $compare_with
338 return in_array( $compare, $compare_with, true );
339 }
340
341 if ( is_array( $compare ) && is_string( $compare_with ) ) {
342 // Check if a string $compare_with is in the array $compare
343 return in_array( $compare_with, $compare, true );
344 }
345
346 return false;
347
348 default:
349 return false;
350 }
351 }
352
353 /**
354 * Compare value for a number type.
355 *
356 * @param object $filter Filter object.
357 * @return bool
358 */
359 public function number_compare( $filter ) {// phpcs:ignore
360 if ( ! is_object( $filter ) || ! isset( $filter->condition, $filter->compare, $filter->compare_with ) ) {
361 return false;
362 }
363
364 $condition = $filter->condition;
365 $compare = is_array( $filter->compare ) ? array_map(
366 static function( $val ) {
367 return (float) $val;
368 },
369 $filter->compare
370 ) : (float) $filter->compare;
371 $compare_with = (float) AttributeFactory::get_value( $filter->compare_with, $this->product );
372
373 switch ( $condition ) {
374 case 'equal':
375 return $compare === $compare_with;
376
377 case 'not_equal':
378 return $compare !== $compare_with;
379
380 case 'greater':
381 return $compare_with > $compare;
382
383 case 'greater_equal':
384 return $compare_with >= $compare;
385
386 case 'lesser':
387 return $compare_with < $compare;
388
389 case 'lesser_equal':
390 return $compare_with <= $compare;
391
392 case 'between':
393 return $compare_with >= $compare[0] && $compare_with <= $compare[1]; // @phpstan-ignore-line
394
395 default:
396 return false;
397 }//end switch
398 }
399
400 /**
401 * Compare value for a string type.
402 *
403 * @param object $filter Filter object.
404 * @return bool
405 */
406 public function string_compare( $filter ) {
407 if ( ! is_object( $filter ) || ! isset( $filter->condition, $filter->compare, $filter->compare_with ) ) {
408 return false;
409 }
410
411 $condition = $filter->condition;
412 $compare = $filter->compare;
413 $compare_with = AttributeFactory::get_value( $filter->compare_with, $this->product );
414
415 if ( is_array( $compare ) ) {
416 $compare = wp_json_encode( $compare );
417 }
418
419 if ( !is_string( $compare ) ) {
420 $compare = (string) $compare;
421 }
422
423 switch ( $condition ) {
424 case 'equal':
425 return $compare === $compare_with;
426
427 case 'not_equal':
428 return $compare !== $compare_with;
429
430 case 'contain':
431 return stripos( $compare_with, $compare ) !== false;
432
433 case 'not_contain':
434 return stripos( $compare_with, $compare ) === false;
435
436 case 'start_with':
437 return stripos( $compare_with, $compare ) === 0;
438
439 case 'end_with':
440 return substr( $compare_with, -strlen( $compare ) ) === $compare;
441
442 default:
443 return false;
444 }//end switch
445 }
446
447 /**
448 * @param array $filters Filter array.
449 * @return bool
450 */
451 public function check_all_conditions( $filters ) {
452 $final_result = true;
453 $first_group = true;
454
455 if ( empty( $filters ) ) {
456 return true;
457 }
458
459 foreach ( $filters as $group ) {
460 if ( is_array( $group ) ) {
461 $group = (object) $group;
462 }
463
464 $group_result = $this->check_group_conditions( $group->base_filters );
465
466 if ( $first_group ) {
467 $final_result = $group_result;
468 $first_group = false;
469 } elseif ( $group->base_operator === 'and' ) {
470 $final_result = $final_result && $group_result; // phpcs:ignore
471 } elseif ( $group->base_operator === 'or' ) {
472 $final_result = $final_result || $group_result; // phpcs:ignore
473 }
474 }
475
476 return $final_result;
477 }
478
479 /**
480 * Get the column for array compare
481 * Sometime we need to get the column id for array compare.
482 * For example, we need to compare the product id with the array of product ids
483 *
484 * @param string $compare_with Compare with value.
485 * @return string
486 */
487 public function get_array_compare_column( $compare_with ) {
488 $attributes_by_ids = array(
489 'attributes', // Product Attributes
490 'customer_country', // Customer Country
491 'customer_state', // Customer State
492 'customer_history_total_order_made_by_ids', // Number of Orders Made with the Following Products
493 'customer_history_total_amount_sold_by_ids', // Total Amount Sold with the Following Products
494 'customer_history_total_quantity_sold_by_ids', // Number of Orders Made with the Following Products
495 );
496
497 if ( in_array( $compare_with, $attributes_by_ids, true ) ) {
498 return 'id';
499 }
500
501 return 'name';
502 }
503
504 }
505