Completed
Pull Request — 2.x (#3260)
by Phil
07:34
created

PodsForm::attributes()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 6

Duplication

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

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

class A {
    var $property;
}

the property is implicitly global.

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

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

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

class A {
    var $property;
}

the property is implicitly global.

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

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

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

class A {
    var $property;
}

the property is implicitly global.

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

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

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

class A {
    var $property;
}

the property is implicitly global.

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

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

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

class A {
    var $property;
}

the property is implicitly global.

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

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

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

class A {
    var $property;
}

the property is implicitly global.

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

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

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

Please refer to the PHP core documentation on constructors.

Loading history...
60
     *
61
     * @license http://www.gnu.org/licenses/gpl-2.0.html
62
     * @since 2.0
63
     */
64
    private function __construct() {
65
        add_action( 'admin_init', array( $this, 'admin_init' ), 14 );
66
    }
67
68
    /**
69
     * Prevent clones
70
     *
71
     * @since 2.3
72
     */
73
    private function __clone() {
74
        // Hulk smash
75
    }
76
77
    /**
78
     * Output a field's label
79
     *
80
     * @since 2.0
81
     */
82
83
    /**
84
     * Output a field's label
85
     *
86
     * @param string $name Field name
87
     * @param string $label Label text
88
     * @param string $help Help text
89
     * @param array $options Field options
90
     *
91
     * @return string Label HTML
92
     *
93
     * @since 2.0
94
     */
95
    public static function label( $name, $label, $help = '', $options = null ) {
96
        if ( is_array( $label ) || is_object( $label ) ) {
97
            $options = $label;
98
            $label = $options[ 'label' ];
99
100
            if ( empty( $label ) )
101
                $label = ucwords( str_replace( '_', ' ', $name ) );
102
103
            $help = $options[ 'help' ];
104
        }
105
        else
106
            $options = self::options( null, $options );
107
108
        $label = apply_filters( 'pods_form_ui_label_text', $label, $name, $help, $options );
109
        $help = apply_filters( 'pods_form_ui_label_help', $help, $name, $label, $options );
110
111
        ob_start();
112
113
        $name_clean = self::clean( $name );
114
        $name_more_clean = self::clean( $name, true );
115
116
        $type = 'label';
117
        $attributes = array();
118
        $attributes[ 'class' ] = 'pods-form-ui-' . $type . ' pods-form-ui-' . $type . '-' . $name_more_clean;
119
        $attributes[ 'for' ] = ( false === strpos( $name_clean, 'pods-form-ui-' ) ? 'pods-form-ui-' : '' ) . $name_clean;
120
        $attributes = self::merge_attributes( $attributes, $name, $type, $options, false );
121
122
        pods_view( PODS_DIR . 'ui/fields/_label.php', compact( array_keys( get_defined_vars() ) ) );
123
124
        $output = ob_get_clean();
125
126
        return apply_filters( 'pods_form_ui_' . $type, $output, $name, $label, $help, $attributes, $options );
127
    }
128
129
    /**
130
     * Output a Field Comment Paragraph
131
     *
132
     * @param string $name Field name
133
     * @param string $message Field comments
134
     * @param array $options Field options
135
     *
136
     * @return string Comment HTML
137
     *
138
     * @since 2.0
139
     */
140
    public static function comment( $name, $message = null, $options = null ) {
141
        $options = self::options( null, $options );
142
143
        $name_more_clean = self::clean( $name, true );
144
145
        if ( isset( $options[ 'description' ] ) && !empty( $options[ 'description' ] ) )
146
            $message = $options[ 'description' ];
147
        elseif ( empty( $message ) )
148
            return '';
149
150
        $message = apply_filters( 'pods_form_ui_comment_text', $message, $name, $options );
151
152
        ob_start();
153
154
        $type = 'comment';
155
        $attributes = array();
156
        $attributes[ 'class' ] = 'pods-form-ui-' . $type . ' pods-form-ui-' . $type . '-' . $name_more_clean;
157
        $attributes = self::merge_attributes( $attributes, $name, $type, $options, false );
158
159
        pods_view( PODS_DIR . 'ui/fields/_comment.php', compact( array_keys( get_defined_vars() ) ) );
160
161
        $output = ob_get_clean();
162
163
        return apply_filters( 'pods_form_ui_' . $type, $output, $name, $message, $attributes, $options );
164
    }
165
166
    /**
167
     * Output a field
168
     *
169
     * @param string $name Field name
170
     * @param mixed $value Field value
171
     * @param string $type Field type
172
     * @param array $options Field options
173
     * @param array $pod Pod data
174
     * @param int $id Item ID
175
     *
176
     * @return string Field HTML
177
     *
178
     * @since 2.0
179
     */
180
    public static function field( $name, $value, $type = 'text', $options = null, $pod = null, $id = null ) {
181
		// Take a field array
182
		if ( is_array( $name ) || is_object( $name ) ) {
183
			$options = $name;
184
185
			if ( is_object( $type ) ) {
186
				$pod = $type;
187
				$id = $options;
188
			}
189
190
			$name = pods_v( 'name', $options );
191
			$type = pods_v( 'type', $options );
192
		}
193
194
        $options = self::options( $type, $options );
195
196
        if ( null === $value || ( '' === $value && 'boolean' == $type ) || ( !empty( $pod ) && empty( $id ) ) )
197
            $value = self::default_value( $value, $type, $name, $options, $pod, $id );
198
199
        if ( false === self::permission( $type, $name, $options, null, $pod, $id ) )
200
            return false;
201
202
        $value = apply_filters( 'pods_form_ui_field_' . $type . '_value', $value, $name, $options, $pod, $id );
203
        $form_field_type = self::$field_type;
204
205
        ob_start();
206
207
        $helper = false;
208
209
        if ( 0 < strlen( pods_v( 'input_helper', $options ) ) )
210
            $helper = pods_api()->load_helper( array( 'name' => $options[ 'input_helper' ] ) );
211
212
        if ( ( !isset( $options[ 'data' ] ) || empty( $options[ 'data' ] ) ) && is_object( self::$loaded[ $type ] ) && method_exists( self::$loaded[ $type ], 'data' ) )
213
            $data = $options[ 'data' ] = self::$loaded[ $type ]->data( $name, $value, $options, $pod, $id, true );
214
215
        if ( true === apply_filters( 'pods_form_ui_field_' . $type . '_override', false, $name, $value, $options, $pod, $id ) )
216
            do_action( 'pods_form_ui_field_' . $type, $name, $value, $options, $pod, $id );
217
        elseif ( !empty( $helper ) && 0 < strlen( pods_v( 'code', $helper ) ) && false === strpos( $helper[ 'code' ], '$this->' ) && ( !defined( 'PODS_DISABLE_EVAL' ) || !PODS_DISABLE_EVAL ) )
218
            eval( '?>' . $helper[ 'code' ] );
0 ignored issues
show
Coding Style introduced by
It is generally not recommended to use eval unless absolutely required.

On one hand, eval might be exploited by malicious users if they somehow manage to inject dynamic content. On the other hand, with the emergence of faster PHP runtimes like the HHVM, eval prevents some optimization that they perform.

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