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