WP_Comments_List_Table

Core class used to implement displaying comments in a list table.

Defined (1)

The class is defined in the following location(s).

/wp-admin/includes/class-wp-comments-list-table.php  
  1. class WP_Comments_List_Table extends WP_List_Table { 
  2.  
  3. public $checkbox = true; 
  4.  
  5. public $pending_count = array(); 
  6.  
  7. public $extra_items; 
  8.  
  9. private $user_can; 
  10.  
  11. /** 
  12. * Constructor. 
  13. * @since 3.1.0 
  14. * @access public 
  15. * @see WP_List_Table::__construct() for more information on default arguments. 
  16. * @global int $post_id 
  17. * @param array $args An associative array of arguments. 
  18. */ 
  19. public function __construct( $args = array() ) { 
  20. global $post_id; 
  21.  
  22. $post_id = isset( $_REQUEST['p'] ) ? absint( $_REQUEST['p'] ) : 0; 
  23.  
  24. if ( get_option( 'show_avatars' ) ) { 
  25. add_filter( 'comment_author', array( $this, 'floated_admin_avatar' ), 10, 2 ); 
  26.  
  27. parent::__construct( array( 
  28. 'plural' => 'comments',  
  29. 'singular' => 'comment',  
  30. 'ajax' => true,  
  31. 'screen' => isset( $args['screen'] ) ? $args['screen'] : null,  
  32. ) ); 
  33.  
  34. public function floated_admin_avatar( $name, $comment_ID ) { 
  35. $comment = get_comment( $comment_ID ); 
  36. $avatar = get_avatar( $comment, 32, 'mystery' ); 
  37. return "$avatar $name"; 
  38.  
  39. /** 
  40. * @return bool 
  41. */ 
  42. public function ajax_user_can() { 
  43. return current_user_can('edit_posts'); 
  44.  
  45. /** 
  46. * @global int $post_id 
  47. * @global string $comment_status 
  48. * @global string $search 
  49. * @global string $comment_type 
  50. */ 
  51. public function prepare_items() { 
  52. global $post_id, $comment_status, $search, $comment_type; 
  53.  
  54. $comment_status = isset( $_REQUEST['comment_status'] ) ? $_REQUEST['comment_status'] : 'all'; 
  55. if ( !in_array( $comment_status, array( 'all', 'moderated', 'approved', 'spam', 'trash' ) ) ) 
  56. $comment_status = 'all'; 
  57.  
  58. $comment_type = !empty( $_REQUEST['comment_type'] ) ? $_REQUEST['comment_type'] : ''; 
  59.  
  60. $search = ( isset( $_REQUEST['s'] ) ) ? $_REQUEST['s'] : ''; 
  61.  
  62. $post_type = ( isset( $_REQUEST['post_type'] ) ) ? sanitize_key( $_REQUEST['post_type'] ) : ''; 
  63.  
  64. $user_id = ( isset( $_REQUEST['user_id'] ) ) ? $_REQUEST['user_id'] : ''; 
  65.  
  66. $orderby = ( isset( $_REQUEST['orderby'] ) ) ? $_REQUEST['orderby'] : ''; 
  67. $order = ( isset( $_REQUEST['order'] ) ) ? $_REQUEST['order'] : ''; 
  68.  
  69. $comments_per_page = $this->get_per_page( $comment_status ); 
  70.  
  71. $doing_ajax = defined( 'DOING_AJAX' ) && DOING_AJAX; 
  72.  
  73. if ( isset( $_REQUEST['number'] ) ) { 
  74. $number = (int) $_REQUEST['number']; 
  75. else { 
  76. $number = $comments_per_page + min( 8, $comments_per_page ); // Grab a few extra 
  77.  
  78. $page = $this->get_pagenum(); 
  79.  
  80. if ( isset( $_REQUEST['start'] ) ) { 
  81. $start = $_REQUEST['start']; 
  82. } else { 
  83. $start = ( $page - 1 ) * $comments_per_page; 
  84.  
  85. if ( $doing_ajax && isset( $_REQUEST['offset'] ) ) { 
  86. $start += $_REQUEST['offset']; 
  87.  
  88. $status_map = array( 
  89. 'moderated' => 'hold',  
  90. 'approved' => 'approve',  
  91. 'all' => '',  
  92. ); 
  93.  
  94. $args = array( 
  95. 'status' => isset( $status_map[$comment_status] ) ? $status_map[$comment_status] : $comment_status,  
  96. 'search' => $search,  
  97. 'user_id' => $user_id,  
  98. 'offset' => $start,  
  99. 'number' => $number,  
  100. 'post_id' => $post_id,  
  101. 'type' => $comment_type,  
  102. 'orderby' => $orderby,  
  103. 'order' => $order,  
  104. 'post_type' => $post_type,  
  105. ); 
  106.  
  107. $_comments = get_comments( $args ); 
  108. if ( is_array( $_comments ) ) { 
  109. update_comment_cache( $_comments ); 
  110.  
  111. $this->items = array_slice( $_comments, 0, $comments_per_page ); 
  112. $this->extra_items = array_slice( $_comments, $comments_per_page ); 
  113.  
  114. $_comment_post_ids = array_unique( wp_list_pluck( $_comments, 'comment_post_ID' ) ); 
  115.  
  116. $this->pending_count = get_pending_comments_num( $_comment_post_ids ); 
  117.  
  118. $total_comments = get_comments( array_merge( $args, array( 
  119. 'count' => true,  
  120. 'offset' => 0,  
  121. 'number' => 0 
  122. ) ) ); 
  123.  
  124. $this->set_pagination_args( array( 
  125. 'total_items' => $total_comments,  
  126. 'per_page' => $comments_per_page,  
  127. ) ); 
  128.  
  129. /** 
  130. * @param string $comment_status 
  131. * @return int 
  132. */ 
  133. public function get_per_page( $comment_status = 'all' ) { 
  134. $comments_per_page = $this->get_items_per_page( 'edit_comments_per_page' ); 
  135. /** 
  136. * Filters the number of comments listed per page in the comments list table. 
  137. * @since 2.6.0 
  138. * @param int $comments_per_page The number of comments to list per page. 
  139. * @param string $comment_status The comment status name. Default 'All'. 
  140. */ 
  141. return apply_filters( 'comments_per_page', $comments_per_page, $comment_status ); 
  142.  
  143. /** 
  144. * @global string $comment_status 
  145. */ 
  146. public function no_items() { 
  147. global $comment_status; 
  148.  
  149. if ( 'moderated' === $comment_status ) { 
  150. _e( 'No comments awaiting moderation.' ); 
  151. } else { 
  152. _e( 'No comments found.' ); 
  153.  
  154. /** 
  155. * @global int $post_id 
  156. * @global string $comment_status 
  157. * @global string $comment_type 
  158. */ 
  159. protected function get_views() { 
  160. global $post_id, $comment_status, $comment_type; 
  161.  
  162. $status_links = array(); 
  163. $num_comments = ( $post_id ) ? wp_count_comments( $post_id ) : wp_count_comments(); 
  164.  
  165. $stati = array( 
  166. /** translators: %s: all comments count */ 
  167. 'all' => _nx_noop( 
  168. 'All <span class="count">(%s)</span>',  
  169. 'All <span class="count">(%s)</span>',  
  170. 'comments' 
  171. ), // singular not used 
  172.  
  173. /** translators: %s: pending comments count */ 
  174. 'moderated' => _nx_noop( 
  175. 'Pending <span class="count">(%s)</span>',  
  176. 'Pending <span class="count">(%s)</span>',  
  177. 'comments' 
  178. ),  
  179.  
  180. /** translators: %s: approved comments count */ 
  181. 'approved' => _nx_noop( 
  182. 'Approved <span class="count">(%s)</span>',  
  183. 'Approved <span class="count">(%s)</span>',  
  184. 'comments' 
  185. ),  
  186.  
  187. /** translators: %s: spam comments count */ 
  188. 'spam' => _nx_noop( 
  189. 'Spam <span class="count">(%s)</span>',  
  190. 'Spam <span class="count">(%s)</span>',  
  191. 'comments' 
  192. ),  
  193.  
  194. /** translators: %s: trashed comments count */ 
  195. 'trash' => _nx_noop( 
  196. 'Trash <span class="count">(%s)</span>',  
  197. 'Trash <span class="count">(%s)</span>',  
  198. 'comments' 
  199. ); 
  200.  
  201. if ( !EMPTY_TRASH_DAYS ) 
  202. unset($stati['trash']); 
  203.  
  204. $link = admin_url( 'edit-comments.php' ); 
  205. if ( !empty($comment_type) && 'all' != $comment_type ) 
  206. $link = add_query_arg( 'comment_type', $comment_type, $link ); 
  207.  
  208. foreach ( $stati as $status => $label ) { 
  209. $class = ( $status === $comment_status ) ? ' class="current"' : ''; 
  210.  
  211. if ( !isset( $num_comments->$status ) ) 
  212. $num_comments->$status = 10; 
  213. $link = add_query_arg( 'comment_status', $status, $link ); 
  214. if ( $post_id ) 
  215. $link = add_query_arg( 'p', absint( $post_id ), $link ); 
  216. /** 
  217. // I toyed with this, but decided against it. Leaving it in here in case anyone thinks it is a good idea. ~ Mark 
  218. if ( !empty( $_REQUEST['s'] ) ) 
  219. $link = add_query_arg( 's', esc_attr( wp_unslash( $_REQUEST['s'] ) ), $link ); 
  220. */ 
  221. $status_links[ $status ] = "<a href='$link'$class>" . sprintf( 
  222. translate_nooped_plural( $label, $num_comments->$status ),  
  223. sprintf( '<span class="%s-count">%s</span>',  
  224. ( 'moderated' === $status ) ? 'pending' : $status,  
  225. number_format_i18n( $num_comments->$status ) 
  226. ) . '</a>'; 
  227.  
  228. /** 
  229. * Filters the comment status links. 
  230. * @since 2.5.0 
  231. * @param array $status_links An array of fully-formed status links. Default 'All'. 
  232. * Accepts 'All', 'Pending', 'Approved', 'Spam', and 'Trash'. 
  233. */ 
  234. return apply_filters( 'comment_status_links', $status_links ); 
  235.  
  236. /** 
  237. * @global string $comment_status 
  238. * @return array 
  239. */ 
  240. protected function get_bulk_actions() { 
  241. global $comment_status; 
  242.  
  243. $actions = array(); 
  244. if ( in_array( $comment_status, array( 'all', 'approved' ) ) ) 
  245. $actions['unapprove'] = __( 'Unapprove' ); 
  246. if ( in_array( $comment_status, array( 'all', 'moderated' ) ) ) 
  247. $actions['approve'] = __( 'Approve' ); 
  248. if ( in_array( $comment_status, array( 'all', 'moderated', 'approved', 'trash' ) ) ) 
  249. $actions['spam'] = _x( 'Mark as Spam', 'comment' ); 
  250.  
  251. if ( 'trash' === $comment_status ) { 
  252. $actions['untrash'] = __( 'Restore' ); 
  253. } elseif ( 'spam' === $comment_status ) { 
  254. $actions['unspam'] = _x( 'Not Spam', 'comment' ); 
  255.  
  256. if ( in_array( $comment_status, array( 'trash', 'spam' ) ) || !EMPTY_TRASH_DAYS ) 
  257. $actions['delete'] = __( 'Delete Permanently' ); 
  258. else 
  259. $actions['trash'] = __( 'Move to Trash' ); 
  260.  
  261. return $actions; 
  262.  
  263. /** 
  264. * @global string $comment_status 
  265. * @global string $comment_type 
  266. * @param string $which 
  267. */ 
  268. protected function extra_tablenav( $which ) { 
  269. global $comment_status, $comment_type; 
  270. ?> 
  271. <div class="alignleft actions"> 
  272. <?php 
  273. if ( 'top' === $which ) { 
  274. ?> 
  275. <label class="screen-reader-text" for="filter-by-comment-type"><?php _e( 'Filter by comment type' ); ?></label> 
  276. <select id="filter-by-comment-type" name="comment_type"> 
  277. <option value=""><?php _e( 'All comment types' ); ?></option> 
  278. <?php 
  279. /** 
  280. * Filters the comment types dropdown menu. 
  281. * @since 2.7.0 
  282. * @param array $comment_types An array of comment types. Accepts 'Comments', 'Pings'. 
  283. */ 
  284. $comment_types = apply_filters( 'admin_comment_types_dropdown', array( 
  285. 'comment' => __( 'Comments' ),  
  286. 'pings' => __( 'Pings' ),  
  287. ) ); 
  288.  
  289. foreach ( $comment_types as $type => $label ) 
  290. echo "\t" . '<option value="' . esc_attr( $type ) . '"' . selected( $comment_type, $type, false ) . ">$label</option>\n"; 
  291. ?> 
  292. </select> 
  293. <?php 
  294. /** 
  295. * Fires just before the Filter submit button for comment types. 
  296. * @since 3.5.0 
  297. */ 
  298. do_action( 'restrict_manage_comments' ); 
  299. submit_button( __( 'Filter' ), 'button', 'filter_action', false, array( 'id' => 'post-query-submit' ) ); 
  300.  
  301. if ( ( 'spam' === $comment_status || 'trash' === $comment_status ) && current_user_can( 'moderate_comments' ) ) { 
  302. wp_nonce_field( 'bulk-destroy', '_destroy_nonce' ); 
  303. $title = ( 'spam' === $comment_status ) ? esc_attr__( 'Empty Spam' ) : esc_attr__( 'Empty Trash' ); 
  304. submit_button( $title, 'apply', 'delete_all', false ); 
  305. /** 
  306. * Fires after the Filter submit button for comment types. 
  307. * @since 2.5.0 
  308. * @param string $comment_status The comment status name. Default 'All'. 
  309. */ 
  310. do_action( 'manage_comments_nav', $comment_status ); 
  311. echo '</div>'; 
  312.  
  313. /** 
  314. * @return string|false 
  315. */ 
  316. public function current_action() { 
  317. if ( isset( $_REQUEST['delete_all'] ) || isset( $_REQUEST['delete_all2'] ) ) 
  318. return 'delete_all'; 
  319.  
  320. return parent::current_action(); 
  321.  
  322. /** 
  323. * @global int $post_id 
  324. * @return array 
  325. */ 
  326. public function get_columns() { 
  327. global $post_id; 
  328.  
  329. $columns = array(); 
  330.  
  331. if ( $this->checkbox ) 
  332. $columns['cb'] = '<input type="checkbox" />'; 
  333.  
  334. $columns['author'] = __( 'Author' ); 
  335. $columns['comment'] = _x( 'Comment', 'column name' ); 
  336.  
  337. if ( ! $post_id ) { 
  338. /** translators: column name or table row header */ 
  339. $columns['response'] = __( 'In Response To' ); 
  340.  
  341. $columns['date'] = _x( 'Submitted On', 'column name' ); 
  342.  
  343. return $columns; 
  344.  
  345. /** 
  346. * @return array 
  347. */ 
  348. protected function get_sortable_columns() { 
  349. return array( 
  350. 'author' => 'comment_author',  
  351. 'response' => 'comment_post_ID',  
  352. 'date' => 'comment_date' 
  353. ); 
  354.  
  355. /** 
  356. * Get the name of the default primary column. 
  357. * @since 4.3.0 
  358. * @access protected 
  359. * @return string Name of the default primary column, in this case, 'comment'. 
  360. */ 
  361. protected function get_default_primary_column_name() { 
  362. return 'comment'; 
  363.  
  364. /** 
  365. * @access public 
  366. */ 
  367. public function display() { 
  368. wp_nonce_field( "fetch-list-" . get_class( $this ), '_ajax_fetch_list_nonce' ); 
  369.  
  370. $this->display_tablenav( 'top' ); 
  371.  
  372. $this->screen->render_screen_reader_content( 'heading_list' ); 
  373.  
  374. ?> 
  375. <table class="wp-list-table <?php echo implode( ' ', $this->get_table_classes() ); ?>"> 
  376. <thead> 
  377. <tr> 
  378. <?php $this->print_column_headers(); ?> 
  379. </tr> 
  380. </thead> 
  381.  
  382. <tbody id="the-comment-list" data-wp-lists="list:comment"> 
  383. <?php $this->display_rows_or_placeholder(); ?> 
  384. </tbody> 
  385.  
  386. <tbody id="the-extra-comment-list" data-wp-lists="list:comment" style="display: none;"> 
  387. <?php 
  388. $this->items = $this->extra_items; 
  389. $this->display_rows_or_placeholder(); 
  390. ?> 
  391. </tbody> 
  392.  
  393. <tfoot> 
  394. <tr> 
  395. <?php $this->print_column_headers( false ); ?> 
  396. </tr> 
  397. </tfoot> 
  398.  
  399. </table> 
  400. <?php 
  401.  
  402. $this->display_tablenav( 'bottom' ); 
  403.  
  404. /** 
  405. * @global WP_Post $post 
  406. * @global WP_Comment $comment 
  407. * @param WP_Comment $item 
  408. */ 
  409. public function single_row( $item ) { 
  410. global $post, $comment; 
  411.  
  412. $comment = $item; 
  413.  
  414. $the_comment_class = wp_get_comment_status( $comment ); 
  415. if ( ! $the_comment_class ) { 
  416. $the_comment_class = ''; 
  417. $the_comment_class = join( ' ', get_comment_class( $the_comment_class, $comment, $comment->comment_post_ID ) ); 
  418.  
  419. if ( $comment->comment_post_ID > 0 ) { 
  420. $post = get_post( $comment->comment_post_ID ); 
  421. $this->user_can = current_user_can( 'edit_comment', $comment->comment_ID ); 
  422.  
  423. echo "<tr id='comment-$comment->comment_ID' class='$the_comment_class'>"; 
  424. $this->single_row_columns( $comment ); 
  425. echo "</tr>\n"; 
  426.  
  427. unset( $GLOBALS['post'], $GLOBALS['comment'] ); 
  428.  
  429. /** 
  430. * Generate and display row actions links. 
  431. * @since 4.3.0 
  432. * @access protected 
  433. * @global string $comment_status Status for the current listed comments. 
  434. * @param WP_Comment $comment The comment object. 
  435. * @param string $column_name Current column name. 
  436. * @param string $primary Primary column name. 
  437. * @return string|void Comment row actions output. 
  438. */ 
  439. protected function handle_row_actions( $comment, $column_name, $primary ) { 
  440. global $comment_status; 
  441.  
  442. if ( $primary !== $column_name ) { 
  443. return ''; 
  444.  
  445. if ( ! $this->user_can ) { 
  446. return; 
  447.  
  448. $the_comment_status = wp_get_comment_status( $comment ); 
  449.  
  450. $out = ''; 
  451.  
  452. $del_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "delete-comment_$comment->comment_ID" ) ); 
  453. $approve_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "approve-comment_$comment->comment_ID" ) ); 
  454.  
  455. $url = "comment.php?c=$comment->comment_ID"; 
  456.  
  457. $approve_url = esc_url( $url . "&action=approvecomment&$approve_nonce" ); 
  458. $unapprove_url = esc_url( $url . "&action=unapprovecomment&$approve_nonce" ); 
  459. $spam_url = esc_url( $url . "&action=spamcomment&$del_nonce" ); 
  460. $unspam_url = esc_url( $url . "&action=unspamcomment&$del_nonce" ); 
  461. $trash_url = esc_url( $url . "&action=trashcomment&$del_nonce" ); 
  462. $untrash_url = esc_url( $url . "&action=untrashcomment&$del_nonce" ); 
  463. $delete_url = esc_url( $url . "&action=deletecomment&$del_nonce" ); 
  464.  
  465. // Preorder it: Approve | Reply | Quick Edit | Edit | Spam | Trash. 
  466. $actions = array( 
  467. 'approve' => '', 'unapprove' => '',  
  468. 'reply' => '',  
  469. 'quickedit' => '',  
  470. 'edit' => '',  
  471. 'spam' => '', 'unspam' => '',  
  472. 'trash' => '', 'untrash' => '', 'delete' => '' 
  473. ); 
  474.  
  475. // Not looking at all comments. 
  476. if ( $comment_status && 'all' != $comment_status ) { 
  477. if ( 'approved' === $the_comment_status ) { 
  478. $actions['unapprove'] = "<a href='$unapprove_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID:e7e7d3:action=dim-comment&new=unapproved' class='vim-u vim-destructive' aria-label='" . esc_attr__( 'Unapprove this comment' ) . "'>" . __( 'Unapprove' ) . '</a>'; 
  479. } elseif ( 'unapproved' === $the_comment_status ) { 
  480. $actions['approve'] = "<a href='$approve_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID:e7e7d3:action=dim-comment&new=approved' class='vim-a vim-destructive' aria-label='" . esc_attr__( 'Approve this comment' ) . "'>" . __( 'Approve' ) . '</a>'; 
  481. } else { 
  482. $actions['approve'] = "<a href='$approve_url' data-wp-lists='dim:the-comment-list:comment-$comment->comment_ID:unapproved:e7e7d3:e7e7d3:new=approved' class='vim-a' aria-label='" . esc_attr__( 'Approve this comment' ) . "'>" . __( 'Approve' ) . '</a>'; 
  483. $actions['unapprove'] = "<a href='$unapprove_url' data-wp-lists='dim:the-comment-list:comment-$comment->comment_ID:unapproved:e7e7d3:e7e7d3:new=unapproved' class='vim-u' aria-label='" . esc_attr__( 'Unapprove this comment' ) . "'>" . __( 'Unapprove' ) . '</a>'; 
  484.  
  485. if ( 'spam' !== $the_comment_status ) { 
  486. $actions['spam'] = "<a href='$spam_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID::spam=1' class='vim-s vim-destructive' aria-label='" . esc_attr__( 'Mark this comment as spam' ) . "'>" . /** translators: mark as spam link */ _x( 'Spam', 'verb' ) . '</a>'; 
  487. } elseif ( 'spam' === $the_comment_status ) { 
  488. $actions['unspam'] = "<a href='$unspam_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID:66cc66:unspam=1' class='vim-z vim-destructive' aria-label='" . esc_attr__( 'Restore this comment from the spam' ) . "'>" . _x( 'Not Spam', 'comment' ) . '</a>'; 
  489.  
  490. if ( 'trash' === $the_comment_status ) { 
  491. $actions['untrash'] = "<a href='$untrash_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID:66cc66:untrash=1' class='vim-z vim-destructive' aria-label='" . esc_attr__( 'Restore this comment from the Trash' ) . "'>" . __( 'Restore' ) . '</a>'; 
  492.  
  493. if ( 'spam' === $the_comment_status || 'trash' === $the_comment_status || !EMPTY_TRASH_DAYS ) { 
  494. $actions['delete'] = "<a href='$delete_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID::delete=1' class='delete vim-d vim-destructive' aria-label='" . esc_attr__( 'Delete this comment permanently' ) . "'>" . __( 'Delete Permanently' ) . '</a>'; 
  495. } else { 
  496. $actions['trash'] = "<a href='$trash_url' data-wp-lists='delete:the-comment-list:comment-$comment->comment_ID::trash=1' class='delete vim-d vim-destructive' aria-label='" . esc_attr__( 'Move this comment to the Trash' ) . "'>" . _x( 'Trash', 'verb' ) . '</a>'; 
  497.  
  498. if ( 'spam' !== $the_comment_status && 'trash' !== $the_comment_status ) { 
  499. $actions['edit'] = "<a href='comment.php?action=editcomment&c={$comment->comment_ID}' aria-label='" . esc_attr__( 'Edit this comment' ) . "'>". __( 'Edit' ) . '</a>'; 
  500.  
  501. $format = '<a data-comment-id="%d" data-post-id="%d" data-action="%s" class="%s" aria-label="%s" href="#">%s</a>'; 
  502.  
  503. $actions['quickedit'] = sprintf( $format, $comment->comment_ID, $comment->comment_post_ID, 'edit', 'vim-q comment-inline', esc_attr__( 'Quick edit this comment inline' ), __( 'Quick Edit' ) ); 
  504.  
  505. $actions['reply'] = sprintf( $format, $comment->comment_ID, $comment->comment_post_ID, 'replyto', 'vim-r comment-inline', esc_attr__( 'Reply to this comment' ), __( 'Reply' ) ); 
  506.  
  507. /** This filter is documented in wp-admin/includes/dashboard.php */ 
  508. $actions = apply_filters( 'comment_row_actions', array_filter( $actions ), $comment ); 
  509.  
  510. $i = 0; 
  511. $out .= '<div class="row-actions">'; 
  512. foreach ( $actions as $action => $link ) { 
  513. ++$i; 
  514. ( ( ( 'approve' === $action || 'unapprove' === $action ) && 2 === $i ) || 1 === $i ) ? $sep = '' : $sep = ' | '; 
  515.  
  516. // Reply and quickedit need a hide-if-no-js span when not added with ajax 
  517. if ( ( 'reply' === $action || 'quickedit' === $action ) && ! defined('DOING_AJAX') ) 
  518. $action .= ' hide-if-no-js'; 
  519. elseif ( ( $action === 'untrash' && $the_comment_status === 'trash' ) || ( $action === 'unspam' && $the_comment_status === 'spam' ) ) { 
  520. if ( '1' == get_comment_meta( $comment->comment_ID, '_wp_trash_meta_status', true ) ) 
  521. $action .= ' approve'; 
  522. else 
  523. $action .= ' unapprove'; 
  524.  
  525. $out .= "<span class='$action'>$sep$link</span>"; 
  526. $out .= '</div>'; 
  527.  
  528. $out .= '<button type="button" class="toggle-row"><span class="screen-reader-text">' . __( 'Show more details' ) . '</span></button>'; 
  529.  
  530. return $out; 
  531.  
  532. /** 
  533. * @param WP_Comment $comment The comment object. 
  534. */ 
  535. public function column_cb( $comment ) { 
  536. if ( $this->user_can ) { ?> 
  537. <label class="screen-reader-text" for="cb-select-<?php echo $comment->comment_ID; ?>"><?php _e( 'Select comment' ); ?></label> 
  538. <input id="cb-select-<?php echo $comment->comment_ID; ?>" type="checkbox" name="delete_comments[]" value="<?php echo $comment->comment_ID; ?>" /> 
  539. <?php 
  540.  
  541. /** 
  542. * @param WP_Comment $comment The comment object. 
  543. */ 
  544. public function column_comment( $comment ) { 
  545. echo '<div class="comment-author">'; 
  546. $this->column_author( $comment ); 
  547. echo '</div>'; 
  548.  
  549. if ( $comment->comment_parent ) { 
  550. $parent = get_comment( $comment->comment_parent ); 
  551. if ( $parent ) { 
  552. $parent_link = esc_url( get_comment_link( $parent ) ); 
  553. $name = get_comment_author( $parent ); 
  554. printf( 
  555. /** translators: %s: comment link */ 
  556. __( 'In reply to %s.' ),  
  557. '<a href="' . $parent_link . '">' . $name . '</a>' 
  558. ); 
  559.  
  560. comment_text( $comment ); 
  561. if ( $this->user_can ) { ?> 
  562. <div id="inline-<?php echo $comment->comment_ID; ?>" class="hidden"> 
  563. <textarea class="comment" rows="1" cols="1"><?php 
  564. /** This filter is documented in wp-admin/includes/comment.php */ 
  565. echo esc_textarea( apply_filters( 'comment_edit_pre', $comment->comment_content ) ); 
  566. ?></textarea> 
  567. <div class="author-email"><?php echo esc_attr( $comment->comment_author_email ); ?></div> 
  568. <div class="author"><?php echo esc_attr( $comment->comment_author ); ?></div> 
  569. <div class="author-url"><?php echo esc_attr( $comment->comment_author_url ); ?></div> 
  570. <div class="comment_status"><?php echo $comment->comment_approved; ?></div> 
  571. </div> 
  572. <?php 
  573.  
  574. /** 
  575. * @global string $comment_status 
  576. * @param WP_Comment $comment The comment object. 
  577. */ 
  578. public function column_author( $comment ) { 
  579. global $comment_status; 
  580.  
  581. $author_url = get_comment_author_url( $comment ); 
  582.  
  583. $author_url_display = untrailingslashit( preg_replace( '|^http(s)?://(www\.)?|i', '', $author_url ) ); 
  584. if ( strlen( $author_url_display ) > 50 ) { 
  585. $author_url_display = wp_html_excerpt( $author_url_display, 49, '…' ); 
  586.  
  587. echo "<strong>"; comment_author( $comment ); echo '</strong><br />'; 
  588. if ( ! empty( $author_url_display ) ) { 
  589. printf( '<a href="%s">%s</a><br />', esc_url( $author_url ), esc_html( $author_url_display ) ); 
  590.  
  591. if ( $this->user_can ) { 
  592. if ( ! empty( $comment->comment_author_email ) ) { 
  593. /** This filter is documented in wp-includes/comment-template.php */ 
  594. $email = apply_filters( 'comment_email', $comment->comment_author_email, $comment ); 
  595.  
  596. if ( ! empty( $email ) && '@' !== $email ) { 
  597. printf( '<a href="%1$s">%2$s</a><br />', esc_url( 'mailto:' . $email ), esc_html( $email ) ); 
  598.  
  599. $author_ip = get_comment_author_IP( $comment ); 
  600. if ( $author_ip ) { 
  601. $author_ip_url = add_query_arg( array( 's' => $author_ip, 'mode' => 'detail' ), admin_url( 'edit-comments.php' ) ); 
  602. if ( 'spam' === $comment_status ) { 
  603. $author_ip_url = add_query_arg( 'comment_status', 'spam', $author_ip_url ); 
  604. printf( '<a href="%1$s">%2$s</a>', esc_url( $author_ip_url ), esc_html( $author_ip ) ); 
  605.  
  606. /** 
  607. * @access public 
  608. * @param WP_Comment $comment The comment object. 
  609. */ 
  610. public function column_date( $comment ) { 
  611. /** translators: 1: comment date, 2: comment time */ 
  612. $submitted = sprintf( __( '%1$s at %2$s' ),  
  613. /** translators: comment date format. See https://secure.php.net/date */ 
  614. get_comment_date( __( 'Y/m/d' ), $comment ),  
  615. get_comment_date( __( 'g:i a' ), $comment ) 
  616. ); 
  617.  
  618. echo '<div class="submitted-on">'; 
  619. if ( 'approved' === wp_get_comment_status( $comment ) && ! empty ( $comment->comment_post_ID ) ) { 
  620. printf( 
  621. '<a href="%s">%s</a>',  
  622. esc_url( get_comment_link( $comment ) ),  
  623. $submitted 
  624. ); 
  625. } else { 
  626. echo $submitted; 
  627. echo '</div>'; 
  628.  
  629. /** 
  630. * @access public 
  631. * @param WP_Comment $comment The comment object. 
  632. */ 
  633. public function column_response( $comment ) { 
  634. $post = get_post(); 
  635.  
  636. if ( ! $post ) { 
  637. return; 
  638.  
  639. if ( isset( $this->pending_count[$post->ID] ) ) { 
  640. $pending_comments = $this->pending_count[$post->ID]; 
  641. } else { 
  642. $_pending_count_temp = get_pending_comments_num( array( $post->ID ) ); 
  643. $pending_comments = $this->pending_count[$post->ID] = $_pending_count_temp[$post->ID]; 
  644.  
  645. if ( current_user_can( 'edit_post', $post->ID ) ) { 
  646. $post_link = "<a href='" . get_edit_post_link( $post->ID ) . "' class='comments-edit-item-link'>"; 
  647. $post_link .= esc_html( get_the_title( $post->ID ) ) . '</a>'; 
  648. } else { 
  649. $post_link = esc_html( get_the_title( $post->ID ) ); 
  650.  
  651. echo '<div class="response-links">'; 
  652. if ( 'attachment' === $post->post_type && ( $thumb = wp_get_attachment_image( $post->ID, array( 80, 60 ), true ) ) ) { 
  653. echo $thumb; 
  654. echo $post_link; 
  655. $post_type_object = get_post_type_object( $post->post_type ); 
  656. echo "<a href='" . get_permalink( $post->ID ) . "' class='comments-view-item-link'>" . $post_type_object->labels->view_item . '</a>'; 
  657. echo '<span class="post-com-count-wrapper post-com-count-', $post->ID, '">'; 
  658. $this->comments_bubble( $post->ID, $pending_comments ); 
  659. echo '</span> '; 
  660. echo '</div>'; 
  661.  
  662. /** 
  663. * @param WP_Comment $comment The comment object. 
  664. * @param string $column_name The custom column's name. 
  665. */ 
  666. public function column_default( $comment, $column_name ) { 
  667. /** 
  668. * Fires when the default column output is displayed for a single row. 
  669. * @since 2.8.0 
  670. * @param string $column_name The custom column's name. 
  671. * @param int $comment->comment_ID The custom column's unique ID number. 
  672. */ 
  673. do_action( 'manage_comments_custom_column', $column_name, $comment->comment_ID );