Completed
Pull Request — 2.x (#3260)
by Phil
05:52
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 any of:
250
        //  * Not admin
251
        //  * this isn't a flexible relationship enabled field
252
        //  * we're already in a modal
253
        if ( ! is_admin() || 'pick' != $field[ 'type' ] || empty( $field[ 'pick_flexible' ] ) || pods_is_modal_window() ) {
254
            return $output;
255
        }
256
257
        wp_enqueue_style( 'responsive-modal' );
258
        wp_enqueue_script( 'responsive-modal' );
259
260
        // Set the file name and args based on the content type of the relationship
261
        switch ( $field[ 'pick_object' ] ) {
262
            case 'post_type':
263
                $file_name = 'post-new.php';
264
                $query_args = array(
265
                    'post_type' => $field[ 'pick_val' ],
266
                );
267
                break;
268
269
            case 'taxonomy':
270
                $file_name = 'edit-tags.php';
271
                $query_args = array(
272
                    'taxonomy' => $field[ 'pick_val' ],
273
                );
274
                break;
275
276
            case 'user':
277
                $file_name = 'user-new.php';
278
                $query_args = array();
279
                break;
280
281
            case 'pod':
282
                $file_name = 'admin.php';
283
                $query_args = array(
284
                    'page'   => 'pods-manage-' . $field[ 'pick_val' ],
285
                    'action' => 'add'
286
                );
287
                break;
288
289
            // Something unsupported
290
            default:
291
                return $output;
292
                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...
293
        }
294
295
        // Add args we always need
296
        $query_args = array_merge(
297
            $query_args,
298
            array(
299
                'pods_modal' => '1', // @todo: Replace string literal with defined constant
300
            )
301
        );
302
303
        // Assemble the URL
304
        $url = add_query_arg( $query_args, admin_url( $file_name ) );
305
306
        ob_start();
307
308
        ?>
309
        <div class="podsform-flex-relationship-container">
310
	        <a href="<?php echo esc_url( $url ); ?>"
311
                data-modal-show="yes please, if it's no trouble"
312
	            id="pods-related-edit-<?php echo esc_attr( $field[ 'name' ] ); ?>"
313
	            class="button pods-related-edit pods-modal"
314
	            data-pod-id="<?php echo esc_attr( $field[ 'pod_id' ] ); ?>"
315
	            data-field-id="<?php echo esc_attr( $field[ 'id' ] ); ?>"
316
	            data-item-id="<?php echo esc_attr( $item_id ); ?>">
317
		        Add New
318
	        </a>
319
	    </div>
320
        <?php
321
322
        $output = ob_get_clean();
323
324
        // @todo: add a filter
325
        return $output;
326
    }
327
328
    /**
329
     * Output field type 'db'
330
     *
331
     * Used for field names and other places where only [a-z0-9_] is accepted
332
     *
333
     * @since 2.0
334
     */
335 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...
336
        $form_field_type = self::$field_type;
337
338
        ob_start();
339
340
        pods_view( PODS_DIR . 'ui/fields/_db.php', compact( array_keys( get_defined_vars() ) ) );
341
342
        $output = ob_get_clean();
343
344
        return apply_filters( 'pods_form_ui_field_db', $output, $name, $value, $options );
345
    }
346
347
    /**
348
     * Output a hidden field
349
     */
350 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...
351
        $form_field_type = self::$field_type;
352
353
        ob_start();
354
355
        pods_view( PODS_DIR . 'ui/fields/_hidden.php', compact( array_keys( get_defined_vars() ) ) );
356
357
        $output = ob_get_clean();
358
359
        return apply_filters( 'pods_form_ui_field_hidden', $output, $name, $value, $options );
360
    }
361
362
	/**
363
	 * Returns a submit button, with provided text and appropriate class, copied from WP Core for use on the frontend
364
	 *
365
	 * @see get_submit_button
366
	 *
367
	 * @param string $text The text of the button (defaults to 'Save Changes')
368
	 * @param string $type The type of button. One of: primary, secondary, delete
369
	 * @param string $name The HTML name of the submit button. Defaults to "submit". If no id attribute
370
	 *               is given in $other_attributes below, $name will be used as the button's id.
371
	 * @param bool $wrap True if the output button should be wrapped in a paragraph tag,
372
	 * 			   false otherwise. Defaults to true
373
	 * @param array|string $other_attributes Other attributes that should be output with the button,
374
	 *                     mapping attributes to their values, such as array( 'tabindex' => '1' ).
375
	 *                     These attributes will be output as attribute="value", such as tabindex="1".
376
	 *                     Defaults to no other attributes. Other attributes can also be provided as a
377
	 *                     string such as 'tabindex="1"', though the array format is typically cleaner.
378
	 *
379
	 * @since 3.0
380
	 */
