Completed
Push — 2.x ( 971a6c...befcfa )
by Scott Kingsley
08:24 queued 03:02
created

PodsForm::field()   F

Complexity

Conditions 25
Paths 252

Size

Total Lines 100
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 25
eloc 36
nc 252
nop 6
dl 0
loc 100
rs 3.5466
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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
        $options = (array) $options;
835
836
        $depends_on = $excludes_on = array();
837
        if ( isset( $options[ 'depends-on' ] ) )
838
            $depends_on = (array) $options[ 'depends-on' ];
839
840
        if ( isset( $options[ 'excludes-on' ] ) )
841
            $excludes_on = (array) $options[ 'excludes-on' ];
842
843
        $classes = array();
844
845 View Code Duplication
        if ( !empty( $depends_on ) ) {
846
            $classes[] = 'pods-depends-on';
847
848
            foreach ( $depends_on as $depends => $on ) {
849
                $classes[] = 'pods-depends-on-' . $prefix . self::clean( $depends, true );
850
851
                if ( !is_bool( $on ) ) {
852
                    $on = (array) $on;
853
854
                    foreach ( $on as $o ) {
855
                        $classes[] = 'pods-depends-on-' . $prefix . self::clean( $depends, true ) . '-' . self::clean( $o, true );
856
                    }
857
                }
858
            }
859
        }
860
861 View Code Duplication
        if ( !empty( $excludes_on ) ) {
862
            $classes[] = 'pods-excludes-on';
863
            foreach ( $excludes_on as $excludes => $on ) {
864
                $classes[] = 'pods-excludes-on-' . $prefix . self::clean( $excludes, true );
865
866
                $on = (array) $on;
867
868
                foreach ( $on as $o ) {
869
                    $classes[] = 'pods-excludes-on-' . $prefix . self::clean( $excludes, true ) . '-' . self::clean( $o, true );
870
                }
871
            }
872
        }
873
874
        $classes = implode( ' ', $classes );
875
876
        return $classes;
877
    }
878
879
    /**
880
     * Change the value of the field
881
     *
882
     * @param mixed $value
883
     * @param string $name
884
     * @param array $options
885
     * @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...
886
     * @param array $pod
887
     * @param int $id
888
     * @param array $traverse
889
     *
890
     * @since 2.3
891
     */
892
    public static function value( $type, $value = null, $name = null, $options = null, $pod = null, $id = null, $traverse = null ) {
893
        self::field_loader( $type );
894
895
        if ( in_array( $type, self::repeatable_field_types() ) && 1 == pods_v( $type . '_repeatable', $options, 0 ) && !is_array( $value ) ) {
896
            if ( 0 < strlen( $value ) ) {
897
                $simple = @json_decode( $value, true );
898
899
                if ( is_array( $simple ) )
900
                    $value = $simple;
901
                else
902
                    $value = (array) $value;
903
            }
904
            else
905
                $value = array();
906
        }
907
908
        if ( method_exists( self::$loaded[ $type ], 'value' ) ) {
909
            if ( is_array( $value ) && in_array( $type, self::tableless_field_types() ) ) {
910 View Code Duplication
                foreach ( $value as &$display_value ) {
911
                    $display_value = call_user_func_array( array( self::$loaded[ $type ], 'value' ), array( $display_value, $name, $options, $pod, $id, $traverse ) );
912
                }
913
            }
914 View Code Duplication
            else
915
                $value = call_user_func_array( array( self::$loaded[ $type ], 'value' ), array( $value, $name, $options, $pod, $id, $traverse ) );
916
        }
917
918
        return $value;
919
    }
920
921
    /**
922
     * Change the way the value of the field is displayed with Pods::get
923
     *
924
     * @param mixed $value
925
     * @param string $name
926
     * @param array $options
927
     * @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...
928
     * @param array $pod
929
     * @param int $id
930
     * @param array $traverse
931
     *
932
     * @since 2.0
933
     */
