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