Completed
Pull Request — 2.x (#3910)
by Scott Kingsley
04:40
created

PodsField_File::pre_save()   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 7
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
201
            /* WP GALLERY OUTPUT */
202
            self::$type . '_wp_gallery_output' => array(
203
	            'label' => __( 'Output as a WP Gallery', 'pods' ),
204
	            'help' => sprintf(
205
	            	__( '<a href="%s" target="_blank">Click here for more info</a>', 'pods' ),
206
					'https://codex.wordpress.org/The_WordPress_Gallery'
207
				),
208
	            'depends-on' => array( self::$type . '_type' => 'images' ),
209
	            'dependency' => true,
210
	            'type' => 'boolean'
211
            ),
212
            self::$type . '_wp_gallery_link' => array(
213
	            'label' => __( 'WP Gallery link', 'pods' ),
214
	            'depends-on' => array( self::$type . '_wp_gallery_output' => 1 ),
215
	            'type' => 'pick',
216
	            'data' => array(
217
		            'post' => __( 'Attachment Page', 'pods' ),
218
		            'file' => __( 'Media File', 'pods' ),
219
		            'none' => __( 'None', 'pods' )
220
	            )
221
            ),
222
            self::$type . '_wp_gallery_columns' => array(
223
	            'label' => __( 'WP Gallery columns', 'pods' ),
224
	            'depends-on' => array( self::$type . '_wp_gallery_output' => 1 ),
225
	            'type' => 'pick',
226
	            'data' => array(
227
		            '1' => 1, '2' => 2, '3' => 3, '4' => 4, '5' => 5, '6' => 6, '7' => 7, '8' => 8, '9' => 9,
228
	            )
229
            ),
230
            self::$type . '_wp_gallery_random_sort' => array(
231
	            'label' => __( 'WP Gallery random order?', 'pods' ),
232
	            'depends-on' => array( self::$type . '_wp_gallery_output' => 1 ),
233
	            'type' => 'boolean'
234
            ),
235
            self::$type . '_wp_gallery_size' => array(
236
	            'label' => __( 'WP Gallery image size', 'pods' ),
237
	            'depends-on' => array( self::$type . '_wp_gallery_output' => 1 ),
238
	            'type' => 'pick',
239
	            'data' => $this->data_image_sizes()
240
            )
241
        );
242
243 View Code Duplication
        if ( !pods_version_check( 'wp', '3.5' ) ) {
244
            unset( $options[ self::$type . '_linked' ] );
245
            unset( $options[ self::$type . '_modal_title' ] );
246
            unset( $options[ self::$type . '_modal_add_button' ] );
247
248
            $options[ self::$type . '_attachment_tab' ][ 'default' ] = 'type';
249
            $options[ self::$type . '_attachment_tab' ][ 'data' ] = array(
250
                'type' => __( 'Upload File', 'pods' ),
251
                'library' => __( 'Media Library', 'pods' )
252
            );
253
        }
254
255
        return $options;
256
    }
257
258
    /**
259
     * Define the current field's schema for DB table storage
260
     *
261
     * @param array $options
262
     *
263
     * @return array
264
     * @since 2.0
265
     */
266
    public function schema ( $options = null ) {
267
        $schema = false;
268
269
        return $schema;
270
    }
271
272
    /**
273
     * Change the way the value of the field is displayed with Pods::get
274
     *
275
     * @param mixed $value
276
     * @param string $name
277
     * @param array $options
278
     * @param array $pod
279
     * @param int $id
280
     *
281
     * @return mixed|null
282
     * @since 2.0
283
     */
284
    public function display ( $value = null, $name = null, $options = null, $pod = null, $id = null ) {
285
    	if ( 1 == $options[ self::$type . '_wp_gallery_output' ] ) {
286
    		return $this->do_wp_gallery( $value, $options );
287
		}
288
289
        if ( is_array( $value ) && !empty( $value ) ) {
290
            if ( isset( $value[ 'ID' ] ) )
291
                $value = wp_get_attachment_url( $value[ 'ID' ] );
292
            else {
293
                $attachments = $value;
294
                $value = array();
295
296 View Code Duplication
                foreach ( $attachments as $v ) {
297
                    if ( !is_array( $v ) )
298
                        $value[] = $v;
299
                    elseif ( isset( $v[ 'ID' ] ) )
300
                        $value[] = wp_get_attachment_url( $v[ 'ID' ] );
301
                }
302
303
                $value = implode( ' ', $value );
304
            }
305
        }
306
307
        return $value;
308
    }
