Completed
Pull Request — 2.x (#3260)
by Phil
05:58
created

PodsForm::dependencies()   D

Complexity

Conditions 10
Paths 16

Size

Total Lines 45
Code Lines 25

Duplication

Lines 27
Ratio 60 %
Metric Value
dl 27
loc 45
rs 4.8197
cc 10
eloc 25
nc 16
nop 2

How to fix   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 ( isset( $options[ 'description' ] ) && !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' ] = '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
196
        if ( null === $value || ( '' === $value && 'boolean' == $type ) || ( !empty( $pod ) && empty( $id ) ) )
197
            $value = self::default_value( $value, $type, $name, $options, $pod, $id );
198
199
        if ( false === self::permission( $type, $name, $options, null, $pod, $id ) )
200
            return false;
201
202
        $value = apply_filters( 'pods_form_ui_field_' . $type . '_value', $value, $name, $options, $pod, $id );
203
        $form_field_type = self::$field_type;
204
205
        ob_start();
206
207
        $helper = false;
208
209
        if ( 0 < strlen( pods_v( 'input_helper', $options ) ) )
210
            $helper = pods_api()->load_helper( array( 'name' => $options[ 'input_helper' ] ) );
211
212
        if ( ( !isset( $options[ 'data' ] ) || empty( $options[ 'data' ] ) ) && is_object( self::$loaded[ $type ] ) && method_exists( self::$loaded[ $type ], 'data' ) )
213
            $data = $options[ 'data' ] = self::$loaded[ $type ]->data( $name, $value, $options, $pod, $id, true );
214
215
        if ( true === apply_filters( 'pods_form_ui_field_' . $type . '_override', false, $name, $value, $options, $pod, $id ) )
216
            do_action( 'pods_form_ui_field_' . $type, $name, $value, $options, $pod, $id );
217
        elseif ( !empty( $helper ) && 0 < strlen( pods_v( 'code', $helper ) ) && false === strpos( $helper[ 'code' ], '$this->' ) && ( !defined( 'PODS_DISABLE_EVAL' ) || !PODS_DISABLE_EVAL ) )
218
            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...
219
        elseif ( method_exists( get_class(), 'field_' . $type ) )
220
            echo call_user_func( array( get_class(), 'field_' . $type ), $name, $value, $options );
221
        elseif ( is_object( self::$loaded[ $type ] ) && method_exists( self::$loaded[ $type ], 'input' ) )
222
            self::$loaded[ $type ]->input( $name, $value, $options, $pod, $id );
223
        else
224
            do_action( 'pods_form_ui_field_' . $type, $name, $value, $options, $pod, $id );
225
226
        $output = ob_get_clean();
227
228
        return apply_filters( 'pods_form_ui_field_' . $type, $output, $name, $value, $options, $pod, $id );
229
    }
230
231
    /**
232
     * Output a flexible relationship button
233
     *
234
     * @todo  : support other content types
235
     * @todo  : replace thickbox
236
     *
237
     * @param array $field Field options array
238
     *
239
     * @param int   $item_id
240
     *
241
     * @return string Button HTML
242
     *
243
     * @since 2.7
244
     */
245
    public static function flex_relationship( $field, $item_id ) {
246
247
        $output = '';
248
249
        // Early exit if this isn't a flexible relationship enabled field
250
        if ( 'pick' != $field[ 'type' ] || !$field[ 'options' ][ 'pick_flexible' ] ) {
251
            return $output;
252
        }
253
254
        // @todo: early exit if we're already in a modal
255
256
        ob_start();
257
258
        // Set the file name and args based on the content type of the relationship
259
        switch ( $field[ 'pick_object' ] ) {
260
            case 'post_type':
261
                $file_name = 'post-new.php';
262
                $query_args = array(
263
                    'post_type' => $field[ 'pick_val' ],
264
                );
265
                break;
266
267
            // Something unsupported
268
            default:
269
                return $output;
270
                break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
271
        }
272
273
        // Add args we always need
274
        $query_args = array_merge(
275
            $query_args,
276
            array(
277
                'pods_modal' => '1', // @todo: No hard-coded constants, create a constant for the purpose
278
                'TB_iframe'  => 'true',
279
                'width'      => '753',
280
                'height'     => '798',
281
            )
282
        );
283
284
        // Assemble the URL
285
        $url = add_query_arg(
286
            $query_args,
287
            admin_url( $file_name )
288
        );
289
        ?>
290
        <a href="<?php echo $url; ?>"
291
            id="pods-related-edit-<?php echo $field[ 'name' ]; ?>"
292
            class="button pods-related-edit"
293
            data-pod-id="<?php echo $field[ 'pod_id' ]; ?>"
294
            data-field-id="<?php echo $field[ 'id' ]; ?>"
295
            data-item-id="<?php echo $item_id; ?>"> Add New</a>
296
        <?php
297
298
        $output = ob_get_clean();
299
300
        // @todo: add a filter
301
        return $output;
302
    }
303
304
    /**
305
     * Output field type 'db'
306
     *
307
     * Used for field names and other places where only [a-z0-9_] is accepted
308
     *
309
     * @since 2.0
310
     */
311 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...
312
        $form_field_type = self::$field_type;
313
314
        ob_start();
315
316
        pods_view( PODS_DIR . 'ui/fields/_db.php', compact( array_keys( get_defined_vars() ) ) );
317
318
        $output = ob_get_clean();
319
320
        return apply_filters( 'pods_form_ui_field_db', $output, $name, $value, $options );
321
    }
322
323
    /**
324
     * Output a hidden field
325
     */
326 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...
327
        $form_field_type = self::$field_type;
328
329
        ob_start();
330
331
        pods_view( PODS_DIR . 'ui/fields/_hidden.php', compact( array_keys( get_defined_vars() ) ) );
332
333
        $output = ob_get_clean();
334
335
        return apply_filters( 'pods_form_ui_field_hidden', $output, $name, $value, $options );
336
    }
