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