309
310
    /**
311
     * Customize output of the form field
312
     *
313
     * @param string $name
314
     * @param mixed $value
315
     * @param array $options
316
     * @param array $pod
317
     * @param int $id
318
     *
319
     * @since 2.0
320
     */
321
    public function input ( $name, $value = null, $options = null, $pod = null, $id = null ) {
322
        $options = (array) $options;
323
        $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...
324
325 View Code Duplication
        if ( !is_admin() ) {
326
            include_once( ABSPATH . '/wp-admin/includes/template.php' );
327
328
            if ( is_multisite() )
329
                include_once( ABSPATH . '/wp-admin/includes/ms.php' );
330
        }
331
332 View Code Duplication
        if ( ( ( defined( 'PODS_DISABLE_FILE_UPLOAD' ) && true === PODS_DISABLE_FILE_UPLOAD )
333
               || ( defined( 'PODS_UPLOAD_REQUIRE_LOGIN' ) && is_bool( PODS_UPLOAD_REQUIRE_LOGIN ) && true === PODS_UPLOAD_REQUIRE_LOGIN && !is_user_logged_in() )
334
               || ( defined( 'PODS_UPLOAD_REQUIRE_LOGIN' ) && !is_bool( PODS_UPLOAD_REQUIRE_LOGIN ) && ( !is_user_logged_in() || !current_user_can( PODS_UPLOAD_REQUIRE_LOGIN ) ) ) )
335
             && ( ( defined( 'PODS_DISABLE_FILE_BROWSER' ) && true === PODS_DISABLE_FILE_BROWSER )
336
                  || ( defined( 'PODS_FILES_REQUIRE_LOGIN' ) && is_bool( PODS_FILES_REQUIRE_LOGIN ) && true === PODS_FILES_REQUIRE_LOGIN && !is_user_logged_in() )
337
                  || ( defined( 'PODS_FILES_REQUIRE_LOGIN' ) && !is_bool( PODS_FILES_REQUIRE_LOGIN ) && ( !is_user_logged_in() || !current_user_can( PODS_FILES_REQUIRE_LOGIN ) ) ) )
338
        ) {
339
            ?>
340
        <p>You do not have access to upload / browse files. Contact your website admin to resolve.</p>
341
        <?php
342
            return;
343
        }
344
345
        // Use plupload if attachment isn't available
346
        if ( 'attachment' == pods_var( self::$type . '_uploader', $options ) && ( !is_user_logged_in() || ( !current_user_can( 'upload_files' ) && !current_user_can( 'edit_files' ) ) ) )
347
            $field_type = 'plupload';
348
        elseif ( 'plupload' == pods_var( self::$type . '_uploader', $options ) )
349
            $field_type = 'plupload';
350 View Code Duplication
        elseif ( 'attachment' == pods_var( self::$type . '_uploader', $options ) ) {
351
            if ( !pods_version_check( 'wp', '3.5' ) || !is_admin() ) // @todo test frontend media modal
352
                $field_type = 'attachment';
353
            else
354
                $field_type = 'media';
355
        }
356 View Code Duplication
        else {
357
            // Support custom File Uploader integration
358
            do_action( 'pods_form_ui_field_file_uploader_' . pods_var( self::$type . '_uploader', $options ), $name, $value, $options, $pod, $id );
359
            do_action( 'pods_form_ui_field_file_uploader', pods_var( self::$type . '_uploader', $options ), $name, $value, $options, $pod, $id );
360
            return;
361
        }
362
363
        pods_view( PODS_DIR . 'ui/fields/' . $field_type . '.php', compact( array_keys( get_defined_vars() ) ) );
364
    }
365
366
    /**
367
     * Build regex necessary for JS validation
368
     *
369
     * @param mixed $value
370
     * @param string $name
371
     * @param array $options
372
     * @param string $pod
373
     * @param int $id
374
     *
375
     * @return bool
376
     * @since 2.0
377
     */
378
    public function regex ( $value = null, $name = null, $options = null, $pod = null, $id = null ) {
379
        return false;
380
    }
