Register taxonomy with sortable column and filter added automatically
<?php
/*
Plugin Name: Add Custom Taxonomies
Plugin URI: #
Description: Adds custom taxonomies with columns and filters
Author: PIE
Version: 1.0
Author URI: pie.co.de
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
if ( ! class_exists( 'PIE_Add_Custom_Taxonomies' ) ) {
/**
* Class PIE_Add_Custom_Taxonomies
*/
class PIE_Add_Custom_Taxonomies {
/**
* Taxonomies to register
*
* @var array
*/
public $taxonomies = array();
/**
* PIE_Add_Custom_Taxonomies constructor.
*
* @param array $taxonomies
*/
public function __construct( $taxonomies ) {
$this->taxonomies = $taxonomies;
$this->init();
}
/**
* Initialise Plugin.
*/
public function init() {
// Register taxonomies
add_action( 'init', array( $this, 'register_custom_taxonomies' ) );
// Add columns
add_filter( 'manage_edit-product_columns', array( $this, 'add_column_headers' ) );
add_action( 'manage_product_posts_custom_column', array( $this, 'add_column_values' ), 10, 2 );
add_filter( 'manage_edit-product_sortable_columns', array( $this, 'make_columns_sortable' ) );
add_filter( 'posts_clauses', array( $this, 'sort_columns' ), 10, 2 );
// Add filter
add_action( 'restrict_manage_posts', array( $this, 'add_filters' ) );
}
/**
* Register custom taxonomies
*/
public function register_custom_taxonomies() {
foreach ( $this->taxonomies as $post_type => $taxonomy ) {
$this->register_taxonomy( $taxonomy, $post_type );
}
}
/**
* Register custom taxonomy
*
* @param string $taxonomy Taxonomy name
* @param string $post_type Post type to register to
*/
public function register_taxonomy( $taxonomy, $post_type ) {
$name = ucwords( str_replace( '-', ' ', $taxonomy ) );
$name_plural = $name . 's';
$labels = array(
'name' => $name_plural,
'singular_name' => $name,
'menu_name' => $name,
'all_items' => 'All ' . $name_plural,
'parent_item' => 'Parent ' . $name,
'parent_item_colon' => 'Parent ' . $name . ':',
'new_item_name' => 'New ' . $name . ' Name',
'add_new_item' => 'Add New ' . $name,
'edit_item' => 'Edit ' . $name,
'update_item' => 'Update ' . $name,
'separate_items_with_commas' => 'Separate ' . $name . ' with commas',
'search_items' => 'Search ' . $name_plural,
'add_or_remove_items' => 'Add or remove ' . $name_plural,
'choose_from_most_used' => 'Choose from the most used ' . $name_plural,
);
$args = array(
'labels' => $labels,
'hierarchical' => true,
'public' => true,
'show_ui' => true,
'show_admin_column' => false,
'show_in_nav_menus' => true,
'show_tagcloud' => true,
);
register_taxonomy( $taxonomy, $post_type, $args );
}
/**
* Add custom taxonomy column headers
*
* @param $defaults
*
* @return mixed
*/
public function add_column_headers( $defaults ) {
foreach ( $this->taxonomies as $taxonomy ) {
$name = ucwords( str_replace( '-', ' ', $taxonomy ) );
$name_plural = $name . 's';
$defaults[ $taxonomy ] = $name_plural;
}
return $defaults;
}
/**
* Add custom taxonomy column values
*
* @param $column_name
* @param $post_id
*/
public function add_column_values( $column_name, $post_id ) {
foreach ( $this->taxonomies as $taxonomy ) {
if ( $column_name == $taxonomy ) {
$terms = get_the_terms( $post_id, $taxonomy );
if ( is_array( $terms ) ) {
foreach ( $terms as $term ) {
echo '<a href="' . get_edit_term_link( $term->term_id, $taxonomy ) . '" rel="tag">' . $term->name . '</a>' . PHP_EOL;
}
}
}
}
}
/**
* Make column sortable
*
* @param $columns
*
* @return mixed
*/
public function make_columns_sortable( $columns ) {
foreach ( $this->taxonomies as $taxonomy ) {
$columns[ $taxonomy ] = $taxonomy;
}
return $columns;
}
/**
* Sort custom taxonomy columns as required
*
* @param $clauses
* @param $wp_query
*
* @return array
*
*/
public function sort_columns( $pieces, $query ) {
if ( ! is_admin() || ! $query->is_main_query() ) {
return $pieces;
}
foreach ( $this->taxonomies as $taxonomy ) {
global $wpdb;
if ( ( $orderby = $query->get( 'orderby' ) ) == $taxonomy ) {
if ( ( $order = strtoupper( $query->get( 'order' ) ) ) != 'DESC' ) {
$order = 'ASC';
}
$pieces['join'] .= ' LEFT JOIN ' . $wpdb->term_relationships . ' AS tr ON ' . $wpdb->posts . '.ID = tr.object_id' . ' LEFT JOIN ' . $wpdb->term_taxonomy . ' AS tt ON tr.term_taxonomy_id = tt.term_taxonomy_id' . ' LEFT JOIN ' . $wpdb->terms . ' AS t ON tt.term_id = t.term_id';
$pieces['fields'] .= ', group_concat(t.name ORDER BY t.name ' . $order . ') AS ' . $orderby;
$pieces['where'] .= ' AND ( tt.taxonomy = "distributor" OR tt.taxonomy IS NULL ) ';
$pieces['groupby'] = $wpdb->posts . '.ID';
$pieces['orderby'] = $orderby . ' ' . $order . ', ' . $wpdb->posts . '.post_title ASC';
}
}
return $pieces;
}
/**
* Add filter for custom taxonomies
*/
public function add_filters() {
global $typenow;
if ( array_key_exists( $typenow, $this->taxonomies ) ) {
foreach ( $this->taxonomies as $tax_slug ) {
$tax_obj = get_taxonomy( $tax_slug );
$tax_name = $tax_obj->labels->name;
$terms = get_terms( $tax_slug );
echo "<select name='$tax_slug' id='$tax_slug' class='postform'>";
echo "<option value=''>Show All $tax_name</option>";
foreach ( $terms as $term ) {
echo '<option value=' . $term->slug, $_GET[ $tax_slug ] == $term->slug ? ' selected="selected"' : '', '>' . $term->name . ' (' . $term->count . ')</option>';
}
echo "</select>";
}
}
}
}
// @todo extract to settings page so users can add their own
// @todo settings page should have drop down for post type, taxonomy name (rework of naming needed!) and options for filter/column
$taxonomies = array(
'product' => 'distributor',
);
new PIE_Add_Custom_Taxonomies( $taxonomies );
}