[ Index ]

PHP Cross Reference of BuddyPress

title

Body

[close]

/src/bp-groups/classes/ -> class-bp-groups-group.php (source)

   1  <?php
   2  /**
   3   * BuddyPress Groups Classes.
   4   *
   5   * @package BuddyPress
   6   * @subpackage GroupsClasses
   7   * @since 1.0.0
   8   */
   9  
  10  // Exit if accessed directly.
  11  defined( 'ABSPATH' ) || exit;
  12  
  13  /**
  14   * BuddyPress Group object.
  15   *
  16   * @since 1.6.0
  17   */
  18  class BP_Groups_Group {
  19  
  20      /**
  21       * ID of the group.
  22       *
  23       * @since 1.6.0
  24       * @var int
  25       */
  26      public $id;
  27  
  28      /**
  29       * User ID of the group's creator.
  30       *
  31       * @since 1.6.0
  32       * @var int
  33       */
  34      public $creator_id;
  35  
  36      /**
  37       * Name of the group.
  38       *
  39       * @since 1.6.0
  40       * @var string
  41       */
  42      public $name;
  43  
  44      /**
  45       * Group slug.
  46       *
  47       * @since 1.6.0
  48       * @var string
  49       */
  50      public $slug;
  51  
  52      /**
  53       * Group description.
  54       *
  55       * @since 1.6.0
  56       * @var string
  57       */
  58      public $description;
  59  
  60      /**
  61       * Group status.
  62       *
  63       * Core statuses are 'public', 'private', and 'hidden'.
  64       *
  65       * @since 1.6.0
  66       * @var string
  67       */
  68      public $status;
  69  
  70      /**
  71       * Parent ID.
  72       *
  73       * ID of parent group, if applicable.
  74       *
  75       * @since 2.7.0
  76       * @var int
  77       */
  78      public $parent_id;
  79  
  80      /**
  81       * Controls whether the group has a forum enabled.
  82       *
  83       * @since 1.6.0
  84       * @since 3.0.0 Previously, this referred to Legacy Forums. It's still used by bbPress 2 for integration.
  85       *
  86       * @var int
  87       */
  88      public $enable_forum;
  89  
  90      /**
  91       * Date the group was created.
  92       *
  93       * @since 1.6.0
  94       * @var string
  95       */
  96      public $date_created;
  97  
  98      /**
  99       * Data about the group's admins.
 100       *
 101       * @since 1.6.0
 102       * @var array
 103       */
 104      protected $admins;
 105  
 106      /**
 107       * Data about the group's moderators.
 108       *
 109       * @since 1.6.0
 110       * @var array
 111       */
 112      protected $mods;
 113  
 114      /**
 115       * Total count of group members.
 116       *
 117       * @since 1.6.0
 118       * @var int
 119       */
 120      protected $total_member_count;
 121  
 122      /**
 123       * Is the current user a member of this group?
 124       *
 125       * @since 1.2.0
 126       * @var bool
 127       */
 128      protected $is_member;
 129  
 130      /**
 131       * Is the current user a member of this group?
 132       * Alias of $is_member for backward compatibility.
 133       *
 134       * @since 2.9.0
 135       * @var bool
 136       */
 137      protected $is_user_member;
 138  
 139      /**
 140       * Does the current user have an outstanding invitation to this group?
 141       *
 142       * @since 1.9.0
 143       * @var bool
 144       */
 145      protected $is_invited;
 146  
 147      /**
 148       * Does the current user have a pending membership request to this group?
 149       *
 150       * @since 1.9.0
 151       * @var bool
 152       */
 153      protected $is_pending;
 154  
 155      /**
 156       * Timestamp of the last activity that happened in this group.
 157       *
 158       * @since 1.2.0
 159       * @var string
 160       */
 161      protected $last_activity;
 162  
 163      /**
 164       * If this is a private or hidden group, does the current user have access?
 165       *
 166       * @since 1.6.0
 167       * @var bool
 168       */
 169      protected $user_has_access;
 170  
 171      /**
 172       * Can the current user know that this group exists?
 173       *
 174       * @since 2.9.0
 175       * @var bool
 176       */
 177      protected $is_visible;
 178  
 179      /**
 180       * Raw arguments passed to the constructor.
 181       *
 182       * Not currently used by BuddyPress.
 183       *
 184       * @since 2.0.0
 185       * @var array
 186       */
 187      public $args;
 188  
 189      /**
 190       * Constructor method.
 191       *
 192       * @since 1.6.0
 193       *
 194       * @param int|null $id   Optional. If the ID of an existing group is provided,
 195       *                       the object will be pre-populated with info about that group.
 196       * @param array    $args {
 197       *     Array of optional arguments.
 198       *     @type bool $populate_extras Deprecated.
 199       * }
 200       */
 201  	public function __construct( $id = null, $args = array() ) {
 202  
 203          // Deprecated notice about $args.
 204          if ( ! empty( $args ) ) {
 205              _deprecated_argument(
 206                  __METHOD__,
 207                  '1.6.0',
 208                  sprintf(
 209                      /* translators: 1: the name of the method. 2: the name of the file. */
 210                      esc_html__( '%1$s no longer accepts arguments. See the inline documentation at %2$s for more details.', 'buddypress' ),
 211                      __METHOD__,
 212                      __FILE__
 213                  )
 214              );
 215          }
 216  
 217          if ( ! empty( $id ) ) {
 218              $this->id = (int) $id;
 219              $this->populate();
 220          }
 221      }
 222  
 223      /**
 224       * Set up data about the current group.
 225       *
 226       * @since 1.6.0
 227       */
 228  	public function populate() {
 229          global $wpdb;
 230  
 231          // Get BuddyPress.
 232          $bp    = buddypress();
 233  
 234          // Check cache for group data.
 235          $group = wp_cache_get( $this->id, 'bp_groups' );
 236  
 237          // Cache missed, so query the DB.
 238          if ( false === $group ) {
 239              $group = $wpdb->get_row( $wpdb->prepare( "SELECT g.* FROM {$bp->groups->table_name} g WHERE g.id = %d", $this->id ) );
 240  
 241              wp_cache_set( $this->id, $group, 'bp_groups' );
 242          }
 243  
 244          // No group found so set the ID and bail.
 245          if ( empty( $group ) || is_wp_error( $group ) ) {
 246              $this->id = 0;
 247              return;
 248          }
 249  
 250          // Group found so setup the object variables.
 251          $this->id           = (int) $group->id;
 252          $this->creator_id   = (int) $group->creator_id;
 253          $this->name         = stripslashes( $group->name );
 254          $this->slug         = $group->slug;
 255          $this->description  = stripslashes( $group->description );
 256          $this->status       = $group->status;
 257          $this->parent_id    = (int) $group->parent_id;
 258          $this->enable_forum = (int) $group->enable_forum;
 259          $this->date_created = $group->date_created;
 260      }
 261  
 262      /**
 263       * Save the current group to the database.
 264       *
 265       * @since 1.6.0
 266       *
 267       * @return bool True on success, false on failure.
 268       */
 269  	public function save() {
 270          global $wpdb;
 271  
 272          $bp = buddypress();
 273  
 274          $this->creator_id   = apply_filters( 'groups_group_creator_id_before_save',   $this->creator_id,   $this->id );
 275          $this->name         = apply_filters( 'groups_group_name_before_save',         $this->name,         $this->id );
 276          $this->slug         = apply_filters( 'groups_group_slug_before_save',         $this->slug,         $this->id );
 277          $this->description  = apply_filters( 'groups_group_description_before_save',  $this->description,  $this->id );
 278          $this->status       = apply_filters( 'groups_group_status_before_save',       $this->status,       $this->id );
 279          $this->parent_id    = apply_filters( 'groups_group_parent_id_before_save',    $this->parent_id,    $this->id );
 280          $this->enable_forum = apply_filters( 'groups_group_enable_forum_before_save', $this->enable_forum, $this->id );
 281          $this->date_created = apply_filters( 'groups_group_date_created_before_save', $this->date_created, $this->id );
 282  
 283          /**
 284           * Fires before the current group item gets saved.
 285           *
 286           * Please use this hook to filter the properties above. Each part will be passed in.
 287           *
 288           * @since 1.0.0
 289           *
 290           * @param BP_Groups_Group $this Current instance of the group item being saved. Passed by reference.
 291           */
 292          do_action_ref_array( 'groups_group_before_save', array( &$this ) );
 293  
 294          // Groups need at least a name.
 295          if ( empty( $this->name ) ) {
 296              return false;
 297          }
 298  
 299          // Set slug with group title if not passed.
 300          if ( empty( $this->slug ) ) {
 301              $this->slug = sanitize_title( $this->name );
 302          }
 303  
 304          // Sanity check.
 305          if ( empty( $this->slug ) ) {
 306              return false;
 307          }
 308  
 309          // Check for slug conflicts if creating new group.
 310          if ( empty( $this->id ) ) {
 311              $this->slug = groups_check_slug( $this->slug );
 312          }
 313  
 314          if ( !empty( $this->id ) ) {
 315              $sql = $wpdb->prepare(
 316                  "UPDATE {$bp->groups->table_name} SET
 317                      creator_id = %d,
 318                      name = %s,
 319                      slug = %s,
 320                      description = %s,
 321                      status = %s,
 322                      parent_id = %d,
 323                      enable_forum = %d,
 324                      date_created = %s
 325                  WHERE
 326                      id = %d
 327                  ",
 328                      $this->creator_id,
 329                      $this->name,
 330                      $this->slug,
 331                      $this->description,
 332                      $this->status,
 333                      $this->parent_id,
 334                      $this->enable_forum,
 335                      $this->date_created,
 336                      $this->id
 337              );
 338          } else {
 339              $sql = $wpdb->prepare(
 340                  "INSERT INTO {$bp->groups->table_name} (
 341                      creator_id,
 342                      name,
 343                      slug,
 344                      description,
 345                      status,
 346                      parent_id,
 347                      enable_forum,
 348                      date_created
 349                  ) VALUES (
 350                      %d, %s, %s, %s, %s, %d, %d, %s
 351                  )",
 352                      $this->creator_id,
 353                      $this->name,
 354                      $this->slug,
 355                      $this->description,
 356                      $this->status,
 357                      $this->parent_id,
 358                      $this->enable_forum,
 359                      $this->date_created
 360              );
 361          }
 362  
 363          if ( false === $wpdb->query($sql) )
 364              return false;
 365  
 366          if ( empty( $this->id ) )
 367              $this->id = $wpdb->insert_id;
 368  
 369          /**
 370           * Fires after the current group item has been saved.
 371           *
 372           * @since 1.0.0
 373           *
 374           * @param BP_Groups_Group $this Current instance of the group item that was saved. Passed by reference.
 375           */
 376          do_action_ref_array( 'groups_group_after_save', array( &$this ) );
 377  
 378          wp_cache_delete( $this->id, 'bp_groups' );
 379  
 380          return true;
 381      }
 382  
 383      /**
 384       * Delete the current group.
 385       *
 386       * @since 1.6.0
 387       *
 388       * @return bool True on success, false on failure.
 389       */
 390  	public function delete() {
 391          global $wpdb;
 392  
 393          // Delete groupmeta for the group.
 394          groups_delete_groupmeta( $this->id );
 395  
 396          // Fetch the user IDs of all the members of the group.
 397          $user_ids    = BP_Groups_Member::get_group_member_ids( $this->id );
 398          $user_id_str = esc_sql( implode( ',', wp_parse_id_list( $user_ids ) ) );
 399  
 400          // Modify group count usermeta for members.
 401          $wpdb->query( "UPDATE {$wpdb->usermeta} SET meta_value = meta_value - 1 WHERE meta_key = 'total_group_count' AND user_id IN ( {$user_id_str} )" );
 402  
 403          // Now delete all group member entries.
 404          BP_Groups_Member::delete_all( $this->id );
 405  
 406          /**
 407           * Fires before the deletion of a group.
 408           *
 409           * @since 1.2.0
 410           *
 411           * @param BP_Groups_Group $this     Current instance of the group item being deleted. Passed by reference.
 412           * @param array           $user_ids Array of user IDs that were members of the group.
 413           */
 414          do_action_ref_array( 'bp_groups_delete_group', array( &$this, $user_ids ) );
 415  
 416          wp_cache_delete( $this->id, 'bp_groups' );
 417  
 418          $bp = buddypress();
 419  
 420          // Finally remove the group entry from the DB.
 421          if ( !$wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->groups->table_name} WHERE id = %d", $this->id ) ) )
 422              return false;
 423  
 424          return true;
 425      }
 426  
 427      /**
 428       * Magic getter.
 429       *
 430       * @since 2.7.0
 431       *
 432       * @param string $key Property name.
 433       * @return mixed
 434       */
 435  	public function __get( $key ) {
 436          switch ( $key ) {
 437              case 'last_activity' :
 438              case 'total_member_count' :
 439              case 'forum_id' :
 440                  $retval = groups_get_groupmeta( $this->id, $key );
 441  
 442                  if ( 'last_activity' !== $key ) {
 443                      $retval = (int) $retval;
 444                  }
 445  
 446                  return $retval;
 447  
 448              case 'admins' :
 449                  return $this->get_admins();
 450  
 451              case 'mods' :
 452                  return $this->get_mods();
 453  
 454              case 'is_member' :
 455              case 'is_user_member' :
 456                  return $this->get_is_member();
 457  
 458              case 'is_invited' :
 459                  return groups_check_user_has_invite( bp_loggedin_user_id(), $this->id );
 460  
 461              case 'is_pending' :
 462                  return groups_check_for_membership_request( bp_loggedin_user_id(), $this->id );
 463  
 464              case 'user_has_access' :
 465                  return $this->get_user_has_access();
 466  
 467              case 'is_visible' :
 468                  return $this->is_visible();
 469  
 470              default :
 471                  return isset( $this->{$key} ) ? $this->{$key} : null;
 472          }
 473      }
 474  
 475      /**
 476       * Magic issetter.
 477       *
 478       * Used to maintain backward compatibility for properties that are now
 479       * accessible only via magic method.
 480       *
 481       * @since 2.7.0
 482       *
 483       * @param string $key Property name.
 484       * @return bool
 485       */
 486  	public function __isset( $key ) {
 487          switch ( $key ) {
 488              case 'admins' :
 489              case 'is_invited' :
 490              case 'is_member' :
 491              case 'is_user_member' :
 492              case 'is_pending' :
 493              case 'last_activity' :
 494              case 'mods' :
 495              case 'total_member_count' :
 496              case 'user_has_access' :
 497              case 'is_visible' :
 498              case 'forum_id' :
 499                  return true;
 500  
 501              default :
 502                  return isset( $this->{$key} );
 503          }
 504      }
 505  
 506      /**
 507       * Magic setter.
 508       *
 509       * Used to maintain backward compatibility for properties that are now
 510       * accessible only via magic method.
 511       *
 512       * @since 2.7.0
 513       *
 514       * @param string $key   Property name.
 515       * @param mixed  $value Property value.
 516       * @return bool
 517       */
 518  	public function __set( $key, $value ) {
 519          switch ( $key ) {
 520              case 'user_has_access' :
 521                  return $this->user_has_access = (bool) $value;
 522  
 523              default :
 524                  $this->{$key} = $value;
 525          }
 526      }
 527  
 528      /**
 529       * Get a list of the group's admins.
 530       *
 531       * Used to provide cache-friendly access to the 'admins' property of
 532       * the group object.
 533       *
 534       * @since 2.7.0
 535       *
 536       * @return array|null
 537       */
 538  	protected function get_admins() {
 539          if ( isset( $this->admins ) ) {
 540              return $this->admins;
 541          }
 542  
 543          $this->set_up_admins_and_mods();
 544          return $this->admins;
 545      }
 546  
 547      /**
 548       * Get a list of the group's mods.
 549       *
 550       * Used to provide cache-friendly access to the 'mods' property of
 551       * the group object.
 552       *
 553       * @since 2.7.0
 554       *
 555       * @return array|null
 556       */
 557  	protected function get_mods() {
 558          if ( isset( $this->mods ) ) {
 559              return $this->mods;
 560          }
 561  
 562          $this->set_up_admins_and_mods();
 563          return $this->mods;
 564      }
 565  
 566      /**
 567       * Set up admins and mods for the current group object.
 568       *
 569       * Called only when the 'admins' or 'mods' property is accessed.
 570       *
 571       * @since 2.7.0
 572       */
 573  	protected function set_up_admins_and_mods() {
 574          $admin_ids = BP_Groups_Member::get_group_administrator_ids( $this->id );
 575          $admin_ids_plucked = wp_list_pluck( $admin_ids, 'user_id' );
 576  
 577          $mod_ids = BP_Groups_Member::get_group_moderator_ids( $this->id );
 578          $mod_ids_plucked = wp_list_pluck( $mod_ids, 'user_id' );
 579  
 580          $admin_mod_ids = array_merge( $admin_ids_plucked, $mod_ids_plucked );
 581          $admin_mod_users = array();
 582  
 583          if ( ! empty( $admin_mod_ids ) ) {
 584              $admin_mod_users = get_users( array(
 585                  'include' => $admin_mod_ids,
 586                  'blog_id' => null,
 587              ) );
 588          }
 589  
 590          $admin_objects = $mod_objects = array();
 591          foreach ( $admin_mod_users as $admin_mod_user ) {
 592              $obj = new stdClass();
 593              $obj->user_id = $admin_mod_user->ID;
 594              $obj->user_login = $admin_mod_user->user_login;
 595              $obj->user_email = $admin_mod_user->user_email;
 596              $obj->user_nicename = $admin_mod_user->user_nicename;
 597  
 598              if ( in_array( $admin_mod_user->ID, $admin_ids_plucked, true ) ) {
 599                  $obj->is_admin = 1;
 600                  $obj->is_mod = 0;
 601                  $admin_objects[] = $obj;
 602              } else {
 603                  $obj->is_admin = 0;
 604                  $obj->is_mod = 1;
 605                  $mod_objects[] = $obj;
 606              }
 607          }
 608  
 609          $this->admins = $admin_objects;
 610          $this->mods   = $mod_objects;
 611      }
 612  
 613      /**
 614       * Checks whether the logged-in user is a member of the group.
 615       *
 616       * @since 2.7.0
 617       *
 618       * @return bool|int
 619       */
 620  	protected function get_is_member() {
 621          if ( isset( $this->is_member ) ) {
 622              return $this->is_member;
 623          }
 624  
 625          $this->is_member = groups_is_user_member( bp_loggedin_user_id(), $this->id );
 626          return $this->is_member;
 627      }
 628  
 629      /**
 630       * Checks whether the logged-in user has access to the group.
 631       *
 632       * @since 2.7.0
 633       *
 634       * @return bool
 635       */
 636  	protected function get_user_has_access() {
 637          if ( isset( $this->user_has_access ) ) {
 638              return $this->user_has_access;
 639          }
 640  
 641          if ( ( 'private' === $this->status ) || ( 'hidden' === $this->status ) ) {
 642  
 643              // Assume user does not have access to hidden/private groups.
 644              $this->user_has_access = false;
 645  
 646              // Group members or community moderators have access.
 647              if ( ( is_user_logged_in() && $this->get_is_member() ) || bp_current_user_can( 'bp_moderate' ) ) {
 648                  $this->user_has_access = true;
 649              }
 650          } else {
 651              $this->user_has_access = true;
 652          }
 653  
 654          return $this->user_has_access;
 655      }
 656  
 657      /**
 658       * Checks whether the current user can know the group exists.
 659       *
 660       * @since 2.9.0
 661       *
 662       * @return bool
 663       */
 664  	protected function is_visible() {
 665          if ( isset( $this->is_visible ) ) {
 666              return $this->is_visible;
 667          }
 668  
 669          if ( 'hidden' === $this->status ) {
 670  
 671              // Assume user can not know about hidden groups.
 672              $this->is_visible = false;
 673  
 674              // Group members or community moderators have access.
 675              if ( ( is_user_logged_in() && $this->get_is_member() ) || bp_current_user_can( 'bp_moderate' ) ) {
 676                  $this->is_visible = true;
 677              }
 678          } else {
 679              $this->is_visible = true;
 680          }
 681  
 682          return $this->is_visible;
 683      }
 684  
 685      /** Static Methods ****************************************************/
 686  
 687      /**
 688       * Get whether a group exists for a given slug.
 689       *
 690       * @since 1.6.0
 691       * @since 10.0.0 Updated to add the deprecated notice.
 692       *
 693       * @param string      $slug       Slug to check.
 694       * @param string|bool $table_name Deprecated.
 695       * @return int|null|bool False if empty slug, group ID if found; `null` if not.
 696       */
 697  	public static function group_exists( $slug, $table_name = false ) {
 698  
 699          if ( false !== $table_name ) {
 700              _deprecated_argument(
 701                  __METHOD__,
 702                  '1.6.0',
 703                  sprintf(
 704                      /* translators: 1: the name of the method. 2: the name of the file. */
 705                      esc_html__( '%1$s no longer accepts a table name argument. See the inline documentation at %2$s for more details.', 'buddypress' ),
 706                      __METHOD__,
 707                      __FILE__
 708                  )
 709              );
 710          }
 711  
 712          if ( empty( $slug ) ) {
 713              return false;
 714          }
 715  
 716          $groups = self::get(
 717              array(
 718                  'slug'              => $slug,
 719                  'per_page'          => 1,
 720                  'page'              => 1,
 721                  'update_meta_cache' => false,
 722                  'show_hidden'       => true,
 723              )
 724          );
 725  
 726          $group_id = null;
 727          if ( $groups['groups'] ) {
 728              $group_id = current( $groups['groups'] )->id;
 729          }
 730  
 731          return $group_id;
 732      }
 733  
 734      /**
 735       * Get the ID of a group by the group's slug.
 736       *
 737       * Alias of {@link BP_Groups_Group::group_exists()}.
 738       *
 739       * @since 1.6.0
 740       *
 741       * @param string $slug See {@link BP_Groups_Group::group_exists()}.
 742       * @return int|null|bool See {@link BP_Groups_Group::group_exists()}.
 743       */
 744  	public static function get_id_from_slug( $slug ) {
 745          return self::group_exists( $slug );
 746      }
 747  
 748      /**
 749       * Get whether a group exists for an old slug.
 750       *
 751       * @since 2.9.0
 752       *
 753       * @param string      $slug       Slug to check.
 754       *
 755       * @return int|null|false Group ID if found; null if not; false if missing parameters.
 756       */
 757  	public static function get_id_by_previous_slug( $slug ) {
 758          global $wpdb;
 759  
 760          if ( empty( $slug ) ) {
 761              return false;
 762          }
 763  
 764          $args = array(
 765              'meta_query'         => array(
 766                  array(
 767                      'key'   => 'previous_slug',
 768                      'value' => $slug
 769                  ),
 770              ),
 771              'orderby'            => 'meta_id',
 772              'order'              => 'DESC',
 773              'per_page'           => 1,
 774              'page'               => 1,
 775              'update_meta_cache'  => false,
 776              'show_hidden'        => true,
 777          );
 778          $groups = BP_Groups_Group::get( $args );
 779  
 780          $group_id = null;
 781          if ( $groups['groups'] ) {
 782              $group_id = current( $groups['groups'] )->id;
 783          }
 784  
 785          return $group_id;
 786      }
 787  
 788      /**
 789       * Get IDs of users with outstanding invites to a given group from a specified user.
 790       *
 791       * @since 1.6.0
 792       * @since 2.9.0 Added $sent as a parameter.
 793       *
 794       * @param  int      $user_id  ID of the inviting user.
 795       * @param  int      $group_id ID of the group.
 796       * @param  int|null $sent     Query for a specific invite sent status. If 0, this will query for users
 797       *                            that haven't had an invite sent to them yet. If 1, this will query for
 798       *                            users that have had an invite sent to them. If null, no invite status will
 799       *                            queried. Default: null.
 800       * @return array    IDs of users who have been invited to the group by the user but have not
 801       *                  yet accepted.
 802       */
 803  	public static function get_invites( $user_id, $group_id, $sent = null ) {
 804          if ( 0 === $sent ) {
 805              $sent_arg = 'draft';
 806          } else if ( 1 === $sent ) {
 807              $sent_arg = 'sent';
 808          } else {
 809              $sent_arg = 'all';
 810          }
 811  
 812          return groups_get_invites( array(
 813              'item_id'     => $group_id,
 814              'inviter_id'  => $user_id,
 815              'invite_sent' => $sent_arg,
 816              'fields'      => 'user_ids',
 817          ) );
 818      }
 819  
 820      /**
 821       * Get a list of a user's groups, filtered by a search string.
 822       *
 823       * @since 1.6.0
 824       *
 825       * @param string   $filter  Search term. Matches against 'name' and
 826       *                          'description' fields.
 827       * @param int      $user_id ID of the user whose groups are being searched.
 828       *                          Default: the displayed user.
 829       * @param mixed    $order   Not used.
 830       * @param int|null $limit   Optional. The max number of results to return.
 831       *                          Default: null (no limit).
 832       * @param int|null $page    Optional. The page offset of results to return.
 833       *                          Default: null (no limit).
 834       * @return false|array {
 835       *     @type array $groups Array of matched and paginated group IDs.
 836       *     @type int   $total  Total count of groups matching the query.
 837       * }
 838       */
 839  	public static function filter_user_groups( $filter, $user_id = 0, $order = false, $limit = null, $page = null ) {
 840          if ( empty( $user_id ) ) {
 841              $user_id = bp_displayed_user_id();
 842          }
 843  
 844          $args = array(
 845              'search_terms' => $filter,
 846              'user_id'      => $user_id,
 847              'per_page'     => $limit,
 848              'page'         => $page,
 849              'order'        => $order,
 850          );
 851  
 852          $groups = BP_Groups_Group::get( $args );
 853  
 854          // Modify the results to match the old format.
 855          $paged_groups = array();
 856          $i = 0;
 857          foreach ( $groups['groups'] as $group ) {
 858              $paged_groups[ $i ] = new stdClass;
 859              $paged_groups[ $i ]->group_id = $group->id;
 860              $i++;
 861          }
 862  
 863          return array( 'groups' => $paged_groups, 'total' => $groups['total'] );
 864      }
 865  
 866      /**
 867       * Get a list of groups, filtered by a search string.
 868       *
 869       * @since 1.6.0
 870       *
 871       * @param string      $filter  Search term. Matches against 'name' and
 872       *                             'description' fields.
 873       * @param int|null    $limit   Optional. The max number of results to return.
 874       *                             Default: null (no limit).
 875       * @param int|null    $page    Optional. The page offset of results to return.
 876       *                             Default: null (no limit).
 877       * @param string|bool $sort_by Column to sort by. Default: false (default
 878       *        sort).
 879       * @param string|bool $order   ASC or DESC. Default: false (default sort).
 880       * @return array {
 881       *     @type array $groups Array of matched and paginated group IDs.
 882       *     @type int   $total  Total count of groups matching the query.
 883       * }
 884       */
 885  	public static function search_groups( $filter, $limit = null, $page = null, $sort_by = false, $order = false ) {
 886          $args = array(
 887              'search_terms' => $filter,
 888              'per_page'     => $limit,
 889              'page'         => $page,
 890              'orderby'      => $sort_by,
 891              'order'        => $order,
 892          );
 893  
 894          $groups = BP_Groups_Group::get( $args );
 895  
 896          // Modify the results to match the old format.
 897          $paged_groups = array();
 898          $i = 0;
 899          foreach ( $groups['groups'] as $group ) {
 900              $paged_groups[ $i ] = new stdClass;
 901              $paged_groups[ $i ]->group_id = $group->id;
 902              $i++;
 903          }
 904  
 905          return array( 'groups' => $paged_groups, 'total' => $groups['total'] );
 906      }
 907  
 908      /**
 909       * Check for the existence of a slug.
 910       *
 911       * @since 1.6.0
 912       *
 913       * @param string $slug Slug to check.
 914       * @return string|null The slug, if found. Otherwise null.
 915       */
 916  	public static function check_slug( $slug ) {
 917          global $wpdb;
 918  
 919          $bp = buddypress();
 920  
 921          return $wpdb->get_var( $wpdb->prepare( "SELECT slug FROM {$bp->groups->table_name} WHERE slug = %s", $slug ) );
 922      }
 923  
 924      /**
 925       * Get the slug for a given group ID.
 926       *
 927       * @since 1.6.0
 928       *
 929       * @param int $group_id ID of the group.
 930       * @return string|null The slug, if found. Otherwise null.
 931       */
 932  	public static function get_slug( $group_id ) {
 933          global $wpdb;
 934  
 935          $bp = buddypress();
 936  
 937          return $wpdb->get_var( $wpdb->prepare( "SELECT slug FROM {$bp->groups->table_name} WHERE id = %d", $group_id ) );
 938      }
 939  
 940      /**
 941       * Check whether a given group has any members.
 942       *
 943       * @since 1.6.0
 944       *
 945       * @param int $group_id ID of the group.
 946       * @return bool True if the group has members, otherwise false.
 947       */
 948  	public static function has_members( $group_id ) {
 949          global $wpdb;
 950  
 951          $bp = buddypress();
 952  
 953          $members = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(id) FROM {$bp->groups->table_name_members} WHERE group_id = %d", $group_id ) );
 954  
 955          if ( empty( $members ) )
 956              return false;
 957  
 958          return true;
 959      }
 960  
 961      /**
 962       * Check whether a group has outstanding membership requests.
 963       *
 964       * @since 1.6.0
 965       *
 966       * @param int $group_id ID of the group.
 967       * @return int|null The number of outstanding requests, or null if
 968       *                  none are found.
 969       */
 970  	public static function has_membership_requests( $group_id ) {
 971          global $wpdb;
 972  
 973          $bp = buddypress();
 974  
 975          return $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(id) FROM {$bp->groups->table_name_members} WHERE group_id = %d AND is_confirmed = 0", $group_id ) );
 976      }
 977  
 978      /**
 979       * Get outstanding membership requests for a group.
 980       *
 981       * @since 1.6.0
 982       *
 983       * @param int      $group_id ID of the group.
 984       * @param int|null $limit    Optional. Max number of results to return.
 985       *                           Default: null (no limit).
 986       * @param int|null $page     Optional. Page offset of results returned. Default:
 987       *                           null (no limit).
 988       * @return array {
 989       *     @type array $requests The requested page of located requests.
 990       *     @type int   $total    Total number of requests outstanding for the
 991       *                           group.
 992       * }
 993       */
 994  	public static function get_membership_requests( $group_id, $limit = null, $page = null ) {
 995          $args = array(
 996              'item_id' => $group_id
 997          );
 998          if ( $limit ) {
 999              $args['per_page'] = $limit;
1000          }
1001          if ( $page ) {
1002              $args['page'] = $page;
1003          }
1004  
1005          $requests = groups_get_requests( $args );
1006          $total    = count( groups_get_membership_requested_user_ids( $group_id ) );
1007  
1008          return array( 'requests' => $requests, 'total' => $total );
1009      }
1010  
1011      /**
1012       * Query for groups.
1013       *
1014       * @see WP_Meta_Query::queries for a description of the 'meta_query'
1015       *      parameter format.
1016       *
1017       * @since 1.6.0
1018       * @since 2.6.0 Added `$group_type`, `$group_type__in`, and `$group_type__not_in` parameters.
1019       * @since 2.7.0 Added `$update_admin_cache` and `$parent_id` parameters.
1020       * @since 2.8.0 Changed `$search_terms` parameter handling and added `$search_columns` parameter.
1021       * @since 2.9.0 Added `$slug` parameter.
1022       *
1023       * @param array $args {
1024       *     Array of parameters. All items are optional.
1025       *     @type string       $type               Optional. Shorthand for certain orderby/order combinations.
1026       *                                            'newest', 'active', 'popular', 'alphabetical', 'random'.
1027       *                                            When present, will override orderby and order params.
1028       *                                            Default: null.
1029       *     @type string       $orderby            Optional. Property to sort by. 'date_created', 'last_activity',
1030       *                                            'total_member_count', 'name', 'random', 'meta_id'.
1031       *                                            Default: 'date_created'.
1032       *     @type string       $order              Optional. Sort order. 'ASC' or 'DESC'. Default: 'DESC'.
1033       *     @type int          $per_page           Optional. Number of items to return per page of results.
1034       *                                            Default: null (no limit).
1035       *     @type int          $page               Optional. Page offset of results to return.
1036       *                                            Default: null (no limit).
1037       *     @type int          $user_id            Optional. If provided, results will be limited to groups
1038       *                                            of which the specified user is a member. Default: null.
1039        *     @type array|string $slug               Optional. Array or comma-separated list of group slugs to limit
1040        *                                            results to.
1041       *                                            Default: false.
1042       *     @type string       $search_terms       Optional. If provided, only groups whose names or descriptions
1043       *                                            match the search terms will be returned. Allows specifying the
1044       *                                            wildcard position using a '*' character before or after the
1045       *                                            string or both. Works in concert with $search_columns.
1046       *                                            Default: false.
1047         *     @type string       $search_columns     Optional. If provided, only apply the search terms to the
1048         *                                            specified columns. Works in concert with $search_terms.
1049         *                                            Default: empty array.
1050       *     @type array|string $group_type         Array or comma-separated list of group types to limit results to.
1051       *     @type array|string $group_type__in     Array or comma-separated list of group types to limit results to.
1052       *     @type array|string $group_type__not_in Array or comma-separated list of group types that will be
1053       *                                            excluded from results.
1054       *     @type array        $meta_query         Optional. An array of meta_query conditions.
1055       *                                            See {@link WP_Meta_Query::queries} for description.
1056       *     @type array|string $value              Optional. Array or comma-separated list of group IDs. Results
1057       *                                            will be limited to groups within the list. Default: false.
1058       *     @type array|string $parent_id          Optional. Array or comma-separated list of group IDs. Results
1059       *                                            will be limited to children of the specified groups. Default: null.
1060       *     @type array|string $exclude            Optional. Array or comma-separated list of group IDs.
1061       *                                            Results will exclude the listed groups. Default: false.
1062       *     @type bool         $update_meta_cache  Whether to pre-fetch groupmeta for the returned groups.
1063       *                                            Default: true.
1064       *     @type bool         $update_admin_cache Whether to pre-fetch administrator IDs for the returned
1065       *                                            groups. Default: false.
1066       *     @type bool         $show_hidden        Whether to include hidden groups in results. Default: false.
1067        *     @type array|string $status             Optional. Array or comma-separated list of group statuses to limit
1068        *                                            results to. If specified, $show_hidden is ignored.
1069       *                                            Default: empty array.
1070        *     @type string       $fields             Which fields to return. Specify 'ids' to fetch a list of IDs.
1071        *                                            Default: 'all' (return BP_Groups_Group objects).
1072        *                                            If set, meta and admin caches will not be prefetched.
1073       * }
1074       * @return array {
1075       *     @type array $groups Array of group objects returned by the
1076       *                         paginated query. (IDs only if `fields` is set to `ids`.)
1077       *     @type int   $total  Total count of all groups matching non-
1078       *                         paginated query params.
1079       * }
1080       */
1081  	public static function get( $args = array() ) {
1082          global $wpdb;
1083  
1084          $function_args = func_get_args();
1085  
1086          // Backward compatibility with old method of passing arguments.
1087          if ( ! is_array( $args ) || count( $function_args ) > 1 ) {
1088              _deprecated_argument(
1089                  __METHOD__,
1090                  '1.7',
1091                  sprintf(
1092                      /* translators: 1: the name of the method. 2: the name of the file. */
1093                      esc_html__( 'Arguments passed to %1$s should be in an associative array. See the inline documentation at %2$s for more details.', 'buddypress' ),
1094                      __METHOD__,
1095                      __FILE__
1096                  )
1097              );
1098  
1099              $old_args_keys = array(
1100                  0 => 'type',
1101                  1 => 'per_page',
1102                  2 => 'page',
1103                  3 => 'user_id',
1104                  4 => 'search_terms',
1105                  5 => 'include',
1106                  6 => 'populate_extras',
1107                  7 => 'exclude',
1108                  8 => 'show_hidden',
1109              );
1110  
1111              $args = bp_core_parse_args_array( $old_args_keys, $function_args );
1112          }
1113  
1114          $defaults = array(
1115              'type'               => null,
1116              'orderby'            => 'date_created',
1117              'order'              => 'DESC',
1118              'per_page'           => null,
1119              'page'               => null,
1120              'user_id'            => 0,
1121              'slug'               => array(),
1122              'search_terms'       => false,
1123              'search_columns'     => array(),
1124              'group_type'         => '',
1125              'group_type__in'     => '',
1126              'group_type__not_in' => '',
1127              'meta_query'         => false,
1128              'include'            => false,
1129              'parent_id'          => null,
1130              'update_meta_cache'  => true,
1131              'update_admin_cache' => false,
1132              'exclude'            => false,
1133              'show_hidden'        => false,
1134              'status'             => array(),
1135              'fields'             => 'all',
1136          );
1137  
1138          $r = bp_parse_args(
1139              $args,
1140              $defaults,
1141              'bp_groups_group_get'
1142          );
1143  
1144          $bp = buddypress();
1145  
1146          $sql = array(
1147              'select'     => "SELECT DISTINCT g.id",
1148              'from'       => "{$bp->groups->table_name} g",
1149              'where'      => '',
1150              'orderby'    => '',
1151              'pagination' => '',
1152          );
1153  
1154          if ( ! empty( $r['user_id'] ) ) {
1155              $sql['from'] .= " JOIN {$bp->groups->table_name_members} m ON ( g.id = m.group_id )";
1156          }
1157  
1158          $where_conditions = array();
1159  
1160          if ( ! empty( $r['status'] ) ) {
1161              if ( ! is_array( $r['status'] ) ) {
1162                  $r['status'] = preg_split( '/[\s,]+/', $r['status'] );
1163              }
1164              $r['status'] = array_map( 'sanitize_title', $r['status'] );
1165              $status_in = "'" . implode( "','", $r['status'] ) . "'";
1166              $where_conditions['status'] = "g.status IN ({$status_in})";
1167          } elseif ( empty( $r['show_hidden'] ) ) {
1168              $where_conditions['hidden'] = "g.status != 'hidden'";
1169          }
1170  
1171          if ( ! empty( $r['slug'] ) ) {
1172              if ( ! is_array( $r['slug'] ) ) {
1173                  $r['slug'] = preg_split( '/[\s,]+/', $r['slug'] );
1174              }
1175              $r['slug'] = array_map( 'sanitize_title', $r['slug'] );
1176              $slug_in = "'" . implode( "','", $r['slug'] ) . "'";
1177              $where_conditions['slug'] = "g.slug IN ({$slug_in})";
1178          }
1179  
1180          $search = '';
1181          if ( isset( $r['search_terms'] ) ) {
1182              $search = trim( $r['search_terms'] );
1183          }
1184  
1185          if ( $search ) {
1186              $leading_wild = ( ltrim( $search, '*' ) != $search );
1187              $trailing_wild = ( rtrim( $search, '*' ) != $search );
1188              if ( $leading_wild && $trailing_wild ) {
1189                  $wild = 'both';
1190              } elseif ( $leading_wild ) {
1191                  $wild = 'leading';
1192              } elseif ( $trailing_wild ) {
1193                  $wild = 'trailing';
1194              } else {
1195                  // Default is to wrap in wildcard characters.
1196                  $wild = 'both';
1197              }
1198              $search = trim( $search, '*' );
1199  
1200              $searches = array();
1201              $leading_wild = ( 'leading' == $wild || 'both' == $wild ) ? '%' : '';
1202              $trailing_wild = ( 'trailing' == $wild || 'both' == $wild ) ? '%' : '';
1203              $wildcarded = $leading_wild . bp_esc_like( $search ) . $trailing_wild;
1204  
1205              $search_columns = array( 'name', 'description' );
1206              if ( $r['search_columns'] ) {
1207                  $search_columns = array_intersect( $r['search_columns'], $search_columns );
1208              }
1209  
1210              foreach ( $search_columns as $search_column ) {
1211                  $searches[] = $wpdb->prepare( "$search_column LIKE %s", $wildcarded );
1212              }
1213  
1214              $where_conditions['search'] = '(' . implode(' OR ', $searches) . ')';
1215          }
1216  
1217          $meta_query_sql = self::get_meta_query_sql( $r['meta_query'] );
1218  
1219          if ( ! empty( $meta_query_sql['join'] ) ) {
1220              $sql['from'] .= $meta_query_sql['join'];
1221          }
1222  
1223          if ( ! empty( $meta_query_sql['where'] ) ) {
1224              $where_conditions['meta'] = $meta_query_sql['where'];
1225          }
1226  
1227          // Only use 'group_type__in', if 'group_type' is not set.
1228          if ( empty( $r['group_type'] ) && ! empty( $r['group_type__in']) ) {
1229              $r['group_type'] = $r['group_type__in'];
1230          }
1231  
1232          // Group types to exclude. This has priority over inclusions.
1233          if ( ! empty( $r['group_type__not_in'] ) ) {
1234              $group_type_clause = self::get_sql_clause_for_group_types( $r['group_type__not_in'], 'NOT IN' );
1235  
1236          // Group types to include.
1237          } elseif ( ! empty( $r['group_type'] ) ) {
1238              $group_type_clause = self::get_sql_clause_for_group_types( $r['group_type'], 'IN' );
1239          }
1240  
1241          if ( ! empty( $group_type_clause ) ) {
1242              $where_conditions['group_type'] = $group_type_clause;
1243          }
1244  
1245          if ( ! empty( $r['user_id'] ) ) {
1246              $where_conditions['user'] = $wpdb->prepare( "m.user_id = %d AND m.is_confirmed = 1 AND m.is_banned = 0", $r['user_id'] );
1247          }
1248  
1249          if ( ! empty( $r['include'] ) ) {
1250              $include        = implode( ',', wp_parse_id_list( $r['include'] ) );
1251              $where_conditions['include'] = "g.id IN ({$include})";
1252          }
1253  
1254          if ( ! is_null( $r['parent_id'] ) ) {
1255              // For legacy reasons, `false` means groups with no parent.
1256              if ( false === $r['parent_id'] ) {
1257                  $parent_id = 0;
1258              } else {
1259                  $parent_id = implode( ',', wp_parse_id_list( $r['parent_id'] ) );
1260              }
1261  
1262              $where_conditions['parent_id'] = "g.parent_id IN ({$parent_id})";
1263          }
1264  
1265          if ( ! empty( $r['exclude'] ) ) {
1266              $exclude        = implode( ',', wp_parse_id_list( $r['exclude'] ) );
1267              $where_conditions['exclude'] = "g.id NOT IN ({$exclude})";
1268          }
1269  
1270          /* Order/orderby ********************************************/
1271  
1272          $order   = $r['order'];
1273          $orderby = $r['orderby'];
1274  
1275          // If a 'type' parameter was passed, parse it and overwrite
1276          // 'order' and 'orderby' params passed to the function.
1277          if (  ! empty( $r['type'] ) ) {
1278  
1279              /**
1280               * Filters the 'type' parameter used to overwrite 'order' and 'orderby' values.
1281               *
1282               * @since 2.1.0
1283               *
1284               * @param array  $value Converted 'type' value for order and orderby.
1285               * @param string $value Parsed 'type' value for the get method.
1286               */
1287              $order_orderby = apply_filters( 'bp_groups_get_orderby', self::convert_type_to_order_orderby( $r['type'] ), $r['type'] );
1288  
1289              // If an invalid type is passed, $order_orderby will be
1290              // an array with empty values. In this case, we stick
1291              // with the default values of $order and $orderby.
1292              if ( ! empty( $order_orderby['order'] ) ) {
1293                  $order = $order_orderby['order'];
1294              }
1295  
1296              if ( ! empty( $order_orderby['orderby'] ) ) {
1297                  $orderby = $order_orderby['orderby'];
1298              }
1299          }
1300  
1301          // 'total_member_count' and 'last_activity' sorts require additional table joins.
1302          if ( 'total_member_count' === $orderby ) {
1303              $sql['from'] .= " JOIN {$bp->groups->table_name_groupmeta} gm_total_member_count ON ( g.id = gm_total_member_count.group_id )";
1304              $where_conditions['total_member_count'] = "gm_total_member_count.meta_key = 'total_member_count'";
1305          } elseif ( 'last_activity' === $orderby ) {
1306  
1307              $sql['from'] .= " JOIN {$bp->groups->table_name_groupmeta} gm_last_activity on ( g.id = gm_last_activity.group_id )";
1308              $where_conditions['last_activity'] = "gm_last_activity.meta_key = 'last_activity'";
1309          }
1310  
1311          // If 'meta_id' is the requested order, and there's no meta query, fall back to the default.
1312          if ( 'meta_id' === $orderby && empty( $meta_query_sql['join'] ) ) {
1313              $orderby = 'date_created';
1314          }
1315  
1316          // Sanitize 'order'.
1317          $order = bp_esc_sql_order( $order );
1318  
1319          /**
1320           * Filters the converted 'orderby' term.
1321           *
1322           * @since 2.1.0
1323           *
1324           * @param string $value   Converted 'orderby' term.
1325           * @param string $orderby Original orderby value.
1326           * @param string $value   Parsed 'type' value for the get method.
1327           */
1328          $orderby = apply_filters( 'bp_groups_get_orderby_converted_by_term', self::convert_orderby_to_order_by_term( $orderby ), $orderby, $r['type'] );
1329  
1330          // Random order is a special case.
1331          if ( 'rand()' === $orderby ) {
1332              $sql['orderby'] = "ORDER BY rand()";
1333          } else {
1334              $sql['orderby'] = "ORDER BY {$orderby} {$order}";
1335          }
1336  
1337          if ( ! empty( $r['per_page'] ) && ! empty( $r['page'] ) && $r['per_page'] != -1 ) {
1338              $sql['pagination'] = $wpdb->prepare( "LIMIT %d, %d", intval( ( $r['page'] - 1 ) * $r['per_page']), intval( $r['per_page'] ) );
1339          }
1340  
1341          $where = '';
1342          if ( ! empty( $where_conditions ) ) {
1343              $sql['where'] = implode( ' AND ', $where_conditions );
1344              $where = "WHERE {$sql['where']}";
1345          }
1346  
1347          $paged_groups_sql = "{$sql['select']} FROM {$sql['from']} {$where} {$sql['orderby']} {$sql['pagination']}";
1348  
1349          /**
1350           * Filters the pagination SQL statement.
1351           *
1352           * @since 1.5.0
1353           *
1354           * @param string $value Concatenated SQL statement.
1355           * @param array  $sql   Array of SQL parts before concatenation.
1356           * @param array  $r     Array of parsed arguments for the get method.
1357           */
1358          $paged_groups_sql = apply_filters( 'bp_groups_get_paged_groups_sql', $paged_groups_sql, $sql, $r );
1359  
1360          $cached = bp_core_get_incremented_cache( $paged_groups_sql, 'bp_groups' );
1361          if ( false === $cached ) {
1362              $paged_group_ids = $wpdb->get_col( $paged_groups_sql );
1363              bp_core_set_incremented_cache( $paged_groups_sql, 'bp_groups', $paged_group_ids );
1364          } else {
1365              $paged_group_ids = $cached;
1366          }
1367  
1368          if ( 'ids' === $r['fields'] ) {
1369              // We only want the IDs.
1370              $paged_groups = array_map( 'intval', $paged_group_ids );
1371          } else {
1372              $uncached_group_ids = bp_get_non_cached_ids( $paged_group_ids, 'bp_groups' );
1373              if ( $uncached_group_ids ) {
1374                  $group_ids_sql = implode( ',', array_map( 'intval', $uncached_group_ids ) );
1375                  $group_data_objects = $wpdb->get_results( "SELECT g.* FROM {$bp->groups->table_name} g WHERE g.id IN ({$group_ids_sql})" );
1376                  foreach ( $group_data_objects as $group_data_object ) {
1377                      wp_cache_set( $group_data_object->id, $group_data_object, 'bp_groups' );
1378                  }
1379              }
1380  
1381              $paged_groups = array();
1382              foreach ( $paged_group_ids as $paged_group_id ) {
1383                  $paged_groups[] = new BP_Groups_Group( $paged_group_id );
1384              }
1385  
1386              $group_ids = array();
1387              foreach ( (array) $paged_groups as $group ) {
1388                  $group_ids[] = $group->id;
1389              }
1390  
1391              // Grab all groupmeta.
1392              if ( ! empty( $r['update_meta_cache'] ) ) {
1393                  bp_groups_update_meta_cache( $group_ids );
1394              }
1395  
1396              // Prefetch all administrator IDs, if requested.
1397              if ( $r['update_admin_cache'] ) {
1398                  BP_Groups_Member::prime_group_admins_mods_cache( $group_ids );
1399              }
1400  
1401              // Set up integer properties needing casting.
1402              $int_props = array(
1403                  'id', 'creator_id', 'enable_forum'
1404              );
1405  
1406              // Integer casting.
1407              foreach ( $paged_groups as $key => $g ) {
1408                  foreach ( $int_props as $int_prop ) {
1409                      $paged_groups[ $key ]->{$int_prop} = (int) $paged_groups[ $key ]->{$int_prop};
1410                  }
1411              }
1412  
1413          }
1414  
1415          // Find the total number of groups in the results set.
1416          $total_groups_sql = "SELECT COUNT(DISTINCT g.id) FROM {$sql['from']} $where";
1417  
1418          /**
1419           * Filters the SQL used to retrieve total group results.
1420           *
1421           * @since 1.5.0
1422           *
1423           * @param string $t_sql     Concatenated SQL statement used for retrieving total group results.
1424           * @param array  $total_sql Array of SQL parts for the query.
1425           * @param array  $r         Array of parsed arguments for the get method.
1426           */
1427          $total_groups_sql = apply_filters( 'bp_groups_get_total_groups_sql', $total_groups_sql, $sql, $r );
1428  
1429          $cached = bp_core_get_incremented_cache( $total_groups_sql, 'bp_groups' );
1430          if ( false === $cached ) {
1431              $total_groups = (int) $wpdb->get_var( $total_groups_sql );
1432              bp_core_set_incremented_cache( $total_groups_sql, 'bp_groups', $total_groups );
1433          } else {
1434              $total_groups = (int) $cached;
1435          }
1436  
1437          return array( 'groups' => $paged_groups, 'total' => $total_groups );
1438      }
1439  
1440      /**
1441       * Get the SQL for the 'meta_query' param in BP_Activity_Activity::get()
1442       *
1443       * We use WP_Meta_Query to do the heavy lifting of parsing the
1444       * meta_query array and creating the necessary SQL clauses.
1445       *
1446       * @since 1.8.0
1447       *
1448       * @param array $meta_query An array of meta_query filters. See the
1449       *                          documentation for {@link WP_Meta_Query} for details.
1450       * @return array $sql_array 'join' and 'where' clauses.
1451       */
1452  	protected static function get_meta_query_sql( $meta_query = array() ) {
1453          global $wpdb;
1454  
1455          $sql_array = array(
1456              'join'  => '',
1457              'where' => '',
1458          );
1459  
1460          if ( ! empty( $meta_query ) ) {
1461              $groups_meta_query = new WP_Meta_Query( $meta_query );
1462  
1463              // WP_Meta_Query expects the table name at
1464              // $wpdb->group.
1465              $wpdb->groupmeta = buddypress()->groups->table_name_groupmeta;
1466  
1467              $meta_sql = $groups_meta_query->get_sql( 'group', 'g', 'id' );
1468              $sql_array['join']  = $meta_sql['join'];
1469              $sql_array['where'] = self::strip_leading_and( $meta_sql['where'] );
1470          }
1471  
1472          return $sql_array;
1473      }
1474  
1475      /**
1476       * Convert the 'type' parameter to 'order' and 'orderby'.
1477       *
1478       * @since 1.8.0
1479       *
1480       * @param string $type The 'type' shorthand param.
1481       *
1482       * @return array {
1483       *     @type string $order   SQL-friendly order string.
1484       *     @type string $orderby SQL-friendly orderby column name.
1485       * }
1486       */
1487  	protected static function convert_type_to_order_orderby( $type = '' ) {
1488          $order = $orderby = '';
1489  
1490          switch ( $type ) {
1491              case 'newest' :
1492                  $order   = 'DESC';
1493                  $orderby = 'date_created';
1494                  break;
1495  
1496              case 'active' :
1497                  $order   = 'DESC';
1498                  $orderby = 'last_activity';
1499                  break;
1500  
1501              case 'popular' :
1502                  $order   = 'DESC';
1503                  $orderby = 'total_member_count';
1504                  break;
1505  
1506              case 'alphabetical' :
1507                  $order   = 'ASC';
1508                  $orderby = 'name';
1509                  break;
1510  
1511              case 'random' :
1512                  $order   = '';
1513                  $orderby = 'random';
1514                  break;
1515          }
1516  
1517          return array( 'order' => $order, 'orderby' => $orderby );
1518      }
1519  
1520      /**
1521       * Convert the 'orderby' param into a proper SQL term/column.
1522       *
1523       * @since 1.8.0
1524       *
1525       * @param string $orderby Orderby term as passed to get().
1526       * @return string $order_by_term SQL-friendly orderby term.
1527       */
1528  	protected static function convert_orderby_to_order_by_term( $orderby ) {
1529          $order_by_term = '';
1530  
1531          switch ( $orderby ) {
1532              case 'date_created' :
1533              default :
1534                  $order_by_term = 'g.date_created';
1535                  break;
1536  
1537              case 'last_activity' :
1538                  $order_by_term = 'gm_last_activity.meta_value';
1539                  break;
1540  
1541              case 'total_member_count' :
1542                  $order_by_term = 'CONVERT(gm_total_member_count.meta_value, SIGNED)';
1543                  break;
1544  
1545              case 'name' :
1546                  $order_by_term = 'g.name';
1547                  break;
1548  
1549              case 'random' :
1550                  $order_by_term = 'rand()';
1551                  break;
1552  
1553              case 'meta_id' :
1554                  $order_by_term = buddypress()->groups->table_name_groupmeta . '.id';
1555                  break;
1556          }
1557  
1558          return $order_by_term;
1559      }
1560  
1561      /**
1562       * Get a list of groups whose names start with a given letter.
1563       *
1564       * @since 1.6.0
1565       *
1566       * @param string            $letter          The letter.
1567       * @param int|null          $limit           Optional. The max number of results to return.
1568       *                                           Default: null (no limit).
1569       * @param int|null          $page            Optional. The page offset of results to return.
1570       *                                           Default: null (no limit).
1571       * @param bool              $populate_extras Deprecated.
1572       * @param string|array|bool $exclude         Optional. Array or comma-separated list of group
1573       *                                           IDs to exclude from results.
1574       * @return false|array {
1575       *     @type array $groups Array of group objects returned by the
1576       *                         paginated query.
1577       *     @type int   $total  Total count of all groups matching non-
1578       *                         paginated query params.
1579       * }
1580       */
1581  	public static function get_by_letter( $letter, $limit = null, $page = null, $populate_extras = true, $exclude = false ) {
1582  
1583          if ( true !== $populate_extras ) {
1584              _deprecated_argument(
1585                  __METHOD__,
1586                  '1.6.0',
1587                  sprintf(
1588                      /* translators: 1: the name of the method. 2: the name of the file. */
1589                      esc_html__( '%1$s no longer accepts setting $populate_extras. See the inline documentation at %2$s for more details.', 'buddypress' ),
1590                      __METHOD__,
1591                      __FILE__
1592                  )
1593              );
1594          }
1595  
1596          // Multibyte compliance.
1597          if ( function_exists( 'mb_strlen' ) ) {
1598              if ( mb_strlen( $letter, 'UTF-8' ) > 1 || is_numeric( $letter ) || !$letter ) {
1599                  return false;
1600              }
1601          } else {
1602              if ( strlen( $letter ) > 1 || is_numeric( $letter ) || !$letter ) {
1603                  return false;
1604              }
1605          }
1606  
1607          return self::get(
1608              array(
1609                  'per_page'       => $limit,
1610                  'page'           => $page,
1611                  'search_terms'   => $letter . '*',
1612                  'search_columns' => array( 'name' ),
1613                  'exclude'        => $exclude,
1614              )
1615          );
1616      }
1617  
1618      /**
1619       * Get a list of random groups.
1620       *
1621       * Use BP_Groups_Group::get() with 'type' = 'random' instead.
1622       *
1623       * @since 1.6.0
1624       * @since 10.0.0 Deprecate the `$populate_extras` arg.
1625       *
1626       * @param int|null          $limit           Optional. The max number of results to return.
1627       *                                           Default: null (no limit).
1628       * @param int|null          $page            Optional. The page offset of results to return.
1629       *                                           Default: null (no limit).
1630       * @param int               $user_id         Optional. If present, groups will be limited to
1631       *                                           those of which the specified user is a member.
1632       * @param string|bool       $search_terms    Optional. Limit groups to those whose name
1633       *                                           or description field contain the search string.
1634       * @param bool              $populate_extras Deprecated.
1635       * @param string|array|bool $exclude         Optional. Array or comma-separated list of group
1636       *                                           IDs to exclude from results.
1637       * @return array {
1638       *     @type array $groups Array of group objects returned by the
1639       *                         paginated query.
1640       *     @type int   $total  Total count of all groups matching non-
1641       *                         paginated query params.
1642       * }
1643       */
1644  	public static function get_random( $limit = null, $page = null, $user_id = 0, $search_terms = false, $populate_extras = true, $exclude = false ) {
1645  
1646          if ( true !== $populate_extras ) {
1647              _deprecated_argument(
1648                  __METHOD__,
1649                  '10.0.0',
1650                  sprintf(
1651                      /* translators: 1: the name of the method. 2: the name of the file. */
1652                      esc_html__( '%1$s no longer accepts setting $populate_extras. See the inline documentation at %2$s for more details.', 'buddypress' ),
1653                      __METHOD__,
1654                      __FILE__
1655                  )
1656              );
1657          }
1658  
1659          return self::get(
1660              array(
1661                  'type'         => 'random',
1662                  'per_page'     => $limit,
1663                  'page'         => $page,
1664                  'user_id'      => $user_id,
1665                  'search_terms' => $search_terms,
1666                  'exclude'      => $exclude,
1667              )
1668          );
1669      }
1670  
1671      /**
1672       * Fetch extra data for a list of groups.
1673       *
1674       * This method is used throughout the class, by methods that take a
1675       * $populate_extras parameter.
1676       *
1677       * Data fetched:
1678       *     - Logged-in user's status within each group (is_member,
1679       *       is_confirmed, is_pending, is_banned)
1680       *
1681       * @since 1.6.0
1682       *
1683       * @param array        $paged_groups Array of groups.
1684       * @param string|array $group_ids    Array or comma-separated list of IDs matching
1685       *                                   $paged_groups.
1686       * @param string|bool  $type         Not used.
1687       * @return array $paged_groups
1688       */
1689  	public static function get_group_extras( &$paged_groups, &$group_ids, $type = false ) {
1690          $user_id = bp_loggedin_user_id();
1691  
1692          foreach ( $paged_groups as &$group ) {
1693              $group->is_member  = groups_is_user_member( $user_id, $group->id )  ? 1 : 0;
1694              $group->is_invited = groups_is_user_invited( $user_id, $group->id ) ? 1 : 0;
1695              $group->is_pending = groups_is_user_pending( $user_id, $group->id ) ? 1 : 0;
1696              $group->is_banned  = (bool) groups_is_user_banned( $user_id, $group->id );
1697          }
1698  
1699          return $paged_groups;
1700      }
1701  
1702      /**
1703       * Delete all invitations to a given group.
1704       *
1705       * @since 1.6.0
1706       *
1707       * @param int $group_id ID of the group whose invitations are being deleted.
1708       * @return int|null Number of rows records deleted on success, null on
1709       *                  failure.
1710       */
1711  	public static function delete_all_invites( $group_id ) {
1712          if ( empty( $group_id ) ) {
1713              return false;
1714          }
1715  
1716          $invites_class = new BP_Groups_Invitation_Manager();
1717  
1718          return $invites_class->delete( array(
1719              'item_id' => $group_id,
1720          ) );
1721      }
1722  
1723      /**
1724       * Get a total group count for the site.
1725       *
1726       * Will include hidden groups in the count only if
1727       * bp_current_user_can( 'bp_moderate' ).
1728       *
1729       * @since 1.6.0
1730       * @since 10.0.0 Added the `$skip_cache` parameter.
1731       *
1732       * @global BuddyPress $bp   The one true BuddyPress instance.
1733       * @global wpdb       $wpdb WordPress database object.
1734       *
1735       * @param bool $skip_cache Optional. Skip getting count from cache.
1736       *                         Defaults to false.
1737       * @return int
1738       */
1739  	public static function get_total_group_count( $skip_cache = false ) {
1740          global $wpdb;
1741  
1742          $cache_key = 'bp_total_group_count';
1743          $count     = wp_cache_get( $cache_key, 'bp' );
1744  
1745          if ( false === $count || true === $skip_cache ) {
1746              $hidden_sql = '';
1747              if ( ! bp_current_user_can( 'bp_moderate' ) ) {
1748                  $hidden_sql = "WHERE status != 'hidden'";
1749              }
1750  
1751              $bp    = buddypress();
1752              $count = $wpdb->get_var( "SELECT COUNT(id) FROM {$bp->groups->table_name} {$hidden_sql}" );
1753  
1754              wp_cache_set( $cache_key, (int) $count, 'bp' );
1755          }
1756  
1757          /**
1758           * Filters the total group count.
1759           *
1760           * @since 10.0.0
1761           *
1762           * @param int $count Total group count.
1763           */
1764          return (int) apply_filters( 'bp_groups_total_group_count', (int) $count );
1765      }
1766  
1767      /**
1768       * Get the member count for a group.
1769       *
1770       * @since 1.6.0
1771       * @since 10.0.0 Updated to use the `groups_get_group_members`.
1772       *
1773       * @param int  $group_id   Group ID.
1774       * @param bool $skip_cache Optional. Skip getting count from cache. Defaults to false.
1775       * @return int Count of confirmed members for the group.
1776       */
1777  	public static function get_total_member_count( $group_id, $skip_cache = false ) {
1778          $cache_key = 'total_member_count';
1779          $count     = groups_get_groupmeta( $group_id, $cache_key );
1780  
1781          if ( false === $count || true === $skip_cache ) {
1782              $members = groups_get_group_members(
1783                  array(
1784                      'group_id'   => $group_id,
1785                      'group_role' => array( 'member', 'admin', 'mod' ),
1786                      'type'       => 'active',
1787                  )
1788              );
1789  
1790              $count = $members['count'] ? $members['count'] : 0;
1791  
1792              groups_update_groupmeta( $group_id, $cache_key, (int) $count );
1793          }
1794  
1795          /**
1796           * Filters the total member count for a group.
1797           *
1798           * @since 10.0.0
1799           *
1800           * @param int $count    Total member count for group.
1801           * @param int $group_id The ID of the group.
1802           */
1803          return (int) apply_filters( 'bp_groups_total_member_count', (int) $count, (int) $group_id );
1804      }
1805  
1806      /**
1807       * Get an array containing ids for each group type.
1808       *
1809       * A bit of a kludge workaround for some issues
1810       * with bp_has_groups().
1811       *
1812       * @since 1.7.0
1813       *
1814       * @return array
1815       */
1816  	public static function get_group_type_ids() {
1817          global $wpdb;
1818  
1819          $bp  = buddypress();
1820          $ids = array();
1821  
1822          $ids['all']     = $wpdb->get_col( "SELECT id FROM {$bp->groups->table_name}" );
1823          $ids['public']  = $wpdb->get_col( "SELECT id FROM {$bp->groups->table_name} WHERE status = 'public'" );
1824          $ids['private'] = $wpdb->get_col( "SELECT id FROM {$bp->groups->table_name} WHERE status = 'private'" );
1825          $ids['hidden']  = $wpdb->get_col( "SELECT id FROM {$bp->groups->table_name} WHERE status = 'hidden'" );
1826  
1827          return $ids;
1828      }
1829  
1830      /**
1831       * Get SQL clause for group type(s).
1832       *
1833       * @since 2.6.0
1834       *
1835       * @param  string|array $group_types Group type(s).
1836       * @param  string       $operator    'IN' or 'NOT IN'.
1837       * @return string       $clause      SQL clause.
1838       */
1839  	protected static function get_sql_clause_for_group_types( $group_types, $operator ) {
1840          global $wpdb;
1841  
1842          // Sanitize operator.
1843          if ( 'NOT IN' !== $operator ) {
1844              $operator = 'IN';
1845          }
1846  
1847          // Parse and sanitize types.
1848          if ( ! is_array( $group_types ) ) {
1849              $group_types = preg_split( '/[,\s+]/', $group_types );
1850          }
1851  
1852          $types = array();
1853          foreach ( $group_types as $gt ) {
1854              if ( bp_groups_get_group_type_object( $gt ) ) {
1855                  $types[] = $gt;
1856              }
1857          }
1858  
1859          $tax_query = new WP_Tax_Query( array(
1860              array(
1861                  'taxonomy' => bp_get_group_type_tax_name(),
1862                  'field'    => 'name',
1863                  'operator' => $operator,
1864                  'terms'    => $types,
1865              ),
1866          ) );
1867  
1868          $site_id  = bp_get_taxonomy_term_site_id( bp_get_group_type_tax_name() );
1869          $switched = false;
1870          if ( $site_id !== get_current_blog_id() ) {
1871              switch_to_blog( $site_id );
1872              $switched = true;
1873          }
1874  
1875          $sql_clauses = $tax_query->get_sql( 'g', 'id' );
1876  
1877          $clause = '';
1878  
1879          // The no_results clauses are the same between IN and NOT IN.
1880          if ( false !== strpos( $sql_clauses['where'], '0 = 1' ) ) {
1881              $clause = self::strip_leading_and( $sql_clauses['where'] );
1882  
1883          // The tax_query clause generated for NOT IN can be used almost as-is.
1884          } elseif ( 'NOT IN' === $operator ) {
1885              $clause = self::strip_leading_and( $sql_clauses['where'] );
1886  
1887          // IN clauses must be converted to a subquery.
1888          } elseif ( preg_match( '/' . $wpdb->term_relationships . '\.term_taxonomy_id IN \([0-9, ]+\)/', $sql_clauses['where'], $matches ) ) {
1889              $clause = " g.id IN ( SELECT object_id FROM $wpdb->term_relationships WHERE {$matches[0]} )";
1890          }
1891  
1892          if ( $switched ) {
1893              restore_current_blog();
1894          }
1895  
1896          return $clause;
1897      }
1898  
1899      /**
1900       * Strips the leading AND and any surrounding whitespace from a string.
1901       *
1902       * Used here to normalize SQL fragments generated by `WP_Meta_Query` and
1903       * other utility classes.
1904       *
1905       * @since 2.7.0
1906       *
1907       * @param string $s String.
1908       * @return string
1909       */
1910  	protected static function strip_leading_and( $s ) {
1911          return preg_replace( '/^\s*AND\s*/', '', $s );
1912      }
1913  }


Generated: Thu Oct 28 01:00:59 2021 Cross-referenced by PHPXref 0.7.1