337
338
	/**
339
	 * Returns a submit button, with provided text and appropriate class, copied from WP Core for use on the frontend
340
	 *
341
	 * @see get_submit_button
342
	 *
343
	 * @param string $text The text of the button (defaults to 'Save Changes')
344
	 * @param string $type The type of button. One of: primary, secondary, delete
345
	 * @param string $name The HTML name of the submit button. Defaults to "submit". If no id attribute
346
	 *               is given in $other_attributes below, $name will be used as the button's id.
347
	 * @param bool $wrap True if the output button should be wrapped in a paragraph tag,
348
	 * 			   false otherwise. Defaults to true
349
	 * @param array|string $other_attributes Other attributes that should be output with the button,
350
	 *                     mapping attributes to their values, such as array( 'tabindex' => '1' ).
351
	 *                     These attributes will be output as attribute="value", such as tabindex="1".
352
	 *                     Defaults to no other attributes. Other attributes can also be provided as a
353
	 *                     string such as 'tabindex="1"', though the array format is typically cleaner.
354
	 *
355
	 * @since 3.0
356
	 */
357
	public static function submit_button( $text = null, $type = 'primary large', $name = 'submit', $wrap = true, $other_attributes = null ) {
358
359
		if ( function_exists( 'get_submit_button' ) ) {
360
			return get_submit_button( $text, $type, $name, $wrap, $other_attributes );
361
		}
362
363
		if ( !is_array( $type ) ) {
364
			$type = explode( ' ', $type );
365
		}
366
367
		$button_shorthand = array(
368
			'primary',
369
			'small',
370
			'large'
371
		);
372
373
		$classes = array(
374
			'button'
375
		);
376
377
		foreach ( $type as $t ) {
378
			if ( 'secondary' === $t || 'button-secondary' === $t ) {
379
				continue;
380
			}
381
382
			$classes[] = in_array( $t, $button_shorthand ) ? 'button-' . $t : $t;
383
		}
384
385
		$class = implode( ' ', array_unique( $classes ) );
386
387
		if ( 'delete' === $type ) {
388
			$class = 'button-secondary delete';
389
		}
390
391
		$text = $text ? $text : __( 'Save Changes' );
392
393
		// Default the id attribute to $name unless an id was specifically provided in $other_attributes
394
		$id = $name;
395
396
		if ( is_array( $other_attributes ) && isset( $other_attributes[ 'id' ] ) ) {
397
			$id = $other_attributes[ 'id' ];
398
			unset( $other_attributes[ 'id' ] );
399
		}
400
401
		$attributes = '';
402
403
		if ( is_array( $other_attributes ) ) {
404
			foreach ( $other_attributes as $attribute => $value ) {
405
				$attributes .= $attribute . '="' . esc_attr( $value ) . '" '; // Trailing space is important
406
			}
407
		}
408
		elseif ( !empty( $other_attributes ) ) { // Attributes provided as a string
409
			$attributes = $other_attributes;
410
		}
411
412
		$button = '<input type="submit" name="' . esc_attr( $name ) . '" id="' . esc_attr( $id ) . '" class="' . esc_attr( $class );
413
		$button .= '" value="' . esc_attr( $text ) . '" ' . $attributes . ' />';
414
415
		if ( $wrap ) {
416
			$button = '<p class="submit">' . $button . '</p>';
417
		}
418
419
		return $button;
420
421
	}
422
423
    /**
424
     * Output a row (label, field, and comment)
425
     *
426
     * @param string $name Field name
427
     * @param mixed $value Field value
428
     * @param string $type Field type
429
     * @param array $options Field options
430
     * @param array $pod Pod data
431
     * @param int $id Item ID
432
     *
433
     * @return string Row HTML
434
     *
435
     * @since 2.0
436
     */
437
    public static function row( $name, $value, $type = 'text', $options = null, $pod = null, $id = null ) {
438
        $options = self::options( null, $options );
439
440
        ob_start();
441
442
        pods_view( PODS_DIR . 'ui/fields/_row.php', compact( array_keys( get_defined_vars() ) ) );
443
444
        $output = ob_get_clean();
445
446
        return apply_filters( 'pods_form_ui_field_row', $output, $name, $value, $options, $pod, $id );
447
    }
448
449
    /**
450
     * Output a field's attributes
451
     *
452
     * @since 2.0
453
     */
454
    public static function attributes( $attributes, $name = null, $type = null, $options = null ) {
455
        $attributes = (array) apply_filters( 'pods_form_ui_field_' . $type . '_attributes', $attributes, $name, $options );
456
457
        foreach ( $attributes as $attribute => $value ) {
458
            if ( null === $value )
459
                continue;
460
461
            echo ' ' . esc_attr( (string) $attribute ) . '="' . esc_attr( (string) $value ) . '"';
462
        }
463
    }
464
465
    /**
466
     * Output a field's data (for use with jQuery)
467
     *
468
     * @since 2.0
469
     */
470
    public static function data( $data, $name = null, $type = null, $options = null ) {
471
        $data = (array) apply_filters( 'pods_form_ui_field_' . $type . '_data', $data, $name, $options );
472
473
        foreach ( $data as $key => $value ) {
474
            if ( null === $value )
475
                continue;
476
477
            $key = sanitize_title( $key );
478
479
            if ( is_array( $value ) )
480
                $value = implode( ',', $value );
481
482
            echo ' data-' . esc_attr( (string) $key ) . '="' . esc_attr( (string) $value ) . '"';
483
        }
484
    }
485
486
    /**
487
     * Merge attributes and handle classes
488
     *
489
     * @since 2.0
490
     */
