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