[ Index ]

PHP Cross Reference of BuddyPress

title

Body

[close]

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

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


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