Categories
How To

Taxonomy Icons

Giving each taxonomy an icon. Not the term, the taxonomy.

Last year I talked about how I made icons for my taxonomy terms. When you have a limited number of terms, that makes sense. When you have a taxonomy with the potential for a high volume of terms, like nations (192), or worse an unlimited number of terms, this approach looses its value.

Instead, I realized what I needed for a particular project was a custom icon for each taxonomy. Not the term.

I split this up into two files because I used a slightly different setup for my settings API, but the tl;dr of all this is I made a settings page under themes called “Taxonomy Icons” which loads all the public, non-default taxonomies and associates them with an icon.

For this to work for you, you will need to have your images in a folder and define that as your IMAGE_PATH in the code below. Also mine is using .svg files, so change that if you’re not.

File 1: taxonomy-icons.php File 1: taxonomy-icons.php

The one gotcha with this is I usually set my default values with $this->plugin_vars = array(); in the __construct function. You can’t do that with custom taxonomies, as they don’t exist yet.

class TaxonomyIcons {

	private $settings;
	const SETTINGS_KEY = 'taxicons_settings';
	const IMAGE_PATH   = '/path/to/your/images/';

	/*
	 * Construct
	 *
	 * Actions to happen immediately
	 */
    public function __construct() {

		add_action( 'admin_menu', array( $this, 'admin_menu' ) );
		add_action( 'admin_init', array( $this, 'admin_init' ) );
		add_action( 'init', array( $this, 'init' ) );

		// Normally this array is all the default values
		// Since we can't set it here, it's a placeholder
		$this->plugin_vars = array();

		// Create the list of imagess
		$this->images_array = array();
		foreach ( glob( static::IMAGE_PATH . '*.svg' ) as $file) {
			$this->images_array[ basename($file, '.svg') ] = basename($file);
		}

		// Permissions needed to use this plugin
		$this->plugin_permission = 'edit_posts';

		// Menus and their titles
		$this->plugin_menus = array(
			'taxicons'    => array(
				'slug'         => 'taxicons',
				'submenu'      => 'themes.php',
				'display_name' => __ ( 'Taxonomy Icons', 'taxonomy-icons' ),
			),
		);
    }

	/**
	 * admin_init function.
	 *
	 * @access public
	 * @return void
	 * @since 0.1.0
	 */
	function admin_init() {
		// Since we couldn't set it in _construct, we do it here
		// Create a default (false) for all current taxonomies
		$taxonomies = get_taxonomies( array( 'public' => true, '_builtin' => false ), 'names', 'and' );
		if ( $taxonomies && empty( $this->plugin_vars ) ) {
			foreach ( $taxonomies as $taxonomy ) {
				$this->plugin_vars[$taxonomy] = false;
			}
		}
	}

	/**
	 * init function.
	 *
	 * @access public
	 * @return void
	 * @since 0.1.0
	 */
	function init() {
		add_shortcode( 'taxonomy-icon', array( $this, 'shortcode' ) );
	}

	/**
	 * Get Settings
	 *
	 * @access public
	 * @param bool $force (default: false)
	 * @return settings array
	 * @since 0.1.0
	 */
	function get_settings( $force = false) {
		if ( is_null( $this->settings ) || $force ) {
			$this->settings = get_option( static::SETTINGS_KEY, $this->plugin_vars );
		}
		return $this->settings;
	}

	/**
	 * Get individual setting
	 *
	 * @access public
	 * @param mixed $key
	 * @return key value (if available)
	 * @since 0.1.0
	 */
	function get_setting( $key ) {
		$this->get_settings();
		if ( isset( $this->settings[$key] ) ) {
			return $this->settings[$key];
		} else {
			return false;
		}
	}

	/**
	 * Set setting from array
	 *
	 * @access public
	 * @param mixed $key
	 * @param mixed $value
	 * @return void
	 * @since 0.1.0
	 */
	function set_setting( $key, $value ) {
		$this->settings[$key] = $value;
	}

	/**
	 * Save individual setting
	 *
	 * @access public
	 * @return void
	 * @since 0.1.0
	 */
	function save_settings() {
		update_option( static::SETTINGS_KEY, $this->settings );
	}

	/**
	 * admin_menu function.
	 *
	 * @access public
	 * @return void
	 * @since 0.1.0
	 */
	function admin_menu() {

		foreach ( $this->plugin_menus as $menu ) {
			$hook_suffixes[ $menu['slug'] ] = add_submenu_page(
				$menu['submenu'],
				$menu['display_name'],
				$menu['display_name'],
				$this->plugin_permission,
				$menu['slug'],
				array( $this, 'render_page' )
			);
		}

		foreach ( $hook_suffixes as $hook_suffix ) {
			add_action( 'load-' . $hook_suffix , array( $this, 'plugin_load' ) );
		}
	}

	/**
	 * Plugin Load
	 * Tells plugin to handle post requests
	 *
	 * @access public
	 * @return void
	 * @since 0.1.0
	 */
	function plugin_load() {
		$this->handle_post_request();
	}

	/**
	 * Handle Post Requests
	 *
	 * This saves our settings
	 *
	 * @access public
	 * @return void
	 * @since 0.1.0
	 */
	function handle_post_request() {
		if ( empty( $_POST['action'] ) || 'save' != $_POST['action'] || !current_user_can( 'edit_posts' ) ) return;

		if ( !wp_verify_nonce( $_POST['_wpnonce'], 'taxicons-save-settings' ) ) die( 'Cheating, eh?' );

		$this->get_settings();

		$post_vars = $this->plugin_vars;
		foreach ( $post_vars as $var => $default ) {
			if ( !isset( $_POST[$var] ) ) continue;
			$this->set_setting( $var, sanitize_text_field( $_POST[$var] ) );
		}

		$this->save_settings();
	}

