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 / post-types / class-acf-taxonomy.php
secure-custom-fields / includes / post-types Last commit date
class-acf-field-group.php 2 months ago class-acf-post-type.php 2 months ago class-acf-taxonomy.php 2 months ago class-acf-ui-options-page.php 1 year ago class-scf-field-manager.php 6 months ago index.php 1 year ago
class-acf-taxonomy.php
811 lines
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit; // Exit if accessed directly.
5 }
6
7 if ( ! class_exists( 'ACF_Taxonomy' ) ) {
8 class ACF_Taxonomy extends ACF_Internal_Post_Type {
9
10 /**
11 * The ACF internal post type name.
12 *
13 * @var string
14 */
15 public $post_type = 'acf-taxonomy';
16
17 /**
18 * The prefix for the key used in the main post array.
19 *
20 * @var string
21 */
22 public $post_key_prefix = 'taxonomy_';
23
24 /**
25 * The cache key for a singular post.
26 *
27 * @var string
28 */
29 public $cache_key = 'acf_get_taxonomy_post:key:';
30
31 /**
32 * The cache key for a collection of posts.
33 *
34 * @var string
35 */
36 public $cache_key_plural = 'acf_get_taxonomy_posts';
37
38 /**
39 * The hook name for a singular post.
40 *
41 * @var string
42 */
43 public $hook_name = 'taxonomy';
44
45 /**
46 * The hook name for a collection of posts.
47 *
48 * @var string
49 */
50 public $hook_name_plural = 'taxonomies';
51
52 /**
53 * The name of the store used for the post type.
54 *
55 * @var string
56 */
57 public $store = 'taxonomies';
58
59 /**
60 * Constructs the class.
61 */
62 public function __construct() {
63 $this->register_post_type();
64
65 // Include admin classes in admin.
66 if ( is_admin() ) {
67 acf_include( 'includes/admin/admin-internal-post-type-list.php' );
68 acf_include( 'includes/admin/admin-internal-post-type.php' );
69 acf_include( 'includes/admin/post-types/admin-taxonomy.php' );
70 acf_include( 'includes/admin/post-types/admin-taxonomies.php' );
71 }
72
73 parent::__construct();
74
75 add_action( 'acf/init', array( $this, 'register_taxonomies' ), 6 );
76 }
77
78 /**
79 * Registers the acf-taxonomy custom post type with WordPress.
80 *
81 * @since ACF 6.1
82 */
83 public function register_post_type() {
84 $cap = acf_get_setting( 'capability' );
85
86 register_post_type(
87 'acf-taxonomy',
88 array(
89 'labels' => array(
90 'name' => __( 'Taxonomies', 'secure-custom-fields' ),
91 'singular_name' => __( 'Taxonomies', 'secure-custom-fields' ),
92 'add_new' => __( 'Add New', 'secure-custom-fields' ),
93 'add_new_item' => __( 'Add New Taxonomy', 'secure-custom-fields' ),
94 'edit_item' => __( 'Edit Taxonomy', 'secure-custom-fields' ),
95 'new_item' => __( 'New Taxonomy', 'secure-custom-fields' ),
96 'view_item' => __( 'View Taxonomy', 'secure-custom-fields' ),
97 'search_items' => __( 'Search Taxonomies', 'secure-custom-fields' ),
98 'not_found' => __( 'No Taxonomies found', 'secure-custom-fields' ),
99 'not_found_in_trash' => __( 'No Taxonomies found in Trash', 'secure-custom-fields' ),
100 ),
101 'public' => false,
102 'hierarchical' => true,
103 'show_ui' => true,
104 'show_in_menu' => false,
105 '_builtin' => false,
106 'capability_type' => 'post',
107 'capabilities' => array(
108 'edit_post' => $cap,
109 'delete_post' => $cap,
110 'edit_posts' => $cap,
111 'delete_posts' => $cap,
112 ),
113 'supports' => false,
114 'rewrite' => false,
115 'query_var' => false,
116 )
117 );
118 }
119
120 /**
121 * Register activated taxonomies with WordPress
122 *
123 * @since ACF 6.1
124 */
125 public function register_taxonomies() {
126 $taxonomies = $this->get_posts( array( 'active' => true ) );
127 foreach ( $taxonomies as $taxonomy ) {
128 $args = $this->get_taxonomy_args( $taxonomy );
129 if ( ! taxonomy_exists( $taxonomy['taxonomy'] ) ) {
130 register_taxonomy( $taxonomy['taxonomy'], (array) $taxonomy['object_type'], $args );
131 } else {
132 // Flag on the store we bailed on registering this as it already exists.
133 $store = acf_get_store( $this->store );
134 $store_value = $store->get( $taxonomy['key'] );
135 $store_value['not_registered'] = true;
136 $store->set( $taxonomy['key'], $store_value );
137 }
138 }
139 }
140
141 /**
142 * Gets the default settings array for an ACF taxonomy.
143 *
144 * @return array
145 */
146 public function get_settings_array() {
147 return array(
148 // ACF-specific settings.
149 'ID' => 0,
150 'key' => '',
151 'title' => '',
152 'menu_order' => 0,
153 'active' => true,
154 'taxonomy' => '', // Taxonomy key passed as first param to register_taxonomy().
155 'object_type' => array(), // Converted to objects array passed as second parameter.
156 'advanced_configuration' => 0,
157 'import_source' => '',
158 'import_date' => '',
159 // Settings passed to register_taxonomy().
160 'labels' => array(
161 'singular_name' => '',
162 'name' => '',
163 'menu_name' => '',
164 'search_items' => '',
165 'popular_items' => '',
166 'all_items' => '',
167 'parent_item' => '',
168 'parent_item_colon' => '',
169 'name_field_description' => '',
170 'slug_field_description' => '',
171 'parent_field_description' => '',
172 'desc_field_description' => '',
173 'edit_item' => '',
174 'view_item' => '',
175 'update_item' => '',
176 'add_new_item' => '',
177 'new_item_name' => '',
178 'separate_items_with_commas' => '',
179 'add_or_remove_items' => '',
180 'choose_from_most_used' => '',
181 'not_found' => '',
182 'no_terms' => '',
183 'filter_by_item' => '',
184 'items_list_navigation' => '',
185 'items_list' => '',
186 'most_used' => '',
187 'back_to_items' => '',
188 'item_link' => '',
189 'item_link_description' => '',
190 ),
191 'description' => '',
192 'capabilities' => array(
193 'manage_terms' => 'manage_categories',
194 'edit_terms' => 'manage_categories',
195 'delete_terms' => 'manage_categories',
196 'assign_terms' => 'edit_posts',
197 ),
198 'public' => true,
199 'publicly_queryable' => true,
200 'hierarchical' => false,
201 'show_ui' => true,
202 'show_in_menu' => true,
203 'show_in_nav_menus' => true,
204 'show_in_rest' => true,
205 'rest_base' => '',
206 'rest_namespace' => 'wp/v2',
207 'rest_controller_class' => 'WP_REST_Terms_Controller',
208 'show_tagcloud' => true,
209 'show_in_quick_edit' => true,
210 'show_admin_column' => false,
211 'rewrite' => array(
212 'permalink_rewrite' => 'taxonomy_key', // ACF-specific option.
213 'slug' => '',
214 'with_front' => true,
215 'rewrite_hierarchical' => false,
216 ),
217 'query_var' => 'taxonomy_key',
218 'query_var_name' => '',
219 'default_term' => array(
220 'default_term_enabled' => false,
221 'default_term_name' => '',
222 'default_term_slug' => '',
223 'default_term_description' => '',
224 ),
225 'sort' => null,
226 'meta_box' => 'default',
227 'meta_box_cb' => '',
228 'meta_box_sanitize_cb' => '',
229 'allow_ai_access' => false,
230 'ai_description' => '',
231 );
232 }
233
234 /**
235 * Validates post type values before allowing save from the global $_POST object.
236 * Errors are added to the form using acf_add_internal_post_type_validation_error().
237 *
238 * @since ACF 6.1
239 *
240 * @return boolean validity status
241 */
242 public function ajax_validate_values() {
243 if ( empty( $_POST['acf_taxonomy'] ) || empty( $_POST['acf_taxonomy']['taxonomy'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified elsewhere.
244 return false;
245 }
246
247 $taxonomy_key = acf_sanitize_request_args( wp_unslash( $_POST['acf_taxonomy']['taxonomy'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verified elsewhere.
248 $taxonomy_key = is_string( $taxonomy_key ) ? $taxonomy_key : '';
249 $valid = true;
250
251 if ( strlen( $taxonomy_key ) > 32 ) {
252 $valid = false;
253 acf_add_internal_post_type_validation_error( 'taxonomy', __( 'The taxonomy key must be under 32 characters.', 'secure-custom-fields' ) );
254 }
255
256 if ( preg_match( '/^[a-z0-9_-]*$/', $taxonomy_key ) !== 1 ) {
257 $valid = false;
258 acf_add_internal_post_type_validation_error( 'taxonomy', __( 'The taxonomy key must only contain lower case alphanumeric characters, underscores or dashes.', 'secure-custom-fields' ) );
259 }
260
261 if ( in_array( $taxonomy_key, acf_get_wp_reserved_terms(), true ) ) {
262 $valid = false;
263 /* translators: %s a link to WordPress.org's Reserved Terms page */
264 $message = sprintf( __( 'This field must not be a WordPress <a href="%s" target="_blank">reserved term</a>.', 'secure-custom-fields' ), 'https://codex.wordpress.org/Reserved_Terms' );
265 acf_add_internal_post_type_validation_error( 'taxonomy', $message );
266 } else {
267 // Check if this post key exists in the ACF store for registered post types, excluding those which failed registration.
268 $store = acf_get_store( $this->store );
269 $post_id = (int) acf_maybe_get_POST( 'post_id', 0 );
270
271 $matches = array_filter(
272 $store->get_data(),
273 function ( $item ) use ( $taxonomy_key ) {
274 return $item['taxonomy'] === $taxonomy_key && empty( $item['not_registered'] );
275 }
276 );
277 $duplicates = array_filter(
278 $matches,
279 function ( $item ) use ( $post_id ) {
280 return $item['ID'] !== $post_id;
281 }
282 );
283
284 if ( $duplicates ) {
285 $valid = false;
286 acf_add_internal_post_type_validation_error( 'taxonomy', __( 'This taxonomy key is already in use by another taxonomy in ACF and cannot be used.', 'secure-custom-fields' ) );
287 // If we're not already in use with another ACF taxonomy, check if we're registered, but not by ACF.
288 } elseif ( empty( $matches ) && taxonomy_exists( $taxonomy_key ) ) {
289 $valid = false;
290 acf_add_internal_post_type_validation_error( 'taxonomy', __( 'This taxonomy key is already in use by another taxonomy registered outside of ACF and cannot be used.', 'secure-custom-fields' ) );
291 }
292 }
293
294 $valid = apply_filters( "acf/{$this->hook_name}/ajax_validate_values", $valid, $_POST['acf_taxonomy'] ); // phpcs:ignore WordPress.Security -- Raw input send to hook for validation.
295
296 return $valid;
297 }
298
299 /**
300 * Parses ACF taxonomy settings and returns an array of taxonomy
301 * args that can be easily handled by `register_taxonomy()`.
302 *
303 * Omits settings that line up with the WordPress defaults to reduce the size
304 * of the array passed to `register_taxonomy()`, which might be exported.
305 *
306 * @since ACF 6.1
307 *
308 * @param array $post The main ACF taxonomy settings array.
309 * @param boolean $escape_labels Determines if the label values should be escaped.
310 * @return array
311 */
312 public function get_taxonomy_args( $post, $escape_labels = true ) {
313 $args = array();
314
315 // Make sure any provided labels are escaped strings and not empty.
316 $labels = array_filter( $post['labels'] );
317 $labels = array_map( 'strval', $labels );
318 if ( $escape_labels ) {
319 $labels = array_map( 'esc_html', $labels );
320 }
321 if ( ! empty( $labels ) ) {
322 $args['labels'] = $labels;
323 }
324
325 // Description is an optional string.
326 if ( ! empty( $post['description'] ) ) {
327 $args['description'] = (string) $post['description'];
328 }
329
330 // ACF requires the public setting to decide other settings.
331 $args['public'] = ! empty( $post['public'] );
332
333 // WordPress and ACF both default to false, so this can be omitted if still false.
334 if ( ! empty( $post['hierarchical'] ) ) {
335 $args['hierarchical'] = true;
336 }
337
338 // WordPress defaults to the same as $args['public'].
339 $publicly_queryable = (bool) $post['publicly_queryable'];
340 if ( $publicly_queryable !== $args['public'] ) {
341 $args['publicly_queryable'] = $publicly_queryable;
342 }
343
344 // WordPress defaults to the same as $args['public'].
345 $show_ui = (bool) $post['show_ui'];
346 if ( $show_ui !== $args['public'] ) {
347 $args['show_ui'] = $show_ui;
348 }
349
350 // WordPress defaults to the same as $args['show_ui'].
351 $show_in_menu = $post['show_in_menu'];
352 if ( $show_in_menu !== $show_ui ) {
353 $args['show_in_menu'] = (bool) $show_in_menu;
354 }
355
356 // WordPress defaults to the same as $args['public'].
357 $show_in_nav_menus = (bool) $post['show_in_nav_menus'];
358 if ( $show_in_nav_menus !== $args['public'] ) {
359 $args['show_in_nav_menus'] = $show_in_nav_menus;
360 }
361
362 // ACF defaults to true, but can be overridden.
363 $show_in_rest = (bool) $post['show_in_rest'];
364 $args['show_in_rest'] = $show_in_rest;
365
366 // WordPress defaults to `$taxonomy`.
367 $rest_base = (string) $post['rest_base'];
368 if ( ! empty( $rest_base ) && $rest_base !== $post['taxonomy'] ) {
369 $args['rest_base'] = $rest_base;
370 }
371
372 // WordPress defaults to "wp/v2".
373 $rest_namespace = (string) $post['rest_namespace'];
374 if ( ! empty( $rest_namespace ) && 'wp/v2' !== $rest_namespace ) {
375 $args['rest_namespace'] = $post['rest_namespace'];
376 }
377
378 // WordPress defaults to `WP_REST_Terms_Controller`.
379 $rest_controller_class = (string) $post['rest_controller_class'];
380 if ( ! empty( $rest_controller_class ) && 'WP_REST_Terms_Controller' !== $rest_controller_class ) {
381 $args['rest_controller_class'] = $rest_controller_class;
382 }
383
384 // WordPress defaults to the same as `$args['show_ui']`.
385 $show_tagcloud = (bool) $post['show_tagcloud'];
386 if ( $show_tagcloud !== $show_ui ) {
387 $args['show_tagcloud'] = $show_tagcloud;
388 }
389
390 // WordPress defaults to the same as `$args['show_ui']`.
391 $show_in_quick_edit = (bool) $post['show_in_quick_edit'];
392 if ( $show_in_quick_edit !== $show_ui ) {
393 $args['show_in_quick_edit'] = $show_tagcloud;
394 }
395
396 // WordPress defaults to false.
397 $show_admin_column = (bool) $post['show_admin_column'];
398 if ( $show_admin_column ) {
399 $args['show_admin_column'] = true;
400 }
401
402 $capabilities = array();
403
404 if ( ! empty( $post['capabilities']['manage_terms'] ) && 'manage_categories' !== $post['capabilities']['manage_terms'] ) {
405 $capabilities['manage_terms'] = (string) $post['capabilities']['manage_terms'];
406 }
407
408 if ( ! empty( $post['capabilities']['edit_terms'] ) && 'manage_categories' !== $post['capabilities']['edit_terms'] ) {
409 $capabilities['edit_terms'] = (string) $post['capabilities']['edit_terms'];
410 }
411
412 if ( ! empty( $post['capabilities']['delete_terms'] ) && 'manage_categories' !== $post['capabilities']['delete_terms'] ) {
413 $capabilities['delete_terms'] = (string) $post['capabilities']['delete_terms'];
414 }
415
416 if ( ! empty( $post['capabilities']['assign_terms'] ) && 'edit_posts' !== $post['capabilities']['assign_terms'] ) {
417 $capabilities['assign_terms'] = (string) $post['capabilities']['assign_terms'];
418 }
419
420 if ( ! empty( $capabilities ) ) {
421 $args['capabilities'] = $capabilities;
422 }
423
424 // WordPress defaults to the tags/categories metabox, but a custom callback or `false` is also supported.
425 $meta_box = isset( $post['meta_box'] ) ? (string) $post['meta_box'] : 'default';
426
427 if ( 'custom' === $meta_box && ! empty( $post['meta_box_cb'] ) ) {
428 $args['meta_box_cb'] = array( $this, 'build_safe_context_for_metabox_cb' );
429
430 if ( ! empty( $post['meta_box_sanitize_cb'] ) ) {
431 $args['meta_box_sanitize_cb'] = (string) $post['meta_box_sanitize_cb'];
432 }
433 } elseif ( 'disabled' === $meta_box ) {
434 $args['meta_box_cb'] = false;
435 }
436
437 // The rewrite arg can be a boolean or array of further settings. WordPress and ACF default to true.
438 $rewrite = (array) $post['rewrite'];
439 $rewrite_enabled = true;
440 $rewrite_args = array();
441
442 // Value of ACF select (not passed to `register_taxonomy()`).
443 $rewrite['permalink_rewrite'] = isset( $rewrite['permalink_rewrite'] ) ? (string) $rewrite['permalink_rewrite'] : 'taxonomy_key';
444
445 if ( 'no_permalink' === $rewrite['permalink_rewrite'] ) {
446 $rewrite_enabled = false;
447 }
448
449 // Rewrite slug defaults to $taxonomy key.
450 if ( ! empty( $rewrite['slug'] ) && $rewrite['slug'] !== $post['taxonomy'] && 'custom_permalink' === $rewrite['permalink_rewrite'] ) {
451 $rewrite_args['slug'] = (string) $rewrite['slug'];
452 }
453
454 // WordPress defaults to true.
455 if ( isset( $rewrite['with_front'] ) && ! $rewrite['with_front'] && $rewrite_enabled ) {
456 $rewrite_args['with_front'] = false;
457 }
458
459 // WordPress defaults to false.
460 if ( isset( $rewrite['rewrite_hierarchical'] ) && $rewrite['rewrite_hierarchical'] && $rewrite_enabled ) {
461 $rewrite_args['hierarchical'] = true;
462 }
463
464 if ( $rewrite_enabled && ! empty( $rewrite_args ) ) {
465 $args['rewrite'] = $rewrite_args;
466 } elseif ( ! $rewrite_enabled ) {
467 $args['rewrite'] = false;
468 }
469
470 // WordPress and ACF default to $taxonomy key, a boolean can also be used.
471 $query_var = (string) $post['query_var'];
472 if ( 'custom_query_var' === $query_var ) {
473 $query_var_name = (string) $post['query_var_name'];
474
475 if ( ! empty( $query_var_name ) && $query_var_name !== $post['taxonomy'] ) {
476 $args['query_var'] = $query_var_name;
477 }
478 } elseif ( 'none' === $query_var ) {
479 $args['query_var'] = false;
480 }
481
482 // WordPress accepts a string or an array of term info, but always converts into an array.
483 $default_term = (array) $post['default_term'];
484 if ( isset( $default_term['default_term_enabled'] ) && $default_term['default_term_enabled'] ) {
485 $args['default_term'] = array();
486
487 if ( isset( $default_term['default_term_name'] ) && ! empty( $default_term['default_term_name'] ) ) {
488 $args['default_term']['name'] = (string) $default_term['default_term_name'];
489 }
490
491 if ( isset( $default_term['default_term_slug'] ) && ! empty( $default_term['default_term_slug'] ) ) {
492 $args['default_term']['slug'] = (string) $default_term['default_term_slug'];
493 }
494
495 if ( isset( $default_term['default_term_description'] ) && ! empty( $default_term['default_term_description'] ) ) {
496 $args['default_term']['description'] = (string) $default_term['default_term_description'];
497 }
498 }
499
500 // WordPress defaults to null, equivalent to false.
501 $sort = (bool) $post['sort'];
502 if ( $sort ) {
503 $args['sort'] = true;
504 }
505
506 return apply_filters( 'acf/taxonomy/registration_args', $args, $post );
507 }
508
509 /**
510 * Ensure the metabox being called does not perform any unsafe operations.
511 *
512 * @since ACF 6.3.8
513 *
514 * @param WP_Post $post The post being rendered.
515 * @param array $tax The provided taxonomy information required for callback render.
516 * @return mixed The callback result.
517 */
518 public function build_safe_context_for_metabox_cb( $post, $tax ) {
519 $taxonomies = $this->get_posts();
520 $this_tax = array_filter(
521 $taxonomies,
522 function ( $taxonomy ) use ( $tax ) {
523 return $taxonomy['taxonomy'] === $tax['args']['taxonomy'];
524 }
525 );
526 if ( empty( $this_tax ) || ! is_array( $this_tax ) ) {
527 // Unable to find the ACF taxonomy. Don't do anything.
528 return;
529 }
530 $acf_taxonomy = array_shift( $this_tax );
531 $original_cb = isset( $acf_taxonomy['meta_box_cb'] ) ? $acf_taxonomy['meta_box_cb'] : false;
532
533 // Prevent access to any wp_ prefixed functions in a callback.
534 if ( apply_filters( 'acf/taxonomy/prevent_access_to_wp_functions_in_meta_box_cb', true ) && substr( strtolower( $original_cb ), 0, 3 ) === 'wp_' ) {
535 // Don't execute register meta box callbacks if an internal wp function by default.
536 return;
537 }
538
539 $unset = array( '_POST', '_GET', '_REQUEST', '_COOKIE', '_SESSION', '_FILES', '_ENV', '_SERVER' );
540 $originals = array();
541
542 foreach ( $unset as $var ) {
543 if ( isset( $GLOBALS[ $var ] ) ) {
544 $originals[ $var ] = $GLOBALS[ $var ];
545 $GLOBALS[ $var ] = array(); //phpcs:ignore -- used for building a safe context
546 }
547 }
548
549 $return = false;
550 if ( is_callable( $original_cb ) ) {
551 $return = call_user_func( $original_cb, $post, $tax );
552 }
553
554 foreach ( $unset as $var ) {
555 if ( isset( $originals[ $var ] ) ) {
556 $GLOBALS[ $var ] = $originals[ $var ]; //phpcs:ignore -- used for restoring the original context
557 }
558 }
559
560 return $return;
561 }
562
563 /**
564 * Returns a string that can be used to create a taxonomy in PHP.
565 *
566 * @since ACF 6.1
567 *
568 * @param array $post The main taxonomy array.
569 * @return string
570 */
571 public function export_post_as_php( $post = array() ) {
572 $return = '';
573 if ( empty( $post ) ) {
574 return $return;
575 }
576
577 $post = $this->validate_post( $post );
578 $taxonomy_key = $post['taxonomy'];
579 $objects = (array) $post['object_type'];
580 $objects = var_export( $objects, true ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions -- Used for PHP export.
581 $args = $this->get_taxonomy_args( $post, false );
582 $args = var_export( $args, true ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions -- Used for PHP export.
583
584 if ( ! $args ) {
585 return $return;
586 }
587
588 $args = $this->format_code_for_export( $args );
589 $objects = $this->format_code_for_export( $objects );
590
591 $return .= "register_taxonomy( '{$taxonomy_key}', {$objects}, {$args} );\r\n";
592
593 return esc_textarea( $return );
594 }
595
596 /**
597 * Flush rewrite rules whenever anything changes about a taxonomy.
598 *
599 * @since ACF 6.1
600 *
601 * @param array $post The main post type array.
602 */
603 public function flush_post_cache( $post ) {
604 // Bail early if we won't be able to register/unregister the taxonomy.
605 if ( ! isset( $post['taxonomy'] ) ) {
606 return;
607 }
608
609 // Temporarily unregister the taxonomy so that we can re-register with the latest args below.
610 if ( empty( $post['active'] ) || taxonomy_exists( $post['taxonomy'] ) ) {
611 unregister_taxonomy( $post['taxonomy'] );
612 }
613
614 // When this is being called, the post type may not have been registered yet, so we do it now.
615 if ( ! empty( $post['active'] ) ) {
616 $post['object_type'] = isset( $post['object_type'] ) ? (array) $post['object_type'] : array();
617 register_taxonomy( $post['taxonomy'], $post['object_type'], $this->get_taxonomy_args( $post ) );
618 }
619
620 parent::flush_post_cache( $post );
621 flush_rewrite_rules();
622 }
623
624 /**
625 * Translates an ACF post.
626 *
627 * @since ACF 6.1
628 *
629 * @param array $post The field group array.
630 * @return array
631 */
632 public function translate_post( $post = array() ) {
633 // Get settings.
634 $l10n = acf_get_setting( 'l10n' );
635 $l10n_textdomain = acf_get_setting( 'l10n_textdomain' );
636
637 // Translate field settings if textdomain is set.
638 if ( $l10n && $l10n_textdomain ) {
639 $post['title'] = acf_translate( $post['title'] );
640 $post['description'] = acf_translate( $post['description'] );
641 foreach ( $post['labels'] as $key => $label ) {
642 $post['labels'][ $key ] = acf_translate( $label );
643 }
644
645 /**
646 * Filters the post array to translate strings.
647 *
648 * @date 12/02/2014
649 * @since ACF 5.0.0
650 *
651 * @param array $post The post array.
652 */
653 $post = apply_filters( "acf/translate_{$this->hook_name}", $post );
654 }
655
656 return $post;
657 }
658
659 /**
660 * Imports a taxonomy from CPTUI.
661 *
662 * @since ACF 6.1
663 *
664 * @param array $args Arguments from CPTUI.
665 * @return array
666 */
667 public function import_cptui_taxonomy( $args ) {
668 $acf_args = $this->get_settings_array();
669
670 // Convert string boolean values to proper booleans.
671 foreach ( $args as $key => $value ) {
672 if ( in_array( $value, array( 'true', 'false' ), true ) ) {
673 $args[ $key ] = filter_var( $value, FILTER_VALIDATE_BOOLEAN );
674 }
675 }
676
677 if ( isset( $args['name'] ) ) {
678 $acf_args['taxonomy'] = (string) $args['name'];
679 unset( $args['name'] );
680 }
681
682 if ( isset( $args['labels'] ) ) {
683 $acf_args['labels'] = array_merge( $acf_args['labels'], $args['labels'] );
684 unset( $args['labels'] );
685 }
686
687 // ACF uses "name" as title, and stores in labels array.
688 if ( isset( $args['label'] ) ) {
689 $acf_args['title'] = (string) $args['label'];
690 $acf_args['labels']['name'] = (string) $args['label'];
691 unset( $args['label'] );
692 }
693
694 if ( isset( $args['singular_label'] ) ) {
695 $acf_args['labels']['singular_name'] = (string) $args['singular_label'];
696 unset( $args['singular_label'] );
697 }
698
699 // ACF handles the meta_box_cb with two different settings.
700 if ( isset( $args['meta_box_cb'] ) ) {
701 if ( false === $args['meta_box_cb'] ) {
702 $acf_args['meta_box'] = 'disabled';
703 } elseif ( ! empty( $args['meta_box_cb'] ) ) {
704 $acf_args['meta_box'] = 'custom';
705 $acf_args['meta_box_cb'] = $args['meta_box_cb'];
706 }
707
708 unset( $args['meta_box_cb'] );
709 }
710
711 // ACF handles the query var and query var slug/name differently.
712 if ( isset( $args['query_var'] ) ) {
713 if ( ! $args['query_var'] ) {
714 $acf_args['query_var'] = 'none';
715 } elseif ( ! empty( $args['query_var_slug'] ) ) {
716 $acf_args['query_var'] = 'custom_query_var';
717 } else {
718 $acf_args['query_var'] = 'taxonomy_key';
719 }
720
721 unset( $args['query_var'] );
722 }
723
724 if ( isset( $args['query_var_slug'] ) ) {
725 $acf_args['query_var_name'] = (string) $args['query_var_slug'];
726 unset( $args['query_var_slug'] );
727 }
728
729 if ( isset( $args['rewrite'] ) ) {
730 $rewrite = (bool) $args['rewrite'];
731
732 if ( ! $rewrite ) {
733 $acf_args['rewrite']['permalink_rewrite'] = 'no_permalink';
734 } elseif ( ! empty( $args['rewrite_slug'] ) ) {
735 $acf_args['rewrite']['permalink_rewrite'] = 'custom_permalink';
736 } else {
737 $acf_args['rewrite']['permalink_rewrite'] = 'taxonomy_key';
738 }
739
740 unset( $args['rewrite'] );
741 }
742
743 if ( isset( $args['rewrite_slug'] ) ) {
744 $acf_args['rewrite']['slug'] = (string) $args['rewrite_slug'];
745 unset( $args['rewrite_slug'] );
746 }
747
748 if ( isset( $args['rewrite_withfront'] ) ) {
749 $acf_args['rewrite']['with_front'] = $args['rewrite_withfront'] === '1';
750 unset( $args['rewrite_withfront'] );
751 }
752
753 if ( isset( $args['rewrite_hierarchical'] ) ) {
754 $acf_args['rewrite']['rewrite_hierarchical'] = $args['rewrite_hierarchical'] === '1';
755 unset( $args['rewrite_hierarchical'] );
756 }
757
758 // CPTUI stores all default_term settings as comma separate values.
759 if ( isset( $args['default_term'] ) ) {
760 if ( '' !== $args['default_term'] ) {
761 $default_term = explode( ',', $args['default_term'] );
762 $default_term = array_map( 'trim', $default_term );
763
764 if ( isset( $default_term[0] ) ) {
765 $acf_args['default_term']['default_term_enabled'] = true;
766 $acf_args['default_term']['default_term_name'] = (string) $default_term[0];
767 }
768
769 if ( isset( $default_term[1] ) ) {
770 $acf_args['default_term']['default_term_slug'] = (string) $default_term[1];
771 }
772
773 if ( isset( $default_term[2] ) ) {
774 $acf_args['default_term']['default_term_description'] = (string) $default_term[2];
775 }
776 }
777
778 unset( $args['default_term'] );
779 }
780
781 if ( isset( $args['object_types'] ) ) {
782 $acf_args['object_type'] = $args['object_types'];
783 unset( $args['object_types'] );
784 }
785
786 $acf_args = wp_parse_args( $args, $acf_args );
787 $acf_args['key'] = uniqid( 'taxonomy_' );
788 $acf_args['advanced_configuration'] = true;
789 $acf_args['import_source'] = 'cptui';
790 $acf_args['import_date'] = time();
791
792 $existing_taxonomies = acf_get_acf_taxonomies();
793
794 foreach ( $existing_taxonomies as $existing_taxonomy ) {
795 // Taxonomy already exists, so we need to update rather than import.
796 if ( $acf_args['taxonomy'] === $existing_taxonomy['taxonomy'] ) {
797 $acf_args = $this->prepare_post_for_import( $acf_args );
798 $acf_args['ID'] = $existing_taxonomy['ID'];
799 $acf_args['key'] = $existing_taxonomy['key'];
800 return $this->update_post( $acf_args );
801 }
802 }
803
804 return $this->import_post( $acf_args );
805 }
806 }
807
808 }
809
810 acf_new_instance( 'ACF_Taxonomy' );
811