491
    public static function merge_attributes( $attributes, $name = null, $type = null, $options = null, $classes = '' ) {
492
        $options = (array) $options;
493
494
        if ( !in_array( $type, array( 'label', 'comment' ) ) ) {
495
            $name_clean = self::clean( $name );
496
            $name_more_clean = self::clean( $name, true );
497
            $_attributes = array();
498
            $_attributes[ 'name' ] = $name;
499
            $_attributes[ 'data-name-clean' ] = $name_more_clean;
500
501
            if ( 0 < strlen( pods_v( 'label', $options, '' ) ) )
502
                $_attributes[ 'data-label' ] = strip_tags( pods_v( 'label', $options ) );
503
504
            $_attributes[ 'id' ] = 'pods-form-ui-' . $name_clean;
505
            $_attributes[ 'class' ] = 'pods-form-ui-field-type-' . $type . ' pods-form-ui-field-name-' . $name_more_clean;
506
507
            if ( isset( $options[ 'dependency' ] ) && false !== $options[ 'dependency' ] )
508
                $_attributes[ 'class' ] .= ' pods-dependent-toggle';
509
510
            $attributes = array_merge( $_attributes, (array) $attributes );
511
512 View Code Duplication
            if ( isset( $options[ 'attributes' ] ) && is_array( $options[ 'attributes' ] ) && !empty( $options[ 'attributes' ] ) )
513
                $attributes = array_merge( $attributes, $options[ 'attributes' ] );
514
        }
515
        elseif ( isset( $options[ $type . '_attributes' ] ) && is_array( $options[ $type . '_attributes' ] ) && !empty( $options[ $type . '_attributes' ] ) )
516
            $attributes = array_merge( $attributes, $options[ $type . '_attributes' ] );
517
518
        if ( isset( $options[ 'class' ] ) && !empty( $options[ 'class' ] ) ) {
519
            if ( is_array( $options[ 'class' ] ) )
520
                $options[ 'class' ] = implode( ' ', $options[ 'class' ] );
521
522
            $options[ 'class' ] = (string) $options[ 'class' ];
523 View Code Duplication
            if ( isset( $attributes[ 'class' ] ) )
524
                $attributes[ 'class' ] = $attributes[ 'class' ] . ' ' . $options[ 'class' ];
525
            else
526
                $attributes[ 'class' ] = $options[ 'class' ];
527
528
            $attributes[ 'class' ] = trim( $attributes[ 'class' ] );
529
        }
530
531
        if ( !empty( $classes ) ) {
532 View Code Duplication
            if ( isset( $attributes[ 'class' ] ) )
533
                $attributes[ 'class' ] = $attributes[ 'class' ] . ' ' . $classes;
534
            else
535
                $attributes[ 'class' ] = $classes;
536
        }
537
538
        if ( isset( $options[ 'placeholder' ] ) && !empty( $options[ 'placeholder' ] ) ) {
539
            if ( is_array( $options[ 'placeholder' ] ) )
540
                $options[ 'placeholder' ] = implode( ' ', $options[ 'placeholder' ] );
541
542
            $options[ 'placeholder' ] = (string) $options[ 'placeholder' ];
543
			$attributes[ 'placeholder' ] = trim( $options[ 'placeholder' ] );
544
        }
545
546
        if ( 1 == pods_v( 'required', $options, 0 ) )
547
            $attributes[ 'class' ] .= ' pods-validate pods-validate-required';
548
549
        $max_length = (int) pods_var( 'maxlength', $options, pods_v( $type . '_max_length', $options, 0 ), null, true );
550
551
        if ( 0 < $max_length )
552
            $attributes[ 'maxlength' ] = $max_length;
553
554
        $attributes = (array) apply_filters( 'pods_form_ui_field_' . $type . '_merge_attributes', $attributes, $name, $options );
555
        return $attributes;
556
    }
557
558
    /**
559
     * Setup options for a field and store them for later use
560
     *
561
     * @param $type
562
     * @param $options
563
     *
564
     * @return array
565
     *
566
     * @static
567
     *
568
     * @since 2.0
569
     */
570
    public static function options( $type, $options ) {
571
        $options = (array) $options;
572
573
        if ( !is_object( $options ) && isset( $options[ 'options' ] ) ) {
574
            $options_temp = $options[ 'options' ];
575
576
            unset( $options[ 'options' ] );
577
578
            $options = array_merge( $options_temp, $options );
579
580
            $override = array(
581
                'class'
582
            );
583
584
            foreach ( $override as $check ) {
585
                if ( isset( $options_temp[ $check ] ) )
586
                    $options[ $check ] = $options_temp[ $check ];
587
            }
588
        }
589
590
        $defaults = self::options_setup( $type, $options );
591
592
        $core_defaults = array(
593
            'id' => 0,
594
            'label' => '',
595
            'description' => '',
596
            'help' => '',
597
            'default' => null,
598
            'attributes' => array(),
599
            'class' => '',
600
            'grouped' => 0,
601
        );
602
603
        $defaults = array_merge( $core_defaults, $defaults );
604
605
        foreach ( $defaults as $option => $settings ) {
606
            $default = $settings;
607
608
            if ( is_array( $settings ) && isset( $settings[ 'default' ] ) )
609
                $default = $settings[ 'default' ];
610
611
            if ( !isset( $options[ $option ] ) )
612
                $options[ $option ] = $default;
613
        }
614
615
        return $options;
616
    }
617
618
    /**
619
     * Get options for a field type and setup defaults
620
     *
621
     * @static
622
     *
623
     * @param $type
624
     *
625
     * @return array|null
626
     *
627
     * @since 2.0
628
     */
629
    public static function options_setup( $type = null, $options = null ) {
630
        $core_defaults = array(
631
            'id' => 0,
632
            'name' => '',
633
            'label' => '',
634
            'description' => '',
635
            'help' => '',
636
            'default' => null,
637
            'attributes' => array(),
638
            'class' => '',
639
            'type' => 'text',
640
            'group' => 0,
641
            'grouped' => 0,
642
            'developer_mode' => false,
643
            'dependency' => false,
644
            'depends-on' => array(),
645
            'excludes-on' => array(),
646
            'options' => array()
647
        );
648
649
        if ( !empty( $options ) && is_array( $options ) )
650
            $core_defaults = array_merge( $core_defaults, $options );
651
652
        if ( null === $type )
653
            return $core_defaults;
654
        else
655
            self::field_loader( $type );
656
657
        $options = apply_filters( 'pods_field_' . $type . '_options', (array) self::$loaded[ $type ]->options(), $type );
658
659
        $first_field = current( $options );
660
661
        if ( !empty( $options ) && !isset( $first_field[ 'name' ] ) && !isset( $first_field[ 'label' ] ) ) {
662
            $all_options = array();
663
664
            foreach ( $options as $group => $group_options ) {
665
                $all_options = array_merge( $all_options, self::fields_setup( $group_options, $core_defaults ) );
666
            }
667
668
            $options = $all_options;
669
        }
670
        else
671
            $options = self::fields_setup( $options, $core_defaults );
672
673
        return $options;
674
    }
