Completed
Pull Request — 2.x (#4187)
by Scott Kingsley
06:00
created

PodsForm::field_method()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 16
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 10
nc 3
nop 0
dl 0
loc 16
rs 9.2
c 0
b 0
f 0
1
<?php
2
/**
3
 * @package Pods
4
 */
5
class PodsForm {
0 ignored issues
show
Coding Style introduced by
Since you have declared the constructor as private, maybe you should also declare the class as final.
Loading history...
6
7
    /**
8
     * @var PodsForm
9
     */
10
    protected static $instance = null;
11
12
    /**
13
     * @var string
14
     */
15
    static $field = null;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $field.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
16
17
    /**
18
     * @var string
19
     */
20
    static $field_group = null;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $field_group.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
21
22
    /**
23
     * @var string
24
     */
25
    static $field_type = null;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $field_type.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
26
27
    /**
28
     * @var array
29
     */
30
    static $field_types = array();
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $field_types.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
31
32
    /**
33
     * @var array
34
     */
35
    static $loaded = array();
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $loaded.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
36
37
    /**
38
     * @var int
39
     */
40
    static $form_counter = 0;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $form_counter.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
41
42
    /**
43
     * Singleton handling for a basic pods_form() request
44
     *
45
     * @return \PodsForm
46
     *
47
     * @since 2.3.5
48
     */
49
    public static function init () {
50
        if ( !is_object( self::$instance ) )
51
            self::$instance = new PodsForm();
52
53
        return self::$instance;
54
    }
55
56
    /**
57
     * Master handler for all field / form methods
58
     *
59
     * @return \PodsForm
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
60
     *
61
     * @license http://www.gnu.org/licenses/gpl-2.0.html
62
     * @since 2.0
63
     */
64
    private function __construct() {
65
        add_action( 'admin_init', array( $this, 'admin_init' ), 14 );
66
    }
67
68
    /**
69
     * Prevent clones
70
     *
71
     * @since 2.3
72
     */
73
    private function __clone() {
74
        // Hulk smash
75
    }
76
77
    /**
78
     * Output a field's label
79
     *
80
     * @since 2.0
81
     */
82
83
    /**
84
     * Output a field's label
85
     *
86
     * @param string $name Field name
87
     * @param string $label Label text
88
     * @param string $help Help text
89
     * @param array $options Field options
90
     *
91
     * @return string Label HTML
92
     *
93
     * @since 2.0
94
     */
95
    public static function label( $name, $label, $help = '', $options = null ) {
96
        if ( is_array( $label ) || is_object( $label ) ) {
97
            $options = $label;
98
            $label = $options[ 'label' ];
99
100
            if ( empty( $label ) )
101
                $label = ucwords( str_replace( '_', ' ', $name ) );
102
103
            $help = $options[ 'help' ];
104
        }
105
        else
106
            $options = self::options( null, $options );
107
108
        $label = apply_filters( 'pods_form_ui_label_text', $label, $name, $help, $options );
109
        $help = apply_filters( 'pods_form_ui_label_help', $help, $name, $label, $options );
110
111
        ob_start();
112
113
        $name_clean = self::clean( $name );
114
        $name_more_clean = self::clean( $name, true );
115
116
        $type = 'label';
117
        $attributes = array();
118
        $attributes[ 'class' ] = 'pods-form-ui-' . $type . ' pods-form-ui-' . $type . '-' . $name_more_clean;
119
        $attributes[ 'for' ] = ( false === strpos( $name_clean, 'pods-form-ui-' ) ? 'pods-form-ui-' : '' ) . $name_clean;
120
        $attributes = self::merge_attributes( $attributes, $name, $type, $options, false );
121
122
        pods_view( PODS_DIR . 'ui/fields/_label.php', compact( array_keys( get_defined_vars() ) ) );
123
124
        $output = ob_get_clean();
125
126
        return apply_filters( 'pods_form_ui_' . $type, $output, $name, $label, $help, $attributes, $options );
127
    }
128
129
    /**
130
     * Output a Field Comment Paragraph
131
     *
132
     * @param string $name Field name
133
     * @param string $message Field comments
134
     * @param array $options Field options
135
     *
136
     * @return string Comment HTML
137
     *
138
     * @since 2.0
139
     */
140
    public static function comment( $name, $message = null, $options = null ) {
141
        $options = self::options( null, $options );
142
143
        $name_more_clean = self::clean( $name, true );
144
145
        if ( ! empty( $options[ 'description' ] ) )
146
            $message = $options[ 'description' ];
147
        elseif ( empty( $message ) )
148
            return '';
149
150
        $message = apply_filters( 'pods_form_ui_comment_text', $message, $name, $options );
151
152
        ob_start();
153
154
        $type = 'comment';
155
        $attributes = array();
156
        $attributes[ 'class' ] = 'description pods-form-ui-' . $type . ' pods-form-ui-' . $type . '-' . $name_more_clean;
157
        $attributes = self::merge_attributes( $attributes, $name, $type, $options, false );
158
159
        pods_view( PODS_DIR . 'ui/fields/_comment.php', compact( array_keys( get_defined_vars() ) ) );
160
161
        $output = ob_get_clean();
162
163
        return apply_filters( 'pods_form_ui_' . $type, $output, $name, $message, $attributes, $options );
164
    }
165
166
    /**
167
     * Output a field
168
     *
169
     * @param string $name Field name
170
     * @param mixed $value Field value
171
     * @param string $type Field type
172
     * @param array $options Field options
173
     * @param array $pod Pod data
174
     * @param int $id Item ID
175
     *
176
     * @return string Field HTML
177
     *
178
     * @since 2.0
179
     */
180
    public static function field( $name, $value, $type = 'text', $options = null, $pod = null, $id = null ) {
181
		// Take a field array
182
		if ( is_array( $name ) || is_object( $name ) ) {
183
			$options = $name;
184
185
			if ( is_object( $type ) ) {
186
				$pod = $type;
187
				$id = $options;
188
			}
189
190
			$name = pods_v( 'name', $options );
191
			$type = pods_v( 'type', $options );
192
		}
193
194
        $options = self::options( $type, $options );
195
        $options = apply_filters( 'pods_form_ui_field_' . $type . '_options', $options, $value, $name, $pod, $id );
196
197
        if ( null === $value || ( '' === $value && 'boolean' === $type ) || ( !empty( $pod ) && empty( $id ) ) )
198
            $value = self::default_value( $value, $type, $name, $options, $pod, $id );
199
200
        // Fix double help qtip when using single checkboxes (boolean type)
201
        if ( 'boolean' === $type )
202
        	$options['help'] = '';
203
204
        if ( false === self::permission( $type, $name, $options, null, $pod, $id ) )
205
            return false;
206
207
        $value = apply_filters( 'pods_form_ui_field_' . $type . '_value', $value, $name, $options, $pod, $id );
208
        $form_field_type = self::$field_type;
209
210
        ob_start();
211
212
        $helper = false;
213
214
	    /**
215
	     * Input helpers are deprecated and not guaranteed to work properly.
216
	     *
217
	     * They will be entirely removed in Pods 3.0.
218
	     *
219
	     * @deprecated 2.7
220
	     */
221
	    if ( 0 < strlen( pods_v( 'input_helper', $options ) ) ) {
222
		    $helper = pods_api()->load_helper( array( 'name' => $options['input_helper'] ) );
223
	    }
224
225
        // @todo Move into DFV field method or PodsObject later
226
	    if ( ( ! isset( $options['data'] ) || empty( $options['data'] ) ) && is_object( self::$loaded[ $type ] ) && method_exists( self::$loaded[ $type ], 'data' ) ) {
227
		    $data = $options['data'] = self::$loaded[ $type ]->data( $name, $value, $options, $pod, $id, true );
228
	    }
229
230
	    /**
231
	     * pods_form_ui_field_{$type}_override filter leaves too much to be done by developer.
232
	     *
233
	     * It will be replaced in Pods 3.0 with better documentation.
234
	     *
235
	     * @deprecated 2.7
236
	     */
237
	    if ( true === apply_filters( 'pods_form_ui_field_' . $type . '_override', false, $name, $value, $options, $pod, $id ) ) {
238
		    /**
239
		     * pods_form_ui_field_{$type} action leaves too much to be done by developer.
240
		     *
241
		     * It will be replaced in Pods 3.0 with better documentation.
242
		     *
243
		     * @deprecated 2.7
244
		     */
245
		    do_action( 'pods_form_ui_field_' . $type, $name, $value, $options, $pod, $id );
246
	    } elseif ( ! empty( $helper ) && 0 < strlen( pods_v( 'code', $helper ) ) && false === strpos( $helper['code'], '$this->' ) && ( ! defined( 'PODS_DISABLE_EVAL' ) || ! PODS_DISABLE_EVAL ) ) {
247
		    /**
248
		     * Input helpers are deprecated and not guaranteed to work properly.
249
		     *
250
		     * They will be entirely removed in Pods 3.0.
251
		     *
252
		     * @deprecated 2.7
253
		     */
254
		    eval( '?>' . $helper['code'] );
0 ignored issues
show
Coding Style introduced by
It is generally not recommended to use eval unless absolutely required.

On one hand, eval might be exploited by malicious users if they somehow manage to inject dynamic content. On the other hand, with the emergence of faster PHP runtimes like the HHVM, eval prevents some optimization that they perform.

Loading history...
255
	    } elseif ( method_exists( get_class(), 'field_' . $type ) ) {
256
	    	// @todo Move these custom field methods into real/faux field classes
257
		    echo call_user_func( array( get_class(), 'field_' . $type ), $name, $value, $options );
258
	    } elseif ( is_object( self::$loaded[ $type ] ) && method_exists( self::$loaded[ $type ], 'input' ) ) {
259
		    self::$loaded[ $type ]->input( $name, $value, $options, $pod, $id );
260
	    } else {
261
	    	/**
262
		     * pods_form_ui_field_{$type} action 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
267
		     */
268
		    do_action( 'pods_form_ui_field_' . $type, $name, $value, $options, $pod, $id );
269
	    }
270
271
        $output = ob_get_clean();
272
273
	    /**
274
	     * pods_form_ui_field_{$type} filter will remain supported.
275
	     *
276
	     * It is not intended for replacing but augmenting input markup.
277
	     */
278
        return apply_filters( 'pods_form_ui_field_' . $type, $output, $name, $value, $options, $pod, $id );
279
    }
280
281
    /**
282
     * Output field type 'db'
283
     *
284
     * Used for field names and other places where only [a-z0-9_] is accepted
285
     *
286
     * @since 2.0
287
     */
288 View Code Duplication
    protected static function field_db( $name, $value = null, $options = null ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
289
        $form_field_type = self::$field_type;
290
291
        ob_start();
292
293
        pods_view( PODS_DIR . 'ui/fields/_db.php', compact( array_keys( get_defined_vars() ) ) );
294
295
        $output = ob_get_clean();
296
297
        return apply_filters( 'pods_form_ui_field_db', $output, $name, $value, $options );
298
    }
299
300
    /**
301
     * Output a hidden field
302
     */
303 View Code Duplication
    protected static function field_hidden( $name, $value = null, $options = null ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
304
        $form_field_type = self::$field_type;
305
306
        ob_start();
307
308
        pods_view( PODS_DIR . 'ui/fields/_hidden.php', compact( array_keys( get_defined_vars() ) ) );
309
310
        $output = ob_get_clean();
311
312
        return apply_filters( 'pods_form_ui_field_hidden', $output, $name, $value, $options );
313
    }
314
315
	/**
316
	 * Returns a submit button, with provided text and appropriate class, copied from WP Core for use on the frontend
317
	 *
318
	 * @see get_submit_button
319
	 *
320
	 * @param string $text The text of the button (defaults to 'Save Changes')
321
	 * @param string $type The type of button. One of: primary, secondary, delete
322
	 * @param string $name The HTML name of the submit button. Defaults to "submit". If no id attribute
323
	 *               is given in $other_attributes below, $name will be used as the button's id.
324
	 * @param bool $wrap True if the output button should be wrapped in a paragraph tag,
325
	 * 			   false otherwise. Defaults to true
326
	 * @param array|string $other_attributes Other attributes that should be output with the button,
327
	 *                     mapping attributes to their values, such as array( 'tabindex' => '1' ).
328
	 *                     These attributes will be output as attribute="value", such as tabindex="1".
329
	 *                     Defaults to no other attributes. Other attributes can also be provided as a
330
	 *                     string such as 'tabindex="1"', though the array format is typically cleaner.
331
	 *
332
	 * @since 3.0
333
	 */
334
	public static function submit_button( $text = null, $type = 'primary large', $name = 'submit', $wrap = true, $other_attributes = null ) {
335
336
		if ( function_exists( 'get_submit_button' ) ) {
337
			return get_submit_button( $text, $type, $name, $wrap, $other_attributes );
338
		}
339
340
		if ( !is_array( $type ) ) {
341
			$type = explode( ' ', $type );
342
		}
343
344
		$button_shorthand = array(
345
			'primary',
346
			'small',
347
			'large'
348
		);
349
350
		$classes = array(
351
			'button'
352
		);
353
354
		foreach ( $type as $t ) {
355
			if ( 'secondary' === $t || 'button-secondary' === $t ) {
356
				continue;
357
			}
358
359
			$classes[] = in_array( $t, $button_shorthand ) ? 'button-' . $t : $t;
360
		}
361
362
		$class = implode( ' ', array_unique( $classes ) );
363
364
		if ( 'delete' === $type ) {
365
			$class = 'button-secondary delete';
366
		}
367
368
		$text = $text ? $text : __( 'Save Changes' );
369
370
		// Default the id attribute to $name unless an id was specifically provided in $other_attributes
371
		$id = $name;
372
373
		if ( is_array( $other_attributes ) && isset( $other_attributes[ 'id' ] ) ) {
374
			$id = $other_attributes[ 'id' ];
375
			unset( $other_attributes[ 'id' ] );
376
		}
377
378
		$attributes = '';
379
380
		if ( is_array( $other_attributes ) ) {
381
			foreach ( $other_attributes as $attribute => $value ) {
382
				$attributes .= $attribute . '="' . esc_attr( $value ) . '" '; // Trailing space is important
383
			}
384
		}
385
		elseif ( !empty( $other_attributes ) ) { // Attributes provided as a string
386
			$attributes = $other_attributes;
387
		}
388
389
		$button = '<input type="submit" name="' . esc_attr( $name ) . '" id="' . esc_attr( $id ) . '" class="' . esc_attr( $class );
390
		$button .= '" value="' . esc_attr( $text ) . '" ' . $attributes . ' />';
391
392
		if ( $wrap ) {
393
			$button = '<p class="submit">' . $button . '</p>';
394
		}
395
396
		return $button;
397
398
	}
399
400
    /**
401
     * Output a row (label, field, and comment)
402
     *
403
     * @param string $name Field name
404
     * @param mixed $value Field value
405
     * @param string $type Field type
406
     * @param array $options Field options
407
     * @param array $pod Pod data
408
     * @param int $id Item ID
409
     *
410
     * @return string Row HTML
411
     *
412
     * @since 2.0
413
     */
414
    public static function row( $name, $value, $type = 'text', $options = null, $pod = null, $id = null ) {
415
        $options = self::options( null, $options );
416
417
        ob_start();
418
419
        pods_view( PODS_DIR . 'ui/fields/_row.php', compact( array_keys( get_defined_vars() ) ) );
420
421
        $output = ob_get_clean();
422
423
        return apply_filters( 'pods_form_ui_field_row', $output, $name, $value, $options, $pod, $id );
424
    }
425
426
    /**
427
     * Output a field's attributes
428
     *
429
     * @since 2.0
430
     */
431
    public static function attributes( $attributes, $name = null, $type = null, $options = null ) {
432
        $attributes = (array) apply_filters( 'pods_form_ui_field_' . $type . '_attributes', $attributes, $name, $options );
433
434
        foreach ( $attributes as $attribute => $value ) {
435
            if ( null === $value )
436
                continue;
437
438
            echo ' ' . esc_attr( (string) $attribute ) . '="' . esc_attr( (string) $value ) . '"';
439
        }
440
    }
441
442
    /**
443
     * Output a field's data (for use with jQuery)
444
     *
445
     * @since 2.0
446
     */
447
    public static function data( $data, $name = null, $type = null, $options = null ) {
448
        $data = (array) apply_filters( 'pods_form_ui_field_' . $type . '_data', $data, $name, $options );
449
450
        foreach ( $data as $key => $value ) {
451
            if ( null === $value )
452
                continue;
453
454
            $key = sanitize_title( $key );
455
456
            if ( is_array( $value ) )
457
                $value = implode( ',', $value );
458
459
            echo ' data-' . esc_attr( (string) $key ) . '="' . esc_attr( (string) $value ) . '"';
460
        }
461
    }
462
463
    /**
464
     * Merge attributes and handle classes
465
     *
466
     * @since 2.0
467
     */
468
    public static function merge_attributes( $attributes, $name = null, $type = null, $options = null, $classes = '' ) {
469
        $options = (array) $options;
470
471
        if ( !in_array( $type, array( 'label', 'comment' ) ) ) {
472
            $name_clean = self::clean( $name );
473
            $name_more_clean = self::clean( $name, true );
474
            $_attributes = array();
475
            $_attributes[ 'name' ] = $name;
476
            $_attributes[ 'data-name-clean' ] = $name_more_clean;
477
478
            if ( 0 < strlen( pods_v( 'label', $options, '' ) ) )
479
                $_attributes[ 'data-label' ] = strip_tags( pods_v( 'label', $options ) );
480
481
            $_attributes['id'] = 'pods-form-ui-' . $name_clean . ( self::$form_counter > 1 ? '-' . self::$form_counter : '' );
482
            $_attributes['class'] = 'pods-form-ui-field pods-form-ui-field-type-' . $type . ' pods-form-ui-field-name-' . $name_more_clean;
483
484
            if ( isset( $options[ 'dependency' ] ) && false !== $options[ 'dependency' ] )
485
                $_attributes[ 'class' ] .= ' pods-dependent-toggle';
486
487
            $attributes = array_merge( $_attributes, (array) $attributes );
488
489 View Code Duplication
            if ( isset( $options[ 'attributes' ] ) && is_array( $options[ 'attributes' ] ) && !empty( $options[ 'attributes' ] ) )
490
                $attributes = array_merge( $attributes, $options[ 'attributes' ] );
491
        }
492
        elseif ( isset( $options[ $type . '_attributes' ] ) && is_array( $options[ $type . '_attributes' ] ) && !empty( $options[ $type . '_attributes' ] ) )
493
            $attributes = array_merge( $attributes, $options[ $type . '_attributes' ] );
494
495
        if ( isset( $options[ 'class' ] ) && !empty( $options[ 'class' ] ) ) {
496
            if ( is_array( $options[ 'class' ] ) )
497
                $options[ 'class' ] = implode( ' ', $options[ 'class' ] );
498
499
            $options[ 'class' ] = (string) $options[ 'class' ];
500 View Code Duplication
            if ( isset( $attributes[ 'class' ] ) )
501
                $attributes[ 'class' ] = $attributes[ 'class' ] . ' ' . $options[ 'class' ];
502
            else
503
                $attributes[ 'class' ] = $options[ 'class' ];
504
505
            $attributes[ 'class' ] = trim( $attributes[ 'class' ] );
506
        }
507
508
        if ( !empty( $classes ) ) {
509 View Code Duplication
            if ( isset( $attributes[ 'class' ] ) )
510
                $attributes[ 'class' ] = $attributes[ 'class' ] . ' ' . $classes;
511
            else
512
                $attributes[ 'class' ] = $classes;
513
        }
514
515
        if ( isset( $options[ 'placeholder' ] ) && !empty( $options[ 'placeholder' ] ) ) {
516
            if ( is_array( $options[ 'placeholder' ] ) )
517
                $options[ 'placeholder' ] = implode( ' ', $options[ 'placeholder' ] );
518
519
            $options[ 'placeholder' ] = (string) $options[ 'placeholder' ];
520
			$attributes[ 'placeholder' ] = trim( $options[ 'placeholder' ] );
521
        }
522
523
        if ( 1 == pods_v( 'required', $options, 0 ) )
524
            $attributes[ 'class' ] .= ' pods-validate pods-validate-required';
525
526
        $max_length = (int) pods_var( 'maxlength', $options, pods_v( $type . '_max_length', $options, 0 ), null, true );
527
528
        if ( 0 < $max_length )
529
            $attributes[ 'maxlength' ] = $max_length;
530
531
        $attributes = (array) apply_filters( 'pods_form_ui_field_' . $type . '_merge_attributes', $attributes, $name, $options );
532
        return $attributes;
533
    }
534
535
    /**
536
     * Setup options for a field and store them for later use
537
     *
538
     * @param $type
539
     * @param $options
540
     *
541
     * @return array
542
     *
543
     * @static
544
     *
545
     * @since 2.0
546
     */
547
    public static function options( $type, $options ) {
548
        $options = (array) $options;
549
550
        if ( !is_object( $options ) && isset( $options[ 'options' ] ) ) {
551
            $options_temp = $options[ 'options' ];
552
553
            unset( $options[ 'options' ] );
554
555
            $options = array_merge( $options_temp, $options );
556
557
            $override = array(
558
                'class'
559
            );
560
561
            foreach ( $override as $check ) {
562
                if ( isset( $options_temp[ $check ] ) )
563
                    $options[ $check ] = $options_temp[ $check ];
564
            }
565
        }
566
567
        $defaults = self::options_setup( $type, $options );
568
569
        $core_defaults = array(
570
            'id' => 0,
571
            'label' => '',
572
            'description' => '',
573
            'help' => '',
574
            'default' => null,
575
            'attributes' => array(),
576
            'class' => '',
577
            'grouped' => 0,
578
        );
579
580
        $defaults = array_merge( $core_defaults, $defaults );
581
582
        foreach ( $defaults as $option => $settings ) {
583
            $default = $settings;
584
585
            if ( is_array( $settings ) && isset( $settings[ 'default' ] ) )
586
                $default = $settings[ 'default' ];
587
588
            if ( !isset( $options[ $option ] ) )
589
                $options[ $option ] = $default;
590
        }
591
592
        return $options;
593
    }
594
595
    /**
596
     * Get options for a field type and setup defaults
597
     *
598
     * @static
599
     *
600
     * @param $type
601
     *
602
     * @return array|null
603
     *
604
     * @since 2.0
605
     */
606
    public static function options_setup( $type = null, $options = null ) {
607
        $core_defaults = array(
608
            'id' => 0,
609
            'name' => '',
610
            'label' => '',
611
            'description' => '',
612
            'help' => '',
613
            'default' => null,
614
            'attributes' => array(),
615
            'class' => '',
616
            'type' => 'text',
617
            'group' => 0,
618
            'grouped' => 0,
619
            'developer_mode' => false,
620
            'dependency' => false,
621
            'depends-on' => array(),
622
            'excludes-on' => array(),
623
            'options' => array()
624
        );
625
626
        if ( !empty( $options ) && is_array( $options ) )
627
            $core_defaults = array_merge( $core_defaults, $options );
628
629
        if ( null === $type )
630
            return $core_defaults;
631
        else
632
            self::field_loader( $type );
633
634
        $options = apply_filters( 'pods_field_' . $type . '_options', (array) self::$loaded[ $type ]->options(), $type );
635
636
        $first_field = current( $options );
637
638
        if ( !empty( $options ) && !isset( $first_field[ 'name' ] ) && !isset( $first_field[ 'label' ] ) ) {
639
            $all_options = array();
640
641
            foreach ( $options as $group => $group_options ) {
642
                $all_options = array_merge( $all_options, self::fields_setup( $group_options, $core_defaults ) );
643
            }
644
645
            $options = $all_options;
646
        }
647
        else
648
            $options = self::fields_setup( $options, $core_defaults );
649
650
        return $options;
651
    }
652
653
    /**
654
     * Get Admin options for a field type and setup defaults
655
     *
656
     * @static
657
     *
658
     * @param $type
659
     *
660
     * @return array|null
661
     *
662
     * @since 2.0
663
     */
664
    public static function ui_options( $type ) {
665
        $core_defaults = array(
666
            'id' => 0,
667
            'name' => '',
668
            'label' => '',
669
            'description' => '',
670
            'help' => '',
671
            'default' => null,
672
            'attributes' => array(),
673
            'class' => '',
674
            'type' => 'text',
675
            'group' => 0,
676
            'grouped' => 0,
677
            'developer_mode' => false,
678
            'dependency' => false,
679
            'depends-on' => array(),
680
            'excludes-on' => array(),
681
            'options' => array()
682
        );
683
684
        self::field_loader( $type );
685
686
        $options = apply_filters( 'pods_field_' . $type . '_ui_options', (array) self::$loaded[ $type ]->ui_options(), $type );
687
688
        $first_field = current( $options );
689
690
        if ( !empty( $options ) && !isset( $first_field[ 'name' ] ) && !isset( $first_field[ 'label' ] ) ) {
691
            foreach ( $options as $group => $group_options ) {
692
                $options[ $group ] = self::fields_setup( $group_options, $core_defaults );
693
            }
694
        }
695
        else
696
            $options = self::fields_setup( $options, $core_defaults );
697
698
        return $options;
699
    }
700
701
    /**
702
     * Get options for a field and setup defaults
703
     *
704
     *
705
     * @param null $fields
706
     * @param null $core_defaults
707
     * @param bool $single
708
     *
709
     * @return array|null
710
     *
711
     * @static
712
     * @since 2.0
713
     */
714
    public static function fields_setup( $fields = null, $core_defaults = null, $single = false ) {
715
        if ( empty( $core_defaults ) ) {
716
            $core_defaults = array(
717
                'id' => 0,
718
                'name' => '',
719
                'label' => '',
720
                'description' => '',
721
                'help' => '',
722
                'default' => null,
723
                'attributes' => array(),
724
                'class' => '',
725
                'type' => 'text',
726
                'group' => 0,
727
                'grouped' => 0,
728
                'developer_mode' => false,
729
                'dependency' => false,
730
                'depends-on' => array(),
731
                'excludes-on' => array(),
732
                'options' => array()
733
            );
734
        }
735
736
        if ( $single )
737
            $fields = array( $fields );
738
739
        foreach ( $fields as $f => $field ) {
0 ignored issues
show
Bug introduced by
The expression $fields of type array<integer,null,{"0":"null"}>|null is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
740
            $fields[ $f ] = self::field_setup( $field, $core_defaults, pods_v( 'type', $field, 'text' ) );
741
742
            if ( !$single && strlen( $fields[ $f ][ 'name' ] ) < 1 )
743
                $fields[ $f ][ 'name' ] = $f;
744
        }
745
746
        if ( $single )
747
            $fields = $fields[ 0 ];
748
749
        return $fields;
750
    }
751
752
    /**
753
     * Get options for a field and setup defaults
754
     *
755
     * @static
756
     *
757
     * @param null $field
758
     * @param null $core_defaults
759
     * @param null $type
760
     *
761
     * @return array|null
762
     *
763
     * @since 2.0
764
     */
765
    public static function field_setup( $field = null, $core_defaults = null, $type = null ) {
766
        $options = array();
767
768
        if ( empty( $core_defaults ) ) {
769
            $core_defaults = array(
770
                'id' => 0,
771
                'name' => '',
772
                'label' => '',
773
                'description' => '',
774
                'help' => '',
775
                'default' => null,
776
                'attributes' => array(),
777
                'class' => '',
778
                'type' => 'text',
779
                'group' => 0,
780
                'grouped' => 0,
781
                'developer_mode' => false,
782
                'dependency' => false,
783
                'depends-on' => array(),
784
                'excludes-on' => array(),
785
                'options' => array()
786
            );
787
788
            if ( null !== $type ) {
789
                self::field_loader( $type );
790
791
                if ( method_exists( self::$loaded[ $type ], 'options' ) )
792
                    $options = apply_filters( 'pods_field_' . $type . '_options', (array) self::$loaded[ $type ]->options(), $type );
793
            }
794
        }
795
796
        if ( !is_array( $field ) )
797
            $field = array( 'default' => $field );
798
799
        if ( isset( $field[ 'group' ] ) && is_array( $field[ 'group' ] ) ) {
800
            foreach ( $field[ 'group' ] as $g => $group_option ) {
801
                $field[ 'group' ][ $g ] = array_merge( $core_defaults, $group_option );
802
803
                if ( strlen( $field[ 'group' ][ $g ][ 'name' ] ) < 1 )
804
                    $field[ 'group' ][ $g ][ 'name' ] = $g;
805
            }
806
        }
807
808
        $field = array_merge( $core_defaults, $field );
809
810
        foreach ( $options as $option => $settings ) {
811
            $v = null;
812
813
            if ( isset( $settings[ 'default' ] ) )
814
                $v = $settings[ 'default' ];
815
816
            if ( !isset( $field[ 'options' ][ $option ] ) )
817
                $field[ 'options' ][ $option ] = $v;
818
        }
819
820
        return $field;
821
    }
822
823
    /**
824
     * Setup dependency / exclusion classes
825
     *
826
     * @param array $options array( 'depends-on' => ..., 'excludes-on' => ...)
827
     * @param string $prefix
828
     *
829
     * @return string
830
     * @static
831
     * @since 2.0
832
     */
833
    public static function dependencies( $options, $prefix = '' ) {
834
835
        $options = (array) $options;
836
        $classes = $data = array();
837
838
        $depends_on = $excludes_on = $wildcard_on = array();
839
        if ( isset( $options[ 'depends-on' ] ) ) {
840
            $depends_on = (array) $options[ 'depends-on' ];
841
        }
842
843
        if ( isset( $options[ 'excludes-on' ] ) ) {
844
            $excludes_on = (array) $options[ 'excludes-on' ];
845
        }
846
847
        if ( isset( $options[ 'wildcard-on' ] ) ) {
848
            $wildcard_on = (array) $options[ 'wildcard-on' ];
849
        }
850
851 View Code Duplication
        if ( ! empty( $depends_on ) ) {
852
            $classes[] = 'pods-depends-on';
853
854
            foreach ( $depends_on as $depends => $on ) {
855
                $classes[] = 'pods-depends-on-' . $prefix . self::clean( $depends, true );
856
857
                if ( ! is_bool( $on ) ) {
858
                    $on = (array) $on;
859
860
                    foreach ( $on as $o ) {
861
                        $classes[] = 'pods-depends-on-' . $prefix . self::clean( $depends, true ) . '-' . self::clean( $o, true );
862
                    }
863
                }
864
            }
865
        }
866
867 View Code Duplication
        if ( ! empty( $excludes_on ) ) {
868
            $classes[] = 'pods-excludes-on';
869
            foreach ( $excludes_on as $excludes => $on ) {
870
                $classes[] = 'pods-excludes-on-' . $prefix . self::clean( $excludes, true );
871
872
                $on = (array) $on;
873
874
                foreach ( $on as $o ) {
875
                    $classes[] = 'pods-excludes-on-' . $prefix . self::clean( $excludes, true ) . '-' . self::clean( $o, true );
876
                }
877
            }
878
        }
879
880
        if ( ! empty( $wildcard_on ) ) {
881
            $classes[] = 'pods-wildcard-on';
882
883
            // Add the appropriate classes and data attribs per value dependency
884
            foreach ( $wildcard_on as $target => $wildcards ) {
885
                $target = $prefix . self::clean( $target, true );
886
                $classes[] = 'pods-wildcard-on-' . $target;
887
                $data[ 'pods-wildcard-' . $target ] = $wildcards;
888
            }
889
        }
890
891
        $classes = implode( ' ', $classes );
892
893
        return array( 'classes' => $classes, 'data' => $data );
894
    }
895
896
    /**
897
     * Change the value of the field
898
     *
899
     * @param mixed $value
900
     * @param string $name
901
     * @param array $options
902
     * @param array $fields
0 ignored issues
show
Bug introduced by
There is no parameter named $fields. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
903
     * @param array $pod
904
     * @param int $id
905
     * @param array $traverse
906
     *
907
     * @since 2.3
908
     */
909
    public static function value( $type, $value = null, $name = null, $options = null, $pod = null, $id = null, $traverse = null ) {
910
        self::field_loader( $type );
911
912
        if ( in_array( $type, self::repeatable_field_types() ) && 1 == pods_v( $type . '_repeatable', $options, 0 ) && !is_array( $value ) ) {
913
            if ( 0 < strlen( $value ) ) {
914
                $simple = @json_decode( $value, true );
915
916
                if ( is_array( $simple ) )
917
                    $value = $simple;
918
                else
919
                    $value = (array) $value;
920
            }
921
            else
922
                $value = array();
923
        }
924
925
        if ( method_exists( self::$loaded[ $type ], 'value' ) ) {
926
            if ( is_array( $value ) && in_array( $type, self::tableless_field_types() ) ) {
927 View Code Duplication
                foreach ( $value as &$display_value ) {
928
                    $display_value = call_user_func_array( array( self::$loaded[ $type ], 'value' ), array( $display_value, $name, $options, $pod, $id, $traverse ) );
929
                }
930
            }
931 View Code Duplication
            else
932
                $value = call_user_func_array( array( self::$loaded[ $type ], 'value' ), array( $value, $name, $options, $pod, $id, $traverse ) );
933
        }
934
935
        return $value;
936
    }
937
938
    /**
939
     * Change the way the value of the field is displayed with Pods::get
940
     *
941
     * @param mixed $value
942
     * @param string $name
943
     * @param array $options
944
     * @param array $fields
0 ignored issues
show
Bug introduced by
There is no parameter named $fields. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
945
     * @param array $pod
946
     * @param int $id
947
     * @param array $traverse
948
     *
949
     * @since 2.0
950
     */
951
    public static function display( $type, $value = null, $name = null, $options = null, $pod = null, $id = null, $traverse = null ) {
952
        self::field_loader( $type );
953
954
        $tableless_field_types = self::tableless_field_types();
955
956
        if ( method_exists( self::$loaded[ $type ], 'display' ) ) {
957
            if ( is_array( $value ) && !in_array( $type, $tableless_field_types ) ) {
958 View Code Duplication
                foreach ( $value as $k => $display_value ) {
959
                    $value[ $k ] = call_user_func_array( array( self::$loaded[ $type ], 'display' ), array( $display_value, $name, $options, $pod, $id, $traverse ) );
960
                }
961
            }
962 View Code Duplication
            else
963
                $value = call_user_func_array( array( self::$loaded[ $type ], 'display' ), array( $value, $name, $options, $pod, $id, $traverse ) );
964
        }
965
966
        $value = apply_filters( 'pods_form_display_' . $type, $value, $name, $options, $pod, $id, $traverse );
967
968
        return $value;
969
    }
970
971
    /**
972
     * Setup regex for JS / PHP
973
     *
974
     * @static
975
     *
976
     * @param $type
977
     * @param $options
978
     *
979
     * @return mixed|void
980
     * @since 2.0
981
     */
982 View Code Duplication
    public static function regex( $type, $options ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
983
        self::field_loader( $type );
984
985
        $regex = false;
986
987
        if ( method_exists( self::$loaded[ $type ], 'regex' ) )
988
            $regex = self::$loaded[ $type ]->regex( $options );
989
990
        $regex = apply_filters( 'pods_field_' . $type . '_regex', $regex, $options, $type );
991
992
        return $regex;
993
    }
994
995
    /**
996
     * Setup value preparation for sprintf
997
     *
998
     * @static
999
     *
1000
     * @param $type
1001
     * @param $options
1002
     *
1003
     * @return mixed|void
1004
     * @since 2.0
1005
     */
1006 View Code Duplication
    public static function prepare( $type, $options ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1007
        self::field_loader( $type );
1008
1009
        $prepare = '%s';
1010
1011
        if ( method_exists( self::$loaded[ $type ], 'prepare' ) )
1012
            $prepare = self::$loaded[ $type ]->prepare( $options );
1013
1014
        $prepare = apply_filters( 'pods_field_' . $type . '_prepare', $prepare, $options, $type );
1015
1016
        return $prepare;
1017
    }
1018
1019
    /**
1020
     * Validate a value before it's saved
1021
     *
1022
     * @param string $type
1023
     * @param mixed $value
1024
     * @param string $name
1025
     * @param array $options
1026
     * @param array $fields
1027
     * @param array $pod
1028
     * @param int $id
1029
     * @param array|object $params
1030
     *
1031
     * @static
1032
     *
1033
     * @since 2.0
1034
     */
1035
    public static function validate( $type, $value, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
1036
        self::field_loader( $type );
1037
1038
        $validate = true;
1039
1040
        if ( 1 == pods_v( 'pre_save', $options, 1 ) && method_exists( self::$loaded[ $type ], 'validate' ) )
1041
            $validate = self::$loaded[ $type ]->validate( $value, $name, $options, $fields, $pod, $id, $params );
1042
1043
        $validate = apply_filters( 'pods_field_' . $type . '_validate', $validate, $value, $name, $options, $fields, $pod, $id, $type, $params );
1044
1045
        return $validate;
1046
    }
1047
1048
    /**
1049
     * Change the value or perform actions after validation but before saving to the DB
1050
     *
1051
     * @param string $type
1052
     * @param mixed $value
1053
     * @param int $id
1054
     * @param string $name
1055
     * @param array $options
1056
     * @param array $fields
1057
     * @param array $pod
1058
     * @param object $params
1059
     *
1060
     * @static
1061
     *
1062
     * @since 2.0
1063
     */
1064 View Code Duplication
    public static function pre_save( $type, $value, $id = null, $name = null, $options = null, $fields = null, $pod = null, $params = null ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1065
        self::field_loader( $type );
1066
1067
        if ( 1 == pods_v( 'field_pre_save', $options, 1 ) && method_exists( self::$loaded[ $type ], 'pre_save' ) )
1068
            $value = self::$loaded[ $type ]->pre_save( $value, $id, $name, $options, $fields, $pod, $params );
1069
1070
        return $value;
1071
    }
1072
1073
    /**
1074
     * Save the value to the DB
1075
     *
1076
     * @param string $type
1077
     * @param mixed $value
1078
     * @param int $id
1079
     * @param string $name
1080
     * @param array $options
1081
     * @param array $fields
1082
     * @param array $pod
1083
     * @param object $params
1084
     *
1085
     * @static
1086
     *
1087
     * @since 2.3
1088
     */
1089 View Code Duplication
    public static function save( $type, $value, $id = null, $name = null, $options = null, $fields = null, $pod = null, $params = null ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1090
        self::field_loader( $type );
1091
1092
        $saved = null;
1093
1094
        if ( 1 == pods_v( 'field_save', $options, 1 ) && method_exists( self::$loaded[ $type ], 'save' ) )
1095
            $saved = self::$loaded[ $type ]->save( $value, $id, $name, $options, $fields, $pod, $params );
1096
1097
        return $saved;
1098
    }
1099
1100
    /**
1101
     * Delete the value from the DB
1102
     *
1103
     * @param string $type
1104
     * @param int $id
1105
     * @param string $name
1106
     * @param array $options
1107
     * @param array $pod
1108
     *
1109
     * @static
1110
     *
1111
     * @since 2.3
1112
     */
1113 View Code Duplication
    public static function delete( $type, $id = null, $name = null, $options = null, $pod = null ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1114
        self::field_loader( $type );
1115
1116
        $deleted = null;
1117
1118
        if ( 1 == pods_v( 'field_delete', $options, 1 ) && method_exists( self::$loaded[ $type ], 'delete' ) )
1119
            $deleted = self::$loaded[ $type ]->delete( $id, $name, $options, $pod );
1120
1121
        return $deleted;
1122
    }
1123
1124
    /**
1125
     * Check if a user has permission to be editing a field
1126
     *
1127
     * @param $type
1128
     * @param null $name
1129
     * @param null $options
1130
     * @param null $fields
1131
     * @param null $pod
1132
     * @param null $id
1133
     * @param null $params
1134
     *
1135
     * @static
1136
     *
1137
     * @since 2.0
1138
     */
1139
    public static function permission( $type, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
1140
        $permission = pods_permission( $options );
1141
1142
        $permission = (boolean) apply_filters( 'pods_form_field_permission', $permission, $type, $name, $options, $fields, $pod, $id, $params );
1143
1144
        return $permission;
1145
    }
1146
1147
    /**
1148
     * Parse the default the value
1149
     *
1150
     * @since 2.0
1151
     */
1152
    public static function default_value( $value, $type = 'text', $name = null, $options = null, $pod = null, $id = null ) {
1153
        $default_value = pods_v( 'default_value', $options );
1154
1155
		if ( '' === $default_value || null === $default_value ) {
1156
			$default_value = $value;
1157
		}
1158
1159
        $default = pods_v( 'default', $options, $default_value, true );
1160
1161
	    if ( is_string( $default ) ) {
1162
		    $default_value = str_replace( array( '{@', '}' ), '', trim( $default ) );
1163
	    }
1164
1165
        if ( $default != $default_value && 1 == (int) pods_v( 'default_evaluate_tags', $options, 1 ) )
1166
            $default = pods_evaluate_tags( $default );
1167
1168
        $default = pods_var_raw( pods_v( 'default_value_parameter', $options ), 'request', $default, null, true );
1169
1170
        if ( $default != $value )
1171
            $value = $default;
1172
1173
        if ( is_array( $value ) )
1174
            $value = pods_serial_comma( $value );
1175
1176
        return apply_filters( 'pods_form_field_default_value', $value, $default, $type, $options, $pod, $id );
1177
    }
1178
1179
    /**
1180
     * Clean a value for use in class / id
1181
     *
1182
     * @since 2.0
1183
     */
1184
    public static function clean( $input, $noarray = false, $db_field = false ) {
1185
1186
	    $output = trim( (string) $input );
1187
1188
        $output = str_replace( '--1', 'podsfixtemp1', $output );
1189
        $output = str_replace( '__1', 'podsfixtemp2', $output );
1190
1191
        if ( false !== $noarray ) {
1192
	        $output = preg_replace( '/\[podsfixtemp\d+\]/', '-', $output );
1193
	        $output = preg_replace( '/\[\d*\]/', '-', $output );
1194
        }
1195
1196
        $output = str_replace( array( '[', ']' ), '-', $output );
1197
1198
	    $output = pods_clean_name( $output );
1199
1200
        $output = preg_replace( '/([^a-z0-9\-_])/', '', $output );
1201
	    $output = preg_replace( '/(_){2,}/', '_', $output );
1202
	    $output = preg_replace( '/(-){2,}/', '-', $output );
1203
1204
	    if ( true !== $db_field ) {
1205
		    $output = str_replace( '_', '-', $output );
1206
	    }
1207
1208
	    $output = rtrim( $output, '-' );
1209
1210
        $output = str_replace( 'podsfixtemp1', '--1', $output );
1211
        $output = str_replace( 'podsfixtemp2', '__1', $output );
1212
1213
        return $output;
1214
    }
1215
1216
    /**
1217
     * Run admin_init methods for each field type
1218
     *
1219
     * @since 2.3
1220
     */
1221
    public function admin_init() {
1222
        $admin_field_types = pods_transient_get( 'pods_form_admin_init_field_types' );
1223
1224
        if ( empty( $admin_field_types ) ) {
1225
            $admin_field_types = array();
1226
1227
            $field_types = self::field_types();
1228
1229
            foreach ( $field_types as $field_type => $field_type_data ) {
1230
                $has_admin_init = self::field_method( $field_type_data[ 'type' ], 'admin_init' );
1231
1232
                if ( false !== $has_admin_init ) {
1233
	                $admin_field_types[] = $field_type;
1234
                }
1235
            }
1236
1237
            pods_transient_set( 'pods_form_admin_init_field_types', $admin_field_types );
1238
        }
1239
        else {
1240
            foreach ( $admin_field_types as $field_type ) {
1241
                self::field_method( $field_type, 'admin_init' );
1242
            }
1243
        }
1244
    }
1245
1246
    /**
1247
     * Autoload a Field Type's class
1248
     *
1249
     * @param string $field_type Field Type indentifier
1250
     * @param string $file The Field Type class file location
1251
     *
1252
     * @return string
1253
     * @access public
1254
     * @static
1255
     * @since 2.0
1256
     */
1257
    public static function field_loader( $field_type, $file = '' ) {
1258
        if ( isset( self::$loaded[ $field_type ] ) ) {
1259
            $class_vars = get_class_vars( get_class( self::$loaded[ $field_type ] ) ); // PHP 5.2.x workaround
1260
1261
            self::$field_group = ( isset( $class_vars[ 'group' ] ) ? $class_vars[ 'group' ] : '' );
1262
            self::$field_type = $class_vars[ 'type' ];
1263
1264
            if ( 'Unknown' != $class_vars[ 'label' ] )
1265
                return self::$loaded[ $field_type ];
1266
        }
1267
1268
        include_once PODS_DIR . 'classes/PodsField.php';
1269
1270
        $field_type = self::clean( $field_type, true, true );
1271
1272
        $class_name = ucfirst( $field_type );
1273
        $class_name = "PodsField_{$class_name}";
1274
1275
        $content_dir = realpath( WP_CONTENT_DIR );
1276
        $plugins_dir = realpath( WP_PLUGIN_DIR );
1277
        $muplugins_dir = realpath( WPMU_PLUGIN_DIR );
1278
        $abspath_dir = realpath( ABSPATH );
1279
        $pods_dir = realpath( PODS_DIR );
1280
1281
        if ( !class_exists( $class_name ) ) {
1282
            if ( isset( self::$field_types[ $field_type ] ) && !empty( self::$field_types[ $field_type ][ 'file' ] ) )
1283
                $file = realpath( self::$field_types[ $field_type ][ 'file' ] );
1284
1285
            if ( !empty( $file ) && 0 === strpos( $file, $abspath_dir ) && file_exists( $file ) )
1286
                include_once $file;
1287
            else {
1288
                $file = str_replace( '../', '', apply_filters( 'pods_form_field_include', PODS_DIR . 'classes/fields/' . basename( $field_type ) . '.php', $field_type ) );
1289
                $file = realpath( $file );
1290
1291
                if ( file_exists( $file ) && ( 0 === strpos( $file, $pods_dir ) || 0 === strpos( $file, $content_dir ) || 0 === strpos( $file, $plugins_dir ) || 0 === strpos( $file, $muplugins_dir ) || 0 === strpos( $file, $abspath_dir ) ) )
1292
                    include_once $file;
1293
            }
1294
        }
1295
1296
        if ( class_exists( $class_name ) )
1297
            $class = new $class_name();
1298
        else {
1299
            $class = new PodsField();
1300
            $class_name = 'PodsField';
1301
        }
1302
1303
        $class_vars = get_class_vars( $class_name ); // PHP 5.2.x workaround
1304
1305
        self::$field_group = ( isset( $class_vars[ 'group' ] ) ? $class_vars[ 'group' ] : '' );
1306
        self::$field_type = $class_vars[ 'type' ];
1307
1308
        self::$loaded[ $field_type ] =& $class;
1309
1310
        return self::$loaded[ $field_type ];
1311
    }
1312
1313
    /**
1314
     * Run a method from a Field Type's class
1315
     *
1316
     * @param string $field_type Field Type indentifier
0 ignored issues
show
Bug introduced by
There is no parameter named $field_type. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1317
     * @param string $method Method name
0 ignored issues
show
Bug introduced by
There is no parameter named $method. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1318
     * @param mixed $arg More arguments
0 ignored issues
show
Bug introduced by
There is no parameter named $arg. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
1319
     *
1320
     * @return mixed
1321
     * @access public
1322
     * @static
1323
     * @since 2.0
1324
     */
1325
    public static function field_method() {
1326
        $args = func_get_args();
1327
1328
        if ( empty( $args ) && count( $args ) < 2 )
1329
            return false;
1330
1331
        $field_type = array_shift( $args );
1332
        $method = array_shift( $args );
1333
1334
        $class = self::field_loader( $field_type );
1335
1336
        if ( method_exists( $class, $method ) )
1337
            return call_user_func_array( array( $class, $method ), $args );
1338
1339
        return false;
1340
    }
1341
1342
    /**
1343
     * Add a new Pod field type
1344
     *
1345
     * @param string $type The new field type identifier
1346
     * @param string $file The new field type class file location
1347
     *
1348
     * @return array Field Type data
1349
     *
1350
     * @since 2.3
1351
     */
1352
    public static function register_field_type( $type, $file = null ) {
1353
        $field_type = pods_transient_get( 'pods_field_type_' . $type );
1354
1355
        if ( empty( $field_type ) || $field_type[ 'type' ] != $type || $field_type[ 'file' ] != $file ) {
1356
            self::field_loader( $type, $file );
1357
1358
            $class_vars = get_class_vars( get_class( self::$loaded[ $type ] ) ); // PHP 5.2.x workaround
1359
1360
            self::$field_types[ $type ] = $class_vars;
1361
            self::$field_types[ $type ][ 'file' ] = $file;
1362
1363
            pods_transient_set( 'pods_field_type_' . $type, self::$field_types[ $type ] );
1364
        }
1365
        else
1366
            self::$field_types[ $type ] = $field_type;
1367
1368
        return self::$field_types[ $type ];
1369
    }
1370
1371
    /**
1372
     * Get a list of all available field types and include
1373
     *
1374
     * @return array Registered Field Types data
1375
     *
1376
     * @since 2.3
1377
     */
1378
    public static function field_types() {
1379
        $field_types = array(
1380
            'text',
1381
            'website',
1382
            'link',
1383
            'phone',
1384
            'email',
1385
            'password',
1386
            'paragraph',
1387
            'wysiwyg',
1388
            'code',
1389
            'datetime',
1390
            'date',
1391
            'time',
1392
            'number',
1393
            'currency',
1394
            'file',
1395
            'avatar',
1396
            'oembed',
1397
            'pick',
1398
            'boolean',
1399
            'color',
1400
            'slug',
1401
        );
1402
1403
        $field_types = array_merge( $field_types, array_keys( self::$field_types ) );
1404
1405
        $field_types = array_filter( array_unique( $field_types ) );
1406
1407
        $types = apply_filters( 'pods_api_field_types', $field_types );
1408
1409
        $field_types = pods_transient_get( 'pods_field_types' );
1410
1411
        if ( empty( $field_types ) || count( $types ) != count( $field_types ) ) {
1412
            $field_types = array();
1413
1414
            foreach ( $types as $field_type ) {
1415
                $file = null;
1416
1417
                if ( isset( self::$field_types[ $field_type ] ) )
1418
                    $file = self::$field_types[ $field_type ][ 'file' ];
1419
1420
                self::field_loader( $field_type, $file );
1421
1422
                if ( !isset( self::$loaded[ $field_type ] ) || !is_object( self::$loaded[ $field_type ] ) )
1423
                    continue;
1424
1425
                $class_vars = get_class_vars( get_class( self::$loaded[ $field_type ] ) ); // PHP 5.2.x workaround
1426
1427
                $field_types[ $field_type ] = $class_vars;
1428
                $field_types[ $field_type ][ 'file' ] = $file;
1429
            }
1430
1431
            self::$field_types = $field_types;
1432
1433
            pods_transient_set( 'pods_field_types', self::$field_types );
1434
        }
1435
        else
1436
            self::$field_types = array_merge( $field_types, self::$field_types );
1437
1438
        return self::$field_types;
1439
    }
1440
1441
    /**
1442
     * Get list of available tableless field types
1443
     *
1444
     * @return array Tableless field types
1445
     *
1446
     * @since 2.3
1447
     */
1448
    public static function tableless_field_types() {
1449
	    static $field_types = null;
1450
1451
	    if ( null === $field_types ) {
1452
		    $field_types = array(
1453
			    'pick',
1454
			    'file',
1455
			    'avatar',
1456
			    'taxonomy',
1457
			    'comment',
1458
		    );
1459
1460
		    $field_types = apply_filters( 'pods_tableless_field_types', $field_types );
1461
	    }
1462
	    return $field_types;
1463
    }
1464
1465
    /**
1466
     * Get list of available file field types
1467
     *
1468
     * @return array File field types
1469
     *
1470
     * @since 2.3
1471
     */
1472 View Code Duplication
    public static function file_field_types() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1473
	    static $field_types = null;
1474
1475
	    if ( null === $field_types ) {
1476
		    $field_types = array( 'file', 'avatar' );
1477
1478
		    $field_types = apply_filters( 'pods_file_field_types', $field_types );
1479
	    }
1480
	    return $field_types;
1481
    }
1482
1483
    /**
1484
     * Get list of available repeatable field types
1485
     *
1486
     * @return array Repeatable field types
1487
     *
1488
     * @since 2.3
1489
     */
1490
    public static function repeatable_field_types() {
1491
	    static $field_types = null;
1492
1493
	    if ( null === $field_types ) {
1494
		    $field_types = array(
1495
			    'code',
1496
			    'color',
1497
			    'currency',
1498
			    'date',
1499
			    'datetime',
1500
			    'email',
1501
			    'number',
1502
			    'paragraph',
1503
			    'phone',
1504
			    'text',
1505
			    'time',
1506
			    'website',
1507
			    'wysiwyg'
1508
		    );
1509
1510
		    $field_types = apply_filters( 'pods_repeatable_field_types', $field_types );
1511
	    }
1512
	    return $field_types;
1513
    }
1514
1515
    /**
1516
     * Get list of available number field types
1517
     *
1518
     * @return array Number field types
1519
     *
1520
     * @since 2.3
1521
     */
1522 View Code Duplication
    public static function number_field_types() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1523
	    static $field_types = null;
1524
1525
	    if ( null === $field_types ) {
1526
		    $field_types = array( 'currency', 'number' );
1527
1528
		    $field_types = apply_filters( 'pods_tableless_field_types', $field_types );
1529
	    }
1530
	    return $field_types;
1531
    }
