PluginProbe
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO / 1.2.18
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO v1.2.18
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.2.18, at app/Utility/Conditions.php

514 lines 13.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php // phpcs:ignore
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 { // phpcs:ignore
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 if ( is_array( $compare ) ) {
310 $compare = array_map( 'trim', $compare ); // Trim all values in the array
311 }
312
313 if ( is_array( $compare_with ) ) {
314 $compare_with = array_map( 'trim', $compare_with ); // Trim all values in the array
315 }
316
317 switch ( $condition ) {
318 case 'not_in_list':
319 if ( is_array( $compare ) && is_array( $compare_with ) ) {
320 // Check if there are no common elements between the two arrays
321 return !count( array_intersect( $compare, $compare_with ) );
322 }
323
324 if ( is_array( $compare_with ) ) {
325 // Check if a scalar $compare is not in the array $compare_with
326 return !in_array( $compare, $compare_with, true );
327 }
328
329 if ( is_array( $compare ) && is_string( $compare_with ) ) {
330 // Check if a string $compare_with is not in the array $compare
331 return !in_array( $compare_with, $compare, true );
332 }
333
334 return false;
335
336 case 'in_list':
337 // return $compare;
338 // Ensure $compare[0] is an array before calling array_intersect
339 if ( is_array( $compare ) && is_array( $compare_with ) ) {
340 // Extract IDs from $compare if $compare_with is an array of IDs
341 return (bool) count( array_intersect( $compare, $compare_with ) );
342 }
343
344 if ( is_array( $compare_with ) && is_string( $compare ) ) {
345 // Check if a scalar $compare is in the array $compare_with
346 return in_array( $compare, $compare_with, true );
347 }
348
349 if ( is_array( $compare ) && is_string( $compare_with ) ) {
350 // Check if a string $compare_with is in the array $compare
351 return in_array( $compare_with, $compare, true );
352 }
353
354 return false;
355
356 default:
357 return false;
358 }
359 }
360
361 /**
362 * Compare value for a number type.
363 *
364 * @param object $filter Filter object.
365 * @return bool
366 */
367 public function number_compare( $filter ) {// phpcs:ignore
368 if ( ! is_object( $filter ) || ! isset( $filter->condition, $filter->compare, $filter->compare_with ) ) {
369 return false;
370 }
371
372 $condition = $filter->condition;
373 $compare = is_array( $filter->compare ) ? array_map(
374 static function( $val ) {
375 return (float) $val;
376 },
377 $filter->compare
378 ) : (float) $filter->compare;
379 $compare_with = (float) AttributeFactory::get_value( $filter->compare_with, $this->product );
380
381 switch ( $condition ) {
382 case 'equal':
383 return $compare === $compare_with;
384
385 case 'not_equal':
386 return $compare !== $compare_with;
387
388 case 'greater':
389 return $compare_with > $compare;
390
391 case 'greater_equal':
392 return $compare_with >= $compare;
393
394 case 'lesser':
395 return $compare_with < $compare;
396
397 case 'lesser_equal':
398 return $compare_with <= $compare;
399
400 case 'between':
401 // @phpstan-ignore-next-line
402 return $compare_with >= $compare[0] && $compare_with <= $compare[1];
403
404 default:
405 return false;
406 }//end switch
407 }
408
409 /**
410 * Compare value for a string type.
411 *
412 * @param object $filter Filter object.
413 * @return bool
414 */
415 public function string_compare( $filter ) {
416 if ( ! is_object( $filter ) || ! isset( $filter->condition, $filter->compare, $filter->compare_with ) ) {
417 return false;
418 }
419
420 $condition = $filter->condition;
421 $compare = $filter->compare;
422 $compare_with = AttributeFactory::get_value( $filter->compare_with, $this->product );
423
424 if ( is_array( $compare ) ) {
425 $compare = wp_json_encode( $compare );
426 }
427
428 if ( !is_string( $compare ) ) {
429 $compare = (string) $compare;
430 }
431
432 switch ( $condition ) {
433 case 'equal':
434 return $compare === $compare_with;
435
436 case 'not_equal':
437 return $compare !== $compare_with;
438
439 case 'contain':
440 return stripos( $compare_with, $compare ) !== false;
441
442 case 'not_contain':
443 return stripos( $compare_with, $compare ) === false;
444
445 case 'start_with':
446 return stripos( $compare_with, $compare ) === 0;
447
448 case 'end_with':
449 return substr( $compare_with, -strlen( $compare ) ) === $compare;
450
451 default:
452 return false;
453 }//end switch
454 }
455
456 /**
457 * @param array $filters Filter array.
458 * @return bool
459 */
460 public function check_all_conditions( $filters ) {
461 $final_result = true;
462 $first_group = true;
463
464 if ( empty( $filters ) ) {
465 return true;
466 }
467
468 foreach ( $filters as $group ) {
469 if ( is_array( $group ) ) {
470 $group = (object) $group;
471 }
472
473 $group_result = $this->check_group_conditions( $group->base_filters );
474
475 if ( $first_group ) {
476 $final_result = $group_result;
477 $first_group = false;
478 } elseif ( $group->base_operator === 'and' ) {
479 $final_result = $final_result && $group_result; // phpcs:ignore
480 } elseif ( $group->base_operator === 'or' ) {
481 $final_result = $final_result || $group_result; // phpcs:ignore
482 }
483 }
484
485 return $final_result;
486 }
487
488 /**
489 * Get the column for array compare
490 * Sometime we need to get the column id for array compare.
491 * For example, we need to compare the product id with the array of product ids
492 *
493 * @param string $compare_with Compare with value.
494 * @return string
495 */
496 public function get_array_compare_column( $compare_with ) {
497 $attributes_by_ids = array(
498 'attributes', // Product Attributes
499 'customer_country', // Customer Country
500 'customer_state', // Customer State
501 'customer_history_total_order_made_by_ids', // Number of Orders Made with the Following Products
502 'customer_history_total_amount_sold_by_ids', // Total Amount Sold with the Following Products
503 'customer_history_total_quantity_sold_by_ids', // Number of Orders Made with the Following Products
504 );
505
506 if ( in_array( $compare_with, $attributes_by_ids, true ) ) {
507 return 'id';
508 }
509
510 return 'name';
511 }
512
513 }
514