Completed
Pull Request — 2.x (#3260)
by Phil
09:19
created

PodsForm::row()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 11
Code Lines 6

Duplication

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

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

class A {
    var $property;
}

the property is implicitly global.

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

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

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

class A {
    var $property;
}

the property is implicitly global.

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

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

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

class A {
    var $property;
}

the property is implicitly global.

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

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

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

class A {
    var $property;
}

the property is implicitly global.

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

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

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

class A {
    var $property;
}

the property is implicitly global.

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

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

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

class A {
    var $property;
}

the property is implicitly global.

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

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

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

Please refer to the PHP core documentation on constructors.

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

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

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