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