| 1 |
<?php |
| 2 |
/** |
| 3 |
* Handles the roles table on the Roles admin screen. |
| 4 |
* |
| 5 |
* @package Members |
| 6 |
* @subpackage Admin |
| 7 |
* @author The MemberPress Team |
| 8 |
* @copyright Copyright (c) 2009 - 2018, The MemberPress Team |
| 9 |
* @link https://members-plugin.com/ |
| 10 |
* @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html |
| 11 |
*/ |
| 12 |
namespace Members\Admin; |
| 13 |
|
| 14 |
defined('ABSPATH') || exit; |
| 15 |
/** |
| 16 |
* Role list table for the roles management page in the admin. Extends the core `WP_List_Table` |
| 17 |
* class in the admin. |
| 18 |
* |
| 19 |
* @since 2.0.0 |
| 20 |
* @access public |
| 21 |
*/ |
| 22 |
class Role_List_Table extends \WP_List_Table { |
| 23 |
|
| 24 |
/** |
| 25 |
* The current view. |
| 26 |
* |
| 27 |
* @since 2.0.0 |
| 28 |
* @access public |
| 29 |
* @var string |
| 30 |
*/ |
| 31 |
public $role_view = 'all'; |
| 32 |
|
| 33 |
/** |
| 34 |
* Array of role views. |
| 35 |
* |
| 36 |
* @since 2.0.0 |
| 37 |
* @access public |
| 38 |
* @var array |
| 39 |
*/ |
| 40 |
public $role_views = array(); |
| 41 |
|
| 42 |
/** |
| 43 |
* Allowed role views. |
| 44 |
* |
| 45 |
* @since 2.0.0 |
| 46 |
* @access public |
| 47 |
* @var array |
| 48 |
*/ |
| 49 |
public $allowed_role_views = array(); |
| 50 |
|
| 51 |
/** |
| 52 |
* The default role. This will be assigned the value of `get_option( 'default_role' )`. |
| 53 |
* |
| 54 |
* @since 2.0.0 |
| 55 |
* @access public |
| 56 |
* @var string |
| 57 |
*/ |
| 58 |
public $default_role = 'subscriber'; |
| 59 |
|
| 60 |
/** |
| 61 |
* The current user object. |
| 62 |
* |
| 63 |
* @since 2.0.0 |
| 64 |
* @access public |
| 65 |
* @var object |
| 66 |
*/ |
| 67 |
public $current_user = ''; |
| 68 |
|
| 69 |
/** |
| 70 |
* Sets up the list table. |
| 71 |
* |
| 72 |
* @since 2.0.0 |
| 73 |
* @access public |
| 74 |
* @return void |
| 75 |
*/ |
| 76 |
public function __construct() { |
| 77 |
|
| 78 |
$args = array( |
| 79 |
'plural' => 'roles', |
| 80 |
'singular' => 'role', |
| 81 |
); |
| 82 |
|
| 83 |
parent::__construct( $args ); |
| 84 |
|
| 85 |
// Get the current user object. |
| 86 |
$this->current_user = new \WP_User( get_current_user_id() ); |
| 87 |
|
| 88 |
// Get the defined default role. |
| 89 |
$this->default_role = get_option( 'default_role', $this->default_role ); |
| 90 |
|
| 91 |
// Get the role views. |
| 92 |
$this->allowed_role_views = array_keys( $this->get_views() ); |
| 93 |
|
| 94 |
// Get the current view. |
| 95 |
if ( isset( $_GET['view'] ) && in_array( $_GET['view'], $this->allowed_role_views ) ) |
| 96 |
$this->role_view = $_GET['view']; |
| 97 |
} |
| 98 |
|
| 99 |
/** |
| 100 |
* Sets up the items (roles) to list. |
| 101 |
* |
| 102 |
* @since 2.0.0 |
| 103 |
* @access public |
| 104 |
* @return void |
| 105 |
*/ |
| 106 |
public function prepare_items() { |
| 107 |
|
| 108 |
$roles = array(); |
| 109 |
|
| 110 |
// Get the roles for the view. |
| 111 |
if ( ! empty( $this->role_views[ $this->role_view ]['roles'] ) ) |
| 112 |
$roles = $this->role_views[ $this->role_view ]['roles']; |
| 113 |
|
| 114 |
// Allow devs to filter the items. |
| 115 |
$roles = apply_filters( 'members_manage_roles_items', $roles, $this->role_view ); |
| 116 |
|
| 117 |
// Sort the roles if given something to sort by. |
| 118 |
if ( isset( $_GET['orderby'] ) && isset( $_GET['order'] ) ) { |
| 119 |
|
| 120 |
// Sort by title/role name, descending. |
| 121 |
if ( 'title' === $_GET['orderby'] && 'desc' === $_GET['order'] ) |
| 122 |
arsort( $roles ); |
| 123 |
|
| 124 |
// Sort by role, ascending. |
| 125 |
elseif ( 'role' === $_GET['orderby'] && 'asc' === $_GET['order'] ) |
| 126 |
ksort( $roles ); |
| 127 |
|
| 128 |
// Sort by role, descending. |
| 129 |
elseif ( 'role' === $_GET['orderby'] && 'desc' === $_GET['order'] ) |
| 130 |
krsort( $roles ); |
| 131 |
|
| 132 |
// Sort by title/role name, ascending. |
| 133 |
else |
| 134 |
asort( $roles ); |
| 135 |
|
| 136 |
// Sort by title/role name, ascending. |
| 137 |
} else { |
| 138 |
asort( $roles ); |
| 139 |
} |
| 140 |
|
| 141 |
// Get the per page option name. |
| 142 |
$option = $this->screen->get_option( 'per_page', 'option' ); |
| 143 |
|
| 144 |
if ( ! $option ) |
| 145 |
$option = str_replace( '-', '_', "{$this->screen->id}_per_page" ); |
| 146 |
|
| 147 |
// Get the number of roles to show per page. |
| 148 |
$per_page = (int) get_user_option( $option ); |
| 149 |
|
| 150 |
if ( ! $per_page || $per_page < 1 ) { |
| 151 |
|
| 152 |
$per_page = $this->screen->get_option( 'per_page', 'default' ); |
| 153 |
|
| 154 |
if ( ! $per_page ) |
| 155 |
$per_page = 20; |
| 156 |
} |
| 157 |
|
| 158 |
// Set up some current page variables. |
| 159 |
$current_page = $this->get_pagenum(); |
| 160 |
$items = $roles; |
| 161 |
$total_count = count( $items ); |
| 162 |
|
| 163 |
// Set the current page items. |
| 164 |
$this->items = array_slice( $items, ( $current_page - 1 ) * $per_page, $per_page ); |
| 165 |
|
| 166 |
// Set the pagination arguments. |
| 167 |
$this->set_pagination_args( array( 'total_items' => $total_count, 'per_page' => $per_page ) ); |
| 168 |
} |
| 169 |
|
| 170 |
/** |
| 171 |
* Returns an array of columns to show. |
| 172 |
* |
| 173 |
* @see members_manage_roles_columns() |
| 174 |
* @since 2.0.0 |
| 175 |
* @access public |
| 176 |
* @return array |
| 177 |
*/ |
| 178 |
public function get_columns() { |
| 179 |
return get_column_headers( $this->screen ); |
| 180 |
} |
| 181 |
|
| 182 |
/** |
| 183 |
* Returns the default column output. By default, this will return an empty string. The |
| 184 |
* purpose of the method is to provide plugin authors a hook to return content for |
| 185 |
* custom columns: `members_manage_roles_column_{$column_name}`. |
| 186 |
* |
| 187 |
* @since 1.1.0 |
| 188 |
* @access protected |
| 189 |
* @param string $role |
| 190 |
* @param string $column_name |
| 191 |
* @return string |
| 192 |
*/ |
| 193 |
protected function column_default( $role, $column_name ) { |
| 194 |
|
| 195 |
return apply_filters( "members_manage_roles_column_{$column_name}", '', $role ); |
| 196 |
} |
| 197 |
|
| 198 |
/** |
| 199 |
* The checkbox column callback. |
| 200 |
* |
| 201 |
* @since 2.0.0 |
| 202 |
* @access protected |
| 203 |
* @param string $role |
| 204 |
* @return string |
| 205 |
*/ |
| 206 |
protected function column_cb( $role ) { |
| 207 |
|
| 208 |
if ( $role == get_option( 'default_role' ) ) { |
| 209 |
$out = sprintf( '<input type="checkbox" disabled="disabled" title="%s" />', esc_attr__( 'The default role cannot be selected for bulk actions.', 'members' ) ); |
| 210 |
} elseif ( in_array( $role, $this->current_user->roles ) ) { |
| 211 |
$out = sprintf( '<input type="checkbox" disabled="disabled" title="%s" />', esc_attr__( 'Your own role cannot be selected for bulk actions.', 'members' ) ); |
| 212 |
} elseif ( ! members_is_role_editable( $role ) ) { |
| 213 |
$out = sprintf( '<input type="checkbox" disabled="disabled" title="%s" />', esc_attr__( 'This role is not editable.', 'members' ) ); |
| 214 |
} else { |
| 215 |
$out = sprintf( '<input type="checkbox" name="roles[%1$s]" value="%1$s" />', esc_attr( $role ) ); |
| 216 |
} |
| 217 |
|
| 218 |
return apply_filters( 'members_manage_roles_column_cb', $out, $role ); |
| 219 |
} |
| 220 |
|
| 221 |
/** |
| 222 |
* The role name column callback. |
| 223 |
* |
| 224 |
* @since 2.0.0 |
| 225 |
* @access protected |
| 226 |
* @param string $role |
| 227 |
* @return string |
| 228 |
*/ |
| 229 |
protected function column_title( $role ) { |
| 230 |
|
| 231 |
$states = array(); |
| 232 |
$role_states = ''; |
| 233 |
|
| 234 |
// If the role is the default role. |
| 235 |
if ( $role == get_option( 'default_role' ) ) |
| 236 |
$states['default'] = esc_html__( 'Default Role', 'members' ); |
| 237 |
|
| 238 |
// If the current user has this role. |
| 239 |
if ( members_current_user_has_role( $role ) ) |
| 240 |
$states['mine'] = esc_html__( 'Your Role', 'members' ); |
| 241 |
|
| 242 |
// Allow devs to filter the role states. |
| 243 |
$states = apply_filters( 'members_role_states', $states, $role ); |
| 244 |
|
| 245 |
// If we have states, string them together. |
| 246 |
if ( ! empty( $states ) ) { |
| 247 |
|
| 248 |
foreach ( $states as $state => $label ) |
| 249 |
$states[ $state ] = sprintf( '<span class="role-state">%s</span>', $label ); |
| 250 |
|
| 251 |
$role_states = ' – ' . join( ', ', $states ); |
| 252 |
} |
| 253 |
|
| 254 |
// Add the title and role states. |
| 255 |
if ( current_user_can( 'edit_roles' ) ) |
| 256 |
$title = sprintf( '<strong><a class="row-title" href="%s">%s</a>%s</strong>', esc_url( members_get_edit_role_url( $role ) ), esc_html( members_get_role( $role )->get( 'label' ) ), $role_states ); |
| 257 |
|
| 258 |
else |
| 259 |
$title = sprintf( '<strong><span class="row-title">%s</span>%s</strong>', esc_html( members_get_role( $role )->get( 'label' ) ), $role_states ); |
| 260 |
|
| 261 |
return apply_filters( 'members_manage_roles_column_role_name', $title, $role ); |
| 262 |
} |
| 263 |
|
| 264 |
/** |
| 265 |
* The role column callback. |
| 266 |
* |
| 267 |
* @since 2.0.0 |
| 268 |
* @access protected |
| 269 |
* @param string $role |
| 270 |
* @return string |
| 271 |
*/ |
| 272 |
protected function column_role( $role ) { |
| 273 |
return apply_filters( 'members_manage_roles_column_role', members_sanitize_role( $role ), $role ); |
| 274 |
} |
| 275 |
|
| 276 |
/** |
| 277 |
* The users column callback. |
| 278 |
* |
| 279 |
* @since 2.0.0 |
| 280 |
* @access protected |
| 281 |
* @param string $role |
| 282 |
* @return string |
| 283 |
*/ |
| 284 |
protected function column_users( $role ) { |
| 285 |
|
| 286 |
$user_count = members_get_role_user_count( $role ); |
| 287 |
|
| 288 |
$output = number_format_i18n( $user_count ); |
| 289 |
|
| 290 |
if ( 0 < absint( $user_count ) && current_user_can( 'list_users' ) ) { |
| 291 |
|
| 292 |
$output = sprintf( |
| 293 |
'<a href="%s">%s</a>', |
| 294 |
esc_url( add_query_arg( 'role', $role, admin_url( 'users.php' ) ) ), |
| 295 |
$output |
| 296 |
); |
| 297 |
} |
| 298 |
|
| 299 |
return apply_filters( 'members_manage_roles_column_users', $output, $role ); |
| 300 |
} |
| 301 |
|
| 302 |
/** |
| 303 |
* The caps column callback. |
| 304 |
* |
| 305 |
* @since 2.0.0 |
| 306 |
* @access protected |
| 307 |
* @param string $role |
| 308 |
* @return string |
| 309 |
*/ |
| 310 |
protected function column_granted_caps( $role ) { |
| 311 |
return apply_filters( 'members_manage_roles_column_granted_caps', members_get_role_granted_cap_count( $role ), $role ); |
| 312 |
} |
| 313 |
|
| 314 |
/** |
| 315 |
* The caps column callback. |
| 316 |
* |
| 317 |
* @since 2.0.0 |
| 318 |
* @access protected |
| 319 |
* @param string $role |
| 320 |
* @return string |
| 321 |
*/ |
| 322 |
protected function column_denied_caps( $role ) { |
| 323 |
return apply_filters( 'members_manage_roles_column_denied_caps', members_get_role_denied_cap_count( $role ), $role ); |
| 324 |
} |
| 325 |
|
| 326 |
/** |
| 327 |
* Returns the name of the primary column. |
| 328 |
* |
| 329 |
* @since 2.0.0 |
| 330 |
* @access protected |
| 331 |
* @return string |
| 332 |
*/ |
| 333 |
protected function get_default_primary_column_name() { |
| 334 |
return 'title'; |
| 335 |
} |
| 336 |
|
| 337 |
/** |
| 338 |
* Handles the row actions. |
| 339 |
* |
| 340 |
* @since 2.0.0 |
| 341 |
* @access protected |
| 342 |
* @param string $role |
| 343 |
* @param string $column_name |
| 344 |
* @param string $primary |
| 345 |
* @return array |
| 346 |
*/ |
| 347 |
protected function handle_row_actions( $role, $column_name, $primary ) { |
| 348 |
|
| 349 |
$actions = array(); |
| 350 |
|
| 351 |
// Only add row actions on the primary column (title/role name). |
| 352 |
if ( $primary === $column_name ) { |
| 353 |
|
| 354 |
// If the role can be edited. |
| 355 |
if ( members_is_role_editable( $role ) ) { |
| 356 |
|
| 357 |
// If the current user can edit the role, add an edit link. |
| 358 |
if ( current_user_can( 'edit_roles' ) ) |
| 359 |
$actions['edit'] = sprintf( '<a href="%s">%s</a>', esc_url( members_get_edit_role_url( $role ) ), esc_html__( 'Edit', 'members' ) ); |
| 360 |
|
| 361 |
// If the current user can delete the role, add a delete link. |
| 362 |
if ( ( is_multisite() && is_super_admin() && $role !== $this->default_role ) || ( current_user_can( 'delete_roles' ) && $role !== $this->default_role && ! current_user_can( $role ) ) ) |
| 363 |
$actions['delete'] = sprintf( '<a class="members-delete-role-link" href="%s">%s</a>', esc_url( members_get_delete_role_url( $role ) ), esc_html__( 'Delete', 'members' ) ); |
| 364 |
|
| 365 |
// If the role cannot be edited. |
| 366 |
} elseif ( current_user_can( 'edit_roles' ) ) { |
| 367 |
|
| 368 |
// Add the view role link. |
| 369 |
$actions['view'] = sprintf( '<a href="%s">%s</a>', esc_url( members_get_edit_role_url( $role ) ), esc_html__( 'View', 'members' ) ); |
| 370 |
} |
| 371 |
|
| 372 |
// If the current user can create roles, add the clone role link. |
| 373 |
if ( current_user_can( 'create_roles' ) ) |
| 374 |
$actions['clone'] = sprintf( '<a href="%s">%s</a>', esc_url( members_get_clone_role_url( $role ) ), esc_html__( 'Clone', 'members' ) ); |
| 375 |
|
| 376 |
// If this is the default role and the current user can manage options, add a default role change link. |
| 377 |
if ( current_user_can( 'manage_options' ) && $role === $this->default_role ) |
| 378 |
$actions['default_role'] = sprintf( '<a href="%s">%s</a>', esc_url( admin_url( 'options-general.php#default_role' ) ), esc_html__( 'Change Default', 'members' ) ); |
| 379 |
|
| 380 |
// If the currrent user can view users, add a users link. |
| 381 |
if ( current_user_can( 'list_users' ) ) |
| 382 |
$actions['users'] = sprintf( '<a href="%s">%s</a>', members_get_role_users_url( $role ), esc_html__( 'Users', 'members' ) ); |
| 383 |
|
| 384 |
// Allow devs to filter the row actions. |
| 385 |
$actions = apply_filters( 'members_roles_row_actions', $actions, $role ); |
| 386 |
} |
| 387 |
|
| 388 |
return $this->row_actions( $actions ); |
| 389 |
} |
| 390 |
|
| 391 |
/** |
| 392 |
* Returns an array of sortable columns. |
| 393 |
* |
| 394 |
* @since 2.0.0 |
| 395 |
* @access protected |
| 396 |
* @return array |
| 397 |
*/ |
| 398 |
protected function get_sortable_columns() { |
| 399 |
|
| 400 |
return array( |
| 401 |
'title' => array( 'title', true ), |
| 402 |
'role' => array( 'role', false ), |
| 403 |
); |
| 404 |
} |
| 405 |
|
| 406 |
/** |
| 407 |
* Returns an array of views for the list table. |
| 408 |
* |
| 409 |
* @since 2.0.0 |
| 410 |
* @access protected |
| 411 |
* @return array |
| 412 |
*/ |
| 413 |
protected function get_views() { |
| 414 |
|
| 415 |
// Get the current user. |
| 416 |
$current_user = wp_get_current_user(); |
| 417 |
|
| 418 |
$views = array(); |
| 419 |
$current = ' class="current"'; |
| 420 |
|
| 421 |
$this->role_views['all'] = array( |
| 422 |
'label_count' => _n_noop( 'All %s', 'All %s', 'members' ), |
| 423 |
'roles' => array_keys( members_get_roles() ) |
| 424 |
); |
| 425 |
|
| 426 |
$this->role_views['mine'] = array( |
| 427 |
'label_count' => _n_noop( 'Mine %s', 'Mine %s', 'members' ), |
| 428 |
'roles' => $current_user->roles |
| 429 |
); |
| 430 |
|
| 431 |
$this->role_views['active'] = array( |
| 432 |
'label_count' => _n_noop( 'Has Users %s', 'Has Users %s', 'members' ), |
| 433 |
'roles' => members_get_active_roles() |
| 434 |
); |
| 435 |
|
| 436 |
$this->role_views['inactive'] = array( |
| 437 |
'label_count' => _n_noop( 'No Users %s', 'No Users %s', 'members' ), |
| 438 |
'roles' =>members_get_inactive_roles() |
| 439 |
); |
| 440 |
|
| 441 |
$this->role_views['editable'] = array( |
| 442 |
'label_count' => _n_noop( 'Editable %s', 'Editable %s', 'members' ), |
| 443 |
'roles' => members_get_editable_roles() |
| 444 |
); |
| 445 |
|
| 446 |
$this->role_views['uneditable'] = array( |
| 447 |
'label_count' => _n_noop( 'Uneditable %s', 'Uneditable %s', 'members' ), |
| 448 |
'roles' => members_get_uneditable_roles() |
| 449 |
); |
| 450 |
|
| 451 |
// Loop through the role groups and put them into the view list. |
| 452 |
foreach ( members_get_role_groups() as $group ) { |
| 453 |
|
| 454 |
// Skip role groups that shouldn't be shown in the view list. |
| 455 |
if ( ! $group->show_in_view_list ) |
| 456 |
continue; |
| 457 |
|
| 458 |
$this->role_views[ "group-{$group->name}" ] = array( |
| 459 |
'label_count' => $group->label_count, |
| 460 |
'roles' => $group->roles |
| 461 |
); |
| 462 |
} |
| 463 |
|
| 464 |
// Loop through the default views and put them into the view list. |
| 465 |
foreach ( $this->role_views as $view => $args ) { |
| 466 |
|
| 467 |
$count = count( $args['roles'] ); |
| 468 |
|
| 469 |
// Skip any views with 0 roles. |
| 470 |
if ( 0 >= $count ) |
| 471 |
continue; |
| 472 |
|
| 473 |
$noop = $args['label_count']; |
| 474 |
|
| 475 |
// Add the view link. |
| 476 |
$views[ $view ] = sprintf( |
| 477 |
'<a%s href="%s">%s</a>', |
| 478 |
$view === $this->role_view ? $current : '', |
| 479 |
'all' === $view ? esc_url( members_get_edit_roles_url() ) : esc_url( members_get_role_view_url( $view ) ), |
| 480 |
sprintf( translate_nooped_plural( $noop, $count, $noop['domain'] ), sprintf( '<span class="count">(%s)</span>', number_format_i18n( $count ) ) ) |
| 481 |
); |
| 482 |
} |
| 483 |
|
| 484 |
return apply_filters( 'members_manage_roles_views', $views, $this->role_view, members_get_edit_roles_url() ); |
| 485 |
} |
| 486 |
|
| 487 |
/** |
| 488 |
* Displays the list table. |
| 489 |
* |
| 490 |
* @since 2.0.0 |
| 491 |
* @access public |
| 492 |
* @return void |
| 493 |
*/ |
| 494 |
public function display() { |
| 495 |
|
| 496 |
$this->views(); |
| 497 |
|
| 498 |
parent::display(); |
| 499 |
} |
| 500 |
|
| 501 |
/** |
| 502 |
* Returns an array of bulk actions available. |
| 503 |
* |
| 504 |
* @since 2.0.0 |
| 505 |
* @access protected |
| 506 |
* @return array |
| 507 |
*/ |
| 508 |
protected function get_bulk_actions() { |
| 509 |
$actions = array(); |
| 510 |
|
| 511 |
if ( current_user_can( 'delete_roles' ) ) |
| 512 |
$actions['delete'] = esc_html__( 'Delete', 'members' ); |
| 513 |
|
| 514 |
if ( current_user_can( 'list_roles' ) ) |
| 515 |
$actions['export'] = esc_html__( 'Export', 'members' ); |
| 516 |
|
| 517 |
return apply_filters( 'members_manage_roles_bulk_actions', $actions ); |
| 518 |
} |
| 519 |
} |
| 520 |
|