934
    public static function display( $type, $value = null, $name = null, $options = null, $pod = null, $id = null, $traverse = null ) {
935
        self::field_loader( $type );
936
937
        $tableless_field_types = self::tableless_field_types();
938
939
        if ( method_exists( self::$loaded[ $type ], 'display' ) ) {
940
            if ( is_array( $value ) && !in_array( $type, $tableless_field_types ) ) {
941 View Code Duplication
                foreach ( $value as $k => $display_value ) {
942
                    $value[ $k ] = call_user_func_array( array( self::$loaded[ $type ], 'display' ), array( $display_value, $name, $options, $pod, $id, $traverse ) );
943
                }
944
            }
945 View Code Duplication
            else
946
                $value = call_user_func_array( array( self::$loaded[ $type ], 'display' ), array( $value, $name, $options, $pod, $id, $traverse ) );
947
        }
948
949
        $value = apply_filters( 'pods_form_display_' . $type, $value, $name, $options, $pod, $id, $traverse );
950
951
        return $value;
952
    }
953
954
    /**
955
     * Setup regex for JS / PHP
956
     *
957
     * @static
958
     *
959
     * @param $type
960
     * @param $options
961
     *
962
     * @return mixed|void
963
     * @since 2.0
964
     */
965 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...
966
        self::field_loader( $type );
967
968
        $regex = false;
969
970
        if ( method_exists( self::$loaded[ $type ], 'regex' ) )
971
            $regex = self::$loaded[ $type ]->regex( $options );
972
973
        $regex = apply_filters( 'pods_field_' . $type . '_regex', $regex, $options, $type );
974
975
        return $regex;
976
    }
977
978
    /**
979
     * Setup value preparation for sprintf
980
     *
981
     * @static
982
     *
983
     * @param $type
984
     * @param $options
985
     *
986
     * @return mixed|void
987
     * @since 2.0
988
     */
989 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...
990
        self::field_loader( $type );
991
992
        $prepare = '%s';
993
994
        if ( method_exists( self::$loaded[ $type ], 'prepare' ) )
995
            $prepare = self::$loaded[ $type ]->prepare( $options );
996
997
        $prepare = apply_filters( 'pods_field_' . $type . '_prepare', $prepare, $options, $type );
998
999
        return $prepare;
1000
    }
1001
1002
    /**
1003
     * Validate a value before it's saved
1004
     *
1005
     * @param string $type
1006
     * @param mixed $value
1007
     * @param string $name
1008
     * @param array $options
1009
     * @param array $fields
1010
     * @param array $pod
1011
     * @param int $id
1012
     * @param array|object $params
1013
     *
1014
     * @static
1015
     *
1016
     * @since 2.0
1017
     */
1018
    public static function validate( $type, $value, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
1019
        self::field_loader( $type );
1020
1021
        $validate = true;
1022
1023
        if ( 1 == pods_v( 'pre_save', $options, 1 ) && method_exists( self::$loaded[ $type ], 'validate' ) )
1024
            $validate = self::$loaded[ $type ]->validate( $value, $name, $options, $fields, $pod, $id, $params );
1025
1026
        $validate = apply_filters( 'pods_field_' . $type . '_validate', $validate, $value, $name, $options, $fields, $pod, $id, $type, $params );
1027
1028
        return $validate;
1029
    }
1030
1031
    /**
1032
     * Change the value or perform actions after validation but before saving to the DB
1033
     *
1034
     * @param string $type
1035
     * @param mixed $value
1036
     * @param int $id
1037
     * @param string $name
1038
     * @param array $options
1039
     * @param array $fields
1040
     * @param array $pod
1041
     * @param object $params
1042
     *
1043
     * @static
1044
     *
1045
     * @since 2.0
1046
     */
1047 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...
1048
        self::field_loader( $type );
1049
1050
        if ( 1 == pods_v( 'field_pre_save', $options, 1 ) && method_exists( self::$loaded[ $type ], 'pre_save' ) )
1051
            $value = self::$loaded[ $type ]->pre_save( $value, $id, $name, $options, $fields, $pod, $params );
1052
1053
        return $value;
1054
    }
1055
1056
    /**
1057
     * Save the value to the DB
1058
     *
1059
     * @param string $type
1060
     * @param mixed $value
1061
     * @param int $id
1062
     * @param string $name
1063
     * @param array $options
1064
     * @param array $fields
1065
     * @param array $pod
1066
     * @param object $params
1067
     *
1068
     * @static
1069
     *
1070
     * @since 2.3
1071
     */
1072 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...
1073
        self::field_loader( $type );
1074
1075
        $saved = null;
1076
1077
        if ( 1 == pods_v( 'field_save', $options, 1 ) && method_exists( self::$loaded[ $type ], 'save' ) )
