Completed
Pull Request — 2.x (#3260)
by Phil
06:21
created

PodsForm::data()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 15
Code Lines 9

Duplication

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