381
	public static function submit_button( $text = null, $type = 'primary large', $name = 'submit', $wrap = true, $other_attributes = null ) {
382
383
		if ( function_exists( 'get_submit_button' ) ) {
384
			return get_submit_button( $text, $type, $name, $wrap, $other_attributes );
385
		}
386
387
		if ( !is_array( $type ) ) {
388
			$type = explode( ' ', $type );
389
		}
390
391
		$button_shorthand = array(
392
			'primary',
393
			'small',
394
			'large'
395
		);
396
397
		$classes = array(
398
			'button'
399
		);
400
401
		foreach ( $type as $t ) {
402
			if ( 'secondary' === $t || 'button-secondary' === $t ) {
403
				continue;
404
			}
405
406
			$classes[] = in_array( $t, $button_shorthand ) ? 'button-' . $t : $t;
407
		}
408
409
		$class = implode( ' ', array_unique( $classes ) );
410
411
		if ( 'delete' === $type ) {
412
			$class = 'button-secondary delete';
413
		}
414
415
		$text = $text ? $text : __( 'Save Changes' );
416
417
		// Default the id attribute to $name unless an id was specifically provided in $other_attributes
418
		$id = $name;
419
420
		if ( is_array( $other_attributes ) && isset( $other_attributes[ 'id' ] ) ) {
421
			$id = $other_attributes[ 'id' ];
422
			unset( $other_attributes[ 'id' ] );
423
		}
424
425
		$attributes = '';
426
427
		if ( is_array( $other_attributes ) ) {
428
			foreach ( $other_attributes as $attribute => $value ) {
429
				$attributes .= $attribute . '="' . esc_attr( $value ) . '" '; // Trailing space is important
430
			}
431
		}
432
		elseif ( !empty( $other_attributes ) ) { // Attributes provided as a string
433
			$attributes = $other_attributes;
434
		}
435
436
		$button = '<input type="submit" name="' . esc_attr( $name ) . '" id="' . esc_attr( $id ) . '" class="' . esc_attr( $class );
437
		$button .= '" value="' . esc_attr( $text ) . '" ' . $attributes . ' />';
438
439
		if ( $wrap ) {
440
			$button = '<p class="submit">' . $button . '</p>';
441
		}
442
443
		return $button;
444
445
	}
446
447
    /**
448
     * Output a row (label, field, and comment)
449
     *
450
     * @param string $name Field name
451
     * @param mixed $value Field value
452
     * @param string $type Field type
453
     * @param array $options Field options
454
     * @param array $pod Pod data
455
     * @param int $id Item ID
456
     *
457
     * @return string Row HTML
458
     *
459
     * @since 2.0
460
     */
461
    public static function row( $name, $value, $type = 'text', $options = null, $pod = null, $id = null ) {
462
        $options = self::options( null, $options );
463
464
        ob_start();
465
466
        pods_view( PODS_DIR . 'ui/fields/_row.php', compact( array_keys( get_defined_vars() ) ) );
467
468
        $output = ob_get_clean();
469
470
        return apply_filters( 'pods_form_ui_field_row', $output, $name, $value, $options, $pod, $id );
471
    }
472
473
    /**
474
     * Output a field's attributes
475
     *
476
     * @since 2.0
477
     */
478
    public static function attributes( $attributes, $name = null, $type = null, $options = null ) {
479
        $attributes = (array) apply_filters( 'pods_form_ui_field_' . $type . '_attributes', $attributes, $name, $options );
480
481
        foreach ( $attributes as $attribute => $value ) {
482
            if ( null === $value )
483
                continue;
484
485
            echo ' ' . esc_attr( (string) $attribute ) . '="' . esc_attr( (string) $value ) . '"';
486
        }
487
    }
488
489
    /**
490
     * Output a field's data (for use with jQuery)
491
     *
492
     * @since 2.0
493
     */
494
    public static function data( $data, $name = null, $type = null, $options = null ) {
495
        $data = (array) apply_filters( 'pods_form_ui_field_' . $type . '_data', $data, $name, $options );
496
497
        foreach ( $data as $key => $value ) {
498
            if ( null === $value )
499
                continue;
500
501
            $key = sanitize_title( $key );
502
503
            if ( is_array( $value ) )
504
                $value = implode( ',', $value );
505
506
            echo ' data-' . esc_attr( (string) $key ) . '="' . esc_attr( (string) $value ) . '"';
507
        }
508
    }
509
510
    /**
511
     * Merge attributes and handle classes
512
     *
513
     * @since 2.0
514
     */
515
    public static function merge_attributes( $attributes, $name = null, $type = null, $options = null, $classes = '' ) {
516
        $options = (array) $options;
517
518
        if ( !in_array( $type, array( 'label', 'comment' ) ) ) {
519
            $name_clean = self::clean( $name );
520
            $name_more_clean = self::clean( $name, true );
521
            $_attributes = array();
522
            $_attributes[ 'name' ] = $name;
523
            $_attributes[ 'data-name-clean' ] = $name_more_clean;
524
525
            if ( 0 < strlen( pods_v( 'label', $options, '' ) ) )
526
                $_attributes[ 'data-label' ] = strip_tags( pods_v( 'label', $options ) );
527
528
            $_attributes[ 'id' ] = 'pods-form-ui-' . $name_clean;
529
            $_attributes[ 'class' ] = 'pods-form-ui-field-type-' . $type . ' pods-form-ui-field-name-' . $name_more_clean;
530
531
            if ( isset( $options[ 'dependency' ] ) && false !== $options[ 'dependency' ] )
532
                $_attributes[ 'class' ] .= ' pods-dependent-toggle';
533
534
            $attributes = array_merge( $_attributes, (array) $attributes );
535
536 View Code Duplication
            if ( isset( $options[ 'attributes' ] ) && is_array( $options[ 'attributes' ] ) && !empty( $options[ 'attributes' ] ) )
537
                $attributes = array_merge( $attributes, $options[ 'attributes' ] );
538
        }
539
        elseif ( isset( $options[ $type . '_attributes' ] ) && is_array( $options[ $type . '_attributes' ] ) && !empty( $options[ $type . '_attributes' ] ) )
540
            $attributes = array_merge( $attributes, $options[ $type . '_attributes' ] );
541
542
        if ( isset( $options[ 'class' ] ) && !empty( $options[ 'class' ] ) ) {
543
            if ( is_array( $options[ 'class' ] ) )
544
                $options[ 'class' ] = implode( ' ', $options[ 'class' ] );
545
546
            $options[ 'class' ] = (string) $options[ 'class' ];
547 View Code Duplication
            if ( isset( $attributes[ 'class' ] ) )
548
                $attributes[ 'class' ] = $attributes[ 'class' ] . ' ' . $options[ 'class' ];
549
            else
550
                $attributes[ 'class' ] = $options[ 'class' ];
551
552
            $attributes[ 'class' ] = trim( $attributes[ 'class' ] );
553
        }
554
555
        if ( !empty( $classes ) ) {
556 View Code Duplication
            if ( isset( $attributes[ 'class' ] ) )
557
                $attributes[ 'class' ] = $attributes[ 'class' ] . ' ' . $classes;
558
            else
559
                $attributes[ 'class' ] = $classes;
560
        }
561
562
        if ( isset( $options[ 'placeholder' ] ) && !empty( $options[ 'placeholder' ] ) ) {
563
            if ( is_array( $options[ 'placeholder' ] ) )
564
                $options[ 'placeholder' ] = implode( ' ', $options[ 'placeholder' ] );
565
566
            $options[ 'placeholder' ] = (string) $options[ 'placeholder' ];
567
			$attributes[ 'placeholder' ] = trim( $options[ 'placeholder' ] );
568
        }
569
570
        if ( 1 == pods_v( 'required', $options, 0 ) )
571
            $attributes[ 'class' ] .= ' pods-validate pods-validate-required';
572
573
        $max_length = (int) pods_var( 'maxlength', $options, pods_v( $type . '_max_length', $options, 0 ), null, true );
574
575
        if ( 0 < $max_length )
576
            $attributes[ 'maxlength' ] = $max_length;
577
578
        $attributes = (array) apply_filters( 'pods_form_ui_field_' . $type . '_merge_attributes', $attributes, $name, $options );
579
        return $attributes;
580
    }
