Last active
April 26, 2017 19:21
-
-
Save CodeProKid/f90389e33faee23807fc18c2818f3e1f to your computer and use it in GitHub Desktop.
wp-cli command to swap terms
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class RK_Term_Swap extends WP_CLI { | |
/** | |
* Swaps one term for another on posts. | |
* | |
* ## OPTIONS | |
* <origin_term> | |
* : The term ID or slug of the term you want to query against, and remove from existing posts | |
* | |
* <origin_taxonomy> | |
* : The name of the taxonomy the origin term is in | |
* | |
* <destination_term> | |
* : The ID of the destination term to add to the post (if it already exists). If the term | |
* doesn't exist, you can just pass the name and it will create it for you. | |
* | |
* <destination_taxonomy> | |
* : The name of the taxonomy the new term is in | |
* | |
* [--origin_term_parent] | |
* : The slug or ID of the parent term for the origin term | |
* --- | |
* default: null | |
* options: | |
* - string (slug) | |
* - int (term_id) | |
* | |
* [--destination_term_parent] | |
* : The slug or ID of the parent term for the destination term | |
* --- | |
* default: null | |
* options: | |
* - string (slug) | |
* - int (term_id) | |
* | |
* [--detach_origin_term] | |
* : Whether or not to detach the origin term from the post | |
* --- | |
* default: true | |
* options: | |
* - true | |
* - false | |
* | |
* [--delete_origin_term] | |
* : Whether or not to delete the old term from the system completely | |
* default: false | |
* options: | |
* - true | |
* - false | |
* | |
* [--author_id] | |
* : Narrow results to posts attached to a particular author ID | |
* --- | |
* default: null | |
* options: | |
* - int (author term id) | |
* | |
* ## EXAMPLES | |
* | |
* # Adds a new tag called "MyEvent" to all posts categorized under "Events" and removes | |
* them from that category, and deletes the "Events" term | |
* $ wp mason swap-terms Events category MyEvent post_tag --delete_origin_term=true | |
* | |
* # Attaches all posts tagged with the "MyEvent" tag to an existing "Events" category | |
* and leaves the tag attached to the post | |
* $ wp mason swap-terms MyEvent post_tag events category --destination_term_parent=entertainment --detatch_origin_term=false | |
* | |
* @subcommand swap-terms | |
* | |
* @param array $args | |
* @param array $assoc_args | |
*/ | |
public function swap_terms( $args, $assoc_args ) { | |
// Map args to variables | |
$origin_term = ( isset( $args[0] ) ) ? $args[0] : ''; | |
$origin_taxonomy = ( isset( $args[1] ) ) ? $args[1] : ''; | |
$destination_term = ( isset( $args[2] ) ) ? $args[2] : ''; | |
$destination_taxonomy = ( isset( $args[3] ) ) ? $args[3] : ''; | |
// First thing we should do is check if the origin and destination taxonomies exist. No need to go any further if they don't | |
if ( ! taxonomy_exists( $origin_taxonomy ) ) { | |
WP_CLI::error( sprintf( __( 'Origin taxonomy "%s" does not exist', 'mason' ), $origin_taxonomy ) ); | |
} elseif ( ! taxonomy_exists( $destination_taxonomy ) ) { | |
WP_CLI::error( sprintf( __( 'Destination taxonomy "%s" does not exist', 'mason' ), $destination_taxonomy ) ); | |
} | |
// Setup the default args for the script | |
$default_args = array( | |
'origin_term_parent' => '', | |
'destination_term_parent' => '', | |
'detach_origin_term' => 'true', | |
'delete_origin_term' => 'false', | |
'author_id' => '', | |
); | |
$settings = wp_parse_args( $assoc_args, $default_args ); | |
// Need an ID for parent term, so get one if a slug is passed | |
if ( ! empty( $settings['origin_term_parent'] ) && is_string( $settings['origin_term_parent'] ) ) { | |
$settings['origin_term_parent'] = $this->get_term_id_from_slug( $settings['origin_term_parent'], $origin_taxonomy ); | |
} | |
if ( ! empty( $settings['destination_term_parent'] ) && is_string( $settings['destination_term_parent'] ) ) { | |
$settings['destination_term_parent'] = $this->get_term_id_from_slug( $settings['destination_term_parent'], $destination_taxonomy ); | |
} | |
// Check to make sure the origin term actually exists | |
if ( ! $origin_term_array = wpcom_vip_term_exists( $origin_term, $origin_taxonomy, $settings['origin_term_parent'] ) ) { | |
WP_CLI::error( sprintf( __( 'Origin term "%s" does not exist in the "%s" taxonomy', 'mason' ), $origin_term, $origin_taxonomy ) ); | |
} else { | |
$origin_term_id = (int) $origin_term_array['term_id']; | |
} | |
// If the destination term doesn't exist, we have to create it, otherwise just return the term ID | |
if ( ! $destination_term_array = wpcom_vip_term_exists( $destination_term, $destination_taxonomy, $settings['destination_term_parent'] ) ) { | |
$term_insert = wp_insert_term( $destination_term, $destination_taxonomy, array( 'parent' => $settings['destination_term_parent'] ) ); | |
if ( empty( $term_insert ) || is_wp_error( $term_insert ) ) { | |
WP_CLI::error( sprintf( __( 'Oh no! Something went wrong here. We tried to create your new destination term "%s" in the "%s" taxonomy, but it failed.', 'mason' ), $destination_term, $destination_taxonomy ) ); | |
} else { | |
WP_CLI::success( sprintf( __( 'We successfully created a new term with the id "%d" for the "%s" term in the "%s" taxonomy', 'mason' ), $term_insert['term_id'], $destination_term, $destination_taxonomy ) ); | |
$destination_term_id = $term_insert['term_id']; | |
} | |
} else { | |
$destination_term_id = (int) $destination_term_array['term_id']; | |
} | |
$tax_query = array( 'relation' => 'AND' ); | |
$tax_query[] = array( | |
'taxonomy' => $origin_taxonomy, | |
'field' => 'term_id', | |
'include_children' => false, | |
'terms' => $origin_term_id, | |
); | |
if ( ! empty( $settings['author_id'] ) ) { | |
if ( false === wpcom_vip_term_exists( (int) $settings['author_id'], 'author' ) ) { | |
WP_CLI::error( sprintf( __( 'Could not find an author with the ID: %s', 'mason' ), $settings['author_id'] ) ); | |
} else { | |
$tax_query[] = array( | |
'taxonomy' => 'author', | |
'field' => 'term_id', | |
'terms' => (int) $settings['author_id'], | |
); | |
} | |
} | |
WP_CLI::success( __( 'Starting query for posts attached to origin term...', 'mason' ) ); | |
WP_CLI::line(); | |
WP_CLI::line(); | |
// Build out the args | |
$query_args = array( | |
'post_type' => 'post', | |
'post_status' => 'publish', | |
'posts_per_page' => 100, | |
'fields' => 'ids', | |
'tax_query' => $tax_query, | |
); | |
$total_posts_query = new WP_Query( $query_args ); | |
$total_posts = $total_posts_query->found_posts; | |
WP_CLI::success( 'total posts found: ' . $total_posts ); | |
$progress = \WP_CLI\Utils\make_progress_bar( __( 'Swapping Terms', 'mason' ), $total_posts ); | |
$posts_affected = 0; | |
$page = 1; | |
// Kick off a do while loop | |
do { | |
// Need to page the query if we are not detaching the origin term | |
if ( 'false' === $settings['detach_origin_term'] ) { | |
$query_args['paged'] = $page; | |
} | |
$query = new WP_Query( $query_args ); | |
$posts_with_term = $query->posts; | |
if ( is_array( $posts_with_term ) && ! empty( $posts_with_term ) ) { | |
foreach ( $posts_with_term as $id ) { | |
// Add the new term to the post | |
$result = wp_add_object_terms( $id, $destination_term_id, $destination_taxonomy ); | |
// Make sure the term got attached properly | |
if ( ! is_wp_error( $result ) ) { | |
// If we should detach the old term, do it here. | |
if ( 'true' === $settings['detach_origin_term'] ) { | |
$removal = wp_remove_object_terms( $id, $origin_term, $origin_taxonomy ); | |
if ( true !== $removal ) { | |
// Die if we couldn't handle the old term removal for some reason | |
WP_CLI::error( sprintf( __( 'Oh no! Could not remove term "%s" from post ID: "%d"', 'mason' ), $origin_term, $id ) ); | |
} | |
} | |
$posts_affected++; | |
$progress->tick(); | |
} else { | |
WP_CLI::error( sprintf( __( 'Could not add the term "%s" to post ID "%d"', 'mason' ), $destination_term, $id ) ); | |
} | |
} | |
} | |
$page++; | |
} while( 0 < count ( $posts_with_term ) ); | |
$progress->finish(); | |
// If we should delete the original term, do it now. | |
if ( 'true' === $settings['delete_origin_term'] ) { | |
$delete_origin_term = wp_delete_term( $origin_term_id, $origin_taxonomy ); | |
// Make sure the term actually got deleted | |
if ( true !== $delete_origin_term ) { | |
WP_CLI::warning( sprintf( __( 'Could not delete the term "%s" from the "%s" taxonomy for whatever reason. Please delete it from the admin manually', 'mason' ), $origin_term, $origin_taxonomy ) ); | |
} else { | |
WP_CLI::success( sprintf( __( 'Successfully deleted the term "%s" from the "%s" taxonomy', 'mason' ), $origin_term, $origin_taxonomy ) ); | |
} | |
} | |
WP_CLI::success( sprintf( __( 'All done here, %d posts affected', 'mason' ), $posts_affected ) ); | |
} | |
/** | |
* Get's the term_id from the term slug. | |
* | |
* @param string $slug Term slug name | |
* @param string $taxonomy Name of the taxonomy the term is in | |
* @return mixed|int Either kill the script, or return the term_id | |
*/ | |
private function get_term_id_from_slug( $slug, $taxonomy ) { | |
$term_obj = wpcom_vip_get_term_by( 'slug', $slug, $taxonomy ); | |
if ( ! empty( $term_obj ) && ! is_wp_error( $term_obj ) ) { | |
WP_CLI::success( sprintf( __( 'Found a term id "%d" for slug "%s" in the "%s" taxonomy', 'mason' ), $term_obj->term_id, $slug, $taxonomy ) ); | |
return $term_obj->term_id; | |
} else { | |
WP_CLI::error( sprintf( __( 'Could not find an id for the term slug "%s" in the "%s" taxonomy', 'mason' ), $slug, $taxonomy ) ); | |
} | |
} | |
} | |
WP_CLI::add_command( 'rk', 'RK_Term_Swap' ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment