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