1532
1533
    /**
1534
     * Get list of available date field types
1535
     *
1536
     * @return array Date field types
1537
     *
1538
     * @since 2.3
1539
     */
1540 View Code Duplication
    public static function date_field_types() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1541
	    static $field_types = null;
1542
1543
	    if ( null === $field_types ) {
1544
		    $field_types = array( 'date', 'datetime', 'time' );
1545
1546
		    $field_types = apply_filters( 'pods_tableless_field_types', $field_types );
1547
	    }
1548
	    return $field_types;
1549
    }
1550
1551
    /**
1552
     * Get list of available text field types
1553
     *
1554
     * @return array Text field types
1555
     *
1556
     * @since 2.3
1557
     */
1558
    public static function text_field_types() {
1559
	    static $field_types = null;
1560
1561
	    if ( null === $field_types ) {
1562
		    $field_types = array( 'code', 'paragraph', 'slug', 'password', 'text', 'wysiwyg' );
1563
1564
		    $field_types = apply_filters( 'pods_text_field_types', $field_types );
1565
	    }
1566
	    return $field_types;
1567
    }
1568
1569
    /**
1570
     * Get list of available text field types
1571
     *
1572
     * @return array Text field types
1573
     *
1574
     * @since 2.3
1575
     */
1576
    public static function block_field_types() {
1577
	    static $field_types = null;
1578
1579
	    if ( null === $field_types ) {
1580
		    $field_types = array( 'heading', 'html' );
1581
1582
		    /**
1583
		     * Returns the available text field types
1584
		     *
1585
		     * @since unknown
1586
		     *
1587
		     * @param object $field_types Outputs the field types
1588
		     */
1589
1590
		    $field_types = apply_filters( 'pods_block_field_types', $field_types );
1591
	    }
1592
	    return $field_types;
1593
    }
1594
1595
	/**
1596
	 * Get list of available text field types
1597
	 *
1598
	 * @return array Text field types
1599
	 *
1600
	 * @since 2.3
1601
	 */
1602
	public static function simple_tableless_objects() {
1603
		static $object_types = null;
1604
1605
		if ( null === $object_types ) {
1606
			$object_types = PodsForm::field_method( 'pick', 'simple_objects' );
1607
		}
1608
		return $object_types;
1609
	}
1610
1611
	}
1612