1078
            $saved = self::$loaded[ $type ]->save( $value, $id, $name, $options, $fields, $pod, $params );
1079
1080
        return $saved;
1081
    }
1082
1083
    /**
1084
     * Delete the value from the DB
1085
     *
1086
     * @param string $type
1087
     * @param int $id
1088
     * @param string $name
1089
     * @param array $options
1090
     * @param array $pod
1091
     *
1092
     * @static
1093
     *
1094
     * @since 2.3
1095
     */
1096 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...
1097
        self::field_loader( $type );
1098
1099
        $deleted = null;
1100
1101
        if ( 1 == pods_v( 'field_delete', $options, 1 ) && method_exists( self::$loaded[ $type ], 'delete' ) )
1102
            $deleted = self::$loaded[ $type ]->delete( $id, $name, $options, $pod );
1103
1104
        return $deleted;
1105
    }
1106
1107
    /**
1108
     * Check if a user has permission to be editing a field
1109
     *
1110
     * @param $type
1111
     * @param null $name
1112
     * @param null $options
1113
     * @param null $fields
1114
     * @param null $pod
1115
     * @param null $id
1116
     * @param null $params
1117
     *
1118
     * @static
1119
     *
1120
     * @since 2.0
1121
     */
1122
    public static function permission( $type, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
1123
        $permission = pods_permission( $options );
1124
1125
        $permission = (boolean) apply_filters( 'pods_form_field_permission', $permission, $type, $name, $options, $fields, $pod, $id, $params );
1126
1127
        return $permission;
1128
    }
1129
1130
    /**
1131
     * Parse the default the value
1132
     *
1133
     * @since 2.0
1134
     */
1135
    public static function default_value( $value, $type = 'text', $name = null, $options = null, $pod = null, $id = null ) {
0 ignored issues
show
Unused Code introduced by
The parameter $name is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1136
        $default_value = pods_v( 'default_value', $options );
1137
1138
		if ( '' === $default_value || null === $default_value ) {
1139
			$default_value = $value;
1140
		}
1141
1142
        $default = pods_v( 'default', $options, $default_value, true );
1143
1144
	    if ( is_string( $default ) ) {
1145
		    $default_value = str_replace( array( '{@', '}' ), '', trim( $default ) );
1146
	    }
1147
1148
        if ( $default != $default_value && 1 == (int) pods_v( 'default_evaluate_tags', $options, 1 ) )
1149
            $default = pods_evaluate_tags( $default );
1150
1151
        $default = pods_var_raw( pods_v( 'default_value_parameter', $options ), 'request', $default, null, true );
1152
1153
        if ( $default != $value )
1154
            $value = $default;
1155
1156
        if ( is_array( $value ) )
1157
            $value = pods_serial_comma( $value );
1158
1159
        return apply_filters( 'pods_form_field_default_value', $value, $default, $type, $options, $pod, $id );
1160
    }
1161
1162
    /**
1163
     * Clean a value for use in class / id
1164
     *
1165
     * @since 2.0
1166
     */
1167
    public static function clean( $input, $noarray = false, $db_field = false ) {
1168
1169
	    $output = trim( (string) $input );
1170
1171
        $output = str_replace( '--1', 'podsfixtemp1', $output );
1172
        $output = str_replace( '__1', 'podsfixtemp2', $output );
1173
1174
        if ( false !== $noarray ) {
1175
	        $output = preg_replace( '/\[podsfixtemp\d+\]/', '-', $output );
1176
	        $output = preg_replace( '/\[\d*\]/', '-', $output );
1177
        }
1178
1179
        $output = str_replace( array( '[', ']' ), '-', $output );
1180
1181
	    $output = pods_clean_name( $output );
1182
1183
        $output = preg_replace( '/([^a-z0-9\-_])/', '', $output );
1184
	    $output = preg_replace( '/(_){2,}/', '_', $output );
1185
	    $output = preg_replace( '/(-){2,}/', '-', $output );
1186
1187
	    if ( true !== $db_field ) {
1188
		    $output = str_replace( '_', '-', $output );
1189
	    }
1190
1191
	    $output = rtrim( $output, '-' );
1192
1193
        $output = str_replace( 'podsfixtemp1', '--1', $output );
1194
        $output = str_replace( 'podsfixtemp2', '__1', $output );
1195
1196
        return $output;
1197
    }
