leglesslizard
7/28/2016 - 7:46 PM

Register taxonomy with sortable column and filter added automatically

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 );
}