[ Index ]

PHP Cross Reference of BuddyPress

title

Body

[close]

/src/bp-groups/ -> bp-groups-admin.php (source)

   1  <?php
   2  /**
   3   * BuddyPress Groups component admin screen.
   4   *
   5   * Props to WordPress core for the Comments admin screen, and its contextual
   6   * help text, on which this implementation is heavily based.
   7   *
   8   * @package BuddyPress
   9   * @subpackage Groups
  10   * @since 1.7.0
  11   */
  12  
  13  // Exit if accessed directly.
  14  defined( 'ABSPATH' ) || exit;
  15  
  16  // Include WP's list table class.
  17  if ( ! class_exists( 'WP_List_Table' ) ) {
  18      require ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
  19  }
  20  
  21  // The per_page screen option. Has to be hooked in extremely early.
  22  if ( is_admin() && ! empty( $_REQUEST['page'] ) && 'bp-groups' == $_REQUEST['page'] ) {
  23      add_filter( 'set-screen-option', 'bp_groups_admin_screen_options', 10, 3 );
  24  }
  25  
  26  /**
  27   * Register the Groups component admin screen.
  28   *
  29   * @since 1.7.0
  30   */
  31  function bp_groups_add_admin_menu() {
  32  
  33      // Add our screen.
  34      $hook = add_menu_page(
  35          _x( 'Groups', 'Admin Groups page title', 'buddypress' ),
  36          _x( 'Groups', 'Admin Groups menu', 'buddypress' ),
  37          'bp_moderate',
  38          'bp-groups',
  39          'bp_groups_admin',
  40          'div'
  41      );
  42  
  43      // Hook into early actions to load custom CSS and our init handler.
  44      add_action( "load-$hook", 'bp_groups_admin_load' );
  45  }
  46  add_action( bp_core_admin_hook(), 'bp_groups_add_admin_menu' );
  47  
  48  /**
  49   * Redirects the user on the Goups network admin screen when BuddyPress is network activated.
  50   *
  51   * @since 7.0.0
  52   */
  53  function bp_group_site_admin_network_admin_redirect() {
  54      wp_safe_redirect( add_query_arg( 'page', 'bp-groups', network_admin_url( 'admin.php' ) ) );
  55      exit();
  56  }
  57  
  58  /**
  59   * Create Groups submenu to manage BuddyPress types.
  60   *
  61   * @since 7.0.0
  62   */
  63  function bp_groups_admin_types_menu() {
  64      if ( ! bp_is_root_blog() ) {
  65          return;
  66      }
  67  
  68      if ( bp_is_network_activated() && ! bp_is_multiblog_mode() && is_network_admin() ) {
  69          // Adds a 'bp-groups' submenu to go to the root blog Group types screen.
  70          $group_type_admin_url = add_query_arg( 'taxonomy', 'bp_group_type', get_admin_url( bp_get_root_blog_id(), 'edit-tags.php' ) );
  71          add_submenu_page(
  72              'bp-groups',
  73              __( 'Group Types', 'buddypress' ),
  74              __( 'Group Types', 'buddypress' ),
  75              'bp_moderate',
  76              esc_url( $group_type_admin_url )
  77          );
  78      } elseif ( ! is_network_admin() ) {
  79          if ( bp_is_network_activated() && ! bp_is_multiblog_mode() ) {
  80              // Adds a 'bp-groups' menu to the root blog menu.
  81              $redirect_hook = add_menu_page(
  82                  _x( 'Groups', 'Admin Groups page title', 'buddypress' ),
  83                  _x( 'Groups', 'Admin Groups menu', 'buddypress' ),
  84                  'bp_moderate',
  85                  'bp-groups',
  86                  '__return_empty_string',
  87                  'div'
  88              );
  89  
  90              add_action( "load-{$redirect_hook}", 'bp_group_site_admin_network_admin_redirect' );
  91          }
  92  
  93          // Add the submenu to manage Group Types.
  94          add_submenu_page(
  95              'bp-groups',
  96              __( 'Group Types', 'buddypress' ),
  97              __( 'Group Types', 'buddypress' ),
  98              'bp_moderate',
  99              basename( add_query_arg( 'taxonomy', 'bp_group_type', bp_get_admin_url( 'edit-tags.php' ) ) )
 100          );
 101      }
 102  }
 103  add_action( 'bp_admin_menu', 'bp_groups_admin_types_menu' );
 104  
 105  /**
 106   * Add groups component to custom menus array.
 107   *
 108   * This ensures that the Groups menu item appears in the proper order on the
 109   * main Dashboard menu.
 110   *
 111   * @since 1.7.0
 112   *
 113   * @param array $custom_menus Array of BP top-level menu items.
 114   * @return array Menu item array, with Groups added.
 115   */
 116  function bp_groups_admin_menu_order( $custom_menus = array() ) {
 117      array_push( $custom_menus, 'bp-groups' );
 118      return $custom_menus;
 119  }
 120  add_filter( 'bp_admin_menu_order', 'bp_groups_admin_menu_order' );
 121  
 122  /**
 123   * Set up the Groups admin page.
 124   *
 125   * Loaded before the page is rendered, this function does all initial setup,
 126   * including: processing form requests, registering contextual help, and
 127   * setting up screen options.
 128   *
 129   * @since 1.7.0
 130   *
 131   * @global BP_Groups_List_Table $bp_groups_list_table Groups screen list table.
 132   */
 133  function bp_groups_admin_load() {
 134      global $bp_groups_list_table;
 135  
 136      // Build redirection URL.
 137      $redirect_to = remove_query_arg( array( 'action', 'action2', 'gid', 'deleted', 'error', 'updated', 'success_new', 'error_new', 'success_modified', 'error_modified' ), $_SERVER['REQUEST_URI'] );
 138  
 139      $doaction   = bp_admin_list_table_current_bulk_action();
 140      $min        = bp_core_get_minified_asset_suffix();
 141  
 142      /**
 143       * Fires at top of groups admin page.
 144       *
 145       * @since 1.7.0
 146       *
 147       * @param string $doaction Current $_GET action being performed in admin screen.
 148       */
 149      do_action( 'bp_groups_admin_load', $doaction );
 150  
 151      // Edit screen.
 152      if ( 'do_delete' == $doaction && ! empty( $_GET['gid'] ) ) {
 153  
 154          check_admin_referer( 'bp-groups-delete' );
 155  
 156          $group_ids = wp_parse_id_list( $_GET['gid'] );
 157  
 158          $count = 0;
 159          foreach ( $group_ids as $group_id ) {
 160              if ( groups_delete_group( $group_id ) ) {
 161                  $count++;
 162              }
 163          }
 164  
 165          $redirect_to = add_query_arg( 'deleted', $count, $redirect_to );
 166  
 167          bp_core_redirect( $redirect_to );
 168  
 169      } elseif ( 'edit' == $doaction && ! empty( $_GET['gid'] ) ) {
 170          // Columns screen option.
 171          add_screen_option( 'layout_columns', array( 'default' => 2, 'max' => 2, ) );
 172  
 173          get_current_screen()->add_help_tab( array(
 174              'id'      => 'bp-group-edit-overview',
 175              'title'   => __( 'Overview', 'buddypress' ),
 176              'content' =>
 177                  '<p>' . __( 'This page is a convenient way to edit the details associated with one of your groups.', 'buddypress' ) . '</p>' .
 178                  '<p>' . __( 'The Name and Description box is fixed in place, but you can reposition all the other boxes using drag and drop, and can minimize or expand them by clicking the title bar of each box. Use the Screen Options tab to hide or unhide, or to choose a 1- or 2-column layout for this screen.', 'buddypress' ) . '</p>'
 179          ) );
 180  
 181          // Help panel - sidebar links.
 182          get_current_screen()->set_help_sidebar(
 183              '<p><strong>' . __( 'For more information:', 'buddypress' ) . '</strong></p>' .
 184              '<p><a href="https://buddypress.org/support">' . __( 'Support Forums', 'buddypress' ) . '</a></p>'
 185          );
 186  
 187          // Register metaboxes for the edit screen.
 188          add_meta_box( 'submitdiv', _x( 'Save', 'group admin edit screen', 'buddypress' ), 'bp_groups_admin_edit_metabox_status', get_current_screen()->id, 'side', 'high' );
 189          add_meta_box( 'bp_group_settings', _x( 'Settings', 'group admin edit screen', 'buddypress' ), 'bp_groups_admin_edit_metabox_settings', get_current_screen()->id, 'side', 'core' );
 190          add_meta_box( 'bp_group_add_members', _x( 'Add New Members', 'group admin edit screen', 'buddypress' ), 'bp_groups_admin_edit_metabox_add_new_members', get_current_screen()->id, 'normal', 'core' );
 191          add_meta_box( 'bp_group_members', _x( 'Manage Members', 'group admin edit screen', 'buddypress' ), 'bp_groups_admin_edit_metabox_members', get_current_screen()->id, 'normal', 'core' );
 192  
 193          // Group Type metabox. Only added if group types have been registered.
 194          $group_types = bp_groups_get_group_types();
 195          if ( ! empty( $group_types ) ) {
 196              add_meta_box(
 197                  'bp_groups_admin_group_type',
 198                  _x( 'Group Type', 'groups admin edit screen', 'buddypress' ),
 199                  'bp_groups_admin_edit_metabox_group_type',
 200                  get_current_screen()->id,
 201                  'side',
 202                  'core'
 203              );
 204          }
 205  
 206          /**
 207           * Fires after the registration of all of the default group meta boxes.
 208           *
 209           * @since 1.7.0
 210           */
 211          do_action( 'bp_groups_admin_meta_boxes' );
 212  
 213          // Enqueue JavaScript files.
 214          wp_enqueue_script( 'postbox' );
 215          wp_enqueue_script( 'dashboard' );
 216  
 217      // Index screen.
 218      } else {
 219          // Create the Groups screen list table.
 220          $bp_groups_list_table = new BP_Groups_List_Table();
 221  
 222          // The per_page screen option.
 223          add_screen_option( 'per_page', array( 'label' => _x( 'Groups', 'Groups per page (screen options)', 'buddypress' )) );
 224  
 225          // Help panel - overview text.
 226          get_current_screen()->add_help_tab( array(
 227              'id'      => 'bp-groups-overview',
 228              'title'   => __( 'Overview', 'buddypress' ),
 229              'content' =>
 230                  '<p>' . __( 'You can manage groups much like you can manage comments and other content. This screen is customizable in the same ways as other management screens, and you can act on groups by using the on-hover action links or the Bulk Actions.', 'buddypress' ) . '</p>',
 231          ) );
 232  
 233          get_current_screen()->add_help_tab( array(
 234              'id'      => 'bp-groups-overview-actions',
 235              'title'   => __( 'Group Actions', 'buddypress' ),
 236              'content' =>
 237                  '<p>' . __( 'Clicking "Visit" will take you to the group&#8217;s public page. Use this link to see what the group looks like on the front end of your site.', 'buddypress' ) . '</p>' .
 238                  '<p>' . __( 'Clicking "Edit" will take you to a Dashboard panel where you can manage various details about the group, such as its name and description, its members, and other settings.', 'buddypress' ) . '</p>' .
 239                  '<p>' . __( 'If you click "Delete" under a specific group, or select a number of groups and then choose Delete from the Bulk Actions menu, you will be led to a page where you&#8217;ll be asked to confirm the permanent deletion of the group(s).', 'buddypress' ) . '</p>',
 240          ) );
 241  
 242          // Help panel - sidebar links.
 243          get_current_screen()->set_help_sidebar(
 244              '<p><strong>' . __( 'For more information:', 'buddypress' ) . '</strong></p>' .
 245              '<p>' . __( '<a href="https://buddypress.org/support/">Support Forums</a>', 'buddypress' ) . '</p>'
 246          );
 247  
 248          // Add accessible hidden heading and text for Groups screen pagination.
 249          get_current_screen()->set_screen_reader_content( array(
 250              /* translators: accessibility text */
 251              'heading_pagination' => __( 'Groups list navigation', 'buddypress' ),
 252          ) );
 253      }
 254  
 255      $bp = buddypress();
 256  
 257      // Enqueue CSS and JavaScript.
 258      wp_enqueue_script( 'bp_groups_admin_js', $bp->plugin_url . "bp-groups/admin/js/admin{$min}.js", array( 'jquery', 'wp-ajax-response', 'jquery-ui-autocomplete' ), bp_get_version(), true );
 259      wp_localize_script( 'bp_groups_admin_js', 'BP_Group_Admin', array(
 260          'add_member_placeholder' => __( 'Start typing a username to add a new member.', 'buddypress' ),
 261          'warn_on_leave'          => __( 'If you leave this page, you will lose any unsaved changes you have made to the group.', 'buddypress' ),
 262      ) );
 263      wp_enqueue_style( 'bp_groups_admin_css', $bp->plugin_url . "bp-groups/admin/css/admin{$min}.css", array(), bp_get_version() );
 264  
 265      wp_style_add_data( 'bp_groups_admin_css', 'rtl', 'replace' );
 266      if ( $min ) {
 267          wp_style_add_data( 'bp_groups_admin_css', 'suffix', $min );
 268      }
 269  
 270  
 271      if ( $doaction && 'save' == $doaction ) {
 272          // Get group ID.
 273          $group_id = isset( $_REQUEST['gid'] ) ? (int) $_REQUEST['gid'] : '';
 274  
 275          $redirect_to = add_query_arg( array(
 276              'gid'    => (int) $group_id,
 277              'action' => 'edit'
 278          ), $redirect_to );
 279  
 280          // Check this is a valid form submission.
 281          check_admin_referer( 'edit-group_' . $group_id );
 282  
 283          // Get the group from the database.
 284          $group = groups_get_group( $group_id );
 285  
 286          // If the group doesn't exist, just redirect back to the index.
 287          if ( empty( $group->slug ) ) {
 288              wp_redirect( $redirect_to );
 289              exit;
 290          }
 291  
 292          // Check the form for the updated properties.
 293          // Store errors.
 294          $error = 0;
 295          $success_new = $error_new = $success_modified = $error_modified = array();
 296  
 297          // Name, description and slug must not be empty.
 298          if ( empty( $_POST['bp-groups-name'] ) ) {
 299              $error = $error - 1;
 300          }
 301          if ( empty( $_POST['bp-groups-description'] ) ) {
 302              $error = $error - 2;
 303          }
 304          if ( empty( $_POST['bp-groups-slug'] ) ) {
 305              $error = $error - 4;
 306          }
 307  
 308          /*
 309           * Group name, slug, and description are handled with
 310           * groups_edit_base_group_details().
 311           */
 312          if ( ! $error && ! groups_edit_base_group_details( array(
 313                  'group_id'       => $group_id,
 314                  'name'           => $_POST['bp-groups-name'],
 315                  'slug'           => $_POST['bp-groups-slug'],
 316                  'description'    => $_POST['bp-groups-description'],
 317                  'notify_members' => false,
 318              ) ) ) {
 319              $error = $group_id;
 320          }
 321  
 322          // Enable discussion forum.
 323          $enable_forum   = ( isset( $_POST['group-show-forum'] ) ) ? 1 : 0;
 324  
 325          /**
 326           * Filters the allowed status values for the group.
 327           *
 328           * @since 1.0.2
 329           *
 330           * @param array $value Array of allowed group statuses.
 331           */
 332          $allowed_status = apply_filters( 'groups_allowed_status', array( 'public', 'private', 'hidden' ) );
 333          $status         = ( in_array( $_POST['group-status'], (array) $allowed_status ) ) ? $_POST['group-status'] : 'public';
 334  
 335          /**
 336           * Filters the allowed invite status values for the group.
 337           *
 338           * @since 1.5.0
 339           *
 340           * @param array $value Array of allowed invite statuses.
 341           */
 342          $allowed_invite_status = apply_filters( 'groups_allowed_invite_status', array( 'members', 'mods', 'admins' ) );
 343          $invite_status           = in_array( $_POST['group-invite-status'], (array) $allowed_invite_status ) ? $_POST['group-invite-status'] : 'members';
 344  
 345          if ( !groups_edit_group_settings( $group_id, $enable_forum, $status, $invite_status ) ) {
 346              $error = $group_id;
 347          }
 348  
 349          // Process new members.
 350          $user_names = array();
 351  
 352          if ( ! empty( $_POST['bp-groups-new-members'] ) ) {
 353              $user_names = array_merge( $user_names, explode( ',', $_POST['bp-groups-new-members'] ) );
 354          }
 355  
 356          if ( ! empty( $user_names ) ) {
 357  
 358              foreach( array_values( $user_names ) as $user_name ) {
 359                  $un = trim( $user_name );
 360  
 361                  // Make sure the user exists before attempting
 362                  // to add to the group.
 363                  $user = get_user_by( 'slug', $un );
 364  
 365                  if ( empty( $user ) ) {
 366                      $error_new[] = $un;
 367                  } else {
 368                      if ( ! groups_join_group( $group_id, $user->ID ) ) {
 369                          $error_new[]   = $un;
 370                      } else {
 371                          $success_new[] = $un;
 372                      }
 373                  }
 374              }
 375          }
 376  
 377          // Process member role changes.
 378          if ( ! empty( $_POST['bp-groups-role'] ) && ! empty( $_POST['bp-groups-existing-role'] ) ) {
 379  
 380              // Before processing anything, make sure you're not
 381              // attempting to remove the all user admins.
 382              $admin_count = 0;
 383              foreach ( (array) $_POST['bp-groups-role'] as $new_role ) {
 384                  if ( 'admin' == $new_role ) {
 385                      $admin_count++;
 386                      break;
 387                  }
 388              }
 389  
 390              if ( ! $admin_count ) {
 391  
 392                  $redirect_to = add_query_arg( 'no_admins', 1, $redirect_to );
 393                  $error = $group_id;
 394  
 395              } else {
 396  
 397                  // Process only those users who have had their roles changed.
 398                  foreach ( (array) $_POST['bp-groups-role'] as $user_id => $new_role ) {
 399                      $user_id = (int) $user_id;
 400  
 401                      $existing_role = isset( $_POST['bp-groups-existing-role'][$user_id] ) ? $_POST['bp-groups-existing-role'][$user_id] : '';
 402  
 403                      if ( $existing_role != $new_role ) {
 404                          $result = false;
 405  
 406                          switch ( $new_role ) {
 407                              case 'mod' :
 408                                  // Admin to mod is a demotion. Demote to
 409                                  // member, then fall through.
 410                                  if ( 'admin' == $existing_role ) {
 411                                      groups_demote_member( $user_id, $group_id );
 412                                  }
 413  
 414                              case 'admin' :
 415                                  // If the user was banned, we must
 416                                  // unban first.
 417                                  if ( 'banned' == $existing_role ) {
 418                                      groups_unban_member( $user_id, $group_id );
 419                                  }
 420  
 421                                  // At this point, each existing_role
 422                                  // is a member, so promote.
 423                                  $result = groups_promote_member( $user_id, $group_id, $new_role );
 424  
 425                                  break;
 426  
 427                              case 'member' :
 428  
 429                                  if ( 'admin' == $existing_role || 'mod' == $existing_role ) {
 430                                      $result = groups_demote_member( $user_id, $group_id );
 431                                  } elseif ( 'banned' == $existing_role ) {
 432                                      $result = groups_unban_member( $user_id, $group_id );
 433                                  }
 434  
 435                                  break;
 436  
 437                              case 'banned' :
 438  
 439                                  $result = groups_ban_member( $user_id, $group_id );
 440  
 441                                  break;
 442  
 443                              case 'remove' :
 444  
 445                                  $result = groups_remove_member( $user_id, $group_id );
 446  
 447                                  break;
 448                          }
 449  
 450                          // Store the success or failure.
 451                          if ( $result ) {
 452                              $success_modified[] = $user_id;
 453                          } else {
 454                              $error_modified[]   = $user_id;
 455                          }
 456                      }
 457                  }
 458              }
 459          }
 460  
 461          /**
 462           * Fires before redirect so plugins can do something first on save action.
 463           *
 464           * @since 1.6.0
 465           *
 466           * @param int $group_id ID of the group being edited.
 467           */
 468          do_action( 'bp_group_admin_edit_after', $group_id );
 469  
 470          // Create the redirect URL.
 471          if ( $error ) {
 472              // This means there was an error updating group details.
 473              $redirect_to = add_query_arg( 'error', (int) $error, $redirect_to );
 474          } else {
 475              // Group details were update successfully.
 476              $redirect_to = add_query_arg( 'updated', 1, $redirect_to );
 477          }
 478  
 479          if ( !empty( $success_new ) ) {
 480              $success_new = implode( ',', array_filter( $success_new, 'urlencode' ) );
 481              $redirect_to = add_query_arg( 'success_new', $success_new, $redirect_to );
 482          }
 483  
 484          if ( !empty( $error_new ) ) {
 485              $error_new = implode( ',', array_filter( $error_new, 'urlencode' ) );
 486              $redirect_to = add_query_arg( 'error_new', $error_new, $redirect_to );
 487          }
 488  
 489          if ( !empty( $success_modified ) ) {
 490              $success_modified = implode( ',', array_filter( $success_modified, 'urlencode' ) );
 491              $redirect_to = add_query_arg( 'success_modified', $success_modified, $redirect_to );
 492          }
 493  
 494          if ( !empty( $error_modified ) ) {
 495              $error_modified = implode( ',', array_filter( $error_modified, 'urlencode' ) );
 496              $redirect_to = add_query_arg( 'error_modified', $error_modified, $redirect_to );
 497          }
 498  
 499          /**
 500           * Filters the URL to redirect to after successfully editing a group.
 501           *
 502           * @since 1.7.0
 503           *
 504           * @param string $redirect_to URL to redirect user to.
 505           */
 506          wp_redirect( apply_filters( 'bp_group_admin_edit_redirect', $redirect_to ) );
 507          exit;
 508  
 509  
 510      // If a referrer and a nonce is supplied, but no action, redirect back.
 511      } elseif ( ! empty( $_GET['_wp_http_referer'] ) ) {
 512          wp_redirect( remove_query_arg( array( '_wp_http_referer', '_wpnonce' ), stripslashes( $_SERVER['REQUEST_URI'] ) ) );
 513          exit;
 514      }
 515  }
 516  
 517  /**
 518   * Handle save/update of screen options for the Groups component admin screen.
 519   *
 520   * @since 1.7.0
 521   *
 522   * @param string $value     Will always be false unless another plugin filters it first.
 523   * @param string $option    Screen option name.
 524   * @param string $new_value Screen option form value.
 525   * @return string|int Option value. False to abandon update.
 526   */
 527  function bp_groups_admin_screen_options( $value, $option, $new_value ) {
 528      if ( 'toplevel_page_bp_groups_per_page' != $option && 'toplevel_page_bp_groups_network_per_page' != $option )
 529          return $value;
 530  
 531      // Per page.
 532      $new_value = (int) $new_value;
 533      if ( $new_value < 1 || $new_value > 999 )
 534          return $value;
 535  
 536      return $new_value;
 537  }
 538  
 539  /**
 540   * Select the appropriate Groups admin screen, and output it.
 541   *
 542   * @since 1.7.0
 543   */
 544  function bp_groups_admin() {
 545      // Decide whether to load the index or edit screen.
 546      $doaction = bp_admin_list_table_current_bulk_action();
 547  
 548      // Display the single group edit screen.
 549      if ( 'edit' == $doaction && ! empty( $_GET['gid'] ) ) {
 550          bp_groups_admin_edit();
 551  
 552      // Display the group deletion confirmation screen.
 553      } elseif ( 'delete' == $doaction && ! empty( $_GET['gid'] ) ) {
 554          bp_groups_admin_delete();
 555  
 556      // Otherwise, display the groups index screen.
 557      } else {
 558          bp_groups_admin_index();
 559      }
 560  }
 561  
 562  /**
 563   * Display the single groups edit screen.
 564   *
 565   * @since 1.7.0
 566   */
 567  function bp_groups_admin_edit() {
 568  
 569      if ( ! bp_current_user_can( 'bp_moderate' ) )
 570          die( '-1' );
 571  
 572      $messages = array();
 573  
 574      // If the user has just made a change to a group, build status messages.
 575      if ( !empty( $_REQUEST['no_admins'] ) || ! empty( $_REQUEST['error'] ) || ! empty( $_REQUEST['updated'] ) || ! empty( $_REQUEST['error_new'] ) || ! empty( $_REQUEST['success_new'] ) || ! empty( $_REQUEST['error_modified'] ) || ! empty( $_REQUEST['success_modified'] ) ) {
 576          $no_admins        = ! empty( $_REQUEST['no_admins']        ) ? 1                                             : 0;
 577          $errors           = ! empty( $_REQUEST['error']            ) ? $_REQUEST['error']                            : '';
 578          $updated          = ! empty( $_REQUEST['updated']          ) ? $_REQUEST['updated']                          : '';
 579          $error_new        = ! empty( $_REQUEST['error_new']        ) ? explode( ',', $_REQUEST['error_new'] )        : array();
 580          $success_new      = ! empty( $_REQUEST['success_new']      ) ? explode( ',', $_REQUEST['success_new'] )      : array();
 581          $error_modified   = ! empty( $_REQUEST['error_modified']   ) ? explode( ',', $_REQUEST['error_modified'] )   : array();
 582          $success_modified = ! empty( $_REQUEST['success_modified'] ) ? explode( ',', $_REQUEST['success_modified'] ) : array();
 583  
 584          if ( ! empty( $no_admins ) ) {
 585              $messages[] = __( 'You cannot remove all administrators from a group.', 'buddypress' );
 586          }
 587  
 588          if ( ! empty( $errors ) ) {
 589              if ( $errors < 0 ) {
 590                  $messages[] = __( 'Group name, slug, and description are all required fields.', 'buddypress' );
 591              } else {
 592                  $messages[] = __( 'An error occurred when trying to update your group details.', 'buddypress' );
 593              }
 594  
 595          } elseif ( ! empty( $updated ) ) {
 596              $messages[] = __( 'The group has been updated successfully.', 'buddypress' );
 597          }
 598  
 599          if ( ! empty( $error_new ) ) {
 600              /* translators: %s: comma separated list of usernames */
 601              $messages[] = sprintf( __( 'The following users could not be added to the group: %s', 'buddypress' ), '<em>' . esc_html( implode( ', ', $error_new ) ) . '</em>' );
 602          }
 603  
 604          if ( ! empty( $success_new ) ) {
 605              /* translators: %s: comma separated list of usernames */
 606              $messages[] = sprintf( __( 'The following users were successfully added to the group: %s', 'buddypress' ), '<em>' . esc_html( implode( ', ', $success_new ) ) . '</em>' );
 607          }
 608  
 609          if ( ! empty( $error_modified ) ) {
 610              $error_modified = bp_groups_admin_get_usernames_from_ids( $error_modified );
 611              /* translators: %s: comma separated list of usernames */
 612              $messages[] = sprintf( __( 'An error occurred when trying to modify the following members: %s', 'buddypress' ), '<em>' . esc_html( implode( ', ', $error_modified ) ) . '</em>' );
 613          }
 614  
 615          if ( ! empty( $success_modified ) ) {
 616              $success_modified = bp_groups_admin_get_usernames_from_ids( $success_modified );
 617              /* translators: %s: comma separated list of usernames */
 618              $messages[] = sprintf( __( 'The following members were successfully modified: %s', 'buddypress' ), '<em>' . esc_html( implode( ', ', $success_modified ) ) . '</em>' );
 619          }
 620      }
 621  
 622      $is_error = ! empty( $no_admins ) || ! empty( $errors ) || ! empty( $error_new ) || ! empty( $error_modified );
 623  
 624      // Get the group from the database.
 625      $group = groups_get_group( (int) $_GET['gid'] );
 626  
 627      $group_name = isset( $group->name ) ? bp_get_group_name( $group ) : '';
 628  
 629      // Construct URL for form.
 630      $form_url = remove_query_arg( array( 'action', 'deleted', 'no_admins', 'error', 'error_new', 'success_new', 'error_modified', 'success_modified' ), $_SERVER['REQUEST_URI'] );
 631      $form_url = add_query_arg( 'action', 'save', $form_url );
 632  
 633      /**
 634       * Fires before the display of the edit form.
 635       *
 636       * Useful for plugins to modify the group before display.
 637       *
 638       * @since 1.7.0
 639       *
 640       * @param BP_Groups_Group $this Instance of the current group being edited. Passed by reference.
 641       */
 642      do_action_ref_array( 'bp_groups_admin_edit', array( &$group ) ); ?>
 643  
 644      <div class="wrap">
 645          <h1 class="wp-heading-inline"><?php _e( 'Edit Group', 'buddypress' ); ?></h1>
 646  
 647          <?php if ( is_user_logged_in() && bp_user_can_create_groups() ) : ?>
 648              <a class="page-title-action" href="<?php echo trailingslashit( bp_get_groups_directory_permalink() . 'create' ); ?>"><?php _e( 'Add New', 'buddypress' ); ?></a>
 649          <?php endif; ?>
 650  
 651          <hr class="wp-header-end">
 652  
 653          <?php // If the user has just made a change to an group, display the status messages. ?>
 654          <?php if ( !empty( $messages ) ) : ?>
 655              <div id="moderated" class="<?php echo ( $is_error ) ? 'error' : 'updated'; ?> notice is-dismissible"><p><?php echo implode( "</p><p>", $messages ); ?></p></div>
 656          <?php endif; ?>
 657  
 658          <?php if ( $group->id ) : ?>
 659  
 660              <form action="<?php echo esc_url( $form_url ); ?>" id="bp-groups-edit-form" method="post">
 661                  <div id="poststuff">
 662  
 663                      <div id="post-body" class="metabox-holder columns-<?php echo 1 == get_current_screen()->get_columns() ? '1' : '2'; ?>">
 664                          <div id="post-body-content">
 665                              <div id="postdiv">
 666                                  <div id="bp_groups_name" class="groupbox">
 667                                      <h2><?php _e( 'Name and Description', 'buddypress' ); ?></h2>
 668                                      <div class="inside">
 669                                          <label for="bp-groups-name" class="screen-reader-text"><?php
 670                                              /* translators: accessibility text */
 671                                              _e( 'Group Name', 'buddypress' );
 672                                          ?></label>
 673                                          <input type="text" name="bp-groups-name" id="bp-groups-name" value="<?php echo esc_attr( stripslashes( $group_name ) ) ?>" />
 674                                          <div id="bp-groups-permalink-box">
 675                                              <strong><?php esc_html_e( 'Permalink:', 'buddypress' ) ?></strong>
 676                                              <span id="bp-groups-permalink">
 677                                                  <?php bp_groups_directory_permalink(); ?> <input type="text" id="bp-groups-slug" name="bp-groups-slug" value="<?php bp_group_slug( $group ); ?>" autocomplete="off"> /
 678                                              </span>
 679                                              <a href="<?php echo bp_group_permalink( $group ) ?>" class="button button-small" id="bp-groups-visit-group"><?php esc_html_e( 'Visit Group', 'buddypress' ) ?></a>
 680                                          </div>
 681  
 682                                          <label for="bp-groups-description" class="screen-reader-text"><?php
 683                                              /* translators: accessibility text */
 684                                              _e( 'Group Description', 'buddypress' );
 685                                          ?></label>
 686                                          <?php wp_editor( stripslashes( $group->description ), 'bp-groups-description', array( 'media_buttons' => false, 'teeny' => true, 'textarea_rows' => 5, 'quicktags' => array( 'buttons' => 'strong,em,link,block,del,ins,img,code,spell,close' ) ) ); ?>
 687                                      </div>
 688                                  </div>
 689                              </div>
 690                          </div><!-- #post-body-content -->
 691  
 692                          <div id="postbox-container-1" class="postbox-container">
 693                              <?php do_meta_boxes( get_current_screen()->id, 'side', $group ); ?>
 694                          </div>
 695  
 696                          <div id="postbox-container-2" class="postbox-container">
 697                              <?php do_meta_boxes( get_current_screen()->id, 'normal', $group ); ?>
 698                              <?php do_meta_boxes( get_current_screen()->id, 'advanced', $group ); ?>
 699                          </div>
 700                      </div><!-- #post-body -->
 701  
 702                  </div><!-- #poststuff -->
 703                  <?php wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?>
 704                  <?php wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false ); ?>
 705                  <?php wp_nonce_field( 'edit-group_' . $group->id ); ?>
 706              </form>
 707  
 708          <?php else : ?>
 709  
 710              <p><?php
 711                  printf(
 712                      '%1$s <a href="%2$s">%3$s</a>',
 713                      __( 'No group found with this ID.', 'buddypress' ),
 714                      esc_url( bp_get_admin_url( 'admin.php?page=bp-groups' ) ),
 715                      __( 'Go back and try again.', 'buddypress' )
 716                  );
 717              ?></p>
 718  
 719          <?php endif; ?>
 720  
 721      </div><!-- .wrap -->
 722  
 723  <?php
 724  }
 725  
 726  /**
 727   * Display the Group delete confirmation screen.
 728   *
 729   * We include a separate confirmation because group deletion is truly
 730   * irreversible.
 731   *
 732   * @since 1.7.0
 733   */
 734  function bp_groups_admin_delete() {
 735  
 736      if ( ! bp_current_user_can( 'bp_moderate' ) ) {
 737          die( '-1' );
 738      }
 739  
 740      $group_ids = isset( $_REQUEST['gid'] ) ? $_REQUEST['gid'] : 0;
 741      if ( ! is_array( $group_ids ) ) {
 742          $group_ids = explode( ',', $group_ids );
 743      }
 744      $group_ids = wp_parse_id_list( $group_ids );
 745      $groups    = groups_get_groups( array(
 746          'include'     => $group_ids,
 747          'show_hidden' => true,
 748          'per_page'    => null, // Return all results.
 749      ) );
 750  
 751      // Create a new list of group ids, based on those that actually exist.
 752      $gids = array();
 753      foreach ( $groups['groups'] as $group ) {
 754          $gids[] = $group->id;
 755      }
 756  
 757      $base_url  = remove_query_arg( array( 'action', 'action2', 'paged', 's', '_wpnonce', 'gid' ), $_SERVER['REQUEST_URI'] ); ?>
 758  
 759      <div class="wrap">
 760          <h1 class="wp-heading-inline"><?php _e( 'Delete Groups', 'buddypress' ) ?></h1>
 761          <hr class="wp-header-end">
 762  
 763          <p><?php _e( 'You are about to delete the following groups:', 'buddypress' ) ?></p>
 764  
 765          <ul class="bp-group-delete-list">
 766          <?php foreach ( $groups['groups'] as $group ) : ?>
 767              <li><?php echo esc_html( bp_get_group_name( $group ) ); ?></li>
 768          <?php endforeach; ?>
 769          </ul>
 770  
 771          <p><strong><?php _e( 'This action cannot be undone.', 'buddypress' ) ?></strong></p>
 772  
 773          <a class="button-primary" href="<?php echo esc_url( wp_nonce_url( add_query_arg( array( 'action' => 'do_delete', 'gid' => implode( ',', $gids ) ), $base_url ), 'bp-groups-delete' ) ); ?>"><?php _e( 'Delete Permanently', 'buddypress' ) ?></a>
 774          <a class="button" href="<?php echo esc_attr( $base_url ); ?>"><?php _e( 'Cancel', 'buddypress' ) ?></a>
 775      </div>
 776  
 777      <?php
 778  }
 779  
 780  /**
 781   * Display the Groups admin index screen.
 782   *
 783   * This screen contains a list of all BuddyPress groups.
 784   *
 785   * @since 1.7.0
 786   *
 787   * @global BP_Groups_List_Table $bp_groups_list_table Group screen list table.
 788   * @global string $plugin_page Currently viewed plugin page.
 789   */
 790  function bp_groups_admin_index() {
 791      global $bp_groups_list_table, $plugin_page;
 792  
 793      $messages = array();
 794  
 795      // If the user has just made a change to a group, build status messages.
 796      if ( ! empty( $_REQUEST['deleted'] ) ) {
 797          $deleted  = ! empty( $_REQUEST['deleted'] ) ? (int) $_REQUEST['deleted'] : 0;
 798  
 799          if ( $deleted > 0 ) {
 800              /* translators: %s: number of deleted groups */
 801              $messages[] = sprintf( _n( '%s group has been permanently deleted.', '%s groups have been permanently deleted.', $deleted, 'buddypress' ), number_format_i18n( $deleted ) );
 802          }
 803      }
 804  
 805      // Prepare the group items for display.
 806      $bp_groups_list_table->prepare_items();
 807  
 808      /**
 809       * Fires before the display of messages for the edit form.
 810       *
 811       * Useful for plugins to modify the messages before display.
 812       *
 813       * @since 1.7.0
 814       *
 815       * @param array $messages Array of messages to be displayed.
 816       */
 817      do_action( 'bp_groups_admin_index', $messages ); ?>
 818  
 819      <div class="wrap">
 820  
 821          <h1 class="wp-heading-inline"><?php _e( 'Groups', 'buddypress' ); ?></h1>
 822  
 823          <?php if ( is_user_logged_in() && bp_user_can_create_groups() ) : ?>
 824              <a class="page-title-action" href="<?php echo trailingslashit( bp_get_groups_directory_permalink() . 'create' ); ?>"><?php _e( 'Add New', 'buddypress' ); ?></a>
 825          <?php endif; ?>
 826  
 827          <?php if ( !empty( $_REQUEST['s'] ) ) : ?>
 828              <span class="subtitle"><?php printf( __( 'Search results for &#8220;%s&#8221;', 'buddypress' ), wp_html_excerpt( esc_html( stripslashes( $_REQUEST['s'] ) ), 50 ) ); ?></span>
 829          <?php endif; ?>
 830  
 831          <hr class="wp-header-end">
 832  
 833          <?php // If the user has just made a change to an group, display the status messages. ?>
 834          <?php if ( !empty( $messages ) ) : ?>
 835              <div id="moderated" class="<?php echo ( ! empty( $_REQUEST['error'] ) ) ? 'error' : 'updated'; ?> notice is-dismissible"><p><?php echo implode( "<br/>\n", $messages ); ?></p></div>
 836          <?php endif; ?>
 837  
 838          <?php // Display each group on its own row. ?>
 839          <?php $bp_groups_list_table->views(); ?>
 840  
 841          <form id="bp-groups-form" action="" method="get">
 842              <?php $bp_groups_list_table->search_box( __( 'Search all Groups', 'buddypress' ), 'bp-groups' ); ?>
 843              <input type="hidden" name="page" value="<?php echo esc_attr( $plugin_page ); ?>" />
 844              <?php $bp_groups_list_table->display(); ?>
 845          </form>
 846  
 847      </div>
 848  
 849  <?php
 850  }
 851  
 852  /**
 853   * Markup for the single group's Settings metabox.
 854   *
 855   * @since 1.7.0
 856   *
 857   * @param object $item Information about the current group.
 858   */
 859  function bp_groups_admin_edit_metabox_settings( $item ) {
 860  
 861      $invite_status = bp_group_get_invite_status( $item->id ); ?>
 862  
 863      <?php if ( bp_is_active( 'forums' ) ) : ?>
 864          <div class="bp-groups-settings-section" id="bp-groups-settings-section-forum">
 865              <label for="group-show-forum"><input type="checkbox" name="group-show-forum" id="group-show-forum" <?php checked( $item->enable_forum ) ?> /> <?php _e( 'Enable discussion forum', 'buddypress' ) ?></label>
 866          </div>
 867      <?php endif; ?>
 868  
 869      <div class="bp-groups-settings-section" id="bp-groups-settings-section-status">
 870          <fieldset>
 871              <legend><?php _e( 'Privacy', 'buddypress' ); ?></legend>
 872  
 873              <label for="bp-group-status-public"><input type="radio" name="group-status" id="bp-group-status-public" value="public" <?php checked( $item->status, 'public' ) ?> /><?php _e( 'Public', 'buddypress' ) ?></label>
 874              <label for="bp-group-status-private"><input type="radio" name="group-status" id="bp-group-status-private" value="private" <?php checked( $item->status, 'private' ) ?> /><?php _e( 'Private', 'buddypress' ) ?></label>
 875              <label for="bp-group-status-hidden"><input type="radio" name="group-status" id="bp-group-status-hidden" value="hidden" <?php checked( $item->status, 'hidden' ) ?> /><?php _e( 'Hidden', 'buddypress' ) ?></label>
 876          </fieldset>
 877      </div>
 878  
 879      <div class="bp-groups-settings-section" id="bp-groups-settings-section-invite-status">
 880          <fieldset>
 881              <legend><?php _e( 'Who can invite others to this group?', 'buddypress' ); ?></legend>
 882  
 883              <label for="bp-group-invite-status-members"><input type="radio" name="group-invite-status" id="bp-group-invite-status-members" value="members" <?php checked( $invite_status, 'members' ) ?> /><?php _e( 'All group members', 'buddypress' ) ?></label>
 884              <label for="bp-group-invite-status-mods"><input type="radio" name="group-invite-status" id="bp-group-invite-status-mods" value="mods" <?php checked( $invite_status, 'mods' ) ?> /><?php _e( 'Group admins and mods only', 'buddypress' ) ?></label>
 885              <label for="bp-group-invite-status-admins"><input type="radio" name="group-invite-status" id="bp-group-invite-status-admins" value="admins" <?php checked( $invite_status, 'admins' ) ?> /><?php _e( 'Group admins only', 'buddypress' ) ?></label>
 886          </fieldset>
 887      </div>
 888  
 889  <?php
 890  }
 891  
 892  /**
 893   * Output the markup for a single group's Add New Members metabox.
 894   *
 895   * @since 1.7.0
 896   *
 897   * @param BP_Groups_Group $item The BP_Groups_Group object for the current group.
 898   */
 899  function bp_groups_admin_edit_metabox_add_new_members( $item ) {
 900      if ( bp_is_large_install() ) {
 901          $class  = '';
 902          $notice = __( 'Enter a comma-separated list of user logins.', 'buddypress' );
 903      } else {
 904          $class  = 'bp-suggest-user';
 905          $notice = '';
 906      }
 907  
 908      ?>
 909  
 910      <label for="bp-groups-new-members" class="screen-reader-text"><?php
 911          /* translators: accessibility text */
 912          _e( 'Add new members', 'buddypress' );
 913      ?></label>
 914      <input name="bp-groups-new-members" type="text" id="bp-groups-new-members" class="<?php echo esc_attr( $class ); ?>" placeholder="" />
 915      <?php if ( $notice ) : ?>
 916          <p class="description"><?php echo esc_html( $notice ); ?></p>
 917      <?php endif; ?>
 918      <ul id="bp-groups-new-members-list"></ul>
 919      <?php
 920  }
 921  
 922  /**
 923   * Renders the Members metabox on single group pages.
 924   *
 925   * @since 1.7.0
 926   *
 927   * @param BP_Groups_Group $item The BP_Groups_Group object for the current group.
 928   */
 929  function bp_groups_admin_edit_metabox_members( $item ) {
 930      // Use the BP REST API if it supported.
 931      if ( bp_rest_api_is_available() && bp_groups_has_manage_group_members_templates() ) {
 932          wp_enqueue_script( 'bp-group-manage-members' );
 933          wp_localize_script(
 934              'bp-group-manage-members',
 935              'bpGroupManageMembersSettings',
 936              bp_groups_get_group_manage_members_script_data( $item->id )
 937          );
 938  
 939          // Inject the Group Manage Members interface.
 940          bp_groups_manage_group_members_interface( 'admin_footer' );
 941  
 942          /**
 943           * Echo out the JavaScript variable.
 944           * This seems to be required by the autocompleter, leaving this here for now...
 945           */
 946          echo '<script type="text/javascript">var group_id = "' . esc_js( $item->id ) . '";</script>';
 947          return;
 948      }
 949  
 950      // Pull up a list of group members, so we can separate out the types
 951      // We'll also keep track of group members here to place them into a
 952      // JavaScript variable, which will help with group member autocomplete.
 953      $members = array(
 954          'admin'  => array(),
 955          'mod'    => array(),
 956          'member' => array(),
 957          'banned' => array(),
 958      );
 959  
 960      $pagination = array(
 961          'admin'  => array(),
 962          'mod'    => array(),
 963          'member' => array(),
 964          'banned' => array(),
 965      );
 966  
 967      foreach ( $members as $type => &$member_type_users ) {
 968          $page_qs_key       = $type . '_page';
 969          $current_type_page = isset( $_GET[ $page_qs_key ] ) ? absint( $_GET[ $page_qs_key ] ) : 1;
 970          $member_type_query = new BP_Group_Member_Query( array(
 971              'group_id'   => $item->id,
 972              'group_role' => array( $type ),
 973              'type'       => 'alphabetical',
 974              /**
 975               * Filters the admin members type per page value.
 976               *
 977               * @since 2.8.0
 978               *
 979               * @param int    $value Member types per page. Default 10.
 980               * @param string $type  Member type.
 981               */
 982              'per_page'   => apply_filters( 'bp_groups_admin_members_type_per_page', 10, $type ),
 983              'page'       => $current_type_page,
 984          ) );
 985  
 986          $member_type_users   = $member_type_query->results;
 987          $pagination[ $type ] = bp_groups_admin_create_pagination_links( $member_type_query, $type );
 988      }
 989  
 990      // Echo out the JavaScript variable.
 991      echo '<script type="text/javascript">var group_id = "' . esc_js( $item->id ) . '";</script>';
 992  
 993      // Loop through each member type.
 994      foreach ( $members as $member_type => $type_users ) : ?>
 995  
 996          <div class="bp-groups-member-type" id="bp-groups-member-type-<?php echo esc_attr( $member_type ) ?>">
 997  
 998              <h3><?php switch ( $member_type ) :
 999                      case 'admin'  : esc_html_e( 'Administrators', 'buddypress' ); break;
1000                      case 'mod'    : esc_html_e( 'Moderators',     'buddypress' ); break;
1001                      case 'member' : esc_html_e( 'Members',        'buddypress' ); break;
1002                      case 'banned' : esc_html_e( 'Banned Members', 'buddypress' ); break;
1003              endswitch; ?></h3>
1004  
1005              <div class="bp-group-admin-pagination table-top">
1006                  <?php echo $pagination[ $member_type ] ?>
1007              </div>
1008  
1009          <?php if ( !empty( $type_users ) ) : ?>
1010  
1011              <table class="widefat bp-group-members">
1012                  <thead>
1013                      <tr>
1014                          <th scope="col" class="uid-column"><?php _ex( 'ID', 'Group member user_id in group admin', 'buddypress' ); ?></th>
1015                          <th scope="col" class="uname-column"><?php _ex( 'Name', 'Group member name in group admin', 'buddypress' ); ?></th>
1016                          <th scope="col" class="urole-column"><?php _ex( 'Group Role', 'Group member role in group admin', 'buddypress' ); ?></th>
1017                      </tr>
1018                  </thead>
1019  
1020                  <tbody>
1021  
1022                  <?php foreach ( $type_users as $type_user ) : ?>
1023                      <tr>
1024                          <th scope="row" class="uid-column"><?php echo esc_html( $type_user->ID ); ?></th>
1025  
1026                          <td class="uname-column">
1027                              <a style="float: left;" href="<?php echo bp_core_get_user_domain( $type_user->ID ); ?>"><?php echo bp_core_fetch_avatar( array(
1028                                  'item_id' => $type_user->ID,
1029                                  'width'   => '32',
1030                                  'height'  => '32'
1031                              ) ); ?></a>
1032  
1033                              <span style="margin: 8px; float: left;"><?php echo bp_core_get_userlink( $type_user->ID ); ?></span>
1034                          </td>
1035  
1036                          <td class="urole-column">
1037                              <label for="bp-groups-role-<?php echo esc_attr( $type_user->ID ); ?>" class="screen-reader-text"><?php
1038                                  /* translators: accessibility text */
1039                                  _e( 'Select group role for member', 'buddypress' );
1040                              ?></label>
1041                              <select class="bp-groups-role" id="bp-groups-role-<?php echo esc_attr( $type_user->ID ); ?>" name="bp-groups-role[<?php echo esc_attr( $type_user->ID ); ?>]">
1042                                  <optgroup label="<?php esc_attr_e( 'Roles', 'buddypress' ); ?>">
1043                                      <option class="admin"  value="admin"  <?php selected( 'admin',  $member_type ); ?>><?php esc_html_e( 'Administrator', 'buddypress' ); ?></option>
1044                                      <option class="mod"    value="mod"    <?php selected( 'mod',    $member_type ); ?>><?php esc_html_e( 'Moderator',     'buddypress' ); ?></option>
1045                                      <option class="member" value="member" <?php selected( 'member', $member_type ); ?>><?php esc_html_e( 'Member',        'buddypress' ); ?></option>
1046                                      <?php if ( 'banned' === $member_type ) : ?>
1047                                      <option class="banned" value="banned" <?php selected( 'banned', $member_type ); ?>><?php esc_html_e( 'Banned',        'buddypress' ); ?></option>
1048                                      <?php endif; ?>
1049                                  </optgroup>
1050                                  <optgroup label="<?php esc_attr_e( 'Actions', 'buddypress' ); ?>">
1051                                      <option class="remove" value="remove"><?php esc_html_e( 'Remove', 'buddypress' ); ?></option>
1052                                      <?php if ( 'banned' !== $member_type ) : ?>
1053                                          <option class="banned" value="banned"><?php esc_html_e( 'Ban', 'buddypress' ); ?></option>
1054                                      <?php endif; ?>
1055                                  </optgroup>
1056                              </select>
1057  
1058                              <?php
1059                              /**
1060                               * Store the current role for this user,
1061                               * so we can easily detect changes.
1062                               *
1063                               * @todo remove this, and do database detection on save
1064                               */
1065                              ?>
1066                              <input type="hidden" name="bp-groups-existing-role[<?php echo esc_attr( $type_user->ID ); ?>]" value="<?php echo esc_attr( $member_type ); ?>" />
1067                          </td>
1068                      </tr>
1069  
1070                      <?php if ( has_filter( 'bp_groups_admin_manage_member_row' ) ) : ?>
1071                          <tr>
1072                              <td colspan="3">
1073                                  <?php
1074  
1075                                  /**
1076                                   * Fires after the listing of a single row for members in a group on the group edit screen.
1077                                   *
1078                                   * @since 1.8.0
1079                                   *
1080                                   * @param int             $ID   ID of the user being rendered.
1081                                   * @param BP_Groups_Group $item Object for the current group.
1082                                   */
1083                                  do_action( 'bp_groups_admin_manage_member_row', $type_user->ID, $item ); ?>
1084                              </td>
1085                          </tr>
1086                      <?php endif; ?>
1087  
1088                  <?php endforeach; ?>
1089  
1090                  </tbody>
1091              </table>
1092  
1093          <?php else : ?>
1094  
1095              <p class="bp-groups-no-members description"><?php esc_html_e( 'No members of this type', 'buddypress' ); ?></p>
1096  
1097          <?php endif; ?>
1098  
1099          </div><!-- .bp-groups-member-type -->
1100  
1101      <?php endforeach;
1102  }
1103  
1104  /**
1105   * Renders the Status metabox for the Groups admin edit screen.
1106   *
1107   * @since 1.7.0
1108   *
1109   * @param object $item Information about the currently displayed group.
1110   */
1111  function bp_groups_admin_edit_metabox_status( $item ) {
1112      $base_url = add_query_arg( array(
1113          'page' => 'bp-groups',
1114          'gid'  => $item->id
1115      ), bp_get_admin_url( 'admin.php' ) ); ?>
1116  
1117      <div id="submitcomment" class="submitbox">
1118          <div id="major-publishing-actions">
1119              <div id="delete-action">
1120                  <a class="submitdelete deletion" href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'action', 'delete', $base_url ), 'bp-groups-delete' ) ); ?>"><?php _e( 'Delete Group', 'buddypress' ) ?></a>
1121              </div>
1122  
1123              <div id="publishing-action">
1124                  <?php submit_button( __( 'Save Changes', 'buddypress' ), 'primary', 'save', false ); ?>
1125              </div>
1126              <div class="clear"></div>
1127          </div><!-- #major-publishing-actions -->
1128      </div><!-- #submitcomment -->
1129  
1130  <?php
1131  }
1132  
1133  /**
1134   * Render the Group Type metabox.
1135   *
1136   * @since 2.6.0
1137   *
1138   * @param BP_Groups_Group|null $group The BP_Groups_Group object corresponding to the group being edited.
1139   */
1140  function bp_groups_admin_edit_metabox_group_type( BP_Groups_Group $group = null ) {
1141  
1142      // Bail if no group ID.
1143      if ( empty( $group->id ) ) {
1144          return;
1145      }
1146  
1147      $types         = bp_groups_get_group_types( array(), 'objects' );
1148      $current_types = (array) bp_groups_get_group_type( $group->id, false );
1149      $backend_only  = bp_groups_get_group_types( array( 'show_in_create_screen' => false ) );
1150      ?>
1151  
1152      <label for="bp-groups-group-type" class="screen-reader-text"><?php
1153          /* translators: accessibility text */
1154          esc_html_e( 'Select group type', 'buddypress' );
1155      ?></label>
1156  
1157      <ul class="categorychecklist form-no-clear">
1158          <?php foreach ( $types as $type ) : ?>
1159              <li>
1160                  <label class="selectit"><input value="<?php echo esc_attr( $type->name ) ?>" name="bp-groups-group-type[]" type="checkbox" <?php checked( true, in_array( $type->name, $current_types ) ); ?>>
1161                      <?php
1162                          echo esc_html( $type->labels['singular_name'] );
1163                          if ( in_array( $type->name, $backend_only ) ) {
1164                              printf( ' <span class="description">%s</span>', esc_html__( '(Not available on the front end)', 'buddypress' ) );
1165                          }
1166                      ?>
1167  
1168                  </label>
1169              </li>
1170  
1171          <?php endforeach; ?>
1172  
1173      </ul>
1174  
1175      <?php
1176  
1177      wp_nonce_field( 'bp-group-type-change-' . $group->id, 'bp-group-type-nonce' );
1178  }
1179  
1180  /**
1181   * Process changes from the Group Type metabox.
1182   *
1183   * @since 2.6.0
1184   *
1185   * @param int $group_id Group ID.
1186   */
1187  function bp_groups_process_group_type_update( $group_id ) {
1188      if ( ! isset( $_POST['bp-group-type-nonce'] ) ) {
1189          return;
1190      }
1191  
1192      check_admin_referer( 'bp-group-type-change-' . $group_id, 'bp-group-type-nonce' );
1193  
1194      // Permission check.
1195      if ( ! bp_current_user_can( 'bp_moderate' ) ) {
1196          return;
1197      }
1198  
1199      $group_types = ! empty( $_POST['bp-groups-group-type'] ) ? wp_unslash( $_POST['bp-groups-group-type'] ) : array();
1200  
1201      /*
1202       * If an invalid group type is passed, someone's doing something
1203       * fishy with the POST request, so we can fail silently.
1204       */
1205      if ( bp_groups_set_group_type( $group_id, $group_types ) ) {
1206          // @todo Success messages can't be posted because other stuff happens on the page load.
1207      }
1208  }
1209  add_action( 'bp_group_admin_edit_after', 'bp_groups_process_group_type_update' );
1210  
1211  /**
1212   * Create pagination links out of a BP_Group_Member_Query.
1213   *
1214   * This function is intended to create pagination links for use under the
1215   * Manage Members section of the Groups Admin Dashboard pages. It is a stopgap
1216   * measure until a more general pagination solution is in place for BuddyPress.
1217   * Plugin authors should not use this function, as it is likely to be
1218   * deprecated soon.
1219   *
1220   * @since 1.8.0
1221   *
1222   * @param BP_Group_Member_Query $query       A BP_Group_Member_Query object.
1223   * @param string                $member_type member|mod|admin|banned.
1224   * @return string Pagination links HTML.
1225   */
1226  function bp_groups_admin_create_pagination_links( BP_Group_Member_Query $query, $member_type ) {
1227      $pagination = '';
1228  
1229      if ( ! in_array( $member_type, array( 'admin', 'mod', 'member', 'banned' ) ) ) {
1230          return $pagination;
1231      }
1232  
1233      // The key used to paginate this member type in the $_GET global.
1234      $qs_key   = $member_type . '_page';
1235      $url_base = remove_query_arg( array( $qs_key, 'updated', 'success_modified' ), $_SERVER['REQUEST_URI'] );
1236  
1237      $page = isset( $_GET[ $qs_key ] ) ? absint( $_GET[ $qs_key ] ) : 1;
1238  
1239      /**
1240       * Filters the number of members per member type that is displayed in group editing admin area.
1241       *
1242       * @since 2.8.0
1243       *
1244       * @param string $member_type Member type, which is a group role (admin, mod etc).
1245       */
1246      $per_page = apply_filters( 'bp_groups_admin_members_type_per_page', 10, $member_type );
1247  
1248      // Don't show anything if there's no pagination.
1249      if ( 1 === $page && $query->total_users <= $per_page ) {
1250          return $pagination;
1251      }
1252  
1253      $current_page_start = ( ( $page - 1 ) * $per_page ) + 1;
1254      $current_page_end   = $page * $per_page > intval( $query->total_users ) ? $query->total_users : $page * $per_page;
1255  
1256      $pag_links = paginate_links( array(
1257          'base'      => add_query_arg( $qs_key, '%#%', $url_base ),
1258          'format'    => '',
1259          'prev_text' => __( '&laquo;', 'buddypress' ),
1260          'next_text' => __( '&raquo;', 'buddypress' ),
1261          'total'     => ceil( $query->total_users / $per_page ),
1262          'current'   => $page,
1263      ) );
1264  
1265      if ( 1 == $query->total_users ) {
1266          $viewing_text = __( 'Viewing 1 member', 'buddypress' );
1267      } else {
1268          $viewing_text = sprintf(
1269              /* translators: 1: group member from number. 2: group member to number. 3: total group members. */
1270              _nx( 'Viewing %1$s - %2$s of %3$s member', 'Viewing %1$s - %2$s of %3$s members', $query->total_users, 'Group members pagination in group admin', 'buddypress' ),
1271              bp_core_number_format( $current_page_start ),
1272              bp_core_number_format( $current_page_end ),
1273              bp_core_number_format( $query->total_users )
1274          );
1275      }
1276  
1277      $pagination .= '<span class="bp-group-admin-pagination-viewing">' . $viewing_text . '</span>';
1278      $pagination .= '<span class="bp-group-admin-pagination-links">' . $pag_links . '</span>';
1279  
1280      return $pagination;
1281  }
1282  
1283  /**
1284   * Get a set of usernames corresponding to a set of user IDs.
1285   *
1286   * @since 1.7.0
1287   *
1288   * @param array $user_ids Array of user IDs.
1289   * @return array Array of user_logins corresponding to $user_ids.
1290   */
1291  function bp_groups_admin_get_usernames_from_ids( $user_ids = array() ) {
1292  
1293      $usernames = array();
1294      $users     = new WP_User_Query( array( 'blog_id' => 0, 'include' => $user_ids ) );
1295  
1296      foreach ( (array) $users->results as $user ) {
1297          $usernames[] = $user->user_login;
1298      }
1299  
1300      return $usernames;
1301  }
1302  
1303  /**
1304   * AJAX handler for group member autocomplete requests.
1305   *
1306   * @since 1.7.0
1307   */
1308  function bp_groups_admin_autocomplete_handler() {
1309  
1310      // Bail if user user shouldn't be here, or is a large network.
1311      if ( ! bp_current_user_can( 'bp_moderate' ) || bp_is_large_install() ) {
1312          wp_die( -1 );
1313      }
1314  
1315      $term     = isset( $_GET['term'] )     ? sanitize_text_field( $_GET['term'] ) : '';
1316      $group_id = isset( $_GET['group_id'] ) ? absint( $_GET['group_id'] )          : 0;
1317  
1318      if ( ! $term || ! $group_id ) {
1319          wp_die( -1 );
1320      }
1321  
1322      $suggestions = bp_core_get_suggestions( array(
1323          'group_id' => -$group_id,  // A negative value will exclude this group's members from the suggestions.
1324          'limit'    => 10,
1325          'term'     => $term,
1326          'type'     => 'members',
1327      ) );
1328  
1329      $matches = array();
1330  
1331      if ( $suggestions && ! is_wp_error( $suggestions ) ) {
1332          foreach ( $suggestions as $user ) {
1333  
1334              $matches[] = array(
1335                  // Translators: 1: user_login, 2: user_email.
1336                  'label' => sprintf( __( '%1$s (%2$s)', 'buddypress' ), $user->name, $user->ID ),
1337                  'value' => $user->ID,
1338              );
1339          }
1340      }
1341  
1342      wp_die( json_encode( $matches ) );
1343  }
1344  add_action( 'wp_ajax_bp_group_admin_member_autocomplete', 'bp_groups_admin_autocomplete_handler' );
1345  
1346  /**
1347   * Process input from the Group Type bulk change select.
1348   *
1349   * @since 2.7.0
1350   *
1351   * @param string $doaction Current $_GET action being performed in admin screen.
1352   */
1353  function bp_groups_admin_process_group_type_bulk_changes( $doaction ) {
1354      // Bail if no groups are specified or if this isn't a relevant action.
1355      if ( empty( $_REQUEST['gid'] )
1356          || ( empty( $_REQUEST['bp_change_type'] ) && empty( $_REQUEST['bp_change_type2'] ) )
1357          || empty( $_REQUEST['bp_change_group_type'] )
1358      ) {
1359          return;
1360      }
1361  
1362      // Bail if nonce check fails.
1363      check_admin_referer( 'bp-bulk-groups-change-type-' . bp_loggedin_user_id(), 'bp-bulk-groups-change-type-nonce' );
1364  
1365      if ( ! bp_current_user_can( 'bp_moderate' )  ) {
1366          return;
1367      }
1368  
1369      $new_type = '';
1370      if ( ! empty( $_REQUEST['bp_change_type2'] ) ) {
1371          $new_type = sanitize_text_field( $_REQUEST['bp_change_type2'] );
1372      } elseif ( ! empty( $_REQUEST['bp_change_type'] ) ) {
1373          $new_type = sanitize_text_field( $_REQUEST['bp_change_type'] );
1374      }
1375  
1376      // Check that the selected type actually exists.
1377      if ( 'remove_group_type' !== $new_type && null === bp_groups_get_group_type_object( $new_type ) ) {
1378          $error = true;
1379      } else {
1380          // Run through group ids.
1381          $error = false;
1382          foreach ( (array) $_REQUEST['gid'] as $group_id ) {
1383              $group_id = (int) $group_id;
1384  
1385              // Get the old group type to check against.
1386              $current_types = bp_groups_get_group_type( $group_id, false );
1387  
1388              if ( $current_types && 'remove_group_type' === $new_type ) {
1389                  $group_types = array();
1390              } elseif ( ! $current_types || 1 !== count( $current_types ) || $new_type !== $current_types[0] ) {
1391                  $group_types = array( $new_type );
1392              }
1393  
1394              // Set the new group type.
1395              if ( isset( $group_types ) ) {
1396                  $set = bp_groups_set_group_type( $group_id, $group_types );
1397                  if ( false === $set || is_wp_error( $set ) ) {
1398                      $error = true;
1399                  }
1400                  unset( $group_types );
1401              }
1402          }
1403      }
1404  
1405      // If there were any errors, show the error message.
1406      if ( $error ) {
1407          $redirect = add_query_arg( array( 'updated' => 'group-type-change-error' ), wp_get_referer() );
1408      } else {
1409          $redirect = add_query_arg( array( 'updated' => 'group-type-change-success' ), wp_get_referer() );
1410      }
1411  
1412      wp_redirect( $redirect );
1413      exit();
1414  }
1415  add_action( 'bp_groups_admin_load', 'bp_groups_admin_process_group_type_bulk_changes' );
1416  
1417  /**
1418   * Display an admin notice upon group type bulk update.
1419   *
1420   * @since 2.7.0
1421   */
1422  function bp_groups_admin_groups_type_change_notice() {
1423      $updated = isset( $_REQUEST['updated'] ) ? $_REQUEST['updated'] : false;
1424  
1425      // Display feedback.
1426      if ( $updated && in_array( $updated, array( 'group-type-change-error', 'group-type-change-success' ), true ) ) {
1427  
1428          if ( 'group-type-change-error' === $updated ) {
1429              $notice = __( 'There was an error while changing group type. Please try again.', 'buddypress' );
1430              $type   = 'error';
1431          } else {
1432              $notice = __( 'Group type was changed successfully.', 'buddypress' );
1433              $type   = 'updated';
1434          }
1435  
1436          bp_core_add_admin_notice( $notice, $type );
1437      }
1438  }
1439  add_action( bp_core_admin_hook(), 'bp_groups_admin_groups_type_change_notice' );
1440  
1441  /**
1442   * Checks whether a group type already exists.
1443   *
1444   * @since 7.0.0
1445   *
1446   * @param  boolean $exists  True if the group type already exists. False otherwise.
1447   * @param  string  $type_id The group type identifier.
1448   * @return boolean          True if the group type already exists. False otherwise.
1449   */
1450  function bp_groups_type_admin_type_exists( $exists = false, $type_id = '' ) {
1451      if ( ! $type_id ) {
1452          return $exists;
1453      }
1454  
1455      return ! is_null( bp_groups_get_group_type_object( $type_id ) );
1456  }
1457  add_filter( bp_get_group_type_tax_name() . '_check_existing_type', 'bp_groups_type_admin_type_exists', 1, 2 );
1458  
1459  /**
1460   * Set the feedback messages for the Group Types Admin actions.
1461   *
1462   * @since 7.0.0
1463   *
1464   * @param array  $messages The feedback messages.
1465   * @return array           The feedback messages including the ones for the Group Types Admin actions.
1466   */
1467  function bp_groups_type_admin_updated_messages( $messages = array() ) {
1468      $type_taxonomy = bp_get_group_type_tax_name();
1469  
1470      $messages[ $type_taxonomy ] = array(
1471          0  => '',
1472          1  => __( 'Please define the Group Type ID field.', 'buddypress' ),
1473          2  => __( 'Group type successfully added.', 'buddypress' ),
1474          3  => __( 'Sorry, there was an error and the Group type wasn’t added.', 'buddypress' ),
1475          // The following one needs to be != 5.
1476          4  => __( 'Group type successfully updated.', 'buddypress' ),
1477          5  => __( 'Sorry, this Group type already exists.', 'buddypress' ),
1478          6  => __( 'Sorry, the Group type was not deleted: it does not exist.', 'buddypress' ),
1479          7  => __( 'Sorry, This Group type is registered using code, deactivate the plugin or remove the custom code before trying to delete it again.', 'buddypress' ),
1480          8  => __( 'Sorry, there was an error while trying to delete this Group type.', 'buddypress' ),
1481          9  => __( 'Group type successfully deleted.', 'buddypress' ),
1482          10 => __( 'Group type could not be updated due to missing required information.', 'buddypress' ),
1483      );
1484  
1485      return $messages;
1486  }
1487  add_filter( 'term_updated_messages', 'bp_groups_type_admin_updated_messages' );


Generated: Sat Apr 27 01:00:55 2024 Cross-referenced by PHPXref 0.7.1