581
582
    /**
583
     * Setup options for a field and store them for later use
584
     *
585
     * @param $type
586
     * @param $options
587
     *
588
     * @return array
589
     *
590
     * @static
591
     *
592
     * @since 2.0
593
     */
594
    public static function options( $type, $options ) {
595
        $options = (array) $options;
596
597
        if ( !is_object( $options ) && isset( $options[ 'options' ] ) ) {
598
            $options_temp = $options[ 'options' ];
599
600
            unset( $options[ 'options' ] );
601
602
            $options = array_merge( $options_temp, $options );
603
604
            $override = array(
605
                'class'
606
            );
607
608
            foreach ( $override as $check ) {
609
                if ( isset( $options_temp[ $check ] ) )
610
                    $options[ $check ] = $options_temp[ $check ];
611
            }
612
        }
613
614
        $defaults = self::options_setup( $type, $options );
615
616
        $core_defaults = array(
617
            'id' => 0,
618
            'label' => '',
619
            'description' => '',
620
            'help' => '',
621
            'default' => null,
622
            'attributes' => array(),
623
            'class' => '',
624
            'grouped' => 0,
625
        );
626
627
        $defaults = array_merge( $core_defaults, $defaults );
628
629
        foreach ( $defaults as $option => $settings ) {
630
            $default = $settings;
631
632
            if ( is_array( $settings ) && isset( $settings[ 'default' ] ) )
633
                $default = $settings[ 'default' ];
634
635
            if ( !isset( $options[ $option ] ) )
636
                $options[ $option ] = $default;
637
        }
638
639
        return $options;
640
    }
641
642
    /**
643
     * Get options for a field type and setup defaults
644
     *
645
     * @static
646
     *
647
     * @param $type
648
     *
649
     * @return array|null
650
     *
651
     * @since 2.0
652
     */
653
    public static function options_setup( $type = null, $options = null ) {
654
        $core_defaults = array(
655
            'id' => 0,
656
            'name' => '',
657
            'label' => '',
658
            'description' => '',
659
            'help' => '',
660
            'default' => null,
661
            'attributes' => array(),
662
            'class' => '',
663
            'type' => 'text',
664
            'group' => 0,
665
            'grouped' => 0,
666
            'developer_mode' => false,
667
            'dependency' => false,
668
            'depends-on' => array(),
669
            'excludes-on' => array(),
670
            'options' => array()
671
        );
672
673
        if ( !empty( $options ) && is_array( $options ) )
674
            $core_defaults = array_merge( $core_defaults, $options );
675
676
        if ( null === $type )
677
            return $core_defaults;
678
        else
679
            self::field_loader( $type );
680
681
        $options = apply_filters( 'pods_field_' . $type . '_options', (array) self::$loaded[ $type ]->options(), $type );
682
683
        $first_field = current( $options );
684
685
        if ( !empty( $options ) && !isset( $first_field[ 'name' ] ) && !isset( $first_field[ 'label' ] ) ) {
686
            $all_options = array();
687
688
            foreach ( $options as $group => $group_options ) {
689
                $all_options = array_merge( $all_options, self::fields_setup( $group_options, $core_defaults ) );
690
            }
691
692
            $options = $all_options;
693
        }
694
        else
695
            $options = self::fields_setup( $options, $core_defaults );
696
697
        return $options;
698
    }
699
700
    /**
701
     * Get Admin options for a field type and setup defaults
702
     *
703
     * @static
704
     *
705
     * @param $type
706
     *
707
     * @return array|null
708
     *
709
     * @since 2.0
710
     */
711
    public static function ui_options( $type ) {
712
        $core_defaults = array(
713
            'id' => 0,
714
            'name' => '',
715
            'label' => '',
716
            'description' => '',
717
            'help' => '',
718
            'default' => null,
719
            'attributes' => array(),
720
            'class' => '',
721
            'type' => 'text',
722
            'group' => 0,
723
            'grouped' => 0,
724
            'developer_mode' => false,
725
            'dependency' => false,
726
            'depends-on' => array(),
727
            'excludes-on' => array(),
728
            'options' => array()
729
        );
730
731
        self::field_loader( $type );
732
733
        $options = apply_filters( 'pods_field_' . $type . '_ui_options', (array) self::$loaded[ $type ]->ui_options(), $type );
734
735
        $first_field = current( $options );
736
737
        if ( !empty( $options ) && !isset( $first_field[ 'name' ] ) && !isset( $first_field[ 'label' ] ) ) {
738
            foreach ( $options as $group => $group_options ) {
739
                $options[ $group ] = self::fields_setup( $group_options, $core_defaults );
740
            }
741
        }
742
        else
743
            $options = self::fields_setup( $options, $core_defaults );
744
745
        return $options;
746
    }
