Eliminating shared taxonomy terms in WordPress 4.3

Work on the taxonomy roadmap, started in earnest during the 4.1 dev cycle, continues to chug along for WordPress 4.3. We’ve been focusing on the elimination of shared terms: terms in different taxonomies that share the same term_id and thus the same row in the wp_terms database table. In 4.1, we stopped creating shared terms. In 4.2, we began splitting existing taxonomy terms when those terms were updated.

In 4.3, we’ll take the final step. When a WordPress sitesite (versus network, blog) upgrades to 4.3, all existing shared terms will be split.

Toward that end, I’d like to makemake A collection of P2 blogs at make.wordpress.org, which are the home to a number of contributor groups, including core development (make/core, formerly "wpdevel"), the UI working group (make/ui), translators (make/polyglots), the theme reviewers (make/themes), resources for plugin authors (make/plugins), and the accessibility working group (make/accessibility). (a) a final warning to pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party authors, and (b) a plea for help from taxonomyTaxonomy A taxonomy is a way to group things together. In WordPress, some common taxonomies are category, link, tag, or post format. https://codex.wordpress.org/Taxonomies#Default_Taxonomies. mavens and those who maintain very large and complex WordPress installations.

Plugin authors: Dress rehearsal is nearly over

Since 4.2, saving a shared term (via any interface that uses wp_update_term()) causes that term to be split. It’s fairly rare to update a taxonomy term, which has made 4.2 a sort of trial run for authors to ensure that their plugins are ready for the transition. A quick scan of the plugin repo shows that a few dozen authors have taken advantage of this opportunity. I dub these developers Heroes of WordPress and grant them 🌟🌟 many gold stars 🌟🌟. Many authors, however, have neglected to make the necessary updates.

All WP developers should take note that the upgrade to 4.3 is likely to surface many more odd bugs related to shared terms than 4.2 did. Plugin authors are strongly encouraged to review the 4.2 term splitting field guide to understand the potential repercussions for their public plugins as well as their custom client work, and to review techniques for ensuring a smooth transition.

Get involved

The 4.3 ticketticket Created for both bug reports and feature development on the bug tracker. for splitting taxonomy terms on WP upgrade, #30261, is sorely in need of developer feedback. The process of splitting shared terms en masse is potentially resource-intensive, especially on sites with very large numbers of terms (and especially with very large numbers of shared terms). The latest patchpatch A special text file that describes changes to code, by identifying the files and lines which are added, removed, and altered. It may also be referred to as a diff. A patch can be applied to a codebase for testing. on the ticket has some optimizations so that sites with many hundreds of shared terms can be migrated in just a few seconds. If you maintain a site with a large number of (shared) taxonomy terms, or if you maintain a WordPress networknetwork (versus site, blog) with a very large number of sites (especially if you have a custom routine for rolling out database updates), your review and testing of the upgrade routine would be much appreciated.

Booyah

The fun stuff on the taxonomy roadmap – like termmeta – depends on the complete elimination of shared terms. Let’s get the hard stuff done in 4.3, so that we can make all of your taxonomy dreams come true in the next couple releases.

#4-3, #dev-notes, #taxonomy

Taxonomy term splitting in 4.2: a developer guide

In WordPress 4.2, shared taxonomyTaxonomy A taxonomy is a way to group things together. In WordPress, some common taxonomies are category, link, tag, or post format. https://codex.wordpress.org/Taxonomies#Default_Taxonomies. 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 tagtag A directory in Subversion. WordPress uses tags to store a single snapshot of a version (3.6, 3.6.1, etc.), the common convention of tags in version control systems. (Not to be confused with post tags.) 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 pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party 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.orgWordPress.org The community site where WordPress code is created and shared by the users. This is where you can download the source code for WordPress core, plugins and themes as well as the central location for community conversations and organization. https://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 migrationMigration Moving the code, database and media files for a website site from one server to another. Most typically done when changing hosting companies.. 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 releaseRelease A release is the distribution of the final version of an application. A software release may be either public or private and generally constitutes the initial or new generation of a new or upgraded application. A release is preceded by the distribution of alpha and then beta versions of the software..) 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