675
676
    /**
677
     * Get Admin options for a field type and setup defaults
678
     *
679
     * @static
680
     *
681
     * @param $type
682
     *
683
     * @return array|null
684
     *
685
     * @since 2.0
686
     */
687
    public static function ui_options( $type ) {
688
        $core_defaults = array(
689
            'id' => 0,
690
            'name' => '',
691
            'label' => '',
692
            'description' => '',
693
            'help' => '',
694
            'default' => null,
695
            'attributes' => array(),
696
            'class' => '',
697
            'type' => 'text',
698
            'group' => 0,
699
            'grouped' => 0,
700
            'developer_mode' => false,
701
            'dependency' => false,
702
            'depends-on' => array(),
703
            'excludes-on' => array(),
704
            'options' => array()
705
        );
706
707
        self::field_loader( $type );
708
709
        $options = apply_filters( 'pods_field_' . $type . '_ui_options', (array) self::$loaded[ $type ]->ui_options(), $type );
710
711
        $first_field = current( $options );
712
713
        if ( !empty( $options ) && !isset( $first_field[ 'name' ] ) && !isset( $first_field[ 'label' ] ) ) {
714
            foreach ( $options as $group => $group_options ) {
715
                $options[ $group ] = self::fields_setup( $group_options, $core_defaults );
716
            }
717
        }
718
        else
719
            $options = self::fields_setup( $options, $core_defaults );
720
721
        return $options;
722
    }
723
724
    /**
725
     * Get options for a field and setup defaults
726
     *
727
     *
728
     * @param null $fields
729
     * @param null $core_defaults
730
     * @param bool $single
731
     *
732
     * @return array|null
733
     *
734
     * @static
735
     * @since 2.0
736
     */
737
    public static function fields_setup( $fields = null, $core_defaults = null, $single = false ) {
738
        if ( empty( $core_defaults ) ) {
739
            $core_defaults = array(
740
                'id' => 0,
741
                'name' => '',
742
                'label' => '',
743
                'description' => '',
744
                'help' => '',
745
                'default' => null,
746
                'attributes' => array(),
747
                'class' => '',
748
                'type' => 'text',
749
                'group' => 0,
750
                'grouped' => 0,
751
                'developer_mode' => false,
752
                'dependency' => false,
753
                'depends-on' => array(),
754
                'excludes-on' => array(),
755
                'options' => array()
756
            );
757
        }
758
759
        if ( $single )
760
            $fields = array( $fields );
761
762
        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...
763
            $fields[ $f ] = self::field_setup( $field, $core_defaults, pods_v( 'type', $field, 'text' ) );
764
765
            if ( !$single && strlen( $fields[ $f ][ 'name' ] ) < 1 )
766
                $fields[ $f ][ 'name' ] = $f;
767
        }
768
769
        if ( $single )
770
            $fields = $fields[ 0 ];
771
772
        return $fields;
773
    }
774
775
    /**
776
     * Get options for a field and setup defaults
777
     *
778
     * @static
779
     *
780
     * @param null $field
781
     * @param null $core_defaults
782
     * @param null $type
783
     *
784
     * @return array|null
785
     *
786
     * @since 2.0
787
     */
788
    public static function field_setup( $field = null, $core_defaults = null, $type = null ) {
789
        $options = array();
790
791
        if ( empty( $core_defaults ) ) {
792
            $core_defaults = array(
793
                'id' => 0,
794
                'name' => '',
795
                'label' => '',
796
                'description' => '',
797
                'help' => '',
798
                'default' => null,
799
                'attributes' => array(),
800
                'class' => '',
801
                'type' => 'text',
802
                'group' => 0,
803
                'grouped' => 0,
804
                'developer_mode' => false,
805
                'dependency' => false,
806
                'depends-on' => array(),
807
                'excludes-on' => array(),
808
                'options' => array()
809
            );
810
811
            if ( null !== $type ) {
812
                self::field_loader( $type );
813
814
                if ( method_exists( self::$loaded[ $type ], 'options' ) )
815
                    $options = apply_filters( 'pods_field_' . $type . '_options', (array) self::$loaded[ $type ]->options(), $type );
816
            }
817
        }
818
819
        if ( !is_array( $field ) )
820
            $field = array( 'default' => $field );
821
822
        if ( isset( $field[ 'group' ] ) && is_array( $field[ 'group' ] ) ) {
823
            foreach ( $field[ 'group' ] as $g => $group_option ) {
824
                $field[ 'group' ][ $g ] = array_merge( $core_defaults, $group_option );
825
826
                if ( strlen( $field[ 'group' ][ $g ][ 'name' ] ) < 1 )
827
                    $field[ 'group' ][ $g ][ 'name' ] = $g;
828
            }
829
        }
830
831
        $field = array_merge( $core_defaults, $field );
832
833
        foreach ( $options as $option => $settings ) {
834
            $v = null;
835
836
            if ( isset( $settings[ 'default' ] ) )
837
                $v = $settings[ 'default' ];
838
839
            if ( !isset( $field[ 'options' ][ $option ] ) )
840
                $field[ 'options' ][ $option ] = $v;
841
        }
842
843
        return $field;
844
    }
845
846
    /**
847
     * Setup dependency / exclusion classes
848
     *
849
     * @param array $options array( 'depends-on' => ..., 'excludes-on' => ...)
850
     * @param string $prefix
851
     *
852
     * @return string
853
     * @static
854
     * @since 2.0
855
     */
