BP_Notifications_Notification

BuddyPress Notification items.

Defined (1)

The class is defined in the following location(s).

/bp-notifications/classes/class-bp-notifications-notification.php  
  1. class BP_Notifications_Notification { 
  2.  
  3. /** 
  4. * The notification ID. 
  5. * @since 1.9.0 
  6. * @var int 
  7. */ 
  8. public $id; 
  9.  
  10. /** 
  11. * The ID of the item associated with the notification. 
  12. * @since 1.9.0 
  13. * @var int 
  14. */ 
  15. public $item_id; 
  16.  
  17. /** 
  18. * The ID of the secondary item associated with the notification. 
  19. * @since 1.9.0 
  20. * @var int 
  21. */ 
  22. public $secondary_item_id = null; 
  23.  
  24. /** 
  25. * The ID of the user the notification is associated with. 
  26. * @since 1.9.0 
  27. * @var int 
  28. */ 
  29. public $user_id; 
  30.  
  31. /** 
  32. * The name of the component that the notification is for. 
  33. * @since 1.9.0 
  34. * @var string 
  35. */ 
  36. public $component_name; 
  37.  
  38. /** 
  39. * The component action which the notification is related to. 
  40. * @since 1.9.0 
  41. * @var string 
  42. */ 
  43. public $component_action; 
  44.  
  45. /** 
  46. * The date the notification was created. 
  47. * @since 1.9.0 
  48. * @var string 
  49. */ 
  50. public $date_notified; 
  51.  
  52. /** 
  53. * Is the notification new, or has it already been read. 
  54. * @since 1.9.0 
  55. * @var bool 
  56. */ 
  57. public $is_new; 
  58.  
  59. /** Public Methods ********************************************************/ 
  60.  
  61. /** 
  62. * Constructor method. 
  63. * @since 1.9.0 
  64. * @param int $id Optional. Provide an ID to access an existing 
  65. * notification item. 
  66. */ 
  67. public function __construct( $id = 0 ) { 
  68. if ( ! empty( $id ) ) { 
  69. $this->id = (int) $id; 
  70. $this->populate(); 
  71.  
  72. /** 
  73. * Update or insert notification details into the database. 
  74. * @since 1.9.0 
  75. * @global wpdb $wpdb WordPress database object. 
  76. * @return bool True on success, false on failure. 
  77. */ 
  78. public function save() { 
  79. $retval = false; 
  80.  
  81. /** 
  82. * Fires before the current notification item gets saved. 
  83. * Please use this hook to filter the properties above. Each part will be passed in. 
  84. * @since 2.0.0 
  85. * @param BP_Notifications_Notification $value Current instance of the notification item being saved. Passed by reference. 
  86. */ 
  87. do_action_ref_array( 'bp_notification_before_save', array( &$this ) ); 
  88.  
  89. $data = array( 
  90. 'user_id' => $this->user_id,  
  91. 'item_id' => $this->item_id,  
  92. 'secondary_item_id' => $this->secondary_item_id,  
  93. 'component_name' => $this->component_name,  
  94. 'component_action' => $this->component_action,  
  95. 'date_notified' => $this->date_notified,  
  96. 'is_new' => $this->is_new,  
  97. ); 
  98. $data_format = array( '%d', '%d', '%d', '%s', '%s', '%s', '%d' ); 
  99.  
  100. // Update. 
  101. if ( ! empty( $this->id ) ) { 
  102. $result = self::_update( $data, array( 'ID' => $this->id ), $data_format, array( '%d' ) ); 
  103.  
  104. // Insert. 
  105. } else { 
  106. $result = self::_insert( $data, $data_format ); 
  107.  
  108. // Set the notification ID if successful. 
  109. if ( ! empty( $result ) && ! is_wp_error( $result ) ) { 
  110. global $wpdb; 
  111.  
  112. $this->id = $wpdb->insert_id; 
  113. $retval = $wpdb->insert_id; 
  114.  
  115. /** 
  116. * Fires after the current notification item gets saved. 
  117. * @since 2.0.0 
  118. * @param BP_Notifications_Notification $value Current instance of the notification item being saved. 
  119. * Passed by reference. 
  120. */ 
  121. do_action_ref_array( 'bp_notification_after_save', array( &$this ) ); 
  122.  
  123. // Return the result. 
  124. return $retval; 
  125.  
  126. /** 
  127. * Fetch data for an existing notification from the database. 
  128. * @since 1.9.0 
  129. * @global BuddyPress $bp The one true BuddyPress instance. 
  130. * @global wpdb $wpdb WordPress database object. 
  131. */ 
  132. public function populate() { 
  133. global $wpdb; 
  134.  
  135. $bp = buddypress(); 
  136.  
  137. // Look for a notification. 
  138. $notification = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$bp->notifications->table_name} WHERE id = %d", $this->id ) ); 
  139.  
  140. // Setup the notification data. 
  141. if ( ! empty( $notification ) && ! is_wp_error( $notification ) ) { 
  142. $this->item_id = (int) $notification->item_id; 
  143. $this->secondary_item_id = (int) $notification->secondary_item_id; 
  144. $this->user_id = (int) $notification->user_id; 
  145. $this->component_name = $notification->component_name; 
  146. $this->component_action = $notification->component_action; 
  147. $this->date_notified = $notification->date_notified; 
  148. $this->is_new = (int) $notification->is_new; 
  149.  
  150. /** Protected Static Methods **********************************************/ 
  151.  
  152. /** 
  153. * Create a notification entry. 
  154. * @since 1.9.0 
  155. * @param array $data { 
  156. * Array of notification data, passed to {@link wpdb::insert()}. 
  157. * @type int $user_id ID of the associated user. 
  158. * @type int $item_id ID of the associated item. 
  159. * @type int $secondary_item_id ID of the secondary associated item. 
  160. * @type string $component_name Name of the associated component. 
  161. * @type string $component_action Name of the associated component 
  162. * action. 
  163. * @type string $date_notified Timestamp of the notification. 
  164. * @type bool $is_new True if the notification is unread, otherwise false. 
  165. * } 
  166. * @param array $data_format See {@link wpdb::insert()}. 
  167. * @return int|false The number of rows inserted, or false on error. 
  168. */ 
  169. protected static function _insert( $data = array(), $data_format = array() ) { 
  170. global $wpdb; 
  171. return $wpdb->insert( buddypress()->notifications->table_name, $data, $data_format ); 
  172.  
  173. /** 
  174. * Update notifications. 
  175. * @since 1.9.0 
  176. * @see wpdb::update() for further description of paramater formats. 
  177. * @param array $data Array of notification data to update, passed to 
  178. * {@link wpdb::update()}. Accepts any property of a 
  179. * BP_Notification_Notification object. 
  180. * @param array $where The WHERE params as passed to wpdb::update(). 
  181. * Typically consists of array( 'ID' => $id ) to specify the ID 
  182. * of the item being updated. See {@link wpdb::update()}. 
  183. * @param array $data_format See {@link wpdb::insert()}. 
  184. * @param array $where_format See {@link wpdb::insert()}. 
  185. * @return int|false The number of rows updated, or false on error. 
  186. */ 
  187. protected static function _update( $data = array(), $where = array(), $data_format = array(), $where_format = array() ) { 
  188. global $wpdb; 
  189. return $wpdb->update( buddypress()->notifications->table_name, $data, $where, $data_format, $where_format ); 
  190.  
  191. /** 
  192. * Delete notifications. 
  193. * @since 1.9.0 
  194. * @see wpdb::update() for further description of paramater formats. 
  195. * @param array $where Array of WHERE clauses to filter by, passed to 
  196. * {@link wpdb::delete()}. Accepts any property of a 
  197. * BP_Notification_Notification object. 
  198. * @param array $where_format See {@link wpdb::insert()}. 
  199. * @return int|false The number of rows updated, or false on error. 
  200. */ 
  201. protected static function _delete( $where = array(), $where_format = array() ) { 
  202. global $wpdb; 
  203. return $wpdb->delete( buddypress()->notifications->table_name, $where, $where_format ); 
  204.  
  205. /** 
  206. * Assemble the WHERE clause of a get() SQL statement. 
  207. * Used by BP_Notifications_Notification::get() to create its WHERE 
  208. * clause. 
  209. * @since 1.9.0 
  210. * @param array $args See {@link BP_Notifications_Notification::get()} 
  211. * for more details. 
  212. * @param string $select_sql SQL SELECT fragment. 
  213. * @param string $from_sql SQL FROM fragment. 
  214. * @param string $join_sql SQL JOIN fragment. 
  215. * @param string $meta_query_sql SQL meta query fragment. 
  216. * @return string WHERE clause. 
  217. */ 
  218. protected static function get_where_sql( $args = array(), $select_sql = '', $from_sql = '', $join_sql = '', $meta_query_sql = '' ) { 
  219. global $wpdb; 
  220.  
  221. $where_conditions = array(); 
  222. $where = ''; 
  223.  
  224. // The id. 
  225. if ( ! empty( $args['id'] ) ) { 
  226. $id_in = implode( ', ', wp_parse_id_list( $args['id'] ) ); 
  227. $where_conditions['id'] = "id IN ({$id_in})"; 
  228.  
  229. // The user_id. 
  230. if ( ! empty( $args['user_id'] ) ) { 
  231. $user_id_in = implode( ', ', wp_parse_id_list( $args['user_id'] ) ); 
  232. $where_conditions['user_id'] = "user_id IN ({$user_id_in})"; 
  233.  
  234. // The item_id. 
  235. if ( ! empty( $args['item_id'] ) ) { 
  236. $item_id_in = implode( ', ', wp_parse_id_list( $args['item_id'] ) ); 
  237. $where_conditions['item_id'] = "item_id IN ({$item_id_in})"; 
  238.  
  239. // The secondary_item_id. 
  240. if ( ! empty( $args['secondary_item_id'] ) ) { 
  241. $secondary_item_id_in = implode( ', ', wp_parse_id_list( $args['secondary_item_id'] ) ); 
  242. $where_conditions['secondary_item_id'] = "secondary_item_id IN ({$secondary_item_id_in})"; 
  243.  
  244. // The component_name. 
  245. if ( ! empty( $args['component_name'] ) ) { 
  246. if ( ! is_array( $args['component_name'] ) ) { 
  247. $component_names = explode( ', ', $args['component_name'] ); 
  248. } else { 
  249. $component_names = $args['component_name']; 
  250.  
  251. $cn_clean = array(); 
  252. foreach ( $component_names as $cn ) { 
  253. $cn_clean[] = $wpdb->prepare( '%s', $cn ); 
  254.  
  255. $cn_in = implode( ', ', $cn_clean ); 
  256. $where_conditions['component_name'] = "component_name IN ({$cn_in})"; 
  257.  
  258. // The component_action. 
  259. if ( ! empty( $args['component_action'] ) ) { 
  260. if ( ! is_array( $args['component_action'] ) ) { 
  261. $component_actions = explode( ', ', $args['component_action'] ); 
  262. } else { 
  263. $component_actions = $args['component_action']; 
  264.  
  265. $ca_clean = array(); 
  266. foreach ( $component_actions as $ca ) { 
  267. $ca_clean[] = $wpdb->prepare( '%s', $ca ); 
  268.  
  269. $ca_in = implode( ', ', $ca_clean ); 
  270. $where_conditions['component_action'] = "component_action IN ({$ca_in})"; 
  271.  
  272. // If is_new. 
  273. if ( ! empty( $args['is_new'] ) && 'both' !== $args['is_new'] ) { 
  274. $where_conditions['is_new'] = "is_new = 1"; 
  275. } elseif ( isset( $args['is_new'] ) && ( 0 === $args['is_new'] || false === $args['is_new'] ) ) { 
  276. $where_conditions['is_new'] = "is_new = 0"; 
  277.  
  278. // The search_terms. 
  279. if ( ! empty( $args['search_terms'] ) ) { 
  280. $search_terms_like = '%' . bp_esc_like( $args['search_terms'] ) . '%'; 
  281. $where_conditions['search_terms'] = $wpdb->prepare( "( component_name LIKE %s OR component_action LIKE %s )", $search_terms_like, $search_terms_like ); 
  282.  
  283. // The date query. 
  284. if ( ! empty( $args['date_query'] ) ) { 
  285. $where_conditions['date_query'] = self::get_date_query_sql( $args['date_query'] ); 
  286.  
  287. // The meta query. 
  288. if ( ! empty( $meta_query_sql['where'] ) ) { 
  289. $where_conditions['meta_query'] = $meta_query_sql['where']; 
  290.  
  291. /** 
  292. * Filters the MySQL WHERE conditions for the Notifications items get method. 
  293. * @since 2.3.0 
  294. * @param array $where_conditions Current conditions for MySQL WHERE statement. 
  295. * @param array $args Parsed arguments passed into method. 
  296. * @param string $select_sql Current SELECT MySQL statement at point of execution. 
  297. * @param string $from_sql Current FROM MySQL statement at point of execution. 
  298. * @param string $join_sql Current INNER JOIN MySQL statement at point of execution. 
  299. * @param string $meta_query_sql Current meta query WHERE statement at point of execution. 
  300. */ 
  301. $where_conditions = apply_filters( 'bp_notifications_get_where_conditions', $where_conditions, $args, $select_sql, $from_sql, $join_sql, $meta_query_sql ); 
  302.  
  303. // Custom WHERE. 
  304. if ( ! empty( $where_conditions ) ) { 
  305. $where = 'WHERE ' . implode( ' AND ', $where_conditions ); 
  306.  
  307. return $where; 
  308.  
  309. /** 
  310. * Assemble the ORDER BY clause of a get() SQL statement. 
  311. * Used by BP_Notifications_Notification::get() to create its ORDER BY 
  312. * clause. 
  313. * @since 1.9.0 
  314. * @param array $args See {@link BP_Notifications_Notification::get()} 
  315. * for more details. 
  316. * @return string ORDER BY clause. 
  317. */ 
  318. protected static function get_order_by_sql( $args = array() ) { 
  319.  
  320. // Setup local variable. 
  321. $conditions = array(); 
  322. $retval = ''; 
  323.  
  324. // Order by. 
  325. if ( ! empty( $args['order_by'] ) ) { 
  326. $order_by = implode( ', ', (array) $args['order_by'] ); 
  327. $conditions['order_by'] = "{$order_by}"; 
  328.  
  329. // Sort order direction. 
  330. if ( ! empty( $args['sort_order'] ) && in_array( $args['sort_order'], array( 'ASC', 'DESC' ) ) ) { 
  331. $sort_order = $args['sort_order']; 
  332. $conditions['sort_order'] = "{$sort_order}"; 
  333.  
  334. // Custom ORDER BY. 
  335. if ( ! empty( $conditions ) ) { 
  336. $retval = 'ORDER BY ' . implode( ' ', $conditions ); 
  337.  
  338. return $retval; 
  339.  
  340. /** 
  341. * Assemble the LIMIT clause of a get() SQL statement. 
  342. * Used by BP_Notifications_Notification::get() to create its LIMIT clause. 
  343. * @since 1.9.0 
  344. * @param array $args See {@link BP_Notifications_Notification::get()} 
  345. * for more details. 
  346. * @return string $retval LIMIT clause. 
  347. */ 
  348. protected static function get_paged_sql( $args = array() ) { 
  349. global $wpdb; 
  350.  
  351. // Setup local variable. 
  352. $retval = ''; 
  353.  
  354. // Custom LIMIT. 
  355. if ( ! empty( $args['page'] ) && ! empty( $args['per_page'] ) ) { 
  356. $page = absint( $args['page'] ); 
  357. $per_page = absint( $args['per_page'] ); 
  358. $offset = $per_page * ( $page - 1 ); 
  359. $retval = $wpdb->prepare( "LIMIT %d, %d", $offset, $per_page ); 
  360.  
  361. return $retval; 
  362.  
  363. /** 
  364. * Assemble query clauses, based on arguments, to pass to $wpdb methods. 
  365. * The insert(), update(), and delete() methods of {@link wpdb} expect 
  366. * arguments of the following forms: 
  367. * - associative arrays whose key/value pairs are column => value, to 
  368. * be used in WHERE, SET, or VALUES clauses. 
  369. * - arrays of "formats", which tell $wpdb->prepare() which type of 
  370. * value to expect when sanitizing (eg, array( '%s', '%d' )) 
  371. * This utility method can be used to assemble both kinds of params,  
  372. * out of a single set of associative array arguments, such as: 
  373. * $args = array( 
  374. * 'user_id' => 4,  
  375. * 'component_name' => 'groups',  
  376. * ); 
  377. * This will be converted to: 
  378. * array( 
  379. * 'data' => array( 
  380. * 'user_id' => 4,  
  381. * 'component_name' => 'groups',  
  382. * ),  
  383. * 'format' => array( 
  384. * '%d',  
  385. * '%s',  
  386. * ),  
  387. * ) 
  388. * which can easily be passed as arguments to the $wpdb methods. 
  389. * @since 1.9.0 
  390. * @param array $args Associative array of filter arguments. 
  391. * See {@BP_Notifications_Notification::get()} 
  392. * for a breakdown. 
  393. * @return array Associative array of 'data' and 'format' args. 
  394. */ 
  395. protected static function get_query_clauses( $args = array() ) { 
  396. $where_clauses = array( 
  397. 'data' => array(),  
  398. 'format' => array(),  
  399. ); 
  400.  
  401. // The id. 
  402. if ( ! empty( $args['id'] ) ) { 
  403. $where_clauses['data']['id'] = absint( $args['id'] ); 
  404. $where_clauses['format'][] = '%d'; 
  405.  
  406. // The user_id. 
  407. if ( ! empty( $args['user_id'] ) ) { 
  408. $where_clauses['data']['user_id'] = absint( $args['user_id'] ); 
  409. $where_clauses['format'][] = '%d'; 
  410.  
  411. // The item_id. 
  412. if ( ! empty( $args['item_id'] ) ) { 
  413. $where_clauses['data']['item_id'] = absint( $args['item_id'] ); 
  414. $where_clauses['format'][] = '%d'; 
  415.  
  416. // The secondary_item_id. 
  417. if ( ! empty( $args['secondary_item_id'] ) ) { 
  418. $where_clauses['data']['secondary_item_id'] = absint( $args['secondary_item_id'] ); 
  419. $where_clauses['format'][] = '%d'; 
  420.  
  421. // The component_name. 
  422. if ( ! empty( $args['component_name'] ) ) { 
  423. $where_clauses['data']['component_name'] = $args['component_name']; 
  424. $where_clauses['format'][] = '%s'; 
  425.  
  426. // The component_action. 
  427. if ( ! empty( $args['component_action'] ) ) { 
  428. $where_clauses['data']['component_action'] = $args['component_action']; 
  429. $where_clauses['format'][] = '%s'; 
  430.  
  431. // If is_new. 
  432. if ( isset( $args['is_new'] ) ) { 
  433. $where_clauses['data']['is_new'] = ! empty( $args['is_new'] ) ? 1 : 0; 
  434. $where_clauses['format'][] = '%d'; 
  435.  
  436. return $where_clauses; 
  437.  
  438. /** Public Static Methods *************************************************/ 
  439.  
  440. /** 
  441. * Check that a specific notification is for a specific user. 
  442. * @since 1.9.0 
  443. * @param int $user_id ID of the user being checked. 
  444. * @param int $notification_id ID of the notification being checked. 
  445. * @return bool True if the notification belongs to the user, otherwise 
  446. * false. 
  447. */ 
  448. public static function check_access( $user_id, $notification_id ) { 
  449. global $wpdb; 
  450.  
  451. $bp = buddypress(); 
  452.  
  453. return $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(id) FROM {$bp->core->table_name_notifications} WHERE id = %d AND user_id = %d", $notification_id, $user_id ) ); 
  454.  
  455. /** 
  456. * Parse notifications query arguments. 
  457. * @since 2.3.0 
  458. * @param mixed $args Args to parse. 
  459. * @return array 
  460. */ 
  461. public static function parse_args( $args = '' ) { 
  462. return wp_parse_args( $args, array( 
  463. 'id' => false,  
  464. 'user_id' => false,  
  465. 'item_id' => false,  
  466. 'secondary_item_id' => false,  
  467. 'component_name' => bp_notifications_get_registered_components(),  
  468. 'component_action' => false,  
  469. 'is_new' => true,  
  470. 'search_terms' => '',  
  471. 'order_by' => false,  
  472. 'sort_order' => false,  
  473. 'page' => false,  
  474. 'per_page' => false,  
  475. 'meta_query' => false,  
  476. 'date_query' => false,  
  477. 'update_meta_cache' => true 
  478. ) ); 
  479.  
  480. /** 
  481. * Get notifications, based on provided filter parameters. 
  482. * @since 1.9.0 
  483. * @param array $args { 
  484. * Associative array of arguments. All arguments but $page and 
  485. * $per_page can be treated as filter values for get_where_sql() 
  486. * and get_query_clauses(). All items are optional. 
  487. * @type int|array $id ID of notification being updated. Can be an 
  488. * array of IDs. 
  489. * @type int|array $user_id ID of user being queried. Can be an 
  490. * array of user IDs. 
  491. * @type int|array $item_id ID of associated item. Can be an array 
  492. * of multiple item IDs. 
  493. * @type int|array $secondary_item_id ID of secondary associated 
  494. * item. Can be an array of multiple IDs. 
  495. * @type string|array $component_name Name of the component to 
  496. * filter by. Can be an array of component names. 
  497. * @type string|array $component_action Name of the action to 
  498. * filter by. Can be an array of actions. 
  499. * @type bool $is_new Whether to limit to new notifications. True 
  500. * returns only new notifications, false returns only non-new 
  501. * notifications. 'both' returns all. Default: true. 
  502. * @type string $search_terms Term to match against component_name 
  503. * or component_action fields. 
  504. * @type string $order_by Database column to order notifications by. 
  505. * @type string $sort_order Either 'ASC' or 'DESC'. 
  506. * @type string $order_by Field to order results by. 
  507. * @type string $sort_order ASC or DESC. 
  508. * @type int $page Number of the current page of results. Default: 
  509. * false (no pagination - all items). 
  510. * @type int $per_page Number of items to show per page. Default: 
  511. * false (no pagination - all items). 
  512. * @type array $meta_query Array of meta_query conditions. See WP_Meta_Query::queries. 
  513. * @type array $date_query Array of date_query conditions. See first parameter of 
  514. * WP_Date_Query::__construct(). 
  515. * @type bool $update_meta_cache Whether to update meta cache. Default: true. 
  516. * } 
  517. * @return array Located notifications. 
  518. */ 
  519. public static function get( $args = array() ) { 
  520. global $wpdb; 
  521.  
  522. // Parse the arguments. 
  523. $r = self::parse_args( $args ); 
  524.  
  525. // Get BuddyPress. 
  526. $bp = buddypress(); 
  527.  
  528. // METADATA. 
  529. $meta_query_sql = self::get_meta_query_sql( $r['meta_query'] ); 
  530.  
  531. // SELECT. 
  532. $select_sql = "SELECT *"; 
  533.  
  534. // FROM. 
  535. $from_sql = "FROM {$bp->notifications->table_name} n "; 
  536.  
  537. // JOIN. 
  538. $join_sql = $meta_query_sql['join']; 
  539.  
  540. // WHERE. 
  541. $where_sql = self::get_where_sql( array( 
  542. 'id' => $r['id'],  
  543. 'user_id' => $r['user_id'],  
  544. 'item_id' => $r['item_id'],  
  545. 'secondary_item_id' => $r['secondary_item_id'],  
  546. 'component_name' => $r['component_name'],  
  547. 'component_action' => $r['component_action'],  
  548. 'is_new' => $r['is_new'],  
  549. 'search_terms' => $r['search_terms'],  
  550. 'date_query' => $r['date_query'] 
  551. ), $select_sql, $from_sql, $join_sql, $meta_query_sql ); 
  552.  
  553. // ORDER BY. 
  554. $order_sql = self::get_order_by_sql( array( 
  555. 'order_by' => $r['order_by'],  
  556. 'sort_order' => $r['sort_order'] 
  557. ) ); 
  558.  
  559. // LIMIT %d, %d. 
  560. $pag_sql = self::get_paged_sql( array( 
  561. 'page' => $r['page'],  
  562. 'per_page' => $r['per_page'] 
  563. ) ); 
  564.  
  565. // Concatenate query parts. 
  566. $sql = "{$select_sql} {$from_sql} {$join_sql} {$where_sql} {$order_sql} {$pag_sql}"; 
  567.  
  568. $results = $wpdb->get_results( $sql ); 
  569.  
  570. // Integer casting. 
  571. foreach ( $results as $key => $result ) { 
  572. $results[$key]->id = (int) $results[$key]->id; 
  573. $results[$key]->user_id = (int) $results[$key]->user_id; 
  574. $results[$key]->item_id = (int) $results[$key]->item_id; 
  575. $results[$key]->secondary_item_id = (int) $results[$key]->secondary_item_id; 
  576. $results[$key]->is_new = (int) $results[$key]->is_new; 
  577.  
  578. // Update meta cache. 
  579. if ( true === $r['update_meta_cache'] ) { 
  580. bp_notifications_update_meta_cache( wp_list_pluck( $results, 'id' ) ); 
  581.  
  582. return $results; 
  583.  
  584. /** 
  585. * Get a count of total notifications matching a set of arguments. 
  586. * @since 1.9.0 
  587. * @see BP_Notifications_Notification::get() for a description of arguments. 
  588. * @param array $args See {@link BP_Notifications_Notification::get()}. 
  589. * @return int Count of located items. 
  590. */ 
  591. public static function get_total_count( $args ) { 
  592. global $wpdb; 
  593.  
  594. // Parse the arguments. 
  595. $r = self::parse_args( $args ); 
  596.  
  597. // Load BuddyPress. 
  598. $bp = buddypress(); 
  599.  
  600. // METADATA. 
  601. $meta_query_sql = self::get_meta_query_sql( $r['meta_query'] ); 
  602.  
  603. // SELECT. 
  604. $select_sql = "SELECT COUNT(*)"; 
  605.  
  606. // FROM. 
  607. $from_sql = "FROM {$bp->notifications->table_name} n "; 
  608.  
  609. // JOIN. 
  610. $join_sql = $meta_query_sql['join']; 
  611.  
  612. // WHERE. 
  613. $where_sql = self::get_where_sql( array( 
  614. 'id' => $r['id'],  
  615. 'user_id' => $r['user_id'],  
  616. 'item_id' => $r['item_id'],  
  617. 'secondary_item_id' => $r['secondary_item_id'],  
  618. 'component_name' => $r['component_name'],  
  619. 'component_action' => $r['component_action'],  
  620. 'is_new' => $r['is_new'],  
  621. 'search_terms' => $r['search_terms'],  
  622. 'date_query' => $r['date_query'] 
  623. ), $select_sql, $from_sql, $join_sql, $meta_query_sql ); 
  624.  
  625. // Concatenate query parts. 
  626. $sql = "{$select_sql} {$from_sql} {$join_sql} {$where_sql}"; 
  627.  
  628. // Return the queried results. 
  629. return (int) $wpdb->get_var( $sql ); 
  630.  
  631. /** 
  632. * Get the SQL for the 'meta_query' param in BP_Notifications_Notification::get(). 
  633. * We use WP_Meta_Query to do the heavy lifting of parsing the 
  634. * meta_query array and creating the necessary SQL clauses. However,  
  635. * since BP_Notifications_Notification::get() builds its SQL differently than 
  636. * WP_Query, we have to alter the return value (stripping the leading 
  637. * AND keyword from the 'where' clause). 
  638. * @since 2.3.0 
  639. * @param array $meta_query An array of meta_query filters. See the 
  640. * documentation for WP_Meta_Query for details. 
  641. * @return array $sql_array 'join' and 'where' clauses. 
  642. */ 
  643. public static function get_meta_query_sql( $meta_query = array() ) { 
  644.  
  645. // Default array keys & empty values. 
  646. $sql_array = array( 
  647. 'join' => '',  
  648. 'where' => '',  
  649. ); 
  650.  
  651. // Bail if no meta query. 
  652. if ( empty( $meta_query ) ) { 
  653. return $sql_array; 
  654.  
  655. // WP_Meta_Query expects the table name at $wpdb->notificationmeta. 
  656. $GLOBALS['wpdb']->notificationmeta = buddypress()->notifications->table_name_meta; 
  657.  
  658. $n_meta_query = new WP_Meta_Query( $meta_query ); 
  659. $meta_sql = $n_meta_query->get_sql( 'notification', 'n', 'id' ); 
  660.  
  661. // Strip the leading AND - it's handled in get(). 
  662. $sql_array['where'] = preg_replace( '/^\sAND/', '', $meta_sql['where'] ); 
  663. $sql_array['join'] = $meta_sql['join']; 
  664.  
  665. return $sql_array; 
  666.  
  667. /** 
  668. * Get the SQL for the 'date_query' param in BP_Notifications_Notification::get(). 
  669. * We use BP_Date_Query, which extends WP_Date_Query, to do the heavy lifting 
  670. * of parsing the date_query array and creating the necessary SQL clauses. 
  671. * However, since BP_Notifications_Notification::get() builds its SQL 
  672. * differently than WP_Query, we have to alter the return value (stripping 
  673. * the leading AND keyword from the query). 
  674. * @since 2.3.0 
  675. * @param array $date_query An array of date_query parameters. See the 
  676. * documentation for the first parameter of WP_Date_Query. 
  677. * @return string 
  678. */ 
  679. public static function get_date_query_sql( $date_query = array() ) { 
  680.  
  681. // Bail if not a proper date query format. 
  682. if ( empty( $date_query ) || ! is_array( $date_query ) ) { 
  683. return ''; 
  684.  
  685. // Date query. 
  686. $date_query = new BP_Date_Query( $date_query, 'date_recorded' ); 
  687.  
  688. // Strip the leading AND - it's handled in get(). 
  689. return preg_replace( '/^\sAND/', '', $date_query->get_sql() ); 
  690.  
  691. /** 
  692. * Update notifications. 
  693. * @since 1.9.0 
  694. * @see BP_Notifications_Notification::get() for a description of 
  695. * accepted update/where arguments. 
  696. * @param array $update_args Associative array of fields to update,  
  697. * and the values to update them to. Of the format 
  698. * array( 'user_id' => 4, 'component_name' => 'groups', ). 
  699. * @param array $where_args Associative array of columns/values, to 
  700. * determine which rows should be updated. Of the format 
  701. * array( 'item_id' => 7, 'component_action' => 'members', ). 
  702. * @return int|bool Number of rows updated on success, false on failure. 
  703. */ 
  704. public static function update( $update_args = array(), $where_args = array() ) { 
  705. $update = self::get_query_clauses( $update_args ); 
  706. $where = self::get_query_clauses( $where_args ); 
  707.  
  708. /** 
  709. * Fires before the update of a notification item. 
  710. * @since 2.3.0 
  711. * @param array $update_args See BP_Notifications_Notification::update(). 
  712. * @param array $where_args See BP_Notifications_Notification::update(). 
  713. */ 
  714. do_action( 'bp_notification_before_update', $update_args, $where_args ); 
  715.  
  716. return self::_update( 
  717. $update['data'],  
  718. $where['data'],  
  719. $update['format'],  
  720. $where['format'] 
  721. ); 
  722.  
  723. /** 
  724. * Delete notifications. 
  725. * @since 1.9.0 
  726. * @see BP_Notifications_Notification::get() for a description of 
  727. * accepted update/where arguments. 
  728. * @param array $args Associative array of columns/values, to determine 
  729. * which rows should be deleted. Of the format 
  730. * array( 'item_id' => 7, 'component_action' => 'members', ). 
  731. * @return int|bool Number of rows deleted on success, false on failure. 
  732. */ 
  733. public static function delete( $args = array() ) { 
  734. $where = self::get_query_clauses( $args ); 
  735.  
  736. /** 
  737. * Fires before the deletion of a notification item. 
  738. * @since 2.0.0 
  739. * @param array $args Associative array of columns/values, to determine 
  740. * which rows should be deleted. Of the format 
  741. * array( 'item_id' => 7, 'component_action' => 'members' ). 
  742. */ 
  743. do_action( 'bp_notification_before_delete', $args ); 
  744.  
  745. return self::_delete( $where['data'], $where['format'] ); 
  746.  
  747. /** Convenience methods ***************************************************/ 
  748.  
  749. /** 
  750. * Delete a single notification by ID. 
  751. * @since 1.9.0 
  752. * @see BP_Notifications_Notification::delete() for explanation of 
  753. * return value. 
  754. * @param int $id ID of the notification item to be deleted. 
  755. * @return bool True on success, false on failure. 
  756. */ 
  757. public static function delete_by_id( $id ) { 
  758. return self::delete( array( 
  759. 'id' => $id,  
  760. ) ); 
  761.  
  762. /** 
  763. * Fetch all the notifications in the database for a specific user. 
  764. * @since 1.9.0 
  765. * @param int $user_id ID of the user whose notifications are being 
  766. * fetched. 
  767. * @param string $status Optional. Status of notifications to fetch. 
  768. * 'is_new' to get only unread items, 'all' to get all. 
  769. * @return array Associative array of notification items. 
  770. */ 
  771. public static function get_all_for_user( $user_id, $status = 'is_new' ) { 
  772. return self::get( array( 
  773. 'user_id' => $user_id,  
  774. 'is_new' => 'is_new' === $status,  
  775. ) ); 
  776.  
  777. /** 
  778. * Fetch all the unread notifications in the database for a specific user. 
  779. * @since 1.9.0 
  780. * @param int $user_id ID of the user whose notifications are being 
  781. * fetched. 
  782. * @return array Associative array of unread notification items. 
  783. */ 
  784. public static function get_unread_for_user( $user_id = 0 ) { 
  785. return self::get( array( 
  786. 'user_id' => $user_id,  
  787. 'is_new' => true,  
  788. ) ); 
  789.  
  790. /** 
  791. * Fetch all the read notifications in the database for a specific user. 
  792. * @since 1.9.0 
  793. * @param int $user_id ID of the user whose notifications are being 
  794. * fetched. 
  795. * @return array Associative array of unread notification items. 
  796. */ 
  797. public static function get_read_for_user( $user_id = 0 ) { 
  798. return self::get( array( 
  799. 'user_id' => $user_id,  
  800. 'is_new' => false,  
  801. ) ); 
  802.  
  803. /** 
  804. * Get unread notifications for a user, in a pagination-friendly format. 
  805. * @since 1.9.0 
  806. * @param array $args { 
  807. * Array of arguments. 
  808. * @type int $user_id ID of the user for whom the notifications are 
  809. * being fetched. Default: logged-in user ID. 
  810. * @type bool $is_new Whether to limit the query to unread 
  811. * notifications. Default: true. 
  812. * @type int $page Number of the page to return. Default: 1. 
  813. * @type int $per_page Number of results to display per page. 
  814. * Default: 10. 
  815. * @type string $search_terms Optional. A term to search against in 
  816. * the 'component_name' and 'component_action' columns. 
  817. * } 
  818. * @return array { 
  819. * @type array $notifications Array of notification results. 
  820. * @type int $total Count of all located notifications matching 
  821. * the query params. 
  822. * } 
  823. */ 
  824. public static function get_current_notifications_for_user( $args = array() ) { 
  825. $r = wp_parse_args( $args, array( 
  826. 'user_id' => bp_loggedin_user_id(),  
  827. 'is_new' => true,  
  828. 'page' => 1,  
  829. 'per_page' => 25,  
  830. 'search_terms' => '',  
  831. ) ); 
  832.  
  833. $notifications = self::get( $r ); 
  834.  
  835. // Bail if no notifications. 
  836. if ( empty( $notifications ) ) { 
  837. return false; 
  838.  
  839. $total_count = self::get_total_count( $r ); 
  840.  
  841. return array( 'notifications' => &$notifications, 'total' => $total_count ); 
  842.  
  843. /** Mark ******************************************************************/ 
  844.  
  845. /** 
  846. * Mark all user notifications as read. 
  847. * @since 1.9.0 
  848. * @param int $user_id The ID of the user who the notifications are for. 
  849. * @param int $is_new Mark as read (1) or unread (0). 
  850. * @param int $item_id Item ID being acted on. 
  851. * @param string $component_name Name of component the notifications are for. 
  852. * @param string $component_action Name of the component action. 
  853. * @param int $secondary_item_id The ID of the secondary item. 
  854. * @return bool|int False on failure to update. ID on success. 
  855. */ 
  856. public static function mark_all_for_user( $user_id, $is_new = 0, $item_id = 0, $component_name = '', $component_action = '', $secondary_item_id = 0 ) { 
  857.  
  858. // Values to be updated. 
  859. $update_args = array( 
  860. 'is_new' => $is_new,  
  861. ); 
  862.  
  863. // WHERE clauses. 
  864. $where_args = array( 
  865. 'user_id' => $user_id,  
  866. ); 
  867.  
  868. if ( ! empty( $item_id ) ) { 
  869. $where_args['item_id'] = $item_id; 
  870.  
  871. if ( ! empty( $component_name ) ) { 
  872. $where_args['component_name'] = $component_name; 
  873.  
  874. if ( ! empty( $component_action ) ) { 
  875. $where_args['component_action'] = $component_action; 
  876.  
  877. if ( ! empty( $secondary_item_id ) ) { 
  878. $where_args['secondary_item_id'] = $secondary_item_id; 
  879.  
  880. return self::update( $update_args, $where_args ); 
  881.  
  882. /** 
  883. * Mark all notifications from a user as read. 
  884. * @since 1.9.0 
  885. * @param int $user_id The ID of the user who the notifications are from. 
  886. * @param int $is_new Mark as read (1) or unread (0). 
  887. * @param string $component_name Name of component the notifications are for. 
  888. * @param string $component_action Name of the component action. 
  889. * @param int $secondary_item_id The ID of the secondary item. 
  890. * @return bool|int 
  891. */ 
  892. public static function mark_all_from_user( $user_id, $is_new = 0, $component_name = '', $component_action = '', $secondary_item_id = 0 ) { 
  893.  
  894. // Values to be updated. 
  895. $update_args = array( 
  896. 'is_new' => $is_new,  
  897. ); 
  898.  
  899. // WHERE clauses. 
  900. $where_args = array( 
  901. 'item_id' => $user_id,  
  902. ); 
  903.  
  904. if ( ! empty( $component_name ) ) { 
  905. $where_args['component_name'] = $component_name; 
  906.  
  907. if ( ! empty( $component_action ) ) { 
  908. $where_args['component_action'] = $component_action; 
  909.  
  910. if ( ! empty( $secondary_item_id ) ) { 
  911. $where_args['secondary_item_id'] = $secondary_item_id; 
  912.  
  913. return self::update( $update_args, $where_args ); 
  914.  
  915. /** 
  916. * Mark all notifications for all users as read by item id, and optional 
  917. * secondary item id, and component name and action. 
  918. * @since 1.9.0 
  919. * @param int $item_id The ID of the item associated with the 
  920. * notifications. 
  921. * @param int $is_new Mark as read (1) or unread (0). 
  922. * @param string $component_name The component that the notifications 
  923. * are associated with. 
  924. * @param string $component_action The action that the notifications 
  925. * are associated with. 
  926. * @param int $secondary_item_id Optional. ID of the secondary 
  927. * associated item. 
  928. * @return bool|int 
  929. */ 
  930. public static function mark_all_by_type( $item_id, $is_new = 0, $component_name = '', $component_action = '', $secondary_item_id = 0 ) { 
  931.  
  932. // Values to be updated. 
  933. $update_args = array( 
  934. 'is_new' => $is_new,  
  935. ); 
  936.  
  937. // WHERE clauses. 
  938. $where_args = array( 
  939. 'item_id' => $item_id,  
  940. ); 
  941.  
  942. if ( ! empty( $component_name ) ) { 
  943. $where_args['component_name'] = $component_name; 
  944.  
  945. if ( ! empty( $component_action ) ) { 
  946. $where_args['component_action'] = $component_action; 
  947.  
  948. if ( ! empty( $secondary_item_id ) ) { 
  949. $where_args['secondary_item_id'] = $secondary_item_id; 
  950.  
  951. return self::update( $update_args, $where_args );