ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilCronManagerGUI.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
33
39{
40 private const array TABLE_ACTION_NAMESPACE = ['cron', 'jobs'];
41 private const string TABLE_ACTION_PARAM_NAME = 'table_action';
42 private const string TABLE_ACTION_IDENTIFIER_NAME = 'jid';
43 private const string FORM_PARAM_SCHEDULE_PREFIX = 'schedule_';
44 public const FORM_PARAM_MAIN_SECTION = 'main';
45 public const FORM_PARAM_JOB_INPUT = 'additional_job_input';
46 public const FORM_PARAM_GROUP_SCHEDULE = 'schedule';
47
48 private readonly ilLanguage $lng;
49 private readonly ilCtrlInterface $ctrl;
50 private readonly ilSetting $settings;
52 private readonly Factory $ui_factory;
53 private readonly Renderer $ui_renderer;
54 private readonly ilUIService $ui_service;
56 private readonly \ILIAS\DI\RBACServices $rbac;
57 private readonly ilErrorHandling $error;
58 private readonly WrapperFactory $http_wrapper;
59 private readonly \ILIAS\HTTP\GlobalHttpState $http;
60 private readonly \ILIAS\Refinery\Factory $refinery;
61 private readonly JobManager $cron_manager;
62 private readonly ilObjUser $actor;
63
64 public function __construct()
65 {
67 global $DIC;
68
69 $this->lng = $DIC->language();
70 $this->ctrl = $DIC->ctrl();
71 $this->settings = $DIC->settings();
72 $this->tpl = $DIC->ui()->mainTemplate();
73 $this->ui_factory = $DIC->ui()->factory();
74 $this->ui_renderer = $DIC->ui()->renderer();
75 $this->ui_service = $DIC->uiService();
76 $this->rbac = $DIC->rbac();
77 $this->error = $DIC['ilErr'];
78 $this->http_wrapper = $DIC->http()->wrapper();
79 $this->http = $DIC->http();
80 $this->refinery = $DIC->refinery();
81 $this->actor = $DIC->user();
82 $this->cron_repository = $DIC->cron()->repository();
83 $this->cron_manager = $DIC->cron()->manager();
84
85 $this->lng->loadLanguageModule('cron');
86 $this->lng->loadLanguageModule('cmps');
87 }
88
92 private function retrieveTableActionJobIds(): array
93 {
94 $retrieval = $this->http_wrapper->query();
95 if (strtoupper($this->http->request()->getMethod()) === 'POST') {
96 $retrieval = $this->http_wrapper->post();
97 }
98
99 $trafo = $this->refinery->byTrying([
100 $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->string()),
101 $this->refinery->always([])
102 ]);
103
104 $ids = $retrieval->retrieve(
105 $this->getJobIdParameterName(),
106 $trafo
107 );
108
109 if (count($ids) === 1 && $ids[0] === 'ALL_OBJECTS') {
110 $tableFilterMediator = new JobTableFilterMediator(
111 $this->cron_repository->findAll(),
112 $this->ui_factory,
113 $this->ui_service,
114 $this->lng
115 );
116 $filter = $tableFilterMediator->filter(
117 $this->ctrl->getFormAction(
118 $this,
119 'render',
120 '',
121 true
122 )
123 );
124 $ids = array_map(
125 static fn(JobEntity $entity): string => $entity->getEffectiveJobId(),
126 $tableFilterMediator->filteredJobs(
127 $filter
128 )->toArray()
129 );
130 }
131
132 return $ids;
133 }
134
135 private function getTableActionParameterName(): string
136 {
137 return implode('_', array_merge(self::TABLE_ACTION_NAMESPACE, [self::TABLE_ACTION_PARAM_NAME]));
138 }
139
144 private function addProblematicItemsInfo(
145 \ILIAS\Cron\Job\JobCollection $filtered_jobs,
146 \ILIAS\UI\Component\MessageBox\MessageBox $message,
147 array $components
148 ): array {
149 $problematic_jobs = $filtered_jobs->filter(static function (JobEntity $entity): bool {
150 return $entity->getJobResultStatus() === JobResult::STATUS_CRASHED;
151 });
152 if (count($problematic_jobs) > 0) {
153 $problematic_jobs_info = $this->ui_factory->messageBox()->info(
154 $this->lng->txt('cron_jobs_with_required_intervention')
155 )->withLinks(
156 array_map(
157 function (JobEntity $entity): \ILIAS\UI\Component\Link\Standard {
158 return $this->ui_factory->link()->standard(
159 $entity->getEffectiveTitle(),
160 '#job-' . $entity->getEffectiveJobId()
161 );
162 },
164 $problematic_jobs,
165 OrderedJobEntities::ORDER_BY_NAME
166 ))->toArray()
167 )
168 );
169
170 if (in_array($message, $components, true)) {
171 $components = array_merge(
172 array_slice($components, 0, array_search($message, $components, true) + 1),
173 [$problematic_jobs_info],
174 array_slice($components, array_search($message, $components, true) + 1)
175 );
176 } else {
177 array_unshift($components, $problematic_jobs_info);
178 }
179 }
180
181 return $components;
182 }
183
184 private function getJobIdParameterName(): string
185 {
186 return implode('_', array_merge(self::TABLE_ACTION_NAMESPACE, [self::TABLE_ACTION_IDENTIFIER_NAME]));
187 }
188
193 private function getRequestValue(
194 string $key,
195 \ILIAS\Refinery\Transformation $trafo,
196 bool $force_retrieval = false,
197 $default = null
198 ) {
199 $exc = null;
200
201 try {
202 if ($force_retrieval || $this->http_wrapper->query()->has($key)) {
203 return $this->http_wrapper->query()->retrieve($key, $trafo);
204 }
205 } catch (OutOfBoundsException $e) {
206 $exc = $e;
207 }
208
209 try {
210 if ($force_retrieval || $this->http_wrapper->post()->has($key)) {
211 return $this->http_wrapper->post()->retrieve($key, $trafo);
212 }
213 } catch (OutOfBoundsException $e) {
214 $exc = $e;
215 }
216
217 if ($force_retrieval && $exc) {
218 throw $exc;
219 }
220
221 return $default ?? null;
222 }
223
224 public function executeCommand(): void
225 {
226 if (!$this->rbac->system()->checkAccess('visible,read', SYSTEM_FOLDER_ID)) {
227 $this->error->raiseError($this->lng->txt('no_permission'), $this->error->WARNING);
228 }
229
230 $class = $this->ctrl->getNextClass($this) ?? '';
231
232 switch (strtolower($class)) {
233 case strtolower(ilPropertyFormGUI::class):
234 $job_id = $this->getRequestValue($this->getJobIdParameterName(), $this->refinery->kindlyTo()->string());
235 $job = $this->cron_repository->getJobInstanceById(ilUtil::stripSlashes($job_id));
236 $form = $this->initLegacyEditForm($job);
237 $this->ctrl->forwardCommand($form);
238 break;
239 }
240
241 $cmd = $this->ctrl->getCmd('render');
242 $this->$cmd();
243 }
244
245 private function handleTableActions(): void
246 {
247 $action = $this->http_wrapper->query()->retrieve(
248 $this->getTableActionParameterName(),
249 $this->refinery->byTrying([
250 $this->refinery->kindlyTo()->string(),
251 $this->refinery->always('')
252 ])
253 );
254 match ($action) {
255 'run' => $this->run(),
256 'activate' => $this->activate(),
257 'deactivate' => $this->deactivate(),
258 'reset' => $this->reset(),
259 'edit' => $this->edit(),
260 default => $this->render()
261 };
262 }
263
264 protected function render(): void
265 {
266 $tstamp = $this->lng->txt('cronjob_last_start_unknown');
267 if ($this->settings->get('last_cronjob_start_ts')) {
269 new ilDateTime(
270 $this->settings->get('last_cronjob_start_ts'),
272 )
273 );
274 }
275
276 $message = $this->ui_factory->messageBox()->info($this->lng->txt('cronjob_last_start') . ': ' . $tstamp);
277
278 $cronJobs = $this->cron_repository->findAll();
279
280 $tableFilterMediator = new JobTableFilterMediator(
281 $cronJobs,
282 $this->ui_factory,
283 $this->ui_service,
284 $this->lng
285 );
286 $filter = $tableFilterMediator->filter(
287 $this->ctrl->getFormAction(
288 $this,
289 'render',
290 '',
291 true
292 )
293 );
294
295 $filtered_jobs = $tableFilterMediator->filteredJobs(
296 $filter
297 );
298
299 $tbl = new JobTable(
300 $this,
301 'handleTableActions',
302 self::TABLE_ACTION_NAMESPACE,
303 self::TABLE_ACTION_PARAM_NAME,
304 self::TABLE_ACTION_IDENTIFIER_NAME,
305 $this->ui_factory,
306 $this->http->request(),
307 $this->ctrl,
308 $this->lng,
309 $filtered_jobs,
310 $this->cron_repository,
311 $this->rbac->system()->checkAccess('write', SYSTEM_FOLDER_ID)
312 );
313
314 $this->tpl->setContent(
315 $this->ui_renderer->render(
316 $this->addProblematicItemsInfo(
317 $filtered_jobs,
318 $message,
319 [$message, $filter, $tbl->getComponent()]
320 )
321 )
322 );
323 }
324
325 public function edit(?ILIAS\UI\Component\Input\Container\Form\Form $form = null): void
326 {
327 if (!$this->rbac->system()->checkAccess('write', SYSTEM_FOLDER_ID)) {
328 $this->error->raiseError($this->lng->txt('no_permission'), $this->error->WARNING);
329 }
330
331 if ($form === null) {
332 $job_ids = $this->retrieveTableActionJobIds();
333 if (count($job_ids) !== 1) {
334 $this->ctrl->redirect($this, 'render');
335 }
336
337 $job_id = current($job_ids);
338 $job = $this->cron_repository->getJobInstanceById($job_id);
339 if ($job && $job->usesLegacyForms()) {
340 $this->ctrl->setParameter($this, $this->getJobIdParameterName(), $job->getId());
341 $this->ctrl->redirect($this, 'editLegacy');
342 }
343
344 $form = $this->initEditForm($job);
345 }
346
347 $this->tpl->setContent($this->ui_renderer->render($form));
348 }
349
350 public function editLegacy(?ilPropertyFormGUI $a_form = null): void
351 {
352 if (!$this->rbac->system()->checkAccess('write', SYSTEM_FOLDER_ID)) {
353 $this->error->raiseError($this->lng->txt('no_permission'), $this->error->WARNING);
354 }
355
356 if ($a_form === null) {
357 $job_ids = $this->retrieveTableActionJobIds();
358 if (count($job_ids) !== 1) {
359 $this->ctrl->redirect($this, 'render');
360 }
361
362 $job_id = current($job_ids);
363 $job = $this->cron_repository->getJobInstanceById($job_id);
364 $a_form = $this->initLegacyEditForm($job);
365 }
366
367 $this->tpl->setContent($a_form->getHTML());
368 }
369
370 private function getScheduleTypeFormElementName(JobScheduleType $schedule_type): string
371 {
372 return match ($schedule_type) {
373 JobScheduleType::DAILY => $this->lng->txt('cron_schedule_daily'),
374 JobScheduleType::WEEKLY => $this->lng->txt('cron_schedule_weekly'),
375 JobScheduleType::MONTHLY => $this->lng->txt('cron_schedule_monthly'),
376 JobScheduleType::QUARTERLY => $this->lng->txt('cron_schedule_quarterly'),
377 JobScheduleType::YEARLY => $this->lng->txt('cron_schedule_yearly'),
378 JobScheduleType::IN_MINUTES => sprintf($this->lng->txt('cron_schedule_in_minutes'), 'x'),
379 JobScheduleType::IN_HOURS => sprintf($this->lng->txt('cron_schedule_in_hours'), 'x'),
380 JobScheduleType::IN_DAYS => sprintf($this->lng->txt('cron_schedule_in_days'), 'x'),
381 };
382 }
383
384 protected function getScheduleValueFormElementName(JobScheduleType $schedule_type): string
385 {
386 return match ($schedule_type) {
387 JobScheduleType::IN_MINUTES => 'smini',
388 JobScheduleType::IN_HOURS => 'shri',
389 JobScheduleType::IN_DAYS => 'sdyi',
390 default => throw new InvalidArgumentException(
391 sprintf(
392 'The passed argument %s is invalid!',
393 var_export($schedule_type, true)
394 )
395 ),
396 };
397 }
398
399 protected function hasScheduleValue(JobScheduleType $schedule_type): bool
400 {
401 return in_array($schedule_type, [
402 JobScheduleType::IN_MINUTES,
403 JobScheduleType::IN_HOURS,
404 JobScheduleType::IN_DAYS
405 ], true);
406 }
407
408 protected function initEditForm(?CronJob $job): ILIAS\UI\Component\Input\Container\Form\Form
409 {
410 if (!($job instanceof CronJob)) {
411 $this->ctrl->redirect($this, 'render');
412 }
413
414 $this->ctrl->setParameter($this, $this->getJobIdParameterName(), $job->getId());
415
416 $jobs_data = $this->cron_repository->getCronJobData($job->getId());
417 $job_data = $jobs_data[0];
418
419 $section_inputs = [];
420 if ($job->hasFlexibleSchedule()) {
421 $schedule_type_groups = [];
422 foreach ($job->getAllScheduleTypes() as $schedule_type) {
423 if (!in_array($schedule_type, $job->getValidScheduleTypes(), true)) {
424 continue;
425 }
426
427 $schedule_type_inputs = [];
428 if (in_array($schedule_type, $job->getScheduleTypesWithValues(), true)) {
429 $schedule_value_input = $this->ui_factory
430 ->input()
431 ->field()
432 ->numeric(
433 $this->lng->txt('cron_schedule_value')
434 )->withAdditionalTransformation(
435 $this->refinery->in()->series([
436 $this->refinery->int()->isGreaterThanOrEqual(1)
437 ])
438 )->withRequired(true);
439
440 if (is_numeric($job_data['schedule_type']) &&
441 JobScheduleType::tryFrom((int) $job_data['schedule_type']) === $schedule_type) {
442 $schedule_value_input = $schedule_value_input->withValue(
443 $job_data['schedule_value'] === null ? null : (int) $job_data['schedule_value']
444 );
445 }
446
447 $schedule_type_inputs = [
448 $this->getScheduleValueFormElementName($schedule_type) => $schedule_value_input
449 ];
450 }
451
452 $schedule_type_groups[self::FORM_PARAM_SCHEDULE_PREFIX . $schedule_type->value] = $this->ui_factory
453 ->input()
454 ->field()
455 ->group(
456 $schedule_type_inputs,
457 $this->getScheduleTypeFormElementName($schedule_type)
458 )
459 ->withDedicatedName(self::FORM_PARAM_SCHEDULE_PREFIX . $schedule_type->value);
460 }
461
462 $default_schedule_type = current($job->getValidScheduleTypes())->value;
463
464 $section_inputs['schedule'] = $this->ui_factory
465 ->input()
466 ->field()
467 ->switchableGroup(
468 $schedule_type_groups,
469 $this->lng->txt('cron_schedule_type')
470 )
471 ->withRequired(true)
472 ->withValue(
473 $job_data['schedule_type'] === null ?
474 self::FORM_PARAM_SCHEDULE_PREFIX . $default_schedule_type :
475 self::FORM_PARAM_SCHEDULE_PREFIX . $job_data['schedule_type']
476 );
477 }
478
479 $main_section = $this->ui_factory->input()->field()->section(
480 $section_inputs,
481 $this->lng->txt('cron_action_edit') . ': "' . $job->getTitle() . '"'
482 );
483
484 $inputs = [
485 self::FORM_PARAM_MAIN_SECTION => $main_section
486 ];
487
488 if ($job->hasCustomSettings()) {
489 $inputs = array_merge(
490 $inputs,
491 [
492 self::FORM_PARAM_JOB_INPUT =>
494 $this->ui_factory,
495 $this->refinery,
496 $this->lng
497 )
498 ]
499 );
500 }
501
502 return $this->ui_factory
503 ->input()
504 ->container()
505 ->form()
506 ->standard($this->ctrl->getFormAction($this, 'update'), $inputs)
507 ->withDedicatedName('cron_form');
508 }
509
513 #[\Deprecated('Will be removed without any alternative, KS/UI forms will be expected', since: '13.0')]
515 {
516 if (!($job instanceof CronJob)) {
517 $this->ctrl->redirect($this, 'render');
518 }
519
520 $this->ctrl->setParameter($this, $this->getJobIdParameterName(), $job->getId());
521
522 $jobs_data = $this->cron_repository->getCronJobData($job->getId());
523 $job_data = $jobs_data[0];
524
525 $form = new ilPropertyFormGUI();
526 $form->setFormAction($this->ctrl->getFormAction($this, 'updateLegacy'));
527 $form->setTitle($this->lng->txt('cron_action_edit') . ': "' . $job->getTitle() . '"');
528
529 if ($job->hasFlexibleSchedule()) {
530 $type = new ilRadioGroupInputGUI($this->lng->txt('cron_schedule_type'), 'type');
531 $type->setRequired(true);
532 $type->setValue($job_data['schedule_type'] === null ? null : (string) $job_data['schedule_type']);
533
534 foreach ($job->getAllScheduleTypes() as $schedule_type) {
535 if (!in_array($schedule_type, $job->getValidScheduleTypes(), true)) {
536 continue;
537 }
538
539 $option = new ilRadioOption(
540 $this->getScheduleTypeFormElementName($schedule_type),
541 (string) $schedule_type->value
542 );
543 $type->addOption($option);
544
545 if (in_array($schedule_type, $job->getScheduleTypesWithValues(), true)) {
546 $scheduleValue = new ilNumberInputGUI(
547 $this->lng->txt('cron_schedule_value'),
548 $this->getScheduleValueFormElementName($schedule_type)
549 );
550 $scheduleValue->allowDecimals(false);
551 $scheduleValue->setRequired(true);
552 $scheduleValue->setSize(5);
553 if (is_numeric($job_data['schedule_type']) &&
554 JobScheduleType::tryFrom((int) $job_data['schedule_type']) === $schedule_type) {
555 $scheduleValue->setValue(
556 $job_data['schedule_value'] === null ? null : (string) $job_data['schedule_value']
557 );
558 }
559 $option->addSubItem($scheduleValue);
560 }
561 }
562
563 $form->addItem($type);
564 }
565
566 if ($job->hasCustomSettings()) {
567 $job->addCustomSettingsToForm($form);
568 }
569
570 $form->addCommandButton('updateLegacy', $this->lng->txt('save'));
571 $form->addCommandButton('render', $this->lng->txt('cancel'));
572
573 return $form;
574 }
575
576 public function update(): void
577 {
578 if (!$this->rbac->system()->checkAccess('write', SYSTEM_FOLDER_ID)) {
579 $this->error->raiseError($this->lng->txt('no_permission'), $this->error->WARNING);
580 }
581
582 $job_id = $this->getRequestValue($this->getJobIdParameterName(), $this->refinery->kindlyTo()->string());
583 if (!$job_id) {
584 $this->ctrl->redirect($this, 'render');
585 }
586
587 $job = $this->cron_repository->getJobInstanceById($job_id);
588 $form = $this->initEditForm($job);
589
590 $form_valid = false;
591 $form_data = null;
592 if ($this->http->request()->getMethod() === 'POST') {
593 $form = $form->withRequest($this->http->request());
594 $form_data = $form->getData();
595 $form_valid = $form_data !== null;
596 }
597
598 if (!$form_valid) {
599 $this->edit($form);
600 return;
601 }
602
603 if ($job instanceof CronJob) {
604 if ($job->hasFlexibleSchedule()) {
605 $schedule_group = $form_data[self::FORM_PARAM_MAIN_SECTION][self::FORM_PARAM_GROUP_SCHEDULE];
606
607 $type = JobScheduleType::from(
608 (int) ltrim($schedule_group[0], self::FORM_PARAM_SCHEDULE_PREFIX)
609 );
610
611 $value = match (true) {
612 $this->hasScheduleValue($type) => (int) $schedule_group[1][$this->getScheduleValueFormElementName(
613 $type
614 )],
615 default => null,
616 };
617
618 $this->cron_repository->updateJobSchedule($job, $type, $value);
619 }
620
621 if ($job->hasCustomSettings()) {
622 $job->saveCustomConfiguration($form_data[self::FORM_PARAM_JOB_INPUT]);
623 }
624
625 $this->tpl->setOnScreenMessage('success', $this->lng->txt('cron_action_edit_success'), true);
626 $this->ctrl->redirect($this, 'render');
627 }
628
629 $this->edit($form);
630 }
631
635 #[\Deprecated('Will be removed without any alternative, KS/UI forms will be expected', since: '12.0')]
636 public function updateLegacy(): void
637 {
638 if (!$this->rbac->system()->checkAccess('write', SYSTEM_FOLDER_ID)) {
639 $this->error->raiseError($this->lng->txt('no_permission'), $this->error->WARNING);
640 }
641
642 $job_id = $this->getRequestValue($this->getJobIdParameterName(), $this->refinery->kindlyTo()->string());
643 if (!$job_id) {
644 $this->ctrl->redirect($this, 'render');
645 }
646
647 $job = $this->cron_repository->getJobInstanceById($job_id);
648
649 $form = $this->initLegacyEditForm($job);
650 if ($job instanceof CronJob && $form->checkInput()) {
651 $valid = true;
652 if ($job->hasCustomSettings() && !$job->saveCustomSettings($form)) {
653 $valid = false;
654 }
655
656 if ($valid && $job->hasFlexibleSchedule()) {
657 $type = JobScheduleType::from((int) $form->getInput('type'));
658 $value = match (true) {
659 $this->hasScheduleValue($type) => (int) $form->getInput(
660 $this->getScheduleValueFormElementName($type)
661 ),
662 default => null,
663 };
664
665 $this->cron_repository->updateJobSchedule($job, $type, $value);
666 }
667
668 if ($valid) {
669 $this->tpl->setOnScreenMessage('success', $this->lng->txt('cron_action_edit_success'), true);
670 $this->ctrl->redirect($this, 'render');
671 }
672 }
673
674 $form->setValuesByPost();
675 $this->editLegacy($form);
676 }
677
678 public function run(): void
679 {
680 $this->confirm('run');
681 }
682
683 public function confirmedRun(): void
684 {
685 if (!$this->rbac->system()->checkAccess('write', SYSTEM_FOLDER_ID)) {
686 $this->error->raiseError($this->lng->txt('no_permission'), $this->error->WARNING);
687 }
688
689 $job_ids = $this->retrieveTableActionJobIds();
690 if (count($job_ids) !== 1) {
691 $this->ctrl->redirect($this, 'render');
692 }
693
694 $job_id = current($job_ids);
695 if ($this->cron_manager->runJobManual($job_id, $this->actor)) {
696 $this->tpl->setOnScreenMessage('success', $this->lng->txt('cron_action_run_success'), true);
697 } else {
698 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('cron_action_run_fail'), true);
699 }
700
701 $this->ctrl->redirect($this, 'render');
702 }
703
704 public function activate(): void
705 {
706 $this->confirm('activate');
707 }
708
709 public function confirmedActivate(): void
710 {
711 if (!$this->rbac->system()->checkAccess('write', SYSTEM_FOLDER_ID)) {
712 $this->error->raiseError($this->lng->txt('no_permission'), $this->error->WARNING);
713 }
714
715 $jobs = $this->getMultiActionData();
716 if ($jobs !== []) {
717 foreach ($jobs as $job) {
718 if ($this->cron_manager->isJobInactive($job->getId())) {
719 $this->cron_manager->resetJob($job, $this->actor);
720 }
721 }
722
723 $this->tpl->setOnScreenMessage('success', $this->lng->txt('cron_action_activate_success'), true);
724 } else {
725 $this->tpl->setOnScreenMessage('info', $this->lng->txt('no_checkbox'), true);
726 }
727
728 $this->ctrl->redirect($this, 'render');
729 }
730
731 public function deactivate(): void
732 {
733 $this->confirm('deactivate');
734 }
735
736 public function confirmedDeactivate(): void
737 {
738 if (!$this->rbac->system()->checkAccess('write', SYSTEM_FOLDER_ID)) {
739 $this->error->raiseError($this->lng->txt('no_permission'), $this->error->WARNING);
740 }
741
742 $jobs = $this->getMultiActionData();
743 if ($jobs !== []) {
744 foreach ($jobs as $job) {
745 if ($this->cron_manager->isJobActive($job->getId())) {
746 $this->cron_manager->deactivateJob($job, $this->actor, true);
747 }
748 }
749
750 $this->tpl->setOnScreenMessage('success', $this->lng->txt('cron_action_deactivate_success'), true);
751 } else {
752 $this->tpl->setOnScreenMessage('info', $this->lng->txt('no_checkbox'), true);
753 }
754
755 $this->ctrl->redirect($this, 'render');
756 }
757
758 public function reset(): void
759 {
760 $this->confirm('reset');
761 }
762
763 public function confirmedReset(): void
764 {
765 if (!$this->rbac->system()->checkAccess('write', SYSTEM_FOLDER_ID)) {
766 $this->error->raiseError($this->lng->txt('no_permission'), $this->error->WARNING);
767 }
768
769 $jobs = $this->getMultiActionData();
770 if ($jobs !== []) {
771 foreach ($jobs as $job) {
772 $this->cron_manager->resetJob($job, $this->actor);
773 }
774 $this->tpl->setOnScreenMessage('success', $this->lng->txt('cron_action_reset_success'), true);
775 } else {
776 $this->tpl->setOnScreenMessage('info', $this->lng->txt('no_checkbox'), true);
777 }
778
779 $this->ctrl->redirect($this, 'render');
780 }
781
785 protected function getMultiActionData(): array
786 {
787 $res = [];
788
789 $job_ids = [];
790 try {
791 $job_ids = $this->retrieveTableActionJobIds();
792 } catch (\ILIAS\Refinery\ConstraintViolationException|OutOfBoundsException) {
793 }
794
795 foreach ($job_ids as $job_id) {
796 $job = $this->cron_repository->getJobInstanceById($job_id);
797 if ($job instanceof CronJob) {
798 $res[$job_id] = $job;
799 }
800 }
801
802 return $res;
803 }
804
805 protected function confirm(string $a_action): void
806 {
807 if (!$this->rbac->system()->checkAccess('write', SYSTEM_FOLDER_ID)) {
808 $this->error->raiseError($this->lng->txt('no_permission'), $this->error->WARNING);
809 }
810
811 $jobs = $this->getMultiActionData();
812 if ($jobs === []) {
813 $this->tpl->setOnScreenMessage('info', $this->lng->txt('no_checkbox'), true);
814 $this->ctrl->redirect($this, 'render');
815 }
816
817 if ($a_action === 'run') {
818 $jobs = array_filter($jobs, static function (CronJob $job): bool {
819 return $job->isManuallyExecutable();
820 });
821
822 if ($jobs === []) {
823 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('cron_no_executable_job_selected'), true);
824 $this->ctrl->redirect($this, 'render');
825 }
826 }
827
828 $cgui = new ilConfirmationGUI();
829
830 if (count($jobs) === 1) {
831 $jobKeys = array_keys($jobs);
832 $job_id = array_pop($jobKeys);
833 $job = array_pop($jobs);
834 $title = $job->getTitle();
835 if (!$title) {
836 $title = preg_replace('[^A-Za-z0-9_\-]', '', $job->getId());
837 }
838
839 $cgui->setHeaderText(
840 sprintf(
841 $this->lng->txt('cron_action_' . $a_action . '_sure'),
842 $title
843 )
844 );
845
846 $cgui->addHiddenItem($this->getJobIdParameterName() . '[]', $job_id);
847 } else {
848 $cgui->setHeaderText($this->lng->txt('cron_action_' . $a_action . '_sure_multi'));
849
850 foreach ($jobs as $job_id => $job) {
851 $cgui->addItem($this->getJobIdParameterName() . '[]', $job_id, $job->getTitle());
852 }
853 }
854
855 $cgui->setFormAction($this->ctrl->getFormAction($this, 'confirmed' . ucfirst($a_action)));
856 $cgui->setCancel($this->lng->txt('cancel'), 'render');
857 $cgui->setConfirm($this->lng->txt('cron_action_' . $a_action), 'confirmed' . ucfirst($a_action));
858
859 $this->tpl->setContent($cgui->getHTML());
860 }
861
865 public function addToExternalSettingsForm(int $a_form_id): array
866 {
867 $form_elements = [];
868 $fields = [];
869 $data = $this->cron_repository->getCronJobData();
870 foreach ($data as $item) {
871 $job = $this->cron_repository->getJobInstance(
872 $item['job_id'],
873 $item['component'],
874 $item['class']
875 );
876 if ($job !== null) {
877 $job->addToExternalSettingsForm($a_form_id, $fields, (bool) $item['job_status']);
878 }
879 }
880
881 if ($fields !== []) {
882 $form_elements = [
883 'cron_jobs' => [
884 'jumpToCronJobs',
885 $fields
886 ]
887 ];
888 }
889
890 return $form_elements;
891 }
892}
$components
getCustomConfigurationInput(\ILIAS\UI\Factory $ui_factory, \ILIAS\Refinery\Factory $factory, \ilLanguage $lng)
Definition: CronJob.php:241
getAllScheduleTypes()
Get all available schedule types.
Definition: CronJob.php:196
getScheduleTypesWithValues()
Definition: CronJob.php:204
getValidScheduleTypes()
Returns a collection of all valid schedule types for a specific job.
Definition: CronJob.php:217
addCustomSettingsToForm(\ilPropertyFormGUI $a_form)
Definition: CronJob.php:253
Builds a Color from either hex- or rgb values.
Definition: Factory.php:31
const IL_CAL_UNIX
error(string $a_errmsg)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
@ilCtrl_Calls ilCronManagerGUI: ilPropertyFormGUI @ilCtrl_isCalledBy ilCronManagerGUI: ilAdministrati...
readonly JobManager $cron_manager
getScheduleValueFormElementName(JobScheduleType $schedule_type)
readonly ILIAS DI RBACServices $rbac
readonly ilLanguage $lng
const string FORM_PARAM_SCHEDULE_PREFIX
addProblematicItemsInfo(\ILIAS\Cron\Job\JobCollection $filtered_jobs, \ILIAS\UI\Component\MessageBox\MessageBox $message, array $components)
readonly ilSetting $settings
readonly ILIAS HTTP GlobalHttpState $http
const string TABLE_ACTION_IDENTIFIER_NAME
readonly JobRepository $cron_repository
readonly ilErrorHandling $error
getRequestValue(string $key, \ILIAS\Refinery\Transformation $trafo, bool $force_retrieval=false, $default=null)
readonly ilUIService $ui_service
initLegacyEditForm(?CronJob $job)
readonly ilGlobalTemplateInterface $tpl
hasScheduleValue(JobScheduleType $schedule_type)
edit(?ILIAS\UI\Component\Input\Container\Form\Form $form=null)
readonly Factory $ui_factory
addToExternalSettingsForm(int $a_form_id)
editLegacy(?ilPropertyFormGUI $a_form=null)
getScheduleTypeFormElementName(JobScheduleType $schedule_type)
const string TABLE_ACTION_PARAM_NAME
readonly WrapperFactory $http_wrapper
readonly ilCtrlInterface $ctrl
readonly ilObjUser $actor
readonly Renderer $ui_renderer
const array TABLE_ACTION_NAMESPACE
readonly ILIAS Refinery Factory $refinery
confirm(string $a_action)
static formatDate(ilDateTime $date, bool $a_skip_day=false, bool $a_include_wd=false, bool $include_seconds=false, ?ilObjUser $user=null,)
@classDescription Date and time handling
Error Handling & global info handling.
language handling
This class represents a number property in a property form.
User class.
This class represents a property form user interface.
This class represents a property in a property form.
This class represents an option in a radio group.
ILIAS Setting Class.
Filter service.
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
const SYSTEM_FOLDER_ID
Definition: constants.php:35
return['delivery_method'=> 'php',]
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$valid
This is how the factory for UI elements looks.
Definition: Factory.php:38
An entity that renders components to a string output.
Definition: Renderer.php:31
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$res
Definition: ltiservices.php:69
static http()
Fetches the global http state from ILIAS.
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
filter(string $filter_id, $class_path, string $cmd, bool $activated=true, bool $expanded=true)
Interface Observer \BackgroundTasks Contains several chained tasks and infos about them.
global $DIC
Definition: shib_login.php:26
$message
Definition: xapiexit.php:31