1198
1199
    /**
1200
     * Run admin_init methods for each field type
1201
     *
1202
     * @since 2.3
1203
     */
1204
    public function admin_init() {
1205
        $admin_field_types = pods_transient_get( 'pods_form_admin_init_field_types' );
1206
1207
        if ( empty( $admin_field_types ) ) {
1208
            $admin_field_types = array();
1209
1210
            $field_types = self::field_types();
1211
1212
            foreach ( $field_types as $field_type => $field_type_data ) {
1213
                $has_ajax = self::field_method( $field_type_data[ 'type' ], 'admin_init' );
1214
1215
                if ( false !== $has_ajax )
1216
                    $admin_field_types[] = $field_type;
1217
            }
1218
1219
            pods_transient_set( 'pods_form_admin_init_field_types', $admin_field_types );
1220
        }
1221
        else {
1222
            foreach ( $admin_field_types as $field_type ) {
1223
                self::field_method( $field_type, 'admin_init' );
1224
            }
1225
        }
1226
    }
1227
1228
    /**
1229
     * Autoload a Field Type's class
1230
     *
1231
     * @param string $field_type Field Type indentifier
1232
     * @param string $file The Field Type class file location
1233
     *
1234
     * @return string
1235
     * @access public
1236
     * @static
1237
     * @since 2.0
1238
     */
1239
    public static function field_loader( $field_type, $file = '' ) {
1240
        if ( isset( self::$loaded[ $field_type ] ) ) {
1241
            $class_vars = get_class_vars( get_class( self::$loaded[ $field_type ] ) ); // PHP 5.2.x workaround
1242
1243
            self::$field_group = ( isset( $class_vars[ 'group' ] ) ? $class_vars[ 'group' ] : '' );
1244
            self::$field_type = $class_vars[ 'type' ];
1245
1246
            if ( 'Unknown' != $class_vars[ 'label' ] )
1247
                return self::$loaded[ $field_type ];
1248
        }
1249
1250
        include_once PODS_DIR . 'classes/PodsField.php';
1251
1252
        $field_type = self::clean( $field_type, true, true );
1253
1254
        $class_name = ucfirst( $field_type );
1255
        $class_name = "PodsField_{$class_name}";
1256
1257
        $content_dir = realpath( WP_CONTENT_DIR );
1258
        $plugins_dir = realpath( WP_PLUGIN_DIR );
1259
        $muplugins_dir = realpath( WPMU_PLUGIN_DIR );
1260
        $abspath_dir = realpath( ABSPATH );
1261
        $pods_dir = realpath( PODS_DIR );
1262
1263
        if ( !class_exists( $class_name ) ) {
1264
            if ( isset( self::$field_types[ $field_type ] ) && !empty( self::$field_types[ $field_type ][ 'file' ] ) )
1265
                $file = realpath( self::$field_types[ $field_type ][ 'file' ] );
1266
1267
            if ( !empty( $file ) && 0 === strpos( $file, $abspath_dir ) && file_exists( $file ) )
1268
                include_once $file;
1269
            else {
1270
                $file = str_replace( '../', '', apply_filters( 'pods_form_field_include', PODS_DIR . 'classes/fields/' . basename( $field_type ) . '.php', $field_type ) );
1271
                $file = realpath( $file );
1272
1273
                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 ) ) )
1274
                    include_once $file;
1275
            }
1276
        }
1277
1278
        if ( class_exists( $class_name ) )
1279
            $class = new $class_name();
1280
        else {
1281
            $class = new PodsField();
1282
            $class_name = 'PodsField';
1283
        }
1284
1285
        $class_vars = get_class_vars( $class_name ); // PHP 5.2.x workaround
1286
1287
        self::$field_group = ( isset( $class_vars[ 'group' ] ) ? $class_vars[ 'group' ] : '' );
1288
        self::$field_type = $class_vars[ 'type' ];
1289
1290
        self::$loaded[ $field_type ] =& $class;
1291
1292
        return self::$loaded[ $field_type ];
1293
    }
1294
1295
    /**
1296
     * Run a method from a Field Type's class
1297
     *
1298
     * @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...
1299
     * @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...
1300
     * @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...
1301
     *
1302
     * @return mixed
1303
     * @access public
1304
     * @static
1305
     * @since 2.0
1306
     */
