/wp-content/plugins/bbpress/includes/common/engagements.php

https://github.com/livinglab/openlab · PHP · 963 lines · 307 code · 120 blank · 536 comment · 17 complexity · 288ecefb57b8b69737e5aedbd329d7d1 MD5 · raw file

  1. <?php
  2. /**
  3. * bbPress Common Engagements
  4. *
  5. * This file contains the common classes and functions for interacting with the
  6. * bbPress engagements API. See `includes/users/engagements.php` for more.
  7. *
  8. * @package bbPress
  9. * @subpackage Common
  10. */
  11. // Exit if accessed directly
  12. defined( 'ABSPATH' ) || exit;
  13. /**
  14. * Return the strategy used for storing user engagements
  15. *
  16. * @since 2.6.0 bbPress (r6722)
  17. *
  18. * @param string $rel_key The key used to index this relationship
  19. * @param string $rel_type The type of meta to look in
  20. *
  21. * @return string
  22. */
  23. function bbp_user_engagements_interface( $rel_key = '', $rel_type = 'post' ) {
  24. return apply_filters( 'bbp_user_engagements_interface', bbpress()->engagements, $rel_key, $rel_type );
  25. }
  26. /**
  27. * Base strategy class for interfacing with User Engagements, which other
  28. * classes will extend.
  29. *
  30. * @since 2.6.0 bbPress (r6722)
  31. */
  32. class BBP_User_Engagements_Base {
  33. /**
  34. * Type of strategy being used.
  35. *
  36. * @since 2.6.0 bbPress (r6737)
  37. *
  38. * @var string
  39. */
  40. public $type = '';
  41. /**
  42. * Add a user id to an object
  43. *
  44. * @since 2.6.0 bbPress (r6722)
  45. *
  46. * @param int $object_id The object id
  47. * @param int $user_id The user id
  48. * @param string $meta_key The relationship key
  49. * @param string $meta_type The relationship type (usually 'post')
  50. * @param bool $unique Whether meta key should be unique to the object
  51. *
  52. * @return bool Returns true on success, false on failure
  53. */
  54. public function add_user_to_object( $object_id = 0, $user_id = 0, $meta_key = '', $meta_type = 'post', $unique = false ) {
  55. }
  56. /**
  57. * Remove a user id from an object
  58. *
  59. * @since 2.6.0 bbPress (r6722)
  60. *
  61. * @param int $object_id The object id
  62. * @param int $user_id The user id
  63. * @param string $meta_key The relationship key
  64. * @param string $meta_type The relationship type (usually 'post')
  65. *
  66. * @return bool Returns true on success, false on failure
  67. */
  68. public function remove_user_from_object( $object_id = 0, $user_id = 0, $meta_key = '', $meta_type = 'post' ) {
  69. }
  70. /**
  71. * Remove a user id from all objects
  72. *
  73. * @since 2.6.0 bbPress (r6722)
  74. *
  75. * @param int $user_id The user id
  76. * @param string $meta_key The relationship key
  77. * @param string $meta_type The relationship type (usually 'post')
  78. *
  79. * @return bool Returns true on success, false on failure
  80. */
  81. public function remove_user_from_all_objects( $user_id = 0, $meta_key = '', $meta_type = 'post' ) {
  82. }
  83. /**
  84. * Remove an object from all users
  85. *
  86. * @since 2.6.0 bbPress (r6722)
  87. *
  88. * @param int $object_id The object id
  89. * @param int $user_id The user id
  90. * @param string $meta_key The relationship key
  91. * @param string $meta_type The relationship type (usually 'post')
  92. *
  93. * @return bool Returns true on success, false on failure
  94. */
  95. public function remove_object_from_all_users( $object_id = 0, $meta_key = '', $meta_type = 'post' ) {
  96. }
  97. /**
  98. * Remove all users from all objects
  99. *
  100. * @since 2.6.0 bbPress (r6722)
  101. *
  102. * @param string $meta_key The relationship key
  103. * @param string $meta_type The relationship type (usually 'post')
  104. *
  105. * @return bool Returns true on success, false on failure
  106. */
  107. public function remove_all_users_from_all_objects( $meta_key = '', $meta_type = 'post' ) {
  108. }
  109. /**
  110. * Get users of an object
  111. *
  112. * @since 2.6.0 bbPress (r6722)
  113. *
  114. * @param int $object_id The object id
  115. * @param string $meta_key The key used to index this relationship
  116. * @param string $meta_type The type of meta to look in
  117. *
  118. * @return array Returns ids of users
  119. */
  120. public function get_users_for_object( $object_id = 0, $meta_key = '', $meta_type = 'post' ) {
  121. }
  122. /**
  123. * Get the part of the query responsible for JOINing objects to relationships.
  124. *
  125. * @since 2.6.0 bbPress (r6737)
  126. *
  127. * @param array $args
  128. * @param string $meta_key
  129. * @param string $meta_type
  130. *
  131. * @return array
  132. */
  133. public function get_query( $args = array(), $context_key = '', $meta_key = '', $meta_type = 'post' ) {
  134. }
  135. }
  136. /**
  137. * Meta strategy for interfacing with User Engagements
  138. *
  139. * @since 2.6.0 bbPress (r6722)
  140. */
  141. class BBP_User_Engagements_Meta extends BBP_User_Engagements_Base {
  142. /**
  143. * Type of strategy being used.
  144. *
  145. * @since 2.6.0 bbPress (r6737)
  146. *
  147. * @var string
  148. */
  149. public $type = 'meta';
  150. /**
  151. * Add a user id to an object
  152. *
  153. * @since 2.6.0 bbPress (r6722)
  154. *
  155. * @param int $object_id The object id
  156. * @param int $user_id The user id
  157. * @param string $meta_key The relationship key
  158. * @param string $meta_type The relationship type (usually 'post')
  159. * @param bool $unique Whether meta key should be unique to the object
  160. *
  161. * @return bool Returns true on success, false on failure
  162. */
  163. public function add_user_to_object( $object_id = 0, $user_id = 0, $meta_key = '', $meta_type = 'post', $unique = false ) {
  164. return add_metadata( $meta_type, $object_id, $meta_key, $user_id, $unique );
  165. }
  166. /**
  167. * Remove a user id from an object
  168. *
  169. * @since 2.6.0 bbPress (r6722)
  170. *
  171. * @param int $object_id The object id
  172. * @param int $user_id The user id
  173. * @param string $meta_key The relationship key
  174. * @param string $meta_type The relationship type (usually 'post')
  175. *
  176. * @return bool Returns true on success, false on failure
  177. */
  178. public function remove_user_from_object( $object_id = 0, $user_id = 0, $meta_key = '', $meta_type = 'post' ) {
  179. return delete_metadata( $meta_type, $object_id, $meta_key, $user_id, false );
  180. }
  181. /**
  182. * Remove a user id from all objects
  183. *
  184. * @since 2.6.0 bbPress (r6722)
  185. *
  186. * @param int $user_id The user id
  187. * @param string $meta_key The relationship key
  188. * @param string $meta_type The relationship type (usually 'post')
  189. *
  190. * @return bool Returns true on success, false on failure
  191. */
  192. public function remove_user_from_all_objects( $user_id = 0, $meta_key = '', $meta_type = 'post' ) {
  193. return delete_metadata( $meta_type, null, $meta_key, $user_id, true );
  194. }
  195. /**
  196. * Remove an object from all users
  197. *
  198. * @since 2.6.0 bbPress (r6722)
  199. *
  200. * @param int $object_id The object id
  201. * @param int $user_id The user id
  202. * @param string $meta_key The relationship key
  203. * @param string $meta_type The relationship type (usually 'post')
  204. *
  205. * @return bool Returns true on success, false on failure
  206. */
  207. public function remove_object_from_all_users( $object_id = 0, $meta_key = '', $meta_type = 'post' ) {
  208. return delete_metadata( $meta_type, $object_id, $meta_key, null, false );
  209. }
  210. /**
  211. * Remove all users from all objects
  212. *
  213. * @since 2.6.0 bbPress (r6722)
  214. *
  215. * @param string $meta_key The relationship key
  216. * @param string $meta_type The relationship type (usually 'post')
  217. *
  218. * @return bool Returns true on success, false on failure
  219. */
  220. public function remove_all_users_from_all_objects( $meta_key = '', $meta_type = 'post' ) {
  221. return delete_metadata( $meta_type, null, $meta_key, null, true );
  222. }
  223. /**
  224. * Get users of an object
  225. *
  226. * @since 2.6.0 bbPress (r6722)
  227. *
  228. * @param int $object_id The object id
  229. * @param string $meta_key The key used to index this relationship
  230. * @param string $meta_type The type of meta to look in
  231. *
  232. * @return array Returns ids of users
  233. */
  234. public function get_users_for_object( $object_id = 0, $meta_key = '', $meta_type = 'post' ) {
  235. return wp_parse_id_list( get_metadata( $meta_type, $object_id, $meta_key, false ) );
  236. }
  237. /**
  238. * Get the part of the query responsible for JOINing objects to relationships.
  239. *
  240. * @since 2.6.0 bbPress (r6737)
  241. *
  242. * @param array $args
  243. * @param string $meta_key
  244. * @param string $meta_type
  245. *
  246. * @return array
  247. */
  248. public function get_query( $args = array(), $context_key = '', $meta_key = '', $meta_type = 'post' ) {
  249. // Backwards compat for pre-2.6.0
  250. if ( is_numeric( $args ) ) {
  251. $args = array(
  252. 'meta_query' => array( array(
  253. 'key' => $meta_key,
  254. 'value' => bbp_get_user_id( $args, false, false ),
  255. 'compare' => 'NUMERIC'
  256. ) )
  257. );
  258. }
  259. // Default arguments
  260. $defaults = array(
  261. 'meta_query' => array( array(
  262. 'key' => $meta_key,
  263. 'value' => bbp_get_displayed_user_id(),
  264. 'compare' => 'NUMERIC'
  265. ) )
  266. );
  267. // Parse arguments
  268. return bbp_parse_args( $args, $defaults, $context_key );
  269. }
  270. }
  271. /**
  272. * Term strategy for interfacing with User Engagements
  273. *
  274. * @since 2.6.0 bbPress (r6737)
  275. */
  276. class BBP_User_Engagements_Term extends BBP_User_Engagements_Base {
  277. /**
  278. * Type of strategy being used.
  279. *
  280. * @since 2.6.0 bbPress (r6737)
  281. *
  282. * @var string
  283. */
  284. public $type = 'term';
  285. /**
  286. * Register an engagement taxonomy just-in-time for immediate use
  287. *
  288. * @since 2.6.0 bbPress (r6737)
  289. *
  290. * @param string $tax_key
  291. * @param string $object_type
  292. */
  293. private function jit_taxonomy( $tax_key = '', $object_type = 'user' ) {
  294. // Bail if taxonomy already exists
  295. if ( taxonomy_exists( $tax_key ) ) {
  296. return;
  297. }
  298. // Register the taxonomy
  299. register_taxonomy( $tax_key, 'bbp_' . $object_type, array(
  300. 'labels' => array(),
  301. 'description' => '',
  302. 'public' => false,
  303. 'publicly_queryable' => false,
  304. 'hierarchical' => false,
  305. 'show_ui' => false,
  306. 'show_in_menu' => false,
  307. 'show_in_nav_menus' => false,
  308. 'show_tagcloud' => false,
  309. 'show_in_quick_edit' => false,
  310. 'show_admin_column' => false,
  311. 'meta_box_cb' => false,
  312. 'capabilities' => array(),
  313. 'rewrite' => false,
  314. 'query_var' => '',
  315. 'update_count_callback' => '',
  316. 'show_in_rest' => false,
  317. 'rest_base' => false,
  318. 'rest_controller_class' => false,
  319. '_builtin' => false
  320. ) );
  321. }
  322. /**
  323. * Add a user id to an object
  324. *
  325. * @since 2.6.0 bbPress (r6737)
  326. *
  327. * @param int $object_id The object id
  328. * @param int $user_id The user id
  329. * @param string $meta_key The relationship key
  330. * @param string $meta_type The relationship type (usually 'post')
  331. * @param bool $unique Whether meta key should be unique to the object
  332. *
  333. * @return bool Returns true on success, false on failure
  334. */
  335. public function add_user_to_object( $object_id = 0, $user_id = 0, $meta_key = '', $meta_type = 'post', $unique = false ) {
  336. $user_key = "{$meta_key}_user_id_{$user_id}";
  337. $tax_key = "{$meta_key}_{$meta_type}";
  338. $this->jit_taxonomy( $tax_key );
  339. return wp_add_object_terms( $object_id, $user_key, $tax_key );
  340. }
  341. /**
  342. * Remove a user id from an object
  343. *
  344. * @since 2.6.0 bbPress (r6737)
  345. *
  346. * @param int $object_id The object id
  347. * @param int $user_id The user id
  348. * @param string $meta_key The relationship key
  349. * @param string $meta_type The relationship type (usually 'post')
  350. *
  351. * @return bool Returns true on success, false on failure
  352. */
  353. public function remove_user_from_object( $object_id = 0, $user_id = 0, $meta_key = '', $meta_type = 'post' ) {
  354. $user_key = "{$meta_key}_user_id_{$user_id}";
  355. $tax_key = "{$meta_key}_{$meta_type}";
  356. $this->jit_taxonomy( $tax_key );
  357. return wp_remove_object_terms( $object_id, $user_key, $tax_key );
  358. }
  359. /**
  360. * Remove a user id from all objects
  361. *
  362. * @since 2.6.0 bbPress (r6737)
  363. *
  364. * @param int $user_id The user id
  365. * @param string $meta_key The relationship key
  366. * @param string $meta_type The relationship type (usually 'post')
  367. *
  368. * @return bool Returns true on success, false on failure
  369. */
  370. public function remove_user_from_all_objects( $user_id = 0, $meta_key = '', $meta_type = 'post' ) {
  371. $user_key = "{$meta_key}_user_id_{$user_id}";
  372. $tax_key = "{$meta_key}_{$meta_type}";
  373. $this->jit_taxonomy( $tax_key );
  374. $term = get_term_by( 'slug', $user_key, $tax_key );
  375. return wp_delete_term( $term->term_id, $tax_key );
  376. }
  377. /**
  378. * Remove an object from all users
  379. *
  380. * @since 2.6.0 bbPress (r6737)
  381. *
  382. * @param int $object_id The object id
  383. * @param int $user_id The user id
  384. * @param string $meta_key The relationship key
  385. * @param string $meta_type The relationship type (usually 'post')
  386. *
  387. * @return bool Returns true on success, false on failure
  388. */
  389. public function remove_object_from_all_users( $object_id = 0, $meta_key = '', $meta_type = 'post' ) {
  390. return wp_delete_object_term_relationships( $object_id, get_object_taxonomies( 'bbp_user' ) );
  391. }
  392. /**
  393. * Remove all users from all objects
  394. *
  395. * @since 2.6.0 bbPress (r6737)
  396. *
  397. * @param string $meta_key The relationship key
  398. * @param string $meta_type The relationship type (usually 'post')
  399. *
  400. * @return bool Returns true on success, false on failure
  401. */
  402. public function remove_all_users_from_all_objects( $meta_key = '', $meta_type = 'post' ) {
  403. // TODO
  404. }
  405. /**
  406. * Get users of an object
  407. *
  408. * @since 2.6.0 bbPress (r6737)
  409. *
  410. * @param int $object_id The object id
  411. * @param string $meta_key The key used to index this relationship
  412. * @param string $meta_type The type of meta to look in
  413. *
  414. * @return array Returns ids of users
  415. */
  416. public function get_users_for_object( $object_id = 0, $meta_key = '', $meta_type = 'post' ) {
  417. $user_key = "{$meta_key}_user_id_";
  418. $tax_key = "{$meta_key}_{$meta_type}";
  419. $this->jit_taxonomy( $tax_key );
  420. // Get terms
  421. $terms = get_terms( array(
  422. 'object_ids' => $object_id,
  423. 'taxonomy' => $tax_key
  424. ) );
  425. // Slug part to replace
  426. $user_ids = array();
  427. // Loop through terms and get the user ID
  428. foreach ( $terms as $term ) {
  429. $user_ids[] = str_replace( $user_key, '', $term->slug );
  430. }
  431. // Parse & return
  432. return wp_parse_id_list( $user_ids );
  433. }
  434. /**
  435. * Get the part of the query responsible for JOINing objects to relationships.
  436. *
  437. * @since 2.6.0 bbPress (r6737)
  438. *
  439. * @param array $args
  440. * @param string $meta_key
  441. * @param string $meta_type
  442. *
  443. * @return array
  444. */
  445. public function get_query( $args = array(), $context_key = '', $meta_key = '', $meta_type = 'post' ) {
  446. $tax_key = "{$meta_key}_{$meta_type}";
  447. $user_key = "{$meta_key}_user_id_";
  448. // Make sure the taxonomy is registered
  449. $this->jit_taxonomy( $tax_key );
  450. // Backwards compat for pre-2.6.0
  451. if ( is_numeric( $args ) ) {
  452. $args = array(
  453. 'tax_query' => array( array(
  454. 'taxonomy' => $tax_key,
  455. 'terms' => $user_key . bbp_get_user_id( $args, false, false ),
  456. 'field' => 'slug'
  457. ) )
  458. );
  459. }
  460. // Default arguments
  461. $defaults = array(
  462. 'tax_query' => array( array(
  463. 'taxonomy' => $tax_key,
  464. 'terms' => $user_key . bbp_get_displayed_user_id(),
  465. 'field' => 'slug'
  466. ) )
  467. );
  468. // Parse arguments
  469. return bbp_parse_args( $args, $defaults, $context_key );
  470. }
  471. }
  472. /**
  473. * User strategy for interfacing with User Engagements
  474. *
  475. * This strategy largely exists for backwards compatibility with bbPress 2.5,
  476. * or installations that have not upgraded their databases to 2.6 or above.
  477. *
  478. * Note: this strategy is going to be a bit less tidy than the others, because
  479. * it needs to do weird things to maintain the 2.5 status-quo. Do not use this
  480. * strategy as an example when building your own.
  481. *
  482. * @since 2.6.0 bbPress (r6844)
  483. */
  484. class BBP_User_Engagements_User extends BBP_User_Engagements_Base {
  485. /**
  486. * Type of strategy being used.
  487. *
  488. * @since 2.6.0 bbPress (r6844)
  489. *
  490. * @var string
  491. */
  492. public $type = 'user';
  493. /**
  494. * Private function to map 2.6 meta keys to 2.5 user-option keys.
  495. *
  496. * @since 2.6.0 bbPress (r6844)
  497. *
  498. * @param string $meta_key
  499. * @param int $object_id
  500. * @param bool $prefix
  501. *
  502. * @return string
  503. */
  504. private function get_user_option_key( $meta_key = '', $object_id = 0, $prefix = false ) {
  505. switch ( $meta_key ) {
  506. // Favorites
  507. case '_bbp_favorite' :
  508. $key = '_bbp_favorites';
  509. break;
  510. // Subscriptions
  511. case '_bbp_subscription' :
  512. // Maybe guess at post type
  513. $post_type = ! empty( $object_id )
  514. ? get_post_type( $object_id )
  515. : bbp_get_topic_post_type();
  516. // Forums & Topics used different keys :/
  517. $key = ( bbp_get_forum_post_type() === $post_type )
  518. ? '_bbp_forum_subscriptions'
  519. : '_bbp_subscriptions';
  520. break;
  521. // Unknown, so pluralize
  522. default :
  523. $key = "{$meta_key}s";
  524. break;
  525. }
  526. // Maybe prefix the key (for use in raw database queries)
  527. if ( true === $prefix ) {
  528. $key = bbp_db()->get_blog_prefix() . $key;
  529. }
  530. // Return the old (pluralized) user option key
  531. return $key;
  532. }
  533. /**
  534. * Private function to get a 2.5 compatible cache key.
  535. *
  536. * This method exists to provide backwards compatibility with bbPress 2.5,
  537. * which had caching surrounding the FIND_IN_SET usermeta queries.
  538. *
  539. * @since 2.6.3 bbPress (r6991)
  540. *
  541. * @param string $meta_key
  542. * @param int $object_id
  543. *
  544. * @return string
  545. */
  546. private function get_cache_key( $meta_key = '', $object_id = 0 ) {
  547. // No negative numbers in cache keys (zero is weird, but not disallowed)
  548. $object_id = absint( $object_id );
  549. // Maybe guess at post type
  550. $post_type = ! empty( $object_id )
  551. ? get_post_type( $object_id )
  552. : bbp_get_topic_post_type();
  553. switch ( $meta_key ) {
  554. // Favorites
  555. case '_bbp_favorite' :
  556. $key = 'bbp_get_topic_favoriters_';
  557. break;
  558. // Subscriptions
  559. case '_bbp_subscription' :
  560. // Forums & Topics used different keys :/
  561. $key = ( bbp_get_forum_post_type() === $post_type )
  562. ? 'bbp_get_forum_subscribers_'
  563. : 'bbp_get_topic_subscribers_';
  564. break;
  565. // Unknown, so pluralize
  566. default :
  567. $nounize = rtrim( $meta_key, 'e' );
  568. $key = "bbp_get_{$post_type}_{$nounize}ers_";
  569. break;
  570. }
  571. // Return the old (pluralized) user option key with object ID appended
  572. return "{$key}{$object_id}";
  573. }
  574. /**
  575. * Get the user engagement cache for a given meta key and object ID.
  576. *
  577. * This method exists to provide backwards compatibility with bbPress 2.5,
  578. * which had caching surrounding the FIND_IN_SET queries in usermeta.
  579. *
  580. * @since 2.6.3 bbPress (r6991)
  581. *
  582. * @param string $meta_key
  583. * @param int $object_id
  584. *
  585. * @return mixed Results from cache get
  586. */
  587. private function cache_get( $meta_key = '', $object_id = 0 ) {
  588. $cache_key = $this->get_cache_key( $meta_key, $object_id );
  589. return wp_cache_get( $cache_key, 'bbpress_engagements' );
  590. }
  591. /**
  592. * Set the user engagement cache for a given meta key and object ID.
  593. *
  594. * This method exists to provide backwards compatibility with bbPress 2.5,
  595. * which had caching surrounding the FIND_IN_SET queries in usermeta.
  596. *
  597. * @since 2.6.3 bbPress (r6991)
  598. *
  599. * @param string $meta_key
  600. * @param int $object_id
  601. *
  602. * @return mixed Results from cache set
  603. */
  604. private function cache_set( $meta_key = '', $object_id = 0, $user_ids = array() ) {
  605. $cache_key = $this->get_cache_key( $meta_key, $object_id );
  606. $user_ids = $this->parse_comma_list( $user_ids );
  607. return wp_cache_set( $cache_key, $user_ids, 'bbpress_engagements' );
  608. }
  609. /**
  610. * Delete the user engagement cache for a given meta key and object ID.
  611. *
  612. * This method exists to provide backwards compatibility with bbPress 2.5,
  613. * which had caching surrounding the FIND_IN_SET queries in usermeta.
  614. *
  615. * @since 2.6.3 bbPress (r6991)
  616. *
  617. * @param string $meta_key
  618. * @param int $object_id
  619. *
  620. * @return mixed Results from cache delete
  621. */
  622. private function cache_delete( $meta_key = '', $object_id = 0 ) {
  623. $cache_key = $this->get_cache_key( $meta_key, $object_id );
  624. return wp_cache_delete( $cache_key, 'bbpress_engagements' );
  625. }
  626. /**
  627. * Turn a comma-separated string into an array of integers
  628. *
  629. * @since 2.6.0 bbPress (r6844)
  630. *
  631. * @param string $results
  632. * @return array
  633. */
  634. private function parse_comma_list( $results = '' ) {
  635. return array_filter( wp_parse_id_list( $results ) );
  636. }
  637. /**
  638. * Add a user id to an object
  639. *
  640. * @since 2.6.0 bbPress (r6844)
  641. *
  642. * @param int $object_id The object id
  643. * @param int $user_id The user id
  644. * @param string $meta_key The relationship key
  645. * @param string $meta_type The relationship type (usually 'post')
  646. * @param bool $unique Whether meta key should be unique to the object
  647. *
  648. * @return bool Returns true on success, false on failure
  649. */
  650. public function add_user_to_object( $object_id = 0, $user_id = 0, $meta_key = '', $meta_type = 'post', $unique = false ) {
  651. $retval = false;
  652. $option_key = $this->get_user_option_key( $meta_key, $object_id );
  653. $object_ids = $this->parse_comma_list( get_user_option( $option_key, $user_id ) );
  654. $exists = array_search( $object_id, $object_ids );
  655. // Not already added, so add it
  656. if ( false === $exists ) {
  657. $object_ids[] = $object_id;
  658. $object_ids = implode( ',', $this->parse_comma_list( $object_ids ) );
  659. $retval = update_user_option( $user_id, $option_key, $object_ids );
  660. // Delete cache if successful (accounts for int & true)
  661. if ( false !== $retval ) {
  662. $this->cache_delete( $meta_key, $object_id );
  663. }
  664. }
  665. // Return true if added, or false if not
  666. return $retval;
  667. }
  668. /**
  669. * Remove a user id from an object
  670. *
  671. * @since 2.6.0 bbPress (r6844)
  672. *
  673. * @param int $object_id The object id
  674. * @param int $user_id The user id
  675. * @param string $meta_key The relationship key
  676. * @param string $meta_type The relationship type (usually 'post')
  677. *
  678. * @return bool Returns true on success, false on failure
  679. */
  680. public function remove_user_from_object( $object_id = 0, $user_id = 0, $meta_key = '', $meta_type = 'post' ) {
  681. $retval = false;
  682. $option_key = $this->get_user_option_key( $meta_key, $object_id );
  683. $object_ids = $this->parse_comma_list( get_user_option( $option_key, $user_id ) );
  684. $exists = array_search( $object_id, $object_ids );
  685. // Exists, so remove it
  686. if ( false !== $exists ) {
  687. unset( $object_ids[ $exists ] );
  688. $object_ids = implode( ',', $this->parse_comma_list( $object_ids ) );
  689. $retval = ! empty( $object_ids )
  690. ? update_user_option( $user_id, $option_key, $object_ids )
  691. : delete_user_option( $user_id, $option_key );
  692. // Delete cache if successful (accounts for int & true)
  693. if ( false !== $retval ) {
  694. $this->cache_delete( $meta_key, $object_id );
  695. }
  696. }
  697. // Return true if removed, or false if not
  698. return $retval;
  699. }
  700. /**
  701. * Remove a user id from all objects
  702. *
  703. * @since 2.6.0 bbPress (r6844)
  704. *
  705. * @param int $user_id The user id
  706. * @param string $meta_key The relationship key
  707. * @param string $meta_type The relationship type (usually 'post')
  708. *
  709. * @return bool Returns true on success, false on failure
  710. */
  711. public function remove_user_from_all_objects( $user_id = 0, $meta_key = '', $meta_type = 'post' ) {
  712. // Get the key
  713. $option_key = $this->get_user_option_key( $meta_key );
  714. // Get the option
  715. $object_ids = $this->parse_comma_list( get_user_option( $option_key, $user_id ) );
  716. // Attempt to delete the user option
  717. $retval = delete_user_option( $user_id, $option_key );
  718. // Try to delete caches, but only if everything else succeeded
  719. if ( ! empty( $retval ) && ! empty( $object_ids ) ) {
  720. foreach ( $object_ids as $object_id ) {
  721. $this->cache_delete( $meta_key, $object_id );
  722. }
  723. }
  724. // Return true if user was removed, or false if not
  725. return $retval;
  726. }
  727. /**
  728. * Remove an object from all users
  729. *
  730. * @since 2.6.0 bbPress (r6844)
  731. *
  732. * @param int $object_id The object id
  733. * @param int $user_id The user id
  734. * @param string $meta_key The relationship key
  735. * @param string $meta_type The relationship type (usually 'post')
  736. *
  737. * @return bool Returns true on success, false on failure
  738. */
  739. public function remove_object_from_all_users( $object_id = 0, $meta_key = '', $meta_type = 'post' ) {
  740. // Query for users
  741. $user_ids = $this->get_users_for_object( $object_id, $meta_key, $meta_type );
  742. $u_count = count( $user_ids );
  743. // Count number of removals
  744. $removed = array();
  745. $r_count = 0;
  746. // Users have engaged, so remove them
  747. if ( ! empty( $u_count ) ) {
  748. // Loop through users and remove them from the object
  749. foreach ( $user_ids as $user_id ) {
  750. $removed[] = $this->remove_user_from_object( $object_id, $user_id, $meta_key, $meta_type );
  751. }
  752. // Count the removed users
  753. $r_count = count( $removed );
  754. }
  755. // Return true if successfully removed from all users
  756. return ( $r_count === $u_count );
  757. }
  758. /**
  759. * Remove all users from all objects
  760. *
  761. * @since 2.6.0 bbPress (r6844)
  762. *
  763. * @param string $meta_key The relationship key
  764. * @param string $meta_type The relationship type (usually 'post')
  765. *
  766. * @return bool Returns true on success, false on failure
  767. */
  768. public function remove_all_users_from_all_objects( $meta_key = '', $meta_type = 'post' ) {
  769. // Query for users
  770. $option_key = $this->get_user_option_key( $meta_key, 0, true );
  771. $bbp_db = bbp_db();
  772. $user_ids = $bbp_db->get_col( "SELECT user_id FROM {$bbp_db->usermeta} WHERE meta_key = '{$option_key}'" );
  773. $u_count = count( $user_ids );
  774. // Count number of removals
  775. $removed = array();
  776. $r_count = 0;
  777. // Users have engaged, so remove them
  778. if ( ! empty( $u_count ) ) {
  779. // Loop through users and remove their user options
  780. foreach ( $user_ids as $user_id ) {
  781. $removed[] = $this->remove_user_from_all_objects( $user_id, $meta_key );
  782. }
  783. // Count the removed users
  784. $r_count = count( $removed );
  785. }
  786. // Return true if successfully removed from all users
  787. return ( $r_count === $u_count );
  788. }
  789. /**
  790. * Get users of an object
  791. *
  792. * The database queries in this function were cached in bbPress versions
  793. * older than 2.6, but no longer are to avoid cache pollution.
  794. *
  795. * @since 2.6.0 bbPress (r6844)
  796. *
  797. * @param int $object_id The object id
  798. * @param string $meta_key The key used to index this relationship
  799. * @param string $meta_type The type of meta to look in
  800. *
  801. * @return array Returns ids of users
  802. */
  803. public function get_users_for_object( $object_id = 0, $meta_key = '', $meta_type = 'post' ) {
  804. // Try to get user IDs from cache
  805. $user_ids = $this->cache_get( $meta_key, $object_id );
  806. // Cache is empty, so hit the database
  807. if ( false === $user_ids ) {
  808. $option_key = $this->get_user_option_key( $meta_key, $object_id, true );
  809. $bbp_db = bbp_db();
  810. $user_ids = $bbp_db->get_col( "SELECT user_id FROM {$bbp_db->usermeta} WHERE meta_key = '{$option_key}' and FIND_IN_SET('{$object_id}', meta_value) > 0" );
  811. // Always cache results (even if empty, to prevent multiple misses)
  812. $this->cache_set( $meta_key, $object_id, $user_ids );
  813. }
  814. // Return parsed IDs
  815. return $this->parse_comma_list( $user_ids );
  816. }
  817. /**
  818. * Get the part of the query responsible for JOINing objects to relationships.
  819. *
  820. * @since 2.6.0 bbPress (r6844)
  821. *
  822. * @param array $args
  823. * @param string $meta_key
  824. * @param string $meta_type
  825. *
  826. * @return array
  827. */
  828. public function get_query( $args = array(), $context_key = '', $meta_key = '', $meta_type = 'post' ) {
  829. $user_id = bbp_get_user_id( $args, true, true );
  830. $option_key = $this->get_user_option_key( $meta_key );
  831. $object_ids = $this->parse_comma_list( get_user_option( $option_key, $user_id ) );
  832. // Maybe trick WP_Query into ".ID IN (0)" to return no results
  833. if ( empty( $object_ids ) ) {
  834. $object_ids = array( 0 );
  835. }
  836. // Maybe include these post IDs
  837. $args = array(
  838. 'post__in' => $object_ids
  839. );
  840. // Parse arguments
  841. return bbp_parse_args( $args, array(), $context_key );
  842. }
  843. }