ILIAS  release_8 Revision v8.24
class.ilTimingsCronReminder.php
Go to the documentation of this file.
1<?php
2
3declare(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 {
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}
const SCHEDULE_TYPE_DAILY
@depracated This will be replaced with an ENUM in ILIAS 9
static _getLanguageOfUser(int $a_usr_id)
Get language object of user.
language handling
Component logger with individual log levels by component id.
static _getInstallationSignature()
static _lookupName(int $a_user_id)
lookup user name
static _lookupLogin(int $a_user_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
special template class to simplify handling of ITX/PEAR
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
buildTopMailBody(int $user_id, string $language_variable)
sendExceededMail(int $user_id, array $ref_ids, string $mail_body)
buildFreshlyStartedMails(array $users_with_freshly_started_objects)
buildExceededMails(array $users_with_exceeded_objects)
sendFreshlyStartedMail(int $user_id, array $ref_ids, string $mail_body)
buildMailSalutation(int $user_id, ilTemplate $tpl)
markFreshlyStartedInDatabase(int $user_id, array $ref_ids)
getAlreadySentNotifications(int $user_id, bool $for_exceeded=true)
gatherUsers()
Read all active users.
markExceededInDatabase(int $user_id, array $ref_ids)
hasAutoActivation()
Is to be activated on "installation", does only work for ILIAS core cron jobs.
fillObjectListForMailBody(array $objects, ilTemplate $tpl)
static lookupTimingsExceededByUser(array $a_user_ids)
Check if users currently exceeded ANY object.
static lookupTimings(array $a_user_ids, array &$a_meta=null, bool $a_only_exceeded=true)
Lookup references, users with exceeded timings.
const ANONYMOUS_USER_ID
Definition: constants.php:27
global $DIC
Definition: feed.php:28
Interface ilDBInterface.
if($DIC->http() ->request() ->getMethod()=="GET" &&isset($DIC->http() ->request() ->getQueryParams()['tex'])) $tpl
Definition: latex.php:41
$ref_id
Definition: ltiauth.php:67
if($format !==null) $name
Definition: metadata.php:247
string $key
Consumer key/client ID value.
Definition: System.php:193
$query
$type