How to customize the term list in your WordPress admin

There are many reference articles about posts and custom post types in WordPress management screen customization, but there was little customization information on the term list screen, so I summarized it.
In particular, the ability to add a term list refinement is a must-see.

Prerequisites

  • Verified WordPress version is 5.7.1.
  • The term used is the category of the post.
  • We are using Advanced Custom Fields PRO to add input fields to the term.
    The items you added are being narrowed down.
    As an example, a custom field called "Authentication" is set, and the values "OK (OK)", "NG (ng)" and "unconfirmed" can be selected by Select.

Add a column to the term list

function add_taxonomy_category_columns($columns)
{
    $column_slug = $columns['slug'];
    $column_posts = $columns['posts'];

unset($columns['slug']);
    unset($columns['posts']);

$columns['authentication'] = __('Authentication');
    $columns['slug'] = $column_slug;
    $columns['posts'] = $column_posts;

return $columns;
}
add_filter('manage_edit-category_columns', 'add_taxonomy_category_columns');

function custom_taxonomy_category_column($content, $column_name, $term_id)
{
    if ($column_name == 'authentication') {
        $authentication = get_term_meta($term_id, 'authentication', true);

switch ($authentication) {
            case 'ok':
                echo '<span class="fc-ok">'. __('OK'). '</span>';
                break;
            case 'ng':
                echo '<span class="fc-ng">'. __('NG'). '</span>';
                break;
            case 'unconfirmed':
            default:
                echo '<span class="fc-unconfirmed">'. __('unconfirmed'). '</span>';
        }
    }
}
add_action('manage_category_custom_column', 'custom_taxonomy_category_column', 10, 3);

add_taxonomy_category_columns

Use this function to set the column headings for a list. $columns['slug'] unset $columns['posts'] to change the order of the columns.

add_filter('manage_edit-category_columns', 'add_taxonomy_category_columns');

When using this filter, the "manage_edit-category_columns" part becomes "manage_edit-{Term Slug} _columns".

When setting it as a tag of a post, it will be "manage_edit-post_tag_columns".

custom_taxonomy_category_column

This function specifies what is displayed in each row of the term list. The display is sorted according to the contents contained in the custom field.

add_action('manage_category_custom_column', 'custom_taxonomy_category_column', 10, 3);

When using this filter, the "manage_category_custom_column" part becomes "manage_{Term Slug}_custom_column".

When setting it as a tag of a post, it becomes "manage_post_tag_custom_column".

Add a filter at the top of the term list

function views_edit_category($views)
{
    $post_type = 'post';
    $taxonomy = 'category';
    
$types = array(
        array('authentication' => NULL),
        array('authentication' => 'ok'),
        array('authentication' => 'ng'),
        array('authentication' => 'unconfirmed')
    );

remove_filter('pre_get_terms', 'pre_get_terms_edit_category');
    
foreach ($types as $type) {

$query = array(
            Specify taxonomy (custom classification)
            'taxonomy' => array($taxonomy),
            Also get terms without posts (categories with custom taxonomies)
            'hide_empty' => false,
            'fields' => 'count',
        );
        if ($type['authentication']) {
            $query['meta_query'] = array(
                array(
                    'key' => 'authentication',
                    'value' => $type['authentication'],
                )
            );
        }
        
$result = get_terms($query);
        
if ($type['authentication'] == NULL):
            $class = (empty($_GET['authentication'])) ? ' class="current"' : '';
            $views['all'] = sprintf(__('<a href="%s"' . $class . '>' . __('All') . ' <span class="count">(%d)</span></ a>', 'all'),
                admin_url('edit-tags.php?taxonomy='. $taxonomy. '&post_type='. $post_type),
                $result);
        elseif ($type['authentication'] == 'ok'):
            $class = (!empty($_GET['authentication']) && $_GET['authentication'] == 'ok') ? ' class="current"' : '';
            $views['ok'] = sprintf(__('<a href="%s"' . $class . '>' . __('OK') . ' <span class="count">(%d)</span></ a>', 'publish'),
                admin_url('edit-tags.php?taxonomy='. $taxonomy. '&post_type='. $post_type. '&authentication=' . $type['authentication']),
                $result);
        elseif ($type['authentication'] == 'ng'):
            $class = (!empty($_GET['authentication']) && $_GET['authentication'] == 'ng') ? ' class="current"' : '';
            $views['ng'] = sprintf(__('<a href="%s"' . $class . '>' . __('NG') . ((sizeof($result) > 1) ? "s" : "") . ' <span class="count">(%d)</span></a>', 'draft'),
                admin_url('edit-tags.php?taxonomy='. $taxonomy. '&post_type='. $post_type. '&authentication=' . $type['authentication']),
                $result);
        elseif ($type['authentication'] == 'unconfirmed'):
            $class = (!empty($_GET['authentication']) && $_GET['authentication'] == 'unconfirmed') ? ' class="current"' : '';
            $views['unconfirmed'] = sprintf(__('<a href="%s"' . $class . '>' . __('unconfirmed') . ' <span class="count">(%d)</span ></a>', 'pending'),
                admin_url('edit-tags.php?taxonomy='. $taxonomy. '&post_type='. $post_type. '&authentication=' . $type['authentication']),
                $result);
        endif;
    }

add_filter('pre_get_terms', 'pre_get_terms_edit_category');
    
return $views;
}
add_filter('views_edit-category', 'views_edit_category');

function pre_get_terms_edit_category($query)
{
    if(is_admin() && (!get_current_screen() || get_current_screen()->id != 'edit-tag')) {
        return;
    }
    
if ($_GET['authentication']) {
        $meta_query = array(
            array(
                'key' => 'authentication',
                'value' => $_GET['authentication'],
            )
        );
        $query->query_vars['meta_query'] = $meta_query;
    }
}
add_filter('pre_get_terms',  'pre_get_terms_edit_category');

views_edit_category($views)

Use this function to display the filters at the top of the term list.
The points are remove_filter('pre_get_terms', ' pre_get_terms_edit_category'); and add_filter(' pre_get_terms', 'pre_get_terms_edit_ category'); Are.
Remove the filters described below before proceeding, and add them at the end.
This filter is because it affects the main_query and gets in the way of processing.

add_filter('views_edit-category', 'views_edit_category');

When using this filter, the "views_edit-category" part becomes "views_edit-{term slug}".

When setting it as a tag of a post, it becomes "views_edit-post_tag".

pre_get_terms_edit_category($query)

This function will narrow down the term list.
If a parameter exists that you want to use for refinement, add a refiner to $query->query_vars['meta_query'] .

add_filter('pre_get_terms', 'pre_get_terms_edit_category');

This filter interrupts processing before getting the term list. Set refiner criteria at that time.

Reference site

manage_{$screen->id}_columns – Hook | Developer.WordPress.org
Filters the column headers for a list table on a specific screen.
manage_{$this->screen->taxonomy}_custom_column – Hook | Developer.WordPress.org
Filters the displayed columns in the terms list table.
views_{$this->screen->id} – Hook | Developer.WordPress.org
Filters the list of available list table views.
pre_get_terms – Hook | Developer.WordPress.org
Fires before terms are retrieved.