[ 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          global $wpdb;
 775  
 776          $bp  = buddypress();
 777          $sql = $wpdb->prepare( "SELECT user_id FROM {$bp->groups->table_name_members} WHERE group_id = %d and is_confirmed = 0 AND inviter_id = %d", $group_id, $user_id );
 778  
 779          // Query for a specific invite sent status.
 780          if ( ! is_null( $sent ) ) {
 781              $sql .= $wpdb->prepare( ' AND invite_sent = %d', $sent );
 782          }
 783  
 784          return $wpdb->get_col( $sql );
 785      }
 786  
 787      /**
 788       * Get a list of a user's groups, filtered by a search string.
 789       *
 790       * @since 1.6.0
 791       *
 792       * @param string   $filter  Search term. Matches against 'name' and
 793       *                          'description' fields.
 794       * @param int      $user_id ID of the user whose groups are being searched.
 795       *                          Default: the displayed user.
 796       * @param mixed    $order   Not used.
 797       * @param int|null $limit   Optional. The max number of results to return.
 798       *                          Default: null (no limit).
 799       * @param int|null $page    Optional. The page offset of results to return.
 800       *                          Default: null (no limit).
 801       * @return false|array {
 802       *     @type array $groups Array of matched and paginated group IDs.
 803       *     @type int   $total  Total count of groups matching the query.
 804       * }
 805       */
 806  	public static function filter_user_groups( $filter, $user_id = 0, $order = false, $limit = null, $page = null ) {
 807          if ( empty( $user_id ) ) {
 808              $user_id = bp_displayed_user_id();
 809          }
 810  
 811          $args = array(
 812              'search_terms' => $filter,
 813              'user_id'      => $user_id,
 814              'per_page'     => $limit,
 815              'page'         => $page,
 816              'order'        => $order,
 817          );
 818  
 819          $groups = BP_Groups_Group::get( $args );
 820  
 821          // Modify the results to match the old format.
 822          $paged_groups = array();
 823          $i = 0;
 824          foreach ( $groups['groups'] as $group ) {
 825              $paged_groups[ $i ] = new stdClass;
 826              $paged_groups[ $i ]->group_id = $group->id;
 827              $i++;
 828          }
 829  
 830          return array( 'groups' => $paged_groups, 'total' => $groups['total'] );
 831      }
 832  
 833      /**
 834       * Get a list of groups, filtered by a search string.
 835       *
 836       * @since 1.6.0
 837       *
 838       * @param string      $filter  Search term. Matches against 'name' and
 839       *                             'description' fields.
 840       * @param int|null    $limit   Optional. The max number of results to return.
 841       *                             Default: null (no limit).
 842       * @param int|null    $page    Optional. The page offset of results to return.
 843       *                             Default: null (no limit).
 844       * @param string|bool $sort_by Column to sort by. Default: false (default
 845       *        sort).
 846       * @param string|bool $order   ASC or DESC. Default: false (default sort).
 847       * @return array {
 848       *     @type array $groups Array of matched and paginated group IDs.
 849       *     @type int   $total  Total count of groups matching the query.
 850       * }
 851       */
 852  	public static function search_groups( $filter, $limit = null, $page = null, $sort_by = false, $order = false ) {
 853          $args = array(
 854              'search_terms' => $filter,
 855              'per_page'     => $limit,
 856              'page'         => $page,
 857              'orderby'      => $sort_by,
 858              'order'        => $order,
 859          );
 860  
 861          $groups = BP_Groups_Group::get( $args );
 862  
 863          // Modify the results to match the old format.
 864          $paged_groups = array();
 865          $i = 0;
 866          foreach ( $groups['groups'] as $group ) {
 867              $paged_groups[ $i ] = new stdClass;
 868              $paged_groups[ $i ]->group_id = $group->id;
 869              $i++;
 870          }
 871  
 872          return array( 'groups' => $paged_groups, 'total' => $groups['total'] );
 873      }
 874  
 875      /**
 876       * Check for the existence of a slug.
 877       *
 878       * @since 1.6.0
 879       *
 880       * @param string $slug Slug to check.
 881       * @return string|null The slug, if found. Otherwise null.
 882       */
 883  	public static function check_slug( $slug ) {
 884          global $wpdb;
 885  
 886          $bp = buddypress();
 887  
 888          return $wpdb->get_var( $wpdb->prepare( "SELECT slug FROM {$bp->groups->table_name} WHERE slug = %s", $slug ) );
 889      }
 890  
 891      /**
 892       * Get the slug for a given group ID.
 893       *
 894       * @since 1.6.0
 895       *
 896       * @param int $group_id ID of the group.
 897       * @return string|null The slug, if found. Otherwise null.
 898       */
 899  	public static function get_slug( $group_id ) {
 900          global $wpdb;
 901  
 902          $bp = buddypress();
 903  
 904          return $wpdb->get_var( $wpdb->prepare( "SELECT slug FROM {$bp->groups->table_name} WHERE id = %d", $group_id ) );
 905      }
 906  
 907      /**
 908       * Check whether a given group has any members.
 909       *
 910       * @since 1.6.0
 911       *
 912       * @param int $group_id ID of the group.
 913       * @return bool True if the group has members, otherwise false.
 914       */
 915  	public static function has_members( $group_id ) {
 916          global $wpdb;
 917  
 918          $bp = buddypress();
 919  
 920          $members = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(id) FROM {$bp->groups->table_name_members} WHERE group_id = %d", $group_id ) );
 921  
 922          if ( empty( $members ) )
 923              return false;
 924  
 925          return true;
 926      }
 927  
 928      /**
 929       * Check whether a group has outstanding membership requests.
 930       *
 931       * @since 1.6.0
 932       *
 933       * @param int $group_id ID of the group.
 934       * @return int|null The number of outstanding requests, or null if
 935       *                  none are found.
 936       */
 937  	public static function has_membership_requests( $group_id ) {
 938          global $wpdb;
 939  
 940          $bp = buddypress();
 941  
 942          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 ) );
 943      }
 944  
 945      /**
 946       * Get outstanding membership requests for a group.
 947       *
 948       * @since 1.6.0
 949       *
 950       * @param int      $group_id ID of the group.
 951       * @param int|null $limit    Optional. Max number of results to return.
 952       *                           Default: null (no limit).
 953       * @param int|null $page     Optional. Page offset of results returned. Default:
 954       *                           null (no limit).
 955       * @return array {
 956       *     @type array $requests The requested page of located requests.
 957       *     @type int   $total    Total number of requests outstanding for the
 958       *                           group.
 959       * }
 960       */
 961  	public static function get_membership_requests( $group_id, $limit = null, $page = null ) {
 962          global $wpdb;
 963  
 964          if ( !empty( $limit ) && !empty( $page ) ) {
 965              $pag_sql = $wpdb->prepare( " LIMIT %d, %d", intval( ( $page - 1 ) * $limit), intval( $limit ) );
 966          }
 967  
 968          $bp = buddypress();
 969  
 970          $paged_requests = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$bp->groups->table_name_members} WHERE group_id = %d AND is_confirmed = 0 AND inviter_id = 0{$pag_sql}", $group_id ) );
 971          $total_requests = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(id) FROM {$bp->groups->table_name_members} WHERE group_id = %d AND is_confirmed = 0 AND inviter_id = 0", $group_id ) );
 972  
 973          return array( 'requests' => $paged_requests, 'total' => $total_requests );
 974      }
 975  
 976      /**
 977       * Query for groups.
 978       *
 979       * @see WP_Meta_Query::queries for a description of the 'meta_query'
 980       *      parameter format.
 981       *
 982       * @since 1.6.0
 983       * @since 2.6.0 Added `$group_type`, `$group_type__in`, and `$group_type__not_in` parameters.
 984       * @since 2.7.0 Added `$update_admin_cache` and `$parent_id` parameters.
 985       * @since 2.8.0 Changed `$search_terms` parameter handling and added `$search_columns` parameter.
 986       * @since 2.9.0 Added `$slug` parameter.
 987       *
 988       * @param array $args {
 989       *     Array of parameters. All items are optional.
 990       *     @type string       $type               Optional. Shorthand for certain orderby/order combinations.
 991       *                                            'newest', 'active', 'popular', 'alphabetical', 'random'.
 992       *                                            When present, will override orderby and order params.
 993       *                                            Default: null.
 994       *     @type string       $orderby            Optional. Property to sort by. 'date_created', 'last_activity',
 995       *                                            'total_member_count', 'name', 'random', 'meta_id'.
 996       *                                            Default: 'date_created'.
 997       *     @type string       $order              Optional. Sort order. 'ASC' or 'DESC'. Default: 'DESC'.
 998       *     @type int          $per_page           Optional. Number of items to return per page of results.
 999       *                                            Default: null (no limit).
1000       *     @type int          $page               Optional. Page offset of results to return.
1001       *                                            Default: null (no limit).
1002       *     @type int          $user_id            Optional. If provided, results will be limited to groups
1003       *                                            of which the specified user is a member. Default: null.
1004        *     @type array|string $slug               Optional. Array or comma-separated list of group slugs to limit
1005        *                                            results to.
1006       *                                            Default: false.
1007       *     @type string       $search_terms       Optional. If provided, only groups whose names or descriptions
1008       *                                            match the search terms will be returned. Allows specifying the
1009       *                                            wildcard position using a '*' character before or after the
1010       *                                            string or both. Works in concert with $search_columns.
1011       *                                            Default: false.
1012         *     @type string       $search_columns     Optional. If provided, only apply the search terms to the
1013         *                                            specified columns. Works in concert with $search_terms.
1014         *                                            Default: empty array.
1015       *     @type array|string $group_type         Array or comma-separated list of group types to limit results to.
1016       *     @type array|string $group_type__in     Array or comma-separated list of group types to limit results to.
1017       *     @type array|string $group_type__not_in Array or comma-separated list of group types that will be
1018       *                                            excluded from results.
1019       *     @type array        $meta_query         Optional. An array of meta_query conditions.
1020       *                                            See {@link WP_Meta_Query::queries} for description.
1021       *     @type array|string $value              Optional. Array or comma-separated list of group IDs. Results
1022       *                                            will be limited to groups within the list. Default: false.
1023       *     @type array|string $parent_id          Optional. Array or comma-separated list of group IDs. Results
1024       *                                            will be limited to children of the specified groups. Default: null.
1025       *     @type array|string $exclude            Optional. Array or comma-separated list of group IDs.
1026       *                                            Results will exclude the listed groups. Default: false.
1027       *     @type bool         $update_meta_cache  Whether to pre-fetch groupmeta for the returned groups.
1028       *                                            Default: true.
1029       *     @type bool         $update_admin_cache Whether to pre-fetch administrator IDs for the returned
1030       *                                            groups. Default: false.
1031       *     @type bool         $show_hidden        Whether to include hidden groups in results. Default: false.
1032        *     @type array|string $status             Optional. Array or comma-separated list of group statuses to limit
1033        *                                            results to. If specified, $show_hidden is ignored.
1034       *                                            Default: empty array.
1035        *     @type string       $fields             Which fields to return. Specify 'ids' to fetch a list of IDs.
1036        *                                            Default: 'all' (return BP_Groups_Group objects).
1037        *                                            If set, meta and admin caches will not be prefetched.
1038       * }
1039       * @return array {
1040       *     @type array $groups Array of group objects returned by the
1041       *                         paginated query. (IDs only if `fields` is set to `ids`.)
1042       *     @type int   $total  Total count of all groups matching non-
1043       *                         paginated query params.
1044       * }
1045       */
1046  	public static function get( $args = array() ) {
1047          global $wpdb;
1048  
1049          // Backward compatibility with old method of passing arguments.
1050          if ( ! is_array( $args ) || func_num_args() > 1 ) {
1051              _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__ ) );
1052  
1053              $old_args_keys = array(
1054                  0 => 'type',
1055                  1 => 'per_page',
1056                  2 => 'page',
1057                  3 => 'user_id',
1058                  4 => 'search_terms',
1059                  5 => 'include',
1060                  6 => 'populate_extras',
1061                  7 => 'exclude',
1062                  8 => 'show_hidden',
1063              );
1064  
1065              $args = bp_core_parse_args_array( $old_args_keys, func_get_args() );
1066          }
1067  
1068          $defaults = array(
1069              'type'               => null,
1070              'orderby'            => 'date_created',
1071              'order'              => 'DESC',
1072              'per_page'           => null,
1073              'page'               => null,
1074              'user_id'            => 0,
1075              'slug'               => array(),
1076              'search_terms'       => false,
1077              'search_columns'     => array(),
1078              'group_type'         => '',
1079              'group_type__in'     => '',
1080              'group_type__not_in' => '',
1081              'meta_query'         => false,
1082              'include'            => false,
1083              'parent_id'          => null,
1084              'update_meta_cache'  => true,
1085              'update_admin_cache' => false,
1086              'exclude'            => false,
1087              'show_hidden'        => false,
1088              'status'             => array(),
1089              'fields'             => 'all',
1090          );
1091  
1092          $r = bp_parse_args( $args, $defaults, 'bp_groups_group_get' );
1093  
1094          $bp = buddypress();
1095  
1096          $sql = array(
1097              'select'     => "SELECT DISTINCT g.id",
1098              'from'       => "{$bp->groups->table_name} g",
1099              'where'      => '',
1100              'orderby'    => '',
1101              'pagination' => '',
1102          );
1103  
1104          if ( ! empty( $r['user_id'] ) ) {
1105              $sql['from'] .= " JOIN {$bp->groups->table_name_members} m ON ( g.id = m.group_id )";
1106          }
1107  
1108          $where_conditions = array();
1109  
1110          if ( ! empty( $r['status'] ) ) {
1111              if ( ! is_array( $r['status'] ) ) {
1112                  $r['status'] = preg_split( '/[\s,]+/', $r['status'] );
1113              }
1114              $r['status'] = array_map( 'sanitize_title', $r['status'] );
1115              $status_in = "'" . implode( "','", $r['status'] ) . "'";
1116              $where_conditions['status'] = "g.status IN ({$status_in})";
1117          } elseif ( empty( $r['show_hidden'] ) ) {
1118              $where_conditions['hidden'] = "g.status != 'hidden'";
1119          }
1120  
1121          if ( ! empty( $r['slug'] ) ) {
1122              if ( ! is_array( $r['slug'] ) ) {
1123                  $r['slug'] = preg_split( '/[\s,]+/', $r['slug'] );
1124              }
1125              $r['slug'] = array_map( 'sanitize_title', $r['slug'] );
1126              $slug_in = "'" . implode( "','", $r['slug'] ) . "'";
1127              $where_conditions['slug'] = "g.slug IN ({$slug_in})";
1128          }
1129  
1130          $search = '';
1131          if ( isset( $r['search_terms'] ) ) {
1132              $search = trim( $r['search_terms'] );
1133          }
1134  
1135          if ( $search ) {
1136              $leading_wild = ( ltrim( $search, '*' ) != $search );
1137              $trailing_wild = ( rtrim( $search, '*' ) != $search );
1138              if ( $leading_wild && $trailing_wild ) {
1139                  $wild = 'both';
1140              } elseif ( $leading_wild ) {
1141                  $wild = 'leading';
1142              } elseif ( $trailing_wild ) {
1143                  $wild = 'trailing';
1144              } else {
1145                  // Default is to wrap in wildcard characters.
1146                  $wild = 'both';
1147              }
1148              $search = trim( $search, '*' );
1149  
1150              $searches = array();
1151              $leading_wild = ( 'leading' == $wild || 'both' == $wild ) ? '%' : '';
1152              $trailing_wild = ( 'trailing' == $wild || 'both' == $wild ) ? '%' : '';
1153              $wildcarded = $leading_wild . bp_esc_like( $search ) . $trailing_wild;
1154  
1155              $search_columns = array( 'name', 'description' );
1156              if ( $r['search_columns'] ) {
1157                  $search_columns = array_intersect( $r['search_columns'], $search_columns );
1158              }
1159  
1160              foreach ( $search_columns as $search_column ) {
1161                  $searches[] = $wpdb->prepare( "$search_column LIKE %s", $wildcarded );
1162              }
1163  
1164              $where_conditions['search'] = '(' . implode(' OR ', $searches) . ')';
1165          }
1166  
1167          $meta_query_sql = self::get_meta_query_sql( $r['meta_query'] );
1168  
1169          if ( ! empty( $meta_query_sql['join'] ) ) {
1170              $sql['from'] .= $meta_query_sql['join'];
1171          }
1172  
1173          if ( ! empty( $meta_query_sql['where'] ) ) {
1174              $where_conditions['meta'] = $meta_query_sql['where'];
1175          }
1176  
1177          // Only use 'group_type__in', if 'group_type' is not set.
1178          if ( empty( $r['group_type'] ) && ! empty( $r['group_type__in']) ) {
1179              $r['group_type'] = $r['group_type__in'];
1180          }
1181  
1182          // Group types to exclude. This has priority over inclusions.
1183          if ( ! empty( $r['group_type__not_in'] ) ) {
1184              $group_type_clause = self::get_sql_clause_for_group_types( $r['group_type__not_in'], 'NOT IN' );
1185  
1186          // Group types to include.
1187          } elseif ( ! empty( $r['group_type'] ) ) {
1188              $group_type_clause = self::get_sql_clause_for_group_types( $r['group_type'], 'IN' );
1189          }
1190  
1191          if ( ! empty( $group_type_clause ) ) {
1192              $where_conditions['group_type'] = $group_type_clause;
1193          }
1194  
1195          if ( ! empty( $r['user_id'] ) ) {
1196              $where_conditions['user'] = $wpdb->prepare( "m.user_id = %d AND m.is_confirmed = 1 AND m.is_banned = 0", $r['user_id'] );
1197          }
1198  
1199          if ( ! empty( $r['include'] ) ) {
1200              $include        = implode( ',', wp_parse_id_list( $r['include'] ) );
1201              $where_conditions['include'] = "g.id IN ({$include})";
1202          }
1203  
1204          if ( ! is_null( $r['parent_id'] ) ) {
1205              // For legacy reasons, `false` means groups with no parent.
1206              if ( false === $r['parent_id'] ) {
1207                  $parent_id = 0;
1208              } else {
1209                  $parent_id = implode( ',', wp_parse_id_list( $r['parent_id'] ) );
1210              }
1211  
1212              $where_conditions['parent_id'] = "g.parent_id IN ({$parent_id})";
1213          }
1214  
1215          if ( ! empty( $r['exclude'] ) ) {
1216              $exclude        = implode( ',', wp_parse_id_list( $r['exclude'] ) );
1217              $where_conditions['exclude'] = "g.id NOT IN ({$exclude})";
1218          }
1219  
1220          /* Order/orderby ********************************************/
1221  
1222          $order   = $r['order'];
1223          $orderby = $r['orderby'];
1224  
1225          // If a 'type' parameter was passed, parse it and overwrite
1226          // 'order' and 'orderby' params passed to the function.
1227          if (  ! empty( $r['type'] ) ) {
1228  
1229              /**
1230               * Filters the 'type' parameter used to overwrite 'order' and 'orderby' values.
1231               *
1232               * @since 2.1.0
1233               *
1234               * @param array  $value Converted 'type' value for order and orderby.
1235               * @param string $value Parsed 'type' value for the get method.
1236               */
1237              $order_orderby = apply_filters( 'bp_groups_get_orderby', self::convert_type_to_order_orderby( $r['type'] ), $r['type'] );
1238  
1239              // If an invalid type is passed, $order_orderby will be
1240              // an array with empty values. In this case, we stick
1241              // with the default values of $order and $orderby.
1242              if ( ! empty( $order_orderby['order'] ) ) {
1243                  $order = $order_orderby['order'];
1244              }
1245  
1246              if ( ! empty( $order_orderby['orderby'] ) ) {
1247                  $orderby = $order_orderby['orderby'];
1248              }
1249          }
1250  
1251          // 'total_member_count' and 'last_activity' sorts require additional table joins.
1252          if ( 'total_member_count' === $orderby ) {
1253              $sql['from'] .= " JOIN {$bp->groups->table_name_groupmeta} gm_total_member_count ON ( g.id = gm_total_member_count.group_id )";
1254              $where_conditions['total_member_count'] = "gm_total_member_count.meta_key = 'total_member_count'";
1255          } elseif ( 'last_activity' === $orderby ) {
1256  
1257              $sql['from'] .= " JOIN {$bp->groups->table_name_groupmeta} gm_last_activity on ( g.id = gm_last_activity.group_id )";
1258              $where_conditions['last_activity'] = "gm_last_activity.meta_key = 'last_activity'";
1259          }
1260  
1261          // If 'meta_id' is the requested order, and there's no meta query, fall back to the default.
1262          if ( 'meta_id' === $orderby && empty( $meta_query_sql['join'] ) ) {
1263              $orderby = 'date_created';
1264          }
1265  
1266          // Sanitize 'order'.
1267          $order = bp_esc_sql_order( $order );
1268  
1269          /**
1270           * Filters the converted 'orderby' term.
1271           *
1272           * @since 2.1.0
1273           *
1274           * @param string $value   Converted 'orderby' term.
1275           * @param string $orderby Original orderby value.
1276           * @param string $value   Parsed 'type' value for the get method.
1277           */
1278          $orderby = apply_filters( 'bp_groups_get_orderby_converted_by_term', self::convert_orderby_to_order_by_term( $orderby ), $orderby, $r['type'] );
1279  
1280          // Random order is a special case.
1281          if ( 'rand()' === $orderby ) {
1282              $sql['orderby'] = "ORDER BY rand()";
1283          } else {
1284              $sql['orderby'] = "ORDER BY {$orderby} {$order}";
1285          }
1286  
1287          if ( ! empty( $r['per_page'] ) && ! empty( $r['page'] ) && $r['per_page'] != -1 ) {
1288              $sql['pagination'] = $wpdb->prepare( "LIMIT %d, %d", intval( ( $r['page'] - 1 ) * $r['per_page']), intval( $r['per_page'] ) );
1289          }
1290  
1291          $where = '';
1292          if ( ! empty( $where_conditions ) ) {
1293              $sql['where'] = implode( ' AND ', $where_conditions );
1294              $where = "WHERE {$sql['where']}";
1295          }
1296  
1297          $paged_groups_sql = "{$sql['select']} FROM {$sql['from']} {$where} {$sql['orderby']} {$sql['pagination']}";
1298  
1299          /**
1300           * Filters the pagination SQL statement.
1301           *
1302           * @since 1.5.0
1303           *
1304           * @param string $value Concatenated SQL statement.
1305           * @param array  $sql   Array of SQL parts before concatenation.
1306           * @param array  $r     Array of parsed arguments for the get method.
1307           */
1308          $paged_groups_sql = apply_filters( 'bp_groups_get_paged_groups_sql', $paged_groups_sql, $sql, $r );
1309  
1310          $cached = bp_core_get_incremented_cache( $paged_groups_sql, 'bp_groups' );
1311          if ( false === $cached ) {
1312              $paged_group_ids = $wpdb->get_col( $paged_groups_sql );
1313              bp_core_set_incremented_cache( $paged_groups_sql, 'bp_groups', $paged_group_ids );
1314          } else {
1315              $paged_group_ids = $cached;
1316          }
1317  
1318          if ( 'ids' === $r['fields'] ) {
1319              // We only want the IDs.
1320              $paged_groups = array_map( 'intval', $paged_group_ids );
1321          } else {
1322              $uncached_group_ids = bp_get_non_cached_ids( $paged_group_ids, 'bp_groups' );
1323              if ( $uncached_group_ids ) {
1324                  $group_ids_sql = implode( ',', array_map( 'intval', $uncached_group_ids ) );
1325                  $group_data_objects = $wpdb->get_results( "SELECT g.* FROM {$bp->groups->table_name} g WHERE g.id IN ({$group_ids_sql})" );
1326                  foreach ( $group_data_objects as $group_data_object ) {
1327                      wp_cache_set( $group_data_object->id, $group_data_object, 'bp_groups' );
1328                  }
1329              }
1330  
1331              $paged_groups = array();
1332              foreach ( $paged_group_ids as $paged_group_id ) {
1333                  $paged_groups[] = new BP_Groups_Group( $paged_group_id );
1334              }
1335  
1336              $group_ids = array();
1337              foreach ( (array) $paged_groups as $group ) {
1338                  $group_ids[] = $group->id;
1339              }
1340  
1341              // Grab all groupmeta.
1342              if ( ! empty( $r['update_meta_cache'] ) ) {
1343                  bp_groups_update_meta_cache( $group_ids );
1344              }
1345  
1346              // Prefetch all administrator IDs, if requested.
1347              if ( $r['update_admin_cache'] ) {
1348                  BP_Groups_Member::prime_group_admins_mods_cache( $group_ids );
1349              }
1350  
1351              // Set up integer properties needing casting.
1352              $int_props = array(
1353                  'id', 'creator_id', 'enable_forum'
1354              );
1355  
1356              // Integer casting.
1357              foreach ( $paged_groups as $key => $g ) {
1358                  foreach ( $int_props as $int_prop ) {
1359                      $paged_groups[ $key ]->{$int_prop} = (int) $paged_groups[ $key ]->{$int_prop};
1360                  }
1361              }
1362  
1363          }
1364  
1365          // Find the total number of groups in the results set.
1366          $total_groups_sql = "SELECT COUNT(DISTINCT g.id) FROM {$sql['from']} $where";
1367  
1368          /**
1369           * Filters the SQL used to retrieve total group results.
1370           *
1371           * @since 1.5.0
1372           *
1373           * @param string $t_sql     Concatenated SQL statement used for retrieving total group results.
1374           * @param array  $total_sql Array of SQL parts for the query.
1375           * @param array  $r         Array of parsed arguments for the get method.
1376           */
1377          $total_groups_sql = apply_filters( 'bp_groups_get_total_groups_sql', $total_groups_sql, $sql, $r );
1378  
1379          $cached = bp_core_get_incremented_cache( $total_groups_sql, 'bp_groups' );
1380          if ( false === $cached ) {
1381              $total_groups = (int) $wpdb->get_var( $total_groups_sql );
1382              bp_core_set_incremented_cache( $total_groups_sql, 'bp_groups', $total_groups );
1383          } else {
1384              $total_groups = (int) $cached;
1385          }
1386  
1387          return array( 'groups' => $paged_groups, 'total' => $total_groups );
1388      }
1389  
1390      /**
1391       * Get the SQL for the 'meta_query' param in BP_Activity_Activity::get()
1392       *
1393       * We use WP_Meta_Query to do the heavy lifting of parsing the
1394       * meta_query array and creating the necessary SQL clauses.
1395       *
1396       * @since 1.8.0
1397       *
1398       * @param array $meta_query An array of meta_query filters. See the
1399       *                          documentation for {@link WP_Meta_Query} for details.
1400       * @return array $sql_array 'join' and 'where' clauses.
1401       */
1402  	protected static function get_meta_query_sql( $meta_query = array() ) {
1403          global $wpdb;
1404  
1405          $sql_array = array(
1406              'join'  => '',
1407              'where' => '',
1408          );
1409  
1410          if ( ! empty( $meta_query ) ) {
1411              $groups_meta_query = new WP_Meta_Query( $meta_query );
1412  
1413              // WP_Meta_Query expects the table name at
1414              // $wpdb->group.
1415              $wpdb->groupmeta = buddypress()->groups->table_name_groupmeta;
1416  
1417              $meta_sql = $groups_meta_query->get_sql( 'group', 'g', 'id' );
1418              $sql_array['join']  = $meta_sql['join'];
1419              $sql_array['where'] = self::strip_leading_and( $meta_sql['where'] );
1420          }
1421  
1422          return $sql_array;
1423      }
1424  
1425      /**
1426       * Convert the 'type' parameter to 'order' and 'orderby'.
1427       *
1428       * @since 1.8.0
1429       *
1430       * @param string $type The 'type' shorthand param.
1431       *
1432       * @return array {
1433       *     @type string $order   SQL-friendly order string.
1434       *     @type string $orderby SQL-friendly orderby column name.
1435       * }
1436       */
1437  	protected static function convert_type_to_order_orderby( $type = '' ) {
1438          $order = $orderby = '';
1439  
1440          switch ( $type ) {
1441              case 'newest' :
1442                  $order   = 'DESC';
1443                  $orderby = 'date_created';
1444                  break;
1445  
1446              case 'active' :
1447                  $order   = 'DESC';
1448                  $orderby = 'last_activity';
1449                  break;
1450  
1451              case 'popular' :
1452                  $order   = 'DESC';
1453                  $orderby = 'total_member_count';
1454                  break;
1455  
1456              case 'alphabetical' :
1457                  $order   = 'ASC';
1458                  $orderby = 'name';
1459                  break;
1460  
1461              case 'random' :
1462                  $order   = '';
1463                  $orderby = 'random';
1464                  break;
1465          }
1466  
1467          return array( 'order' => $order, 'orderby' => $orderby );
1468      }
1469  
1470      /**
1471       * Convert the 'orderby' param into a proper SQL term/column.
1472       *
1473       * @since 1.8.0
1474       *
1475       * @param string $orderby Orderby term as passed to get().
1476       * @return string $order_by_term SQL-friendly orderby term.
1477       */
1478  	protected static function convert_orderby_to_order_by_term( $orderby ) {
1479          $order_by_term = '';
1480  
1481          switch ( $orderby ) {
1482              case 'date_created' :
1483              default :
1484                  $order_by_term = 'g.date_created';
1485                  break;
1486  
1487              case 'last_activity' :
1488                  $order_by_term = 'gm_last_activity.meta_value';
1489                  break;
1490  
1491              case 'total_member_count' :
1492                  $order_by_term = 'CONVERT(gm_total_member_count.meta_value, SIGNED)';
1493                  break;
1494  
1495              case 'name' :
1496                  $order_by_term = 'g.name';
1497                  break;
1498  
1499              case 'random' :
1500                  $order_by_term = 'rand()';
1501                  break;
1502  
1503              case 'meta_id' :
1504                  $order_by_term = buddypress()->groups->table_name_groupmeta . '.id';
1505                  break;
1506          }
1507  
1508          return $order_by_term;
1509      }
1510  
1511      /**
1512       * Get a list of groups whose names start with a given letter.
1513       *
1514       * @since 1.6.0
1515       *
1516       * @param string            $letter          The letter.
1517       * @param int|null          $limit           Optional. The max number of results to return.
1518       *                                           Default: null (no limit).
1519       * @param int|null          $page            Optional. The page offset of results to return.
1520       *                                           Default: null (no limit).
1521       * @param bool              $populate_extras Deprecated.
1522       * @param string|array|bool $exclude         Optional. Array or comma-separated list of group
1523       *                                           IDs to exclude from results.
1524       * @return false|array {
1525       *     @type array $groups Array of group objects returned by the
1526       *                         paginated query.
1527       *     @type int   $total  Total count of all groups matching non-
1528       *                         paginated query params.
1529       * }
1530       */
1531  	public static function get_by_letter( $letter, $limit = null, $page = null, $populate_extras = true, $exclude = false ) {
1532          global $wpdb;
1533  
1534          $pag_sql = $hidden_sql = $exclude_sql = '';
1535  
1536          // Multibyte compliance.
1537          if ( function_exists( 'mb_strlen' ) ) {
1538              if ( mb_strlen( $letter, 'UTF-8' ) > 1 || is_numeric( $letter ) || !$letter ) {
1539                  return false;
1540              }
1541          } else {
1542              if ( strlen( $letter ) > 1 || is_numeric( $letter ) || !$letter ) {
1543                  return false;
1544              }
1545          }
1546  
1547          $args = array(
1548              'per_page'       => $limit,
1549              'page'           => $page,
1550              'search_terms'   => $letter . '*',
1551              'search_columns' => array( 'name' ),
1552              'exclude'        => $exclude,
1553          );
1554  
1555          return BP_Groups_Group::get( $args );
1556      }
1557  
1558      /**
1559       * Get a list of random groups.
1560       *
1561       * Use BP_Groups_Group::get() with 'type' = 'random' instead.
1562       *
1563       * @since 1.6.0
1564       *
1565       * @param int|null          $limit           Optional. The max number of results to return.
1566       *                                           Default: null (no limit).
1567       * @param int|null          $page            Optional. The page offset of results to return.
1568       *                                           Default: null (no limit).
1569       * @param int               $user_id         Optional. If present, groups will be limited to
1570       *                                           those of which the specified user is a member.
1571       * @param string|bool       $search_terms    Optional. Limit groups to those whose name
1572       *                                           or description field contain the search string.
1573       * @param bool              $populate_extras Optional. Whether to fetch extra
1574       *                                           information about the groups. Default: true.
1575       * @param string|array|bool $exclude         Optional. Array or comma-separated list of group
1576       *                                           IDs to exclude from results.
1577       * @return array {
1578       *     @type array $groups Array of group objects returned by the
1579       *                         paginated query.
1580       *     @type int   $total  Total count of all groups matching non-
1581       *                         paginated query params.
1582       * }
1583       */
1584  	public static function get_random( $limit = null, $page = null, $user_id = 0, $search_terms = false, $populate_extras = true, $exclude = false ) {
1585          $args = array(
1586              'type'               => 'random',
1587              'per_page'           => $limit,
1588              'page'               => $page,
1589              'user_id'            => $user_id,
1590              'search_terms'       => $search_terms,
1591              'exclude'            => $exclude,
1592          );
1593  
1594          return BP_Groups_Group::get( $args );
1595      }
1596  
1597      /**
1598       * Fetch extra data for a list of groups.
1599       *
1600       * This method is used throughout the class, by methods that take a
1601       * $populate_extras parameter.
1602       *
1603       * Data fetched:
1604       *     - Logged-in user's status within each group (is_member,
1605       *       is_confirmed, is_pending, is_banned)
1606       *
1607       * @since 1.6.0
1608       *
1609       * @param array        $paged_groups Array of groups.
1610       * @param string|array $group_ids    Array or comma-separated list of IDs matching
1611       *                                   $paged_groups.
1612       * @param string|bool  $type         Not used.
1613       * @return array $paged_groups
1614       */
1615  	public static function get_group_extras( &$paged_groups, &$group_ids, $type = false ) {
1616          $user_id = bp_loggedin_user_id();
1617  
1618          foreach ( $paged_groups as &$group ) {
1619              $group->is_member  = groups_is_user_member( $user_id, $group->id )  ? 1 : 0;
1620              $group->is_invited = groups_is_user_invited( $user_id, $group->id ) ? 1 : 0;
1621              $group->is_pending = groups_is_user_pending( $user_id, $group->id ) ? 1 : 0;
1622              $group->is_banned  = (bool) groups_is_user_banned( $user_id, $group->id );
1623          }
1624  
1625          return $paged_groups;
1626      }
1627  
1628      /**
1629       * Delete all invitations to a given group.
1630       *
1631       * @since 1.6.0
1632       *
1633       * @param int $group_id ID of the group whose invitations are being deleted.
1634       * @return int|null Number of rows records deleted on success, null on
1635       *                  failure.
1636       */
1637  	public static function delete_all_invites( $group_id ) {
1638          global $wpdb;
1639  
1640          $bp = buddypress();
1641  
1642          return $wpdb->query( $wpdb->prepare( "DELETE FROM {$bp->groups->table_name_members} WHERE group_id = %d AND invite_sent = 1", $group_id ) );
1643      }
1644  
1645      /**
1646       * Get a total group count for the site.
1647       *
1648       * Will include hidden groups in the count only if
1649       * bp_current_user_can( 'bp_moderate' ).
1650       *
1651       * @since 1.6.0
1652       *
1653       * @return int Group count.
1654       */
1655  	public static function get_total_group_count() {
1656          global $wpdb;
1657  
1658          $hidden_sql = '';
1659          if ( !bp_current_user_can( 'bp_moderate' ) )
1660              $hidden_sql = "WHERE status != 'hidden'";
1661  
1662          $bp = buddypress();
1663  
1664          return $wpdb->get_var( "SELECT COUNT(id) FROM {$bp->groups->table_name} {$hidden_sql}" );
1665      }
1666  
1667      /**
1668       * Get the member count for a group.
1669       *
1670       * @since 1.6.0
1671       *
1672       * @param int $group_id Group ID.
1673       * @return int Count of confirmed members for the group.
1674       */
1675  	public static function get_total_member_count( $group_id ) {
1676          global $wpdb;
1677  
1678          $bp = buddypress();
1679  
1680          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 ) );
1681      }
1682  
1683      /**
1684       * Get an array containing ids for each group type.
1685       *
1686       * A bit of a kludge workaround for some issues
1687       * with bp_has_groups().
1688       *
1689       * @since 1.7.0
1690       *
1691       * @return array
1692       */
1693  	public static function get_group_type_ids() {
1694          global $wpdb;
1695  
1696          $bp  = buddypress();
1697          $ids = array();
1698  
1699          $ids['all']     = $wpdb->get_col( "SELECT id FROM {$bp->groups->table_name}" );
1700          $ids['public']  = $wpdb->get_col( "SELECT id FROM {$bp->groups->table_name} WHERE status = 'public'" );
1701          $ids['private'] = $wpdb->get_col( "SELECT id FROM {$bp->groups->table_name} WHERE status = 'private'" );
1702          $ids['hidden']  = $wpdb->get_col( "SELECT id FROM {$bp->groups->table_name} WHERE status = 'hidden'" );
1703  
1704          return $ids;
1705      }
1706  
1707      /**
1708       * Get SQL clause for group type(s).
1709       *
1710       * @since 2.6.0
1711       *
1712       * @param  string|array $group_types Group type(s).
1713       * @param  string       $operator    'IN' or 'NOT IN'.
1714       * @return string       $clause      SQL clause.
1715       */
1716  	protected static function get_sql_clause_for_group_types( $group_types, $operator ) {
1717          global $wpdb;
1718  
1719          // Sanitize operator.
1720          if ( 'NOT IN' !== $operator ) {
1721              $operator = 'IN';
1722          }
1723  
1724          // Parse and sanitize types.
1725          if ( ! is_array( $group_types ) ) {
1726              $group_types = preg_split( '/[,\s+]/', $group_types );
1727          }
1728  
1729          $types = array();
1730          foreach ( $group_types as $gt ) {
1731              if ( bp_groups_get_group_type_object( $gt ) ) {
1732                  $types[] = $gt;
1733              }
1734          }
1735  
1736          $tax_query = new WP_Tax_Query( array(
1737              array(
1738                  'taxonomy' => 'bp_group_type',
1739                  'field'    => 'name',
1740                  'operator' => $operator,
1741                  'terms'    => $types,
1742              ),
1743          ) );
1744  
1745          $site_id  = bp_get_taxonomy_term_site_id( 'bp_group_type' );
1746          $switched = false;
1747          if ( $site_id !== get_current_blog_id() ) {
1748              switch_to_blog( $site_id );
1749              $switched = true;
1750          }
1751  
1752          $sql_clauses = $tax_query->get_sql( 'g', 'id' );
1753  
1754          $clause = '';
1755  
1756          // The no_results clauses are the same between IN and NOT IN.
1757          if ( false !== strpos( $sql_clauses['where'], '0 = 1' ) ) {
1758              $clause = self::strip_leading_and( $sql_clauses['where'] );
1759  
1760          // The tax_query clause generated for NOT IN can be used almost as-is.
1761          } elseif ( 'NOT IN' === $operator ) {
1762              $clause = self::strip_leading_and( $sql_clauses['where'] );
1763  
1764          // IN clauses must be converted to a subquery.
1765          } elseif ( preg_match( '/' . $wpdb->term_relationships . '\.term_taxonomy_id IN \([0-9, ]+\)/', $sql_clauses['where'], $matches ) ) {
1766              $clause = " g.id IN ( SELECT object_id FROM $wpdb->term_relationships WHERE {$matches[0]} )";
1767          }
1768  
1769          if ( $switched ) {
1770              restore_current_blog();
1771          }
1772  
1773          return $clause;
1774      }
1775  
1776      /**
1777       * Strips the leading AND and any surrounding whitespace from a string.
1778       *
1779       * Used here to normalize SQL fragments generated by `WP_Meta_Query` and
1780       * other utility classes.
1781       *
1782       * @since 2.7.0
1783       *
1784       * @param string $s String.
1785       * @return string
1786       */
1787  	protected static function strip_leading_and( $s ) {
1788          return preg_replace( '/^\s*AND\s*/', '', $s );
1789      }
1790  }


Generated: Tue Jul 16 01:01:43 2019 Cross-referenced by PHPXref 0.7.1