1307
    public static function field_method() {
1308
        $args = func_get_args();
1309
1310
        if ( empty( $args ) && count( $args ) < 2 )
1311
            return false;
1312
1313
        $field_type = array_shift( $args );
1314
        $method = array_shift( $args );
1315
1316
        $class = self::field_loader( $field_type );
1317
1318
        if ( method_exists( $class, $method ) )
1319
            return call_user_func_array( array( $class, $method ), $args );
1320
1321
        return false;
1322
    }
1323
1324
    /**
1325
     * Add a new Pod field type
1326
     *
1327
     * @param string $type The new field type identifier
1328
     * @param string $file The new field type class file location
1329
     *
1330
     * @return array Field Type data
1331
     *
1332
     * @since 2.3
1333
     */
1334
    public static function register_field_type( $type, $file = null ) {
1335
        $field_type = pods_transient_get( 'pods_field_type_' . $type );
1336
1337
        if ( empty( $field_type ) || $field_type[ 'type' ] != $type || $field_type[ 'file' ] != $file ) {
1338
            self::field_loader( $type, $file );
1339
1340
            $class_vars = get_class_vars( get_class( self::$loaded[ $type ] ) ); // PHP 5.2.x workaround
1341
1342
            self::$field_types[ $type ] = $class_vars;
1343
            self::$field_types[ $type ][ 'file' ] = $file;
1344
1345
            pods_transient_set( 'pods_field_type_' . $type, self::$field_types[ $type ] );
1346
        }
1347
        else
1348
            self::$field_types[ $type ] = $field_type;
1349
1350
        return self::$field_types[ $type ];
1351
    }
1352
1353
    /**
1354
     * Get a list of all available field types and include
1355
     *
1356
     * @return array Registered Field Types data
1357
     *
1358
     * @since 2.3
1359
     */
1360
    public static function field_types() {
1361
        $field_types = array(
1362
            'text',
1363
            'website',
1364
            'link',
1365
            'phone',
1366
            'email',
1367
            'password',
1368
            'paragraph',
1369
            'wysiwyg',
1370
            'code',
1371
            'datetime',
1372
            'date',
1373
            'time',
1374
            'number',
1375
            'currency',
1376
            'file',
1377
            'avatar',
1378
            'oembed',
1379
            'pick',
1380
            'boolean',
1381
            'color',
1382
            'slug',
1383
        );
1384
1385
        $field_types = array_merge( $field_types, array_keys( self::$field_types ) );
1386
1387
        $field_types = array_filter( array_unique( $field_types ) );
1388
1389
        $types = apply_filters( 'pods_api_field_types', $field_types );
1390
1391
        $field_types = pods_transient_get( 'pods_field_types' );
1392
1393
        if ( empty( $field_types ) || count( $types ) != count( $field_types ) ) {
1394
            $field_types = array();
1395
1396
            foreach ( $types as $field_type ) {
1397
                $file = null;
1398
1399
                if ( isset( self::$field_types[ $field_type ] ) )
1400
                    $file = self::$field_types[ $field_type ][ 'file' ];
1401
1402
                self::field_loader( $field_type, $file );
1403
1404
                if ( !isset( self::$loaded[ $field_type ] ) || !is_object( self::$loaded[ $field_type ] ) )
1405
                    continue;
1406
1407
                $class_vars = get_class_vars( get_class( self::$loaded[ $field_type ] ) ); // PHP 5.2.x workaround
1408
1409
                $field_types[ $field_type ] = $class_vars;
1410
                $field_types[ $field_type ][ 'file' ] = $file;
1411
            }
1412
1413
            self::$field_types = $field_types;
1414
1415
            pods_transient_set( 'pods_field_types', self::$field_types );
1416
        }
1417
        else
1418
            self::$field_types = array_merge( $field_types, self::$field_types );
1419
1420
        return self::$field_types;
1421
    }
1422
1423
    /**
1424
     * Get list of available tableless field types
1425
     *
1426
     * @return array Tableless field types
1427
     *
1428
     * @since 2.3
1429
     */
1430 View Code Duplication
    public static function tableless_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...
1431
	    static $field_types = null;
