PluginProbe ʕ •ᴥ•ʔ
Secure Custom Fields / 6.4.0-beta2
Secure Custom Fields v6.4.0-beta2
6.9.5 6.9.4 6.9.3 6.9.2 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-relationship.php
secure-custom-fields / includes / fields Last commit date
class-acf-field-accordion.php 1 year ago class-acf-field-button-group.php 1 year ago class-acf-field-checkbox.php 1 year ago class-acf-field-color_picker.php 1 year ago class-acf-field-date_picker.php 1 year ago class-acf-field-date_time_picker.php 1 year ago class-acf-field-email.php 1 year ago class-acf-field-file.php 1 year ago class-acf-field-google-map.php 1 year ago class-acf-field-group.php 1 year ago class-acf-field-icon_picker.php 1 year ago class-acf-field-image.php 1 year ago class-acf-field-link.php 1 year ago class-acf-field-message.php 1 year ago class-acf-field-number.php 1 year ago class-acf-field-oembed.php 1 year ago class-acf-field-output.php 1 year ago class-acf-field-page_link.php 1 year ago class-acf-field-password.php 1 year ago class-acf-field-post_object.php 1 year ago class-acf-field-radio.php 1 year ago class-acf-field-range.php 1 year ago class-acf-field-relationship.php 1 year 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 1 year 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 1 year ago index.php 1 year ago
class-acf-field-relationship.php
889 lines
1 <?php
2
3 if ( ! class_exists( 'acf_field_relationship' ) ) :
4
5 class acf_field_relationship extends acf_field {
6
7
8 /**
9 * This function will setup the field type data
10 *
11 * @type function
12 * @date 5/03/2014
13 * @since 5.0.0
14 */
15 public function initialize() {
16 $this->name = 'relationship';
17 $this->label = __( 'Relationship', 'acf' );
18 $this->category = 'relational';
19 $this->description = __( 'A dual-column interface to select one or more posts, pages, or custom post type items to create a relationship with the item that you\'re currently editing. Includes options to search and filter.', 'acf' );
20 $this->preview_image = acf_get_url() . '/assets/images/field-type-previews/field-preview-relationship.png';
21 $this->doc_url = 'https://www.advancedcustomfields.com/resources/relationship/';
22 $this->defaults = array(
23 'post_type' => array(),
24 'taxonomy' => array(),
25 'min' => 0,
26 'max' => 0,
27 'filters' => array( 'search', 'post_type', 'taxonomy' ),
28 'elements' => array(),
29 'return_format' => 'object',
30 'bidirectional_target' => array(),
31 );
32 add_filter( 'acf/conditional_logic/choices', array( $this, 'render_field_relation_conditional_choices' ), 10, 3 );
33
34 // extra
35 add_action( 'wp_ajax_acf/fields/relationship/query', array( $this, 'ajax_query' ) );
36 add_action( 'wp_ajax_nopriv_acf/fields/relationship/query', array( $this, 'ajax_query' ) );
37 }
38
39 /**
40 * Filters choices in relation conditions.
41 *
42 * @since 6.3
43 *
44 * @param array $choices The selected choice.
45 * @param array $conditional_field The conditional field settings object.
46 * @param string $rule_value The rule value.
47 * @return array
48 */
49 public function render_field_relation_conditional_choices( $choices, $conditional_field, $rule_value ) {
50 if ( ! is_array( $conditional_field ) || $conditional_field['type'] !== 'relationship' ) {
51 return $choices;
52 }
53 if ( ! empty( $rule_value ) ) {
54 $post_title = get_the_title( $rule_value );
55 $choices = array( $rule_value => $post_title );
56 }
57 return $choices;
58 }
59
60 /**
61 * description
62 *
63 * @type function
64 * @date 16/12/2015
65 * @since 5.3.2
66 *
67 * @param $post_id (int)
68 * @return $post_id (int)
69 */
70 function input_admin_enqueue_scripts() {
71
72 // localize
73 acf_localize_text(
74 array(
75 // 'Minimum values reached ( {min} values )' => __('Minimum values reached ( {min} values )', 'acf'),
76 'Maximum values reached ( {max} values )' => __( 'Maximum values reached ( {max} values )', 'acf' ),
77 'Loading' => __( 'Loading', 'acf' ),
78 'No matches found' => __( 'No matches found', 'acf' ),
79 )
80 );
81 }
82
83 /**
84 * Returns AJAX results for the Relationship field.
85 *
86 * @since 5.0.0
87 *
88 * @return void
89 */
90 public function ajax_query() {
91 $nonce = acf_request_arg( 'nonce', '' );
92 $key = acf_request_arg( 'field_key', '' );
93 $conditional_logic = (bool) acf_request_arg( 'conditional_logic', false );
94
95 if ( $conditional_logic ) {
96 if ( ! acf_current_user_can_admin() ) {
97 die();
98 }
99
100 // Use the standard ACF admin nonce.
101 $nonce = '';
102 $key = '';
103 }
104
105 if ( ! acf_verify_ajax( $nonce, $key ) ) {
106 die();
107 }
108
109 acf_send_ajax_results( $this->get_ajax_query( $_POST ) );
110 }
111
112 /**
113 * This function will return an array of data formatted for use in a select2 AJAX response
114 *
115 * @since 5.0.9
116 *
117 * @param array $options An array of options for the query.
118 * @return array
119 */
120 public function get_ajax_query( $options = array() ) {
121 // defaults
122 $options = wp_parse_args(
123 $options,
124 array(
125 'post_id' => 0,
126 's' => '',
127 'field_key' => '',
128 'paged' => 1,
129 'post_type' => '',
130 'include' => '',
131 'taxonomy' => '',
132 )
133 );
134
135 // load field
136 $field = acf_get_field( $options['field_key'] );
137 if ( ! $field ) {
138 return false;
139 }
140
141 // vars
142 $results = array();
143 $args = array();
144 $s = false;
145 $is_search = false;
146
147 // paged
148 $args['posts_per_page'] = 20;
149 $args['paged'] = intval( $options['paged'] );
150
151 // search
152 if ( $options['s'] !== '' && empty( $options['include'] ) ) {
153 // strip slashes (search may be integer)
154 $s = wp_unslash( strval( $options['s'] ) );
155
156 // update vars
157 $args['s'] = $s;
158 $is_search = true;
159 }
160
161 // post_type
162 if ( ! empty( $options['post_type'] ) ) {
163 $args['post_type'] = acf_get_array( $options['post_type'] );
164 } elseif ( ! empty( $field['post_type'] ) ) {
165 $args['post_type'] = acf_get_array( $field['post_type'] );
166 } else {
167 $args['post_type'] = acf_get_post_types();
168 }
169
170 // post status
171 if ( ! empty( $options['post_status'] ) ) {
172 $args['post_status'] = acf_get_array( $options['post_status'] );
173 } elseif ( ! empty( $field['post_status'] ) ) {
174 $args['post_status'] = acf_get_array( $field['post_status'] );
175 }
176
177 // taxonomy
178 if ( ! empty( $options['taxonomy'] ) ) {
179
180 // vars
181 $term = acf_decode_taxonomy_term( $options['taxonomy'] );
182
183 // tax query
184 $args['tax_query'] = array();
185
186 // append
187 $args['tax_query'][] = array(
188 'taxonomy' => $term['taxonomy'],
189 'field' => 'slug',
190 'terms' => $term['term'],
191 );
192 } elseif ( ! empty( $field['taxonomy'] ) ) {
193
194 // vars
195 $terms = acf_decode_taxonomy_terms( $field['taxonomy'] );
196
197 // append to $args
198 $args['tax_query'] = array(
199 'relation' => 'OR',
200 );
201
202 // now create the tax queries
203 foreach ( $terms as $k => $v ) {
204 $args['tax_query'][] = array(
205 'taxonomy' => $k,
206 'field' => 'slug',
207 'terms' => $v,
208 );
209 }
210 }
211
212 if ( ! empty( $options['include'] ) ) {
213 // If we have an include, we need to return only the selected posts.
214 $args['post__in'] = array( $options['include'] );
215 }
216
217 // filters
218 $args = apply_filters( 'acf/fields/relationship/query', $args, $field, $options['post_id'] );
219 $args = apply_filters( 'acf/fields/relationship/query/name=' . $field['name'], $args, $field, $options['post_id'] );
220 $args = apply_filters( 'acf/fields/relationship/query/key=' . $field['key'], $args, $field, $options['post_id'] );
221
222 // get posts grouped by post type
223 $groups = acf_get_grouped_posts( $args );
224
225 // bail early if no posts
226 if ( empty( $groups ) ) {
227 return false;
228 }
229
230 // loop
231 foreach ( array_keys( $groups ) as $group_title ) {
232
233 // vars
234 $posts = acf_extract_var( $groups, $group_title );
235
236 // data
237 $data = array(
238 'text' => $group_title,
239 'children' => array(),
240 );
241
242 // convert post objects to post titles
243 foreach ( array_keys( $posts ) as $post_id ) {
244 $posts[ $post_id ] = $this->get_post_title( $posts[ $post_id ], $field, $options['post_id'] );
245 }
246
247 // order posts by search
248 if ( $is_search && empty( $args['orderby'] ) && isset( $args['s'] ) ) {
249 $posts = acf_order_by_search( $posts, $args['s'] );
250 }
251
252 // append to $data
253 foreach ( array_keys( $posts ) as $post_id ) {
254 $data['children'][] = $this->get_post_result( $post_id, $posts[ $post_id ] );
255 }
256
257 // append to $results
258 $results[] = $data;
259 }
260
261 // add as optgroup or results
262 if ( count( $args['post_type'] ) == 1 ) {
263 $results = $results[0]['children'];
264 }
265
266 // vars
267 $response = array(
268 'results' => $results,
269 'limit' => $args['posts_per_page'],
270 );
271
272 // return
273 return $response;
274 }
275
276 /**
277 * This function will return an array containing id, text and maybe description data
278 *
279 * @type function
280 * @date 7/07/2016
281 * @since 5.4.0
282 *
283 * @param $id (mixed)
284 * @param $text (string)
285 * @return (array)
286 */
287 function get_post_result( $id, $text ) {
288
289 // vars
290 $result = array(
291 'id' => $id,
292 'text' => $text,
293 );
294
295 // return
296 return $result;
297 }
298
299
300 /**
301 * This function returns the HTML for a result
302 *
303 * @type function
304 * @date 1/11/2013
305 * @since 5.0.0
306 *
307 * @param $post (object)
308 * @param $field (array)
309 * @param $post_id (int) the post_id to which this value is saved to
310 * @return (string)
311 */
312 function get_post_title( $post, $field, $post_id = 0, $is_search = 0 ) {
313
314 // get post_id
315 if ( ! $post_id ) {
316 $post_id = acf_get_form_data( 'post_id' );
317 }
318
319 // vars
320 $title = acf_get_post_title( $post, $is_search );
321
322 // featured_image
323 if ( acf_in_array( 'featured_image', $field['elements'] ) ) {
324
325 // vars
326 $class = 'thumbnail';
327 $thumbnail = acf_get_post_thumbnail( $post->ID, array( 17, 17 ) );
328
329 // icon
330 if ( $thumbnail['type'] == 'icon' ) {
331 $class .= ' -' . $thumbnail['type'];
332 }
333
334 // append
335 $title = '<div class="' . $class . '">' . $thumbnail['html'] . '</div>' . $title;
336 }
337
338 // filters
339 $title = apply_filters( 'acf/fields/relationship/result', $title, $post, $field, $post_id );
340 $title = apply_filters( 'acf/fields/relationship/result/name=' . $field['_name'], $title, $post, $field, $post_id );
341 $title = apply_filters( 'acf/fields/relationship/result/key=' . $field['key'], $title, $post, $field, $post_id );
342
343 // return
344 return $title;
345 }
346
347
348 /**
349 * Create the HTML interface for your field
350 *
351 * @param $field - an array holding all the field's data
352 *
353 * @type action
354 * @since 3.6
355 * @date 23/01/13
356 */
357 function render_field( $field ) {
358
359 // vars
360 $post_type = acf_get_array( $field['post_type'] );
361 $taxonomy = acf_get_array( $field['taxonomy'] );
362 $filters = acf_get_array( $field['filters'] );
363
364 // filters
365 $filter_count = count( $filters );
366 $filter_post_type_choices = array();
367 $filter_taxonomy_choices = array();
368
369 // post_type filter
370 if ( in_array( 'post_type', $filters ) ) {
371 $filter_post_type_choices = array(
372 '' => __( 'Select post type', 'acf' ),
373 ) + acf_get_pretty_post_types( $post_type );
374 }
375
376 // taxonomy filter
377 if ( in_array( 'taxonomy', $filters ) ) {
378 $term_choices = array();
379 $filter_taxonomy_choices = array(
380 '' => __( 'Select taxonomy', 'acf' ),
381 );
382
383 // check for specific taxonomy setting
384 if ( $taxonomy ) {
385 $terms = acf_get_encoded_terms( $taxonomy );
386 $term_choices = acf_get_choices_from_terms( $terms, 'slug' );
387
388 // if no terms were specified, find all terms
389 } else {
390
391 // restrict taxonomies by the post_type selected
392 $term_args = array();
393 if ( $post_type ) {
394 $term_args['taxonomy'] = acf_get_taxonomies(
395 array(
396 'post_type' => $post_type,
397 )
398 );
399 }
400
401 // get terms
402 $terms = acf_get_grouped_terms( $term_args );
403 $term_choices = acf_get_choices_from_grouped_terms( $terms, 'slug' );
404 }
405
406 // append term choices
407 $filter_taxonomy_choices = $filter_taxonomy_choices + $term_choices;
408 }
409
410 // div attributes
411 $atts = array(
412 'id' => $field['id'],
413 'class' => "acf-relationship {$field['class']}",
414 'data-min' => $field['min'],
415 'data-max' => $field['max'],
416 'data-s' => '',
417 'data-paged' => 1,
418 'data-post_type' => '',
419 'data-taxonomy' => '',
420 'data-nonce' => wp_create_nonce( $field['key'] ),
421 );
422
423 ?>
424 <div <?php echo acf_esc_attrs( $atts ); ?>>
425
426 <?php
427 acf_hidden_input(
428 array(
429 'name' => $field['name'],
430 'value' => '',
431 )
432 );
433 ?>
434
435 <?php
436
437 /* filters */
438 if ( $filter_count ) :
439 ?>
440 <div class="filters -f<?php echo esc_attr( $filter_count ); ?>">
441 <?php
442
443 /* search */
444 if ( in_array( 'search', $filters ) ) :
445 ?>
446 <div class="filter -search">
447 <?php
448 acf_text_input(
449 array(
450 'placeholder' => __( 'Search...', 'acf' ),
451 'data-filter' => 's',
452 )
453 );
454 ?>
455 </div>
456 <?php
457 endif;
458
459 /* post_type */
460 if ( in_array( 'post_type', $filters ) ) :
461 ?>
462 <div class="filter -post_type">
463 <?php
464 acf_select_input(
465 array(
466 'choices' => $filter_post_type_choices,
467 'data-filter' => 'post_type',
468 )
469 );
470 ?>
471 </div>
472 <?php
473 endif;
474
475 /* post_type */
476 if ( in_array( 'taxonomy', $filters ) ) :
477 ?>
478 <div class="filter -taxonomy">
479 <?php
480 acf_select_input(
481 array(
482 'choices' => $filter_taxonomy_choices,
483 'data-filter' => 'taxonomy',
484 )
485 );
486 ?>
487 </div>
488 <?php endif; ?>
489 </div>
490 <?php endif; ?>
491
492 <div class="selection">
493 <div class="choices">
494 <ul class="acf-bl list choices-list"></ul>
495 </div>
496 <div class="values">
497 <ul class="acf-bl list values-list">
498 <?php
499 if ( ! empty( $field['value'] ) ) :
500
501 // get posts
502 $posts = acf_get_posts(
503 array(
504 'post__in' => $field['value'],
505 'post_type' => $field['post_type'],
506 )
507 );
508
509 // loop
510 foreach ( $posts as $post ) :
511 ?>
512 <li>
513 <?php
514 acf_hidden_input(
515 array(
516 'name' => $field['name'] . '[]',
517 'value' => $post->ID,
518 )
519 );
520 ?>
521 <span tabindex="0" data-id="<?php echo esc_attr( $post->ID ); ?>" class="acf-rel-item acf-rel-item-remove">
522 <?php echo acf_esc_html( $this->get_post_title( $post, $field ) ); ?>
523 <a href="#" class="acf-icon -minus small dark" data-name="remove_item"></a>
524 </span>
525 </li>
526 <?php endforeach; ?>
527 <?php endif; ?>
528 </ul>
529 </div>
530 </div>
531 </div>
532 <?php
533 }
534
535
536 /**
537 * Create extra options for your field. This is rendered when editing a field.
538 * The value of $field['name'] can be used (like bellow) to save extra data to the $field
539 *
540 * @type action
541 * @since 3.6
542 * @date 23/01/13
543 *
544 * @param $field - an array holding all the field's data
545 */
546 function render_field_settings( $field ) {
547 acf_render_field_setting(
548 $field,
549 array(
550 'label' => __( 'Filter by Post Type', 'acf' ),
551 'instructions' => '',
552 'type' => 'select',
553 'name' => 'post_type',
554 'choices' => acf_get_pretty_post_types(),
555 'multiple' => 1,
556 'ui' => 1,
557 'allow_null' => 1,
558 'placeholder' => __( 'All post types', 'acf' ),
559 )
560 );
561
562 acf_render_field_setting(
563 $field,
564 array(
565 'label' => __( 'Filter by Post Status', 'acf' ),
566 'instructions' => '',
567 'type' => 'select',
568 'name' => 'post_status',
569 'choices' => acf_get_pretty_post_statuses(),
570 'multiple' => 1,
571 'ui' => 1,
572 'allow_null' => 1,
573 'placeholder' => __( 'Any post status', 'acf' ),
574 )
575 );
576
577 acf_render_field_setting(
578 $field,
579 array(
580 'label' => __( 'Filter by Taxonomy', 'acf' ),
581 'instructions' => '',
582 'type' => 'select',
583 'name' => 'taxonomy',
584 'choices' => acf_get_taxonomy_terms(),
585 'multiple' => 1,
586 'ui' => 1,
587 'allow_null' => 1,
588 'placeholder' => __( 'All taxonomies', 'acf' ),
589 )
590 );
591
592 acf_render_field_setting(
593 $field,
594 array(
595 'label' => __( 'Filters', 'acf' ),
596 'instructions' => '',
597 'type' => 'checkbox',
598 'name' => 'filters',
599 'choices' => array(
600 'search' => __( 'Search', 'acf' ),
601 'post_type' => __( 'Post Type', 'acf' ),
602 'taxonomy' => __( 'Taxonomy', 'acf' ),
603 ),
604 )
605 );
606
607 acf_render_field_setting(
608 $field,
609 array(
610 'label' => __( 'Return Format', 'acf' ),
611 'instructions' => '',
612 'type' => 'radio',
613 'name' => 'return_format',
614 'choices' => array(
615 'object' => __( 'Post Object', 'acf' ),
616 'id' => __( 'Post ID', 'acf' ),
617 ),
618 'layout' => 'horizontal',
619 )
620 );
621 }
622
623 /**
624 * Renders the field settings used in the "Validation" tab.
625 *
626 * @since 6.0
627 *
628 * @param array $field The field settings array.
629 * @return void
630 */
631 function render_field_validation_settings( $field ) {
632 $field['min'] = empty( $field['min'] ) ? '' : $field['min'];
633 $field['max'] = empty( $field['max'] ) ? '' : $field['max'];
634
635 acf_render_field_setting(
636 $field,
637 array(
638 'label' => __( 'Minimum Posts', 'acf' ),
639 'instructions' => '',
640 'type' => 'number',
641 'name' => 'min',
642 )
643 );
644
645 acf_render_field_setting(
646 $field,
647 array(
648 'label' => __( 'Maximum Posts', 'acf' ),
649 'instructions' => '',
650 'type' => 'number',
651 'name' => 'max',
652 )
653 );
654 }
655
656 /**
657 * Renders the field settings used in the "Presentation" tab.
658 *
659 * @since 6.0
660 *
661 * @param array $field The field settings array.
662 * @return void
663 */
664 function render_field_presentation_settings( $field ) {
665 acf_render_field_setting(
666 $field,
667 array(
668 'label' => __( 'Elements', 'acf' ),
669 'instructions' => __( 'Selected elements will be displayed in each result', 'acf' ),
670 'type' => 'checkbox',
671 'name' => 'elements',
672 'choices' => array(
673 'featured_image' => __( 'Featured Image', 'acf' ),
674 ),
675 )
676 );
677 }
678
679 /**
680 * Renders the field settings used in the "Advanced" tab.
681 *
682 * @since 6.2
683 *
684 * @param array $field The field settings array.
685 * @return void
686 */
687 public function render_field_advanced_settings( $field ) {
688 acf_render_bidirectional_field_settings( $field );
689 }
690
691 /**
692 * This filter is applied to the $value after it is loaded from the db and before it is returned to the template
693 *
694 * @type filter
695 * @since 3.6
696 * @date 23/01/13
697 *
698 * @param $value (mixed) the value which was loaded from the database
699 * @param $post_id (mixed) the post_id from which the value was loaded
700 * @param $field (array) the field array holding all the field options
701 *
702 * @return $value (mixed) the modified value
703 */
704 function format_value( $value, $post_id, $field ) {
705
706 // bail early if no value
707 if ( empty( $value ) ) {
708 return $value;
709 }
710
711 // force value to array
712 $value = acf_get_array( $value );
713
714 // convert to int
715 $value = array_map( 'intval', $value );
716
717 // load posts if needed
718 if ( $field['return_format'] == 'object' ) {
719
720 // get posts
721 $value = acf_get_posts(
722 array(
723 'post__in' => $value,
724 'post_type' => $field['post_type'],
725 )
726 );
727 }
728
729 // return
730 return $value;
731 }
732
733
734 /**
735 * description
736 *
737 * @type function
738 * @date 11/02/2014
739 * @since 5.0.0
740 *
741 * @param $post_id (int)
742 * @return $post_id (int)
743 */
744 function validate_value( $valid, $value, $field, $input ) {
745
746 // default
747 if ( empty( $value ) || ! is_array( $value ) ) {
748 $value = array();
749 }
750
751 // min
752 if ( count( $value ) < $field['min'] ) {
753 $valid = _n( '%1$s requires at least %2$s selection', '%1$s requires at least %2$s selections', $field['min'], 'acf' );
754 $valid = sprintf( $valid, $field['label'], $field['min'] );
755 }
756
757 // return
758 return $valid;
759 }
760
761
762 /**
763 * Filters the field value before it is saved into the database.
764 *
765 * @since 3.6
766 *
767 * @param mixed $value The value which will be saved in the database.
768 * @param integer $post_id The post_id of which the value will be saved.
769 * @param array $field The field array holding all the field options.
770 *
771 * @return mixed $value The modified value.
772 */
773 public function update_value( $value, $post_id, $field ) {
774
775 // Bail early if no value.
776 if ( empty( $value ) ) {
777 acf_update_bidirectional_values( array(), $post_id, $field );
778 return $value;
779 }
780
781 // Format array of values.
782 // - ensure each value is an id.
783 // - Parse each id as string for SQL LIKE queries.
784 if ( acf_is_sequential_array( $value ) ) {
785 $value = array_map( 'acf_idval', $value );
786 $value = array_map( 'strval', $value );
787
788 // Parse single value for id.
789 } else {
790 $value = acf_idval( $value );
791 }
792
793 acf_update_bidirectional_values( acf_get_array( $value ), $post_id, $field );
794
795 // Return value.
796 return $value;
797 }
798
799 /**
800 * Validates relationship fields updated via the REST API.
801 *
802 * @param boolean $valid The current validity booleean
803 * @param integer $value The value of the field
804 * @param array $field The field array
805 * @return boolean|WP_Error
806 */
807 public function validate_rest_value( $valid, $value, $field ) {
808 return acf_get_field_type( 'post_object' )->validate_rest_value( $valid, $value, $field );
809 }
810
811 /**
812 * Return the schema array for the REST API.
813 *
814 * @param array $field
815 * @return array
816 */
817 public function get_rest_schema( array $field ) {
818 $schema = array(
819 'type' => array( 'integer', 'array', 'null' ),
820 'required' => ! empty( $field['required'] ),
821 'items' => array(
822 'type' => 'integer',
823 ),
824 );
825
826 if ( empty( $field['allow_null'] ) ) {
827 $schema['minItems'] = 1;
828 }
829
830 if ( ! empty( $field['min'] ) ) {
831 $schema['minItems'] = (int) $field['min'];
832 }
833
834 if ( ! empty( $field['max'] ) ) {
835 $schema['maxItems'] = (int) $field['max'];
836 }
837
838 return $schema;
839 }
840
841 /**
842 * @see \acf_field::get_rest_links()
843 * @param mixed $value The raw (unformatted) field value.
844 * @param integer|string $post_id
845 * @param array $field
846 * @return array
847 */
848 public function get_rest_links( $value, $post_id, array $field ) {
849 $links = array();
850
851 if ( empty( $value ) ) {
852 return $links;
853 }
854
855 foreach ( (array) $value as $object_id ) {
856 if ( ! $post_type = get_post_type( $object_id ) or ! $post_type = get_post_type_object( $post_type ) ) {
857 continue;
858 }
859 $rest_base = acf_get_object_type_rest_base( $post_type );
860 $links[] = array(
861 'rel' => $post_type->name === 'attachment' ? 'acf:attachment' : 'acf:post',
862 'href' => rest_url( sprintf( '/wp/v2/%s/%s', $rest_base, $object_id ) ),
863 'embeddable' => true,
864 );
865 }
866
867 return $links;
868 }
869
870 /**
871 * Apply basic formatting to prepare the value for default REST output.
872 *
873 * @param mixed $value
874 * @param string|integer $post_id
875 * @param array $field
876 * @return mixed
877 */
878 public function format_value_for_rest( $value, $post_id, array $field ) {
879 return acf_format_numerics( $value );
880 }
881 }
882
883
884 // initialize
885 acf_register_field_type( 'acf_field_relationship' );
886 endif; // class_exists check
887
888 ?>
889