381
382
    /**
383
     * Validate a value before it's saved
384
     *
385
     * @param mixed $value
386
     * @param string $name
387
     * @param array $options
388
     * @param array $fields
389
     * @param array $pod
390
     * @param int $id
391
     * @param null $params
392
     *
393
     * @return bool
394
     * @since 2.0
395
     */
396
    public function validate ( $value, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
397
        // check file size
398
        // check file extensions
399
        return true;
400
    }
401
402
    /**
403
     * Change the value or perform actions after validation but before saving to the DB
404
     *
405
     * @param mixed $value
406
     * @param int $id
407
     * @param string $name
408
     * @param array $options
409
     * @param array $fields
410
     * @param array $pod
411
     * @param object $params
412
     *
413
     * @return mixed
414
     * @since 2.0
415
     */
416
    public function pre_save ( $value, $id = null, $name = null, $options = null, $fields = null, $pod = null, $params = null ) {
417
        return $value;
418
    }
419
420
    /**
421
     * Save the value to the DB
422
     *
423
     * @param mixed $value
424
     * @param int $id
425
     * @param string $name
426
     * @param array $options
427
     * @param array $fields
428
     * @param array $pod
429
     * @param object $params
430
     *
431
     * @since 2.3
432
     */
433
    public function save ( $value, $id = null, $name = null, $options = null, $fields = null, $pod = null, $params = null ) {
434
        if ( empty( self::$api ) )
435
            self::$api = pods_api();
436
437
        // File title / field handling
438
        foreach ( $value as $id ) {
439
            $title = false;
440
441
            if ( is_array( $id ) ) {
442 View Code Duplication
                if ( isset( $id[ 'title' ] ) && 0 < strlen( trim( $id[ 'title' ] ) ) )
443
                    $title = trim( $id[ 'title' ] );
444
445
                if ( isset( $id[ 'id' ] ) )
446
                    $id = (int) $id[ 'id' ];
447
                else
448
                    $id = 0;
449
            }
450
451
            if ( empty( $id ) )
452
                continue;
453
454
            $attachment_data = array();
455
456
            // Update the title if set
457
            if ( false !== $title && 1 == pods_var( self::$type . '_edit_title', $options, 0 ) ) {
458
                $attachment_data['post_title'] = $title;
459
            }
460
461
            // Update attachment parent if it's not set yet and we're updating a post
462
            if ( ! empty( $params->id ) && ! empty( $pod['type'] ) && 'post_type' == $pod['type'] ) {
463
                $attachment = get_post( $id );
464
                if ( isset( $attachment->post_parent ) && 0 === (int) $attachment->post_parent ) {
465
                    $attachment_data['post_parent'] = (int) $params->id;
466
                }
467
            }
468
469
            // Update the attachment if it the data array is not still empty
470
            if ( ! empty( $attachment_data ) ) {
471
                $attachment_data['ID'] = $id;
472
                self::$api->save_wp_object( 'media', $attachment_data );
473
            }
474
        }
475
    }
476
477
    /**
478
     * Customize the Pods UI manage table column output
479
     *
480
     * @param int $id
481
     * @param mixed $value
482
     * @param string $name
483
     * @param array $options
484
     * @param array $fields
485
     * @param array $pod
486
     *
487
     * @return mixed|void
488
     * @since 2.0
489
     */
490
    public function ui ( $id, $value, $name = null, $options = null, $fields = null, $pod = null ) {
491
        if ( empty( $value ) )
492
            return;
493
494
        if ( !empty( $value ) && isset( $value[ 'ID' ] ) )
495
            $value = array( $value );
496
497
        $image_size = apply_filters( 'pods_form_ui_field_file_ui_image_size', 'thumbnail', $id, $value, $name, $options, $pod );
498
499
        return $this->images( $id, $value, $name, $options, $pod, $image_size );
500
    }
501
502
    /**
503
     * Return image(s) markup
504
     *
505
     * @param int $id
506
     * @param mixed $value
507
     * @param string $name
508
     * @param array $options
509
     * @param array $pod
510
     * @param string $image_size
511
     *
512
     * @return string
513
     * @since 2.3
514
     */
515
    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...
516
        $images = '';
517
518
        if ( empty( $value ) || !is_array( $value ) )
