[ Index ]

PHP Cross Reference of BuddyPress

title

Body

[close]

/src/bp-members/classes/ -> class-bp-members-admin.php (source)

   1  <?php
   2  /**
   3   * BuddyPress Members Admin
   4   *
   5   * @package BuddyPress
   6   * @subpackage MembersAdmin
   7   * @since 2.0.0
   8   */
   9  
  10  // Exit if accessed directly.
  11  defined( 'ABSPATH' ) || exit;
  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       * @return BP_Members_Admin
  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          $this->members_invites_page = '';
 144  
 145          // Specific config: BuddyPress is not network activated.
 146          $this->subsite_activated = (bool) is_multisite() && ! bp_is_network_activated();
 147  
 148          // When BuddyPress is not network activated, only Super Admin can moderate signups.
 149          if ( ! empty( $this->subsite_activated ) ) {
 150              $this->capability = 'manage_network_users';
 151          }
 152      }
 153  
 154      /**
 155       * Set admin-related actions and filters.
 156       *
 157       * @since 2.0.0
 158       */
 159  	private function setup_actions() {
 160  
 161          /** Extended Profile *************************************************
 162           */
 163  
 164          // Enqueue all admin JS and CSS.
 165          add_action( 'bp_admin_enqueue_scripts', array( $this, 'enqueue_scripts'   )        );
 166  
 167          // Add some page specific output to the <head>.
 168          add_action( 'bp_admin_head',            array( $this, 'admin_head'        ), 999   );
 169  
 170          // Add menu item to all users menu.
 171          add_action( 'admin_menu',               array( $this, 'admin_menus'       ), 5     );
 172          add_action( 'network_admin_menu',       array( $this, 'admin_menus'       ), 5     );
 173          add_action( 'user_admin_menu',          array( $this, 'user_profile_menu' ), 5     );
 174  
 175          // Create the Profile Navigation (Profile/Extended Profile).
 176          add_action( 'edit_user_profile',        array( $this, 'profile_nav'       ), 99, 1 );
 177          add_action( 'show_user_profile',        array( $this, 'profile_nav'       ), 99, 1 );
 178  
 179          // Editing users of a specific site.
 180          add_action( "admin_head-site-users.php", array( $this, 'profile_admin_head' ) );
 181  
 182          // Add a row action to users listing.
 183          if ( bp_core_do_network_admin() ) {
 184              add_filter( 'ms_user_row_actions',        array( $this, 'row_actions'                    ), 10, 2 );
 185              add_action( 'admin_init',                 array( $this, 'add_edit_profile_url_filter'    )        );
 186              add_action( 'wp_after_admin_bar_render',  array( $this, 'remove_edit_profile_url_filter' )        );
 187          }
 188  
 189          // Add user row actions for single site.
 190          add_filter( 'user_row_actions', array( $this, 'row_actions' ), 10, 2 );
 191  
 192          // Process changes to member type.
 193          add_action( 'bp_members_admin_load', array( $this, 'process_member_type_update' ) );
 194  
 195          /** Signups **********************************************************
 196           */
 197  
 198          if ( is_admin() ) {
 199  
 200              // Filter non multisite user query to remove sign-up users.
 201              if ( ! is_multisite() ) {
 202                  add_action( 'pre_user_query', array( $this, 'remove_signups_from_user_query' ), 10, 1 );
 203              }
 204  
 205              // Reorganise the views navigation in users.php and signups page.
 206              if ( current_user_can( $this->capability ) ) {
 207                  $user_screen = $this->users_screen;
 208  
 209                  /**
 210                   * Users screen on multiblog is users, but signups
 211                   * need to be managed in the network for this case
 212                   */
 213                  if ( bp_is_network_activated() && bp_is_multiblog_mode() && false === strpos( $user_screen, '-network' ) ) {
 214                      $user_screen .= '-network';
 215                  }
 216  
 217                  add_filter( "views_{$user_screen}", array( $this, 'signup_filter_view'    ), 10, 1 );
 218                  add_filter( 'set-screen-option',    array( $this, 'signup_screen_options' ), 10, 3 );
 219              }
 220  
 221              // Registration is turned on.
 222              add_action( 'update_site_option_registration',  array( $this, 'multisite_registration_on' ),   10, 2 );
 223              add_action( 'update_option_users_can_register', array( $this, 'single_site_registration_on' ), 10, 2 );
 224  
 225              // Member invitations are enabled.
 226              if ( bp_is_network_activated() ) {
 227                  add_action( 'update_site_option_bp-enable-members-invitations', array( $this, 'multisite_registration_on' ), 10, 2 );
 228              } else {
 229                  add_action( 'update_option_bp-enable-members-invitations', array( $this, 'single_site_registration_on' ), 10, 2 );
 230              }
 231          }
 232  
 233          /** Users List - Members Types ***************************************
 234           */
 235  
 236          if ( is_admin() && bp_get_member_types() ) {
 237  
 238              // Add "Change type" <select> to WP admin users list table and process bulk members type changes.
 239              add_action( 'restrict_manage_users', array( $this, 'users_table_output_type_change_select' ) );
 240              add_action( 'load-users.php',        array( $this, 'users_table_process_bulk_type_change'  ) );
 241  
 242              // Add the member type column to the WP admin users list table.
 243              add_filter( 'manage_users_columns',       array( $this, 'users_table_add_type_column'    )        );
 244              add_filter( 'manage_users_custom_column', array( $this, 'users_table_populate_type_cell' ), 10, 3 );
 245  
 246              // Filter WP admin users list table to include users of the specified type.
 247              add_filter( 'pre_get_users', array( $this, 'users_table_filter_by_type' ) );
 248          }
 249      }
 250  
 251      /**
 252       * Create registration pages when multisite user registration is turned on.
 253       *
 254       * @since 2.7.0
 255       *
 256       * @param string $option_name Current option name; value is always 'registration'.
 257       * @param string $value
 258       */
 259  	public function multisite_registration_on( $option_name, $value ) {
 260          // Is registration enabled or are network invitations enabled?
 261          if ( ( 'user' === $value || 'all' === $value )
 262              || bp_get_members_invitations_allowed() ) {
 263              bp_core_add_page_mappings( array(
 264                  'register' => 1,
 265                  'activate' => 1
 266              ) );
 267          }
 268      }
 269  
 270      /**
 271       * Create registration pages when single site registration is turned on.
 272       *
 273       * @since 2.7.0
 274       *
 275       * @param string $old_value
 276       * @param string $value
 277       */
 278  	public function single_site_registration_on( $old_value, $value ) {
 279          // Single site.
 280          if ( ! is_multisite() && ( ! empty( $value ) || bp_get_members_invitations_allowed() ) ) {
 281              bp_core_add_page_mappings( array(
 282                  'register' => 1,
 283                  'activate' => 1
 284              ) );
 285          }
 286      }
 287  
 288      /**
 289       * Get the user ID.
 290       *
 291       * Look for $_GET['user_id']. If anything else, force the user ID to the
 292       * current user's ID so they aren't left without a user to edit.
 293       *
 294       * @since 2.1.0
 295       *
 296       * @return int
 297       */
 298  	private function get_user_id() {
 299          if ( ! empty( $this->user_id ) ) {
 300              return $this->user_id;
 301          }
 302  
 303          $this->user_id = (int) get_current_user_id();
 304  
 305          // We'll need a user ID when not on self profile.
 306          if ( ! empty( $_GET['user_id'] ) ) {
 307              $this->user_id = (int) $_GET['user_id'];
 308          }
 309  
 310          return $this->user_id;
 311      }
 312  
 313      /**
 314       * Can the current user edit the one displayed.
 315       *
 316       * Self profile editing / or bp_moderate check.
 317       * This might be replaced by more granular capabilities
 318       * in the future.
 319       *
 320       * @since 2.1.0
 321       *
 322       * @param int $user_id ID of the user being checked for edit ability.
 323       *
 324       * @return bool
 325       */
 326  	private function member_can_edit( $user_id = 0 ) {
 327          $retval = false;
 328  
 329          // Bail if no user ID was passed.
 330          if ( empty( $user_id ) ) {
 331              return $retval;
 332          }
 333  
 334          // Member can edit if they are viewing their own profile.
 335          if ( $this->current_user_id === $user_id ) {
 336              $retval = true;
 337  
 338          // Trust the 'bp_moderate' capability.
 339          } else {
 340              $retval = bp_current_user_can( 'bp_moderate' );
 341          }
 342  
 343          return $retval;
 344      }
 345  
 346      /**
 347       * Get admin notice when saving a user or member profile.
 348       *
 349       * @since 2.1.0
 350       *
 351       * @return array
 352       */
 353  	private function get_user_notice() {
 354  
 355          // Setup empty notice for return value.
 356          $notice = array();
 357  
 358          // Updates.
 359          if ( ! empty( $_REQUEST['updated'] ) ) {
 360              switch ( $_REQUEST['updated'] ) {
 361              case 'avatar':
 362                  $notice = array(
 363                      'class'   => 'updated',
 364                      'message' => __( 'Profile photo was deleted.', 'buddypress' )
 365                  );
 366                  break;
 367              case 'ham' :
 368                  $notice = array(
 369                      'class'   => 'updated',
 370                      'message' => __( 'User removed as spammer.', 'buddypress' )
 371                  );
 372                  break;
 373              case 'spam' :
 374                  $notice = array(
 375                      'class'   => 'updated',
 376                      'message' => __( 'User marked as spammer. Spam users are visible only to site admins.', 'buddypress' )
 377                  );
 378                  break;
 379              case 1 :
 380                  $notice = array(
 381                      'class'   => 'updated',
 382                      'message' => __( 'Profile updated.', 'buddypress' )
 383                  );
 384                  break;
 385              }
 386          }
 387  
 388          // Errors.
 389          if ( ! empty( $_REQUEST['error'] ) ) {
 390              switch ( $_REQUEST['error'] ) {
 391              case 'avatar':
 392                  $notice = array(
 393                      'class'   => 'error',
 394                      'message' => __( 'There was a problem deleting that profile photo. Please try again.', 'buddypress' )
 395                  );
 396                  break;
 397              case 'ham' :
 398                  $notice = array(
 399                      'class'   => 'error',
 400                      'message' => __( 'User could not be removed as spammer.', 'buddypress' )
 401                  );
 402                  break;
 403              case 'spam' :
 404                  $notice = array(
 405                      'class'   => 'error',
 406                      'message' => __( 'User could not be marked as spammer.', 'buddypress' )
 407                  );
 408                  break;
 409              case 1 :
 410                  $notice = array(
 411                      'class'   => 'error',
 412                      'message' => __( 'An error occurred while trying to update the profile.', 'buddypress' )
 413                  );
 414                  break;
 415              case 2:
 416                  $notice = array(
 417                      'class'   => 'error',
 418                      'message' => __( 'Your changes have not been saved. Please fill in all required fields, and save your changes again.', 'buddypress' )
 419                  );
 420                  break;
 421              case 3:
 422                  $notice = array(
 423                      'class'   => 'error',
 424                      'message' => __( 'There was a problem updating some of your profile information. Please try again.', 'buddypress' )
 425                  );
 426                  break;
 427              }
 428          }
 429  
 430          return $notice;
 431      }
 432  
 433      /**
 434       * Create the /user/ admin Profile submenus for all members.
 435       *
 436       * @since 2.1.0
 437       *
 438       */
 439  	public function user_profile_menu() {
 440  
 441          // Setup the hooks array.
 442          $hooks = array();
 443  
 444          // Add the faux "Edit Profile" submenu page.
 445          $hooks['user'] = $this->user_page = add_submenu_page(
 446              'profile.php',
 447              __( 'Edit Profile',  'buddypress' ),
 448              __( 'Edit Profile',  'buddypress' ),
 449              'exist',
 450              'bp-profile-edit',
 451              array( $this, 'user_admin' )
 452          );
 453  
 454          // Setup the screen ID's.
 455          $this->screen_id = array(
 456              $this->user_page    . '-user',
 457              $this->user_profile . '-user'
 458          );
 459  
 460          // Loop through new hooks and add method actions.
 461          foreach ( $hooks as $key => $hook ) {
 462              add_action( "load-{$hook}", array( $this, $key . '_admin_load' ) );
 463          }
 464  
 465          // Add the profile_admin_head method to proper admin_head actions.
 466          add_action( "admin_head-{$this->user_page}", array( $this, 'profile_admin_head' ) );
 467          add_action( "admin_head-profile.php",        array( $this, 'profile_admin_head' ) );
 468      }
 469  
 470      /**
 471       * Create the All Users / Profile > Edit Profile and All Users Signups submenus.
 472       *
 473       * @since 2.0.0
 474       *
 475       */
 476  	public function admin_menus() {
 477  
 478          // Setup the hooks array.
 479          $hooks = array();
 480  
 481          // Manage user's profile.
 482          $hooks['user'] = $this->user_page = add_submenu_page(
 483              $this->user_profile . '.php',
 484              __( 'Edit Profile',  'buddypress' ),
 485              __( 'Edit Profile',  'buddypress' ),
 486              'read',
 487              'bp-profile-edit',
 488              array( $this, 'user_admin' )
 489          );
 490  
 491          // Only show sign-ups where they belong.
 492          if ( ( ! bp_is_network_activated() && ! is_network_admin() ) || ( is_network_admin() && bp_is_network_activated() ) ) {
 493  
 494              // Manage signups.
 495              $hooks['signups'] = $this->signups_page = add_users_page(
 496                  __( 'Manage Signups',  'buddypress' ),
 497                  __( 'Manage Signups',  'buddypress' ),
 498                  $this->capability,
 499                  'bp-signups',
 500                  array( $this, 'signups_admin' )
 501              );
 502          }
 503  
 504          // For consistency with non-Multisite, we add a Tools menu in
 505          // the Network Admin as a home for our Tools panel.
 506          if ( is_multisite() && bp_core_do_network_admin() ) {
 507              $tools_parent = 'network-tools';
 508          } else {
 509              $tools_parent = 'tools.php';
 510          }
 511  
 512          $hooks['members_invitations'] = $this->members_invites_page = add_submenu_page(
 513              $tools_parent,
 514              __( 'Manage Invitations',  'buddypress' ),
 515              __( 'Manage Invitations',  'buddypress' ),
 516              $this->capability,
 517              'bp-members-invitations',
 518              array( $this, 'invitations_admin' )
 519          );
 520  
 521          $edit_page         = 'user-edit';
 522          $profile_page      = 'profile';
 523          $this->users_page  = 'users';
 524  
 525          // Self profile check is needed for this pages.
 526          $page_head = array(
 527              $edit_page        . '.php',
 528              $profile_page     . '.php',
 529              $this->user_page,
 530              $this->users_page . '.php',
 531          );
 532  
 533          // Append '-network' to each array item if in network admin.
 534          if ( is_network_admin() ) {
 535              $edit_page          .= '-network';
 536              $profile_page       .= '-network';
 537              $this->user_page    .= '-network';
 538              $this->users_page   .= '-network';
 539              $this->signups_page .= '-network';
 540  
 541              $this->members_invites_page .= '-network';
 542          }
 543  
 544          // Setup the screen ID's.
 545          $this->screen_id = array(
 546              $edit_page,
 547              $this->user_page,
 548              $profile_page
 549          );
 550  
 551          // Loop through new hooks and add method actions.
 552          foreach ( $hooks as $key => $hook ) {
 553              add_action( "load-{$hook}", array( $this, $key . '_admin_load' ) );
 554          }
 555  
 556          // Add the profile_admin_head method to proper admin_head actions.
 557          foreach ( $page_head as $head ) {
 558              add_action( "admin_head-{$head}", array( $this, 'profile_admin_head' ) );
 559          }
 560  
 561          // Highlight the BuddyPress tools submenu when managing invitations.
 562          add_action( "admin_head-{$this->members_invites_page}", 'bp_core_modify_admin_menu_highlight' );
 563      }
 564  
 565      /**
 566       * Highlight the Users menu if on Edit Profile and check if on the user's admin profile.
 567       *
 568       * @since 2.1.0
 569       */
 570  	public function profile_admin_head() {
 571          global $submenu_file, $parent_file;
 572  
 573          // Is the user editing their own profile?
 574          if ( is_user_admin() || ( defined( 'IS_PROFILE_PAGE' ) && IS_PROFILE_PAGE ) ) {
 575              $this->is_self_profile = true;
 576  
 577          // Is the user attempting to edit their own profile.
 578          } elseif ( isset( $_GET['user_id' ] ) || ( isset( $_GET['page'] ) && ( 'bp-profile-edit' === $_GET['page'] ) ) ) {
 579              $this->is_self_profile = (bool) ( $this->get_user_id() === $this->current_user_id );
 580          }
 581  
 582          // Force the parent file to users.php to open the correct top level menu
 583          // but only if not editing a site via the network site editing page.
 584          if ( 'sites.php' !== $parent_file ) {
 585              $parent_file  = 'users.php';
 586              $submenu_file = 'users.php';
 587          }
 588  
 589          // Editing your own profile, so recheck some vars.
 590          if ( true === $this->is_self_profile ) {
 591  
 592              // Use profile.php as the edit page.
 593              $edit_page = 'profile.php';
 594  
 595              // Set profile.php as the parent & sub files to correct the menu nav.
 596              if ( is_blog_admin() || is_user_admin() ) {
 597                  $parent_file  = 'profile.php';
 598                  $submenu_file = 'profile.php';
 599              }
 600  
 601          // Not editing yourself, so use user-edit.php.
 602          } else {
 603              $edit_page = 'user-edit.php';
 604          }
 605  
 606          if ( is_user_admin() ) {
 607              $this->edit_profile_url = add_query_arg( $this->edit_profile_args, user_admin_url( 'profile.php' ) );
 608              $this->edit_url         = user_admin_url( 'profile.php' );
 609  
 610          } elseif ( is_blog_admin() ) {
 611              $this->edit_profile_url = add_query_arg( $this->edit_profile_args, admin_url( 'users.php' ) );
 612              $this->edit_url         = admin_url( $edit_page );
 613  
 614          } elseif ( is_network_admin() ) {
 615              $this->edit_profile_url = add_query_arg( $this->edit_profile_args, network_admin_url( 'users.php' ) );
 616              $this->edit_url         = network_admin_url( $edit_page );
 617          }
 618      }
 619  
 620      /**
 621       * Remove the Edit Profile page.
 622       *
 623       * We add these pages in order to integrate with WP's Users panel, but
 624       * we want them to show up as a row action of the WP panel, not as separate
 625       * subnav items under the Users menu.
 626       *
 627       * @since 2.0.0
 628       */
 629  	public function admin_head() {
 630          remove_submenu_page( 'users.php',   'bp-profile-edit' );
 631          remove_submenu_page( 'profile.php', 'bp-profile-edit' );
 632  
 633          // Manage Invitations Tool screen is a tab of BP Tools.
 634          if ( is_network_admin() ) {
 635              remove_submenu_page( 'network-tools', 'bp-members-invitations' );
 636          } else {
 637              remove_submenu_page( 'tools.php', 'bp-members-invitations' );
 638          }
 639      }
 640  
 641      /** Community Profile *****************************************************/
 642  
 643      /**
 644       * Add some specific styling to the Edit User and Edit User's Profile page.
 645       *
 646       * @since 2.0.0
 647       */
 648  	public function enqueue_scripts() {
 649          if ( ! in_array( get_current_screen()->id, $this->screen_id ) ) {
 650              return;
 651          }
 652  
 653          $min = bp_core_get_minified_asset_suffix();
 654          $css = $this->css_url . "admin{$min}.css";
 655  
 656          /**
 657           * Filters the CSS URL to enqueue in the Members admin area.
 658           *
 659           * @since 2.0.0
 660           *
 661           * @param string $css URL to the CSS admin file to load.
 662           */
 663          $css = apply_filters( 'bp_members_admin_css', $css );
 664  
 665          wp_enqueue_style( 'bp-members-css', $css, array(), bp_get_version() );
 666  
 667          wp_style_add_data( 'bp-members-css', 'rtl', 'replace' );
 668          if ( $min ) {
 669              wp_style_add_data( 'bp-members-css', 'suffix', $min );
 670          }
 671  
 672          // Only load JavaScript for BuddyPress profile.
 673          if ( get_current_screen()->id == $this->user_page ) {
 674              $js = $this->js_url . "admin{$min}.js";
 675  
 676              /**
 677               * Filters the JS URL to enqueue in the Members admin area.
 678               *
 679               * @since 2.0.0
 680               *
 681               * @param string $js URL to the JavaScript admin file to load.
 682               */
 683              $js = apply_filters( 'bp_members_admin_js', $js );
 684              wp_enqueue_script( 'bp-members-js', $js, array( 'jquery' ), bp_get_version(), true );
 685  
 686              if ( ! bp_core_get_root_option( 'bp-disable-avatar-uploads' ) && buddypress()->avatar->show_avatars ) {
 687                  /**
 688                   * Get Thickbox.
 689                   *
 690                   * We cannot simply use add_thickbox() here as WordPress is not playing
 691                   * nice with Thickbox width/height see https://core.trac.wordpress.org/ticket/17249
 692                   * Using media-upload might be interesting in the future for the send to editor stuff
 693                   * and we make sure the tb_window is wide enough
 694                   */
 695                  wp_enqueue_style ( 'thickbox' );
 696                  wp_enqueue_script( 'media-upload' );
 697  
 698                  // Get Avatar Uploader.
 699                  bp_attachments_enqueue_scripts( 'BP_Attachment_Avatar' );
 700              }
 701          }
 702  
 703          /**
 704           * Fires after all of the members JavaScript and CSS are enqueued.
 705           *
 706           * @since 2.0.0
 707           *
 708           * @param string $id        ID of the current screen.
 709           * @param array  $screen_id Array of allowed screens to add scripts and styles to.
 710           */
 711          do_action( 'bp_members_admin_enqueue_scripts', get_current_screen()->id, $this->screen_id );
 712      }
 713  
 714      /**
 715       * Create the Profile navigation in Edit User & Edit Profile pages.
 716       *
 717       * @since 2.0.0
 718       *
 719       * @param object|null $user   User to create profile navigation for.
 720       * @param string      $active Which profile to highlight.
 721       * @return string|null
 722       */
 723  	public function profile_nav( $user = null, $active = 'WordPress' ) {
 724  
 725          // Bail if no user ID exists here.
 726          if ( empty( $user->ID ) ) {
 727              return;
 728          }
 729  
 730          // Add the user ID to query arguments when not editing yourself.
 731          if ( false === $this->is_self_profile ) {
 732              $query_args = array( 'user_id' => $user->ID );
 733          } else {
 734              $query_args = array();
 735          }
 736  
 737          // Conditionally add a referer if it exists in the existing request.
 738          if ( ! empty( $_REQUEST['wp_http_referer'] ) ) {
 739              $wp_http_referer = wp_unslash( $_REQUEST['wp_http_referer'] );
 740              $wp_http_referer = wp_validate_redirect( esc_url_raw( $wp_http_referer ) );
 741              $query_args['wp_http_referer'] = urlencode( $wp_http_referer );
 742          }
 743  
 744          // Setup the two distinct "edit" URL's.
 745          $community_url = add_query_arg( $query_args, $this->edit_profile_url );
 746          $wordpress_url = add_query_arg( $query_args, $this->edit_url         );
 747  
 748          $bp_active = false;
 749          $wp_active = ' nav-tab-active';
 750          if ( 'BuddyPress' === $active ) {
 751              $bp_active = ' nav-tab-active';
 752              $wp_active = false;
 753          } ?>
 754  
 755          <h2 id="profile-nav" class="nav-tab-wrapper">
 756              <?php
 757              /**
 758               * In configs where BuddyPress is not network activated, as regular
 759               * admins do not have the capacity to edit other users, we must add
 760               * this check.
 761               */
 762              if ( current_user_can( 'edit_user', $user->ID ) ) : ?>
 763  
 764                  <a class="nav-tab<?php echo esc_attr( $wp_active ); ?>" href="<?php echo esc_url( $wordpress_url );?>"><?php _e( 'Profile', 'buddypress' ); ?></a>
 765  
 766              <?php endif; ?>
 767  
 768              <a class="nav-tab<?php echo esc_attr( $bp_active ); ?>" href="<?php echo esc_url( $community_url );?>"><?php _e( 'Extended Profile', 'buddypress' ); ?></a>
 769          </h2>
 770  
 771          <?php
 772      }
 773  
 774      /**
 775       * Set up the user's profile admin page.
 776       *
 777       * Loaded before the page is rendered, this function does all initial
 778       * setup, including: processing form requests, registering contextual
 779       * help, and setting up screen options.
 780       *
 781       * @since 2.0.0
 782       * @since 6.0.0 The `delete_avatar` action is now managed into this method.
 783       */
 784  	public function user_admin_load() {
 785  
 786          // Get the user ID.
 787          $user_id = $this->get_user_id();
 788  
 789          // Can current user edit this profile?
 790          if ( ! $this->member_can_edit( $user_id ) ) {
 791              wp_die( __( 'You cannot edit the requested user.', 'buddypress' ) );
 792          }
 793  
 794          // Build redirection URL.
 795          $redirect_to = remove_query_arg( array( 'action', 'error', 'updated', 'spam', 'ham', 'delete_avatar' ), $_SERVER['REQUEST_URI'] );
 796          $doaction    = ! empty( $_REQUEST['action'] ) ? $_REQUEST['action'] : false;
 797  
 798          if ( ! empty( $_REQUEST['user_status'] ) ) {
 799              $spam = (bool) ( 'spam' === $_REQUEST['user_status'] );
 800  
 801              if ( $spam !== bp_is_user_spammer( $user_id ) ) {
 802                  $doaction = $_REQUEST['user_status'];
 803              }
 804          }
 805  
 806          /**
 807           * Fires at the start of the signups admin load.
 808           *
 809           * @since 2.0.0
 810           *
 811           * @param string $doaction Current bulk action being processed.
 812           * @param array  $_REQUEST Current $_REQUEST global.
 813           */
 814          do_action_ref_array( 'bp_members_admin_load', array( $doaction, $_REQUEST ) );
 815  
 816          /**
 817           * Filters the allowed actions for use in the user admin page.
 818           *
 819           * @since 2.0.0
 820           *
 821           * @param array $value Array of allowed actions to use.
 822           */
 823          $allowed_actions = apply_filters( 'bp_members_admin_allowed_actions', array( 'update', 'delete_avatar', 'spam', 'ham' ) );
 824  
 825          // Prepare the display of the Community Profile screen.
 826          if ( ! in_array( $doaction, $allowed_actions ) ) {
 827              add_screen_option( 'layout_columns', array( 'default' => 2, 'max' => 2, ) );
 828  
 829              get_current_screen()->add_help_tab( array(
 830                  'id'      => 'bp-profile-edit-overview',
 831                  'title'   => __( 'Overview', 'buddypress' ),
 832                  'content' =>
 833                  '<p>' . __( 'This is the admin view of a user&#39;s profile.', 'buddypress' ) . '</p>' .
 834                  '<p>' . __( 'In the main column, you can edit the fields of the user&#39;s extended profile.', 'buddypress' ) . '</p>' .
 835                  '<p>' . __( 'In the right-hand column, you can update the user&#39;s status, delete the user&#39;s avatar, and view recent statistics.', 'buddypress' ) . '</p>'
 836              ) );
 837  
 838              // Help panel - sidebar links.
 839              get_current_screen()->set_help_sidebar(
 840                  '<p><strong>' . __( 'For more information:', 'buddypress' ) . '</strong></p>' .
 841                  '<p>' . __( '<a href="https://codex.buddypress.org/administrator-guide/extended-profiles/">Managing Profiles</a>', 'buddypress' ) . '</p>' .
 842                  '<p>' . __( '<a href="https://buddypress.org/support/">Support Forums</a>', 'buddypress' ) . '</p>'
 843              );
 844  
 845              // Register metaboxes for the edit screen.
 846              add_meta_box(
 847                  'submitdiv',
 848                  _x( 'Status', 'members user-admin edit screen', 'buddypress' ),
 849                  array( $this, 'user_admin_status_metabox' ),
 850                  get_current_screen()->id,
 851                  'side',
 852                  'core'
 853              );
 854  
 855              // In case xprofile is not active.
 856              $this->stats_metabox->context  = 'normal';
 857              $this->stats_metabox->priority = 'core';
 858  
 859              /**
 860               * Fires before loading the profile fields if component is active.
 861               *
 862               * Plugins should not use this hook, please use 'bp_members_admin_user_metaboxes' instead.
 863               *
 864               * @since 2.0.0
 865               *
 866               * @param int    $user_id       Current user ID for the screen.
 867               * @param string $id            Current screen ID.
 868               * @param object $stats_metabox Object holding position data for use with the stats metabox.
 869               */
 870              do_action_ref_array( 'bp_members_admin_xprofile_metabox', array( $user_id, get_current_screen()->id, $this->stats_metabox ) );
 871  
 872              // If xProfile is inactive, difficult to know what's profile we're on.
 873              if ( 'normal' === $this->stats_metabox->context ) {
 874                  $display_name = bp_core_get_user_displayname( $user_id );
 875              } else {
 876                  $display_name = __( 'Member', 'buddypress' );
 877              }
 878  
 879              // Set the screen id.
 880              $screen_id = get_current_screen()->id;
 881  
 882              // User Stat metabox.
 883              add_meta_box(
 884                  'bp_members_admin_user_stats',
 885                  sprintf(
 886                      /* translators: %s: member name */
 887                      _x( "%s's Stats", 'members user-admin edit screen', 'buddypress' ),
 888                      $display_name
 889                  ),
 890                  array( $this, 'user_admin_stats_metabox' ),
 891                  $screen_id,
 892                  sanitize_key( $this->stats_metabox->context ),
 893                  sanitize_key( $this->stats_metabox->priority )
 894              );
 895  
 896              if ( buddypress()->avatar->show_avatars ) {
 897                  // Avatar Metabox.
 898                  add_meta_box(
 899                      'bp_members_user_admin_avatar',
 900                      _x( 'Profile Photo', 'members user-admin edit screen', 'buddypress' ),
 901                      array( $this, 'user_admin_avatar_metabox' ),
 902                      $screen_id,
 903                      'side',
 904                      'low'
 905                  );
 906              }
 907  
 908              // Member Type metabox. Only added if member types have been registered.
 909              $member_types = bp_get_member_types();
 910              if ( ! empty( $member_types ) ) {
 911                  add_meta_box(
 912                      'bp_members_admin_member_type',
 913                      _x( 'Member Type', 'members user-admin edit screen', 'buddypress' ),
 914                      array( $this, 'user_admin_member_type_metabox' ),
 915                      $screen_id,
 916                      'side',
 917                      'core'
 918                  );
 919              }
 920  
 921              /**
 922               * Fires at the end of the Community Profile screen.
 923               *
 924               * Plugins can restrict metabox to "bp_moderate" admins by checking if
 925               * the first argument ($this->is_self_profile) is false in their callback.
 926               * They can also restrict their metabox to self profile editing
 927               * by setting it to true.
 928               *
 929               * @since 2.0.0
 930               *
 931               * @param bool $is_self_profile Whether or not it is the current user's profile.
 932               * @param int  $user_id         Current user ID.
 933               */
 934              do_action( 'bp_members_admin_user_metaboxes', $this->is_self_profile, $user_id );
 935  
 936              // Enqueue JavaScript files.
 937              wp_enqueue_script( 'postbox'   );
 938              wp_enqueue_script( 'dashboard' );
 939  
 940          // Spam or Ham user.
 941          } elseif ( in_array( $doaction, array( 'spam', 'ham' ) ) && empty( $this->is_self_profile ) ) {
 942  
 943              check_admin_referer( 'edit-bp-profile_' . $user_id );
 944  
 945              if ( bp_core_process_spammer_status( $user_id, $doaction ) ) {
 946                  $redirect_to = add_query_arg( 'updated', $doaction, $redirect_to );
 947              } else {
 948                  $redirect_to = add_query_arg( 'error', $doaction, $redirect_to );
 949              }
 950  
 951              bp_core_redirect( $redirect_to );
 952  
 953          // Eventually delete avatar.
 954          } elseif ( 'delete_avatar' === $doaction ) {
 955  
 956              // Check the nonce.
 957              check_admin_referer( 'delete_avatar' );
 958  
 959              $redirect_to = remove_query_arg( '_wpnonce', $redirect_to );
 960  
 961              if ( bp_core_delete_existing_avatar( array( 'item_id' => $user_id ) ) ) {
 962                  $redirect_to = add_query_arg( 'updated', 'avatar', $redirect_to );
 963              } else {
 964                  $redirect_to = add_query_arg( 'error', 'avatar', $redirect_to );
 965              }
 966  
 967              bp_core_redirect( $redirect_to );
 968  
 969          // Update other stuff once above ones are done.
 970          } else {
 971              $this->redirect = $redirect_to;
 972  
 973              /**
 974               * Fires at end of user profile admin load if doaction does not match any available actions.
 975               *
 976               * @since 2.0.0
 977               *
 978               * @param string $doaction Current bulk action being processed.
 979               * @param int    $user_id  Current user ID.
 980               * @param array  $_REQUEST Current $_REQUEST global.
 981               * @param string $redirect Determined redirect url to send user to.
 982               */
 983              do_action_ref_array( 'bp_members_admin_update_user', array( $doaction, $user_id, $_REQUEST, $this->redirect ) );
 984  
 985              bp_core_redirect( $this->redirect );
 986          }
 987      }
 988  
 989      /**
 990       * Display the user's profile.
 991       *
 992       * @since 2.0.0
 993       */
 994  	public function user_admin() {
 995  
 996          if ( ! bp_current_user_can( 'bp_moderate' ) && empty( $this->is_self_profile ) ) {
 997              die( '-1' );
 998          }
 999  
1000          // Get the user ID.
1001          $user_id = $this->get_user_id();
1002          $user    = get_user_to_edit( $user_id );
1003  
1004          // Construct title.
1005          if ( true === $this->is_self_profile ) {
1006              $title = __( 'Profile',   'buddypress' );
1007          } else {
1008              $title = __( 'Edit User', 'buddypress' );
1009          }
1010  
1011          // Construct URL for form.
1012          $request_url     = remove_query_arg( array( 'action', 'error', 'updated', 'spam', 'ham' ), $_SERVER['REQUEST_URI'] );
1013          $form_action_url = add_query_arg( 'action', 'update', $request_url );
1014          $wp_http_referer = false;
1015          if ( ! empty( $_REQUEST['wp_http_referer'] ) ) {
1016              $wp_http_referer = wp_unslash( $_REQUEST['wp_http_referer'] );
1017              $wp_http_referer = remove_query_arg( array( 'action', 'updated' ), $wp_http_referer );
1018              $wp_http_referer = wp_validate_redirect( esc_url_raw( $wp_http_referer ) );
1019          }
1020  
1021          // Prepare notice for admin.
1022          $notice = $this->get_user_notice();
1023  
1024          if ( ! empty( $notice ) ) : ?>
1025  
1026              <div <?php if ( 'updated' === $notice['class'] ) : ?>id="message" <?php endif; ?>class="<?php echo esc_attr( $notice['class'] ); ?>  notice is-dismissible">
1027  
1028                  <p><?php echo esc_html( $notice['message'] ); ?></p>
1029  
1030                  <?php if ( !empty( $wp_http_referer ) && ( 'updated' === $notice['class'] ) ) : ?>
1031  
1032                      <p><a href="<?php echo esc_url( $wp_http_referer ); ?>"><?php esc_html_e( '&larr; Back to Users', 'buddypress' ); ?></a></p>
1033  
1034                  <?php endif; ?>
1035  
1036              </div>
1037  
1038          <?php endif; ?>
1039  
1040          <div class="wrap" id="community-profile-page">
1041              <h1 class="wp-heading-inline"><?php echo esc_html( $title ); ?></h1>
1042  
1043              <?php if ( empty( $this->is_self_profile ) ) : ?>
1044  
1045                  <?php if ( current_user_can( 'create_users' ) ) : ?>
1046  
1047                      <a href="user-new.php" class="page-title-action"><?php echo esc_html_x( 'Add New', 'user', 'buddypress' ); ?></a>
1048  
1049                  <?php elseif ( is_multisite() && current_user_can( 'promote_users' ) ) : ?>
1050  
1051                      <a href="user-new.php" class="page-title-action"><?php echo esc_html_x( 'Add Existing', 'user', 'buddypress' ); ?></a>
1052  
1053                  <?php endif; ?>
1054  
1055              <?php endif; ?>
1056  
1057              <hr class="wp-header-end">
1058  
1059              <?php if ( ! empty( $user ) ) :
1060  
1061                  $this->profile_nav( $user, 'BuddyPress' ); ?>
1062  
1063                  <form action="<?php echo esc_url( $form_action_url ); ?>" id="your-profile" method="post">
1064                      <div id="poststuff">
1065  
1066                          <div id="post-body" class="metabox-holder columns-<?php echo 1 == get_current_screen()->get_columns() ? '1' : '2'; ?>">
1067  
1068                              <div id="postbox-container-1" class="postbox-container">
1069                                  <?php do_meta_boxes( get_current_screen()->id, 'side', $user ); ?>
1070                              </div>
1071  
1072                              <div id="postbox-container-2" class="postbox-container">
1073                                  <?php do_meta_boxes( get_current_screen()->id, 'normal',   $user ); ?>
1074                                  <?php do_meta_boxes( get_current_screen()->id, 'advanced', $user ); ?>
1075                              </div>
1076                          </div><!-- #post-body -->
1077  
1078                      </div><!-- #poststuff -->
1079  
1080                      <?php wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?>
1081                      <?php wp_nonce_field( 'meta-box-order',  'meta-box-order-nonce', false ); ?>
1082                      <?php wp_nonce_field( 'edit-bp-profile_' . $user->ID ); ?>
1083  
1084                  </form>
1085  
1086              <?php else : ?>
1087  
1088                  <p><?php
1089                      printf(
1090                          '%1$s <a href="%2$s">%3$s</a>',
1091                          __( 'No user found with this ID.', 'buddypress' ),
1092                          esc_url( bp_get_admin_url( 'users.php' ) ),
1093                          __( 'Go back and try again.', 'buddypress' )
1094                      );
1095                  ?></p>
1096  
1097              <?php endif; ?>
1098  
1099          </div><!-- .wrap -->
1100          <?php
1101      }
1102  
1103      /**
1104       * Render the Status metabox for user's profile screen.
1105       *
1106       * Actions are:
1107       * - Update profile fields if xProfile component is active
1108       * - Spam/Unspam user
1109       *
1110       * @since 2.0.0
1111       *
1112       * @param WP_User|null $user The WP_User object to be edited.
1113       */
1114  	public function user_admin_status_metabox( $user = null ) {
1115  
1116          // Bail if no user id or if the user has not activated their account yet.
1117          if ( empty( $user->ID ) ) {
1118              return;
1119          }
1120  
1121          // Bail if user has not been activated yet (how did you get here?).
1122          if ( isset( $user->user_status ) && ( 2 == $user->user_status ) ) : ?>
1123  
1124              <p class="not-activated"><?php esc_html_e( 'User account has not yet been activated', 'buddypress' ); ?></p><br/>
1125  
1126              <?php return;
1127  
1128          endif; ?>
1129  
1130          <div class="submitbox" id="submitcomment">
1131              <div id="minor-publishing">
1132                  <div id="misc-publishing-actions">
1133                      <?php
1134  
1135                      // Get the spam status once here to compare against below.
1136                      $is_spammer = bp_is_user_spammer( $user->ID );
1137  
1138                      /**
1139                       * In configs where BuddyPress is not network activated,
1140                       * regular admins cannot mark a user as a spammer on front
1141                       * end. This prevent them to do it in the back end.
1142                       *
1143                       * Also prevent admins from marking themselves or other
1144                       * admins as spammers.
1145                       */
1146                      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' ) ) ) : ?>
1147  
1148                          <div class="misc-pub-section" id="comment-status-radio">
1149                              <label class="approved"><input type="radio" name="user_status" value="ham" <?php checked( $is_spammer, false ); ?>><?php esc_html_e( 'Active', 'buddypress' ); ?></label><br />
1150                              <label class="spam"><input type="radio" name="user_status" value="spam" <?php checked( $is_spammer, true ); ?>><?php esc_html_e( 'Spammer', 'buddypress' ); ?></label>
1151                          </div>
1152  
1153                      <?php endif ;?>
1154  
1155                      <div class="misc-pub-section curtime misc-pub-section-last">
1156                          <?php
1157  
1158                          // Translators: Publish box date format, see http://php.net/date.
1159                          $datef = __( 'M j, Y @ G:i', 'buddypress' );
1160                          $date  = date_i18n( $datef, strtotime( $user->user_registered ) );
1161                          ?>
1162                          <span id="timestamp">
1163                              <?php
1164                              /* translators: %s: registration date */
1165                              printf( __( 'Registered on: %s', 'buddypress' ), '<strong>' . $date . '</strong>' );
1166                              ?>
1167                          </span>
1168                      </div>
1169                  </div> <!-- #misc-publishing-actions -->
1170  
1171                  <div class="clear"></div>
1172              </div><!-- #minor-publishing -->
1173  
1174              <div id="major-publishing-actions">
1175  
1176                  <div id="publishing-action">
1177                      <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>
1178                      <?php submit_button( esc_html__( 'Update Profile', 'buddypress' ), 'primary', 'save', false ); ?>
1179                  </div>
1180                  <div class="clear"></div>
1181              </div><!-- #major-publishing-actions -->
1182  
1183          </div><!-- #submitcomment -->
1184  
1185          <?php
1186      }
1187  
1188      /**
1189       * Render the fallback metabox in case a user has been marked as a spammer.
1190       *
1191       * @since 2.0.0
1192       *
1193       * @param WP_User|null $user The WP_User object to be edited.
1194       */
1195  	public function user_admin_spammer_metabox( $user = null ) {
1196      ?>
1197          <p>
1198              <?php
1199              /* translators: %s: member name */
1200              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 ) ) );
1201              ?>
1202          </p>
1203      <?php
1204      }
1205  
1206      /**
1207       * Render the Stats metabox to moderate inappropriate images.
1208       *
1209       * @since 2.0.0
1210       *
1211       * @param WP_User|null $user The WP_User object to be edited.
1212       */
1213  	public function user_admin_stats_metabox( $user = null ) {
1214  
1215          // Bail if no user ID.
1216          if ( empty( $user->ID ) ) {
1217              return;
1218          }
1219  
1220          // If account is not activated last activity is the time user registered.
1221          if ( isset( $user->user_status ) && 2 == $user->user_status ) {
1222              $last_active = $user->user_registered;
1223  
1224          // Account is activated, getting user's last activity.
1225          } else {
1226              $last_active = bp_get_user_last_activity( $user->ID );
1227          }
1228  
1229          $datef = __( 'M j, Y @ G:i', 'buddypress' );
1230          $date  = date_i18n( $datef, strtotime( $last_active ) ); ?>
1231  
1232          <ul>
1233              <li class="bp-members-profile-stats">
1234                  <?php
1235                  /* translators: %s: date */
1236                  printf( __( 'Last active: %1$s', 'buddypress' ), '<strong>' . $date . '</strong>' );
1237                  ?>
1238              </li>
1239  
1240              <?php
1241              // Loading other stats only if user has activated their account.
1242              if ( empty( $user->user_status ) ) {
1243  
1244                  /**
1245                   * Fires in the user stats metabox if the user has activated their account.
1246                   *
1247                   * @since 2.0.0
1248                   *
1249                   * @param array  $value Array holding the user ID.
1250                   * @param object $user  Current displayed user object.
1251                   */
1252                  do_action( 'bp_members_admin_user_stats', array( 'user_id' => $user->ID ), $user );
1253              }
1254              ?>
1255          </ul>
1256  
1257          <?php
1258      }
1259  
1260      /**
1261       * Render the Avatar metabox to moderate inappropriate images.
1262       *
1263       * @since 6.0.0
1264       *
1265       * @param WP_User|null $user The WP_User object for the user being edited.
1266       */
1267  	public function user_admin_avatar_metabox( $user = null ) {
1268  
1269          if ( empty( $user->ID ) ) {
1270              return;
1271          } ?>
1272  
1273          <div class="avatar">
1274  
1275              <?php echo bp_core_fetch_avatar( array(
1276                  'item_id' => $user->ID,
1277                  'object'  => 'user',
1278                  'type'    => 'full',
1279                  'title'   => $user->display_name
1280              ) ); ?>
1281  
1282              <?php if ( bp_get_user_has_avatar( $user->ID ) ) :
1283  
1284                  $query_args = array(
1285                      'user_id' => $user->ID,
1286                      'action'  => 'delete_avatar'
1287                  );
1288  
1289                  if ( ! empty( $_REQUEST['wp_http_referer'] ) ) {
1290                      $wp_http_referer = wp_unslash( $_REQUEST['wp_http_referer'] );
1291                      $wp_http_referer = remove_query_arg( array( 'action', 'updated' ), $wp_http_referer );
1292                      $wp_http_referer = wp_validate_redirect( esc_url_raw( $wp_http_referer ) );
1293                      $query_args['wp_http_referer'] = urlencode( $wp_http_referer );
1294                  }
1295  
1296                  $community_url = add_query_arg( $query_args, $this->edit_profile_url );
1297                  $delete_link   = wp_nonce_url( $community_url, 'delete_avatar' ); ?>
1298  
1299                  <a href="<?php echo esc_url( $delete_link ); ?>" class="bp-members-avatar-user-admin"><?php esc_html_e( 'Delete Profile Photo', 'buddypress' ); ?></a>
1300  
1301              <?php endif;
1302  
1303              // Load the Avatar UI templates if user avatar uploads are enabled.
1304              if ( ! bp_core_get_root_option( 'bp-disable-avatar-uploads' ) ) : ?>
1305                  <a href="#TB_inline?width=800px&height=400px&inlineId=bp-members-avatar-editor" class="thickbox bp-members-avatar-user-edit"><?php esc_html_e( 'Edit Profile Photo', 'buddypress' ); ?></a>
1306                  <div id="bp-members-avatar-editor" style="display:none;">
1307                      <?php bp_attachments_get_template_part( 'avatars/index' ); ?>
1308                  </div>
1309              <?php endif; ?>
1310  
1311          </div>
1312          <?php
1313      }
1314  
1315      /**
1316       * Render the Member Type metabox.
1317       *
1318       * @since 2.2.0
1319       *
1320       * @param WP_User|null $user The WP_User object to be edited.
1321       */
1322  	public function user_admin_member_type_metabox( $user = null ) {
1323  
1324          // Bail if no user ID.
1325          if ( empty( $user->ID ) ) {
1326              return;
1327          }
1328  
1329          $types        = bp_get_member_types( array(), 'objects' );
1330          $current_type = (array) bp_get_member_type( $user->ID, false );
1331          $types_count  = count( array_filter( $current_type ) );
1332          ?>
1333  
1334          <label for="bp-members-profile-member-type" class="screen-reader-text">
1335              <?php
1336              /* translators: accessibility text */
1337              esc_html_e( 'Select member type', 'buddypress' );
1338              ?>
1339          </label>
1340          <ul class="categorychecklist form-no-clear">
1341              <?php foreach ( $types as $type ) : ?>
1342                  <li>
1343                      <label class="selectit">
1344                          <input value="<?php echo esc_attr( $type->name ) ?>" name="bp-members-profile-member-type[]" type="checkbox" <?php checked( true, in_array( $type->name, $current_type ) ); ?>>
1345                          <?php echo esc_html( $type->labels['singular_name'] ); ?>
1346                      </label>
1347                  </li>
1348              <?php endforeach; ?>
1349              <input type="hidden" value="<?php echo intval( $types_count ); ?>" name="bp-members-profile-member-types-count" />
1350          </ul>
1351  
1352          <?php
1353          wp_nonce_field( 'bp-member-type-change-' . $user->ID, 'bp-member-type-nonce' );
1354      }
1355  
1356      /**
1357       * Process changes from the Member Type metabox.
1358       *
1359       * @since 2.2.0
1360       */
1361  	public function process_member_type_update() {
1362          if ( ! isset( $_POST['bp-member-type-nonce'] ) || ! isset( $_POST['bp-members-profile-member-types-count'] ) ) {
1363              return;
1364          }
1365  
1366          $user_id = $this->get_user_id();
1367  
1368          check_admin_referer( 'bp-member-type-change-' . $user_id, 'bp-member-type-nonce' );
1369  
1370          // Permission check.
1371          if ( ! bp_current_user_can( 'bp_moderate' ) && $user_id != bp_loggedin_user_id() ) {
1372              return;
1373          }
1374  
1375          if ( isset( $_POST['bp-members-profile-member-type'] ) ) {
1376              // Member type [string] must either reference a valid member type, or be empty.
1377              $member_type = wp_parse_slug_list( wp_unslash( $_POST['bp-members-profile-member-type'] ) );
1378              $member_type = array_filter( $member_type );
1379          } elseif ( 0 !== intval( $_POST['bp-members-profile-member-types-count'] ) ) {
1380              $member_type = false;
1381          }
1382  
1383          // Nothing to do there.
1384          if ( ! isset( $member_type ) ) {
1385              return;
1386          }
1387  
1388          /*
1389           * If an invalid member type is passed, someone's doing something
1390           * fishy with the POST request, so we can fail silently.
1391           */
1392          if ( bp_set_member_type( $user_id, $member_type ) ) {
1393              // @todo Success messages can't be posted because other stuff happens on the page load.
1394          }
1395      }
1396  
1397      /**
1398       * Add a link to Profile in Users listing row actions.
1399       *
1400       * @since 2.0.0
1401       *
1402       * @param array|string $actions WordPress row actions (edit, delete).
1403       * @param object|null  $user    The object for the user row.
1404       * @return null|string|array Merged actions.
1405       */
1406  	public function row_actions( $actions = '', $user = null ) {
1407  
1408          // Bail if no user ID.
1409          if ( empty( $user->ID ) ) {
1410              return;
1411          }
1412  
1413          // Setup args array.
1414          $args = array();
1415  
1416          // Add the user ID if it's not for the current user.
1417          if ( $user->ID !== $this->current_user_id ) {
1418              $args['user_id'] = $user->ID;
1419          }
1420  
1421          // Add the referer.
1422          $wp_http_referer = wp_unslash( $_SERVER['REQUEST_URI'] );
1423          $wp_http_referer = wp_validate_redirect( esc_url_raw( $wp_http_referer ) );
1424          $args['wp_http_referer'] = urlencode( $wp_http_referer );
1425  
1426          // Add the "Extended" link if the current user can edit this user.
1427          if ( current_user_can( 'edit_user', $user->ID ) || bp_current_user_can( 'bp_moderate' ) ) {
1428  
1429              // Add query args and setup the Extended link.
1430              $edit_profile      = add_query_arg( $args, $this->edit_profile_url );
1431              $edit_profile_link = sprintf( '<a href="%1$s">%2$s</a>',  esc_url( $edit_profile ), esc_html__( 'Extended', 'buddypress' ) );
1432  
1433              /**
1434               * Check the edit action is available
1435               * and preserve the order edit | profile | remove/delete.
1436               */
1437              if ( ! empty( $actions['edit'] ) ) {
1438                  $edit_action = $actions['edit'];
1439                  unset( $actions['edit'] );
1440  
1441                  $new_edit_actions = array(
1442                      'edit'         => $edit_action,
1443                      'edit-profile' => $edit_profile_link,
1444                  );
1445  
1446              // If not available simply add the edit profile action.
1447              } else {
1448                  $new_edit_actions = array( 'edit-profile' => $edit_profile_link );
1449              }
1450  
1451              $actions = array_merge( $new_edit_actions, $actions );
1452          }
1453  
1454          return $actions;
1455      }
1456  
1457      /**
1458       * Add a filter to edit profile url in WP Admin Bar.
1459       *
1460       * @since 2.1.0
1461       */
1462  	public function add_edit_profile_url_filter() {
1463          add_filter( 'bp_members_edit_profile_url', array( $this, 'filter_adminbar_profile_link' ), 10, 3 );
1464      }
1465  
1466      /**
1467       * Filter the profile url.
1468       *
1469       * @since 2.1.0
1470       *
1471       *
1472       * @param string $profile_link Profile Link for admin bar.
1473       * @param string $url          Profile URL.
1474       * @param int    $user_id      User ID.
1475       * @return string
1476       */
1477  	public function filter_adminbar_profile_link( $profile_link = '', $url = '', $user_id = 0 ) {
1478          if ( ! is_super_admin( $user_id ) && is_admin() ) {
1479              $profile_link = user_admin_url( 'profile.php' );
1480          }
1481          return $profile_link;
1482      }
1483  
1484      /**
1485       * Remove the filter to edit profile url in WP Admin Bar.
1486       *
1487       * @since 2.1.0
1488       */
1489  	public function remove_edit_profile_url_filter() {
1490          remove_filter( 'bp_members_edit_profile_url', array( $this, 'filter_adminbar_profile_link' ), 10 );
1491      }
1492  
1493      /** Signups Management ****************************************************/
1494  
1495      /**
1496       * Display the admin preferences about signups pagination.
1497       *
1498       * @since 2.0.0
1499       *
1500       * @param int    $value     Value for signup option.
1501       * @param string $option    Value for the option key.
1502       * @param int    $new_value Value for the saved option.
1503       * @return int The pagination preferences.
1504       */
1505  	public function signup_screen_options( $value = 0, $option = '', $new_value = 0 ) {
1506          if ( 'users_page_bp_signups_network_per_page' != $option && 'users_page_bp_signups_per_page' != $option ) {
1507              return $value;
1508          }
1509  
1510          // Per page.
1511          $new_value = (int) $new_value;
1512          if ( $new_value < 1 || $new_value > 999 ) {
1513              return $value;
1514          }
1515  
1516          return $new_value;
1517      }
1518  
1519      /**
1520       * Make sure no signups will show in users list.
1521       *
1522       * This is needed to handle signups that may have not been activated
1523       * before the 2.0.0 upgrade.
1524       *
1525       * @since 2.0.0
1526       *
1527       * @param WP_User_Query|null $query The users query.
1528       * @return WP_User_Query|null The users query without the signups.
1529       */
1530  	public function remove_signups_from_user_query( $query = null ) {
1531          global $wpdb;
1532  
1533          // Bail if this is an ajax request.
1534          if ( defined( 'DOING_AJAX' ) ) {
1535              return;
1536          }
1537  
1538          // Bail if updating BuddyPress.
1539          if ( bp_is_update() ) {
1540              return;
1541          }
1542  
1543          // Bail if there is no current admin screen.
1544          if ( ! function_exists( 'get_current_screen' ) || ! get_current_screen() ) {
1545              return;
1546          }
1547  
1548          // Get current screen.
1549          $current_screen = get_current_screen();
1550  
1551          // Bail if not on a users page.
1552          if ( ! isset( $current_screen->id ) || $this->users_page !== $current_screen->id ) {
1553              return;
1554          }
1555  
1556          // Bail if already querying by an existing role.
1557          if ( ! empty( $query->query_vars['role'] ) ) {
1558              return;
1559          }
1560  
1561          $query->query_where .= " AND {$wpdb->users}.user_status != 2";
1562      }
1563  
1564      /**
1565       * Filter the WP Users List Table views to include 'bp-signups'.
1566       *
1567       * @since 2.0.0
1568       *
1569       * @param array $views WP List Table views.
1570       * @return array The views with the signup view added.
1571       */
1572  	public function signup_filter_view( $views = array() ) {
1573          global $role;
1574  
1575          // Remove the 'current' class from All if we're on the signups view.
1576          if ( 'registered' === $role ) {
1577              $views['all'] = str_replace( 'class="current"', '', $views['all'] );
1578              $class        = 'current';
1579          } else {
1580              $class        = '';
1581          }
1582  
1583          $signups = BP_Signup::count_signups();
1584  
1585          if ( is_network_admin() ) {
1586              $base_url = network_admin_url( 'users.php' );
1587          } else {
1588              $base_url = bp_get_admin_url( 'users.php' );
1589          }
1590  
1591          $url = add_query_arg( 'page', 'bp-signups', $base_url );
1592  
1593          /* translators: %s: number of pending accounts */
1594          $text = sprintf( _x( 'Pending %s', 'signup users', 'buddypress' ), '<span class="count">(' . number_format_i18n( $signups ) . ')</span>' );
1595  
1596          $views['registered'] = sprintf( '<a href="%1$s" class="%2$s">%3$s</a>', esc_url( $url ), $class, $text );
1597  
1598          return $views;
1599      }
1600  
1601      /**
1602       * Load the Signup WP Users List table.
1603       *
1604       * @since 2.0.0
1605       *
1606       * @param string $class    The name of the class to use.
1607       * @param string $required The parent class.
1608       * @return WP_List_Table|null The List table.
1609       */
1610  	public static function get_list_table_class( $class = '', $required = '' ) {
1611          if ( empty( $class ) ) {
1612              return;
1613          }
1614  
1615          if ( ! empty( $required ) ) {
1616              require_once( ABSPATH . 'wp-admin/includes/class-wp-' . $required . '-list-table.php' );
1617          }
1618  
1619          return new $class();
1620      }
1621  
1622      /**
1623       * Set up the signups admin page.
1624       *
1625       * Loaded before the page is rendered, this function does all initial
1626       * setup, including: processing form requests, registering contextual
1627       * help, and setting up screen options.
1628       *
1629       * @since 2.0.0
1630       *
1631       * @global $bp_members_signup_list_table
1632       */
1633  	public function signups_admin_load() {
1634          global $bp_members_signup_list_table;
1635  
1636          // Build redirection URL.
1637          $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'] );
1638          $doaction    = bp_admin_list_table_current_bulk_action();
1639  
1640          /**
1641           * Fires at the start of the signups admin load.
1642           *
1643           * @since 2.0.0
1644           *
1645           * @param string $doaction Current bulk action being processed.
1646           * @param array  $_REQUEST Current $_REQUEST global.
1647           */
1648          do_action( 'bp_signups_admin_load', $doaction, $_REQUEST );
1649  
1650          /**
1651           * Filters the allowed actions for use in the user signups admin page.
1652           *
1653           * @since 2.0.0
1654           *
1655           * @param array $value Array of allowed actions to use.
1656           */
1657          $allowed_actions = apply_filters( 'bp_signups_admin_allowed_actions', array( 'do_delete', 'do_activate', 'do_resend' ) );
1658  
1659          // Prepare the display of the Community Profile screen.
1660          if ( ! in_array( $doaction, $allowed_actions ) || ( -1 == $doaction ) ) {
1661  
1662              if ( is_network_admin() ) {
1663                  $bp_members_signup_list_table = self::get_list_table_class( 'BP_Members_MS_List_Table', 'ms-users' );
1664              } else {
1665                  $bp_members_signup_list_table = self::get_list_table_class( 'BP_Members_List_Table', 'users' );
1666              }
1667  
1668              // The per_page screen option.
1669              add_screen_option( 'per_page', array( 'label' => _x( 'Pending Accounts', 'Pending Accounts per page (screen options)', 'buddypress' ) ) );
1670  
1671              get_current_screen()->add_help_tab( array(
1672                  'id'      => 'bp-signups-overview',
1673                  'title'   => __( 'Overview', 'buddypress' ),
1674                  'content' =>
1675                  '<p>' . __( 'This is the administration screen for pending accounts on your site.', 'buddypress' ) . '</p>' .
1676                  '<p>' . __( 'From the screen options, you can customize the displayed columns and the pagination of this screen.', 'buddypress' ) . '</p>' .
1677                  '<p>' . __( 'You can reorder the list of your pending accounts by clicking on the Username, Email or Registered column headers.', 'buddypress' ) . '</p>' .
1678                  '<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>'
1679              ) );
1680  
1681              get_current_screen()->add_help_tab( array(
1682                  'id'      => 'bp-signups-actions',
1683                  'title'   => __( 'Actions', 'buddypress' ),
1684                  'content' =>
1685                  '<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>' .
1686                  '<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>' .
1687                  '<li>' . __( '"Delete" allows you to delete a pending account from your site. You will be asked to confirm this deletion.', 'buddypress' ) . '</li></ul>' .
1688                  '<p>' . __( 'By clicking on a Username you will be able to activate a pending account from the confirmation screen.', 'buddypress' ) . '</p>' .
1689                  '<p>' . __( 'Bulk actions allow you to perform these 3 actions for the selected rows.', 'buddypress' ) . '</p>'
1690              ) );
1691  
1692              // Help panel - sidebar links.
1693              get_current_screen()->set_help_sidebar(
1694                  '<p><strong>' . __( 'For more information:', 'buddypress' ) . '</strong></p>' .
1695                  '<p>' . __( '<a href="https://buddypress.org/support/">Support Forums</a>', 'buddypress' ) . '</p>'
1696              );
1697  
1698              // Add accessible hidden headings and text for the Pending Users screen.
1699              get_current_screen()->set_screen_reader_content( array(
1700                  /* translators: accessibility text */
1701                  'heading_views'      => __( 'Filter users list', 'buddypress' ),
1702                  /* translators: accessibility text */
1703                  'heading_pagination' => __( 'Pending users list navigation', 'buddypress' ),
1704                  /* translators: accessibility text */
1705                  'heading_list'       => __( 'Pending users list', 'buddypress' ),
1706              ) );
1707  
1708          } else {
1709              if ( ! empty( $_REQUEST['signup_ids' ] ) ) {
1710                  $signups = wp_parse_id_list( $_REQUEST['signup_ids' ] );
1711              }
1712  
1713              // Handle resent activation links.
1714              if ( 'do_resend' == $doaction ) {
1715  
1716                  // Nonce check.
1717                  check_admin_referer( 'signups_resend' );
1718  
1719                  $resent = BP_Signup::resend( $signups );
1720  
1721                  if ( empty( $resent ) ) {
1722                      $redirect_to = add_query_arg( 'error', $doaction, $redirect_to );
1723                  } else {
1724                      $query_arg = array( 'updated' => 'resent' );
1725  
1726                      if ( ! empty( $resent['resent'] ) ) {
1727                          $query_arg['resent'] = count( $resent['resent'] );
1728                      }
1729  
1730                      if ( ! empty( $resent['errors'] ) ) {
1731                          $query_arg['notsent'] = count( $resent['errors'] );
1732                          set_transient( '_bp_admin_signups_errors', $resent['errors'], 30 );
1733                      }
1734  
1735                      $redirect_to = add_query_arg( $query_arg, $redirect_to );
1736                  }
1737  
1738                  bp_core_redirect( $redirect_to );
1739  
1740              // Handle activated accounts.
1741              } elseif ( 'do_activate' == $doaction ) {
1742  
1743                  // Nonce check.
1744                  check_admin_referer( 'signups_activate' );
1745  
1746                  $activated = BP_Signup::activate( $signups );
1747  
1748                  if ( empty( $activated ) ) {
1749                      $redirect_to = add_query_arg( 'error', $doaction, $redirect_to );
1750                  } else {
1751                      $query_arg = array( 'updated' => 'activated' );
1752  
1753                      if ( ! empty( $activated['activated'] ) ) {
1754                          $query_arg['activated'] = count( $activated['activated'] );
1755                      }
1756  
1757                      if ( ! empty( $activated['errors'] ) ) {
1758                          $query_arg['notactivated'] = count( $activated['errors'] );
1759                          set_transient( '_bp_admin_signups_errors', $activated['errors'], 30 );
1760                      }
1761  
1762                      $redirect_to = add_query_arg( $query_arg, $redirect_to );
1763                  }
1764  
1765                  bp_core_redirect( $redirect_to );
1766  
1767              // Handle sign-ups delete.
1768              } elseif ( 'do_delete' == $doaction ) {
1769  
1770                  // Nonce check.
1771                  check_admin_referer( 'signups_delete' );
1772  
1773                  $deleted = BP_Signup::delete( $signups );
1774  
1775                  if ( empty( $deleted ) ) {
1776                      $redirect_to = add_query_arg( 'error', $doaction, $redirect_to );
1777                  } else {
1778                      $query_arg = array( 'updated' => 'deleted' );
1779  
1780                      if ( ! empty( $deleted['deleted'] ) ) {
1781                          $query_arg['deleted'] = count( $deleted['deleted'] );
1782                      }
1783  
1784                      if ( ! empty( $deleted['errors'] ) ) {
1785                          $query_arg['notdeleted'] = count( $deleted['errors'] );
1786                          set_transient( '_bp_admin_signups_errors', $deleted['errors'], 30 );
1787                      }
1788  
1789                      $redirect_to = add_query_arg( $query_arg, $redirect_to );
1790                  }
1791  
1792                  bp_core_redirect( $redirect_to );
1793  
1794              // Plugins can update other stuff from here.
1795              } else {
1796                  $this->redirect = $redirect_to;
1797  
1798                  /**
1799                   * Fires at end of signups admin load if doaction does not match any actions.
1800                   *
1801                   * @since 2.0.0
1802                   *
1803                   * @param string $doaction Current bulk action being processed.
1804                   * @param array  $_REQUEST Current $_REQUEST global.
1805                   * @param string $redirect Determined redirect url to send user to.
1806                   */
1807                  do_action( 'bp_members_admin_update_signups', $doaction, $_REQUEST, $this->redirect );
1808  
1809                  bp_core_redirect( $this->redirect );
1810              }
1811          }
1812      }
1813  
1814      /**
1815       * Display any activation errors.
1816       *
1817       * @since 2.0.0
1818       */
1819  	public function signups_display_errors() {
1820  
1821          // Look for sign-up errors.
1822          $errors = get_transient( '_bp_admin_signups_errors' );
1823  
1824          // Bail if no activation errors.
1825          if ( empty( $errors ) ) {
1826              return;
1827          }
1828  
1829          // Loop through errors and display them.
1830          foreach ( $errors as $error ) : ?>
1831  
1832              <li><?php echo esc_html( $error[0] );?>: <?php echo esc_html( $error[1] );?></li>
1833  
1834          <?php endforeach;
1835  
1836          // Delete the redirect transient.
1837          delete_transient( '_bp_admin_signups_errors' );
1838      }
1839  
1840      /**
1841       * Get admin notice when viewing the sign-up page.
1842       *
1843       * @since 2.1.0
1844       *
1845       * @return array
1846       */
1847  	private function get_signup_notice() {
1848  
1849          // Setup empty notice for return value.
1850          $notice = array();
1851  
1852          // Updates.
1853          if ( ! empty( $_REQUEST['updated'] ) ) {
1854              switch ( $_REQUEST['updated'] ) {
1855                  case 'resent':
1856                      $notice = array(
1857                          'class'   => 'updated',
1858                          'message' => ''
1859                      );
1860  
1861                      if ( ! empty( $_REQUEST['resent'] ) ) {
1862                          $notice['message'] .= sprintf(
1863                              /* translators: %s: number of activation emails sent */
1864                              _nx( '%s activation email successfully sent! ', '%s activation emails successfully sent! ',
1865                               absint( $_REQUEST['resent'] ),
1866                               'signup resent',
1867                               'buddypress'
1868                              ),
1869                              number_format_i18n( absint( $_REQUEST['resent'] ) )
1870                          );
1871                      }
1872  
1873                      if ( ! empty( $_REQUEST['notsent'] ) ) {
1874                          $notice['message'] .= sprintf(
1875                              /* translators: %s: number of unsent activation emails */
1876                              _nx( '%s activation email was not sent.', '%s activation emails were not sent.',
1877                               absint( $_REQUEST['notsent'] ),
1878                               'signup notsent',
1879                               'buddypress'
1880                              ),
1881                              number_format_i18n( absint( $_REQUEST['notsent'] ) )
1882                          );
1883  
1884                          if ( empty( $_REQUEST['resent'] ) ) {
1885                              $notice['class'] = 'error';
1886                          }
1887                      }
1888  
1889                      break;
1890  
1891                  case 'activated':
1892                      $notice = array(
1893                          'class'   => 'updated',
1894                          'message' => ''
1895                      );
1896  
1897                      if ( ! empty( $_REQUEST['activated'] ) ) {
1898                          $notice['message'] .= sprintf(
1899                              /* translators: %s: number of activated accounts */
1900                              _nx( '%s account successfully activated! ', '%s accounts successfully activated! ',
1901                               absint( $_REQUEST['activated'] ),
1902                               'signup resent',
1903                               'buddypress'
1904                              ),
1905                              number_format_i18n( absint( $_REQUEST['activated'] ) )
1906                          );
1907                      }
1908  
1909                      if ( ! empty( $_REQUEST['notactivated'] ) ) {
1910                          $notice['message'] .= sprintf(
1911                              /* translators: %s: number of accounts not activated */
1912                              _nx( '%s account was not activated.', '%s accounts were not activated.',
1913                               absint( $_REQUEST['notactivated'] ),
1914                               'signup notsent',
1915                               'buddypress'
1916                              ),
1917                              number_format_i18n( absint( $_REQUEST['notactivated'] ) )
1918                          );
1919  
1920                          if ( empty( $_REQUEST['activated'] ) ) {
1921                              $notice['class'] = 'error';
1922                          }
1923                      }
1924  
1925                      break;
1926  
1927                  case 'deleted':
1928                      $notice = array(
1929                          'class'   => 'updated',
1930                          'message' => ''
1931                      );
1932  
1933                      if ( ! empty( $_REQUEST['deleted'] ) ) {
1934                          $notice['message'] .= sprintf(
1935                              /* translators: %s: number of deleted signups */
1936                              _nx( '%s sign-up successfully deleted!', '%s sign-ups successfully deleted!',
1937                               absint( $_REQUEST['deleted'] ),
1938                               'signup deleted',
1939                               'buddypress'
1940                              ),
1941                              number_format_i18n( absint( $_REQUEST['deleted'] ) )
1942                          );
1943                      }
1944  
1945                      if ( ! empty( $_REQUEST['notdeleted'] ) ) {
1946                          $notdeleted         = absint( $_REQUEST['notdeleted'] );
1947                          $notice['message'] .= sprintf(
1948                              _nx(
1949                                  /* translators: %s: number of deleted signups not deleted */
1950                                  '%s sign-up was not deleted.', '%s sign-ups were not deleted.',
1951                                  $notdeleted,
1952                                  'signup notdeleted',
1953                                  'buddypress'
1954                              ),
1955                              number_format_i18n( $notdeleted )
1956                          );
1957  
1958                          if ( empty( $_REQUEST['deleted'] ) ) {
1959                              $notice['class'] = 'error';
1960                          }
1961                      }
1962  
1963                      break;
1964              }
1965          }
1966  
1967          // Errors.
1968          if ( ! empty( $_REQUEST['error'] ) ) {
1969              switch ( $_REQUEST['error'] ) {
1970                  case 'do_resend':
1971                      $notice = array(
1972                          'class'   => 'error',
1973                          'message' => esc_html__( 'There was a problem sending the activation emails. Please try again.', 'buddypress' ),
1974                      );
1975                      break;
1976  
1977                  case 'do_activate':
1978                      $notice = array(
1979                          'class'   => 'error',
1980                          'message' => esc_html__( 'There was a problem activating accounts. Please try again.', 'buddypress' ),
1981                      );
1982                      break;
1983  
1984                  case 'do_delete':
1985                      $notice = array(
1986                          'class'   => 'error',
1987                          'message' => esc_html__( 'There was a problem deleting sign-ups. Please try again.', 'buddypress' ),
1988                      );
1989                      break;
1990              }
1991          }
1992  
1993          return $notice;
1994      }
1995  
1996      /**
1997       * Signups admin page router.
1998       *
1999       * Depending on the context, display
2000       * - the list of signups,
2001       * - or the delete confirmation screen,
2002       * - or the activate confirmation screen,
2003       * - or the "resend" email confirmation screen.
2004       *
2005       * Also prepare the admin notices.
2006       *
2007       * @since 2.0.0
2008       */
2009  	public function signups_admin() {
2010          $doaction = bp_admin_list_table_current_bulk_action();
2011  
2012          // Prepare notices for admin.
2013          $notice = $this->get_signup_notice();
2014  
2015          // Display notices.
2016          if ( ! empty( $notice ) ) :
2017              if ( 'updated' === $notice['class'] ) : ?>
2018  
2019                  <div id="message" class="<?php echo esc_attr( $notice['class'] ); ?> notice is-dismissible">
2020  
2021              <?php else: ?>
2022  
2023                  <div class="<?php echo esc_attr( $notice['class'] ); ?> notice is-dismissible">
2024  
2025              <?php endif; ?>
2026  
2027                  <p><?php echo $notice['message']; ?></p>
2028  
2029                  <?php if ( ! empty( $_REQUEST['notactivated'] ) || ! empty( $_REQUEST['notdeleted'] ) || ! empty( $_REQUEST['notsent'] ) ) :?>
2030  
2031                      <ul><?php $this->signups_display_errors();?></ul>
2032  
2033                  <?php endif ;?>
2034  
2035              </div>
2036  
2037          <?php endif;
2038  
2039          // Show the proper screen.
2040          switch ( $doaction ) {
2041              case 'activate' :
2042              case 'delete' :
2043              case 'resend' :
2044                  $this->signups_admin_manage( $doaction );
2045                  break;
2046  
2047              default:
2048                  $this->signups_admin_index();
2049                  break;
2050  
2051          }
2052      }
2053  
2054      /**
2055       * This is the list of the Pending accounts (signups).
2056       *
2057       * @since 2.0.0
2058       *
2059       * @global $plugin_page
2060       * @global $bp_members_signup_list_table
2061       */
2062  	public function signups_admin_index() {
2063          global $plugin_page, $bp_members_signup_list_table;
2064  
2065          $usersearch = ! empty( $_REQUEST['s'] ) ? stripslashes( $_REQUEST['s'] ) : '';
2066  
2067          // Prepare the group items for display.
2068          $bp_members_signup_list_table->prepare_items();
2069  
2070          if ( is_network_admin() ) {
2071              $form_url = network_admin_url( 'users.php' );
2072          } else {
2073              $form_url = bp_get_admin_url( 'users.php' );
2074          }
2075  
2076          $form_url = add_query_arg(
2077              array(
2078                  'page' => 'bp-signups',
2079              ),
2080              $form_url
2081          );
2082  
2083          $search_form_url = remove_query_arg(
2084              array(
2085                  'action',
2086                  'deleted',
2087                  'notdeleted',
2088                  'error',
2089                  'updated',
2090                  'delete',
2091                  'activate',
2092                  'activated',
2093                  'notactivated',
2094                  'resend',
2095                  'resent',
2096                  'notresent',
2097                  'do_delete',
2098                  'do_activate',
2099                  'do_resend',
2100                  'action2',
2101                  '_wpnonce',
2102                  'signup_ids'
2103              ), $_SERVER['REQUEST_URI']
2104          );
2105  
2106          ?>
2107  
2108          <div class="wrap">
2109              <h1 class="wp-heading-inline"><?php _e( 'Users', 'buddypress' ); ?></h1>
2110  
2111              <?php if ( current_user_can( 'create_users' ) ) : ?>
2112  
2113                  <a href="user-new.php" class="page-title-action"><?php echo esc_html_x( 'Add New', 'user', 'buddypress' ); ?></a>
2114  
2115              <?php elseif ( is_multisite() && current_user_can( 'promote_users' ) ) : ?>
2116  
2117                  <a href="user-new.php" class="page-title-action"><?php echo esc_html_x( 'Add Existing', 'user', 'buddypress' ); ?></a>
2118  
2119              <?php endif;
2120  
2121              if ( $usersearch ) {
2122                  printf( '<span class="subtitle">' . __( 'Search results for &#8220;%s&#8221;', 'buddypress' ) . '</span>', esc_html( $usersearch ) );
2123              }
2124              ?>
2125  
2126              <hr class="wp-header-end">
2127  
2128              <?php // Display each signups on its own row. ?>
2129              <?php $bp_members_signup_list_table->views(); ?>
2130  
2131              <form id="bp-signups-search-form" action="<?php echo esc_url( $search_form_url ) ;?>">
2132                  <input type="hidden" name="page" value="<?php echo esc_attr( $plugin_page ); ?>" />
2133                  <?php $bp_members_signup_list_table->search_box( __( 'Search Pending Users', 'buddypress' ), 'bp-signups' ); ?>
2134              </form>
2135  
2136              <form id="bp-signups-form" action="<?php echo esc_url( $form_url );?>" method="post">
2137                  <?php $bp_members_signup_list_table->display(); ?>
2138              </form>
2139          </div>
2140      <?php
2141      }
2142  
2143      /**
2144       * This is the confirmation screen for actions.
2145       *
2146       * @since 2.0.0
2147       *
2148       * @param string $action Delete, activate, or resend activation link.
2149       *
2150       * @return null|false
2151       */
2152  	public function signups_admin_manage( $action = '' ) {
2153          if ( ! current_user_can( $this->capability ) || empty( $action ) ) {
2154              die( '-1' );
2155          }
2156  
2157          // Get the user IDs from the URL.
2158          $ids = false;
2159          if ( ! empty( $_POST['allsignups'] ) ) {
2160              $ids = wp_parse_id_list( $_POST['allsignups'] );
2161          } elseif ( ! empty( $_GET['signup_id'] ) ) {
2162              $ids = absint( $_GET['signup_id'] );
2163          }
2164  
2165          if ( empty( $ids ) ) {
2166              return false;
2167          }
2168  
2169          // Query for signups, and filter out those IDs that don't
2170          // correspond to an actual signup.
2171          $signups_query = BP_Signup::get( array(
2172              'include' => $ids,
2173          ) );
2174  
2175          $signups    = $signups_query['signups'];
2176          $signup_ids = wp_list_pluck( $signups, 'signup_id' );
2177  
2178          // Set up strings.
2179          switch ( $action ) {
2180              case 'delete' :
2181                  $header_text = __( 'Delete Pending Accounts', 'buddypress' );
2182                  if ( 1 == count( $signup_ids ) ) {
2183                      $helper_text = __( 'You are about to delete the following account:', 'buddypress' );
2184                  } else {
2185                      $helper_text = __( 'You are about to delete the following accounts:', 'buddypress' );
2186                  }
2187                  break;
2188  
2189              case 'activate' :
2190                  $header_text = __( 'Activate Pending Accounts', 'buddypress' );
2191                  if ( 1 == count( $signup_ids ) ) {
2192                      $helper_text = __( 'You are about to activate the following account:', 'buddypress' );
2193                  } else {
2194                      $helper_text = __( 'You are about to activate the following accounts:', 'buddypress' );
2195                  }
2196                  break;
2197  
2198              case 'resend' :
2199                  $header_text = __( 'Resend Activation Emails', 'buddypress' );
2200                  if ( 1 == count( $signup_ids ) ) {
2201                      $helper_text = __( 'You are about to resend an activation email to the following account:', 'buddypress' );
2202                  } else {
2203                      $helper_text = __( 'You are about to resend an activation email to the following accounts:', 'buddypress' );
2204                  }
2205                  break;
2206          }
2207  
2208          // These arguments are added to all URLs.
2209          $url_args = array( 'page' => 'bp-signups' );
2210  
2211          // These arguments are only added when performing an action.
2212          $action_args = array(
2213              'action'     => 'do_' . $action,
2214              'signup_ids' => implode( ',', $signup_ids )
2215          );
2216  
2217          if ( is_network_admin() ) {
2218              $base_url = network_admin_url( 'users.php' );
2219          } else {
2220              $base_url = bp_get_admin_url( 'users.php' );
2221          }
2222  
2223          $cancel_url = add_query_arg( $url_args, $base_url );
2224          $action_url = wp_nonce_url(
2225              add_query_arg(
2226                  array_merge( $url_args, $action_args ),
2227                  $base_url
2228              ),
2229              'signups_' . $action
2230          );
2231  
2232          // Prefetch registration field data.
2233          $fdata = array();
2234          if ( 'activate' === $action && bp_is_active( 'xprofile' ) ) {
2235              $field_groups = bp_xprofile_get_groups( array(
2236                  'exclude_fields'    => 1,
2237                  'update_meta_cache' => false,
2238                  'fetch_fields'      => true,
2239              ) );
2240  
2241              foreach( $field_groups as $fg ) {
2242                  foreach( $fg->fields as $f ) {
2243                      $fdata[ $f->id ] = $f->name;
2244                  }
2245              }
2246          }
2247  
2248          ?>
2249  
2250          <div class="wrap">
2251              <h1 class="wp-heading-inline"><?php echo esc_html( $header_text ); ?></h1>
2252              <hr class="wp-header-end">
2253  
2254              <p><?php echo esc_html( $helper_text ); ?></p>
2255  
2256              <ol class="bp-signups-list">
2257              <?php foreach ( $signups as $signup ) :
2258                  $last_notified = mysql2date( 'Y/m/d g:i:s a', $signup->date_sent );
2259                  $profile_field_ids = array();
2260  
2261                  // Get all xprofile field IDs except field 1.
2262                  if ( ! empty( $signup->meta['profile_field_ids'] ) ) {
2263                      $profile_field_ids = array_flip( explode( ',', $signup->meta['profile_field_ids'] ) );
2264                      unset( $profile_field_ids[1] );
2265                  } ?>
2266  
2267                  <li>
2268                      <strong><?php echo esc_html( $signup->user_login ) ?></strong>
2269  
2270                      <?php if ( 'activate' == $action ) : ?>
2271                          <table class="wp-list-table widefat fixed striped">
2272                              <tbody>
2273                                  <tr>
2274                                      <td class="column-fields"><?php esc_html_e( 'Display Name', 'buddypress' ); ?></td>
2275                                      <td><?php echo esc_html( $signup->user_name ); ?></td>
2276                                  </tr>
2277  
2278                                  <tr>
2279                                      <td class="column-fields"><?php esc_html_e( 'Email', 'buddypress' ); ?></td>
2280                                      <td><?php echo sanitize_email( $signup->user_email ); ?></td>
2281                                  </tr>
2282  
2283                                  <?php if ( bp_is_active( 'xprofile' ) && ! empty( $profile_field_ids ) ) : ?>
2284                                      <?php foreach ( $profile_field_ids as $pid => $noop ) :
2285                                          $field_value = isset( $signup->meta[ "field_{$pid}" ] ) ? $signup->meta[ "field_{$pid}" ] : ''; ?>
2286                                          <tr>
2287                                              <td class="column-fields"><?php echo esc_html( $fdata[ $pid ] ); ?></td>
2288                                              <td><?php echo $this->format_xprofile_field_for_display( $field_value ); ?></td>
2289                                          </tr>
2290  
2291                                      <?php endforeach;  ?>
2292  
2293                                  <?php endif; ?>
2294  
2295                                  <?php
2296                                  /**
2297                                   * Fires inside the table listing the activate action confirmation details.
2298                                   *
2299                                   * @since 6.0.0
2300                                   *
2301                                   * @param object $signup The Sign-up Object.
2302                                   */
2303                                  do_action( 'bp_activate_signup_confirmation_details', $signup );
2304                                  ?>
2305  
2306                              </tbody>
2307                          </table>
2308  
2309                          <?php
2310                          /**
2311                           * Fires outside the table listing the activate action confirmation details.
2312                           *
2313                           * @since 6.0.0
2314                           *
2315                           * @param object $signup The Sign-up Object.
2316                           */
2317                          do_action( 'bp_activate_signup_confirmation_after_details', $signup );
2318                          ?>
2319  
2320                      <?php endif; ?>
2321  
2322                      <?php if ( 'resend' == $action ) : ?>
2323  
2324                          <p class="description">
2325                              <?php
2326                              /* translators: %s: notification date */
2327                              printf( esc_html__( 'Last notified: %s', 'buddypress'), $last_notified );
2328                              ?>
2329  
2330                              <?php if ( ! empty( $signup->recently_sent ) ) : ?>
2331  
2332                                  <span class="attention wp-ui-text-notification"> <?php esc_html_e( '(less than 24 hours ago)', 'buddypress' ); ?></span>
2333  
2334                              <?php endif; ?>
2335                          </p>
2336  
2337                      <?php endif; ?>
2338  
2339                  </li>
2340  
2341              <?php endforeach; ?>
2342              </ol>
2343  
2344              <?php if ( 'delete' === $action ) : ?>
2345  
2346                  <p><strong><?php esc_html_e( 'This action cannot be undone.', 'buddypress' ) ?></strong></p>
2347  
2348              <?php endif ; ?>
2349  
2350              <a class="button-primary" href="<?php echo esc_url( $action_url ); ?>"><?php esc_html_e( 'Confirm', 'buddypress' ); ?></a>
2351              <a class="button" href="<?php echo esc_url( $cancel_url ); ?>"><?php esc_html_e( 'Cancel', 'buddypress' ) ?></a>
2352          </div>
2353  
2354          <?php
2355      }
2356  
2357      /** Users List Management ****************************************************/
2358  
2359      /**
2360       * Display a dropdown to bulk change the member type of selected user(s).
2361       *
2362       * @since 2.7.0
2363       *
2364       * @param string $which Where this dropdown is displayed - top or bottom.
2365       */
2366  	public function users_table_output_type_change_select( $which = 'top' ) {
2367  
2368          // Bail if current user cannot promote users.
2369          if ( ! bp_current_user_can( 'promote_users' ) ) {
2370              return;
2371          }
2372  
2373          // `$which` is only passed in WordPress 4.6+. Avoid duplicating controls in earlier versions.
2374          static $displayed = false;
2375          if ( version_compare( bp_get_major_wp_version(), '4.6', '<' ) && $displayed ) {
2376              return;
2377          }
2378          $displayed = true;
2379  
2380          $id_name = 'bottom' === $which ? 'bp_change_type2' : 'bp_change_type';
2381  
2382          $types = bp_get_member_types( array(), 'objects' ); ?>
2383  
2384          <label class="screen-reader-text" for="<?php echo $id_name; ?>"><?php _e( 'Change member type to&hellip;', 'buddypress' ) ?></label>
2385          <select name="<?php echo $id_name; ?>" id="<?php echo $id_name; ?>" style="display:inline-block;float:none;">
2386              <option value=""><?php _e( 'Change member type to&hellip;', 'buddypress' ) ?></option>
2387  
2388              <?php foreach( $types as $type ) : ?>
2389  
2390                  <option value="<?php echo esc_attr( $type->name ); ?>"><?php echo esc_html( $type->labels['singular_name'] ); ?></option>
2391  
2392              <?php endforeach; ?>
2393  
2394              <option value="remove_member_type"><?php _e( 'No Member Type', 'buddypress' ) ?></option>
2395  
2396          </select>
2397          <?php
2398          wp_nonce_field( 'bp-bulk-users-change-type-' . bp_loggedin_user_id(), 'bp-bulk-users-change-type-nonce' );
2399          submit_button( __( 'Change', 'buddypress' ), 'button', 'bp_change_member_type', false );
2400      }
2401  
2402      /**
2403       * Process bulk member type change submission from the WP admin users list table.
2404       *
2405       * @since 2.7.0
2406       */
2407  	public function users_table_process_bulk_type_change() {
2408          // Output the admin notice.
2409          $this->users_type_change_notice();
2410  
2411          // Bail if no users are specified or if this isn't a BuddyPress action.
2412          if ( empty( $_REQUEST['users'] )
2413              || ( empty( $_REQUEST['bp_change_type'] ) && empty( $_REQUEST['bp_change_type2'] ) )
2414              || empty( $_REQUEST['bp_change_member_type'] )
2415          ) {
2416              return;
2417          }
2418  
2419          // Bail if nonce check fails.
2420          check_admin_referer( 'bp-bulk-users-change-type-' . bp_loggedin_user_id(), 'bp-bulk-users-change-type-nonce' );
2421  
2422          // Bail if current user cannot promote users.
2423          if ( ! bp_current_user_can( 'promote_users' ) ) {
2424              return;
2425          }
2426  
2427          $new_type = '';
2428          if ( ! empty( $_REQUEST['bp_change_type2'] ) ) {
2429              $new_type = sanitize_text_field( $_REQUEST['bp_change_type2'] );
2430          } elseif ( ! empty( $_REQUEST['bp_change_type'] ) ) {
2431              $new_type = sanitize_text_field( $_REQUEST['bp_change_type'] );
2432          }
2433  
2434          // Check that the selected type actually exists.
2435          if ( 'remove_member_type' != $new_type && null === bp_get_member_type_object( $new_type ) ) {
2436              $error = true;
2437          } else {
2438              // Run through user ids.
2439              $error = false;
2440              foreach ( (array) $_REQUEST['users'] as $user_id ) {
2441                  $user_id = (int) $user_id;
2442  
2443                  // Get the old member types to check against.
2444                  $current_types = bp_get_member_type( $user_id, false );
2445  
2446                  if ( $current_types && 'remove_member_type' === $new_type ) {
2447                      $member_types = array();
2448                  } elseif ( ! $current_types || 1 !== count( $current_types ) || $new_type !== $current_types[0] ) {
2449                      // Set the new member type.
2450                      $member_types = array( $new_type );
2451                  }
2452  
2453                  if ( isset( $member_types ) ) {
2454                      $set = bp_set_member_type( $user_id, $member_types );
2455                      if ( false === $set || is_wp_error( $set ) ) {
2456                          $error = true;
2457                      }
2458                      unset( $member_types );
2459                  }
2460              }
2461          }
2462  
2463          // If there were any errors, show the error message.
2464          if ( $error ) {
2465              $redirect = add_query_arg( array( 'updated' => 'member-type-change-error' ), wp_get_referer() );
2466          } else {
2467              $redirect = add_query_arg( array( 'updated' => 'member-type-change-success' ), wp_get_referer() );
2468          }
2469  
2470          wp_redirect( $redirect );
2471          exit();
2472      }
2473  
2474      /**
2475       * Display an admin notice upon member type bulk update.
2476       *
2477       * @since 2.7.0
2478       */
2479  	public function users_type_change_notice() {
2480          $updated = isset( $_REQUEST['updated'] ) ? $_REQUEST['updated'] : false;
2481  
2482          // Display feedback.
2483          if ( $updated && in_array( $updated, array( 'member-type-change-error', 'member-type-change-success' ), true ) ) {
2484  
2485              if ( 'member-type-change-error' === $updated ) {
2486                  $notice = __( 'There was an error while changing member type. Please try again.', 'buddypress' );
2487                  $type   = 'error';
2488              } else {
2489                  $notice = __( 'Member type was changed successfully.', 'buddypress' );
2490                  $type   = 'updated';
2491              }
2492  
2493              bp_core_add_admin_notice( $notice, $type );
2494          }
2495      }
2496  
2497      /**
2498       * Add member type column to the WordPress admin users list table.
2499       *
2500       * @since 2.7.0
2501       *
2502       * @param array $columns Users table columns.
2503       *
2504       * @return array $columns
2505       */
2506  	public function users_table_add_type_column( $columns = array() ) {
2507          $columns[ bp_get_member_type_tax_name() ] = _x( 'Member Type', 'Label for the WP users table member type column', 'buddypress' );
2508  
2509          return $columns;
2510      }
2511  
2512      /**
2513       * Return member's type for display in the WP admin users list table.
2514       *
2515       * @since 2.7.0
2516       *
2517       * @param string $retval
2518       * @param string $column_name
2519       * @param int $user_id
2520       *
2521       * @return string Member type as a link to filter all users.
2522       */
2523  	public function users_table_populate_type_cell( $retval = '', $column_name = '', $user_id = 0 ) {
2524          // Only looking for member type column.
2525          if ( bp_get_member_type_tax_name() !== $column_name ) {
2526              return $retval;
2527          }
2528  
2529          // Get the member type.
2530          $member_type = bp_get_member_type( $user_id, false );
2531  
2532          // Build the Output.
2533          if ( $member_type ) {
2534              $member_types = array_filter( array_map( 'bp_get_member_type_object', $member_type ) );
2535              if ( ! $member_types ) {
2536                  return $retval;
2537              }
2538  
2539              $type_links = array();
2540              foreach ( $member_types as $type ) {
2541                  $url          = add_query_arg( array( 'bp-member-type' => urlencode( $type->name ) ) );
2542                  $type_links[] = sprintf(
2543                      '<a href="%1$s">%2$s</a>',
2544                      esc_url( $url ),
2545                      esc_html( $type->labels['singular_name'] )
2546                  );
2547              }
2548  
2549              $retval = implode( ', ', $type_links );
2550          }
2551  
2552          return $retval;
2553      }
2554  
2555      /**
2556       * Filter WP Admin users list table to include users of the specified type.
2557       *
2558       * @param WP_Query $query
2559       *
2560       * @since 2.7.0
2561       */
2562  	public function users_table_filter_by_type( $query ) {
2563          global $pagenow;
2564  
2565          if ( is_admin() && 'users.php' === $pagenow && ! empty( $_REQUEST['bp-member-type'] ) ) {
2566              $type_slug = sanitize_text_field( $_REQUEST['bp-member-type'] );
2567  
2568              // Check that the type is registered.
2569              if ( null == bp_get_member_type_object( $type_slug ) ) {
2570                  return;
2571              }
2572  
2573              // Get the list of users that are assigned to this member type.
2574              $type = bp_get_term_by( 'slug', $type_slug, bp_get_member_type_tax_name() );
2575  
2576              if ( empty( $type->term_id ) ) {
2577                  return;
2578              }
2579  
2580              $user_ids = bp_get_objects_in_term( $type->term_id, bp_get_member_type_tax_name() );
2581  
2582              if ( $user_ids && ! is_wp_error( $user_ids ) ) {
2583                  $query->set( 'include', (array) $user_ids );
2584              }
2585          }
2586      }
2587  
2588      /**
2589       * Formats a signup's xprofile field data for display.
2590       *
2591       * Operates recursively on arrays, which are then imploded with commas.
2592       *
2593       * @since 2.8.0
2594       *
2595       * @param string|array $value Field value.
2596       * @return string
2597       */
2598  	protected function format_xprofile_field_for_display( $value ) {
2599          if ( is_array( $value ) ) {
2600              $value = array_map( array( $this, 'format_xprofile_field_for_display' ), $value );
2601              $value = implode( ', ', $value );
2602          } else {
2603              $value = stripslashes( $value );
2604              $value = esc_html( $value );
2605          }
2606  
2607          return $value;
2608      }
2609  
2610      /**
2611       * Set up the signups admin page.
2612       *
2613       * Loaded before the page is rendered, this function does all initial
2614       * setup, including: processing form requests, registering contextual
2615       * help, and setting up screen options.
2616       *
2617       * @since 8.0.0
2618       *
2619       * @global $bp_members_invitations_list_table
2620       */
2621  	public function members_invitations_admin_load() {
2622          global $bp_members_invitations_list_table;
2623  
2624          // Build redirection URL.
2625          $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'] );
2626          $doaction    = bp_admin_list_table_current_bulk_action();
2627  
2628          /**
2629           * Fires at the start of the member invitations admin load.
2630           *
2631           * @since 8.0.0
2632           *
2633           * @param string $doaction Current bulk action being processed.
2634           * @param array  $_REQUEST Current $_REQUEST global.
2635           */
2636          do_action( 'bp_members_invitations_admin_load', $doaction, $_REQUEST );
2637  
2638          /**
2639           * Filters the allowed actions for use in the user signups admin page.
2640           *
2641           * @since 8.0.0
2642           *
2643           * @param array $value Array of allowed actions to use.
2644           */
2645          $allowed_actions = apply_filters( 'bp_members_invitations_admin_allowed_actions', array( 'do_delete',  'do_resend' ) );
2646  
2647          // Prepare the display of the bulk invitation action screen.
2648          if ( ! in_array( $doaction, $allowed_actions ) ) {
2649  
2650              $bp_members_invitations_list_table = self::get_list_table_class( 'BP_Members_Invitations_List_Table', 'users' );
2651  
2652              // The per_page screen option.
2653              add_screen_option( 'per_page', array( 'label' => _x( 'Members Invitations', 'Members Invitations per page (screen options)', 'buddypress' ) ) );
2654  
2655              get_current_screen()->add_help_tab( array(
2656                  'id'      => 'bp-members-invitations-overview',
2657                  'title'   => __( 'Overview', 'buddypress' ),
2658                  'content' =>
2659                  '<p>' . __( 'This is the administration screen for member invitations on your site.', 'buddypress' ) . '</p>' .
2660                  '<p>' . __( 'From the screen options, you can customize the displayed columns and the pagination of this screen.', 'buddypress' ) . '</p>' .
2661                  '<p>' . __( 'You can reorder the list of invitations by clicking on the Invitee, Inviter, Date Modified, Email Sent, or Accepted column headers.', 'buddypress' ) . '</p>' .
2662                  '<p>' . __( 'Using the search form, you can find specific invitations more easily. The Invitee Email field will be included in the search.', 'buddypress' ) . '</p>'
2663              ) );
2664  
2665              get_current_screen()->add_help_tab( array(
2666                  'id'      => 'bp-members-invitations-actions',
2667                  'title'   => __( 'Actions', 'buddypress' ),
2668                  'content' =>
2669                  '<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>' .
2670                  '<ul><li>' . __( '"Send" or "Resend" takes you to the confirmation screen before being able to send or resend the invitation email to the desired pending invitee.', 'buddypress' ) . '</li>' .
2671                  '<li>' . __( '"Delete" allows you to delete an unsent or accepted invitation from your site; "Cancel" allows you to cancel a sent, but not yet accepted, invitation. You will be asked to confirm this deletion.', 'buddypress' ) . '</li></ul>' .
2672                  '<p>' . __( 'Bulk actions allow you to perform these actions for the selected rows.', 'buddypress' ) . '</p>'
2673              ) );
2674  
2675              // Help panel - sidebar links.
2676              get_current_screen()->set_help_sidebar(
2677                  '<p><strong>' . __( 'For more information:', 'buddypress' ) . '</strong></p>' .
2678                  '<p>' . __( '<a href="https://buddypress.org/support/">Support Forums</a>', 'buddypress' ) . '</p>'
2679              );
2680  
2681              // Add accessible hidden headings and text for the Pending Users screen.
2682              get_current_screen()->set_screen_reader_content( array(
2683                  /* translators: accessibility text */
2684                  'heading_views'      => __( 'Filter invitations list', 'buddypress' ),
2685                  /* translators: accessibility text */
2686                  'heading_pagination' => __( 'Invitation list navigation', 'buddypress' ),
2687                  /* translators: accessibility text */
2688                  'heading_list'       => __( 'Invitations list', 'buddypress' ),
2689              ) );
2690  
2691          } else {
2692              if ( empty( $_REQUEST['invite_ids' ] ) ) {
2693                  return;
2694              }
2695              $invite_ids = wp_parse_id_list( $_REQUEST['invite_ids' ] );
2696  
2697              // Handle resent invitations.
2698              if ( 'do_resend' == $doaction ) {
2699  
2700                  // Nonce check.
2701                  check_admin_referer( 'invitations_resend' );
2702  
2703                  $success = 0;
2704                  foreach ( $invite_ids as $invite_id ) {
2705                      if ( bp_members_invitation_resend_by_id( $invite_id ) ) {
2706                          $success++;
2707                      }
2708                  }
2709  
2710                  $query_arg = array( 'updated' => 'resent' );
2711  
2712                  if ( ! empty( $success ) ) {
2713                      $query_arg['resent'] = $success;
2714                  }
2715  
2716                  $not_sent = count( $invite_ids ) - $success;
2717                  if ( $not_sent > 0 ) {
2718                      $query_arg['notsent'] = $not_sent;
2719                  }
2720  
2721                  $redirect_to = add_query_arg( $query_arg, $redirect_to );
2722  
2723                  bp_core_redirect( $redirect_to );
2724  
2725              // Handle invitation deletion.
2726              } elseif ( 'do_delete' == $doaction ) {
2727  
2728                  // Nonce check.
2729                  check_admin_referer( 'invitations_delete' );
2730  
2731                  $success = 0;
2732                  foreach ( $invite_ids as $invite_id ) {
2733                      if ( bp_members_invitations_delete_by_id( $invite_id ) ) {
2734                          $success++;
2735                      }
2736                  }
2737  
2738                  $query_arg = array( 'updated' => 'deleted' );
2739  
2740                  if ( ! empty( $success ) ) {
2741                      $query_arg['deleted'] = $success;
2742                  }
2743  
2744                  $notdeleted = count( $invite_ids ) - $success;
2745                  if ( $notdeleted > 0 ) {
2746                      $query_arg['notdeleted'] = $notdeleted;
2747                  }
2748  
2749                  $redirect_to = add_query_arg( $query_arg, $redirect_to );
2750  
2751                  bp_core_redirect( $redirect_to );
2752  
2753              // Plugins can update other stuff from here.
2754              } else {
2755                  $this->redirect = $redirect_to;
2756  
2757                  /**
2758                   * Fires at end of member invitations admin load
2759                   * if doaction does not match any actions.
2760                   *
2761                   * @since 8.0.0
2762                   *
2763                   * @param string $doaction Current bulk action being processed.
2764                   * @param array  $_REQUEST Current $_REQUEST global.
2765                   * @param string $redirect Determined redirect url to send user to.
2766                   */
2767                  do_action( 'bp_members_admin_update_invitations', $doaction, $_REQUEST, $this->redirect );
2768  
2769                  bp_core_redirect( $this->redirect );
2770              }
2771          }
2772      }
2773  
2774      /**
2775       * Get admin notice when viewing the invitations management page.
2776       *
2777       * @since 8.0.0
2778       *
2779       * @return array
2780       */
2781  	private function get_members_invitations_notice() {
2782  
2783          // Setup empty notice for return value.
2784          $notice = array();
2785  
2786          // Updates.
2787          if ( ! empty( $_REQUEST['updated'] ) ) {
2788              switch ( $_REQUEST['updated'] ) {
2789                  case 'resent':
2790                      $notice = array(
2791                          'class'   => 'updated',
2792                          'message' => ''
2793                      );
2794  
2795                      if ( ! empty( $_REQUEST['resent'] ) ) {
2796                          $resent             = absint( $_REQUEST['resent'] );
2797                          $notice['message'] .= sprintf(
2798                              _nx(
2799                                  /* translators: %s: number of invitation emails sent */
2800                                  '%s invtitation email successfully sent! ', '%s invitation emails successfully sent! ',
2801                                  $resent,
2802                                  'members invitation resent',
2803                                  'buddypress'
2804                              ),
2805                              number_format_i18n( $resent )
2806                          );
2807                      }
2808  
2809                      if ( ! empty( $_REQUEST['notsent'] ) ) {
2810                          $notsent            = absint( $_REQUEST['notsent'] );
2811                          $notice['message'] .= sprintf(
2812                              _nx(
2813                                  /* translators: %s: number of unsent invitation emails */
2814                                  '%s invitation email was not sent.', '%s invitation emails were not sent.',
2815                                  $notsent,
2816                                  'members invitation notsent',
2817                                  'buddypress'
2818                              ),
2819                              number_format_i18n( $notsent )
2820                          );
2821  
2822                          if ( empty( $_REQUEST['resent'] ) ) {
2823                              $notice['class'] = 'error';
2824                          }
2825                      }
2826  
2827                      break;
2828  
2829                  case 'deleted':
2830                      $notice = array(
2831                          'class'   => 'updated',
2832                          'message' => ''
2833                      );
2834  
2835                      if ( ! empty( $_REQUEST['deleted'] ) ) {
2836                          $deleted            = absint( $_REQUEST['deleted'] );
2837                          $notice['message'] .= sprintf(
2838                              _nx(
2839                                  /* translators: %s: number of deleted invitations */
2840                                  '%s invitation successfully deleted!', '%s invitations successfully deleted!',
2841                                  $deleted,
2842                                  'members invitation deleted',
2843                                  'buddypress'
2844                              ),
2845                              number_format_i18n( $deleted )
2846                          );
2847                      }
2848  
2849                      if ( ! empty( $_REQUEST['notdeleted'] ) ) {
2850                          $notdeleted         = absint( $_REQUEST['notdeleted'] );
2851                          $notice['message'] .= sprintf(
2852                              _nx(
2853                                  /* translators: %s: number of invitations that failed to be deleted */
2854                                  '%s invitation was not deleted.', '%s invitations were not deleted.',
2855                                  $notdeleted,
2856                                  'members invitation notdeleted',
2857                                  'buddypress'
2858                              ),
2859                              number_format_i18n( $notdeleted )
2860                          );
2861  
2862                          if ( empty( $_REQUEST['deleted'] ) ) {
2863                              $notice['class'] = 'error';
2864                          }
2865                      }
2866  
2867                      break;
2868              }
2869          }
2870  
2871          // Errors.
2872          if ( ! empty( $_REQUEST['error'] ) ) {
2873              switch ( $_REQUEST['error'] ) {
2874                  case 'do_resend':
2875                      $notice = array(
2876                          'class'   => 'error',
2877                          'message' => esc_html__( 'There was a problem sending the invitation emails. Please try again.', 'buddypress' ),
2878                      );
2879                      break;
2880  
2881                  case 'do_delete':
2882                      $notice = array(
2883                          'class'   => 'error',
2884                          'message' => esc_html__( 'There was a problem deleting invitations. Please try again.', 'buddypress' ),
2885                      );
2886                      break;
2887              }
2888          }
2889  
2890          return $notice;
2891      }
2892  
2893      /**
2894       * Member invitations admin page router.
2895       *
2896       * Depending on the context, display
2897       * - the list of invitations,
2898       * - or the delete confirmation screen,
2899       * - or the "resend" email confirmation screen.
2900       *
2901       * Also prepare the admin notices.
2902       *
2903       * @since 8.0.0
2904       */
2905  	public function invitations_admin() {
2906          $doaction = bp_admin_list_table_current_bulk_action();
2907  
2908          // Prepare notices for admin.
2909          $notice = $this->get_members_invitations_notice();
2910  
2911          // Display notices.
2912          if ( ! empty( $notice ) ) :
2913              if ( 'updated' === $notice['class'] ) : ?>
2914  
2915                  <div id="message" class="<?php echo esc_attr( $notice['class'] ); ?> notice is-dismissible">
2916  
2917              <?php else: ?>
2918  
2919                  <div class="<?php echo esc_attr( $notice['class'] ); ?> notice is-dismissible">
2920  
2921              <?php endif; ?>
2922  
2923                  <p><?php echo $notice['message']; ?></p>
2924              </div>
2925  
2926          <?php endif;
2927  
2928          // Show the proper screen.
2929          switch ( $doaction ) {
2930              case 'delete' :
2931              case 'resend' :
2932                  $this->invitations_admin_manage( $doaction );
2933                  break;
2934  
2935              default:
2936                  $this->invitations_admin_index();
2937                  break;
2938          }
2939      }
2940  
2941      /**
2942       * This is the list of invitations.
2943       *
2944       * @since 8.0.0
2945       *
2946       * @global $plugin_page
2947       * @global $bp_members_invitations_list_table
2948       */
2949  	public function invitations_admin_index() {
2950          global $plugin_page, $bp_members_invitations_list_table;
2951  
2952          $usersearch = ! empty( $_REQUEST['s'] ) ? stripslashes( $_REQUEST['s'] ) : '';
2953  
2954          // Prepare the group items for display.
2955          $bp_members_invitations_list_table->prepare_items();
2956  
2957          if ( is_network_admin() ) {
2958              $form_url = network_admin_url( 'admin.php' );
2959          } else {
2960              $form_url = bp_get_admin_url( 'tools.php' );
2961          }
2962  
2963          $form_url = add_query_arg(
2964              array(
2965                  'page' => 'bp-members-invitations',
2966              ),
2967              $form_url
2968          );
2969  
2970          $search_form_url = remove_query_arg(
2971              array(
2972                  'action',
2973                  'deleted',
2974                  'notdeleted',
2975                  'error',
2976                  'updated',
2977                  'delete',
2978                  'activate',
2979                  'activated',
2980                  'notactivated',
2981                  'resend',
2982                  'resent',
2983                  'notresent',
2984                  'do_delete',
2985                  'do_activate',
2986                  'do_resend',
2987                  'action2',
2988                  '_wpnonce',
2989                  'invite_ids'
2990              ), $_SERVER['REQUEST_URI']
2991          );
2992  
2993          ?>
2994  
2995          <div class="wrap">
2996              <h1 class="wp-heading-inline"><?php esc_html_e( 'BuddyPress tools', 'buddypress' ); ?></h1>
2997              <hr class="wp-header-end">
2998  
2999              <h2 class="nav-tab-wrapper"><?php bp_core_admin_tabs( __( 'Manage Invitations', 'buddypress' ), 'tools' ); ?></h2>
3000  
3001              <?php
3002              if ( $usersearch ) {
3003                  printf( '<span class="subtitle">' . __( 'Search results for &#8220;%s&#8221;', 'buddypress' ) . '</span>', esc_html( $usersearch ) );
3004              }
3005              ?>
3006  
3007              <?php // Display each invitation on its own row. ?>
3008              <?php $bp_members_invitations_list_table->views(); ?>
3009  
3010              <form id="bp-members-invitations-search-form" action="<?php echo esc_url( $search_form_url ) ;?>">
3011                  <input type="hidden" name="page" value="<?php echo esc_attr( $plugin_page ); ?>" />
3012                  <?php $bp_members_invitations_list_table->search_box( __( 'Search Invitations', 'buddypress' ), 'bp-members-invitations' ); ?>
3013              </form>
3014  
3015              <form id="bp-members-invitations-form" action="<?php echo esc_url( $form_url );?>" method="post">
3016                  <?php $bp_members_invitations_list_table->display(); ?>
3017              </form>
3018          </div>
3019      <?php
3020      }
3021  
3022      /**
3023       * This is the confirmation screen for actions.
3024       *
3025       * @since 8.0.0
3026       *
3027       * @param string $action Delete or resend invitation.
3028       * @return null|false
3029       */
3030  	public function invitations_admin_manage( $action = '' ) {
3031          if ( ! current_user_can( $this->capability ) || empty( $action ) ) {
3032              die( '-1' );
3033          }
3034  
3035          // Get the IDs from the URL.
3036          $ids = false;
3037          if ( ! empty( $_POST['invite_ids'] ) ) {
3038              $ids = wp_parse_id_list( $_POST['invite_ids'] );
3039          } elseif ( ! empty( $_GET['invite_id'] ) ) {
3040              $ids = absint( $_GET['invite_id'] );
3041          }
3042  
3043  
3044          if ( empty( $ids ) ) {
3045              return false;
3046          }
3047  
3048          // Check invite IDs and set up strings.
3049          switch ( $action ) {
3050              case 'delete' :
3051                  // Query for matching invites, and filter out bad IDs.
3052                  $args = array(
3053                      'id'          => $ids,
3054                      'invite_sent' => 'all',
3055                      'accepted'    => 'all',
3056                  );
3057                  $invites    = bp_members_invitations_get_invites( $args );
3058                  $invite_ids = wp_list_pluck( $invites, 'id' );
3059  
3060                  $header_text = __( 'Delete Invitations', 'buddypress' );
3061                  if ( 0 === count( $invite_ids ) ) {
3062                      $helper_text = __( 'No invites were found, nothing to delete!', 'buddypress' );
3063                  } else {
3064                      $helper_text = _n( 'You are about to delete the following invitation:', 'You are about to delete the following invitations:', count( $invite_ids ), 'buddypress' );
3065                  }
3066                  break;
3067  
3068              case 'resend' :
3069                  /**
3070                   * Query for matching invites, and filter out bad IDs
3071                   * or those that have already been accepted.
3072                   */
3073                  $args = array(
3074                      'id'          => $ids,
3075                      'invite_sent' => 'all',
3076                      'accepted'    => 'pending',
3077                  );
3078                  $invites    = bp_members_invitations_get_invites( $args );
3079                  $invite_ids = wp_list_pluck( $invites, 'id' );
3080  
3081                  $header_text = __( 'Resend Invitation Emails', 'buddypress' );
3082                  if ( 0 === count( $invite_ids ) ) {
3083                      $helper_text = __( 'No pending invites were found, nothing to resend!', 'buddypress' );
3084                  } else {
3085                      $helper_text = _n( 'You are about to resend an invitation email to the following address:', 'You are about to resend invitation emails to the following addresses:', count( $invite_ids ), 'buddypress' );
3086                  }
3087                  break;
3088          }
3089  
3090          // These arguments are added to all URLs.
3091          $url_args = array( 'page' => 'bp-members-invitations' );
3092  
3093          // These arguments are only added when performing an action.
3094          $action_args = array(
3095              'action'     => 'do_' . $action,
3096              'invite_ids' => implode( ',', $invite_ids )
3097          );
3098  
3099          if ( is_network_admin() ) {
3100              $base_url = network_admin_url( 'admin.php' );
3101          } else {
3102              $base_url = bp_get_admin_url( 'tools.php' );
3103          }
3104  
3105          $cancel_url = add_query_arg( $url_args, $base_url );
3106          $action_url = wp_nonce_url(
3107              add_query_arg(
3108                  array_merge( $url_args, $action_args ),
3109                  $base_url
3110              ),
3111              'invitations_' . $action
3112          );
3113  
3114          ?>
3115  
3116          <div class="wrap">
3117              <h1 class="wp-heading-inline"><?php echo esc_html( $header_text ); ?></h1>
3118              <hr class="wp-header-end">
3119  
3120              <p><?php echo esc_html( $helper_text ); ?></p>
3121  
3122              <?php if ( $invites ) : ?>
3123  
3124                  <ol class="bp-invitations-list">
3125                      <?php foreach ( $invites as $invite ) :
3126                          if ( $invite->invite_sent ) {
3127                              $last_notified = mysql2date( 'Y/m/d g:i:s a', $invite->date_modified );
3128                          } else {
3129                              $last_notified = __( 'Not yet notified', 'buddypress');
3130                          }
3131                          ?>
3132  
3133                          <li>
3134                              <strong><?php echo esc_html( $invite->invitee_email ) ?></strong>
3135  
3136                              <?php if ( 'resend' === $action ) : ?>
3137  
3138                                  <p class="description">
3139                                      <?php
3140                                      /* translators: %s: notification date */
3141                                      printf( esc_html__( 'Last notified: %s', 'buddypress'), $last_notified );
3142                                      ?>
3143                                  </p>
3144  
3145                              <?php endif; ?>
3146  
3147                          </li>
3148  
3149                      <?php endforeach; ?>
3150                  </ol>
3151  
3152              <?php endif ; ?>
3153  
3154              <?php if ( 'delete' === $action ) : ?>
3155  
3156                  <p><strong><?php esc_html_e( 'This action cannot be undone.', 'buddypress' ) ?></strong></p>
3157  
3158              <?php endif; ?>
3159  
3160              <?php if ( $invites ) : ?>
3161  
3162                  <a class="button-primary" href="<?php echo esc_url( $action_url ); ?>" <?php disabled( ! $invites ); ?>><?php esc_html_e( 'Confirm', 'buddypress' ); ?></a>
3163  
3164              <?php endif; ?>
3165  
3166              <a class="button" href="<?php echo esc_url( $cancel_url ); ?>"><?php esc_html_e( 'Cancel', 'buddypress' ) ?></a>
3167          </div>
3168  
3169          <?php
3170      }
3171  
3172  }
3173  endif; // End class_exists check.


Generated: Tue May 18 01:01:42 2021 Cross-referenced by PHPXref 0.7.1