[ 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, $notification_id ) {
 560          global $wpdb;
 561  
 562          $bp = buddypress();
 563  
 564          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 ) );
 565      }
 566  
 567      /**
 568       * Parse notifications query arguments.
 569       *
 570       * @since 2.3.0
 571       *
 572       * @param mixed $args Args to parse.
 573       * @return array
 574       */
 575  	public static function parse_args( $args = '' ) {
 576          return wp_parse_args( $args, array(
 577              'id'                => false,
 578              'user_id'           => false,
 579              'item_id'           => false,
 580              'secondary_item_id' => false,
 581              'component_name'    => bp_notifications_get_registered_components(),
 582              'component_action'  => false,
 583              'is_new'            => true,
 584              'search_terms'      => '',
 585              'order_by'          => false,
 586              'sort_order'        => false,
 587              'page'              => false,
 588              'per_page'          => false,
 589              'meta_query'        => false,
 590              'date_query'        => false,
 591              'update_meta_cache' => true
 592          ) );
 593      }
 594  
 595      /**
 596       * Get notifications, based on provided filter parameters.
 597       *
 598       * @since 1.9.0
 599       *
 600       * @param array $args {
 601       *     Associative array of arguments. All arguments but $page and
 602       *     $per_page can be treated as filter values for get_where_sql()
 603       *     and get_query_clauses(). All items are optional.
 604       *     @type int|array    $id                ID of notification being updated. Can be an
 605       *                                           array of IDs.
 606       *     @type int|array    $user_id           ID of user being queried. Can be an
 607       *                                           array of user IDs.
 608       *     @type int|array    $item_id           ID of associated item. Can be an array
 609       *                                           of multiple item IDs.
 610       *     @type int|array    $secondary_item_id ID of secondary associated
 611       *                                           item. Can be an array of multiple IDs.
 612       *     @type string|array $component_name    Name of the component to
 613       *                                           filter by. Can be an array of component names.
 614       *     @type string|array $component_action  Name of the action to
 615       *                                           filter by. Can be an array of actions.
 616       *     @type bool         $is_new            Whether to limit to new notifications. True
 617       *                                           returns only new notifications, false returns only non-new
 618       *                                           notifications. 'both' returns all. Default: true.
 619       *     @type string       $search_terms      Term to match against component_name
 620       *                                           or component_action fields.
 621       *     @type string       $order_by          Database column to order notifications by.
 622       *     @type string       $sort_order        Either 'ASC' or 'DESC'.
 623       *     @type string       $order_by          Field to order results by.
 624       *     @type string       $sort_order        ASC or DESC.
 625       *     @type int          $page              Number of the current page of results. Default:
 626       *                                           false (no pagination - all items).
 627       *     @type int          $per_page          Number of items to show per page. Default:
 628       *                                           false (no pagination - all items).
 629       *     @type array        $meta_query        Array of meta_query conditions. See WP_Meta_Query::queries.
 630       *     @type array        $date_query        Array of date_query conditions. See first parameter of
 631       *                                           WP_Date_Query::__construct().
 632       *     @type bool         $update_meta_cache Whether to update meta cache. Default: true.
 633       * }
 634       * @return array Located notifications.
 635       */
 636  	public static function get( $args = array() ) {
 637          global $wpdb;
 638  
 639          // Parse the arguments.
 640          $r = self::parse_args( $args );
 641  
 642          // Get BuddyPress.
 643          $bp = buddypress();
 644  
 645          // METADATA.
 646          $meta_query_sql = self::get_meta_query_sql( $r['meta_query'] );
 647  
 648          // SELECT.
 649          $select_sql = "SELECT *";
 650  
 651          // FROM.
 652          $from_sql   = "FROM {$bp->notifications->table_name} n ";
 653  
 654          // JOIN.
 655          $join_sql   = $meta_query_sql['join'];
 656  
 657          // WHERE.
 658          $where_sql  = self::get_where_sql( array(
 659              'id'                => $r['id'],
 660              'user_id'           => $r['user_id'],
 661              'item_id'           => $r['item_id'],
 662              'secondary_item_id' => $r['secondary_item_id'],
 663              'component_name'    => $r['component_name'],
 664              'component_action'  => $r['component_action'],
 665              'is_new'            => $r['is_new'],
 666              'search_terms'      => $r['search_terms'],
 667              'date_query'        => $r['date_query']
 668          ), $select_sql, $from_sql, $join_sql, $meta_query_sql );
 669  
 670          // ORDER BY.
 671          $order_sql  = self::get_order_by_sql( array(
 672              'order_by'   => $r['order_by'],
 673              'sort_order' => $r['sort_order']
 674          ) );
 675  
 676          // LIMIT %d, %d.
 677          $pag_sql    = self::get_paged_sql( array(
 678              'page'     => $r['page'],
 679              'per_page' => $r['per_page']
 680          ) );
 681  
 682          // Concatenate query parts.
 683          $sql = "{$select_sql} {$from_sql} {$join_sql} {$where_sql} {$order_sql} {$pag_sql}";
 684  
 685          $results = $wpdb->get_results( $sql );
 686  
 687          // Integer casting.
 688          foreach ( $results as $key => $result ) {
 689              $results[$key]->id                = (int) $results[$key]->id;
 690              $results[$key]->user_id           = (int) $results[$key]->user_id;
 691              $results[$key]->item_id           = (int) $results[$key]->item_id;
 692              $results[$key]->secondary_item_id = (int) $results[$key]->secondary_item_id;
 693              $results[$key]->is_new            = (int) $results[$key]->is_new;
 694          }
 695  
 696          // Update meta cache.
 697          if ( true === $r['update_meta_cache'] ) {
 698              bp_notifications_update_meta_cache( wp_list_pluck( $results, 'id' ) );
 699          }
 700  
 701          return $results;
 702      }
 703  
 704      /**
 705       * Get a count of total notifications matching a set of arguments.
 706       *
 707       * @since 1.9.0
 708       *
 709       * @see BP_Notifications_Notification::get() for a description of arguments.
 710       *
 711       * @param array $args See {@link BP_Notifications_Notification::get()}.
 712       * @return int Count of located items.
 713       */
 714  	public static function get_total_count( $args ) {
 715          global $wpdb;
 716  
 717          // Parse the arguments.
 718          $r = self::parse_args( $args );
 719  
 720          // Load BuddyPress.
 721          $bp = buddypress();
 722  
 723          // METADATA.
 724          $meta_query_sql = self::get_meta_query_sql( $r['meta_query'] );
 725  
 726          // SELECT.
 727          $select_sql = "SELECT COUNT(*)";
 728  
 729          // FROM.
 730          $from_sql   = "FROM {$bp->notifications->table_name} n ";
 731  
 732          // JOIN.
 733          $join_sql   = $meta_query_sql['join'];
 734  
 735          // WHERE.
 736          $where_sql  = self::get_where_sql( array(
 737              'id'                => $r['id'],
 738              'user_id'           => $r['user_id'],
 739              'item_id'           => $r['item_id'],
 740              'secondary_item_id' => $r['secondary_item_id'],
 741              'component_name'    => $r['component_name'],
 742              'component_action'  => $r['component_action'],
 743              'is_new'            => $r['is_new'],
 744              'search_terms'      => $r['search_terms'],
 745              'date_query'        => $r['date_query']
 746          ), $select_sql, $from_sql, $join_sql, $meta_query_sql );
 747  
 748          // Concatenate query parts.
 749          $sql = "{$select_sql} {$from_sql} {$join_sql} {$where_sql}";
 750  
 751          // Return the queried results.
 752          return (int) $wpdb->get_var( $sql );
 753      }
 754  
 755      /**
 756       * Get the SQL for the 'meta_query' param in BP_Notifications_Notification::get().
 757       *
 758       * We use WP_Meta_Query to do the heavy lifting of parsing the
 759       * meta_query array and creating the necessary SQL clauses. However,
 760       * since BP_Notifications_Notification::get() builds its SQL differently than
 761       * WP_Query, we have to alter the return value (stripping the leading
 762       * AND keyword from the 'where' clause).
 763       *
 764       * @since 2.3.0
 765       *
 766       * @param  array $meta_query An array of meta_query filters. See the
 767       *                           documentation for WP_Meta_Query for details.
 768       * @return array $sql_array 'join' and 'where' clauses.
 769       */
 770  	public static function get_meta_query_sql( $meta_query = array() ) {
 771  
 772          // Default array keys & empty values.
 773          $sql_array = array(
 774              'join'  => '',
 775              'where' => '',
 776          );
 777  
 778          // Bail if no meta query.
 779          if ( empty( $meta_query ) ) {
 780              return $sql_array;
 781          }
 782  
 783          // WP_Meta_Query expects the table name at $wpdb->notificationmeta.
 784          $GLOBALS['wpdb']->notificationmeta = buddypress()->notifications->table_name_meta;
 785  
 786          $n_meta_query = new WP_Meta_Query( $meta_query );
 787          $meta_sql     = $n_meta_query->get_sql( 'notification', 'n', 'id' );
 788  
 789          // Strip the leading AND - it's handled in get().
 790          $sql_array['where'] = preg_replace( '/^\sAND/', '', $meta_sql['where'] );
 791          $sql_array['join']  = $meta_sql['join'];
 792  
 793          return $sql_array;
 794      }
 795  
 796      /**
 797       * Get the SQL for the 'date_query' param in BP_Notifications_Notification::get().
 798       *
 799       * We use BP_Date_Query, which extends WP_Date_Query, to do the heavy lifting
 800       * of parsing the date_query array and creating the necessary SQL clauses.
 801       * However, since BP_Notifications_Notification::get() builds its SQL
 802       * differently than WP_Query, we have to alter the return value (stripping
 803       * the leading AND keyword from the query).
 804       *
 805       * @since 2.3.0
 806       *
 807       * @param array $date_query An array of date_query parameters. See the
 808       *                          documentation for the first parameter of WP_Date_Query.
 809       * @return string
 810       */
 811  	public static function get_date_query_sql( $date_query = array() ) {
 812  
 813          // Bail if not a proper date query format.
 814          if ( empty( $date_query ) || ! is_array( $date_query ) ) {
 815              return '';
 816          }
 817  
 818          // Date query.
 819          $date_query = new BP_Date_Query( $date_query, 'date_notified' );
 820  
 821          // Strip the leading AND - it's handled in get().
 822          return preg_replace( '/^\sAND/', '', $date_query->get_sql() );
 823      }
 824  
 825      /**
 826       * Update notifications.
 827       *
 828       * @since 1.9.0
 829       *
 830       * @see BP_Notifications_Notification::get() for a description of
 831       *      accepted update/where arguments.
 832       *
 833       * @param array $update_args Associative array of fields to update,
 834       *                           and the values to update them to. Of the format
 835       *                           array( 'user_id' => 4, 'component_name' => 'groups', ).
 836       * @param array $where_args  Associative array of columns/values, to
 837       *                           determine which rows should be updated. Of the format
 838       *                           array( 'item_id' => 7, 'component_action' => 'members', ).
 839       * @return int|false Number of rows updated on success, false on failure.
 840       */
 841  	public static function update( $update_args = array(), $where_args = array() ) {
 842          $update = self::get_query_clauses( $update_args );
 843          $where  = self::get_query_clauses( $where_args  );
 844  
 845          /**
 846           * Fires before the update of a notification item.
 847           *
 848           * @since 2.3.0
 849           *
 850           * @param array $update_args See BP_Notifications_Notification::update().
 851           * @param array $where_args  See BP_Notifications_Notification::update().
 852           */
 853          do_action( 'bp_notification_before_update', $update_args, $where_args );
 854  
 855          return self::_update(
 856              $update['data'],
 857              $where['data'],
 858              $update['format'],
 859              $where['format']
 860          );
 861      }
 862  
 863      /**
 864       * Delete notifications.
 865       *
 866       * @since 1.9.0
 867       *
 868       * @see BP_Notifications_Notification::get() for a description of
 869       *      accepted update/where arguments.
 870       *
 871       * @param array $args Associative array of columns/values, to determine
 872       *                    which rows should be deleted.  Of the format
 873       *                    array( 'item_id' => 7, 'component_action' => 'members', ).
 874       * @return int|false Number of rows deleted on success, false on failure.
 875       */
 876  	public static function delete( $args = array() ) {
 877          $where = self::get_query_clauses( $args );
 878  
 879          /**
 880           * Fires before the deletion of a notification item.
 881           *
 882           * @since 2.0.0
 883           *
 884           * @param array $args Associative array of columns/values, to determine
 885           *                    which rows should be deleted. Of the format
 886           *                    array( 'item_id' => 7, 'component_action' => 'members' ).
 887           */
 888          do_action( 'bp_notification_before_delete', $args );
 889  
 890          return self::_delete( $where['data'], $where['format'] );
 891      }
 892  
 893      /** Convenience methods ***************************************************/
 894  
 895      /**
 896       * Delete a single notification by ID.
 897       *
 898       * @since 1.9.0
 899       *
 900       * @see BP_Notifications_Notification::delete() for explanation of
 901       *      return value.
 902       *
 903       * @param int $id ID of the notification item to be deleted.
 904       * @return int|false True on success, false on failure.
 905       */
 906  	public static function delete_by_id( $id ) {
 907          return self::delete( array(
 908              'id' => $id,
 909          ) );
 910      }
 911  
 912      /**
 913       * Fetch all the notifications in the database for a specific user.
 914       *
 915       * @since 1.9.0
 916       *
 917       * @param int    $user_id ID of the user whose notifications are being
 918       *                        fetched.
 919       * @param string $status  Optional. Status of notifications to fetch.
 920       *                        'is_new' to get only unread items, 'all' to get all.
 921       * @return array Associative array of notification items.
 922       */
 923  	public static function get_all_for_user( $user_id, $status = 'is_new' ) {
 924          return self::get( array(
 925              'user_id' => $user_id,
 926              'is_new'  => 'is_new' === $status,
 927          ) );
 928      }
 929  
 930      /**
 931       * Fetch all the unread notifications in the database for a specific user.
 932       *
 933       * @since 1.9.0
 934       *
 935       * @param int $user_id ID of the user whose notifications are being
 936       *                     fetched.
 937       * @return array Associative array of unread notification items.
 938       */
 939  	public static function get_unread_for_user( $user_id = 0 ) {
 940          return self::get( array(
 941              'user_id' => $user_id,
 942              'is_new'  => true,
 943          ) );
 944      }
 945  
 946      /**
 947       * Fetch all the read notifications in the database for a specific user.
 948       *
 949       * @since 1.9.0
 950       *
 951       * @param int $user_id ID of the user whose notifications are being
 952       *                     fetched.
 953       * @return array Associative array of unread notification items.
 954       */
 955  	public static function get_read_for_user( $user_id = 0 ) {
 956          return self::get( array(
 957              'user_id' => $user_id,
 958              'is_new'  => false,
 959          ) );
 960      }
 961  
 962      /**
 963       * Get unread notifications for a user, in a pagination-friendly format.
 964       *
 965       * @since 1.9.0
 966       *
 967       * @param array $args {
 968       *     Array of arguments.
 969       *     @type int    $user_id      ID of the user for whom the notifications are
 970       *                                being fetched. Default: logged-in user ID.
 971       *     @type bool   $is_new       Whether to limit the query to unread
 972       *                                notifications. Default: true.
 973       *     @type int    $page         Number of the page to return. Default: 1.
 974       *     @type int    $per_page     Number of results to display per page.
 975       *                                Default: 10.
 976       *     @type string $search_terms Optional. A term to search against in
 977       *                                the 'component_name' and 'component_action' columns.
 978       * }
 979       * @return array {
 980       *     @type array $notifications Array of notification results.
 981       *     @type int   $total         Count of all located notifications matching
 982       *                                the query params.
 983       * }
 984       */
 985  	public static function get_current_notifications_for_user( $args = array() ) {
 986          $r = wp_parse_args( $args, array(
 987              'user_id'      => bp_loggedin_user_id(),
 988              'is_new'       => true,
 989              'page'         => 1,
 990              'per_page'     => 25,
 991              'search_terms' => '',
 992          ) );
 993  
 994          $notifications = self::get( $r );
 995  
 996          // Bail if no notifications.
 997          if ( empty( $notifications ) ) {
 998              return false;
 999          }
1000  
1001          $total_count = self::get_total_count( $r );
1002  
1003          return array( 'notifications' => &$notifications, 'total' => $total_count );
1004      }
1005  
1006      /** Mark ******************************************************************/
1007  
1008      /**
1009       * Mark all user notifications as read.
1010       *
1011       * @since 1.9.0
1012       *
1013       * @param int    $user_id           The ID of the user who the notifications are for.
1014       * @param int    $is_new            Mark as read (1) or unread (0).
1015       * @param int    $item_id           Item ID being acted on.
1016       * @param string $component_name    Name of component the notifications are for.
1017       * @param string $component_action  Name of the component action.
1018       * @param int    $secondary_item_id The ID of the secondary item.
1019       * @return int|false False on failure to update. ID on success.
1020       */
1021  	public static function mark_all_for_user( $user_id, $is_new = 0, $item_id = 0, $component_name = '', $component_action = '', $secondary_item_id = 0 ) {
1022  
1023          // Values to be updated.
1024          $update_args = array(
1025              'is_new' => $is_new,
1026          );
1027  
1028          // WHERE clauses.
1029          $where_args = array(
1030              'user_id' => $user_id,
1031          );
1032  
1033          if ( ! empty( $item_id ) ) {
1034              $where_args['item_id'] = $item_id;
1035          }
1036  
1037          if ( ! empty( $component_name ) ) {
1038              $where_args['component_name'] = $component_name;
1039          }
1040  
1041          if ( ! empty( $component_action ) ) {
1042              $where_args['component_action'] = $component_action;
1043          }
1044  
1045          if ( ! empty( $secondary_item_id ) ) {
1046              $where_args['secondary_item_id'] = $secondary_item_id;
1047          }
1048  
1049          return self::update( $update_args, $where_args );
1050      }
1051  
1052      /**
1053       * Mark all notifications from a user as read.
1054       *
1055       * @since 1.9.0
1056       *
1057       * @param int    $user_id           The ID of the user who the notifications are from.
1058       * @param int    $is_new            Mark as read (1) or unread (0).
1059       * @param string $component_name    Name of component the notifications are for.
1060       * @param string $component_action  Name of the component action.
1061       * @param int    $secondary_item_id The ID of the secondary item.
1062       * @return int|false
1063       */
1064  	public static function mark_all_from_user( $user_id, $is_new = 0, $component_name = '', $component_action = '', $secondary_item_id = 0 ) {
1065  
1066          // Values to be updated.
1067          $update_args = array(
1068              'is_new' => $is_new,
1069          );
1070  
1071          // WHERE clauses.
1072          $where_args = array(
1073              'item_id' => $user_id,
1074          );
1075  
1076          if ( ! empty( $component_name ) ) {
1077              $where_args['component_name'] = $component_name;
1078          }
1079  
1080          if ( ! empty( $component_action ) ) {
1081              $where_args['component_action'] = $component_action;
1082          }
1083  
1084          if ( ! empty( $secondary_item_id ) ) {
1085              $where_args['secondary_item_id'] = $secondary_item_id;
1086          }
1087  
1088          return self::update( $update_args, $where_args );
1089      }
1090  
1091      /**
1092       * Mark all notifications for all users as read by item id, and optional
1093       * secondary item id, and component name and action.
1094       *
1095       * @since 1.9.0
1096       *
1097       * @param int    $item_id           The ID of the item associated with the
1098       *                                  notifications.
1099       * @param int    $is_new            Mark as read (1) or unread (0).
1100       * @param string $component_name    The component that the notifications
1101       *                                  are associated with.
1102       * @param string $component_action  The action that the notifications
1103       *                                  are associated with.
1104       * @param int    $secondary_item_id Optional. ID of the secondary
1105       *                                  associated item.
1106       * @return int|false
1107       */
1108  	public static function mark_all_by_type( $item_id, $is_new = 0, $component_name = '', $component_action = '', $secondary_item_id = 0 ) {
1109  
1110          // Values to be updated.
1111          $update_args = array(
1112              'is_new' => $is_new,
1113          );
1114  
1115          // WHERE clauses.
1116          $where_args = array(
1117              'item_id' => $item_id,
1118          );
1119  
1120          if ( ! empty( $component_name ) ) {
1121              $where_args['component_name'] = $component_name;
1122          }
1123  
1124          if ( ! empty( $component_action ) ) {
1125              $where_args['component_action'] = $component_action;
1126          }
1127  
1128          if ( ! empty( $secondary_item_id ) ) {
1129              $where_args['secondary_item_id'] = $secondary_item_id;
1130          }
1131  
1132          return self::update( $update_args, $where_args );
1133      }
1134  
1135      /**
1136       * Get a user's unread notifications, grouped by component and action.
1137       *
1138       * Multiple notifications of the same type (those that share the same component_name
1139       * and component_action) are collapsed for formatting as "You have 5 pending
1140       * friendship requests", etc. See bp_notifications_get_notifications_for_user().
1141       * For a full-fidelity list of user notifications, use
1142       * bp_notifications_get_all_notifications_for_user().
1143       *
1144       * @since 3.0.0
1145       *
1146       * @param int $user_id ID of the user whose notifications are being fetched.
1147       * @return array Notifications items for formatting into a list.
1148       */
1149  	public static function get_grouped_notifications_for_user( $user_id ) {
1150          global $wpdb;
1151  
1152          // Load BuddyPress.
1153          $bp = buddypress();
1154  
1155          // SELECT.
1156          $select_sql = "SELECT id, user_id, item_id, secondary_item_id, component_name, component_action, date_notified, is_new, COUNT(id) as total_count ";
1157  
1158          // FROM.
1159          $from_sql = "FROM {$bp->notifications->table_name} n ";
1160  
1161          // WHERE.
1162          $where_sql = self::get_where_sql( array(
1163              'user_id'        => $user_id,
1164              'is_new'         => 1,
1165              'component_name' => bp_notifications_get_registered_components(),
1166          ), $select_sql, $from_sql );
1167  
1168          // GROUP
1169          $group_sql = "GROUP BY user_id, component_name, component_action";
1170  
1171          // SORT
1172          $order_sql = "ORDER BY date_notified desc";
1173  
1174          // Concatenate query parts.
1175          $sql = "{$select_sql} {$from_sql} {$where_sql} {$group_sql} {$order_sql}";
1176  
1177          // Return the queried results.
1178          return $wpdb->get_results( $sql );
1179      }
1180  }


Generated: Tue Jul 16 01:01:43 2019 Cross-referenced by PHPXref 0.7.1