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