856
    public static function dependencies( $options, $prefix = '' ) {
857
        $options = (array) $options;
858
859
        $depends_on = $excludes_on = array();
860
        if ( isset( $options[ 'depends-on' ] ) )
861
            $depends_on = (array) $options[ 'depends-on' ];
862
863
        if ( isset( $options[ 'excludes-on' ] ) )
864
            $excludes_on = (array) $options[ 'excludes-on' ];
865
866
        $classes = array();
867
868 View Code Duplication
        if ( !empty( $depends_on ) ) {
869
            $classes[] = 'pods-depends-on';
870
871
            foreach ( $depends_on as $depends => $on ) {
872
                $classes[] = 'pods-depends-on-' . $prefix . self::clean( $depends, true );
873
874
                if ( !is_bool( $on ) ) {
875
                    $on = (array) $on;
876
877
                    foreach ( $on as $o ) {
878
                        $classes[] = 'pods-depends-on-' . $prefix . self::clean( $depends, true ) . '-' . self::clean( $o, true );
879
                    }
880
                }
881
            }
882
        }
883
884 View Code Duplication
        if ( !empty( $excludes_on ) ) {
885
            $classes[] = 'pods-excludes-on';
886
            foreach ( $excludes_on as $excludes => $on ) {
887
                $classes[] = 'pods-excludes-on-' . $prefix . self::clean( $excludes, true );
888
889
                $on = (array) $on;
890
891
                foreach ( $on as $o ) {
892
                    $classes[] = 'pods-excludes-on-' . $prefix . self::clean( $excludes, true ) . '-' . self::clean( $o, true );
893
                }
894
            }
895
        }
896
897
        $classes = implode( ' ', $classes );
898
899
        return $classes;
900
    }
901
902
    /**
903
     * Change the value of the field
904
     *
905
     * @param mixed $value
906
     * @param string $name
907
     * @param array $options
908
     * @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...
909
     * @param array $pod
910
     * @param int $id
911
     * @param array $traverse
912
     *
913
     * @since 2.3
914
     */
915
    public static function value( $type, $value = null, $name = null, $options = null, $pod = null, $id = null, $traverse = null ) {
916
        self::field_loader( $type );
917
918
        if ( in_array( $type, self::repeatable_field_types() ) && 1 == pods_v( $type . '_repeatable', $options, 0 ) && !is_array( $value ) ) {
919
            if ( 0 < strlen( $value ) ) {
920
                $simple = @json_decode( $value, true );
1 ignored issue
show
Unused Code introduced by
The call to json_decode() has too many arguments starting with true.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
921
922
                if ( is_array( $simple ) )
923
                    $value = $simple;
924
                else
925
                    $value = (array) $value;
926
            }
927
            else
928
                $value = array();
929
        }
930
931
        if ( method_exists( self::$loaded[ $type ], 'value' ) ) {
932
            if ( is_array( $value ) && in_array( $type, self::tableless_field_types() ) ) {
933 View Code Duplication
                foreach ( $value as &$display_value ) {
934
                    $display_value = call_user_func_array( array( self::$loaded[ $type ], 'value' ), array( $display_value, $name, $options, $pod, $id, $traverse ) );
935
                }
936
            }
937 View Code Duplication
            else
938
                $value = call_user_func_array( array( self::$loaded[ $type ], 'value' ), array( $value, $name, $options, $pod, $id, $traverse ) );
939
        }
940
941
        return $value;
942
    }
943
944
    /**
945
     * Change the way the value of the field is displayed with Pods::get
946
     *
947
     * @param mixed $value
948
     * @param string $name
949
     * @param array $options
950
     * @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...
951
     * @param array $pod
952
     * @param int $id
953
     * @param array $traverse
954
     *
955
     * @since 2.0
956
     */
957
    public static function display( $type, $value = null, $name = null, $options = null, $pod = null, $id = null, $traverse = null ) {
958
        self::field_loader( $type );
959
960
        $tableless_field_types = self::tableless_field_types();
961
962
        if ( method_exists( self::$loaded[ $type ], 'display' ) ) {
963
            if ( is_array( $value ) && !in_array( $type, $tableless_field_types ) ) {
964 View Code Duplication
                foreach ( $value as $k => $display_value ) {
965
                    $value[ $k ] = call_user_func_array( array( self::$loaded[ $type ], 'display' ), array( $display_value, $name, $options, $pod, $id, $traverse ) );
966
                }
967
            }
968 View Code Duplication
            else
969
                $value = call_user_func_array( array( self::$loaded[ $type ], 'display' ), array( $value, $name, $options, $pod, $id, $traverse ) );
970
        }
971
972
        $value = apply_filters( 'pods_form_display_' . $type, $value, $name, $options, $pod, $id, $traverse );
973
974
        return $value;
975
    }
976
977
    /**
978
     * Setup regex for JS / PHP
979
     *
980
     * @static
981
     *
982
     * @param $type
983
     * @param $options
984
     *
985
     * @return mixed|void
986
     * @since 2.0
987
     */
988 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...
989
        self::field_loader( $type );
990
991
        $regex = false;
992
993
        if ( method_exists( self::$loaded[ $type ], 'regex' ) )
994
            $regex = self::$loaded[ $type ]->regex( $options );
995
996
        $regex = apply_filters( 'pods_field_' . $type . '_regex', $regex, $options, $type );
997
998
        return $regex;
999
    }
1000
1001
    /**
1002
     * Setup value preparation for sprintf
1003
     *
1004
     * @static
1005
     *
1006
     * @param $type
1007
     * @param $options
1008
     *
1009
     * @return mixed|void
1010
     * @since 2.0
1011
     */
1012 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...
1013
        self::field_loader( $type );
1014
1015
        $prepare = '%s';
1016
1017
        if ( method_exists( self::$loaded[ $type ], 'prepare' ) )
1018
            $prepare = self::$loaded[ $type ]->prepare( $options );
1019
1020
        $prepare = apply_filters( 'pods_field_' . $type . '_prepare', $prepare, $options, $type );
1021
1022
        return $prepare;
1023
    }
1024
1025
    /**
1026
     * Validate a value before it's saved
1027
     *
1028
     * @param string $type
1029
     * @param mixed $value
1030
     * @param string $name
1031
     * @param array $options
1032
     * @param array $fields
1033
     * @param array $pod
1034
     * @param int $id
1035
     * @param array|object $params
1036
     *
1037
     * @static
1038
     *
1039
     * @since 2.0
1040
     */
