ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
class.ilForumNotification.php
Go to the documentation of this file.
1 <?php
2 
19 declare(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, user_id_noti)
194  VALUES(%s, %s, %s, %s, %s, %s)',
195  ['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->user->getId()
203  ]
204  );
205  }
206 
207  public function deleteAdminForce(): void
208  {
209  $this->db->manipulateF(
210  '
211  DELETE FROM frm_notification
212  WHERE user_id = %s
213  AND frm_id = %s
214  AND admin_force_noti = %s
215  AND user_id_noti > %s',
216  ['integer', 'integer', 'integer', 'integer'],
217  [(int) $this->getUserId(), $this->getForumId(), 1, 0]
218  );
219  }
220 
221  public function deleteUserToggle(): void
222  {
223  $this->db->manipulateF(
224  '
225  DELETE FROM frm_notification
226  WHERE user_id = %s
227  AND frm_id = %s
228  AND admin_force_noti = %s
229  AND user_toggle_noti = %s
230  AND user_id_noti > %s',
231  ['integer', 'integer', 'integer', 'integer', 'integer'],
232  [(int) $this->getUserId(), $this->getForumId(), 1, 1, 0]
233  );
234  }
235 
236  public function updateUserToggle(): void
237  {
238  $this->db->manipulateF(
239  'UPDATE frm_notification SET user_toggle_noti = %s WHERE user_id = %s AND frm_id = %s AND admin_force_noti = %s',
240  ['integer', 'integer', 'integer', 'integer'],
241  [$this->getUserToggle(), (int) $this->getUserId(), $this->getForumId(), 1]
242  );
243  }
244 
245  /* If a new member enters a Course or a Group, this function checks
246  * if this CRS/GRP contains a forum and a notification setting set by admin or moderator
247  * and inserts the new member into frm_notification
248  * */
249  public static function checkForumsExistsInsert(int $ref_id, int $user_id): void
250  {
251  global $DIC;
252 
253  $ilUser = $DIC->user();
254 
255  $node_data = self::getCachedNodeData($ref_id);
256 
257  foreach ($node_data as $data) {
258  //check frm_properties if frm_noti is enabled
259  $frm_noti = new ilForumNotification((int) $data['ref_id']);
260  if ($user_id !== 0) {
261  $frm_noti->setUserId($user_id);
262  } else {
263  $frm_noti->setUserId($ilUser->getId());
264  }
265 
266  $admin_force = ilForumProperties::_isAdminForceNoti((int) $data['obj_id']);
267  $frm_noti->setAdminForce($admin_force);
268 
269  $user_toggle = ilForumProperties::_isUserToggleNoti((int) $data['obj_id']);
270  if ($user_toggle) {
271  $frm_noti->setAdminForce(true);
272  }
273 
274  if ($admin_force || $user_toggle) {
275  $frm_noti->setUserToggle($user_toggle);
276  $frm_noti->setForumId((int) $data['obj_id']);
277  if (!$frm_noti->existsNotification()) {
278  $frm_noti->insertAdminForce();
279  }
280  }
281  }
282  }
283 
284  public static function checkForumsExistsDelete(int $ref_id, int $user_id): void
285  {
286  global $DIC;
287 
288  $ilUser = $DIC->user();
289 
290  $node_data = self::getCachedNodeData($ref_id);
291 
292  foreach ($node_data as $data) {
293  $frm_noti = new ilForumNotification((int) $data['ref_id']);
294  $objFrmMods = new ilForumModerators((int) $data['ref_id']);
295  $moderator_ids = $objFrmMods->getCurrentModerators();
296 
297  if ($user_id !== 0) {
298  $frm_noti->setUserId($user_id);
299  } else {
300  $frm_noti->setUserId($ilUser->getId());
301  }
302 
303  $frm_noti->setForumId((int) $data['obj_id']);
304  if (!in_array($frm_noti->getUserId(), $moderator_ids, true)) {
305  $frm_noti->deleteAdminForce();
306  }
307  }
308  }
309 
310  public static function getCachedNodeData(int $ref_id): array
311  {
312  global $DIC;
313 
314  if (!array_key_exists($ref_id, self::$node_data_cache)) {
315  $container_node = $DIC->repositoryTree()->getNodeData($ref_id);
316  if (!isset($container_node['child'])) {
317  return [];
318  }
319 
320  $node_data = $DIC->repositoryTree()->getSubTree(
321  $container_node,
322  true,
323  ['frm']
324  );
325  $node_data = array_filter($node_data, static function (array $forum_node) use ($DIC, $ref_id): bool {
326  // filter out forum if a grp lies in the path (#0027702)
327  foreach ($DIC->repositoryTree()->getNodePath((int) $forum_node['child'], $ref_id) as $path_node) {
328  $notRootNode = (int) $path_node['child'] !== $ref_id;
329  $isGroup = $path_node['type'] === 'grp';
330  if ($notRootNode && $isGroup) {
331  return false;
332  }
333  }
334 
335  return true;
336  });
337  self::$node_data_cache[$ref_id] = $node_data;
338  }
339 
340  return self::$node_data_cache[$ref_id];
341  }
342 
343  public static function _clearForcedForumNotifications(array $move_tree_event): void
344  {
345  global $DIC;
346  $ilDB = $DIC->database();
347 
348  if ($move_tree_event['tree'] !== 'tree') {
349  return;
350  }
351 
353  $source_forum = ilObjectFactory::getInstanceByRefId((int) $move_tree_event['source_id']);
354  if ($source_forum->isParentMembershipEnabledContainer()) {
355  $ilDB->manipulateF(
356  'DELETE FROM frm_notification WHERE frm_id = %s AND admin_force_noti = %s',
357  ['integer', 'integer'],
358  [$source_forum->getId(), 1]
359  );
360  }
361  }
362 
363  public function update(): void
364  {
365  $this->db->manipulateF(
366  'UPDATE frm_notification SET admin_force_noti = %s, user_toggle_noti = %s, ' .
367  'interested_events = %s WHERE user_id = %s AND frm_id = %s',
368  ['integer', 'integer', 'integer', 'integer', 'integer'],
369  [
370  (int) $this->getAdminForce(),
371  (int) $this->getUserToggle(),
372  $this->getInterestedEvents(),
373  (int) $this->getUserId(),
374  $this->getForumId()
375  ]
376  );
377  }
378 
379  public function deleteNotificationAllUsers(): void
380  {
381  $this->db->manipulateF(
382  'DELETE FROM frm_notification WHERE frm_id = %s AND user_id_noti > %s',
383  ['integer', 'integer'],
384  [$this->getForumId(), 0]
385  );
386  }
387 
391  public function read(): array
392  {
393  $result = [];
394 
395  $res = $this->db->queryF('SELECT * FROM frm_notification WHERE frm_id = %s', ['integer'], [$this->getForumId()]);
396  while ($row = $this->db->fetchAssoc($res)) {
397  $result[(int) $row['user_id']]['notification_id'] = (int) $row['notification_id'];
398  $result[(int) $row['user_id']]['user_id'] = (int) $row['user_id'];
399  $result[(int) $row['user_id']]['frm_id'] = (int) $row['frm_id'];
400  $result[(int) $row['user_id']]['thread_id'] = (int) $row['thread_id'];
401  $result[(int) $row['user_id']]['admin_force_noti'] = (int) $row['admin_force_noti'];
402  $result[(int) $row['user_id']]['user_toggle_noti'] = (int) $row['user_toggle_noti'];
403  $result[(int) $row['user_id']]['interested_events'] = (int) $row['interested_events'];
404  $result[(int) $row['user_id']]['user_id_noti'] = (int) $row['user_id_noti'];
405  }
406 
407  return $result;
408  }
409 
410  public static function mergeThreadNotifications($merge_source_thread_id, $merge_target_thread_id): void
411  {
412  global $DIC;
413 
414  $ilDB = $DIC->database();
415 
416  $res = $ilDB->queryF(
417  'SELECT notification_id, user_id FROM frm_notification WHERE frm_id = %s AND thread_id = %s ORDER BY user_id ASC',
418  ['integer', 'integer'],
419  [0, $merge_source_thread_id]
420  );
421 
422  $res_2 = $ilDB->queryF(
423  'SELECT DISTINCT user_id FROM frm_notification WHERE frm_id = %s AND thread_id = %s ORDER BY user_id ASC',
424  ['integer', 'integer'],
425  [0, $merge_target_thread_id]
426  );
427 
428  $users_already_notified = [];
429  while ($users_row = $ilDB->fetchAssoc($res_2)) {
430  $users_already_notified[(int) $users_row['user_id']] = (int) $users_row['user_id'];
431  }
432 
433  while ($row = $ilDB->fetchAssoc($res)) {
434  if (isset($users_already_notified[(int) $row['user_id']])) {
435  $ilDB->manipulateF(
436  'DELETE FROM frm_notification WHERE notification_id = %s',
437  ['integer'],
438  [$row['notification_id']]
439  );
440  } else {
441  $ilDB->update(
442  'frm_notification',
443  ['thread_id' => ['integer', $merge_target_thread_id]],
444  ['thread_id' => ['integer', $merge_source_thread_id]]
445  );
446  }
447  }
448  }
449 
450  public function existsNotification(): bool
451  {
452  $res = $this->db->queryF(
453  'SELECT user_id FROM frm_notification WHERE user_id = %s AND frm_id = %s AND admin_force_noti = %s',
454  ['integer', 'integer', 'integer'],
455  [(int) $this->getUserId(), $this->getForumId(), (int) $this->getAdminForce()]
456  );
457 
458  return $this->db->numRows($res) > 0;
459  }
460 
461  public function cloneFromSource(int $sourceRefId): void
462  {
463  $sourceNotificationSettings = new self($sourceRefId);
464  $records = $sourceNotificationSettings->read();
465 
466  foreach ($records as $usrId => $row) {
467  $this->setUserId($usrId);
468  $this->setAdminForce((bool) $row['admin_force_noti']);
469  $this->setUserToggle((bool) $row['user_toggle_noti']);
470  $this->setUserIdNoti((int) $row['user_id_noti']);
471  $this->setInterestedEvents((int) $row['interested_events']);
472 
473  $this->insertAdminForce();
474  }
475  }
476 
477  public function updateInterestedEvents(): void
478  {
479  $this->db->manipulateF(
480  'UPDATE frm_notification SET interested_events = %s WHERE user_id = %s AND frm_id = %s',
481  ['integer', 'integer', 'integer'],
482  [$this->getInterestedEvents(), (int) $this->getUserId(), $this->getForumId()]
483  );
484  }
485 
486  public function readInterestedEvents(): int
487  {
488  $interested_events = ilForumNotificationEvents::DEACTIVATED;
489 
490  $this->db->setLimit(1);
491  $res = $this->db->queryF(
492  'SELECT interested_events FROM frm_notification WHERE user_id = %s AND frm_id = %s',
493  ['integer', 'integer'],
494  [(int) $this->getUserId(), $this->getForumId()]
495  );
496 
497  while ($row = $this->db->fetchAssoc($res)) {
498  $interested_events = (int) $row['interested_events'];
499  }
500 
501  return $interested_events;
502  }
503 
507  public function readAllForcedEvents(): array
508  {
509  $res = $this->db->queryF(
510  'SELECT * FROM frm_notification WHERE admin_force_noti = %s AND frm_id = %s',
511  ['integer', 'integer'],
512  [1, $this->forum_id]
513  );
514 
515  while ($row = $this->db->fetchAssoc($res)) {
516  $notificationConfig = new self($this->ref_id);
517  $notificationConfig->setNotificationId((int) $row['notification_id']);
518  $notificationConfig->setUserId((int) $row['user_id']);
519  $notificationConfig->setForumId((int) $row['frm_id']);
520  $notificationConfig->setAdminForce((bool) $row['admin_force_noti']);
521  $notificationConfig->setUserToggle((bool) $row['user_toggle_noti']);
522  $notificationConfig->setInterestedEvents((int) $row['interested_events']);
523 
524  self::$forced_events_cache[(int) $row['user_id']] = $notificationConfig;
525  }
526 
527  return self::$forced_events_cache;
528  }
529 
530  public function getForcedEventsObjectByUserId(int $user_id): self
531  {
532  if (!isset(self::$forced_events_cache[$user_id])) {
533  $this->readAllForcedEvents();
534  }
535 
536  if (!isset(self::$forced_events_cache[$user_id])) {
537  self::$forced_events_cache[$user_id] = $this->createMissingNotification($user_id);
538  }
539 
540  return self::$forced_events_cache[$user_id];
541  }
542 
543  private function createMissingNotification(int $user_id): self
544  {
545  $new_object = new self($this->ref_id);
546  $new_object->setUserId($user_id);
547  $new_object->setForumId($this->forum_id);
548  $new_object->insertAdminForce();
549 
550  return $new_object;
551  }
552 
556  public function updateUserNotifications(array $usr_ids, ilForumProperties $object_properties): void
557  {
558  $notification_settings_by_usr_id = $this->read();
559  foreach ($usr_ids as $usr_id) {
560  $this->setUserId($usr_id);
561  $this->setAdminForce(true);
562  $this->setUserToggle($object_properties->isUserToggleNoti());
563  $this->setInterestedEvents($object_properties->getInterestedEvents());
564 
565  if (array_key_exists($usr_id, $notification_settings_by_usr_id) &&
566  $object_properties->getNotificationType() === NotificationType::ALL_USERS) {
567  $this->update();
568  } elseif (!$this->existsNotification()) {
569  $this->insertAdminForce();
570  }
571  }
572  }
573 }
$res
Definition: ltiservices.php:66
setUserToggle(bool $a_user_toggle)
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
static _isAdminForceNoti(int $a_obj_id)
setNotificationId(int $a_notification_id)
$ref_id
Definition: ltiauth.php:65
setAdminForce(bool $a_admin_force)
__construct(private int $ref_id)
static getInstanceByRefId(int $ref_id, bool $stop_on_error=true)
get an instance of an Ilias object by reference id
global $DIC
Definition: shib_login.php:26
static getCachedNodeData(int $ref_id)
getForcedEventsObjectByUserId(int $user_id)
readonly ilDBInterface $db
setInterestedEvents(int $interested_events)
static _isUserToggleNoti(int $a_obj_id)
static mergeThreadNotifications($merge_source_thread_id, $merge_target_thread_id)
static checkForumsExistsDelete(int $ref_id, int $user_id)
static checkForumsExistsInsert(int $ref_id, int $user_id)
updateUserNotifications(array $usr_ids, ilForumProperties $object_properties)
setUserIdNoti(int $a_user_id_noti)