PluginProbe ʕ •ᴥ•ʔ
JetFormBuilder — Dynamic Blocks Form Builder / 3.1.2
JetFormBuilder — Dynamic Blocks Form Builder v3.1.2
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 2 years ago
query-conditions-builder.php
569 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 /**
41 * @since 3.1.0
42 */
43 const RELATIONS_TYPES = array( 'AND', 'OR' );
44
45 use With_View;
46
47 private $conditions = array();
48
49 private $relation_type = 'AND';
50
51 /**
52 * @var array
53 */
54 private $current_condition;
55
56 /**
57 * @var \Generator
58 */
59 private $generator;
60
61 public function get_types(): array {
62 return array(
63 self::TYPE_EQUAL_STATIC => array(
64 'callback' => array( $this, 'build_equal_static' ),
65 ),
66 self::TYPE_EQUAL => array(
67 'callback' => array( $this, 'build_equal_column' ),
68 ),
69 self::TYPE_EQUAL_COLUMNS => array(
70 'callback' => array( $this, 'build_equal_two_columns' ),
71 ),
72 self::TYPE_LIKE => array(
73 'callback' => array( $this, 'build_like' ),
74 ),
75 self::TYPE_NOT_LIKE => array(
76 'callback' => array( $this, 'build_not_like' ),
77 ),
78 self::TYPE_MORE_STATIC => array(
79 'callback' => array( $this, 'build_more_static' ),
80 ),
81 self::TYPE_LESS_STATIC => array(
82 'callback' => array( $this, 'build_less_static' ),
83 ),
84 self::TYPE_IN => array(
85 'callback' => array( $this, 'build_in' ),
86 ),
87 /**
88 * @since 3.1.0
89 */
90 self::TYPE_NOT_EQUAL => array(
91 'callback' => array( $this, 'build_not_equal_column' ),
92 ),
93 self::TYPE_LIKE_END => array(
94 'callback' => array( $this, 'build_like_end' ),
95 ),
96 self::TYPE_NOT_LIKE_END => array(
97 'callback' => array( $this, 'build_not_like_end' ),
98 ),
99 self::TYPE_LESS_OR_EQUAL_STATIC => array(
100 'callback' => array( $this, 'build_less_or_equal_static' ),
101 ),
102 self::TYPE_MORE_OR_EQUAL_STATIC => array(
103 'callback' => array( $this, 'build_more_or_equal_static' ),
104 ),
105 );
106 }
107
108 /**
109 * @param array|Query_Conditions_Builder $condition
110 *
111 * @return $this
112 */
113 public function set_condition( $condition ): Query_Conditions_Builder {
114 if ( ! is_array( $condition ) && ! ( $condition instanceof Query_Conditions_Builder ) ) {
115 return $this;
116 }
117 $this->conditions[] = $condition;
118
119 return $this;
120 }
121
122 public function set_conditions( array $conditions ): Query_Conditions_Builder {
123 foreach ( $conditions as $condition ) {
124 $this->set_condition( $condition );
125 }
126
127 return $this;
128 }
129
130 public function after_set_view() {
131 try {
132 $view = $this->view();
133 } catch ( Query_Builder_Exception $exception ) {
134 return;
135 }
136
137 $this->set_conditions( $view->conditions() );
138 }
139
140 /**
141 * @return string
142 */
143 public function result(): string {
144 if ( ! $this->conditions ) {
145 return '';
146 }
147
148 return 'WHERE ' . $this->prepare_conditions();
149 }
150
151 /**
152 * @return string
153 */
154 public function prepare_conditions(): string {
155 $this->generator = $this->generate_conditions();
156 $prepared = array();
157
158 foreach ( $this->generator as $condition ) {
159 $prepared[] = $this->prepare();
160 }
161
162 return implode(
163 sprintf( "\r\n\t%s ", $this->relation_type ),
164 $prepared
165 );
166 }
167
168 /**
169 * @return mixed
170 */
171 public function prepare() {
172 $condition = $this->generator->current();
173
174 if ( $condition instanceof Query_Conditions_Builder ) {
175 return sprintf( "(\r\n%s\r\n)", $condition->prepare_conditions() );
176 }
177
178 $type = $this->get_condition_type();
179
180 list ( $first, $second ) = $this->get_condition_values();
181
182 $callback = $this->get_types()[ $type ]['callback'];
183
184 return call_user_func( $callback, $first, $second );
185 }
186
187 /**
188 * @return string
189 */
190 private function get_condition_type(): string {
191 $condition = $this->generator->current();
192 $type = $condition['type'] ?? false;
193
194 if ( ! $type || ! in_array( $type, array_keys( $this->get_types() ), true ) ) {
195 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
196 _doing_it_wrong( __METHOD__, "Undefined condition type: $type", '2.0.0' );
197 wp_die();
198 }
199
200 return $type;
201 }
202
203 public function build_equal_static( $first, $second ): string {
204 global $wpdb;
205
206 return $wpdb->prepare(
207 '%s = %s',
208 $first,
209 $second
210 );
211 }
212
213 /**
214 * @param $column_name
215 * @param $second
216 *
217 * @return string
218 */
219 public function build_equal_column( $column_name, $second ): string {
220 global $wpdb;
221
222 $format = $this->get_format_value( $second );
223 $format_col = $this->get_format_column();
224 $column_name = Db_Tools::sanitize_column( $column_name );
225
226 try {
227 $column_name = $this->view()->column( $column_name );
228 } catch ( Query_Builder_Exception $exception ) {
229 // silence
230 }
231
232 return $wpdb->prepare(
233 // phpcs:ignore WordPress.DB
234 sprintf( $format_col, $column_name ) . " = {$format}",
235 $second
236 );
237 }
238
239 /**
240 * @param $column_name
241 * @param $second
242 *
243 * @return string
244 * @since 3.1.0
245 */
246 public function build_not_equal_column( $column_name, $second ): string {
247 global $wpdb;
248
249 $format = $this->get_format_value( $second );
250 $format_col = $this->get_format_column();
251 $column_name = Db_Tools::sanitize_column( $column_name );
252
253 try {
254 $column_name = $this->view()->column( $column_name );
255 } catch ( Query_Builder_Exception $exception ) {
256 // silence
257 }
258
259 return $wpdb->prepare(
260 // phpcs:ignore WordPress.DB
261 sprintf( $format_col, $column_name ) . " != {$format}",
262 $second
263 );
264 }
265
266 /**
267 * @param $column_name
268 * @param $second
269 *
270 * @return string
271 */
272 public function build_equal_two_columns( $column_name, $second ): string {
273 $column_name = Db_Tools::sanitize_column( $column_name );
274 $second = Db_Tools::sanitize_column( $second );
275
276 try {
277 $column_name = $this->view()->column( $column_name );
278 $second = $this->view()->column( $second );
279 } catch ( Query_Builder_Exception $exception ) {
280 // silence
281 }
282
283 return "{$column_name} = {$second}";
284 }
285
286 /**
287 * @param $column_name
288 * @param $second
289 *
290 * @return string
291 */
292 public function build_like( $column_name, $second ): string {
293 $second = esc_sql( $second );
294 $column_name = Db_Tools::sanitize_column( $column_name );
295
296 try {
297 $column_name = $this->view()->column( $column_name );
298 } catch ( Query_Builder_Exception $exception ) {
299 // silence
300 }
301
302 return "{$column_name} LIKE '%{$second}%'";
303 }
304
305 /**
306 * @param $column_name
307 * @param $second
308 *
309 * @return string
310 */
311 public function build_not_like( $column_name, $second ): string {
312 $second = esc_sql( $second );
313 $column_name = Db_Tools::sanitize_column( $column_name );
314
315 try {
316 $column_name = $this->view()->column( $column_name );
317 } catch ( Query_Builder_Exception $exception ) {
318 // silence
319 }
320
321 return "{$column_name} NOT LIKE '%{$second}%'";
322 }
323
324 /**
325 * @param $column_name
326 * @param $second
327 *
328 * @return string
329 */
330 public function build_like_end( $column_name, $second ): string {
331 $second = esc_sql( $second );
332 $column_name = Db_Tools::sanitize_column( $column_name );
333
334 try {
335 $column_name = $this->view()->column( $column_name );
336 } catch ( Query_Builder_Exception $exception ) {
337 // silence
338 }
339
340 return "{$column_name} LIKE '{$second}%'";
341 }
342
343 /**
344 * @param $column_name
345 * @param $second
346 *
347 * @return string
348 */
349 public function build_not_like_end( $column_name, $second ): string {
350 $second = esc_sql( $second );
351 $column_name = Db_Tools::sanitize_column( $column_name );
352
353 try {
354 $column_name = $this->view()->column( $column_name );
355 } catch ( Query_Builder_Exception $exception ) {
356 // silence
357 }
358
359 return "{$column_name} NOT LIKE '{$second}%'";
360 }
361
362 /**
363 * @param $column_name
364 * @param $second
365 *
366 * @return string
367 */
368 public function build_more_static( $column_name, $second ): string {
369 global $wpdb;
370
371 $format = $this->get_format_value( $second );
372 $format_col = $this->get_format_column();
373 $column_name = Db_Tools::sanitize_column( $column_name );
374
375 try {
376 $column_name = $this->view()->column( $column_name );
377 } catch ( Query_Builder_Exception $exception ) {
378 // silence
379 }
380
381 // phpcs:disable WordPress.DB
382 return $wpdb->prepare(
383 sprintf( $format_col, $column_name ) . ' > ' . $format,
384 $second
385 );
386 // phpcs:enable WordPress.DB
387 }
388
389 /**
390 * @param $column_name
391 * @param $second
392 *
393 * @return string
394 */
395 public function build_more_or_equal_static( $column_name, $second ): string {
396 global $wpdb;
397
398 $format = $this->get_format_value( $second );
399 $format_col = $this->get_format_column();
400 $column_name = Db_Tools::sanitize_column( $column_name );
401
402 try {
403 $column_name = $this->view()->column( $column_name );
404 } catch ( Query_Builder_Exception $exception ) {
405 // silence
406 }
407
408 // phpcs:disable WordPress.DB
409 return $wpdb->prepare(
410 sprintf( $format_col, $column_name ) . ' >= ' . $format,
411 $second
412 );
413 // phpcs:enable WordPress.DB
414 }
415
416 /**
417 * .wrap > *:not(h1, #poststuff) {
418 display: none;
419 }
420 */
421 /**
422 * @param $column_name
423 * @param $second
424 *
425 * @return string
426 */
427 public function build_less_static( $column_name, $second ): string {
428 global $wpdb;
429
430 $format = $this->get_format_value( $second );
431 $format_col = $this->get_format_column();
432 $column_name = Db_Tools::sanitize_column( $column_name );
433
434 try {
435 $column_name = $this->view()->column( $column_name );
436 } catch ( Query_Builder_Exception $exception ) {
437 // silence
438 }
439
440 // phpcs:disable WordPress.DB
441 return $wpdb->prepare(
442 sprintf( $format_col, $column_name ) . ' < ' . $format,
443 $second
444 );
445 // phpcs:enable WordPress.DB
446 }
447
448 /**
449 * @param $column_name
450 * @param $second
451 *
452 * @return string
453 */
454 public function build_less_or_equal_static( $column_name, $second ): string {
455 global $wpdb;
456
457 $format = $this->get_format_value( $second );
458 $format_col = $this->get_format_column();
459 $column_name = Db_Tools::sanitize_column( $column_name );
460
461 try {
462 $column_name = $this->view()->column( $column_name );
463 } catch ( Query_Builder_Exception $exception ) {
464 // silence
465 }
466
467 // phpcs:disable WordPress.DB
468 return $wpdb->prepare(
469 sprintf( $format_col, $column_name ) . ' <= ' . $format,
470 $second
471 );
472 // phpcs:enable WordPress.DB
473 }
474
475 /**
476 * @param $column_name
477 * @param $second
478 *
479 * @return string
480 */
481 public function build_in( $column_name, $second ): string {
482 if ( ! is_array( $second ) ) {
483 $second = array( $second );
484 }
485
486 $in_list = array();
487
488 foreach ( $second as $in_item ) {
489 if ( ! is_scalar( $in_item ) ) {
490 continue;
491 }
492
493 $in_list[] = is_numeric( $in_item )
494 ? $in_item
495 : sprintf( "'%s'", sanitize_key( $in_item ) );
496 }
497
498 $right_part = implode( ', ', $in_list );
499 $column_name = Db_Tools::sanitize_column( $column_name );
500
501 try {
502 $column_name = $this->view()->column( $column_name );
503 } catch ( Query_Builder_Exception $exception ) {
504 // silence
505 }
506
507 return "{$column_name} IN ({$right_part})";
508 }
509
510 /**
511 * @return array
512 */
513 public function get_condition_values(): array {
514 $condition = $this->generator->current();
515
516 return $condition['values'] ?? array();
517 }
518
519 /**
520 * @return $this
521 * @since 3.1.0
522 */
523 public function set_relation_and(): Query_Conditions_Builder {
524 return $this->set_relation_type( 'AND' );
525 }
526
527 /**
528 * @return $this
529 * @since 3.1.0
530 */
531 public function set_relation_or(): Query_Conditions_Builder {
532 return $this->set_relation_type( 'OR' );
533 }
534
535 protected function set_relation_type( string $type ): Query_Conditions_Builder {
536 if ( ! in_array( $type, self::RELATIONS_TYPES, true ) ) {
537 return $this;
538 }
539 $this->relation_type = $type;
540
541 return $this;
542 }
543
544 protected function generate_conditions(): \Generator {
545 foreach ( $this->conditions as $condition ) {
546 yield $condition;
547 }
548 }
549
550 protected function get_format_value( $value ) {
551 /** @var array $condition */
552 $condition = $this->generator->current();
553
554 if ( ! empty( $condition['format'] ) ) {
555 return $condition['format'];
556 }
557
558 return is_numeric( $value ) ? '%d' : '%s';
559 }
560
561 protected function get_format_column() {
562 /** @var array $condition */
563 $condition = $this->generator->current();
564
565 return empty( $condition['format_col'] ) ? '%s' : $condition['format_col'];
566 }
567
568 }
569