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