fetcher = new CommentFetcher(); } /** * Creates a new comment. * * ## OPTIONS * * [--=] * : 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 * * ... * : One or more IDs of comments to update. * * --= * : 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( '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=] * : How many comments to generate? * --- * default: 100 * --- * * [--post_id=] * : Assign comments to a specific post. * * [--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 * * * : The comment to get. * * [--field=] * : Instead of returning the whole comment, returns the value of a single field. * * [--fields=] * : Limit the output to specific fields. Defaults to all fields. * * [--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 * * [--=] * : One or more args to pass to WP_Comment_Query. * * [--field=] * : Prints the value of a single field for each comment. * * [--fields=] * : Limit the output to specific object fields. * * [--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 * * ... * : 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 * * ... * : 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 * * ... * : 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 * * ... * : 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 * * ... * : 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 * * ... * : 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 * * ... * : 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 * * [] * : 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 * * ... * : 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 * * * : 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 * * * : 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." ); } } }