-
Notifications
You must be signed in to change notification settings - Fork 94
Add wp term prune command to remove terms with 0 or 1 published posts
#586
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
Copilot
wants to merge
5
commits into
main
Choose a base branch
from
copilot/prune-terms-with-low-posts
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+240
−0
Draft
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
f1c0666
Initial plan
Copilot 23cd649
Add wp term prune command to delete terms with 0 or 1 published posts
Copilot ffec9fa
Update src/Term_Command.php
swissspidy 7140614
Update src/Term_Command.php
swissspidy be42053
Combine two foreach loops in prune() into a single loop
Copilot File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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
This file contains hidden or 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,137 @@ | ||
| Feature: Prune unused taxonomy terms | ||
|
|
||
| Background: | ||
| Given a WP install | ||
|
|
||
| Scenario: Prune terms with no published posts | ||
| When I run `wp term create post_tag 'Unused Tag' --slug=unused-tag --porcelain` | ||
| Then STDOUT should be a number | ||
| And save STDOUT as {TERM_ID} | ||
|
|
||
| When I run `wp term prune post_tag` | ||
| Then STDOUT should contain: | ||
| """ | ||
| Deleted post_tag {TERM_ID}. | ||
| """ | ||
| And STDOUT should contain: | ||
| """ | ||
| Success: | ||
| """ | ||
| And the return code should be 0 | ||
|
|
||
| When I try `wp term get post_tag {TERM_ID}` | ||
| Then STDERR should contain: | ||
| """ | ||
| Error: Term doesn't exist. | ||
| """ | ||
|
|
||
| Scenario: Does not prune terms with more than one published post | ||
| When I run `wp term create post_tag 'Popular Tag' --slug=popular-tag --porcelain` | ||
| Then STDOUT should be a number | ||
| And save STDOUT as {TERM_ID} | ||
|
|
||
| When I run `wp post create --post_title='Post 1' --post_status=publish --porcelain` | ||
| Then STDOUT should be a number | ||
| And save STDOUT as {POST_ID_1} | ||
|
|
||
| When I run `wp post create --post_title='Post 2' --post_status=publish --porcelain` | ||
| Then STDOUT should be a number | ||
| And save STDOUT as {POST_ID_2} | ||
|
|
||
| When I run `wp post term set {POST_ID_1} post_tag {TERM_ID} --by=id` | ||
| Then STDOUT should not be empty | ||
|
|
||
| When I run `wp post term set {POST_ID_2} post_tag {TERM_ID} --by=id` | ||
| Then STDOUT should not be empty | ||
|
|
||
| When I run `wp term prune post_tag` | ||
| Then STDOUT should not contain: | ||
| """ | ||
| Deleted post_tag {TERM_ID}. | ||
| """ | ||
|
|
||
| When I run `wp term get post_tag {TERM_ID} --field=name` | ||
| Then STDOUT should be: | ||
| """ | ||
| Popular Tag | ||
| """ | ||
|
|
||
| Scenario: Prune terms with exactly one published post | ||
| When I run `wp term create post_tag 'Single Post Tag' --slug=single-post-tag --porcelain` | ||
| Then STDOUT should be a number | ||
| And save STDOUT as {TERM_ID} | ||
|
|
||
| When I run `wp post create --post_title='Post 1' --post_status=publish --porcelain` | ||
| Then STDOUT should be a number | ||
| And save STDOUT as {POST_ID} | ||
|
|
||
| When I run `wp post term set {POST_ID} post_tag {TERM_ID} --by=id` | ||
| Then STDOUT should not be empty | ||
|
|
||
| When I run `wp term prune post_tag` | ||
| Then STDOUT should contain: | ||
| """ | ||
| Deleted post_tag {TERM_ID}. | ||
| """ | ||
| And the return code should be 0 | ||
|
|
||
| When I try `wp term get post_tag {TERM_ID}` | ||
| Then STDERR should contain: | ||
| """ | ||
| Error: Term doesn't exist. | ||
| """ | ||
|
|
||
| Scenario: Dry run previews terms without deleting them | ||
| When I run `wp term create post_tag 'Unused Tag' --slug=unused-tag --porcelain` | ||
| Then STDOUT should be a number | ||
| And save STDOUT as {TERM_ID} | ||
|
|
||
| When I run `wp term prune post_tag --dry-run` | ||
| Then STDOUT should contain: | ||
| """ | ||
| Would delete post_tag {TERM_ID}. | ||
| """ | ||
| And STDOUT should contain: | ||
| """ | ||
| Success: | ||
| """ | ||
| And the return code should be 0 | ||
|
|
||
| When I run `wp term get post_tag {TERM_ID} --field=name` | ||
| Then STDOUT should be: | ||
| """ | ||
| Unused Tag | ||
| """ | ||
|
|
||
| Scenario: Prune with an invalid taxonomy | ||
| When I try `wp term prune nonexistent_taxonomy` | ||
| Then STDERR should be: | ||
| """ | ||
| Error: Taxonomy nonexistent_taxonomy doesn't exist. | ||
| """ | ||
| And the return code should be 1 | ||
|
|
||
| Scenario: Prune multiple taxonomies at once | ||
| # Assign an extra post to the default Uncategorized category so its count | ||
| # exceeds the prune threshold and it won't interfere with the test. | ||
| When I run `wp post create --post_title='Extra Post' --post_status=publish --post_category=1 --porcelain` | ||
| Then STDOUT should be a number | ||
|
|
||
| When I run `wp term create post_tag 'Unused Tag' --slug=unused-tag --porcelain` | ||
| Then STDOUT should be a number | ||
| And save STDOUT as {TAG_TERM_ID} | ||
|
|
||
| When I run `wp term create category 'Unused Category' --slug=unused-category --porcelain` | ||
| Then STDOUT should be a number | ||
| And save STDOUT as {CAT_TERM_ID} | ||
|
|
||
| When I run `wp term prune post_tag category` | ||
| Then STDOUT should contain: | ||
| """ | ||
| Deleted post_tag {TAG_TERM_ID}. | ||
| """ | ||
| And STDOUT should contain: | ||
| """ | ||
| Deleted category {CAT_TERM_ID}. | ||
| """ | ||
| And the return code should be 0 |
This file contains hidden or 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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,6 +35,11 @@ | |
| * Success: Updated category term count | ||
| * Success: Updated post_tag term count | ||
| * | ||
| * # Prune terms with 0 or 1 published posts | ||
| * $ wp term prune post_tag | ||
| * Deleted post_tag 15. | ||
| * Success: Pruned 1 of 5 terms. | ||
| * | ||
| * @package wp-cli | ||
| */ | ||
| class Term_Command extends WP_CLI_Command { | ||
|
|
@@ -682,6 +687,103 @@ public function recount( $args ) { | |
| } | ||
| } | ||
|
|
||
| /** | ||
| * Removes terms with 0 or 1 published posts from one or more taxonomies. | ||
| * | ||
| * Useful for cleaning up large sites with many unused or barely-used terms. | ||
| * The term count is based on the number of published posts assigned to each | ||
| * term. | ||
| * | ||
| * ## OPTIONS | ||
| * | ||
| * <taxonomy>... | ||
| * : One or more taxonomies to prune. | ||
| * | ||
| * [--dry-run] | ||
| * : Preview the terms to be pruned, without actually deleting them. | ||
| * | ||
| * ## EXAMPLES | ||
| * | ||
| * # Prune post tags with 0 or 1 published posts. | ||
| * $ wp term prune post_tag | ||
| * Deleted post_tag 15. | ||
| * Success: Pruned 1 of 5 terms. | ||
| * | ||
| * # Dry run to preview which terms would be pruned. | ||
| * $ wp term prune post_tag --dry-run | ||
| * Would delete post_tag 15. | ||
| * Success: 1 post_tag term would be pruned. | ||
| * | ||
| * # Prune multiple taxonomies at once. | ||
| * $ wp term prune category post_tag | ||
| * Deleted category 8. | ||
| * Success: Pruned 1 of 3 terms. | ||
| * Deleted post_tag 15. | ||
| * Success: Pruned 1 of 5 terms. | ||
| */ | ||
| public function prune( $args, $assoc_args ) { | ||
| $dry_run = (bool) Utils\get_flag_value( $assoc_args, 'dry-run', false ); | ||
|
|
||
| foreach ( $args as $taxonomy ) { | ||
| if ( ! taxonomy_exists( $taxonomy ) ) { | ||
| WP_CLI::error( "Taxonomy {$taxonomy} doesn't exist." ); | ||
| } | ||
|
|
||
| $terms = get_terms( | ||
| [ | ||
| 'taxonomy' => $taxonomy, | ||
| 'hide_empty' => false, | ||
| ] | ||
| ); | ||
|
|
||
| // This should never happen because of the taxonomy_exists check above. | ||
| if ( is_wp_error( $terms ) ) { | ||
| WP_CLI::warning( "Could not retrieve terms for taxonomy {$taxonomy}." ); | ||
| continue; | ||
| } | ||
|
|
||
| /** | ||
| * @var \WP_Term[] $terms | ||
| */ | ||
|
|
||
| $total = count( $terms ); | ||
| $successes = 0; | ||
| $errors = 0; | ||
|
|
||
| foreach ( $terms as $term ) { | ||
| if ( $term->count > 1 ) { | ||
| continue; | ||
| } | ||
|
|
||
| if ( $dry_run ) { | ||
| WP_CLI::log( "Would delete {$taxonomy} {$term->term_id}." ); | ||
| ++$successes; | ||
| continue; | ||
| } | ||
|
|
||
| $result = wp_delete_term( $term->term_id, $taxonomy ); | ||
|
|
||
| if ( is_wp_error( $result ) ) { | ||
| WP_CLI::warning( $result ); | ||
| ++$errors; | ||
| } elseif ( $result ) { | ||
| WP_CLI::log( "Deleted {$taxonomy} {$term->term_id}." ); | ||
| ++$successes; | ||
| } else { | ||
| WP_CLI::warning( "Failed to delete {$taxonomy} {$term->term_id}." ); | ||
| ++$errors; | ||
| } | ||
| } | ||
|
|
||
| if ( $dry_run ) { | ||
| $term_word = Utils\pluralize( 'term', $successes ); | ||
| WP_CLI::success( "{$successes} {$taxonomy} {$term_word} would be pruned." ); | ||
| } else { | ||
| Utils\report_batch_operation_results( 'term', 'prune', $total, $successes, $errors ); | ||
| } | ||
| } | ||
|
Comment on lines
+727
to
+784
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Here is a suggested refactoring that applies these improvements: global $wpdb;
$dry_run = (bool) Utils\get_flag_value( $assoc_args, 'dry-run', false );
foreach ( $args as $taxonomy ) {
if ( ! taxonomy_exists( $taxonomy ) ) {
WP_CLI::error( "Taxonomy {$taxonomy} doesn't exist." );
}
$term_ids_to_prune = $wpdb->get_col(
$wpdb->prepare(
"SELECT term_id FROM {$wpdb->term_taxonomy} WHERE taxonomy = %s AND count <= 1",
$taxonomy
)
);
$total = count( $term_ids_to_prune );
$successes = 0;
$errors = 0;
if ( $total > 0 ) {
foreach ( $term_ids_to_prune as $term_id ) {
if ( $dry_run ) {
WP_CLI::log( "Would delete {$taxonomy} {$term_id}." );
++$successes;
continue;
}
$result = wp_delete_term( $term_id, $taxonomy );
if ( is_wp_error( $result ) ) {
WP_CLI::warning( $result );
++$errors;
} elseif ( $result ) {
WP_CLI::log( "Deleted {$taxonomy} {$term_id}." );
++$successes;
} else {
WP_CLI::warning( "Term {$term_id} in taxonomy {$taxonomy} doesn't exist." );
}
}
}
if ( $dry_run ) {
$term_word = Utils\pluralize( 'term', $successes );
WP_CLI::success( "{$successes} {$taxonomy} {$term_word} would be pruned." );
} else {
Utils\report_batch_operation_results( 'term', 'prune', $total, $successes, $errors );
}
} |
||
| } | ||
|
|
||
| /** | ||
| * Migrate a term of a taxonomy to another taxonomy. | ||
| * | ||
|
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.