PluginProbe ʕ •ᴥ•ʔ
Secure Custom Fields / 6.8.1
Secure Custom Fields v6.8.1
6.9.1 6.9.0 6.8.9 6.8.7 6.8.8 6.8.6 6.8.4 6.8.5 trunk 6.4.0-beta1 6.4.0-beta2 6.4.1 6.4.1-beta3 6.4.1-beta4 6.4.1-beta5 6.4.1-beta6 6.4.1-beta7 6.4.2 6.5.0 6.5.1 6.5.2 6.5.3 6.5.4 6.5.5 6.5.6 6.5.7 6.6.0 6.7.0 6.7.1 6.8.0 6.8.1 6.8.2 6.8.3
secure-custom-fields / includes / fields / class-acf-field-gallery.php
secure-custom-fields / includes / fields Last commit date
FlexibleContent 8 months ago class-acf-field-accordion.php 1 year ago class-acf-field-button-group.php 8 months ago class-acf-field-checkbox.php 8 months ago class-acf-field-clone.php 6 months ago class-acf-field-color_picker.php 8 months ago class-acf-field-date_picker.php 10 months ago class-acf-field-date_time_picker.php 10 months ago class-acf-field-email.php 1 year ago class-acf-field-file.php 6 months ago class-acf-field-flexible-content.php 8 months ago class-acf-field-gallery.php 1 year ago class-acf-field-google-map.php 6 months ago class-acf-field-group.php 10 months ago class-acf-field-icon_picker.php 8 months ago class-acf-field-image.php 6 months ago class-acf-field-link.php 1 year ago class-acf-field-message.php 1 year ago class-acf-field-nav-menu.php 1 year ago class-acf-field-number.php 1 year ago class-acf-field-oembed.php 10 months ago class-acf-field-output.php 1 year ago class-acf-field-page_link.php 4 months ago class-acf-field-password.php 1 year ago class-acf-field-post_object.php 4 months ago class-acf-field-radio.php 8 months ago class-acf-field-range.php 1 year ago class-acf-field-relationship.php 4 months ago class-acf-field-repeater.php 8 months ago class-acf-field-select.php 1 year ago class-acf-field-separator.php 1 year ago class-acf-field-tab.php 1 year ago class-acf-field-taxonomy.php 8 months ago class-acf-field-text.php 1 year ago class-acf-field-textarea.php 1 year ago class-acf-field-time_picker.php 1 year ago class-acf-field-true_false.php 1 year ago class-acf-field-url.php 1 year ago class-acf-field-user.php 1 year ago class-acf-field-wysiwyg.php 1 year ago class-acf-field.php 10 months ago class-acf-repeater-table.php 1 year ago index.php 1 year ago
class-acf-field-gallery.php
924 lines
1 <?php
2 /**
3 * The Gallery Field.
4 *
5 * @package wordpress/secure-custom-fields
6 */
7
8 // phpcs:disable PEAR.NamingConventions.ValidClassName
9
10 if ( ! class_exists( 'acf_field_gallery' ) ) :
11
12 /**
13 * The Field Gallery class.
14 */
15 class acf_field_gallery extends acf_field {
16 /**
17 * This function will setup the field type data
18 *
19 * @type function
20 * @date 5/03/2014
21 * @since ACF 5.0.0
22 *
23 * @return void
24 */
25 public function initialize() {
26
27 // vars
28 $this->name = 'gallery';
29 $this->label = __( 'Gallery', 'secure-custom-fields' );
30 $this->category = 'content';
31 $this->description = __( 'An interactive interface for managing a collection of attachments, such as images.', 'secure-custom-fields' );
32 $this->preview_image = acf_get_url() . '/assets/images/field-type-previews/field-preview-gallery.png';
33 $this->doc_url = 'https://developer.wordpress.org/secure-custom-fields/features/fields/gallery/';
34 $this->tutorial_url = 'https://developer.wordpress.org/secure-custom-fields/features/fields/gallery/gallery-tutorial/';
35 $this->pro = true;
36 $this->supports = array( 'bindings' => false );
37 $this->defaults = array(
38 'return_format' => 'array',
39 'preview_size' => 'medium',
40 'insert' => 'append',
41 'library' => 'all',
42 'min' => 0,
43 'max' => 0,
44 'min_width' => 0,
45 'min_height' => 0,
46 'min_size' => 0,
47 'max_width' => 0,
48 'max_height' => 0,
49 'max_size' => 0,
50 'mime_types' => '',
51 );
52
53 // actions
54 add_action( 'wp_ajax_acf/fields/gallery/get_attachment', array( $this, 'ajax_get_attachment' ) );
55 add_action( 'wp_ajax_nopriv_acf/fields/gallery/get_attachment', array( $this, 'ajax_get_attachment' ) );
56
57 add_action( 'wp_ajax_acf/fields/gallery/update_attachment', array( $this, 'ajax_update_attachment' ) );
58 add_action( 'wp_ajax_nopriv_acf/fields/gallery/update_attachment', array( $this, 'ajax_update_attachment' ) );
59
60 add_action( 'wp_ajax_acf/fields/gallery/get_sort_order', array( $this, 'ajax_get_sort_order' ) );
61 add_action( 'wp_ajax_nopriv_acf/fields/gallery/get_sort_order', array( $this, 'ajax_get_sort_order' ) );
62 }
63
64 /**
65 * Enqueue admin scripts.
66 *
67 * @type function
68 * @date 16/12/2015
69 * @since ACF 5.3.2
70 */
71 public function input_admin_enqueue_scripts() {
72
73 // localize
74 acf_localize_text(
75 array(
76 'Add Image to Gallery' => __( 'Add Image to Gallery', 'secure-custom-fields' ),
77 'Maximum selection reached' => __( 'Maximum selection reached', 'secure-custom-fields' ),
78 )
79 );
80 }
81
82 /**
83 * AJAX handler for retrieving and rendering an attachment.
84 *
85 * @since ACF 5.0.0
86 *
87 * @return void
88 */
89 public function ajax_get_attachment() {
90 // Get args.
91 $args = acf_request_args(
92 array(
93 'id' => 0,
94 'field_key' => '',
95 'nonce' => '',
96 )
97 );
98
99 // Validate request.
100 if ( ! acf_verify_ajax( $args['nonce'], $args['field_key'] ) ) {
101 die();
102 }
103
104 // Cast args.
105 $args['id'] = (int) $args['id'];
106
107 // Bail early if no id.
108 if ( ! $args['id'] ) {
109 die();
110 }
111
112 // Load field.
113 $field = acf_get_field( $args['field_key'] );
114 if ( ! $field ) {
115 die();
116 }
117
118 // Render.
119 $this->render_attachment( $args['id'], $field );
120 die;
121 }
122
123 /**
124 * AJAX handler for updating an attachment.
125 *
126 * @since ACF 5.0.0
127 *
128 * @return void
129 */
130 public function ajax_update_attachment() {
131 $args = acf_request_args(
132 array(
133 'nonce' => '',
134 'field_key' => '',
135 )
136 );
137
138 if ( ! acf_verify_ajax( $args['nonce'], $args['field_key'] ) ) {
139 wp_send_json_error();
140 }
141
142 // bail early if no attachments
143 if ( empty( $_POST['attachments'] ) ) {
144 wp_send_json_error();
145 }
146
147 // loop over attachments
148 foreach ( wp_unslash( $_POST['attachments'] ) as $id => $changes ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized by WP core when saved.
149
150 if ( ! current_user_can( 'edit_post', $id ) ) {
151 wp_send_json_error();
152 }
153
154 $post = get_post( $id, ARRAY_A );
155
156 if ( 'attachment' !== $post['post_type'] ) {
157 wp_send_json_error();
158 }
159
160 if ( isset( $changes['title'] ) ) {
161 $post['post_title'] = $changes['title'];
162 }
163
164 if ( isset( $changes['caption'] ) ) {
165 $post['post_excerpt'] = $changes['caption'];
166 }
167
168 if ( isset( $changes['description'] ) ) {
169 $post['post_content'] = $changes['description'];
170 }
171
172 if ( isset( $changes['alt'] ) ) {
173 $alt = wp_unslash( $changes['alt'] );
174 if ( get_post_meta( $id, '_wp_attachment_image_alt', true ) !== $alt ) {
175 $alt = wp_strip_all_tags( $alt, true );
176 update_post_meta( $id, '_wp_attachment_image_alt', wp_slash( $alt ) );
177 }
178 }
179
180 // save post
181 wp_update_post( $post );
182
183 /** This filter is documented in wp-admin/includes/media.php */
184 // - seems off to run this filter AFTER the update_post function, but there is a reason
185 // - when placed BEFORE, an empty post_title will be populated by WP
186 // - this filter will still allow 3rd party to save extra image data!
187 $post = apply_filters( 'attachment_fields_to_save', $post, $changes );
188
189 // save meta
190 acf_save_post( $id );
191 }
192
193 // return
194 wp_send_json_success();
195 }
196
197 /**
198 * AJAX handler for getting the attachment sort order.
199 *
200 * @since ACF 5.0.0
201 *
202 * @return void
203 */
204 public function ajax_get_sort_order() {
205 $order = 'DESC';
206 $args = acf_parse_args(
207 $_POST, // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified below.
208 array(
209 'ids' => 0,
210 'sort' => 'date',
211 'field_key' => '',
212 'nonce' => '',
213 )
214 );
215
216 if ( ! acf_verify_ajax( $args['nonce'], $args['field_key'] ) ) {
217 wp_send_json_error();
218 }
219
220 // Reverse order.
221 if ( 'reverse' === $args['sort'] ) {
222 $ids = array_reverse( $args['ids'] );
223 wp_send_json_success( $ids );
224 }
225
226 // Ascending order.
227 if ( 'title' === $args['sort'] ) {
228 $order = 'ASC';
229 }
230
231 // Find attachments (DISTINCT POSTS).
232 $ids = get_posts(
233 array(
234 'post_type' => 'attachment',
235 'numberposts' => -1,
236 'post_status' => 'any',
237 'post__in' => $args['ids'],
238 'order' => $order,
239 'orderby' => $args['sort'],
240 'fields' => 'ids',
241 )
242 );
243
244 if ( ! empty( $ids ) ) {
245 wp_send_json_success( $ids );
246 }
247
248 wp_send_json_error();
249 }
250
251 /**
252 * Renders the sidebar HTML shown when selecting an attachment.
253 *
254 * @date 13/12/2013
255 * @since ACF 5.0.0
256 *
257 * @param integer $id The attachment ID.
258 * @param array $field The field array.
259 * @return void
260 */
261 public function render_attachment( $id, $field ) {
262 // Load attachment data.
263 $attachment = wp_prepare_attachment_for_js( $id );
264 $compat = get_compat_media_markup( $id );
265
266 // Get attachment thumbnail (video).
267 if ( isset( $attachment['thumb']['src'] ) ) {
268 $thumb = $attachment['thumb']['src'];
269
270 // Look for thumbnail size (image).
271 } elseif ( isset( $attachment['sizes']['thumbnail']['url'] ) ) {
272 $thumb = $attachment['sizes']['thumbnail']['url'];
273
274 // Use url for svg.
275 } elseif ( 'image' === $attachment['type'] ) {
276 $thumb = $attachment['url'];
277
278 // Default to icon.
279 } else {
280 $thumb = wp_mime_type_icon( $id );
281 }
282
283 // Get attachment dimensions / time / size.
284 $dimensions = '';
285 if ( 'audio' === $attachment['type'] ) {
286 $dimensions = __( 'Length', 'secure-custom-fields' ) . ': ' . $attachment['fileLength'];
287 } elseif ( ! empty( $attachment['width'] ) ) {
288 $dimensions = $attachment['width'] . ' x ' . $attachment['height'];
289 }
290 if ( ! empty( $attachment['filesizeHumanReadable'] ) ) {
291 $dimensions .= ' (' . $attachment['filesizeHumanReadable'] . ')';
292 }
293
294 ?>
295 <div class="acf-gallery-side-info">
296 <img src="<?php echo esc_url( $thumb ); ?>" alt="<?php echo esc_attr( $attachment['alt'] ); ?>" />
297 <p class="filename"><strong><?php echo esc_html( $attachment['filename'] ); ?></strong></p>
298 <p class="uploaded"><?php echo esc_html( $attachment['dateFormatted'] ); ?></p>
299 <p class="dimensions"><?php echo esc_html( $dimensions ); ?></p>
300 <p class="actions">
301 <a href="#" class="acf-gallery-edit" data-id="<?php echo esc_attr( $id ); ?>"><?php esc_html_e( 'Edit', 'secure-custom-fields' ); ?></a>
302 <a href="#" class="acf-gallery-remove" data-id="<?php echo esc_attr( $id ); ?>"><?php esc_html_e( 'Remove', 'secure-custom-fields' ); ?></a>
303 </p>
304 </div>
305 <table class="form-table">
306 <tbody>
307 <?php
308
309 // Render fields.
310 $prefix = 'attachments[' . $id . ']';
311
312 acf_render_field_wrap(
313 array(
314 'name' => 'title',
315 'prefix' => $prefix,
316 'type' => 'text',
317 'label' => __( 'Title', 'secure-custom-fields' ),
318 'value' => $attachment['title'],
319 ),
320 'tr'
321 );
322
323 acf_render_field_wrap(
324 array(
325 'name' => 'caption',
326 'prefix' => $prefix,
327 'type' => 'textarea',
328 'label' => __( 'Caption', 'secure-custom-fields' ),
329 'value' => $attachment['caption'],
330 ),
331 'tr'
332 );
333
334 acf_render_field_wrap(
335 array(
336 'name' => 'alt',
337 'prefix' => $prefix,
338 'type' => 'text',
339 'label' => __( 'Alt Text', 'secure-custom-fields' ),
340 'value' => $attachment['alt'],
341 ),
342 'tr'
343 );
344
345 acf_render_field_wrap(
346 array(
347 'name' => 'description',
348 'prefix' => $prefix,
349 'type' => 'textarea',
350 'label' => __( 'Description', 'secure-custom-fields' ),
351 'value' => $attachment['description'],
352 ),
353 'tr'
354 );
355
356 ?>
357 </tbody>
358 </table>
359 <?php
360
361 // Display compat fields.
362 echo $compat['item']; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- escaped inside get_compat_media_markup().
363 }
364
365 /**
366 * Creates the HTML interface for the gallery field.
367 *
368 * @param array $field The field array holding all the field's data.
369 *
370 * @type action
371 * @since ACF 3.6
372 * @date 23/01/13
373 * @return void
374 */
375 public function render_field( $field ) {
376
377 // Enqueue uploader assets.
378 acf_enqueue_uploader();
379
380 // Control attributes.
381 $attrs = array(
382 'id' => $field['id'],
383 'class' => "acf-gallery {$field['class']}",
384 'data-library' => $field['library'],
385 'data-preview_size' => $field['preview_size'],
386 'data-min' => $field['min'],
387 'data-max' => $field['max'],
388 'data-mime_types' => $field['mime_types'],
389 'data-insert' => $field['insert'],
390 'data-columns' => 4,
391 'data-nonce' => wp_create_nonce( $field['key'] ),
392 );
393
394 // Set gallery height with default of 400px and minimum of 200px.
395 $height = acf_get_user_setting( 'gallery_height', 400 );
396 $height = max( $height, 200 );
397 $attrs['style'] = "height:{$height}px";
398
399 // Load attachments.
400 $attachments = array();
401 if ( $field['value'] ) {
402
403 // Clean value into an array of IDs.
404 $attachment_ids = array_map( 'intval', acf_array( $field['value'] ) );
405
406 // Find posts in database (ensures all results are real).
407 $posts = acf_get_posts(
408 array(
409 'post_type' => 'attachment',
410 'post__in' => $attachment_ids,
411 'update_post_meta_cache' => true,
412 'update_post_term_cache' => false,
413 )
414 );
415
416 // Load attachment data for each post.
417 $attachments = array_map( 'acf_get_attachment', $posts );
418 }
419
420 ?>
421 <div <?php echo acf_esc_attrs( $attrs ); ?>>
422 <input type="hidden" name="<?php echo esc_attr( $field['name'] ); ?>" value="" />
423 <div class="acf-gallery-main">
424 <div class="acf-gallery-attachments">
425 <?php if ( $attachments ) : ?>
426 <?php
427 foreach ( $attachments as $i => $attachment ) :
428
429 // Vars
430 $a_id = $attachment['ID'];
431 $a_title = $attachment['title'];
432 $a_type = $attachment['type'];
433 $a_filename = $attachment['filename'];
434 $a_class = "acf-gallery-attachment -{$a_type}";
435
436 // Get thumbnail.
437 $a_thumbnail = acf_get_post_thumbnail( $a_id, $field['preview_size'] );
438 $a_class .= ( 'icon' === $a_thumbnail['type'] ) ? ' -icon' : '';
439
440 ?>
441 <div class="<?php echo esc_attr( $a_class ); ?>" data-id="<?php echo esc_attr( $a_id ); ?>">
442 <input type="hidden" name="<?php echo esc_attr( $field['name'] ); ?>[]" value="<?php echo esc_attr( $a_id ); ?>" />
443 <div class="margin">
444 <div class="thumbnail">
445 <img src="<?php echo esc_url( $a_thumbnail['url'] ); ?>" alt="" />
446 </div>
447 <?php if ( 'image' !== $a_type ) : ?>
448 <div class="filename"><?php echo acf_esc_html( acf_get_truncated( $a_filename, 30 ) ); ?></div>
449 <?php endif; ?>
450 </div>
451 <div class="actions">
452 <a class="acf-icon -cancel dark acf-gallery-remove" href="#" data-id="<?php echo esc_attr( $a_id ); ?>" title="<?php esc_html_e( 'Remove', 'secure-custom-fields' ); ?>"></a>
453 </div>
454 </div>
455 <?php endforeach; ?>
456 <?php endif; ?>
457 </div>
458 <div class="acf-gallery-toolbar">
459 <ul class="acf-hl">
460 <li>
461 <a href="#" class="acf-button button button-primary acf-gallery-add"><?php esc_html_e( 'Add to gallery', 'secure-custom-fields' ); ?></a>
462 </li>
463 <li class="acf-fr">
464 <select class="acf-gallery-sort">
465 <option value=""><?php esc_html_e( 'Bulk actions', 'secure-custom-fields' ); ?></option>
466 <option value="date"><?php esc_html_e( 'Sort by date uploaded', 'secure-custom-fields' ); ?></option>
467 <option value="modified"><?php esc_html_e( 'Sort by date modified', 'secure-custom-fields' ); ?></option>
468 <option value="title"><?php esc_html_e( 'Sort by title', 'secure-custom-fields' ); ?></option>
469 <option value="reverse"><?php esc_html_e( 'Reverse current order', 'secure-custom-fields' ); ?></option>
470 </select>
471 </li>
472 </ul>
473 </div>
474 </div>
475 <div class="acf-gallery-side">
476 <div class="acf-gallery-side-inner">
477 <div class="acf-gallery-side-data"></div>
478 <div class="acf-gallery-toolbar">
479 <ul class="acf-hl">
480 <li>
481 <a href="#" class="acf-button button acf-gallery-close"><?php esc_html_e( 'Close', 'secure-custom-fields' ); ?></a>
482 </li>
483 <li class="acf-fr">
484 <a class="acf-button button button-primary acf-gallery-update" href="#"><?php esc_html_e( 'Update', 'secure-custom-fields' ); ?></a>
485 </li>
486 </ul>
487 </div>
488 </div>
489 </div>
490 </div>
491 <?php
492 }
493
494
495 /**
496 * Create extra options for your field. This is rendered when editing a field.
497 * The value of $field['name'] can be used (like bellow) to save extra data to the $field
498 *
499 * @type action
500 * @since ACF 3.6
501 * @date 23/01/13
502 *
503 * @param array $field an array holding all the field's data.
504 */
505 public function render_field_settings( $field ) {
506 acf_render_field_setting(
507 $field,
508 array(
509 'label' => __( 'Return Format', 'secure-custom-fields' ),
510 'instructions' => '',
511 'type' => 'radio',
512 'name' => 'return_format',
513 'layout' => 'horizontal',
514 'choices' => array(
515 'array' => __( 'Image Array', 'secure-custom-fields' ),
516 'url' => __( 'Image URL', 'secure-custom-fields' ),
517 'id' => __( 'Image ID', 'secure-custom-fields' ),
518 ),
519 )
520 );
521
522 acf_render_field_setting(
523 $field,
524 array(
525 'label' => __( 'Library', 'secure-custom-fields' ),
526 'instructions' => __( 'Limit the media library choice', 'secure-custom-fields' ),
527 'type' => 'radio',
528 'name' => 'library',
529 'layout' => 'horizontal',
530 'choices' => array(
531 'all' => __( 'All', 'secure-custom-fields' ),
532 'uploadedTo' => __( 'Uploaded to post', 'secure-custom-fields' ),
533 ),
534 )
535 );
536 }
537
538 /**
539 * Renders the field settings used in the "Validation" tab.
540 *
541 * @since ACF 6.0
542 *
543 * @param array $field The field settings array.
544 * @return void
545 */
546 public function render_field_validation_settings( $field ) {
547 // Clear numeric settings.
548 $clear = array(
549 'min',
550 'max',
551 'min_width',
552 'min_height',
553 'min_size',
554 'max_width',
555 'max_height',
556 'max_size',
557 );
558
559 foreach ( $clear as $k ) {
560 if ( empty( $field[ $k ] ) ) {
561 $field[ $k ] = '';
562 }
563 }
564
565 acf_render_field_setting(
566 $field,
567 array(
568 'label' => __( 'Minimum Selection', 'secure-custom-fields' ),
569 'instructions' => '',
570 'type' => 'number',
571 'name' => 'min',
572 )
573 );
574
575 acf_render_field_setting(
576 $field,
577 array(
578 'label' => __( 'Maximum Selection', 'secure-custom-fields' ),
579 'instructions' => '',
580 'type' => 'number',
581 'name' => 'max',
582 )
583 );
584
585 acf_render_field_setting(
586 $field,
587 array(
588 'label' => __( 'Minimum', 'secure-custom-fields' ),
589 'hint' => __( 'Restrict which images can be uploaded', 'secure-custom-fields' ),
590 'type' => 'text',
591 'name' => 'min_width',
592 'prepend' => __( 'Width', 'secure-custom-fields' ),
593 'append' => 'px',
594 )
595 );
596
597 acf_render_field_setting(
598 $field,
599 array(
600 'label' => '',
601 'type' => 'text',
602 'name' => 'min_height',
603 'prepend' => __( 'Height', 'secure-custom-fields' ),
604 'append' => 'px',
605 '_append' => 'min_width',
606 )
607 );
608
609 acf_render_field_setting(
610 $field,
611 array(
612 'label' => '',
613 'type' => 'text',
614 'name' => 'min_size',
615 'prepend' => __( 'File size', 'secure-custom-fields' ),
616 'append' => 'MB',
617 '_append' => 'min_width',
618 )
619 );
620
621 acf_render_field_setting(
622 $field,
623 array(
624 'label' => __( 'Maximum', 'secure-custom-fields' ),
625 'hint' => __( 'Restrict which images can be uploaded', 'secure-custom-fields' ),
626 'type' => 'text',
627 'name' => 'max_width',
628 'prepend' => __( 'Width', 'secure-custom-fields' ),
629 'append' => 'px',
630 )
631 );
632
633 acf_render_field_setting(
634 $field,
635 array(
636 'label' => '',
637 'type' => 'text',
638 'name' => 'max_height',
639 'prepend' => __( 'Height', 'secure-custom-fields' ),
640 'append' => 'px',
641 '_append' => 'max_width',
642 )
643 );
644
645 acf_render_field_setting(
646 $field,
647 array(
648 'label' => '',
649 'type' => 'text',
650 'name' => 'max_size',
651 'prepend' => __( 'File size', 'secure-custom-fields' ),
652 'append' => 'MB',
653 '_append' => 'max_width',
654 )
655 );
656
657 acf_render_field_setting(
658 $field,
659 array(
660 'label' => __( 'Allowed File Types', 'secure-custom-fields' ),
661 'hint' => __( 'Comma separated list. Leave blank for all types', 'secure-custom-fields' ),
662 'type' => 'text',
663 'name' => 'mime_types',
664 )
665 );
666 }
667
668 /**
669 * Renders the field settings used in the "Presentation" tab.
670 *
671 * @since ACF 6.0
672 *
673 * @param array $field The field settings array.
674 * @return void
675 */
676 public function render_field_presentation_settings( $field ) {
677 acf_render_field_setting(
678 $field,
679 array(
680 'label' => __( 'Insert', 'secure-custom-fields' ),
681 'instructions' => __( 'Specify where new attachments are added', 'secure-custom-fields' ),
682 'type' => 'select',
683 'name' => 'insert',
684 'choices' => array(
685 'append' => __( 'Append to the end', 'secure-custom-fields' ),
686 'prepend' => __( 'Prepend to the beginning', 'secure-custom-fields' ),
687 ),
688 )
689 );
690
691 acf_render_field_setting(
692 $field,
693 array(
694 'label' => __( 'Preview Size', 'secure-custom-fields' ),
695 'instructions' => '',
696 'type' => 'select',
697 'name' => 'preview_size',
698 'choices' => acf_get_image_sizes(),
699 )
700 );
701 }
702
703 /**
704 * Filters the value after it is loaded from the database and before it is returned to the template.
705 *
706 * @type filter
707 * @since ACF 3.6
708 * @date 23/01/13
709 *
710 * @param mixed $value The value which was loaded from the database.
711 * @param mixed $post_id The post ID from which the value was loaded.
712 * @param array $field The field array holding all the field options.
713 *
714 * @return mixed The modified value.
715 */
716 public function format_value( $value, $post_id, $field ) {
717
718 // Bail early if no value.
719 if ( ! $value ) {
720 return false;
721 }
722
723 // Clean value into an array of IDs.
724 $attachment_ids = array_map( 'intval', acf_array( $value ) );
725
726 // Find posts in database (ensures all results are real).
727 $posts = acf_get_posts(
728 array(
729 'post_type' => 'attachment',
730 'post__in' => $attachment_ids,
731 'update_post_meta_cache' => true,
732 'update_post_term_cache' => false,
733 )
734 );
735
736 // Bail early if no posts found.
737 if ( ! $posts ) {
738 return false;
739 }
740
741 // Format values using field settings.
742 $value = array();
743 foreach ( $posts as $post ) {
744 switch ( $field['return_format'] ) {
745 case 'object':
746 $item = $post;
747 break;
748 case 'array':
749 $item = acf_get_attachment( $post );
750 break;
751 case 'url':
752 $item = wp_get_attachment_url( $post->ID );
753 break;
754 default:
755 $item = $post->ID;
756 }
757
758 // Append item.
759 $value[] = $item;
760 }
761
762 // Return.
763 return $value;
764 }
765
766
767 /**
768 * Validates the value for this field.
769 *
770 * @type function
771 * @date 11/02/2014
772 * @since ACF 5.0.0
773 *
774 * @param bool $valid Whether the value is valid.
775 * @param mixed $value The field value.
776 * @param array $field The field array.
777 * @param string $input The input element's name attribute.
778 * @return bool|string True if valid, error message if not.
779 */
780 public function validate_value( $valid, $value, $field, $input ) {
781
782 if ( empty( $value ) || ! is_array( $value ) ) {
783 $value = array();
784 }
785
786 if ( count( $value ) < $field['min'] ) {
787 /* translators: 1: field label, 2: minimum number of selections */
788 $valid = _n( '%1$s requires at least %2$s selection', '%1$s requires at least %2$s selections', $field['min'], 'secure-custom-fields' );
789 $valid = sprintf( $valid, $field['label'], $field['min'] );
790 }
791
792 return $valid;
793 }
794
795
796 /**
797 * This filter is applied to the $value before it is updated in the db
798 *
799 * @type filter
800 * @since ACF 3.6
801 * @date 23/01/13
802 *
803 * @param mixed $value The value which will be saved in the database.
804 * @param mixed $post_id The post_id of which the value will be saved.
805 * @param array $field The field array holding all the field options.
806 *
807 * @return $value - the modified value
808 */
809 public function update_value( $value, $post_id, $field ) {
810
811 // Bail early if no value.
812 if ( empty( $value ) ) {
813 return $value;
814 }
815
816 // Convert to array.
817 $value = acf_array( $value );
818
819 // Format array of values.
820 // - ensure each value is an id.
821 // - Parse each id as string for SQL LIKE queries.
822 $value = array_map( 'acf_idval', $value );
823 $value = array_map( 'strval', $value );
824
825 // Return value.
826 return $value;
827 }
828
829 /**
830 * Validates file fields updated via the REST API.
831 *
832 * @param boolean $valid The current validity boolean.
833 * @param integer $value The value of the field.
834 * @param array $field The field array.
835 * @return boolean|WP
836 */
837 public function validate_rest_value( $valid, $value, $field ) {
838 if ( ! $valid || ! is_array( $value ) ) {
839 return $valid;
840 }
841
842 foreach ( $value as $attachment_id ) {
843 $file_valid = acf_get_field_type( 'file' )->validate_rest_value( $valid, $attachment_id, $field );
844
845 if ( is_wp_error( $file_valid ) ) {
846 return $file_valid;
847 }
848 }
849
850 return $valid;
851 }
852
853 /**
854 * Return the schema array for the REST API.
855 *
856 * @param array $field The field array.
857 * @return array
858 */
859 public function get_rest_schema( array $field ) {
860 $schema = array(
861 'type' => array( 'array', 'null' ),
862 'required' => ! empty( $field['required'] ),
863 'items' => array(
864 'type' => 'number',
865 ),
866 );
867
868 if ( ! empty( $field['min'] ) ) {
869 $schema['minItems'] = (int) $field['min'];
870 }
871
872 if ( ! empty( $field['max'] ) ) {
873 $schema['maxItems'] = (int) $field['max'];
874 }
875
876 return $schema;
877 }
878
879 /**
880 * Returns an array of links for this field's value.
881 *
882 * @see \acf_field::get_rest_links()
883 * @param mixed $value The raw (unformatted) field value.
884 * @param integer|string $post_id The post ID.
885 * @param array $field The field array.
886 * @return array
887 */
888 public function get_rest_links( $value, $post_id, array $field ) {
889 $links = array();
890
891 if ( empty( $value ) ) {
892 return $links;
893 }
894
895 foreach ( (array) $value as $object_id ) {
896 $links[] = array(
897 'rel' => 'acf:attachment',
898 'href' => rest_url( '/wp/v2/media/' . $object_id ),
899 'embeddable' => true,
900 );
901 }
902
903 return $links;
904 }
905
906 /**
907 * Apply basic formatting to prepare the value for default REST output.
908 *
909 * @param mixed $value The field value.
910 * @param string|integer $post_id The post ID.
911 * @param array $field The field array.
912 * @return mixed
913 */
914 public function format_value_for_rest( $value, $post_id, array $field ) {
915 return acf_format_numerics( $value );
916 }
917 }
918
919
920 // initialize
921 acf_register_field_type( 'acf_field_gallery' );
922 endif; // class_exists check
923
924 ?>