Half-Elf on Tech

Thoughts From a Professional Lesbian

Tag: terms

  • Custom Terms and CMB2

    Custom Terms and CMB2

    Let’s say you have some custom taxonomies in WordPress. And let’s say you want to add a special field to them for an icon. How would you do it?

    There’s a cool plugin by someone I know that can do this, called WP SVG Icons and it works great. But it wasn’t quite what I needed.

    You see, I had 832 really awesome SVG icons I wanted to use. In order to use Evan’s plugin I’d have to convert them into a font using Icomoon. I already had about 300 in a font, which is cool, but I was in the thought to move these from fonts to pure SVG anyway since they’ll show up in better detail if you don’t have retina screens. Also they’re smaller and loaded on demand and … well it is what it is.

    I decided the simplest solution was as follows:

    1. Upload all the SVG to the server
    2. Add a custom term meta field to the taxonomies for ‘icon’
    3. Show the icon on the Terms List Page
    4. Show the icon on the Term Edit page

    And yes, it works.

    Where Do The Icons Go?

    I put them in my theme. They’re pretty specific to the theme itself, but usually things that are related to custom data ends up in mu-plugins since I want them to exist outside of the theme. For the record, I also have CMB2 outside the theme, so the code is all there, but the images are in the theme. You can decide how you want.

    Adding Custom Term Meta

    There are a lot of ways of doing this, but as I’m using CMB2, well, I’m using CMB2 so it looks like this:

    add_action( 'cmb2_admin_init', 'my_register_taxonomy_metabox' );
    function my_register_taxonomy_metabox() {
    	$prefix = 'my_termsmeta_';
    
    	$cmb_term = new_cmb2_box( array(
    		'id'               => $prefix . 'edit',
    		'title'            => 'Category Metabox',
    		'object_types'     => array( 'term' ),
    		'taxonomies'       => array( 'my_cliches', 'my_chartags' ),
    		'new_term_section' => true, 
    	) );
    
    	$cmb_term->add_field( array(
    		'name'		=> 'Icon',
    		'desc'		=> 'Name of the image you want to use, without filetype (i.e. carrot)',
    		'id'		=> $prefix . 'icon',
    		'type'		=> 'text_medium',
    		'before_field'	=> 'cmb2_before_field_icon',
    	) );
    }
    

    You’ll notice before_field there. That’s what will let me do the 4th item on my list. The description tells you how to use the field. Don’t worry, I do sanity checks later on.

    Show The Icon On The Terms List

    I wanted the icon to show after save so that people would be able to know what they’d added and change it if needed.

    add_filter( "manage_edit-{my_taxonomy}_columns", "my_terms_column_header" );
    add_action( "manage_{my_taxonomy}_custom_column",  "my_terms_column_rows", 10, 3  );
    
    function my_terms_column_header($columns){
        $columns['icon'] = 'Icon';
        return $columns;
    }
    
    function my_terms_column_rows($value, $content, $term_id){
    	$icon = get_term_meta( $term_id, 'lez_termsmeta_icon', true );
    	$iconpath = get_stylesheet_directory().'/images/symbolicons/'.$icon.'.svg';
    	if ( empty($icon) || !file_exists( $iconpath ) ) {
    		$content = 'N/A';
    	} else {
    		$content = '<span role="img" class="cmb2-icon">'.file_get_contents($iconpath).'</span>';
    	}
        return $content;
    }
    

    You can see where I’m checking if the icon has been set and if the file exists. What this does is first generate a column for the icon and then populate the content based on the term information.

    Icons shown on the list of terms

    There you can see the icon, looking rather nice.

    See The Icon When You Edit

    This is a little different. I had to check the output the of the field value, which is set by CMB2, and then base the rest of the code off that.

    function cmb2_before_field_icon( $field_args, $field ) {
    	$icon = $field->value;
    	$iconpath = get_stylesheet_directory().'/images/symbolicons/'.$icon.'.svg';
    	if ( !empty($icon) || file_exists( $iconpath ) ) {
    		echo '<span role="img" class="cmb2-icon">'.file_get_contents(get_stylesheet_directory_uri().'/images/symbolicons/'.$icon.'.svg').'</span>';
    	}
    }
    

    Again I double check the file actually exists, just in case you typo.

    The edit term page

    I put it before the field because that looked better to me, but there are other places this could go.

    Results?

    I started this because, originally, it was all done with CSS. That meant if people added in new terms, someone with admin ability had to go in and edit things. This way, people can not only see what they’ve added, but you can get a quick view of what doesn’t have icons set. It’s instructive and has visual feedback.

    The ‘next level up’ would be to only allow selection from a dropdown.

    For the least amount of hustle, add this to your my_register_taxonomy_metabox function:

    	$icon_array = array();
    	foreach (glob( get_stylesheet_directory().'/images/symbolicons/*.svg' ) as $file) {
    		$icon_array[ basename($file, '.svg') ] = basename($file, '.svg');
    	}
    

    And then replace 'type' => 'text_medium', with this:

    	    'type'             => 'select',
    	    'show_option_none' => true,
    	    'default'          => 'custom',
    	    'options'          => $icon_array,
    

    And voila. Done. Now you’re even harder to get wrong.

    names as dropdowns

    It even looks good.