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


Generated: Mon Nov 18 01:01:37 2019 Cross-referenced by PHPXref 0.7.1