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