Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save shayanabbas/aa6b79010dc0be06e9228f8901fd78a7 to your computer and use it in GitHub Desktop.
Save shayanabbas/aa6b79010dc0be06e9228f8901fd78a7 to your computer and use it in GitHub Desktop.
The script provided below is a WP-CLI command script that renames the 'industry' taxonomy to 'segment' and migrates all terms and associated posts.

WordPress Taxonomy Migration: A Robust WP-CLI Command

In the world of WordPress, taxonomies are a way to group things together. We've all dealt with categories and tags, which are a couple of taxonomies that come built into WordPress. But sometimes, you may need to rename a custom taxonomy and ensure that all the terms under that taxonomy get migrated to the newly named taxonomy.

Today, I will introduce a WP-CLI command that renames a custom taxonomy while preserving all its terms. The script also ensures it only runs once to prevent any inadvertent reruns.

In our example, we're migrating the taxonomy 'industry' to a new taxonomy called 'segment'. Both these taxonomies are related to a custom post type 'case'.

The WP-CLI Command Script

The script provided below is a WP-CLI command script that renames the 'industry' taxonomy to 'segment' and migrates all terms and associated posts.

<?php
/**
 * Plugin Name: WP CLI Taxonomy Migration
 * Description: Renames the 'industry' taxonomy to 'segment' and migrates all terms and associated posts.
 * Version: 1.0
 */

// Register the WP-CLI command for the migration
if (defined('WP_CLI') && WP_CLI) {
    WP_CLI::add_command('migrate_terms', 'TaxonomyMigrationCommand');
}

// WP-CLI command class for the migration
class TaxonomyMigrationCommand extends WP_CLI_Command
{
    /**
     * Renames the 'industry' taxonomy to 'segment' and migrates all terms and associated posts.
     *
     * ## EXAMPLES
     *
     * wp migrate_terms
     *
     * @when after_wp_load
     */
    public function __invoke()
    {
        // Check if the migration has already been done
        if (get_transient('taxonomy_migration_done')) {
            WP_CLI::success('Taxonomy migration has already been completed.');
            return;
        }

        // Migrate terms from 'industry' to 'segment'
        $this->migrateTerms('industry', 'segment');

        // Set the flag indicating the migration is done
        set_transient('taxonomy_migration_done', true, YEAR_IN_SECONDS);

        WP_CLI::success('Taxonomy migration completed successfully.');
    }

    /**
     * Migrates terms from one taxonomy to another and updates associated posts.
     *
     * @param string $sourceTaxonomy Source taxonomy to migrate from.
     * @param string $targetTaxonomy Target taxonomy to migrate to.
     */
    private function migrateTerms($sourceTaxonomy, $targetTaxonomy)
    {
        // Get all terms from the source taxonomy
        $terms = get_terms([
            'taxonomy' => $sourceTaxonomy,
            'hide_empty' => false,
        ]);

        // Loop through each term and migrate it to the target taxonomy
        foreach ($terms as $term) {
            // Create a new term in the target taxonomy with the same properties
            $newTerm = wp_insert_term($term->name, $targetTaxonomy, [
                'slug' => $term->slug,
                'description' => $term->description,
                'parent' => $term->parent,
            ]);

            // Check if the new term was created successfully
            if (!is_wp_error($newTerm)) {
                // Get all posts associated with the current term
                $posts = get_posts([
                    'post_type' => 'case',
                    'tax_query' => [
                        [
                            'taxonomy' => $sourceTaxonomy,
                            'field' => 'slug',
                            'terms' => $term->slug,
                        ],
                    ],
                    'posts_per_page' => -1,
                ]);

                // Loop through each post and update the taxonomy references
                foreach ($posts as $post) {
                    // Update the post's taxonomy terms from 'industry' to 'segment'
                    wp_set_post_terms($post->ID, [$newTerm['term_id']], $targetTaxonomy, true);
                }
            }
        }
    }
}

This script can be placed in your theme's functions.php file or within a custom plugin file.

Adding the Script as a Plugin

To add the code as a custom plugin, follow these steps:

  1. Create a new folder in the /wp-content/plugins/ directory of your WordPress installation. For example, create a folder called taxonomy-migration.
  2. Create a new PHP file inside the folder and name it taxonomy-migration.php.
  3. Open the taxonomy-migration.php file and paste the entire code provided above into it.
  4. Save the file.

After following these steps, the plugin should be ready to use. You can activate it from the WordPress admin dashboard's Plugins section.

Adding the Script in the functions.php File

To add the code in your theme's functions.php file, follow these steps:

  1. Open your theme's functions.php file.
  2. Paste the entire code provided above at the end of the file.
  3. Save the file.

After making these changes, the script will be added to your theme's functions.php file and will be ready to use.

In our example, we're migrating the taxonomy 'industry' to a new taxonomy called 'segment'. Both these taxonomies are related to a custom post type 'case'.
<?php
/**
* Plugin Name: WP CLI Taxonomy Migration
* Description: Renames the 'industry' taxonomy to 'segment' and migrates all terms and associated posts.
* Version: 1.0
*/
// Register the WP-CLI command for the migration
if (defined('WP_CLI') && WP_CLI) {
WP_CLI::add_command('migrate_terms', 'TaxonomyMigrationCommand');
}
// WP-CLI command class for the migration
class TaxonomyMigrationCommand extends WP_CLI_Command
{
/**
* Renames the 'industry' taxonomy to 'segment' and migrates all terms and associated posts.
*
* ## EXAMPLES
*
* wp migrate_terms
*
* @when after_wp_load
*/
public function __invoke()
{
// Check if the migration has already been done
if (get_transient('taxonomy_migration_done')) {
WP_CLI::success('Taxonomy migration has already been completed.');
return;
}
// Migrate terms from 'industry' to 'segment'
$this->migrateTerms('industry', 'segment');
// Set the flag indicating the migration is done
set_transient('taxonomy_migration_done', true, YEAR_IN_SECONDS);
WP_CLI::success('Taxonomy migration completed successfully.');
}
/**
* Migrates terms from one taxonomy to another and updates associated posts.
*
* @param string $sourceTaxonomy Source taxonomy to migrate from.
* @param string $targetTaxonomy Target taxonomy to migrate to.
*/
private function migrateTerms($sourceTaxonomy, $targetTaxonomy)
{
// Get all terms from the source taxonomy
$terms = get_terms([
'taxonomy' => $sourceTaxonomy,
'hide_empty' => false,
]);
// Loop through each term and migrate it to the target taxonomy
foreach ($terms as $term) {
// Create a new term in the target taxonomy with the same properties
$newTerm = wp_insert_term($term->name, $targetTaxonomy, [
'slug' => $term->slug,
'description' => $term->description,
'parent' => $term->parent,
]);
// Check if the new term was created successfully
if (!is_wp_error($newTerm)) {
// Get all posts associated with the current term
$posts = get_posts([
'post_type' => 'case',
'tax_query' => [
[
'taxonomy' => $sourceTaxonomy,
'field' => 'slug',
'terms' => $term->slug,
],
],
'posts_per_page' => -1,
]);
// Loop through each post and update the taxonomy references
foreach ($posts as $post) {
// Update the post's taxonomy terms from 'industry' to 'segment'
wp_set_post_terms($post->ID, [$newTerm['term_id']], $targetTaxonomy, true);
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment