/wp-admin/includes/class-wp-comments-list-table.php

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