[ Index ]

PHP Cross Reference of BuddyPress

title

Body

[close]

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

   1  <?php
   2  /**
   3   * BuddyPress Groups Functions.
   4   *
   5   * Functions are where all the magic happens in BuddyPress. They will
   6   * handle the actual saving or manipulation of information. Usually they will
   7   * hand off to a database class for data access, then return
   8   * true or false on success or failure.
   9   *
  10   * @package BuddyPress
  11   * @subpackage GroupsFunctions
  12   * @since 1.5.0
  13   */
  14  
  15  // Exit if accessed directly.
  16  defined( 'ABSPATH' ) || exit;
  17  
  18  /**
  19   * Check whether there is a Groups directory page in the $bp global.
  20   *
  21   * @since 1.5.0
  22   *
  23   * @return bool True if set, False if empty.
  24   */
  25  function bp_groups_has_directory() {
  26      $bp = buddypress();
  27  
  28      return (bool) !empty( $bp->pages->groups->id );
  29  }
  30  
  31  /**
  32   * Fetch a single group object.
  33   *
  34   * When calling up a group object, you should always use this function instead
  35   * of instantiating BP_Groups_Group directly, so that you will inherit cache
  36   * support and pass through the groups_get_group filter.
  37   *
  38   * @since 1.2.0
  39   * @since 2.7.0 The function signature was changed to accept a group ID only,
  40   *              instead of an array containing the group ID.
  41   *
  42   * @param int $group_id ID of the group.
  43   * @return BP_Groups_Group $group The group object.
  44   */
  45  function groups_get_group( $group_id ) {
  46      /*
  47       * Backward compatibilty.
  48       * Old-style arguments take the form of an array or a query string.
  49       */
  50      if ( ! is_numeric( $group_id ) ) {
  51          $r = bp_parse_args(
  52              $group_id,
  53              array(
  54                  'group_id'        => false,
  55                  'load_users'      => false,
  56                  'populate_extras' => false,
  57              ),
  58              'groups_get_group'
  59          );
  60  
  61          $group_id = $r['group_id'];
  62      }
  63  
  64      $group = new BP_Groups_Group( $group_id );
  65  
  66      /**
  67       * Filters a single group object.
  68       *
  69       * @since 1.2.0
  70       *
  71       * @param BP_Groups_Group $group Single group object.
  72       */
  73      return apply_filters( 'groups_get_group', $group );
  74  }
  75  
  76  /**
  77   * Retrieve group by a given field.
  78   *
  79   * @since 10.0.0
  80   *
  81   * @param string     $field (Required) The field to use to retrieve the group.
  82   *                          Possible values are `'id'` or `'slug'`.
  83   * @param string|int $value (Required) A value for the $field. A Group ID or slug.
  84   * @return BP_Groups_Group|bool The Group object if found, false otherwise.
  85   */
  86  function bp_get_group_by( $field, $value ) {
  87      $group_id = $value;
  88  
  89      if ( 'slug' === $field && is_string( $value ) ) {
  90          $group_id = groups_get_id( $value );
  91      }
  92  
  93      $group = groups_get_group( array( 'group_id' => (int) $group_id ) );
  94  
  95      if ( empty( $group->id ) ) {
  96          return false;
  97      }
  98  
  99      return $group;
 100  }
 101  
 102  /**
 103   * Retrieve a Group.
 104   *
 105   * When used into the context of a Groups loop built by the `BP_Groups_Template` class, it defaults to the
 106   * Group being iterated on.
 107   *
 108   * @since 10.0.0
 109   *
 110   * @global BP_Groups_Template $groups_template Groups template object.
 111   *
 112   * @param false|int|string|object|BP_Groups_Group $group (Optional) The Group ID, the Group Slug or the Group object.
 113   *                                                       Default: false.
 114   * @return BP_Groups_Group|bool The Group object if found, false otherwise.
 115   */
 116  function bp_get_group( $group = false ) {
 117      global $groups_template;
 118  
 119      $group_obj = false;
 120  
 121      if ( $group instanceof BP_Groups_Group || ( is_object( $group ) && ! empty( $group->id ) ) ) {
 122          $group_obj = $group;
 123  
 124          // Nothing requested? Let's use the current Group of the Groups Loop, if available.
 125      } elseif ( ! $group && isset( $groups_template->group ) && is_object( $groups_template->group ) ) {
 126          $group_obj = $groups_template->group;
 127      } else {
 128          $current_group = null;
 129  
 130          // Let's get the current group if we can.
 131          if ( did_action( 'bp_groups_set_current_group' ) ) {
 132              $current_group = groups_get_current_group();
 133          }
 134  
 135          $field = '';
 136          if ( is_string( $group ) ) {
 137              $field = 'slug';
 138          } elseif ( is_numeric( $group ) ) {
 139              $field = 'id';
 140              $group = (int) $group;
 141          }
 142  
 143          // Let's use the current Group if it matches with the requested field value.
 144          if ( isset( $current_group->{$field} ) && $current_group->{$field} === $group ) {
 145              $group_obj = $current_group;
 146          } else {
 147              $group_obj = bp_get_group_by( $field, $group );
 148          }
 149      }
 150  
 151      return $group_obj;
 152  }
 153  
 154  /** Group Creation, Editing & Deletion ****************************************/
 155  
 156  /**
 157   * Create a group.
 158   *
 159   * @since 1.0.0
 160   *
 161   * @param array|string $args {
 162   *     An array of arguments.
 163   *     @type int|bool $group_id     Pass a group ID to update an existing item, or
 164   *                                  0 / false to create a new group. Default: 0.
 165   *     @type int      $creator_id   The user ID that creates the group.
 166   *     @type string   $name         The group name.
 167   *     @type string   $description  Optional. The group's description.
 168   *     @type string   $slug         The group slug.
 169   *     @type string   $status       The group's status. Accepts 'public', 'private' or
 170   *                                  'hidden'. Defaults to 'public'.
 171   *     @type int      $parent_id    The ID of the parent group. Default: 0.
 172   *     @type int      $enable_forum Optional. Whether the group has a forum enabled.
 173   *                                  If a bbPress forum is enabled for the group,
 174   *                                  set this to 1. Default: 0.
 175   *     @type string   $date_created The GMT time, in Y-m-d h:i:s format, when the group
 176   *                                  was created. Defaults to the current time.
 177   * }
 178   * @return int|bool The ID of the group on success. False on error.
 179   */
 180  function groups_create_group( $args = '' ) {
 181  
 182      $args = bp_parse_args(
 183          $args,
 184          array(
 185              'group_id'     => 0,
 186              'creator_id'   => 0,
 187              'name'         => '',
 188              'description'  => '',
 189              'slug'         => '',
 190              'status'       => null,
 191              'parent_id'    => null,
 192              'enable_forum' => null,
 193              'date_created' => null,
 194          ),
 195          'groups_create_group'
 196      );
 197  
 198      extract( $args, EXTR_SKIP );
 199  
 200      // Pass an existing group ID.
 201      if ( ! empty( $group_id ) ) {
 202          $group = groups_get_group( $group_id );
 203          $name  = ! empty( $name ) ? $name : $group->name;
 204          $slug  = ! empty( $slug ) ? $slug : $group->slug;
 205          $creator_id  = ! empty( $creator_id ) ? $creator_id : $group->creator_id;
 206          $description = ! empty( $description ) ? $description : $group->description;
 207          $status = ! is_null( $status ) ? $status : $group->status;
 208          $parent_id = ! is_null( $parent_id ) ? $parent_id : $group->parent_id;
 209          $enable_forum = ! is_null( $enable_forum ) ? $enable_forum : $group->enable_forum;
 210          $date_created = ! is_null( $date_created ) ? $date_created : $group->date_created;
 211  
 212          // Groups need at least a name.
 213          if ( empty( $name ) ) {
 214              return false;
 215          }
 216  
 217      // Create a new group.
 218      } else {
 219          // Instantiate new group object.
 220          $group = new BP_Groups_Group;
 221  
 222          // Check for null values, reset to sensible defaults.
 223          $status = ! is_null( $status ) ? $status : 'public';
 224          $parent_id = ! is_null( $parent_id ) ? $parent_id : 0;
 225          $enable_forum = ! is_null( $enable_forum ) ? $enable_forum : 0;
 226          $date_created = ! is_null( $date_created ) ? $date_created : bp_core_current_time();
 227      }
 228  
 229      // Set creator ID.
 230      if ( $creator_id ) {
 231          $group->creator_id = (int) $creator_id;
 232      } elseif ( is_user_logged_in() ) {
 233          $group->creator_id = bp_loggedin_user_id();
 234      }
 235  
 236      if ( ! $group->creator_id ) {
 237          return false;
 238      }
 239  
 240      // Validate status.
 241      if ( ! groups_is_valid_status( $status ) ) {
 242          return false;
 243      }
 244  
 245      // Set group name.
 246      $group->name         = $name;
 247      $group->description  = $description;
 248      $group->slug         = $slug;
 249      $group->status       = $status;
 250      $group->parent_id    = $parent_id;
 251      $group->enable_forum = (int) $enable_forum;
 252      $group->date_created = $date_created;
 253  
 254      // Save group.
 255      if ( ! $group->save() ) {
 256          return false;
 257      }
 258  
 259      // If this is a new group, set up the creator as the first member and admin.
 260      if ( empty( $group_id ) ) {
 261          $member                = new BP_Groups_Member;
 262          $member->group_id      = $group->id;
 263          $member->user_id       = $group->creator_id;
 264          $member->is_admin      = 1;
 265          $member->user_title    = __( 'Group Admin', 'buddypress' );
 266          $member->is_confirmed  = 1;
 267          $member->date_modified = bp_core_current_time();
 268          $member->save();
 269  
 270          /**
 271           * Fires after the creation of a new group and a group creator needs to be made.
 272           *
 273           * @since 1.5.0
 274           *
 275           * @param int              $id     ID of the newly created group.
 276           * @param BP_Groups_Member $member Instance of the member who is assigned
 277           *                                 as group creator.
 278           * @param BP_Groups_Group  $group  Instance of the group being created.
 279           */
 280          do_action( 'groups_create_group', $group->id, $member, $group );
 281  
 282      } else {
 283  
 284          /**
 285           * Fires after the update of a group.
 286           *
 287           * @since 1.5.0
 288           *
 289           * @param int             $id    ID of the updated group.
 290           * @param BP_Groups_Group $group Instance of the group being updated.
 291           */
 292          do_action( 'groups_update_group', $group->id, $group );
 293      }
 294  
 295      /**
 296       * Fires after the creation or update of a group.
 297       *
 298       * @since 1.0.0
 299       *
 300       * @param int             $id    ID of the newly created group.
 301       * @param BP_Groups_Group $group Instance of the group being updated.
 302       */
 303      do_action( 'groups_created_group', $group->id, $group );
 304  
 305      return $group->id;
 306  }
 307  
 308  /**
 309   * Edit the base details for a group.
 310   *
 311   * These are the settings that appear on the first page of the group's Admin
 312   * section (Name, Description, and "Notify members...").
 313   *
 314   * @since 1.0.0
 315   *
 316   * @param array $args {
 317   *     An array of optional arguments.
 318   *     @type int    $group_id       ID of the group.
 319   *     @type string $name           Name of the group.
 320   *     @type string $slug           Slug of the group.
 321   *     @type string $description    Description of the group.
 322   *     @type bool   $notify_members Whether to send an email notification to group
 323   *                                  members about changes in these details.
 324   * }
 325   * @return bool True on success, false on failure.
 326   */
 327  function groups_edit_base_group_details( $args = array() ) {
 328      $function_args = func_get_args();
 329  
 330      // Backward compatibility with old method of passing arguments.
 331      if ( ! is_array( $args ) || count( $function_args ) > 1 ) {
 332          _deprecated_argument( __METHOD__, '2.9.0', sprintf( __( 'Arguments passed to %1$s should be in an associative array. See the inline documentation at %2$s for more details.', 'buddypress' ), __METHOD__, __FILE__ ) );
 333  
 334          $old_args_keys = array(
 335              0 => 'group_id',
 336              1 => 'name',
 337              2 => 'description',
 338              3 => 'notify_members',
 339          );
 340  
 341          $args = bp_core_parse_args_array( $old_args_keys, $function_args );
 342      }
 343  
 344      $r = bp_parse_args(
 345          $args,
 346          array(
 347              'group_id'       => bp_get_current_group_id(),
 348              'name'           => null,
 349              'slug'           => null,
 350              'description'    => null,
 351              'notify_members' => false,
 352          ),
 353          'groups_edit_base_group_details'
 354      );
 355  
 356      if ( ! $r['group_id'] ) {
 357          return false;
 358      }
 359  
 360      $group     = groups_get_group( $r['group_id'] );
 361      $old_group = clone $group;
 362  
 363      // Group name, slug and description can never be empty. Update only if provided.
 364      if ( $r['name'] ) {
 365          $group->name = $r['name'];
 366      }
 367      if ( $r['slug'] && $r['slug'] != $group->slug ) {
 368          $group->slug = groups_check_slug( $r['slug'] );
 369      }
 370      if ( $r['description'] ) {
 371          $group->description = $r['description'];
 372      }
 373  
 374      if ( ! $group->save() ) {
 375          return false;
 376      }
 377  
 378      // Maybe update the "previous_slug" groupmeta.
 379      if ( $group->slug != $old_group->slug ) {
 380          /*
 381           * If the old slug exists in this group's past, delete that entry.
 382           * Recent previous_slugs are preferred when selecting the current group
 383           * from an old group slug, so we want the previous slug to be
 384           * saved "now" in the groupmeta table and don't need the old record.
 385           */
 386          groups_delete_groupmeta( $group->id, 'previous_slug', $old_group->slug );
 387          groups_add_groupmeta( $group->id, 'previous_slug', $old_group->slug );
 388      }
 389  
 390      if ( $r['notify_members'] ) {
 391          groups_notification_group_updated( $group->id, $old_group );
 392      }
 393  
 394      /**
 395       * Fired after a group's details are updated.
 396       *
 397       * @since 2.2.0
 398       *
 399       * @param int             $value          ID of the group.
 400       * @param BP_Groups_Group $old_group      Group object, before being modified.
 401       * @param bool            $notify_members Whether to send an email notification to members about the change.
 402       */
 403      do_action( 'groups_details_updated', $group->id, $old_group, $r['notify_members'] );
 404  
 405      return true;
 406  }
 407  
 408  /**
 409   * Edit the base details for a group.
 410   *
 411   * These are the settings that appear on the Settings page of the group's Admin
 412   * section (privacy settings, "enable forum", invitation status).
 413   *
 414   * @since 1.0.0
 415   *
 416   * @param int         $group_id      ID of the group.
 417   * @param bool        $enable_forum  Whether to enable a forum for the group.
 418   * @param string      $status        Group status. 'public', 'private', 'hidden'.
 419   * @param string|bool $invite_status Optional. Who is allowed to send invitations
 420   *                                   to the group. 'members', 'mods', or 'admins'.
 421   * @param int|bool    $parent_id     Parent group ID.
 422   * @return bool True on success, false on failure.
 423   */
 424  function groups_edit_group_settings( $group_id, $enable_forum, $status, $invite_status = false, $parent_id = false ) {
 425  
 426      $group = groups_get_group( $group_id );
 427      $group->enable_forum = $enable_forum;
 428  
 429      /**
 430       * Before we potentially switch the group status, if it has been changed to public
 431       * from private and there are outstanding membership requests, auto-accept those requests.
 432       */
 433      if ( 'private' == $group->status && 'public' == $status )
 434          groups_accept_all_pending_membership_requests( $group->id );
 435  
 436      // Now update the status.
 437      $group->status = $status;
 438  
 439      // Update the parent ID if necessary.
 440      if ( false !== $parent_id ) {
 441          $group->parent_id = $parent_id;
 442      }
 443  
 444      if ( !$group->save() )
 445          return false;
 446  
 447      // Set the invite status.
 448      if ( $invite_status )
 449          groups_update_groupmeta( $group->id, 'invite_status', $invite_status );
 450  
 451      groups_update_groupmeta( $group->id, 'last_activity', bp_core_current_time() );
 452  
 453      /**
 454       * Fires after the update of a groups settings.
 455       *
 456       * @since 1.0.0
 457       *
 458       * @param int $id ID of the group that was updated.
 459       */
 460      do_action( 'groups_settings_updated', $group->id );
 461  
 462      return true;
 463  }
 464  
 465  /**
 466   * Delete a group and all of its associated metadata.
 467   *
 468   * @since 1.0.0
 469   *
 470   * @param int $group_id ID of the group to delete.
 471   * @return bool True on success, false on failure.
 472   */
 473  function groups_delete_group( $group_id ) {
 474  
 475      /**
 476       * Fires before the deletion of a group.
 477       *
 478       * @since 1.5.0
 479       *
 480       * @param int $group_id ID of the group to be deleted.
 481       */
 482      do_action( 'groups_before_delete_group', $group_id );
 483  
 484      // Get the group object.
 485      $group = groups_get_group( $group_id );
 486  
 487      // Bail if group cannot be deleted.
 488      if ( ! $group->delete() ) {
 489          return false;
 490      }
 491  
 492      // Remove all outstanding invites for this group.
 493      groups_delete_all_group_invites( $group_id );
 494  
 495      /**
 496       * Fires after the deletion of a group.
 497       *
 498       * @since 1.0.0
 499       *
 500       * @param int $group_id ID of the group that was deleted.
 501       */
 502      do_action( 'groups_delete_group', $group_id );
 503  
 504      return true;
 505  }
 506  
 507  /**
 508   * Check a group status (eg 'private') against the list of registered statuses.
 509   *
 510   * @since 1.1.0
 511   *
 512   * @param string $status Status to check.
 513   * @return bool True if status is allowed, otherwise false.
 514   */
 515  function groups_is_valid_status( $status ) {
 516      $bp = buddypress();
 517  
 518      return in_array( $status, (array) $bp->groups->valid_status, true );
 519  }
 520  
 521  /**
 522   * Provide a unique, sanitized version of a group slug.
 523   *
 524   * @since 1.0.0
 525   *
 526   * @param string $slug Group slug to check.
 527   * @return string $slug A unique and sanitized slug.
 528   */
 529  function groups_check_slug( $slug ) {
 530      $bp = buddypress();
 531  
 532      // First, make the proposed slug work in a URL.
 533      $slug = sanitize_title( $slug );
 534  
 535      if ( 'wp' == substr( $slug, 0, 2 ) )
 536          $slug = substr( $slug, 2, strlen( $slug ) - 2 );
 537  
 538      if ( in_array( $slug, (array) $bp->groups->forbidden_names ) )
 539          $slug = $slug . '-' . rand();
 540  
 541      if ( BP_Groups_Group::check_slug( $slug ) ) {
 542          do {
 543              $slug = $slug . '-' . rand();
 544          }
 545          while ( BP_Groups_Group::check_slug( $slug ) );
 546      }
 547  
 548      return $slug;
 549  }
 550  
 551  /**
 552   * Get slug from a group.
 553   *
 554   * @since 1.0.0
 555   * @since 10.0.0 Updated to use `bp_get_group`.
 556   *
 557   * @param int|string|BP_Groups_Group $group The Group ID, the Group Slug or the Group object.
 558   * @return bool|string The group's slug. False if group doesn't exist.
 559   */
 560  function groups_get_slug( $group ) {
 561  
 562      $group = bp_get_group( $group );
 563  
 564      if ( empty( $group->id ) ) {
 565          return false;
 566      }
 567  
 568      return ! empty( $group->slug ) ? $group->slug : '';
 569  }
 570  
 571  /**
 572   * Get a group ID by its slug.
 573   *
 574   * @since 1.6.0
 575   *
 576   * @param string $group_slug The group's slug.
 577   * @return int|null The group ID on success, null on failure.
 578   */
 579  function groups_get_id( $group_slug ) {
 580      return BP_Groups_Group::group_exists( $group_slug );
 581  }
 582  
 583  /**
 584   * Get a group ID by checking against old (not currently active) slugs.
 585   *
 586   * @since 2.9.0
 587   *
 588   * @param string $group_slug The group's slug.
 589   * @return int|null The group ID on success, null on failure.
 590   */
 591  function groups_get_id_by_previous_slug( $group_slug ) {
 592      return BP_Groups_Group::get_id_by_previous_slug( $group_slug );
 593  }
 594  
 595  /** User Actions **************************************************************/
 596  
 597  /**
 598   * Remove a user from a group.
 599   *
 600   * @since 1.0.0
 601   * @since 10.0.0 Updated to use `bp_get_group`.
 602   *
 603   * @param int|string|BP_Groups_Group $group   The Group ID, the Group Slug or the Group object.
 604   * @param int                        $user_id Optional. ID of the user. Defaults to the currently
 605   *                                            logged-in user.
 606   * @return bool True on success, false on failure.
 607   */
 608  function groups_leave_group( $group, $user_id = 0 ) {
 609  
 610      $group = bp_get_group( $group );
 611  
 612      if ( empty( $group->id ) ) {
 613          return false;
 614      }
 615  
 616      if ( empty( $user_id ) ) {
 617          $user_id = bp_loggedin_user_id();
 618      }
 619  
 620      // Don't let single admins leave the group.
 621      if ( count( groups_get_group_admins( $group->id ) ) < 2 ) {
 622          if ( groups_is_user_admin( $user_id, $group->id ) ) {
 623              bp_core_add_message( __( 'As the only admin, you cannot leave the group.', 'buddypress' ), 'error' );
 624              return false;
 625          }
 626      }
 627  
 628      if ( ! BP_Groups_Member::delete( $user_id, $group->id ) ) {
 629          return false;
 630      }
 631  
 632      bp_core_add_message( __( 'You successfully left the group.', 'buddypress' ) );
 633  
 634      /**
 635       * Fires after a user leaves a group.
 636       *
 637       * @since 1.0.0
 638       * @since 10.0.0 Updated to add the `$group` parameter.
 639       *
 640       * @param int             $group_id ID of the group.
 641       * @param int             $user_id  ID of the user leaving the group.
 642       * @param BP_Groups_Group $group    The group object.
 643       */
 644      do_action( 'groups_leave_group', $group->id, $user_id, $group );
 645  
 646      return true;
 647  }
 648  
 649  /**
 650   * Add a user to a group.
 651   *
 652   * @since 1.0.0
 653   * @since 10.0.0 Updated to use `bp_get_group`.
 654   *
 655   * @param int|string|BP_Groups_Group $group   The Group ID, the Group Slug or the Group object.
 656   * @param int                        $user_id Optional. ID of the user. Defaults to the currently
 657   *                                            logged-in user.
 658   * @return bool True on success, false on failure.
 659   */
 660  function groups_join_group( $group, $user_id = 0 ) {
 661  
 662      $group = bp_get_group( $group );
 663  
 664      if ( empty( $group->id ) ) {
 665          return false;
 666      }
 667  
 668      $group_id = $group->id;
 669  
 670      if ( empty( $user_id ) ) {
 671          $user_id = bp_loggedin_user_id();
 672      }
 673  
 674      // Check if the user has an outstanding invite. If so, delete it.
 675      if ( groups_check_user_has_invite( $user_id, $group_id ) ) {
 676          groups_delete_invite( $user_id, $group_id );
 677      }
 678  
 679      // Check if the user has an outstanding request. If so, delete it.
 680      if ( groups_check_for_membership_request( $user_id, $group_id ) ) {
 681          groups_delete_membership_request( null, $user_id, $group_id );
 682      }
 683  
 684      // User is already a member, just return true.
 685      if ( groups_is_user_member( $user_id, $group_id ) ) {
 686          return true;
 687      }
 688  
 689      $new_member                = new BP_Groups_Member();
 690      $new_member->group_id      = $group_id;
 691      $new_member->user_id       = $user_id;
 692      $new_member->inviter_id    = 0;
 693      $new_member->is_admin      = 0;
 694      $new_member->user_title    = '';
 695      $new_member->date_modified = bp_core_current_time();
 696      $new_member->is_confirmed  = 1;
 697  
 698      if ( ! $new_member->save() ) {
 699          return false;
 700      }
 701  
 702      // Record this in activity streams.
 703      if ( bp_is_active( 'activity' ) ) {
 704          groups_record_activity(
 705              array(
 706                  'type'    => 'joined_group',
 707                  'item_id' => $group_id,
 708                  'user_id' => $user_id,
 709              )
 710          );
 711      }
 712  
 713      /**
 714       * Fires after a user joins a group.
 715       *
 716       * @since 1.0.0
 717       * @since 10.0.0 Added the `$group` parameter.
 718       *
 719       * @param int             $group_id ID of the group.
 720       * @param int             $user_id  ID of the user joining the group.
 721       * @param BP_Groups_Group $group    The group object.
 722       */
 723      do_action( 'groups_join_group', $group_id, $user_id, $group );
 724  
 725      return true;
 726  }
 727  
 728  /**
 729   * Update the last_activity meta value for a given group.
 730   *
 731   * @since 1.0.0
 732   * @since 10.0.0 Updated to use `bp_get_group`.
 733   *
 734   * @param int|string|BP_Groups_Group $group The Group ID, the Group Slug or the Group object.
 735   *                                          Default: the current group's ID.
 736   * @return bool False on failure.
 737   */
 738  function groups_update_last_activity( $group = 0 ) {
 739  
 740      $group = bp_get_group( $group );
 741  
 742      if ( empty( $group->id ) ) {
 743          return false;
 744      }
 745  
 746      groups_update_groupmeta( $group->id, 'last_activity', bp_core_current_time() );
 747  }
 748  add_action( 'groups_join_group', 'groups_update_last_activity' );
 749  add_action( 'groups_leave_group', 'groups_update_last_activity' );
 750  add_action( 'groups_created_group', 'groups_update_last_activity' );
 751  
 752  /** General Group Functions ***************************************************/
 753  
 754  /**
 755   * Get a list of group administrators.
 756   *
 757   * @since 1.0.0
 758   *
 759   * @param int $group_id ID of the group.
 760   * @return array Info about group admins (user_id + date_modified).
 761   */
 762  function groups_get_group_admins( $group_id ) {
 763      return BP_Groups_Member::get_group_administrator_ids( $group_id );
 764  }
 765  
 766  /**
 767   * Get a list of group moderators.
 768   *
 769   * @since 1.0.0
 770   *
 771   * @param int $group_id ID of the group.
 772   * @return array Info about group admins (user_id + date_modified).
 773   */
 774  function groups_get_group_mods( $group_id ) {
 775      return BP_Groups_Member::get_group_moderator_ids( $group_id );
 776  }
 777  
 778  /**
 779   * Fetch the members of a group.
 780   *
 781   * Since BuddyPress 1.8, a procedural wrapper for BP_Group_Member_Query.
 782   * Previously called BP_Groups_Member::get_all_for_group().
 783   *
 784   * To use the legacy query, filter 'bp_use_legacy_group_member_query',
 785   * returning true.
 786   *
 787   * @since 1.0.0
 788   * @since 3.0.0 $group_id now supports multiple values. Only works if legacy query is not
 789   *              in use.
 790   *
 791   * @param array $args {
 792   *     An array of optional arguments.
 793   *     @type int|array|string $group_id            ID of the group to limit results to. Also accepts multiple values
 794   *                                                 either as an array or as a comma-delimited string.
 795   *     @type int              $page                Page of results to be queried. Default: 1.
 796   *     @type int              $per_page            Number of items to return per page of results. Default: 20.
 797   *     @type int              $max                 Optional. Max number of items to return.
 798   *     @type array            $exclude             Optional. Array of user IDs to exclude.
 799   *     @type bool|int         $exclude_admins_mods True (or 1) to exclude admins and mods from results. Default: 1.
 800   *     @type bool|int         $exclude_banned      True (or 1) to exclude banned users from results. Default: 1.
 801   *     @type array            $group_role          Optional. Array of group roles to include.
 802   *     @type string           $search_terms        Optional. Filter results by a search string.
 803   *     @type string           $type                Optional. Sort the order of results. 'last_joined', 'first_joined', or
 804   *                                                 any of the $type params available in {@link BP_User_Query}. Default:
 805   *                                                 'last_joined'.
 806   * }
 807   * @return false|array Multi-d array of 'members' list and 'count'.
 808   */
 809  function groups_get_group_members( $args = array() ) {
 810      $function_args = func_get_args();
 811  
 812      // Backward compatibility with old method of passing arguments.
 813      if ( ! is_array( $args ) || count( $function_args ) > 1 ) {
 814          /* translators: 1: the name of the method. 2: the name of the file. */
 815          _deprecated_argument( __METHOD__, '2.0.0', sprintf( __( 'Arguments passed to %1$s should be in an associative array. See the inline documentation at %2$s for more details.', 'buddypress' ), __METHOD__, __FILE__ ) );
 816  
 817          $old_args_keys = array(
 818              0 => 'group_id',
 819              1 => 'per_page',
 820              2 => 'page',
 821              3 => 'exclude_admins_mods',
 822              4 => 'exclude_banned',
 823              5 => 'exclude',
 824              6 => 'group_role',
 825          );
 826  
 827          $args = bp_core_parse_args_array( $old_args_keys, $function_args );
 828      }
 829  
 830      $r = bp_parse_args(
 831          $args,
 832          array(
 833              'group_id'            => bp_get_current_group_id(),
 834              'per_page'            => false,
 835              'page'                => false,
 836              'exclude_admins_mods' => true,
 837              'exclude_banned'      => true,
 838              'exclude'             => false,
 839              'group_role'          => array(),
 840              'search_terms'        => false,
 841              'type'                => 'last_joined',
 842          ),
 843          'groups_get_group_members'
 844      );
 845  
 846      // For legacy users. Use of BP_Groups_Member::get_all_for_group() is deprecated.
 847      if ( apply_filters( 'bp_use_legacy_group_member_query', false, __FUNCTION__, $function_args ) ) {
 848          $retval = BP_Groups_Member::get_all_for_group( $r['group_id'], $r['per_page'], $r['page'], $r['exclude_admins_mods'], $r['exclude_banned'], $r['exclude'] );
 849      } else {
 850  
 851          // Both exclude_admins_mods and exclude_banned are legacy arguments.
 852          // Convert to group_role.
 853          if ( empty( $r['group_role'] ) ) {
 854              $r['group_role'] = array( 'member' );
 855  
 856              if ( ! $r['exclude_admins_mods'] ) {
 857                  $r['group_role'][] = 'mod';
 858                  $r['group_role'][] = 'admin';
 859              }
 860  
 861              if ( ! $r['exclude_banned'] ) {
 862                  $r['group_role'][] = 'banned';
 863              }
 864          }
 865  
 866          // Perform the group member query (extends BP_User_Query).
 867          $members = new BP_Group_Member_Query( array(
 868              'group_id'       => $r['group_id'],
 869              'per_page'       => $r['per_page'],
 870              'page'           => $r['page'],
 871              'group_role'     => $r['group_role'],
 872              'exclude'        => $r['exclude'],
 873              'search_terms'   => $r['search_terms'],
 874              'type'           => $r['type'],
 875          ) );
 876  
 877          // Structure the return value as expected by the template functions.
 878          $retval = array(
 879              'members' => array_values( $members->results ),
 880              'count'   => $members->total_users,
 881          );
 882      }
 883  
 884      return $retval;
 885  }
 886  
 887  /**
 888   * Get the member count for a group.
 889   *
 890   * @since 1.2.3
 891   * @since 10.0.0 Updated to use `bp_get_group`.
 892   *
 893   * @param int|string|BP_Groups_Group $group      The Group ID, the Group Slug or the Group object.
 894   * @param bool                       $skip_cache Optional. Skip grabbing from cache. Defaults to false.
 895   * @return int|bool Count of confirmed members for the group. False if group doesn't exist.
 896   */
 897  function groups_get_total_member_count( $group, $skip_cache = false ) {
 898  
 899      $group = bp_get_group( $group );
 900  
 901      if ( empty( $group->id ) ) {
 902          return false;
 903      }
 904  
 905      return (int) BP_Groups_Group::get_total_member_count( $group->id, (bool) $skip_cache );
 906  }
 907  
 908  /** Group Fetching, Filtering & Searching  ************************************/
 909  
 910  /**
 911   * Get a collection of groups, based on the parameters passed.
 912   *
 913   * @since 1.2.0
 914   * @since 2.6.0 Added `$group_type`, `$group_type__in`, and `$group_type__not_in` parameters.
 915   * @since 2.7.0 Added `$update_admin_cache` and `$parent_id` parameters.
 916   *
 917   * @param array|string $args {
 918   *     Array of arguments. Supports all arguments of
 919   *     {@link BP_Groups_Group::get()}. Where the default values differ, they
 920   *     have been described here.
 921   *     @type int $per_page Default: 20.
 922   *     @type int $page Default: 1.
 923   * }
 924   * @return array See {@link BP_Groups_Group::get()}.
 925   */
 926  function groups_get_groups( $args = '' ) {
 927  
 928      $r = bp_parse_args(
 929          $args,
 930          array(
 931              'type'               => false,          // Active, newest, alphabetical, random, popular.
 932              'order'              => 'DESC',         // 'ASC' or 'DESC'
 933              'orderby'            => 'date_created', // date_created, last_activity, total_member_count, name, random, meta_id.
 934              'user_id'            => false,          // Pass a user_id to limit to only groups that this user is a member of.
 935              'include'            => false,          // Only include these specific groups (group_ids).
 936              'exclude'            => false,          // Do not include these specific groups (group_ids).
 937              'parent_id'          => null,           // Get groups that are children of the specified group(s).
 938              'slug'               => array(),        // Find a group or groups by slug.
 939              'search_terms'       => false,          // Limit to groups that match these search terms.
 940              'search_columns'     => array(),        // Select which columns to search.
 941              'group_type'         => '',             // Array or comma-separated list of group types to limit results to.
 942              'group_type__in'     => '',             // Array or comma-separated list of group types to limit results to.
 943              'group_type__not_in' => '',             // Array or comma-separated list of group types that will be excluded from results.
 944              'meta_query'         => false,          // Filter by groupmeta. See WP_Meta_Query for syntax.
 945              'show_hidden'        => false,          // Show hidden groups to non-admins.
 946              'status'             => array(),        // Array or comma-separated list of group statuses to limit results to.
 947              'per_page'           => 20,             // The number of results to return per page.
 948              'page'               => 1,              // The page to return if limiting per page.
 949              'update_meta_cache'  => true,           // Pre-fetch groupmeta for queried groups.
 950              'update_admin_cache' => false,
 951              'fields'             => 'all',          // Return BP_Groups_Group objects or a list of ids.
 952          ),
 953          'groups_get_groups'
 954      );
 955  
 956      $groups = BP_Groups_Group::get( array(
 957          'type'               => $r['type'],
 958          'user_id'            => $r['user_id'],
 959          'include'            => $r['include'],
 960          'exclude'            => $r['exclude'],
 961          'slug'               => $r['slug'],
 962          'parent_id'          => $r['parent_id'],
 963          'search_terms'       => $r['search_terms'],
 964          'search_columns'     => $r['search_columns'],
 965          'group_type'         => $r['group_type'],
 966          'group_type__in'     => $r['group_type__in'],
 967          'group_type__not_in' => $r['group_type__not_in'],
 968          'meta_query'         => $r['meta_query'],
 969          'show_hidden'        => $r['show_hidden'],
 970          'status'             => $r['status'],
 971          'per_page'           => $r['per_page'],
 972          'page'               => $r['page'],
 973          'update_meta_cache'  => $r['update_meta_cache'],
 974          'update_admin_cache' => $r['update_admin_cache'],
 975          'order'              => $r['order'],
 976          'orderby'            => $r['orderby'],
 977          'fields'             => $r['fields'],
 978      ) );
 979  
 980      /**
 981       * Filters the collection of groups based on parsed parameters.
 982       *
 983       * @since 1.2.0
 984       *
 985       * @param BP_Groups_Group $groups Object of found groups based on parameters.
 986       *                                Passed by reference.
 987       * @param array           $r      Array of parsed arguments used for group query.
 988       *                                Passed by reference.
 989       */
 990      return apply_filters_ref_array( 'groups_get_groups', array( &$groups, &$r ) );
 991  }
 992  
 993  /**
 994   * Get the total group count for the site.
 995   *
 996   * @since 1.2.0
 997   * @since 10.0.0 Added the `$skip_cache` parameter.
 998   *
 999   * @param bool $skip_cache Optional. Skip getting count from cache.
1000   *                         Defaults to false.
1001   * @return int
1002   */
1003  function groups_get_total_group_count( $skip_cache = false ) {
1004      return (int) BP_Groups_Group::get_total_group_count( $skip_cache );
1005  }
1006  
1007  /**
1008   * Get the IDs of the groups of which a specified user is a member.
1009   *
1010   * @since 1.0.0
1011   *
1012   * @param int $user_id  ID of the user.
1013   * @param int $pag_num  Optional. Max number of results to return.
1014   *                      Default: false (no limit).
1015   * @param int $pag_page Optional. Page offset of results to return.
1016   *                      Default: false (no limit).
1017   * @return array {
1018   *     @type array $groups Array of groups returned by paginated query.
1019   *     @type int   $total Count of groups matching query.
1020   * }
1021   */
1022  function groups_get_user_groups( $user_id = 0, $pag_num = 0, $pag_page = 0 ) {
1023  
1024      if ( empty( $user_id ) ) {
1025          $user_id = bp_displayed_user_id();
1026      }
1027  
1028      return BP_Groups_Member::get_group_ids( $user_id, $pag_num, $pag_page );
1029  }
1030  
1031  /**
1032   * Get a list of groups of which the specified user is a member.
1033   *
1034   * Get a list of the groups to which this member belongs,
1035   * filtered by group membership status and role.
1036   * Usage examples: Used with no arguments specified,
1037   *
1038   *    bp_get_user_groups( bp_loggedin_user_id() );
1039   *
1040   * returns an array of the groups in which the logged-in user
1041   * is an unpromoted member. To fetch an array of all groups that
1042   * the current user belongs to, in any membership role,
1043   * member, moderator or administrator, use
1044   *
1045   *    bp_get_user_groups( $user_id, array(
1046   *        'is_admin' => null,
1047   *        'is_mod' => null,
1048   *    ) );
1049   *
1050   * @since 2.6.0
1051   *
1052   * @param int $user_id ID of the user.
1053   * @param array $args {
1054   *     Array of optional args.
1055   *     @param bool|null   $is_confirmed Whether to return only confirmed memberships. Pass `null` to disable this
1056   *                                      filter. Default: true.
1057   *     @param bool|null   $is_banned    Whether to return only banned memberships. Pass `null` to disable this filter.
1058   *                                      Default: false.
1059   *     @param bool|null   $is_admin     Whether to return only admin memberships. Pass `null` to disable this filter.
1060   *                                      Default: false.
1061   *     @param bool|null   $is_mod       Whether to return only mod memberships. Pass `null` to disable this filter.
1062   *                                      Default: false.
1063   *     @param bool|null   $invite_sent  Whether to return only memberships with 'invite_sent'. Pass `null` to disable
1064   *                                      this filter. Default: false.
1065   *     @param string      $orderby      Field to order by. Accepts 'id' (membership ID), 'group_id', 'date_modified'.
1066   *                                      Default: 'group_id'.
1067   *     @param string      $order        Sort order. Accepts 'ASC' or 'DESC'. Default: 'ASC'.
1068   * }
1069   * @return array Array of matching group memberships, keyed by group ID.
1070   */
1071  function bp_get_user_groups( $user_id, $args = array() ) {
1072      $r = bp_parse_args(
1073          $args,
1074          array(
1075              'is_confirmed' => true,
1076              'is_banned'    => false,
1077              'is_admin'     => false,
1078              'is_mod'       => false,
1079              'invite_sent'  => null,
1080              'orderby'      => 'group_id',
1081              'order'        => 'ASC',
1082          ),
1083          'get_user_groups'
1084      );
1085  
1086      $user_id = intval( $user_id );
1087  
1088      // Standard memberships
1089      $membership_ids = wp_cache_get( $user_id, 'bp_groups_memberships_for_user' );
1090      if ( false === $membership_ids ) {
1091          $membership_ids = BP_Groups_Member::get_membership_ids_for_user( $user_id );
1092          wp_cache_set( $user_id, $membership_ids, 'bp_groups_memberships_for_user' );
1093      }
1094  
1095      // Prime the membership cache.
1096      $uncached_membership_ids = bp_get_non_cached_ids( $membership_ids, 'bp_groups_memberships' );
1097      if ( ! empty( $uncached_membership_ids ) ) {
1098          $uncached_memberships = BP_Groups_Member::get_memberships_by_id( $uncached_membership_ids );
1099  
1100          foreach ( $uncached_memberships as $uncached_membership ) {
1101              wp_cache_set( $uncached_membership->id, $uncached_membership, 'bp_groups_memberships' );
1102          }
1103      }
1104  
1105      // Prime the invitations- and requests-as-memberships cache
1106      $invitation_ids = array();
1107      if ( true !== $r['is_confirmed'] || false !== $r['invite_sent'] ) {
1108          $invitation_ids = groups_get_invites( array(
1109              'user_id'     => $user_id,
1110              'invite_sent' => 'all',
1111              'type'        => 'all',
1112              'fields'      => 'ids'
1113          ) );
1114  
1115          // Prime the invitations cache.
1116          $uncached_invitation_ids = bp_get_non_cached_ids( $invitation_ids, 'bp_groups_invitations_as_memberships' );
1117          if ( $uncached_invitation_ids ) {
1118              $uncached_invitations = groups_get_invites( array(
1119                  'id'          => $uncached_invitation_ids,
1120                  'invite_sent' => 'all',
1121                  'type'        => 'all'
1122              ) );
1123              foreach ( $uncached_invitations as $uncached_invitation ) {
1124                  // Reshape the result as a membership db entry.
1125                  $invitation = new StdClass;
1126                  $invitation->id            = $uncached_invitation->id;
1127                  $invitation->group_id      = $uncached_invitation->item_id;
1128                  $invitation->user_id       = $uncached_invitation->user_id;
1129                  $invitation->inviter_id    = $uncached_invitation->inviter_id;
1130                  $invitation->is_admin      = false;
1131                  $invitation->is_mod        = false;
1132                  $invitation->user_title    = '';
1133                  $invitation->date_modified = $uncached_invitation->date_modified;
1134                  $invitation->comments      = $uncached_invitation->content;
1135                  $invitation->is_confirmed  = false;
1136                  $invitation->is_banned     = false;
1137                  $invitation->invite_sent   = $uncached_invitation->invite_sent;
1138                  wp_cache_set( $uncached_invitation->id, $invitation, 'bp_groups_invitations_as_memberships' );
1139              }
1140          }
1141      }
1142  
1143      // Assemble filter array for use in `wp_list_filter()`.
1144      $filters = wp_array_slice_assoc( $r, array( 'is_confirmed', 'is_banned', 'is_admin', 'is_mod', 'invite_sent' ) );
1145      foreach ( $filters as $filter_name => $filter_value ) {
1146          if ( is_null( $filter_value ) ) {
1147              unset( $filters[ $filter_name ] );
1148          }
1149      }
1150  
1151      // Populate group membership array from cache, and normalize.
1152      $groups    = array();
1153      $int_keys  = array( 'id', 'group_id', 'user_id', 'inviter_id' );
1154      $bool_keys = array( 'is_admin', 'is_mod', 'is_confirmed', 'is_banned', 'invite_sent' );
1155      foreach ( $membership_ids as $membership_id ) {
1156          $membership = wp_cache_get( $membership_id, 'bp_groups_memberships' );
1157  
1158          // Sanity check.
1159          if ( ! isset( $membership->group_id ) ) {
1160              continue;
1161          }
1162  
1163          // Integer values.
1164          foreach ( $int_keys as $index ) {
1165              $membership->{$index} = intval( $membership->{$index} );
1166          }
1167  
1168          // Boolean values.
1169          foreach ( $bool_keys as $index ) {
1170              $membership->{$index} = (bool) $membership->{$index};
1171          }
1172  
1173          foreach ( $filters as $filter_name => $filter_value ) {
1174              if ( ! isset( $membership->{$filter_name} ) || $filter_value != $membership->{$filter_name} ) {
1175                  continue 2;
1176              }
1177          }
1178  
1179          $group_id = (int) $membership->group_id;
1180  
1181          $groups[ $group_id ] = $membership;
1182      }
1183  
1184      // Populate group invitations array from cache, and normalize.
1185      foreach ( $invitation_ids as $invitation_id ) {
1186          $invitation = wp_cache_get( $invitation_id, 'bp_groups_invitations_as_memberships' );
1187  
1188          // Sanity check.
1189          if ( ! isset( $invitation->group_id ) ) {
1190              continue;
1191          }
1192  
1193          // Integer values.
1194          foreach ( $int_keys as $index ) {
1195              $invitation->{$index} = intval( $invitation->{$index} );
1196          }
1197  
1198          // Boolean values.
1199          foreach ( $bool_keys as $index ) {
1200              $invitation->{$index} = (bool) $invitation->{$index};
1201          }
1202  
1203          foreach ( $filters as $filter_name => $filter_value ) {
1204              if ( ! isset( $invitation->{$filter_name} ) || $filter_value != $invitation->{$filter_name} ) {
1205                  continue 2;
1206              }
1207          }
1208  
1209          $group_id = (int) $invitation->group_id;
1210  
1211          $groups[ $group_id ] = $invitation;
1212      }
1213  
1214      // By default, results are ordered by membership id.
1215      if ( 'group_id' === $r['orderby'] ) {
1216          ksort( $groups );
1217      } elseif ( in_array( $r['orderby'], array( 'id', 'date_modified' ) ) ) {
1218          $groups = bp_sort_by_key( $groups, $r['orderby'] );
1219      }
1220  
1221      // By default, results are ordered ASC.
1222      if ( 'DESC' === strtoupper( $r['order'] ) ) {
1223          // `true` to preserve keys.
1224          $groups = array_reverse( $groups, true );
1225      }
1226  
1227      return $groups;
1228  }
1229  
1230  /**
1231   * Get the count of groups of which the specified user is a member.
1232   *
1233   * @since 1.0.0
1234   *
1235   * @param int $user_id Optional. Default: ID of the displayed user.
1236   * @return int Group count.
1237   */
1238  function groups_total_groups_for_user( $user_id = 0 ) {
1239  
1240      if ( empty( $user_id ) )
1241          $user_id = ( bp_displayed_user_id() ) ? bp_displayed_user_id() : bp_loggedin_user_id();
1242  
1243      $count = wp_cache_get( 'bp_total_groups_for_user_' . $user_id, 'bp' );
1244  
1245      if ( false === $count ) {
1246          $count = BP_Groups_Member::total_group_count( $user_id );
1247          wp_cache_set( 'bp_total_groups_for_user_' . $user_id, $count, 'bp' );
1248      }
1249  
1250      return (int) $count;
1251  }
1252  
1253  /**
1254   * Get the BP_Groups_Group object corresponding to the current group.
1255   *
1256   * @since 1.5.0
1257   *
1258   * @global BuddyPress $bp The one true BuddyPress instance.
1259   *
1260   * @return BP_Groups_Group|bool The current group object or false.
1261   */
1262  function groups_get_current_group() {
1263      $bp = buddypress();
1264  
1265      $current_group = isset( $bp->groups->current_group )
1266          ? $bp->groups->current_group
1267          : false;
1268  
1269      /**
1270       * Filters the BP_Groups_Group object corresponding to the current group.
1271       *
1272       * @since 1.5.0
1273       *
1274       * @param BP_Groups_Group|bool $current_group Current BP_Groups_Group object or false.
1275       */
1276      return apply_filters( 'groups_get_current_group', $current_group );
1277  }
1278  
1279  /** Group Avatars *************************************************************/
1280  
1281  /**
1282   * Generate the avatar upload directory path for a given group.
1283   *
1284   * @since 1.1.0
1285   *
1286   * @param int $group_id Optional. ID of the group. Default: ID of the current group.
1287   * @return string
1288   */
1289  function groups_avatar_upload_dir( $group_id = 0 ) {
1290  
1291      if ( empty( $group_id ) ) {
1292          $group_id = bp_get_current_group_id();
1293      }
1294  
1295      $directory = 'group-avatars';
1296      $path      = bp_core_avatar_upload_path() . '/' . $directory . '/' . $group_id;
1297      $newbdir   = $path;
1298      $newurl    = bp_core_avatar_url() . '/' . $directory . '/' . $group_id;
1299      $newburl   = $newurl;
1300      $newsubdir = '/' . $directory . '/' . $group_id;
1301  
1302      /**
1303       * Filters the avatar upload directory path for a given group.
1304       *
1305       * @since 1.1.0
1306       *
1307       * @param array $value Array of parts related to the groups avatar upload directory.
1308       */
1309      return apply_filters( 'groups_avatar_upload_dir', array(
1310          'path'    => $path,
1311          'url'     => $newurl,
1312          'subdir'  => $newsubdir,
1313          'basedir' => $newbdir,
1314          'baseurl' => $newburl,
1315          'error'   => false
1316      ) );
1317  }
1318  
1319  /** Group Member Status Checks ************************************************/
1320  
1321  /**
1322   * Get the Group roles.
1323   *
1324   * @since 5.0.0
1325   *
1326   * @return array The list of Group role objects.
1327   */
1328  function bp_groups_get_group_roles() {
1329      return array(
1330          'admin' => (object) array(
1331              'id'           => 'admin',
1332              'name'         => __( 'Administrator', 'buddypress' ),
1333              'is_admin'     => true,
1334              'is_banned'    => false,
1335              'is_confirmed' => true,
1336              'is_mod'       => false,
1337          ),
1338          'mod' => (object) array(
1339              'id'           => 'mod',
1340              'name'         => __( 'Moderator', 'buddypress' ),
1341              'is_admin'     => false,
1342              'is_banned'    => false,
1343              'is_confirmed' => true,
1344              'is_mod'       => true,
1345          ),
1346          'member' => (object) array(
1347              'id'           => 'member',
1348              'name'         => __( 'Member', 'buddypress' ),
1349              'is_admin'     => false,
1350              'is_banned'    => false,
1351              'is_confirmed' => true,
1352              'is_mod'       => false,
1353          ),
1354          'banned' => (object) array(
1355              'id'           => 'banned',
1356              'name'         => __( 'Banned', 'buddypress' ),
1357              'is_admin'     => false,
1358              'is_banned'    => true,
1359              'is_confirmed' => true,
1360              'is_mod'       => false,
1361          ),
1362      );
1363  }
1364  
1365  /**
1366   * Check whether a user is an admin of a given group.
1367   *
1368   * @since 1.0.0
1369   *
1370   * @param int $user_id ID of the user.
1371   * @param int $group_id ID of the group.
1372   * @return int|bool ID of the membership if the user is admin, otherwise false.
1373   */
1374  function groups_is_user_admin( $user_id, $group_id ) {
1375      $is_admin = false;
1376  
1377      $user_groups = bp_get_user_groups( $user_id, array(
1378          'is_admin' => true,
1379      ) );
1380  
1381      if ( isset( $user_groups[ $group_id ] ) ) {
1382          $is_admin = $user_groups[ $group_id ]->id;
1383      }
1384  
1385      return $is_admin;
1386  }
1387  
1388  /**
1389   * Check whether a user is a mod of a given group.
1390   *
1391   * @since 1.0.0
1392   *
1393   * @param int $user_id ID of the user.
1394   * @param int $group_id ID of the group.
1395   * @return int|bool ID of the membership if the user is mod, otherwise false.
1396   */
1397  function groups_is_user_mod( $user_id, $group_id ) {
1398      $is_mod = false;
1399  
1400      $user_groups = bp_get_user_groups( $user_id, array(
1401          'is_mod' => true,
1402      ) );
1403  
1404      if ( isset( $user_groups[ $group_id ] ) ) {
1405          $is_mod = $user_groups[ $group_id ]->id;
1406      }
1407  
1408      return $is_mod;
1409  }
1410  
1411  /**
1412   * Check whether a user is a member of a given group.
1413   *
1414   * @since 1.0.0
1415   *
1416   * @param int $user_id ID of the user.
1417   * @param int $group_id ID of the group.
1418   * @return int|bool ID of the membership if the user is member, otherwise false.
1419   */
1420  function groups_is_user_member( $user_id, $group_id ) {
1421      $is_member = false;
1422  
1423      $user_groups = bp_get_user_groups( $user_id, array(
1424          'is_admin' => null,
1425          'is_mod' => null,
1426      ) );
1427  
1428      if ( isset( $user_groups[ $group_id ] ) ) {
1429          $is_member = $user_groups[ $group_id ]->id;
1430      }
1431  
1432      return $is_member;
1433  }
1434  
1435  /**
1436   * Check whether a user is banned from a given group.
1437   *
1438   * @since 1.0.0
1439   *
1440   * @param int $user_id  ID of the user.
1441   * @param int $group_id ID of the group.
1442   * @return int|bool ID of the membership if the user is banned, otherwise false.
1443   */
1444  function groups_is_user_banned( $user_id, $group_id ) {
1445      $is_banned = false;
1446  
1447      $user_groups = bp_get_user_groups( $user_id, array(
1448          'is_confirmed' => null,
1449          'is_banned' => true,
1450      ) );
1451  
1452      if ( isset( $user_groups[ $group_id ] ) ) {
1453          $is_banned = $user_groups[ $group_id ]->id;
1454      }
1455  
1456      return $is_banned;
1457  }
1458  
1459  /**
1460   * Check whether a user has an outstanding invitation to a group.
1461   *
1462   * @since 2.6.0
1463   * @since 5.0.0 Added $type parameter.
1464   *
1465   * @param int    $user_id  ID of the user.
1466   * @param int    $group_id ID of the group.
1467   * @param string $type     If 'sent', results are limited to those invitations
1468   *                         that have actually been sent (non-draft).
1469   *                         Possible values: 'sent', 'draft', or 'all' Default: 'sent'.
1470   * @return int|bool ID of the membership if the user is invited, otherwise false.
1471   */
1472  function groups_is_user_invited( $user_id, $group_id, $type = 'sent' ) {
1473      return groups_check_has_invite_from_user( $user_id, $group_id, false, $type );
1474  }
1475  
1476  /**
1477   * Check whether a user has a pending membership request for a group.
1478   *
1479   * @since 2.6.0
1480   *
1481   * @param int $user_id ID of the user.
1482   * @param int $group_id ID of the group.
1483   * @return int|bool ID of the membership if the user is pending, otherwise false.
1484   */
1485  function groups_is_user_pending( $user_id, $group_id ) {
1486      if ( empty( $user_id ) || empty( $group_id ) ) {
1487          return false;
1488      }
1489  
1490      $args = array(
1491          'user_id'     => $user_id,
1492          'item_id'     => $group_id,
1493      );
1494      $invites_class = new BP_Groups_Invitation_Manager();
1495  
1496      return $invites_class->request_exists( $args );
1497  }
1498  
1499  /**
1500   * Is the specified user the creator of the group?
1501   *
1502   * @since 1.2.6
1503   *
1504   * @param int $user_id ID of the user.
1505   * @param int $group_id ID of the group.
1506   * @return int|null
1507   */
1508  function groups_is_user_creator( $user_id, $group_id ) {
1509      return BP_Groups_Member::check_is_creator( $user_id, $group_id );
1510  }
1511  
1512  /** Group Invitations *********************************************************/
1513  
1514  /**
1515   * Get group objects for groups that a user is currently invited to.
1516   *
1517   * @since 1.0.0
1518   *
1519   * @param int               $user_id ID of the invited user.
1520   * @param int|bool          $limit   Limit to restrict to.
1521   * @param int|bool          $page    Optional. Page offset of results to return.
1522   * @param string|array|bool $exclude Array of comma-separated list of group IDs
1523   *                                   to exclude from results.
1524   * @return array {
1525   *     @type array $groups Array of groups returned by paginated query.
1526   *     @type int   $total  Count of groups matching query.
1527   * }
1528   */
1529  function groups_get_invites_for_user( $user_id = 0, $limit = false, $page = false, $exclude = false ) {
1530      if ( empty( $user_id ) ) {
1531          $user_id = bp_loggedin_user_id();
1532      }
1533  
1534      $group_ids = groups_get_invited_to_group_ids( $user_id );
1535  
1536      // Remove excluded groups.
1537      if ( $exclude ) {
1538          $group_ids = array_diff( $group_ids, wp_parse_id_list( $exclude ) );
1539      }
1540  
1541      // Avoid passing an empty array.
1542      if ( ! $group_ids ) {
1543          $group_ids = array( 0 );
1544      }
1545  
1546      // Get a filtered list of groups.
1547      $args = array(
1548          'include'     => $group_ids,
1549          'show_hidden' => true,
1550          'per_page'    => $limit,
1551          'page'        => $page,
1552      );
1553  
1554      return groups_get_groups( $args );
1555  }
1556  
1557  /**
1558   * Get the total group invite count for a user.
1559   *
1560   * @since 2.0.0
1561   *
1562   * @param int $user_id The user ID.
1563   * @return int
1564   */
1565  function groups_get_invite_count_for_user( $user_id = 0 ) {
1566      if ( empty( $user_id ) ) {
1567          $user_id = bp_loggedin_user_id();
1568      }
1569  
1570      $invites = groups_get_invites_for_user( $user_id );
1571      return $invites['total'];
1572  }
1573  
1574  /**
1575   * Get an array of group IDs to which a user is invited.
1576   *
1577   * @since 5.0.0
1578   *
1579   * @param int $user_id The user ID.
1580   *
1581   * @return array Array of group IDs.
1582   */
1583   function groups_get_invited_to_group_ids( $user_id = 0 ) {
1584      if ( empty( $user_id ) ) {
1585          $user_id = bp_loggedin_user_id();
1586      }
1587  
1588      $group_ids = groups_get_invites( array(
1589          'user_id'     => $user_id,
1590          'invite_sent' => 'sent',
1591          'fields'      => 'item_ids'
1592      ) );
1593  
1594      return array_unique( $group_ids );
1595  }
1596  
1597  /**
1598   * Invite a user to a group.
1599   *
1600   * @since 1.0.0
1601   *
1602   * @param array|string $args {
1603   *     Array of arguments.
1604   *     @type int    $user_id       ID of the user being invited.
1605   *     @type int    $group_id      ID of the group to which the user is being invited.
1606   *     @type int    $inviter_id    Optional. ID of the inviting user. Default:
1607   *                                 ID of the logged-in user.
1608   *     @type string $date_modified Optional. Modified date for the invitation.
1609   *                                 Default: current date/time.
1610   *     @type string $content       Optional. Message to invitee.
1611   *     @type bool   $send_invite   Optional. Whether the invitation should be
1612   *                                 sent now. Default: false.
1613   * }
1614   * @return bool True on success, false on failure.
1615   */
1616  function groups_invite_user( $args = '' ) {
1617  
1618      $r = bp_parse_args(
1619          $args,
1620          array(
1621              'user_id'       => false,
1622              'group_id'      => false,
1623              'inviter_id'    => bp_loggedin_user_id(),
1624              'date_modified' => bp_core_current_time(),
1625              'content'       => '',
1626              'send_invite'   => 0,
1627          ),
1628          'groups_invite_user'
1629      );
1630  
1631      $inv_args = array(
1632          'user_id'       => $r['user_id'],
1633          'item_id'       => $r['group_id'],
1634          'inviter_id'    => $r['inviter_id'],
1635          'date_modified' => $r['date_modified'],
1636          'content'       => $r['content'],
1637          'send_invite'   => $r['send_invite'],
1638      );
1639  
1640      // Create the unsent invitataion.
1641      $invites_class = new BP_Groups_Invitation_Manager();
1642      $created       = $invites_class->add_invitation( $inv_args );
1643  
1644      /**
1645       * Fires after the creation of a new group invite.
1646       *
1647       * @since 1.0.0
1648       *
1649       * @param array    $r       Array of parsed arguments for the group invite.
1650       * @param int|bool $created The ID of the invitation or false if it couldn't be created.
1651       */
1652      do_action( 'groups_invite_user', $r, $created );
1653  
1654      return $created;
1655  }
1656  
1657  /**
1658   * Uninvite a user from a group.
1659   *
1660   * @since 1.0.0
1661   *
1662   * @param int $user_id  ID of the user.
1663   * @param int $group_id ID of the group.
1664   * @param int $inviter_id ID of the inviter.
1665   * @return bool True on success, false on failure.
1666   */
1667  function groups_uninvite_user( $user_id, $group_id, $inviter_id = false ) {
1668      if ( empty( $user_id ) || empty( $group_id ) ) {
1669          return false;
1670      }
1671  
1672      $invites_class = new BP_Groups_Invitation_Manager();
1673      $success       = $invites_class->delete( array(
1674          'user_id'    => $user_id,
1675          'item_id'    => $group_id,
1676          'inviter_id' => $inviter_id,
1677      ) );
1678  
1679      if ( $success ) {
1680          /**
1681           * Fires after uninviting a user from a group.
1682           *
1683           * @since 1.0.0
1684           * @since 2.7.0 Added $inviter_id parameter
1685           *
1686           * @param int $group_id    ID of the group being uninvited from.
1687           * @param int $user_id     ID of the user being uninvited.
1688           * @param int $inviter_id  ID of the inviter.
1689           */
1690          do_action( 'groups_uninvite_user', $group_id, $user_id, $inviter_id );
1691      }
1692  
1693      return $success;
1694  }
1695  
1696  /**
1697   * Process the acceptance of a group invitation.
1698   *
1699   * Returns true if a user is already a member of the group.
1700   *
1701   * @since 1.0.0
1702   *
1703   * @param int $user_id  ID of the user.
1704   * @param int $group_id ID of the group.
1705   * @return bool True when the user is a member of the group, otherwise false.
1706   */
1707  function groups_accept_invite( $user_id, $group_id ) {
1708      $invites_class = new BP_Groups_Invitation_Manager();
1709      $args = array(
1710          'user_id'     => $user_id,
1711          'item_id'     => $group_id,
1712          'invite_sent' => 'sent',
1713      );
1714  
1715      return $invites_class->accept_invitation( $args );
1716  }
1717  
1718  /**
1719   * Reject a group invitation.
1720   *
1721   * @since 1.0.0
1722   * @since 5.0.0 The $inviter_id arg was added.
1723   *
1724   * @param int $user_id    ID of the user.
1725   * @param int $group_id   ID of the group.
1726   * @param int $inviter_id ID of the inviter.
1727   *
1728   * @return bool True on success, false on failure.
1729   */
1730  function groups_reject_invite( $user_id, $group_id, $inviter_id = false ) {
1731      if ( empty( $user_id ) || empty( $group_id ) ) {
1732          return false;
1733      }
1734  
1735      $invites_class = new BP_Groups_Invitation_Manager();
1736      $success       = $invites_class->delete( array(
1737          'user_id'    => $user_id,
1738          'item_id'    => $group_id,
1739          'inviter_id' => $inviter_id,
1740      ) );
1741  
1742      /**
1743       * Fires after a user rejects a group invitation.
1744       *
1745       * @since 1.0.0
1746       * @since 5.0.0 The $inviter_id arg was added.
1747       *
1748       * @param int $user_id    ID of the user rejecting the invite.
1749       * @param int $group_id   ID of the group being rejected.
1750       * @param int $inviter_id ID of the inviter.
1751       */
1752      do_action( 'groups_reject_invite', $user_id, $group_id, $inviter_id );
1753  
1754      return $success;
1755  }
1756  
1757  /**
1758   * Delete a group invitation.
1759   *
1760   * @since 1.0.0
1761   * @since 5.0.0 The $inviter_id arg was added.
1762   *
1763   * @param int $user_id  ID of the invited user.
1764   * @param int $group_id ID of the group.
1765   * @param int $inviter_id ID of the inviter.
1766   *
1767   * @return bool True on success, false on failure.
1768   */
1769  function groups_delete_invite( $user_id, $group_id, $inviter_id = false ) {
1770      if ( empty( $user_id ) || empty( $group_id ) ) {
1771          return false;
1772      }
1773  
1774      $invites_class = new BP_Groups_Invitation_Manager();
1775      $success       = $invites_class->delete( array(
1776          'user_id'    => $user_id,
1777          'item_id'    => $group_id,
1778          'inviter_id' => $inviter_id,
1779      ) );
1780  
1781      /**
1782       * Fires after the deletion of a group invitation.
1783       *
1784       * @since 1.9.0
1785       * @since 5.0.0 The $inviter_id arg was added.
1786       *
1787       * @param int $user_id  ID of the user whose invitation is being deleted.
1788       * @param int $group_id ID of the group whose invitation is being deleted.
1789       * @param int $inviter_id ID of the inviter.
1790       */
1791      do_action( 'groups_delete_invite', $user_id, $group_id, $inviter_id );
1792  
1793      return true;
1794  }
1795  
1796  /**
1797   * Send some or all pending invites by a single user to a specific group.
1798   *
1799   * @since 1.0.0
1800   * @since 5.0.0 Parameters changed to associative array.
1801   *
1802   * @param array $args {
1803   *     An array of optional arguments.
1804   *     @type int    $user_id       ID of the invited user.
1805   *     @type string $invitee_email Email address of the invited user, if not a member of the site.
1806   *     @type string $group_id      ID of the group or an array of group IDs.
1807   *     @type string $inviter_id    ID of the user extending the invitation.
1808   *     @type bool   $force_resend  Whether to resend the email & notification if one has already been sent.
1809   * }
1810   */
1811  function groups_send_invites( ...$args ) {
1812      // Backward compatibility with old method of passing arguments.
1813      if ( ! is_array( $args[0] ) || count( $args ) > 1 ) {
1814          _deprecated_argument( __METHOD__, '5.0.0', sprintf( __( 'Arguments passed to %1$s should be in an associative array. See the inline documentation at %2$s for more details.', 'buddypress' ), __METHOD__, __FILE__ ) );
1815  
1816          $old_args_keys = array(
1817              0 => 'inviter_id',
1818              1 => 'group_id',
1819          );
1820  
1821          $args = bp_core_parse_args_array( $old_args_keys, $args );
1822      } else {
1823          $args = reset( $args );
1824      }
1825  
1826      $r = bp_parse_args(
1827          $args,
1828          array(
1829              'user_id'       => false,
1830              'invitee_email' => '',
1831              'group_id'      => 0,
1832              'inviter_id'    => bp_loggedin_user_id(),
1833              'force_resend'  => false,
1834          ),
1835          'groups_send_invitation'
1836      );
1837  
1838      $args = array(
1839          'user_id'       => $r['user_id'],
1840          'invitee_email' => $r['invitee_email'],
1841          'item_id'       => $r['group_id'],
1842          'inviter_id'    => $r['inviter_id'],
1843      );
1844  
1845      /*
1846       * We will generally only want to fetch unsent invitations.
1847       * If force_resend is true, then we need to fetch both sent and draft invites.
1848       */
1849      if ( $r['force_resend'] ) {
1850          $args['invite_sent'] = 'all';
1851      } else {
1852          $args['invite_sent'] = 'draft';
1853      }
1854  
1855      $invites = groups_get_invites( $args );
1856  
1857      $invited_users = array();
1858  
1859      $invites_class = new BP_Groups_Invitation_Manager();
1860      foreach ( $invites as $invite ) {
1861          $invited_users[] = $invite->user_id;
1862          $invites_class->send_invitation_by_id( $invite->id );
1863      }
1864  
1865      /**
1866       * Fires after the sending of invites for a group.
1867       *
1868       * @since 1.0.0
1869       * @since 2.5.0 Added $user_id to passed parameters.
1870       *
1871       * @param int   $group_id      ID of the group who's being invited to.
1872       * @param array $invited_users Array of users being invited to the group.
1873       * @param int   $user_id       ID of the inviting user.
1874       */
1875      do_action( 'groups_send_invites', $r['group_id'], $invited_users, $r['inviter_id'] );
1876  }
1877  
1878  /**
1879   * Get IDs of users with outstanding invites to a given group.
1880   *
1881   * @since 1.0.0
1882   * @since 2.9.0 Added $sent as a parameter.
1883   *
1884   * @param  int      $user_id  ID of the inviting user.
1885   * @param  int      $group_id ID of the group.
1886   * @param  int|null $sent     Query for a specific invite sent status. If 0, this will query for users
1887   *                            that haven't had an invite sent to them yet. If 1, this will query for
1888   *                            users that have had an invite sent to them. If null, no invite status will
1889   *                            queried. Default: null.
1890   * @return array    IDs of users who have been invited to the group by the user but have not
1891   *                  yet accepted.
1892   */
1893  function groups_get_invites_for_group( $user_id, $group_id, $sent = null ) {
1894      return BP_Groups_Group::get_invites( $user_id, $group_id, $sent );
1895  }
1896  
1897  /**
1898   * Get invitations to a given group filtered by arguments.
1899   *
1900   * @since 5.0.0
1901   *
1902   * @param int   $group_id ID of the group.
1903   * @param array $args     Invitation arguments.
1904   *                        See BP_Invitation::get() for list.
1905   *
1906   * @return array $invites     Matching BP_Invitation objects.
1907   */
1908  function groups_get_invites( $args = array() ) {
1909      $invites_class = new BP_Groups_Invitation_Manager();
1910      return $invites_class->get_invitations( $args );
1911  }
1912  
1913  /**
1914   * Check to see whether a user has already been invited to a group.
1915   *
1916   * By default, the function checks for invitations that have been sent.
1917   * Entering 'all' as the $type parameter will return unsent invitations as
1918   * well (useful to make sure AJAX requests are not duplicated).
1919   *
1920   * @since 1.0.0
1921   *
1922   * @param int    $user_id  ID of potential group member.
1923   * @param int    $group_id ID of potential group.
1924   * @param string $type     Optional. Use 'sent' to check for sent invites,
1925   *                         'all' to check for all. Default: 'sent'.
1926   * @return int|bool ID of the first found membership if found, otherwise false.
1927   */
1928  function groups_check_user_has_invite( $user_id, $group_id, $type = 'sent' ) {
1929      return groups_check_has_invite_from_user( $user_id, $group_id, false, $type );
1930  }
1931  
1932  /**
1933   * Check to see whether a user has already been invited to a group by a particular user.
1934   *
1935   * By default, the function checks for invitations that have been sent.
1936   * Entering 'all' as the $type parameter will return unsent invitations as
1937   * well (useful to make sure AJAX requests are not duplicated).
1938   *
1939   * @since 5.0.0
1940   *
1941   * @param int    $user_id    ID of potential group member.
1942   * @param int    $group_id   ID of potential group.
1943   * @param string $inviter_id Optional. Use 'sent' to check for sent invites,
1944   *                           'all' to check for all. Default: 'sent'.
1945   * @param string $type       Optional. Specify a user ID to limit to only invited from that user.
1946   *                           Default: 'false'.
1947   * @return int|bool ID of the first found membership if found, otherwise false.
1948   */
1949   function groups_check_has_invite_from_user( $user_id, $group_id, $inviter_id = false, $type = 'sent' ) {
1950      if ( empty( $user_id ) || empty( $group_id ) ) {
1951          return false;
1952      }
1953  
1954      $args = array(
1955          'user_id'     => $user_id,
1956          'item_id'     => $group_id,
1957          'invite_sent' => 'sent',
1958      );
1959      if ( $inviter_id ) {
1960          $args['inviter_id'] = $inviter_id;
1961      }
1962      if ( $type === 'draft' || $type === 'all' ) {
1963          $args['invite_sent'] = $type;
1964      }
1965  
1966      $invites_class = new BP_Groups_Invitation_Manager();
1967  
1968      return $invites_class->invitation_exists( $args );
1969  }
1970  
1971  /**
1972   * Delete all invitations to a given group.
1973   *
1974   * @since 1.0.0
1975   *
1976   * @param int $group_id ID of the group whose invitations are being deleted.
1977   * @return int|null Number of rows records deleted on success, null on failure.
1978   */
1979  function groups_delete_all_group_invites( $group_id ) {
1980      return BP_Groups_Group::delete_all_invites( $group_id );
1981  }
1982  
1983  /** Group Promotion & Banning *************************************************/
1984  
1985  /**
1986   * Promote a member to a new status within a group.
1987   *
1988   * @since 1.0.0
1989   *
1990   * @param int    $user_id  ID of the user.
1991   * @param int    $group_id ID of the group.
1992   * @param string $status   The new status. 'mod' or 'admin'.
1993   * @return bool True on success, false on failure.
1994   */
1995  function groups_promote_member( $user_id, $group_id, $status ) {
1996  
1997      if ( ! bp_is_item_admin() )
1998          return false;
1999  
2000      $member = new BP_Groups_Member( $user_id, $group_id );
2001  
2002      // Don't use this action. It's deprecated as of BuddyPress 1.6.
2003      do_action( 'groups_premote_member', $group_id, $user_id, $status );
2004  
2005      /**
2006       * Fires before the promotion of a user to a new status.
2007       *
2008       * @since 1.6.0
2009       *
2010       * @param int    $group_id ID of the group being promoted in.
2011       * @param int    $user_id  ID of the user being promoted.
2012       * @param string $status   New status being promoted to.
2013       */
2014      do_action( 'groups_promote_member', $group_id, $user_id, $status );
2015  
2016      return $member->promote( $status );
2017  }
2018  
2019  /**
2020   * Demote a user to 'member' status within a group.
2021   *
2022   * @since 1.0.0
2023   *
2024   * @param int $user_id  ID of the user.
2025   * @param int $group_id ID of the group.
2026   * @return bool True on success, false on failure.
2027   */
2028  function groups_demote_member( $user_id, $group_id ) {
2029  
2030      if ( ! bp_is_item_admin() )
2031          return false;
2032  
2033      $member = new BP_Groups_Member( $user_id, $group_id );
2034  
2035      /**
2036       * Fires before the demotion of a user to 'member'.
2037       *
2038       * @since 1.0.0
2039       *
2040       * @param int $group_id ID of the group being demoted in.
2041       * @param int $user_id  ID of the user being demoted.
2042       */
2043      do_action( 'groups_demote_member', $group_id, $user_id );
2044  
2045      return $member->demote();
2046  }
2047  
2048  /**
2049   * Ban a member from a group.
2050   *
2051   * @since 1.0.0
2052   *
2053   * @param int $user_id  ID of the user.
2054   * @param int $group_id ID of the group.
2055   * @return bool True on success, false on failure.
2056   */
2057  function groups_ban_member( $user_id, $group_id ) {
2058  
2059      if ( ! bp_is_item_admin() )
2060          return false;
2061  
2062      $member = new BP_Groups_Member( $user_id, $group_id );
2063  
2064      /**
2065       * Fires before the banning of a member from a group.
2066       *
2067       * @since 1.0.0
2068       *
2069       * @param int $group_id ID of the group being banned from.
2070       * @param int $user_id  ID of the user being banned.
2071       */
2072      do_action( 'groups_ban_member', $group_id, $user_id );
2073  
2074      return $member->ban();
2075  }
2076  
2077  /**
2078   * Unban a member from a group.
2079   *
2080   * @since 1.0.0
2081   *
2082   * @param int $user_id  ID of the user.
2083   * @param int $group_id ID of the group.
2084   * @return bool True on success, false on failure.
2085   */
2086  function groups_unban_member( $user_id, $group_id ) {
2087  
2088      if ( ! bp_is_item_admin() )
2089          return false;
2090  
2091      $member = new BP_Groups_Member( $user_id, $group_id );
2092  
2093      /**
2094       * Fires before the unbanning of a member from a group.
2095       *
2096       * @since 1.0.0
2097       *
2098       * @param int $group_id ID of the group being unbanned from.
2099       * @param int $user_id  ID of the user being unbanned.
2100       */
2101      do_action( 'groups_unban_member', $group_id, $user_id );
2102  
2103      return $member->unban();
2104  }
2105  
2106  /** Group Removal *************************************************************/
2107  
2108  /**
2109   * Remove a member from a group.
2110   *
2111   * @since 1.2.6
2112   *
2113   * @param int $user_id  ID of the user.
2114   * @param int $group_id ID of the group.
2115   * @return bool True on success, false on failure.
2116   */
2117  function groups_remove_member( $user_id, $group_id ) {
2118  
2119      if ( ! bp_is_item_admin() ) {
2120          return false;
2121      }
2122  
2123      $member = new BP_Groups_Member( $user_id, $group_id );
2124  
2125      /**
2126       * Fires before the removal of a member from a group.
2127       *
2128       * @since 1.2.6
2129       *
2130       * @param int $group_id ID of the group being removed from.
2131       * @param int $user_id  ID of the user being removed.
2132       */
2133      do_action( 'groups_remove_member', $group_id, $user_id );
2134  
2135      return $member->remove();
2136  }
2137  
2138  /** Group Membership **********************************************************/
2139  
2140  /**
2141   * Create a group membership request.
2142   *
2143   * @since 1.0.0
2144   *
2145   * @param array|string $args {
2146   *     Array of arguments.
2147   *     @type int    $user_id       ID of the user being invited.
2148   *     @type int    $group_id      ID of the group to which the user is being invited.
2149   *     @type string $content       Optional. Message to invitee.
2150   *     @type string $date_modified Optional. Modified date for the invitation.
2151   *                                 Default: current date/time.
2152   * }
2153   * @return bool True on success, false on failure.
2154   */
2155  function groups_send_membership_request( ...$args ) {
2156      // Backward compatibility with old method of passing arguments.
2157      if ( ! is_array( $args[0] ) || count( $args ) > 1 ) {
2158          _deprecated_argument( __METHOD__, '5.0.0', sprintf( __( 'Arguments passed to %1$s should be in an associative array. See the inline documentation at %2$s for more details.', 'buddypress' ), __METHOD__, __FILE__ ) );
2159  
2160          $old_args_keys = array(
2161              0 => 'user_id',
2162              1 => 'group_id',
2163          );
2164  
2165          $args = bp_core_parse_args_array( $old_args_keys, $args );
2166      } else {
2167          $args = reset( $args );
2168      }
2169  
2170      $r = bp_parse_args(
2171          $args,
2172          array(
2173              'user_id'       => false,
2174              'group_id'      => false,
2175              'content'       => '',
2176              'date_modified' => bp_core_current_time(),
2177          ),
2178          'groups_send_membership_request'
2179      );
2180  
2181      $inv_args = array(
2182          'user_id'       => $r['user_id'],
2183          'item_id'       => $r['group_id'],
2184          'content'       => $r['content'],
2185          'date_modified' => $r['date_modified'],
2186      );
2187  
2188      $invites_class = new BP_Groups_Invitation_Manager();
2189      $request_id = $invites_class->add_request( $inv_args );
2190  
2191      // If a new request was created, send the emails.
2192      if ( $request_id && is_int( $request_id ) ) {
2193          $invites_class->send_request_notification_by_id( $request_id, $r );
2194          $admins = groups_get_group_admins( $r['group_id'] );
2195  
2196          /**
2197           * Fires after the creation of a new membership request.
2198           *
2199           * @since 1.0.0
2200           *
2201           * @param int   $requesting_user_id  ID of the user requesting membership.
2202           * @param array $admins              Array of group admins.
2203           * @param int   $group_id            ID of the group being requested to.
2204           * @param int   $request_id          ID of the request.
2205           */
2206          do_action( 'groups_membership_requested', $r['user_id'], $admins, $r['group_id'], $request_id );
2207  
2208          return $request_id;
2209      }
2210  
2211      return false;
2212  }
2213  
2214  /**
2215   * Accept a pending group membership request.
2216   *
2217   * @since 1.0.0
2218   * @since 5.0.0 Deprecated $membership_id argument.
2219   *
2220   * @param int $membership_id Deprecated 5.0.0.
2221   * @param int $user_id       Required. ID of the user who requested membership.
2222   *                           Provide this value along with $group_id to override
2223   *                           $membership_id.
2224   * @param int $group_id      Required. ID of the group to which membership is being
2225   *                           requested. Provide this value along with $user_id to
2226   *                           override $membership_id.
2227   * @return bool True on success, false on failure.
2228   */
2229  function groups_accept_membership_request( $membership_id, $user_id = 0, $group_id = 0 ) {
2230  
2231      if ( ! empty( $membership_id ) ) {
2232          /* translators: 1: the name of the method. 2: the name of the file. */
2233          _deprecated_argument( __METHOD__, '5.0.0', sprintf( __( 'Argument `membership_id` passed to %1$s is deprecated. See the inline documentation at %2$s for more details.', 'buddypress' ), __METHOD__, __FILE__ ) );
2234      }
2235  
2236      if ( ! $user_id || ! $group_id ) {
2237          return false;
2238      }
2239  
2240      $invites_class = new BP_Groups_Invitation_Manager();
2241      $args = array(
2242          'user_id' => $user_id,
2243          'item_id' => $group_id,
2244      );
2245  
2246      return $invites_class->accept_request( $args );
2247  }
2248  
2249  /**
2250   * Reject a pending group membership request.
2251   *
2252   * @since 1.0.0
2253   *
2254   * @param int $membership_id Deprecated 5.0.0.
2255   * @param int $user_id       Optional. ID of the user who requested membership.
2256   *                           Provide this value along with $group_id to override
2257   *                           $membership_id.
2258   * @param int $group_id      Optional. ID of the group to which membership is being
2259   *                           requested. Provide this value along with $user_id to
2260   *                           override $membership_id.
2261   * @return bool True on success, false on failure.
2262   */
2263  function groups_reject_membership_request( $membership_id, $user_id = 0, $group_id = 0 ) {
2264  
2265      if ( ! empty( $membership_id ) ){
2266          _deprecated_argument( __METHOD__, '5.0.0', sprintf( __( 'Argument `membership_id` passed to %1$s is deprecated. See the inline documentation at %2$s for more details.', 'buddypress' ), __METHOD__, __FILE__ ) );
2267      }
2268  
2269      if ( ! groups_delete_membership_request( false, $user_id, $group_id ) ) {
2270          return false;
2271      }
2272  
2273      /**
2274       * Fires after a group membership request has been rejected.
2275       *
2276       * @since 1.0.0
2277       *
2278       * @param int  $user_id  ID of the user who rejected membership.
2279       * @param int  $group_id ID of the group that was rejected membership to.
2280       * @param bool $value    If membership was accepted.
2281       */
2282      do_action( 'groups_membership_rejected', $user_id, $group_id, false );
2283  
2284      return true;
2285  }
2286  
2287  /**
2288   * Delete a pending group membership request.
2289   *
2290   * @since 1.2.0
2291   *
2292   * @param int $membership_id Deprecated 5.0.0.
2293   * @param int $user_id       Optional. ID of the user who requested membership.
2294   *                           Provide this value along with $group_id to override
2295   *                           $membership_id.
2296   * @param int $group_id      Optional. ID of the group to which membership is being
2297   *                           requested. Provide this value along with $user_id to
2298   *                           override $membership_id.
2299   * @return false|BP_Groups_Member True on success, false on failure.
2300   */
2301  function groups_delete_membership_request( $membership_id, $user_id = 0, $group_id = 0 ) {
2302      if ( ! empty( $membership_id ) ){
2303          /* translators: 1: method name. 2: file name. */
2304          _deprecated_argument( __METHOD__, '5.0.0', sprintf( __( 'Argument `membership_id` passed to %1$s is deprecated. See the inline documentation at %2$s for more details.', 'buddypress' ), __METHOD__, __FILE__ ) );
2305      }
2306  
2307      if ( empty( $user_id ) || empty( $group_id ) ) {
2308          return false;
2309      }
2310  
2311      $invites_class = new BP_Groups_Invitation_Manager();
2312      $success       = $invites_class->delete_requests( array(
2313          'user_id' => $user_id,
2314          'item_id' => $group_id
2315      ) );
2316  
2317      return $success;
2318  }
2319  
2320  /**
2321   * Get group membership requests filtered by arguments.
2322   *
2323   * @since 5.0.0
2324   *
2325   * @param int   $group_id ID of the group.
2326   * @param array $args     Invitation arguments.
2327   *                        See BP_Invitation::get() for list.
2328   *
2329   * @return array $requests Matching BP_Invitation objects.
2330   */
2331  function groups_get_requests( $args = array() ) {
2332      $invites_class = new BP_Groups_Invitation_Manager();
2333      return $invites_class->get_requests( $args );
2334  }
2335  
2336  /**
2337   * Check whether a user has an outstanding membership request for a given group.
2338   *
2339   * @since 1.0.0
2340   *
2341   * @param int $user_id  ID of the user.
2342   * @param int $group_id ID of the group.
2343   * @return int|bool ID of the request if found, otherwise false.
2344   */
2345  function groups_check_for_membership_request( $user_id, $group_id ) {
2346      if ( empty( $user_id ) || empty( $group_id ) ) {
2347          return false;
2348      }
2349  
2350      $args = array(
2351          'user_id' => $user_id,
2352          'item_id' => $group_id,
2353      );
2354      $invites_class = new BP_Groups_Invitation_Manager();
2355  
2356      return $invites_class->request_exists( $args );
2357  }
2358  
2359   /**
2360    * Get an array of group IDs to which a user has requested membership.
2361    *
2362    * @since 5.0.0
2363    *
2364    * @param int $user_id The user ID.
2365    *
2366    * @return array Array of group IDs.
2367    */
2368   function groups_get_membership_requested_group_ids( $user_id = 0 ) {
2369      if ( ! $user_id ) {
2370          $user_id = bp_loggedin_user_id();
2371      }
2372  
2373      $group_ids     = groups_get_requests( array(
2374          'user_id' => $user_id,
2375          'fields'  => 'item_ids'
2376      ) );
2377  
2378      return $group_ids;
2379  }
2380  
2381   /**
2382    * Get an array of group IDs to which a user has requested membership.
2383    *
2384    * @since 5.0.0
2385    *
2386    * @param int $user_id The user ID.
2387    *
2388    * @return array Array of group IDs.
2389    */
2390   function groups_get_membership_requested_user_ids( $group_id = 0 ) {
2391      if ( ! $group_id ) {
2392          $group_id = bp_get_current_group_id();
2393      }
2394  
2395      $requests = groups_get_requests( array(
2396          'item_id' => $group_id,
2397          'fields'  => 'user_ids'
2398      ) );
2399  
2400      return $requests;
2401  }
2402  
2403  /**
2404   * Accept all pending membership requests to a group.
2405   *
2406   * @since 1.0.2
2407   *
2408   * @param int $group_id ID of the group.
2409   * @return bool True on success, false on failure.
2410   */
2411  function groups_accept_all_pending_membership_requests( $group_id = 0 ) {
2412      if ( ! $group_id ) {
2413          $group_id = bp_get_current_group_id();
2414      }
2415  
2416      $user_ids = groups_get_membership_requested_user_ids( $group_id );
2417  
2418      if ( ! $user_ids ) {
2419          return false;
2420      }
2421  
2422      foreach ( (array) $user_ids as $user_id ) {
2423          groups_accept_membership_request( false, $user_id, $group_id );
2424      }
2425  
2426      /**
2427       * Fires after the acceptance of all pending membership requests to a group.
2428       *
2429       * @since 1.0.2
2430       *
2431       * @param int $group_id ID of the group whose pending memberships were accepted.
2432       */
2433      do_action( 'groups_accept_all_pending_membership_requests', $group_id );
2434  
2435      return true;
2436  }
2437  
2438  /** Group Meta ****************************************************************/
2439  
2440  /**
2441   * Delete metadata for a group.
2442   *
2443   * @since 1.0.0
2444   *
2445   * @param int         $group_id   ID of the group.
2446   * @param string|bool $meta_key   The key of the row to delete.
2447   * @param string|bool $meta_value Optional. Metadata value. If specified, only delete
2448   *                                metadata entries with this value.
2449   * @param bool        $delete_all Optional. If true, delete matching metadata entries
2450   *                                for all groups. Otherwise, only delete matching
2451   *                                metadata entries for the specified group.
2452   *                                Default: false.
2453   * @return bool True on success, false on failure.
2454   */
2455  function groups_delete_groupmeta( $group_id, $meta_key = false, $meta_value = false, $delete_all = false ) {
2456      global $wpdb;
2457  
2458      // Legacy - if no meta_key is passed, delete all for the item.
2459      if ( empty( $meta_key ) ) {
2460          $table_name = buddypress()->groups->table_name_groupmeta;
2461          $sql        = "SELECT meta_key FROM {$table_name} WHERE group_id = %d";
2462          $query      = $wpdb->prepare( $sql, $group_id );
2463          $keys       = $wpdb->get_col( $query );
2464  
2465          // With no meta_key, ignore $delete_all.
2466          $delete_all = false;
2467      } else {
2468          $keys = array( $meta_key );
2469      }
2470  
2471      add_filter( 'query', 'bp_filter_metaid_column_name' );
2472  
2473      $retval = true;
2474      foreach ( $keys as $key ) {
2475          $retval = delete_metadata( 'group', $group_id, $key, $meta_value, $delete_all );
2476      }
2477  
2478      remove_filter( 'query', 'bp_filter_metaid_column_name' );
2479  
2480      return $retval;
2481  }
2482  
2483  /**
2484   * Get a piece of group metadata.
2485   *
2486   * @since 1.0.0
2487   *
2488   * @param int    $group_id ID of the group.
2489   * @param string $meta_key Metadata key.
2490   * @param bool   $single   Optional. If true, return only the first value of the
2491   *                         specified meta_key. This parameter has no effect if
2492   *                         meta_key is empty.
2493   * @return mixed Metadata value.
2494   */
2495  function groups_get_groupmeta( $group_id, $meta_key = '', $single = true ) {
2496      add_filter( 'query', 'bp_filter_metaid_column_name' );
2497      $retval = get_metadata( 'group', $group_id, $meta_key, $single );
2498      remove_filter( 'query', 'bp_filter_metaid_column_name' );
2499  
2500      return $retval;
2501  }
2502  
2503  /**
2504   * Update a piece of group metadata.
2505   *
2506   * @since 1.0.0
2507   *
2508   * @param int    $group_id   ID of the group.
2509   * @param string $meta_key   Metadata key.
2510   * @param mixed  $meta_value Value to store.
2511   * @param mixed  $prev_value Optional. If specified, only update existing
2512   *                           metadata entries with the specified value.
2513   *                           Otherwise, update all entries.
2514   * @return bool|int $retval Returns false on failure. On successful update of existing
2515   *                          metadata, returns true. On successful creation of new metadata,
2516   *                          returns the integer ID of the new metadata row.
2517   */
2518  function groups_update_groupmeta( $group_id, $meta_key, $meta_value, $prev_value = '' ) {
2519      add_filter( 'query', 'bp_filter_metaid_column_name' );
2520      $retval = update_metadata( 'group', $group_id, $meta_key, $meta_value, $prev_value );
2521      remove_filter( 'query', 'bp_filter_metaid_column_name' );
2522  
2523      return $retval;
2524  }
2525  
2526  /**
2527   * Add a piece of group metadata.
2528   *
2529   * @since 2.0.0
2530   *
2531   * @param int    $group_id   ID of the group.
2532   * @param string $meta_key   Metadata key.
2533   * @param mixed  $meta_value Metadata value.
2534   * @param bool   $unique     Optional. Whether to enforce a single metadata value
2535   *                           for the given key. If true, and the object already
2536   *                           has a value for the key, no change will be made.
2537   *                           Default: false.
2538   * @return int|bool The meta ID on successful update, false on failure.
2539   */
2540  function groups_add_groupmeta( $group_id, $meta_key, $meta_value, $unique = false ) {
2541      add_filter( 'query', 'bp_filter_metaid_column_name' );
2542      $retval = add_metadata( 'group', $group_id, $meta_key, $meta_value, $unique );
2543      remove_filter( 'query', 'bp_filter_metaid_column_name' );
2544  
2545      return $retval;
2546  }
2547  
2548  /** Group Cleanup Functions ***************************************************/
2549  
2550  /**
2551   * Delete all group membership information for the specified user.
2552   *
2553   * @since 1.0.0
2554   *
2555   * @param int $user_id ID of the user.
2556   */
2557  function groups_remove_data_for_user( $user_id ) {
2558      BP_Groups_Member::delete_all_for_user( $user_id );
2559  
2560      /**
2561       * Fires after the deletion of all data for a user.
2562       *
2563       * @since 1.1.0
2564       *
2565       * @param int $user_id ID of the user whose data is being deleted.
2566       */
2567      do_action( 'groups_remove_data_for_user', $user_id );
2568  }
2569  add_action( 'wpmu_delete_user',  'groups_remove_data_for_user' );
2570  add_action( 'bp_make_spam_user', 'groups_remove_data_for_user' );
2571  
2572  /**
2573   * Deletes user group data on the 'delete_user' hook.
2574   *
2575   * @since 6.0.0
2576   *
2577   * @param int $user_id The ID of the deleted user.
2578   */
2579  function bp_groups_remove_data_for_user_on_delete_user( $user_id ) {
2580      if ( ! bp_remove_user_data_on_delete_user_hook( 'groups', $user_id ) ) {
2581          return;
2582      }
2583  
2584      groups_remove_data_for_user( $user_id );
2585  }
2586  add_action( 'delete_user', 'bp_groups_remove_data_for_user_on_delete_user' );
2587  
2588  /**
2589   * Update orphaned child groups when the parent is deleted.
2590   *
2591   * @since 2.7.0
2592   *
2593   * @param BP_Groups_Group $group Instance of the group item being deleted.
2594   */
2595  function bp_groups_update_orphaned_groups_on_group_delete( $group ) {
2596      // Get child groups and set the parent to the deleted parent's parent.
2597      $grandparent_group_id = $group->parent_id;
2598      $child_args = array(
2599          'parent_id'         => $group->id,
2600          'show_hidden'       => true,
2601          'per_page'          => false,
2602          'update_meta_cache' => false,
2603      );
2604      $children = groups_get_groups( $child_args );
2605      $children = $children['groups'];
2606  
2607      foreach ( $children as $cgroup ) {
2608          $cgroup->parent_id = $grandparent_group_id;
2609          $cgroup->save();
2610      }
2611  }
2612  add_action( 'bp_groups_delete_group', 'bp_groups_update_orphaned_groups_on_group_delete', 10, 2 );
2613  
2614  /** Group Types ***************************************************************/
2615  
2616  /**
2617   * Output the slug of the Group type taxonomy.
2618   *
2619   * @since 7.0.0
2620   */
2621  function bp_group_type_tax_name() {
2622      echo bp_get_group_type_tax_name();
2623  }
2624  
2625      /**
2626       * Return the slug of the Group type taxonomy.
2627       *
2628       * @since 7.0.0
2629       *
2630       * @return string The unique Group taxonomy slug.
2631       */
2632  	function bp_get_group_type_tax_name() {
2633          /**
2634           * Filters the slug of the Group type taxonomy.
2635           *
2636           * @since 7.0.0
2637           *
2638           * @param string $value Group type taxonomy slug.
2639           */
2640          return apply_filters( 'bp_get_group_type_tax_name', 'bp_group_type' );
2641      }
2642  
2643  /**
2644   * Returns labels used by the Group type taxonomy.
2645   *
2646   * @since 7.0.0
2647   *
2648   * @return array
2649   */
2650  function bp_get_group_type_tax_labels() {
2651  
2652      /**
2653       * Filters Group type taxonomy labels.
2654       *
2655       * @since 7.0.0
2656       *
2657       * @param array $value Associative array (name => label).
2658       */
2659      return apply_filters(
2660          'bp_get_group_type_tax_labels',
2661          array(
2662  
2663              // General labels
2664              'name'                          => _x( 'Group Types', 'Group type taxonomy name', 'buddypress' ),
2665              'singular_name'                 => _x( 'Group Type', 'Group type taxonomy singular name', 'buddypress' ),
2666              'search_items'                  => _x( 'Search Group Types', 'Group type taxonomy search items label', 'buddypress' ),
2667              'popular_items'                 => _x( 'Popular Group Types', 'Group type taxonomy popular items label', 'buddypress' ),
2668              'all_items'                     => _x( 'All Group Types', 'Group type taxonomy all items label', 'buddypress' ),
2669              'parent_item'                   => _x( 'Parent Group Type', 'Group type taxonomy parent item label', 'buddypress' ),
2670              'parent_item_colon'             => _x( 'Parent Group Type:', 'Group type taxonomy parent item label', 'buddypress' ),
2671              'edit_item'                     => _x( 'Edit Group Type', 'Group type taxonomy edit item label', 'buddypress' ),
2672              'view_item'                     => _x( 'View Group Type', 'Group type taxonomy view item label', 'buddypress' ),
2673              'update_item'                   => _x( 'Update Group Type', 'Group type taxonomy update item label', 'buddypress' ),
2674              'add_new_item'                  => _x( 'Add New Group Type', 'Group type taxonomy add new item label', 'buddypress' ),
2675              'new_item_name'                 => _x( 'New Group Type Name', 'Group type taxonomy new item name label', 'buddypress' ),
2676              'separate_items_with_commas'    => _x( 'Separate group types with commas', 'Group type taxonomy separate items with commas label', 'buddypress' ),
2677              'add_or_remove_items'           => _x( 'Add or remove group types', 'Group type taxonomy add or remove items label', 'buddypress' ),
2678              'choose_from_most_used'         => _x( 'Choose from the most used group types', 'Group type taxonomy choose from most used label', 'buddypress' ),
2679              'not_found'                     => _x( 'No group types found.', 'Group type taxonomy not found label', 'buddypress' ),
2680              'no_terms'                      => _x( 'No group types', 'Group type taxonomy no terms label', 'buddypress' ),
2681              'items_list_navigation'         => _x( 'Group Types list navigation', 'Group type taxonomy items list navigation label', 'buddypress' ),
2682              'items_list'                    => _x( 'Group Types list', 'Group type taxonomy items list label', 'buddypress' ),
2683  
2684              /* translators: Tab heading when selecting from the most used terms. */
2685              'most_used'                     => _x( 'Most Used', 'Group type taxonomy most used items label', 'buddypress' ),
2686              'back_to_items'                 => _x( '&larr; Back to Group Types', 'Group type taxonomy back to items label', 'buddypress' ),
2687  
2688              // Specific to BuddyPress.
2689              'bp_type_id_label'              => _x( 'Group Type ID', 'BP Member type ID label', 'buddypress' ),
2690              'bp_type_id_description'        => _x( 'Lower-case string, no spaces or special characters. Used to identify the group type.', 'BP Group type ID description', 'buddypress' ),
2691              'bp_type_show_in_create_screen' => _x( 'Show on Group Creation', 'BP Group type show in create screen', 'buddypress' ),
2692              'bp_type_show_in_list'          => _x( 'Show on Group', 'BP Group type show in list', 'buddypress' ),
2693          )
2694      );
2695  }
2696  
2697  /**
2698   * Returns arguments used by the Group type taxonomy.
2699   *
2700   * @since 7.0.0
2701   *
2702   * @return array
2703   */
2704  function bp_get_group_type_tax_args() {
2705  
2706      /**
2707       * Filters Group type taxonomy args.
2708       *
2709       * @since 7.0.0
2710       *
2711       * @param array $value Associative array (key => arg).
2712       */
2713      return apply_filters(
2714          'bp_get_group_type_tax_args',
2715          array_merge(
2716              array(
2717                  'description' => _x( 'BuddyPress Group Types', 'Group type taxonomy description', 'buddypress' ),
2718                  'labels'      => array_merge( bp_get_group_type_tax_labels(), bp_get_taxonomy_common_labels() ),
2719              ),
2720              bp_get_taxonomy_common_args()
2721          )
2722      );
2723  }
2724  
2725  /**
2726   * Register the Group Types taxonomy.
2727   *
2728   * @since 7.0.0
2729   *
2730   * @param array $taxonomies BuddyPress default taxonomies.
2731   * @return array            BuddyPress default taxonomies.
2732   */
2733  function bp_groups_register_group_type_taxonomy( $taxonomies = array() ) {
2734      return array_merge(
2735          $taxonomies,
2736          array(
2737              // Group Type.
2738              bp_get_group_type_tax_name() => array(
2739                  'object'    => 'bp_group',
2740                  'component' => 'groups',
2741                  'args'      => bp_get_group_type_tax_args(),
2742              ),
2743          )
2744      );
2745  }
2746  add_filter( 'bp_get_default_taxonomies', 'bp_groups_register_group_type_taxonomy', 1 );
2747  
2748  /**
2749   * Fire the 'bp_groups_register_group_types' action.
2750   *
2751   * @since 2.6.0
2752   */
2753  function bp_groups_register_group_types() {
2754      /**
2755       * Fires when it's appropriate to register group types.
2756       *
2757       * @since 2.6.0
2758       */
2759      do_action( 'bp_groups_register_group_types' );
2760  }
2761  add_action( 'bp_register_taxonomies', 'bp_groups_register_group_types' );
2762  
2763  /**
2764   * Extend generic Type metadata schema to match Group Type needs.
2765   *
2766   * @since 7.0.0
2767   *
2768   * @param array  $schema   The generic Type metadata schema.
2769   * @param string $taxonomy The taxonomy name the schema applies to.
2770   * @return array           The Group Type metadata schema.
2771   */
2772  function bp_get_group_type_metadata_schema( $schema = array(), $taxonomy = '' ) {
2773      if ( bp_get_group_type_tax_name() === $taxonomy ) {
2774  
2775          // Directory
2776          if ( isset( $schema['bp_type_has_directory']['description'] ) ) {
2777              $schema['bp_type_has_directory']['description'] = __( 'Make a list of groups matching this type available on the groups directory.', 'buddypress' );
2778          }
2779  
2780          // Slug
2781          if ( isset( $schema['bp_type_directory_slug']['description'] ) ) {
2782              $schema['bp_type_directory_slug']['description'] = __( 'Enter if you want the type slug to be different from its ID.', 'buddypress' );
2783          }
2784  
2785          // Create
2786          $schema['bp_type_show_in_create_screen'] = array(
2787              'description'       => __( 'Show during group creation, and when a group admin is on the group&rsquo;s settings page.', 'buddypress' ),
2788              'type'              => 'boolean',
2789              'single'            => true,
2790              'sanitize_callback' => 'absint',
2791          );
2792  
2793          // List
2794          $schema['bp_type_show_in_list'] = array(
2795              'description'       => __( 'Show where group types may be listed, like in the group header.', 'buddypress' ),
2796              'type'              => 'boolean',
2797              'single'            => true,
2798              'sanitize_callback' => 'absint',
2799          );
2800      }
2801  
2802      return $schema;
2803  }
2804  add_filter( 'bp_get_type_metadata_schema', 'bp_get_group_type_metadata_schema', 1, 2 );
2805  
2806  /**
2807   * Registers the Group type metadata.
2808   *
2809   * @since 7.0.0
2810   */
2811  function bp_register_group_type_metadata() {
2812      $type_taxonomy = bp_get_group_type_tax_name();
2813  
2814      foreach ( bp_get_type_metadata_schema( false, $type_taxonomy ) as $meta_key => $meta_args ) {
2815          bp_register_type_meta( $type_taxonomy, $meta_key, $meta_args );
2816      }
2817  }
2818  add_action( 'bp_register_type_metadata', 'bp_register_group_type_metadata', 11 );
2819  
2820  /**
2821   * Register a group type.
2822   *
2823   * @since 2.6.0
2824   * @since 2.7.0 Introduce $has_directory, $show_in_create_screen, $show_in_list, and
2825   *              $description, $create_screen_checked as $args parameters.
2826   *
2827   * @param string $group_type Unique string identifier for the group type.
2828   * @param array  $args {
2829   *     Array of arguments describing the group type.
2830   *
2831   *     @type string|bool $has_directory         Set the slug to be used for custom group directory page. eg.
2832   *                                              example.com/groups/type/MY_SLUG. Default: false.
2833   *     @type bool        $show_in_create_screen Whether this group type is allowed to be selected on the group creation
2834   *                                              page. Default: false.
2835   *     @type bool|null   $show_in_list          Whether this group type should be shown in lists rendered by
2836   *                                              bp_group_type_list(). Default: null. If $show_in_create_screen is true,
2837   *                                              this will default to true, unless this is set explicitly to false.
2838   *     @type string      $description           A short descriptive summary of what the group type is. Currently shown
2839   *                                              on a group's "Manage > Settings" page when selecting group types.
2840   *     @type bool        $create_screen_checked If $show_in_create_screen is true, whether we should have our group type
2841   *                                              checkbox checked by default. Handy if you want to imply that the group
2842   *                                              type should be enforced, but decision lies with the group creator.
2843   *                                              Default: false.
2844   *     @type array       $labels {
2845   *         Array of labels to use in various parts of the interface.
2846   *
2847   *         @type string $name          Default name. Should typically be plural.
2848   *         @type string $singular_name Singular name.
2849   *     }
2850   * }
2851   * @return object|WP_Error Group type object on success, WP_Error object on failure.
2852   */
2853  function bp_groups_register_group_type( $group_type, $args = array() ) {
2854      $bp = buddypress();
2855  
2856      if ( isset( $bp->groups->types[ $group_type ] ) ) {
2857          return new WP_Error( 'bp_group_type_exists', __( 'Group type already exists.', 'buddypress' ), $group_type );
2858      }
2859  
2860      $r = bp_parse_args(
2861          $args,
2862          array(
2863              'has_directory'         => false,
2864              'show_in_create_screen' => false,
2865              'show_in_list'          => null,
2866              'description'           => '',
2867              'create_screen_checked' => false,
2868              'labels'                => array(),
2869              'code'                  => true,
2870              'db_id'                 => 0,
2871          ),
2872          'register_group_type'
2873      );
2874  
2875      $group_type = sanitize_key( $group_type );
2876  
2877      /**
2878       * Filters the list of illegal group type names.
2879       *
2880       * - 'any' is a special pseudo-type, representing items unassociated with any group type.
2881       * - 'null' is a special pseudo-type, representing users without any type.
2882       * - '_none' is used internally to denote an item that should not apply to any group types.
2883       *
2884       * @since 2.6.0
2885       *
2886       * @param array $illegal_names Array of illegal names.
2887       */
2888      $illegal_names = apply_filters( 'bp_group_type_illegal_names', array( 'any', 'null', '_none' ) );
2889      if ( in_array( $group_type, $illegal_names, true ) ) {
2890          return new WP_Error( 'bp_group_type_illegal_name', __( 'You may not register a group type with this name.', 'buddypress' ), $group_type );
2891      }
2892  
2893      // Store the group type name as data in the object (not just as the array key).
2894      $r['name'] = $group_type;
2895  
2896      // Make sure the relevant labels have been filled in.
2897      $default_name = isset( $r['labels']['name'] ) ? $r['labels']['name'] : ucfirst( $r['name'] );
2898      $r['labels'] = array_merge( array(
2899          'name'          => $default_name,
2900          'singular_name' => $default_name,
2901      ), $r['labels'] );
2902  
2903      // Directory slug.
2904      if ( ! empty( $r['has_directory'] ) ) {
2905          // A string value is intepreted as the directory slug.
2906          if ( is_string( $r['has_directory'] ) ) {
2907              $directory_slug = $r['has_directory'];
2908  
2909          // Otherwise fall back on group type.
2910          } else {
2911              $directory_slug = $group_type;
2912          }
2913  
2914          // Sanitize for use in URLs.
2915          $r['directory_slug'] = sanitize_title( $directory_slug );
2916          $r['has_directory']  = true;
2917      } else {
2918          $r['directory_slug'] = '';
2919          $r['has_directory']  = false;
2920      }
2921  
2922      // Type lists.
2923      if ( true === $r['show_in_create_screen'] && is_null( $r['show_in_list'] ) ) {
2924          $r['show_in_list'] = true;
2925      } else {
2926          $r['show_in_list'] = (bool) $r['show_in_list'];
2927      }
2928  
2929      $bp->groups->types[ $group_type ] = $type = (object) $r;
2930  
2931      /**
2932       * Fires after a group type is registered.
2933       *
2934       * @since 2.6.0
2935       *
2936       * @param string $group_type Group type identifier.
2937       * @param object $type       Group type object.
2938       */
2939      do_action( 'bp_groups_register_group_type', $group_type, $type );
2940  
2941      return $type;
2942  }
2943  
2944  /**
2945   * Get a list of all registered group type objects.
2946   *
2947   * @since 2.6.0
2948   *
2949   * @see bp_groups_register_group_type() for accepted arguments.
2950   *
2951   * @param array|string $args     Optional. An array of key => value arguments to match against
2952   *                               the group type objects. Default empty array.
2953   * @param string       $output   Optional. The type of output to return. Accepts 'names'
2954   *                               or 'objects'. Default 'names'.
2955   * @param string       $operator Optional. The logical operation to perform. 'or' means only one
2956   *                               element from the array needs to match; 'and' means all elements
2957   *                               must match. Accepts 'or' or 'and'. Default 'and'.
2958   * @return array       $types    A list of groups type names or objects.
2959   */
2960  function bp_groups_get_group_types( $args = array(), $output = 'names', $operator = 'and' ) {
2961      $types = buddypress()->groups->types;
2962  
2963      // Merge with types available into the database.
2964      if ( ! isset( $args['code'] ) || true !== $args['code'] ) {
2965          $types = bp_get_taxonomy_types( bp_get_group_type_tax_name(), $types );
2966      }
2967  
2968      $types = wp_filter_object_list( $types, $args, $operator );
2969  
2970      /**
2971       * Filters the array of group type objects.
2972       *
2973       * This filter is run before the $output filter has been applied, so that
2974       * filtering functions have access to the entire group type objects.
2975       *
2976       * @since 2.6.0
2977       *
2978       * @param array  $types     group type objects, keyed by name.
2979       * @param array  $args      Array of key=>value arguments for filtering.
2980       * @param string $operator  'or' to match any of $args, 'and' to require all.
2981       */
2982      $types = apply_filters( 'bp_groups_get_group_types', $types, $args, $operator );
2983  
2984      if ( 'names' === $output ) {
2985          $types = wp_list_pluck( $types, 'name' );
2986      }
2987  
2988      return $types;
2989  }
2990  
2991  /**
2992   * Retrieve a group type object by name.
2993   *
2994   * @since 2.6.0
2995   *
2996   * @param string $group_type The name of the group type.
2997   * @return object A group type object.
2998   */
2999  function bp_groups_get_group_type_object( $group_type ) {
3000      $types = bp_groups_get_group_types( array(), 'objects' );
3001  
3002      if ( empty( $types[ $group_type ] ) ) {
3003          return null;
3004      }
3005  
3006      return $types[ $group_type ];
3007  }
3008  
3009  /**
3010   * Only gets the group types registered by code.
3011   *
3012   * @since 7.0.0
3013   *
3014   * @return array The group types registered by code.
3015   */
3016  function bp_get_group_types_registered_by_code() {
3017      return bp_groups_get_group_types(
3018          array(
3019              'code' => true,
3020          ),
3021          'objects'
3022      );
3023  }
3024  add_filter( bp_get_group_type_tax_name() . '_registered_by_code', 'bp_get_group_types_registered_by_code' );
3025  
3026  /**
3027   * Generates missing metadata for a type registered by code.
3028   *
3029   * @since 7.0.0
3030   *
3031   * @return array The group type metadata.
3032   */
3033  function bp_set_registered_by_code_group_type_metadata( $metadata = array(), $type = '' ) {
3034      $group_type = bp_groups_get_group_type_object( $type );
3035  
3036      foreach ( get_object_vars( $group_type ) as $object_key => $object_value ) {
3037          if ( 'labels' === $object_key ) {
3038              foreach ( $object_value as $label_key => $label_value ) {
3039                  $metadata[ 'bp_type_' . $label_key ] = $label_value;
3040              }
3041          } elseif ( ! in_array( $object_key, array( 'name', 'code', 'db_id' ), true ) ) {
3042              $metadata[ 'bp_type_' . $object_key ] = $object_value;
3043          }
3044      }
3045  
3046      /**
3047       * Save metadata into database to avoid generating metadata
3048       * each time a type is listed into the Types Admin screen.
3049       */
3050      if ( isset( $group_type->db_id ) && $group_type->db_id ) {
3051          bp_update_type_metadata( $group_type->db_id, bp_get_group_type_tax_name(), $metadata );
3052      }
3053  
3054      return $metadata;
3055  }
3056  add_filter( bp_get_group_type_tax_name() . '_set_registered_by_code_metada', 'bp_set_registered_by_code_group_type_metadata', 10, 2 );
3057  
3058  /**
3059   * Insert group types registered by code not yet saved into the database as WP Terms.
3060   *
3061   * @since 7.0.0
3062   */
3063  function bp_insert_group_types_registered_by_code() {
3064      $all_types     = bp_groups_get_group_types( array(), 'objects' );
3065      $unsaved_types = wp_filter_object_list( $all_types, array( 'db_id' => 0 ), 'and', 'name' );
3066  
3067      if ( $unsaved_types ) {
3068          foreach ( $unsaved_types as $type_name ) {
3069              bp_insert_term(
3070                  $type_name,
3071                  bp_get_group_type_tax_name(),
3072                  array(
3073                      'slug' => $type_name,
3074                  )
3075              );
3076          }
3077      }
3078  }
3079  add_action( bp_get_group_type_tax_name() . '_add_form', 'bp_insert_group_types_registered_by_code', 1 );
3080  
3081  /**
3082   * Set type for a group.
3083   *
3084   * @since 2.6.0
3085   * @since 2.7.0 $group_type parameter also accepts an array of group types now.
3086   *
3087   * @param int          $group_id   ID of the group.
3088   * @param string|array $group_type Group type or array of group types to set.
3089   * @param bool         $append     Optional. True to append this to existing types for group,
3090   *                                 false to replace. Default: false.
3091   * @return false|array $retval See bp_set_object_terms().
3092   */
3093  function bp_groups_set_group_type( $group_id, $group_type, $append = false ) {
3094      // Pass an empty group type to remove group's type.
3095      if ( ! empty( $group_type ) && is_string( $group_type ) && ! bp_groups_get_group_type_object( $group_type ) ) {
3096          return false;
3097      }
3098  
3099      // Cast as array.
3100      $group_type = (array) $group_type;
3101  
3102      // Validate group types.
3103      foreach ( $group_type as $type ) {
3104          // Remove any invalid group types.
3105          if ( is_null( bp_groups_get_group_type_object( $type ) ) ) {
3106              unset( $group_type[ $type ] );
3107          }
3108      }
3109  
3110      $retval = bp_set_object_terms( $group_id, $group_type, bp_get_group_type_tax_name(), $append );
3111  
3112      // Bust the cache if the type has been updated.
3113      if ( ! is_wp_error( $retval ) ) {
3114          wp_cache_delete( $group_id, 'bp_groups_group_type' );
3115  
3116          /**
3117           * Fires just after a group type has been changed.
3118           *
3119           * @since 2.6.0
3120           *
3121           * @param int          $group_id   ID of the group whose group type has been updated.
3122           * @param string|array $group_type Group type or array of group types.
3123           * @param bool         $append     Whether the type is being appended to existing types.
3124           */
3125          do_action( 'bp_groups_set_group_type', $group_id, $group_type, $append );
3126      }
3127  
3128      return $retval;
3129  }
3130  
3131  /**
3132   * Get type for a group.
3133   *
3134   * @since 2.6.0
3135   * @since 7.0.0 Adds the `$use_db` parameter.
3136   *
3137   * @param int  $group_id ID of the group.
3138   * @param bool $single   Optional. Whether to return a single type string. If multiple types are found
3139   *                       for the group, the oldest one will be returned. Default: true.
3140   * @param bool $use_db   Optional. Whether to request all group types or only the ones registered by code.
3141   *                       Default: true.
3142   * @return string|array|bool On success, returns a single group type (if `$single` is true) or an array of group
3143   *                           types (if `$single` is false). Returns false on failure.
3144   */
3145  function bp_groups_get_group_type( $group_id, $single = true, $use_db = true ) {
3146      $types = wp_cache_get( $group_id, 'bp_groups_group_type' );
3147  
3148      if ( false === $types ) {
3149          $raw_types = bp_get_object_terms( $group_id, bp_get_group_type_tax_name() );
3150  
3151          if ( ! is_wp_error( $raw_types ) ) {
3152              $types = array();
3153  
3154              // Only include currently registered group types.
3155              foreach ( $raw_types as $gtype ) {
3156                  if ( bp_groups_get_group_type_object( $gtype->name ) ) {
3157                      $types[] = $gtype->name;
3158                  }
3159              }
3160  
3161              wp_cache_set( $group_id, $types, 'bp_groups_group_type' );
3162          }
3163      }
3164  
3165      if ( false === $use_db && $types ) {
3166          $registred_by_code = bp_get_group_types_registered_by_code();
3167          $ctype_names       = wp_list_pluck( $registred_by_code, 'name' );
3168          $types             = array_intersect( $types, $ctype_names );
3169      }
3170  
3171      $type = false;
3172      if ( ! empty( $types ) ) {
3173          if ( $single ) {
3174              $type = end( $types );
3175          } else {
3176              $type = $types;
3177          }
3178      }
3179  
3180      /**
3181       * Filters a groups's group type(s).
3182       *
3183       * @since 2.6.0
3184       *
3185       * @param string|array $type     Group type.
3186       * @param int          $group_id ID of the group.
3187       * @param bool         $single   Whether to return a single type string, or an array.
3188       */
3189      return apply_filters( 'bp_groups_get_group_type', $type, $group_id, $single );
3190  }
3191  
3192  /**
3193   * Remove type for a group.
3194   *
3195   * @since 2.6.0
3196   *
3197   * @param int            $group_id   ID of the user.
3198   * @param string         $group_type Group type.
3199   * @return bool|WP_Error $deleted    True on success. False or WP_Error on failure.
3200   */
3201  function bp_groups_remove_group_type( $group_id, $group_type ) {
3202      if ( empty( $group_type ) || ! bp_groups_get_group_type_object( $group_type ) ) {
3203          return false;
3204      }
3205  
3206      // No need to continue if the group doesn't have the type.
3207      $existing_types = bp_groups_get_group_type( $group_id, false );
3208      if ( ! in_array( $group_type, $existing_types, true ) ) {
3209          return false;
3210      }
3211  
3212      $deleted = bp_remove_object_terms( $group_id, $group_type, bp_get_group_type_tax_name() );
3213  
3214      // Bust the case, if the type has been removed.
3215      if ( ! is_wp_error( $deleted ) ) {
3216          wp_cache_delete( $group_id, 'bp_groups_group_type' );
3217  
3218          /**
3219           * Fires just after a group's group type has been removed.
3220           *
3221           * @since 2.6.0
3222           *
3223           * @param int    $group      ID of the group whose group type has been removed.
3224           * @param string $group_type Group type.
3225           */
3226          do_action( 'bp_groups_remove_group_type', $group_id, $group_type );
3227      }
3228  
3229      return $deleted;
3230  }
3231  
3232  /**
3233   * Check whether the given group has a certain group type.
3234   *
3235   * @since 2.6.0
3236   *
3237   * @param  int    $group_id   ID of the group.
3238   * @param  string $group_type Group type.
3239   * @return bool   Whether the group has the give group type.
3240   */
3241  function bp_groups_has_group_type( $group_id, $group_type ) {
3242      if ( empty( $group_type ) || ! bp_groups_get_group_type_object( $group_type ) ) {
3243          return false;
3244      }
3245  
3246      // Get all group's group types.
3247      $types = bp_groups_get_group_type( $group_id, false );
3248  
3249      if ( ! is_array( $types ) ) {
3250          return false;
3251      }
3252  
3253      return in_array( $group_type, $types );
3254  }
3255  
3256  /**
3257   * Get the "current" group type, if one is provided, in group directories.
3258   *
3259   * @since 2.7.0
3260   *
3261   * @return string
3262   */
3263  function bp_get_current_group_directory_type() {
3264  
3265      /**
3266       * Filters the "current" group type, if one is provided, in group directories.
3267       *
3268       * @since 2.7.0
3269       *
3270       * @param string $value "Current" group type.
3271       */
3272      return apply_filters( 'bp_get_current_group_directory_type', buddypress()->groups->current_directory_type );
3273  }
3274  
3275  /**
3276   * Delete a group's type when the group is deleted.
3277   *
3278   * @since 2.6.0
3279   *
3280   * @param  int   $group_id ID of the group.
3281   * @return array|null $value    See {@see bp_groups_set_group_type()}.
3282   */
3283  function bp_remove_group_type_on_group_delete( $group_id = 0 ) {
3284      bp_groups_set_group_type( $group_id, '' );
3285  }
3286  add_action( 'groups_delete_group', 'bp_remove_group_type_on_group_delete' );
3287  
3288  /**
3289   * Finds and exports group membership data associated with an email address.
3290   *
3291   * @since 4.0.0
3292   *
3293   * @param string $email_address  The user's email address.
3294   * @param int    $page           Batch number.
3295   * @return array An array of personal data.
3296   */
3297  function bp_groups_memberships_personal_data_exporter( $email_address, $page ) {
3298      $number = 20;
3299  
3300      $email_address = trim( $email_address );
3301  
3302      $data_to_export = array();
3303  
3304      $user = get_user_by( 'email', $email_address );
3305  
3306      if ( ! $user ) {
3307          return array(
3308              'data' => array(),
3309              'done' => true,
3310          );
3311      }
3312  
3313      $memberships = BP_Groups_Member::get_user_memberships( $user->ID, array(
3314          'type'     => 'membership',
3315          'page'     => $page,
3316          'per_page' => $number,
3317      ) );
3318  
3319      foreach ( $memberships as $membership ) {
3320          $group = groups_get_group( $membership->group_id );
3321  
3322          $item_data = array(
3323              array(
3324                  'name'  => __( 'Group Name', 'buddypress' ),
3325                  'value' => bp_get_group_name( $group ),
3326              ),
3327              array(
3328                  'name'  => __( 'Group URL', 'buddypress' ),
3329                  'value' => bp_get_group_permalink( $group ),
3330              ),
3331          );
3332  
3333          if ( $membership->inviter_id ) {
3334              $item_data[] = array(
3335                  'name'  => __( 'Invited By', 'buddypress' ),
3336                  'value' => bp_core_get_userlink( $membership->inviter_id ),
3337              );
3338          }
3339  
3340          if ( $group->creator_id === $user->ID ) {
3341              $group_role = __( 'Creator', 'buddypress' );
3342          } elseif ( $membership->is_admin ) {
3343              $group_role = __( 'Admin', 'buddypress' );
3344          } elseif ( $membership->is_mod ) {
3345              $group_role = __( 'Moderator', 'buddypress' );
3346          } else {
3347              $group_role = __( 'Member', 'buddypress' );
3348          }
3349  
3350          $item_data[] = array(
3351              'name'  => __( 'Group Role', 'buddypress' ),
3352              'value' => $group_role,
3353          );
3354  
3355          $item_data[] = array(
3356              'name'  => __( 'Date Joined', 'buddypress' ),
3357              'value' => $membership->date_modified,
3358          );
3359  
3360          $data_to_export[] = array(
3361              'group_id'    => 'bp_groups_memberships',
3362              'group_label' => __( 'Group Memberships', 'buddypress' ),
3363              'item_id'     => "bp-group-membership-{$group->id}",
3364              'data'        => $item_data,
3365          );
3366      }
3367  
3368      // Tell core if we have more items to process.
3369      $done = count( $memberships ) < $number;
3370  
3371      return array(
3372          'data' => $data_to_export,
3373          'done' => $done,
3374      );
3375  }
3376  
3377  /**
3378   * Finds and exports data on pending group membership requests associated with an email address.
3379   *
3380   * @since 4.0.0
3381   *
3382   * @param string $email_address  The user's email address.
3383   * @param int    $page           Batch number.
3384   * @return array An array of personal data.
3385   */
3386  function bp_groups_pending_requests_personal_data_exporter( $email_address, $page ) {
3387      $number = 20;
3388  
3389      $email_address = trim( $email_address );
3390  
3391      $data_to_export = array();
3392  
3393      $user = get_user_by( 'email', $email_address );
3394  
3395      if ( ! $user ) {
3396          return array(
3397              'data' => array(),
3398              'done' => true,
3399          );
3400      }
3401  
3402      $requests = groups_get_requests( array(
3403          'user_id'  => $user->ID,
3404          'page'     => $page,
3405          'per_page' => $number,
3406      ) );
3407  
3408      foreach ( $requests as $request ) {
3409          $group = groups_get_group( $request->item_id );
3410  
3411          $item_data = array(
3412              array(
3413                  'name'  => __( 'Group Name', 'buddypress' ),
3414                  'value' => bp_get_group_name( $group ),
3415              ),
3416              array(
3417                  'name'  => __( 'Group URL', 'buddypress' ),
3418                  'value' => bp_get_group_permalink( $group ),
3419              ),
3420              array(
3421                  'name'  => __( 'Date Sent', 'buddypress' ),
3422                  'value' => $request->date_modified,
3423              ),
3424          );
3425  
3426          $data_to_export[] = array(
3427              'group_id'    => 'bp_groups_pending_requests',
3428              'group_label' => __( 'Pending Group Membership Requests', 'buddypress' ),
3429              'item_id'     => "bp-group-pending-request-{$group->id}",
3430              'data'        => $item_data,
3431          );
3432      }
3433  
3434      // Tell core if we have more items to process.
3435      $done = count( $requests ) < $number;
3436  
3437      return array(
3438          'data' => $data_to_export,
3439          'done' => $done,
3440      );
3441  }
3442  
3443  /**
3444   * Finds and exports data on pending group invitations sent by a user associated with an email address.
3445   *
3446   * @since 4.0.0
3447   *
3448   * @param string $email_address  The user's email address.
3449   * @param int    $page           Batch number.
3450   * @return array An array of personal data.
3451   */
3452  function bp_groups_pending_sent_invitations_personal_data_exporter( $email_address, $page ) {
3453      $number = 20;
3454  
3455      $email_address = trim( $email_address );
3456  
3457      $data_to_export = array();
3458  
3459      $user = get_user_by( 'email', $email_address );
3460  
3461      if ( ! $user ) {
3462          return array(
3463              'data' => array(),
3464              'done' => true,
3465          );
3466      }
3467  
3468      $invitations = groups_get_invites( array(
3469          'inviter_id'  => $user->ID,
3470          'page'        => $page,
3471          'per_page'    => $number,
3472      ) );
3473  
3474      foreach ( $invitations as $invitation ) {
3475          $group = groups_get_group( $invitation->item_id );
3476  
3477          $item_data = array(
3478              array(
3479                  'name'  => __( 'Group Name', 'buddypress' ),
3480                  'value' => bp_get_group_name( $group ),
3481              ),
3482              array(
3483                  'name'  => __( 'Group URL', 'buddypress' ),
3484                  'value' => bp_get_group_permalink( $group ),
3485              ),
3486              array(
3487                  'name'  => __( 'Sent To', 'buddypress' ),
3488                  'value' => bp_core_get_userlink( $invitation->user_id ),
3489              ),
3490              array(
3491                  'name'  => __( 'Date Sent', 'buddypress' ),
3492                  'value' => $invitation->date_modified,
3493              ),
3494          );
3495  
3496          $data_to_export[] = array(
3497              'group_id'    => 'bp_groups_pending_sent_invitations',
3498              'group_label' => __( 'Pending Group Invitations (Sent)', 'buddypress' ),
3499              'item_id'     => "bp-group-pending-sent-invitation-{$group->id}",
3500              'data'        => $item_data,
3501          );
3502      }
3503  
3504      // Tell core if we have more items to process.
3505      $done = count( $invitations ) < $number;
3506  
3507      return array(
3508          'data' => $data_to_export,
3509          'done' => $done,
3510      );
3511  }
3512  
3513  /**
3514   * Finds and exports data on pending group invitations received by a user associated with an email address.
3515   *
3516   * @since 4.0.0
3517   *
3518   * @param string $email_address  The user's email address.
3519   * @param int    $page           Batch number.
3520   * @return array An array of personal data.
3521   */
3522  function bp_groups_pending_received_invitations_personal_data_exporter( $email_address, $page ) {
3523      $number = 20;
3524  
3525      $email_address = trim( $email_address );
3526  
3527      $data_to_export = array();
3528  
3529      $user = get_user_by( 'email', $email_address );
3530  
3531      if ( ! $user ) {
3532          return array(
3533              'data' => array(),
3534              'done' => true,
3535          );
3536      }
3537  
3538      $invitations = groups_get_invites( array(
3539          'user_id'  => $user->ID,
3540          'page'     => $page,
3541          'per_page' => $number,
3542      ) );
3543  
3544      foreach ( $invitations as $invitation ) {
3545          $group = groups_get_group( $invitation->item_id );
3546  
3547          $item_data = array(
3548              array(
3549                  'name'  => __( 'Group Name', 'buddypress' ),
3550                  'value' => bp_get_group_name( $group ),
3551              ),
3552              array(
3553                  'name'  => __( 'Group URL', 'buddypress' ),
3554                  'value' => bp_get_group_permalink( $group ),
3555              ),
3556              array(
3557                  'name'  => __( 'Invited By', 'buddypress' ),
3558                  'value' => bp_core_get_userlink( $invitation->inviter_id ),
3559              ),
3560              array(
3561                  'name'  => __( 'Date Sent', 'buddypress' ),
3562                  'value' => $invitation->date_modified,
3563              ),
3564          );
3565  
3566          $data_to_export[] = array(
3567              'group_id'    => 'bp_groups_pending_received_invitations',
3568              'group_label' => __( 'Pending Group Invitations (Received)', 'buddypress' ),
3569              'item_id'     => "bp-group-pending-received-invitation-{$group->id}",
3570              'data'        => $item_data,
3571          );
3572      }
3573  
3574      // Tell core if we have more items to process.
3575      $done = count( $invitations ) < $number;
3576  
3577      return array(
3578          'data' => $data_to_export,
3579          'done' => $done,
3580      );
3581  }
3582  
3583  /**
3584   * Migrate invitations and requests from pre-5.0 group_members table to invitations table.
3585   *
3586   * @since 5.0.0
3587   */
3588  function bp_groups_migrate_invitations() {
3589      global $wpdb;
3590      $bp = buddypress();
3591  
3592      $records = $wpdb->get_results( "SELECT id, group_id, user_id, inviter_id, date_modified, comments, invite_sent FROM {$bp->groups->table_name_members} WHERE is_confirmed = 0 AND is_banned = 0" );
3593      if ( empty( $records ) ) {
3594          return;
3595      }
3596  
3597      $processed = array();
3598      $values = array();
3599      foreach ( $records as $record ) {
3600          $values[] = $wpdb->prepare(
3601              "(%d, %d, %s, %s, %d, %d, %s, %s, %s, %d, %d)",
3602              (int) $record->user_id,
3603              (int) $record->inviter_id,
3604              '',
3605              'bp_groups_invitation_manager',
3606              (int) $record->group_id,
3607              0,
3608              ( 0 === (int) $record->inviter_id ) ? 'request' : 'invite',
3609              $record->comments,
3610              $record->date_modified,
3611              (int) $record->invite_sent,
3612              0
3613          );
3614          $processed[] = (int) $record->id;
3615      }
3616  
3617      $table_name = BP_Invitation_Manager::get_table_name();
3618      $query = "INSERT INTO {$table_name} (user_id, inviter_id, invitee_email, class, item_id, secondary_item_id, type, content, date_modified, invite_sent, accepted) VALUES ";
3619      $query .= implode(', ', $values );
3620      $query .= ';';
3621      $wpdb->query( $query );
3622  
3623      $ids_to_delete = implode( ',', $processed );
3624      if ( $ids_to_delete ) {
3625          $wpdb->query( "DELETE FROM {$bp->groups->table_name_members} WHERE ID IN ($ids_to_delete)" );
3626      }
3627  }
3628  
3629  /**
3630   * Register a new Group Extension.
3631   *
3632   * @since 1.1.0
3633   * @since 10.0.0 The function was moved from the `/bp-groups/classes/class-bp-group-extension.php` file.
3634   *               It only registers Group Extensions if their corresponding class name has not been already
3635   *               registered.
3636   *
3637   * @param string $group_extension_class Name of the Extension class.
3638   * @return bool                         Returns true on success, otherwise false.
3639   */
3640  function bp_register_group_extension( $group_extension_class = '' ) {
3641      if ( ! class_exists( $group_extension_class ) ) {
3642          return false;
3643      }
3644  
3645      $bp = buddypress();
3646  
3647      if ( isset( $bp->groups->group_extensions[ $group_extension_class ] ) ) {
3648          return false;
3649      }
3650  
3651      // Add the new Group extension to the registered ones.
3652      $bp->groups->group_extensions[ $group_extension_class ] = true;
3653  
3654      return true;
3655  }
3656  
3657  /**
3658   * Init Registered Group Extensions.
3659   *
3660   * @since 10.0.0
3661   */
3662  function bp_init_group_extensions() {
3663      $registered_group_extensions = buddypress()->groups->group_extensions;
3664  
3665      if ( ! $registered_group_extensions ) {
3666          return;
3667      }
3668  
3669      foreach ( array_keys( $registered_group_extensions ) as $group_extension_class ) {
3670          $extension = new $group_extension_class;
3671  
3672          add_action( 'bp_actions', array( &$extension, '_register' ), 8 );
3673          add_action( 'admin_init', array( &$extension, '_register' ) );
3674      }
3675  }
3676  add_action( 'bp_init', 'bp_init_group_extensions', 11 );


Generated: Tue Sep 21 01:01:37 2021 Cross-referenced by PHPXref 0.7.1