WP_Users_List_Table

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

Defined (1)

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

/wp-admin/includes/class-wp-users-list-table.php  
  1. class WP_Users_List_Table extends WP_List_Table { 
  2.  
  3. /** 
  4. * Site ID to generate the Users list table for. 
  5. * @since 3.1.0 
  6. * @access public 
  7. * @var int 
  8. */ 
  9. public $site_id; 
  10.  
  11. /** 
  12. * Whether or not the current Users list table is for Multisite. 
  13. * @since 3.1.0 
  14. * @access public 
  15. * @var bool 
  16. */ 
  17. public $is_site_users; 
  18.  
  19. /** 
  20. * Constructor. 
  21. * @since 3.1.0 
  22. * @access public 
  23. * @see WP_List_Table::__construct() for more information on default arguments. 
  24. * @param array $args An associative array of arguments. 
  25. */ 
  26. public function __construct( $args = array() ) { 
  27. parent::__construct( array( 
  28. 'singular' => 'user',  
  29. 'plural' => 'users',  
  30. 'screen' => isset( $args['screen'] ) ? $args['screen'] : null,  
  31. ) ); 
  32.  
  33. $this->is_site_users = 'site-users-network' === $this->screen->id; 
  34.  
  35. if ( $this->is_site_users ) 
  36. $this->site_id = isset( $_REQUEST['id'] ) ? intval( $_REQUEST['id'] ) : 0; 
  37.  
  38. /** 
  39. * Check the current user's permissions. 
  40. * @since 3.1.0 
  41. * @access public 
  42. * @return bool 
  43. */ 
  44. public function ajax_user_can() { 
  45. if ( $this->is_site_users ) 
  46. return current_user_can( 'manage_sites' ); 
  47. else 
  48. return current_user_can( 'list_users' ); 
  49.  
  50. /** 
  51. * Prepare the users list for display. 
  52. * @since 3.1.0 
  53. * @access public 
  54. * @global string $role 
  55. * @global string $usersearch 
  56. */ 
  57. public function prepare_items() { 
  58. global $role, $usersearch; 
  59.  
  60. $usersearch = isset( $_REQUEST['s'] ) ? wp_unslash( trim( $_REQUEST['s'] ) ) : ''; 
  61.  
  62. $role = isset( $_REQUEST['role'] ) ? $_REQUEST['role'] : ''; 
  63.  
  64. $per_page = ( $this->is_site_users ) ? 'site_users_network_per_page' : 'users_per_page'; 
  65. $users_per_page = $this->get_items_per_page( $per_page ); 
  66.  
  67. $paged = $this->get_pagenum(); 
  68.  
  69. if ( 'none' === $role ) { 
  70. $args = array( 
  71. 'number' => $users_per_page,  
  72. 'offset' => ( $paged-1 ) * $users_per_page,  
  73. 'include' => wp_get_users_with_no_role(),  
  74. 'search' => $usersearch,  
  75. 'fields' => 'all_with_meta' 
  76. ); 
  77. } else { 
  78. $args = array( 
  79. 'number' => $users_per_page,  
  80. 'offset' => ( $paged-1 ) * $users_per_page,  
  81. 'role' => $role,  
  82. 'search' => $usersearch,  
  83. 'fields' => 'all_with_meta' 
  84. ); 
  85.  
  86. if ( '' !== $args['search'] ) 
  87. $args['search'] = '*' . $args['search'] . '*'; 
  88.  
  89. if ( $this->is_site_users ) 
  90. $args['blog_id'] = $this->site_id; 
  91.  
  92. if ( isset( $_REQUEST['orderby'] ) ) 
  93. $args['orderby'] = $_REQUEST['orderby']; 
  94.  
  95. if ( isset( $_REQUEST['order'] ) ) 
  96. $args['order'] = $_REQUEST['order']; 
  97.  
  98. /** 
  99. * Filters the query arguments used to retrieve users for the current users list table. 
  100. * @since 4.4.0 
  101. * @param array $args Arguments passed to WP_User_Query to retrieve items for the current 
  102. * users list table. 
  103. */ 
  104. $args = apply_filters( 'users_list_table_query_args', $args ); 
  105.  
  106. // Query the user IDs for this page 
  107. $wp_user_search = new WP_User_Query( $args ); 
  108.  
  109. $this->items = $wp_user_search->get_results(); 
  110.  
  111. $this->set_pagination_args( array( 
  112. 'total_items' => $wp_user_search->get_total(),  
  113. 'per_page' => $users_per_page,  
  114. ) ); 
  115.  
  116. /** 
  117. * Output 'no users' message. 
  118. * @since 3.1.0 
  119. * @access public 
  120. */ 
  121. public function no_items() { 
  122. _e( 'No users found.' ); 
  123.  
  124. /** 
  125. * Return an associative array listing all the views that can be used 
  126. * with this table. 
  127. * Provides a list of roles and user count for that role for easy 
  128. * Filtersing of the user table. 
  129. * @since 3.1.0 
  130. * @access protected 
  131. * @global string $role 
  132. * @return array An array of HTML links, one for each view. 
  133. */ 
  134. protected function get_views() { 
  135. global $role; 
  136.  
  137. $wp_roles = wp_roles(); 
  138.  
  139. if ( $this->is_site_users ) { 
  140. $url = 'site-users.php?id=' . $this->site_id; 
  141. switch_to_blog( $this->site_id ); 
  142. $users_of_blog = count_users(); 
  143. restore_current_blog(); 
  144. } else { 
  145. $url = 'users.php'; 
  146. $users_of_blog = count_users(); 
  147.  
  148. $total_users = $users_of_blog['total_users']; 
  149. $avail_roles =& $users_of_blog['avail_roles']; 
  150. unset($users_of_blog); 
  151.  
  152. $class = empty($role) ? ' class="current"' : ''; 
  153. $role_links = array(); 
  154. $role_links['all'] = "<a href='$url'$class>" . sprintf( _nx( 'All <span class="count">(%s)</span>', 'All <span class="count">(%s)</span>', $total_users, 'users' ), number_format_i18n( $total_users ) ) . '</a>'; 
  155. foreach ( $wp_roles->get_names() as $this_role => $name ) { 
  156. if ( !isset($avail_roles[$this_role]) ) 
  157. continue; 
  158.  
  159. $class = ''; 
  160.  
  161. if ( $this_role === $role ) { 
  162. $class = ' class="current"'; 
  163.  
  164. $name = translate_user_role( $name ); 
  165. /** translators: User role name with count */ 
  166. $name = sprintf( __('%1$s <span class="count">(%2$s)</span>'), $name, number_format_i18n( $avail_roles[$this_role] ) ); 
  167. $role_links[$this_role] = "<a href='" . esc_url( add_query_arg( 'role', $this_role, $url ) ) . "'$class>$name</a>"; 
  168.  
  169. if ( ! empty( $avail_roles['none' ] ) ) { 
  170.  
  171. $class = ''; 
  172.  
  173. if ( 'none' === $role ) { 
  174. $class = ' class="current"'; 
  175.  
  176. $name = __( 'No role' ); 
  177. /** translators: User role name with count */ 
  178. $name = sprintf( __('%1$s <span class="count">(%2$s)</span>'), $name, number_format_i18n( $avail_roles['none' ] ) ); 
  179. $role_links['none'] = "<a href='" . esc_url( add_query_arg( 'role', 'none', $url ) ) . "'$class>$name</a>"; 
  180.  
  181.  
  182. return $role_links; 
  183.  
  184. /** 
  185. * Retrieve an associative array of bulk actions available on this table. 
  186. * @since 3.1.0 
  187. * @access protected 
  188. * @return array Array of bulk actions. 
  189. */ 
  190. protected function get_bulk_actions() { 
  191. $actions = array(); 
  192.  
  193. if ( is_multisite() ) { 
  194. if ( current_user_can( 'remove_users' ) ) 
  195. $actions['remove'] = __( 'Remove' ); 
  196. } else { 
  197. if ( current_user_can( 'delete_users' ) ) 
  198. $actions['delete'] = __( 'Delete' ); 
  199.  
  200. return $actions; 
  201.  
  202. /** 
  203. * Output the controls to allow user roles to be changed in bulk. 
  204. * @since 3.1.0 
  205. * @access protected 
  206. * @param string $which Whether this is being invoked above ("top") 
  207. * or below the table ("bottom"). 
  208. */ 
  209. protected function extra_tablenav( $which ) { 
  210. $id = 'bottom' === $which ? 'new_role2' : 'new_role'; 
  211. ?> 
  212. <div class="alignleft actions"> 
  213. <?php if ( current_user_can( 'promote_users' ) && $this->has_items() ) : ?> 
  214. <label class="screen-reader-text" for="<?php echo $id ?>"><?php _e( 'Change role to…' ) ?></label> 
  215. <select name="<?php echo $id ?>" id="<?php echo $id ?>"> 
  216. <option value=""><?php _e( 'Change role to…' ) ?></option> 
  217. <?php wp_dropdown_roles(); ?> 
  218. </select> 
  219. <?php 
  220. submit_button( __( 'Change' ), 'button', 'changeit', false ); 
  221. endif; 
  222.  
  223. /** 
  224. * Fires just before the closing div containing the bulk role-change controls 
  225. * in the Users list table. 
  226. * @since 3.5.0 
  227. * @since 4.6.0 The `$which` parameter was added. 
  228. * @param string $which The location of the extra table nav markup: 'top' or 'bottom'. 
  229. */ 
  230. do_action( 'restrict_manage_users', $which ); 
  231. echo '</div>'; 
  232.  
  233. /** 
  234. * Capture the bulk action required, and return it. 
  235. * Overridden from the base class implementation to capture 
  236. * the role change drop-down. 
  237. * @since 3.1.0 
  238. * @access public 
  239. * @return string The bulk action required. 
  240. */ 
  241. public function current_action() { 
  242. if ( isset( $_REQUEST['changeit'] ) && 
  243. ( ! empty( $_REQUEST['new_role'] ) || ! empty( $_REQUEST['new_role2'] ) ) ) { 
  244. return 'promote'; 
  245.  
  246. return parent::current_action(); 
  247.  
  248. /** 
  249. * Get a list of columns for the list table. 
  250. * @since 3.1.0 
  251. * @access public 
  252. * @return array Array in which the key is the ID of the column,  
  253. * and the value is the description. 
  254. */ 
  255. public function get_columns() { 
  256. $c = array( 
  257. 'cb' => '<input type="checkbox" />',  
  258. 'username' => __( 'Username' ),  
  259. 'name' => __( 'Name' ),  
  260. 'email' => __( 'Email' ),  
  261. 'role' => __( 'Role' ),  
  262. 'posts' => __( 'Posts' ) 
  263. ); 
  264.  
  265. if ( $this->is_site_users ) 
  266. unset( $c['posts'] ); 
  267.  
  268. return $c; 
  269.  
  270. /** 
  271. * Get a list of sortable columns for the list table. 
  272. * @since 3.1.0 
  273. * @access protected 
  274. * @return array Array of sortable columns. 
  275. */ 
  276. protected function get_sortable_columns() { 
  277. $c = array( 
  278. 'username' => 'login',  
  279. 'email' => 'email',  
  280. ); 
  281.  
  282. return $c; 
  283.  
  284. /** 
  285. * Generate the list table rows. 
  286. * @since 3.1.0 
  287. * @access public 
  288. */ 
  289. public function display_rows() { 
  290. // Query the post counts for this page 
  291. if ( ! $this->is_site_users ) 
  292. $post_counts = count_many_users_posts( array_keys( $this->items ) ); 
  293.  
  294. foreach ( $this->items as $userid => $user_object ) { 
  295. if ( is_multisite() && empty( $user_object->allcaps ) ) 
  296. continue; 
  297.  
  298. echo "\n\t" . $this->single_row( $user_object, '', '', isset( $post_counts ) ? $post_counts[ $userid ] : 0 ); 
  299.  
  300. /** 
  301. * Generate HTML for a single row on the users.php admin panel. 
  302. * @since 3.1.0 
  303. * @since 4.2.0 The `$style` parameter was deprecated. 
  304. * @since 4.4.0 The `$role` parameter was deprecated. 
  305. * @access public 
  306. * @param object $user_object The current user object. 
  307. * @param string $style Deprecated. Not used. 
  308. * @param string $role Deprecated. Not used. 
  309. * @param int $numposts Optional. Post count to display for this user. Defaults 
  310. * to zero, as in, a new user has made zero posts. 
  311. * @return string Output for a single row. 
  312. */ 
  313. public function single_row( $user_object, $style = '', $role = '', $numposts = 0 ) { 
  314. if ( ! ( $user_object instanceof WP_User ) ) { 
  315. $user_object = get_userdata( (int) $user_object ); 
  316. $user_object->filter = 'display'; 
  317. $email = $user_object->user_email; 
  318.  
  319. if ( $this->is_site_users ) 
  320. $url = "site-users.php?id={$this->site_id}&"; 
  321. else 
  322. $url = 'users.php?'; 
  323.  
  324. $user_roles = $this->get_role_list( $user_object ); 
  325.  
  326. // Set up the hover actions for this user 
  327. $actions = array(); 
  328. $checkbox = ''; 
  329. // Check if the user for this row is editable 
  330. if ( current_user_can( 'list_users' ) ) { 
  331. // Set up the user editing link 
  332. $edit_link = esc_url( add_query_arg( 'wp_http_referer', urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ), get_edit_user_link( $user_object->ID ) ) ); 
  333.  
  334. if ( current_user_can( 'edit_user', $user_object->ID ) ) { 
  335. $edit = "<strong><a href=\"$edit_link\">$user_object->user_login</a></strong><br />"; 
  336. $actions['edit'] = '<a href="' . $edit_link . '">' . __( 'Edit' ) . '</a>'; 
  337. } else { 
  338. $edit = "<strong>$user_object->user_login</strong><br />"; 
  339.  
  340. if ( !is_multisite() && get_current_user_id() != $user_object->ID && current_user_can( 'delete_user', $user_object->ID ) ) 
  341. $actions['delete'] = "<a class='submitdelete' href='" . wp_nonce_url( "users.php?action=delete&user=$user_object->ID", 'bulk-users' ) . "'>" . __( 'Delete' ) . "</a>"; 
  342. if ( is_multisite() && get_current_user_id() != $user_object->ID && current_user_can( 'remove_user', $user_object->ID ) ) 
  343. $actions['remove'] = "<a class='submitdelete' href='" . wp_nonce_url( $url."action=remove&user=$user_object->ID", 'bulk-users' ) . "'>" . __( 'Remove' ) . "</a>"; 
  344.  
  345. /** 
  346. * Filters the action links displayed under each user in the Users list table. 
  347. * @since 2.8.0 
  348. * @param array $actions An array of action links to be displayed. 
  349. * Default 'Edit', 'Delete' for single site, and 
  350. * 'Edit', 'Remove' for Multisite. 
  351. * @param WP_User $user_object WP_User object for the currently-listed user. 
  352. */ 
  353. $actions = apply_filters( 'user_row_actions', $actions, $user_object ); 
  354.  
  355. // Role classes. 
  356. $role_classes = esc_attr( implode( ' ', array_keys( $user_roles ) ) ); 
  357.  
  358. // Set up the checkbox ( because the user is editable, otherwise it's empty ) 
  359. $checkbox = '<label class="screen-reader-text" for="user_' . $user_object->ID . '">' . sprintf( __( 'Select %s' ), $user_object->user_login ) . '</label>' 
  360. . "<input type='checkbox' name='users[]' id='user_{$user_object->ID}' class='{$role_classes}' value='{$user_object->ID}' />"; 
  361.  
  362. } else { 
  363. $edit = '<strong>' . $user_object->user_login . '</strong>'; 
  364. $avatar = get_avatar( $user_object->ID, 32 ); 
  365.  
  366. // Comma-separated list of user roles. 
  367. $roles_list = implode( ', ', $user_roles ); 
  368.  
  369. $r = "<tr id='user-$user_object->ID'>"; 
  370.  
  371. list( $columns, $hidden, $sortable, $primary ) = $this->get_column_info(); 
  372.  
  373. foreach ( $columns as $column_name => $column_display_name ) { 
  374. $classes = "$column_name column-$column_name"; 
  375. if ( $primary === $column_name ) { 
  376. $classes .= ' has-row-actions column-primary'; 
  377. if ( 'posts' === $column_name ) { 
  378. $classes .= ' num'; // Special case for that column 
  379.  
  380. if ( in_array( $column_name, $hidden ) ) { 
  381. $classes .= ' hidden'; 
  382.  
  383. $data = 'data-colname="' . wp_strip_all_tags( $column_display_name ) . '"'; 
  384.  
  385. $attributes = "class='$classes' $data"; 
  386.  
  387. if ( 'cb' === $column_name ) { 
  388. $r .= "<th scope='row' class='check-column'>$checkbox</th>"; 
  389. } else { 
  390. $r .= "<td $attributes>"; 
  391. switch ( $column_name ) { 
  392. case 'username': 
  393. $r .= "$avatar $edit"; 
  394. break; 
  395. case 'name': 
  396. $r .= "$user_object->first_name $user_object->last_name"; 
  397. break; 
  398. case 'email': 
  399. $r .= "<a href='" . esc_url( "mailto:$email" ) . "'>$email</a>"; 
  400. break; 
  401. case 'role': 
  402. $r .= esc_html( $roles_list ); 
  403. break; 
  404. case 'posts': 
  405. if ( $numposts > 0 ) { 
  406. $r .= "<a href='edit.php?author=$user_object->ID' class='edit'>"; 
  407. $r .= '<span aria-hidden="true">' . $numposts . '</span>'; 
  408. $r .= '<span class="screen-reader-text">' . sprintf( _n( '%s post by this author', '%s posts by this author', $numposts ), number_format_i18n( $numposts ) ) . '</span>'; 
  409. $r .= '</a>'; 
  410. } else { 
  411. $r .= 0; 
  412. break; 
  413. default: 
  414. /** 
  415. * Filters the display output of custom columns in the Users list table. 
  416. * @since 2.8.0 
  417. * @param string $output Custom column output. Default empty. 
  418. * @param string $column_name Column name. 
  419. * @param int $user_id ID of the currently-listed user. 
  420. */ 
  421. $r .= apply_filters( 'manage_users_custom_column', '', $column_name, $user_object->ID ); 
  422.  
  423. if ( $primary === $column_name ) { 
  424. $r .= $this->row_actions( $actions ); 
  425. $r .= "</td>"; 
  426. $r .= '</tr>'; 
  427.  
  428. return $r; 
  429.  
  430. /** 
  431. * Gets the name of the default primary column. 
  432. * @since 4.3.0 
  433. * @access protected 
  434. * @return string Name of the default primary column, in this case, 'username'. 
  435. */ 
  436. protected function get_default_primary_column_name() { 
  437. return 'username'; 
  438.  
  439. /** 
  440. * Returns an array of user roles for a given user object. 
  441. * @since 4.4.0 
  442. * @access protected 
  443. * @param WP_User $user_object The WP_User object. 
  444. * @return array An array of user roles. 
  445. */ 
  446. protected function get_role_list( $user_object ) { 
  447. $wp_roles = wp_roles(); 
  448.  
  449. $role_list = array(); 
  450.  
  451. foreach ( $user_object->roles as $role ) { 
  452. if ( isset( $wp_roles->role_names[ $role ] ) ) { 
  453. $role_list[ $role ] = translate_user_role( $wp_roles->role_names[ $role ] ); 
  454.  
  455. if ( empty( $role_list ) ) { 
  456. $role_list['none'] = _x( 'None', 'no user roles' ); 
  457.  
  458. /** 
  459. * Filters the returned array of roles for a user. 
  460. * @since 4.4.0 
  461. * @param array $role_list An array of user roles. 
  462. * @param WP_User $user_object A WP_User object. 
  463. */ 
  464. return apply_filters( 'get_role_list', $role_list, $user_object ); 
  465.