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