Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
75.00% |
120 / 160 |
|
66.67% |
10 / 15 |
CRAP | |
0.00% |
0 / 1 |
| board | |
75.00% |
120 / 160 |
|
66.67% |
10 / 15 |
146.56 | |
0.00% |
0 / 1 |
| __construct | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
1 | |||
| add_to_queue | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| get_type | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| is_available | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| is_enabled_by_default | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
| get_notified_users | |
100.00% |
14 / 14 |
|
100.00% |
1 / 1 |
6 | |||
| load_notifications | |
71.62% |
53 / 74 |
|
0.00% |
0 / 1 |
27.25 | |||
| notify | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
2 | |||
| update_notification | |
92.31% |
12 / 13 |
|
0.00% |
0 / 1 |
7.02 | |||
| mark_notifications | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
9 | |||
| mark_notifications_by_parent | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
9 | |||
| mark_notifications_by_id | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
20 | |||
| delete_notifications | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
6 | |||
| prune_notifications | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
6 | |||
| purge_notifications | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
2 | |||
| 1 | <?php |
| 2 | /** |
| 3 | * |
| 4 | * This file is part of the phpBB Forum Software package. |
| 5 | * |
| 6 | * @copyright (c) phpBB Limited <https://www.phpbb.com> |
| 7 | * @license GNU General Public License, version 2 (GPL-2.0) |
| 8 | * |
| 9 | * For full copyright and license information, please see |
| 10 | * the docs/CREDITS.txt file. |
| 11 | * |
| 12 | */ |
| 13 | |
| 14 | namespace phpbb\notification\method; |
| 15 | |
| 16 | /** |
| 17 | * In Board notification method class |
| 18 | * This class handles in board notifications. This method is enabled by default. |
| 19 | * |
| 20 | * @package notifications |
| 21 | */ |
| 22 | class board extends \phpbb\notification\method\base |
| 23 | { |
| 24 | /** @var \phpbb\user_loader */ |
| 25 | protected $user_loader; |
| 26 | |
| 27 | /** @var \phpbb\db\driver\driver_interface */ |
| 28 | protected $db; |
| 29 | |
| 30 | /** @var \phpbb\cache\driver\driver_interface */ |
| 31 | protected $cache; |
| 32 | |
| 33 | /** @var \phpbb\user */ |
| 34 | protected $user; |
| 35 | |
| 36 | /** @var \phpbb\config\config */ |
| 37 | protected $config; |
| 38 | |
| 39 | /** @var string */ |
| 40 | protected $notification_types_table; |
| 41 | |
| 42 | /** @var string */ |
| 43 | protected $notifications_table; |
| 44 | |
| 45 | /** |
| 46 | * Notification Method Board Constructor |
| 47 | * |
| 48 | * @param \phpbb\user_loader $user_loader |
| 49 | * @param \phpbb\db\driver\driver_interface $db |
| 50 | * @param \phpbb\cache\driver\driver_interface $cache |
| 51 | * @param \phpbb\user $user |
| 52 | * @param \phpbb\config\config $config |
| 53 | * @param string $notification_types_table |
| 54 | * @param string $notifications_table |
| 55 | */ |
| 56 | public function __construct(\phpbb\user_loader $user_loader, \phpbb\db\driver\driver_interface $db, \phpbb\cache\driver\driver_interface $cache, \phpbb\user $user, \phpbb\config\config $config, $notification_types_table, $notifications_table) |
| 57 | { |
| 58 | $this->user_loader = $user_loader; |
| 59 | $this->db = $db; |
| 60 | $this->cache = $cache; |
| 61 | $this->user = $user; |
| 62 | $this->config = $config; |
| 63 | $this->notification_types_table = $notification_types_table; |
| 64 | $this->notifications_table = $notifications_table; |
| 65 | |
| 66 | } |
| 67 | |
| 68 | /** |
| 69 | * {@inheritdoc} |
| 70 | */ |
| 71 | public function add_to_queue(\phpbb\notification\type\type_interface $notification) |
| 72 | { |
| 73 | $this->queue[] = $notification; |
| 74 | } |
| 75 | |
| 76 | /** |
| 77 | * {@inheritdoc} |
| 78 | */ |
| 79 | public function get_type() |
| 80 | { |
| 81 | return 'notification.method.board'; |
| 82 | } |
| 83 | |
| 84 | /** |
| 85 | * {@inheritdoc} |
| 86 | */ |
| 87 | public function is_available() |
| 88 | { |
| 89 | return $this->config['allow_board_notifications']; |
| 90 | } |
| 91 | |
| 92 | /** |
| 93 | * {@inheritdoc} |
| 94 | */ |
| 95 | public function is_enabled_by_default() |
| 96 | { |
| 97 | return true; |
| 98 | } |
| 99 | |
| 100 | /** |
| 101 | * {@inheritdoc} |
| 102 | */ |
| 103 | public function get_notified_users($notification_type_id, array $options) |
| 104 | { |
| 105 | $notified_users = array(); |
| 106 | $sql = 'SELECT n.* |
| 107 | FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt |
| 108 | WHERE n.notification_type_id = ' . (int) $notification_type_id . |
| 109 | (isset($options['item_id']) ? ' AND n.item_id = ' . (int) $options['item_id'] : '') . |
| 110 | (isset($options['item_parent_id']) ? ' AND n.item_parent_id = ' . (int) $options['item_parent_id'] : '') . |
| 111 | (isset($options['user_id']) ? ' AND n.user_id = ' . (int) $options['user_id'] : '') . |
| 112 | (isset($options['read']) ? ' AND n.notification_read = ' . (int) $options['read'] : '') .' |
| 113 | AND nt.notification_type_id = n.notification_type_id |
| 114 | AND nt.notification_type_enabled = 1'; |
| 115 | $result = $this->db->sql_query($sql); |
| 116 | while ($row = $this->db->sql_fetchrow($result)) |
| 117 | { |
| 118 | $notified_users[$row['user_id']] = $row; |
| 119 | } |
| 120 | $this->db->sql_freeresult($result); |
| 121 | |
| 122 | return $notified_users; |
| 123 | } |
| 124 | |
| 125 | /** |
| 126 | * {@inheritdoc} |
| 127 | */ |
| 128 | public function load_notifications(array $options = array()) |
| 129 | { |
| 130 | // Merge default options |
| 131 | $options = array_merge(array( |
| 132 | 'notification_id' => false, |
| 133 | 'user_id' => $this->user->data['user_id'], |
| 134 | 'order_by' => 'notification_time', |
| 135 | 'order_dir' => 'DESC', |
| 136 | 'limit' => 0, |
| 137 | 'start' => 0, |
| 138 | 'all_unread' => false, |
| 139 | 'count_unread' => false, |
| 140 | 'count_total' => false, |
| 141 | ), $options); |
| 142 | |
| 143 | // If all_unread, count_unread must be true |
| 144 | $options['count_unread'] = ($options['all_unread']) ? true : $options['count_unread']; |
| 145 | |
| 146 | // Anonymous users and bots never receive notifications |
| 147 | if ($options['user_id'] == $this->user->data['user_id'] && ($this->user->data['user_id'] == ANONYMOUS || $this->user->data['user_type'] == USER_IGNORE)) |
| 148 | { |
| 149 | return array( |
| 150 | 'notifications' => array(), |
| 151 | 'unread_count' => 0, |
| 152 | 'total_count' => 0, |
| 153 | ); |
| 154 | } |
| 155 | |
| 156 | $notifications = $user_ids = array(); |
| 157 | $load_special = array(); |
| 158 | $total_count = $unread_count = 0; |
| 159 | |
| 160 | if ($options['count_unread']) |
| 161 | { |
| 162 | // Get the total number of unread notifications |
| 163 | $sql = 'SELECT COUNT(n.notification_id) AS unread_count |
| 164 | FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt |
| 165 | WHERE n.user_id = ' . (int) $options['user_id'] . ' |
| 166 | AND n.notification_read = 0 |
| 167 | AND nt.notification_type_id = n.notification_type_id |
| 168 | AND nt.notification_type_enabled = 1'; |
| 169 | $result = $this->db->sql_query($sql); |
| 170 | $unread_count = (int) $this->db->sql_fetchfield('unread_count'); |
| 171 | $this->db->sql_freeresult($result); |
| 172 | } |
| 173 | |
| 174 | if ($options['count_total']) |
| 175 | { |
| 176 | // Get the total number of notifications |
| 177 | $sql = 'SELECT COUNT(n.notification_id) AS total_count |
| 178 | FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt |
| 179 | WHERE n.user_id = ' . (int) $options['user_id'] . ' |
| 180 | AND nt.notification_type_id = n.notification_type_id |
| 181 | AND nt.notification_type_enabled = 1'; |
| 182 | $result = $this->db->sql_query($sql); |
| 183 | $total_count = (int) $this->db->sql_fetchfield('total_count'); |
| 184 | $this->db->sql_freeresult($result); |
| 185 | } |
| 186 | |
| 187 | if (!$options['count_total'] || $total_count) |
| 188 | { |
| 189 | $rowset = array(); |
| 190 | |
| 191 | // Get the main notifications |
| 192 | $sql = 'SELECT n.*, nt.notification_type_name |
| 193 | FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt |
| 194 | WHERE n.user_id = ' . (int) $options['user_id'] . |
| 195 | (($options['notification_id']) ? ((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']) : '') . ' |
| 196 | AND nt.notification_type_id = n.notification_type_id |
| 197 | AND nt.notification_type_enabled = 1 |
| 198 | ORDER BY n.' . $this->db->sql_escape($options['order_by']) . ' ' . $this->db->sql_escape($options['order_dir']); |
| 199 | $result = $this->db->sql_query_limit($sql, $options['limit'], $options['start']); |
| 200 | |
| 201 | while ($row = $this->db->sql_fetchrow($result)) |
| 202 | { |
| 203 | $rowset[$row['notification_id']] = $row; |
| 204 | } |
| 205 | $this->db->sql_freeresult($result); |
| 206 | |
| 207 | // Get all unread notifications |
| 208 | if ($unread_count && $options['all_unread'] && !empty($rowset)) |
| 209 | { |
| 210 | $sql = 'SELECT n.*, nt.notification_type_name |
| 211 | FROM ' . $this->notifications_table . ' n, ' . $this->notification_types_table . ' nt |
| 212 | WHERE n.user_id = ' . (int) $options['user_id'] . ' |
| 213 | AND n.notification_read = 0 |
| 214 | AND ' . $this->db->sql_in_set('n.notification_id', array_keys($rowset), true) . ' |
| 215 | AND nt.notification_type_id = n.notification_type_id |
| 216 | AND nt.notification_type_enabled = 1 |
| 217 | ORDER BY n.' . $this->db->sql_escape($options['order_by']) . ' ' . $this->db->sql_escape($options['order_dir']); |
| 218 | $result = $this->db->sql_query_limit($sql, $options['limit'], $options['start']); |
| 219 | |
| 220 | while ($row = $this->db->sql_fetchrow($result)) |
| 221 | { |
| 222 | $rowset[$row['notification_id']] = $row; |
| 223 | } |
| 224 | $this->db->sql_freeresult($result); |
| 225 | } |
| 226 | |
| 227 | foreach ($rowset as $row) |
| 228 | { |
| 229 | $notification = $this->notification_manager->get_item_type_class($row['notification_type_name'], $row); |
| 230 | |
| 231 | // Array of user_ids to query all at once |
| 232 | $user_ids = array_merge($user_ids, $notification->users_to_query()); |
| 233 | |
| 234 | // Some notification types also require querying additional tables themselves |
| 235 | if (!isset($load_special[$row['notification_type_name']])) |
| 236 | { |
| 237 | $load_special[$row['notification_type_name']] = array(); |
| 238 | } |
| 239 | $load_special[$row['notification_type_name']] = array_merge($load_special[$row['notification_type_name']], $notification->get_load_special()); |
| 240 | |
| 241 | $notifications[$row['notification_id']] = $notification; |
| 242 | } |
| 243 | |
| 244 | $this->user_loader->load_users($user_ids); |
| 245 | |
| 246 | // Allow each type to load its own special items |
| 247 | foreach ($load_special as $item_type => $data) |
| 248 | { |
| 249 | $item_class = $this->notification_manager->get_item_type_class($item_type); |
| 250 | |
| 251 | $item_class->load_special($data, $notifications); |
| 252 | } |
| 253 | } |
| 254 | |
| 255 | return array( |
| 256 | 'notifications' => $notifications, |
| 257 | 'unread_count' => $unread_count, |
| 258 | 'total_count' => $total_count, |
| 259 | ); |
| 260 | } |
| 261 | |
| 262 | /** |
| 263 | * {@inheritdoc} |
| 264 | */ |
| 265 | public function notify() |
| 266 | { |
| 267 | $insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, $this->notifications_table); |
| 268 | |
| 269 | /** @var \phpbb\notification\type\type_interface $notification */ |
| 270 | foreach ($this->queue as $notification) |
| 271 | { |
| 272 | $data = $notification->get_insert_array(); |
| 273 | $insert_buffer->insert($data); |
| 274 | } |
| 275 | |
| 276 | $insert_buffer->flush(); |
| 277 | |
| 278 | // We're done, empty the queue |
| 279 | $this->empty_queue(); |
| 280 | } |
| 281 | |
| 282 | /** |
| 283 | * {@inheritdoc} |
| 284 | */ |
| 285 | public function update_notification($notification, array $data, array $options) |
| 286 | { |
| 287 | // Allow the notifications class to over-ride the update_notifications functionality |
| 288 | if (method_exists($notification, 'update_notifications')) |
| 289 | { |
| 290 | // Return False to over-ride the rest of the update |
| 291 | if ($notification->update_notifications($data) === false) |
| 292 | { |
| 293 | return; |
| 294 | } |
| 295 | } |
| 296 | |
| 297 | $notification_type_id = $this->notification_manager->get_notification_type_id($notification->get_type()); |
| 298 | $update_array = $notification->create_update_array($data); |
| 299 | |
| 300 | $sql = 'UPDATE ' . $this->notifications_table . ' |
| 301 | SET ' . $this->db->sql_build_array('UPDATE', $update_array) . ' |
| 302 | WHERE notification_type_id = ' . (int) $notification_type_id . |
| 303 | (isset($options['item_id']) ? ' AND item_id = ' . (int) $options['item_id'] : '') . |
| 304 | (isset($options['item_parent_id']) ? ' AND item_parent_id = ' . (int) $options['item_parent_id'] : '') . |
| 305 | (isset($options['user_id']) ? ' AND user_id = ' . (int) $options['user_id'] : '') . |
| 306 | (isset($options['read']) ? ' AND notification_read = ' . (int) $options['read'] : ''); |
| 307 | $this->db->sql_query($sql); |
| 308 | } |
| 309 | |
| 310 | /** |
| 311 | * {@inheritdoc} |
| 312 | */ |
| 313 | public function mark_notifications($notification_type_id, $item_id, $user_id, $time = false, $mark_read = true) |
| 314 | { |
| 315 | $time = ($time !== false) ? $time : time(); |
| 316 | |
| 317 | $sql = 'UPDATE ' . $this->notifications_table . ' |
| 318 | SET notification_read = ' . ($mark_read ? 1 : 0) . ' |
| 319 | WHERE notification_time <= ' . (int) $time . |
| 320 | (($notification_type_id !== false) ? ' AND ' . |
| 321 | (is_array($notification_type_id) ? $this->db->sql_in_set('notification_type_id', $notification_type_id) : 'notification_type_id = ' . $notification_type_id) : '') . |
| 322 | (($user_id !== false) ? ' AND ' . (is_array($user_id) ? $this->db->sql_in_set('user_id', $user_id) : 'user_id = ' . (int) $user_id) : '') . |
| 323 | (($item_id !== false) ? ' AND ' . (is_array($item_id) ? $this->db->sql_in_set('item_id', $item_id) : 'item_id = ' . (int) $item_id) : ''); |
| 324 | $this->db->sql_query($sql); |
| 325 | } |
| 326 | |
| 327 | /** |
| 328 | * {@inheritdoc} |
| 329 | */ |
| 330 | public function mark_notifications_by_parent($notification_type_id, $item_parent_id, $user_id, $time = false, $mark_read = true) |
| 331 | { |
| 332 | $time = ($time !== false) ? $time : time(); |
| 333 | |
| 334 | $sql = 'UPDATE ' . $this->notifications_table . ' |
| 335 | SET notification_read = ' . ($mark_read ? 1 : 0) . ' |
| 336 | WHERE notification_time <= ' . (int) $time . |
| 337 | (($notification_type_id !== false) ? ' AND ' . |
| 338 | (is_array($notification_type_id) ? $this->db->sql_in_set('notification_type_id', $notification_type_id) : 'notification_type_id = ' . $notification_type_id) : '') . |
| 339 | (($item_parent_id !== false) ? ' AND ' . (is_array($item_parent_id) ? $this->db->sql_in_set('item_parent_id', $item_parent_id, false, true) : 'item_parent_id = ' . (int) $item_parent_id) : '') . |
| 340 | (($user_id !== false) ? ' AND ' . (is_array($user_id) ? $this->db->sql_in_set('user_id', $user_id) : 'user_id = ' . (int) $user_id) : ''); |
| 341 | $this->db->sql_query($sql); |
| 342 | } |
| 343 | |
| 344 | /** |
| 345 | * {@inheritdoc} |
| 346 | */ |
| 347 | public function mark_notifications_by_id($notification_id, $time = false, $mark_read = true) |
| 348 | { |
| 349 | $time = ($time !== false) ? $time : time(); |
| 350 | |
| 351 | $sql = 'UPDATE ' . $this->notifications_table . ' |
| 352 | SET notification_read = ' . ($mark_read ? 1 : 0) . ' |
| 353 | WHERE notification_time <= ' . (int) $time . ' |
| 354 | AND ' . ((is_array($notification_id)) ? $this->db->sql_in_set('notification_id', $notification_id) : 'notification_id = ' . (int) $notification_id); |
| 355 | $this->db->sql_query($sql); |
| 356 | } |
| 357 | |
| 358 | /** |
| 359 | * {@inheritdoc} |
| 360 | */ |
| 361 | public function delete_notifications($notification_type_id, $item_id, $parent_id = false, $user_id = false) |
| 362 | { |
| 363 | $sql = 'DELETE FROM ' . $this->notifications_table . ' |
| 364 | WHERE notification_type_id = ' . (int) $notification_type_id . ' |
| 365 | AND ' . (is_array($item_id) ? $this->db->sql_in_set('item_id', $item_id) : 'item_id = ' . (int) $item_id) . |
| 366 | (($parent_id !== false) ? ' AND ' . ((is_array($parent_id) ? $this->db->sql_in_set('item_parent_id', $parent_id) : 'item_parent_id = ' . (int) $parent_id)) : '') . |
| 367 | (($user_id !== false) ? ' AND ' . ((is_array($user_id) ? $this->db->sql_in_set('user_id', $user_id) : 'user_id = ' . (int) $user_id)) : ''); |
| 368 | $this->db->sql_query($sql); |
| 369 | } |
| 370 | |
| 371 | /** |
| 372 | * {@inheritdoc} |
| 373 | */ |
| 374 | public function prune_notifications($timestamp, $only_read = true) |
| 375 | { |
| 376 | $sql = 'DELETE FROM ' . $this->notifications_table . ' |
| 377 | WHERE notification_time < ' . (int) $timestamp . |
| 378 | (($only_read) ? ' AND notification_read = 1' : ''); |
| 379 | $this->db->sql_query($sql); |
| 380 | |
| 381 | $this->config->set('read_notification_last_gc', time(), false); |
| 382 | } |
| 383 | |
| 384 | /** |
| 385 | * {@inheritdoc} |
| 386 | */ |
| 387 | public function purge_notifications($notification_type_id) |
| 388 | { |
| 389 | $sql = 'DELETE FROM ' . $this->notifications_table . ' |
| 390 | WHERE notification_type_id = ' . (int) $notification_type_id; |
| 391 | $this->db->sql_query($sql); |
| 392 | |
| 393 | $sql = 'DELETE FROM ' . $this->notification_types_table . ' |
| 394 | WHERE notification_type_id = ' . (int) $notification_type_id; |
| 395 | $this->db->sql_query($sql); |
| 396 | |
| 397 | $this->cache->destroy('sql', $this->notification_types_table); |
| 398 | } |
| 399 | } |