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

PodsForm::flex_relationship()   C

Complexity

Conditions 10
Paths 6

Size

Total Lines 82
Code Lines 46

Duplication

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