/bp-groups/classes/class-bp-groups-group.php

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