747
748
    /**
749
     * Get options for a field and setup defaults
750
     *
751
     *
752
     * @param null $fields
753
     * @param null $core_defaults
754
     * @param bool $single
755
     *
756
     * @return array|null
757
     *
758
     * @static
759
     * @since 2.0
760
     */
761
    public static function fields_setup( $fields = null, $core_defaults = null, $single = false ) {
762
        if ( empty( $core_defaults ) ) {
763
            $core_defaults = array(
764
                'id' => 0,
765
                'name' => '',
766
                'label' => '',
767
                'description' => '',
768
                'help' => '',
769
                'default' => null,
770
                'attributes' => array(),
771
                'class' => '',
772
                'type' => 'text',
773
                'group' => 0,
774
                'grouped' => 0,
775
                'developer_mode' => false,
776
                'dependency' => false,
777
                'depends-on' => array(),
778
                'excludes-on' => array(),
779
                'options' => array()
780
            );
781
        }
782
783
        if ( $single )
784
            $fields = array( $fields );
785
786
        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...
787
            $fields[ $f ] = self::field_setup( $field, $core_defaults, pods_v( 'type', $field, 'text' ) );
788
789
            if ( !$single && strlen( $fields[ $f ][ 'name' ] ) < 1 )
790
                $fields[ $f ][ 'name' ] = $f;
791
        }
792
793
        if ( $single )
794
            $fields = $fields[ 0 ];
795
796
        return $fields;
797
    }
798
799
    /**
800
     * Get options for a field and setup defaults
801
     *
802
     * @static
803
     *
804
     * @param null $field
805
     * @param null $core_defaults
806
     * @param null $type
807
     *
808
     * @return array|null
809
     *
810
     * @since 2.0
811
     */
812
    public static function field_setup( $field = null, $core_defaults = null, $type = null ) {
813
        $options = array();
814
815
        if ( empty( $core_defaults ) ) {
816
            $core_defaults = array(
817
                'id' => 0,
818
                'name' => '',
819
                'label' => '',
820
                'description' => '',
821
                'help' => '',
822
                'default' => null,
823
                'attributes' => array(),
824
                'class' => '',
825
                'type' => 'text',
826
                'group' => 0,
827
                'grouped' => 0,
828
                'developer_mode' => false,
829
                'dependency' => false,
830
                'depends-on' => array(),
831
                'excludes-on' => array(),
832
                'options' => array()
833
            );
834
835
            if ( null !== $type ) {
836
                self::field_loader( $type );
837
838
                if ( method_exists( self::$loaded[ $type ], 'options' ) )
839
                    $options = apply_filters( 'pods_field_' . $type . '_options', (array) self::$loaded[ $type ]->options(), $type );
840
            }
841
        }
842
843
        if ( !is_array( $field ) )
844
            $field = array( 'default' => $field );
845
846
        if ( isset( $field[ 'group' ] ) && is_array( $field[ 'group' ] ) ) {
847
            foreach ( $field[ 'group' ] as $g => $group_option ) {
848
                $field[ 'group' ][ $g ] = array_merge( $core_defaults, $group_option );
849
850
                if ( strlen( $field[ 'group' ][ $g ][ 'name' ] ) < 1 )
851
                    $field[ 'group' ][ $g ][ 'name' ] = $g;
852
            }
853
        }
854
855
        $field = array_merge( $core_defaults, $field );
856
857
        foreach ( $options as $option => $settings ) {
858
            $v = null;
859
860
            if ( isset( $settings[ 'default' ] ) )
861
                $v = $settings[ 'default' ];
862
863
            if ( !isset( $field[ 'options' ][ $option ] ) )
864
                $field[ 'options' ][ $option ] = $v;
865
        }
866
867
        return $field;
868
    }
869
870
    /**
871
     * Setup dependency / exclusion classes
872
     *
873
     * @param array $options array( 'depends-on' => ..., 'excludes-on' => ...)
874
     * @param string $prefix
875
     *
876
     * @return string
877
     * @static
878
     * @since 2.0
879
     */
880
    public static function dependencies( $options, $prefix = '' ) {
881
        $options = (array) $options;
882
883
        $depends_on = $excludes_on = array();
884
        if ( isset( $options[ 'depends-on' ] ) )
885
            $depends_on = (array) $options[ 'depends-on' ];
886
887
        if ( isset( $options[ 'excludes-on' ] ) )
888
            $excludes_on = (array) $options[ 'excludes-on' ];
889
890
        $classes = array();
891
892 View Code Duplication
        if ( !empty( $depends_on ) ) {
893
            $classes[] = 'pods-depends-on';
894
895
            foreach ( $depends_on as $depends => $on ) {
896
                $classes[] = 'pods-depends-on-' . $prefix . self::clean( $depends, true );
897
898
                if ( !is_bool( $on ) ) {
899
                    $on = (array) $on;
900
901
                    foreach ( $on as $o ) {
902
                        $classes[] = 'pods-depends-on-' . $prefix . self::clean( $depends, true ) . '-' . self::clean( $o, true );
903
                    }
904
                }
905
            }
906
        }
907
908 View Code Duplication
        if ( !empty( $excludes_on ) ) {
909
            $classes[] = 'pods-excludes-on';
910
            foreach ( $excludes_on as $excludes => $on ) {
911
                $classes[] = 'pods-excludes-on-' . $prefix . self::clean( $excludes, true );
912
913
                $on = (array) $on;
914
915
                foreach ( $on as $o ) {
916
                    $classes[] = 'pods-excludes-on-' . $prefix . self::clean( $excludes, true ) . '-' . self::clean( $o, true );
917
                }
918
            }
919
        }
920
921
        $classes = implode( ' ', $classes );
922
923
        return $classes;
924
    }
925
926
    /**
927
     * Change the value of the field
928
     *
929
     * @param mixed $value
930
     * @param string $name
931
     * @param array $options
932
     * @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...
933
     * @param array $pod
934
     * @param int $id
935
     * @param array $traverse
936
     *
937
     * @since 2.3
938
     */
939
    public static function value( $type, $value = null, $name = null, $options = null, $pod = null, $id = null, $traverse = null ) {
940
        self::field_loader( $type );
941
942
        if ( in_array( $type, self::repeatable_field_types() ) && 1 == pods_v( $type . '_repeatable', $options, 0 ) && !is_array( $value ) ) {
943
            if ( 0 < strlen( $value ) ) {
944
                $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...
945
946
                if ( is_array( $simple ) )
947
                    $value = $simple;
948
                else
949
                    $value = (array) $value;
950
            }
951
            else
952
                $value = array();
953
        }
954
955
        if ( method_exists( self::$loaded[ $type ], 'value' ) ) {
956
            if ( is_array( $value ) && in_array( $type, self::tableless_field_types() ) ) {
957 View Code Duplication
                foreach ( $value as &$display_value ) {
958
                    $display_value = call_user_func_array( array( self::$loaded[ $type ], 'value' ), array( $display_value, $name, $options, $pod, $id, $traverse ) );
959
                }
960
            }
961 View Code Duplication
            else
962
                $value = call_user_func_array( array( self::$loaded[ $type ], 'value' ), array( $value, $name, $options, $pod, $id, $traverse ) );
963
        }
964
965
        return $value;
966
    }
967
968
    /**
969
     * Change the way the value of the field is displayed with Pods::get
970
     *
971
     * @param mixed $value
972
     * @param string $name
973
     * @param array $options
974
     * @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...
975
     * @param array $pod
976
     * @param int $id
977
     * @param array $traverse
978
     *
979
     * @since 2.0
980
     */
981
    public static function display( $type, $value = null, $name = null, $options = null, $pod = null, $id = null, $traverse = null ) {
982
        self::field_loader( $type );
983
984
        $tableless_field_types = self::tableless_field_types();
985
986
        if ( method_exists( self::$loaded[ $type ], 'display' ) ) {
987
            if ( is_array( $value ) && !in_array( $type, $tableless_field_types ) ) {
988 View Code Duplication
                foreach ( $value as $k => $display_value ) {
989
                    $value[ $k ] = call_user_func_array( array( self::$loaded[ $type ], 'display' ), array( $display_value, $name, $options, $pod, $id, $traverse ) );
990
                }
991
            }
992 View Code Duplication
            else
993
                $value = call_user_func_array( array( self::$loaded[ $type ], 'display' ), array( $value, $name, $options, $pod, $id, $traverse ) );
994
        }
995
996
        $value = apply_filters( 'pods_form_display_' . $type, $value, $name, $options, $pod, $id, $traverse );
997
998
        return $value;
999
    }
1000
1001
    /**
1002
     * Setup regex for JS / PHP
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 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...
1013
        self::field_loader( $type );
1014
1015
        $regex = false;
1016
1017
        if ( method_exists( self::$loaded[ $type ], 'regex' ) )
1018
            $regex = self::$loaded[ $type ]->regex( $options );
1019
1020
        $regex = apply_filters( 'pods_field_' . $type . '_regex', $regex, $options, $type );
1021
1022
        return $regex;
1023
    }
1024
1025
    /**
1026
     * Setup value preparation for sprintf
1027
     *
1028
     * @static
1029
     *
1030
     * @param $type
1031
     * @param $options
1032
     *
1033
     * @return mixed|void
1034
     * @since 2.0
1035
     */
1036 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...
1037
        self::field_loader( $type );
1038
1039
        $prepare = '%s';
1040
1041
        if ( method_exists( self::$loaded[ $type ], 'prepare' ) )
1042
            $prepare = self::$loaded[ $type ]->prepare( $options );
1043
1044
        $prepare = apply_filters( 'pods_field_' . $type . '_prepare', $prepare, $options, $type );
1045
1046
        return $prepare;
1047
    }
1048
1049
    /**
1050
     * Validate a value before it's saved
1051
     *
1052
     * @param string $type
1053
     * @param mixed $value
1054
     * @param string $name
1055
     * @param array $options
1056
     * @param array $fields
1057
     * @param array $pod
1058
     * @param int $id
1059
     * @param array|object $params
1060
     *
1061
     * @static
1062
     *
1063
     * @since 2.0
1064
     */
1065
    public static function validate( $type, $value, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
1066
        self::field_loader( $type );
1067
1068
        $validate = true;
1069
1070
        if ( 1 == pods_v( 'pre_save', $options, 1 ) && method_exists( self::$loaded[ $type ], 'validate' ) )
1071
            $validate = self::$loaded[ $type ]->validate( $value, $name, $options, $fields, $pod, $id, $params );
1072
1073
        $validate = apply_filters( 'pods_field_' . $type . '_validate', $validate, $value, $name, $options, $fields, $pod, $id, $type, $params );
1074
1075
        return $validate;
1076
    }
1077
1078
    /**
1079
     * Change the value or perform actions after validation but before saving to the DB
1080
     *
1081
     * @param string $type
1082
     * @param mixed $value
1083
     * @param int $id
1084
     * @param string $name
1085
     * @param array $options
1086
     * @param array $fields
1087
     * @param array $pod
1088
     * @param object $params
1089
     *
1090
     * @static
1091
     *
1092
     * @since 2.0
1093
     */