1041
    public static function validate( $type, $value, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
1042
        self::field_loader( $type );
1043
1044
        $validate = true;
1045
1046
        if ( 1 == pods_v( 'pre_save', $options, 1 ) && method_exists( self::$loaded[ $type ], 'validate' ) )
1047
            $validate = self::$loaded[ $type ]->validate( $value, $name, $options, $fields, $pod, $id, $params );
1048
1049
        $validate = apply_filters( 'pods_field_' . $type . '_validate', $validate, $value, $name, $options, $fields, $pod, $id, $type, $params );
1050
1051
        return $validate;
1052
    }
1053
1054
    /**
1055
     * Change the value or perform actions after validation but before saving to the DB
1056
     *
1057
     * @param string $type
1058
     * @param mixed $value
1059
     * @param int $id
1060
     * @param string $name
1061
     * @param array $options
1062
     * @param array $fields
1063
     * @param array $pod
1064
     * @param object $params
1065
     *
1066
     * @static
1067
     *
1068
     * @since 2.0
1069
     */
1070 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...
1071
        self::field_loader( $type );
1072
1073
        if ( 1 == pods_v( 'field_pre_save', $options, 1 ) && method_exists( self::$loaded[ $type ], 'pre_save' ) )
1074
            $value = self::$loaded[ $type ]->pre_save( $value, $id, $name, $options, $fields, $pod, $params );
1075
1076
        return $value;
1077
    }
1078
1079
    /**
1080
     * Save the value to the DB
1081
     *
1082
     * @param string $type
1083
     * @param mixed $value
1084
     * @param int $id
1085
     * @param string $name
1086
     * @param array $options
1087
     * @param array $fields
1088
     * @param array $pod
1089
     * @param object $params
1090
     *
1091
     * @static
1092
     *
1093
     * @since 2.3
1094
     */
1095 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...
1096
        self::field_loader( $type );
1097
1098
        $saved = null;
1099
1100
        if ( 1 == pods_v( 'field_save', $options, 1 ) && method_exists( self::$loaded[ $type ], 'save' ) )
1101
            $saved = self::$loaded[ $type ]->save( $value, $id, $name, $options, $fields, $pod, $params );
1102
1103
        return $saved;
1104
    }
1105
1106
    /**
1107
     * Delete the value from the DB
1108
     *
1109
     * @param string $type
1110
     * @param int $id
1111
     * @param string $name
1112
     * @param array $options
1113
     * @param array $pod
1114
     *
1115
     * @static
1116
     *
1117
     * @since 2.3
1118
     */
1119 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...
1120
        self::field_loader( $type );
1121
1122
        $deleted = null;
1123
1124
        if ( 1 == pods_v( 'field_delete', $options, 1 ) && method_exists( self::$loaded[ $type ], 'delete' ) )
1125
            $deleted = self::$loaded[ $type ]->delete( $id, $name, $options, $pod );
1126
1127
        return $deleted;
1128
    }
1129
1130
    /**
1131
     * Check if a user has permission to be editing a field
1132
     *
1133
     * @param $type
1134
     * @param null $name
1135
     * @param null $options
1136
     * @param null $fields
1137
     * @param null $pod
1138
     * @param null $id
1139
     * @param null $params
1140
     *
1141
     * @static
1142
     *
1143
     * @since 2.0
1144
     */
1145
    public static function permission( $type, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
1146
        $permission = pods_permission( $options );
1147
1148
        $permission = (boolean) apply_filters( 'pods_form_field_permission', $permission, $type, $name, $options, $fields, $pod, $id, $params );
1149
1150
        return $permission;
1151
    }
1152
1153
    /**
1154
     * Parse the default the value
1155
     *
1156
     * @since 2.0
1157
     */
1158
    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...
1159
        $default_value = pods_v( 'default_value', $options );
1160
1161
		if ( '' === $default_value || null === $default_value ) {
1162
			$default_value = $value;
1163
		}
1164
1165
        $default = pods_v( 'default', $options, $default_value, true );
1166
1167
	    if ( is_string( $default ) ) {
1168
		    $default_value = str_replace( array( '{@', '}' ), '', trim( $default ) );
1169
	    }
1170
1171
        if ( $default != $default_value && 1 == (int) pods_v( 'default_evaluate_tags', $options, 1 ) )
1172
            $default = pods_evaluate_tags( $default );
1173
1174
        $default = pods_var_raw( pods_v( 'default_value_parameter', $options ), 'request', $default, null, true );
1175
1176
        if ( $default != $value )
1177
            $value = $default;
1178
1179
        if ( is_array( $value ) )
1180
            $value = pods_serial_comma( $value );
1181
1182
        return apply_filters( 'pods_form_field_default_value', $value, $default, $type, $options, $pod, $id );
1183
    }
1184
1185
    /**
1186
     * Clean a value for use in class / id
1187
     *
1188
     * @since 2.0
1189
     */
1190
    public static function clean( $input, $noarray = false, $db_field = false ) {
1191
        $input = str_replace( array( '--1', '__1' ), '00000', (string) $input );
1192
        if ( false !== $noarray )
1193
            $input = preg_replace( '/\[\d*\]/', '-', $input );
1194
        $output = str_replace( array( '[', ']' ), '-', strtolower( $input ) );
1195
        $output = preg_replace( '/([^a-z0-9\-_])/', '', $output );
1196
        $output = trim( str_replace( array( '__', '_', '--' ), '-', $output ), '-' );
1197
        $output = str_replace( '00000', '--1', $output );
1198
        if ( false !== $db_field )
1199
            $output = str_replace( '-', '_', $output );
1200
        return $output;
1201
    }
1202
1203
    /**
1204
     * Run admin_init methods for each field type
1205
     *
1206
     * @since 2.3
1207
     */
