Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
0ccc287
feat: add --all flag to comment delete command
shawnhooper Oct 15, 2025
be45039
fix: linting errors
shawnhooper Oct 15, 2025
24f1c4c
fix: phpstan issues
shawnhooper Oct 15, 2025
c4d8775
fix: phpstan issues
shawnhooper Oct 15, 2025
ea5d314
fix: incorrect return type
shawnhooper Oct 15, 2025
846b801
fix: always return array
shawnhooper Oct 15, 2025
6dbf62d
fix: code style
shawnhooper Oct 15, 2025
e0f124b
fix: update test expectations to handle comment deletion order
shawnhooper Oct 15, 2025
000c832
fix: remove $exclude code
shawnhooper Oct 16, 2025
860bb2b
fix: defer comment counts
shawnhooper Oct 20, 2025
3af6933
fix: strict comparison on mixed
shawnhooper Oct 20, 2025
3c9ea3c
fix: strict comparison on mixed
shawnhooper Oct 20, 2025
95e7211
fix: phpcs comparison
shawnhooper Oct 20, 2025
1e396e8
fix: behat tests. Add checks for multiple success lines
shawnhooper Oct 20, 2025
a7849ca
fix: behat tests. Add checks for multiple success lines
shawnhooper Oct 20, 2025
669caae
test: Delete comments with explicit defer-term-counting flag
shawnhooper Oct 20, 2025
8a3df5b
test: Success/Error returns
shawnhooper Oct 20, 2025
db90889
fix: remove --defer-comment-count flag, not referenced in coommand def
shawnhooper Oct 21, 2025
1c8144c
test: return to STDERR
shawnhooper Oct 21, 2025
37c0ba6
test: combined success/warning output to STDOUT
shawnhooper Oct 21, 2025
61f74b6
test: trying to get combined success/fail ouput
shawnhooper Oct 21, 2025
d33e0b8
test: add blank line to return
shawnhooper Oct 21, 2025
fc0e2a2
test: could it be STDERR, now that we have the foramtting fixed?
shawnhooper Oct 21, 2025
fb2d6be
test: Separates STDOUT and STDERR
shawnhooper Oct 21, 2025
d0dd60a
Last try on STDOUT
shawnhooper Oct 21, 2025
a8bdff2
test: ah, the problem was I try vs I run
shawnhooper Oct 21, 2025
c26733a
revert: comment change
shawnhooper Oct 28, 2025
6efbeed
lint: use @var instead of not is_array check
shawnhooper Oct 28, 2025
3c52d46
doc: include warning about potential slow command
shawnhooper Oct 28, 2025
bc3cc1d
lint: remove additional spaces
shawnhooper Oct 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions features/comment.feature
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Feature: Manage WordPress comments
"""
Success: Trashed comment 3.
Success: Trashed comment 4.
Success: Deleted 2 comments.
"""

When I run `wp comment delete 3`
Expand Down Expand Up @@ -472,3 +473,148 @@ Feature: Manage WordPress comments
And I run `wp comment unspam {COMMENT_ID} --url=www.example.com`
And I run `wp comment trash {COMMENT_ID} --url=www.example.com`
And I run `wp comment untrash {COMMENT_ID} --url=www.example.com`

Scenario: Delete all comments with --all flag
Given a WP install
And I run `wp comment create --comment_post_ID=1 --comment_content='Comment 1' --porcelain`
And save STDOUT as {COMMENT_ID_1}
And I run `wp comment create --comment_post_ID=1 --comment_content='Comment 2' --porcelain`
And save STDOUT as {COMMENT_ID_2}
And I run `wp comment create --comment_post_ID=1 --comment_content='Comment 3' --porcelain`
And save STDOUT as {COMMENT_ID_3}

When I run `wp comment list --format=count`
Then STDOUT should be:
"""
4
"""

When I run `wp comment delete --all`
Then STDOUT should contain:
"""
Success: Trashed comment 1.
"""
And STDOUT should contain:
"""
Success: Trashed comment {COMMENT_ID_1}.
"""
And STDOUT should contain:
"""
Success: Trashed comment {COMMENT_ID_2}.
"""
And STDOUT should contain:
"""
Success: Trashed comment {COMMENT_ID_3}.
"""

When I run `wp comment list --format=count`
Then STDOUT should be:
"""
0
"""

Scenario: Delete all comments with --all flag and --force
Given a WP install
And I run `wp comment create --comment_post_ID=1 --comment_content='Comment 1' --porcelain`
And save STDOUT as {COMMENT_ID_1}
And I run `wp comment create --comment_post_ID=1 --comment_content='Comment 2' --porcelain`
And save STDOUT as {COMMENT_ID_2}

When I run `wp comment list --format=count`
Then STDOUT should be:
"""
3
"""

When I run `wp comment delete --all --force`
Then STDOUT should contain:
"""
Success: Deleted comment 1.
"""
And STDOUT should contain:
"""
Success: Deleted comment {COMMENT_ID_1}.
"""
And STDOUT should contain:
"""
Success: Deleted comment {COMMENT_ID_2}.
"""

When I run `wp comment list --format=count`
Then STDOUT should be:
"""
0
"""

Scenario: Delete all comments when no comments exist
Given a WP install
And I run `wp comment delete $(wp comment list --field=ID) --force`

When I run `wp comment delete --all`
Then STDOUT should be:
"""
Success: No comments deleted.
"""

Scenario: Delete multiple comments shows summary message
Given a WP install
And I run `wp comment create --comment_post_ID=1 --comment_content='Comment 1' --porcelain`
And save STDOUT as {COMMENT_ID_1}
And I run `wp comment create --comment_post_ID=1 --comment_content='Comment 2' --porcelain`
And save STDOUT as {COMMENT_ID_2}
And I run `wp comment create --comment_post_ID=1 --comment_content='Comment 3' --porcelain`
And save STDOUT as {COMMENT_ID_3}

When I run `wp comment delete {COMMENT_ID_1} {COMMENT_ID_2} {COMMENT_ID_3}`
Then STDOUT should contain:
"""
Success: Trashed comment {COMMENT_ID_1}.
"""
And STDOUT should contain:
"""
Success: Trashed comment {COMMENT_ID_2}.
"""
And STDOUT should contain:
"""
Success: Trashed comment {COMMENT_ID_3}.
"""
And STDOUT should contain:
"""
Success: Deleted 3 comments.
"""

Scenario: Delete comments with mixed success and failure
Given a WP install
And I run `wp comment create --comment_post_ID=1 --comment_content='Comment 1' --porcelain`
And save STDOUT as {COMMENT_ID_1}
And I run `wp comment create --comment_post_ID=1 --comment_content='Comment 2' --porcelain`
And save STDOUT as {COMMENT_ID_2}

When I try `wp comment delete {COMMENT_ID_1} {COMMENT_ID_2} 99999`
Then STDOUT should contain:
"""
Success: Trashed comment {COMMENT_ID_1}.
"""
And STDOUT should contain:
"""
Success: Trashed comment {COMMENT_ID_2}.
"""
And STDERR should contain:
"""
Warning: Failed deleting comment 99999.
"""
And STDERR should contain:
"""
Error: Failed deleting 1 comments.
"""
And the return code should be 1

Scenario: Error when no comment IDs and no --all flag provided
Given a WP install