1094 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...
1095
        self::field_loader( $type );
1096
1097
        if ( 1 == pods_v( 'field_pre_save', $options, 1 ) && method_exists( self::$loaded[ $type ], 'pre_save' ) )
1098
            $value = self::$loaded[ $type ]->pre_save( $value, $id, $name, $options, $fields, $pod, $params );
1099
1100
        return $value;
1101
    }
1102
1103
    /**
1104
     * Save the value to the DB
1105
     *
1106
     * @param string $type
1107
     * @param mixed $value
1108
     * @param int $id
1109
     * @param string $name
1110
     * @param array $options
1111
     * @param array $fields
1112
     * @param array $pod
1113
     * @param object $params
1114
     *
1115
     * @static
1116
     *
1117
     * @since 2.3
1118
     */
1119 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...
1120
        self::field_loader( $type );
1121
1122
        $saved = null;
1123
1124
        if ( 1 == pods_v( 'field_save', $options, 1 ) && method_exists( self::$loaded[ $type ], 'save' ) )
1125
            $saved = self::$loaded[ $type ]->save( $value, $id, $name, $options, $fields, $pod, $params );
1126
1127
        return $saved;
1128
    }
1129
1130
    /**
1131
     * Delete the value from the DB
1132
     *
1133
     * @param string $type
1134
     * @param int $id
1135
     * @param string $name
1136
     * @param array $options
1137
     * @param array $pod
1138
     *
1139
     * @static
1140
     *
1141
     * @since 2.3
1142
     */
1143 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...
1144
        self::field_loader( $type );
1145
1146
        $deleted = null;
1147
1148
        if ( 1 == pods_v( 'field_delete', $options, 1 ) && method_exists( self::$loaded[ $type ], 'delete' ) )
1149
            $deleted = self::$loaded[ $type ]->delete( $id, $name, $options, $pod );
1150
1151
        return $deleted;
1152
    }
1153
1154
    /**
1155
     * Check if a user has permission to be editing a field
1156
     *
1157
     * @param $type
1158
     * @param null $name
1159
     * @param null $options
1160
     * @param null $fields
1161
     * @param null $pod
1162
     * @param null $id
1163
     * @param null $params
1164
     *
1165
     * @static
1166
     *
1167
     * @since 2.0
1168
     */
1169
    public static function permission( $type, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
1170
        $permission = pods_permission( $options );
1171
1172
        $permission = (boolean) apply_filters( 'pods_form_field_permission', $permission, $type, $name, $options, $fields, $pod, $id, $params );
1173
1174
        return $permission;
1175
    }
1176
1177
    /**
1178
     * Parse the default the value
1179
     *
1180
     * @since 2.0
1181
     */
1182
    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...
1183
        $default_value = pods_v( 'default_value', $options );
1184
1185
		if ( '' === $default_value || null === $default_value ) {
1186
			$default_value = $value;
1187
		}
1188
1189
        $default = pods_v( 'default', $options, $default_value, true );
1190
1191
	    if ( is_string( $default ) ) {
1192
		    $default_value = str_replace( array( '{@', '}' ), '', trim( $default ) );
1193
	    }
1194
1195
        if ( $default != $default_value && 1 == (int) pods_v( 'default_evaluate_tags', $options, 1 ) )
1196
            $default = pods_evaluate_tags( $default );
1197
1198
        $default = pods_var_raw( pods_v( 'default_value_parameter', $options ), 'request', $default, null, true );
1199
1200
        if ( $default != $value )
1201
            $value = $default;
1202
1203
        if ( is_array( $value ) )
1204
            $value = pods_serial_comma( $value );
1205
1206
        return apply_filters( 'pods_form_field_default_value', $value, $default, $type, $options, $pod, $id );
1207
    }
1208
1209
    /**
1210
     * Clean a value for use in class / id
1211
     *
1212
     * @since 2.0
1213
     */
1214
    public static function clean( $input, $noarray = false, $db_field = false ) {
1215
        $input = str_replace( array( '--1', '__1' ), '00000', (string) $input );
1216
        if ( false !== $noarray )
1217
            $input = preg_replace( '/\[\d*\]/', '-', $input );
1218
        $output = str_replace( array( '[', ']' ), '-', strtolower( $input ) );
1219
        $output = preg_replace( '/([^a-z0-9\-_])/', '', $output );
1220
        $output = trim( str_replace( array( '__', '_', '--' ), '-', $output ), '-' );
1221
        $output = str_replace( '00000', '--1', $output );
1222
        if ( false !== $db_field )
1223
            $output = str_replace( '-', '_', $output );
1224
        return $output;
1225
    }
1226
1227
    /**
1228
     * Run admin_init methods for each field type
1229
     *
1230
     * @since 2.3
1231
     */
1232
    public function admin_init() {
1233
        $admin_field_types = pods_transient_get( 'pods_form_admin_init_field_types' );
1234
1235
        if ( empty( $admin_field_types ) ) {
1236
            $admin_field_types = array();
1237
1238
            $field_types = self::field_types();
1239
1240
            foreach ( $field_types as $field_type => $field_type_data ) {
1241
                $has_ajax = self::field_method( $field_type_data[ 'type' ], 'admin_init' );
1242
1243
                if ( false !== $has_ajax )
1244
                    $admin_field_types[] = $field_type;
1245
            }
1246
1247
            pods_transient_set( 'pods_form_admin_init_field_types', $admin_field_types );
1248
        }
1249
        else {
1250
            foreach ( $admin_field_types as $field_type ) {
1251
                self::field_method( $field_type, 'admin_init' );
1252
            }
1253
        }
1254
    }
1255
1256
    /**
1257
     * Autoload a Field Type's class
1258
     *
1259
     * @param string $field_type Field Type indentifier
1260
     * @param string $file The Field Type class file location
1261
     *
1262
     * @return string
1263
     * @access public
1264
     * @static
1265
     * @since 2.0
1266
     */
1267
    public static function field_loader( $field_type, $file = '' ) {
1268
        if ( isset( self::$loaded[ $field_type ] ) ) {
1269
            $class_vars = get_class_vars( get_class( self::$loaded[ $field_type ] ) ); // PHP 5.2.x workaround
1270
1271
            self::$field_group = ( isset( $class_vars[ 'group' ] ) ? $class_vars[ 'group' ] : '' );
1272
            self::$field_type = $class_vars[ 'type' ];
1273
1274
            if ( 'Unknown' != $class_vars[ 'label' ] )
1275
                return self::$loaded[ $field_type ];
1276
        }
1277
1278
        include_once PODS_DIR . 'classes/PodsField.php';
1279
1280
        $field_type = self::clean( $field_type, true, true );
1281
1282
        $class_name = ucfirst( $field_type );
1283
        $class_name = "PodsField_{$class_name}";
1284
1285
        $content_dir = realpath( WP_CONTENT_DIR );
1286
        $plugins_dir = realpath( WP_PLUGIN_DIR );
1287
        $muplugins_dir = realpath( WPMU_PLUGIN_DIR );
1288
        $abspath_dir = realpath( ABSPATH );
1289
1290
        if ( !class_exists( $class_name ) ) {
1291
            if ( isset( self::$field_types[ $field_type ] ) && !empty( self::$field_types[ $field_type ][ 'file' ] ) )
1292
                $file = realpath( self::$field_types[ $field_type ][ 'file' ] );
1293
1294
            if ( !empty( $file ) && 0 === strpos( $file, $abspath_dir ) && file_exists( $file ) )
1295
                include_once $file;
1296
            else {
1297
                $file = str_replace( '../', '', apply_filters( 'pods_form_field_include', PODS_DIR . 'classes/fields/' . basename( $field_type ) . '.php', $field_type ) );
1298
                $file = realpath( $file );
1299
1300
                if ( file_exists( $file ) && ( 0 === strpos( $file, $content_dir ) || 0 === strpos( $file, $plugins_dir ) || 0 === strpos( $file, $muplugins_dir ) || 0 === strpos( $file, $abspath_dir ) ) )
1301
                    include_once $file;
1302
            }
1303
        }
1304
1305
        if ( class_exists( $class_name ) )
1306
            $class = new $class_name();
1307
        else {
1308
            $class = new PodsField();
1309
            $class_name = 'PodsField';
1310
        }
1311
1312
        $class_vars = get_class_vars( $class_name ); // PHP 5.2.x workaround
1313
1314
        self::$field_group = ( isset( $class_vars[ 'group' ] ) ? $class_vars[ 'group' ] : '' );
1315
        self::$field_type = $class_vars[ 'type' ];
1316
1317
        self::$loaded[ $field_type ] =& $class;
1318
1319
        return self::$loaded[ $field_type ];
1320
    }
1321
1322
    /**
1323
     * Run a method from a Field Type's class
1324
     *
1325
     * @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...
1326
     * @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...
1327
     * @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...
1328
     *
1329
     * @return mixed
1330
     * @access public
1331
     * @static
1332
     * @since 2.0
1333
     */
1334
    public static function field_method() {
1335
        $args = func_get_args();
1336
1337
        if ( empty( $args ) && count( $args ) < 2 )
1338
            return false;
1339
1340
        $field_type = array_shift( $args );
1341
        $method = array_shift( $args );
1342
1343
        $class = self::field_loader( $field_type );
1344
1345
        if ( method_exists( $class, $method ) )
1346
            return call_user_func_array( array( $class, $method ), $args );
1347
1348
        return false;
1349
    }
1350
1351
    /**
1352
     * Add a new Pod field type
1353
     *
1354
     * @param string $type The new field type identifier
1355
     * @param string $file The new field type class file location
1356
     *
1357
     * @return array Field Type data
1358
     *
1359
     * @since 2.3
1360
     */
1361
    public static function register_field_type( $type, $file = null ) {
1362
        $field_type = pods_transient_get( 'pods_field_type_' . $type );
1363
1364
        if ( empty( $field_type ) || $field_type[ 'type' ] != $type || $field_type[ 'file' ] != $file ) {
1365
            self::field_loader( $type, $file );
1366
1367
            $class_vars = get_class_vars( get_class( self::$loaded[ $type ] ) ); // PHP 5.2.x workaround
1368
1369
            self::$field_types[ $type ] = $class_vars;
1370
            self::$field_types[ $type ][ 'file' ] = $file;
1371
1372
            pods_transient_set( 'pods_field_type_' . $type, self::$field_types[ $type ] );
1373
        }
1374
        else
1375
            self::$field_types[ $type ] = $field_type;
1376
1377
        return self::$field_types[ $type ];
1378
    }
1379
1380
    /**
1381
     * Get a list of all available field types and include
1382
     *
1383
     * @return array Registered Field Types data
1384
     *
1385
     * @since 2.3
1386
     */
