balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

class-wp-comments-list-table.php (30242B)


      1 <?php
      2 /**
      3  * List Table API: WP_Comments_List_Table class
      4  *
      5  * @package WordPress
      6  * @subpackage Administration
      7  * @since 3.1.0
      8  */
      9 
     10 /**
     11  * Core class used to implement displaying comments in a list table.
     12  *
     13  * @since 3.1.0
     14  * @access private
     15  *
     16  * @see WP_List_Table
     17  */
     18 class WP_Comments_List_Table extends WP_List_Table {
     19 
     20 	public $checkbox = true;
     21 
     22 	public $pending_count = array();
     23 
     24 	public $extra_items;
     25 
     26 	private $user_can;
     27 
     28 	/**
     29 	 * Constructor.
     30 	 *
     31 	 * @since 3.1.0
     32 	 *
     33 	 * @see WP_List_Table::__construct() for more information on default arguments.
     34 	 *
     35 	 * @global int $post_id
     36 	 *
     37 	 * @param array $args An associative array of arguments.
     38 	 */
     39 	public function __construct( $args = array() ) {
     40 		global $post_id;
     41 
     42 		$post_id = isset( $_REQUEST['p'] ) ? absint( $_REQUEST['p'] ) : 0;
     43 
     44 		if ( get_option( 'show_avatars' ) ) {
     45 			add_filter( 'comment_author', array( $this, 'floated_admin_avatar' ), 10, 2 );
     46 		}
     47 
     48 		parent::__construct(
     49 			array(
     50 				'plural'   => 'comments',
     51 				'singular' => 'comment',
     52 				'ajax'     => true,
     53 				'screen'   => isset( $args['screen'] ) ? $args['screen'] : null,
     54 			)
     55 		);
     56 	}
     57 
     58 	/**
     59 	 * Adds avatars to comment author names.
     60 	 *
     61 	 * @since 3.1.0
     62 	 *
     63 	 * @param string $name       Comment author name.
     64 	 * @param int    $comment_id Comment ID.
     65 	 * @return string Avatar with the user name.
     66 	 */
     67 	public function floated_admin_avatar( $name, $comment_id ) {
     68 		$comment = get_comment( $comment_id );
     69 		$avatar  = get_avatar( $comment, 32, 'mystery' );
     70 		return "$avatar $name";
     71 	}
     72 
     73 	/**
     74 	 * @return bool
     75 	 */
     76 	public function ajax_user_can() {
     77 		return current_user_can( 'edit_posts' );
     78 	}
     79 
     80 	/**
     81 	 * @global string $mode           List table view mode.
     82 	 * @global int    $post_id
     83 	 * @global string $comment_status
     84 	 * @global string $comment_type
     85 	 * @global string $search
     86 	 */
     87 	public function prepare_items() {
     88 		global $mode, $post_id, $comment_status, $comment_type, $search;
     89 
     90 		if ( ! empty( $_REQUEST['mode'] ) ) {
     91 			$mode = 'excerpt' === $_REQUEST['mode'] ? 'excerpt' : 'list';
     92 			set_user_setting( 'posts_list_mode', $mode );
     93 		} else {
     94 			$mode = get_user_setting( 'posts_list_mode', 'list' );
     95 		}
     96 
     97 		$comment_status = isset( $_REQUEST['comment_status'] ) ? $_REQUEST['comment_status'] : 'all';
     98 
     99 		if ( ! in_array( $comment_status, array( 'all', 'mine', 'moderated', 'approved', 'spam', 'trash' ), true ) ) {
    100 			$comment_status = 'all';
    101 		}
    102 
    103 		$comment_type = ! empty( $_REQUEST['comment_type'] ) ? $_REQUEST['comment_type'] : '';
    104 
    105 		$search = ( isset( $_REQUEST['s'] ) ) ? $_REQUEST['s'] : '';
    106 
    107 		$post_type = ( isset( $_REQUEST['post_type'] ) ) ? sanitize_key( $_REQUEST['post_type'] ) : '';
    108 
    109 		$user_id = ( isset( $_REQUEST['user_id'] ) ) ? $_REQUEST['user_id'] : '';
    110 
    111 		$orderby = ( isset( $_REQUEST['orderby'] ) ) ? $_REQUEST['orderby'] : '';
    112 		$order   = ( isset( $_REQUEST['order'] ) ) ? $_REQUEST['order'] : '';
    113 
    114 		$comments_per_page = $this->get_per_page( $comment_status );
    115 
    116 		$doing_ajax = wp_doing_ajax();
    117 
    118 		if ( isset( $_REQUEST['number'] ) ) {
    119 			$number = (int) $_REQUEST['number'];
    120 		} else {
    121 			$number = $comments_per_page + min( 8, $comments_per_page ); // Grab a few extra.
    122 		}
    123 
    124 		$page = $this->get_pagenum();
    125 
    126 		if ( isset( $_REQUEST['start'] ) ) {
    127 			$start = $_REQUEST['start'];
    128 		} else {
    129 			$start = ( $page - 1 ) * $comments_per_page;
    130 		}
    131 
    132 		if ( $doing_ajax && isset( $_REQUEST['offset'] ) ) {
    133 			$start += $_REQUEST['offset'];
    134 		}
    135 
    136 		$status_map = array(
    137 			'mine'      => '',
    138 			'moderated' => 'hold',
    139 			'approved'  => 'approve',
    140 			'all'       => '',
    141 		);
    142 
    143 		$args = array(
    144 			'status'    => isset( $status_map[ $comment_status ] ) ? $status_map[ $comment_status ] : $comment_status,
    145 			'search'    => $search,
    146 			'user_id'   => $user_id,
    147 			'offset'    => $start,
    148 			'number'    => $number,
    149 			'post_id'   => $post_id,
    150 			'type'      => $comment_type,
    151 			'orderby'   => $orderby,
    152 			'order'     => $order,
    153 			'post_type' => $post_type,
    154 		);
    155 
    156 		/**
    157 		 * Filters the arguments for the comment query in the comments list table.
    158 		 *
    159 		 * @since 5.1.0
    160 		 *
    161 		 * @param array $args An array of get_comments() arguments.
    162 		 */
    163 		$args = apply_filters( 'comments_list_table_query_args', $args );
    164 
    165 		$_comments = get_comments( $args );
    166 
    167 		if ( is_array( $_comments ) ) {
    168 			update_comment_cache( $_comments );
    169 
    170 			$this->items       = array_slice( $_comments, 0, $comments_per_page );
    171 			$this->extra_items = array_slice( $_comments, $comments_per_page );
    172 
    173 			$_comment_post_ids = array_unique( wp_list_pluck( $_comments, 'comment_post_ID' ) );
    174 
    175 			$this->pending_count = get_pending_comments_num( $_comment_post_ids );
    176 		}
    177 
    178 		$total_comments = get_comments(
    179 			array_merge(
    180 				$args,
    181 				array(
    182 					'count'  => true,
    183 					'offset' => 0,
    184 					'number' => 0,
    185 				)
    186 			)
    187 		);
    188 
    189 		$this->set_pagination_args(
    190 			array(
    191 				'total_items' => $total_comments,
    192 				'per_page'    => $comments_per_page,
    193 			)
    194 		);
    195 	}
    196 
    197 	/**
    198 	 * @param string $comment_status
    199 	 * @return int
    200 	 */
    201 	public function get_per_page( $comment_status = 'all' ) {
    202 		$comments_per_page = $this->get_items_per_page( 'edit_comments_per_page' );
    203 
    204 		/**
    205 		 * Filters the number of comments listed per page in the comments list table.
    206 		 *
    207 		 * @since 2.6.0
    208 		 *
    209 		 * @param int    $comments_per_page The number of comments to list per page.
    210 		 * @param string $comment_status    The comment status name. Default 'All'.
    211 		 */
    212 		return apply_filters( 'comments_per_page', $comments_per_page, $comment_status );
    213 	}
    214 
    215 	/**
    216 	 * @global string $comment_status
    217 	 */
    218 	public function no_items() {
    219 		global $comment_status;
    220 
    221 		if ( 'moderated' === $comment_status ) {
    222 			_e( 'No comments awaiting moderation.' );
    223 		} elseif ( 'trash' === $comment_status ) {
    224 			_e( 'No comments found in Trash.' );
    225 		} else {
    226 			_e( 'No comments found.' );
    227 		}
    228 	}
    229 
    230 	/**
    231 	 * @global int $post_id
    232 	 * @global string $comment_status
    233 	 * @global string $comment_type
    234 	 */
    235 	protected function get_views() {
    236 		global $post_id, $comment_status, $comment_type;
    237 
    238 		$status_links = array();
    239 		$num_comments = ( $post_id ) ? wp_count_comments( $post_id ) : wp_count_comments();
    240 
    241 		$stati = array(
    242 			/* translators: %s: Number of comments. */
    243 			'all'       => _nx_noop(
    244 				'All <span class="count">(%s)</span>',
    245 				'All <span class="count">(%s)</span>',
    246 				'comments'
    247 			), // Singular not used.
    248 
    249 			/* translators: %s: Number of comments. */
    250 			'mine'      => _nx_noop(
    251 				'Mine <span class="count">(%s)</span>',
    252 				'Mine <span class="count">(%s)</span>',
    253 				'comments'
    254 			),
    255 
    256 			/* translators: %s: Number of comments. */
    257 			'moderated' => _nx_noop(
    258 				'Pending <span class="count">(%s)</span>',
    259 				'Pending <span class="count">(%s)</span>',
    260 				'comments'
    261 			),
    262 
    263 			/* translators: %s: Number of comments. */
    264 			'approved'  => _nx_noop(
    265 				'Approved <span class="count">(%s)</span>',
    266 				'Approved <span class="count">(%s)</span>',
    267 				'comments'
    268 			),
    269 
    270 			/* translators: %s: Number of comments. */
    271 			'spam'      => _nx_noop(
    272 				'Spam <span class="count">(%s)</span>',
    273 				'Spam <span class="count">(%s)</span>',
    274 				'comments'
    275 			),
    276 
    277 			/* translators: %s: Number of comments. */
    278 			'trash'     => _nx_noop(
    279 				'Trash <span class="count">(%s)</span>',
    280 				'Trash <span class="count">(%s)</span>',
    281 				'comments'
    282 			),
    283 		);
    284 
    285 		if ( ! EMPTY_TRASH_DAYS ) {
    286 			unset( $stati['trash'] );
    287 		}
    288 
    289 		$link = admin_url( 'edit-comments.php' );
    290 
    291 		if ( ! empty( $comment_type ) && 'all' !== $comment_type ) {
    292 			$link = add_query_arg( 'comment_type', $comment_type, $link );
    293 		}
    294 
    295 		foreach ( $stati as $status => $label ) {
    296 			$current_link_attributes = '';
    297 
    298 			if ( $status === $comment_status ) {
    299 				$current_link_attributes = ' class="current" aria-current="page"';
    300 			}
    301 
    302 			if ( 'mine' === $status ) {
    303 				$current_user_id    = get_current_user_id();
    304 				$num_comments->mine = get_comments(
    305 					array(
    306 						'post_id' => $post_id ? $post_id : 0,
    307 						'user_id' => $current_user_id,
    308 						'count'   => true,
    309 					)
    310 				);
    311 				$link               = add_query_arg( 'user_id', $current_user_id, $link );
    312 			} else {
    313 				$link = remove_query_arg( 'user_id', $link );
    314 			}
    315 
    316 			if ( ! isset( $num_comments->$status ) ) {
    317 				$num_comments->$status = 10;
    318 			}
    319 
    320 			$link = add_query_arg( 'comment_status', $status, $link );
    321 
    322 			if ( $post_id ) {
    323 				$link = add_query_arg( 'p', absint( $post_id ), $link );
    324 			}
    325 
    326 			/*
    327 			// I toyed with this, but decided against it. Leaving it in here in case anyone thinks it is a good idea. ~ Mark
    328 			if ( !empty( $_REQUEST['s'] ) )
    329 				$link = add_query_arg( 's', esc_attr( wp_unslash( $_REQUEST['s'] ) ), $link );
    330 			*/
    331 
    332 			$status_links[ $status ] = "<a href='$link'$current_link_attributes>" . sprintf(
    333 				translate_nooped_plural( $label, $num_comments->$status ),
    334 				sprintf(
    335 					'<span class="%s-count">%s</span>',
    336 					( 'moderated' === $status ) ? 'pending' : $status,
    337 					number_format_i18n( $num_comments->$status )
    338 				)
    339 			) . '</a>';
    340 		}
    341 
    342 		/**
    343 		 * Filters the comment status links.
    344 		 *
    345 		 * @since 2.5.0
    346 		 * @since 5.1.0 The 'Mine' link was added.
    347 		 *
    348 		 * @param string[] $status_links An associative array of fully-formed comment status links. Includes 'All', 'Mine',
    349 		 *                              'Pending', 'Approved', 'Spam', and 'Trash'.
    350 		 */
    351 		return apply_filters( 'comment_status_links', $status_links );
    352 	}
    353 
    354 	/**
    355 	 * @global string $comment_status
    356 	 *
    357 	 * @return array
    358 	 */
    359 	protected function get_bulk_actions() {
    360 		global $comment_status;
    361 
    362 		$actions = array();
    363 
    364 		if ( in_array( $comment_status, array( 'all', 'approved' ), true ) ) {
    365 			$actions['unapprove'] = __( 'Unapprove' );
    366 		}
    367 
    368 		if ( in_array( $comment_status, array( 'all', 'moderated' ), true ) ) {
    369 			$actions['approve'] = __( 'Approve' );
    370 		}
    371 
    372 		if ( in_array( $comment_status, array( 'all', 'moderated', 'approved', 'trash' ), true ) ) {
    373 			$actions['spam'] = _x( 'Mark as spam', 'comment' );
    374 		}
    375 
    376 		if ( 'trash' === $comment_status ) {
    377 			$actions['untrash'] = __( 'Restore' );
    378 		} elseif ( 'spam' === $comment_status ) {
    379 			$actions['unspam'] = _x( 'Not spam', 'comment' );
    380 		}
    381 
    382 		if ( in_array( $comment_status, array( 'trash', 'spam' ), true ) || ! EMPTY_TRASH_DAYS ) {
    383 			$actions['delete'] = __( 'Delete permanently' );
    384 		} else {
    385 			$actions['trash'] = __( 'Move to Trash' );
    386 		}
    387 
    388 		return $actions;
    389 	}
    390 
    391 	/**
    392 	 * @global string $comment_status
    393 	 * @global string $comment_type
    394 	 *
    395 	 * @param string $which
    396 	 */
    397 	protected function extra_tablenav( $which ) {
    398 		global $comment_status, $comment_type;
    399 		static $has_items;
    400 
    401 		if ( ! isset( $has_items ) ) {
    402 			$has_items = $this->has_items();
    403 		}
    404 
    405 		echo '<div class="alignleft actions">';
    406 
    407 		if ( 'top' === $which ) {
    408 			ob_start();
    409 
    410 			$this->comment_type_dropdown( $comment_type );
    411 
    412 			/**
    413 			 * Fires just before the Filter submit button for comment types.
    414 			 *
    415 			 * @since 3.5.0
    416 			 */
    417 			do_action( 'restrict_manage_comments' );
    418 
    419 			$output = ob_get_clean();
    420 
    421 			if ( ! empty( $output ) && $this->has_items() ) {
    422 				echo $output;
    423 				submit_button( __( 'Filter' ), '', 'filter_action', false, array( 'id' => 'post-query-submit' ) );
    424 			}
    425 		}
    426 
    427 		if ( ( 'spam' === $comment_status || 'trash' === $comment_status ) && $has_items
    428 			&& current_user_can( 'moderate_comments' )
    429 		) {
    430 			wp_nonce_field( 'bulk-destroy', '_destroy_nonce' );
    431 			$title = ( 'spam' === $comment_status ) ? esc_attr__( 'Empty Spam' ) : esc_attr__( 'Empty Trash' );
    432 			submit_button( $title, 'apply', 'delete_all', false );
    433 		}
    434 
    435 		/**
    436 		 * Fires after the Filter submit button for comment types.
    437 		 *
    438 		 * @since 2.5.0
    439 		 * @since 5.6.0 The `$which` parameter was added.
    440 		 *
    441 		 * @param string $comment_status The comment status name. Default 'All'.
    442 		 * @param string $which          The location of the extra table nav markup: 'top' or 'bottom'.
    443 		 */
    444 		do_action( 'manage_comments_nav', $comment_status, $which );
    445 
    446 		echo '</div>';
    447 	}
    448 
    449 	/**
    450 	 * @return string|false
    451 	 */
    452 	public function current_action() {
    453 		if ( isset( $_REQUEST['delete_all'] ) || isset( $_REQUEST['delete_all2'] ) ) {
    454 			return 'delete_all';
    455 		}
    456 
    457 		return parent::current_action();
    458 	}
    459 
    460 	/**
    461 	 * @global int $post_id
    462 	 *
    463 	 * @return array
    464 	 */
    465 	public function get_columns() {
    466 		global $post_id;
    467 
    468 		$columns = array();
    469 
    470 		if ( $this->checkbox ) {
    471 			$columns['cb'] = '<input type="checkbox" />';
    472 		}
    473 
    474 		$columns['author']  = __( 'Author' );
    475 		$columns['comment'] = _x( 'Comment', 'column name' );
    476 
    477 		if ( ! $post_id ) {
    478 			/* translators: Column name or table row header. */
    479 			$columns['response'] = __( 'In response to' );
    480 		}
    481 
    482 		$columns['date'] = _x( 'Submitted on', 'column name' );
    483 
    484 		return $columns;
    485 	}
    486 
    487 	/**
    488 	 * Displays a comment type drop-down for filtering on the Comments list table.
    489 	 *
    490 	 * @since 5.5.0
    491 	 * @since 5.6.0 Renamed from `comment_status_dropdown()` to `comment_type_dropdown()`.
    492 	 *
    493 	 * @param string $comment_type The current comment type slug.
    494 	 */
    495 	protected function comment_type_dropdown( $comment_type ) {
    496 		/**
    497 		 * Filters the comment types shown in the drop-down menu on the Comments list table.
    498 		 *
    499 		 * @since 2.7.0
    500 		 *
    501 		 * @param string[] $comment_types Array of comment type labels keyed by their name.
    502 		 */
    503 		$comment_types = apply_filters(
    504 			'admin_comment_types_dropdown',
    505 			array(
    506 				'comment' => __( 'Comments' ),
    507 				'pings'   => __( 'Pings' ),
    508 			)
    509 		);
    510 
    511 		if ( $comment_types && is_array( $comment_types ) ) {
    512 			printf( '<label class="screen-reader-text" for="filter-by-comment-type">%s</label>', __( 'Filter by comment type' ) );
    513 
    514 			echo '<select id="filter-by-comment-type" name="comment_type">';
    515 
    516 			printf( "\t<option value=''>%s</option>", __( 'All comment types' ) );
    517 
    518 			foreach ( $comment_types as $type => $label ) {
    519 				if ( get_comments(
    520 					array(
    521 						'number' => 1,
    522 						'type'   => $type,
    523 					)
    524 				) ) {
    525 					printf(
    526 						"\t<option value='%s'%s>%s</option>\n",
    527 						esc_attr( $type ),
    528 						selected( $comment_type, $type, false ),
    529 						esc_html( $label )
    530 					);
    531 				}
    532 			}
    533 
    534 			echo '</select>';
    535 		}
    536 	}
    537 
    538 	/**
    539 	 * @return array
    540 	 */
    541 	protected function get_sortable_columns() {
    542 		return array(
    543 			'author'   => 'comment_author',
    544 			'response' => 'comment_post_ID',
    545 			'date'     => 'comment_date',
    546 		);
    547 	}
    548 
    549 	/**
    550 	 * Get the name of the default primary column.
    551 	 *
    552 	 * @since 4.3.0
    553 	 *
    554 	 * @return string Name of the default primary column, in this case, 'comment'.
    555 	 */
    556 	protected function get_default_primary_column_name() {
    557 		return 'comment';
    558 	}
    559 
    560 	/**
    561 	 * Displays the comments table.
    562 	 *
    563 	 * Overrides the parent display() method to render extra comments.
    564 	 *
    565 	 * @since 3.1.0
    566 	 */
    567 	public function display() {
    568 		wp_nonce_field( 'fetch-list-' . get_class( $this ), '_ajax_fetch_list_nonce' );
    569 		static $has_items;
    570 
    571 		if ( ! isset( $has_items ) ) {
    572 			$has_items = $this->has_items();
    573 
    574 			if ( $has_items ) {
    575 				$this->display_tablenav( 'top' );
    576 			}
    577 		}
    578 
    579 		$this->screen->render_screen_reader_content( 'heading_list' );
    580 
    581 		?>
    582 <table class="wp-list-table <?php echo implode( ' ', $this->get_table_classes() ); ?>">
    583 	<thead>
    584 	<tr>
    585 		<?php $this->print_column_headers(); ?>
    586 	</tr>
    587 	</thead>
    588 
    589 	<tbody id="the-comment-list" data-wp-lists="list:comment">
    590 		<?php $this->display_rows_or_placeholder(); ?>
    591 	</tbody>
    592 
    593 	<tbody id="the-extra-comment-list" data-wp-lists="list:comment" style="display: none;">
    594 		<?php
    595 			/*
    596 			 * Back up the items to restore after printing the extra items markup.
    597 			 * The extra items may be empty, which will prevent the table nav from displaying later.
    598 			 */
    599 			$items       = $this->items;
    600 			$this->items = $this->extra_items;
    601 			$this->display_rows_or_placeholder();
    602 			$this->items = $items;
    603 		?>
    604 	</tbody>
    605 
    606 	<tfoot>
    607 	<tr>
    608 		<?php $this->print_column_headers( false ); ?>
    609 	</tr>
    610 	</tfoot>
    611 
    612 </table>
    613 		<?php
    614 
    615 		$this->display_tablenav( 'bottom' );
    616 	}
    617 
    618 	/**
    619 	 * @global WP_Post    $post    Global post object.
    620 	 * @global WP_Comment $comment Global comment object.
    621 	 *
    622 	 * @param WP_Comment $item
    623 	 */
    624 	public function single_row( $item ) {
    625 		global $post, $comment;
    626 
    627 		$comment = $item;
    628 
    629 		$the_comment_class = wp_get_comment_status( $comment );
    630 
    631 		if ( ! $the_comment_class ) {
    632 			$the_comment_class = '';
    633 		}
    634 
    635 		$the_comment_class = implode( ' ', get_comment_class( $the_comment_class, $comment, $comment->comment_post_ID ) );
    636 
    637 		if ( $comment->comment_post_ID > 0 ) {
    638 			$post = get_post( $comment->comment_post_ID );
    639 		}
    640 
    641 		$this->user_can = current_user_can( 'edit_comment', $comment->comment_ID );
    642 
    643 		echo "<tr id='comment-$comment->comment_ID' class='$the_comment_class'>";
    644 		$this->single_row_columns( $comment );
    645 		echo "</tr>\n";
    646 
    647 		unset( $GLOBALS['post'], $GLOBALS['comment'] );
    648 	}
    649 
    650 	/**
    651 	 * Generate and display row actions links.
    652 	 *
    653 	 * @since 4.3.0
    654 	 *
    655 	 * @global string $comment_status Status for the current listed comments.
    656 	 *
    657 	 * @param WP_Comment $comment     The comment object.
    658 	 * @param string     $column_name Current column name.
    659 	 * @param string     $primary     Primary column name.
    660 	 * @return string Row actions output for comments. An empty string
    661 	 *                if the current column is not the primary column,
    662 	 *                or if the current user cannot edit the comment.
    663 	 */
    664 	protected function handle_row_actions( $comment, $column_name, $primary ) {
    665 		global $comment_status;
    666 
    667 		if ( $primary !== $column_name ) {
    668 			return '';
    669 		}
    670 
    671 		if ( ! $this->user_can ) {
    672 			return '';
    673 		}
    674 
    675 		$the_comment_status = wp_get_comment_status( $comment );
    676 
    677 		$out = '';
    678 
    679 		$del_nonce     = esc_html( '_wpnonce=' . wp_create_nonce( "delete-comment_$comment->comment_ID" ) );
    680 		$approve_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "approve-comment_$comment->comment_ID" ) );
    681 
    682 		$url = "comment.php?c=$comment->comment_ID";
    683 
    684 		$approve_url   = esc_url( $url . "&action=approvecomment&$approve_nonce" );
    685 		$unapprove_url = esc_url( $url . "&action=unapprovecomment&$approve_nonce" );
    686 		$spam_url      = esc_url( $url . "&action=spamcomment&$del_nonce" );
    687 		$unspam_url    = esc_url( $url . "&action=unspamcomment&$del_nonce" );
    688 		$trash_url     = esc_url( $url . "&action=trashcomment&$del_nonce" );
    689 		$untrash_url   = esc_url( $url . "&action=untrashcomment&$del_nonce" );
    690 		$delete_url    = esc_url( $url . "&action=deletecomment&$del_nonce" );
    691 
    692 		// Preorder it: Approve | Reply | Quick Edit | Edit | Spam | Trash.
    693 		$actions = array(
    694 			'approve'   => '',
    695 			'unapprove' => '',
    696 			'reply'     => '',
    697 			'quickedit' => '',
    698 			'edit'      => '',
    699 			'spam'      => '',
    700 			'unspam'    => '',
    701 			'trash'     => '',
    702 			'untrash'   => '',
    703 			'delete'    => '',
    704 		);
    705 
    706 		// Not looking at all comments.
    707 		if ( $comment_status && 'all' !== $comment_status ) {
    708 			if ( 'approved' === $the_comment_status ) {
    709 				$actions['unapprove'] = sprintf(
    710 					'<a href="%s" data-wp-lists="%s" class="vim-u vim-destructive aria-button-if-js" aria-label="%s">%s</a>',
    711 					$unapprove_url,
    712 					"delete:the-comment-list:comment-{$comment->comment_ID}:e7e7d3:action=dim-comment&amp;new=unapproved",
    713 					esc_attr__( 'Unapprove this comment' ),
    714 					__( 'Unapprove' )
    715 				);
    716 			} elseif ( 'unapproved' === $the_comment_status ) {
    717 				$actions['approve'] = sprintf(
    718 					'<a href="%s" data-wp-lists="%s" class="vim-a vim-destructive aria-button-if-js" aria-label="%s">%s</a>',
    719 					$approve_url,
    720 					"delete:the-comment-list:comment-{$comment->comment_ID}:e7e7d3:action=dim-comment&amp;new=approved",
    721 					esc_attr__( 'Approve this comment' ),
    722 					__( 'Approve' )
    723 				);
    724 			}
    725 		} else {
    726 			$actions['approve'] = sprintf(
    727 				'<a href="%s" data-wp-lists="%s" class="vim-a aria-button-if-js" aria-label="%s">%s</a>',
    728 				$approve_url,
    729 				"dim:the-comment-list:comment-{$comment->comment_ID}:unapproved:e7e7d3:e7e7d3:new=approved",
    730 				esc_attr__( 'Approve this comment' ),
    731 				__( 'Approve' )
    732 			);
    733 
    734 			$actions['unapprove'] = sprintf(
    735 				'<a href="%s" data-wp-lists="%s" class="vim-u aria-button-if-js" aria-label="%s">%s</a>',
    736 				$unapprove_url,
    737 				"dim:the-comment-list:comment-{$comment->comment_ID}:unapproved:e7e7d3:e7e7d3:new=unapproved",
    738 				esc_attr__( 'Unapprove this comment' ),
    739 				__( 'Unapprove' )
    740 			);
    741 		}
    742 
    743 		if ( 'spam' !== $the_comment_status ) {
    744 			$actions['spam'] = sprintf(
    745 				'<a href="%s" data-wp-lists="%s" class="vim-s vim-destructive aria-button-if-js" aria-label="%s">%s</a>',
    746 				$spam_url,
    747 				"delete:the-comment-list:comment-{$comment->comment_ID}::spam=1",
    748 				esc_attr__( 'Mark this comment as spam' ),
    749 				/* translators: "Mark as spam" link. */
    750 				_x( 'Spam', 'verb' )
    751 			);
    752 		} elseif ( 'spam' === $the_comment_status ) {
    753 			$actions['unspam'] = sprintf(
    754 				'<a href="%s" data-wp-lists="%s" class="vim-z vim-destructive aria-button-if-js" aria-label="%s">%s</a>',
    755 				$unspam_url,
    756 				"delete:the-comment-list:comment-{$comment->comment_ID}:66cc66:unspam=1",
    757 				esc_attr__( 'Restore this comment from the spam' ),
    758 				_x( 'Not Spam', 'comment' )
    759 			);
    760 		}
    761 
    762 		if ( 'trash' === $the_comment_status ) {
    763 			$actions['untrash'] = sprintf(
    764 				'<a href="%s" data-wp-lists="%s" class="vim-z vim-destructive aria-button-if-js" aria-label="%s">%s</a>',
    765 				$untrash_url,
    766 				"delete:the-comment-list:comment-{$comment->comment_ID}:66cc66:untrash=1",
    767 				esc_attr__( 'Restore this comment from the Trash' ),
    768 				__( 'Restore' )
    769 			);
    770 		}
    771 
    772 		if ( 'spam' === $the_comment_status || 'trash' === $the_comment_status || ! EMPTY_TRASH_DAYS ) {
    773 			$actions['delete'] = sprintf(
    774 				'<a href="%s" data-wp-lists="%s" class="delete vim-d vim-destructive aria-button-if-js" aria-label="%s">%s</a>',
    775 				$delete_url,
    776 				"delete:the-comment-list:comment-{$comment->comment_ID}::delete=1",
    777 				esc_attr__( 'Delete this comment permanently' ),
    778 				__( 'Delete Permanently' )
    779 			);
    780 		} else {
    781 			$actions['trash'] = sprintf(
    782 				'<a href="%s" data-wp-lists="%s" class="delete vim-d vim-destructive aria-button-if-js" aria-label="%s">%s</a>',
    783 				$trash_url,
    784 				"delete:the-comment-list:comment-{$comment->comment_ID}::trash=1",
    785 				esc_attr__( 'Move this comment to the Trash' ),
    786 				_x( 'Trash', 'verb' )
    787 			);
    788 		}
    789 
    790 		if ( 'spam' !== $the_comment_status && 'trash' !== $the_comment_status ) {
    791 			$actions['edit'] = sprintf(
    792 				'<a href="%s" aria-label="%s">%s</a>',
    793 				"comment.php?action=editcomment&amp;c={$comment->comment_ID}",
    794 				esc_attr__( 'Edit this comment' ),
    795 				__( 'Edit' )
    796 			);
    797 
    798 			$format = '<button type="button" data-comment-id="%d" data-post-id="%d" data-action="%s" class="%s button-link" aria-expanded="false" aria-label="%s">%s</button>';
    799 
    800 			$actions['quickedit'] = sprintf(
    801 				$format,
    802 				$comment->comment_ID,
    803 				$comment->comment_post_ID,
    804 				'edit',
    805 				'vim-q comment-inline',
    806 				esc_attr__( 'Quick edit this comment inline' ),
    807 				__( 'Quick&nbsp;Edit' )
    808 			);
    809 
    810 			$actions['reply'] = sprintf(
    811 				$format,
    812 				$comment->comment_ID,
    813 				$comment->comment_post_ID,
    814 				'replyto',
    815 				'vim-r comment-inline',
    816 				esc_attr__( 'Reply to this comment' ),
    817 				__( 'Reply' )
    818 			);
    819 		}
    820 
    821 		/** This filter is documented in wp-admin/includes/dashboard.php */
    822 		$actions = apply_filters( 'comment_row_actions', array_filter( $actions ), $comment );
    823 
    824 		$always_visible = false;
    825 
    826 		$mode = get_user_setting( 'posts_list_mode', 'list' );
    827 
    828 		if ( 'excerpt' === $mode ) {
    829 			$always_visible = true;
    830 		}
    831 
    832 		$out .= '<div class="' . ( $always_visible ? 'row-actions visible' : 'row-actions' ) . '">';
    833 
    834 		$i = 0;
    835 
    836 		foreach ( $actions as $action => $link ) {
    837 			++$i;
    838 
    839 			if ( ( ( 'approve' === $action || 'unapprove' === $action ) && 2 === $i )
    840 				|| 1 === $i
    841 			) {
    842 				$sep = '';
    843 			} else {
    844 				$sep = ' | ';
    845 			}
    846 
    847 			// Reply and quickedit need a hide-if-no-js span when not added with Ajax.
    848 			if ( ( 'reply' === $action || 'quickedit' === $action ) && ! wp_doing_ajax() ) {
    849 				$action .= ' hide-if-no-js';
    850 			} elseif ( ( 'untrash' === $action && 'trash' === $the_comment_status )
    851 				|| ( 'unspam' === $action && 'spam' === $the_comment_status )
    852 			) {
    853 				if ( '1' === get_comment_meta( $comment->comment_ID, '_wp_trash_meta_status', true ) ) {
    854 					$action .= ' approve';
    855 				} else {
    856 					$action .= ' unapprove';
    857 				}
    858 			}
    859 
    860 			$out .= "<span class='$action'>$sep$link</span>";
    861 		}
    862 
    863 		$out .= '</div>';
    864 
    865 		$out .= '<button type="button" class="toggle-row"><span class="screen-reader-text">' . __( 'Show more details' ) . '</span></button>';
    866 
    867 		return $out;
    868 	}
    869 
    870 	/**
    871 	 * @param WP_Comment $comment The comment object.
    872 	 */
    873 	public function column_cb( $comment ) {
    874 		if ( $this->user_can ) {
    875 			?>
    876 		<label class="screen-reader-text" for="cb-select-<?php echo $comment->comment_ID; ?>"><?php _e( 'Select comment' ); ?></label>
    877 		<input id="cb-select-<?php echo $comment->comment_ID; ?>" type="checkbox" name="delete_comments[]" value="<?php echo $comment->comment_ID; ?>" />
    878 			<?php
    879 		}
    880 	}
    881 
    882 	/**
    883 	 * @param WP_Comment $comment The comment object.
    884 	 */
    885 	public function column_comment( $comment ) {
    886 		echo '<div class="comment-author">';
    887 			$this->column_author( $comment );
    888 		echo '</div>';
    889 
    890 		if ( $comment->comment_parent ) {
    891 			$parent = get_comment( $comment->comment_parent );
    892 
    893 			if ( $parent ) {
    894 				$parent_link = esc_url( get_comment_link( $parent ) );
    895 				$name        = get_comment_author( $parent );
    896 				printf(
    897 					/* translators: %s: Comment link. */
    898 					__( 'In reply to %s.' ),
    899 					'<a href="' . $parent_link . '">' . $name . '</a>'
    900 				);
    901 			}
    902 		}
    903 
    904 		comment_text( $comment );
    905 
    906 		if ( $this->user_can ) {
    907 			/** This filter is documented in wp-admin/includes/comment.php */
    908 			$comment_content = apply_filters( 'comment_edit_pre', $comment->comment_content );
    909 			?>
    910 		<div id="inline-<?php echo $comment->comment_ID; ?>" class="hidden">
    911 			<textarea class="comment" rows="1" cols="1"><?php echo esc_textarea( $comment_content ); ?></textarea>
    912 			<div class="author-email"><?php echo esc_attr( $comment->comment_author_email ); ?></div>
    913 			<div class="author"><?php echo esc_attr( $comment->comment_author ); ?></div>
    914 			<div class="author-url"><?php echo esc_attr( $comment->comment_author_url ); ?></div>
    915 			<div class="comment_status"><?php echo $comment->comment_approved; ?></div>
    916 		</div>
    917 			<?php
    918 		}
    919 	}
    920 
    921 	/**
    922 	 * @global string $comment_status
    923 	 *
    924 	 * @param WP_Comment $comment The comment object.
    925 	 */
    926 	public function column_author( $comment ) {
    927 		global $comment_status;
    928 
    929 		$author_url = get_comment_author_url( $comment );
    930 
    931 		$author_url_display = untrailingslashit( preg_replace( '|^http(s)?://(www\.)?|i', '', $author_url ) );
    932 
    933 		if ( strlen( $author_url_display ) > 50 ) {
    934 			$author_url_display = wp_html_excerpt( $author_url_display, 49, '&hellip;' );
    935 		}
    936 
    937 		echo '<strong>';
    938 		comment_author( $comment );
    939 		echo '</strong><br />';
    940 
    941 		if ( ! empty( $author_url_display ) ) {
    942 			printf( '<a href="%s">%s</a><br />', esc_url( $author_url ), esc_html( $author_url_display ) );
    943 		}
    944 
    945 		if ( $this->user_can ) {
    946 			if ( ! empty( $comment->comment_author_email ) ) {
    947 				/** This filter is documented in wp-includes/comment-template.php */
    948 				$email = apply_filters( 'comment_email', $comment->comment_author_email, $comment );
    949 
    950 				if ( ! empty( $email ) && '@' !== $email ) {
    951 					printf( '<a href="%1$s">%2$s</a><br />', esc_url( 'mailto:' . $email ), esc_html( $email ) );
    952 				}
    953 			}
    954 
    955 			$author_ip = get_comment_author_IP( $comment );
    956 
    957 			if ( $author_ip ) {
    958 				$author_ip_url = add_query_arg(
    959 					array(
    960 						's'    => $author_ip,
    961 						'mode' => 'detail',
    962 					),
    963 					admin_url( 'edit-comments.php' )
    964 				);
    965 
    966 				if ( 'spam' === $comment_status ) {
    967 					$author_ip_url = add_query_arg( 'comment_status', 'spam', $author_ip_url );
    968 				}
    969 
    970 				printf( '<a href="%1$s">%2$s</a>', esc_url( $author_ip_url ), esc_html( $author_ip ) );
    971 			}
    972 		}
    973 	}
    974 
    975 	/**
    976 	 * @param WP_Comment $comment The comment object.
    977 	 */
    978 	public function column_date( $comment ) {
    979 		$submitted = sprintf(
    980 			/* translators: 1: Comment date, 2: Comment time. */
    981 			__( '%1$s at %2$s' ),
    982 			/* translators: Comment date format. See https://www.php.net/manual/datetime.format.php */
    983 			get_comment_date( __( 'Y/m/d' ), $comment ),
    984 			/* translators: Comment time format. See https://www.php.net/manual/datetime.format.php */
    985 			get_comment_date( __( 'g:i a' ), $comment )
    986 		);
    987 
    988 		echo '<div class="submitted-on">';
    989 
    990 		if ( 'approved' === wp_get_comment_status( $comment ) && ! empty( $comment->comment_post_ID ) ) {
    991 			printf(
    992 				'<a href="%s">%s</a>',
    993 				esc_url( get_comment_link( $comment ) ),
    994 				$submitted
    995 			);
    996 		} else {
    997 			echo $submitted;
    998 		}
    999 
   1000 		echo '</div>';
   1001 	}
   1002 
   1003 	/**
   1004 	 * @param WP_Comment $comment The comment object.
   1005 	 */
   1006 	public function column_response( $comment ) {
   1007 		$post = get_post();
   1008 
   1009 		if ( ! $post ) {
   1010 			return;
   1011 		}
   1012 
   1013 		if ( isset( $this->pending_count[ $post->ID ] ) ) {
   1014 			$pending_comments = $this->pending_count[ $post->ID ];
   1015 		} else {
   1016 			$_pending_count_temp              = get_pending_comments_num( array( $post->ID ) );
   1017 			$pending_comments                 = $_pending_count_temp[ $post->ID ];
   1018 			$this->pending_count[ $post->ID ] = $pending_comments;
   1019 		}
   1020 
   1021 		if ( current_user_can( 'edit_post', $post->ID ) ) {
   1022 			$post_link  = "<a href='" . get_edit_post_link( $post->ID ) . "' class='comments-edit-item-link'>";
   1023 			$post_link .= esc_html( get_the_title( $post->ID ) ) . '</a>';
   1024 		} else {
   1025 			$post_link = esc_html( get_the_title( $post->ID ) );
   1026 		}
   1027 
   1028 		echo '<div class="response-links">';
   1029 
   1030 		if ( 'attachment' === $post->post_type ) {
   1031 			$thumb = wp_get_attachment_image( $post->ID, array( 80, 60 ), true );
   1032 			if ( $thumb ) {
   1033 				echo $thumb;
   1034 			}
   1035 		}
   1036 
   1037 		echo $post_link;
   1038 
   1039 		$post_type_object = get_post_type_object( $post->post_type );
   1040 		echo "<a href='" . get_permalink( $post->ID ) . "' class='comments-view-item-link'>" . $post_type_object->labels->view_item . '</a>';
   1041 
   1042 		echo '<span class="post-com-count-wrapper post-com-count-', $post->ID, '">';
   1043 		$this->comments_bubble( $post->ID, $pending_comments );
   1044 		echo '</span> ';
   1045 
   1046 		echo '</div>';
   1047 	}
   1048 
   1049 	/**
   1050 	 * @param WP_Comment $comment     The comment object.
   1051 	 * @param string     $column_name The custom column's name.
   1052 	 */
   1053 	public function column_default( $comment, $column_name ) {
   1054 		/**
   1055 		 * Fires when the default column output is displayed for a single row.
   1056 		 *
   1057 		 * @since 2.8.0
   1058 		 *
   1059 		 * @param string $column_name The custom column's name.
   1060 		 * @param int    $comment_id  The custom column's unique ID number.
   1061 		 */
   1062 		do_action( 'manage_comments_custom_column', $column_name, $comment->comment_ID );
   1063 	}
   1064 }