An update on shared term splitting

Background reading: #30335 and the notes on shared term splitting in https://make.wordpress.org/core/2014/11/20/dev-chat-summary-november-19th/.

As part of the work on the taxonomy roadmap in 4.1, shared terms (terms which are shared across more than one taxonomyTaxonomy A taxonomy is a way to group things together. In WordPress, some common taxonomies are category, link, tag, or post format. https://codex.wordpress.org/Taxonomies#Default_Taxonomies. due to a slug collision) now get split when the term gets updated. The end result being that editing a term in one taxonomy will no longer affect the term in another taxonomy.

Many plugins store term IDs in post metaMeta Meta is a term that refers to the inside workings of a group. For us, this is the team that works on internal WordPress sites like WordCamp Central and Make WordPress., options, terms (!), etc, and the side effect of shared term splitting is that these caches can break when the ID of a term they reference changes. Not only that, but the breakage (and the cause) can be invisible to the user and hard to track down if they do notice it.

Following a discussion in #core Slack I’m proposing that shared term splitting is removed from 4.1 and we’ll add it back in for 4.2 and allow a full releaseRelease A release is the distribution of the final version of an application. A software release may be either public or private and generally constitutes the initial or new generation of a new or upgraded application. A release is preceded by the distribution of alpha and then beta versions of the software. cycle to get the word out to developers about the change. I’ll makemake A collection of P2 blogs at make.wordpress.org, which are the home to a number of contributor groups, including core development (make/core, formerly "wpdevel"), the UI working group (make/ui), translators (make/polyglots), the theme reviewers (make/themes), resources for plugin authors (make/plugins), and the accessibility working group (make/accessibility). the final decision during tomorrow’s dev chat.

Thanks in particular to @mboynes for his time spent on this.

(Note that this only affects existing terms; new terms do not get shared since r30240.)

#4-1, #dev-notes, #roadmap, #taxonomy

An update on the taxonomy roadmap

In 2013, @nacin laid out a potential roadmap for the WordPress taxonomy component. Progress on this roadmap has necessarily been deliberate and, as a result, somewhat slow. But some important steps have been taken in the last few months.

Improvements in 4.1

Recall the problem. Since 2.3 – when WP’s taxonomyTaxonomy A taxonomy is a way to group things together. In WordPress, some common taxonomies are category, link, tag, or post format. https://codex.wordpress.org/Taxonomies#Default_Taxonomies. schema was first introduced – terms have been “shared” between taxonomies when they happen to share the same slug. This architecture was designed to enable serendipitous connections between bloggers writing about similar subjects, especially when combined with “global” terms, which are shared across a multisitemultisite Used to describe a WordPress installation with a network of multiple blogs, grouped by sites. This installation type has shared users tables, and creates separate database tables for each blog (wp_posts becomes wp_0_posts). See also network, blog, site networknetwork (versus site, blog). However, as WP has developed as a CMS and taxonomies have been put to much broader use than originally envisioned, this feature has ended up causing more problem than it solved. Shared slugs in particular have caused a good deal of frustration for users and developers. A notable example is the infamous #5809: changing a term in one taxonomy (say, ‘Chicago’ in the taxonomy ‘cool_cities’) would update all terms that happened to share the same slug (say, ‘Chicago’ in the taxonomy ‘cool_bands’).

Fixing this behavior has required a series of carefully staged maneuvers. Here’s what’s happened during the 4.1 cycle:

  • Unit testunit test Code written to test a small piece of code or functionality within a larger application. Everything from themes to WordPress core have a series of unit tests. Also see regression. coverage has been improved for wp_insert_term(), wp_update_term(), and term_exists() ([29798], [29830], [29875]).
  • We fixed a few edge-case bugs in term_exists() #29589 #29851. These fixes, plus the increased test coverage, have made us confident in our ability to prevent the creation of unwanted duplicate terms in most cases, a prerequisite for the next item.
  • We removed the UNIQUE index from the ‘slug’ column in wp_terms #22023, and added some failsafe logic to avoid duplicate term creation in certain edge cases [30238]. This step is small but critical. “Splitting” existing shared terms means creating a new row in the wp_terms table for each item in wp_term_taxonomy that currently shares its ‘term_id’ with another item. But when we split these terms, we cannot change their slugs, or we’ll break backward compatibility with things like taxonomy archive permalinks. That is: example.com/cool_bands/chicago and example.com/cool_cities/chicago must continue to work. So the ‘slug’ column of the terms table must not enforce uniqueness.
  • We stopped creating new shared terms #21950. This means that each new item inserted into wp_term_taxonomy will correspond to a new row in wp_terms, even if the new item shares its slug with an existing term.
  • Updating a shared term will cause it to be split into two separate terms #5809. This addresses the primary pain point of shared terms: you can now change ‘Chicago’ to ‘The Windy City’ without your readers thinking that you’re confused about the artists behind this hard-rockin’ hit. (Edit – term splitting was removed for WP 4.1, and is slated for 4.2.)

In short, while 4.1 won’t completely remove shared terms from WP – see below – it should alleviate the pains they inflict.

Looking ahead

The continued existence of shared terms in the database means that we still have to deal with the translationtranslation The process (or result) of changing text, words, and display formatting to support another language. Also see localization, internationalization. between ‘term_id’+’taxonomy’ and ‘term_taxonomy_id’, a requirement that limits the cool things we can do with terms. As such, cleaning up existing shared terms is a top priority. #30261 lays out some suggestions for how to expunge them from the database. This step isn’t practical for 4.1: we can only split existing terms when the 4.1 database schema change has been applied #22023, and schema changes are not immediate in multisite enviroments. But we can consider it for 4.2.

Once term_ids and term_taxonomy_ids are in one-to-one correspondence, we can start on some of the more exciting items that Nacin outlined. Termmeta #10142 becomes a viable possibility once we can rely on unique term_ids. And collapsing the wp_terms and wp_term_taxonomy tables #30262 will allow us to simplify and streamline the internals of our taxonomy functions. These are tasks that we can start exploring for 4.3 and beyond, at least one version after we’ve split existing terms on all installations. These tickets are a good starting place for people who are interested in following (and contributing to) the future of taxonomies in WordPress.

#4-1, #dev-notes, #roadmaps, #taxonomy

Potential roadmap for taxonomy meta and post relationships

In the days before the WordPress Community Summit in October, a number of contributing developers huddled together to discuss a number of long-term architecture ideas. Among them were taxonomyTaxonomy A taxonomy is a way to group things together. In WordPress, some common taxonomies are category, link, tag, or post format. https://codex.wordpress.org/Taxonomies#Default_Taxonomies. metaMeta Meta is a term that refers to the inside workings of a group. For us, this is the team that works on internal WordPress sites like WordCamp Central and Make WordPress. and post relationships. (Ah, I see I now have your attention!) This post is more or less a proposed roadmap. It’s an ambitious plan that is designed to take place over perhaps five or more releases.

(During WordCampWordCamp WordCamps are casual, locally-organized conferences covering everything related to WordPress. They're one of the places where the WordPress community comes together to teach one another what they’ve learned throughout the year and share the joy. Learn more. San Francisco’s keynote, @matt talked a little about a new aim to build teams of contributors and reviewers around individual coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. components. There will be a lot more on that in the coming days and weeks. For now, here’s a post that covers two components, post types and taxonomy.)

The discussion included all core committers at the time — @ryan, @markjaquith, @westi, @azaozz, @nacin, @dd32, @koopersmith, and @duck_ — and a number of contributing developers, including @aaroncampbell, @dh-shredder, @helen, and @scribu.

At the moment, terms are represented in WordPress using two different IDs: a term ID, and a term taxonomy ID. A term ID (and name and slug) can actually appear in multiple taxonomies, so to identify a particular term, you must have either the term ID and the corresponding taxonomy, or just the term taxonomy ID. This dates back to the original taxonomy schema in WordPress 2.3. At the time, the concept of “shared terms” seemed like it could be an important abstraction. Hindsight is 20/20, and shared terms are the bane of taxonomies in WordPress.

So when we talk about term meta, we’re actually talking about term taxonomy meta — meta associated with a term taxonomy ID, not a term ID. The problem is, the public ID used in the APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. and elsewhere is the term ID (and, by necessity, a taxonomy is also passed). This confusion — and the need for there to be only one object identifier in our metadata API (term taxonomy ID, not two, as in term ID and taxonomy) — has long forced us to table the discussion of term metadata.

(There are separate conceptual issues here — at what point does a term with metadata simply become a post-like object that can relate to other posts? And given post relationships, could terms and posts actually converge in their underlying schema? I’m not actually going to answer those questions in this post. Purely talking schema and architecture at this point.)

At WordCamp San Francisco last year, four of us — me, Gary Pendergast (@pento), @scribu, and @koopersmith — came up with a rather crazy way to makemake A collection of P2 blogs at make.wordpress.org, which are the home to a number of contributor groups, including core development (make/core, formerly "wpdevel"), the UI working group (make/ui), translators (make/polyglots), the theme reviewers (make/themes), resources for plugin authors (make/plugins), and the accessibility working group (make/accessibility). major changes to our table schema while still being backwards compatible. In fact, we came up with two ways to do it. This was the plan everyone heard and discussed at the summit.

It was clear that shared terms had to go. The first step is removing a UNIQUE index on the slug field in the wp_terms table. (This is dependent on #17689.) Then, we stop creating new shared terms. Step three, on an upgrade routine, we actively look for any existing shared terms and split them.

These three initial steps must happen over two to three major releases, as we’re talking about a bugbug A bug is an error or unexpected result. Performance improvements, code optimization, and are considered enhancements, not defects. After feature freeze, only bugs are dealt with, with regressions (adverse changes from the previous version) being the highest priority. fix, a schema change, an API change, and an upgrade routine — in that order.

Then comes the fun part, in yet another major releasemajor release A release, identified by the first two numbers (3.6), which is the focus of a full release cycle and feature development. WordPress uses decimaling count for major release versions, so 2.8, 2.9, 3.0, and 3.1 are sequential and comparable in scope.. With shared terms split, term ID and term taxonomy ID will be identical  on every install.  If we moved the slug and name fields from wp_terms to wp_term_taxonomy, we could actually drop wp_terms.

How can we remove an entire table but still be backwards compatible? We came up with two solutions:

  1. Because all fields in wp_terms will exist in wp_term_taxonomy, wp_terms can be recreated as a MySQLMySQL MySQL is a relational database management system. A database is a structured collection of data where content, configuration and other options are stored. https://www.mysql.com/. view to be a read-only mirror of term data, thus being compatible with all existing queries.
  2. Because all fields in wp_terms will exist in wp_term_taxonomy, and because table aliases like `t`and `tt` are always used when joining these two tables, $wpdb->terms can simply be set to $wpdb->term_taxonomy. A query that previously joined wp_terms with wp_term_taxonomy would just join itself.

In all: Using the second approach (yes, it works), it took about 20 lines of code to make WordPress run without a wp_terms table. Wow, right?

So by this point, we would finally have a sane taxonomy schema. Less joins, a cleaner API (probably helped by a new WP_Term object to model WP_Post and WP_User), no more shared terms headaches, and a single, sane ID for a single taxonomy’s term.

Once that is all finished, we can finally have term meta. Maybe. (Kidding. (Kind of.))

Where do post relationships come in? The existing Posts 2 Posts pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party by @scribu is fantastic and serves the niche well. But we’re not really comfortable making any architecture or API changes along these lines while our taxonomy schema is still in a far from ideal state.

The post relationships plugin supports posts to posts, and posts to users. Core taxonomy relationships supports posts to terms, but it can also be rigged to relate users to terms. (It also supported links to terms, yet another object type.) We didn’t fully iron out this idea yet, but one idea is to convert the current wp_term_relationships table to a more generic object relationships table, which can support posts to posts, posts to users, terms to users, and of course posts to terms (and, really, any arbitrary relationship).

A disclaimer: This post doesn’t promise anything. Do not rely on the contents of this post for future projects.  It will take us some time to lay out the proper groundwork and make sure we get this right. Do not expect this to happen in WordPress 3.7, or even 3.8. (Actually, do not expect this to happen at all.)

That said, I’m really glad to get this information out there and I’m excited to hear any feedback you may have. We are always thinking toward the future, and a lot of contributing developers have mile-long roadmaps in their heads — it’s long past time to get those on paper.

#post-types, #roadmaps, #taxonomy

WordPress 3.5 admin columns for custom taxonomies

WordPress 3.5 is here!! If you haven’t played with it yet, go get it!
I’m proud to be listed as a contributor on this releaseRelease A release is the distribution of the final version of an application. A software release may be either public or private and generally constitutes the initial or new generation of a new or upgraded application. A release is preceded by the distribution of alpha and then beta versions of the software. and want to highlight a new feature geared towards developers that I helped work on. If you have checked the register_taxonomy() codex page recently, you may have noticed a new optional argument, ‘show_admin_column.’

From the codex:

show_admin_column
(boolean) (optional) Whether to allow automatic creation of taxonomyTaxonomy A taxonomy is a way to group things together. In WordPress, some common taxonomies are category, link, tag, or post format. https://codex.wordpress.org/Taxonomies#Default_Taxonomies. columns on associated post-types.
Default: false

As stated, this new argument allows easy registration of taxonomy columns on post (and custom post typeCustom Post Type WordPress can hold and display many different types of content. A single item of such a content is generally called a post, although post is also a specific post type. Custom Post Types gives your site the ability to have templated posts, to simplify the concept.) list table screens much like the default tags’ and categories’ columns.

'show_admin_column' in action

This should makemake A collection of P2 blogs at make.wordpress.org, which are the home to a number of contributor groups, including core development (make/core, formerly "wpdevel"), the UI working group (make/ui), translators (make/polyglots), the theme reviewers (make/themes), resources for plugin authors (make/plugins), and the accessibility working group (make/accessibility). pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party and theme developers happy as they’ll no longer need to build these columns manually.

The new argument in action:

// hook into the init action and call create_activity_taxonomies when it fires
add_action( 'init', 'create_activity_taxonomies' );

// create taxonomy, "fitness-type" for the post type "activity"
function create_activity_taxonomies() {
	// Add new taxonomy, make it hierarchical (like categories)
	$labels = array(
		'name' => _x( 'Fitness Types', 'taxonomy general name' ),
		'singular_name' => _x( 'Fitness Type', 'taxonomy singular name' ),
		'search_items' => __( 'Search Fitness Types' ),
		'all_items' => __( 'All Fitness Types' ),
		'parent_item' => __( 'Parent Fitness Type' ),
		'parent_item_colon' => __( 'Parent Fitness Type:' ),
		'edit_item' => __( 'Edit Fitness Type' ),
		'update_item' => __( 'Update Fitness Type' ),
		'add_new_item' => __( 'Add New Fitness Type' ),
		'new_item_name' => __( 'New Fitness Type Name' ),
		'menu_name' => __( 'Fitness Type' ),
	);

	register_taxonomy( 'fitness-type', array( 'activity' ), array(
		'hierarchical' => true,
		'labels' => $labels,
		'show_ui' => true,
		'show_admin_column' => true,
		'query_var' => true,
		'rewrite' => array( 'slug' => 'fitness-type' ),
	) );
}

Another key addition is the “manage_taxonomies_for_{$post_type}_columnsfilterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output.. This allows developers to add a taxonomy column to a post type outside of the register_taxonomy() function:

Example:

add_filter( 'manage_taxonomies_for_activity_columns', 'activity_type_columns' );
function activity_type_columns( $taxonomies ) {
	$taxonomies[] = 'activity-type';
	return $taxonomies;
}

#3-5, #admin-columns, #dev-notes, #register_taxonomy, #taxonomy