ILIAS  release_8 Revision v8.24
class.ilCronDeleteInactiveUserAccounts.php
Go to the documentation of this file.
1<?php
2
26{
27 private const DEFAULT_INACTIVITY_PERIOD = 365;
28 private const DEFAULT_REMINDER_PERIOD = 0;
29
30 private int $period;
31 private int $reminderTimer;
33 private array $include_roles;
38 private \ILIAS\HTTP\GlobalHttpState $http;
39 private \ILIAS\Refinery\Factory $refinery;
41 private \ilGlobalTemplateInterface $main_tpl;
42
43 public function __construct()
44 {
45 global $DIC;
46 $this->main_tpl = $DIC->ui()->mainTemplate();
47
48 if ($DIC) {
49 if (isset($DIC['http'])) {
50 $this->http = $DIC->http();
51 }
52
53 if (isset($DIC['lng'])) {
54 $this->lng = $DIC->language();
55 }
56
57 if (isset($DIC['refinery'])) {
58 $this->refinery = $DIC->refinery();
59 }
60
61 if (isset($DIC['ilObjDataCache'])) {
62 $this->objectDataCache = $DIC['ilObjDataCache'];
63 }
64
65 if (isset($DIC['rbacreview'])) {
66 $this->rbacReview = $DIC->rbac()->review();
67 }
68
69 if (isset($DIC['cron.repository'])) {
70 $this->cronRepository = $DIC->cron()->repository();
71 }
72
73 if (isset($DIC['ilSetting'])) {
74 $this->settings = $DIC->settings();
75
76 $include_roles = $DIC['ilSetting']->get(
77 'cron_inactive_user_delete_include_roles',
78 null
79 );
80 if ($include_roles === null) {
81 $this->include_roles = [];
82 } else {
83 $this->include_roles = array_filter(array_map('intval', explode(',', $include_roles)));
84 }
85
86 $this->period = (int) $this->settings->get(
87 'cron_inactive_user_delete_period',
89 );
90 $this->reminderTimer = (int) $this->settings->get(
91 'cron_inactive_user_reminder_period',
93 );
94 }
95 }
96 }
97
101 protected function isDecimal($number): bool
102 {
103 $number = (string) $number;
104
105 return strpos($number, ',') || strpos($number, '.');
106 }
107
108 protected function getTimeDifferenceBySchedule(int $schedule_time, int $multiplier): int
109 {
110 $time_difference = 0;
111
112 switch ($schedule_time) {
114 $time_difference = 86400;
115 break;
117 $time_difference = 60 * $multiplier;
118 break;
120 $time_difference = 3600 * $multiplier;
121 break;
123 $time_difference = 86400 * $multiplier;
124 break;
126 $time_difference = 604800;
127 break;
129 $time_difference = 2629743;
130 break;
132 $time_difference = 7889229;
133 break;
135 $time_difference = 31556926;
136 break;
137 }
138
139 return $time_difference;
140 }
141
142 public function getId(): string
143 {
144 return "user_inactive";
145 }
146
147 public function getTitle(): string
148 {
149 return $this->lng->txt("delete_inactive_user_accounts");
150 }
151
152 public function getDescription(): string
153 {
154 return $this->lng->txt("delete_inactive_user_accounts_desc");
155 }
156
157 public function getDefaultScheduleType(): int
158 {
160 }
161
162 public function getDefaultScheduleValue(): ?int
163 {
164 return null;
165 }
166
167 public function hasAutoActivation(): bool
168 {
169 return false;
170 }
171
172 public function hasFlexibleSchedule(): bool
173 {
174 return true;
175 }
176
177 public function hasCustomSettings(): bool
178 {
179 return true;
180 }
181
182 public function run(): ilCronJobResult
183 {
184 global $DIC;
185
186 $rbacreview = $DIC->rbac()->review();
187 $ilLog = $DIC['ilLog'];
188
190 $reminder_time = $this->reminderTimer;
191 $checkMail = $this->period - $reminder_time;
192 $usr_ids = ilObjUser::getUserIdsByInactivityPeriod($checkMail);
193 $counter = 0;
194 $userDeleted = 0;
195 $userMailsDelivered = 0;
196 foreach ($usr_ids as $usr_id) {
197 if ($usr_id === ANONYMOUS_USER_ID || $usr_id === SYSTEM_USER_ID) {
198 continue;
199 }
200
201 $continue = true;
202 foreach ($this->include_roles as $role_id) {
203 if ($rbacreview->isAssigned($usr_id, $role_id)) {
204 $continue = false;
205 break;
206 }
207 }
208
209 if ($continue) {
210 continue;
211 }
212
215 $timestamp_last_login = strtotime($user->getLastLogin());
216 $grace_period_over = time() - ($this->period * 24 * 60 * 60);
217 if ($timestamp_last_login < $grace_period_over) {
218 $user->delete();
219 $userDeleted++;
220 } elseif ($reminder_time > 0) {
221 $timestamp_for_deletion = $timestamp_last_login - $grace_period_over;
222 $account_will_be_deleted_on = $this->calculateDeletionData($timestamp_for_deletion);
224 $user,
225 $reminder_time,
226 $account_will_be_deleted_on
227 );
228 if ($mailSent) {
229 $userMailsDelivered++;
230 }
231 }
232 $counter++;
233 }
234
235 if ($counter) {
237 }
238
240 $ilLog->write(
241 "CRON - ilCronDeleteInactiveUserAccounts::run(), deleted " .
242 "=> $userDeleted User(s), sent reminder mail to $userMailsDelivered User(s)"
243 );
244
245 $result = new ilCronJobResult();
246 $result->setStatus($status);
247
248 return $result;
249 }
250
251 protected function calculateDeletionData(int $date_for_deletion): int
252 {
253 $cron_timing = $this->cronRepository->getCronJobData($this->getId());
254 $time_difference = 0;
255 $multiplier = 1;
256
257 if (!is_array($cron_timing) || !isset($cron_timing[0]) || !is_array($cron_timing[0])) {
258 return time() + $date_for_deletion + $time_difference;
259 }
260
261 if (array_key_exists('schedule_type', $cron_timing[0])) {
262 if ($cron_timing[0]['schedule_value'] !== null) {
263 $multiplier = (int) $cron_timing[0]['schedule_value'];
264 }
265 $time_difference = $this->getTimeDifferenceBySchedule(
266 (int) $cron_timing[0]['schedule_type'],
267 $multiplier
268 );
269 }
270 return time() + $date_for_deletion + $time_difference;
271 }
272
273 public function addCustomSettingsToForm(ilPropertyFormGUI $a_form): void
274 {
275 $this->lng->loadLanguageModule("user");
276
277 $schedule = $a_form->getItemByPostVar('type');
278 $schedule->setTitle($this->lng->txt('delete_inactive_user_accounts_frequency'));
279 $schedule->setInfo($this->lng->txt('delete_inactive_user_accounts_frequency_desc'));
280
281 $sub_mlist = new ilMultiSelectInputGUI(
282 $this->lng->txt('delete_inactive_user_accounts_include_roles'),
283 'cron_inactive_user_delete_include_roles'
284 );
285 $sub_mlist->setInfo($this->lng->txt('delete_inactive_user_accounts_include_roles_desc'));
286 $roles = [];
287 foreach ($this->rbacReview->getGlobalRoles() as $role_id) {
288 if ($role_id !== ANONYMOUS_ROLE_ID) {
289 $roles[$role_id] = $this->objectDataCache->lookupTitle($role_id);
290 }
291 }
292 $sub_mlist->setOptions($roles);
293 $setting = $this->settings->get('cron_inactive_user_delete_include_roles', null);
294 if ($setting === null) {
295 $setting = [];
296 } else {
297 $setting = explode(',', $setting);
298 }
299 $sub_mlist->setValue($setting);
300 $sub_mlist->setWidth(300);
301 $a_form->addItem($sub_mlist);
302
303 $default_setting = (string) self::DEFAULT_INACTIVITY_PERIOD;
304
305 $sub_text = new ilNumberInputGUI(
306 $this->lng->txt('delete_inactive_user_accounts_period'),
307 'cron_inactive_user_delete_period'
308 );
309 $sub_text->allowDecimals(false);
310 $sub_text->setInfo($this->lng->txt('delete_inactive_user_accounts_period_desc'));
311 $sub_text->setValue($this->settings->get("cron_inactive_user_delete_period", $default_setting));
312 $sub_text->setSize(4);
313 $sub_text->setMaxLength(4);
314 $sub_text->setRequired(true);
315 $a_form->addItem($sub_text);
316
317 $sub_period = new ilNumberInputGUI(
318 $this->lng->txt('send_mail_to_inactive_users'),
319 'cron_inactive_user_reminder_period'
320 );
321 $sub_period->allowDecimals(false);
322 $sub_period->setInfo($this->lng->txt("send_mail_to_inactive_users_desc"));
323 $sub_period->setValue($this->settings->get("cron_inactive_user_reminder_period", $default_setting));
324 $sub_period->setSuffix($this->lng->txt("send_mail_to_inactive_users_suffix"));
325 $sub_period->setSize(4);
326 $sub_period->setMaxLength(4);
327 $sub_period->setRequired(false);
328 $sub_period->setMinValue(0);
329 $a_form->addItem($sub_period);
330 }
331
332 public function saveCustomSettings(ilPropertyFormGUI $a_form): bool
333 {
334 $this->lng->loadLanguageModule("user");
335
336 $valid = true;
337
338 $cron_period = $this->http->wrapper()->post()->retrieve(
339 'type',
340 $this->refinery->kindlyTo()->int()
341 );
342
343 $cron_period_custom = 0;
344 $delete_period = 0;
345 $reminder_period = '';
346
347 $empty_string_trafo = $this->refinery->custom()->transformation(static function ($value): string {
348 if ($value === '') {
349 return '';
350 }
351
352 throw new Exception('The value to be transformed is not an empty string');
353 });
354
355 if ($this->http->wrapper()->post()->has('sdyi')) {
356 $cron_period_custom = $this->http->wrapper()->post()->retrieve(
357 'sdyi',
358 $this->refinery->byTrying([
359 $this->refinery->kindlyTo()->int(),
360 $empty_string_trafo
361 ])
362 );
363 }
364
365 if ($this->http->wrapper()->post()->has('cron_inactive_user_delete_period')) {
366 $delete_period = $this->http->wrapper()->post()->retrieve(
367 'cron_inactive_user_delete_period',
368 $this->refinery->byTrying([
369 $this->refinery->kindlyTo()->int(),
370 $this->refinery->in()->series([
371 $this->refinery->kindlyTo()->float(),
372 $this->refinery->kindlyTo()->int()
373 ])
374 ])
375 );
376 }
377
378 if ($this->http->wrapper()->post()->has('cron_inactive_user_reminder_period')) {
379 $reminder_period = $this->http->wrapper()->post()->retrieve(
380 'cron_inactive_user_reminder_period',
381 $this->refinery->byTrying([
382 $empty_string_trafo,
383 $this->refinery->byTrying([
384 $this->refinery->kindlyTo()->int(),
385 $this->refinery->in()->series([
386 $this->refinery->kindlyTo()->float(),
387 $this->refinery->kindlyTo()->int()
388 ])
389 ])
390 ])
391 );
392 }
393
394 if ($this->isDecimal($delete_period)) {
395 $valid = false;
396 $a_form->getItemByPostVar('cron_inactive_user_delete_period')->setAlert(
397 $this->lng->txt('send_mail_to_inactive_users_numbers_only')
398 );
399 }
400
401 if ($this->isDecimal($reminder_period)) {
402 $valid = false;
403 $a_form->getItemByPostVar('cron_inactive_user_reminder_period')->setAlert(
404 $this->lng->txt('send_mail_to_inactive_users_numbers_only')
405 );
406 }
407
408 if ($reminder_period >= $delete_period) {
409 $valid = false;
410 $a_form->getItemByPostVar('cron_inactive_user_reminder_period')->setAlert(
411 $this->lng->txt('send_mail_to_inactive_users_must_be_smaller_than')
412 );
413 }
414
415 if ($cron_period >= ilCronJob::SCHEDULE_TYPE_IN_DAYS && $cron_period <= ilCronJob::SCHEDULE_TYPE_YEARLY && $reminder_period > 0) {
416 $logic = true;
417 $check_window_logic = $delete_period - $reminder_period;
418 if ($cron_period === ilCronJob::SCHEDULE_TYPE_IN_DAYS) {
419 if ($check_window_logic < $cron_period_custom) {
420 $logic = false;
421 }
422 } elseif ($cron_period === ilCronJob::SCHEDULE_TYPE_WEEKLY) {
423 if ($check_window_logic <= 7) {
424 $logic = false;
425 }
426 } elseif ($cron_period === ilCronJob::SCHEDULE_TYPE_MONTHLY) {
427 if ($check_window_logic <= 31) {
428 $logic = false;
429 }
430 } elseif ($cron_period === ilCronJob::SCHEDULE_TYPE_QUARTERLY) {
431 if ($check_window_logic <= 92) {
432 $logic = false;
433 }
434 } elseif ($cron_period === ilCronJob::SCHEDULE_TYPE_YEARLY) {
435 if ($check_window_logic <= 366) {
436 $logic = false;
437 }
438 }
439
440 if (!$logic) {
441 $valid = false;
442 $a_form->getItemByPostVar('cron_inactive_user_reminder_period')->setAlert(
443 $this->lng->txt('send_mail_reminder_window_too_small')
444 );
445 }
446 }
447
448 if ($delete_period > 0) {
449 $roles = implode(',', $this->http->wrapper()->post()->retrieve(
450 'cron_inactive_user_delete_include_roles',
451 $this->refinery->byTrying([
452 $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->int()),
453 $this->refinery->always([])
454 ])
455 ));
456
457 $this->settings->set('cron_inactive_user_delete_include_roles', $roles);
458 $this->settings->set('cron_inactive_user_delete_period', (string) $delete_period);
459 }
460
461 if ($this->reminderTimer > $reminder_period) {
463 }
464
465 $this->settings->set('cron_inactive_user_reminder_period', (string) $reminder_period);
466
467 if (!$valid) {
468 $this->main_tpl->setOnScreenMessage('failure', $this->lng->txt("form_input_not_valid"));
469 return false;
470 }
471
472 return true;
473 }
474}
hasAutoActivation()
Is to be activated on "installation", does only work for ILIAS core cron jobs.
getTimeDifferenceBySchedule(int $schedule_time, int $multiplier)
static sendReminderMailIfNeeded(ilObjUser $user, int $reminderTime, int $time_frame_for_deletion)
const SCHEDULE_TYPE_IN_DAYS
@depracated This will be replaced with an ENUM in ILIAS 9
const SCHEDULE_TYPE_IN_HOURS
@depracated This will be replaced with an ENUM in ILIAS 9
const SCHEDULE_TYPE_IN_MINUTES
@depracated This will be replaced with an ENUM in ILIAS 9
const SCHEDULE_TYPE_WEEKLY
@depracated This will be replaced with an ENUM in ILIAS 9
const SCHEDULE_TYPE_YEARLY
@depracated This will be replaced with an ENUM in ILIAS 9
const SCHEDULE_TYPE_DAILY
@depracated This will be replaced with an ENUM in ILIAS 9
const SCHEDULE_TYPE_QUARTERLY
@depracated This will be replaced with an ENUM in ILIAS 9
const SCHEDULE_TYPE_MONTHLY
@depracated This will be replaced with an ENUM in ILIAS 9
language handling
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This class represents a number property in a property form.
static getUserIdsByInactivityPeriod(int $periodInDays)
Get ids of all users that have been inactive for at least the given period.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getInstanceByObjId(?int $obj_id, bool $stop_on_error=true)
get an instance of an Ilias object by object id
This class represents a property form user interface.
getItemByPostVar(string $a_post_var)
class ilRbacReview Contains Review functions of core Rbac.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
const ANONYMOUS_ROLE_ID
Definition: constants.php:28
const SYSTEM_USER_ID
This file contains constants for PHPStan analyis, see: https://phpstan.org/config-reference#constants...
Definition: constants.php:26
const ANONYMOUS_USER_ID
Definition: constants.php:27
$valid
global $DIC
Definition: feed.php:28
static http()
Fetches the global http state from ILIAS.