File: //usr/local/wp/vendor/wp-cli/entity-command/src/Comment_Command.php
<?php
use WP_CLI\CommandWithDBObject;
use WP_CLI\Fetchers\Comment as CommentFetcher;
use WP_CLI\Utils;
/**
* Creates, updates, deletes, and moderates comments.
*
* ## EXAMPLES
*
* # Create a new comment.
* $ wp comment create --comment_post_ID=15 --comment_content="hello blog" --comment_author="wp-cli"
* Success: Created comment 932.
*
* # Update an existing comment.
* $ wp comment update 123 --comment_author='That Guy'
* Success: Updated comment 123.
*
* # Delete an existing comment.
* $ wp comment delete 1337 --force
* Success: Deleted comment 1337.
*
* # Trash all spam comments.
* $ wp comment delete $(wp comment list --status=spam --format=ids)
* Success: Trashed comment 264.
* Success: Trashed comment 262.
*
* @package wp-cli
*/
class Comment_Command extends CommandWithDBObject {
protected $obj_type = 'comment';
protected $obj_id_key = 'comment_ID';
protected $obj_fields = [
'comment_ID',
'comment_post_ID',
'comment_date',
'comment_approved',
'comment_author',
'comment_author_email',
];
private $fetcher;
public function __construct() {
$this->fetcher = new CommentFetcher();
}
/**
* Creates a new comment.
*
* ## OPTIONS
*
* [--<field>=<value>]
* : Associative args for the new comment. See wp_insert_comment().
*
* [--porcelain]
* : Output just the new comment id.
*
* ## EXAMPLES
*
* # Create comment.
* $ wp comment create --comment_post_ID=15 --comment_content="hello blog" --comment_author="wp-cli"
* Success: Created comment 932.
*/
public function create( $args, $assoc_args ) {
$assoc_args = wp_slash( $assoc_args );
parent::_create(
$args,
$assoc_args,
function ( $params ) {
if ( isset( $params['comment_post_ID'] ) ) {
$post_id = $params['comment_post_ID'];
$post = get_post( $post_id );
if ( ! $post ) {
return new WP_Error( 'no_post', "Can't find post {$post_id}." );
}
} else {
// Make sure it's set for older WP versions else get undefined PHP notice.
$params['comment_post_ID'] = 0;
}
// We use wp_insert_comment() instead of wp_new_comment() to stay at a low level and
// avoid wp_die() formatted messages or notifications
$comment_id = wp_insert_comment( $params );
if ( ! $comment_id ) {
return new WP_Error( 'db_error', 'Could not create comment.' );
}
return $comment_id;
}
);
}
/**
* Updates one or more comments.
*
* ## OPTIONS
*
* <id>...
* : One or more IDs of comments to update.
*
* --<field>=<value>
* : One or more fields to update. See wp_update_comment().
*
* ## EXAMPLES
*
* # Update comment.
* $ wp comment update 123 --comment_author='That Guy'
* Success: Updated comment 123.
*/
public function update( $args, $assoc_args ) {
$assoc_args = wp_slash( $assoc_args );
parent::_update(
$args,
$assoc_args,
function ( $params ) {
if ( ! wp_update_comment( $params ) ) {
return new WP_Error( 'db_error', 'Could not update comment.' );
}
return true;
}
);
}
/**
* Generates some number of new dummy comments.
*
* Creates a specified number of new comments with dummy data.
*
* ## OPTIONS
*
* [--count=<number>]
* : How many comments to generate?
* ---
* default: 100
* ---
*
* [--post_id=<post-id>]
* : Assign comments to a specific post.
*
* [--format=<format>]
* : Render output in a particular format.
* ---
* default: progress
* options:
* - progress
* - ids
* ---
*
* ## EXAMPLES
*
* # Generate comments for the given post.
* $ wp comment generate --format=ids --count=3 --post_id=123
* 138 139 140
*
* # Add meta to every generated comment.
* $ wp comment generate --format=ids --count=3 | xargs -d ' ' -I % wp comment meta add % foo bar
* Success: Added custom field.
* Success: Added custom field.
* Success: Added custom field.
*/
public function generate( $args, $assoc_args ) {
$defaults = [
'count' => 100,
'post_id' => 0,
];
$assoc_args = array_merge( $defaults, $assoc_args );
$format = Utils\get_flag_value( $assoc_args, 'format', 'progress' );
$notify = false;
if ( 'progress' === $format ) {
$notify = Utils\make_progress_bar( 'Generating comments', $assoc_args['count'] );
}
$comment_count = wp_count_comments();
$total = (int) $comment_count->total_comments;
$limit = $total + $assoc_args['count'];
for ( $index = $total; $index < $limit; $index++ ) {
$comment_id = wp_insert_comment(
[
'comment_content' => "Comment {$index}",
'comment_post_ID' => $assoc_args['post_id'],
]
);
if ( 'progress' === $format ) {
$notify->tick();
} elseif ( 'ids' === $format ) {
echo $comment_id;
if ( $index < $limit - 1 ) {
echo ' ';
}
}
}
if ( 'progress' === $format ) {
$notify->finish();
}
}
/**
* Gets the data of a single comment.
*
* ## OPTIONS
*
* <id>
* : The comment to get.
*
* [--field=<field>]
* : Instead of returning the whole comment, returns the value of a single field.
*
* [--fields=<fields>]
* : Limit the output to specific fields. Defaults to all fields.
*
* [--format=<format>]
* : Render output in a particular format.
* ---
* default: table
* options:
* - table
* - csv
* - json
* - yaml
* ---
*
* ## EXAMPLES
*
* # Get comment.
* $ wp comment get 21 --field=content
* Thanks for all the comments, everyone!
*/
public function get( $args, $assoc_args ) {
$comment_id = (int) $args[0];
$comment = get_comment( $comment_id );
if ( empty( $comment ) ) {
WP_CLI::error( 'Invalid comment ID.' );
}
if ( ! isset( $comment->url ) ) {
$comment->url = get_comment_link( $comment );
}
if ( empty( $assoc_args['fields'] ) ) {
$comment_array = get_object_vars( $comment );
$assoc_args['fields'] = array_keys( $comment_array );
}
$formatter = $this->get_formatter( $assoc_args );
$formatter->display_item( $comment );
}
/**
* Gets a list of comments.
*
* Display comments based on all arguments supported by
* [WP_Comment_Query()](https://developer.wordpress.org/reference/classes/WP_Comment_Query/__construct/).
*
* ## OPTIONS
*
* [--<field>=<value>]
* : One or more args to pass to WP_Comment_Query.
*
* [--field=<field>]
* : Prints the value of a single field for each comment.
*
* [--fields=<fields>]
* : Limit the output to specific object fields.
*
* [--format=<format>]
* : Render output in a particular format.
* ---
* default: table
* options:
* - table
* - ids
* - csv
* - json
* - count
* - yaml
* ---
*
* ## AVAILABLE FIELDS
*
* These fields will be displayed by default for each comment:
*
* * comment_ID
* * comment_post_ID
* * comment_date
* * comment_approved
* * comment_author
* * comment_author_email
*
* These fields are optionally available:
*
* * comment_author_url
* * comment_author_IP
* * comment_date_gmt
* * comment_content
* * comment_karma
* * comment_agent
* * comment_type
* * comment_parent
* * user_id
* * url
*
* ## EXAMPLES
*
* # List comment IDs.
* $ wp comment list --field=ID
* 22
* 23
* 24
*
* # List comments of a post.
* $ wp comment list --post_id=1 --fields=ID,comment_date,comment_author
* +------------+---------------------+----------------+
* | comment_ID | comment_date | comment_author |
* +------------+---------------------+----------------+
* | 1 | 2015-06-20 09:00:10 | Mr WordPress |
* +------------+---------------------+----------------+
*
* # List approved comments.
* $ wp comment list --number=3 --status=approve --fields=ID,comment_date,comment_author
* +------------+---------------------+----------------+
* | comment_ID | comment_date | comment_author |
* +------------+---------------------+----------------+
* | 1 | 2015-06-20 09:00:10 | Mr WordPress |
* | 30 | 2013-03-14 12:35:07 | John Doe |
* | 29 | 2013-03-14 11:56:08 | Jane Doe |
* +------------+---------------------+----------------+
*
* # List unapproved comments.
* $ wp comment list --number=3 --status=hold --fields=ID,comment_date,comment_author
* +------------+---------------------+----------------+
* | comment_ID | comment_date | comment_author |
* +------------+---------------------+----------------+
* | 8 | 2023-11-10 13:13:06 | John Doe |
* | 7 | 2023-11-10 13:09:55 | Mr WordPress |
* | 9 | 2023-11-10 11:22:31 | Jane Doe |
* +------------+---------------------+----------------+
*
* # List comments marked as spam.
* $ wp comment list --status=spam --fields=ID,comment_date,comment_author
* +------------+---------------------+----------------+
* | comment_ID | comment_date | comment_author |
* +------------+---------------------+----------------+
* | 2 | 2023-11-10 11:22:31 | Jane Doe |
* +------------+---------------------+----------------+
*
* # List comments in trash.
* $ wp comment list --status=trash --fields=ID,comment_date,comment_author
* +------------+---------------------+----------------+
* | comment_ID | comment_date | comment_author |
* +------------+---------------------+----------------+
* | 3 | 2023-11-10 11:22:31 | John Doe |
* +------------+---------------------+----------------+
*
* @subcommand list
*/
public function list_( $args, $assoc_args ) {
$formatter = $this->get_formatter( $assoc_args );
if ( 'ids' === $formatter->format ) {
$assoc_args['fields'] = 'comment_ID';
}
$assoc_args = self::process_csv_arguments_to_arrays( $assoc_args );
if ( 'count' === $formatter->format ) {
$assoc_args['count'] = true;
}
if ( ! empty( $assoc_args['comment__in'] )
&& ! empty( $assoc_args['orderby'] )
&& 'comment__in' === $assoc_args['orderby']
&& Utils\wp_version_compare( '4.4', '<' ) ) {
$comments = [];
foreach ( $assoc_args['comment__in'] as $comment_id ) {
$comment = get_comment( $comment_id );
if ( $comment ) {
$comments[] = $comment;
} else {
WP_CLI::warning( "Invalid comment {$comment_id}." );
}
}
} else {
$query = new WP_Comment_Query();
$comments = $query->query( $assoc_args );
}
if ( 'count' === $formatter->format ) {
echo $comments;
} else {
if ( 'ids' === $formatter->format ) {
$comments = wp_list_pluck( $comments, 'comment_ID' );
} elseif ( is_array( $comments ) ) {
$comments = array_map(
function ( $comment ) {
$comment->url = get_comment_link( $comment->comment_ID );
return $comment;
},
$comments
);
}
$formatter->display_items( $comments );
}
}
/**
* Deletes a comment.
*
* ## OPTIONS
*
* <id>...
* : One or more IDs of comments to delete.
*
* [--force]
* : Skip the trash bin.
*
* ## EXAMPLES
*
* # Delete comment.
* $ wp comment delete 1337 --force
* Success: Deleted comment 1337.
*
* # Delete multiple comments.
* $ wp comment delete 1337 2341 --force
* Success: Deleted comment 1337.
* Success: Deleted comment 2341.
*/
public function delete( $args, $assoc_args ) {
parent::_delete(
$args,
$assoc_args,
function ( $comment_id, $assoc_args ) {
$force = Utils\get_flag_value( $assoc_args, 'force' );
$status = wp_get_comment_status( $comment_id );
$result = wp_delete_comment( $comment_id, $force );
if ( ! $result ) {
return [ 'error', "Failed deleting comment {$comment_id}." ];
}
$verb = ( $force || 'trash' === $status ) ? 'Deleted' : 'Trashed';
return [ 'success', "{$verb} comment {$comment_id}." ];
}
);
}
private function call( $args, $status, $success, $failure ) {
$comment_id = absint( $args );
$func = "wp_{$status}_comment";
if ( ! $func( $comment_id ) ) {
WP_CLI::error( sprintf( $failure, "comment {$comment_id}" ) );
}
WP_CLI::success( sprintf( $success, "comment {$comment_id}" ) );
}
private function set_status( $args, $status, $success ) {
$comment = $this->fetcher->get_check( $args );
$result = wp_set_comment_status( $comment->comment_ID, $status, true );
if ( is_wp_error( $result ) ) {
WP_CLI::error( $result );
}
WP_CLI::success( "{$success} comment {$comment->comment_ID}." );
}
/**
* Warns if `$_SERVER['SERVER_NAME']` not set as used in email from-address sent to post author in `wp_notify_postauthor()`.
*/
private function check_server_name() {
if ( empty( $_SERVER['SERVER_NAME'] ) ) {
WP_CLI::warning( 'Site url not set - defaulting to \'example.com\'. Any notification emails sent to post author may appear to come from \'example.com\'.' );
$_SERVER['SERVER_NAME'] = 'example.com';
}
}
/**
* Trashes a comment.
*
* ## OPTIONS
*
* <id>...
* : The IDs of the comments to trash.
*
* ## EXAMPLES
*
* # Trash comment.
* $ wp comment trash 1337
* Success: Trashed comment 1337.
*/
public function trash( $args, $assoc_args ) {
foreach ( $args as $id ) {
$this->call( $id, __FUNCTION__, 'Trashed %s.', 'Failed trashing %s.' );
}
}
/**
* Untrashes a comment.
*
* ## OPTIONS
*
* <id>...
* : The IDs of the comments to untrash.
*
* ## EXAMPLES
*
* # Untrash comment.
* $ wp comment untrash 1337
* Success: Untrashed comment 1337.
*/
public function untrash( $args, $assoc_args ) {
$this->check_server_name();
foreach ( $args as $id ) {
$this->call( $id, __FUNCTION__, 'Untrashed %s.', 'Failed untrashing %s.' );
}
}
/**
* Marks a comment as spam.
*
* ## OPTIONS
*
* <id>...
* : The IDs of the comments to mark as spam.
*
* ## EXAMPLES
*
* # Spam comment.
* $ wp comment spam 1337
* Success: Marked as spam comment 1337.
*/
public function spam( $args, $assoc_args ) {
foreach ( $args as $id ) {
$this->call( $id, __FUNCTION__, 'Marked %s as spam.', 'Failed marking %s as spam.' );
}
}
/**
* Unmarks a comment as spam.
*
* ## OPTIONS
*
* <id>...
* : The IDs of the comments to unmark as spam.
*
* ## EXAMPLES
*
* # Unspam comment.
* $ wp comment unspam 1337
* Success: Unspammed comment 1337.
*/
public function unspam( $args, $assoc_args ) {
$this->check_server_name();
foreach ( $args as $id ) {
$this->call( $id, __FUNCTION__, 'Unspammed %s.', 'Failed unspamming %s.' );
}
}
/**
* Approves a comment.
*
* ## OPTIONS
*
* <id>...
* : The IDs of the comments to approve.
*
* ## EXAMPLES
*
* # Approve comment.
* $ wp comment approve 1337
* Success: Approved comment 1337.
*/
public function approve( $args, $assoc_args ) {
$this->check_server_name();
foreach ( $args as $id ) {
$this->set_status( $id, 'approve', 'Approved' );
}
}
/**
* Unapproves a comment.
*
* ## OPTIONS
*
* <id>...
* : The IDs of the comments to unapprove.
*
* ## EXAMPLES
*
* # Unapprove comment.
* $ wp comment unapprove 1337
* Success: Unapproved comment 1337.
*/
public function unapprove( $args, $assoc_args ) {
$this->check_server_name();
foreach ( $args as $id ) {
$this->set_status( $id, 'hold', 'Unapproved' );
}
}
/**
* Counts comments, on whole blog or on a given post.
*
* ## OPTIONS
*
* [<post-id>]
* : The ID of the post to count comments in.
*
* ## EXAMPLES
*
* # Count comments on whole blog.
* $ wp comment count
* approved: 33
* spam: 3
* trash: 1
* post-trashed: 0
* all: 34
* moderated: 1
* total_comments: 37
*
* # Count comments in a post.
* $ wp comment count 42
* approved: 19
* spam: 0
* trash: 0
* post-trashed: 0
* all: 19
* moderated: 0
* total_comments: 19
*/
public function count( $args, $assoc_args ) {
$post_id = Utils\get_flag_value( $args, 0, 0 );
$count = wp_count_comments( $post_id );
// Move total_comments to the end of the object
$total = $count->total_comments;
unset( $count->total_comments );
$count->total_comments = $total;
foreach ( $count as $status => $count ) {
WP_CLI::line( str_pad( "$status:", 17 ) . $count );
}
}
/**
* Recalculates the comment_count value for one or more posts.
*
* ## OPTIONS
*
* <id>...
* : IDs for one or more posts to update.
*
* ## EXAMPLES
*
* # Recount comment for the post.
* $ wp comment recount 123
* Updated post 123 comment count to 67.
*/
public function recount( $args ) {
foreach ( $args as $id ) {
if ( wp_update_comment_count( $id ) ) {
$post = get_post( $id );
WP_CLI::log( "Updated post {$post->ID} comment count to {$post->comment_count}." );
} else {
WP_CLI::warning( "Post {$id} doesn't exist." );
}
}
}
/**
* Gets the status of a comment.
*
* ## OPTIONS
*
* <id>
* : The ID of the comment to check.
*
* ## EXAMPLES
*
* # Get status of comment.
* $ wp comment status 1337
* approved
*/
public function status( $args, $assoc_args ) {
list( $comment_id ) = $args;
$status = wp_get_comment_status( $comment_id );
if ( false === $status ) {
WP_CLI::error( "Could not check status of comment {$comment_id}." );
} else {
WP_CLI::line( $status );
}
}
/**
* Verifies whether a comment exists.
*
* Displays a success message if the comment does exist.
*
* ## OPTIONS
*
* <id>
* : The ID of the comment to check.
*
* ## EXAMPLES
*
* # Check whether comment exists.
* $ wp comment exists 1337
* Success: Comment with ID 1337 exists.
*/
public function exists( $args ) {
if ( $this->fetcher->get( $args[0] ) ) {
WP_CLI::success( "Comment with ID {$args[0]} exists." );
}
}
}