519
            return $images;
520
521
        foreach ( $value as $v ) {
522
            $images .= pods_image( $v, $image_size );
523
        }
524
525
        return $images;
526
    }
527
528
	/**
529
	 * Data callback for Image Sizes
530
	 *
531
	 * @param string $name The name of the field
532
	 * @param string|array $value The value of the field
533
	 * @param array $options Field options
534
	 * @param array $pod Pod data
535
	 * @param int $id Item ID
536
	 *
537
	 * @return array
538
	 *
539
	 * @since 2.3
540
	 */
541 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...
542
		$data = array();
543
544
		$image_sizes = get_intermediate_image_sizes();
545
546
		foreach ( $image_sizes as $image_size ) {
547
			$data[ $image_size ] = ucwords( str_replace( '-', ' ', $image_size ) );
548
		}
549
550
		return apply_filters( 'pods_form_ui_field_pick_' . __FUNCTION__, $data, $name, $value, $options, $pod, $id );
551
	}
552
553
	/**
554
	 * Create a WP Gallery from the passed values (need to be attachments)
555
	 *
556
	 * @since  2.7
557
	 * @param  string|array  $value    The value(s)
558
	 * @param  array         $options  The field options
559
	 * @return string
560
	 */
561
	public function do_wp_gallery( $value, $options ) {
562
		$args = array();
563
		if ( ! empty( $options[ self::$type . '_wp_gallery_columns' ] ) ) {
564
			$args['columns'] = $options[ self::$type . '_wp_gallery_columns' ];
565
		}
566
		if ( ! empty( $options[ self::$type . '_wp_gallery_random_sort' ] ) ) {
567
			$args['orderby'] = 'rand';
568
		}
569
		if ( ! empty( $options[ self::$type . '_wp_gallery_link' ] ) ) {
570
			$args['link'] = $options[ self::$type . '_wp_gallery_link' ];
571
		}
572
		if ( ! empty( $options[ self::$type . '_wp_gallery_size' ] ) ) {
573
			$args['size'] = $options[ self::$type . '_wp_gallery_size' ];
574
		}
575
576
		if ( isset( $value[ 'ID' ] ) ) {
577
			$args['ids'] = $value[ 'ID' ];
578
		} else {
579
			$images = array();
580 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...
581
				if ( ! is_array( $v ) ) {
582
					$images[] = (int) $v;
583
				} elseif ( isset( $v[ 'ID' ] ) ) {
584
					$images[] = (int) $v[ 'ID' ];
585
				}
586
			}
587
			$args['ids'] = implode( ',', $images );
588
		}
589
590
		if ( is_callable( 'gallery_shortcode' ) ) {
591
			return gallery_shortcode( $args );
592
		} else {
593
			$shortcode = '[gallery';
594
			foreach ( $args as $key => $value ) {
595
				$shortcode .= ' ' . $key . '="' . $value . '"';
596
			}
597
			$shortcode .= ']';
598
			return do_shortcode( $shortcode );
599
		}
600
	}
601
602
    /**
603
     * Handle file row output for uploaders
604
     *
605
     * @param array $attributes
606
     * @param int $limit
607
     * @param bool $editable
608
     * @param int $id
609
     * @param string $icon
610
     * @param string $name
611
     *
612
     * @return string
613
     * @since 2.0
614
     */
