Skip to content

Instantly share code, notes, and snippets.

@pierrerocket
Created September 13, 2024 15:22
Show Gist options
  • Save pierrerocket/12c0f4c4d10f4a9916c5b9931cfe7018 to your computer and use it in GitHub Desktop.
Save pierrerocket/12c0f4c4d10f4a9916c5b9931cfe7018 to your computer and use it in GitHub Desktop.
WP CLI to Migrate Categories to Tags and set a category for Posts.
// It's pretty common to be working on sites where clients used categories all wrong and you want to migrate those to tags.
// I wrote this for a site with a lot of posts and I didnt want to risk it failing.
if (defined('WP_CLI') && WP_CLI) {
class Migrate_Categories_To_Tags_Command {
/**
* Migrate categories to tags, clear existing tags, and update posts.
*
* ## EXAMPLES
*
* wp migrate categories-to-tags
*
* @when after_wp_load
*/
public function __invoke() {
$target_category_name = 'Category Name';
$posts = get_posts(['post_type' => 'post', 'numberposts' => -1, 'post_status' => 'any']);
if (empty($posts)) {
WP_CLI::success("No posts found.");
return;
}
// Check if the target category exists, if not create it
$target_category = get_term_by('name', $target_category_name, 'category');
if (!$target_category) {
$result = wp_insert_term($target_category_name, 'category');
if (is_wp_error($result)) {
WP_CLI::error("Failed to create target category '$target_category_name'.");
return;
}
$target_category_id = $result['term_id'];
WP_CLI::success("Created target category '$target_category_name'.");
} else {
$target_category_id = $target_category->term_id;
WP_CLI::success("Target category '$target_category_name' already exists.");
}
$all_categories_verified = true;
foreach ($posts as $post) {
WP_CLI::line("Processing post: {$post->ID}");
// Read post categories
$categories = wp_get_post_categories($post->ID);
$category_names = [];
foreach ($categories as $category_id) {
$category = get_term($category_id, 'category');
if ($category) {
$category_names[] = $category->name;
}
}
WP_CLI::line("Categories found for post {$post->ID}: " . implode(', ', $category_names));
// Clear existing tags
WP_CLI::line("Clearing existing tags for post {$post->ID}...");
wp_set_post_tags($post->ID, []);
// Create tags identical to post categories
$tags_created = [];
foreach ($category_names as $category_name) {
$existing_tag = get_term_by('name', $category_name, 'post_tag');
if (!$existing_tag) {
$result = wp_insert_term($category_name, 'post_tag');
if (is_wp_error($result)) {
WP_CLI::warning("Failed to create tag '$category_name': " . $result->get_error_message());
continue; // Skip this tag creation due to error
}
$tags_created[] = $category_name;
WP_CLI::line("Tag created: $category_name");
} else {
$tags_created[] = $existing_tag->name;
WP_CLI::line("Tag already exists: $category_name");
}
}
WP_CLI::line("Tags Created/Found for post {$post->ID}: " . implode(', ', $tags_created));
// Assign tags to the post
wp_set_post_tags($post->ID, $tags_created);
// Retrieve and normalize created tags
$tags = get_the_tags($post->ID);
if ($tags === false) {
WP_CLI::line("No tags found for post ID {$post->ID} after creation.");
$tag_names = [];
} else {
$tag_names = array_map(function($tag) {
return trim(strtolower($tag->name));
}, $tags);
}
$normalized_category_names = array_map('trim', array_map('strtolower', $category_names));
// Verify if tags match the post's categories
$tags_match = !(array_diff($normalized_category_names, $tag_names) || array_diff($tag_names, $normalized_category_names));
if ($tags_match) {
WP_CLI::line("Tags and Categories match for post ID {$post->ID}.");
} else {
WP_CLI::line("Tags and Categories don't match for post ID {$post->ID}.");
WP_CLI::line("Categories: " . implode(', ', $normalized_category_names));
WP_CLI::line("Tags: " . implode(', ', $tag_names));
$missing_tags = array_diff($normalized_category_names, $tag_names);
$extra_tags = array_diff($tag_names, $normalized_category_names);
if (!empty($missing_tags)) {
WP_CLI::line("Missing Tags (should have been created): " . implode(', ', $missing_tags));
}
if (!empty($extra_tags)) {
WP_CLI::line("Extra Tags (should not exist): " . implode(', ', $extra_tags));
}
$all_categories_verified = false;
WP_CLI::error("Verification failed for post ID {$post->ID}. Stopping process.");
return;
}
// Finalize by clearing categories and assigning a category to the post
wp_set_post_categories($post->ID, [$target_category_id]);
WP_CLI::line("Categories Deleted and New Category Assigned to post ID {$post->ID}");
}
if ($all_categories_verified) {
WP_CLI::success("All tags successfully verified to match categories.");
}
}
}
WP_CLI::add_command('migrate categories-to-tags', 'Migrate_Categories_To_Tags_Command');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment