Completed
Pull Request — 2.x (#3260)
by Phil
09:24 queued 03:48
created

PodsForm::flex_relationship()   C

Complexity

Conditions 10
Paths 6

Size

Total Lines 81
Code Lines 46

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 81
rs 5.5056
cc 10
eloc 46
nc 6
nop 2

How to fix   Long Method    Complexity   

Long Method

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

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

Commonly applied refactorings include:

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

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

class A {
    var $property;
}

the property is implicitly global.

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

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

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

class A {
    var $property;
}

the property is implicitly global.

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

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

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

class A {
    var $property;
}

the property is implicitly global.

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

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

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

class A {
    var $property;
}

the property is implicitly global.

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

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

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

class A {
    var $property;
}

the property is implicitly global.

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

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

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

class A {
    var $property;
}

the property is implicitly global.

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

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

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

Please refer to the PHP core documentation on constructors.

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