[ Index ]

PHP Cross Reference of BuddyPress

title

Body

[close]

/src/bp-notifications/classes/ -> class-bp-notifications-notification.php (source)

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


Generated: Thu Dec 3 01:01:38 2020 Cross-referenced by PHPXref 0.7.1