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