When I try `wp comment delete`
Then STDERR should be:
"""
Error: Please specify one or more comment IDs, or use --all.
"""
And the return code should be 1
113 changes: 99 additions & 14 deletions src/Comment_Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -416,9 +416,12 @@ function ( $comment ) {
*
* ## OPTIONS
*
* <id>...
* [<id>...]
* : One or more IDs of comments to delete.
*
* [--all]
* : If set, all comments will be deleted. This command might be slow on a site with lots of comments.
*
* [--force]
* : Skip the trash bin.
*
Expand All @@ -432,25 +435,65 @@ function ( $comment ) {
* $ wp comment delete 1337 2341 --force
* Success: Deleted comment 1337.
* Success: Deleted comment 2341.
*
* # Delete all comments.
* $ wp comment delete --all --force
* Success: Deleted comment 1337.
* Success: Deleted comment 2341.
* Success: Deleted 2 of 2 comments.
*/
public function delete( $args, $assoc_args ) {
parent::_delete(
$args,
$assoc_args,
function ( $comment_id, $assoc_args ) {
$force = (bool) Utils\get_flag_value( $assoc_args, 'force' );
$all = Utils\get_flag_value( $assoc_args, 'all', false );

$status = wp_get_comment_status( $comment_id );
$result = wp_delete_comment( $comment_id, $force );
// Check if comment IDs or --all is passed.
$args = $this->check_optional_args_and_all( $args, $all, 'delete' );
if ( ! $args ) {
return;
}

if ( ! $result ) {
return [ 'error', "Failed deleting comment {$comment_id}." ];
}
$status = 0;

$defer_term_counting = wp_defer_comment_counting();
if ( $all ) {
wp_defer_term_counting( true );
}

$total = count( $args );
$successfully_deleted = 0;

$force = (bool) Utils\get_flag_value( $assoc_args, 'force' );

$verb = ( $force || 'trash' === $status ) ? 'Deleted' : 'Trashed';
return [ 'success', "{$verb} comment {$comment_id}." ];
foreach ( $args as $comment_id ) {

$comment_status = wp_get_comment_status( $comment_id );
$result = wp_delete_comment( $comment_id, $force );

if ( ! $result ) {
$response = [ 'error', "Failed deleting comment {$comment_id}." ];
$status = $this->success_or_failure( $response );
// Keep status as 1 (error) if any deletion fails
} else {
$verb = ( $force || 'trash' === $comment_status ) ? 'Deleted' : 'Trashed';
$response = [ 'success', "{$verb} comment {$comment_id}." ];
$this->success_or_failure( $response );
++$successfully_deleted;
}
);
}

if ( $all ) {
wp_defer_term_counting( $defer_term_counting );
}

if ( 0 === $status ) {
if ( $total > 1 ) {
WP_CLI::success( "Deleted {$successfully_deleted} comments." );
}
} else {
$error_count = $total - $successfully_deleted;
WP_CLI::error( "Failed deleting {$error_count} comments." );
}

exit( $status );
}

private function call( $args, $status, $success, $failure ) {
Expand Down Expand Up @@ -734,4 +777,46 @@ public function exists( $args ) {
WP_CLI::success( "Comment with ID {$args[0]} exists." );
}
}

/**
* If have optional args ([<id>...]) and an all option, then check have something to do.
*
* @param array $args Passed-in arguments.
* @param bool $all All flag.
* @param string $verb Optional. Verb to use. Defaults to 'delete'.
* @return array Same as $args if not all, otherwise all comment IDs.
*/
private function check_optional_args_and_all( $args, $all, $verb = 'delete' ) {
if ( $all ) {
$args = $this->get_all_comment_ids();
}

if ( empty( $args ) ) {
if ( ! $all ) {
WP_CLI::error( 'Please specify one or more comment IDs, or use --all.' );
}

$past_tense_verb = Utils\past_tense_verb( $verb );
WP_CLI::success( "No comments {$past_tense_verb}." );
}

return $args;
}

/**
* Gets all available comment IDs.
*/
private function get_all_comment_ids(): array {
$query = new WP_Comment_Query();

/** @var array $comments */
$comments = $query->query(
array(
'fields' => 'ids',
'number' => 0, // Get all comments
)
);

return $comments;
}
}