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