PluginProbe ʕ •ᴥ•ʔ
Advanced Custom Fields (ACF®) / 6.8.9
Advanced Custom Fields (ACF®) v6.8.9
6.8.9 6.8.8 6.8.7 6.8.6 6.8.5 6.8.4 6.8.3 6.8.2 6.8.1 5.8.5 5.8.6 5.8.7 5.8.8 5.8.9 5.9.0 5.9.1 5.9.2 5.9.3 5.9.4 5.9.5 5.9.6 5.9.7 5.9.8 5.9.9 6.0.0 6.0.1 6.0.2 6.0.3 6.0.4 6.0.5 6.0.6 6.0.7 6.1.0 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.1.6 6.1.7 6.1.8 6.2.0 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.2.6 6.2.6.1 6.2.7 6.2.8 6.2.9 6.3.0 6.3.1 6.3.10.2 6.3.11 6.3.12 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.6.1 6.4.0 6.4.0.1 6.4.1 6.4.2 6.4.3 6.5.0 6.5.1 6.6.0 6.6.1 6.6.2 6.7.0 6.7.1 6.7.2 6.8.0 trunk 1.0.0 1.0.2 1.0.3 1.0.5 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.1.1 2.1.3 2.1.4 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.6 3.0.7 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 3.2.0 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.2.8 3.2.9 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9 3.4.0 3.4.1 3.4.2 3.4.3 3.5.0 3.5.1 3.5.2 3.5.3 3.5.4 3.5.5 3.5.6 3.5.7 3.5.8 4.0.0 4.0.1 4.0.2 4.0.3 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.1.5 4.1.6 4.1.8 4.2.0 4.2.1 4.2.2 4.3.0 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.3.7 4.3.8 4.3.9 4.4.0 4.4.1 4.4.10 4.4.11 4.4.12 4.4.2 4.4.3 4.4.4 4.4.5 4.4.6 4.4.7 4.4.8 4.4.9 5.10 5.10.1 5.10.2 5.11 5.11.1 5.11.2 5.11.3 5.11.4 5.12 5.12.1 5.12.2 5.12.3 5.12.4 5.12.5 5.12.6 5.6.10 5.6.2 5.6.3 5.6.4 5.6.5 5.6.6 5.6.7 5.6.8 5.6.9 5.7.0 5.7.1 5.7.10 5.7.12 5.7.13 5.7.2 5.7.3 5.7.4 5.7.5 5.7.6 5.7.7 5.7.8 5.7.9 5.8.0 5.8.1 5.8.10 5.8.11 5.8.12 5.8.13 5.8.14 5.8.2 5.8.3 5.8.4
advanced-custom-fields / includes / admin / post-types / admin-taxonomies.php
advanced-custom-fields / includes / admin / post-types Last commit date
admin-field-group.php 5 months ago admin-field-groups.php 6 months ago admin-post-type.php 6 months ago admin-post-types.php 6 months ago admin-taxonomies.php 6 months ago admin-taxonomy.php 6 months ago index.php 2 years ago
admin-taxonomies.php
364 lines
1 <?php
2 /**
3 * @package ACF
4 * @author WP Engine
5 *
6 * © 2026 Advanced Custom Fields (ACF®). All rights reserved.
7 * "ACF" is a trademark of WP Engine.
8 * Licensed under the GNU General Public License v2 or later.
9 * https://www.gnu.org/licenses/gpl-2.0.html
10 */
11
12 if ( ! defined( 'ABSPATH' ) ) {
13 exit; // Exit if accessed directly.
14 }
15
16 if ( ! class_exists( 'ACF_Admin_Taxonomies' ) ) :
17
18 /**
19 * The ACF Post Types admin controller class
20 */
21 class ACF_Admin_Taxonomies extends ACF_Admin_Internal_Post_Type_List {
22
23 /**
24 * The slug for the internal post type.
25 *
26 * @var string
27 */
28 public $post_type = 'acf-taxonomy';
29
30 /**
31 * The admin body class used for the post type.
32 *
33 * @var string
34 */
35 public $admin_body_class = 'acf-admin-taxonomies';
36
37 /**
38 * The name of the store used for the post type.
39 *
40 * @var string
41 */
42 public $store = 'taxonomies';
43
44 /**
45 * Constructor.
46 * @since 6.2
47 */
48 public function __construct() {
49 add_action( 'admin_menu', array( $this, 'admin_menu' ), 9 );
50 parent::__construct();
51 }
52
53 /**
54 * Current screen actions for the taxonomies list admin page.
55 *
56 * @since 6.1
57 */
58 public function current_screen() {
59 // Bail early if not post types admin page.
60 if ( ! acf_is_screen( "edit-{$this->post_type}" ) ) {
61 return;
62 }
63
64 parent::current_screen();
65
66 // Run a first-run routine to set some defaults which are stored in user preferences.
67 if ( ! acf_get_user_setting( 'taxonomies-first-run', false ) ) {
68 $option_key = 'manageedit-' . $this->post_type . 'columnshidden';
69 $hidden_items = get_user_option( $option_key );
70
71 if ( ! is_array( $hidden_items ) ) {
72 $hidden_items = array();
73 }
74
75 if ( ! in_array( 'acf-key', $hidden_items ) ) {
76 $hidden_items[] = 'acf-key';
77 }
78 update_user_option( get_current_user_id(), $option_key, $hidden_items, true );
79
80 acf_update_user_setting( 'taxonomies-first-run', true );
81 }
82 }
83
84 /**
85 * Add any menu items required for taxonomies.
86 *
87 * @since 6.1
88 */
89 public function admin_menu() {
90 $parent_slug = 'edit.php?post_type=acf-field-group';
91 $cap = acf_get_setting( 'capability' );
92 add_submenu_page( $parent_slug, __( 'Taxonomies', 'acf' ), __( 'Taxonomies', 'acf' ), $cap, 'edit.php?post_type=acf-taxonomy' );
93 }
94
95 /**
96 * Customizes the admin table columns.
97 *
98 * @date 1/4/20
99 * @since 5.9.0
100 *
101 * @param array $_columns The columns array.
102 * @return array
103 */
104 public function admin_table_columns( $_columns ) {
105 // Set the "no found" label to be our custom HTML for no results.
106 if ( empty( acf_request_arg( 's' ) ) ) {
107 global $wp_post_types;
108 $wp_post_types[ $this->post_type ]->labels->not_found = $this->get_not_found_html();
109 }
110
111 $columns = array(
112 'cb' => $_columns['cb'],
113 'title' => $_columns['title'],
114 'acf-description' => __( 'Description', 'acf' ),
115 'acf-key' => __( 'Key', 'acf' ),
116 'acf-post-types' => __( 'Post Types', 'acf' ),
117 'acf-field-groups' => __( 'Field Groups', 'acf' ),
118 'acf-count' => __( 'Terms', 'acf' ),
119 );
120
121 if ( acf_get_local_json_files( $this->post_type ) ) {
122 $columns['acf-json'] = __( 'Local JSON', 'acf' );
123 }
124
125 return $columns;
126 }
127
128 /**
129 * Renders a specific admin table column.
130 *
131 * @date 17/4/20
132 * @since 5.9.0
133 *
134 * @param string $column_name The name of the column to display.
135 * @param array $post The main ACF post array.
136 * @return void
137 */
138 public function render_admin_table_column( $column_name, $post ) {
139 switch ( $column_name ) {
140 case 'acf-key':
141 echo '<i class="acf-icon acf-icon-key-solid"></i>';
142 echo esc_html( $post['key'] );
143 break;
144
145 // Description.
146 case 'acf-description':
147 if ( ( is_string( $post['description'] ) || is_numeric( $post['description'] ) ) && ! empty( $post['description'] ) ) {
148 echo '<span class="acf-description">' . acf_esc_html( $post['description'] ) . '</span>';
149 } else {
150 echo '<span class="acf-emdash" aria-hidden="true">—</span>';
151 echo '<span class="screen-reader-text">' . esc_html__( 'No description', 'acf' ) . '</span>';
152 }
153 break;
154
155 case 'acf-field-groups':
156 $this->render_admin_table_column_field_groups( $post );
157 break;
158
159 case 'acf-post-types':
160 $this->render_admin_table_column_post_types( $post );
161 break;
162
163 case 'acf-count':
164 $this->render_admin_table_column_num_terms( $post );
165 break;
166
167 // Local JSON.
168 case 'acf-json':
169 $this->render_admin_table_column_local_status( $post );
170 break;
171 }
172 }
173
174 /**
175 * Renders the field groups attached to the taxonomy in the list table.
176 *
177 * @since 6.1
178 *
179 * @param array $taxonomy The main taxonomy array.
180 * @return void
181 */
182 public function render_admin_table_column_field_groups( $taxonomy ) {
183 $field_groups = acf_get_field_groups( array( 'taxonomy' => $taxonomy['taxonomy'] ) );
184
185 if ( empty( $field_groups ) ) {
186 echo '<span class="acf-emdash" aria-hidden="true">—</span>';
187 echo '<span class="screen-reader-text">' . esc_html__( 'No field groups', 'acf' ) . '</span>';
188 return;
189 }
190
191 $labels = wp_list_pluck( $field_groups, 'title' );
192 $limit = 3;
193 $shown_labels = array_slice( $labels, 0, $limit );
194 $hidden_labels = array_slice( $labels, $limit );
195 $text = implode( ', ', $shown_labels );
196
197 if ( ! empty( $hidden_labels ) ) {
198 $text .= ', <span class="acf-more-items acf-js-tooltip" title="' . implode( ', ', $hidden_labels ) . '">+' . count( $hidden_labels ) . '</span>';
199 }
200
201 echo acf_esc_html( $text );
202 }
203
204 /**
205 * Renders the post types attached to the taxonomy in the list table.
206 *
207 * @since 6.1
208 *
209 * @param array $taxonomy The main taxonomy array.
210 * @return void
211 */
212 public function render_admin_table_column_post_types( $taxonomy ) {
213 $post_types = get_post_types( array(), 'objects' );
214 $labels = array();
215 $object_types = array();
216
217 if ( ! empty( $taxonomy['object_type'] ) ) {
218 $object_types = (array) $taxonomy['object_type'];
219 }
220
221 foreach ( $object_types as $post_type_slug ) {
222 if ( ! isset( $post_types[ $post_type_slug ] ) ) {
223 continue;
224 }
225
226 $post_type = $post_types[ $post_type_slug ];
227
228 if ( empty( $post_type->label ) ) {
229 continue;
230 }
231
232 $labels[] = $post_type->label;
233 }
234
235 $acf_post_types = acf_get_internal_post_type_posts( 'acf-post-type' );
236
237 foreach ( $acf_post_types as $acf_post_type ) {
238 if ( is_array( $acf_post_type['taxonomies'] ) && in_array( $taxonomy['taxonomy'], $acf_post_type['taxonomies'], true ) ) {
239 $labels[] = $acf_post_type['title'];
240 }
241 }
242
243 if ( empty( $labels ) ) {
244 echo '<span class="acf-emdash" aria-hidden="true">—</span>';
245 echo '<span class="screen-reader-text">' . esc_html__( 'No post types', 'acf' ) . '</span>';
246 return;
247 }
248
249 $labels = array_unique( $labels );
250 $limit = 3;
251 $shown_labels = array_slice( $labels, 0, $limit );
252 $hidden_labels = array_slice( $labels, $limit );
253 $text = implode( ', ', $shown_labels );
254
255 if ( ! empty( $hidden_labels ) ) {
256 $text .= ', <span class="acf-more-items acf-js-tooltip" title="' . implode( ', ', $hidden_labels ) . '">+' . count( $hidden_labels ) . '</span>';
257 }
258
259 echo acf_esc_html( $text );
260 }
261
262 /**
263 * Renders the number of terms created for the taxonomy in the list table.
264 *
265 * @since 6.1
266 *
267 * @param array $taxonomy The main taxonomy array.
268 * @return void
269 */
270 public function render_admin_table_column_num_terms( $taxonomy ) {
271 $no_terms = '<span class="acf-emdash" aria-hidden="true">—</span>';
272 $no_terms .= '<span class="screen-reader-text">' . esc_html__( 'No terms', 'acf' ) . '</span>';
273
274 // WP doesn't count terms for taxonomies that don't exist and instead returns WP_Error.
275 if ( empty( $taxonomy['active'] ) || 'trash' === get_post_status( $taxonomy['ID'] ) ) {
276 echo acf_esc_html( $no_terms );
277 return;
278 }
279
280 $num_terms = wp_count_terms(
281 array(
282 'taxonomy' => $taxonomy['taxonomy'],
283 'hide_empty' => false,
284 'parent' => 0,
285 )
286 );
287
288 if ( ! $num_terms || ! is_numeric( $num_terms ) ) {
289 echo acf_esc_html( $no_terms );
290 return;
291 }
292
293 printf(
294 '<a href="%s">%s</a>',
295 esc_url( admin_url( 'edit-tags.php?taxonomy=' . $taxonomy['taxonomy'] ) ),
296 esc_html( number_format_i18n( $num_terms ) )
297 );
298 }
299
300 /**
301 * Gets the translated action notice text for list table actions (activate, deactivate, sync, etc.).
302 *
303 * @since 6.1
304 *
305 * @param string $action The action being performed.
306 * @param integer $count The number of items the action was performed on.
307 * @return string
308 */
309 public function get_action_notice_text( $action, $count = 1 ) {
310 $text = '';
311 $count = (int) $count;
312
313 switch ( $action ) {
314 case 'acfactivatecomplete':
315 $text = sprintf(
316 /* translators: %s number of taxonomies activated */
317 _n( 'Taxonomy activated.', '%s taxonomies activated.', $count, 'acf' ),
318 $count
319 );
320 break;
321 case 'acfdeactivatecomplete':
322 $text = sprintf(
323 /* translators: %s number of taxonomies deactivated */
324 _n( 'Taxonomy deactivated.', '%s taxonomies deactivated.', $count, 'acf' ),
325 $count
326 );
327 break;
328 case 'acfduplicatecomplete':
329 $text = sprintf(
330 /* translators: %s number of taxonomies duplicated */
331 _n( 'Taxonomy duplicated.', '%s taxonomies duplicated.', $count, 'acf' ),
332 $count
333 );
334 break;
335 case 'acfsynccomplete':
336 $text = sprintf(
337 /* translators: %s number of taxonomies synchronized */
338 _n( 'Taxonomy synchronized.', '%s taxonomies synchronized.', $count, 'acf' ),
339 $count
340 );
341 break;
342 }
343
344 return $text;
345 }
346
347 /**
348 * Returns the registration error state.
349 *
350 * @since 6.1
351 *
352 * @return string
353 */
354 public function get_registration_error_state() {
355 return '<span class="acf-js-tooltip dashicons dashicons-warning" title="' .
356 __( 'This taxonomy could not be registered because its key is in use by another taxonomy registered by another plugin or theme.', 'acf' ) .
357 '"></span> ' . _x( 'Registration Failed', 'post status', 'acf' );
358 }
359 }
360
361 // Instantiate.
362 acf_new_instance( 'ACF_Admin_Taxonomies' );
363 endif; // Class exists check.
364