PluginProbe ʕ •ᴥ•ʔ
Pods – Custom Content Types and Fields / 2.8.23.4
Pods – Custom Content Types and Fields v2.8.23.4
2.7.31.4 2.8.23.5 2.9.19.5 3.0.10.5 3.1.4.3 3.2.8.4 3.3.9.2 2.8.23.4 2.9.19.4 3.0.10.4 3.1.4.2 3.2.8.3 3.3.9.1 trunk 1.14.8 2.7.31.3 2.8.23.3 2.9.19.3 3.0.10.3 3.1.4.1 3.2.0 3.2.1 3.2.1.1 3.2.2 3.2.4 3.2.5 3.2.6 3.2.7 3.2.7.1 3.2.8 3.2.8.1 3.2.8.2 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9
pods / classes / fields / file.php
pods / classes / fields Last commit date
avatar.php 2 weeks ago boolean.php 2 weeks ago code.php 2 weeks ago color.php 2 weeks ago comment.php 2 weeks ago currency.php 2 weeks ago date.php 2 weeks ago datetime.php 2 weeks ago email.php 2 weeks ago file.php 2 weeks ago heading.php 2 weeks ago html.php 2 weeks ago link.php 2 weeks ago number.php 2 weeks ago oembed.php 2 weeks ago paragraph.php 2 weeks ago password.php 2 weeks ago phone.php 2 weeks ago pick.php 2 weeks ago slug.php 2 weeks ago taxonomy.php 2 weeks ago text.php 2 weeks ago time.php 2 weeks ago website.php 2 weeks ago wysiwyg.php 2 weeks ago
file.php
1392 lines
1 <?php
2
3 /**
4 * @package Pods\Fields
5 */
6 class PodsField_File extends PodsField {
7
8 /**
9 * {@inheritdoc}
10 */
11 public static $group = 'Relationships / Media';
12
13 /**
14 * {@inheritdoc}
15 */
16 public static $type = 'file';
17
18 /**
19 * {@inheritdoc}
20 */
21 public static $label = 'File / Image / Video';
22
23 /**
24 * {@inheritdoc}
25 */
26 protected static $api = false;
27
28 /**
29 * Temporary upload directory.
30 * @var string
31 */
32 private static $tmp_upload_dir;
33
34 /**
35 * {@inheritdoc}
36 */
37 public function setup() {
38
39 static::$group = __( 'Relationships / Media', 'pods' );
40 static::$label = __( 'File / Image / Video', 'pods' );
41
42 }
43
44 /**
45 * {@inheritdoc}
46 */
47 public function admin_init() {
48
49 // Hook into AJAX for Uploads.
50 add_action( 'wp_ajax_pods_upload', array( $this, 'admin_ajax_upload' ) );
51 add_action( 'wp_ajax_nopriv_pods_upload', array( $this, 'admin_ajax_upload' ) );
52
53 }
54
55 /**
56 * {@inheritdoc}
57 */
58 public function options() {
59
60 $sizes = get_intermediate_image_sizes();
61
62 $image_sizes = array();
63
64 foreach ( $sizes as $size ) {
65 $image_sizes[ $size ] = ucwords( str_replace( '-', ' ', $size ) );
66 }
67
68 $type = static::$type;
69
70 $options = array(
71 static::$type . '_format_type' => array(
72 'label' => __( 'Upload Limit', 'pods' ),
73 'default' => 'single',
74 'required' => true,
75 'type' => 'pick',
76 'data' => array(
77 'single' => __( 'Single File', 'pods' ),
78 'multi' => __( 'Multiple Files', 'pods' ),
79 ),
80 'pick_show_select_text' => 0,
81 'dependency' => true,
82 ),
83 static::$type . '_uploader' => array(
84 'label' => __( 'File Uploader', 'pods' ),
85 'default' => 'attachment',
86 'required' => true,
87 'type' => 'pick',
88 'data' => apply_filters(
89 "pods_form_ui_field_{$type}_uploader_options",
90 array(
91 'attachment' => __( 'Upload and/or Select (Media Library)', 'pods' ),
92 'plupload' => __( 'Upload only (Plupload)', 'pods' ),
93 )
94 ),
95 'pick_show_select_text' => 0,
96 'dependency' => true,
97 ),
98 static::$type . '_attachment_tab' => array(
99 'label' => __( 'Media Library Default Tab', 'pods' ),
100 'depends-on' => array( static::$type . '_uploader' => 'attachment' ),
101 'default' => 'upload',
102 'required' => true,
103 'type' => 'pick',
104 'data' => array(
105 // These keys must match WP media modal router names.
106 'upload' => __( 'Upload File', 'pods' ),
107 'browse' => __( 'Media Library', 'pods' ),
108 ),
109 'pick_show_select_text' => 0,
110 ),
111 static::$type . '_upload_dir' => array(
112 'label' => __( 'Upload Directory', 'pods' ),
113 'default' => 'wp',
114 'type' => 'pick',
115 'required' => true,
116 'data' => array(
117 'wp' => __( 'WordPress Default', 'pods' ) . ' (/wp-content/uploads/yyyy/mm/)',
118 'uploads' => __( 'Custom directory within the default uploads directory', 'pods' ),
119 ),
120 'pick_show_select_text' => 0,
121 'depends-on' => array( static::$type . '_uploader' => 'plupload' ),
122 'dependency' => true,
123 ),
124 static::$type . '_upload_dir_custom' => array(
125 'label' => __( 'Custom Upload Directory', 'pods' ),
126 'help' => __( 'Magic tags are allowed for this field. The path is relative to the /wp-content/uploads/ folder on your site.', 'pods' ),
127 'placeholder' => 'my-custom-folder',
128 'required' => true,
129 'depends-on' => array(
130 static::$type . '_uploader' => 'plupload',
131 static::$type . '_upload_dir' => 'uploads',
132 ),
133 /**
134 * Allow filtering the custom upload directory used.
135 *
136 * @since 2.7.28
137 *
138 * @param string $default_directory The custom upload directory to use by default for new fields.
139 */
140 'default' => apply_filters( "pods_form_ui_field_{$type}_upload_dir_custom", '' ),
141 'type' => 'text',
142 ),
143 static::$type . '_edit_title' => array(
144 'label' => __( 'Editable Title', 'pods' ),
145 'default' => 1,
146 'type' => 'boolean',
147 ),
148 static::$type . '_show_edit_link' => array(
149 'label' => __( 'Show Edit Link', 'pods' ),
150 'default' => 0,
151 'type' => 'boolean',
152 ),
153 static::$type . '_linked' => array(
154 'label' => __( 'Show Download Link', 'pods' ),
155 'default' => 0,
156 'type' => 'boolean',
157 ),
158 static::$type . '_limit' => array(
159 'label' => __( 'Max Number of Files', 'pods' ),
160 'depends-on' => array( static::$type . '_format_type' => 'multi' ),
161 'default' => 0,
162 'type' => 'number',
163 ),
164 static::$type . '_restrict_filesize' => array(
165 'label' => __( 'Restrict File Size', 'pods' ),
166 'help' => __( 'Valid size suffixes are: GB (gigabytes), MB (megabytes), KB (kilobytes), or B (bytes). Defaults to the <a href="https://developer.wordpress.org/reference/functions/wp_max_upload_size/">wp_max_upload_size</a> setting.', 'pods' ),
167 'depends-on' => array( static::$type . '_uploader' => 'plupload' ),
168 'default' => '',
169 'text_placeholder' => '10MB',
170 'type' => 'text',
171 ),
172 static::$type . '_type' => array(
173 'label' => __( 'Restrict File Types', 'pods' ),
174 'default' => apply_filters( "pods_form_ui_field_{$type}_type_default", 'images' ),
175 'type' => 'pick',
176 'data' => apply_filters(
177 "pods_form_ui_field_{$type}_type_options",
178 array(
179 'images' => __( 'Images (jpg, jpeg, png, gif)', 'pods' ),
180 'video' => __( 'Video (mpg, mov, flv, mp4, etc..)', 'pods' ),
181 'audio' => __( 'Audio (mp3, m4a, wav, wma, etc..)', 'pods' ),
182 'text' => __( 'Text (txt, csv, tsv, rtx, etc..)', 'pods' ),
183 'any' => __( 'Any Type (no restriction)', 'pods' ),
184 'other' => __( 'Other (customize allowed extensions)', 'pods' ),
185 )
186 ),
187 'pick_show_select_text' => 0,
188 'dependency' => true,
189 ),
190 static::$type . '_allowed_extensions' => array(
191 'label' => __( 'Allowed File Extensions', 'pods' ),
192 'description' => __( 'Separate file extensions with a comma (ex. jpg,png,mp4,mov). This only applies to the file uploader, media library selection will continue to fallback to the mime-type group like Images, Video, etc.', 'pods' ),
193 'depends-on' => array( static::$type . '_type' => 'other' ),
194 'default' => apply_filters( "pods_form_ui_field_{$type}_extensions_default", '' ),
195 'text_placeholder' => 'jpg,png,mp4,mov',
196 'type' => 'text',
197 ),
198 static::$type . '_field_template' => array(
199 'label' => __( 'List Style', 'pods' ),
200 'help' => __( 'You can choose which style you would like the files to appear within the form.', 'pods' ),
201 'depends-on' => array( static::$type . '_type' => 'images' ),
202 'default' => apply_filters( "pods_form_ui_field_{$type}_template_default", 'rows' ),
203 'type' => 'pick',
204 'data' => apply_filters(
205 "pods_form_ui_field_{$type}_type_templates",
206 array(
207 'rows' => __( 'Rows', 'pods' ),
208 'tiles' => __( 'Tiles', 'pods' ),
209 )
210 ),
211 'pick_show_select_text' => 0,
212 ),
213 static::$type . '_add_button' => array(
214 'label' => __( 'Add Button Text', 'pods' ),
215 'default' => __( 'Add File', 'pods' ),
216 'type' => 'text',
217 ),
218 static::$type . '_modal_title' => array(
219 'label' => __( 'Modal Title', 'pods' ),
220 'depends-on' => array( static::$type . '_uploader' => 'attachment' ),
221 'default' => __( 'Attach a file', 'pods' ),
222 'type' => 'text',
223 ),
224 static::$type . '_modal_add_button' => array(
225 'label' => __( 'Modal Add Button Text', 'pods' ),
226 'depends-on' => array( static::$type . '_uploader' => 'attachment' ),
227 'default' => __( 'Add File', 'pods' ),
228 'type' => 'text',
229 ),
230
231 /* WP GALLERY OUTPUT */
232 static::$type . '_wp_gallery_output' => array(
233 'label' => __( 'Output as a WP Gallery', 'pods' ),
234 'help' => sprintf( __( '<a href="%s" target="_blank" rel="noopener noreferrer">Click here for more info</a>', 'pods' ), 'https://wordpress.org/support/article/inserting-images-into-posts-and-pages/' ),
235 'depends-on' => array( static::$type . '_type' => 'images' ),
236 'dependency' => true,
237 'type' => 'boolean',
238 ),
239 static::$type . '_wp_gallery_link' => array(
240 'label' => __( 'Gallery Image Links', 'pods' ),
241 'depends-on' => array( static::$type . '_wp_gallery_output' => true ),
242 'type' => 'pick',
243 'data' => array(
244 'post' => __( 'Attachment Page', 'pods' ),
245 'file' => __( 'Media File', 'pods' ),
246 'none' => __( 'None', 'pods' ),
247 ),
248 'pick_show_select_text' => 0,
249 ),
250 static::$type . '_wp_gallery_columns' => array(
251 'label' => __( 'Gallery Image Columns', 'pods' ),
252 'depends-on' => array( static::$type . '_wp_gallery_output' => true ),
253 'type' => 'pick',
254 'data' => array(
255 '1' => '1',
256 '2' => '2',
257 '3' => '3',
258 '4' => '4',
259 '5' => '5',
260 '6' => '6',
261 '7' => '7',
262 '8' => '8',
263 '9' => '9',
264 ),
265 'pick_show_select_text' => 0,
266 ),
267 static::$type . '_wp_gallery_random_sort' => array(
268 'label' => __( 'Gallery Randomized Order', 'pods' ),
269 'depends-on' => array( static::$type . '_wp_gallery_output' => true ),
270 'type' => 'boolean',
271 ),
272 static::$type . '_wp_gallery_size' => array(
273 'label' => __( 'Gallery Image Size', 'pods' ),
274 'depends-on' => array( static::$type . '_wp_gallery_output' => true ),
275 'type' => 'pick',
276 'data' => $this->data_image_sizes(),
277 'pick_show_select_text' => 0,
278 ),
279 );
280
281 return $options;
282
283 }
284
285 /**
286 * {@inheritdoc}
287 */
288 public function prepare( $options = null ) {
289 $format = static::$prepare;
290
291 // Maybe use number format for storage if limit is one.
292 if ( $options instanceof Field && 1 === $options->get_limit() ) {
293 $format = '%d';
294 }
295
296 return $format;
297 }
298
299 /**
300 * {@inheritdoc}
301 */
302 public function schema( $options = null ) {
303 return false;
304 }
305
306 /**
307 * {@inheritdoc}
308 */
309 public function display( $value = null, $name = null, $options = null, $pod = null, $id = null ) {
310
311 if ( ! empty( $options[ static::$type . '_wp_gallery_output' ] ) ) {
312 return $this->do_wp_gallery( $value, $options );
313 }
314
315 if ( is_array( $value ) && ! empty( $value ) ) {
316 if ( isset( $value['ID'] ) ) {
317 $value = wp_get_attachment_url( $value['ID'] );
318 } else {
319 $attachments = $value;
320 $value = array();
321
322 foreach ( $attachments as $v ) {
323 if ( ! is_array( $v ) ) {
324 $value[] = $v;
325 } elseif ( isset( $v['ID'] ) ) {
326 $value[] = wp_get_attachment_url( $v['ID'] );
327 }
328 }
329
330 $value = implode( ' ', $value );
331 }
332 }
333
334 return $value;
335
336 }
337
338 /**
339 * Determine whether someone has access to upload/browse for a file field in general.
340 *
341 * @return bool Whether someone has access to upload/browse for a file field in general.
342 */
343 public function has_access_to_upload_browse() {
344 /**
345 * Access Checking
346 */
347 $is_user_logged_in = is_user_logged_in();
348
349 $file_upload_requirements = [
350 'disabled' => ( defined( 'PODS_DISABLE_FILE_UPLOAD' ) && true === PODS_DISABLE_FILE_UPLOAD ),
351 'require_login' => ( defined( 'PODS_UPLOAD_REQUIRE_LOGIN' ) && true === PODS_UPLOAD_REQUIRE_LOGIN && ! $is_user_logged_in ),
352 'require_login_cap' => ( defined( 'PODS_UPLOAD_REQUIRE_LOGIN' ) && is_string( PODS_UPLOAD_REQUIRE_LOGIN ) && ( ! $is_user_logged_in || ! current_user_can( PODS_UPLOAD_REQUIRE_LOGIN ) ) ),
353 ];
354
355 $file_browser_requirements = [
356 'disabled' => ( defined( 'PODS_DISABLE_FILE_BROWSER' ) && true === PODS_DISABLE_FILE_BROWSER ),
357 'require_login' => ( defined( 'PODS_FILES_REQUIRE_LOGIN' ) && true === PODS_FILES_REQUIRE_LOGIN && ! $is_user_logged_in ),
358 'require_login_cap' => ( defined( 'PODS_FILES_REQUIRE_LOGIN' ) && is_string( PODS_FILES_REQUIRE_LOGIN ) && ( ! $is_user_logged_in || ! current_user_can( PODS_FILES_REQUIRE_LOGIN ) ) ),
359 ];
360
361 $file_upload_requirements = array_filter( $file_upload_requirements );
362 $file_browser_requirements = array_filter( $file_browser_requirements );
363
364 return empty( $file_upload_requirements ) || empty( $file_browser_requirements );
365 }
366
367 /**
368 * {@inheritdoc}
369 */
370 public function input( $name, $value = null, $options = null, $pod = null, $id = null ) {
371
372 $options = ( is_array( $options ) || is_object( $options ) ) ? $options : (array) $options;
373
374 $type = pods_v( 'type', $options, static::$type );
375
376 $args = compact( array_keys( get_defined_vars() ) );
377 $args = (object) $args;
378
379 if ( ! $this->has_access_to_upload_browse() ) {
380 ?>
381 <p><?php esc_html_e( 'You do not have access to upload / browse files. Contact your website admin to resolve.', 'pods' ); ?></p>
382 <?php
383
384 return;
385 }
386
387 wp_enqueue_media();
388
389 wp_enqueue_script( 'pods-i18n' );
390
391 // Ensure the media library is initialized
392 $this->render_input_script( $args );
393 }
394
395 /**
396 * {@inheritdoc}
397 */
398 public function build_dfv_field_options( $options, $args ) {
399
400 if ( ! is_admin() ) {
401 include_once ABSPATH . '/wp-admin/includes/template.php';
402
403 if ( is_multisite() ) {
404 include_once ABSPATH . '/wp-admin/includes/ms.php';
405 }
406 }
407
408 // Enforce defaults.
409 $all_options = static::options();
410
411 foreach ( $all_options as $option_name => $option ) {
412 $default = pods_v( 'default', $option, '' );
413
414 $options[ $option_name ] = pods_v( $option_name, $options, $default );
415
416 if ( '' === $options[ $option_name ] ) {
417 $options[ $option_name ] = $default;
418 }
419 }
420
421 // Handle default template setting.
422 $file_field_template = pods_v( $args->type . '_field_template', $options );
423
424 // Get which file types the field is limited to.
425 $limit_file_type = pods_v( $args->type . '_type', $options );
426
427 $options[ $args->type . '_type' ] = $limit_file_type;
428
429 // Non-image file types are forced to rows template right now.
430 if ( 'images' !== $limit_file_type ) {
431 $file_field_template = 'rows';
432 }
433
434 $options[ $args->type . '_field_template' ] = $file_field_template;
435
436 // Enforce limit.
437 $file_limit = 1;
438
439 if ( 'multi' === pods_v( $args->type . '_format_type', $options, 'single' ) ) {
440 $file_limit = (int) pods_v( $args->type . '_limit', $options, 0 );
441
442 if ( $file_limit < 0 ) {
443 $file_limit = 0;
444 }
445 }
446
447 $options[ $args->type . '_limit' ] = $file_limit;
448
449 // Build types and extensions to limit by.
450 if ( 'images' === $limit_file_type ) {
451 $limit_types = 'image';
452 $limit_extensions = 'jpg,jpeg,png,gif';
453 } elseif ( 'video' === $limit_file_type ) {
454 $limit_types = 'video';
455 $limit_extensions = 'mpg,mov,flv,mp4';
456 } elseif ( 'audio' === $limit_file_type ) {
457 $limit_types = 'audio';
458 $limit_extensions = 'mp3,m4a,wav,wma';
459 } elseif ( 'text' === $limit_file_type ) {
460 $limit_types = 'text';
461 $limit_extensions = 'txt,rtx,csv,tsv';
462 } elseif ( 'any' === $limit_file_type ) {
463 $limit_types = '';
464 $limit_extensions = '*';
465 } else {
466 $limit_types = pods_v( $args->type . '_allowed_extensions', $options, '', true );
467
468 $limit_extensions = $limit_types;
469 }
470
471 // Find and replace certain characters to properly split by commas.
472 $find = array(
473 ' ',
474 '.',
475 "\n",
476 "\t",
477 ';',
478 );
479
480 $replace = array(
481 '',
482 ',',
483 ',',
484 ',',
485 );
486
487 $limit_types = trim( str_replace( $find, $replace, $limit_types ), ',' );
488 $limit_extensions = trim( str_replace( $find, $replace, $limit_extensions ), ',' );
489 $mime_types = get_allowed_mime_types();
490
491 if ( ! in_array( $limit_file_type, array( 'images', 'video', 'audio', 'text', 'any' ), true ) ) {
492 $new_limit_types = array();
493
494 $limit_types = array_filter( explode( ',', $limit_types ) );
495
496 foreach ( $limit_types as $k => $limit_type ) {
497 if ( isset( $mime_types[ $limit_type ] ) ) {
498 $mime = explode( '/', $mime_types[ $limit_type ] );
499 $mime = $mime[0];
500
501 if ( ! in_array( $mime, $new_limit_types, true ) ) {
502 $new_limit_types[] = $mime;
503 }
504 } else {
505 $found = false;
506
507 foreach ( $mime_types as $type => $mime ) {
508 if ( false !== strpos( $type, $limit_type ) ) {
509 $mime = explode( '/', $mime );
510 $mime = $mime[0];
511
512 if ( ! in_array( $mime, $new_limit_types, true ) ) {
513 $new_limit_types[] = $mime;
514 }
515
516 $found = true;
517 }
518 }
519
520 if ( ! $found ) {
521 $new_limit_types[] = $limit_type;
522 }
523 }//end if
524 }//end foreach
525
526 if ( ! empty( $new_limit_types ) ) {
527 $limit_types = implode( ',', $new_limit_types );
528 }
529 }//end if
530
531 $options['limit_types'] = $limit_types;
532 $options['limit_extensions'] = $limit_extensions;
533
534 $is_user_logged_in = is_user_logged_in();
535
536 // @todo: plupload specific options need accommodation
537 if ( 'plupload' === pods_v( static::$type . '_uploader', $options ) ) {
538 wp_enqueue_script( 'plupload-all' );
539
540 $pod_id = (int) pods_v( 'pod_id', $args->pod, 0 );
541 $field_id = (int) pods_v( 'id', $options, 0 );
542 $item_id = (int) pods_v( 'id', $args, 0 );
543
544 if ( $is_user_logged_in ) {
545 $uid = 'user_' . get_current_user_id();
546 } else {
547 $uid = pods_session_id();
548 }
549
550 $uri_hash = wp_create_nonce( 'pods_uri_' . $_SERVER['REQUEST_URI'] );
551
552 $nonce_name = 'pods_upload:' . json_encode( compact( 'pod_name', 'field_name', 'uid', 'uri_hash', 'id' ) );
553 $field_nonce = wp_create_nonce( $nonce_name );
554
555 $plupload_init = [
556 'runtimes' => 'html5,silverlight,flash,html4',
557 'url' => admin_url( 'admin-ajax.php?pods_ajax=1', 'relative' ),
558 'file_data_name' => 'Filedata',
559 'multiple_queues' => false,
560 'max_file_size' => wp_max_upload_size() . 'b',
561 'flash_swf_url' => includes_url( 'js/plupload/plupload.flash.swf' ),
562 'silverlight_xap_url' => includes_url( 'js/plupload/plupload.silverlight.xap' ),
563 'filters' => [
564 [
565 'title' => __( 'Allowed Files', 'pods' ),
566 'extensions' => '*',
567 ],
568 ],
569 'multipart' => true,
570 'urlstream_upload' => true,
571 'multipart_params' => [
572 '_wpnonce' => $field_nonce,
573 'action' => 'pods_upload',
574 'method' => 'upload',
575 'pod' => $pod_id,
576 'field' => $field_id,
577 'item_id' => $item_id,
578 'uri' => $uri_hash,
579 ],
580 ];
581
582 // Disable multi selection if only one is allowed.
583 if ( 1 === $file_limit ) {
584 $plupload_init['multi_selection'] = false;
585 }
586
587 // Backwards compatibility: Pass post ID if we're in an add or edit post screen.
588 $post = get_post();
589 if ( $post instanceof WP_Post ) {
590 $plupload_init['multipart_params']['post_id'] = $post->ID;
591 }
592
593 $options['plupload_init'] = $plupload_init;
594 }//end if
595
596 return $options;
597
598 }
599
600 /**
601 * {@inheritdoc}
602 */
603 public function build_dfv_field_attributes( $attributes, $args ) {
604
605 // Add template class.
606 $attributes['class'] .= ' pods-field-template-' . $args->options[ $args->type . '_field_template' ];
607
608 return $attributes;
609
610 }
611
612 /**
613 * {@inheritdoc}
614 */
615 public function build_dfv_field_item_data( $args ) {
616
617 $data = array();
618
619 $title_editable = (int) pods_v( $args->type . '_edit_title', $args->options, 0 );
620
621 $value = $args->value;
622
623 if ( empty( $value ) ) {
624 $value = array();
625 } else {
626 $value = (array) $value;
627 }
628
629 foreach ( $value as $id ) {
630 $attachment = get_post( $id );
631
632 if ( empty( $attachment ) ) {
633 continue;
634 }
635
636 $icon = '';
637
638 // @todo Add access check
639 $edit_link = get_edit_post_link( $attachment->ID, 'raw' );
640
641 $link = get_permalink( $attachment->ID );
642 $download = wp_get_attachment_url( $attachment->ID );
643
644 $thumb = wp_get_attachment_image_src( $id, 'thumbnail', true );
645
646 if ( ! empty( $thumb[0] ) ) {
647 $icon = $thumb[0];
648 }
649
650 $title = $attachment->post_title;
651
652 if ( 0 === $title_editable ) {
653 $title = basename( $attachment->guid );
654 }
655
656 $data[] = array(
657 'id' => esc_html( $id ),
658 'icon' => esc_attr( $icon ),
659 'name' => wp_strip_all_tags( html_entity_decode( $title ) ),
660 'edit_link' => html_entity_decode( esc_url( $edit_link ) ),
661 'link' => html_entity_decode( esc_url( $link ) ),
662 'download' => html_entity_decode( esc_url( $download ) ),
663 'selected' => true,
664 );
665 }//end foreach
666
667 return $data;
668
669 }
670
671 /**
672 * {@inheritdoc}
673 */
674 public function validate( $value, $name = null, $options = null, $fields = null, $pod = null, $id = null, $params = null ) {
675
676 // @todo Check file size
677 // @todo Check file extensions
678 return parent::validate( $value, $name, $options, $fields, $pod, $id, $params );
679
680 }
681
682 /**
683 * {@inheritdoc}
684 */
685 public function save( $value, $id = null, $name = null, $options = null, $fields = null, $pod = null, $params = null ) {
686
687 if ( empty( self::$api ) ) {
688 self::$api = pods_api();
689 }
690
691 if ( null === $value ) {
692 $value = [];
693 } elseif ( ! is_array( $value ) || isset( $value['id'] ) ) {
694 $value = [
695 $value,
696 ];
697 }
698
699 $value = array_unique( array_filter( $value ), SORT_REGULAR );
700
701 // Handle File title saving.
702 foreach ( $value as $id ) {
703 $title = false;
704
705 if ( is_array( $id ) ) {
706 if ( isset( $id['title'] ) && 0 < strlen( trim( $id['title'] ) ) ) {
707 $title = trim( $id['title'] );
708 }
709
710 if ( isset( $id['id'] ) ) {
711 $id = (int) $id['id'];
712 } else {
713 $id = 0;
714 }
715 }
716
717 if ( empty( $id ) ) {
718 continue;
719 }
720
721 $attachment = null;
722 $attachment_data = array();
723
724 // Update the title if set.
725 if ( false !== $title && 1 === (int) pods_v( static::$type . '_edit_title', $options, 0 ) ) {
726 $attachment_data['post_title'] = $title;
727 }
728
729 // Update attachment parent if it's not set yet and we're updating a post.
730 if ( ! empty( $params->id ) && ! empty( $pod['type'] ) && 'post_type' === $pod['type'] ) {
731 $attachment = get_post( $id );
732
733 if ( isset( $attachment->post_parent ) && 0 === (int) $attachment->post_parent ) {
734 $attachment_data['post_parent'] = (int) $params->id;
735 }
736 }
737
738 // Update the attachment if it the data array is not still empty.
739 if ( ! empty( $attachment_data ) ) {
740 $attachment_data['ID'] = $id;
741
742 if ( $attachment ) {
743 // Add post type to trigger attachment update filters from other plugins.
744 $attachment_data['post_type'] = $attachment->post_type;
745 }
746
747 self::$api->save_wp_object( 'media', $attachment_data );
748 }
749 }//end foreach
750
751 }
752
753 /**
754 * {@inheritdoc}
755 */
756 public function ui( $id, $value, $name = null, $options = null, $fields = null, $pod = null ) {
757
758 if ( empty( $value ) ) {
759 return;
760 }
761
762 if ( ! empty( $value ) && isset( $value['ID'] ) ) {
763 $value = array( $value );
764 }
765
766 $type = static::$type;
767 $image_size = apply_filters( "pods_form_ui_field_{$type}_ui_image_size", 'thumbnail', $id, $value, $name, $options, $pod );
768
769 return $this->images( $id, $value, $name, $options, $pod, $image_size );
770
771 }
772
773 /**
774 * Return image(s) markup.
775 *
776 * @param int $id Item ID.
777 * @param mixed $value Field value.
778 * @param string $name Field name.
779 * @param array $options Field options.
780 * @param array $pod Pod options.
781 * @param string $image_size Image size.
782 *
783 * @return string
784 * @since 2.3.0
785 */
786 public function images( $id, $value, $name = null, $options = null, $pod = null, $image_size = null ) {
787
788 $images = '';
789
790 if ( empty( $value ) || ! is_array( $value ) ) {
791 return $images;
792 }
793
794 foreach ( $value as $v ) {
795 $images .= pods_image( $v, $image_size );
796 }
797
798 return $images;
799
800 }
801
802 /**
803 * Data callback for Image Sizes.
804 *
805 * @param string $name The name of the field.
806 * @param string|array $value The value of the field.
807 * @param array $options Field options.
808 * @param array $pod Pod data.
809 * @param int $id Item ID.
810 *
811 * @return array
812 *
813 * @since 2.3.0
814 */
815 public function data_image_sizes( $name = null, $value = null, $options = null, $pod = null, $id = null ) {
816
817 $data = array();
818
819 $image_sizes = get_intermediate_image_sizes();
820
821 foreach ( $image_sizes as $image_size ) {
822 $data[ $image_size ] = ucwords( str_replace( '-', ' ', $image_size ) );
823 }
824
825 $data['full'] = __( 'Full Size' ); // Translated by WordPress core.
826
827 return apply_filters( 'pods_form_ui_field_pick_data_image_sizes', $data, $name, $value, $options, $pod, $id );
828
829 }
830
831 /**
832 * Create a WP Gallery from the passed values (need to be attachments)
833 *
834 * @since 2.7.0
835 *
836 * @param string|array $value The value(s).
837 * @param array $options The field options.
838 *
839 * @return string
840 */
841 public function do_wp_gallery( $value, $options ) {
842
843 if ( ! $value ) {
844 return '';
845 }
846
847 $shortcode_args = array();
848
849 if ( ! empty( $options[ static::$type . '_wp_gallery_columns' ] ) ) {
850 $shortcode_args['columns'] = absint( $options[ static::$type . '_wp_gallery_columns' ] );
851 }
852
853 if ( ! empty( $options[ static::$type . '_wp_gallery_random_sort' ] ) ) {
854 $shortcode_args['orderby'] = 'rand';
855 }
856
857 if ( ! empty( $options[ static::$type . '_wp_gallery_link' ] ) ) {
858 $shortcode_args['link'] = $options[ static::$type . '_wp_gallery_link' ];
859 }
860
861 if ( ! empty( $options[ static::$type . '_wp_gallery_size' ] ) ) {
862 $shortcode_args['size'] = $options[ static::$type . '_wp_gallery_size' ];
863 }
864
865 if ( isset( $value['ID'] ) ) {
866 $shortcode_args['ids'] = $value['ID'];
867 } else {
868 $images = array();
869
870 foreach ( (array) $value as $v ) {
871 if ( ! is_array( $v ) ) {
872 $images[] = (int) $v;
873 } elseif ( isset( $v['ID'] ) ) {
874 $images[] = (int) $v['ID'];
875 }
876 }
877
878 $shortcode_args['ids'] = implode( ',', $images );
879 }
880
881 if ( is_callable( 'gallery_shortcode' ) ) {
882 return gallery_shortcode( $shortcode_args );
883 } else {
884 $shortcode = '[gallery';
885
886 foreach ( $shortcode_args as $key => $shortcode_arg ) {
887 $shortcode .= ' ' . esc_attr( $key ) . '="' . esc_attr( $shortcode_arg ) . '"';
888 }
889
890 $shortcode .= ']';
891
892 return do_shortcode( $shortcode );
893 }
894
895 }
896
897 /**
898 * Handle file row output for uploaders
899 *
900 * @param array $attributes Field options.
901 * @param int $limit List limit.
902 * @param bool $editable Whether the items should be editable.
903 * @param null|int|string $id Item ID.
904 * @param null|string $icon Icon URL.
905 * @param null|string $name File name.
906 * @param bool $linked Whether the items should be linked.
907 * @param null|string $link Link URL.
908 *
909 * @return string
910 * @since 2.0.0
911 *
912 * @deprecated 2.7.0
913 */
914 public function markup( $attributes, $limit = 1, $editable = true, $id = null, $icon = null, $name = null, $linked = false, $link = null ) {
915
916 _doing_it_wrong( 'PodsField_File::markup', esc_html__( 'This method has been deprecated and will be removed from Pods 3.0', 'pods' ), '2.7' );
917
918 // Preserve current file type.
919 $field_type = PodsForm::$field_type;
920
921 ob_start();
922
923 if ( empty( $id ) ) {
924 $id = '{{id}}';
925 }
926
927 if ( empty( $icon ) ) {
928 $icon = '{{icon}}';
929 }
930
931 if ( empty( $name ) ) {
932 $name = '{{name}}';
933 }
934
935 if ( empty( $link ) ) {
936 $link = '{{link}}';
937 }
938
939 $editable = (boolean) $editable;
940 $linked = (boolean) $linked;
941 ?>
942 <li class="pods-file hidden" id="pods-file-<?php echo esc_attr( $id ); ?>">
943 <?php
944 // @codingStandardsIgnoreLine
945 echo PodsForm::field( $attributes['name'] . '[' . $id . '][id]', $id, 'hidden' );
946 ?>
947
948 <ul class="pods-file-meta media-item">
949 <?php if ( 1 !== (int) $limit ) { ?>
950 <li class="pods-file-col pods-file-handle">Handle</li>
951 <?php } ?>
952
953 <li class="pods-file-col pods-file-icon">
954 <img class="pinkynail" src="<?php echo esc_url( $icon ); ?>" alt="Icon" />
955 </li>
956
957 <li class="pods-file-col pods-file-name">
958 <?php
959 if ( $editable ) {
960 // @codingStandardsIgnoreLine
961 echo PodsForm::field( $attributes['name'] . '[' . $id . '][title]', $name, 'text' );
962 } else {
963 echo esc_html( $name );
964 }
965 ?>
966 </li>
967
968 <li class="pods-file-col pods-file-actions">
969 <ul>
970 <li class="pods-file-col pods-file-delete"><a href="#delete">Delete</a></li>
971 <?php
972 if ( $linked ) {
973 ?>
974 <li class="pods-file-col pods-file-download">
975 <a href="<?php echo esc_url( $link ); ?>" target="_blank" rel="noopener noreferrer">Download</a></li>
976 <?php
977 }
978 ?>
979 </ul>
980 </li>
981 </ul>
982 </li>
983 <?php
984 PodsForm::$field_type = $field_type;
985
986 return ob_get_clean();
987
988 }
989
990 /**
991 * Handle AJAX plupload calls.
992 *
993 * @since 2.3.0
994 */
995 public function admin_ajax_upload() {
996
997 pods_session_start();
998
999 // Sanitize input @codingStandardsIgnoreLine
1000 $params = pods_unslash( (array) $_POST );
1001
1002 foreach ( $params as $key => $value ) {
1003 if ( 'action' === $key ) {
1004 continue;
1005 }
1006
1007 unset( $params[ $key ] );
1008
1009 $params[ str_replace( '_podsfix_', '', $key ) ] = $value;
1010 }
1011
1012 $params = (object) $params;
1013
1014 $methods = array(
1015 'upload',
1016 );
1017
1018 if ( ! isset( $params->method ) || ! in_array( $params->method, $methods, true ) || ! isset( $params->pod ) || ! isset( $params->field ) || ! isset( $params->uri ) || empty( $params->uri ) ) {
1019 return pods_error( __( 'Invalid AJAX request', 'pods' ), PodsInit::$admin );
1020 } elseif ( ! empty( $params->pod ) && empty( $params->field ) ) {
1021 return pods_error( __( 'Invalid AJAX request', 'pods' ), PodsInit::$admin );
1022 } elseif ( empty( $params->pod ) && ! current_user_can( 'upload_files' ) ) {
1023 return pods_error( __( 'Invalid AJAX request', 'pods' ), PodsInit::$admin );
1024 }
1025
1026 /**
1027 * Access Checking
1028 */
1029 $upload_disabled = false;
1030 $is_user_logged_in = is_user_logged_in();
1031
1032 if ( defined( 'PODS_DISABLE_FILE_UPLOAD' ) && true === PODS_DISABLE_FILE_UPLOAD ) {
1033 $upload_disabled = true;
1034 } elseif ( ! $is_user_logged_in && defined( 'PODS_UPLOAD_REQUIRE_LOGIN' ) ) {
1035 if ( true === PODS_UPLOAD_REQUIRE_LOGIN ) {
1036 $upload_disabled = true;
1037 } elseif ( is_string( PODS_UPLOAD_REQUIRE_LOGIN ) && ! current_user_can( PODS_UPLOAD_REQUIRE_LOGIN ) ) {
1038 $upload_disabled = true;
1039 }
1040 }
1041
1042 $uid = pods_session_id();
1043
1044 if ( $is_user_logged_in ) {
1045 $uid = 'user_' . get_current_user_id();
1046 }
1047
1048 $nonce_check = 'pods_upload_' . (int) $params->pod . '_' . $uid . '_' . $params->uri . '_' . (int) $params->field;
1049
1050 if ( true === $upload_disabled || ! isset( $params->_wpnonce ) || false === wp_verify_nonce( $params->_wpnonce, $nonce_check ) ) {
1051 return pods_error( __( 'Unauthorized request', 'pods' ), PodsInit::$admin );
1052 }
1053
1054 $pod = array();
1055 $field = array(
1056 'type' => 'file',
1057 'options' => array(),
1058 );
1059
1060 if ( empty( self::$api ) ) {
1061 self::$api = pods_api();
1062 }
1063
1064 self::$api->display_errors = false;
1065
1066 if ( ! empty( $params->pod ) ) {
1067 $pod = self::$api->load_pod( array( 'id' => (int) $params->pod ) );
1068 $field = self::$api->load_field( array( 'id' => (int) $params->field ) );
1069
1070 if ( empty( $pod ) || empty( $field ) || (int) $pod['id'] !== (int) $field['pod_id'] || ! isset( $pod['fields'][ $field['name'] ] ) ) {
1071 return pods_error( __( 'Invalid field request', 'pods' ), PodsInit::$admin );
1072 }
1073
1074 if ( ! in_array( $field['type'], PodsForm::file_field_types(), true ) ) {
1075 return pods_error( __( 'Invalid field', 'pods' ), PodsInit::$admin );
1076 }
1077 }
1078
1079 $method = $params->method;
1080
1081 // Cleaning up $params
1082 unset( $params->action, $params->method, $params->_wpnonce );
1083
1084 $params->item_id = (int) pods_v( 'item_id', $params, 0 );
1085
1086 /**
1087 * Upload a new file (advanced - returns URL and ID)
1088 */
1089 if ( 'upload' === $method ) {
1090 $file = $_FILES['Filedata'];
1091
1092 $limit_size = pods_v( $field['type'] . '_restrict_filesize', $field['options'] );
1093
1094 if ( ! empty( $limit_size ) ) {
1095 if ( false !== stripos( $limit_size, 'GB' ) ) {
1096 $limit_size = (float) trim( str_ireplace( 'GB', '', $limit_size ) );
1097 $limit_size = $limit_size * 1025 * 1025 * 1025;
1098 // convert to MB to KB to B
1099 } elseif ( false !== stripos( $limit_size, 'MB' ) ) {
1100 $limit_size = (float) trim( str_ireplace( 'MB', '', $limit_size ) );
1101 $limit_size = $limit_size * 1025 * 1025;
1102 // convert to KB to B
1103 } elseif ( false !== stripos( $limit_size, 'KB' ) ) {
1104 $limit_size = (float) trim( str_ireplace( 'KB', '', $limit_size ) );
1105 $limit_size *= 1025;
1106 // convert to B
1107 } elseif ( false !== stripos( $limit_size, 'B' ) ) {
1108 $limit_size = (float) trim( str_ireplace( 'B', '', $limit_size ) );
1109 } else {
1110 $limit_size = wp_max_upload_size();
1111 }
1112
1113 if ( 0 < $limit_size && $limit_size < $file['size'] ) {
1114 $error = __( 'File size too large, max size is %s', 'pods' );
1115 $error = sprintf( $error, pods_v( $field['type'] . '_restrict_filesize', $field['options'] ) );
1116
1117 return pods_error( '<div style="color:#FF0000">Error: ' . $error . '</div>' );
1118 }
1119 }//end if
1120
1121 $limit_file_type = pods_v( $field['type'] . '_type', $field['options'], 'images' );
1122
1123 if ( 'images' === $limit_file_type ) {
1124 $limit_types = 'jpg,jpeg,png,gif';
1125 } elseif ( 'video' === $limit_file_type ) {
1126 $limit_types = 'mpg,mov,flv,mp4';
1127 } elseif ( 'audio' === $limit_file_type ) {
1128 $limit_types = 'mp3,m4a,wav,wma';
1129 } elseif ( 'text' === $limit_file_type ) {
1130 $limit_types = 'txt,rtx,csv,tsv';
1131 } elseif ( 'any' === $limit_file_type ) {
1132 $limit_types = '';
1133 } else {
1134 $limit_types = pods_v( $field['type'] . '_allowed_extensions', $field['options'], '', true );
1135 }
1136
1137 $limit_types = trim(
1138 str_replace(
1139 array( ' ', '.', "\n", "\t", ';' ), array(
1140 '',
1141 ',',
1142 ',',
1143 ',',
1144 ), $limit_types
1145 ), ','
1146 );
1147
1148 $mime_types = get_allowed_mime_types();
1149
1150 if ( in_array( $limit_file_type, array( 'images', 'audio', 'video' ), true ) ) {
1151 $new_limit_types = array();
1152
1153 foreach ( $mime_types as $type => $mime ) {
1154 if ( 0 === strpos( $mime, $limit_file_type ) ) {
1155 $type = explode( '|', $type );
1156
1157 $new_limit_types = array_merge( $new_limit_types, $type );
1158 }
1159 }
1160
1161 if ( ! empty( $new_limit_types ) ) {
1162 $limit_types = implode( ',', $new_limit_types );
1163 }
1164 } elseif ( 'any' !== $limit_file_type ) {
1165 $new_limit_types = array();
1166
1167 $limit_types = explode( ',', $limit_types );
1168
1169 foreach ( $limit_types as $k => $limit_type ) {
1170 $found = false;
1171
1172 foreach ( $mime_types as $type => $mime ) {
1173 if ( 0 === strpos( $mime, $limit_type ) ) {
1174 $type = explode( '|', $type );
1175
1176 foreach ( $type as $t ) {
1177 if ( ! in_array( $t, $new_limit_types, true ) ) {
1178 $new_limit_types[] = $t;
1179 }
1180 }
1181
1182 $found = true;
1183 }
1184 }
1185
1186 if ( ! $found ) {
1187 $new_limit_types[] = $limit_type;
1188 }
1189 }//end foreach
1190
1191 if ( ! empty( $new_limit_types ) ) {
1192 $limit_types = implode( ',', $new_limit_types );
1193 }
1194 }//end if
1195
1196 $limit_types = explode( ',', $limit_types );
1197
1198 $limit_types = array_filter( array_unique( $limit_types ) );
1199
1200 if ( ! empty( $limit_types ) ) {
1201 $file_info = pathinfo( $file['name'] );
1202 $ok = false;
1203
1204 if ( isset( $file_info['extension'] ) ) {
1205 // Enforce lowercase for the extension checking.
1206 $file_info['extension'] = strtolower( $file_info['extension'] );
1207
1208 foreach ( $limit_types as $limit_type ) {
1209 $limit_type = strtolower( trim( $limit_type, ' .' ) );
1210
1211 if ( $limit_type === $file_info['extension'] ) {
1212 $ok = true;
1213
1214 break;
1215 }
1216 }
1217 }
1218
1219 if ( false === $ok ) {
1220 $error = __( 'File type not allowed, please use one of the following: %s', 'pods' );
1221 $error = sprintf( $error, '.' . implode( ', .', $limit_types ) );
1222
1223 return pods_error( '<div style="color:#FF0000">Error: ' . $error . '</div>' );
1224 }
1225 }//end if
1226
1227 $custom_handler = apply_filters( 'pods_upload_handle', null, 'Filedata', $params->item_id, $params, $field );
1228
1229 if ( null === $custom_handler ) {
1230
1231 // Start custom directory.
1232 $upload_dir = pods_v( $field['type'] . '_upload_dir', $field['options'], 'wp' );
1233
1234 if ( 'wp' !== $upload_dir ) {
1235 $custom_dir = pods_v( $field['type'] . '_upload_dir_custom', $field['options'], '' );
1236 $context_pod = null;
1237
1238 if ( $params->item_id ) {
1239 $context_pod = pods( pods_v( 'name', $pod, false ), $params->item_id );
1240
1241 if ( ! $context_pod->exists() ) {
1242 $context_pod = null;
1243 }
1244 }
1245
1246 /**
1247 * Filter the custom upload directory Pod context.
1248 *
1249 * @since 2.7.28
1250 *
1251 * @param Pods $context_pod The Pods object of the associated pod for the post type.
1252 * @param array $params The POSTed parameters for the request.
1253 * @param array $field The field configuration associated to the upload field.
1254 * @param array $pod The pod configuration associated to the upload field.
1255 */
1256 $context_pod = apply_filters( 'pods_upload_dir_custom_context_pod', $context_pod, $params, $field, $pod );
1257
1258 $custom_dir = pods_evaluate_tags( $custom_dir, array( 'pod' => $context_pod ) );
1259
1260 /**
1261 * Filter the custom Pod upload directory.
1262 *
1263 * @since 2.7.28
1264 *
1265 * @param string $custom_dir The directory to use for the uploaded file.
1266 * @param array $params The POSTed parameters for the request.
1267 * @param Pods $context_pod The Pods object of the associated pod for the post type.
1268 * @param array $field The field configuration associated to the upload field.
1269 * @param array $pod The pod configuration associated to the upload field.
1270 */
1271 $custom_dir = apply_filters( 'pods_upload_dir_custom', $custom_dir, $params, $context_pod, $field, $pod );
1272
1273 self::$tmp_upload_dir = $custom_dir;
1274
1275 add_filter( 'upload_dir', array( $this, 'filter_upload_dir' ) );
1276 }
1277
1278 // Upload file.
1279 $post_id = 0;
1280 if ( 'post_type' === pods_v( 'type', $pod, null ) ) {
1281 $post_id = $params->item_id;
1282 }
1283
1284 $attachment_id = media_handle_upload( 'Filedata', $post_id );
1285
1286 // End custom directory.
1287 if ( 'wp' !== $upload_dir ) {
1288 remove_filter( 'upload_dir', array( $this, 'filter_upload_dir' ) );
1289
1290 self::$tmp_upload_dir = null;
1291 }
1292
1293 if ( is_object( $attachment_id ) ) {
1294 $errors = array();
1295
1296 foreach ( $attachment_id->errors['upload_error'] as $error_code => $error_message ) {
1297 $errors[] = '[' . $error_code . '] ' . $error_message;
1298 }
1299
1300 return pods_error( '<div style="color:#FF0000">Error: ' . implode( '</div><div>', $errors ) . '</div>' );
1301 } else {
1302 $attachment = get_post( $attachment_id, ARRAY_A );
1303
1304 $attachment['filename'] = basename( $attachment['guid'] );
1305
1306 $thumb = wp_get_attachment_image_src( $attachment['ID'], 'thumbnail', true );
1307
1308 $attachment['thumbnail'] = '';
1309
1310 if ( ! empty( $thumb[0] ) ) {
1311 $attachment['thumbnail'] = $thumb[0];
1312 }
1313
1314 $attachment['link'] = get_permalink( $attachment['ID'] );
1315 $attachment['edit_link'] = get_edit_post_link( $attachment['ID'] );
1316 $attachment['download'] = wp_get_attachment_url( $attachment['ID'] );
1317
1318 $attachment = apply_filters( 'pods_upload_attachment', $attachment, $params->item_id );
1319
1320 wp_send_json( $attachment );
1321 }//end if
1322 }//end if
1323 }//end if
1324
1325 die();
1326 // KBAI!
1327 }
1328
1329 /**
1330 * Modify the upload directory.
1331 *
1332 * @since 2.7.28
1333 *
1334 * @see wp_upload_dir()
1335 *
1336 * @param array $uploads The uploads directory information.
1337 *
1338 * @return array The filtered uploads directory information.
1339 */
1340 public function filter_upload_dir( $uploads ) {
1341 if ( empty( self::$tmp_upload_dir ) ) {
1342 return $uploads;
1343 }
1344
1345 $dir = trim( self::$tmp_upload_dir, '/' );
1346 $subdir = trim( $uploads['subdir'], '/' );
1347
1348 foreach ( $uploads as $key => $val ) {
1349 if ( ! is_string( $val ) ) {
1350 continue;
1351 }
1352
1353 if ( $subdir ) {
1354 $uploads[ $key ] = str_replace( $subdir, $dir, $val );
1355 } elseif ( in_array( $key, array( 'path', 'url', 'subdir' ), true ) ) {
1356 $uploads[ $key ] = trailingslashit( $val ) . $dir;
1357 }
1358 }
1359
1360 return $uploads;
1361 }
1362
1363 /**
1364 * Build field data for Pods DFV.
1365 *
1366 * @param object $args {
1367 * Field information arguments.
1368 *
1369 * @type string $name Field name.
1370 * @type string $type Field type.
1371 * @type array $options Field options.
1372 * @type mixed $value Current value.
1373 * @type array $pod Pod information.
1374 * @type int|string $id Current item ID.
1375 * @type string $form_field_type HTML field type.
1376 * }
1377 *
1378 * @return array
1379 */
1380 public function build_dfv_field_data( $args ) {
1381 $data = parent::build_dfv_field_data( $args );
1382
1383 // Normalize arrays for multiple select.
1384 if ( is_array( $data['fieldValue'] ) ) {
1385 $data['fieldValue'] = array_values( $data['fieldValue'] );
1386 }
1387
1388 return $data;
1389 }
1390
1391 }
1392