PluginProbe ʕ •ᴥ•ʔ
Pods – Custom Content Types and Fields / 2.7.31.4
Pods – Custom Content Types and Fields v2.7.31.4
2.7.31.4 2.8.23.5 2.9.19.5 3.0.10.5 3.1.4.3 3.2.8.4 3.3.9.2 2.8.23.4 2.9.19.4 3.0.10.4 3.1.4.2 3.2.8.3 3.3.9.1 trunk 1.14.8 2.7.31.3 2.8.23.3 2.9.19.3 3.0.10.3 3.1.4.1 3.2.0 3.2.1 3.2.1.1 3.2.2 3.2.4 3.2.5 3.2.6 3.2.7 3.2.7.1 3.2.8 3.2.8.1 3.2.8.2 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9
pods / includes / data.php
pods / includes Last commit date
compatibility 4 days ago access.php 4 days ago classes.php 4 days ago data.php 4 days ago general.php 4 days ago media.php 4 days ago
data.php
2475 lines
1 <?php
2 /**
3 * @package Pods\Global\Functions\Data
4 */
5 /**
6 * Filter input and return sanitized output
7 *
8 * @param mixed $input The string, array, or object to sanitize
9 * @param array $params Additional options
10 *
11 * @return array|mixed|object|string|void
12 *
13 * @since 1.2.0
14 *
15 * @see wp_slash
16 */
17 function pods_sanitize( $input, $params = array() ) {
18
19 if ( '' === $input || is_int( $input ) || is_float( $input ) || empty( $input ) ) {
20 return $input;
21 }
22
23 $output = array();
24
25 $defaults = array(
26 'nested' => false,
27 'type' => null,
28 // %s %d %f etc
29 );
30
31 if ( ! is_array( $params ) ) {
32 $defaults['type'] = $params;
33
34 $params = $defaults;
35 } else {
36 $params = array_merge( $defaults, (array) $params );
37 }
38
39 if ( is_object( $input ) ) {
40 $input = get_object_vars( $input );
41
42 $n_params = $params;
43 $n_params['nested'] = true;
44
45 foreach ( $input as $key => $val ) {
46 $output[ pods_sanitize( $key ) ] = pods_sanitize( $val, $n_params );
47 }
48
49 $output = (object) $output;
50 } elseif ( is_array( $input ) ) {
51 $n_params = $params;
52 $n_params['nested'] = true;
53
54 foreach ( $input as $key => $val ) {
55 $output[ pods_sanitize( $key ) ] = pods_sanitize( $val, $n_params );
56 }
57 } elseif ( ! empty( $params['type'] ) && false !== strpos( $params['type'], '%' ) ) {
58 /**
59 * @var $wpdb wpdb
60 */
61 global $wpdb;
62
63 $output = $wpdb->prepare( $params['type'], $output );
64 } elseif ( function_exists( 'wp_slash' ) ) {
65 // @todo Switch this full over to esc_sql once we get sanitization sane again in PodsAPI so we *don't* have to unsanitize in various places
66 $output = wp_slash( $input );
67 } else {
68 $output = esc_sql( $input );
69 }//end if
70
71 return $output;
72
73 }
74
75 /**
76 * Filter input and return sanitized SQL LIKE output
77 *
78 * @param mixed $input The string, array, or object to sanitize
79 *
80 * @return array|mixed|object|string|void
81 *
82 * @since 2.3.9
83 *
84 * @see like_escape
85 */
86 function pods_sanitize_like( $input ) {
87
88 if ( '' === $input || is_int( $input ) || is_float( $input ) || empty( $input ) ) {
89 return $input;
90 }
91
92 $output = array();
93
94 if ( is_object( $input ) ) {
95 $input = get_object_vars( $input );
96
97 foreach ( $input as $key => $val ) {
98 $output[ $key ] = pods_sanitize_like( $val );
99 }
100
101 $output = (object) $output;
102 } elseif ( is_array( $input ) ) {
103 foreach ( $input as $key => $val ) {
104 $output[ $key ] = pods_sanitize_like( $val );
105 }
106 } else {
107 global $wpdb;
108 $input = pods_unslash( $input );
109
110 $output = pods_sanitize( $wpdb->esc_like( $input ) );
111 }
112
113 return $output;
114
115 }
116
117 /**
118 * Filter input and return slashed output
119 *
120 * @param mixed $input The string, array, or object to sanitize
121 * @param array $params Additional options
122 *
123 * @return array|mixed|object|string|void
124 *
125 * @since 2.3.9
126 *
127 * @see wp_slash
128 */
129 function pods_slash( $input, $params = array() ) {
130
131 if ( '' === $input || is_int( $input ) || is_float( $input ) || empty( $input ) ) {
132 return $input;
133 }
134
135 $output = array();
136
137 $defaults = array(
138 'type' => null,
139 // %s %d %f etc
140 );
141
142 if ( ! is_array( $params ) ) {
143 $defaults['type'] = $params;
144
145 $params = $defaults;
146 } else {
147 $params = array_merge( $defaults, (array) $params );
148 }
149
150 if ( empty( $input ) ) {
151 $output = $input;
152 } elseif ( is_object( $input ) ) {
153 $input = get_object_vars( $input );
154
155 foreach ( $input as $key => $val ) {
156 $output[ $key ] = pods_slash( $val, $params );
157 }
158
159 $output = (object) $output;
160 } elseif ( is_array( $input ) ) {
161 foreach ( $input as $key => $val ) {
162 $output[ $key ] = pods_slash( $val, $params );
163 }
164 } elseif ( ! empty( $params['type'] ) && false !== strpos( $params['type'], '%' ) ) {
165 /**
166 * @var $wpdb wpdb
167 */
168 global $wpdb;
169
170 $output = $wpdb->prepare( $params['type'], $output );
171 } elseif ( function_exists( 'wp_slash' ) ) {
172 $output = wp_slash( $input );
173 } else {
174 $output = addslashes( $input );
175 }//end if
176
177 return $output;
178
179 }
180
181 /**
182 * Filter input and return unsanitized output
183 *
184 * @param mixed $input The string, array, or object to unsanitize
185 * @param array $params Additional options
186 *
187 * @return array|mixed|object|string|void
188 *
189 * @since 1.2.0
190 */
191 function pods_unsanitize( $input, $params = array() ) {
192
193 if ( '' === $input || is_int( $input ) || is_float( $input ) || empty( $input ) ) {
194 return $input;
195 }
196
197 $output = array();
198
199 if ( empty( $input ) ) {
200 $output = $input;
201 } elseif ( is_object( $input ) ) {
202 $input = get_object_vars( $input );
203
204 $n_params = (array) $params;
205 $n_params['nested'] = true;
206
207 foreach ( $input as $key => $val ) {
208 $output[ pods_unsanitize( $key ) ] = pods_unsanitize( $val, $n_params );
209 }
210
211 $output = (object) $output;
212 } elseif ( is_array( $input ) ) {
213 $n_params = (array) $params;
214 $n_params['nested'] = true;
215
216 foreach ( $input as $key => $val ) {
217 $output[ pods_unsanitize( $key ) ] = pods_unsanitize( $val, $n_params );
218 }
219 } else {
220 $output = wp_unslash( $input );
221 }//end if
222
223 return $output;
224
225 }
226
227 /**
228 * Filter input and return unslashed output
229 *
230 * @param mixed $input The string, array, or object to unsanitize
231 *
232 * @return array|mixed|object|string|void
233 *
234 * @since 2.3.9
235 *
236 * @see wp_unslash
237 */
238 function pods_unslash( $input ) {
239
240 if ( '' === $input || is_int( $input ) || is_float( $input ) || empty( $input ) ) {
241 return $input;
242 }
243
244 $output = array();
245
246 if ( empty( $input ) ) {
247 $output = $input;
248 } elseif ( is_object( $input ) ) {
249 $input = get_object_vars( $input );
250
251 foreach ( $input as $key => $val ) {
252 $output[ $key ] = pods_unslash( $val );
253 }
254
255 $output = (object) $output;
256 } elseif ( is_array( $input ) ) {
257 foreach ( $input as $key => $val ) {
258 $output[ $key ] = pods_unslash( $val );
259 }
260 } else {
261 $output = wp_unslash( $input );
262 }
263
264 return $output;
265
266 }
267
268 /**
269 * Filter input and return sanitized output
270 *
271 * @param mixed $input The string, array, or object to sanitize
272 * @param string $charlist (optional) List of characters to be stripped from the input.
273 * @param string $lr Direction of the trim, can either be 'l' or 'r'.
274 *
275 * @return array|object|string
276 * @since 1.2.0
277 */
278 function pods_trim( $input, $charlist = null, $lr = null ) {
279
280 $output = array();
281
282 if ( is_object( $input ) ) {
283 $input = get_object_vars( $input );
284
285 foreach ( $input as $key => $val ) {
286 $output[ pods_sanitize( $key ) ] = pods_trim( $val, $charlist, $lr );
287 }
288
289 $output = (object) $output;
290 } elseif ( is_array( $input ) ) {
291 foreach ( $input as $key => $val ) {
292 $output[ pods_sanitize( $key ) ] = pods_trim( $val, $charlist, $lr );
293 }
294 } else {
295 $args = array( $input );
296 if ( null !== $charlist ) {
297 $args[] = $charlist;
298 }
299 if ( 'l' === $lr ) {
300 $function = 'ltrim';
301 } elseif ( 'r' === $lr ) {
302 $function = 'rtrim';
303 } else {
304 $function = 'trim';
305 }
306 $output = call_user_func_array( $function, $args );
307 }//end if
308
309 return $output;
310
311 }
312
313 /**
314 * Traverse an array or object by array values order or a string (name.name.name).
315 *
316 * @since 2.7.18
317 *
318 * @param array|string|int $traverse The traversal names/keys.
319 * @param array|object $value The value to traverse into.
320 *
321 * @return mixed
322 */
323 function pods_traverse( $traverse, $value ) {
324 if ( ! $traverse && ! is_numeric( $traverse ) ) {
325 return $value;
326 }
327
328 if ( is_scalar( $value ) ) {
329 return null;
330 }
331
332 if ( is_object( $value ) ) {
333 $value = (array) $value;
334 }
335
336 if ( ! is_array( $traverse ) ) {
337 $traverse = explode( '.', $traverse );
338 }
339
340 $key = array_shift( $traverse );
341
342 if ( ! isset( $value[ $key ] ) ) {
343 return null;
344 }
345
346 $value = $value[ $key ];
347
348 if ( $traverse ) {
349 $value = pods_traverse( $traverse, $value );
350 }
351
352 return $value;
353 }
354
355 /**
356 * Return a variable (if exists)
357 *
358 * @param mixed $var The variable name, can also be a modifier for specific types
359 * @param string|array|object $type (optional) Super globals, url/url-relative, constants, globals, options,
360 * transients, cache, user data, Pod field values, dates
361 * @param mixed $default (optional) The default value to set if variable doesn't exist
362 * @param bool $strict (optional) Only allow values (must not be empty)
363 * @param array $params (optional) Set 'casting'=>true to cast value from $default, 'allowed'=>$allowed
364 * to restrict a value to what's allowed
365 *
366 * @return mixed The variable (if exists), or default value
367 * @since 2.3.10
368 */
369 function pods_v( $var = null, $type = 'get', $default = null, $strict = false, $params = array() ) {
370
371 $defaults = array(
372 'casting' => false,
373 'allowed' => null,
374 'source' => null,
375 );
376
377 $params = (object) array_merge( $defaults, (array) $params );
378
379 $output = null;
380
381 if ( null === $type || '' === $type ) {
382 // Invalid $type
383 } elseif ( is_array( $type ) ) {
384 if ( isset( $type[ $var ] ) ) {
385 $output = $type[ $var ];
386 }
387 } elseif ( is_object( $type ) ) {
388 if ( isset( $type->{$var} ) ) {
389 $output = $type->{$var};
390 }
391 } else {
392 $type = strtolower( (string) $type );
393
394 if ( $params->source ) {
395 // Using keys for faster isset() checks instead of in_array().
396 $disallowed_types = [];
397
398 if ( 'magic-tag' === $params->source ) {
399 $disallowed_types = [
400 'server' => false,
401 'session' => false,
402 'global' => false,
403 'globals' => false,
404 'cookie' => false,
405 'constant' => false,
406 'option' => false,
407 'site-option' => false,
408 'transient' => false,
409 'site-transient' => false,
410 'cache' => false,
411 'pods-transient' => false,
412 'pods-site-transient' => false,
413 'pods-cache' => false,
414 'pods-option-cache' => false,
415 ];
416 }
417
418 /**
419 * Allow filtering the list of disallowed variable types for the source.
420 *
421 * @since 2.9.4
422 *
423 * @param array $disallowed_types The list of disallowed variable types for the source.
424 * @param string $source The source calling pods_v().
425 */
426 $disallowed_types = apply_filters( "pods_v_disallowed_types_for_source_{$params->source}", $disallowed_types, $params->source );
427
428 if ( isset( $disallowed_types[ $type ] ) ) {
429 return $default;
430 }
431 }
432
433 switch ( $type ) {
434 case 'get':
435 if ( isset( $_GET[ $var ] ) ) {
436 $output = pods_unslash( $_GET[ $var ] );
437 }
438 break;
439 case 'post':
440 if ( isset( $_POST[ $var ] ) ) {
441 $output = pods_unslash( $_POST[ $var ] );
442 }
443 break;
444 case 'request':
445 if ( isset( $_REQUEST[ $var ] ) ) {
446 $output = pods_unslash( $_REQUEST[ $var ] );
447 }
448 break;
449 case 'query':
450 $output = get_query_var( $var, $default );
451 break;
452 case 'url':
453 case 'uri':
454 $url = parse_url( pods_current_url() );
455 $uri = trim( $url['path'], '/' );
456 $uri = array_filter( explode( '/', $uri ) );
457
458 if ( 'first' === $var ) {
459 $var = 0;
460 } elseif ( 'last' === $var ) {
461 $var = -1;
462 }
463
464 if ( is_numeric( $var ) ) {
465 $output = ( $var < 0 ) ? pods_v( count( $uri ) + $var, $uri ) : pods_v( $var, $uri );
466 }
467 break;
468 case 'url-relative':
469 $url_raw = pods_current_url();
470 $prefix = get_site_url();
471
472 if ( substr( $url_raw, 0, strlen( $prefix ) ) == $prefix ) {
473 $url_raw = substr( $url_raw, strlen( $prefix ) + 1, strlen( $url_raw ) );
474 }
475
476 $url = parse_url( $url_raw );
477 $uri = trim( $url['path'], '/' );
478 $uri = array_filter( explode( '/', $uri ) );
479
480 if ( 'first' === $var ) {
481 $var = 0;
482 } elseif ( 'last' === $var ) {
483 $var = -1;
484 }
485
486 if ( is_numeric( $var ) ) {
487 $output = ( $var < 0 ) ? pods_v( count( $uri ) + $var, $uri ) : pods_v( $var, $uri );
488 }
489 break;
490 case 'template-url':
491 $output = get_template_directory_uri();
492 break;
493 case 'stylesheet-url':
494 $output = get_stylesheet_directory_uri();
495 break;
496 case 'site-url':
497 $blog_id = null;
498 $scheme = null;
499 $path = '';
500
501 if ( is_array( $var ) ) {
502 if ( isset( $var[0] ) ) {
503 $blog_id = $var[0];
504 }
505 if ( isset( $var[1] ) ) {
506 $path = $var[1];
507 }
508 if ( isset( $var[2] ) ) {
509 $scheme = $var[2];
510 }
511 } else {
512 $blog_id = $var;
513 }
514
515 $output = get_site_url( $blog_id, $path, $scheme );
516 break;
517 case 'home-url':
518 $blog_id = null;
519 $scheme = null;
520 $path = '';
521
522 if ( is_array( $var ) ) {
523 if ( isset( $var[0] ) ) {
524 $blog_id = $var[0];
525 }
526 if ( isset( $var[1] ) ) {
527 $path = $var[1];
528 }
529 if ( isset( $var[2] ) ) {
530 $scheme = $var[2];
531 }
532 } else {
533 $blog_id = $var;
534 }
535
536 $output = get_home_url( $blog_id, $path, $scheme );
537 break;
538 case 'admin-url':
539 $blog_id = null;
540 $scheme = null;
541 $path = '';
542
543 if ( is_array( $var ) ) {
544 if ( isset( $var[0] ) ) {
545 $blog_id = $var[0];
546 }
547 if ( isset( $var[1] ) ) {
548 $path = $var[1];
549 }
550 if ( isset( $var[2] ) ) {
551 $scheme = $var[2];
552 }
553 } else {
554 $blog_id = $var;
555 }
556
557 $output = get_admin_url( $blog_id, $path, $scheme );
558 break;
559 case 'includes-url':
560 $output = includes_url( $var );
561 break;
562 case 'content-url':
563 $output = content_url( $var );
564 break;
565 case 'plugins-url':
566 $path = '';
567 $plugin = '';
568
569 if ( is_array( $var ) ) {
570 if ( isset( $var[0] ) ) {
571 $path = $var[0];
572 }
573 if ( isset( $var[1] ) ) {
574 $plugin = $var[1];
575 }
576 } else {
577 $path = $var;
578 }
579
580 $output = plugins_url( $path, $plugin );
581 break;
582 case 'network-site-url':
583 $path = '';
584 $scheme = null;
585
586 if ( is_array( $var ) ) {
587 if ( isset( $var[0] ) ) {
588 $path = $var[0];
589 }
590 if ( isset( $var[1] ) ) {
591 $scheme = $var[1];
592 }
593 } else {
594 $path = $var;
595 }
596
597 $output = network_site_url( $path, $scheme );
598 break;
599 case 'network-home-url':
600 $path = '';
601 $scheme = null;
602
603 if ( is_array( $var ) ) {
604 if ( isset( $var[0] ) ) {
605 $path = $var[0];
606 }
607 if ( isset( $var[1] ) ) {
608 $scheme = $var[1];
609 }
610 } else {
611 $path = $var;
612 }
613
614 $output = network_home_url( $path, $scheme );
615 break;
616 case 'network-admin-url':
617 $path = '';
618 $scheme = null;
619
620 if ( is_array( $var ) ) {
621 if ( isset( $var[0] ) ) {
622 $path = $var[0];
623 }
624 if ( isset( $var[1] ) ) {
625 $scheme = $var[1];
626 }
627 } else {
628 $path = $var;
629 }
630
631 $output = network_admin_url( $path, $scheme );
632 break;
633 case 'user-admin-url':
634 $path = '';
635 $scheme = null;
636
637 if ( is_array( $var ) ) {
638 if ( isset( $var[0] ) ) {
639 $path = $var[0];
640 }
641 if ( isset( $var[1] ) ) {
642 $scheme = $var[1];
643 }
644 } else {
645 $path = $var;
646 }
647
648 $output = user_admin_url( $path, $scheme );
649 break;
650 case 'prefix':
651 global $wpdb;
652
653 $output = $wpdb->prefix;
654 break;
655 case 'server':
656 if ( ! pods_strict() ) {
657 if ( isset( $_SERVER[ $var ] ) ) {
658 $output = pods_unslash( $_SERVER[ $var ] );
659 } elseif ( isset( $_SERVER[ strtoupper( $var ) ] ) ) {
660 $output = pods_unslash( $_SERVER[ strtoupper( $var ) ] );
661 }
662 }
663 break;
664 case 'session':
665 if ( isset( $_SESSION[ $var ] ) ) {
666 $output = $_SESSION[ $var ];
667 }
668 break;
669 case 'global':
670 case 'globals':
671 if ( isset( $GLOBALS[ $var ] ) ) {
672 $output = $GLOBALS[ $var ];
673
674 $output = pods_access_bleep_data( $output );
675 }
676 break;
677 case 'cookie':
678 if ( isset( $_COOKIE[ $var ] ) ) {
679 $output = pods_unslash( $_COOKIE[ $var ] );
680 }
681 break;
682 case 'constant':
683 if ( defined( $var ) ) {
684 $output = constant( $var );
685 }
686 break;
687 case 'user':
688 // Prevent deprecation notice from WP.
689 if ( 'id' === $var ) {
690 $var = 'ID';
691 }
692
693 if ( is_user_logged_in() ) {
694 $user = get_userdata( get_current_user_id() );
695
696 $user = pods_access_bleep_data( $user );
697
698 if ( isset( $user->{$var} ) ) {
699 $value = $user->{$var};
700 } elseif ( 'role' === $var ) {
701 $value = '';
702
703 if ( ! empty( $user->roles ) ) {
704 $value = array_shift( $user->roles );
705 }
706 } else {
707 $value = get_user_meta( $user->ID, $var );
708 }
709
710 if ( is_array( $value ) && ! empty( $value ) ) {
711 $output = $value;
712 } elseif ( ! is_array( $value ) && 0 < strlen( $value ) ) {
713 $output = $value;
714 }
715 } elseif ( 'ID' === $var ) {
716 // Return 0 when logged out and calling the ID.
717 $output = 0;
718 }
719 break;
720 case 'option':
721 $output = get_option( $var, $default );
722 break;
723 case 'site-option':
724 $output = get_site_option( $var, $default );
725 break;
726 case 'transient':
727 $output = get_transient( $var );
728 break;
729 case 'site-transient':
730 $output = get_site_transient( $var );
731 break;
732 case 'cache':
733 if ( isset( $GLOBALS['wp_object_cache'] ) && is_object( $GLOBALS['wp_object_cache'] ) ) {
734 $group = 'default';
735 $force = false;
736
737 if ( ! is_array( $var ) ) {
738 $var = explode( '|', $var );
739 }
740
741 if ( isset( $var[0] ) ) {
742 if ( isset( $var[1] ) ) {
743 $group = $var[1];
744 }
745
746 if ( isset( $var[2] ) ) {
747 $force = $var[2];
748 }
749
750 $var = $var[0];
751
752 $output = wp_cache_get( $var, $group, $force );
753 }
754 }//end if
755 break;
756 case 'pods-transient':
757 $callback = null;
758
759 if ( ! is_array( $var ) ) {
760 $var = explode( '|', $var );
761 }
762
763 if ( isset( $var[0] ) ) {
764 if ( isset( $var[1] ) ) {
765 $callback = $var[1];
766 }
767
768 $var = $var[0];
769
770 $output = pods_transient_get( $var, $callback );
771 }
772 break;
773 case 'pods-site-transient':
774 $callback = null;
775
776 if ( ! is_array( $var ) ) {
777 $var = explode( '|', $var );
778 }
779
780 if ( isset( $var[0] ) ) {
781 if ( isset( $var[1] ) ) {
782 $callback = $var[1];
783 }
784
785 $var = $var[0];
786
787 $output = pods_site_transient_get( $var, $callback );
788 }
789 break;
790 case 'pods-cache':
791 if ( isset( $GLOBALS['wp_object_cache'] ) && is_object( $GLOBALS['wp_object_cache'] ) ) {
792 $group = 'default';
793 $callback = null;
794
795 if ( ! is_array( $var ) ) {
796 $var = explode( '|', $var );
797 }
798
799 if ( isset( $var[0] ) ) {
800 if ( isset( $var[1] ) ) {
801 $group = $var[1];
802 }
803
804 if ( isset( $var[2] ) ) {
805 $callback = $var[2];
806 }
807
808 $var = $var[0];
809
810 $output = pods_cache_get( $var, $group, $callback );
811 }
812 }//end if
813 break;
814 case 'pods-option-cache':
815 $group = 'default';
816 $callback = null;
817
818 if ( ! is_array( $var ) ) {
819 $var = explode( '|', $var );
820 }
821
822 if ( isset( $var[0] ) ) {
823 if ( isset( $var[1] ) ) {
824 $group = $var[1];
825 }
826
827 if ( isset( $var[2] ) ) {
828 $callback = $var[2];
829 }
830
831 $var = $var[0];
832
833 $output = pods_option_cache_get( $var, $group, $callback );
834 }
835 break;
836 case 'date':
837 $var = explode( '|', $var );
838
839 if ( ! empty( $var ) ) {
840 $output = date_i18n( $var[0], ( isset( $var[1] ) ? strtotime( $var[1] ) : false ) );
841 }
842 break;
843 case 'pods':
844 case 'pods_display':
845 /**
846 * @var $pods Pods
847 */
848 global $pods;
849
850 if ( is_object( $pods ) && 'Pods' == get_class( $pods ) ) {
851 if ( 'pods' === $type ) {
852 $output = $pods->field( $var );
853
854 if ( is_array( $output ) ) {
855 $options = array(
856 'field' => $var,
857 'fields' => $pods->fields,
858 );
859
860 $output = pods_serial_comma( $output, $options );
861 }
862 } elseif ( 'pods_display' === $type ) {
863 $output = $pods->display( $var );
864 }
865 }
866 break;
867 case 'post_id':
868 if ( empty( $var ) ) {
869 if ( ! empty( $default ) ) {
870 $post_id = $default;
871 } else {
872 // If no $var and no $default then use current post ID
873 $post_id = get_the_ID();
874 }
875 } else {
876 $post_id = $var;
877 }
878 if ( did_action( 'wpml_loaded' ) ) {
879 /* Only call filter if WPML is installed */
880 $post_type = get_post_type( $post_id );
881 $post_id = apply_filters( 'wpml_object_id', $post_id, $post_type, true );
882 } elseif ( function_exists( 'pll_get_post' ) ) {
883 $polylang_id = pll_get_post( $post_id );
884 if ( ! empty( $polylang_id ) ) {
885 $post_id = $polylang_id;
886 }
887 }
888 // Add other translation plugin specific code here
889 /**
890 * Filter to override post_id
891 *
892 * Generally used with language translation plugins in order to return the post id of a
893 * translated post
894 *
895 * @param int $post_id The post ID of current post
896 * @param mixed $default The default value to set if variable doesn't exist
897 * @param mixed $var The variable name, can also be a modifier for specific types
898 * @param bool $strict Only allow values (must not be empty)
899 * @param array $params Set 'casting'=>true to cast value from $default, 'allowed'=>$allowed to restrict a value to what's allowed
900 *
901 * @since 2.6.6
902 */
903 $output = apply_filters( 'pods_var_post_id', $post_id, $default, $var, $strict, $params );
904 break;
905 default:
906 $output = apply_filters( "pods_var_{$type}", $default, $var, $strict, $params );
907 }//end switch
908 }//end if
909
910 if ( null !== $default ) {
911 // Set default
912 if ( null === $output ) {
913 $output = $default;
914 }
915
916 // Casting
917 if ( true === $params->casting ) {
918 $output = pods_cast( $output, $default );
919 }
920 }
921
922 // Strict defaults for empty values
923 if ( true === $strict ) {
924 if ( empty( $output ) ) {
925 $output = $default;
926 }
927 }
928
929 // Allowed values
930 if ( null !== $params->allowed ) {
931 if ( is_array( $params->allowed ) ) {
932 // Not in array and is not the same array
933 if ( ! in_array( $output, $params->allowed, true ) && ( ! is_array( $output ) || $output !== $params->allowed ) ) {
934 $output = $default;
935 }
936 } elseif ( $output !== $params->allowed ) {
937 // Value doesn't match
938 $output = $default;
939 }
940 }
941
942 return $output;
943 }
944
945 /**
946 * Return a sanitized variable (if exists)
947 *
948 * @param mixed $var The variable name, can also be a modifier for specific types
949 * @param string|array|object $type (optional) Super globals, url/url-relative, constants, globals, options,
950 * transients, cache, user data, Pod field values, dates
951 * @param mixed $default (optional) The default value to set if variable doesn't exist
952 * @param bool $strict (optional) Only allow values (must not be empty)
953 * @param array $params (optional) Set 'casting'=>true to cast value from $default, 'allowed'=>$allowed
954 * to restrict a value to what's allowed
955 *
956 * @return mixed The variable (if exists), or default value
957 * @since 2.3.10
958 *
959 * @see pods_v
960 */
961 function pods_v_sanitized( $var = null, $type = 'get', $default = null, $strict = false, $params = array() ) {
962
963 $output = pods_v( $var, $type, $default, $strict, $params );
964
965 $output = pods_sanitize( $output, $params );
966
967 return $output;
968
969 }
970
971 /**
972 * Set a variable
973 *
974 * @param mixed $value The value to be set
975 * @param mixed $var The variable name, or URI segment position / query var name (if $type is 'url')
976 * @param string|array|object $type (optional) Super globals, url/url-relative, constants, globals, user data, Pod
977 * field values
978 *
979 * @return mixed Updated URL (if $type is 'url'), $value (if $type is 'constant'), Item ID (if $type is 'pods'), $type,
980 * or false if not set
981 * @since 2.3.10
982 */
983 function pods_v_set( $value, $var, $type = 'get' ) {
984
985 $ret = false;
986
987 if ( null === $var || '' === $var ) {
988 // Invalid $var
989 } elseif ( null === $type || '' === $type ) {
990 // Invalid $type
991 } elseif ( is_array( $type ) ) {
992 $type[ $var ] = $value;
993
994 $ret = $type;
995 } elseif ( is_object( $type ) ) {
996 $type->{$var} = $value;
997
998 $ret = $type;
999 } else {
1000 $type = strtolower( $type );
1001
1002 if ( 'get' === $type ) {
1003 $_GET[ $var ] = $value;
1004
1005 $ret = $_GET;
1006 } elseif ( 'post' === $type ) {
1007 $_POST[ $var ] = $value;
1008
1009 $ret = $_POST;
1010 } elseif ( 'request' === $type ) {
1011 $_REQUEST[ $var ] = $value;
1012
1013 $ret = $_REQUEST;
1014 } elseif ( 'url' === $type ) {
1015 if ( is_numeric( $var ) && function_exists( 'http_build_url' ) ) {
1016 $url = parse_url( pods_current_url() );
1017 $uri = trim( $url['path'], '/' );
1018 $uri = array_filter( explode( '/', $uri ) );
1019
1020 if ( 'first' === $var ) {
1021 $var = 0;
1022 } elseif ( 'last' === $var ) {
1023 $var = - 1;
1024 }
1025
1026 if ( $var < 0 ) {
1027 $uri[ count( $uri ) + $var ] = $value;
1028 } else {
1029 $uri[ $var ] = $value;
1030 }
1031
1032 $url['path'] = '/' . implode( '/', $uri ) . '/';
1033 $url['path'] = trim( $url['path'], '/' );
1034
1035 $ret = http_build_url( $url );
1036 } else {
1037 $ret = add_query_arg( array( $var => $value ) );
1038 }//end if
1039 } elseif ( 'server' === $type ) {
1040 $_SERVER[ $var ] = $value;
1041
1042 $ret = $_SERVER;
1043 } elseif ( in_array( $type, array( 'global', 'globals' ), true ) ) {
1044 $GLOBALS[ $var ] = $value;
1045
1046 $ret = $GLOBALS;
1047 } elseif ( 'session' === $type ) {
1048 // Session start
1049 pods_session_start();
1050
1051 $_SESSION[ $var ] = $value;
1052
1053 $ret = $_SESSION;
1054 } elseif ( 'cookie' === $type && ! headers_sent() ) {
1055 setcookie( $var, $value, time() + 10 * DAY_IN_SECONDS, COOKIEPATH );
1056
1057 $ret = $_COOKIE;
1058 } elseif ( 'constant' === $type && ! defined( $var ) && ( is_scalar( $value ) || null === $value ) ) {
1059 define( $var, $value );
1060
1061 $ret = constant( $var );
1062 } elseif ( 'user' === $type && is_user_logged_in() ) {
1063 $user = get_userdata( get_current_user_id() );
1064
1065 $user_data = $user->to_array();
1066
1067 if ( 'role' === $var ) {
1068 // Role
1069 $user->set_role( $value );
1070 } elseif ( isset( $user_data[ $var ] ) ) {
1071 // Core field
1072 wp_update_user(
1073 array(
1074 'ID' => $user->ID,
1075 $var => $value,
1076 )
1077 );
1078 } else {
1079 // Meta field
1080 update_user_meta( $user->ID, $var, $value );
1081 }
1082
1083 $ret = get_userdata( $user->ID );
1084 } elseif ( 'pods' === $type ) {
1085 /**
1086 * @var $pods Pods
1087 */
1088 global $pods;
1089
1090 if ( is_object( $pods ) && 'Pods' == get_class( $pods ) && $pods->exists() ) {
1091 $ret = $pods->save( $var, $value );
1092 }
1093 } else {
1094 $ret = apply_filters( "pods_var_set_{$type}", $value, $var );
1095 }//end if
1096 }//end if
1097
1098 return $ret;
1099
1100 }
1101
1102 /**
1103 * Return a variable (if exists)
1104 *
1105 * @param mixed $var The variable name or URI segment position
1106 * @param string $type (optional) Super globals, url/url-relative, constants, globals, options, transients, cache,
1107 * user data, Pod field values, dates
1108 * @param mixed $default (optional) The default value to set if variable doesn't exist
1109 * @param mixed $allowed (optional) The value(s) allowed
1110 * @param bool $strict (optional) Only allow values (must not be empty)
1111 * @param bool $casting (optional) Whether to cast the value returned like provided in $default
1112 * @param string $context (optional) All returned values are sanitized unless this is set to 'raw'
1113 *
1114 * @return mixed The variable (if exists), or default value
1115 * @since 1.10.6
1116 *
1117 * @deprecated 2.4.0 Use pods_v() or pods_v_sanitized() instead.
1118 * @see pods_v_sanitized
1119 */
1120 function pods_var( $var = 'last', $type = 'get', $default = null, $allowed = null, $strict = false, $casting = false, $context = 'display' ) {
1121
1122 if ( 'raw' === $context ) {
1123 $output = pods_v(
1124 $var, $type, $default, $strict, array(
1125 'allowed' => $allowed,
1126 'casting' => $casting,
1127 )
1128 );
1129 } else {
1130 $output = pods_v_sanitized(
1131 $var, $type, $default, $strict, array(
1132 'allowed' => $allowed,
1133 'casting' => $casting,
1134 )
1135 );
1136 }
1137
1138 return $output;
1139
1140 }
1141
1142 /**
1143 * Return a variable's raw value (if exists)
1144 *
1145 * @param mixed $var The variable name or URI segment position
1146 * @param string $type (optional) Super globals, url/url-relative, constants, globals, options, transients, cache,
1147 * user data, Pod field values, dates
1148 * @param mixed $default (optional) The default value to set if variable doesn't exist
1149 * @param mixed $allowed (optional) The value(s) allowed
1150 * @param bool $strict (optional) Only allow values (must not be empty)
1151 * @param bool $casting (optional) Whether to cast the value returned like provided in $default
1152 *
1153 * @return mixed The variable (if exists), or default value
1154 * @since 2.0.0
1155 *
1156 * @deprecated 2.4.0 Use pods_v() instead.
1157 * @see pods_v
1158 */
1159 function pods_var_raw( $var = 'last', $type = 'get', $default = null, $allowed = null, $strict = false, $casting = false ) {
1160
1161 return pods_v(
1162 $var, $type, $default, $strict, array(
1163 'allowed' => $allowed,
1164 'casting' => $casting,
1165 )
1166 );
1167
1168 }
1169
1170 /**
1171 * Set a variable
1172 *
1173 * @param mixed $value The value to be set
1174 * @param mixed $var The variable name or URI segment position
1175 * @param string $type (optional) "url", "get", "post", "request", "server", "session", "cookie", "constant", or "user"
1176 *
1177 * @return mixed $value (if set), $type (if $type is array or object), or $url (if $type is 'url')
1178 * @since 1.10.6
1179 *
1180 * @deprecated 2.4.0 Use pods_v_set() instead.
1181 * @see pods_v_set
1182 */
1183 function pods_var_set( $value, $var = 'last', $type = 'url' ) {
1184
1185 return pods_v_set( $value, $var, $type );
1186
1187 }
1188
1189 /**
1190 * Create a new URL off of the current one, with updated parameters
1191 *
1192 * @param array $array Parameters to be set (empty will remove it)
1193 * @param array $allowed Parameters to keep (if empty, all are kept)
1194 * @param array $excluded Parameters to always remove
1195 * @param string $url URL to base update off of
1196 *
1197 * @return mixed
1198 *
1199 * @since 2.3.10
1200 *
1201 * @see add_query_arg
1202 */
1203 function pods_query_arg( $array = null, $allowed = null, $excluded = null, $url = null ) {
1204
1205 $array = (array) $array;
1206 $allowed = (array) $allowed;
1207 $excluded = (array) $excluded;
1208
1209 // Support for globally defined arguments.
1210 global $pods_query_args;
1211
1212 if ( empty( $pods_query_args ) ) {
1213 $pods_query_args = [
1214 'allowed' => array(),
1215 'excluded' => array(),
1216 ];
1217 }
1218
1219 // Merge any global args that we need to.
1220 $allowed = array_unique( array_merge( $pods_query_args['allowed'], $allowed ) );
1221 $excluded = array_unique( array_merge( $pods_query_args['excluded'], $excluded ) );
1222
1223 if ( ! isset( $_GET ) || $url ) {
1224 $query_args = array();
1225 } else {
1226 $query_args = pods_unsanitize( $_GET );
1227 }
1228
1229 foreach ( $query_args as $key => $val ) {
1230 if ( is_array( $val ) && empty( $val ) ) {
1231 $query_args[ $key ] = false;
1232 } elseif ( ! is_array( $val ) && strlen( $val ) < 1 ) {
1233 $query_args[ $key ] = false;
1234 } elseif ( ! empty( $allowed ) ) {
1235 $allow_it = false;
1236
1237 foreach ( $allowed as $allow ) {
1238 if ( $allow == $key ) {
1239 $allow_it = true;
1240 } elseif ( false !== strpos( $allow, '*' ) && 0 === strpos( $key, trim( $allow, '*' ) ) ) {
1241 $allow_it = true;
1242 }
1243 }
1244
1245 if ( ! $allow_it ) {
1246 $query_args[ $key ] = false;
1247 }
1248 }
1249 }//end foreach
1250
1251 if ( ! empty( $excluded ) ) {
1252 foreach ( $excluded as $exclusion ) {
1253 if ( isset( $query_args[ $exclusion ] ) && ! in_array( $exclusion, $allowed, true ) ) {
1254 $query_args[ $exclusion ] = false;
1255 }
1256 }
1257 }
1258
1259 if ( ! empty( $array ) ) {
1260 foreach ( $array as $key => $val ) {
1261 if ( null !== $val || false === strpos( $key, '*' ) ) {
1262 if ( is_array( $val ) && ! empty( $val ) ) {
1263 $query_args[ $key ] = $val;
1264 } elseif ( ! is_array( $val ) && 0 < strlen( $val ) ) {
1265 $query_args[ $key ] = $val;
1266 } elseif ( isset( $query_args[ $key ] ) ) {
1267 $query_args[ $key ] = false;
1268 }
1269 } else {
1270 $key = str_replace( '*', '', $key );
1271
1272 foreach ( $query_args as $k => $v ) {
1273 if ( false !== strpos( $k, $key ) ) {
1274 $query_args[ $k ] = false;
1275 }
1276 }
1277 }
1278 }
1279 }//end if
1280
1281 if ( null === $url ) {
1282 $url = add_query_arg( $query_args );
1283 } else {
1284 $url = add_query_arg( $query_args, $url );
1285 }
1286
1287 return $url;
1288
1289 }
1290
1291 /**
1292 * Create a new URL off of the current one, with updated parameters
1293 *
1294 * @param array $array Parameters to be set (empty will remove it)
1295 * @param array $allowed Parameters to keep (if empty, all are kept)
1296 * @param array $excluded Parameters to always remove
1297 * @param string $url URL to base update off of
1298 *
1299 * @return mixed
1300 *
1301 * @since 2.0.0
1302 *
1303 * @deprecated 2.4.0 Use pods_query_arg() instead.
1304 * @see pods_query_arg
1305 */
1306 function pods_var_update( $array = null, $allowed = null, $excluded = null, $url = null ) {
1307
1308 return pods_query_arg( $array, $allowed, $excluded, $url );
1309
1310 }
1311
1312 /**
1313 * Cast a value as a specific type
1314 *
1315 * @param mixed $value
1316 * @param mixed $cast_from
1317 *
1318 * @return bool
1319 *
1320 * @since 2.0.0
1321 */
1322 function pods_cast( $value, $cast_from = null ) {
1323
1324 if ( null !== $cast_from ) {
1325 if ( is_object( $value ) && is_array( $cast_from ) ) {
1326 $value = get_object_vars( $value );
1327 } elseif ( is_array( $value ) && is_object( $cast_from ) ) {
1328 $value = (object) $value;
1329 } else {
1330 settype( $value, gettype( $cast_from ) );
1331 }
1332 }
1333
1334 return $value;
1335
1336 }
1337
1338 /**
1339 * Create a slug from an input string
1340 *
1341 * @param string $orig Original string.
1342 * @param bool $strict Whether to only support 0-9, a-z, A-Z, and dash characters.
1343 *
1344 * @return string Sanitized slug
1345 *
1346 * @since 1.8.9
1347 */
1348 function pods_create_slug( $orig, $strict = true ) {
1349 $str = remove_accents( $orig );
1350 $str = preg_replace( '/([_ \\/])/', '-', trim( $str ) );
1351
1352 if ( $strict ) {
1353 $str = preg_replace( '/([^0-9a-z\-])/', '', strtolower( $str ) );
1354 } else {
1355 $str = urldecode( sanitize_title( strtolower( $str ) ) );
1356 }
1357
1358 $str = preg_replace( '/(\-){2,}/', '-', $str );
1359 $str = trim( $str, '-' );
1360 $str = apply_filters( 'pods_create_slug', $str, $orig );
1361
1362 return $str;
1363 }
1364
1365 /**
1366 * Build a unique slug
1367 *
1368 * @param string $slug The slug value
1369 * @param string $column_name The column name
1370 * @param string|array $pod The Pod name or array of Pod data
1371 * @param int $pod_id The Pod ID
1372 * @param int $id The item ID
1373 * @param object $obj (optional)
1374 *
1375 * @param bool $strict
1376 *
1377 * @return string The unique slug name
1378 * @since 1.7.2
1379 */
1380 function pods_unique_slug( $slug, $column_name, $pod, $pod_id = 0, $id = 0, $obj = null, $strict = true ) {
1381
1382 $slug = pods_create_slug( $slug, $strict );
1383
1384 $pod_data = array();
1385
1386 if ( is_array( $pod ) ) {
1387 $pod_data = $pod;
1388 $pod_id = pods_v_sanitized( 'id', $pod_data, 0 );
1389 $pod = pods_v_sanitized( 'name', $pod_data );
1390 }
1391
1392 $pod_id = absint( $pod_id );
1393 $id = absint( $id );
1394
1395 if ( empty( $pod_data ) ) {
1396 $pod_data = pods_api()->load_pod(
1397 array(
1398 'id' => $pod_id,
1399 'name' => $pod,
1400 ), false
1401 );
1402 }
1403
1404 if ( empty( $pod_data ) || empty( $pod_id ) || empty( $pod ) ) {
1405 return $slug;
1406 }
1407
1408 if ( 'table' !== $pod_data['storage'] || ! in_array( $pod_data['type'], array( 'pod', 'table' ), true ) ) {
1409 return $slug;
1410 }
1411
1412 $check_sql = "
1413 SELECT DISTINCT `t`.`{$column_name}` AS `slug`
1414 FROM `@wp_pods_{$pod}` AS `t`
1415 WHERE `t`.`{$column_name}` = %s AND `t`.`id` != %d
1416 LIMIT 1
1417 ";
1418
1419 $slug_check = pods_query( array( $check_sql, $slug, $id ), $obj );
1420
1421 if ( ! empty( $slug_check ) || apply_filters( 'pods_unique_slug_is_bad_flat_slug', false, $slug, $column_name, $pod, $pod_id, $id, $pod_data, $obj ) ) {
1422 $suffix = 2;
1423
1424 do {
1425 $alt_slug = substr( $slug, 0, 200 - ( strlen( $suffix ) + 1 ) ) . "-{$suffix}";
1426
1427 $slug_check = pods_query( array( $check_sql, $alt_slug, $id ), $obj );
1428
1429 $suffix ++;
1430 } while ( ! empty( $slug_check ) || apply_filters( 'pods_unique_slug_is_bad_flat_slug', false, $alt_slug, $column_name, $pod, $pod_id, $id, $pod_data, $obj ) );
1431
1432 $slug = $alt_slug;
1433 }
1434
1435 $slug = apply_filters( 'pods_unique_slug', $slug, $id, $column_name, $pod, $pod_id, $obj );
1436
1437 return $slug;
1438 }
1439
1440 /**
1441 * Return a lowercase alphanumeric name (use pods_js_name if you want "_" instead of "-" )
1442 *
1443 * @param string $orig Input string to clean
1444 * @param boolean $lower Force lowercase
1445 * @param boolean $trim_underscores Whether to trim off underscores
1446 *
1447 * @return string Sanitized name
1448 *
1449 * @since 1.2.0
1450 */
1451 function pods_clean_name( $orig, $lower = true, $trim_underscores = false ) {
1452 if ( null === $orig ) {
1453 return '';
1454 }
1455
1456 $str = trim( (string) $orig );
1457 $str = remove_accents( $str );
1458 $str = preg_replace( '/([^0-9a-zA-Z\-_\s])/', '', $str );
1459 $str = preg_replace( '/(\s_)/', '_', $str );
1460 $str = preg_replace( '/(\s+)/', '_', $str );
1461 $str = preg_replace( '/(-){2,}/', '-', $str );
1462
1463 if ( $lower ) {
1464 $str = strtolower( $str );
1465 }
1466
1467 if ( $trim_underscores ) {
1468 $str = trim( $str, '_' );
1469 }
1470
1471 return $str;
1472 }
1473
1474 /**
1475 * Return a lowercase alphanumeric name (with underscores) for safe Javascript variable names
1476 *
1477 * @param string $orig Input string to clean
1478 * @param boolean $lower Force lowercase
1479 *
1480 * @return string Sanitized name
1481 *
1482 * @since 2.5.3
1483 */
1484 function pods_js_name( $orig, $lower = true ) {
1485
1486 $str = pods_clean_name( $orig, $lower );
1487 $str = str_replace( '-', '_', $str );
1488
1489 return $str;
1490 }
1491
1492 /**
1493 * Get the Absolute Integer of a value
1494 *
1495 * @param string $maybeint
1496 * @param bool $strict (optional) Check if $maybeint is a integer.
1497 * @param bool $allow_negative (optional)
1498 *
1499 * @return integer
1500 * @since 2.0.0
1501 */
1502 function pods_absint( $maybeint, $strict = true, $allow_negative = false ) {
1503 if ( is_null( $maybeint ) ) {
1504 $maybeint = 0;
1505 } elseif ( is_bool( $maybeint ) ) {
1506 $maybeint = (int) $maybeint;
1507 }
1508
1509 if ( true === $strict && ! is_numeric( trim( $maybeint ) ) ) {
1510 return 0;
1511 }
1512
1513 if ( false !== $allow_negative ) {
1514 return intval( $maybeint );
1515 }
1516
1517 return absint( $maybeint );
1518 }
1519
1520 /**
1521 * Functions like str_replace except it will restrict $occurrences
1522 *
1523 * @since 2.0
1524 *
1525 * @param mixed $find
1526 * @param mixed $replace
1527 * @param string $string
1528 * @param int $occurrences (optional)
1529 *
1530 * @return mixed
1531 */
1532 function pods_str_replace( $find, $replace, $string, $occurrences = - 1 ) {
1533
1534 if ( is_array( $string ) ) {
1535 foreach ( $string as $k => $v ) {
1536 $string[ $k ] = pods_str_replace( $find, $replace, $v, $occurrences );
1537 }
1538
1539 return $string;
1540 } elseif ( is_object( $string ) ) {
1541 $string = get_object_vars( $string );
1542
1543 foreach ( $string as $k => $v ) {
1544 $string[ $k ] = pods_str_replace( $find, $replace, $v, $occurrences );
1545 }
1546
1547 return (object) $string;
1548 }
1549
1550 if ( is_array( $find ) ) {
1551 foreach ( $find as &$f ) {
1552 $f = '/' . preg_quote( $f, '/' ) . '/';
1553 }
1554 } else {
1555 $find = '/' . preg_quote( $find, '/' ) . '/';
1556 }
1557 if ( is_string( $string ) ) {
1558 return preg_replace( $find, $replace, $string, $occurrences );
1559 } else {
1560 // Occasionally we will receive non string values (true, false, null). Allow those to pass through
1561 return $string;
1562 }
1563 }
1564
1565 /**
1566 * Use mb_strlen if available, otherwise fallback to strlen
1567 *
1568 * @param string $string
1569 *
1570 * @return int
1571 */
1572 function pods_mb_strlen( $string ) {
1573
1574 if ( function_exists( 'mb_strlen' ) ) {
1575 return mb_strlen( $string );
1576 }
1577
1578 return strlen( $string );
1579
1580 }
1581
1582 /**
1583 * Use mb_substr if available, otherwise fallback to substr
1584 *
1585 * @param string $string
1586 * @param int $start
1587 * @param null|int $length
1588 * @param null|string $encoding
1589 *
1590 * @return string
1591 */
1592 function pods_mb_substr( $string, $start, $length = null, $encoding = null ) {
1593
1594 if ( function_exists( 'mb_substr' ) ) {
1595 if ( null === $encoding ) {
1596 $encoding = mb_internal_encoding();
1597 }
1598
1599 return mb_substr( $string, $start, $length, $encoding );
1600 }
1601
1602 return substr( $string, $start, $length );
1603
1604 }
1605
1606 /**
1607 * Evaluate tags like magic tags but through pods_v and sanitize for SQL with an empty double quote if needed.
1608 *
1609 * @since 2.7.23
1610 *
1611 * @param string|array|object $tags String to be evaluated.
1612 * @param array $args {
1613 * Function arguments.
1614 * @type bool $sanitize Whether to sanitize.
1615 * @type null|mixed $fallback The fallback value to use if not set, should already be sanitized.
1616 * @type Pods $pod Pod to parse the tags through.
1617 * @type bool $use_current_pod Whether to auto-detect the current Pod.
1618 * }
1619 *
1620 * @return string Evaluated string.
1621 *
1622 * @see pods_evaluate_tag
1623 */
1624 function pods_evaluate_tags_sql( $tags, $args = array() ) {
1625 // The temporary placeholder we will use.
1626 $placeholder = '__PODS__TMP__EMPTY_VALUE__';
1627
1628 // Store and overwrite fallback argument.
1629 $fallback = '""';
1630 if ( isset( $args['fallback'] ) ) {
1631 $fallback = $args['fallback'];
1632 $args['fallback'] = $placeholder;
1633 }
1634
1635 $defaults = array(
1636 'sanitize' => true,
1637 'fallback' => $placeholder,
1638 );
1639
1640 // Set default arguments to use.
1641 $args = array_merge( $defaults, $args );
1642
1643 // Evaluate the magic tags.
1644 $evaluated = pods_evaluate_tags( $tags, $args );
1645
1646 $find = array(
1647 '= ' . $placeholder,
1648 '=' . $placeholder,
1649 $placeholder,
1650 );
1651
1652 $replace = array(
1653 '= ' . $fallback,
1654 '=' . $fallback,
1655 '',
1656 );
1657
1658 // Finish sanitizing the string so it is SQL-safe.
1659 $sanitized = str_replace( $find, $replace, $evaluated );
1660
1661 /**
1662 * Allow filtering the result of how we evaluate and sanitize the SQL.
1663 *
1664 * @since 2.7.23
1665 *
1666 * @param string $sanitized The evaluated and sanitized string.
1667 * @param string $evaluated The evaluated string.
1668 * @param string|array|object $tags Original string to be evaluated.
1669 * @param array $args Additional function arguments.
1670 */
1671 return apply_filters( 'pods_evaluate_tags_sql', $sanitized, $evaluated, $tags, $args );
1672 }
1673
1674 /**
1675 * Evaluate tags like magic tags but through pods_v.
1676 *
1677 * @param string|array|object $tags String to be evaluated.
1678 * @param array $args {
1679 * Function arguments.
1680 * @type bool $sanitize Whether to sanitize.
1681 * @type null|mixed $fallback The fallback value to use if not set, should already be sanitized.
1682 * @type Pods $pod Pod to parse the tags through.
1683 * @type bool $use_current_pod Whether to auto-detect the current Pod.
1684 * }
1685 *
1686 * @return string
1687 *
1688 * @since 2.1
1689 *
1690 * @see pods_evaluate_tag
1691 */
1692 function pods_evaluate_tags( $tags, $args = array() ) {
1693
1694 // Back compat.
1695 if ( ! is_array( $args ) ) {
1696 $prev_args = array( 'tags', 'sanitize', 'fallback' );
1697 $args = func_get_args();
1698 $args = array_combine( array_slice( $prev_args, 0, count( $args ) ), $args );
1699 unset( $args['tags'] );
1700 }
1701
1702 if ( is_array( $tags ) ) {
1703 foreach ( $tags as $k => $tag ) {
1704 $tags[ $k ] = pods_evaluate_tags( $tag, $args );
1705 }
1706
1707 return $tags;
1708 }
1709
1710 if ( is_object( $tags ) ) {
1711 $tags = get_object_vars( $tags );
1712
1713 // Evaluate array and cast as object.
1714 $tags = (object) pods_evaluate_tags( $tags, $args );
1715
1716 return $tags;
1717 }
1718
1719 return preg_replace_callback(
1720 '/({@(.*?)})/m',
1721 function ( $tag ) use ( $args ) {
1722 return pods_evaluate_tag( $tag, $args );
1723 },
1724 (string) $tags
1725 );
1726 }
1727
1728 /**
1729 * Evaluate tag like magic tag but sanitized.
1730 *
1731 * @since 2.1
1732 *
1733 * @param string|array $tag String to be evaluated.
1734 * @param array $args {
1735 * Function arguments.
1736 * @type null|mixed $fallback The fallback value to use if not set, should already be sanitized.
1737 * @type Pods $pod Pod to parse the tags through.
1738 * @type bool $use_current_pod Whether to auto-detect the current Pod.
1739 * }
1740 *
1741 * @return string Evaluated content.
1742 *
1743 * @see pods_evaluate_tag
1744 */
1745 function pods_evaluate_tag_sanitized( $tag, $args = array() ) {
1746 if ( ! is_array( $args ) ) {
1747 $args = array();
1748 }
1749 $args['sanitize'] = true;
1750 return pods_evaluate_tag( $tag, $args );
1751 }
1752
1753 /**
1754 * Evaluate tag like magic tag but mapped through pods_v.
1755 *
1756 * @since 2.1
1757 *
1758 * @param string|array $tag String to be evaluated.
1759 * @param array $args {
1760 * Function arguments.
1761 * @type bool $sanitize Whether to sanitize.
1762 * @type null|mixed $fallback The fallback value to use if not set, should already be sanitized.
1763 * @type bool|Pods $pod Pod to parse the tags through.
1764 * @type bool $use_current_pod Whether to auto-detect the current Pod.
1765 * }
1766 *
1767 * @return string Evaluated content.
1768 */
1769 function pods_evaluate_tag( $tag, $args = array() ) {
1770 $defaults = array(
1771 'sanitize' => false,
1772 'fallback' => null,
1773 'pod' => null,
1774 'use_current_pod' => false,
1775 );
1776
1777 // Back compat.
1778 if ( ! is_array( $args ) ) {
1779 $prev_args = array( 'tag', 'sanitize', 'fallback' );
1780 $args = func_get_args();
1781 $args = array_combine( array_slice( $prev_args, 0, count( $args ) ), $args );
1782 unset( $args['tag'] );
1783 }
1784
1785 $args = wp_parse_args( $args, $defaults );
1786 $sanitize = $args['sanitize'];
1787 $fallback = $args['fallback'];
1788 $pod = $args['pod'];
1789
1790 // Handle pods_evaluate_tags
1791 if ( is_array( $tag ) ) {
1792 if ( ! isset( $tag[2] ) && '' === trim( $tag[2] ) ) {
1793 if ( null === $fallback ) {
1794 return '';
1795 }
1796
1797 return $fallback;
1798 }
1799
1800 $tag = $tag[2];
1801 }
1802
1803 if ( $args['use_current_pod'] ) {
1804 $pod = pods();
1805 }
1806
1807 // Handle Pod fields.
1808 // The Pod will call this function without Pod param if no field is found.
1809 if ( $pod instanceof Pods ) {
1810 $value = $pod->do_magic_tags( '{@' . $tag . '}' );
1811
1812 if ( ! $value ) {
1813 if ( null === $fallback ) {
1814 return '';
1815 }
1816
1817 return $fallback;
1818 }
1819
1820 if ( $sanitize ) {
1821 $value = pods_sanitize( $value );
1822 }
1823
1824 return $value;
1825 }
1826
1827 $tag = trim( $tag, ' {@}' );
1828 $tag = explode( ',', $tag );
1829 $tag = pods_trim( $tag );
1830
1831 $value = '';
1832 $helper = isset( $tag[1] ) ? $tag[1] : null;
1833 $before = isset( $tag[2] ) ? $tag[2] : '';
1834 $after = isset( $tag[3] ) ? $tag[3] : '';
1835
1836 $tag = explode( '.', $tag[0] );
1837
1838 if ( empty( $tag ) || ! isset( $tag[0] ) || '' === trim( $tag[0] ) ) {
1839 if ( null === $fallback ) {
1840 return '';
1841 }
1842
1843 return $fallback;
1844 }
1845
1846 // Fix formatting that may be after the first .
1847 if ( 2 < count( $tag ) ) {
1848 $first_tag = $tag[0];
1849 unset( $tag[0] );
1850
1851 $tag = array(
1852 $first_tag,
1853 implode( '.', $tag ),
1854 );
1855 }
1856
1857 $tag = pods_trim( $tag );
1858
1859 $single_supported = array(
1860 'template-url',
1861 'stylesheet-url',
1862 'site-url',
1863 'home-url',
1864 'admin-url',
1865 'includes-url',
1866 'content-url',
1867 'plugins-url',
1868 'network-site-url',
1869 'network-home-url',
1870 'network-admin-url',
1871 'user-admin-url',
1872 'prefix',
1873 );
1874
1875 $pods_v_var = '';
1876 $pods_v_type = 'get';
1877
1878 if ( in_array( $tag[0], $single_supported, true ) ) {
1879 $pods_v_type = $tag[0];
1880 } elseif ( 1 === count( $tag ) ) {
1881 $pods_v_var = $tag[0];
1882 } elseif ( 2 === count( $tag ) ) {
1883 $pods_v_var = $tag[1];
1884 $pods_v_type = $tag[0];
1885 } else {
1886 // Some magic tags support traversal.
1887 $pods_v_var = array_slice( $tag, 1 );
1888 $pods_v_type = $tag[0];
1889 }
1890
1891 $value = pods_v( $pods_v_var, $pods_v_type, null, false, [
1892 'source' => 'magic-tag',
1893 ] );
1894
1895 if ( $helper ) {
1896 if ( ! $pod instanceof Pods ) {
1897 $pod = pods();
1898 }
1899
1900 $value = $pod->helper( $helper, $value );
1901 }
1902
1903 /**
1904 * Allow filtering the evaluated tag value.
1905 *
1906 * @since unknown
1907 *
1908 * @param mixed $value The evaluated tag value.
1909 * @param string $tag The evaluated tag name.
1910 * @param null|mixed $fallback The fallback value to use if not set, should already be sanitized.
1911 */
1912 $value = apply_filters( 'pods_evaluate_tag', $value, $tag, $fallback );
1913
1914 if ( is_array( $value ) && 1 === count( $value ) ) {
1915 $value = current( $value );
1916 }
1917
1918 if ( is_array( $value ) ) {
1919 $value = pods_serial_comma( $value );
1920 }
1921
1922 if ( null === $value ) {
1923 $value = '';
1924 }
1925
1926 if ( $sanitize ) {
1927 $value = pods_sanitize( $value );
1928 }
1929
1930 if ( null !== $fallback && '' === $value ) {
1931 $value = $fallback;
1932 }
1933
1934 return $before . $value . $after;
1935 }
1936
1937 /**
1938 * Split an array into human readable text (Item, Item, and Item)
1939 *
1940 * @param array $value
1941 * @param string $field
1942 * @param array $fields
1943 * @param string $and
1944 * @param string $field_index
1945 *
1946 * @return string
1947 *
1948 * @since 2.0.0
1949 */
1950 function pods_serial_comma( $value, $field = null, $fields = null, $and = null, $field_index = null ) {
1951
1952 if ( is_object( $value ) ) {
1953 $value = get_object_vars( $value );
1954 }
1955
1956 $defaults = array(
1957 'field' => $field,
1958 'fields' => $fields,
1959 'and' => $and,
1960 'field_index' => $field_index,
1961 'separator' => null,
1962 'serial' => true,
1963 );
1964
1965 if ( is_array( $field ) ) {
1966 $defaults['field'] = null;
1967
1968 $params = array_merge( $defaults, $field );
1969 } else {
1970 $params = $defaults;
1971 }
1972
1973 $params = (object) $params;
1974
1975 $simple = false;
1976
1977 if ( ! empty( $params->fields ) && is_array( $params->fields ) && isset( $params->fields[ $params->field ] ) ) {
1978 $params->field = $params->fields[ $params->field ];
1979
1980 $simple_tableless_objects = PodsForm::simple_tableless_objects();
1981
1982 if ( ! empty( $params->field ) && is_array( $params->field ) && in_array( $params->field['type'], PodsForm::tableless_field_types(), true ) ) {
1983 if ( in_array( $params->field['type'], PodsForm::file_field_types(), true ) ) {
1984 if ( null === $params->field_index ) {
1985 $params->field_index = 'guid';
1986 }
1987 } elseif ( in_array( $params->field['pick_object'], $simple_tableless_objects, true ) ) {
1988 $simple = true;
1989 } else {
1990 $pick_object = pods_v( 'pick_object', $params->field );
1991 $pick_val = pods_v( 'pick_val', $params->field );
1992 $table = null;
1993
1994 if ( ! empty( $pick_object ) && ( ! empty( $pick_val ) || in_array( $pick_object, array( 'user', 'media', 'comment' ), true ) ) ) {
1995 $table = pods_api()->get_table_info(
1996 $pick_object,
1997 $pick_val,
1998 null,
1999 null,
2000 $params->field
2001 );
2002 }
2003
2004 if ( ! empty( $table ) ) {
2005 if ( null === $params->field_index ) {
2006 $params->field_index = $table['field_index'];
2007 }
2008 }
2009 }
2010 }
2011 } else {
2012 $params->field = null;
2013 }//end if
2014
2015 if ( $simple && is_array( $params->field ) && ! is_array( $value ) && '' !== $value && null !== $value ) {
2016 $value = PodsForm::field_method( 'pick', 'simple_value', $params->field['name'], $value, $params->field );
2017 }
2018
2019 if ( ! is_array( $value ) ) {
2020 return $value;
2021 }
2022
2023 $value = pods_access_bleep_data( $value );
2024
2025 $original_value = $value;
2026
2027 if ( in_array( $params->separator, array( '', null ), true ) ) {
2028 $params->separator = ', ';
2029 }
2030
2031 if ( null === $params->and ) {
2032 $params->and = ' ' . __( 'and', 'pods' ) . ' ';
2033 }
2034
2035 /**
2036 * Allow filtering the "and" content used for pods_serial_comma.
2037 *
2038 * @since 2.7.17
2039 *
2040 * @param string|null $and The "and" content used, return null to disable.
2041 * @param string $value The value input into pods_serial_comma.
2042 * @param object $params The list of the setup parameters for pods_serial_comma.
2043 */
2044 $params->and = apply_filters( 'pods_serial_comma_and', $params->and, $value, $params );
2045
2046 /**
2047 * Allow filtering the "separator" content used for pods_serial_comma.
2048 *
2049 * @since 2.7.17
2050 *
2051 * @param string $separator The "separator" content used (default ", ").
2052 * @param string $value The value input into pods_serial_comma.
2053 * @param object $params The list of the setup parameters for pods_serial_comma.
2054 */
2055 $params->separator = apply_filters( 'pods_serial_comma_separator', $params->separator, $value, $params );
2056
2057 $last = '';
2058
2059 if ( ! empty( $value ) ) {
2060 $last = array_pop( $value );
2061 }
2062
2063 if ( $simple && is_array( $params->field ) && ! is_array( $last ) && '' !== $last && null !== $last ) {
2064 $last = PodsForm::field_method( 'pick', 'simple_value', $params->field['name'], $last, $params->field );
2065 }
2066
2067 if ( is_array( $last ) ) {
2068 if ( null !== $params->field_index && isset( $last[ $params->field_index ] ) ) {
2069 $last = $last[ $params->field_index ];
2070 } elseif ( isset( $last[0] ) ) {
2071 $last = $last[0];
2072 } elseif ( $simple ) {
2073 $last = current( $last );
2074 } else {
2075 $last = '';
2076 }
2077 }
2078
2079 if ( ! empty( $value ) ) {
2080 if ( null !== $params->field_index && isset( $original_value[ $params->field_index ] ) ) {
2081 return $original_value[ $params->field_index ];
2082 } elseif ( null !== $params->field_index && isset( $value[ $params->field_index ] ) ) {
2083 return $value[ $params->field_index ];
2084 } elseif ( ! is_array( $value ) ) {
2085 $value = array( $value );
2086 }
2087
2088 foreach ( $value as $k => $v ) {
2089 if ( $simple && is_array( $params->field ) && ! is_array( $v ) && '' !== $v && null !== $v ) {
2090 $v = PodsForm::field_method( 'pick', 'simple_value', $params->field['name'], $v, $params->field );
2091 }
2092
2093 if ( is_array( $v ) ) {
2094 if ( null !== $params->field_index && isset( $v[ $params->field_index ] ) ) {
2095 $v = $v[ $params->field_index ];
2096 } elseif ( $simple ) {
2097 $v = trim( implode( $params->separator, $v ), $params->separator . ' ' );
2098 } else {
2099 unset( $value[ $k ] );
2100
2101 continue;
2102 }
2103 }
2104
2105 $value[ $k ] = $v;
2106 }
2107
2108 $has_serial_comma = $params->serial && 1 < count( $value );
2109
2110 $value = trim( implode( $params->separator, $value ), $params->separator . ' ' );
2111
2112 // Add final serial comma.
2113 if ( $has_serial_comma ) {
2114 /**
2115 * Allow filtering the final serial comma (before the "and") used for pods_serial_comma.
2116 *
2117 * @since unknown
2118 *
2119 * @param string $serial_comma The serial comma content used, return an empty string to disable (default ", ").
2120 * @param string $value The formatted value.
2121 * @param string $original_value The original value input into pods_serial_comma.
2122 * @param object $params The list of the setup parameters for pods_serial_comma.
2123 */
2124 $serial_comma = apply_filters( 'pods_serial_comma', $params->separator, $value, $original_value, $params );
2125
2126 if ( '' !== $serial_comma ) {
2127 $value .= $serial_comma;
2128 }
2129 }
2130
2131 $value = trim( $value );
2132 $last = trim( $last );
2133
2134 if ( 0 < strlen( $value ) && 0 < strlen( $last ) ) {
2135 $value = $value . $params->and . $last;
2136 } elseif ( 0 < strlen( $last ) ) {
2137 $value = $last;
2138 } else {
2139 $value = '';
2140 }
2141 } else {
2142 $value = $last;
2143 }//end if
2144
2145 $value = trim( $value, $params->separator . ' ' );
2146
2147 $value = apply_filters( 'pods_serial_comma_value', $value, $original_value, $params );
2148
2149 return (string) $value;
2150 }
2151
2152 /**
2153 * Return a variable if a user is logged in or anonymous, or a specific capability
2154 *
2155 * @param mixed $anon Variable to return if user is anonymous (not logged in)
2156 * @param mixed $user Variable to return if user is logged in
2157 * @param string|array $capability Capability or array of Capabilities to check to return $user on
2158 *
2159 * @return mixed $user Variable to return if user is logged in (if logged in), otherwise $anon
2160 *
2161 * @since 2.0.5
2162 */
2163 function pods_var_user( $anon = false, $user = true, $capability = null ) {
2164
2165 $value = $anon;
2166
2167 if ( is_user_logged_in() ) {
2168 if ( empty( $capability ) ) {
2169 $value = $user;
2170 } else {
2171 $capabilities = (array) $capability;
2172
2173 foreach ( $capabilities as $capability ) {
2174 if ( current_user_can( $capability ) ) {
2175 $value = $user;
2176
2177 break;
2178 }
2179 }
2180 }
2181 }
2182
2183 return $value;
2184 }
2185
2186 /**
2187 * Take a one-level list of items and make it hierarchical
2188 *
2189 * @param array|object $list List of items
2190 * @param array $args Array of parent, children, and id keys to use
2191 *
2192 * @return array|object
2193 * @since 2.3.0
2194 */
2195 function pods_hierarchical_list( $list, $args = array() ) {
2196
2197 if ( empty( $args ) || ( ! is_object( $list ) && ! is_array( $list ) ) ) {
2198 return $list;
2199 }
2200
2201 $defaults = array(
2202 'id' => 'id',
2203 'parent' => 'parent',
2204 'children' => 'children',
2205 'orphans' => true,
2206 'found' => array(),
2207 'list' => array(),
2208 'current_depth' => - 1,
2209 );
2210
2211 $args = array_merge( $defaults, (array) $args );
2212
2213 $list = pods_hierarchical_list_recurse( 0, $list, $args );
2214
2215 return $list;
2216 }
2217
2218 /**
2219 * Recurse list of items and make it hierarchical
2220 *
2221 * @param int $parent Parent ID
2222 * @param array|object $list List of items
2223 * @param array $args Array of parent, children, and id keys to use
2224 *
2225 * @return array|object
2226 * @since 2.3.0
2227 */
2228 function pods_hierarchical_list_recurse( $parent, $list, &$args ) {
2229
2230 $new = array();
2231
2232 $object = false;
2233
2234 if ( is_object( $list ) ) {
2235 $object = true;
2236 $list = get_object_vars( $list );
2237 }
2238
2239 $args['current_depth'] ++;
2240
2241 $depth = $args['current_depth'];
2242
2243 if ( 0 == $depth ) {
2244 $args['list'] = $list;
2245 }
2246
2247 foreach ( $list as $k => $list_item ) {
2248 if ( is_object( $list_item ) && isset( $list_item->{$args['id']} ) ) {
2249 $list_item->{$args['parent']} = (int) pods_v( $args['parent'], $list_item );
2250
2251 if ( is_array( $list_item->{$args['parent']} ) && isset( $list_item->{$args['parent']}[ $args['id'] ] ) && $parent == $list_item->{$args['parent']}[ $args['id'] ] ) {
2252 $list_item->{$args['children']} = pods_hierarchical_list_recurse( $list_item->{$args['id']}, $list, $args );
2253 } elseif ( $parent == $list_item->{$args['parent']} || ( 0 == $depth && $parent == $list_item->{$args['id']} ) ) {
2254 $list_item->{$args['children']} = pods_hierarchical_list_recurse( $list_item->{$args['id']}, $list, $args );
2255 } else {
2256 continue;
2257 }
2258
2259 $args['found'][ $k ] = $list_item;
2260 } elseif ( is_array( $list_item ) && isset( $list_item[ $args['id'] ] ) ) {
2261 $list_item[ $args['parent'] ] = (int) pods_v( $args['parent'], $list_item );
2262
2263 if ( is_array( $list_item[ $args['parent'] ] ) && isset( $list_item[ $args['parent'] ][ $args['id'] ] ) && $parent == $list_item[ $args['parent'] ][ $args['id'] ] ) {
2264 $list_item[ $args['children'] ] = pods_hierarchical_list_recurse( $list_item[ $args['id'] ], $list, $args );
2265 } elseif ( $parent == $list_item[ $args['parent'] ] || ( 0 == $depth && $parent == $list_item[ $args['id'] ] ) ) {
2266 $list_item[ $args['children'] ] = pods_hierarchical_list_recurse( $list_item[ $args['id'] ], $list, $args );
2267 } else {
2268 continue;
2269 }
2270
2271 $args['found'][ $k ] = $list_item;
2272 } else {
2273 continue;
2274 }//end if
2275
2276 $new[ $k ] = $list_item;
2277
2278 $args['current_depth'] = $depth;
2279 }//end foreach
2280
2281 if ( 0 == $depth && empty( $new ) && ! empty( $list ) ) {
2282 $first = current( array_slice( $list, 0, 1 ) );
2283
2284 $new_parent = 0;
2285
2286 $args['current_depth'] = - 1;
2287
2288 if ( is_object( $first ) && isset( $first->{$args['parent']} ) ) {
2289 $new_parent = (int) $first->{$args['parent']};
2290 } elseif ( is_array( $first ) && isset( $first[ $args['parent'] ] ) ) {
2291 $new_parent = (int) $first[ $args['parent'] ];
2292 }
2293
2294 if ( ! empty( $new_parent ) ) {
2295 $new = pods_hierarchical_list_recurse( $new_parent, $list, $args );
2296 }
2297 }
2298
2299 if ( 0 == $depth ) {
2300 $orphans = array();
2301
2302 foreach ( $args['list'] as $k => $list_item ) {
2303 if ( ! isset( $args['found'][ $k ] ) ) {
2304 $orphans[ $k ] = $list_item;
2305 }
2306 }
2307
2308 if ( ! empty( $orphans ) ) {
2309 foreach ( $orphans as $orphan ) {
2310 $new[] = $orphan;
2311 }
2312 }
2313 }
2314
2315 if ( $object ) {
2316 $new = (object) $new;
2317 }
2318
2319 return $new;
2320 }
2321
2322 /**
2323 * Take a one-level list of items and make it hierarchical for <select>
2324 *
2325 * @param array|object $list List of items
2326 * @param array $args Array of index, parent, children, id, and prefix keys to use
2327 *
2328 * @return array|object
2329 * @internal param string $children_key Key to recurse children into
2330 *
2331 * @since 2.3.0
2332 */
2333 function pods_hierarchical_select( $list, $args = array() ) {
2334
2335 $object = false;
2336
2337 if ( is_object( $list ) ) {
2338 $object = true;
2339 $list = get_object_vars( $list );
2340 }
2341
2342 $list = pods_hierarchical_list( $list, $args );
2343
2344 $defaults = array(
2345 'index' => 'name',
2346 'children' => 'children',
2347 'prefix' => '&nbsp;&nbsp;&nbsp;',
2348 );
2349
2350 $args = array_merge( $defaults, (array) $args );
2351
2352 $list = pods_hierarchical_select_recurse( $list, $args, 0 );
2353
2354 if ( $object ) {
2355 $list = (object) $list;
2356 }
2357
2358 return $list;
2359 }
2360
2361 /**
2362 * Recurse list of hierarchical data
2363 *
2364 * @param array $items Items to recurse.
2365 * @param array $args Array of children and prefix keys to use.
2366 * @param int $depth Current depth of recursion.
2367 *
2368 * @return array
2369 * @internal param array|object $list List of items
2370 * @internal param string $children_key Key to recurse children into
2371 *
2372 * @see pods_hierarchical_select
2373 * @since 2.3.0
2374 */
2375 function pods_hierarchical_select_recurse( $items, $args, $depth = 0 ) {
2376
2377 $data = array();
2378
2379 foreach ( $items as $k => $v ) {
2380 $object = false;
2381
2382 if ( is_object( $v ) ) {
2383 $object = true;
2384 $v = get_object_vars( $v );
2385 }
2386
2387 if ( isset( $v[ $args['index'] ] ) ) {
2388 $v[ $args['index'] ] = ( 0 < $depth ? str_repeat( $args['prefix'], $depth ) : '' ) . $v[ $args['index'] ];
2389 }
2390
2391 $children = array();
2392
2393 if ( isset( $v[ $args['children'] ] ) ) {
2394 if ( ! empty( $v[ $args['children'] ] ) ) {
2395 $children = pods_hierarchical_select_recurse( $v[ $args['children'] ], $args, ( $depth + 1 ) );
2396 }
2397
2398 unset( $v[ $args['children'] ] );
2399 }
2400
2401 if ( $object ) {
2402 $v = (object) $v;
2403 }
2404
2405 $data[ $k ] = $v;
2406
2407 if ( ! empty( $children ) ) {
2408 foreach ( $children as $ck => $cv ) {
2409 $data[ $ck ] = $cv;
2410 }
2411 }
2412 }//end foreach
2413
2414 return $data;
2415 }
2416
2417 /**
2418 * Filters a list of objects or arrays, based on a set of key => value arguments.
2419 *
2420 * @param array|object $list An array or object, with objects/arrays to filter
2421 * @param array $args An array of key => value arguments to match against each object
2422 * @param string $operator The logical operation to perform:
2423 * 'AND' means all elements from the array must match;
2424 * 'OR' means only one element needs to match;
2425 * 'NOT' means no elements may match.
2426 * The default is 'AND'.
2427 *
2428 * @see wp_list_filter
2429 * @return array
2430 * @since 2.3.0
2431 */
2432 function pods_list_filter( $list, $args = array(), $operator = 'AND' ) {
2433
2434 if ( empty( $args ) ) {
2435 return $list;
2436 }
2437
2438 $data = $list;
2439
2440 $object = false;
2441
2442 if ( is_object( $data ) ) {
2443 $object = true;
2444 $data = get_object_vars( $data );
2445 }
2446
2447 $filtered = wp_list_filter( $data, $args, $operator );
2448
2449 if ( $object ) {
2450 $filtered = (object) $filtered;
2451 }
2452
2453 return $filtered;
2454 }
2455
2456 /**
2457 * Enforce a URL as safe and fallback to another URL if it is not safe.
2458 *
2459 * @since 2.7.31.3
2460 *
2461 * @param string $url The URL to enforce as safe.
2462 * @param string|null $fallback_url The fallback URL to use if the URL is not valid.
2463 *
2464 * @return string The safe URL or the fallback URL if that was not valid.
2465 */
2466 function pods_enforce_safe_url( $url, $fallback_url = null ) {
2467 $url = wp_sanitize_redirect( $url );
2468
2469 if ( null === $fallback_url ) {
2470 $fallback_url = pods_current_url();
2471 }
2472
2473 return wp_validate_redirect( $url, $fallback_url );
2474 }
2475