PluginProbe ʕ •ᴥ•ʔ
JetFormBuilder — Dynamic Blocks Form Builder / 3.6.4.1
JetFormBuilder — Dynamic Blocks Form Builder v3.6.4.1
3.6.4.1 3.6.4 3.6.3.1 3.6.3 3.6.2.2 3.6.2.1 3.6.2 3.6.1.1 3.6.1 3.6.0.1 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.3.0 1.3.1 1.3.2 1.3.3 1.4.0 1.4.1 1.4.2 1.4.3 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.1.0 2.1.1 2.1.10 2.1.11 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 3.0.0 3.0.0.1 3.0.0.2 3.0.0.3 3.0.1 3.0.1.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.0.1 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.3.2 3.3.3 3.3.3.1 3.3.4 3.3.4.1 3.3.4.2 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.4.5.1 3.4.5.2 3.4.6 3.4.7 3.4.7.1 3.5.0 3.5.1 3.5.1.1 3.5.1.2 3.5.2 3.5.2.1 3.5.3 3.5.4 3.5.5 3.5.6 3.5.6.1 3.5.6.2 3.5.6.3 3.6.0
jetformbuilder / includes / db-queries / query-conditions-builder.php
jetformbuilder / includes / db-queries Last commit date
constraints 2 years ago exceptions 2 years ago models 2 years ago traits 2 years ago views 2 years ago base-db-constraint.php 2 years ago base-db-model.php 2 years ago execution-builder.php 2 years ago query-builder.php 2 years ago query-cache-builder.php 2 years ago query-conditions-builder.php 1 month ago
query-conditions-builder.php
629 lines
1 <?php
2
3
4 namespace Jet_Form_Builder\Db_Queries;
5
6 use Jet_Form_Builder\Db_Queries\Traits\With_View;
7 use Jet_Form_Builder\Exceptions\Query_Builder_Exception;
8 use JFB_Components\Db\Db_Tools;
9
10 // If this file is called directly, abort.
11 if ( ! defined( 'WPINC' ) ) {
12 die;
13 }
14
15 /**
16 * @method Query_Conditions_Builder set_view( Views\View_Base $view )
17 *
18 * Class Query_Conditions_Builder
19 * @package Jet_Form_Builder\Db_Queries
20 */
21 class Query_Conditions_Builder {
22
23 const TYPE_EQUAL_STATIC = 'equal_static';
24 const TYPE_EQUAL = 'equal_column';
25 const TYPE_EQUAL_COLUMNS = 'equal_two_columns';
26 const TYPE_LIKE = 'like';
27 const TYPE_NOT_LIKE = 'not_like';
28 const TYPE_MORE_STATIC = 'more_static';
29 const TYPE_MORE_OR_EQUAL_STATIC = 'more_or_equal_static';
30 const TYPE_LESS_STATIC = 'less_static';
31 const TYPE_LESS_OR_EQUAL_STATIC = 'less_or_equal_static';
32 const TYPE_IN = 'in';
33 /**
34 * @since 3.1.0
35 */
36 const TYPE_NOT_EQUAL = 'not_equal_column';
37 const TYPE_LIKE_END = 'like_end';
38 const TYPE_NOT_LIKE_END = 'not_like_end';
39 /**
40 * @since 3.2.0
41 */
42 const TYPE_IS_NULL = 'is_null';
43
44 /**
45 * @since 3.1.0
46 */
47 const RELATIONS_TYPES = array( 'AND', 'OR' );
48
49 use With_View;
50
51 private $conditions = array();
52
53 private $relation_type = 'AND';
54 private $inherit_view_only = false;
55
56 /**
57 * @var array
58 */
59 private $current_condition;
60
61 /**
62 * @var \Generator
63 */
64 private $generator;
65
66 public function get_types(): array {
67 return array(
68 self::TYPE_EQUAL_STATIC => array(
69 'callback' => array( $this, 'build_equal_static' ),
70 ),
71 self::TYPE_EQUAL => array(
72 'callback' => array( $this, 'build_equal_column' ),
73 ),
74 self::TYPE_EQUAL_COLUMNS => array(
75 'callback' => array( $this, 'build_equal_two_columns' ),
76 ),
77 self::TYPE_LIKE => array(
78 'callback' => array( $this, 'build_like' ),
79 ),
80 self::TYPE_NOT_LIKE => array(
81 'callback' => array( $this, 'build_not_like' ),
82 ),
83 self::TYPE_MORE_STATIC => array(
84 'callback' => array( $this, 'build_more_static' ),
85 ),
86 self::TYPE_LESS_STATIC => array(
87 'callback' => array( $this, 'build_less_static' ),
88 ),
89 self::TYPE_IN => array(
90 'callback' => array( $this, 'build_in' ),
91 ),
92 /**
93 * @since 3.1.0
94 */
95 self::TYPE_NOT_EQUAL => array(
96 'callback' => array( $this, 'build_not_equal_column' ),
97 ),
98 self::TYPE_LIKE_END => array(
99 'callback' => array( $this, 'build_like_end' ),
100 ),
101 self::TYPE_NOT_LIKE_END => array(
102 'callback' => array( $this, 'build_not_like_end' ),
103 ),
104 self::TYPE_LESS_OR_EQUAL_STATIC => array(
105 'callback' => array( $this, 'build_less_or_equal_static' ),
106 ),
107 self::TYPE_MORE_OR_EQUAL_STATIC => array(
108 'callback' => array( $this, 'build_more_or_equal_static' ),
109 ),
110 /**
111 * @since 3.2.0
112 */
113 self::TYPE_IS_NULL => array(
114 'callback' => array( $this, 'build_is_null' ),
115 ),
116 );
117 }
118
119 /**
120 * @param array|Query_Conditions_Builder $condition
121 *
122 * @return $this
123 */
124 public function set_condition( $condition ): Query_Conditions_Builder {
125 if ( ! is_array( $condition ) && ! ( $condition instanceof Query_Conditions_Builder ) ) {
126 return $this;
127 }
128 $this->conditions[] = $condition;
129
130 return $this;
131 }
132
133 public function set_conditions( array $conditions ): Query_Conditions_Builder {
134 foreach ( $conditions as $condition ) {
135 $this->set_condition( $condition );
136 }
137
138 return $this;
139 }
140
141 public function after_set_view() {
142 if ( $this->inherit_view_only ) {
143 return;
144 }
145
146 try {
147 $view = $this->view();
148 } catch ( Query_Builder_Exception $exception ) {
149 return;
150 }
151
152 $this->set_conditions( $view->conditions() );
153 }
154
155 private function inherit_view( Views\View_Base $view ): Query_Conditions_Builder {
156 if ( $this->view ) {
157 return $this;
158 }
159
160 $this->inherit_view_only = true;
161 $this->set_view( $view );
162 $this->inherit_view_only = false;
163
164 return $this;
165 }
166
167 /**
168 * @return string
169 */
170 public function result(): string {
171 if ( ! $this->conditions ) {
172 return '';
173 }
174
175 return 'WHERE ' . $this->prepare_conditions();
176 }
177
178 /**
179 * @return string
180 */
181 public function prepare_conditions(): string {
182 $this->generator = $this->generate_conditions();
183 $prepared = array();
184
185 foreach ( $this->generator as $condition ) {
186 $prepared[] = $this->prepare();
187 }
188
189 return implode(
190 sprintf( "\r\n\t%s ", $this->relation_type ),
191 $prepared
192 );
193 }
194
195 /**
196 * @return mixed
197 */
198 public function prepare() {
199 $condition = $this->generator->current();
200
201 if ( $condition instanceof Query_Conditions_Builder ) {
202 if ( $this->view ) {
203 $condition->inherit_view( $this->view );
204 }
205
206 return sprintf( "(\r\n%s\r\n)", $condition->prepare_conditions() );
207 }
208
209 $type = $this->get_condition_type();
210 $values = $this->get_condition_values();
211 $callback = $this->get_types()[ $type ]['callback'];
212
213 return call_user_func( $callback, $values[0], $values[1] ?? false );
214 }
215
216 /**
217 * @return string
218 */
219 private function get_condition_type(): string {
220 $condition = $this->generator->current();
221 $type = $condition['type'] ?? false;
222
223 if ( ! $type || ! in_array( $type, array_keys( $this->get_types() ), true ) ) {
224 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
225 _doing_it_wrong( __METHOD__, "Undefined condition type: $type", '2.0.0' );
226 wp_die();
227 }
228
229 return $type;
230 }
231
232 public function build_equal_static( $first, $second ): string {
233 global $wpdb;
234
235 return $wpdb->prepare(
236 '%s = %s',
237 $first,
238 $second
239 );
240 }
241
242 /**
243 * @param $column_name
244 * @param $second
245 *
246 * @return string
247 */
248 public function build_equal_column( $column_name, $second ): string {
249 global $wpdb;
250
251 $format = $this->get_format_value( $second );
252 $format_col = $this->get_format_column();
253 $column_name = Db_Tools::sanitize_column( $column_name );
254
255 try {
256 $column_name = $this->view()->column( $column_name );
257 } catch ( Query_Builder_Exception $exception ) {
258 // silence
259 }
260
261 return $wpdb->prepare(
262 // phpcs:ignore WordPress.DB
263 sprintf( $format_col, $column_name ) . " = {$format}",
264 $second
265 );
266 }
267
268 /**
269 * @param $column_name
270 * @param $second
271 *
272 * @return string
273 * @since 3.1.0
274 */
275 public function build_not_equal_column( $column_name, $second ): string {
276 global $wpdb;
277
278 $format = $this->get_format_value( $second );
279 $format_col = $this->get_format_column();
280 $column_name = Db_Tools::sanitize_column( $column_name );
281
282 try {
283 $column_name = $this->view()->column( $column_name );
284 } catch ( Query_Builder_Exception $exception ) {
285 // silence
286 }
287
288 return $wpdb->prepare(
289 // phpcs:ignore WordPress.DB
290 sprintf( $format_col, $column_name ) . " != {$format}",
291 $second
292 );
293 }
294
295 /**
296 * @param $column_name
297 * @param $second
298 *
299 * @return string
300 */
301 public function build_equal_two_columns( $column_name, $second ): string {
302 $column_name = Db_Tools::sanitize_column( $column_name );
303 $second = Db_Tools::sanitize_column( $second );
304
305 try {
306 $column_name = $this->view()->column( $column_name );
307 $second = $this->view()->column( $second );
308 } catch ( Query_Builder_Exception $exception ) {
309 // silence
310 }
311
312 return "{$column_name} = {$second}";
313 }
314
315 /**
316 * @param $column_name
317 * @param $second
318 *
319 * @return string
320 */
321 public function build_like( $column_name, $second ): string {
322 $second = esc_sql( $second );
323 $column_name = Db_Tools::sanitize_column( $column_name );
324
325 try {
326 $column_name = $this->view()->column( $column_name );
327 } catch ( Query_Builder_Exception $exception ) {
328 // silence
329 }
330
331 return "{$column_name} LIKE '%{$second}%'";
332 }
333
334 /**
335 * @param $column_name
336 * @param $second
337 *
338 * @return string
339 */
340 public function build_not_like( $column_name, $second ): string {
341 $second = esc_sql( $second );
342 $column_name = Db_Tools::sanitize_column( $column_name );
343
344 try {
345 $column_name = $this->view()->column( $column_name );
346 } catch ( Query_Builder_Exception $exception ) {
347 // silence
348 }
349
350 return "{$column_name} NOT LIKE '%{$second}%'";
351 }
352
353 /**
354 * @param $column_name
355 * @param $second
356 *
357 * @return string
358 */
359 public function build_like_end( $column_name, $second ): string {
360 $second = esc_sql( $second );
361 $column_name = Db_Tools::sanitize_column( $column_name );
362
363 try {
364 $column_name = $this->view()->column( $column_name );
365 } catch ( Query_Builder_Exception $exception ) {
366 // silence
367 }
368
369 return "{$column_name} LIKE '{$second}%'";
370 }
371
372 /**
373 * @param $column_name
374 * @param $second
375 *
376 * @return string
377 */
378 public function build_not_like_end( $column_name, $second ): string {
379 $second = esc_sql( $second );
380 $column_name = Db_Tools::sanitize_column( $column_name );
381
382 try {
383 $column_name = $this->view()->column( $column_name );
384 } catch ( Query_Builder_Exception $exception ) {
385 // silence
386 }
387
388 return "{$column_name} NOT LIKE '{$second}%'";
389 }
390
391 /**
392 * @param $column_name
393 * @param $second
394 *
395 * @return string
396 */
397 public function build_more_static( $column_name, $second ): string {
398 global $wpdb;
399
400 $format = $this->get_format_value( $second );
401 $format_col = $this->get_format_column();
402 $column_name = Db_Tools::sanitize_column( $column_name );
403
404 try {
405 $column_name = $this->view()->column( $column_name );
406 } catch ( Query_Builder_Exception $exception ) {
407 // silence
408 }
409
410 // phpcs:disable WordPress.DB
411 return $wpdb->prepare(
412 sprintf( $format_col, $column_name ) . ' > ' . $format,
413 $second
414 );
415 // phpcs:enable WordPress.DB
416 }
417
418 /**
419 * @param $column_name
420 * @param $second
421 *
422 * @return string
423 */
424 public function build_more_or_equal_static( $column_name, $second ): string {
425 global $wpdb;
426
427 $format = $this->get_format_value( $second );
428 $format_col = $this->get_format_column();
429 $column_name = Db_Tools::sanitize_column( $column_name );
430
431 try {
432 $column_name = $this->view()->column( $column_name );
433 } catch ( Query_Builder_Exception $exception ) {
434 // silence
435 }
436
437 // phpcs:disable WordPress.DB
438 return $wpdb->prepare(
439 sprintf( $format_col, $column_name ) . ' >= ' . $format,
440 $second
441 );
442 // phpcs:enable WordPress.DB
443 }
444
445 /**
446 * .wrap > *:not(h1, #poststuff) {
447 * display: none;
448 * }
449 */
450 /**
451 * @param $column_name
452 * @param $second
453 *
454 * @return string
455 */
456 public function build_less_static( $column_name, $second ): string {
457 global $wpdb;
458
459 $format = $this->get_format_value( $second );
460 $format_col = $this->get_format_column();
461 $column_name = Db_Tools::sanitize_column( $column_name );
462
463 try {
464 $column_name = $this->view()->column( $column_name );
465 } catch ( Query_Builder_Exception $exception ) {
466 // silence
467 }
468
469 // phpcs:disable WordPress.DB
470 return $wpdb->prepare(
471 sprintf( $format_col, $column_name ) . ' < ' . $format,
472 $second
473 );
474 // phpcs:enable WordPress.DB
475 }
476
477 /**
478 * @param $column_name
479 * @param $second
480 *
481 * @return string
482 */
483 public function build_less_or_equal_static( $column_name, $second ): string {
484 global $wpdb;
485
486 $format = $this->get_format_value( $second );
487 $format_col = $this->get_format_column();
488 $column_name = Db_Tools::sanitize_column( $column_name );
489
490 try {
491 $column_name = $this->view()->column( $column_name );
492 } catch ( Query_Builder_Exception $exception ) {
493 // silence
494 }
495
496 // phpcs:disable WordPress.DB
497 return $wpdb->prepare(
498 sprintf( $format_col, $column_name ) . ' <= ' . $format,
499 $second
500 );
501 // phpcs:enable WordPress.DB
502 }
503
504 /**
505 * @param $column_name
506 * @param $second
507 *
508 * @return string
509 */
510 public function build_in( $column_name, $second ): string {
511 if ( ! is_array( $second ) ) {
512 $second = array( $second );
513 }
514
515 $in_list = array();
516
517 foreach ( $second as $in_item ) {
518 if ( ! is_scalar( $in_item ) ) {
519 continue;
520 }
521
522 $in_list[] = is_numeric( $in_item )
523 ? $in_item
524 : sprintf( "'%s'", sanitize_key( $in_item ) );
525 }
526
527 // Fix: Return FALSE condition when IN list is empty to prevent SQL error
528 if ( empty( $in_list ) ) {
529 $column_name = Db_Tools::sanitize_column( $column_name );
530 try {
531 $column_name = $this->view()->column( $column_name );
532 } catch ( Query_Builder_Exception $exception ) {
533 // silence
534 }
535 return "{$column_name} IN (NULL)";
536 }
537
538 $right_part = implode( ', ', $in_list );
539 $column_name = Db_Tools::sanitize_column( $column_name );
540
541 try {
542 $column_name = $this->view()->column( $column_name );
543 } catch ( Query_Builder_Exception $exception ) {
544 // silence
545 }
546
547 return "{$column_name} IN ({$right_part})";
548 }
549
550 /**
551 * @param $column_name
552 *
553 * @return string
554 * @since 3.2.0
555 */
556 public function build_is_null( $column_name ): string {
557 $column_name = Db_Tools::sanitize_column( $column_name );
558
559 try {
560 $column_name = $this->view()->column( $column_name );
561 } catch ( Query_Builder_Exception $exception ) {
562 // silence
563 }
564
565 // phpcs:disable WordPress.DB
566 return sprintf( '%s IS NULL', $column_name );
567 // phpcs:enable WordPress.DB
568 }
569
570 /**
571 * @return array
572 */
573 public function get_condition_values(): array {
574 $condition = $this->generator->current();
575
576 return $condition['values'] ?? array();
577 }
578
579 /**
580 * @return $this
581 * @since 3.1.0
582 */
583 public function set_relation_and(): Query_Conditions_Builder {
584 return $this->set_relation_type( 'AND' );
585 }
586
587 /**
588 * @return $this
589 * @since 3.1.0
590 */
591 public function set_relation_or(): Query_Conditions_Builder {
592 return $this->set_relation_type( 'OR' );
593 }
594
595 protected function set_relation_type( string $type ): Query_Conditions_Builder {
596 if ( ! in_array( $type, self::RELATIONS_TYPES, true ) ) {
597 return $this;
598 }
599 $this->relation_type = $type;
600
601 return $this;
602 }
603
604 protected function generate_conditions(): \Generator {
605 foreach ( $this->conditions as $condition ) {
606 yield $condition;
607 }
608 }
609
610 protected function get_format_value( $value ) {
611 /** @var array $condition */
612 $condition = $this->generator->current();
613
614 if ( ! empty( $condition['format'] ) ) {
615 return $condition['format'];
616 }
617
618 return is_numeric( $value ) ? '%d' : '%s';
619 }
620
621 protected function get_format_column() {
622 /** @var array $condition */
623 $condition = $this->generator->current();
624
625 return empty( $condition['format_col'] ) ? '%s' : $condition['format_col'];
626 }
627
628 }
629