615
    public function markup ( $attributes, $limit = 1, $editable = true, $id = null, $icon = null, $name = null, $linked = false, $link = null ) {
616
        // Preserve current file type
617
        $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...
618
619
        ob_start();
620
621
        if ( empty( $id ) )
622
            $id = '{{id}}';
623
624
        if ( empty( $icon ) ) {
625
	        $icon = '{{icon}}';
626
        }else{
627
	        $icon = esc_url( $icon );
628
        }
629
630
631
        if ( empty( $name ) )
632
            $name = '{{name}}';
633
634
        if ( empty( $link ) )
635
            $link = '{{link}}';
636
637
        $editable = (boolean) $editable;
638
        $linked = (boolean) $linked;
639
        ?>
640
    <li class="pods-file hidden" id="pods-file-<?php echo esc_attr( $id ); ?>">
641
        <?php echo PodsForm::field( $attributes[ 'name' ] . '[' . $id . '][id]', $id, 'hidden' ); ?>
642
643
        <ul class="pods-file-meta media-item">
644
            <?php if ( 1 != $limit ) { ?>
645
                <li class="pods-file-col pods-file-handle">Handle</li>
646
            <?php } ?>
647
648
            <li class="pods-file-col pods-file-icon">
649
                <img class="pinkynail" src="<?php echo $icon; ?>" alt="Icon" />
650
            </li>
651
652
            <li class="pods-file-col pods-file-name">
653
                <?php
654
                if ( $editable )
655
                    echo PodsForm::field( $attributes[ 'name' ] . '[' . $id . '][title]', $name, 'text' );
656
                else
657
                    echo ( empty( $name ) ? '{{name}}' : $name );
658
                ?>
659
            </li>
660
661
            <li class="pods-file-col pods-file-delete"><a href="#delete">Delete</a></li>
662
663
			<?php
664
				if ( $linked ) {
665
			?>
666
            	<li class="pods-file-col pods-file-download"><a href="<?php echo esc_url( $link ); ?>" target="_blank">Download</a></li>
667
			<?php
668
				}
669
			?>
670
        </ul>
671
    </li>
672
    <?php
673
        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...
674
675
        return ob_get_clean();
676
    }
677
678
    /**
679
     * Handle plupload AJAX
680
     *
681
     * @since 2.3
682
     */
683
    public function admin_ajax_upload () {
684
		pods_session_start();
685
686
        // Sanitize input
687
        $params = pods_unslash( (array) $_POST );
688
689 View Code Duplication
        foreach ( $params as $key => $value ) {
690
            if ( 'action' == $key )
691
                continue;
692
693
            unset( $params[ $key ] );
694
695
            $params[ str_replace( '_podsfix_', '', $key ) ] = $value;
696
        }
697
698
        $params = (object) $params;
699
700
        $methods = array(
701
            'upload',
702
        );
703
704
        if ( !isset( $params->method ) || !in_array( $params->method, $methods ) || !isset( $params->pod ) || !isset( $params->field ) || !isset( $params->uri ) || empty( $params->uri ) )
705
            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...
706
        elseif ( !empty( $params->pod ) && empty( $params->field ) )
707
            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...
708
        elseif ( empty( $params->pod ) && !current_user_can( 'upload_files' ) )
709
            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...
710
711
        // Flash often fails to send cookies with the POST or upload, so we need to pass it in GET or POST instead
712
        if ( is_ssl() && empty( $_COOKIE[ SECURE_AUTH_COOKIE ] ) && !empty( $_REQUEST[ 'auth_cookie' ] ) )
713
            $_COOKIE[ SECURE_AUTH_COOKIE ] = $_REQUEST[ 'auth_cookie' ];
714
        elseif ( empty( $_COOKIE[ AUTH_COOKIE ] ) && !empty( $_REQUEST[ 'auth_cookie' ] ) )
715
            $_COOKIE[ AUTH_COOKIE ] = $_REQUEST[ 'auth_cookie' ];
716
717
        if ( empty( $_COOKIE[ LOGGED_IN_COOKIE ] ) && !empty( $_REQUEST[ 'logged_in_cookie' ] ) )
718
            $_COOKIE[ LOGGED_IN_COOKIE ] = $_REQUEST[ 'logged_in_cookie' ];
719
720
        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...
721
        unset( $current_user );
722
723
        /**
724
         * Access Checking
725
         */
726
        $upload_disabled = false;
727
728
        if ( defined( 'PODS_DISABLE_FILE_UPLOAD' ) && true === PODS_DISABLE_FILE_UPLOAD )
729
            $upload_disabled = true;
730 View Code Duplication
        elseif ( defined( 'PODS_UPLOAD_REQUIRE_LOGIN' ) && is_bool( PODS_UPLOAD_REQUIRE_LOGIN ) && true === PODS_UPLOAD_REQUIRE_LOGIN && !is_user_logged_in() )
731
            $upload_disabled = true;
732 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 ) ) )
733
            $upload_disabled = true;
734
735
        $uid = @session_id();
736
737
        if ( is_user_logged_in() )
738
            $uid = 'user_' . get_current_user_id();
739
740
        $nonce_check = 'pods_upload_' . (int) $params->pod . '_' . $uid . '_' . $params->uri . '_' . (int) $params->field;
