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