Verzeichnisstruktur phpBB-3.2.0


Veröffentlicht
06.01.2017

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

      (Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

manager.php

Zuletzt modifiziert: 09.10.2024, 12:52 - Dateigröße: 31.62 KiB


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