741
742 View Code Duplication
        if ( true === $upload_disabled || !isset( $params->_wpnonce ) || false === wp_verify_nonce( $params->_wpnonce, $nonce_check ) )
743
            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...
744
745
        $pod = array();
746
        $field = array(
747
            'type' => 'file',
748
            'options' => array()
749
        );
750
751
        $api = pods_api();
752
753
	    $api->display_errors = false;
754
755
        if ( !empty( $params->pod ) ) {
756
            $pod = $api->load_pod( array( 'id' => (int) $params->pod ) );
757
            $field = $api->load_field( array( 'id' => (int) $params->field ) );
758
759 View Code Duplication
            if ( empty( $pod ) || empty( $field ) || $pod[ 'id' ] != $field[ 'pod_id' ] || !isset( $pod[ 'fields' ][ $field[ 'name' ] ] ) )
760
                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...
761
762
            if ( !in_array( $field[ 'type' ], PodsForm::file_field_types() ) )
763
                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...
764
        }
765
766
        $method = $params->method;
767
768
        // Cleaning up $params
769
        unset( $params->action );
770
        unset( $params->method );
771
        unset( $params->_wpnonce );
772
773
        $params->post_id = pods_var( 'post_id', $params, 0, null, true );
774
775
        /**
776
         * Upload a new file (advanced - returns URL and ID)
777
         */
