How to get non hierarchal taxonomies, like tags, to have a checkbox system like a hierarchal taxonomy like categories.
Place the following in a plugin or your theme’s function file. All you have to do is change the last lines CUSTOM_TAXONOMY and CUSTOM_POST_TYPE to meet your needs.
<?php
class Tag_Checklist {
private $taxonomy;
private $post_type;
function __construct( $taxonomy, $post_type ) {
$this->taxonomy = $taxonomy;
$this->post_type = $post_type;
// Remove default taxonomy meta box
add_action( 'admin_menu', array( $this, 'remove_meta_box' ) );
// Add new meta box
add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
// Handle Ajax call for adding new term
add_action( 'wp_ajax_add-' . $this->taxonomy , '_wp_ajax_add_non_hierarchical_term' );
}
/**
* Remove default meta box
* @return void
*/
public function remove_meta_box() {
remove_meta_box('tagsdiv-' . $this->taxonomy, $this->post_type, 'normal');
}
/**
* Add new metabox
* @return void
*/
public function add_meta_box() {
$tax = get_taxonomy( $this->taxonomy );
add_meta_box( 'taglist-' . $this->taxonomy, $tax->labels->name, array( $this, 'metabox_content' ), $this->post_type, 'side', 'core' );
}
/**
* Generate metabox content
* @param obj $post Post object
* @return void
*/
public function metabox_content( $post ) {
$taxonomy = $this->taxonomy;
$tax = get_taxonomy( $taxonomy );
?>
<div id="taxonomy-<?php echo $taxonomy; ?>" class="categorydiv">
<ul id="<?php echo $taxonomy; ?>-tabs" class="category-tabs">
<li class="tabs"><a href="#<?php echo $taxonomy; ?>-all"><?php echo $tax->labels->all_items; ?></a></li>
<li class="hide-if-no-js"><a href="#<?php echo $taxonomy; ?>-pop"><?php _e( 'Most Used' ); ?></a></li>
</ul>
<div id="<?php echo $taxonomy; ?>-pop" class="tabs-panel" style="display: none;">
<ul id="<?php echo $taxonomy; ?>checklist-pop" class="categorychecklist form-no-clear" >
<?php $popular_ids = wp_popular_terms_checklist( $taxonomy ); ?>
</ul>
</div>
<div id="<?php echo $taxonomy; ?>-all" class="tabs-panel">
<input type="hidden" name="tax_input[<?php echo $taxonomy; ?>][]" value="0" />
<?php
if( class_exists( 'Walker_Tag_Checklist' ) ) {
$walker = new Walker_Tag_Checklist;
}
?>
<ul id="<?php echo $taxonomy; ?>checklist" data-wp-lists="list:<?php echo $taxonomy; ?>" class="categorychecklist form-no-clear">
<?php wp_terms_checklist($post->ID, array( 'taxonomy' => $taxonomy, 'popular_cats' => $popular_ids , 'walker' => $walker ) ) ?>
</ul>
</div>
<?php if ( current_user_can($tax->cap->edit_terms) ) : ?>
<div id="<?php echo $taxonomy; ?>-adder" class="wp-hidden-children">
<h4>
<a id="<?php echo $taxonomy; ?>-add-toggle" href="#<?php echo $taxonomy; ?>-add" class="hide-if-no-js">
<?php
/* translators: %s: add new taxonomy label */
printf( __( '+ %s' ), $tax->labels->add_new_item );
?>
</a>
</h4>
<p id="<?php echo $taxonomy; ?>-add" class="category-add wp-hidden-child">
<label class="screen-reader-text" for="new<?php echo $taxonomy; ?>"><?php echo $tax->labels->add_new_item; ?></label>
<input type="text" name="new<?php echo $taxonomy; ?>" id="new<?php echo $taxonomy; ?>" class="form-required form-input-tip" value="<?php echo esc_attr( $tax->labels->new_item_name ); ?>" aria-required="true"/>
<input type="button" id="<?php echo $taxonomy; ?>-add-submit" data-wp-lists="add:<?php echo $taxonomy ?>checklist:<?php echo $taxonomy ?>-add" class="button category-add-submit" value="<?php echo esc_attr( $tax->labels->add_new_item ); ?>" />
<?php wp_nonce_field( 'add-'.$taxonomy, '_ajax_nonce-add-'.$taxonomy, false ); ?>
<span id="<?php echo $taxonomy; ?>-ajax-response"></span>
</p>
</div>
<?php endif; ?>
</div>
<?php
}
}
/**
* Mod of WP's Walker_Category_Checklist class
*/
class Walker_Tag_Checklist extends Walker {
var $tree_type = 'tag';
var $db_fields = array ('parent' => 'parent', 'id' => 'term_id');
function start_lvl( &$output, $depth = 0, $args = array() ) {
$indent = str_repeat("\t", $depth);
$output .= "$indent<ul class='children'>\n";
}
function end_lvl( &$output, $depth = 0, $args = array() ) {
$indent = str_repeat("\t", $depth);
$output .= "$indent</ul>\n";
}
function start_el( &$output, $tax_term, $depth, $args, $id = 0 ) {
extract($args);
if ( empty($taxonomy) )
$taxonomy = 'tag';
if ( $taxonomy == 'tag' )
$name = 'post_tag';
else
$name = 'tax_input['.$taxonomy.']';
$class = in_array( $tax_term->term_id, $popular_cats ) ? ' class="popular-category"' : '';
$output .= "\n<li id='{$taxonomy}-{$tax_term->term_id}'$class>" . '<label class="selectit"><input value="' . $tax_term->slug . '" type="checkbox" name="'.$name.'[]" id="in-'.$taxonomy.'-' . $tax_term->term_id . '"' . checked( in_array( $tax_term->term_id, $selected_cats ), true, false ) . disabled( empty( $args['disabled'] ), false, false ) . ' /> ' . esc_html( apply_filters('the_category', $tax_term->name )) . '</label>';
}
function end_el( &$output, $tax_term, $depth = 0, $args = array() ) {
$output .= "</li>\n";
}
}
if( ! function_exists( '_wp_ajax_add_non_hierarchical_term' ) ) {
/**
* Mod of _wp_ajax_add_hierarchical_term to handle non-hierarchical taxonomies
* @return void
*/
function _wp_ajax_add_non_hierarchical_term() {
$action = $_POST['action'];
$taxonomy = get_taxonomy( substr( $action, 4 ) );
check_ajax_referer( $action, '_ajax_nonce-add-' . $taxonomy->name );
if ( !current_user_can( $taxonomy->cap->edit_terms ) )
wp_die( -1 );
$names = explode( ',', $_POST['new'.$taxonomy->name] );
$parent = 0;
if ( $taxonomy->name == 'category' )
$post_category = isset( $_POST['post_category'] ) ? (array) $_POST['post_category'] : array();
else
$post_category = ( isset( $_POST['tax_input'] ) && isset( $_POST['tax_input'][$taxonomy->name] ) ) ? (array) $_POST['tax_input'][$taxonomy->name] : array();
$checked_categories = array_map( 'absint', (array) $post_category );
$popular_ids = wp_popular_terms_checklist( $taxonomy->name, 0, 10, false );
// Set up custom walker
$walker = false;
if( class_exists( 'Walker_Tag_Checklist' ) ) {
$walker = new Walker_Tag_Checklist;
}
foreach ( $names as $tax_name ) {
$tax_name = trim( $tax_name );
$category_nicename = sanitize_title( $tax_name );
if ( '' === $category_nicename )
continue;
if ( ! $cat_id = term_exists( $tax_name, $taxonomy->name, $parent ) )
$cat_id = wp_insert_term( $tax_name, $taxonomy->name, array( 'parent' => $parent ) );
if ( is_wp_error( $cat_id ) )
continue;
else if ( is_array( $cat_id ) )
$cat_id = $cat_id['term_id'];
$checked_categories[] = $cat_id;
if ( $parent ) // Do these all at once in a second
continue;
ob_start();
$args = array(
'taxonomy' => $taxonomy->name,
'selected_cats' => $checked_categories,
'popular_cats' => $popular_ids,
'checked_ontop' => true
);
if( $walker ) {
$args['walker'] = $walker;
}
wp_terms_checklist( 0, $args );
$data = ob_get_contents();
ob_end_clean();
$add = array(
'what' => $taxonomy->name,
'id' => $cat_id,
'data' => str_replace( array("\n", "\t"), '', $data ),
'position' => -1
);
}
$x = new WP_Ajax_Response( $add );
$x->send();
}
}
new Tag_Checklist( 'CUSTOM_TAXONOMY', 'CUSTOM_POST_TYPE' );