Completed
Pull Request — 2.x (#3910)
by
unknown
04:23
created

PodsField_File::regex()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 5
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @package Pods\Fields
4
 */
5
class PodsField_File extends PodsField {
6
7
    /**
8
     * Field Type Group
9
     *
10
     * @var string
11
     * @since 2.0
12
     */
13
    public static $group = 'Relationships / Media';
14
15
    /**
16
     * Field Type Identifier
17
     *
18
     * @var string
19
     * @since 2.0
20
     */
21
    public static $type = 'file';
22
23
    /**
24
     * Field Type Label
25
     *
26
     * @var string
27
     * @since 2.0
28
     */
29
    public static $label = 'File / Image / Video';
30
31
    /**
32
     * API caching for fields that need it during validate/save
33
     *
34
     * @var \PodsAPI
35
     * @since 2.3
36
     */
37
    protected static $api = false;
38
39
    /**
40
     * Do things like register/enqueue scripts and stylesheets
41
     *
42
     * @since 2.0
43
     */
44
    public function __construct () {
45
        self::$label = __( 'File / Image / Video', 'pods' );
46
    }
47
48
    /**
49
     * Add admin_init actions
50
     *
51
     * @since 2.3
52
     */
53
    public function admin_init() {
54
        // AJAX for Uploads
55
        add_action( 'wp_ajax_pods_upload', array( $this, 'admin_ajax_upload' ) );
56
        add_action( 'wp_ajax_nopriv_pods_upload', array( $this, 'admin_ajax_upload' ) );
57
    }
58
59
    /**
60
     * Add options and set defaults to
61
     *
62
     * @param array $options
0 ignored issues
show
Bug introduced by
There is no parameter named $options. 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...
63
     *
64
     * @since 2.0
65
     */
66
    public function options () {
67
        $sizes = get_intermediate_image_sizes();
68
69
        $image_sizes = array();
70
71
        foreach ( $sizes as $size ) {
72
            $image_sizes[ $size ] = ucwords( str_replace( '-', ' ', $size ) );
73
        }
74
75
        $options = array(
76
            self::$type . '_format_type' => array(
77
                'label' => __( 'Upload Limit', 'pods' ),
78
                'default' => 'single',
79
                'type' => 'pick',
80
                'data' => array(
81
                    'single' => __( 'Single File', 'pods' ),
82
                    'multi' => __( 'Multiple Files', 'pods' )
83
                ),
84
                'dependency' => true
85
            ),
86
            self::$type . '_uploader' => array(
87
                'label' => __( 'File Uploader', 'pods' ),
88
                'default' => 'attachment',
89
                'type' => 'pick',
90
                'data' => apply_filters(
91
                    'pods_form_ui_field_file_uploader_options',
92
                    array(
93
                        'attachment' => __( 'Attachments (WP Media Library)', 'pods' ),
94
                        'plupload' => __( 'Plupload', 'pods' )
95
                    )
96
                ),
97
                'dependency' => true
98
            ),
99
            self::$type . '_attachment_tab' => array(
100
                'label' => __( 'Attachments Default Tab', 'pods' ),
101
                'depends-on' => array( self::$type . '_uploader' => 'attachment' ),
102
                'default' => 'upload',
103
                'type' => 'pick',
104
                'data' => array(
105
                    // keys MUST match WP's router names
106
                    'upload' => __( 'Upload File', 'pods' ),
107
                    'browse' => __( 'Media Library', 'pods' )
108
                )
109
            ),
110
            self::$type . '_edit_title' => array(
111
                'label' => __( 'Editable Title', 'pods' ),
112
                'default' => 1,
113
                'type' => 'boolean'
114
            ),
115
            self::$type . '_linked' => array(
116
                'label' => __( 'Link to File in editor', 'pods' ),
117
                'default' => 0,
118
                'type' => 'boolean'
119
            ),
120
            self::$type . '_limit' => array(
121
                'label' => __( 'Max Number of Files', 'pods' ),
122
                'depends-on' => array( self::$type . '_format_type' => 'multi' ),
123
                'default' => 0,
124
                'type' => 'number'
125
            ),
126
            self::$type . '_restrict_filesize' => array(
127
                'label' => __( 'Restrict File Size', 'pods' ),
128
                'depends-on' => array( self::$type . '_uploader' => 'plupload' ),
129
                'default' => '10MB',
130
                'type' => 'text'
131
            ),
132
            self::$type . '_type' => array(
133
                'label' => __( 'Restrict File Types', 'pods' ),
134
                'default' => apply_filters( 'pods_form_ui_field_file_type_default', 'images' ),
135
                'type' => 'pick',
136
                'data' => apply_filters(
137
                    'pods_form_ui_field_file_type_options',
138
                    array(
139
                        'images' => __( 'Images (jpg, jpeg, png, gif)', 'pods' ),
140
                        'video' => __( 'Video (mpg, mov, flv, mp4, etc..)', 'pods' ),
141
                        'audio' => __( 'Audio (mp3, m4a, wav, wma, etc..)', 'pods' ),
142
                        'text' => __( 'Text (txt, csv, tsv, rtx, etc..)', 'pods' ),
143
                        'any' => __( 'Any Type (no restriction)', 'pods' ),
144
                        'other' => __( 'Other (customize allowed extensions)', 'pods' )
145
                    )
146
                ),
147
                'dependency' => true
148
            ),
149
            self::$type . '_allowed_extensions' => array(
150
                'label' => __( 'Allowed File Extensions', 'pods' ),
151
                'description' => __( 'Separate file extensions with a comma (ex. jpg,png,mp4,mov)', 'pods' ),
152
                'depends-on' => array( self::$type . '_type' => 'other' ),
153
                'default' => apply_filters( 'pods_form_ui_field_file_extensions_default', '' ),
154
                'type' => 'text'
155
            ),/*
0 ignored issues
show
Unused Code Comprehensibility introduced by
53% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
156
            self::$type . '_field_template' => array(
157
                'label' => __( 'Field template', 'pods' ),
158
                'default' => apply_filters( 'pods_form_ui_field_file_template_default', 'rows' ),
159
                'depends-on' => array( self::$type . '_type' => 'images' ),
160
                'type' => 'pick',
161
                'data' => apply_filters(
162
                    'pods_form_ui_field_file_type_templates',
163
                    array(
164
                        'rows' => __( 'Rows', 'pods' ),
165
                        'tiles' => __( 'Tiles', 'pods' ),
166
                    )
167
                ),
168
                'dependency' => true
169
            ),
170
            self::$type . '_image_size' => array(
171
                'label' => __( 'Excluded Image Sizes', 'pods' ),
172
                'description' => __( 'Image sizes not to generate when processing the image', 'pods' ),
173
                'depends-on' => array( self::$type . '_type' => 'images' ),
174
                'default' => 'images',
175
                'type' => 'pick',
176
                'pick_format_type' => 'multi',
177
                'pick_format_multi' => 'checkbox',
178
                'data' => apply_filters(
179
                    'pods_form_ui_field_file_image_size_options',
180
                    $image_sizes
181
                )
182
            ),*/
183
            self::$type . '_add_button' => array(
184
                'label' => __( 'Add Button Text', 'pods' ),
185
                'default' => __( 'Add File', 'pods' ),
186
                'type' => 'text'
187
            ),
188
            self::$type . '_modal_title' => array(
189
                'label' => __( 'Modal Title', 'pods' ),
190
                'depends-on' => array( self::$type . '_uploader' => 'attachment' ),
191
                'default' => __( 'Attach a file', 'pods' ),
192
                'type' => 'text'
193
            ),
194
            self::$type . '_modal_add_button' => array(
195
                'label' => __( 'Modal Add Button Text', 'pods' ),
196
                'depends-on' => array( self::$type . '_uploader' => 'attachment' ),
197
                'default' => __( 'Add File', 'pods' ),
198
                'type' => 'text'
199
            ),
200
			/* WP GALLERY OUTPUT */
201
            self::$type . '_wp_gallery_output' => array(
202
	            'label' => __( 'Output as a WP Gallery', 'pods' ),
203
	            'help' => sprintf(
204
	            	__( '<a href="%s" target="_blank">Click here for more info</a>', 'pods' ),
205
					'https://codex.wordpress.org/The_WordPress_Gallery'
206
				),
207
	            'depends-on' => array( self::$type . '_type' => 'images' ),
208
	            'dependency' => true,
209
	            'type' => 'boolean'
210
            ),
211
            self::$type . '_wp_gallery_link' => array(
212
	            'label' => __( 'WP Gallery link', 'pods' ),
213
	            'depends-on' => array( self::$type . '_wp_gallery_output' => 1 ),
214
	            'type' => 'pick',
215
	            'data' => array(
216
		            'post' => __( 'Attachment Page', 'pods' ),
217
		            'file' => __( 'Media File', 'pods' ),
218
		            'none' => __( 'None', 'pods' )
219
	            )
220
            ),
221
            self::$type . '_wp_gallery_columns' => array(
222
	            'label' => __( 'WP Gallery columns', 'pods' ),
223
	            'depends-on' => array( self::$type . '_wp_gallery_output' => 1 ),
224
	            'type' => 'pick',
225
	            'data' => array(
226
		            '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '6' => 6, '7' => 7, '8' => 8, '9' => 9,
227
	            )
228
            ),
229
            self::$type . '_wp_gallery_random_sort' => array(
230
	            'label' => __( 'WP Gallery random order?', 'pods' ),
231
	            'depends-on' => array( self::$type . '_wp_gallery_output' => 1 ),
232
	            'type' => 'boolean'
233
            ),
234
            self::$type . '_wp_gallery_size' => array(
235
	            'label' => __( 'WP Gallery image size', 'pods' ),
236
	            'depends-on' => array( self::$type . '_wp_gallery_output' => 1 ),
237
	            'type' => 'pick',
238
	            'data' => $this->data_image_sizes()
239
            )
240
        );
241
242 View Code Duplication
        if ( !pods_version_check( 'wp', '3.5' ) ) {
243
            unset( $options[ self::$type . '_linked' ] );
244
            unset( $options[ self::$type . '_modal_title' ] );
245
            unset( $options[ self::$type . '_modal_add_button' ] );
246
247
            $options[ self::$type . '_attachment_tab' ][ 'default' ] = 'type';
248
            $options[ self::$type . '_attachment_tab' ][ 'data' ] = array(
249
                'type' => __( 'Upload File', 'pods' ),
250
                'library' => __( 'Media Library', 'pods' )
251
            );
252
        }
253
254
        return $options;
255
    }
256
257
    /**
258
     * Define the current field's schema for DB table storage
259
     *
260
     * @param array $options
261
     *
262
     * @return array
263
     * @since 2.0
264
     */
265
    public function schema ( $options = null ) {
266
        $schema = false;
267
268
        return $schema;
269
    }
270
271
    /**
272
     * Change the way the value of the field is displayed with Pods::get
273
     *
274
     * @param mixed $value
275
     * @param string $name
276
     * @param array $options
277
     * @param array $pod
278
     * @param int $id
279
     *
280
     * @return mixed|null
281
     * @since 2.0
282
     */
283
    public function display ( $value = null, $name = null, $options = null, $pod = null, $id = null ) {
284
    	if ( 1 == $options[ self::$type . '_wp_gallery_output' ] ) {
285
    		return $this->do_wp_gallery( $value, $options );
286
		}
287
288
        if ( is_array( $value ) && !empty( $value ) ) {
289
            if ( isset( $value[ 'ID' ] ) )
290
                $value = wp_get_attachment_url( $value[ 'ID' ] );
291
            else {
292
                $attachments = $value;
293
                $value = array();
294
295 View Code Duplication
                foreach ( $attachments as $v ) {
296
                    if ( !is_array( $v ) )
297
                        $value[] = $v;
298
                    elseif ( isset( $v[ 'ID' ] ) )
299
                        $value[] = wp_get_attachment_url( $v[ 'ID' ] );
300
                }
301
302
                $value = implode( ' ', $value );
303
            }
304
        }
305
306
        return $value;
307
    }
308
309
    /**
310
     * Customize output of the form field
311
     *
312
     * @param string $name
313
     * @param mixed $value
314
     * @param array $options
315
     * @param array $pod
316
     * @param int $id
317
     *
318
     * @since 2.0
319
     */
320
    public function input ( $name, $value = null, $options = null, $pod = null, $id = null ) {
321
        $options = (array) $options;
322
        $form_field_type = PodsForm::$field_type;
0 ignored issues
show
Bug introduced by
The property field_type cannot be accessed from this context as it is declared private in class PodsForm.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
323
324 View Code Duplication
        if ( !is_admin() ) {
325
            include_once( ABSPATH . '/wp-admin/includes/template.php' );
326
327
            if ( is_multisite() )
328
                include_once( ABSPATH . '/wp-admin/includes/ms.php' );
329
        }
330
331 View Code Duplication
        if ( ( ( defined( 'PODS_DISABLE_FILE_UPLOAD' ) && true === PODS_DISABLE_FILE_UPLOAD )
332
               || ( defined( 'PODS_UPLOAD_REQUIRE_LOGIN' ) && is_bool( PODS_UPLOAD_REQUIRE_LOGIN ) && true === PODS_UPLOAD_REQUIRE_LOGIN && !is_user_logged_in() )
333
               || ( defined( 'PODS_UPLOAD_REQUIRE_LOGIN' ) && !is_bool( PODS_UPLOAD_REQUIRE_LOGIN ) && ( !is_user_logged_in() || !current_user_can( PODS_UPLOAD_REQUIRE_LOGIN ) ) ) )
334
             && ( ( defined( 'PODS_DISABLE_FILE_BROWSER' ) && true === PODS_DISABLE_FILE_BROWSER )
335
                  || ( defined( 'PODS_FILES_REQUIRE_LOGIN' ) && is_bool( PODS_FILES_REQUIRE_LOGIN ) && true === PODS_FILES_REQUIRE_LOGIN && !is_user_logged_in() )
336
                  || ( defined( 'PODS_FILES_REQUIRE_LOGIN' ) && !is_bool( PODS_FILES_REQUIRE_LOGIN ) && ( !is_user_logged_in() || !current_user_can( PODS_FILES_REQUIRE_LOGIN ) ) ) )
337
        ) {
338
            ?>
339
        <p>You do not have access to upload / browse files. Contact your website admin to resolve.</p>
340
        <?php
341
            return;
342
        }
343
344
        // Use plupload if attachment isn't available
345
        if ( 'attachment' == pods_var( self::$type . '_uploader', $options ) && ( !is_user_logged_in() || ( !current_user_can( 'upload_files' ) && !current_user_can( 'edit_files' ) ) ) )
346
            $field_type = 'plupload';
347
        elseif ( 'plupload' == pods_var( self::$type . '_uploader', $options ) )
348
            $field_type = 'plupload';
349 View Code Duplication
        elseif ( 'attachment' == pods_var( self::$type . '_uploader', $options ) ) {
350
            if ( !pods_version_check( 'wp', '3.5' ) || !is_admin() ) // @todo test frontend media modal
351
                $field_type = 'attachment';
352
            else
353
                $field_type = 'media';
354
        }
355 View Code Duplication
        else {
356
            // Support custom File Uploader integration
357
            do_action( 'pods_form_ui_field_file_uploader_' . pods_var( self::$type . '_uploader', $options ), $name, $value, $options, $pod, $id );
358
            do_action( 'pods_form_ui_field_file_uploader', pods_var( self::$type . '_uploader', $options ), $name, $value, $options, $pod, $id );
359
            return;
360
        }
361
362
        pods_view( PODS_DIR . 'ui/fields/' . $field_type . '.php', compact( array_keys( get_defined_vars() ) ) );
363
    }
364
365
    /**
366
     * Build regex necessary for JS validation
367
     *
368
     * @param mixed $value
369
     * @param string $name
370
     * @param array $options
371
     * @param string $pod
372
     * @param int $id
373
     *
374
     * @return bool
375
     * @since 2.0
376
     */
377
    public function regex ( $value = null, $name = null, $options = null, $pod = null, $id = null ) {
378
        return false;
379
    }
380
381
    /**
382
     * Validate a value before it's saved
383
     *
384
     * @param mixed $value
385
     * @param string $name
386
     * @param array $options
387
     * @param array $fields
388
     * @param array $pod
389
     * @param int $id
390
     * @param null $params
391
     *
392
     * @return bool
393
     * @since 2.0
394
     */
395
    public function validate ( $value, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
396
        // check file size
397
        // check file extensions
398
        return true;
399
    }
400
401
    /**
402
     * Change the value or perform actions after validation but before saving to the DB
403
     *
404
     * @param mixed $value
405
     * @param int $id
406
     * @param string $name
407
     * @param array $options
408
     * @param array $fields
409
     * @param array $pod
410
     * @param object $params
411
     *
412
     * @return mixed
413
     * @since 2.0
414
     */
415
    public function pre_save ( $value, $id = null, $name = null, $options = null, $fields = null, $pod = null, $params = null ) {
416
        return $value;
417
    }
418
419
    /**
420
     * Save the value to the DB
421
     *
422
     * @param mixed $value
423
     * @param int $id
424
     * @param string $name
425
     * @param array $options
426
     * @param array $fields
427
     * @param array $pod
428
     * @param object $params
429
     *
430
     * @since 2.3
431
     */
432
    public function save ( $value, $id = null, $name = null, $options = null, $fields = null, $pod = null, $params = null ) {
433
        if ( empty( self::$api ) )
434
            self::$api = pods_api();
435
436
        // File title / field handling
437
        foreach ( $value as $id ) {
438
            $title = false;
439
440
            if ( is_array( $id ) ) {
441 View Code Duplication
                if ( isset( $id[ 'title' ] ) && 0 < strlen( trim( $id[ 'title' ] ) ) )
442
                    $title = trim( $id[ 'title' ] );
443
444
                if ( isset( $id[ 'id' ] ) )
445
                    $id = (int) $id[ 'id' ];
446
                else
447
                    $id = 0;
448
            }
449
450
            if ( empty( $id ) )
451
                continue;
452
453
            $attachment_data = array();
454
455
            // Update the title if set
456
            if ( false !== $title && 1 == pods_var( self::$type . '_edit_title', $options, 0 ) ) {
457
                $attachment_data['post_title'] = $title;
458
            }
459
460
            // Update attachment parent if it's not set yet and we're updating a post
461
            if ( ! empty( $params->id ) && ! empty( $pod['type'] ) && 'post_type' == $pod['type'] ) {
462
                $attachment = get_post( $id );
463
                if ( isset( $attachment->post_parent ) && 0 === (int) $attachment->post_parent ) {
464
                    $attachment_data['post_parent'] = (int) $params->id;
465
                }
466
            }
467
468
            // Update the attachment if it the data array is not still empty
469
            if ( ! empty( $attachment_data ) ) {
470
                $attachment_data['ID'] = $id;
471
                self::$api->save_wp_object( 'media', $attachment_data );
472
            }
473
        }
474
    }
475
476
    /**
477
     * Customize the Pods UI manage table column output
478
     *
479
     * @param int $id
480
     * @param mixed $value
481
     * @param string $name
482
     * @param array $options
483
     * @param array $fields
484
     * @param array $pod
485
     *
486
     * @return mixed|void
487
     * @since 2.0
488
     */
489
    public function ui ( $id, $value, $name = null, $options = null, $fields = null, $pod = null ) {
490
        if ( empty( $value ) )
491
            return;
492
493
        if ( !empty( $value ) && isset( $value[ 'ID' ] ) )
494
            $value = array( $value );
495
496
        $image_size = apply_filters( 'pods_form_ui_field_file_ui_image_size', 'thumbnail', $id, $value, $name, $options, $pod );
497
498
        return $this->images( $id, $value, $name, $options, $pod, $image_size );
499
    }
500
501
    /**
502
     * Return image(s) markup
503
     *
504
     * @param int $id
505
     * @param mixed $value
506
     * @param string $name
507
     * @param array $options
508
     * @param array $pod
509
     * @param string $image_size
510
     *
511
     * @return string
512
     * @since 2.3
513
     */
514
    public function images ( $id, $value, $name = null, $options = null, $pod = null, $image_size = null ) {
0 ignored issues
show
Unused Code introduced by
The parameter $id 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...
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...
Unused Code introduced by
The parameter $options 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...
Unused Code introduced by
The parameter $pod 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...
515
        $images = '';
516
517
        if ( empty( $value ) || !is_array( $value ) )
518
            return $images;
519
520
        foreach ( $value as $v ) {
521
            $images .= pods_image( $v, $image_size );
522
        }
523
524
        return $images;
525
    }
526
527
	/**
528
	 * Data callback for Image Sizes
529
	 *
530
	 * @param string $name The name of the field
531
	 * @param string|array $value The value of the field
532
	 * @param array $options Field options
533
	 * @param array $pod Pod data
534
	 * @param int $id Item ID
535
	 *
536
	 * @return array
537
	 *
538
	 * @since 2.3
539
	 */
540 View Code Duplication
	public function data_image_sizes ( $name = null, $value = null, $options = null, $pod = null, $id = 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...
541
		$data = array();
542
543
		$image_sizes = get_intermediate_image_sizes();
544
545
		foreach ( $image_sizes as $image_size ) {
546
			$data[ $image_size ] = ucwords( str_replace( '-', ' ', $image_size ) );
547
		}
548
549
		return apply_filters( 'pods_form_ui_field_pick_' . __FUNCTION__, $data, $name, $value, $options, $pod, $id );
550
	}
551
552
	/**
553
	 * Create a WP Gallery from the passed values (need to be attachments)
554
	 *
555
	 * @since  2.7
556
	 * @param  string|array  $value    The value(s)
557
	 * @param  array         $options  The field options
558
	 * @return string
559
	 */
560
	public function do_wp_gallery( $value, $options ) {
561
		$args = array();
562
		if ( ! empty( $options[ self::$type . '_wp_gallery_columns' ] ) ) {
563
			$args['columns'] = $options[ self::$type . '_wp_gallery_columns' ];
564
		}
565
		if ( ! empty( $options[ self::$type . '_wp_gallery_random_sort' ] ) ) {
566
			$args['orderby'] = 'rand';
567
		}
568
		if ( ! empty( $options[ self::$type . '_wp_gallery_link' ] ) ) {
569
			$args['link'] = $options[ self::$type . '_wp_gallery_link' ];
570
		}
571
		if ( ! empty( $options[ self::$type . '_wp_gallery_size' ] ) ) {
572
			$args['size'] = $options[ self::$type . '_wp_gallery_size' ];
573
		}
574
575
		if ( isset( $value[ 'ID' ] ) ) {
576
			$args['ids'] = $value[ 'ID' ];
577
		} else {
578
			$images = array();
579 View Code Duplication
			foreach ( $value as $v ) {
0 ignored issues
show
Bug introduced by
The expression $value of type string|array 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...
580
				if ( ! is_array( $v ) ) {
581
					$images[] = (int) $v;
582
				} elseif ( isset( $v[ 'ID' ] ) ) {
583
					$images[] = (int) $v[ 'ID' ];
584
				}
585
			}
586
			$args['ids'] = implode( ',', $images );
587
		}
588
589
		if ( is_callable( 'gallery_shortcode' ) ) {
590
			return gallery_shortcode( $args );
591
		} else {
592
			$shortcode = '[gallery';
593
			foreach ( $args as $key => $value ) {
594
				$shortcode .= ' ' . $key . '="' . $value . '"';
595
			}
596
			$shortcode .= ']';
597
			return do_shortcode( $shortcode );
598
		}
599
	}
600
601
    /**
602
     * Handle file row output for uploaders
603
     *
604
     * @param array $attributes
605
     * @param int $limit
606
     * @param bool $editable
607
     * @param int $id
608
     * @param string $icon
609
     * @param string $name
610
     *
611
     * @return string
612
     * @since 2.0
613
     */
614
    public function markup ( $attributes, $limit = 1, $editable = true, $id = null, $icon = null, $name = null, $linked = false, $link = null ) {
615
        // Preserve current file type
616
        $field_type = PodsForm::$field_type;
0 ignored issues
show
Bug introduced by
The property field_type cannot be accessed from this context as it is declared private in class PodsForm.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
617
618
        ob_start();
619
620
        if ( empty( $id ) )
621
            $id = '{{id}}';
622
623
        if ( empty( $icon ) ) {
624
	        $icon = '{{icon}}';
625
        }else{
626
	        $icon = esc_url( $icon );
627
        }
628
629
630
        if ( empty( $name ) )
631
            $name = '{{name}}';
632
633
        if ( empty( $link ) )
634
            $link = '{{link}}';
635
636
        $editable = (boolean) $editable;
637
        $linked = (boolean) $linked;
638
        ?>
639
    <li class="pods-file hidden" id="pods-file-<?php echo esc_attr( $id ); ?>">
640
        <?php echo PodsForm::field( $attributes[ 'name' ] . '[' . $id . '][id]', $id, 'hidden' ); ?>
641
642
        <ul class="pods-file-meta media-item">
643
            <?php if ( 1 != $limit ) { ?>
644
                <li class="pods-file-col pods-file-handle">Handle</li>
645
            <?php } ?>
646
647
            <li class="pods-file-col pods-file-icon">
648
                <img class="pinkynail" src="<?php echo $icon; ?>" alt="Icon" />
649
            </li>
650
651
            <li class="pods-file-col pods-file-name">
652
                <?php
653
                if ( $editable )
654
                    echo PodsForm::field( $attributes[ 'name' ] . '[' . $id . '][title]', $name, 'text' );
655
                else
656
                    echo ( empty( $name ) ? '{{name}}' : $name );
657
                ?>
658
            </li>
659
660
            <li class="pods-file-col pods-file-delete"><a href="#delete">Delete</a></li>
661
662
			<?php
663
				if ( $linked ) {
664
			?>
665
            	<li class="pods-file-col pods-file-download"><a href="<?php echo esc_url( $link ); ?>" target="_blank">Download</a></li>
666
			<?php
667
				}
668
			?>
669
        </ul>
670
    </li>
671
    <?php
672
        PodsForm::$field_type = $field_type;
0 ignored issues
show
Bug introduced by
The property field_type cannot be accessed from this context as it is declared private in class PodsForm.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
673
674
        return ob_get_clean();
675
    }
676
677
    /**
678
     * Handle plupload AJAX
679
     *
680
     * @since 2.3
681
     */
682
    public function admin_ajax_upload () {
683
		pods_session_start();
684
685
        // Sanitize input
686
        $params = pods_unslash( (array) $_POST );
687
688 View Code Duplication
        foreach ( $params as $key => $value ) {
689
            if ( 'action' == $key )
690
                continue;
691
692
            unset( $params[ $key ] );
693
694
            $params[ str_replace( '_podsfix_', '', $key ) ] = $value;
695
        }
696
697
        $params = (object) $params;
698
699
        $methods = array(
700
            'upload',
701
        );
702
703
        if ( !isset( $params->method ) || !in_array( $params->method, $methods ) || !isset( $params->pod ) || !isset( $params->field ) || !isset( $params->uri ) || empty( $params->uri ) )
704
            pods_error( 'Invalid AJAX request', PodsInit::$admin );
0 ignored issues
show
Bug introduced by
The property admin cannot be accessed from this context as it is declared private in class PodsInit.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
705
        elseif ( !empty( $params->pod ) && empty( $params->field ) )
706
            pods_error( 'Invalid AJAX request', PodsInit::$admin );
0 ignored issues
show
Bug introduced by
The property admin cannot be accessed from this context as it is declared private in class PodsInit.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
707
        elseif ( empty( $params->pod ) && !current_user_can( 'upload_files' ) )
708
            pods_error( 'Invalid AJAX request', PodsInit::$admin );
0 ignored issues
show
Bug introduced by
The property admin cannot be accessed from this context as it is declared private in class PodsInit.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
709
710
        // Flash often fails to send cookies with the POST or upload, so we need to pass it in GET or POST instead
711
        if ( is_ssl() && empty( $_COOKIE[ SECURE_AUTH_COOKIE ] ) && !empty( $_REQUEST[ 'auth_cookie' ] ) )
712
            $_COOKIE[ SECURE_AUTH_COOKIE ] = $_REQUEST[ 'auth_cookie' ];
713
        elseif ( empty( $_COOKIE[ AUTH_COOKIE ] ) && !empty( $_REQUEST[ 'auth_cookie' ] ) )
714
            $_COOKIE[ AUTH_COOKIE ] = $_REQUEST[ 'auth_cookie' ];
715
716
        if ( empty( $_COOKIE[ LOGGED_IN_COOKIE ] ) && !empty( $_REQUEST[ 'logged_in_cookie' ] ) )
717
            $_COOKIE[ LOGGED_IN_COOKIE ] = $_REQUEST[ 'logged_in_cookie' ];
718
719
        global $current_user;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
720
        unset( $current_user );
721
722
        /**
723
         * Access Checking
724
         */
725
        $upload_disabled = false;
726
727
        if ( defined( 'PODS_DISABLE_FILE_UPLOAD' ) && true === PODS_DISABLE_FILE_UPLOAD )
728
            $upload_disabled = true;
729 View Code Duplication
        elseif ( defined( 'PODS_UPLOAD_REQUIRE_LOGIN' ) && is_bool( PODS_UPLOAD_REQUIRE_LOGIN ) && true === PODS_UPLOAD_REQUIRE_LOGIN && !is_user_logged_in() )
730
            $upload_disabled = true;
731 View Code Duplication
        elseif ( defined( 'PODS_UPLOAD_REQUIRE_LOGIN' ) && !is_bool( PODS_UPLOAD_REQUIRE_LOGIN ) && ( !is_user_logged_in() || !current_user_can( PODS_UPLOAD_REQUIRE_LOGIN ) ) )
732
            $upload_disabled = true;
733
734
        $uid = @session_id();
735
736
        if ( is_user_logged_in() )
737
            $uid = 'user_' . get_current_user_id();
738
739
        $nonce_check = 'pods_upload_' . (int) $params->pod . '_' . $uid . '_' . $params->uri . '_' . (int) $params->field;
740
741 View Code Duplication
        if ( true === $upload_disabled || !isset( $params->_wpnonce ) || false === wp_verify_nonce( $params->_wpnonce, $nonce_check ) )
742
            pods_error( __( 'Unauthorized request', 'pods' ), PodsInit::$admin );
0 ignored issues
show
Bug introduced by
The property admin cannot be accessed from this context as it is declared private in class PodsInit.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
743
744
        $pod = array();
745
        $field = array(
746
            'type' => 'file',
747
            'options' => array()
748
        );
749
750
        $api = pods_api();
751
752
	    $api->display_errors = false;
753
754
        if ( !empty( $params->pod ) ) {
755
            $pod = $api->load_pod( array( 'id' => (int) $params->pod ) );
756
            $field = $api->load_field( array( 'id' => (int) $params->field ) );
757
758 View Code Duplication
            if ( empty( $pod ) || empty( $field ) || $pod[ 'id' ] != $field[ 'pod_id' ] || !isset( $pod[ 'fields' ][ $field[ 'name' ] ] ) )
759
                pods_error( __( 'Invalid field request', 'pods' ), PodsInit::$admin );
0 ignored issues
show
Bug introduced by
The property admin cannot be accessed from this context as it is declared private in class PodsInit.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
760
761
            if ( !in_array( $field[ 'type' ], PodsForm::file_field_types() ) )
762
                pods_error( __( 'Invalid field', 'pods' ), PodsInit::$admin );
0 ignored issues
show
Bug introduced by
The property admin cannot be accessed from this context as it is declared private in class PodsInit.

This check looks for access to properties that are not accessible from the current context.

If you need to make a property accessible to another context you can either raise its visibility level or provide an accessible getter in the defining class.

Loading history...
763
        }
764
765
        $method = $params->method;
766
767
        // Cleaning up $params
768
        unset( $params->action );
769
        unset( $params->method );
770
        unset( $params->_wpnonce );
771
772
        $params->post_id = pods_var( 'post_id', $params, 0, null, true );
773
774
        /**
775
         * Upload a new file (advanced - returns URL and ID)
776
         */
777
        if ( 'upload' == $method ) {
778
            $file = $_FILES[ 'Filedata' ];
779
780
            $limit_size = pods_var( $field[ 'type' ] . '_restrict_filesize', $field[ 'options' ] );
781
782
            if ( !empty( $limit_size ) ) {
783
                if ( false !== stripos( $limit_size, 'MB' ) ) {
784
                    $limit_size = (float) trim( str_ireplace( 'MB', '', $limit_size ) );
785
                    $limit_size = $limit_size * 1025 * 1025; // convert to KB to B
786
                }
787 View Code Duplication
                elseif ( false !== stripos( $limit_size, 'KB' ) ) {
788
                    $limit_size = (float) trim( str_ireplace( 'KB', '', $limit_size ) );
789
                    $limit_size = $limit_size * 1025 * 1025; // convert to B
790
                }
791 View Code Duplication
                elseif ( false !== stripos( $limit_size, 'GB' ) ) {
792
                    $limit_size = (float) trim( str_ireplace( 'GB', '', $limit_size ) );
793
                    $limit_size = $limit_size * 1025 * 1025 * 1025; // convert to MB to KB to B
794
                }
795
                elseif ( false !== stripos( $limit_size, 'B' ) )
796
                    $limit_size = (float) trim( str_ireplace( 'B', '', $limit_size ) );
797
                else
798
                    $limit_size = wp_max_upload_size();
799
800
                if ( 0 < $limit_size && $limit_size < $file[ 'size' ] ) {
801
                    $error = __( 'File size too large, max size is %s', 'pods' );
802
                    $error = sprintf( $error, pods_var( $field[ 'type' ] . '_restrict_filesize', $field[ 'options' ] ) );
803
804
                    pods_error( '<div style="color:#FF0000">Error: ' . $error . '</div>' );
805
                }
806
            }
807
808
            $limit_file_type = pods_var( $field[ 'type' ] . '_type', $field[ 'options' ], 'images' );
809
810
            if ( 'images' == $limit_file_type )
811
                $limit_types = 'jpg,jpeg,png,gif';
812
            elseif ( 'video' == $limit_file_type )
813
                $limit_types = 'mpg,mov,flv,mp4';
814
            elseif ( 'audio' == $limit_file_type )
815
                $limit_types = 'mp3,m4a,wav,wma';
816
            elseif ( 'text' == $limit_file_type )
817
                $limit_types = 'txt,rtx,csv,tsv';
818
            elseif ( 'any' == $limit_file_type )
819
                $limit_types = '';
820
            else
821
                $limit_types = pods_var( $field[ 'type' ] . '_allowed_extensions', $field[ 'options' ], '', null, true );
822
823
            $limit_types = trim( str_replace( array( ' ', '.', "\n", "\t", ';' ), array( '', ',', ',', ',' ), $limit_types ), ',' );
824
825 View Code Duplication
            if ( pods_version_check( 'wp', '3.5' ) ) {
826
                $mime_types = wp_get_mime_types();
827
828
                if ( in_array( $limit_file_type, array( 'images', 'audio', 'video' ) ) ) {
829
                    $new_limit_types = array();
830
831
                    foreach ( $mime_types as $type => $mime ) {
832
                        if ( 0 === strpos( $mime, $limit_file_type ) ) {
833
                            $type = explode( '|', $type );
834
835
                            $new_limit_types = array_merge( $new_limit_types, $type );
836
                        }
837
                    }
838
839
                    if ( !empty( $new_limit_types ) )
840
                        $limit_types = implode( ',', $new_limit_types );
841
                }
842
                elseif ( 'any' != $limit_file_type ) {
843
                    $new_limit_types = array();
844
845
                    $limit_types = explode( ',', $limit_types );
846
847
                    foreach ( $limit_types as $k => $limit_type ) {
848
                        $found = false;
849
850
                        foreach ( $mime_types as $type => $mime ) {
851
                            if ( 0 === strpos( $mime, $limit_type ) ) {
852
                                $type = explode( '|', $type );
853
854
                                foreach ( $type as $t ) {
855
                                    if ( !in_array( $t, $new_limit_types ) )
856
                                        $new_limit_types[] = $t;
857
                                }
858
859
                                $found = true;
860
                            }
861
                        }
862
863
                        if ( !$found )
864
                            $new_limit_types[] = $limit_type;
865
                    }
866
867
                    if ( !empty( $new_limit_types ) )
868
                        $limit_types = implode( ',', $new_limit_types );
869
                }
870
            }
871
872
            $limit_types = explode( ',', $limit_types );
873
874
            $limit_types = array_filter( array_unique( $limit_types ) );
875
876
            if ( !empty( $limit_types ) ) {
877
                $ok = false;
878
879
                foreach ( $limit_types as $limit_type ) {
880
                    $limit_type = '.' . trim( $limit_type, ' .' );
881
882
                    $pos = ( strlen( $file[ 'name' ] ) - strlen( $limit_type ) );
883
884
                    if ( $pos === stripos( $file[ 'name' ], $limit_type ) ) {
885
                        $ok = true;
886
887
                        break;
888
                    }
889
                }
890
891
                if ( false === $ok ) {
892
                    $error = __( 'File type not allowed, please use one of the following: %s', 'pods' );
893
                    $error = sprintf( $error, '.' . implode( ', .', $limit_types ) );
894
895
                    pods_error( '<div style="color:#FF0000">Error: ' . $error . '</div>' );
896
                }
897
            }
898
899
            $custom_handler = apply_filters( 'pods_upload_handle', null, 'Filedata', $params->post_id, $params, $field );
900
901
            if ( null === $custom_handler ) {
902
				$linked = pods_var( $field[ 'type' ] . '_linked', $field[ 'options' ], 0 );
903
904
                $attachment_id = media_handle_upload( 'Filedata', $params->post_id );
905
906
                if ( is_object( $attachment_id ) ) {
907
                    $errors = array();
908
909
                    foreach ( $attachment_id->errors[ 'upload_error' ] as $error_code => $error_message ) {
910
                        $errors[] = '[' . $error_code . '] ' . $error_message;
911
                    }
912
913
                    pods_error( '<div style="color:#FF0000">Error: ' . implode( '</div><div>', $errors ) . '</div>' );
914
                }
915
                else {
916
                    $attachment = get_post( $attachment_id, ARRAY_A );
917
918
                    $attachment[ 'filename' ] = basename( $attachment[ 'guid' ] );
919
920
                    $thumb = wp_get_attachment_image_src( $attachment[ 'ID' ], 'thumbnail', true );
921
                    $attachment[ 'thumbnail' ] = $thumb[ 0 ];
922
923
					$attachment[ 'link' ] = '';
924
925
					if ( $linked ) {
926
                    	$attachment[ 'link' ] = wp_get_attachment_url( $attachment[ 'ID' ] );
927
					}
928
929
                    $attachment = apply_filters( 'pods_upload_attachment', $attachment, $params->post_id );
930
931
                    wp_send_json( $attachment );
932
                }
933
            }
934
        }
935
936
        die(); // KBAI!
0 ignored issues
show
Coding Style Compatibility introduced by
The method admin_ajax_upload() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
937
    }
938
}
939