Changeset 10521 for trunk/src/bp-members/bp-members-admin.php
- Timestamp:
- 02/05/2016 05:15:55 AM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/bp-members/bp-members-admin.php
r10461 r10521 11 11 defined( 'ABSPATH' ) || exit; 12 12 13 if ( !class_exists( 'BP_Members_Admin' ) ) : 14 15 /** 16 * Load Members admin area. 17 * 18 * @since 2.0.0 19 */ 20 class BP_Members_Admin { 21 22 /** Directory *************************************************************/ 23 24 /** 25 * Path to the BP Members Admin directory. 26 * 27 * @var string $admin_dir 28 */ 29 public $admin_dir = ''; 30 31 /** URLs ******************************************************************/ 32 33 /** 34 * URL to the BP Members Admin directory. 35 * 36 * @var string $admin_url 37 */ 38 public $admin_url = ''; 39 40 /** 41 * URL to the BP Members Admin CSS directory. 42 * 43 * @var string $css_url 44 */ 45 public $css_url = ''; 46 47 /** 48 * URL to the BP Members Admin JS directory. 49 * 50 * @var string 51 */ 52 public $js_url = ''; 53 54 /** Other *****************************************************************/ 55 56 /** 57 * Screen id for edit user's profile page. 58 * 59 * @var string 60 */ 61 public $user_page = ''; 62 63 /** 64 * Setup BP Members Admin. 65 * 66 * @since 2.0.0 67 * 68 * @uses buddypress() to get BuddyPress main instance. 69 */ 70 public static function register_members_admin() { 71 if ( ! is_admin() ) { 72 return; 73 } 74 75 $bp = buddypress(); 76 77 if ( empty( $bp->members->admin ) ) { 78 $bp->members->admin = new self; 79 } 80 81 return $bp->members->admin; 82 } 83 84 /** 85 * Constructor method. 86 * 87 * @since 2.0.0 88 */ 89 public function __construct() { 90 $this->setup_globals(); 91 $this->setup_actions(); 92 } 93 94 /** 95 * Set admin-related globals. 96 * 97 * @since 2.0.0 98 */ 99 private function setup_globals() { 100 $bp = buddypress(); 101 102 // Paths and URLs 103 $this->admin_dir = trailingslashit( $bp->plugin_dir . 'bp-members/admin' ); // Admin path. 104 $this->admin_url = trailingslashit( $bp->plugin_url . 'bp-members/admin' ); // Admin URL. 105 $this->css_url = trailingslashit( $this->admin_url . 'css' ); // Admin CSS URL. 106 $this->js_url = trailingslashit( $this->admin_url . 'js' ); // Admin CSS URL. 107 108 // Capability depends on config. 109 $this->capability = bp_core_do_network_admin() ? 'manage_network_users' : 'edit_users'; 110 111 // The Edit Profile Screen id. 112 $this->user_page = ''; 113 114 // The Show Profile Screen id. 115 $this->user_profile = is_network_admin() ? 'users' : 'profile'; 116 117 // The current user id. 118 $this->current_user_id = get_current_user_id(); 119 120 // The user id being edited. 121 $this->user_id = 0; 122 123 // Is a member editing their own profile. 124 $this->is_self_profile = false; 125 126 // The screen ids to load specific css for. 127 $this->screen_id = array(); 128 129 // The stats metabox default position. 130 $this->stats_metabox = new StdClass(); 131 132 // BuddyPress edit user's profile args. 133 $this->edit_profile_args = array( 'page' => 'bp-profile-edit' ); 134 $this->edit_profile_url = ''; 135 $this->edit_url = ''; 136 137 // Data specific to signups. 138 $this->users_page = ''; 139 $this->signups_page = ''; 140 $this->users_url = bp_get_admin_url( 'users.php' ); 141 $this->users_screen = bp_core_do_network_admin() ? 'users-network' : 'users'; 142 143 // Specific config: BuddyPress is not network activated. 144 $this->subsite_activated = (bool) is_multisite() && ! bp_is_network_activated(); 145 146 // When BuddyPress is not network activated, only Super Admin can moderate signups. 147 if ( ! empty( $this->subsite_activated ) ) { 148 $this->capability = 'manage_network_users'; 149 } 150 } 151 152 /** 153 * Set admin-related actions and filters. 154 * 155 * @since 2.0.0 156 */ 157 private function setup_actions() { 158 159 /** Extended Profile ************************************************* 160 */ 161 162 // Enqueue all admin JS and CSS. 163 add_action( 'bp_admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); 164 165 // Add some page specific output to the <head>. 166 add_action( 'bp_admin_head', array( $this, 'admin_head' ), 999 ); 167 168 // Add menu item to all users menu. 169 add_action( 'admin_menu', array( $this, 'admin_menus' ), 5 ); 170 add_action( 'network_admin_menu', array( $this, 'admin_menus' ), 5 ); 171 add_action( 'user_admin_menu', array( $this, 'user_profile_menu' ), 5 ); 172 173 // Create the Profile Navigation (Profile/Extended Profile). 174 add_action( 'edit_user_profile', array( $this, 'profile_nav' ), 99, 1 ); 175 add_action( 'show_user_profile', array( $this, 'profile_nav' ), 99, 1 ); 176 177 // Editing users of a specific site. 178 add_action( "admin_head-site-users.php", array( $this, 'profile_admin_head' ) ); 179 180 // Add a row action to users listing. 181 if ( bp_core_do_network_admin() ) { 182 add_filter( 'ms_user_row_actions', array( $this, 'row_actions' ), 10, 2 ); 183 add_action( 'admin_init', array( $this, 'add_edit_profile_url_filter' ) ); 184 add_action( 'wp_after_admin_bar_render', array( $this, 'remove_edit_profile_url_filter' ) ); 185 } 186 187 // Add user row actions for single site. 188 add_filter( 'user_row_actions', array( $this, 'row_actions' ), 10, 2 ); 189 190 // Process changes to member type. 191 add_action( 'bp_members_admin_load', array( $this, 'process_member_type_update' ) ); 192 193 /** Signups ********************************************************** 194 */ 195 196 if ( is_admin() ) { 197 198 // Filter non multisite user query to remove sign-up users. 199 if ( ! is_multisite() ) { 200 add_action( 'pre_user_query', array( $this, 'remove_signups_from_user_query' ), 10, 1 ); 201 } 202 203 // Reorganise the views navigation in users.php and signups page. 204 if ( current_user_can( $this->capability ) ) { 205 $user_screen = $this->users_screen; 206 207 /** 208 * Users screen on multiblog is users, but signups 209 * need to be managed in the network for this case 210 */ 211 if ( bp_is_network_activated() && bp_is_multiblog_mode() && false === strpos( $user_screen, '-network' ) ) { 212 $user_screen .= '-network'; 213 } 214 215 add_filter( "views_{$user_screen}", array( $this, 'signup_filter_view' ), 10, 1 ); 216 add_filter( 'set-screen-option', array( $this, 'signup_screen_options' ), 10, 3 ); 217 } 218 } 219 } 220 221 /** 222 * Get the user ID. 223 * 224 * Look for $_GET['user_id']. If anything else, force the user ID to the 225 * current user's ID so they aren't left without a user to edit. 226 * 227 * @since 2.1.0 228 * 229 * @return int 230 */ 231 private function get_user_id() { 232 if ( ! empty( $this->user_id ) ) { 233 return $this->user_id; 234 } 235 236 $this->user_id = (int) get_current_user_id(); 237 238 // We'll need a user ID when not on self profile. 239 if ( ! empty( $_GET['user_id'] ) ) { 240 $this->user_id = (int) $_GET['user_id']; 241 } 242 243 return $this->user_id; 244 } 245 246 /** 247 * Can the current user edit the one displayed. 248 * 249 * Self profile editing / or bp_moderate check. 250 * This might be replaced by more granular capabilities 251 * in the future. 252 * 253 * @since 2.1.0 254 * 255 * @param int $user_id ID of the user being checked for edit ability. 256 * 257 * @return bool 258 */ 259 private function member_can_edit( $user_id = 0 ) { 260 $retval = false; 261 262 // Bail if no user ID was passed. 263 if ( empty( $user_id ) ) { 264 return $retval; 265 } 266 267 // Member can edit if they are viewing their own profile. 268 if ( $this->current_user_id === $user_id ) { 269 $retval = true; 270 271 // Trust the 'bp_moderate' capability. 272 } else { 273 $retval = bp_current_user_can( 'bp_moderate' ); 274 } 275 276 return $retval; 277 } 278 279 /** 280 * Get admin notice when saving a user or member profile. 281 * 282 * @since 2.1.0 283 * 284 * @return array 285 */ 286 private function get_user_notice() { 287 288 // Setup empty notice for return value. 289 $notice = array(); 290 291 // Updates. 292 if ( ! empty( $_REQUEST['updated'] ) ) { 293 switch ( $_REQUEST['updated'] ) { 294 case 'avatar': 295 $notice = array( 296 'class' => 'updated', 297 'message' => __( 'Profile photo was deleted.', 'buddypress' ) 298 ); 299 break; 300 case 'ham' : 301 $notice = array( 302 'class' => 'updated', 303 'message' => __( 'User removed as spammer.', 'buddypress' ) 304 ); 305 break; 306 case 'spam' : 307 $notice = array( 308 'class' => 'updated', 309 'message' => __( 'User marked as spammer. Spam users are visible only to site admins.', 'buddypress' ) 310 ); 311 break; 312 case 1 : 313 $notice = array( 314 'class' => 'updated', 315 'message' => __( 'Profile updated.', 'buddypress' ) 316 ); 317 break; 318 } 319 } 320 321 // Errors. 322 if ( ! empty( $_REQUEST['error'] ) ) { 323 switch ( $_REQUEST['error'] ) { 324 case 'avatar': 325 $notice = array( 326 'class' => 'error', 327 'message' => __( 'There was a problem deleting that profile photo. Please try again.', 'buddypress' ) 328 ); 329 break; 330 case 'ham' : 331 $notice = array( 332 'class' => 'error', 333 'message' => __( 'User could not be removed as spammer.', 'buddypress' ) 334 ); 335 break; 336 case 'spam' : 337 $notice = array( 338 'class' => 'error', 339 'message' => __( 'User could not be marked as spammer.', 'buddypress' ) 340 ); 341 break; 342 case 1 : 343 $notice = array( 344 'class' => 'error', 345 'message' => __( 'An error occurred while trying to update the profile.', 'buddypress' ) 346 ); 347 break; 348 case 2: 349 $notice = array( 350 'class' => 'error', 351 'message' => __( 'Please make sure you fill in all required fields in this profile field group before saving.', 'buddypress' ) 352 ); 353 break; 354 case 3: 355 $notice = array( 356 'class' => 'error', 357 'message' => __( 'There was a problem updating some of your profile information. Please try again.', 'buddypress' ) 358 ); 359 break; 360 } 361 } 362 363 return $notice; 364 } 365 366 /** 367 * Create the /user/ admin Profile submenus for all members. 368 * 369 * @since 2.1.0 370 * 371 * @uses add_submenu_page() To add the Edit Profile page in Profile section. 372 */ 373 public function user_profile_menu() { 374 375 // Setup the hooks array. 376 $hooks = array(); 377 378 // Add the faux "Edit Profile" submenu page. 379 $hooks['user'] = $this->user_page = add_submenu_page( 380 'profile.php', 381 __( 'Edit Profile', 'buddypress' ), 382 __( 'Edit Profile', 'buddypress' ), 383 'exist', 384 'bp-profile-edit', 385 array( $this, 'user_admin' ) 386 ); 387 388 // Setup the screen ID's. 389 $this->screen_id = array( 390 $this->user_page . '-user', 391 $this->user_profile . '-user' 392 ); 393 394 // Loop through new hooks and add method actions. 395 foreach ( $hooks as $key => $hook ) { 396 add_action( "load-{$hook}", array( $this, $key . '_admin_load' ) ); 397 } 398 399 // Add the profile_admin_head method to proper admin_head actions. 400 add_action( "admin_head-{$this->user_page}", array( $this, 'profile_admin_head' ) ); 401 add_action( "admin_head-profile.php", array( $this, 'profile_admin_head' ) ); 402 } 403 404 /** 405 * Create the All Users / Profile > Edit Profile and All Users Signups submenus. 406 * 407 * @since 2.0.0 408 * 409 * @uses add_submenu_page() To add the Edit Profile page in Users/Profile section. 410 */ 411 public function admin_menus() { 412 413 // Setup the hooks array. 414 $hooks = array(); 415 416 // Manage user's profile. 417 $hooks['user'] = $this->user_page = add_submenu_page( 418 $this->user_profile . '.php', 419 __( 'Edit Profile', 'buddypress' ), 420 __( 'Edit Profile', 'buddypress' ), 421 'read', 422 'bp-profile-edit', 423 array( $this, 'user_admin' ) 424 ); 425 426 // Only show sign-ups where they belong. 427 if ( ( ! bp_is_network_activated() && ! is_network_admin() ) || ( is_network_admin() && bp_is_network_activated() ) ) { 428 429 // Manage signups. 430 $hooks['signups'] = $this->signups_page = add_users_page( 431 __( 'Manage Signups', 'buddypress' ), 432 __( 'Manage Signups', 'buddypress' ), 433 $this->capability, 434 'bp-signups', 435 array( $this, 'signups_admin' ) 436 ); 437 } 438 439 $edit_page = 'user-edit'; 440 $profile_page = 'profile'; 441 $this->users_page = 'users'; 442 443 // Self profile check is needed for this pages. 444 $page_head = array( 445 $edit_page . '.php', 446 $profile_page . '.php', 447 $this->user_page, 448 $this->users_page . '.php', 449 ); 450 451 // Append '-network' to each array item if in network admin. 452 if ( is_network_admin() ) { 453 $edit_page .= '-network'; 454 $profile_page .= '-network'; 455 $this->user_page .= '-network'; 456 $this->users_page .= '-network'; 457 $this->signups_page .= '-network'; 458 } 459 460 // Setup the screen ID's. 461 $this->screen_id = array( 462 $edit_page, 463 $this->user_page, 464 $profile_page 465 ); 466 467 // Loop through new hooks and add method actions. 468 foreach ( $hooks as $key => $hook ) { 469 add_action( "load-{$hook}", array( $this, $key . '_admin_load' ) ); 470 } 471 472 // Add the profile_admin_head method to proper admin_head actions. 473 foreach ( $page_head as $head ) { 474 add_action( "admin_head-{$head}", array( $this, 'profile_admin_head' ) ); 475 } 476 } 477 478 /** 479 * Highlight the Users menu if on Edit Profile and check if on the user's admin profile. 480 * 481 * @since 2.1.0 482 */ 483 public function profile_admin_head() { 484 global $submenu_file, $parent_file; 485 486 // Is the user editing their own profile? 487 if ( is_user_admin() || ( defined( 'IS_PROFILE_PAGE' ) && IS_PROFILE_PAGE ) ) { 488 $this->is_self_profile = true; 489 490 // Is the user attempting to edit their own profile. 491 } elseif ( isset( $_GET['user_id' ] ) || ( isset( $_GET['page'] ) && ( 'bp-profile-edit' === $_GET['page'] ) ) ) { 492 $this->is_self_profile = (bool) ( $this->get_user_id() === $this->current_user_id ); 493 } 494 495 // Force the parent file to users.php to open the correct top level menu 496 // but only if not editing a site via the network site editing page. 497 if ( 'sites.php' !== $parent_file ) { 498 $parent_file = 'users.php'; 499 $submenu_file = 'users.php'; 500 } 501 502 // Editing your own profile, so recheck some vars. 503 if ( true === $this->is_self_profile ) { 504 505 // Use profile.php as the edit page. 506 $edit_page = 'profile.php'; 507 508 // Set profile.php as the parent & sub files to correct the menu nav. 509 if ( is_blog_admin() || is_user_admin() ) { 510 $parent_file = 'profile.php'; 511 $submenu_file = 'profile.php'; 512 } 513 514 // Not editing yourself, so use user-edit.php. 515 } else { 516 $edit_page = 'user-edit.php'; 517 } 518 519 if ( is_user_admin() ) { 520 $this->edit_profile_url = add_query_arg( $this->edit_profile_args, user_admin_url( 'profile.php' ) ); 521 $this->edit_url = user_admin_url( 'profile.php' ); 522 523 } elseif ( is_blog_admin() ) { 524 $this->edit_profile_url = add_query_arg( $this->edit_profile_args, admin_url( 'users.php' ) ); 525 $this->edit_url = admin_url( $edit_page ); 526 527 } elseif ( is_network_admin() ) { 528 $this->edit_profile_url = add_query_arg( $this->edit_profile_args, network_admin_url( 'users.php' ) ); 529 $this->edit_url = network_admin_url( $edit_page ); 530 } 531 } 532 533 /** 534 * Remove the Edit Profile page. 535 * 536 * We add these pages in order to integrate with WP's Users panel, but 537 * we want them to show up as a row action of the WP panel, not as separate 538 * subnav items under the Users menu. 539 * 540 * @since 2.0.0 541 */ 542 public function admin_head() { 543 remove_submenu_page( 'users.php', 'bp-profile-edit' ); 544 remove_submenu_page( 'profile.php', 'bp-profile-edit' ); 545 } 546 547 /** Community Profile *****************************************************/ 548 549 /** 550 * Add some specific styling to the Edit User and Edit User's Profile page. 551 * 552 * @since 2.0.0 553 */ 554 public function enqueue_scripts() { 555 if ( ! in_array( get_current_screen()->id, $this->screen_id ) ) { 556 return; 557 } 558 559 $min = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; 560 $css = $this->css_url . "admin{$min}.css"; 561 562 /** 563 * Filters the CSS URL to enqueue in the Members admin area. 564 * 565 * @since 2.0.0 566 * 567 * @param string $css URL to the CSS admin file to load. 568 */ 569 $css = apply_filters( 'bp_members_admin_css', $css ); 570 571 wp_enqueue_style( 'bp-members-css', $css, array(), bp_get_version() ); 572 573 wp_style_add_data( 'bp-members-css', 'rtl', true ); 574 if ( $min ) { 575 wp_style_add_data( 'bp-members-css', 'suffix', $min ); 576 } 577 578 // Only load JavaScript for BuddyPress profile. 579 if ( get_current_screen()->id == $this->user_page ) { 580 $js = $this->js_url . "admin{$min}.js"; 581 582 /** 583 * Filters the JS URL to enqueue in the Members admin area. 584 * 585 * @since 2.0.0 586 * 587 * @param string $js URL to the JavaScript admin file to load. 588 */ 589 $js = apply_filters( 'bp_members_admin_js', $js ); 590 wp_enqueue_script( 'bp-members-js', $js, array( 'jquery' ), bp_get_version(), true ); 591 } 592 593 /** 594 * Fires after all of the members JavaScript and CSS are enqueued. 595 * 596 * @since 2.0.0 597 * 598 * @param string $id ID of the current screen. 599 * @param array $screen_id Array of allowed screens to add scripts and styles to. 600 */ 601 do_action( 'bp_members_admin_enqueue_scripts', get_current_screen()->id, $this->screen_id ); 602 } 603 604 /** 605 * Create the Profile navigation in Edit User & Edit Profile pages. 606 * 607 * @since 2.0.0 608 * 609 * @param object|null $user User to create profile navigation for. 610 * @param string $active Which profile to highlight. 611 * @return string 612 */ 613 public function profile_nav( $user = null, $active = 'WordPress' ) { 614 615 // Bail if no user ID exists here. 616 if ( empty( $user->ID ) ) { 617 return; 618 } 619 620 // Add the user ID to query arguments when not editing yourself. 621 if ( false === $this->is_self_profile ) { 622 $query_args = array( 'user_id' => $user->ID ); 623 } else { 624 $query_args = array(); 625 } 626 627 // Conditionally add a referer if it exists in the existing request. 628 if ( ! empty( $_REQUEST['wp_http_referer'] ) ) { 629 $query_args['wp_http_referer'] = urlencode( stripslashes_deep( $_REQUEST['wp_http_referer'] ) ); 630 } 631 632 // Setup the two distinct "edit" URL's. 633 $community_url = add_query_arg( $query_args, $this->edit_profile_url ); 634 $wordpress_url = add_query_arg( $query_args, $this->edit_url ); 635 636 $bp_active = false; 637 $wp_active = ' nav-tab-active'; 638 if ( 'BuddyPress' === $active ) { 639 $bp_active = ' nav-tab-active'; 640 $wp_active = false; 641 } ?> 642 643 <h2 id="profile-nav" class="nav-tab-wrapper"> 644 <?php 645 /** 646 * In configs where BuddyPress is not network activated, as regular 647 * admins do not have the capacity to edit other users, we must add 648 * this check. 649 */ 650 if ( current_user_can( 'edit_user', $user->ID ) ) : ?> 651 652 <a class="nav-tab<?php echo esc_attr( $wp_active ); ?>" href="<?php echo esc_url( $wordpress_url );?>"><?php _e( 'Profile', 'buddypress' ); ?></a> 653 654 <?php endif; ?> 655 656 <a class="nav-tab<?php echo esc_attr( $bp_active ); ?>" href="<?php echo esc_url( $community_url );?>"><?php _e( 'Extended Profile', 'buddypress' ); ?></a> 657 </h2> 658 659 <?php 660 } 661 662 /** 663 * Set up the user's profile admin page. 664 * 665 * Loaded before the page is rendered, this function does all initial 666 * setup, including: processing form requests, registering contextual 667 * help, and setting up screen options. 668 * 669 * @since 2.0.0 670 */ 671 public function user_admin_load() { 672 673 // Get the user ID. 674 $user_id = $this->get_user_id(); 675 676 // Can current user edit this profile? 677 if ( ! $this->member_can_edit( $user_id ) ) { 678 wp_die( __( 'You cannot edit the requested user.', 'buddypress' ) ); 679 } 680 681 // Build redirection URL. 682 $redirect_to = remove_query_arg( array( 'action', 'error', 'updated', 'spam', 'ham', 'delete_avatar' ), $_SERVER['REQUEST_URI'] ); 683 $doaction = ! empty( $_REQUEST['action'] ) ? $_REQUEST['action'] : false; 684 685 if ( ! empty( $_REQUEST['user_status'] ) ) { 686 $spam = (bool) ( 'spam' === $_REQUEST['user_status'] ); 687 688 if ( $spam !== bp_is_user_spammer( $user_id ) ) { 689 $doaction = $_REQUEST['user_status']; 690 } 691 } 692 693 /** 694 * Fires at the start of the signups admin load. 695 * 696 * @since 2.0.0 697 * 698 * @param string $doaction Current bulk action being processed. 699 * @param array $_REQUEST Current $_REQUEST global. 700 */ 701 do_action_ref_array( 'bp_members_admin_load', array( $doaction, $_REQUEST ) ); 702 703 /** 704 * Filters the allowed actions for use in the user admin page. 705 * 706 * @since 2.0.0 707 * 708 * @param array $value Array of allowed actions to use. 709 */ 710 $allowed_actions = apply_filters( 'bp_members_admin_allowed_actions', array( 'update', 'delete_avatar', 'spam', 'ham' ) ); 711 712 // Prepare the display of the Community Profile screen. 713 if ( ! in_array( $doaction, $allowed_actions ) ) { 714 add_screen_option( 'layout_columns', array( 'default' => 2, 'max' => 2, ) ); 715 716 get_current_screen()->add_help_tab( array( 717 'id' => 'bp-profile-edit-overview', 718 'title' => __( 'Overview', 'buddypress' ), 719 'content' => 720 '<p>' . __( 'This is the admin view of a user's profile.', 'buddypress' ) . '</p>' . 721 '<p>' . __( 'In the main column, you can edit the fields of the user's extended profile.', 'buddypress' ) . '</p>' . 722 '<p>' . __( 'In the right-hand column, you can update the user's status, delete the user's avatar, and view recent statistics.', 'buddypress' ) . '</p>' 723 ) ); 724 725 // Help panel - sidebar links. 726 get_current_screen()->set_help_sidebar( 727 '<p><strong>' . __( 'For more information:', 'buddypress' ) . '</strong></p>' . 728 '<p>' . __( '<a href="https://codex.buddypress.org/administrator-guide/extended-profiles/">Managing Profiles</a>', 'buddypress' ) . '</p>' . 729 '<p>' . __( '<a href="https://buddypress.org/support/">Support Forums</a>', 'buddypress' ) . '</p>' 730 ); 731 732 // Register metaboxes for the edit screen. 733 add_meta_box( 734 'submitdiv', 735 _x( 'Status', 'members user-admin edit screen', 'buddypress' ), 736 array( $this, 'user_admin_status_metabox' ), 737 get_current_screen()->id, 738 'side', 739 'core' 740 ); 741 742 // In case xprofile is not active. 743 $this->stats_metabox->context = 'normal'; 744 $this->stats_metabox->priority = 'core'; 745 746 /** 747 * Fires before loading the profile fields if component is active. 748 * 749 * Plugins should not use this hook, please use 'bp_members_admin_user_metaboxes' instead. 750 * 751 * @since 2.0.0 752 * 753 * @param int $user_id Current user ID for the screen. 754 * @param string $id Current screen ID. 755 * @param object $stats_metabox Object holding position data for use with the stats metabox. 756 */ 757 do_action_ref_array( 'bp_members_admin_xprofile_metabox', array( $user_id, get_current_screen()->id, $this->stats_metabox ) ); 758 759 // If xProfile is inactive, difficult to know what's profile we're on. 760 if ( 'normal' === $this->stats_metabox->context ) { 761 $display_name = bp_core_get_user_displayname( $user_id ); 762 } else { 763 $display_name = __( 'Member', 'buddypress' ); 764 } 765 766 // User Stat metabox. 767 add_meta_box( 768 'bp_members_admin_user_stats', 769 sprintf( _x( "%s's Stats", 'members user-admin edit screen', 'buddypress' ), $display_name ), 770 array( $this, 'user_admin_stats_metabox' ), 771 get_current_screen()->id, 772 sanitize_key( $this->stats_metabox->context ), 773 sanitize_key( $this->stats_metabox->priority ) 774 ); 775 776 // Member Type metabox. Only added if member types have been registered. 777 $member_types = bp_get_member_types(); 778 if ( ! empty( $member_types ) ) { 779 add_meta_box( 780 'bp_members_admin_member_type', 781 _x( 'Member Type', 'members user-admin edit screen', 'buddypress' ), 782 array( $this, 'user_admin_member_type_metabox' ), 783 get_current_screen()->id, 784 'side', 785 'core' 786 ); 787 } 788 789 /** 790 * Fires at the end of the Community Profile screen. 791 * 792 * Plugins can restrict metabox to "bp_moderate" admins by checking if 793 * the first argument ($this->is_self_profile) is false in their callback. 794 * They can also restrict their metabox to self profile editing 795 * by setting it to true. 796 * 797 * @since 2.0.0 798 * 799 * @param bool $is_self_profile Whether or not it is the current user's profile. 800 * @param int $user_id Current user ID. 801 */ 802 do_action( 'bp_members_admin_user_metaboxes', $this->is_self_profile, $user_id ); 803 804 // Enqueue JavaScript files. 805 wp_enqueue_script( 'postbox' ); 806 wp_enqueue_script( 'dashboard' ); 807 808 // Spam or Ham user. 809 } elseif ( in_array( $doaction, array( 'spam', 'ham' ) ) && empty( $this->is_self_profile ) ) { 810 811 check_admin_referer( 'edit-bp-profile_' . $user_id ); 812 813 if ( bp_core_process_spammer_status( $user_id, $doaction ) ) { 814 $redirect_to = add_query_arg( 'updated', $doaction, $redirect_to ); 815 } else { 816 $redirect_to = add_query_arg( 'error', $doaction, $redirect_to ); 817 } 818 819 bp_core_redirect( $redirect_to ); 820 821 // Update other stuff once above ones are done. 822 } else { 823 $this->redirect = $redirect_to; 824 825 /** 826 * Fires at end of user profile admin load if doaction does not match any available actions. 827 * 828 * @since 2.0.0 829 * 830 * @param string $doaction Current bulk action being processed. 831 * @param int $user_id Current user ID. 832 * @param array $_REQUEST Current $_REQUEST global. 833 * @param string $redirect Determined redirect url to send user to. 834 */ 835 do_action_ref_array( 'bp_members_admin_update_user', array( $doaction, $user_id, $_REQUEST, $this->redirect ) ); 836 837 bp_core_redirect( $this->redirect ); 838 } 839 } 840 841 /** 842 * Display the user's profile. 843 * 844 * @since 2.0.0 845 */ 846 public function user_admin() { 847 848 if ( ! bp_current_user_can( 'bp_moderate' ) && empty( $this->is_self_profile ) ) { 849 die( '-1' ); 850 } 851 852 // Get the user ID. 853 $user_id = $this->get_user_id(); 854 $user = get_user_to_edit( $user_id ); 855 856 // Construct title. 857 if ( true === $this->is_self_profile ) { 858 $title = __( 'Profile', 'buddypress' ); 859 } else { 860 $title = __( 'Edit User', 'buddypress' ); 861 } 862 863 // Construct URL for form. 864 $request_url = remove_query_arg( array( 'action', 'error', 'updated', 'spam', 'ham' ), $_SERVER['REQUEST_URI'] ); 865 $form_action_url = add_query_arg( 'action', 'update', $request_url ); 866 $wp_http_referer = false; 867 if ( ! empty( $_REQUEST['wp_http_referer'] ) ) { 868 $wp_http_referer = remove_query_arg( array( 'action', 'updated' ), $_REQUEST['wp_http_referer'] ); 869 } 870 871 // Prepare notice for admin. 872 $notice = $this->get_user_notice(); 873 874 if ( ! empty( $notice ) ) : ?> 875 876 <div <?php if ( 'updated' === $notice['class'] ) : ?>id="message" <?php endif; ?>class="<?php echo esc_attr( $notice['class'] ); ?>"> 877 878 <p><?php echo esc_html( $notice['message'] ); ?></p> 879 880 <?php if ( !empty( $wp_http_referer ) && ( 'updated' === $notice['class'] ) ) : ?> 881 882 <p><a href="<?php echo esc_url( $wp_http_referer ); ?>"><?php esc_html_e( '← Back to Users', 'buddypress' ); ?></a></p> 883 884 <?php endif; ?> 885 886 </div> 887 888 <?php endif; ?> 889 890 <div class="wrap" id="community-profile-page"> 891 <h1><?php echo esc_html( $title ); ?> 892 893 <?php if ( empty( $this->is_self_profile ) ) : ?> 894 895 <?php if ( current_user_can( 'create_users' ) ) : ?> 896 897 <a href="user-new.php" class="add-new-h2"><?php echo esc_html_x( 'Add New', 'user', 'buddypress' ); ?></a> 898 899 <?php elseif ( is_multisite() && current_user_can( 'promote_users' ) ) : ?> 900 901 <a href="user-new.php" class="add-new-h2"><?php echo esc_html_x( 'Add Existing', 'user', 'buddypress' ); ?></a> 902 903 <?php endif; ?> 904 905 <?php endif; ?> 906 </h1> 907 908 <?php if ( ! empty( $user ) ) : 909 910 $this->profile_nav( $user, 'BuddyPress' ); ?> 911 912 <form action="<?php echo esc_url( $form_action_url ); ?>" id="your-profile" method="post"> 913 <div id="poststuff"> 914 915 <div id="post-body" class="metabox-holder columns-<?php echo 1 == get_current_screen()->get_columns() ? '1' : '2'; ?>"> 916 917 <div id="postbox-container-1" class="postbox-container"> 918 <?php do_meta_boxes( get_current_screen()->id, 'side', $user ); ?> 919 </div> 920 921 <div id="postbox-container-2" class="postbox-container"> 922 <?php do_meta_boxes( get_current_screen()->id, 'normal', $user ); ?> 923 <?php do_meta_boxes( get_current_screen()->id, 'advanced', $user ); ?> 924 </div> 925 </div><!-- #post-body --> 926 927 </div><!-- #poststuff --> 928 929 <?php wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?> 930 <?php wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false ); ?> 931 <?php wp_nonce_field( 'edit-bp-profile_' . $user->ID ); ?> 932 933 </form> 934 935 <?php else : ?> 936 937 <p><?php printf( __( 'No user found with this ID. <a href="%s">Go back and try again</a>.', 'buddypress' ), esc_url( bp_get_admin_url( 'users.php' ) ) ); ?></p> 938 939 <?php endif; ?> 940 941 </div><!-- .wrap --> 942 <?php 943 } 944 945 /** 946 * Render the Status metabox for user's profile screen. 947 * 948 * Actions are: 949 * - Update profile fields if xProfile component is active 950 * - Spam/Unspam user 951 * 952 * @since 2.0.0 953 * 954 * @param WP_User|null $user The WP_User object to be edited. 955 */ 956 public function user_admin_status_metabox( $user = null ) { 957 958 // Bail if no user id or if the user has not activated their account yet. 959 if ( empty( $user->ID ) ) { 960 return; 961 } 962 963 // Bail if user has not been activated yet (how did you get here?). 964 if ( isset( $user->user_status ) && ( 2 == $user->user_status ) ) : ?> 965 966 <p class="not-activated"><?php esc_html_e( 'User account has not yet been activated', 'buddypress' ); ?></p><br/> 967 968 <?php return; 969 970 endif; ?> 971 972 <div class="submitbox" id="submitcomment"> 973 <div id="minor-publishing"> 974 <div id="misc-publishing-actions"> 975 <?php 976 977 // Get the spam status once here to compare against below. 978 $is_spammer = bp_is_user_spammer( $user->ID ); 979 980 /** 981 * In configs where BuddyPress is not network activated, 982 * regular admins cannot mark a user as a spammer on front 983 * end. This prevent them to do it in backend. 984 * 985 * Also prevent admins from marking themselves or other 986 * admins as spammers. 987 */ 988 if ( ( empty( $this->is_self_profile ) && ( ! in_array( $user->user_login, get_super_admins() ) ) && empty( $this->subsite_activated ) ) || ( ! empty( $this->subsite_activated ) && current_user_can( 'manage_network_users' ) ) ) : ?> 989 990 <div class="misc-pub-section" id="comment-status-radio"> 991 <label class="approved"><input type="radio" name="user_status" value="ham" <?php checked( $is_spammer, false ); ?>><?php esc_html_e( 'Active', 'buddypress' ); ?></label><br /> 992 <label class="spam"><input type="radio" name="user_status" value="spam" <?php checked( $is_spammer, true ); ?>><?php esc_html_e( 'Spammer', 'buddypress' ); ?></label> 993 </div> 994 995 <?php endif ;?> 996 997 <div class="misc-pub-section curtime misc-pub-section-last"> 998 <?php 999 1000 // Translators: Publish box date format, see http://php.net/date. 1001 $datef = __( 'M j, Y @ G:i', 'buddypress' ); 1002 $date = date_i18n( $datef, strtotime( $user->user_registered ) ); 1003 ?> 1004 <span id="timestamp"><?php printf( __( 'Registered on: %s', 'buddypress' ), '<strong>' . $date . '</strong>' ); ?></span> 1005 </div> 1006 </div> <!-- #misc-publishing-actions --> 1007 1008 <div class="clear"></div> 1009 </div><!-- #minor-publishing --> 1010 1011 <div id="major-publishing-actions"> 1012 1013 <div id="publishing-action"> 1014 <a class="button bp-view-profile" href="<?php echo esc_url( bp_core_get_user_domain( $user->ID ) ); ?>" target="_blank"><?php esc_html_e( 'View Profile', 'buddypress' ); ?></a> 1015 <?php submit_button( esc_html__( 'Update Profile', 'buddypress' ), 'primary', 'save', false ); ?> 1016 </div> 1017 <div class="clear"></div> 1018 </div><!-- #major-publishing-actions --> 1019 1020 </div><!-- #submitcomment --> 1021 1022 <?php 1023 } 1024 1025 /** 1026 * Render the fallback metabox in case a user has been marked as a spammer. 1027 * 1028 * @since 2.0.0 1029 * 1030 * @param WP_User|null $user The WP_User object to be edited. 1031 */ 1032 public function user_admin_spammer_metabox( $user = null ) { 1033 ?> 1034 <p><?php printf( __( '%s has been marked as a spammer. All BuddyPress data associated with the user has been removed', 'buddypress' ), esc_html( bp_core_get_user_displayname( $user->ID ) ) ) ;?></p> 1035 <?php 1036 } 1037 1038 /** 1039 * Render the Stats metabox to moderate inappropriate images. 1040 * 1041 * @since 2.0.0 1042 * 1043 * @param WP_User|null $user The WP_User object to be edited. 1044 */ 1045 public function user_admin_stats_metabox( $user = null ) { 1046 1047 // Bail if no user ID. 1048 if ( empty( $user->ID ) ) { 1049 return; 1050 } 1051 1052 // If account is not activated last activity is the time user registered. 1053 if ( isset( $user->user_status ) && 2 == $user->user_status ) { 1054 $last_active = $user->user_registered; 1055 1056 // Account is activated, getting user's last activity. 1057 } else { 1058 $last_active = bp_get_user_last_activity( $user->ID ); 1059 } 1060 1061 $datef = __( 'M j, Y @ G:i', 'buddypress' ); 1062 $date = date_i18n( $datef, strtotime( $last_active ) ); ?> 1063 1064 <ul> 1065 <li class="bp-members-profile-stats"><?php printf( __( 'Last active: %1$s', 'buddypress' ), '<strong>' . $date . '</strong>' ); ?></li> 1066 1067 <?php 1068 // Loading other stats only if user has activated their account. 1069 if ( empty( $user->user_status ) ) { 1070 1071 /** 1072 * Fires in the user stats metabox if the user has activated their account. 1073 * 1074 * @since 2.0.0 1075 * 1076 * @param array $value Array holding the user ID. 1077 * @param object $user Current displayed user object. 1078 */ 1079 do_action( 'bp_members_admin_user_stats', array( 'user_id' => $user->ID ), $user ); 1080 } 1081 ?> 1082 </ul> 1083 1084 <?php 1085 } 1086 1087 /** 1088 * Render the Member Type metabox. 1089 * 1090 * @since 2.2.0 1091 * 1092 * @param WP_User|null $user The WP_User object to be edited. 1093 */ 1094 public function user_admin_member_type_metabox( $user = null ) { 1095 1096 // Bail if no user ID. 1097 if ( empty( $user->ID ) ) { 1098 return; 1099 } 1100 1101 $types = bp_get_member_types( array(), 'objects' ); 1102 $current_type = bp_get_member_type( $user->ID ); 1103 ?> 1104 1105 <label for="bp-members-profile-member-type" class="screen-reader-text"><?php esc_html_e( 'Select member type', 'buddypress' ); ?></label> 1106 <select name="bp-members-profile-member-type" id="bp-members-profile-member-type"> 1107 <option value="" <?php selected( '', $current_type ); ?>><?php /* translators: no option picked in select box */ esc_attr_e( '----', 'buddypress' ) ?></option> 1108 <?php foreach ( $types as $type ) : ?> 1109 <option value="<?php echo esc_attr( $type->name ) ?>" <?php selected( $type->name, $current_type ) ?>><?php echo esc_html( $type->labels['singular_name'] ) ?></option> 1110 <?php endforeach; ?> 1111 </select> 1112 1113 <?php 1114 1115 wp_nonce_field( 'bp-member-type-change-' . $user->ID, 'bp-member-type-nonce' ); 1116 } 1117 1118 /** 1119 * Process changes from the Member Type metabox. 1120 * 1121 * @since 2.2.0 1122 */ 1123 public function process_member_type_update() { 1124 if ( ! isset( $_POST['bp-member-type-nonce'] ) || ! isset( $_POST['bp-members-profile-member-type'] ) ) { 1125 return; 1126 } 1127 1128 $user_id = $this->get_user_id(); 1129 1130 check_admin_referer( 'bp-member-type-change-' . $user_id, 'bp-member-type-nonce' ); 1131 1132 // Permission check. 1133 if ( ! current_user_can( 'bp_moderate' ) && $user_id != bp_loggedin_user_id() ) { 1134 return; 1135 } 1136 1137 // Member type string must either reference a valid member type, or be empty. 1138 $member_type = stripslashes( $_POST['bp-members-profile-member-type'] ); 1139 if ( ! empty( $member_type ) && ! bp_get_member_type_object( $member_type ) ) { 1140 return; 1141 } 1142 1143 /* 1144 * If an invalid member type is passed, someone's doing something 1145 * fishy with the POST request, so we can fail silently. 1146 */ 1147 if ( bp_set_member_type( $user_id, $member_type ) ) { 1148 // @todo Success messages can't be posted because other stuff happens on the page load. 1149 } 1150 } 1151 1152 /** 1153 * Add a link to Profile in Users listing row actions. 1154 * 1155 * @since 2.0.0 1156 * 1157 * @param array|string $actions WordPress row actions (edit, delete). 1158 * @param object|null $user The object for the user row. 1159 * @return array Merged actions. 1160 */ 1161 public function row_actions( $actions = '', $user = null ) { 1162 1163 // Bail if no user ID. 1164 if ( empty( $user->ID ) ) { 1165 return; 1166 } 1167 1168 // Setup args array. 1169 $args = array(); 1170 1171 // Add the user ID if it's not for the current user. 1172 if ( $user->ID !== $this->current_user_id ) { 1173 $args['user_id'] = $user->ID; 1174 } 1175 1176 // Add the referer. 1177 $args['wp_http_referer'] = urlencode( wp_unslash( $_SERVER['REQUEST_URI'] ) ); 1178 1179 // Add the "Extended" link if the current user can edit this user. 1180 if ( current_user_can( 'edit_user', $user->ID ) || bp_current_user_can( 'bp_moderate' ) ) { 1181 1182 // Add query args and setup the Extended link. 1183 $edit_profile = add_query_arg( $args, $this->edit_profile_url ); 1184 $edit_profile_link = sprintf( '<a href="%1$s">%2$s</a>', esc_url( $edit_profile ), esc_html__( 'Extended', 'buddypress' ) ); 1185 1186 /** 1187 * Check the edit action is available 1188 * and preserve the order edit | profile | remove/delete. 1189 */ 1190 if ( ! empty( $actions['edit'] ) ) { 1191 $edit_action = $actions['edit']; 1192 unset( $actions['edit'] ); 1193 1194 $new_edit_actions = array( 1195 'edit' => $edit_action, 1196 'edit-profile' => $edit_profile_link, 1197 ); 1198 1199 // If not available simply add the edit profile action. 1200 } else { 1201 $new_edit_actions = array( 'edit-profile' => $edit_profile_link ); 1202 } 1203 1204 $actions = array_merge( $new_edit_actions, $actions ); 1205 } 1206 1207 return $actions; 1208 } 1209 1210 /** 1211 * Add a filter to edit profile url in WP Admin Bar. 1212 * 1213 * @since 2.1.0 1214 */ 1215 public function add_edit_profile_url_filter() { 1216 add_filter( 'bp_members_edit_profile_url', array( $this, 'filter_adminbar_profile_link' ), 10, 3 ); 1217 } 1218 1219 /** 1220 * Filter the profile url. 1221 * 1222 * @since 2.1.0 1223 * 1224 * @uses user_admin_url() 1225 * 1226 * @param string $profile_link Profile Link for admin bar. 1227 * @param string $url Profile URL. 1228 * @param int $user_id User ID. 1229 * @return string 1230 */ 1231 public function filter_adminbar_profile_link( $profile_link = '', $url = '', $user_id = 0 ) { 1232 if ( ! is_super_admin( $user_id ) && is_admin() ) { 1233 $profile_link = user_admin_url( 'profile.php' ); 1234 } 1235 return $profile_link; 1236 } 1237 1238 /** 1239 * Remove the filter to edit profile url in WP Admin Bar. 1240 * 1241 * @since 2.1.0 1242 */ 1243 public function remove_edit_profile_url_filter() { 1244 remove_filter( 'bp_members_edit_profile_url', array( $this, 'filter_adminbar_profile_link' ), 10, 3 ); 1245 } 1246 1247 /** Signups Management ****************************************************/ 1248 1249 /** 1250 * Display the admin preferences about signups pagination. 1251 * 1252 * @since 2.0.0 1253 * 1254 * @param int $value Value for signup option. 1255 * @param string $option Value for the option key. 1256 * @param int $new_value Value for the saved option. 1257 * @return int The pagination preferences. 1258 */ 1259 public function signup_screen_options( $value = 0, $option = '', $new_value = 0 ) { 1260 if ( 'users_page_bp_signups_network_per_page' != $option && 'users_page_bp_signups_per_page' != $option ) { 1261 return $value; 1262 } 1263 1264 // Per page. 1265 $new_value = (int) $new_value; 1266 if ( $new_value < 1 || $new_value > 999 ) { 1267 return $value; 1268 } 1269 1270 return $new_value; 1271 } 1272 1273 /** 1274 * Make sure no signups will show in users list. 1275 * 1276 * This is needed to handle signups that may have not been activated 1277 * before the 2.0.0 upgrade. 1278 * 1279 * @since 2.0.0 1280 * 1281 * @param WP_User_Query|null $query The users query. 1282 * @return WP_User_Query The users query without the signups. 1283 */ 1284 public function remove_signups_from_user_query( $query = null ) { 1285 global $wpdb; 1286 1287 // Bail if this is an ajax request. 1288 if ( defined( 'DOING_AJAX' ) ) { 1289 return; 1290 } 1291 1292 // Bail if updating BuddyPress. 1293 if ( bp_is_update() ) { 1294 return; 1295 } 1296 1297 // Bail if there is no current admin screen. 1298 if ( ! function_exists( 'get_current_screen' ) || ! get_current_screen() ) { 1299 return; 1300 } 1301 1302 // Get current screen. 1303 $current_screen = get_current_screen(); 1304 1305 // Bail if not on a users page. 1306 if ( ! isset( $current_screen->id ) || $this->users_page !== $current_screen->id ) { 1307 return; 1308 } 1309 1310 // Bail if already querying by an existing role. 1311 if ( ! empty( $query->query_vars['role'] ) ) { 1312 return; 1313 } 1314 1315 $query->query_where .= " AND {$wpdb->users}.user_status != 2"; 1316 } 1317 1318 /** 1319 * Filter the WP Users List Table views to include 'bp-signups'. 1320 * 1321 * @since 2.0.0 1322 * 1323 * @param array $views WP List Table views. 1324 * @return array The views with the signup view added. 1325 */ 1326 public function signup_filter_view( $views = array() ) { 1327 1328 // Remove the 'current' class from All if we're on the signups view. 1329 if ( $this->signups_page == get_current_screen()->id ) { 1330 $views['all'] = str_replace( 'class="current"', '', $views['all'] ); 1331 $class = 'current'; 1332 } else { 1333 $class = ''; 1334 } 1335 1336 $signups = BP_Signup::count_signups(); 1337 1338 if ( is_network_admin() ) { 1339 $base_url = network_admin_url( 'users.php' ); 1340 } else { 1341 $base_url = bp_get_admin_url( 'users.php' ); 1342 } 1343 1344 $url = add_query_arg( 'page', 'bp-signups', $base_url ); 1345 $text = sprintf( _x( 'Pending %s', 'signup users', 'buddypress' ), '<span class="count">(' . number_format_i18n( $signups ) . ')</span>' ); 1346 1347 $views['registered'] = sprintf( '<a href="%1$s" class="%2$s">%3$s</a>', esc_url( $url ), $class, $text ); 1348 1349 return $views; 1350 } 1351 1352 /** 1353 * Load the Signup WP Users List table. 1354 * 1355 * @since 2.0.0 1356 * 1357 * @param string $class The name of the class to use. 1358 * @param string $required The parent class. 1359 * @return WP_List_Table The List table. 1360 */ 1361 public static function get_list_table_class( $class = '', $required = '' ) { 1362 if ( empty( $class ) ) { 1363 return; 1364 } 1365 1366 if ( ! empty( $required ) ) { 1367 require_once( ABSPATH . 'wp-admin/includes/class-wp-' . $required . '-list-table.php' ); 1368 require_once( buddypress()->members->admin->admin_dir . 'bp-members-admin-classes.php' ); 1369 } 1370 1371 return new $class(); 1372 } 1373 1374 /** 1375 * Set up the signups admin page. 1376 * 1377 * Loaded before the page is rendered, this function does all initial 1378 * setup, including: processing form requests, registering contextual 1379 * help, and setting up screen options. 1380 * 1381 * @since 2.0.0 1382 * 1383 * @global $bp_members_signup_list_table 1384 */ 1385 public function signups_admin_load() { 1386 global $bp_members_signup_list_table; 1387 1388 // Build redirection URL. 1389 $redirect_to = remove_query_arg( array( 'action', 'error', 'updated', 'activated', 'notactivated', 'deleted', 'notdeleted', 'resent', 'notresent', 'do_delete', 'do_resend', 'do_activate', '_wpnonce', 'signup_ids' ), $_SERVER['REQUEST_URI'] ); 1390 $doaction = bp_admin_list_table_current_bulk_action(); 1391 1392 /** 1393 * Fires at the start of the signups admin load. 1394 * 1395 * @since 2.0.0 1396 * 1397 * @param string $doaction Current bulk action being processed. 1398 * @param array $_REQUEST Current $_REQUEST global. 1399 */ 1400 do_action( 'bp_signups_admin_load', $doaction, $_REQUEST ); 1401 1402 /** 1403 * Filters the allowed actions for use in the user signups admin page. 1404 * 1405 * @since 2.0.0 1406 * 1407 * @param array $value Array of allowed actions to use. 1408 */ 1409 $allowed_actions = apply_filters( 'bp_signups_admin_allowed_actions', array( 'do_delete', 'do_activate', 'do_resend' ) ); 1410 1411 // Prepare the display of the Community Profile screen. 1412 if ( ! in_array( $doaction, $allowed_actions ) || ( -1 == $doaction ) ) { 1413 1414 if ( is_network_admin() ) { 1415 $bp_members_signup_list_table = self::get_list_table_class( 'BP_Members_MS_List_Table', 'ms-users' ); 1416 } else { 1417 $bp_members_signup_list_table = self::get_list_table_class( 'BP_Members_List_Table', 'users' ); 1418 } 1419 1420 // The per_page screen option. 1421 add_screen_option( 'per_page', array( 'label' => _x( 'Pending Accounts', 'Pending Accounts per page (screen options)', 'buddypress' ) ) ); 1422 1423 get_current_screen()->add_help_tab( array( 1424 'id' => 'bp-signups-overview', 1425 'title' => __( 'Overview', 'buddypress' ), 1426 'content' => 1427 '<p>' . __( 'This is the administration screen for pending accounts on your site.', 'buddypress' ) . '</p>' . 1428 '<p>' . __( 'From the screen options, you can customize the displayed columns and the pagination of this screen.', 'buddypress' ) . '</p>' . 1429 '<p>' . __( 'You can reorder the list of your pending accounts by clicking on the Username, Email or Registered column headers.', 'buddypress' ) . '</p>' . 1430 '<p>' . __( 'Using the search form, you can find pending accounts more easily. The Username and Email fields will be included in the search.', 'buddypress' ) . '</p>' 1431 ) ); 1432 1433 get_current_screen()->add_help_tab( array( 1434 'id' => 'bp-signups-actions', 1435 'title' => __( 'Actions', 'buddypress' ), 1436 'content' => 1437 '<p>' . __( 'Hovering over a row in the pending accounts list will display action links that allow you to manage pending accounts. You can perform the following actions:', 'buddypress' ) . '</p>' . 1438 '<ul><li>' . __( '"Email" takes you to the confirmation screen before being able to send the activation link to the desired pending account. You can only send the activation email once per day.', 'buddypress' ) . '</li>' . 1439 '<li>' . __( '"Delete" allows you to delete a pending account from your site. You will be asked to confirm this deletion.', 'buddypress' ) . '</li></ul>' . 1440 '<p>' . __( 'By clicking on a Username you will be able to activate a pending account from the confirmation screen.', 'buddypress' ) . '</p>' . 1441 '<p>' . __( 'Bulk actions allow you to perform these 3 actions for the selected rows.', 'buddypress' ) . '</p>' 1442 ) ); 1443 1444 // Help panel - sidebar links. 1445 get_current_screen()->set_help_sidebar( 1446 '<p><strong>' . __( 'For more information:', 'buddypress' ) . '</strong></p>' . 1447 '<p>' . __( '<a href="https://buddypress.org/support/">Support Forums</a>', 'buddypress' ) . '</p>' 1448 ); 1449 1450 // Add accessible hidden headings and text for the Pending Users screen. 1451 if ( bp_get_major_wp_version() >= 4.4 ) { 1452 get_current_screen()->set_screen_reader_content( array( 1453 'heading_views' => __( 'Filter users list', 'buddypress' ), 1454 'heading_pagination' => __( 'Pending users list navigation', 'buddypress' ), 1455 'heading_list' => __( 'Pending users list', 'buddypress' ), 1456 ) ); 1457 } 1458 1459 } else { 1460 if ( ! empty( $_REQUEST['signup_ids' ] ) ) { 1461 $signups = wp_parse_id_list( $_REQUEST['signup_ids' ] ); 1462 } 1463 1464 // Handle resent activation links. 1465 if ( 'do_resend' == $doaction ) { 1466 1467 // Nonce check. 1468 check_admin_referer( 'signups_resend' ); 1469 1470 $resent = BP_Signup::resend( $signups ); 1471 1472 if ( empty( $resent ) ) { 1473 $redirect_to = add_query_arg( 'error', $doaction, $redirect_to ); 1474 } else { 1475 $query_arg = array( 'updated' => 'resent' ); 1476 1477 if ( ! empty( $resent['resent'] ) ) { 1478 $query_arg['resent'] = count( $resent['resent'] ); 1479 } 1480 1481 if ( ! empty( $resent['errors'] ) ) { 1482 $query_arg['notsent'] = count( $resent['errors'] ); 1483 set_transient( '_bp_admin_signups_errors', $resent['errors'], 30 ); 1484 } 1485 1486 $redirect_to = add_query_arg( $query_arg, $redirect_to ); 1487 } 1488 1489 bp_core_redirect( $redirect_to ); 1490 1491 // Handle activated accounts. 1492 } elseif ( 'do_activate' == $doaction ) { 1493 1494 // Nonce check. 1495 check_admin_referer( 'signups_activate' ); 1496 1497 $activated = BP_Signup::activate( $signups ); 1498 1499 if ( empty( $activated ) ) { 1500 $redirect_to = add_query_arg( 'error', $doaction, $redirect_to ); 1501 } else { 1502 $query_arg = array( 'updated' => 'activated' ); 1503 1504 if ( ! empty( $activated['activated'] ) ) { 1505 $query_arg['activated'] = count( $activated['activated'] ); 1506 } 1507 1508 if ( ! empty( $activated['errors'] ) ) { 1509 $query_arg['notactivated'] = count( $activated['errors'] ); 1510 set_transient( '_bp_admin_signups_errors', $activated['errors'], 30 ); 1511 } 1512 1513 $redirect_to = add_query_arg( $query_arg, $redirect_to ); 1514 } 1515 1516 bp_core_redirect( $redirect_to ); 1517 1518 // Handle sign-ups delete. 1519 } elseif ( 'do_delete' == $doaction ) { 1520 1521 // Nonce check. 1522 check_admin_referer( 'signups_delete' ); 1523 1524 $deleted = BP_Signup::delete( $signups ); 1525 1526 if ( empty( $deleted ) ) { 1527 $redirect_to = add_query_arg( 'error', $doaction, $redirect_to ); 1528 } else { 1529 $query_arg = array( 'updated' => 'deleted' ); 1530 1531 if ( ! empty( $deleted['deleted'] ) ) { 1532 $query_arg['deleted'] = count( $deleted['deleted'] ); 1533 } 1534 1535 if ( ! empty( $deleted['errors'] ) ) { 1536 $query_arg['notdeleted'] = count( $deleted['errors'] ); 1537 set_transient( '_bp_admin_signups_errors', $deleted['errors'], 30 ); 1538 } 1539 1540 $redirect_to = add_query_arg( $query_arg, $redirect_to ); 1541 } 1542 1543 bp_core_redirect( $redirect_to ); 1544 1545 // Plugins can update other stuff from here. 1546 } else { 1547 $this->redirect = $redirect_to; 1548 1549 /** 1550 * Fires at end of signups admin load if doaction does not match any actions. 1551 * 1552 * @since 2.0.0 1553 * 1554 * @param string $doaction Current bulk action being processed. 1555 * @param array $_REQUEST Current $_REQUEST global. 1556 * @param string $redirect Determined redirect url to send user to. 1557 */ 1558 do_action( 'bp_members_admin_update_signups', $doaction, $_REQUEST, $this->redirect ); 1559 1560 bp_core_redirect( $this->redirect ); 1561 } 1562 } 1563 } 1564 1565 /** 1566 * Display any activation errors. 1567 * 1568 * @since 2.0.0 1569 */ 1570 public function signups_display_errors() { 1571 1572 // Look for sign-up errors. 1573 $errors = get_transient( '_bp_admin_signups_errors' ); 1574 1575 // Bail if no activation errors. 1576 if ( empty( $errors ) ) { 1577 return; 1578 } 1579 1580 // Loop through errors and display them. 1581 foreach ( $errors as $error ) : ?> 1582 1583 <li><?php echo esc_html( $error[0] );?>: <?php echo esc_html( $error[1] );?></li> 1584 1585 <?php endforeach; 1586 1587 // Delete the redirect transient. 1588 delete_transient( '_bp_admin_signups_errors' ); 1589 } 1590 1591 /** 1592 * Get admin notice when viewing the sign-up page. 1593 * 1594 * @since 2.1.0 1595 * 1596 * @return array 1597 */ 1598 private function get_signup_notice() { 1599 1600 // Setup empty notice for return value. 1601 $notice = array(); 1602 1603 // Updates. 1604 if ( ! empty( $_REQUEST['updated'] ) ) { 1605 switch ( $_REQUEST['updated'] ) { 1606 case 'resent': 1607 $notice = array( 1608 'class' => 'updated', 1609 'message' => '' 1610 ); 1611 1612 if ( ! empty( $_REQUEST['resent'] ) ) { 1613 $notice['message'] .= sprintf( 1614 _nx( '%s activation email successfully sent! ', '%s activation emails successfully sent! ', 1615 absint( $_REQUEST['resent'] ), 1616 'signup resent', 1617 'buddypress' 1618 ), 1619 number_format_i18n( absint( $_REQUEST['resent'] ) ) 1620 ); 1621 } 1622 1623 if ( ! empty( $_REQUEST['notsent'] ) ) { 1624 $notice['message'] .= sprintf( 1625 _nx( '%s activation email was not sent.', '%s activation emails were not sent.', 1626 absint( $_REQUEST['notsent'] ), 1627 'signup notsent', 1628 'buddypress' 1629 ), 1630 number_format_i18n( absint( $_REQUEST['notsent'] ) ) 1631 ); 1632 1633 if ( empty( $_REQUEST['resent'] ) ) { 1634 $notice['class'] = 'error'; 1635 } 1636 } 1637 1638 break; 1639 1640 case 'activated': 1641 $notice = array( 1642 'class' => 'updated', 1643 'message' => '' 1644 ); 1645 1646 if ( ! empty( $_REQUEST['activated'] ) ) { 1647 $notice['message'] .= sprintf( 1648 _nx( '%s account successfully activated! ', '%s accounts successfully activated! ', 1649 absint( $_REQUEST['activated'] ), 1650 'signup resent', 1651 'buddypress' 1652 ), 1653 number_format_i18n( absint( $_REQUEST['activated'] ) ) 1654 ); 1655 } 1656 1657 if ( ! empty( $_REQUEST['notactivated'] ) ) { 1658 $notice['message'] .= sprintf( 1659 _nx( '%s account was not activated.', '%s accounts were not activated.', 1660 absint( $_REQUEST['notactivated'] ), 1661 'signup notsent', 1662 'buddypress' 1663 ), 1664 number_format_i18n( absint( $_REQUEST['notactivated'] ) ) 1665 ); 1666 1667 if ( empty( $_REQUEST['activated'] ) ) { 1668 $notice['class'] = 'error'; 1669 } 1670 } 1671 1672 break; 1673 1674 case 'deleted': 1675 $notice = array( 1676 'class' => 'updated', 1677 'message' => '' 1678 ); 1679 1680 if ( ! empty( $_REQUEST['deleted'] ) ) { 1681 $notice['message'] .= sprintf( 1682 _nx( '%s sign-up successfully deleted!', '%s sign-ups successfully deleted!', 1683 absint( $_REQUEST['deleted'] ), 1684 'signup deleted', 1685 'buddypress' 1686 ), 1687 number_format_i18n( absint( $_REQUEST['deleted'] ) ) 1688 ); 1689 } 1690 1691 if ( ! empty( $_REQUEST['notdeleted'] ) ) { 1692 $notice['message'] .= sprintf( 1693 _nx( '%s sign-up was not deleted.', '%s sign-ups were not deleted.', 1694 absint( $_REQUEST['notdeleted'] ), 1695 'signup notdeleted', 1696 'buddypress' 1697 ), 1698 number_format_i18n( absint( $_REQUEST['notdeleted'] ) ) 1699 ); 1700 1701 if ( empty( $_REQUEST['deleted'] ) ) { 1702 $notice['class'] = 'error'; 1703 } 1704 } 1705 1706 break; 1707 } 1708 } 1709 1710 // Errors. 1711 if ( ! empty( $_REQUEST['error'] ) ) { 1712 switch ( $_REQUEST['error'] ) { 1713 case 'do_resend': 1714 $notice = array( 1715 'class' => 'error', 1716 'message' => esc_html__( 'There was a problem sending the activation emails. Please try again.', 'buddypress' ), 1717 ); 1718 break; 1719 1720 case 'do_activate': 1721 $notice = array( 1722 'class' => 'error', 1723 'message' => esc_html__( 'There was a problem activating accounts. Please try again.', 'buddypress' ), 1724 ); 1725 break; 1726 1727 case 'do_delete': 1728 $notice = array( 1729 'class' => 'error', 1730 'message' => esc_html__( 'There was a problem deleting sign-ups. Please try again.', 'buddypress' ), 1731 ); 1732 break; 1733 } 1734 } 1735 1736 return $notice; 1737 } 1738 1739 /** 1740 * Signups admin page router. 1741 * 1742 * Depending on the context, display 1743 * - the list of signups, 1744 * - or the delete confirmation screen, 1745 * - or the activate confirmation screen, 1746 * - or the "resend" email confirmation screen. 1747 * 1748 * Also prepare the admin notices. 1749 * 1750 * @since 2.0.0 1751 */ 1752 public function signups_admin() { 1753 $doaction = bp_admin_list_table_current_bulk_action(); 1754 1755 // Prepare notices for admin. 1756 $notice = $this->get_signup_notice(); 1757 1758 // Display notices. 1759 if ( ! empty( $notice ) ) : 1760 if ( 'updated' === $notice['class'] ) : ?> 1761 1762 <div id="message" class="<?php echo esc_attr( $notice['class'] ); ?>"> 1763 1764 <?php else: ?> 1765 1766 <div class="<?php echo esc_attr( $notice['class'] ); ?>"> 1767 1768 <?php endif; ?> 1769 1770 <p><?php echo $notice['message']; ?></p> 1771 1772 <?php if ( ! empty( $_REQUEST['notactivated'] ) || ! empty( $_REQUEST['notdeleted'] ) || ! empty( $_REQUEST['notsent'] ) ) :?> 1773 1774 <ul><?php $this->signups_display_errors();?></ul> 1775 1776 <?php endif ;?> 1777 1778 </div> 1779 1780 <?php endif; 1781 1782 // Show the proper screen. 1783 switch ( $doaction ) { 1784 case 'activate' : 1785 case 'delete' : 1786 case 'resend' : 1787 $this->signups_admin_manage( $doaction ); 1788 break; 1789 1790 default: 1791 $this->signups_admin_index(); 1792 break; 1793 1794 } 1795 } 1796 1797 /** 1798 * This is the list of the Pending accounts (signups). 1799 * 1800 * @since 2.0.0 1801 * 1802 * @global $plugin_page 1803 * @global $bp_members_signup_list_table 1804 */ 1805 public function signups_admin_index() { 1806 global $plugin_page, $bp_members_signup_list_table; 1807 1808 $usersearch = ! empty( $_REQUEST['s'] ) ? stripslashes( $_REQUEST['s'] ) : ''; 1809 1810 // Prepare the group items for display. 1811 $bp_members_signup_list_table->prepare_items(); 1812 1813 if ( is_network_admin() ) { 1814 $form_url = network_admin_url( 'users.php' ); 1815 } else { 1816 $form_url = bp_get_admin_url( 'users.php' ); 1817 } 1818 1819 $form_url = add_query_arg( 1820 array( 1821 'page' => 'bp-signups', 1822 ), 1823 $form_url 1824 ); 1825 1826 $search_form_url = remove_query_arg( 1827 array( 1828 'action', 1829 'deleted', 1830 'notdeleted', 1831 'error', 1832 'updated', 1833 'delete', 1834 'activate', 1835 'activated', 1836 'notactivated', 1837 'resend', 1838 'resent', 1839 'notresent', 1840 'do_delete', 1841 'do_activate', 1842 'do_resend', 1843 'action2', 1844 '_wpnonce', 1845 'signup_ids' 1846 ), $_SERVER['REQUEST_URI'] 1847 ); 1848 1849 ?> 1850 1851 <div class="wrap"> 1852 <h1><?php _e( 'Users', 'buddypress' ); ?> 1853 1854 <?php if ( current_user_can( 'create_users' ) ) : ?> 1855 1856 <a href="user-new.php" class="add-new-h2"><?php echo esc_html_x( 'Add New', 'user', 'buddypress' ); ?></a> 1857 1858 <?php elseif ( is_multisite() && current_user_can( 'promote_users' ) ) : ?> 1859 1860 <a href="user-new.php" class="add-new-h2"><?php echo esc_html_x( 'Add Existing', 'user', 'buddypress' ); ?></a> 1861 1862 <?php endif; 1863 1864 if ( $usersearch ) { 1865 printf( '<span class="subtitle">' . __( 'Search results for “%s”', 'buddypress' ) . '</span>', esc_html( $usersearch ) ); 1866 } 1867 1868 ?> 1869 </h1> 1870 1871 <?php // Display each signups on its own row. ?> 1872 <?php $bp_members_signup_list_table->views(); ?> 1873 1874 <form id="bp-signups-search-form" action="<?php echo esc_url( $search_form_url ) ;?>"> 1875 <input type="hidden" name="page" value="<?php echo esc_attr( $plugin_page ); ?>" /> 1876 <?php $bp_members_signup_list_table->search_box( __( 'Search Pending Users', 'buddypress' ), 'bp-signups' ); ?> 1877 </form> 1878 1879 <form id="bp-signups-form" action="<?php echo esc_url( $form_url );?>" method="post"> 1880 <?php $bp_members_signup_list_table->display(); ?> 1881 </form> 1882 </div> 1883 <?php 1884 } 1885 1886 /** 1887 * This is the confirmation screen for actions. 1888 * 1889 * @since 2.0.0 1890 * 1891 * @param string $action Delete, activate, or resend activation link. 1892 * @return string 1893 */ 1894 public function signups_admin_manage( $action = '' ) { 1895 if ( ! current_user_can( $this->capability ) || empty( $action ) ) { 1896 die( '-1' ); 1897 } 1898 1899 // Get the user IDs from the URL. 1900 $ids = false; 1901 if ( ! empty( $_POST['allsignups'] ) ) { 1902 $ids = wp_parse_id_list( $_POST['allsignups'] ); 1903 } elseif ( ! empty( $_GET['signup_id'] ) ) { 1904 $ids = absint( $_GET['signup_id'] ); 1905 } 1906 1907 if ( empty( $ids ) ) { 1908 return false; 1909 } 1910 1911 // Query for signups, and filter out those IDs that don't 1912 // correspond to an actual signup. 1913 $signups_query = BP_Signup::get( array( 1914 'include' => $ids, 1915 ) ); 1916 1917 $signups = $signups_query['signups']; 1918 $signup_ids = wp_list_pluck( $signups, 'signup_id' ); 1919 1920 // Set up strings. 1921 switch ( $action ) { 1922 case 'delete' : 1923 $header_text = __( 'Delete Pending Accounts', 'buddypress' ); 1924 if ( 1 == count( $signup_ids ) ) { 1925 $helper_text = __( 'You are about to delete the following account:', 'buddypress' ); 1926 } else { 1927 $helper_text = __( 'You are about to delete the following accounts:', 'buddypress' ); 1928 } 1929 break; 1930 1931 case 'activate' : 1932 $header_text = __( 'Activate Pending Accounts', 'buddypress' ); 1933 if ( 1 == count( $signup_ids ) ) { 1934 $helper_text = __( 'You are about to activate the following account:', 'buddypress' ); 1935 } else { 1936 $helper_text = __( 'You are about to activate the following accounts:', 'buddypress' ); 1937 } 1938 break; 1939 1940 case 'resend' : 1941 $header_text = __( 'Resend Activation Emails', 'buddypress' ); 1942 if ( 1 == count( $signup_ids ) ) { 1943 $helper_text = __( 'You are about to resend an activation email to the following account:', 'buddypress' ); 1944 } else { 1945 $helper_text = __( 'You are about to resend an activation email to the following accounts:', 'buddypress' ); 1946 } 1947 break; 1948 } 1949 1950 // These arguments are added to all URLs. 1951 $url_args = array( 'page' => 'bp-signups' ); 1952 1953 // These arguments are only added when performing an action. 1954 $action_args = array( 1955 'action' => 'do_' . $action, 1956 'signup_ids' => implode( ',', $signup_ids ) 1957 ); 1958 1959 if ( is_network_admin() ) { 1960 $base_url = network_admin_url( 'users.php' ); 1961 } else { 1962 $base_url = bp_get_admin_url( 'users.php' ); 1963 } 1964 1965 $cancel_url = add_query_arg( $url_args, $base_url ); 1966 $action_url = wp_nonce_url( 1967 add_query_arg( 1968 array_merge( $url_args, $action_args ), 1969 $base_url 1970 ), 1971 'signups_' . $action 1972 ); 1973 1974 ?> 1975 1976 <div class="wrap"> 1977 <h1><?php echo esc_html( $header_text ); ?></h1> 1978 <p><?php echo esc_html( $helper_text ); ?></p> 1979 1980 <ol class="bp-signups-list"> 1981 <?php foreach ( $signups as $signup ) : 1982 1983 $last_notified = mysql2date( 'Y/m/d g:i:s a', $signup->date_sent ); ?> 1984 1985 <li> 1986 <?php echo esc_html( $signup->user_name ) ?> - <?php echo sanitize_email( $signup->user_email );?> 1987 1988 <?php if ( 'resend' == $action ) : ?> 1989 1990 <p class="description"> 1991 <?php printf( esc_html__( 'Last notified: %s', 'buddypress'), $last_notified ) ;?> 1992 1993 <?php if ( ! empty( $signup->recently_sent ) ) : ?> 1994 1995 <span class="attention wp-ui-text-notification"> <?php esc_html_e( '(less than 24 hours ago)', 'buddypress' ); ?></span> 1996 1997 <?php endif; ?> 1998 </p> 1999 2000 <?php endif; ?> 2001 2002 </li> 2003 2004 <?php endforeach; ?> 2005 </ol> 2006 2007 <?php if ( 'delete' === $action ) : ?> 2008 2009 <p><strong><?php esc_html_e( 'This action cannot be undone.', 'buddypress' ) ?></strong></p> 2010 2011 <?php endif ; ?> 2012 2013 <a class="button-primary" href="<?php echo esc_url( $action_url ); ?>"><?php esc_html_e( 'Confirm', 'buddypress' ); ?></a> 2014 <a class="button" href="<?php echo esc_url( $cancel_url ); ?>"><?php esc_html_e( 'Cancel', 'buddypress' ) ?></a> 2015 </div> 2016 2017 <?php 2018 } 2019 } 2020 endif; // End class_exists check. 13 require dirname( __FILE__ ) . '/classes/class-bp-members-admin.php'; 2021 14 2022 15 // Load the BP Members admin.
Note: See TracChangeset
for help on using the changeset viewer.