[ Index ]

PHP Cross Reference of phpBB-3.1.12-deutsch

title

Body

[close]

/phpbb/notification/ -> manager.php (source)

   1  <?php
   2  /**
   3  *
   4  * This file is part of the phpBB Forum Software package.
   5  *
   6  * @copyright (c) phpBB Limited <https://www.phpbb.com>
   7  * @license GNU General Public License, version 2 (GPL-2.0)
   8  *
   9  * For full copyright and license information, please see
  10  * the docs/CREDITS.txt file.
  11  *
  12  */
  13  
  14  namespace phpbb\notification;
  15  
  16  use Symfony\Component\DependencyInjection\ContainerInterface;
  17  
  18  /**
  19  * Notifications service class
  20  */
  21  class manager
  22  {
  23      /** @var array */
  24      protected $notification_types;
  25  
  26      /** @var array */
  27      protected $subscription_types;
  28  
  29      /** @var array */
  30      protected $notification_methods;
  31  
  32      /** @var ContainerInterface */
  33      protected $phpbb_container;
  34  
  35      /** @var \phpbb\user_loader */
  36      protected $user_loader;
  37  
  38      /** @var \phpbb\config\config */
  39      protected $config;
  40  
  41      /** @var \phpbb\event\dispatcher_interface */
  42      protected $phpbb_dispatcher;
  43  
  44      /** @var \phpbb\db\driver\driver_interface */
  45      protected $db;
  46  
  47      /** @var \phpbb\cache\service */
  48      protected $cache;
  49  
  50      /** @var \phpbb\user */
  51      protected $user;
  52  
  53      /** @var string */
  54      protected $phpbb_root_path;
  55  
  56      /** @var string */
  57      protected $php_ext;
  58  
  59      /** @var string */
  60      protected $notification_types_table;
  61  
  62      /** @var string */
  63      protected $notifications_table;
  64  
  65      /** @var string */
  66      protected $user_notifications_table;
  67  
  68      /**
  69      * Notification Constructor
  70      *
  71      * @param array $notification_types
  72      * @param array $notification_methods
  73      * @param ContainerInterface $phpbb_container
  74      * @param \phpbb\user_loader $user_loader
  75      * @param \phpbb\config\config $config
  76      * @param \phpbb\event\dispatcher_interface $phpbb_dispatcher
  77      * @param \phpbb\db\driver\driver_interface $db
  78      * @param \phpbb\cache\service $cache
  79      * @param \phpbb\user $user
  80      * @param string $phpbb_root_path
  81      * @param string $php_ext
  82      * @param string $notification_types_table
  83      * @param string $notifications_table
  84      * @param string $user_notifications_table
  85      *
  86      * @return \phpbb\notification\manager
  87      */
  88  	public function __construct($notification_types, $notification_methods, ContainerInterface $phpbb_container, \phpbb\user_loader $user_loader, \phpbb\config\config $config, \phpbb\event\dispatcher_interface $phpbb_dispatcher, \phpbb\db\driver\driver_interface $db, \phpbb\cache\service $cache, $user, $phpbb_root_path, $php_ext, $notification_types_table, $notifications_table, $user_notifications_table)
  89      {
  90          $this->notification_types = $notification_types;
  91          $this->notification_methods = $notification_methods;
  92          $this->phpbb_container = $phpbb_container;
  93  
  94          $this->user_loader = $user_loader;
  95          $this->config = $config;
  96          $this->phpbb_dispatcher = $phpbb_dispatcher;
  97          $this->db = $db;
  98          $this->cache = $cache;
  99          $this->user = $user;
 100  
 101          $this->phpbb_root_path = $phpbb_root_path;
 102          $this->php_ext = $php_ext;
 103  
 104          $this->notification_types_table = $notification_types_table;
 105          $this->notifications_table = $notifications_table;
 106          $this->user_notifications_table = $user_notifications_table;
 107      }
 108  
 109      /**
 110      * Load the user's notifications
 111      *
 112      * @param array $options Optional options to control what notifications are loaded
 113      *                notification_id        Notification id to load (or array of notification ids)
 114      *                user_id                User id to load notifications for (Default: $user->data['user_id'])
 115      *                order_by            Order by (Default: notification_time)
 116      *                order_dir            Order direction (Default: DESC)
 117      *                 limit                Number of notifications to load (Default: 5)
 118      *                 start                Notifications offset (Default: 0)
 119      *                 all_unread            Load all unread notifications? If set to true, count_unread is set to true (Default: false)
 120      *                 count_unread        Count all unread notifications? (Default: false)
 121      *                 count_total            Count all notifications? (Default: false)
 122      * @return array Array of information based on the request with keys:
 123      *    'notifications'        array of notification type objects
 124      *    'unread_count'        number of unread notifications the user has if count_unread is true in the options
 125      *    'total_count'        number of notifications the user has if count_total is true in the options
 126      */
 127  	public function load_notifications(array $options = array())
 128      {
 129          // Merge default options
 130          $options = array_merge(array(
 131              'notification_id'    => false,
 132              'user_id'            => $this->user->data['user_id'],
 133              'order_by'            => 'notification_time',
 134              'order_dir'            => 'DESC',
 135              'limit'                => 0,
 136              'start'                => 0,
 137              'all_unread'        => false,
 138              'count_unread'        => false,
 139              'count_total'        => false,
 140          ), $options);
 141  
 142          // If all_unread, count_unread must be true
 143          $options['count_unread'] = ($options['all_unread']) ? true : $options['count_unread'];
 144  
 145          // Anonymous users and bots never receive notifications
 146          if ($options['user_id'] == $this->user->data['user_id'] && ($this->user->data['user_id'] == ANONYMOUS || $this->user->data['user_type'] == USER_IGNORE))
 147          {
 148              return array(
 149                  'notifications'        => array(),
 150                  'unread_count'        => 0,
 151                  'total_count'        => 0,
 152              );
 153          }
 154  
 155          $notifications = $user_ids = array();
 156          $load_special = array();
 157          $total_count = $unread_count = 0;
 158  
 159          if ($options['count_unread'])
 160          {
 161              // Get the total number of unread notifications
 162              $sql = 'SELECT COUNT(n.notification_id) AS unread_count
 163                  FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
 164                  WHERE n.user_id = ' . (int) $options['user_id'] . '
 165                      AND n.notification_read = 0
 166                      AND nt.notification_type_id = n.notification_type_id
 167                      AND nt.notification_type_enabled = 1';
 168              $result = $this->db->sql_query($sql);
 169              $unread_count = (int) $this->db->sql_fetchfield('unread_count');
 170              $this->db->sql_freeresult($result);
 171          }
 172  
 173          if ($options['count_total'])
 174          {
 175              // Get the total number of notifications
 176              $sql = 'SELECT COUNT(n.notification_id) AS total_count
 177                  FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
 178                  WHERE n.user_id = ' . (int) $options['user_id'] . '
 179                      AND nt.notification_type_id = n.notification_type_id
 180                      AND nt.notification_type_enabled = 1';
 181              $result = $this->db->sql_query($sql);
 182              $total_count = (int) $this->db->sql_fetchfield('total_count');
 183              $this->db->sql_freeresult($result);
 184          }
 185  
 186          if (!$options['count_total'] || $total_count)
 187          {
 188              $rowset = array();
 189              $selected_unread_count = 0;
 190  
 191              // Get the main notifications
 192              $sql = 'SELECT n.*, nt.notification_type_name
 193                  FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
 194                  WHERE n.user_id = ' . (int) $options['user_id'] .
 195                      (($options['notification_id']) ? ' AND ' . $this->db->sql_in_set('n.notification_id', $options['notification_id']) : '') . '
 196                      AND nt.notification_type_id = n.notification_type_id
 197                      AND nt.notification_type_enabled = 1
 198                  ORDER BY n.' . $this->db->sql_escape($options['order_by']) . ' ' . $this->db->sql_escape($options['order_dir']);
 199              $result = $this->db->sql_query_limit($sql, $options['limit'], $options['start']);
 200  
 201              while ($row = $this->db->sql_fetchrow($result))
 202              {
 203                  $rowset[$row['notification_id']] = $row;
 204                  $selected_unread_count += (int) !$row['notification_read'];
 205              }
 206              $this->db->sql_freeresult($result);
 207  
 208              // Get all unread notifications
 209              if ($selected_unread_count < $unread_count && $options['all_unread'] && !empty($rowset))
 210              {
 211                  $sql = 'SELECT n.*, nt.notification_type_name
 212                  FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
 213                      WHERE n.user_id = ' . (int) $options['user_id'] . '
 214                          AND n.notification_read = 0
 215                          AND ' . $this->db->sql_in_set('n.notification_id', array_keys($rowset), true) . '
 216                          AND nt.notification_type_id = n.notification_type_id
 217                          AND nt.notification_type_enabled = 1
 218                      ORDER BY n.' . $this->db->sql_escape($options['order_by']) . ' ' . $this->db->sql_escape($options['order_dir']);
 219                  $result = $this->db->sql_query_limit($sql, $options['limit'], $options['start']);
 220  
 221                  while ($row = $this->db->sql_fetchrow($result))
 222                  {
 223                      $rowset[$row['notification_id']] = $row;
 224                  }
 225                  $this->db->sql_freeresult($result);
 226              }
 227  
 228              foreach ($rowset as $row)
 229              {
 230                  $notification = $this->get_item_type_class($row['notification_type_name'], $row);
 231  
 232                  // Array of user_ids to query all at once
 233                  $user_ids = array_merge($user_ids, $notification->users_to_query());
 234  
 235                  // Some notification types also require querying additional tables themselves
 236                  if (!isset($load_special[$row['notification_type_name']]))
 237                  {
 238                      $load_special[$row['notification_type_name']] = array();
 239                  }
 240                  $load_special[$row['notification_type_name']] = array_merge($load_special[$row['notification_type_name']], $notification->get_load_special());
 241  
 242                  $notifications[$row['notification_id']] = $notification;
 243              }
 244  
 245              $this->user_loader->load_users($user_ids);
 246  
 247              // Allow each type to load its own special items
 248              foreach ($load_special as $item_type => $data)
 249              {
 250                  $item_class = $this->get_item_type_class($item_type);
 251  
 252                  $item_class->load_special($data, $notifications);
 253              }
 254          }
 255  
 256          return array(
 257              'notifications'        => $notifications,
 258              'unread_count'        => $unread_count,
 259              'total_count'        => $total_count,
 260          );
 261      }
 262  
 263      /**
 264      * Mark notifications read
 265      *
 266      * @param bool|string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types). False to mark read for all item types
 267      * @param bool|int|array $item_id Item id or array of item ids. False to mark read for all item ids
 268      * @param bool|int|array $user_id User id or array of user ids. False to mark read for all user ids
 269      * @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False)
 270      */
 271  	public function mark_notifications_read($notification_type_name, $item_id, $user_id, $time = false)
 272      {
 273          $time = ($time !== false) ? $time : time();
 274  
 275          $sql = 'UPDATE ' . $this->notifications_table . "
 276              SET notification_read = 1
 277              WHERE notification_time <= " . (int) $time .
 278                  (($notification_type_name !== false) ? ' AND ' . $this->db->sql_in_set('notification_type_id', $this->get_notification_type_ids($notification_type_name)) : '') .
 279                  (($user_id !== false) ? ' AND ' . $this->db->sql_in_set('user_id', $user_id) : '') .
 280                  (($item_id !== false) ? ' AND ' . $this->db->sql_in_set('item_id', $item_id) : '');
 281          $this->db->sql_query($sql);
 282      }
 283  
 284      /**
 285      * Mark notifications read from a parent identifier
 286      *
 287      * @param string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types)
 288      * @param bool|int|array $item_parent_id Item parent id or array of item parent ids. False to mark read for all item parent ids
 289      * @param bool|int|array $user_id User id or array of user ids. False to mark read for all user ids
 290      * @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False)
 291      */
 292  	public function mark_notifications_read_by_parent($notification_type_name, $item_parent_id, $user_id, $time = false)
 293      {
 294          $time = ($time !== false) ? $time : time();
 295  
 296          $sql = 'UPDATE ' . $this->notifications_table . "
 297              SET notification_read = 1
 298              WHERE notification_time <= " . (int) $time .
 299                  (($notification_type_name !== false) ? ' AND ' . $this->db->sql_in_set('notification_type_id', $this->get_notification_type_ids($notification_type_name)) : '') .
 300                  (($item_parent_id !== false) ? ' AND ' . $this->db->sql_in_set('item_parent_id', $item_parent_id, false, true) : '') .
 301                  (($user_id !== false) ? ' AND ' . $this->db->sql_in_set('user_id', $user_id) : '');
 302          $this->db->sql_query($sql);
 303      }
 304  
 305      /**
 306      * Mark notifications read
 307      *
 308      * @param int|array $notification_id Notification id or array of notification ids.
 309      * @param bool|int $time Time at which to mark all notifications prior to as read. False to mark all as read. (Default: False)
 310      */
 311  	public function mark_notifications_read_by_id($notification_id, $time = false)
 312      {
 313          $time = ($time !== false) ? $time : time();
 314  
 315          $sql = 'UPDATE ' . $this->notifications_table . "
 316              SET notification_read = 1
 317              WHERE notification_time <= " . (int) $time . '
 318                  AND ' . $this->db->sql_in_set('notification_id', $notification_id);
 319          $this->db->sql_query($sql);
 320      }
 321  
 322      /**
 323      * Add a notification
 324      *
 325      * @param string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types)
 326      *            Note: If you send an array of types, any user who could receive multiple notifications from this single item will only receive
 327      *             a single notification. If they MUST receive multiple notifications, call this function multiple times instead of sending an array
 328      * @param array $data Data specific for this type that will be inserted
 329      * @param array $options Optional options to control what notifications are loaded
 330      *             ignore_users    array of data to specify which users should not receive certain types of notifications
 331      * @return array Information about what users were notified and how they were notified
 332      */
 333  	public function add_notifications($notification_type_name, $data, array $options = array())
 334      {
 335          $options = array_merge(array(
 336              'ignore_users'        => array(),
 337          ), $options);
 338  
 339          if (is_array($notification_type_name))
 340          {
 341              $notified_users = array();
 342              $temp_options = $options;
 343  
 344              foreach ($notification_type_name as $type)
 345              {
 346                  $temp_options['ignore_users'] = $options['ignore_users'] + $notified_users;
 347                  $notified_users += $this->add_notifications($type, $data, $temp_options);
 348              }
 349  
 350              return $notified_users;
 351          }
 352  
 353          $item_id = $this->get_item_type_class($notification_type_name)->get_item_id($data);
 354  
 355          // find out which users want to receive this type of notification
 356          $notify_users = $this->get_item_type_class($notification_type_name)->find_users_for_notification($data, $options);
 357  
 358          /**
 359          * Allow filtering the notify_users array for a notification that is about to be sent.
 360          * Here, $notify_users is already filtered by f_read and the ignored list included in the options variable
 361          *
 362          * @event core.notification_manager_add_notifications
 363          * @var    string    notification_type_name        The forum id from where the topic belongs
 364          * @var    array     data                        Data specific for the notification_type_name used will be inserted
 365          * @var    array     notify_users                The array of userid that are going to be notified for this notification. Set to array() to cancel.
 366          * @var    array     options                        The options that were used when this method was called (read only)
 367          *
 368          * @since 3.1.3-RC1
 369          */
 370          $vars = array(
 371              'notification_type_name',
 372              'data',
 373              'notify_users',
 374              'options',
 375          );
 376          extract($this->phpbb_dispatcher->trigger_event('core.notification_manager_add_notifications', compact($vars)));
 377  
 378          $this->add_notifications_for_users($notification_type_name, $data, $notify_users);
 379  
 380          return $notify_users;
 381      }
 382  
 383      /**
 384      * Add a notification for specific users
 385      *
 386      * @param string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types)
 387      * @param array $data Data specific for this type that will be inserted
 388      * @param array $notify_users User list to notify
 389      */
 390  	public function add_notifications_for_users($notification_type_name, $data, $notify_users)
 391      {
 392          if (is_array($notification_type_name))
 393          {
 394              foreach ($notification_type_name as $type)
 395              {
 396                  $this->add_notifications_for_users($type, $data, $notify_users);
 397              }
 398  
 399              return;
 400          }
 401  
 402          $notification_type_id = $this->get_notification_type_id($notification_type_name);
 403  
 404          $item_id = $this->get_item_type_class($notification_type_name)->get_item_id($data);
 405  
 406          $user_ids = array();
 407          $notification_objects = $notification_methods = array();
 408  
 409          // Never send notifications to the anonymous user!
 410          unset($notify_users[ANONYMOUS]);
 411  
 412          // Make sure not to send new notifications to users who've already been notified about this item
 413          // This may happen when an item was added, but now new users are able to see the item
 414          $sql = 'SELECT n.user_id
 415              FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt
 416              WHERE n.notification_type_id = ' . (int) $notification_type_id . '
 417                  AND n.item_id = ' . (int) $item_id . '
 418                  AND nt.notification_type_id = n.notification_type_id
 419                  AND nt.notification_type_enabled = 1';
 420          $result = $this->db->sql_query($sql);
 421          while ($row = $this->db->sql_fetchrow($result))
 422          {
 423              unset($notify_users[$row['user_id']]);
 424          }
 425          $this->db->sql_freeresult($result);
 426  
 427          if (!sizeof($notify_users))
 428          {
 429              return;
 430          }
 431  
 432          // Allow notifications to perform actions before creating the insert array (such as run a query to cache some data needed for all notifications)
 433          $notification = $this->get_item_type_class($notification_type_name);
 434          $pre_create_data = $notification->pre_create_insert_array($data, $notify_users);
 435          unset($notification);
 436  
 437          $insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, $this->notifications_table);
 438  
 439          // Go through each user so we can insert a row in the DB and then notify them by their desired means
 440          foreach ($notify_users as $user => $methods)
 441          {
 442              $notification = $this->get_item_type_class($notification_type_name);
 443  
 444              $notification->user_id = (int) $user;
 445  
 446              // Insert notification row using buffer.
 447              $insert_buffer->insert($notification->create_insert_array($data, $pre_create_data));
 448  
 449              // Users are needed to send notifications
 450              $user_ids = array_merge($user_ids, $notification->users_to_query());
 451  
 452              foreach ($methods as $method)
 453              {
 454                  // setup the notification methods and add the notification to the queue
 455                  if ($method) // blank means we just insert it as a notification, but do not notify them by any other means
 456                  {
 457                      if (!isset($notification_methods[$method]))
 458                      {
 459                          $notification_methods[$method] = $this->get_method_class($method);
 460                      }
 461  
 462                      $notification_methods[$method]->add_to_queue($notification);
 463                  }
 464              }
 465          }
 466  
 467          $insert_buffer->flush();
 468  
 469          // We need to load all of the users to send notifications
 470          $this->user_loader->load_users($user_ids);
 471  
 472          // run the queue for each method to send notifications
 473          foreach ($notification_methods as $method)
 474          {
 475              $method->notify();
 476          }
 477      }
 478  
 479      /**
 480      * Update a notification
 481      *
 482      * @param string|array $notification_type_name Type identifier or array of item types (only acceptable if the $data is identical for the specified types)
 483      * @param array $data Data specific for this type that will be updated
 484      */
 485  	public function update_notifications($notification_type_name, $data)
 486      {
 487          if (is_array($notification_type_name))
 488          {
 489              foreach ($notification_type_name as $type)
 490              {
 491                  $this->update_notifications($type, $data);
 492              }
 493  
 494              return;
 495          }
 496  
 497          $notification = $this->get_item_type_class($notification_type_name);
 498  
 499          // Allow the notifications class to over-ride the update_notifications functionality
 500          if (method_exists($notification, 'update_notifications'))
 501          {
 502              // Return False to over-ride the rest of the update
 503              if ($notification->update_notifications($data) === false)
 504              {
 505                  return;
 506              }
 507          }
 508  
 509          $notification_type_id = $this->get_notification_type_id($notification_type_name);
 510          $item_id = $notification->get_item_id($data);
 511          $update_array = $notification->create_update_array($data);
 512  
 513          $sql = 'UPDATE ' . $this->notifications_table . '
 514              SET ' . $this->db->sql_build_array('UPDATE', $update_array) . '
 515              WHERE notification_type_id = ' . (int) $notification_type_id . '
 516                  AND item_id = ' . (int) $item_id;
 517          $this->db->sql_query($sql);
 518      }
 519  
 520      /**
 521      * Delete a notification
 522      *
 523      * @param string|array $notification_type_name Type identifier or array of item types (only acceptable if the $item_id is identical for the specified types)
 524      * @param int|array $item_id Identifier within the type (or array of ids)
 525      * @param mixed $parent_id Parent identifier within the type (or array of ids), used in combination with item_id if specified (Default: false; not checked)
 526      */
 527  	public function delete_notifications($notification_type_name, $item_id, $parent_id = false)
 528      {
 529          if (is_array($notification_type_name))
 530          {
 531              foreach ($notification_type_name as $type)
 532              {
 533                  $this->delete_notifications($type, $item_id, $parent_id);
 534              }
 535  
 536              return;
 537          }
 538  
 539          $notification_type_id = $this->get_notification_type_id($notification_type_name);
 540  
 541          $sql = 'DELETE FROM ' . $this->notifications_table . '
 542              WHERE notification_type_id = ' . (int) $notification_type_id . '
 543                  AND ' . $this->db->sql_in_set('item_id', $item_id) .
 544                  (($parent_id !== false) ? ' AND ' . $this->db->sql_in_set('item_parent_id', $parent_id) : '');
 545          $this->db->sql_query($sql);
 546      }
 547  
 548      /**
 549      * Get all of the subscription types
 550      *
 551      * @return array Array of item types
 552      */
 553  	public function get_subscription_types()
 554      {
 555          if ($this->subscription_types === null)
 556          {
 557              $this->subscription_types = array();
 558  
 559              foreach ($this->notification_types as $type_name => $data)
 560              {
 561                  $type = $this->get_item_type_class($type_name);
 562  
 563                  if ($type instanceof \phpbb\notification\type\type_interface && $type->is_available())
 564                  {
 565                      $options = array_merge(array(
 566                          'id' => $type->get_type(),
 567                          'lang' => 'NOTIFICATION_TYPE_' . strtoupper($type->get_type()),
 568                          'group' => 'NOTIFICATION_GROUP_MISCELLANEOUS',
 569                      ), (($type::$notification_option !== false) ? $type::$notification_option : array()));
 570  
 571                      $this->subscription_types[$options['group']][$options['id']] = $options;
 572                  }
 573              }
 574  
 575              // Move Miscellaneous to the very last section
 576              if (isset($this->subscription_types['NOTIFICATION_GROUP_MISCELLANEOUS']))
 577              {
 578                  $miscellaneous = $this->subscription_types['NOTIFICATION_GROUP_MISCELLANEOUS'];
 579                  unset($this->subscription_types['NOTIFICATION_GROUP_MISCELLANEOUS']);
 580                  $this->subscription_types['NOTIFICATION_GROUP_MISCELLANEOUS'] = $miscellaneous;
 581              }
 582          }
 583  
 584          return $this->subscription_types;
 585      }
 586  
 587      /**
 588      * Get all of the subscription methods
 589      *
 590      * @return array Array of methods
 591      */
 592  	public function get_subscription_methods()
 593      {
 594          $subscription_methods = array();
 595  
 596          foreach ($this->notification_methods as $method_name => $data)
 597          {
 598              $method = $this->get_method_class($method_name);
 599  
 600              if ($method instanceof \phpbb\notification\method\method_interface && $method->is_available())
 601              {
 602                  $subscription_methods[$method_name] = array(
 603                      'id'        => $method->get_type(),
 604                      'lang'        => str_replace('.', '_', strtoupper($method->get_type())),
 605                  );
 606              }
 607          }
 608  
 609          return $subscription_methods;
 610      }
 611  
 612  
 613      /**
 614      * Get user's notification data
 615      *
 616      * @param int $user_id The user_id of the user to get the notifications for
 617      *
 618      * @return array User's notification
 619      */
 620  	protected function get_user_notifications($user_id)
 621      {
 622          $sql = 'SELECT method, notify, item_type
 623                  FROM ' . $this->user_notifications_table . '
 624                  WHERE user_id = ' . (int) $user_id . '
 625                      AND item_id = 0';
 626  
 627          $result = $this->db->sql_query($sql);
 628          $user_notifications = array();
 629  
 630          while ($row = $this->db->sql_fetchrow($result))
 631          {
 632              $user_notifications[$row['item_type']][] = $row;
 633          }
 634  
 635          $this->db->sql_freeresult($result);
 636  
 637          return $user_notifications;
 638      }
 639  
 640      /**
 641      * Get global subscriptions (item_id = 0)
 642      *
 643      * @param bool|int $user_id The user_id to add the subscription for (bool false for current user)
 644      *
 645      * @return array Subscriptions
 646      */
 647  	public function get_global_subscriptions($user_id = false)
 648      {
 649          $user_id = ($user_id === false) ? $this->user->data['user_id'] : $user_id;
 650  
 651          $subscriptions = array();
 652  
 653          $user_notifications = $this->get_user_notifications($user_id);
 654  
 655          foreach ($this->get_subscription_types() as $types)
 656          {
 657              foreach ($types as $id => $type)
 658              {
 659  
 660                  if (empty($user_notifications[$id]))
 661                  {
 662                      // No rows at all, default to ''
 663                      $subscriptions[$id] = array('');
 664                  }
 665                  else
 666                  {
 667                      foreach ($user_notifications[$id] as $user_notification)
 668                      {
 669                          if (!$user_notification['notify'])
 670                          {
 671                              continue;
 672                          }
 673  
 674                          if (!isset($subscriptions[$id]))
 675                          {
 676                              $subscriptions[$id] = array();
 677                          }
 678  
 679                          $subscriptions[$id][] = $user_notification['method'];
 680                      }
 681                  }
 682              }
 683          }
 684  
 685          return $subscriptions;
 686      }
 687  
 688      /**
 689      * Add a subscription
 690      *
 691      * @param string $item_type Type identifier of the subscription
 692      * @param int $item_id The id of the item
 693      * @param string $method The method of the notification e.g. '', 'email', or 'jabber'
 694      * @param bool|int $user_id The user_id to add the subscription for (bool false for current user)
 695      */
 696  	public function add_subscription($item_type, $item_id = 0, $method = '', $user_id = false)
 697      {
 698          if ($method !== '')
 699          {
 700              // Make sure to subscribe them to the base subscription
 701              $this->add_subscription($item_type, $item_id, '', $user_id);
 702          }
 703  
 704          $user_id = ($user_id === false) ? $this->user->data['user_id'] : $user_id;
 705  
 706          $sql = 'SELECT notify
 707              FROM ' . $this->user_notifications_table . "
 708              WHERE item_type = '" . $this->db->sql_escape($item_type) . "'
 709                  AND item_id = " . (int) $item_id . '
 710                  AND user_id = ' .(int) $user_id . "
 711                  AND method = '" . $this->db->sql_escape($method) . "'";
 712          $this->db->sql_query($sql);
 713          $current = $this->db->sql_fetchfield('notify');
 714          $this->db->sql_freeresult();
 715  
 716          if ($current === false)
 717          {
 718              $sql = 'INSERT INTO ' . $this->user_notifications_table . ' ' .
 719                  $this->db->sql_build_array('INSERT', array(
 720                      'item_type'        => $item_type,
 721                      'item_id'        => (int) $item_id,
 722                      'user_id'        => (int) $user_id,
 723                      'method'        => $method,
 724                      'notify'        => 1,
 725                  ));
 726              $this->db->sql_query($sql);
 727          }
 728          else if (!$current)
 729          {
 730              $sql = 'UPDATE ' . $this->user_notifications_table . "
 731                  SET notify = 1
 732                  WHERE item_type = '" . $this->db->sql_escape($item_type) . "'
 733                      AND item_id = " . (int) $item_id . '
 734                      AND user_id = ' .(int) $user_id . "
 735                      AND method = '" . $this->db->sql_escape($method) . "'";
 736              $this->db->sql_query($sql);
 737          }
 738      }
 739  
 740      /**
 741      * Delete a subscription
 742      *
 743      * @param string $item_type Type identifier of the subscription
 744      * @param int $item_id The id of the item
 745      * @param string $method The method of the notification e.g. '', 'email', or 'jabber'
 746      * @param bool|int $user_id The user_id to add the subscription for (bool false for current user)
 747      */
 748  	public function delete_subscription($item_type, $item_id = 0, $method = '', $user_id = false)
 749      {
 750          $user_id = ($user_id === false) ? $this->user->data['user_id'] : $user_id;
 751  
 752          // If no method, make sure that no other notification methods for this item are selected before deleting
 753          if ($method === '')
 754          {
 755              $sql = 'SELECT COUNT(*) as num_notifications
 756                  FROM ' . $this->user_notifications_table . "
 757                  WHERE item_type = '" . $this->db->sql_escape($item_type) . "'
 758                      AND item_id = " . (int) $item_id . '
 759                      AND user_id = ' .(int) $user_id . "
 760                      AND method <> ''
 761                      AND notify = 1";
 762              $this->db->sql_query($sql);
 763              $num_notifications = $this->db->sql_fetchfield('num_notifications');
 764              $this->db->sql_freeresult();
 765  
 766              if ($num_notifications)
 767              {
 768                  return;
 769              }
 770          }
 771  
 772          $sql = 'UPDATE ' . $this->user_notifications_table . "
 773              SET notify = 0
 774              WHERE item_type = '" . $this->db->sql_escape($item_type) . "'
 775                  AND item_id = " . (int) $item_id . '
 776                  AND user_id = ' .(int) $user_id . "
 777                  AND method = '" . $this->db->sql_escape($method) . "'";
 778          $this->db->sql_query($sql);
 779  
 780          if (!$this->db->sql_affectedrows())
 781          {
 782              $sql = 'INSERT INTO ' . $this->user_notifications_table . ' ' .
 783                  $this->db->sql_build_array('INSERT', array(
 784                      'item_type'        => $item_type,
 785                      'item_id'        => (int) $item_id,
 786                      'user_id'        => (int) $user_id,
 787                      'method'        => $method,
 788                      'notify'        => 0,
 789                  ));
 790              $this->db->sql_query($sql);
 791          }
 792      }
 793  
 794      /**
 795      * Disable all notifications of a certain type
 796      *
 797      * This should be called when an extension which has notification types
 798      * is disabled so that all those notifications are hidden and do not
 799      * cause errors
 800      *
 801      * @param string $notification_type_name Type identifier of the subscription
 802      */
 803  	public function disable_notifications($notification_type_name)
 804      {
 805          $sql = 'UPDATE ' . $this->notification_types_table . "
 806              SET notification_type_enabled = 0
 807              WHERE notification_type_name = '" . $this->db->sql_escape($notification_type_name) . "'";
 808          $this->db->sql_query($sql);
 809      }
 810  
 811      /**
 812      * Purge all notifications of a certain type
 813      *
 814      * This should be called when an extension which has notification types
 815      * is purged so that all those notifications are removed
 816      *
 817      * @param string $notification_type_name Type identifier of the subscription
 818      */
 819  	public function purge_notifications($notification_type_name)
 820      {
 821          // If a notification is never used, its type will not be added to the database
 822          // nor its id cached. If this method is called by an extension during the
 823          // purge step, and that extension never used its notifications,
 824          // get_notification_type_id() will throw an exception. However,
 825          // because no notification type was added to the database,
 826          // there is nothing to delete, so we can silently drop the exception.
 827          try
 828          {
 829              $notification_type_id = $this->get_notification_type_id($notification_type_name);
 830  
 831              $sql = 'DELETE FROM ' . $this->notifications_table . '
 832                  WHERE notification_type_id = ' . (int) $notification_type_id;
 833              $this->db->sql_query($sql);
 834  
 835              $sql = 'DELETE FROM ' . $this->notification_types_table . '
 836                  WHERE notification_type_id = ' . (int) $notification_type_id;
 837              $this->db->sql_query($sql);
 838  
 839              $this->cache->destroy('notification_type_ids');
 840          }
 841          catch (\phpbb\notification\exception $e)
 842          {
 843              // Continue
 844          }
 845      }
 846  
 847      /**
 848      * Enable all notifications of a certain type
 849      *
 850      * This should be called when an extension which has notification types
 851      * that was disabled is re-enabled so that all those notifications that
 852      * were hidden are shown again
 853      *
 854      * @param string $notification_type_name Type identifier of the subscription
 855      */
 856  	public function enable_notifications($notification_type_name)
 857      {
 858          $sql = 'UPDATE ' . $this->notification_types_table . "
 859              SET notification_type_enabled = 1
 860              WHERE notification_type_name = '" . $this->db->sql_escape($notification_type_name) . "'";
 861          $this->db->sql_query($sql);
 862      }
 863  
 864      /**
 865      * Delete all notifications older than a certain time
 866      *
 867      * @param int $timestamp Unix timestamp to delete all notifications that were created before
 868      * @param bool $only_read True (default) to only prune read notifications
 869      */
 870  	public function prune_notifications($timestamp, $only_read = true)
 871      {
 872          $sql = 'DELETE FROM ' . $this->notifications_table . '
 873              WHERE notification_time < ' . (int) $timestamp .
 874                  (($only_read) ? ' AND notification_read = 1' : '');
 875          $this->db->sql_query($sql);
 876  
 877          $this->config->set('read_notification_last_gc', time(), false);
 878      }
 879  
 880      /**
 881      * Helper to get the notifications item type class and set it up
 882      */
 883  	public function get_item_type_class($notification_type_name, $data = array())
 884      {
 885          $item = $this->load_object($notification_type_name);
 886  
 887          $item->set_initial_data($data);
 888  
 889          return $item;
 890      }
 891  
 892      /**
 893      * Helper to get the notifications method class and set it up
 894      */
 895  	public function get_method_class($method_name)
 896      {
 897          return $this->load_object($method_name);
 898      }
 899  
 900      /**
 901      * Helper to load objects (notification types/methods)
 902      */
 903  	protected function load_object($object_name)
 904      {
 905          $object = $this->phpbb_container->get($object_name);
 906  
 907          if (method_exists($object, 'set_notification_manager'))
 908          {
 909              $object->set_notification_manager($this);
 910          }
 911  
 912          return $object;
 913      }
 914  
 915      /**
 916      * Get the notification type id from the name
 917      *
 918      * @param string $notification_type_name The name
 919      * @return int the notification_type_id
 920      * @throws \phpbb\notification\exception
 921      */
 922  	public function get_notification_type_id($notification_type_name)
 923      {
 924          $notification_type_ids = $this->cache->get('notification_type_ids');
 925  
 926          $this->db->sql_transaction('begin');
 927  
 928          if ($notification_type_ids === false)
 929          {
 930              $notification_type_ids = array();
 931  
 932              $sql = 'SELECT notification_type_id, notification_type_name
 933                  FROM ' . $this->notification_types_table;
 934              $result = $this->db->sql_query($sql);
 935              while ($row = $this->db->sql_fetchrow($result))
 936              {
 937                  $notification_type_ids[$row['notification_type_name']] = (int) $row['notification_type_id'];
 938              }
 939              $this->db->sql_freeresult($result);
 940  
 941              $this->cache->put('notification_type_ids', $notification_type_ids);
 942          }
 943  
 944          if (!isset($notification_type_ids[$notification_type_name]))
 945          {
 946              if (!isset($this->notification_types[$notification_type_name]) && !isset($this->notification_types['notification.type.' . $notification_type_name]))
 947              {
 948                  $this->db->sql_transaction('rollback');
 949                  throw new \phpbb\notification\exception($this->user->lang('NOTIFICATION_TYPE_NOT_EXIST', $notification_type_name));
 950              }
 951  
 952              $sql = 'INSERT INTO ' . $this->notification_types_table . ' ' . $this->db->sql_build_array('INSERT', array(
 953                  'notification_type_name'        => $notification_type_name,
 954                  'notification_type_enabled'        => 1,
 955              ));
 956              $this->db->sql_query($sql);
 957  
 958              $notification_type_ids[$notification_type_name] = (int) $this->db->sql_nextid();
 959  
 960              $this->cache->put('notification_type_ids', $notification_type_ids);
 961          }
 962  
 963          $this->db->sql_transaction('commit');
 964  
 965          return $notification_type_ids[$notification_type_name];
 966      }
 967  
 968      /**
 969      * Get notification type ids (as an array)
 970      *
 971      * @param string|array $notification_type_names Notification type names
 972      * @return array Array of integers
 973      */
 974  	public function get_notification_type_ids($notification_type_names)
 975      {
 976          if (!is_array($notification_type_names))
 977          {
 978              $notification_type_names = array($notification_type_names);
 979          }
 980  
 981          $notification_type_ids = array();
 982  
 983          foreach ($notification_type_names as $name)
 984          {
 985              $notification_type_ids[$name] = $this->get_notification_type_id($name);
 986          }
 987  
 988          return $notification_type_ids;
 989      }
 990  }


Generated: Thu Jan 11 00:25:41 2018 Cross-referenced by PHPXref 0.7.1