778
        if ( 'upload' == $method ) {
779
            $file = $_FILES[ 'Filedata' ];
780
781
            $limit_size = pods_var( $field[ 'type' ] . '_restrict_filesize', $field[ 'options' ] );
782
783
            if ( !empty( $limit_size ) ) {
784
                if ( false !== stripos( $limit_size, 'MB' ) ) {
785
                    $limit_size = (float) trim( str_ireplace( 'MB', '', $limit_size ) );
786
                    $limit_size = $limit_size * 1025 * 1025; // convert to KB to B
787
                }
788 View Code Duplication
                elseif ( false !== stripos( $limit_size, 'KB' ) ) {
789
                    $limit_size = (float) trim( str_ireplace( 'KB', '', $limit_size ) );
790
                    $limit_size = $limit_size * 1025 * 1025; // convert to B
791
                }
792 View Code Duplication
                elseif ( false !== stripos( $limit_size, 'GB' ) ) {
793
                    $limit_size = (float) trim( str_ireplace( 'GB', '', $limit_size ) );
794
                    $limit_size = $limit_size * 1025 * 1025 * 1025; // convert to MB to KB to B
795
                }
796
                elseif ( false !== stripos( $limit_size, 'B' ) )
797
                    $limit_size = (float) trim( str_ireplace( 'B', '', $limit_size ) );
798
                else
799
                    $limit_size = wp_max_upload_size();
800
801
                if ( 0 < $limit_size && $limit_size < $file[ 'size' ] ) {
802
                    $error = __( 'File size too large, max size is %s', 'pods' );
803
                    $error = sprintf( $error, pods_var( $field[ 'type' ] . '_restrict_filesize', $field[ 'options' ] ) );
804
805
                    pods_error( '<div style="color:#FF0000">Error: ' . $error . '</div>' );
806
                }
807
            }
808
809
            $limit_file_type = pods_var( $field[ 'type' ] . '_type', $field[ 'options' ], 'images' );
810
811
            if ( 'images' == $limit_file_type )
812
                $limit_types = 'jpg,jpeg,png,gif';
813
            elseif ( 'video' == $limit_file_type )
814
                $limit_types = 'mpg,mov,flv,mp4';
815
            elseif ( 'audio' == $limit_file_type )
816
                $limit_types = 'mp3,m4a,wav,wma';
817
            elseif ( 'text' == $limit_file_type )
818
                $limit_types = 'txt,rtx,csv,tsv';
819
            elseif ( 'any' == $limit_file_type )
820
                $limit_types = '';
821
            else
822
                $limit_types = pods_var( $field[ 'type' ] . '_allowed_extensions', $field[ 'options' ], '', null, true );
823
824
            $limit_types = trim( str_replace( array( ' ', '.', "\n", "\t", ';' ), array( '', ',', ',', ',' ), $limit_types ), ',' );
825
826 View Code Duplication
            if ( pods_version_check( 'wp', '3.5' ) ) {
827
                $mime_types = wp_get_mime_types();
828
829
                if ( in_array( $limit_file_type, array( 'images', 'audio', 'video' ) ) ) {
830
                    $new_limit_types = array();
831
832
                    foreach ( $mime_types as $type => $mime ) {
833
                        if ( 0 === strpos( $mime, $limit_file_type ) ) {
834
                            $type = explode( '|', $type );
835
836
                            $new_limit_types = array_merge( $new_limit_types, $type );
837
                        }
838
                    }
839
840
                    if ( !empty( $new_limit_types ) )
841
                        $limit_types = implode( ',', $new_limit_types );
842
                }
843
                elseif ( 'any' != $limit_file_type ) {
844
                    $new_limit_types = array();
845
846
                    $limit_types = explode( ',', $limit_types );
847
848
                    foreach ( $limit_types as $k => $limit_type ) {
849
                        $found = false;
850
851
                        foreach ( $mime_types as $type => $mime ) {
852
                            if ( 0 === strpos( $mime, $limit_type ) ) {
853
                                $type = explode( '|', $type );
854
855
                                foreach ( $type as $t ) {
856
                                    if ( !in_array( $t, $new_limit_types ) )
857
                                        $new_limit_types[] = $t;
858
                                }
859
860
                                $found = true;
861
                            }
862
                        }
863
864
                        if ( !$found )
865
                            $new_limit_types[] = $limit_type;
866
                    }
867
868
                    if ( !empty( $new_limit_types ) )
869
                        $limit_types = implode( ',', $new_limit_types );
870
                }
871
            }
872
873
            $limit_types = explode( ',', $limit_types );
874
875
            $limit_types = array_filter( array_unique( $limit_types ) );
876
877
            if ( !empty( $limit_types ) ) {
878
                $ok = false;
879
880
                foreach ( $limit_types as $limit_type ) {
881
                    $limit_type = '.' . trim( $limit_type, ' .' );
882
883
                    $pos = ( strlen( $file[ 'name' ] ) - strlen( $limit_type ) );
884
885
                    if ( $pos === stripos( $file[ 'name' ], $limit_type ) ) {
886
                        $ok = true;
887
888
                        break;
889
                    }
890
                }
891
892
                if ( false === $ok ) {
893
                    $error = __( 'File type not allowed, please use one of the following: %s', 'pods' );
894
                    $error = sprintf( $error, '.' . implode( ', .', $limit_types ) );
895
896
                    pods_error( '<div style="color:#FF0000">Error: ' . $error . '</div>' );
897
                }
898
            }
899
900
            $custom_handler = apply_filters( 'pods_upload_handle', null, 'Filedata', $params->post_id, $params, $field );
901
902
            if ( null === $custom_handler ) {
903
				$linked = pods_var( $field[ 'type' ] . '_linked', $field[ 'options' ], 0 );
904
905
                $attachment_id = media_handle_upload( 'Filedata', $params->post_id );
906
907
                if ( is_object( $attachment_id ) ) {
908
                    $errors = array();
909
910
                    foreach ( $attachment_id->errors[ 'upload_error' ] as $error_code => $error_message ) {
911
                        $errors[] = '[' . $error_code . '] ' . $error_message;
912
                    }
913
914
                    pods_error( '<div style="color:#FF0000">Error: ' . implode( '</div><div>', $errors ) . '</div>' );
915
                }
916
                else {
917
                    $attachment = get_post( $attachment_id, ARRAY_A );
918
919
                    $attachment[ 'filename' ] = basename( $attachment[ 'guid' ] );
920
921
                    $thumb = wp_get_attachment_image_src( $attachment[ 'ID' ], 'thumbnail', true );
922
                    $attachment[ 'thumbnail' ] = $thumb[ 0 ];
923
924
					$attachment[ 'link' ] = '';
925
926
					if ( $linked ) {
927
                    	$attachment[ 'link' ] = wp_get_attachment_url( $attachment[ 'ID' ] );
928
					}
929
930
                    $attachment = apply_filters( 'pods_upload_attachment', $attachment, $params->post_id );
931
932
                    wp_send_json( $attachment );
933
                }
934
            }
935
        }
936
937
        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...
938
    }
939
}
940