Taxonomy term splitting in 4.2: a developer guide

In WordPress 4.2, shared taxonomy terms – those items in the wp_terms table that are shared between multiple taxonomies – will be split into separate terms when one of the shared terms is updated. This change ([31418]) fixes one of WordPress’s most irksome bugs, and is a critical step in our ongoing taxonomy roadmap.

Technical details and backward compatibility

Each row in the wp_term_taxonomy table represents the dyad of a term slug and a taxonomy – say, the tag slug ‘mint’ and the taxonomy ‘herb’. Historically, terms in different taxonomies that shared the same slug would share a single row in the wp_terms table; thus, the ‘mint’ row in wp_terms could correspond to a term-taxonomy pair in the ‘government_building’ taxonomy as well as ‘herb’. Starting with 4.2, when you update a shared taxonomy term – wp_update_term( $mint_id, 'government_building' ) – WordPress will detect whether the term is shared between multiple taxonomies, and if so, will create a new row in wp_terms for the updated term and change all necessary term_taxonomy associations. term_taxonomy_id will stay the same, but term_id will change. This is a case of a shared term being split into separate terms.

In most cases, term splitting will go unnoticed. However, there are some plugins and themes that store term IDs as static data. In these cases, a changed term ID has the potential to cause various sorts of problems.

Who is affected?

In brief, any plugin that independently stores term IDs in the database – postmeta, usermeta, the options table, etc. @mboynes and I looked over the top 100 most popular plugins on wordpress.org, and found eleven that will need changes in order to anticipate term splitting: Jetpack, WordPress SEO by Yoast, Google XML Sitemaps, All in One SEO Pack, Mailpoet, Advanced Custom Fields, Ninja Forms, Types, Custom Sidebars, Paid Memberships Pro, WordPress Download Manager. If you’ve written a plugin, theme, or other customization that stores term IDs in a static way, you’ll be affected too.

What steps should you take?

WP 4.2 will include a number of tools that developers can use for split term ID migration. The most important is the 'split_shared_term' action. Here’s a concrete example, taken from Jetpack. Jetpack stores a post_tag ID in the ‘featured-content’ option, and in some cases, the tag’s term ID may be shared with another taxonomy term. The following is a simple function that could be used to detect when the term is split, and to update the option accordingly:

function jetpack_update_featured_content_for_split_terms( $old_term_id, $new_term_id, $term_taxonomy_id, $taxonomy ) {
    $fc_settings = get_option( 'featured-content', array() );

    // Check to see whether the stored tag ID is the one that's just been split.
    if ( isset( $fc_settings['tag-id'] ) && $old_term_id == $fc_settings['tag-id'] && 'post_tag' == $taxonomy ) {
        // We have a match, so we swap out the old tag ID for the new one and resave the option.
        $fc_settings['tag-id'] = $new_term_id;
        update_option( 'featured-content', $fc_settings );
    }
}
add_action( 'split_shared_term', 'jetpack_update_featured_content_for_split_terms', 10, 4 );

In addition to the 'split_shared_term' action, 4.2 will store information about all terms that are split. Developers can access this information after the fact by using wp_get_split_term( $old_term_id, $taxonomy ). For more details on 'split_shared_term' and wp_get_split_term(), including a number of practical examples, be sure to check out the page in the Plugin Developer Handbook.

What will happen if plugins and themes don’t update?

The vast majority of terms are not shared between taxonomies; shared terms themselves are an odd edge case. The vast majority of plugins and themes do not store term IDs. And, moreover, WP 4.2 will only split terms when a shared term is updated (eg, when its name is updated in the Dashboard) – an infrequent event. (Though note that there are plans to force all shared terms to be split in a future release.) Even in cases where a plugin is technically affected, depending on the way the plugin uses its stored term IDs, there may be no perceptible effect at all.

That said, there are cases where failure to account for split terms could result in fairly disruptive behavior. In the case of Jetpack, for example, Featured Content would stop displaying correctly if the term split were not caught properly. For this reason, it’s critical for developers to examine the way they store term IDs, and to update their plugins and themes accordingly, in time for 4.2 in April.

Questions or concerns? Read over the practical guide in the Plugin Developer Handbook, or leave a comment below.

#4-2, #taxonomy