PluginProbe ʕ •ᴥ•ʔ
Pods – Custom Content Types and Fields / 2.9.19.5
Pods – Custom Content Types and Fields v2.9.19.5
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 / classes / PodsForm.php
pods / classes Last commit date
cli 21 hours ago fields 21 hours ago widgets 21 hours ago Pods.php 21 hours ago PodsAPI.php 21 hours ago PodsAdmin.php 21 hours ago PodsArray.php 21 hours ago PodsComponent.php 21 hours ago PodsComponents.php 21 hours ago PodsData.php 21 hours ago PodsField.php 21 hours ago PodsForm.php 21 hours ago PodsI18n.php 21 hours ago PodsInit.php 21 hours ago PodsMeta.php 21 hours ago PodsMigrate.php 21 hours ago PodsRESTFields.php 21 hours ago PodsRESTHandlers.php 21 hours ago PodsTermSplitting.php 21 hours ago PodsUI.php 21 hours ago PodsView.php 21 hours ago
PodsForm.php
1981 lines
1 <?php
2
3 use Pods\Whatsit\Field;
4
5 /**
6 * @package Pods
7 */
8 class PodsForm {
9
10 /**
11 * @var PodsForm
12 */
13 protected static $instance = null;
14
15 /**
16 * @var string
17 */
18 public static $field = null;
19
20 /**
21 * @var string
22 */
23 public static $field_group = null;
24
25 /**
26 * @var string
27 */
28 public static $field_type = null;
29
30 /**
31 * @var array
32 */
33 public static $field_types = array();
34
35 /**
36 * @var array
37 */
38 public static $loaded = array();
39
40 /**
41 * @var int
42 */
43 public static $form_counter = 0;
44
45 /**
46 * Singleton handling for a basic pods_form() request
47 *
48 * @return \PodsForm
49 *
50 * @since 2.3.5
51 */
52 public static function init() {
53
54 if ( ! is_object( self::$instance ) ) {
55 self::$instance = new self();
56 }
57
58 return self::$instance;
59 }
60
61 /**
62 * Master handler for all field / form methods
63 *
64 * @return \PodsForm
65 *
66 * @license http://www.gnu.org/licenses/gpl-2.0.html
67 * @since 2.0.0
68 */
69 private function __construct() {
70
71 add_action( 'admin_init', array( $this, 'admin_init' ), 14 );
72 }
73
74 /**
75 * Prevent clones
76 *
77 * @since 2.3.0
78 */
79 private function __clone() {
80 // Hulk smash
81 }
82
83 /**
84 * Output a field's label
85 *
86 * @since 2.0.0
87 */
88
89 /**
90 * Output a field's label
91 *
92 * @param string $name Field name
93 * @param string $label Label text
94 * @param string $help Help text
95 * @param array $options Field options
96 *
97 * @return string Label HTML
98 *
99 * @since 2.0.0
100 */
101 public static function label( $name, $label, $help = '', $options = null ) {
102
103 if ( is_array( $label ) || is_object( $label ) ) {
104 $options = $label;
105 $label = $options['label'];
106
107 if ( empty( $label ) ) {
108 $label = ucwords( str_replace( '_', ' ', $name ) );
109 }
110
111 $help = $options['help'];
112 } else {
113 $options = self::options( null, $options );
114 }
115
116 $label = apply_filters( 'pods_form_ui_label_text', $label, $name, $help, $options );
117 $help = apply_filters( 'pods_form_ui_label_help', $help, $name, $label, $options );
118
119 ob_start();
120
121 $name_clean = self::clean( $name );
122 $name_more_clean = self::clean( $name, true );
123
124 $type = 'label';
125 $attributes = array();
126 $attributes['class'] = 'pods-form-ui-' . $type . ' pods-form-ui-' . $type . '-' . $name_more_clean;
127 $attributes['for'] = ( false === strpos( $name_clean, 'pods-form-ui-' ) ? 'pods-form-ui-' : '' ) . $name_clean;
128 $attributes = self::merge_attributes( $attributes, $name, $type, $options, false );
129
130 pods_view( PODS_DIR . 'ui/fields/_label.php', compact( array_keys( get_defined_vars() ) ) );
131
132 $output = ob_get_clean();
133
134 return apply_filters( "pods_form_ui_{$type}", $output, $name, $label, $help, $attributes, $options );
135 }
136
137 /**
138 * Output a Field Comment Paragraph
139 *
140 * @param string $name Field name
141 * @param string $message Field comments
142 * @param array $options Field options
143 *
144 * @return string Comment HTML
145 *
146 * @since 2.0.0
147 */
148 public static function comment( $name, $message = null, $options = null ) {
149
150 $options = self::options( null, $options );
151
152 $name_more_clean = self::clean( $name, true );
153
154 if ( ! empty( $options['description'] ) ) {
155 $message = $options['description'];
156 } elseif ( empty( $message ) ) {
157 return '';
158 }
159
160 $message = apply_filters( 'pods_form_ui_comment_text', $message, $name, $options );
161
162 ob_start();
163
164 $type = 'comment';
165 $attributes = array();
166 $attributes['class'] = 'description pods-form-ui-' . $type . ' pods-form-ui-' . $type . '-' . $name_more_clean;
167 $attributes = self::merge_attributes( $attributes, $name, $type, $options, false );
168
169 pods_view( PODS_DIR . 'ui/fields/_comment.php', compact( array_keys( get_defined_vars() ) ) );
170
171 $output = ob_get_clean();
172
173 return apply_filters( "pods_form_ui_{$type}", $output, $name, $message, $attributes, $options );
174 }
175
176 /**
177 * Output a field
178 *
179 * @param string $name Field name
180 * @param mixed $value Field value
181 * @param string $type Field type
182 * @param array $options Field options
183 * @param array|Pods $pod Pod data or the Pods object.
184 * @param int $id Item ID
185 *
186 * @return string Field HTML
187 *
188 * @since 2.0.0
189 */
190 public static function field( $name, $value, $type = 'text', $options = null, $pod = null, $id = null ) {
191 // Take a field array
192 if ( is_array( $name ) || is_object( $name ) ) {
193 $options = $name;
194
195 if ( is_object( $type ) ) {
196 $pod = $type;
197 $id = $options;
198 }
199
200 $name = pods_v( 'name', $options );
201 $type = pods_v( 'type', $options );
202 }
203
204 $options = self::options( $type, $options );
205 $options = apply_filters( "pods_form_ui_field_{$type}_options", $options, $value, $name, $pod, $id );
206
207 if ( empty( $options['type'] ) ) {
208 $options['type'] = $type;
209 }
210
211 if ( null === $value || ( '' === $value && 'boolean' === $type ) || ( ! empty( $pod ) && empty( $id ) ) ) {
212 $value = self::default_value( $value, $type, $name, $options, $pod, $id );
213 }
214
215 // Fix double help qtip when using single checkboxes (boolean type)
216 if ( 'boolean' === $type ) {
217 $options['help'] = '';
218 }
219
220 if ( false === self::permission( $type, $name, $options, null, $pod, $id ) ) {
221 return false;
222 }
223
224 $value = apply_filters( "pods_form_ui_field_{$type}_value", $value, $name, $options, $pod, $id );
225 $form_field_type = self::$field_type;
226
227 $helper = false;
228
229 $input_helper = pods_v( 'input_helper', $options );
230
231 /**
232 * Input helpers are deprecated and not guaranteed to work properly.
233 *
234 * They will be entirely removed in Pods 3.0.
235 *
236 * @deprecated 2.7.0
237 */
238 if ( is_string( $input_helper ) && 0 < strlen( $input_helper ) ) {
239 $helper = pods_api()->load_helper( array( 'name' => $input_helper ) );
240 }
241
242 if ( empty( $type ) ) {
243 return;
244 }
245
246 // @todo Move into DFV field method or Pods\Whatsit later
247 if ( ( ! isset( $options['data'] ) || empty( $options['data'] ) ) && is_object( self::$loaded[ $type ] ) && method_exists( self::$loaded[ $type ], 'data' ) ) {
248 $options['data'] = self::$loaded[ $type ]->data( $name, $value, $options, $pod, $id, true );
249 $data = $options['data'];
250 }
251
252 $repeatable_field_types = self::repeatable_field_types();
253
254 // Start field render.
255 ob_start();
256
257 /**
258 * pods_form_ui_field_{$type}_override filter leaves too much to be done by developer.
259 *
260 * It will be replaced in Pods 3.0 with better documentation.
261 *
262 * @deprecated 2.7.0
263 */
264 if ( true === apply_filters( "pods_form_ui_field_{$type}_override", false, $name, $value, $options, $pod, $id ) ) {
265 /**
266 * pods_form_ui_field_{$type} action leaves too much to be done by developer.
267 *
268 * It will be replaced in Pods 3.0 with better documentation.
269 *
270 * @deprecated 2.7.0
271 */
272 do_action( "pods_form_ui_field_{$type}", $name, $value, $options, $pod, $id );
273 } elseif ( ! empty( $helper ) && 0 < strlen( (string) pods_v( 'code', $helper ) ) && false === strpos( $helper['code'], '$this->' ) && ( ! defined( 'PODS_DISABLE_EVAL' ) || ! PODS_DISABLE_EVAL ) ) {
274 /**
275 * Input helpers are deprecated and not guaranteed to work properly.
276 *
277 * They will be entirely removed in Pods 3.0.
278 *
279 * @deprecated 2.7.0
280 */
281 eval( '?>' . $helper['code'] );
282 } elseif ( method_exists( get_class(), 'field_' . $type ) ) {
283 // @todo Move these custom field methods into real/faux field classes
284 echo call_user_func( array( get_class(), 'field_' . $type ), $name, $value, $options );
285 } elseif ( is_object( self::$loaded[ $type ] ) && method_exists( self::$loaded[ $type ], 'input' ) ) {
286 // Force non-repeatable field types to be non-repeatable even if option is set to 1.
287 if ( ! empty( $options['repeatable'] ) && ! in_array( $type, $repeatable_field_types, true ) ) {
288 $options['repeatable'] = 0;
289 }
290
291 self::$loaded[ $type ]->input( $name, $value, $options, $pod, $id );
292 } else {
293 /**
294 * pods_form_ui_field_{$type} action leaves too much to be done by developer.
295 *
296 * It will be replaced in Pods 3.0 with better documentation.
297 *
298 * @deprecated 2.7.0
299 */
300 do_action( "pods_form_ui_field_{$type}", $name, $value, $options, $pod, $id );
301 }//end if
302
303 $output = ob_get_clean();
304
305 /**
306 * pods_form_ui_field_{$type} filter will remain supported.
307 *
308 * It is not intended for replacing but augmenting input markup.
309 */
310 return apply_filters( "pods_form_ui_field_{$type}", $output, $name, $value, $options, $pod, $id );
311 }
312
313 /**
314 * Output field type 'db'
315 *
316 * Used for field names and other places where only [a-z0-9_] is accepted
317 *
318 * @since 2.0.0
319 *
320 * @param $name
321 * @param null $value
322 * @param null $options
323 *
324 * @return mixed|void
325 */
326 protected static function field_db( $name, $value = null, $options = null ) {
327
328 $form_field_type = self::$field_type;
329
330 ob_start();
331
332 pods_view( PODS_DIR . 'ui/fields/_db.php', compact( array_keys( get_defined_vars() ) ) );
333
334 $output = ob_get_clean();
335
336 return apply_filters( 'pods_form_ui_field_db', $output, $name, $value, $options );
337 }
338
339 /**
340 * Output a hidden field
341 *
342 * @param $name
343 * @param null $value
344 * @param null $options
345 *
346 * @return mixed|void
347 */
348 protected static function field_hidden( $name, $value = null, $options = null ) {
349
350 $form_field_type = self::$field_type;
351
352 ob_start();
353
354 pods_view( PODS_DIR . 'ui/fields/_hidden.php', compact( array_keys( get_defined_vars() ) ) );
355
356 $output = ob_get_clean();
357
358 return apply_filters( 'pods_form_ui_field_hidden', $output, $name, $value, $options );
359 }
360
361 /**
362 * Returns a submit button, with provided text and appropriate class, copied from WP Core for use on the frontend
363 *
364 * @see get_submit_button
365 *
366 * @param string $text The text of the button (defaults to 'Save Changes')
367 * @param string $type The type of button. One of: primary, secondary, delete
368 * @param string $name The HTML name of the submit button. Defaults to "submit". If no id
369 * attribute is given in $other_attributes below, $name will be used as the
370 * button's id.
371 * @param bool $wrap True if the output button should be wrapped in a paragraph tag,
372 * false otherwise. Defaults to true
373 * @param array|string $other_attributes Other attributes that should be output with the button,
374 * mapping attributes to their values, such as array( 'tabindex' => '1' ).
375 * These attributes will be output as attribute="value", such as
376 * tabindex="1".
377 * Defaults to no other attributes. Other attributes can also be provided as
378 * a
379 * string such as 'tabindex="1"', though the array format is typically
380 * cleaner.
381 *
382 * @since 2.7.0
383 * @return string
384 */
385 public static function submit_button( $text = null, $type = 'primary large', $name = 'submit', $wrap = true, $other_attributes = null ) {
386
387 if ( function_exists( 'get_submit_button' ) ) {
388 return get_submit_button( $text, $type, $name, $wrap, $other_attributes );
389 }
390
391 if ( ! is_array( $type ) ) {
392 $type = explode( ' ', $type );
393 }
394
395 $button_shorthand = array(
396 'primary',
397 'small',
398 'large',
399 );
400
401 $classes = array(
402 'button',
403 );
404
405 foreach ( $type as $t ) {
406 if ( 'secondary' === $t || 'button-secondary' === $t ) {
407 continue;
408 }
409
410 $classes[] = in_array( $t, $button_shorthand ) ? 'button-' . $t : $t;
411 }
412
413 $class = implode( ' ', array_unique( $classes ) );
414
415 if ( 'delete' === $type ) {
416 $class = 'button-secondary delete';
417 }
418
419 $text = $text ? $text : __( 'Save Changes' );
420
421 // Default the id attribute to $name unless an id was specifically provided in $other_attributes
422 $id = $name;
423
424 if ( is_array( $other_attributes ) && isset( $other_attributes['id'] ) ) {
425 $id = $other_attributes['id'];
426 unset( $other_attributes['id'] );
427 }
428
429 $attributes = '';
430
431 if ( is_array( $other_attributes ) ) {
432 foreach ( $other_attributes as $attribute => $value ) {
433 $attributes .= $attribute . '="' . esc_attr( $value ) . '" ';
434 // Trailing space is important
435 }
436 } elseif ( ! empty( $other_attributes ) ) {
437 // Attributes provided as a string
438 $attributes = $other_attributes;
439 }
440
441 $button = '<input type="submit" name="' . esc_attr( $name ) . '" id="' . esc_attr( $id ) . '" class="' . esc_attr( $class );
442 $button .= '" value="' . esc_attr( $text ) . '" ' . $attributes . ' />';
443
444 if ( $wrap ) {
445 $button = '<p class="submit">' . $button . '</p>';
446 }
447
448 return $button;
449
450 }
451
452 /**
453 * Output a row (label, field, and comment)
454 *
455 * @param string $name Field name
456 * @param mixed $value Field value
457 * @param string $type Field type
458 * @param array $options Field options
459 * @param array $pod Pod data
460 * @param int $id Item ID
461 *
462 * @return string Row HTML
463 *
464 * @since 2.0.0
465 */
466 public static function row( $name, $value, $type = 'text', $options = null, $pod = null, $id = null ) {
467
468 $options = self::options( null, $options );
469
470 ob_start();
471
472 pods_view( PODS_DIR . 'ui/fields/_row.php', compact( array_keys( get_defined_vars() ) ) );
473
474 $output = ob_get_clean();
475
476 return apply_filters( 'pods_form_ui_field_row', $output, $name, $value, $options, $pod, $id );
477 }
478
479 /**
480 * Output a field's attributes
481 *
482 * @since 2.0.0
483 *
484 * @param $attributes
485 * @param null $name
486 * @param null $type
487 * @param null $options
488 */
489 public static function attributes( $attributes, $name = null, $type = null, $options = null ) {
490
491 $attributes = (array) apply_filters( "pods_form_ui_field_{$type}_attributes", $attributes, $name, $options );
492
493 foreach ( $attributes as $attribute => $value ) {
494 if ( null === $value ) {
495 continue;
496 }
497
498 echo ' ' . esc_attr( (string) $attribute ) . '="' . esc_attr( (string) $value ) . '"';
499 }
500 }
501
502 /**
503 * Output a field's data (for use with jQuery)
504 *
505 * @since 2.0.0
506 *
507 * @param $data
508 * @param null $name
509 * @param null $type
510 * @param null $options
511 */
512 public static function data( $data, $name = null, $type = null, $options = null ) {
513
514 $data = (array) apply_filters( "pods_form_ui_field_{$type}_data", $data, $name, $options );
515
516 foreach ( $data as $key => $value ) {
517 if ( null === $value ) {
518 continue;
519 }
520
521 $key = sanitize_title( $key );
522
523 if ( is_array( $value ) ) {
524 $value = implode( ',', $value );
525 }
526
527 echo ' data-' . esc_attr( (string) $key ) . '="' . esc_attr( (string) $value ) . '"';
528 }
529 }
530
531 /**
532 * Merge attributes and handle classes
533 *
534 * @since 2.0.0
535 *
536 * @param $attributes
537 * @param null $name
538 * @param null $type
539 * @param null $options
540 * @param string $classes
541 *
542 * @return array
543 */
544 public static function merge_attributes( $attributes, $name = null, $type = null, $options = null, $classes = '' ) {
545
546 $options = (array) $options;
547
548 if ( ! in_array( $type, array( 'label', 'comment' ) ) ) {
549 $name_clean = self::clean( $name );
550 $name_more_clean = self::clean( $name, true );
551 $_attributes = array();
552 $_attributes['name'] = $name;
553 $_attributes['data-name-clean'] = $name_more_clean;
554
555 if ( 0 < strlen( (string) pods_v( 'label', $options, '' ) ) ) {
556 $_attributes['data-label'] = strip_tags( pods_v( 'label', $options ) );
557 }
558
559 $_attributes['id'] = 'pods-form-ui-' . $name_clean . ( self::$form_counter > 1 ? '-' . self::$form_counter : '' );
560 $_attributes['class'] = 'pods-form-ui-field pods-form-ui-field-type-' . $type . ' pods-form-ui-field-name-' . $name_more_clean;
561
562 if ( isset( $options['dependency'] ) && false !== $options['dependency'] ) {
563 $_attributes['class'] .= ' pods-dependent-toggle';
564 }
565
566 $attributes = array_merge( $_attributes, (array) $attributes );
567
568 if ( isset( $options['attributes'] ) && is_array( $options['attributes'] ) && ! empty( $options['attributes'] ) ) {
569 $attributes = array_merge( $attributes, $options['attributes'] );
570 }
571 } elseif ( isset( $options[ $type . '_attributes' ] ) && is_array( $options[ $type . '_attributes' ] ) && ! empty( $options[ $type . '_attributes' ] ) ) {
572 $attributes = array_merge( $attributes, $options[ $type . '_attributes' ] );
573 }//end if
574
575 if ( isset( $options['class'] ) && ! empty( $options['class'] ) ) {
576 if ( is_array( $options['class'] ) ) {
577 $options['class'] = implode( ' ', $options['class'] );
578 }
579
580 $options['class'] = (string) $options['class'];
581 if ( isset( $attributes['class'] ) ) {
582 $attributes['class'] = $attributes['class'] . ' ' . $options['class'];
583 } else {
584 $attributes['class'] = $options['class'];
585 }
586
587 $attributes['class'] = trim( $attributes['class'] );
588 }
589
590 if ( ! empty( $classes ) ) {
591 if ( isset( $attributes['class'] ) ) {
592 $attributes['class'] = $attributes['class'] . ' ' . $classes;
593 } else {
594 $attributes['class'] = $classes;
595 }
596 }
597
598 $placeholder = trim( (string) pods_v( 'placeholder', $options, pods_v( $type . '_placeholder', $options ) ) );
599
600 if ( ! empty( $placeholder ) ) {
601 $attributes['placeholder'] = $placeholder;
602 }
603
604 if ( 1 === (int) pods_v( 'required', $options, 0 ) ) {
605 $attributes['class'] .= ' pods-validate pods-validate-required';
606 }
607
608 $max_length = (int) pods_v( 'maxlength', $options, pods_v( $type . '_max_length', $options, 0 ) );
609
610 if ( 0 < $max_length ) {
611 $attributes['maxlength'] = $max_length;
612 }
613
614 $attributes = (array) apply_filters( "pods_form_ui_field_{$type}_merge_attributes", $attributes, $name, $options );
615
616 return $attributes;
617 }
618
619 /**
620 * Setup options for a field and store them for later use
621 *
622 * @param $type
623 * @param $options
624 *
625 * @return array
626 *
627 * @static
628 *
629 * @since 2.0.0
630 */
631 public static function options( $type, $options ) {
632 if ( is_object( $options ) ) {
633 $options_array = $options->get_args();
634 $options_array['_field_object'] = $options;
635 } else {
636 $options_array = (array) $options;
637 $options_array['_field_object'] = null;
638 }
639
640 $defaults = self::options_setup( $type );
641
642 $core_defaults = [
643 'id' => 0,
644 'label' => '',
645 'description' => '',
646 'help' => '',
647 'default' => null,
648 'attributes' => [],
649 'class' => '',
650 'grouped' => 0,
651 ];
652
653 $defaults = array_merge( $core_defaults, $defaults );
654
655 foreach ( $defaults as $option => $settings ) {
656 $default = $core_defaults['default'];
657
658 if ( ! is_array( $settings ) ) {
659 $default = $settings;
660 } elseif ( isset( $settings['default'] ) ) {
661 $default = $settings['default'];
662 }
663
664 if ( ! isset( $options_array[ $option ] ) ) {
665 $options_array[ $option ] = $default;
666 }
667 }
668
669 return $options_array;
670 }
671
672 /**
673 * Get options for a field type and setup defaults
674 *
675 * @static
676 *
677 * @param $type
678 *
679 * @param null $options
680 *
681 * @return array|null
682 * @since 2.0.0
683 */
684 public static function options_setup( $type = null, $options = null ) {
685
686 $core_defaults = array(
687 'id' => 0,
688 'name' => '',
689 'label' => '',
690 'description' => '',
691 'help' => '',
692 'default' => null,
693 'attributes' => array(),
694 'class' => '',
695 'type' => 'text',
696 'group' => 0,
697 'grouped' => 0,
698 'developer_mode' => false,
699 'dependency' => false,
700 'depends-on' => array(),
701 'depends-on-any' => array(),
702 'excludes-on' => array(),
703 'wildcard-on' => array(),
704 'options' => array(),
705 );
706
707 if ( ! empty( $options ) && is_array( $options ) ) {
708 $core_defaults = array_merge( $core_defaults, $options );
709 }
710
711 if ( null === $type ) {
712 return $core_defaults;
713 } else {
714 self::field_loader( $type );
715 }
716
717 $ui_options = apply_filters( "pods_field_{$type}_options", (array) self::$loaded[ $type ]->options(), $type );
718
719 $first_field = reset( $ui_options );
720
721 if ( ! empty( $ui_options ) && ! isset( $first_field['name'] ) && ! isset( $first_field['label'] ) ) {
722 foreach ( $ui_options as $group => $group_options ) {
723 $ui_options[ $group ] = self::fields_setup( $group_options, $core_defaults );
724 }
725
726 return $ui_options;
727 }
728
729 return self::fields_setup( $ui_options, $core_defaults );
730 }
731
732 /**
733 * Get Admin options for a field type and setup defaults
734 *
735 * @static
736 *
737 * @param $type
738 *
739 * @return array|null
740 *
741 * @since 2.0.0
742 */
743 public static function ui_options( $type ) {
744
745 $core_defaults = array(
746 'id' => 0,
747 'name' => '',
748 'label' => '',
749 'description' => '',
750 'help' => '',
751 'default' => null,
752 'attributes' => array(),
753 'class' => '',
754 'type' => 'text',
755 'group' => 0,
756 'grouped' => 0,
757 'developer_mode' => false,
758 'dependency' => false,
759 'depends-on' => array(),
760 'depends-on-any' => array(),
761 'excludes-on' => array(),
762 'wildcard-on' => array(),
763 'options' => array(),
764 );
765
766 self::field_loader( $type );
767
768 $ui_options = apply_filters( "pods_field_{$type}_ui_options", (array) self::$loaded[ $type ]->ui_options(), $type );
769
770 $first_field = reset( $ui_options );
771
772 if ( ! empty( $ui_options ) && ! isset( $first_field['name'] ) && ! isset( $first_field['label'] ) ) {
773 foreach ( $ui_options as $group => $group_options ) {
774 $ui_options[ $group ] = self::fields_setup( $group_options, $core_defaults );
775 }
776
777 return $ui_options;
778 }
779
780 return self::fields_setup( $ui_options, $core_defaults );
781 }
782
783 /**
784 * Get options for a field and setup defaults
785 *
786 * @param null $fields
787 * @param null $core_defaults
788 * @param bool $single
789 *
790 * @return array|null
791 *
792 * @static
793 * @since 2.0.0
794 */
795 public static function fields_setup( $fields = null, $core_defaults = null, $single = false ) {
796
797 if ( empty( $core_defaults ) ) {
798 $core_defaults = array(
799 'id' => 0,
800 'name' => '',
801 'label' => '',
802 'description' => '',
803 'help' => '',
804 'default' => null,
805 'attributes' => array(),
806 'class' => '',
807 'type' => 'text',
808 'group' => 0,
809 'grouped' => 0,
810 'developer_mode' => false,
811 'dependency' => false,
812 'depends-on' => array(),
813 'depends-on-any' => array(),
814 'excludes-on' => array(),
815 'wildcard-on' => array(),
816 'options' => array(),
817 );
818 }
819
820 if ( $single ) {
821 $fields = array( $fields );
822 }
823
824 foreach ( $fields as $f => $field ) {
825 if ( ! $single && empty( $field['name'] ) ) {
826 $field['name'] = $f;
827 }
828
829 $fields[ $f ] = self::field_setup( $field, $core_defaults, pods_v( 'type', $field, 'text' ) );
830 }
831
832 if ( $single ) {
833 $fields = $fields[0];
834 }
835
836 return $fields;
837 }
838
839 /**
840 * Get options for a field and setup defaults
841 *
842 * @static
843 *
844 * @param null|array|string|Field $field
845 * @param null|array $core_defaults
846 * @param null|string $type
847 *
848 * @return array|null
849 *
850 * @since 2.0.0
851 */
852 public static function field_setup( $field = null, $core_defaults = null, $type = null ) {
853
854 $ui_options = array();
855
856 if ( empty( $core_defaults ) ) {
857 $core_defaults = array(
858 'id' => 0,
859 'name' => '',
860 'label' => '',
861 'description' => '',
862 'help' => '',
863 'default' => null,
864 'attributes' => array(),
865 'class' => '',
866 'type' => 'text',
867 'group' => 0,
868 'grouped' => 0,
869 'developer_mode' => false,
870 'dependency' => false,
871 'depends-on' => array(),
872 'depends-on-any' => array(),
873 'excludes-on' => array(),
874 'wildcard-on' => array(),
875 'options' => array(),
876 );
877
878 if ( null !== $type ) {
879 self::field_loader( $type );
880
881 if ( method_exists( self::$loaded[ $type ], 'options' ) ) {
882 $ui_options = apply_filters( "pods_field_{$type}_options", (array) self::$loaded[ $type ]->options(), $type );
883 }
884 }
885 }//end if
886
887 $is_field_object = $field instanceof Field;
888
889 if ( ! is_array( $field ) && ! $is_field_object ) {
890 $field = [
891 'default' => $field,
892 ];
893 }
894
895 // @todo Revisit this.
896 if ( isset( $field['group'] ) && is_array( $field['group'] ) ) {
897 $group = $field['group'];
898
899 foreach ( $group as $g => $group_option ) {
900 $group[ $g ] = array_merge( $core_defaults, $group_option );
901
902 if ( ! isset( $group[ $g ] ) || '' === $group[ $g ]['name'] ) {
903 $group[ $g ]['name'] = $g;
904 }
905 }
906
907 $field['group'] = $group;
908 }
909
910 $field = pods_config_merge_data( $core_defaults, $field );
911
912 foreach ( $ui_options as $option => $settings ) {
913 if ( ! is_string( $option ) ) {
914 $option = $settings['name'];
915 }
916
917 $default = null;
918
919 if ( isset( $settings['default'] ) ) {
920 $default = $settings['default'];
921 }
922
923 if ( $is_field_object ) {
924 $option_value = $field->get_arg( $option );
925
926 if ( null === $option_value ) {
927 $field->set_arg( $option, $default );
928 }
929 } elseif ( ! isset( $field['options'][ $option ] ) ) {
930 $field['options'][ $option ] = $default;
931 }
932 }
933
934 return $field;
935 }
936
937 /**
938 * Setup dependency / exclusion classes
939 *
940 * @param array $options array( 'depends-on' => ..., 'excludes-on' => ...)
941 * @param string $prefix
942 *
943 * @return array
944 * @static
945 * @since 2.0.0
946 */
947 public static function dependencies( $options, $prefix = 'pods-form-ui-' ) {
948 $options = (array) $options;
949 $classes = [];
950 $data = [];
951
952 $dependency_checks = [
953 'depends-on',
954 'depends-on-any',
955 'excludes-on',
956 ];
957
958 foreach ( $dependency_checks as $dependency_check ) {
959 if ( ! isset( $options[ $dependency_check ] ) ) {
960 continue;
961 }
962
963 $dependency_list = (array) $options[ $dependency_check ];
964
965 if ( ! empty( $dependency_list ) ) {
966 $classes[] = 'pods-' . $dependency_check;
967
968 foreach ( $dependency_list as $depends => $on ) {
969 $classes[] = 'pods-' . $dependency_check . '-' . $prefix . self::clean( $depends, true );
970
971 if ( ! is_bool( $on ) ) {
972 $on = (array) $on;
973
974 foreach ( $on as $o ) {
975 $classes[] = 'pods-' . $dependency_check . '-' . $prefix . self::clean( $depends, true ) . '-' . self::clean( $o, true );
976 }
977 }
978 }
979 }
980 }
981
982 if ( isset( $options['wildcard-on'] ) ) {
983 $wildcard_on = (array) $options['wildcard-on'];
984
985 if ( ! empty( $wildcard_on ) ) {
986 $classes[] = 'pods-wildcard-on';
987
988 // Add the appropriate classes and data attribs per value dependency
989 foreach ( $wildcard_on as $target => $wildcards ) {
990 $target = $prefix . self::clean( $target, true );
991 $classes[] = 'pods-wildcard-on-' . $target;
992 $data[ 'pods-wildcard-' . $target ] = $wildcards;
993 }
994 }
995 }
996
997 $classes = implode( ' ', $classes );
998
999 return array(
1000 'classes' => $classes,
1001 'data' => $data,
1002 );
1003 }
1004
1005 /**
1006 * Change the value of the field
1007 *
1008 * @param $type
1009 * @param mixed $value
1010 * @param string $name
1011 * @param array $options
1012 * @param array $pod
1013 * @param int $id
1014 * @param array $traverse
1015 *
1016 * @return array|mixed|null|object
1017 * @internal param array $fields
1018 * @since 2.3.0
1019 */
1020 public static function value( $type, $value = null, $name = null, $options = null, $pod = null, $id = null, $traverse = null ) {
1021
1022 self::field_loader( $type );
1023
1024 $is_repeatable_field = (
1025 (
1026 (
1027 $options instanceof Field
1028 || $options instanceof Value_Field
1029 )
1030 && $options->is_repeatable()
1031 )
1032 || (
1033 is_array( $options )
1034 && in_array( $type, self::repeatable_field_types(), true )
1035 && 1 === (int) pods_v( 'repeatable', $options )
1036 && (
1037 'wysiwyg' !== $type
1038 || 'tinymce' !== pods_v( 'wysiwyg_editor', $options, 'tinymce', true )
1039 )
1040 )
1041 );
1042
1043 if ( $is_repeatable_field && ! is_array( $value ) ) {
1044 if ( is_string( $value ) && 0 < strlen( $value ) ) {
1045 $simple = @json_decode( $value, true );
1046
1047 if ( is_array( $simple ) ) {
1048 $value = $simple;
1049 } else {
1050 $value = (array) $value;
1051 }
1052 } else {
1053 $value = [];
1054 }
1055 }
1056
1057 if ( is_array( $value ) && in_array( $type, self::tableless_field_types(), true ) ) {
1058 foreach ( $value as &$display_value ) {
1059 $display_value = call_user_func( array(
1060 self::$loaded[ $type ],
1061 'value',
1062 ), $display_value, $name, $options, $pod, $id, $traverse );
1063 }
1064 } else {
1065 $value = call_user_func( array(
1066 self::$loaded[ $type ],
1067 'value',
1068 ), $value, $name, $options, $pod, $id, $traverse );
1069 }//end if
1070
1071 return $value;
1072 }
1073
1074 /**
1075 * Change the way the value of the field is displayed with Pods::get
1076 *
1077 * @param $type
1078 * @param mixed $value
1079 * @param string $name
1080 * @param array $options
1081 * @param array $pod
1082 * @param int $id
1083 * @param array $traverse
1084 *
1085 * @return array|mixed|null|void
1086 * @internal param array $fields
1087 * @since 2.0.0
1088 */
1089 public static function display( $type, $value = null, $name = null, $options = null, $pod = null, $id = null, $traverse = null ) {
1090
1091 self::field_loader( $type );
1092
1093 $tableless_field_types = self::tableless_field_types();
1094
1095 if ( method_exists( self::$loaded[ $type ], 'display_list' ) ) {
1096 $value = call_user_func_array(
1097 array( self::$loaded[ $type ], 'display_list' ), array(
1098 $value,
1099 $name,
1100 $options,
1101 $pod,
1102 $id,
1103 $traverse,
1104 )
1105 );
1106 } elseif ( method_exists( self::$loaded[ $type ], 'display' ) ) {
1107 if ( is_array( $value ) && ! in_array( $type, $tableless_field_types ) ) {
1108 foreach ( $value as $k => $display_value ) {
1109 $value[ $k ] = call_user_func_array(
1110 array( self::$loaded[ $type ], 'display' ), array(
1111 $display_value,
1112 $name,
1113 $options,
1114 $pod,
1115 $id,
1116 $traverse,
1117 )
1118 );
1119 }
1120 } else {
1121 $value = call_user_func_array(
1122 array( self::$loaded[ $type ], 'display' ), array(
1123 $value,
1124 $name,
1125 $options,
1126 $pod,
1127 $id,
1128 $traverse,
1129 )
1130 );
1131 }//end if
1132 }//end if
1133
1134 $value = apply_filters( "pods_form_display_{$type}", $value, $name, $options, $pod, $id, $traverse );
1135
1136 return $value;
1137 }
1138
1139 /**
1140 * Setup regex for JS / PHP
1141 *
1142 * @static
1143 *
1144 * @param $type
1145 * @param $options
1146 *
1147 * @return mixed|void
1148 * @since 2.0.0
1149 */
1150 public static function regex( $type, $options ) {
1151
1152 self::field_loader( $type );
1153
1154 $regex = false;
1155
1156 if ( method_exists( self::$loaded[ $type ], 'regex' ) ) {
1157 $regex = self::$loaded[ $type ]->regex( $options );
1158 }
1159
1160 $regex = apply_filters( "pods_field_{$type}_regex", $regex, $options, $type );
1161
1162 return $regex;
1163 }
1164
1165 /**
1166 * Setup value preparation for sprintf
1167 *
1168 * @static
1169 *
1170 * @param $type
1171 * @param $options
1172 *
1173 * @return mixed|void
1174 * @since 2.0.0
1175 */
1176 public static function prepare( $type, $options ) {
1177
1178 self::field_loader( $type );
1179
1180 $prepare = '%s';
1181
1182 if ( method_exists( self::$loaded[ $type ], 'prepare' ) ) {
1183 $prepare = self::$loaded[ $type ]->prepare( $options );
1184 }
1185
1186 $prepare = apply_filters( "pods_field_{$type}_prepare", $prepare, $options, $type );
1187
1188 return $prepare;
1189 }
1190
1191 /**
1192 * Validate a value before it's saved
1193 *
1194 * @param string $type
1195 * @param mixed $value
1196 * @param string $name
1197 * @param array $options
1198 * @param array $fields
1199 * @param array $pod
1200 * @param int $id
1201 * @param array|object $params
1202 *
1203 * @static
1204 *
1205 * @since 2.0.0
1206 * @return bool|mixed|void
1207 */
1208 public static function validate( $type, $value, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
1209
1210 self::field_loader( $type );
1211
1212 $validate = true;
1213
1214 if ( 1 == pods_v( 'pre_save', $options, 1 ) && method_exists( self::$loaded[ $type ], 'validate' ) ) {
1215 $validate = self::$loaded[ $type ]->validate( $value, $name, $options, $fields, $pod, $id, $params );
1216 }
1217
1218 $validate = apply_filters( "pods_field_{$type}_validate", $validate, $value, $name, $options, $fields, $pod, $id, $type, $params );
1219
1220 return $validate;
1221 }
1222
1223 /**
1224 * Change the value or perform actions after validation but before saving to the DB
1225 *
1226 * @param string $type
1227 * @param mixed $value
1228 * @param int $id
1229 * @param string $name
1230 * @param array $options
1231 * @param array $fields
1232 * @param array $pod
1233 * @param object $params
1234 *
1235 * @static
1236 *
1237 * @since 2.0.0
1238 * @return mixed
1239 */
1240 public static function pre_save( $type, $value, $id = null, $name = null, $options = null, $fields = null, $pod = null, $params = null ) {
1241
1242 self::field_loader( $type );
1243
1244 if ( 1 == pods_v( 'field_pre_save', $options, 1 ) && method_exists( self::$loaded[ $type ], 'pre_save' ) ) {
1245 $value = self::$loaded[ $type ]->pre_save( $value, $id, $name, $options, $fields, $pod, $params );
1246 }
1247
1248 return $value;
1249 }
1250
1251 /**
1252 * Save the value to the DB
1253 *
1254 * @param string $type
1255 * @param mixed $value
1256 * @param int $id
1257 * @param string $name
1258 * @param array $options
1259 * @param array $fields
1260 * @param array $pod
1261 * @param object $params
1262 *
1263 * @static
1264 *
1265 * @since 2.3.0
1266 * @return null
1267 */
1268 public static function save( $type, $value, $id = null, $name = null, $options = null, $fields = null, $pod = null, $params = null ) {
1269
1270 self::field_loader( $type );
1271
1272 $saved = null;
1273
1274 if ( 1 == pods_v( 'field_save', $options, 1 ) && method_exists( self::$loaded[ $type ], 'save' ) ) {
1275 $saved = self::$loaded[ $type ]->save( $value, $id, $name, $options, $fields, $pod, $params );
1276 }
1277
1278 return $saved;
1279 }
1280
1281 /**
1282 * Delete the value from the DB
1283 *
1284 * @param string $type
1285 * @param int $id
1286 * @param string $name
1287 * @param array $options
1288 * @param array $pod
1289 *
1290 * @static
1291 *
1292 * @since 2.3.0
1293 * @return null
1294 */
1295 public static function delete( $type, $id = null, $name = null, $options = null, $pod = null ) {
1296
1297 self::field_loader( $type );
1298
1299 $deleted = null;
1300
1301 if ( 1 == pods_v( 'field_delete', $options, 1 ) && method_exists( self::$loaded[ $type ], 'delete' ) ) {
1302 $deleted = self::$loaded[ $type ]->delete( $id, $name, $options, $pod );
1303 }
1304
1305 return $deleted;
1306 }
1307
1308 /**
1309 * Check if a user has permission to be editing a field
1310 *
1311 * @param $type
1312 * @param null $name
1313 * @param null $options
1314 * @param null $fields
1315 * @param null $pod
1316 * @param null $id
1317 * @param null $params
1318 *
1319 * @static
1320 *
1321 * @since 2.0.0
1322 * @return bool
1323 */
1324 public static function permission( $type, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
1325 $permission = pods_permission( $options );
1326
1327 /**
1328 * @since 2.0.0
1329 * @deprecated 2.8.0
1330 */
1331 return (boolean) apply_filters( 'pods_form_field_permission', $permission, $type, $name, $options, $fields, $pod, $id, $params );
1332 }
1333
1334 /**
1335 * Parse the default the value
1336 *
1337 * @since 2.0.0
1338 *
1339 * @param $value
1340 * @param string $type
1341 * @param null $name
1342 * @param null $options
1343 * @param null $pod
1344 * @param null $id
1345 *
1346 * @return mixed|void
1347 */
1348 public static function default_value( $value, $type = 'text', $name = null, $options = null, $pod = null, $id = null ) {
1349
1350 $default_value = pods_v( 'default_value', $options );
1351
1352 if ( '' === $default_value || null === $default_value ) {
1353 $default_value = $value;
1354 }
1355
1356 $default = pods_v( 'default', $options, $default_value, true );
1357
1358 if ( is_string( $default ) ) {
1359 $default_value = str_replace( array( '{@', '}' ), '', $default );
1360
1361 if ( $default !== $default_value && 1 === (int) pods_v( 'default_evaluate_tags', $options, 1 ) ) {
1362 $default = pods_evaluate_tags( $default );
1363 }
1364 }
1365
1366 $default_value_parameter = pods_v( 'default_value_parameter', $options );
1367
1368 if ( $default_value_parameter ) {
1369 $default_value = pods_v( $default_value_parameter, 'request', $default );
1370
1371 if ( '' !== $default_value ) {
1372 $default = $default_value;
1373 }
1374 }
1375
1376 if ( $default != $value ) {
1377 $value = $default;
1378 }
1379
1380 if ( is_array( $value ) && 'multi' !== pods_v( $type . '_format_type' ) ) {
1381 $value = pods_serial_comma( $value, $name, [ $name => $options ] );
1382 }
1383
1384 return apply_filters( 'pods_form_field_default_value', $value, $default, $type, $options, $pod, $id );
1385 }
1386
1387 /**
1388 * Clean a value for use in class / id
1389 *
1390 * @since 2.0.0
1391 *
1392 * @param $input
1393 * @param bool $noarray
1394 * @param bool $db_field
1395 *
1396 * @return mixed|string
1397 */
1398 public static function clean( $input, $noarray = false, $db_field = false ) {
1399
1400 $output = trim( (string) $input );
1401
1402 $output = str_replace( '--1', 'podsfixtemp1', $output );
1403 $output = str_replace( '__1', 'podsfixtemp2', $output );
1404
1405 if ( false !== $noarray ) {
1406 $output = preg_replace( '/\[podsfixtemp\d+\]/', '-', $output );
1407 $output = preg_replace( '/\[\d*\]/', '-', $output );
1408 }
1409
1410 $output = str_replace( array( '[', ']' ), '-', $output );
1411
1412 $output = pods_clean_name( $output );
1413
1414 $output = preg_replace( '/([^a-z0-9\-_])/', '', $output );
1415 $output = preg_replace( '/(_){2,}/', '_', $output );
1416 $output = preg_replace( '/(-){2,}/', '-', $output );
1417
1418 if ( true !== $db_field ) {
1419 $output = str_replace( '_', '-', $output );
1420 }
1421
1422 $output = rtrim( $output, '-' );
1423
1424 $output = str_replace( 'podsfixtemp1', '--1', $output );
1425 $output = str_replace( 'podsfixtemp2', '__1', $output );
1426
1427 return $output;
1428 }
1429
1430 /**
1431 * Run admin_init methods for each field type
1432 *
1433 * @since 2.3.0
1434 */
1435 public function admin_init() {
1436
1437 $admin_field_types = pods_transient_get( 'pods_form_admin_init_field_types' );
1438
1439 if ( empty( $admin_field_types ) ) {
1440 $admin_field_types = array();
1441
1442 $field_types = self::field_types();
1443
1444 foreach ( $field_types as $field_type => $field_type_data ) {
1445 $has_admin_init = self::field_method( $field_type_data['type'], 'admin_init' );
1446
1447 if ( false !== $has_admin_init ) {
1448 $admin_field_types[] = $field_type;
1449 }
1450 }
1451
1452 pods_transient_set( 'pods_form_admin_init_field_types', $admin_field_types, WEEK_IN_SECONDS );
1453 } else {
1454 foreach ( $admin_field_types as $field_type ) {
1455 self::field_method( $field_type, 'admin_init' );
1456 }
1457 }
1458 }
1459
1460 /**
1461 * Autoload a Field Type's class
1462 *
1463 * @param string $field_type Field Type indentifier
1464 * @param string $file The Field Type class file location
1465 *
1466 * @return string
1467 * @access public
1468 * @static
1469 * @since 2.0.0
1470 */
1471 public static function field_loader( $field_type, $file = '' ) {
1472
1473 if ( isset( self::$loaded[ $field_type ] ) ) {
1474 $class_vars = get_class_vars( get_class( self::$loaded[ $field_type ] ) );
1475 // PHP 5.2.x workaround
1476 self::$field_group = ( isset( $class_vars['group'] ) ? $class_vars['group'] : '' );
1477 self::$field_type = $class_vars['type'];
1478
1479 if ( 'Unknown' !== $class_vars['label'] ) {
1480 return self::$loaded[ $field_type ];
1481 }
1482 }
1483
1484 $field_type = self::clean( $field_type, true, true );
1485
1486 $class_name = ucfirst( $field_type );
1487 $class_name = "PodsField_{$class_name}";
1488
1489 if ( ! class_exists( $class_name ) ) {
1490 if ( isset( self::$field_types[ $field_type ] ) && ! empty( self::$field_types[ $field_type ]['file'] ) ) {
1491 $file = realpath( self::$field_types[ $field_type ]['file'] );
1492 }
1493
1494 /**
1495 * The field type include path.
1496 *
1497 * @since unknown
1498 *
1499 * @param string $file The file path to include for the field type.
1500 */
1501 $file = apply_filters( 'pods_form_field_include', $file, $field_type );
1502
1503 $file = trim( $file );
1504
1505 if ( '' !== $file ) {
1506 $located = pods_validate_safe_path( $file, 'all' );
1507
1508 if ( $located ) {
1509 include_once $located;
1510 }
1511 }
1512 }
1513
1514 if ( class_exists( $class_name ) ) {
1515 $class = new $class_name();
1516 } else {
1517 $class = new PodsField();
1518 $class_name = 'PodsField';
1519 }
1520
1521 $class_vars = get_class_vars( $class_name );
1522
1523 // PHP 5.2.x workaround
1524 self::$field_group = ( isset( $class_vars['group'] ) ? $class_vars['group'] : '' );
1525 self::$field_type = $class_vars['type'];
1526
1527 self::$loaded[ $field_type ] =& $class;
1528
1529 return self::$loaded[ $field_type ];
1530 }
1531
1532 /**
1533 * Run a method from a Field Type's class
1534 *
1535 * @return mixed
1536 * @internal param string $field_type Field Type indentifier
1537 * @internal param string $method Method name
1538 * @internal param mixed $arg More arguments
1539 *
1540 * @access public
1541 * @static
1542 * @since 2.0.0
1543 */
1544 public static function field_method() {
1545
1546 $args = func_get_args();
1547
1548 if ( empty( $args ) && count( $args ) < 2 ) {
1549 return false;
1550 }
1551
1552 $field_type = array_shift( $args );
1553 $method = array_shift( $args );
1554
1555 $class = self::field_loader( $field_type );
1556
1557 if ( method_exists( $class, $method ) ) {
1558 return call_user_func_array( array( $class, $method ), $args );
1559 }
1560
1561 return false;
1562 }
1563
1564 /**
1565 * Add a new Pod field type
1566 *
1567 * @param string $type The new field type identifier
1568 * @param string $file The new field type class file location
1569 *
1570 * @return array Field Type data
1571 *
1572 * @since 2.3.0
1573 */
1574 public static function register_field_type( $type, $file = null ) {
1575
1576 $field_type = pods_transient_get( 'pods_field_type_' . $type );
1577
1578 if ( empty( $field_type ) || $field_type['type'] != $type || $field_type['file'] != $file ) {
1579 self::field_loader( $type, $file );
1580
1581 $class_vars = get_class_vars( get_class( self::$loaded[ $type ] ) );
1582 // PHP 5.2.x workaround
1583 self::$field_types[ $type ] = $class_vars;
1584 self::$field_types[ $type ]['file'] = $file;
1585
1586 pods_transient_set( 'pods_field_type_' . $type, self::$field_types[ $type ], WEEK_IN_SECONDS );
1587 } else {
1588 self::$field_types[ $type ] = $field_type;
1589 }
1590
1591 return self::$field_types[ $type ];
1592 }
1593
1594 /**
1595 * Get a list of all available Pod types (no labels).
1596 *
1597 * @return string[] List of Pod types.
1598 *
1599 * @since 2.8.0
1600 * @deprecated 2.9.17 Use pods_api()->get_pod_types() instead.
1601 */
1602 public static function pod_types_list() {
1603 return array_keys( pods_api()->get_pod_types() );
1604 }
1605
1606 /**
1607 * Get a list of all available Field types.
1608 *
1609 * @return string[] List of Field types.
1610 *
1611 * @since 2.8.0
1612 */
1613 public static function field_types_list() {
1614 $field_types = [
1615 'text',
1616 'website',
1617 // 'link',
1618 'phone',
1619 'email',
1620 'password',
1621 'paragraph',
1622 'wysiwyg',
1623 'code',
1624 'datetime',
1625 'date',
1626 'time',
1627 'number',
1628 'currency',
1629 'file',
1630 'avatar',
1631 'oembed',
1632 'pick',
1633 'boolean',
1634 'color',
1635 'slug',
1636 'heading',
1637 'html',
1638 ];
1639
1640 $field_types = array_merge( $field_types, array_keys( self::$field_types ) );
1641
1642 $field_types = array_filter( array_unique( $field_types ) );
1643
1644 return apply_filters( 'pods_api_field_types', $field_types );
1645 }
1646
1647 /**
1648 * Get a list of all available field types and include
1649 *
1650 * @return array Registered Field Types data
1651 *
1652 * @since 2.3.0
1653 */
1654 public static function field_types() {
1655
1656 $types = self::field_types_list();
1657
1658 $field_types = pods_transient_get( 'pods_field_types' );
1659
1660 if ( empty( $field_types ) || count( $types ) != count( $field_types ) ) {
1661 $field_types = array();
1662
1663 foreach ( $types as $field_type ) {
1664 $file = null;
1665
1666 if ( isset( self::$field_types[ $field_type ] ) ) {
1667 $file = self::$field_types[ $field_type ]['file'];
1668 }
1669
1670 self::field_loader( $field_type, $file );
1671
1672 if ( ! isset( self::$loaded[ $field_type ] ) || ! is_object( self::$loaded[ $field_type ] ) ) {
1673 continue;
1674 }
1675
1676 $class_vars = get_class_vars( get_class( self::$loaded[ $field_type ] ) );
1677 // PHP 5.2.x workaround
1678 $field_types[ $field_type ] = $class_vars;
1679 $field_types[ $field_type ]['file'] = $file;
1680 }
1681
1682 self::$field_types = $field_types;
1683
1684 pods_transient_set( 'pods_field_types', self::$field_types, WEEK_IN_SECONDS );
1685 } else {
1686 self::$field_types = array_merge( $field_types, self::$field_types );
1687 }//end if
1688
1689 return self::$field_types;
1690 }
1691
1692 /**
1693 * Get the list of available tableless field types.
1694 *
1695 * @since 2.3.0
1696 *
1697 * @return array The list of available tableless field types.
1698 */
1699 public static function tableless_field_types() {
1700 static $field_types = null;
1701
1702 if ( null === $field_types ) {
1703 $field_types = [
1704 'pick',
1705 'file',
1706 'avatar',
1707 'taxonomy',
1708 'comment',
1709 'author',
1710 ];
1711
1712 $field_types = apply_filters( 'pods_tableless_field_types', $field_types );
1713 }
1714
1715 return $field_types;
1716 }
1717
1718 /**
1719 * Get the list of available file field types.
1720 *
1721 * @since 2.3.0
1722 *
1723 * @return array The list of available file field types.
1724 */
1725 public static function file_field_types() {
1726 static $field_types = null;
1727
1728 if ( null === $field_types ) {
1729 $field_types = [
1730 'file',
1731 'avatar',
1732 ];
1733
1734 $field_types = apply_filters( 'pods_file_field_types', $field_types );
1735 }
1736
1737 return $field_types;
1738 }
1739
1740 /**
1741 * Get the list of available repeatable field types.
1742 *
1743 * @since 2.3.0
1744 *
1745 * @return array The list of available repeatable field types.
1746 */
1747 public static function repeatable_field_types() {
1748 static $field_types = null;
1749
1750 if ( null === $field_types ) {
1751 $field_types = [
1752 'color',
1753 'currency',
1754 'date',
1755 'datetime',
1756 'email',
1757 'number',
1758 'oembed',
1759 'paragraph',
1760 'password',
1761 'phone',
1762 'text',
1763 'time',
1764 'website',
1765 'wysiwyg',
1766 ];
1767
1768 $field_types = (array) apply_filters( 'pods_repeatable_field_types', $field_types );
1769 }
1770
1771 return $field_types;
1772 }
1773
1774 /**
1775 * Get the list of available number field types.
1776 *
1777 * @since 2.3.0
1778 *
1779 * @return array The list of available number field types.
1780 */
1781 public static function number_field_types() {
1782 static $field_types = null;
1783
1784 if ( null === $field_types ) {
1785 $field_types = [
1786 'currency',
1787 'number',
1788 ];
1789
1790 $field_types = apply_filters( 'pods_tableless_field_types', $field_types );
1791 }
1792
1793 return $field_types;
1794 }
1795
1796 /**
1797 * Get the list of available date field types.
1798 *
1799 * @since 2.3.0
1800 *
1801 * @return array The list of available date field types.
1802 */
1803 public static function date_field_types() {
1804 static $field_types = null;
1805
1806 if ( null === $field_types ) {
1807 $field_types = [
1808 'date',
1809 'datetime',
1810 'time',
1811 ];
1812
1813 $field_types = apply_filters( 'pods_tableless_field_types', $field_types );
1814 }
1815
1816 return $field_types;
1817 }
1818
1819 /**
1820 * Get the list of available text field types.
1821 *
1822 * @since 2.3.0
1823 *
1824 * @return array The list of available text field types.
1825 */
1826 public static function text_field_types() {
1827 static $field_types = null;
1828
1829 if ( null === $field_types ) {
1830 $field_types = [
1831 'code',
1832 'paragraph',
1833 'slug',
1834 'password',
1835 'text',
1836 'wysiwyg',
1837 ];
1838
1839 $field_types = apply_filters( 'pods_text_field_types', $field_types );
1840 }
1841
1842 return $field_types;
1843 }
1844
1845 /**
1846 * Get the list of available Layout field types (backwards compatible version).
1847 *
1848 * @since 2.3.0
1849 *
1850 * @deprecated since 2.3.0
1851 * @see PodsForm::layout_field_types()
1852 *
1853 * @return array The list of available Layout field types.
1854 */
1855 public static function block_field_types() {
1856 _doing_it_wrong( 'PodsForm::layout_field_types', 'This function is deprecated, use PodsForm::layout_field_types instead.', '2.8.0' );
1857
1858 return self::layout_field_types();
1859 }
1860
1861 /**
1862 * Get the list of available Layout field types.
1863 *
1864 * @since 2.8.0
1865 *
1866 * @return array The list of available Layout field types.
1867 */
1868 public static function layout_field_types() {
1869 static $field_types = null;
1870
1871 if ( null === $field_types ) {
1872 $field_types = [
1873 'heading',
1874 'html',
1875 ];
1876
1877 /**
1878 * Allow filtering of the list of Layout field types.
1879 *
1880 * @since 2.8.0
1881 *
1882 * @param array $field_types The list of Layout field types.
1883 */
1884 $field_types = apply_filters( 'pods_layout_field_types', $field_types );
1885 }
1886
1887 return $field_types;
1888 }
1889
1890 /**
1891 * Get the list of available Non-Input field types.
1892 *
1893 * @since 2.8.0
1894 *
1895 * @return array The list of available Non-Input field types.
1896 */
1897 public static function non_input_field_types() {
1898 static $field_types = null;
1899
1900 if ( null === $field_types ) {
1901 $field_types = [
1902 'internal',
1903 ];
1904
1905 /**
1906 * Allow filtering of the list of Non-Input field types.
1907 *
1908 * @since 2.8.0
1909 *
1910 * @param array $field_types The list of Non-Input field types.
1911 */
1912 $field_types = apply_filters( 'pods_non_input_field_types', $field_types );
1913 }
1914
1915 return $field_types;
1916 }
1917
1918 /**
1919 * Get the list of field types that do not use serial comma separators.
1920 *
1921 * @since 2.9.4
1922 *
1923 * @return array The list of field types that do not use serial comma separators.
1924 */
1925 public static function separator_excluded_field_types() {
1926 static $field_types = null;
1927
1928 if ( null === $field_types ) {
1929 $field_types = [
1930 'avatar',
1931 'code',
1932 'link',
1933 'oembed',
1934 'paragraph',
1935 'website',
1936 'wysiwyg',
1937 ];
1938
1939 /**
1940 * Allow filtering of the list of field types that do not use serial comma separators.
1941 *
1942 * @since 2.8.0
1943 *
1944 * @param array $field_types The list of field types that do not use serial comma separators.
1945 */
1946 $field_types = apply_filters( 'pods_separator_excluded_field_types', $field_types );
1947 }
1948
1949 return $field_types;
1950 }
1951
1952 /**
1953 * Get the list of simple tableless objects.
1954 *
1955 * @since 2.3.0
1956 *
1957 * @return array The list of simple tableless objects.
1958 */
1959 public static function simple_tableless_objects() {
1960
1961 static $object_types = null;
1962
1963 if ( null === $object_types ) {
1964 $object_types = self::field_method( 'pick', 'simple_objects' );
1965 }
1966
1967 return $object_types;
1968 }
1969
1970 /**
1971 * Render the postbox header in a compatible way.
1972 *
1973 * @since 2.7.22
1974 *
1975 * @param string $title Header title.
1976 */
1977 public static function render_postbox_header( $title ) {
1978 pods_view( PODS_DIR . 'ui/admin/postbox-header.php', compact( array_keys( get_defined_vars() ) ) );
1979 }
1980 }
1981