A better ‘categories to tags’ converter for WordPress

Are you a WordPress enthusiast? Whether you are a casual blogger or a professional editor, Nelio Content is the editorial calendar that makes your life easier. Take a look at it!

No matter how carefully you plan your tags and category taxonomies at the beginning of your blog project, they will quickly degenerate and become a complete mess. This is specially true for tags on multi-author blogs where each author can freely assign new tags to their posts. So, like it or not, every few months you’ll need to sanitize your terms by converting categories to tags (or the other way around), merging duplicate terms, updating hierarchies and so on.

For the category-to-tags conversion, the obvious choice is the “Categories to tags Converter” plugin. Even if, striclty speaking, this plugin is not part of the WordPress core, it is authored by the WordPress.org team and the default conversion tool you get when accessing the Tools->Import option in your dashboard. For more advanced terms management you can try the Term Management Tools plugin (still working even if its development stopped after his author announced he was leaving WordPress).

Still, both options present a very annoying limitation when trying to convert into tags categories that are part of a hierarchy: posts assigned to a subcategory being converted are not reassigned to its parent category. Let me explain this with an example. In one of my sites, I’ve the following structure:

Category 'programming' has Python, Ruby and Java as subcategories
Category ‘programming’ has Python, Ruby and Java as subcategories

Since very few posts are specific to one of the programming languages, I want to transform them to tags and leave only programming as a category to simplify my content organization. If I try to do it with the previous plugins, I’ll manage to convert Java, Pyhton and Ruby to tags and use these new tags to annotate the corresponding posts but all those posts will disappear from my programming category!!! Clearly, this is not the intended effect. Those are still programming posts and must be found by visitors browsing the programming category. Otherwise, the converter plugins may fix the mess in my taxonomies but at the cost of messing up my site content.

To fix this, I’ve slightly changed the file wpcat2tag-importer.php (the single file containing all the conversion logic of the default plugin) to add the following lines to the function convert_categories()


//Force the posts linked to the converted category to be linked as well to their parent category
if ($category->parent)
{
    $term_order = 0;
    echo __('Linking posts with parent category.', 'wpcat2tag-importer') . "\n";
    $objects_ids = get_objects_in_term($category->term_id, 'category');
    $parent_category=& get_category($category->parent);
    $parent_taxonomy_id=$parent_category->term_taxonomy_id;
    foreach ( $objects_ids as $object_id ) {
        $exists=$wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d AND object_id=%d",$parent_taxonomy_id, $object_id));
        if($exists==0)
        {
            $wpdb->insert($wpdb->term_relationships, array('object_id'=>$object_id, 'term_taxonomy_id'=>$parent_taxonomy_id,'term_order'=>$term_order),array('%d','%d','%d'));
            $count =$wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM $wpdb->term_relationships WHERE term_taxonomy_id = %d",$parent_taxonomy_id));
            $wpdb->update($wpdb->term_taxonomy, array('count' => $count), array('term_id' => $category->parent, 'taxonomy' => 'category'));
        }
    }
}

In short, the code retrieves the posts linked to the category-to-be-converted and for each post checks if the post is also linked to its parent category (in case a parent exist). If not, it adds the link.

Programming category after the conversion, linking to all posts of its former subcategories
Programming category after the conversion, linking to all posts of its former subcategories

Free bonus rant

So, what should I do with this improvement? (let’s assume for a moment that you believe as I do that this is in fact an improvement on the base plugin). The easiest option would be to just add this modification as new plugin on WordPress.org. But, even if we make it nicer and with more options, 1 – I don’t think this is a change big enough to justify a new plugin and 2 – This would not reach all users of the current plugin.

What I really want is to send my patch to the plugin authors so that they study it and openly consider whether this could be integrated in the official (again, not part of the core but as if it was) plugin. Unfortunately, there doesn’t seem to be an easy way to do so (there’s no public repository where to submit a patch/pull request and have an open discussion about it and the support forum seems largely ignored, and even if it wasn’t, I don’t think that would be the place for this). For such an open project like WordPress, I’d definitely expect more open practices for all the ecosystem around it.

Therefore, for now I’m afraid if you’re interested in this functionality, the best option is to copy and paste the above lines of code in your installed PHP file.

Leave a Reply

Your email address will not be published. Required fields are marked *