[ Index ] |
PHP Cross Reference of BuddyPress |
[Summary view] [Print] [Text view]
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_get_group_type_tax_name(), 1750 'field' => 'name', 1751 'operator' => $operator, 1752 'terms' => $types, 1753 ), 1754 ) ); 1755 1756 $site_id = bp_get_taxonomy_term_site_id( bp_get_group_type_tax_name() ); 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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Mon Jan 18 01:01:36 2021 | Cross-referenced by PHPXref 0.7.1 |