Completed
Push — 2.x ( 9dc08a...ea92a3 )
by Scott Kingsley
03:32 queued 03:26
created

PodsForm::label()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 33
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

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