This is going to be a ton of code and a ton of explanation. Most of which can be copy and paste but I suggest taking the time to understand what's going on and why. First thing to understand is that WordPress does not have Taxonomy Metadata but it may someday. This means that we need to save our data as options. Second thing to understand is that we have to deal with multiple hooks:


{$taxonomy}_add_form_fields - The page where we add the terms.
{$taxonomy}_edit_form_fields - Whenever a user clicks the term to edit the slug or description once it's been created.
created_{$taxonomy} - Save the data whenever a taxonomy term is created.
edited_{$taxonomy} - Save the data whenever a taxonomy term is modified / edited.
pre_delete_term - To clean up our data whenever a term is deleted.


Whenever you see {$taxonomy} you would replace it with whatever you taxonomy slug is. In this example I will use the default / built-in Post Categories taxonomy whose slug is category.

The below will not cover adding the fields to Quick Edit or Add New Term Metabox.



Lets start with displaying the textbox to accept classes. Since both pages display their data differently ( and pass separate parameters ) we have to create two separate functions and assign them to {$taxonomy}_add_form_fields and {$taxonomy}_edit_form_fields respectively. Both are commented to point out anything our of the ordinary.

/**
 * Category "Add New" Page - Add Additional Field(s)
 * @param string $taxonomy
 */
function category_fields_new( $taxonomy ) {                             // Function has one field to pass - Taxonomy ( Category in this case )
    wp_nonce_field( 'category_meta_new', 'category_meta_new_nonce' );   // Create a Nonce so that we can verify the integrity of our data
?&gt;
    &lt;div class="form-field"&gt;
        &lt;label for="category_fa"&gt;Font-Awesome Icon&lt;/label&gt;
        &lt;input name="category_icon" id="category_fa" type="text" value="" style="width:100%" /&gt;
        &lt;p class="description"&gt;Enter a custom font-awesome icon - &lt;a href="http://fontawesome.io/icons/" target="_blank"&gt;List of Icons&lt;/a&gt;&lt;/p&gt;
    &lt;/div&gt;
&lt;?php
}
add_action( 'category_add_form_fields', 'category_fields_new', 10 );

/**
 * Category "Edit Term" Page - Add Additional Field(s)
 * @param Object $term
 * @param string $taxonomy
 */
function category_fields_edit( $term, $taxonomy ) {                         // Function has one field to pass - Term ( term object) and Taxonomy ( Category in this case )
    wp_nonce_field( 'category_meta_edit', 'category_meta_edit_nonce' );     // Create a Nonce so that we can verify the integrity of our data
    $category_icon = get_option( "{$taxonomy}_{$term-&gt;term_id}_icon" );     // Get the icon if one is set already
?&gt;
    &lt;tr class="form-field"&gt;
        &lt;th scope="row" valign="top"&gt;
            &lt;label for="category_fa"&gt;Font-Awesome Icon&lt;/label&gt;
        &lt;/th&gt;
        &lt;td&gt;
            &lt;input name="category_icon" id="category_fa" type="text" value="&lt;?php echo ( ! empty( $category_icon ) ) ? $category_icon : ''; ?&gt;" style="width:100%;" /&gt; &lt;!-- IF `$category_icon` is not empty, display it. Otherwise display an empty string --&gt;
            &lt;p class="description"&gt;Enter a custom Font-Awesome icon - &lt;a href="http://fontawesome.io/icons/" target="_blank"&gt;List of Icons&lt;/a&gt;&lt;/p&gt;
        &lt;/td&gt; 
    &lt;/tr&gt;
&lt;?php
}
add_action( 'category_edit_form_fields', 'category_fields_edit', 10, 2 );


The next step is to save our options. Since category creation and category edit will be handled the same way when saving, we'll use the same function for both. We still need to use the created_{$taxonomy} and edited_{$taxonomy}. As mentioned toward the top, since Taxonomy Metadata does not exist we have to save our data to the options table which needs a unique name. This is why we give our option a unique name of {$taxonomy}_{$term_id}_icon which, in this example, translates to category_1_icon.

