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


Generated: Sun Oct 24 01:00:54 2021 Cross-referenced by PHPXref 0.7.1