1387
    public static function field_types() {
1388
        $field_types = array(
1389
            'text',
1390
            'website',
1391
            'phone',
1392
            'email',
1393
            'password',
1394
            'paragraph',
1395
            'wysiwyg',
1396
            'code',
1397
            'datetime',
1398
            'date',
1399
            'time',
1400
            'number',
1401
            'currency',
1402
            'file',
1403
            'avatar',
1404
            'pick',
1405
            'boolean',
1406
            'color',
1407
            'slug'
1408
        );
1409
1410
        $field_types = array_merge( $field_types, array_keys( self::$field_types ) );
1411
1412
        $field_types = array_filter( array_unique( $field_types ) );
1413
1414
        $types = apply_filters( 'pods_api_field_types', $field_types );
1415
1416
        $field_types = pods_transient_get( 'pods_field_types' );
1417
1418
        if ( empty( $field_types ) || count( $types ) != count( $field_types ) ) {
1419
            $field_types = array();
1420
1421
            foreach ( $types as $field_type ) {
1422
                $file = null;
1423
1424
                if ( isset( self::$field_types[ $field_type ] ) )
1425
                    $file = self::$field_types[ $field_type ][ 'file' ];
1426
1427
                self::field_loader( $field_type, $file );
1428
1429
                if ( !isset( self::$loaded[ $field_type ] ) || !is_object( self::$loaded[ $field_type ] ) )
1430
                    continue;
1431
1432
                $class_vars = get_class_vars( get_class( self::$loaded[ $field_type ] ) ); // PHP 5.2.x workaround
1433
1434
                $field_types[ $field_type ] = $class_vars;
1435
                $field_types[ $field_type ][ 'file' ] = $file;
1436
            }
1437
1438
            self::$field_types = $field_types;
1439
1440
            pods_transient_set( 'pods_field_types', self::$field_types );
1441
        }
1442
        else
1443
            self::$field_types = array_merge( $field_types, self::$field_types );
1444
1445
        return self::$field_types;
1446
    }
1447
1448
    /**
1449
     * Get list of available tableless field types
1450
     *
1451
     * @return array Tableless field types
1452
     *
1453
     * @since 2.3
1454
     */
1455 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...
1456
	    static $field_types = null;
1457
1458
	    if ( null === $field_types ) {
1459
		    $field_types = array( 'pick', 'file', 'avatar', 'taxonomy' );
1460
1461
		    $field_types = apply_filters( 'pods_tableless_field_types', $field_types );
1462
	    }
1463
	    return $field_types;
1464
    }
1465
1466
    /**
1467
     * Get list of available file field types
1468
     *
1469
     * @return array File field types
1470
     *
1471
     * @since 2.3
1472
     */
1473 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...
1474
	    static $field_types = null;
1475
1476
	    if ( null === $field_types ) {
1477
		    $field_types = array( 'file', 'avatar' );
1478
1479
		    $field_types = apply_filters( 'pods_file_field_types', $field_types );
1480
	    }
1481
	    return $field_types;
1482
    }
1483
1484
    /**
1485
     * Get list of available repeatable field types
1486
     *
1487
     * @return array Repeatable field types
1488
     *
1489
     * @since 2.3
1490
     */
1491
    public static function repeatable_field_types() {
1492
	    static $field_types = null;
1493
1494
	    if ( null === $field_types ) {
1495
		    $field_types = array(
1496
			    'code',
1497
			    'color',
1498
			    'currency',
1499
			    'date',
1500
			    'datetime',
1501
			    'email',
1502
			    'number',
1503
			    'paragraph',
1504
			    'phone',
1505
			    'text',
1506
			    'time',
1507
			    'website',
1508
			    'wysiwyg'
1509
		    );
1510
1511
		    $field_types = apply_filters( 'pods_repeatable_field_types', $field_types );
1512
	    }
1513
	    return $field_types;
1514
    }
1515
1516
    /**
1517
     * Get list of available number field types
1518
     *
1519
     * @return array Number field types
1520
     *
1521
     * @since 2.3
1522
     */
1523 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...
1524
	    static $field_types = null;
1525
1526
	    if ( null === $field_types ) {
1527
		    $field_types = array( 'currency', 'number' );
1528
1529
		    $field_types = apply_filters( 'pods_tableless_field_types', $field_types );
1530
	    }
1531
	    return $field_types;
1532
    }
1533
1534
    /**
1535
     * Get list of available date field types
1536
     *
1537
     * @return array Date field types
1538
     *
1539
     * @since 2.3
1540
     */
1541 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...
1542
	    static $field_types = null;
1543
1544
	    if ( null === $field_types ) {
1545
		    $field_types = array( 'date', 'datetime', 'time' );
1546
1547
		    $field_types = apply_filters( 'pods_tableless_field_types', $field_types );
1548
	    }
1549
	    return $field_types;
1550
    }
1551
1552
    /**
1553
     * Get list of available text field types
1554
     *
1555
     * @return array Text field types
1556
     *
1557
     * @since 2.3
1558
     */
1559
    public static function text_field_types() {
1560
	    static $field_types = null;
1561
1562
	    if ( null === $field_types ) {
1563
		    $field_types = array( 'code', 'paragraph', 'slug', 'password', 'text', 'wysiwyg' );
1564
1565
		    $field_types = apply_filters( 'pods_text_field_types', $field_types );
1566
	    }
1567
	    return $field_types;
1568
    }
1569
1570
    /**
1571
     * Get list of available text field types
1572
     *
1573
     * @return array Text field types
1574
     *
1575
     * @since 2.3
1576
     */
1577
    public static function block_field_types() {
1578
	    static $field_types = null;
1579
1580
	    if ( null === $field_types ) {
1581
		    $field_types = array( 'heading', 'html' );
1582
1583
		    /**
1584
		     * Returns the available text field types
1585
		     *
1586
		     * @since unknown
1587
		     *
1588
		     * @param object $field_types Outputs the field types
1589
		     */
1590
1591
		    $field_types = apply_filters( 'pods_block_field_types', $field_types );
1592
	    }
1593
	    return $field_types;
1594
    }
1595
1596
	/**
1597
	 * Get list of available text field types
1598
	 *
1599
	 * @return array Text field types
1600
	 *
1601
	 * @since 2.3
1602
	 */
1603
	public static function simple_tableless_objects() {
1604
		static $object_types = null;
1605
1606
		if ( null === $object_types ) {
1607
			$object_types = PodsForm::field_method( 'pick', 'simple_objects' );
1608
		}
1609
		return $object_types;
1610
	}
1611
1612
	}
1613