ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilForumNotification.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
30{
32 private static array $node_data_cache = [];
34 private static array $forced_events_cache = [];
35
36 private readonly ilDBInterface $db;
37 private readonly ilObjUser $user;
38 private int $notification_id;
39 private ?int $user_id = null;
40 private int $forum_id;
41 private int $thread_id;
42 private bool $admin_force = false;
43 private bool $user_toggle = false;
44 private int $interested_events = 0;
45 private int $user_id_noti;
46
47 public function __construct(private int $ref_id)
48 {
49 global $DIC;
50
51 $this->db = $DIC->database();
52 $this->user = $DIC->user();
53 $this->forum_id = $DIC['ilObjDataCache']->lookupObjId($ref_id);
54 }
55
56 public function setNotificationId(int $a_notification_id): void
57 {
58 $this->notification_id = $a_notification_id;
59 }
60
61 public function getNotificationId(): int
62 {
64 }
65
66 public function setUserId(?int $a_user_id): void
67 {
68 $this->user_id = $a_user_id;
69 }
70
71 public function getUserId(): ?int
72 {
73 return $this->user_id;
74 }
75
76 public function setForumId(int $a_forum_id): void
77 {
78 $this->forum_id = $a_forum_id;
79 }
80
81 public function getForumId(): int
82 {
83 return $this->forum_id;
84 }
85
86 public function setThreadId(int $a_thread_id): void
87 {
88 $this->thread_id = $a_thread_id;
89 }
90
91 public function getThreadId(): int
92 {
93 return $this->thread_id;
94 }
95
96 public function setInterestedEvents(int $interested_events): void
97 {
98 $this->interested_events = $interested_events;
99 }
100
101 public function getInterestedEvents(): int
102 {
104 }
105
106 public function setAdminForce(bool $a_admin_force): void
107 {
108 $this->admin_force = $a_admin_force;
109 }
110
111 public function getAdminForce(): bool
112 {
113 return $this->admin_force;
114 }
115
116 public function setUserToggle(bool $a_user_toggle): void
117 {
118 $this->user_toggle = $a_user_toggle;
119 }
120
121 public function getUserToggle(): bool
122 {
123 return $this->user_toggle;
124 }
125
126 public function setForumRefId(int $a_ref_id): void
127 {
128 $this->ref_id = $a_ref_id;
129 }
130
131 public function getForumRefId(): int
132 {
133 return $this->ref_id;
134 }
135
136 //user_id of who sets the setting to notify members
137 public function setUserIdNoti(int $a_user_id_noti): void
138 {
139 $this->user_id_noti = $a_user_id_noti;
140 }
141
142 //user_id of who sets the setting to notify members
143 public function getUserIdNoti(): int
144 {
145 return $this->user_id_noti;
146 }
147
148 public function isAdminForceNotification(): bool
149 {
150 $res = $this->db->queryF(
151 '
152 SELECT admin_force_noti FROM frm_notification
153 WHERE user_id = %s
154 AND frm_id = %s
155 AND user_id_noti > %s ',
156 ['integer', 'integer', 'integer'],
157 [(int) $this->getUserId(), $this->getForumId(), 0]
158 );
159
160 if ($row = $this->db->fetchAssoc($res)) {
161 return (bool) $row['admin_force_noti'];
162 }
163
164 return false;
165 }
166
167 public function isUserToggleNotification(): bool
168 {
169 $res = $this->db->queryF(
170 '
171 SELECT user_toggle_noti FROM frm_notification
172 WHERE user_id = %s
173 AND frm_id = %s
174 AND user_id_noti > %s',
175 ['integer', 'integer', 'integer'],
176 [(int) $this->getUserId(), $this->getForumId(), 0]
177 );
178
179 if ($row = $this->db->fetchAssoc($res)) {
180 return (bool) $row['user_toggle_noti'];
181 }
182 return false;
183 }
184
185 public function insertAdminForce(): void
186 {
187 $next_id = $this->db->nextId('frm_notification');
188 $this->setNotificationId($next_id);
189
190 $this->db->manipulateF(
191 '
192 INSERT INTO frm_notification
193 (notification_id, user_id, frm_id, admin_force_noti, user_toggle_noti, interested_events, user_id_noti)
194 VALUES(%s, %s, %s, %s, %s, %s, %s)',
195 ['integer', 'integer', 'integer', 'integer', 'integer', 'integer', 'integer'],
196 [
197 $next_id,
198 (int) $this->getUserId(),
199 $this->getForumId(),
200 $this->getAdminForce(),
201 $this->getUserToggle(),
202 $this->getInterestedEvents(),
203 $this->user->getId()
204 ]
205 );
206 }
207
208 public function deleteAdminForce(): void
209 {
210 $this->db->manipulateF(
211 '
212 DELETE FROM frm_notification
213 WHERE user_id = %s
214 AND frm_id = %s
215 AND admin_force_noti = %s
216 AND user_id_noti > %s',
217 ['integer', 'integer', 'integer', 'integer'],
218 [(int) $this->getUserId(), $this->getForumId(), 1, 0]
219 );
220 }
221
222 public function deleteUserToggle(): void
223 {
224 $this->db->manipulateF(
225 '
226 DELETE FROM frm_notification
227 WHERE user_id = %s
228 AND frm_id = %s
229 AND admin_force_noti = %s
230 AND user_toggle_noti = %s
231 AND user_id_noti > %s',
232 ['integer', 'integer', 'integer', 'integer', 'integer'],
233 [(int) $this->getUserId(), $this->getForumId(), 1, 1, 0]
234 );
235 }
236
237 public function updateUserToggle(): void
238 {
239 $this->db->manipulateF(
240 'UPDATE frm_notification SET user_toggle_noti = %s WHERE user_id = %s AND frm_id = %s AND admin_force_noti = %s',
241 ['integer', 'integer', 'integer', 'integer'],
242 [$this->getUserToggle(), (int) $this->getUserId(), $this->getForumId(), 1]
243 );
244 }
245
246 /* If a new member enters a Course or a Group, this function checks
247 * if this CRS/GRP contains a forum and a notification setting set by admin or moderator
248 * and inserts the new member into frm_notification
249 * */
250 public static function checkForumsExistsInsert(int $ref_id, int $user_id): void
251 {
252 global $DIC;
253
254 $ilUser = $DIC->user();
255
256 $node_data = self::getCachedNodeData($ref_id);
257
258 foreach ($node_data as $data) {
259 //check frm_properties if frm_noti is enabled
260 $frm_noti = new ilForumNotification((int) $data['ref_id']);
261 if ($user_id !== 0) {
262 $frm_noti->setUserId($user_id);
263 } else {
264 $frm_noti->setUserId($ilUser->getId());
265 }
266
267 $properties = ilForumProperties::getInstance((int) $data['obj_id']);
268 if ($properties->isAdminForceNoti() || $properties->isUserToggleNoti()) {
269 if ($properties->isAdminForceNoti()) {
270 $frm_noti->setInterestedEvents($properties->getInterestedEvents());
271 }
272
273 $frm_noti->setAdminForce($properties->isAdminForceNoti());
274 $frm_noti->setUserToggle($properties->isUserToggleNoti());
275 $frm_noti->setForumId($properties->getObjId());
276 if (!$frm_noti->existsNotification()) {
277 $frm_noti->insertAdminForce();
278 }
279 }
280 }
281 }
282
283 public static function checkForumsExistsDelete(int $ref_id, int $user_id): void
284 {
285 global $DIC;
286
287 $ilUser = $DIC->user();
288
289 $node_data = self::getCachedNodeData($ref_id);
290
291 foreach ($node_data as $data) {
292 $frm_noti = new ilForumNotification((int) $data['ref_id']);
293 $objFrmMods = new ilForumModerators((int) $data['ref_id']);
294 $moderator_ids = $objFrmMods->getCurrentModerators();
295
296 if ($user_id !== 0) {
297 $frm_noti->setUserId($user_id);
298 } else {
299 $frm_noti->setUserId($ilUser->getId());
300 }
301
302 $frm_noti->setForumId((int) $data['obj_id']);
303 if (!in_array($frm_noti->getUserId(), $moderator_ids, true)) {
304 $frm_noti->deleteAdminForce();
305 }
306 }
307 }
308
309 public static function getCachedNodeData(int $ref_id): array
310 {
311 global $DIC;
312
313 if (!array_key_exists($ref_id, self::$node_data_cache)) {
314 $container_node = $DIC->repositoryTree()->getNodeData($ref_id);
315 if (!isset($container_node['child'])) {
316 return [];
317 }
318
319 $node_data = $DIC->repositoryTree()->getSubTree(
320 $container_node,
321 true,
322 ['frm']
323 );
324 $node_data = array_filter($node_data, static function (array $forum_node) use ($DIC, $ref_id): bool {
325 // filter out forum if a grp lies in the path (#0027702)
326 foreach ($DIC->repositoryTree()->getNodePath((int) $forum_node['child'], $ref_id) as $path_node) {
327 $notRootNode = (int) $path_node['child'] !== $ref_id;
328 $isGroup = $path_node['type'] === 'grp';
329 if ($notRootNode && $isGroup) {
330 return false;
331 }
332 }
333
334 return true;
335 });
336 self::$node_data_cache[$ref_id] = $node_data;
337 }
338
339 return self::$node_data_cache[$ref_id];
340 }
341
342 public static function _clearForcedForumNotifications(array $move_tree_event): void
343 {
344 global $DIC;
345 $ilDB = $DIC->database();
346
347 if ($move_tree_event['tree'] !== 'tree') {
348 return;
349 }
350
352 $source_forum = ilObjectFactory::getInstanceByRefId((int) $move_tree_event['source_id']);
353 if ($source_forum->isParentMembershipEnabledContainer()) {
354 $ilDB->manipulateF(
355 'DELETE FROM frm_notification WHERE frm_id = %s AND admin_force_noti = %s',
356 ['integer', 'integer'],
357 [$source_forum->getId(), 1]
358 );
359 }
360 }
361
362 public function update(): void
363 {
364 $this->db->manipulateF(
365 'UPDATE frm_notification SET admin_force_noti = %s, user_toggle_noti = %s, ' .
366 'interested_events = %s WHERE user_id = %s AND frm_id = %s',
367 ['integer', 'integer', 'integer', 'integer', 'integer'],
368 [
369 (int) $this->getAdminForce(),
370 (int) $this->getUserToggle(),
371 $this->getInterestedEvents(),
372 (int) $this->getUserId(),
373 $this->getForumId()
374 ]
375 );
376 }
377
378 public function deleteNotificationAllUsers(): void
379 {
380 $this->db->manipulateF(
381 'DELETE FROM frm_notification WHERE frm_id = %s AND user_id_noti > %s',
382 ['integer', 'integer'],
383 [$this->getForumId(), 0]
384 );
385 }
386
390 public function read(): array
391 {
392 $result = [];
393
394 $res = $this->db->queryF('SELECT * FROM frm_notification WHERE frm_id = %s', ['integer'], [$this->getForumId()]);
395 while ($row = $this->db->fetchAssoc($res)) {
396 $result[(int) $row['user_id']]['notification_id'] = (int) $row['notification_id'];
397 $result[(int) $row['user_id']]['user_id'] = (int) $row['user_id'];
398 $result[(int) $row['user_id']]['frm_id'] = (int) $row['frm_id'];
399 $result[(int) $row['user_id']]['thread_id'] = (int) $row['thread_id'];
400 $result[(int) $row['user_id']]['admin_force_noti'] = (int) $row['admin_force_noti'];
401 $result[(int) $row['user_id']]['user_toggle_noti'] = (int) $row['user_toggle_noti'];
402 $result[(int) $row['user_id']]['interested_events'] = (int) $row['interested_events'];
403 $result[(int) $row['user_id']]['user_id_noti'] = (int) $row['user_id_noti'];
404 }
405
406 return $result;
407 }
408
409 public static function mergeThreadNotifications($merge_source_thread_id, $merge_target_thread_id): void
410 {
411 global $DIC;
412
413 $ilDB = $DIC->database();
414
415 $res = $ilDB->queryF(
416 'SELECT notification_id, user_id FROM frm_notification WHERE frm_id = %s AND thread_id = %s ORDER BY user_id ASC',
417 ['integer', 'integer'],
418 [0, $merge_source_thread_id]
419 );
420
421 $res_2 = $ilDB->queryF(
422 'SELECT DISTINCT user_id FROM frm_notification WHERE frm_id = %s AND thread_id = %s ORDER BY user_id ASC',
423 ['integer', 'integer'],
424 [0, $merge_target_thread_id]
425 );
426
427 $users_already_notified = [];
428 while ($users_row = $ilDB->fetchAssoc($res_2)) {
429 $users_already_notified[(int) $users_row['user_id']] = (int) $users_row['user_id'];
430 }
431
432 while ($row = $ilDB->fetchAssoc($res)) {
433 if (isset($users_already_notified[(int) $row['user_id']])) {
434 $ilDB->manipulateF(
435 'DELETE FROM frm_notification WHERE notification_id = %s',
436 ['integer'],
437 [$row['notification_id']]
438 );
439 } else {
440 $ilDB->update(
441 'frm_notification',
442 ['thread_id' => ['integer', $merge_target_thread_id]],
443 ['thread_id' => ['integer', $merge_source_thread_id]]
444 );
445 }
446 }
447 }
448
449 public function existsNotification(): bool
450 {
451 $res = $this->db->queryF(
452 'SELECT user_id FROM frm_notification WHERE user_id = %s AND frm_id = %s AND admin_force_noti = %s',
453 ['integer', 'integer', 'integer'],
454 [(int) $this->getUserId(), $this->getForumId(), (int) $this->getAdminForce()]
455 );
456
457 return $this->db->numRows($res) > 0;
458 }
459
460 public function cloneFromSource(int $sourceRefId): void
461 {
462 $sourceNotificationSettings = new self($sourceRefId);
463 $records = $sourceNotificationSettings->read();
464
465 foreach ($records as $usrId => $row) {
466 $this->setUserId($usrId);
467 $this->setAdminForce((bool) $row['admin_force_noti']);
468 $this->setUserToggle((bool) $row['user_toggle_noti']);
469 $this->setUserIdNoti((int) $row['user_id_noti']);
470 $this->setInterestedEvents((int) $row['interested_events']);
471
472 $this->insertAdminForce();
473 }
474 }
475
476 public function updateInterestedEvents(): void
477 {
478 $this->db->manipulateF(
479 'UPDATE frm_notification SET interested_events = %s WHERE user_id = %s AND frm_id = %s',
480 ['integer', 'integer', 'integer'],
481 [$this->getInterestedEvents(), (int) $this->getUserId(), $this->getForumId()]
482 );
483 }
484
485 public function readInterestedEvents(): int
486 {
487 $interested_events = ilForumNotificationEvents::DEACTIVATED;
488
489 $this->db->setLimit(1);
490 $res = $this->db->queryF(
491 'SELECT interested_events FROM frm_notification WHERE user_id = %s AND frm_id = %s',
492 ['integer', 'integer'],
493 [(int) $this->getUserId(), $this->getForumId()]
494 );
495
496 while ($row = $this->db->fetchAssoc($res)) {
497 $interested_events = (int) $row['interested_events'];
498 }
499
500 return $interested_events;
501 }
502
506 public function readAllForcedEvents(): array
507 {
508 $res = $this->db->queryF(
509 'SELECT * FROM frm_notification WHERE admin_force_noti = %s AND frm_id = %s',
510 ['integer', 'integer'],
511 [1, $this->forum_id]
512 );
513
514 while ($row = $this->db->fetchAssoc($res)) {
515 $notificationConfig = new self($this->ref_id);
516 $notificationConfig->setNotificationId((int) $row['notification_id']);
517 $notificationConfig->setUserId((int) $row['user_id']);
518 $notificationConfig->setForumId((int) $row['frm_id']);
519 $notificationConfig->setAdminForce((bool) $row['admin_force_noti']);
520 $notificationConfig->setUserToggle((bool) $row['user_toggle_noti']);
521 $notificationConfig->setInterestedEvents((int) $row['interested_events']);
522
523 self::$forced_events_cache[(int) $row['user_id']] = $notificationConfig;
524 }
525
526 return self::$forced_events_cache;
527 }
528
529 public function getForcedEventsObjectByUserId(int $user_id): self
530 {
531 if (!isset(self::$forced_events_cache[$user_id])) {
532 $this->readAllForcedEvents();
533 }
534
535 if (!isset(self::$forced_events_cache[$user_id])) {
536 self::$forced_events_cache[$user_id] = $this->createMissingNotification($user_id);
537 }
538
539 return self::$forced_events_cache[$user_id];
540 }
541
542 private function createMissingNotification(int $user_id): self
543 {
544 $new_object = new self($this->ref_id);
545 $new_object->setUserId($user_id);
546 $new_object->setForumId($this->forum_id);
547 $new_object->insertAdminForce();
548
549 return $new_object;
550 }
551
555 public function updateUserNotifications(array $usr_ids, ilForumProperties $object_properties): void
556 {
557 $notification_settings_by_usr_id = $this->read();
558 foreach ($usr_ids as $usr_id) {
559 $this->setUserId($usr_id);
560 $this->setAdminForce(true);
561 $this->setUserToggle($object_properties->isUserToggleNoti());
562 $this->setInterestedEvents($object_properties->getInterestedEvents());
563
564 if (array_key_exists($usr_id, $notification_settings_by_usr_id) &&
565 $object_properties->getNotificationType() === NotificationType::ALL_USERS) {
566 $this->update();
567 } elseif (!$this->existsNotification()) {
568 $this->insertAdminForce();
569 }
570 }
571 }
572}
Class ilForumModerators.
Class ilForumNotification.
static checkForumsExistsInsert(int $ref_id, int $user_id)
static mergeThreadNotifications($merge_source_thread_id, $merge_target_thread_id)
setUserToggle(bool $a_user_toggle)
setInterestedEvents(int $interested_events)
readonly ilDBInterface $db
getForcedEventsObjectByUserId(int $user_id)
setUserIdNoti(int $a_user_id_noti)
setNotificationId(int $a_notification_id)
static getCachedNodeData(int $ref_id)
setAdminForce(bool $a_admin_force)
__construct(private int $ref_id)
updateUserNotifications(array $usr_ids, ilForumProperties $object_properties)
static checkForumsExistsDelete(int $ref_id, int $user_id)
static getInstance(int $a_obj_id=0)
User class.
static getInstanceByRefId(int $ref_id, bool $stop_on_error=true)
get an instance of an Ilias object by reference id
Interface ilDBInterface.
$ref_id
Definition: ltiauth.php:66
$res
Definition: ltiservices.php:69
global $DIC
Definition: shib_login.php:26