Skip to content
89 changes: 89 additions & 0 deletions features/term-migrate.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
Feature: Manage term custom fields

@require-wp-4.4
Scenario: Migrate an existing term by slug
Given a WP install

When I run `wp term create category apple`
Then STDOUT should not be empty

When I run `wp post create --post_title='Test post' --porcelain`
Then STDOUT should be a number
And save STDOUT as {POST_ID}

When I run `wp post term set {POST_ID} category apple`
Then STDOUT should not be empty

When I run `wp term migrate apple --by=slug --from=category --to=post_tag`
Then STDOUT should be:
"""
Term 'apple' assigned to post 4.
Term 'apple' migrated.
Old instance of term 'apple' removed from its original taxonomy.
Success: Migrated the term 'apple' from taxonomy 'category' to taxonomy 'post_tag' for 1 post.
"""

@require-wp-4.4
Scenario: Migrate an existing term by ID
Given a WP install

When I run `wp term create category apple --porcelain`
Then STDOUT should be a number
And save STDOUT as {TERM_ID}

When I run `wp post create --post_title='Test post' --porcelain`
Then STDOUT should be a number
And save STDOUT as {POST_ID}

When I run `wp post term set {POST_ID} category {TERM_ID}`
Then STDOUT should not be empty

When I run `wp term migrate {TERM_ID} --by=slug --from=category --to=post_tag`
Then STDOUT should be:
"""
Term '{TERM_ID}' assigned to post 4.
Term '{TERM_ID}' migrated.
Old instance of term '{TERM_ID}' removed from its original taxonomy.
Success: Migrated the term '{TERM_ID}' from taxonomy 'category' to taxonomy 'post_tag' for 1 post.
"""

@require-wp-4.4
Scenario: Migrate a term in multiple posts
Given a WP install

When I run `wp term create category orange`
Then STDOUT should not be empty

When I run `wp post create --post_title='Test post' --porcelain`
Then STDOUT should be a number
And save STDOUT as {POST_ID}

When I run `wp post term set {POST_ID} category orange`
Then STDOUT should not be empty

When I run `wp post create --post_title='Test post 2' --porcelain`
Then STDOUT should be a number
And save STDOUT as {POST_ID}

When I run `wp post term set {POST_ID} category orange`
Then STDOUT should not be empty

When I run `wp term migrate orange --by=slug --from=category --to=post_tag`
Then STDOUT should be:
"""
Term 'orange' assigned to post 4.
Term 'orange' assigned to post 5.
Term 'orange' migrated.
Old instance of term 'orange' removed from its original taxonomy.
Success: Migrated the term 'orange' from taxonomy 'category' to taxonomy 'post_tag' for 2 posts.
"""

@require-wp-4.4
Scenario: Try to migrate a term that does not exist
Given a WP install

When I try `wp term migrate peach --by=slug --from=category --to=post_tag`
Then STDERR should be:
"""
Error: Taxonomy term 'peach' for taxonomy 'category' doesn't exist.
"""
84 changes: 84 additions & 0 deletions src/Term_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,90 @@ public function recount( $args ) {
}
}

/**
* Migrate a term of a taxonomy to another taxonomy.
*
* ## OPTIONS
*
* <term>
* : Slug or ID of the term to migrate.
*
* [--by=<field>]
* : Explicitly handle the term value as a slug or id.
* ---
* default: id
* options:
* - slug
* - id
* ---
*
* [--from=<taxonomy>]
* : Taxonomy slug of the term to migrate.
*
* [--to=<taxonomy>]
* : Taxonomy slug to migrate to.
*
* ## EXAMPLES
*
* # Migrate a category's term (video) to tag taxonomy.
* $ wp term migrate 9190 --from=category --to=post_tag
* Term '9190' migrated!
* Old instance of term '9190' removed from its original taxonomy.
* Success: Migrated the term '9190' from taxonomy 'category' to taxonomy 'post_tag' for 1 posts
*/
public function migrate( $args, $assoc_args ) {
$clean_term_cache = $values = array();
$term_reference = $args[0];
$original_taxonomy = Utils\get_flag_value( $assoc_args, 'from' );
$destination_taxonomy = Utils\get_flag_value( $assoc_args, 'to' );

$term = get_term_by( Utils\get_flag_value( $assoc_args, 'by' ), $term_reference, $original_taxonomy );

if ( ! $term ) {
WP_CLI::error( "Taxonomy term '{$term_reference}' for taxonomy '{$original_taxonomy}' doesn't exist." );
}

$original_taxonomy = get_taxonomy( $original_taxonomy );

$id = wp_insert_term( $term->name, $destination_taxonomy, array( 'slug' => $term->slug, 'parent' => 0, 'description' => $term->description ) );

if ( is_wp_error( $id ) ) {
WP_CLI::error( $id->get_error_message() );
}

$post_ids = get_objects_in_term( $term->term_id, $original_taxonomy->name );

foreach ( $post_ids as $post_id ) {
$type = get_post_type( $post_id );
if ( in_array( $type, $original_taxonomy->object_type ) ) {
$term_taxonomy_id = wp_set_object_terms( $post_id, $id['term_id'], $destination_taxonomy, true );

if ( is_wp_error( $term_taxonomy_id ) ) {
WP_CLI::error( "Failed to assign the term '{$term->slug}' to the post {$post_id}. Reason: " . $term_taxonomy_id->get_error_message() );
}

WP_CLI::log( "Term '{$term->slug}' assigned to post {$post_id}." );
}

clean_post_cache( $post_id );
}

clean_term_cache( $term->term_id );

WP_CLI::log( "Term '{$term->slug}' migrated." );

$del = wp_delete_term( $term->term_id, $original_taxonomy->name );

if ( is_wp_error( $del ) ) {
WP_CLI::error( "Failed to delete the term '{$term->slug}'. Reason: " . $del->get_error_message() );
}

WP_CLI::log( "Old instance of term '{$term->slug}' removed from its original taxonomy." );
$post_count = count( $post_ids );
$post_plural = WP_CLI\Utils\pluralize( 'post', $post_count );
WP_CLI::success( "Migrated the term '{$term->slug}' from taxonomy '{$original_taxonomy->name}' to taxonomy '{$destination_taxonomy}' for {$post_count} {$post_plural}." );
}

private function maybe_make_child() {
// 50% chance of making child term
return ( mt_rand(1, 2) == 1 );
Expand Down