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