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