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-taxonomy.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-taxonomy.php
962 lines
1 <?php
2
3 if ( ! class_exists( 'acf_field_taxonomy' ) ) :
4
5 class acf_field_taxonomy extends acf_field {
6
7
8 // vars
9 var $save_post_terms = array();
10
11
12 /**
13 * This function will setup the field type data
14 *
15 * @type function
16 * @date 5/03/2014
17 * @since ACF 5.0.0
18 */
19 public function initialize() {
20 $this->name = 'taxonomy';
21 $this->label = __( 'Taxonomy', 'secure-custom-fields' );
22 $this->category = 'relational';
23 $this->description = __( 'Allows the selection of one or more taxonomy terms based on the criteria and options specified in the fields settings.', 'secure-custom-fields' );
24 $this->preview_image = acf_get_url() . '/assets/images/field-type-previews/field-preview-taxonomy.png';
25 $this->doc_url = 'https://www.advancedcustomfields.com/resources/taxonomy/';
26 $this->defaults = array(
27 'taxonomy' => 'category',
28 'field_type' => 'checkbox',
29 'multiple' => 0,
30 'allow_null' => 0,
31 'return_format' => 'id',
32 'add_term' => 1, // 5.2.3
33 'load_terms' => 0, // 5.2.7
34 'save_terms' => 0, // 5.2.7
35 'bidirectional_target' => array(),
36 );
37
38 // Register filter variations.
39 acf_add_filter_variations( 'acf/fields/taxonomy/query', array( 'name', 'key' ), 1 );
40 acf_add_filter_variations( 'acf/fields/taxonomy/result', array( 'name', 'key' ), 2 );
41
42 // ajax
43 add_action( 'wp_ajax_acf/fields/taxonomy/query', array( $this, 'ajax_query' ) );
44 add_action( 'wp_ajax_nopriv_acf/fields/taxonomy/query', array( $this, 'ajax_query' ) );
45 add_action( 'wp_ajax_acf/fields/taxonomy/add_term', array( $this, 'ajax_add_term' ) );
46 add_filter( 'acf/conditional_logic/choices', array( $this, 'render_field_taxonomy_conditional_choices' ), 10, 3 );
47
48 // actions
49 add_action( 'acf/save_post', array( $this, 'save_post' ), 15, 1 );
50 }
51
52 /**
53 * Returns AJAX results for the Taxonomy field.
54 *
55 * @since ACF 5.0.0
56 *
57 * @return void
58 */
59 public function ajax_query() {
60 $nonce = acf_request_arg( 'nonce', '' );
61 $key = acf_request_arg( 'field_key', '' );
62 $conditional_logic = (bool) acf_request_arg( 'conditional_logic', false );
63
64 if ( $conditional_logic ) {
65 if ( ! acf_current_user_can_admin() ) {
66 die();
67 }
68
69 // Use the standard ACF admin nonce.
70 $nonce = '';
71 $key = '';
72 }
73
74 if ( ! acf_verify_ajax( $nonce, $key ) ) {
75 die();
76 }
77
78 acf_send_ajax_results( $this->get_ajax_query( $_POST ) );
79 }
80
81 /**
82 * This function will return an array of data formatted for use in a select2 AJAX response
83 *
84 * @type function
85 * @date 15/10/2014
86 * @since ACF 5.0.9
87 *
88 * @param $options (array)
89 * @return (array)
90 */
91 function get_ajax_query( $options = array() ) {
92 $options = acf_parse_args(
93 $options,
94 array(
95 'post_id' => 0,
96 's' => '',
97 'field_key' => '',
98 'term_id' => '',
99 'include' => '',
100 'paged' => 1,
101 )
102 );
103
104 $field = acf_get_field( $options['field_key'] );
105 if ( ! $field ) {
106 return false;
107 }
108
109 // if options include isset, then we are loading a specific term.
110 if ( ! empty( $options['include'] ) ) {
111 $options['term_id'] = $options['include'];
112 // paged should be 1.
113 $options['paged'] = 1;
114 }
115
116 // Bail early if taxonomy does not exist.
117 if ( ! taxonomy_exists( $field['taxonomy'] ) ) {
118 return false;
119 }
120
121 $results = array();
122 $is_hierarchical = is_taxonomy_hierarchical( $field['taxonomy'] );
123 $is_pagination = ( $options['paged'] > 0 );
124 $is_search = false;
125 $limit = 20;
126 $offset = 20 * ( $options['paged'] - 1 );
127
128 $args = array(
129 'taxonomy' => $field['taxonomy'],
130 'hide_empty' => false,
131 );
132
133 // Don't bother for hierarchial terms, we will need to load all terms anyway.
134 if ( $is_pagination && ! $is_hierarchical ) {
135 $args['number'] = $limit;
136 $args['offset'] = $offset;
137 }
138
139 // search
140 if ( $options['s'] !== '' ) {
141
142 // strip slashes (search may be integer)
143 $s = wp_unslash( strval( $options['s'] ) );
144
145 $args['search'] = isset( $options['term_id'] ) && $options['term_id'] ? '' : $s;
146 $is_search = true;
147 }
148
149 $args = apply_filters( 'acf/fields/taxonomy/query', $args, $field, $options['post_id'] );
150
151 if ( ! empty( $options['include'] ) ) {
152 // Limit search to a specific id if one is provided.
153 $args['include'] = $options['include'];
154 }
155
156 $terms = acf_get_terms( $args );
157
158 // Sort hierachial.
159 if ( $is_hierarchical ) {
160 $limit = acf_maybe_get( $args, 'number', $limit );
161 $offset = acf_maybe_get( $args, 'offset', $offset );
162
163 $parent = acf_maybe_get( $args, 'parent', 0 );
164 $parent = acf_maybe_get( $args, 'child_of', $parent );
165
166 // This will fail if a search has taken place because parents wont exist.
167 if ( ! $is_search ) {
168 $ordered_terms = _get_term_children( $parent, $terms, $field['taxonomy'] );
169 // Check for empty array. Possible if parent did not exist within original data.
170 if ( ! empty( $ordered_terms ) ) {
171 $terms = $ordered_terms;
172 }
173 }
174
175 // Fake pagination.
176 if ( $is_pagination && ! $options['include'] ) {
177 $terms = array_slice( $terms, $offset, $limit );
178 }
179 }
180
181 // Append to r.
182 foreach ( $terms as $term ) {
183
184 // Add to json.
185 $results[] = array(
186 'id' => $term->term_id,
187 'text' => $this->get_term_title( $term, $field, $options['post_id'], true ),
188 );
189 }
190
191 $response = array(
192 'results' => $results,
193 'limit' => $limit,
194 );
195
196 return $response;
197 }
198
199 /**
200 * Returns the Term's title displayed in the field UI.
201 *
202 * @since ACF 5.0.0
203 *
204 * @param WP_Term $term The term object.
205 * @param array $field The field settings.
206 * @param mixed $post_id The post_id being edited.
207 * @param boolean $unescape Should we return an unescaped post title.
208 * @return string
209 */
210 function get_term_title( $term, $field, $post_id = 0, $unescape = false ) {
211 $title = acf_get_term_title( $term );
212
213 // Default $post_id to current post being edited.
214 $post_id = $post_id ? $post_id : acf_get_form_data( 'post_id' );
215
216 // unescape for select2 output which handles the escaping.
217 if ( $unescape ) {
218 $title = html_entity_decode( $title );
219 }
220
221 /**
222 * Filters the term title.
223 *
224 * @date 1/11/2013
225 * @since ACF 5.0.0
226 *
227 * @param string $title The term title.
228 * @param WP_Term $term The term object.
229 * @param array $field The field settings.
230 * @param (int|string) $post_id The post_id being edited.
231 */
232 return apply_filters( 'acf/fields/taxonomy/result', $title, $term, $field, $post_id );
233 }
234
235
236 /**
237 * This function will return an array of terms for a given field value
238 *
239 * @type function
240 * @date 13/06/2014
241 * @since ACF 5.0.0
242 *
243 * @param $value (array)
244 * @return $value
245 */
246 function get_terms( $value, $taxonomy = 'category' ) {
247
248 // load terms in 1 query to save multiple DB calls from following code
249 if ( count( $value ) > 1 ) {
250 $terms = acf_get_terms(
251 array(
252 'taxonomy' => $taxonomy,
253 'include' => $value,
254 'hide_empty' => false,
255 )
256 );
257 }
258
259 // update value to include $post
260 foreach ( array_keys( $value ) as $i ) {
261 $value[ $i ] = get_term( $value[ $i ], $taxonomy );
262 }
263
264 // filter out null values
265 $value = array_filter( $value );
266
267 // return
268 return $value;
269 }
270
271
272 /**
273 * This filter is appied to the $value after it is loaded from the db
274 *
275 * @type filter
276 * @since ACF 3.6
277 * @date 23/01/13
278 *
279 * @param $value - the value found in the database
280 * @param $post_id - the post_id from which the value was loaded from
281 * @param $field - the field array holding all the field options
282 *
283 * @return $value - the value to be saved in te database
284 */
285 function load_value( $value, $post_id, $field ) {
286
287 // get valid terms
288 $value = acf_get_valid_terms( $value, $field['taxonomy'] );
289
290 // load_terms
291 if ( $field['load_terms'] ) {
292
293 // Decode $post_id for $type and $id.
294 $decoded = acf_decode_post_id( $post_id );
295 $type = $decoded['type'];
296 $id = $decoded['id'];
297
298 if ( $type === 'block' ) {
299 // Get parent block...
300 }
301
302 // get terms
303 $term_ids = wp_get_object_terms(
304 $id,
305 $field['taxonomy'],
306 array(
307 'fields' => 'ids',
308 'orderby' => 'none',
309 )
310 );
311
312 // bail early if no terms
313 if ( empty( $term_ids ) || is_wp_error( $term_ids ) ) {
314 return false;
315 }
316
317 // sort
318 if ( ! empty( $value ) ) {
319 $order = array();
320
321 foreach ( $term_ids as $i => $v ) {
322 $order[ $i ] = array_search( $v, $value );
323 }
324
325 array_multisort( $order, $term_ids );
326 }
327
328 // update value
329 $value = $term_ids;
330 }
331
332 // convert back from array if neccessary
333 if ( $field['field_type'] == 'select' || $field['field_type'] == 'radio' ) {
334 $value = array_shift( $value );
335 }
336
337 // return
338 return $value;
339 }
340
341
342 /**
343 * Filters the field value before it is saved into the database.
344 *
345 * @since ACF 3.6
346 *
347 * @param mixed $value The value which will be saved in the database.
348 * @param integer $post_id The post_id of which the value will be saved.
349 * @param array $field The field array holding all the field options.
350 * @return mixed $value The modified value.
351 */
352 public function update_value( $value, $post_id, $field ) {
353
354 if ( is_array( $value ) ) {
355 $value = array_filter( $value );
356 }
357
358 acf_update_bidirectional_values( acf_get_array( $value ), $post_id, $field, 'term' );
359
360 // save_terms if enabled.
361 if ( $field['save_terms'] ) {
362
363 // vars
364 $taxonomy = $field['taxonomy'];
365
366 // force value to array.
367 $term_ids = acf_get_array( $value );
368
369 // convert to int.
370 $term_ids = array_map( 'intval', $term_ids );
371
372 // get existing term id's (from a previously saved field).
373 $old_term_ids = isset( $this->save_post_terms[ $taxonomy ] ) ? $this->save_post_terms[ $taxonomy ] : array();
374
375 // append
376 $this->save_post_terms[ $taxonomy ] = array_merge( $old_term_ids, $term_ids );
377
378 // if called directly from frontend update_field().
379 if ( ! did_action( 'acf/save_post' ) ) {
380 $this->save_post( $post_id );
381 return $value;
382 }
383 }
384
385 return $value;
386 }
387
388 /**
389 * This function will save any terms in the save_post_terms array
390 *
391 * @since ACF 5.0.9
392 *
393 * @param mixed $post_id The ACF post ID to save to.
394 * @return void
395 */
396 public function save_post( $post_id ) {
397 // Check for saved terms.
398 if ( ! empty( $this->save_post_terms ) ) {
399 /**
400 * Determine object ID allowing for non "post" $post_id (user, taxonomy, etc).
401 * Although not fully supported by WordPress, non "post" objects may use the term relationships table.
402 * Sharing taxonomies across object types is discouraged, but unique taxonomies work well.
403 * Note: Do not attempt to restrict to "post" only. This has been attempted in 5.8.9 and later reverted.
404 */
405 $decoded = acf_decode_post_id( $post_id );
406 $type = $decoded['type'];
407 $id = $decoded['id'];
408
409 if ( $type === 'block' ) {
410 // Get parent block...
411 }
412
413 // Loop over taxonomies and save terms.
414 foreach ( $this->save_post_terms as $taxonomy => $term_ids ) {
415 wp_set_object_terms( $id, $term_ids, $taxonomy, false );
416 }
417
418 // Reset storage.
419 $this->save_post_terms = array();
420 }
421 }
422
423 /**
424 * This filter is appied to the $value after it is loaded from the db and before it is returned to the template
425 *
426 * @type filter
427 * @since ACF 3.6
428 * @date 23/01/13
429 *
430 * @param $value (mixed) the value which was loaded from the database
431 * @param $post_id (mixed) the post_id from which the value was loaded
432 * @param $field (array) the field array holding all the field options
433 *
434 * @return $value (mixed) the modified value
435 */
436 function format_value( $value, $post_id, $field ) {
437
438 // bail early if no value
439 if ( empty( $value ) ) {
440 return false;
441 }
442
443 // force value to array
444 $value = acf_get_array( $value );
445
446 // load posts if needed
447 if ( $field['return_format'] == 'object' ) {
448
449 // get posts
450 $value = $this->get_terms( $value, $field['taxonomy'] );
451 }
452
453 // convert back from array if neccessary
454 if ( $field['field_type'] == 'select' || $field['field_type'] == 'radio' ) {
455 $value = array_shift( $value );
456 }
457
458 // return
459 return $value;
460 }
461
462 /**
463 * Renders the Taxonomy field.
464 *
465 * @since ACF 3.6
466 *
467 * @param array $field The field settings array.
468 * @return void
469 */
470 public function render_field( $field ) {
471 // force value to array
472 $field['value'] = acf_get_array( $field['value'] );
473
474 // vars
475 $div = array(
476 'class' => 'acf-taxonomy-field',
477 'data-save' => $field['save_terms'],
478 'data-ftype' => $field['field_type'],
479 'data-taxonomy' => $field['taxonomy'],
480 'data-allow_null' => $field['allow_null'],
481 'data-nonce' => wp_create_nonce( $field['key'] ),
482 );
483 // get taxonomy
484 $taxonomy = get_taxonomy( $field['taxonomy'] );
485
486 // bail early if taxonomy does not exist
487 if ( ! $taxonomy ) {
488 return;
489 }
490
491 ?>
492 <div <?php echo acf_esc_attrs( $div ); ?>>
493 <?php if ( $field['add_term'] && current_user_can( $taxonomy->cap->manage_terms ) ) : ?>
494 <div class="acf-actions -hover">
495 <a href="#" class="acf-icon -plus acf-js-tooltip small" data-name="add" title="<?php echo esc_attr( $taxonomy->labels->add_new_item ); ?>"></a>
496 </div>
497 <?php
498 endif;
499
500 if ( $field['field_type'] == 'select' ) {
501 $field['multiple'] = 0;
502
503 $this->render_field_select( $field );
504 } elseif ( $field['field_type'] == 'multi_select' ) {
505 $field['multiple'] = 1;
506
507 $this->render_field_select( $field );
508 } elseif ( $field['field_type'] == 'radio' ) {
509 $this->render_field_checkbox( $field );
510 } elseif ( $field['field_type'] == 'checkbox' ) {
511 $this->render_field_checkbox( $field );
512 }
513
514 ?>
515 </div>
516 <?php
517 }
518
519 /**
520 * Create the HTML interface for your field
521 *
522 * @type action
523 * @since ACF 3.6
524 * @date 23/01/13
525 *
526 * @param $field - an array holding all the field's data
527 */
528 function render_field_select( $field ) {
529
530 // Change Field into a select
531 $field['type'] = 'select';
532 $field['ui'] = 1;
533 $field['ajax'] = 1;
534 $field['choices'] = array();
535
536 // value
537 if ( ! empty( $field['value'] ) ) {
538
539 // get terms
540 $terms = $this->get_terms( $field['value'], $field['taxonomy'] );
541
542 // set choices
543 if ( ! empty( $terms ) ) {
544 foreach ( array_keys( $terms ) as $i ) {
545
546 // vars
547 $term = acf_extract_var( $terms, $i );
548
549 // append to choices
550 $field['choices'][ $term->term_id ] = $this->get_term_title( $term, $field );
551 }
552 }
553 }
554
555 // render select
556 acf_render_field( $field );
557 }
558
559
560 /**
561 * Create the HTML interface for your field
562 *
563 * @since ACF 3.6
564 *
565 * @param array $field an array holding all the field's data.
566 */
567 public function render_field_checkbox( $field ) {
568
569 // hidden input.
570 acf_hidden_input(
571 array(
572 'type' => 'hidden',
573 'name' => $field['name'],
574 )
575 );
576
577 // checkbox saves an array.
578 if ( $field['field_type'] == 'checkbox' ) {
579 $field['name'] .= '[]';
580 }
581
582 // taxonomy.
583 $taxonomy_obj = get_taxonomy( $field['taxonomy'] );
584
585 // include walker.
586 acf_include( 'includes/walkers/class-acf-walker-taxonomy-field.php' );
587
588 // vars.
589 $args = array(
590 'taxonomy' => $field['taxonomy'],
591 /* translators: %s: Taxonomy name */
592 'show_option_none' => sprintf( _x( 'No %s', 'No Terms', 'secure-custom-fields' ), $taxonomy_obj->labels->name ),
593 'hide_empty' => false,
594 'style' => 'none',
595 'walker' => new ACF_Taxonomy_Field_Walker( $field ),
596 );
597
598 // filter for 3rd party customization.
599 $args = apply_filters( 'acf/fields/taxonomy/wp_list_categories', $args, $field );
600 $args = apply_filters( 'acf/fields/taxonomy/wp_list_categories/name=' . $field['_name'], $args, $field );
601 $args = apply_filters( 'acf/fields/taxonomy/wp_list_categories/key=' . $field['key'], $args, $field );
602
603 ?>
604 <div class="categorychecklist-holder">
605 <ul class="acf-checkbox-list acf-bl">
606 <?php wp_list_categories( $args ); ?>
607 </ul>
608 </div>
609 <?php
610 }
611
612
613 /**
614 * Create extra options for your field. This is rendered when editing a field.
615 * The value of $field['name'] can be used (like bellow) to save extra data to the $field
616 *
617 * @type action
618 * @since ACF 3.6
619 * @date 23/01/13
620 *
621 * @param $field - an array holding all the field's data
622 */
623 function render_field_settings( $field ) {
624 acf_render_field_setting(
625 $field,
626 array(
627 'label' => __( 'Taxonomy', 'secure-custom-fields' ),
628 'instructions' => __( 'Select the taxonomy to be displayed', 'secure-custom-fields' ),
629 'type' => 'select',
630 'name' => 'taxonomy',
631 'choices' => acf_get_taxonomy_labels(),
632 )
633 );
634
635 acf_render_field_setting(
636 $field,
637 array(
638 'label' => __( 'Create Terms', 'secure-custom-fields' ),
639 'instructions' => __( 'Allow new terms to be created whilst editing', 'secure-custom-fields' ),
640 'name' => 'add_term',
641 'type' => 'true_false',
642 'ui' => 1,
643 )
644 );
645
646 acf_render_field_setting(
647 $field,
648 array(
649 'label' => __( 'Save Terms', 'secure-custom-fields' ),
650 'instructions' => __( 'Connect selected terms to the post', 'secure-custom-fields' ),
651 'name' => 'save_terms',
652 'type' => 'true_false',
653 'ui' => 1,
654 )
655 );
656
657 acf_render_field_setting(
658 $field,
659 array(
660 'label' => __( 'Load Terms', 'secure-custom-fields' ),
661 'instructions' => __( 'Load value from posts terms', 'secure-custom-fields' ),
662 'name' => 'load_terms',
663 'type' => 'true_false',
664 'ui' => 1,
665 )
666 );
667
668 acf_render_field_setting(
669 $field,
670 array(
671 'label' => __( 'Return Value', 'secure-custom-fields' ),
672 'instructions' => '',
673 'type' => 'radio',
674 'name' => 'return_format',
675 'choices' => array(
676 'object' => __( 'Term Object', 'secure-custom-fields' ),
677 'id' => __( 'Term ID', 'secure-custom-fields' ),
678 ),
679 'layout' => 'horizontal',
680 )
681 );
682
683 acf_render_field_setting(
684 $field,
685 array(
686 'label' => __( 'Appearance', 'secure-custom-fields' ),
687 'instructions' => __( 'Select the appearance of this field', 'secure-custom-fields' ),
688 'type' => 'select',
689 'name' => 'field_type',
690 'optgroup' => true,
691 'choices' => array(
692 __( 'Multiple Values', 'secure-custom-fields' ) => array(
693 'checkbox' => __( 'Checkbox', 'secure-custom-fields' ),
694 'multi_select' => __( 'Multi Select', 'secure-custom-fields' ),
695 ),
696 __( 'Single Value', 'secure-custom-fields' ) => array(
697 'radio' => __( 'Radio Buttons', 'secure-custom-fields' ),
698 'select' => _x( 'Select', 'noun', 'secure-custom-fields' ),
699 ),
700 ),
701 )
702 );
703
704 acf_render_field_setting(
705 $field,
706 array(
707 'label' => __( 'Allow Null', 'secure-custom-fields' ),
708 'instructions' => '',
709 'name' => 'allow_null',
710 'type' => 'true_false',
711 'ui' => 1,
712 'conditions' => array(
713 'field' => 'field_type',
714 'operator' => '!=',
715 'value' => 'checkbox',
716 ),
717 )
718 );
719 }
720
721 /**
722 * Renders the field settings used in the "Advanced" tab.
723 *
724 * @since ACF 6.2
725 *
726 * @param array $field The field settings array.
727 * @return void
728 */
729 public function render_field_advanced_settings( $field ) {
730 acf_render_bidirectional_field_settings( $field );
731 }
732
733 /**
734 * Filters choices in taxonomy conditions.
735 *
736 * @since ACF 6.3
737 *
738 * @param array $choices The selected choice.
739 * @param array $conditional_field The conditional field settings object.
740 * @param string $rule_value The rule value.
741 * @return mixed
742 */
743 public function render_field_taxonomy_conditional_choices( $choices, $conditional_field, $rule_value ) {
744 if ( is_array( $conditional_field ) && $conditional_field['type'] === 'taxonomy' ) {
745 if ( ! empty( $rule_value ) ) {
746 $term = get_term( $rule_value );
747 $choices = array( $rule_value => $term->name );
748 }
749 }
750 return $choices;
751 }
752
753
754 /**
755 * AJAX handler for adding Taxonomy field terms.
756 *
757 * @since ACF 5.2.3
758 *
759 * @return void
760 */
761 public function ajax_add_term() {
762 $args = acf_request_args(
763 array(
764 'nonce' => '',
765 'field_key' => '',
766 'term_name' => '',
767 'term_parent' => '',
768 )
769 );
770
771 if ( ! acf_verify_ajax( $args['nonce'], $args['field_key'] ) ) {
772 die();
773 }
774
775 // load field
776 $field = acf_get_field( $args['field_key'] );
777 if ( ! $field ) {
778 die();
779 }
780
781 // vars
782 $taxonomy_obj = get_taxonomy( $field['taxonomy'] );
783 $taxonomy_label = $taxonomy_obj->labels->singular_name;
784
785 // validate cap
786 // note: this situation should never occur due to condition of the add new button
787 if ( ! current_user_can( $taxonomy_obj->cap->manage_terms ) ) {
788 wp_send_json_error(
789 array(
790 /* translators: %s: Taxonomy name */
791 'error' => sprintf( __( 'User unable to add new %s', 'secure-custom-fields' ), $taxonomy_label ),
792 )
793 );
794 }
795
796 // save?
797 if ( $args['term_name'] ) {
798
799 // exists
800 if ( term_exists( $args['term_name'], $field['taxonomy'], $args['term_parent'] ) ) {
801 wp_send_json_error(
802 array(
803 /* translators: %s: Taxonomy name */
804 'error' => sprintf( __( '%s already exists', 'secure-custom-fields' ), $taxonomy_label ),
805 )
806 );
807 }
808
809 // vars
810 $extra = array();
811 if ( $args['term_parent'] ) {
812 $extra['parent'] = (int) $args['term_parent'];
813 }
814
815 // insert
816 $data = wp_insert_term( $args['term_name'], $field['taxonomy'], $extra );
817
818 // error
819 if ( is_wp_error( $data ) ) {
820 wp_send_json_error(
821 array(
822 'error' => $data->get_error_message(),
823 )
824 );
825 }
826
827 // load term
828 $term = get_term( $data['term_id'] );
829
830 // prepend ancenstors count to term name
831 $prefix = '';
832 $ancestors = get_ancestors( $term->term_id, $term->taxonomy );
833 if ( ! empty( $ancestors ) ) {
834 $prefix = str_repeat( '- ', count( $ancestors ) );
835 }
836
837 // success
838 wp_send_json_success(
839 array(
840 /* translators: %s: Taxonomy name */
841 'message' => sprintf( __( '%s added', 'secure-custom-fields' ), $taxonomy_label ),
842 'term_id' => $term->term_id,
843 'term_name' => $term->name,
844 'term_label' => $prefix . $term->name,
845 'term_parent' => $term->parent,
846 )
847 );
848 }
849
850 ?>
851 <form method="post">
852 <?php
853
854 acf_render_field_wrap(
855 array(
856 'label' => __( 'Name', 'secure-custom-fields' ),
857 'name' => 'term_name',
858 'type' => 'text',
859 )
860 );
861
862 if ( is_taxonomy_hierarchical( $field['taxonomy'] ) ) {
863 $choices = array();
864 $response = $this->get_ajax_query( $args );
865
866 if ( $response ) {
867 foreach ( $response['results'] as $v ) {
868 $choices[ $v['id'] ] = $v['text'];
869 }
870 }
871
872 acf_render_field_wrap(
873 array(
874 'label' => __( 'Parent', 'secure-custom-fields' ),
875 'name' => 'term_parent',
876 'type' => 'select',
877 'allow_null' => 1,
878 'ui' => 0,
879 'choices' => $choices,
880 )
881 );
882 }
883
884 ?>
885 <p class="acf-submit">
886 <button class="acf-submit-button button button-primary" type="submit"><?php esc_html_e( 'Add', 'secure-custom-fields' ); ?></button>
887 </p>
888 </form><?php
889
890 // die
891 die;
892 }
893
894 /**
895 * Return the schema array for the REST API.
896 *
897 * @param array $field
898 * @return array
899 */
900 public function get_rest_schema( array $field ) {
901 $schema = array(
902 'type' => array( 'integer', 'array', 'null' ),
903 'required' => ! empty( $field['required'] ),
904 'items' => array(
905 'type' => 'integer',
906 ),
907 );
908
909 if ( empty( $field['allow_null'] ) ) {
910 $schema['minItems'] = 1;
911 }
912
913 if ( in_array( $field['field_type'], array( 'radio', 'select' ) ) ) {
914 $schema['maxItems'] = 1;
915 }
916
917 return $schema;
918 }
919
920 /**
921 * @see \acf_field::get_rest_links()
922 * @param mixed $value The raw (unformatted) field value.
923 * @param integer|string $post_id
924 * @param array $field
925 * @return array
926 */
927 public function get_rest_links( $value, $post_id, array $field ) {
928 $links = array();
929
930 if ( empty( $value ) ) {
931 return $links;
932 }
933
934 foreach ( (array) $value as $object_id ) {
935 $term = get_term( $object_id );
936 if ( ! $term instanceof WP_Term ) {
937 continue;
938 }
939
940 $rest_base = acf_get_object_type_rest_base( get_taxonomy( $term->taxonomy ) );
941 if ( ! $rest_base ) {
942 continue;
943 }
944
945 $links[] = array(
946 'rel' => 'acf:term',
947 'href' => rest_url( sprintf( '/wp/v2/%s/%s', $rest_base, $object_id ) ),
948 'embeddable' => true,
949 'taxonomy' => $term->taxonomy,
950 );
951 }
952
953 return $links;
954 }
955 }
956
957
958 // initialize
959 acf_register_field_type( 'acf_field_taxonomy' );
960 endif; // class_exists check
961
962 ?>