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