1208
    public function admin_init() {
1209
        $admin_field_types = pods_transient_get( 'pods_form_admin_init_field_types' );
1210
1211
        if ( empty( $admin_field_types ) ) {
1212
            $admin_field_types = array();
1213
1214
            $field_types = self::field_types();
1215
1216
            foreach ( $field_types as $field_type => $field_type_data ) {
1217
                $has_ajax = self::field_method( $field_type_data[ 'type' ], 'admin_init' );
1218
1219
                if ( false !== $has_ajax )
1220
                    $admin_field_types[] = $field_type;
1221
            }
1222
1223
            pods_transient_set( 'pods_form_admin_init_field_types', $admin_field_types );
1224
        }
1225
        else {
1226
            foreach ( $admin_field_types as $field_type ) {
1227
                self::field_method( $field_type, 'admin_init' );
1228
            }
1229
        }
1230
    }
1231
1232
    /**
1233
     * Autoload a Field Type's class
1234
     *
1235
     * @param string $field_type Field Type indentifier
1236
     * @param string $file The Field Type class file location
1237
     *
1238
     * @return string
1239
     * @access public
1240
     * @static
1241
     * @since 2.0
1242
     */
1243
    public static function field_loader( $field_type, $file = '' ) {
1244
        if ( isset( self::$loaded[ $field_type ] ) ) {
1245
            $class_vars = get_class_vars( get_class( self::$loaded[ $field_type ] ) ); // PHP 5.2.x workaround
1246
1247
            self::$field_group = ( isset( $class_vars[ 'group' ] ) ? $class_vars[ 'group' ] : '' );
1248
            self::$field_type = $class_vars[ 'type' ];
1249
1250
            if ( 'Unknown' != $class_vars[ 'label' ] )
1251
                return self::$loaded[ $field_type ];
1252
        }
1253
1254
        include_once PODS_DIR . 'classes/PodsField.php';
1255
1256
        $field_type = self::clean( $field_type, true, true );
1257
1258
        $class_name = ucfirst( $field_type );
1259
        $class_name = "PodsField_{$class_name}";
1260
1261
        $content_dir = realpath( WP_CONTENT_DIR );
1262
        $plugins_dir = realpath( WP_PLUGIN_DIR );
1263
        $muplugins_dir = realpath( WPMU_PLUGIN_DIR );
1264
        $abspath_dir = realpath( ABSPATH );
1265
1266
        if ( !class_exists( $class_name ) ) {
1267
            if ( isset( self::$field_types[ $field_type ] ) && !empty( self::$field_types[ $field_type ][ 'file' ] ) )
1268
                $file = realpath( self::$field_types[ $field_type ][ 'file' ] );
1269
1270
            if ( !empty( $file ) && 0 === strpos( $file, $abspath_dir ) && file_exists( $file ) )
1271
                include_once $file;
1272
            else {
1273
                $file = str_replace( '../', '', apply_filters( 'pods_form_field_include', PODS_DIR . 'classes/fields/' . basename( $field_type ) . '.php', $field_type ) );
1274
                $file = realpath( $file );
1275
1276
                if ( file_exists( $file ) && ( 0 === strpos( $file, $content_dir ) || 0 === strpos( $file, $plugins_dir ) || 0 === strpos( $file, $muplugins_dir ) || 0 === strpos( $file, $abspath_dir ) ) )
1277
                    include_once $file;
1278
            }
1279
        }
1280
1281
        if ( class_exists( $class_name ) )
1282
            $class = new $class_name();
1283
        else {
1284
            $class = new PodsField();
1285
            $class_name = 'PodsField';
1286
        }
1287
1288
        $class_vars = get_class_vars( $class_name ); // PHP 5.2.x workaround
1289
1290
        self::$field_group = ( isset( $class_vars[ 'group' ] ) ? $class_vars[ 'group' ] : '' );
1291
        self::$field_type = $class_vars[ 'type' ];
1292
1293
        self::$loaded[ $field_type ] =& $class;
1294
1295
        return self::$loaded[ $field_type ];
1296
    }
1297
1298
    /**
1299
     * Run a method from a Field Type's class
1300
     *
1301
     * @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...
1302
     * @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...
1303
     * @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...
1304
     *
1305
     * @return mixed
1306
     * @access public
1307
     * @static
1308
     * @since 2.0
1309
     */
1310
    public static function field_method() {
1311
        $args = func_get_args();
1312
1313
        if ( empty( $args ) && count( $args ) < 2 )
1314
            return false;
1315
1316
        $field_type = array_shift( $args );
1317
        $method = array_shift( $args );
1318
1319
        $class = self::field_loader( $field_type );
1320
1321
        if ( method_exists( $class, $method ) )
1322
            return call_user_func_array( array( $class, $method ), $args );
1323
1324
        return false;
1325
    }
1326
1327
    /**
1328
     * Add a new Pod field type
1329
     *
1330
     * @param string $type The new field type identifier
1331
     * @param string $file The new field type class file location
1332
     *
1333
     * @return array Field Type data
1334
     *
1335
     * @since 2.3
1336
     */
1337
    public static function register_field_type( $type, $file = null ) {
1338
        $field_type = pods_transient_get( 'pods_field_type_' . $type );
1339
1340
        if ( empty( $field_type ) || $field_type[ 'type' ] != $type || $field_type[ 'file' ] != $file ) {
1341
            self::field_loader( $type, $file );
1342
1343
            $class_vars = get_class_vars( get_class( self::$loaded[ $type ] ) ); // PHP 5.2.x workaround
1344
1345
            self::$field_types[ $type ] = $class_vars;
1346
            self::$field_types[ $type ][ 'file' ] = $file;
1347
1348
            pods_transient_set( 'pods_field_type_' . $type, self::$field_types[ $type ] );
1349
        }
1350
        else
1351
            self::$field_types[ $type ] = $field_type;
1352
1353
        return self::$field_types[ $type ];
1354
    }
1355
1356
    /**
1357
     * Get a list of all available field types and include
1358
     *
1359
     * @return array Registered Field Types data
1360
     *
1361
     * @since 2.3
1362
     */
