ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.ilTimingsCronReminder.php
Go to the documentation of this file.
1 <?php
2 
3 declare(strict_types=0);
4 
6 
24 {
25  private static array $objects_information;
26 
28  private array $users;
29  private int $now;
30 
31  protected ilLogger $log;
32  protected ilLanguage $lng;
34  protected ilDBInterface $db;
36 
40  public function __construct()
41  {
42  global $DIC;
43 
44  $this->log = $DIC->logger()->crs();
45  $this->lng = $DIC->language();
46  $this->lng->loadLanguageModule('crs');
47  $this->db = $DIC->database();
48  $this->obj_data_cache = $DIC['ilObjDataCache'];
49 
50  self::$objects_information = [];
51  $this->users_with_exceeded_timings = [];
52  $this->users = [];
53  $this->now = time();
54  }
55 
56  public function getId(): string
57  {
58  return 'crs_timings_reminder';
59  }
60 
61  public function getTitle(): string
62  {
63  return $this->lng->txt('timings_reminder_notifications');
64  }
65 
66  public function getDescription(): string
67  {
68  return $this->lng->txt('timings_reminder_notifications_info');
69  }
70 
72  {
73  return CronJobScheduleType::SCHEDULE_TYPE_DAILY;
74  }
75 
76  public function getDefaultScheduleValue(): ?int
77  {
78  return null;
79  }
80 
81  public function hasAutoActivation(): bool
82  {
83  return false;
84  }
85 
86  public function hasFlexibleSchedule(): bool
87  {
88  return false;
89  }
90 
91  public function hasCustomSettings(): bool
92  {
93  return false;
94  }
95 
96  public function run(): ilCronJobResult
97  {
98  $this->log->debug('Start.');
99 
100  $result = new ilCronJobResult();
101 
102  $this->gatherUsers();
106 
107  $result->setStatus(ilCronJobResult::STATUS_OK);
108 
109  $this->log->debug('End');
110 
111  return $result;
112  }
113 
117  protected function gatherUsers(): void
118  {
119  $now = time();
120  $query = $this->db->queryF(
121  'SELECT usr_id FROM usr_data WHERE
122  (active = 1 AND time_limit_unlimited = 1) OR
123  (active = 1 AND time_limit_unlimited = 0 AND time_limit_from < %s AND time_limit_until > %s)',
124  ['integer', 'integer'],
125  [$now, $now]
126  );
127  while ($row = $this->db->fetchAssoc($query)) {
128  $usr_id = (int) $row['usr_id'];
129  $this->users[$usr_id] = $usr_id;
130  }
131  $this->log->debug('Found ' . count($this->users) . ' users.');
132  }
133 
134  protected function gatherUsersWithExceededTimings(): void
135  {
136  $this->users_with_exceeded_timings = ilTimingsUser::lookupTimingsExceededByUser($this->users);
137  $this->log->debug('Found ' . count($this->users_with_exceeded_timings) . ' users with exceeded timings.');
138  }
139 
140  protected function getNewExceededObjectForUser(): void
141  {
142  $users_with_exceeded_objects = [];
143 
144  if (is_array($this->users_with_exceeded_timings) && $this->users_with_exceeded_timings !== []) {
145  foreach ($this->users_with_exceeded_timings as $key => $user_id) {
146  $objects = $this->getExceededObjectsForUser($user_id);
147  if (is_array($objects) && $objects !== []) {
148  $obj_data = [];
149  $already_notified = $this->getAlreadySentNotifications($user_id);
150  $objects = array_diff_key($objects, $already_notified);
151  foreach (array_keys($objects) as $ref_id) {
152  $detail_data = $this->getInformationForRefId($ref_id);
153  $obj_data[$ref_id] = $detail_data;
154  }
155  if ($obj_data !== []) {
156  $users_with_exceeded_objects[$user_id] = $obj_data;
157  }
158  }
159  }
160  $this->log->debug('Found ' . count($users_with_exceeded_objects) . ' users with new exceeded timings.');
161 
162  $this->buildExceededMails($users_with_exceeded_objects);
163  }
164  }
165 
166  protected function getFreshlyStartedObjectsForUser(): void
167  {
168  $users_with_new_started_object = [];
169 
170  if (is_array($this->users) && $this->users !== []) {
171  foreach ($this->users as $key => $user_id) {
172  $objects = $this->getObjectsWithTimingsForUser($user_id);
173  if (is_array($objects) && $objects !== []) {
174  $obj_data = [];
175  $already_notified = $this->getAlreadySentNotifications($user_id, false);
176  $this->log->debug('User_id ' . $user_id . ' was already notified for ' . count($already_notified) . ' elements ');
177  $objects = array_diff_key($objects, $already_notified);
178  foreach ($objects as $ref_id => $v) {
179  $obj_data[$ref_id] = $this->getInformationForRefId($ref_id);
180 
181  if (is_array($v)) {
182  if ((isset($v['end']) && isset($v['start'])) && $v['end'] > $this->now) {
183  if ($v['start'] < $this->now) {
184  $users_with_new_started_object[$user_id][$ref_id] = $obj_data[$ref_id];
185  }
186  } else {
187  $this->log->debug('End is already older than today no notification send for user_id ' . $user_id . ' on ref_id ' . $ref_id);
188  }
189  }
190  }
191  }
192  }
193  $this->log->debug('Found ' . count($users_with_new_started_object) . ' users with freshly started timings.');
194 
195  $this->buildFreshlyStartedMails($users_with_new_started_object);
196  }
197  }
198 
199  protected function buildExceededMails(array $users_with_exceeded_objects): void
200  {
201  $this->log->debug('Start.');
202  if (is_array($users_with_exceeded_objects)) {
203  $this->log->debug('...found ' . count($users_with_exceeded_objects));
204  foreach ($users_with_exceeded_objects as $user_id => $exceeded_objects) {
205  $tpl = $this->buildTopMailBody($user_id, 'timings_cron_reminder_exceeded_start');
206  $has_exceeded = $this->fillObjectListForMailBody($exceeded_objects, $tpl);
207 
208  if ($has_exceeded) {
209  $this->sendExceededMail($user_id, $exceeded_objects, $tpl->get());
210  $this->log->debug('start sending exceeded mail to user: ' . $user_id);
211  }
212  }
213  } else {
214  $this->log->warning('no array given.');
215  }
216 
217  $this->log->debug('end.');
218  }
219 
220  protected function buildFreshlyStartedMails(array $users_with_freshly_started_objects): void
221  {
222  $this->log->debug('start.');
223  if (is_array($users_with_freshly_started_objects)) {
224  $this->log->debug('...found ' . count($users_with_freshly_started_objects));
225  foreach ($users_with_freshly_started_objects as $user_id => $freshly_started_objects) {
226  $tpl = $this->buildTopMailBody($user_id, 'timings_cron_reminder_freshly_start');
227  $has_freshly_started = $this->fillObjectListForMailBody($freshly_started_objects, $tpl);
228 
229  if ($has_freshly_started) {
230  $this->sendFreshlyStartedMail($user_id, $freshly_started_objects, $tpl->get());
231  }
232  }
233  } else {
234  $this->log->debug('no array given.');
235  }
236 
237  $this->log->debug('end.');
238  }
239 
240  protected function buildTopMailBody(int $user_id, string $language_variable): ilTemplate
241  {
242  $this->log->debug('start...');
243  $tpl = new ilTemplate('tpl.crs_timings_cron_reminder_mail.html', true, true, 'Modules/Course');
244 
245  $this->getUserLanguage($user_id);
246  $this->buildMailSalutation($user_id, $tpl);
247  $tpl->setVariable('START_BODY', $this->user_lang->txt($language_variable));
248  $this->log->debug('for user: ' . $user_id . ' end.');
249  return $tpl;
250  }
251 
252  protected function fillObjectListForMailBody(array $objects, ilTemplate $tpl): bool
253  {
254  $has_elements = false;
255  foreach ($objects as $object_id => $object_details) {
256  if ($object_details['type'] != 'fold') {
257  $tpl->setCurrentBlock('items');
258  $tpl->setVariable('HREF', $object_details['url']);
259  $tpl->setVariable('ITEM_TITLE', $object_details['title']);
260  $tpl->parseCurrentBlock();
261  $has_elements = true;
262  }
263  }
264  $tpl->setVariable('INSTALLATION_SIGNATURE', \ilMail::_getInstallationSignature());
265  $this->log->debug('found elements: ' . $has_elements);
266  return $has_elements;
267  }
268 
269  protected function getUserLanguage(int $user_id): void
270  {
271  $this->log->debug('start...');
272  $this->user_lang = ilLanguageFactory::_getLanguageOfUser($user_id);
273  $this->user_lang->loadLanguageModule('crs');
274  $this->user_lang->loadLanguageModule('mail');
275  $this->log->debug('user language for user ' . $user_id . ' is ' . $this->user_lang->getLangKey() . ' end.');
276  }
277 
278  protected function buildMailSalutation(int $user_id, ilTemplate $tpl): void
279  {
280  $name = ilObjUser::_lookupName($user_id);
281  if (is_array($name)) {
282  $salutation = $this->user_lang->txt('mail_salutation_n') . ' ';
283  if (($name['gender'] ?? "") != '') {
284  $salutation .= $this->user_lang->txt('salutation_' . $name['gender']) . ' ';
285  }
286  if ($name['title'] != '') {
287  $salutation .= $name['title'] . ' ';
288  }
289  $tpl->setVariable('SALUTATION', $salutation);
290  $tpl->setVariable('FIRSTNAME', $name['firstname']);
291  $tpl->setVariable('LASTNAME', $name['lastname']);
292  $this->log->debug('Salutation: ' . $salutation . ' Firstname: ' . $name['firstname'] . ' Lastname: ' . $name['lastname']);
293  } else {
294  $this->log->debug('did not get an array from _lookupName.');
295  }
296  }
297 
298  protected function sendExceededMail(int $user_id, array $ref_ids, string $mail_body): void
299  {
300  $login = \ilObjUser::_lookupLogin($user_id);
301  if ($login != '') {
302  $mail = new ilMail(ANONYMOUS_USER_ID);
303  if ($this->hasUserActivatedNotification($user_id)) {
304  $mail->enqueue(
305  $login,
306  '',
307  '',
308  $this->user_lang->txt('timings_cron_reminder_exceeded_subject'),
309  $mail_body,
310  [],
311  true
312  );
313  $this->log->debug('...mail send for user ' . $user_id . ' to mail ' . $login . ' has exceeded timings for ' . $mail_body);
314  $this->markExceededInDatabase($user_id, $ref_ids);
315  } else {
316  $this->log->debug('... no mail was sent because user ' . $user_id . ' has deactivated their notifications and has no coaches assigned.');
317  }
318  } else {
319  $this->log->debug('Not send. User ' . $user_id . ' has no email.');
320  }
321  }
322 
323  protected function sendFreshlyStartedMail(int $user_id, array $ref_ids, string $mail_body): void
324  {
325  $login = \ilObjUser::_lookupLogin($user_id);
326 
327  if ($login != '' && $this->hasUserActivatedNotification($user_id)) {
328  $mail = new ilMail(ANONYMOUS_USER_ID);
329  $mail->enqueue(
330  $login,
331  '',
332  '',
333  $this->user_lang->txt('timings_cron_reminder_started_subject'),
334  $mail_body,
335  [],
336  true
337  );
338  $this->log->debug('...mail send for user ' . $user_id . ' to mail ' . $login . ' has freshly started timings for ' . $mail_body);
339  $this->markFreshlyStartedInDatabase($user_id, $ref_ids);
340  } else {
341  $this->log->debug('Not send. User ' . $user_id . ' has no email.');
342  }
343  }
344 
345  protected function markExceededInDatabase(int $user_id, array $ref_ids): void
346  {
347  foreach (array_keys($ref_ids) as $ref_id) {
348  $this->db->manipulateF(
349  'INSERT INTO ' . ilCourseConstants::CRON_TIMINGS_EXCEEDED_TABLE . ' (user_id, ref_id, sent) VALUES ' .
350  ' (%s,%s,%s)',
351  ['integer', 'integer', 'integer'],
352  [$user_id, $ref_id, $this->now]
353  );
354 
355  $this->log->debug('ilTimingsCronReminder->markExceededInDatabase: Marked exceeded in Database. User ' . $user_id . ' ref_id ' . $ref_id);
356  }
357  }
358 
359  protected function markFreshlyStartedInDatabase(int $user_id, array $ref_ids): void
360  {
361  foreach (array_keys($ref_ids) as $ref_id) {
362  $this->db->manipulateF(
363  'INSERT INTO ' . ilCourseConstants::CRON_TIMINGS_STARTED_TABLE . ' (user_id, ref_id, sent) VALUES ' .
364  ' (%s,%s,%s)',
365  ['integer', 'integer', 'integer'],
366  [$user_id, $ref_id, $this->now]
367  );
368 
369  $this->log->debug('ilTimingsCronReminder->markFreshlyStartedInDatabase: Marked freshly started in Database. User ' . $user_id . ' ref_id ' . $ref_id);
370  }
371  }
372 
373  protected function getAlreadySentNotifications(int $user_id, bool $for_exceeded = true): array
374  {
375  $ref_ids = [];
377 
378  if (!$for_exceeded) {
380  }
381 
382  $result = $this->db->queryF(
383  'SELECT * FROM ' . $table . ' WHERE ' .
384  'user_id = %s',
385  ['integer'],
386  [$user_id]
387  );
388 
389  while ($record = $this->db->fetchAssoc($result)) {
390  $ref_ids[$record['ref_id']] = $record['ref_id'];
391  }
392  return $ref_ids;
393  }
394 
395  protected function getInformationForRefId(int $ref_id): array
396  {
397  if (!array_key_exists($ref_id, self::$objects_information)) {
398  $obj_id = $this->obj_data_cache->lookupObjId($ref_id);
399  $type = $this->obj_data_cache->lookupType($obj_id);
400  $value = [
401  'title' => $this->obj_data_cache->lookupTitle($obj_id),
402  'type' => $type,
403  'url' => ilLink::_getLink($ref_id, $type),
404  'obj_id' => $obj_id
405  ];
406  self::$objects_information[$ref_id] = $value;
407 
408  $this->log->debug('ilTimingsCronReminder->getInformationForRefId: ...cached object information for => ' . $value['type'] . ' => ' . $value['title']);
409  }
410  return self::$objects_information[$ref_id];
411  }
412 
413  protected function getExceededObjectsForUser(int $user_id): array
414  {
415  $tmp = [];
416  return ilTimingsUser::lookupTimings([$user_id], $tmp, true);
417  }
418 
419  protected function getObjectsWithTimingsForUser(int $user_id): array
420  {
421  $meta = [];
422  $timings_obj_list = ilTimingsUser::lookupTimings([$user_id], $meta, false);
423  return $meta[$user_id] ?? [];
424  }
425 
426  protected function hasUserActivatedNotification(int $user_id): bool
427  {
428  return true;
429  }
430 }
parseCurrentBlock(string $part=ilGlobalTemplateInterface::DEFAULT_BLOCK)
const ANONYMOUS_USER_ID
Definition: constants.php:27
buildTopMailBody(int $user_id, string $language_variable)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
markExceededInDatabase(int $user_id, array $ref_ids)
gatherUsers()
Read all active users.
static lookupTimings(array $a_user_ids, array &$a_meta=null, bool $a_only_exceeded=true)
Lookup references, users with exceeded timings.
static _lookupName(int $a_user_id)
lookup user name
fillObjectListForMailBody(array $objects, ilTemplate $tpl)
buildMailSalutation(int $user_id, ilTemplate $tpl)
global $DIC
Definition: feed.php:28
buildExceededMails(array $users_with_exceeded_objects)
$ref_id
Definition: ltiauth.php:67
setVariable($variable, $value='')
Sets a variable value.
Definition: IT.php:546
static _getLanguageOfUser(int $a_usr_id)
Get language object of user.
string $key
Consumer key/client ID value.
Definition: System.php:193
sendExceededMail(int $user_id, array $ref_ids, string $mail_body)
buildFreshlyStartedMails(array $users_with_freshly_started_objects)
setCurrentBlock(string $part=ilGlobalTemplateInterface::DEFAULT_BLOCK)
static lookupTimingsExceededByUser(array $a_user_ids)
Check if users currently exceeded ANY object.
markFreshlyStartedInDatabase(int $user_id, array $ref_ids)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
sendFreshlyStartedMail(int $user_id, array $ref_ids, string $mail_body)
getAlreadySentNotifications(int $user_id, bool $for_exceeded=true)
static _getInstallationSignature()
static _lookupLogin(int $a_user_id)