	/**
	 * Render admin settings page
	 * If setup is not complete, display setup instead.
	 *
	 * @access public
	 * @return void
	 * @since 0.1.0
	 */
	function render_page() {
		// Not sure why we'd ever end up here, but just in case
		if ( empty( $_GET['page'] ) ) wp_die( 'Error, page cannot render.' );

		$screen = get_current_screen();
		$view  = $screen->id;

		$this->render_view( $view );
	}

	/**
	 * Render page view
	 *
	 * @access public
	 * @param mixed $view
	 * @param array $args ( default: array() )
	 * @return content based on the $view param
	 * @since 0.1.0
	 */
	function render_view( $view, $args = array() ) {
		extract( $args );
		include 'view-' . $view . '.php';
	}

	/**
	 * Render Taxicon
	 *
	 * This outputs the taxonomy icon associated with a specific taxonomy
	 *
	 * @access public
	 * @param mixed $taxonomy
	 * @return void
	 */
	public function render_taxicon ( $taxonomy ) {

		// BAIL: If it's empty, or the taxonomy doesn't exist
		if ( !$taxonomy || taxonomy_exists( $taxonomy ) == false ) return;

		$filename = $this->get_setting( $taxonomy );

		// BAIL: If the setting is false or otherwise empty
		if ( $filename == false || !$filename || empty( $filename ) ) return;

		$icon     = file_get_contents( static::IMAGE_PATH . $filename  . '.svg' );
		$taxicon  = '<span role="img" class="taxonomy-icon ' . $filename . '">' . $icon . '</span>';

		echo $taxicon;
	}

	/*
	 * Shortcode
	 *
	 * Generate the Taxicon via shortcode
	 *
	 * @param array $atts Attributes for the shortcode
	 *        - tax: The taxonomy
	 * @return SVG icon of awesomeness
	 */
	function shortcode( $atts ) {
		return $this->render_taxicon( $atts[ 'tax' ] );
	}

}

new TaxonomyIcons();

Top ↑

File 2: view-appearance_page_taxicons.php File 2: view-appearance_page_taxicons.php

Why that name? If you look at my render_view function, I pass the ID from get_current_screen() to it, and that means the ID is appearance_page_taxicons and that’s the page name.

<div class="wrap">

	<h1><?php _e( 'Taxonomy Icons', 'taxonomy-icons' ); ?></h1>

	<div>

		<p><?php __( 'Taxonomy Icons allows you to assign an icon to a non-default taxonomy in order to make it look damn awesome.', 'taxonomy-icons' ); ?></p>

		<p><?php __( 'By default, Taxonomy Icons don\'t display in your theme. In order to use them, you can use a shortcode or a function:' , 'taxonomy-icons' ); ?></p>

		<ul>
			<li>Shortcode: <code>[taxonomy-icon tax=TAXONOMY]</code></li>
		</ul>

		<form method="post">

		<?php
		if ( isset( $_GET['updated'] ) ) {
			?>
			<div class="notice notice-success is-dismissible"><p><?php _e( 'Settings saved.', 'taxonomy-icons' ); ?></p></div>
			<?php
		}
		?>

		<input type="hidden" name="action" value="save" />
		<?php wp_nonce_field( 'taxicons-save-settings' ) ?>

		<table class="form-table">

			<tr>
				<th scope="row"><?php _e( 'Category', 'taxonomy-icons' ); ?></th>
				<th scope="row"><?php _e( 'Current Icon', 'taxonomy-icons' ); ?></th>
				<th scope="row"><?php _e( 'Select Icon', 'taxonomy-icons' ); ?></th>
			</tr>

			<?php

			foreach ( $this->plugin_vars as $taxonomy => $value ) {
				?>
				<tr>
					<td>
						<strong><?php echo get_taxonomy( $taxonomy )->label; ?></strong>
						<br /><em><?php echo get_taxonomy( $taxonomy )->name; ?></em>
					</td>

					<td>
						<?php
						if ( $this->get_setting( $taxonomy ) && $this->get_setting( $taxonomy ) !== false ) {
							echo $this->render_taxicon( $taxonomy );
						}
						?>

					</td>

					<td>
						<select name="<?php echo $taxonomy; ?>" class="taxonomy-icon">
							<option value="">-- <?php _e( 'Select an Icon', 'taxonomy-icons' ); ?> --</option>
							<?php
							foreach ( $this->images_array as $file => $name ) {
								?><option value="<?php echo esc_attr( $file ); ?>" <?php echo $file == $this->get_setting( $taxonomy ) ? 'selected="selected"' : ''; ?>><?php echo esc_html( $name ); ?></option><?php
								};
							?>
						</select>
					</td>

				</tr><?php
			}

			?>

			<tr valign="top">
				<td colspan="3">
					<button type="submit" class="button button-primary"><?php _e( 'Save', 'taxonomy-icons' ); ?></button>
				</td>
			</tr>
		</table>
		</form>
	</div>
</div>

Top ↑

End Result End Result

And in the end?

An example of Taxonomy Icons

By the way, the image has some wrong text, but that is what it looks like.

1 reply on “Taxonomy Icons”

… and Mika has deep knowledge about taxonomy. It was one of her strengths in Montessori. Happy Birthday Mika!!!!

Comments are closed.