1363
    public static function field_types() {
1364
        $field_types = array(
1365
            'text',
1366
            'website',
1367
            'phone',
1368
            'email',
1369
            'password',
1370
            'paragraph',
1371
            'wysiwyg',
1372
            'code',
1373
            'datetime',
1374
            'date',
1375
            'time',
1376
            'number',
1377
            'currency',
1378
            'file',
1379
            'avatar',
1380
            'pick',
1381
            'boolean',
1382
            'color',
1383
            'slug'
1384
        );
1385
1386
        $field_types = array_merge( $field_types, array_keys( self::$field_types ) );
1387
1388
        $field_types = array_filter( array_unique( $field_types ) );
1389
1390
        $types = apply_filters( 'pods_api_field_types', $field_types );
1391
1392
        $field_types = pods_transient_get( 'pods_field_types' );
1393
1394
        if ( empty( $field_types ) || count( $types ) != count( $field_types ) ) {
1395
            $field_types = array();
1396
1397
            foreach ( $types as $field_type ) {
1398
                $file = null;
1399
1400
                if ( isset( self::$field_types[ $field_type ] ) )
1401
                    $file = self::$field_types[ $field_type ][ 'file' ];
1402
1403
                self::field_loader( $field_type, $file );
1404
1405
                if ( !isset( self::$loaded[ $field_type ] ) || !is_object( self::$loaded[ $field_type ] ) )
1406
                    continue;
1407
1408
                $class_vars = get_class_vars( get_class( self::$loaded[ $field_type ] ) ); // PHP 5.2.x workaround
1409
1410
                $field_types[ $field_type ] = $class_vars;
1411
                $field_types[ $field_type ][ 'file' ] = $file;
1412
            }
1413
1414
            self::$field_types = $field_types;
1415
1416
            pods_transient_set( 'pods_field_types', self::$field_types );
1417
        }
1418
        else
1419
            self::$field_types = array_merge( $field_types, self::$field_types );
1420
1421
        return self::$field_types;
1422
    }
1423
1424
    /**
1425
     * Get list of available tableless field types
1426
     *
1427
     * @return array Tableless field types
1428
     *
1429
     * @since 2.3
1430
     */
1431 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...
1432
	    static $field_types = null;
1433
1434
	    if ( null === $field_types ) {
1435
		    $field_types = array( 'pick', 'file', 'avatar', 'taxonomy' );
1436
1437
		    $field_types = apply_filters( 'pods_tableless_field_types', $field_types );
1438
	    }
1439
	    return $field_types;
1440
    }
1441
1442
    /**
1443
     * Get list of available file field types
1444
     *
1445
     * @return array File field types
1446
     *
1447
     * @since 2.3
1448
     */
1449 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...
1450
	    static $field_types = null;
1451
1452
	    if ( null === $field_types ) {
1453
		    $field_types = array( 'file', 'avatar' );
1454
1455
		    $field_types = apply_filters( 'pods_file_field_types', $field_types );
1456
	    }
1457
	    return $field_types;
1458
    }
1459
1460
    /**
1461
     * Get list of available repeatable field types
1462
     *
1463
     * @return array Repeatable field types
1464
     *
1465
     * @since 2.3
1466
     */
1467
    public static function repeatable_field_types() {
1468
	    static $field_types = null;
1469
1470
	    if ( null === $field_types ) {
1471
		    $field_types = array(
1472
			    'code',
1473
			    'color',
1474
			    'currency',
1475
			    'date',
1476
			    'datetime',
1477
			    'email',
1478
			    'number',
1479
			    'paragraph',
1480
			    'phone',
1481
			    'text',
1482
			    'time',
1483
			    'website',
1484
			    'wysiwyg'
1485
		    );
1486
1487
		    $field_types = apply_filters( 'pods_repeatable_field_types', $field_types );
1488
	    }
1489
	    return $field_types;
1490
    }
1491
1492
    /**
1493
     * Get list of available number field types
1494
     *
1495
     * @return array Number field types
1496
     *
1497
     * @since 2.3
1498
     */
1499 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...
1500
	    static $field_types = null;
1501
1502
	    if ( null === $field_types ) {
1503
		    $field_types = array( 'currency', 'number' );
1504
1505
		    $field_types = apply_filters( 'pods_tableless_field_types', $field_types );
1506
	    }
1507
	    return $field_types;
1508
    }
1509
1510
    /**
1511
     * Get list of available date field types
1512
     *
1513
     * @return array Date field types
1514
     *
1515
     * @since 2.3
1516
     */
1517 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...
1518
	    static $field_types = null;
1519
1520
	    if ( null === $field_types ) {
1521
		    $field_types = array( 'date', 'datetime', 'time' );
1522
1523
		    $field_types = apply_filters( 'pods_tableless_field_types', $field_types );
1524
	    }
1525
	    return $field_types;
1526
    }
1527
1528
    /**
1529
     * Get list of available text field types
1530
     *
1531
     * @return array Text field types
1532
     *
1533
     * @since 2.3
1534
     */
1535
    public static function text_field_types() {
1536
	    static $field_types = null;
1537
1538
	    if ( null === $field_types ) {
1539
		    $field_types = array( 'code', 'paragraph', 'slug', 'password', 'text', 'wysiwyg' );
1540
1541
		    $field_types = apply_filters( 'pods_text_field_types', $field_types );
1542
	    }
1543
	    return $field_types;
1544
    }
1545
1546
    /**
1547
     * Get list of available text field types
1548
     *
1549
     * @return array Text field types
1550
     *
1551
     * @since 2.3
1552
     */
1553
    public static function block_field_types() {
1554
	    static $field_types = null;
1555
1556
	    if ( null === $field_types ) {
1557
		    $field_types = array( 'heading', 'html' );
1558
1559
		    /**
1560
		     * Returns the available text field types
1561
		     *
1562
		     * @since unknown
1563
		     *
1564
		     * @param object $field_types Outputs the field types
1565
		     */
1566
1567
		    $field_types = apply_filters( 'pods_block_field_types', $field_types );
1568
	    }
1569
	    return $field_types;
1570
    }
1571
1572
	/**
1573
	 * Get list of available text field types
1574
	 *
1575
	 * @return array Text field types
1576
	 *
1577
	 * @since 2.3
1578
	 */
1579
	public static function simple_tableless_objects() {
1580
		static $object_types = null;
1581
1582
		if ( null === $object_types ) {
1583
			$object_types = PodsForm::field_method( 'pick', 'simple_objects' );
1584
		}
1585
		return $object_types;
1586
	}
1587
1588
	}
1589