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


Generated: Thu May 13 01:01:37 2021 Cross-referenced by PHPXref 0.7.1