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


Generated: Tue Mar 19 01:01:09 2024 Cross-referenced by PHPXref 0.7.1