1432
1433
	    if ( null === $field_types ) {
1434
		    $field_types = array( 'pick', 'file', 'avatar', 'taxonomy' );
1435
1436
		    $field_types = apply_filters( 'pods_tableless_field_types', $field_types );
1437
	    }
1438
	    return $field_types;
1439
    }
1440
1441
    /**
1442
     * Get list of available file field types
1443
     *
1444
     * @return array File field types
1445
     *
1446
     * @since 2.3
1447
     */
1448 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...
1449
	    static $field_types = null;
1450
1451
	    if ( null === $field_types ) {
1452
		    $field_types = array( 'file', 'avatar' );
1453
1454
		    $field_types = apply_filters( 'pods_file_field_types', $field_types );
1455
	    }
1456
	    return $field_types;
1457
    }
1458
1459
    /**
1460
     * Get list of available repeatable field types
1461
     *
1462
     * @return array Repeatable field types
1463
     *
1464
     * @since 2.3
1465
     */
1466
    public static function repeatable_field_types() {
1467
	    static $field_types = null;
1468
1469
	    if ( null === $field_types ) {
1470
		    $field_types = array(
1471
			    'code',
1472
			    'color',
1473
			    'currency',
1474
			    'date',
1475
			    'datetime',
1476
			    'email',
1477
			    'number',
1478
			    'paragraph',
1479
			    'phone',
1480
			    'text',
1481
			    'time',
1482
			    'website',
1483
			    'wysiwyg'
1484
		    );
1485
1486
		    $field_types = apply_filters( 'pods_repeatable_field_types', $field_types );
1487
	    }
1488
	    return $field_types;
1489
    }
1490
1491
    /**
1492
     * Get list of available number field types
1493
     *
1494
     * @return array Number field types
1495
     *
1496
     * @since 2.3
1497
     */
1498 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...
1499
	    static $field_types = null;
1500
1501
	    if ( null === $field_types ) {
1502
		    $field_types = array( 'currency', 'number' );
1503
1504
		    $field_types = apply_filters( 'pods_tableless_field_types', $field_types );
1505
	    }
1506
	    return $field_types;
1507
    }
1508
1509
    /**
1510
     * Get list of available date field types
1511
     *
1512
     * @return array Date field types
1513
     *
1514
     * @since 2.3
1515
     */
1516 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...
1517
	    static $field_types = null;
1518
1519
	    if ( null === $field_types ) {
1520
		    $field_types = array( 'date', 'datetime', 'time' );
1521
1522
		    $field_types = apply_filters( 'pods_tableless_field_types', $field_types );
1523
	    }
1524
	    return $field_types;
1525
    }
1526
1527
    /**
1528
     * Get list of available text field types
1529
     *
1530
     * @return array Text field types
1531
     *
1532
     * @since 2.3
1533
     */
1534
    public static function text_field_types() {
1535
	    static $field_types = null;
1536
1537
	    if ( null === $field_types ) {
1538
		    $field_types = array( 'code', 'paragraph', 'slug', 'password', 'text', 'wysiwyg' );
1539
1540
		    $field_types = apply_filters( 'pods_text_field_types', $field_types );
1541
	    }
1542
	    return $field_types;
1543
    }
1544
1545
    /**
1546
     * Get list of available text field types
1547
     *
1548
     * @return array Text field types
1549
     *
1550
     * @since 2.3
1551
     */
1552
    public static function block_field_types() {
1553
	    static $field_types = null;
1554
1555
	    if ( null === $field_types ) {
1556
		    $field_types = array( 'heading', 'html' );
1557
1558
		    /**
1559
		     * Returns the available text field types
1560
		     *
1561
		     * @since unknown
1562
		     *
1563
		     * @param object $field_types Outputs the field types
1564
		     */
1565
1566
		    $field_types = apply_filters( 'pods_block_field_types', $field_types );
1567
	    }
1568
	    return $field_types;
1569
    }
1570
1571
	/**
1572
	 * Get list of available text field types
1573
	 *
1574
	 * @return array Text field types
1575
	 *
1576
	 * @since 2.3
1577
	 */
1578
	public static function simple_tableless_objects() {
1579
		static $object_types = null;
1580
1581
		if ( null === $object_types ) {
1582
			$object_types = PodsForm::field_method( 'pick', 'simple_objects' );
1583
		}
1584
		return $object_types;
1585
	}
1586
1587
	}
1588