/**
 * Save our Additional Taxonomy Fields
 * @param int $term_id
 */
function save_category_fields( $term_id ) {

    /** Verify we're either on the New Category page or Edit Category page using Nonces **/
    /** Verify that a Taxonomy is set **/
    if( isset( $_POST['taxonomy'] ) &amp;&amp; isset( $_POST['category_icon'] ) &amp;&amp;
        ( 
          isset( $_POST['category_meta_new_nonce'] ) &amp;&amp; wp_verify_nonce( $_POST['category_meta_new_nonce'], 'category_meta_new' ) ||        // Verify our New Term Nonce
          isset( $_POST['category_meta_edit_nonce'] ) &amp;&amp; wp_verify_nonce( $_POST['category_meta_edit_nonce'], 'category_meta_edit' )        // Verify our Edited Term Nonce
        )
    ) {
        $taxonomy = $_POST['taxonomy'];
        $category_icon = get_option( "{$taxonomy}_{$term_id}_icon" );   // Grab our icon if one exists

        if( ! empty( $_POST['category_icon'] ) ) {                      // IF the user has entered text, update our field.
            update_option( "{$taxonomy}_{$term_id}_icon", htmlspecialchars( sanitize_text_field( $_POST['category_icon'] ) ) );     // Sanitize our data before adding to the database
        } elseif( ! empty( $category_icon ) ) {                         // Category Icon IS empty but the option is set, they may not want an icon on this category
            delete_option( "{$taxonomy}_{$term_id}_icon" );             // Delete our option
        }

    } // Nonce Conditional
} // End Function
add_action ( 'created_category', 'save_category_fields' );
add_action ( 'edited_category', 'save_category_fields' );


Finally, we need to clean up our options. Postmeta deletes itself when a post is deleted but Options do not. We need to manually delete these so that our options tables does not get bloated with orphaned options.

/**
 * Essential Cleanup of our Options
 * @param int $term_id
 * @param string $taxonomy
 */
function remove_term_options( $term_id, $taxonomy ) {
    delete_option( "{$taxonomy}_{$term_id}_icon" );         // Delete our option
}
add_action( 'pre_delete_term', 'remove_term_options', 10, 2 );




If we want to display each icon that has currently been assigned. Since we're generating a Unique Option Name using the Taxonomy and Term ID we would get the options using that same formula. First let's get our terms, then let's loop through our terms.

$terms = get_terms(            // Returns an array of Term Objects, 
    'category',                 // Pass our Taxonomy
    array(                      // Pass our Arguments
        'hide_empty' =&gt; false   // Show ALL Terms
    )
);

if( ! empty( $terms ) ) {           // Make sure we have some terms to loop through
    foreach( $terms as $term ) {    // Loop through each term
        $icon = get_option( "{$term-&gt;taxonomy}_{$term-&gt;term_id}_icon" );    // Use our formula to grab the Icon - This translate to "category_1_icon"
        echo "Category {$term-&gt;name} Icon: {$icon}&lt;br /&gt;";                  // Display our Category Icon
    }
}


How to add additional field to Add new category part (without plugin use)
I understand that there needs to be a wide variety of power levels in Magic: The Gathering. Even bad cards will see play in limited formats, some because they fill a specific niche (flying removal, fat colorless flyer, providing a counter to certain decks), and others because those decks can't afford to be too picky. However, some cards are just unforgivably terrible. I'm talking about cards that you would only run in sealed if you had absolutely no other options:

Mindless Null: Black 2/2 for 3 with a big disadvantage

Defensive Stance: literally does nothing in exchange for you getting card disadvantage 

Merfolk of the Depths: Would still be bad if it only costed 5...

Archangel's Light: 8 mana just to gain some life and put cheap cards back into your deck. And it's a mythic rare....

There are many more examples, but I think these best illustrate my case. Obviously I'd rather have these cards in the game than not have them at all, but I feel like Wizards of the Coast could have made Magic a more enjoyable game just by keeping the flavor and making all of these cards a tiny bit better...yet they didn't. Why?
