Skip to content

Instantly share code, notes, and snippets.

@CodeProKid
Last active April 26, 2017 19:21
Show Gist options
  • Save CodeProKid/f90389e33faee23807fc18c2818f3e1f to your computer and use it in GitHub Desktop.
Save CodeProKid/f90389e33faee23807fc18c2818f3e1f to your computer and use it in GitHub Desktop.
wp-cli command to swap terms
<?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