19 declare(strict_types=1);
56 private readonly \ILIAS\DI\RBACServices
$rbac;
59 private readonly \ILIAS\HTTP\GlobalHttpState
$http;
69 $this->
lng = $DIC->language();
70 $this->
ctrl = $DIC->ctrl();
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();
81 $this->actor = $DIC->user();
82 $this->cron_repository = $DIC->cron()->repository();
83 $this->cron_manager = $DIC->cron()->manager();
85 $this->
lng->loadLanguageModule(
'cron');
86 $this->
lng->loadLanguageModule(
'cmps');
94 $retrieval = $this->http_wrapper->query();
95 if (strtoupper($this->
http->request()->getMethod()) ===
'POST') {
96 $retrieval = $this->http_wrapper->post();
104 $ids = $retrieval->retrieve(
109 if (count($ids) === 1 && $ids[0] ===
'ALL_OBJECTS') {
111 $this->cron_repository->findAll(),
116 $filter = $tableFilterMediator->
filter(
117 $this->
ctrl->getFormAction(
126 $tableFilterMediator->filteredJobs(
137 return implode(
'_', array_merge(self::TABLE_ACTION_NAMESPACE, [self::TABLE_ACTION_PARAM_NAME]));
145 \
ILIAS\Cron\Job\JobCollection $filtered_jobs,
149 $problematic_jobs = $filtered_jobs->filter(
static function (
JobEntity $entity):
bool {
152 if (count($problematic_jobs) > 0) {
153 $problematic_jobs_info = $this->ui_factory->messageBox()->info(
154 $this->
lng->txt(
'cron_jobs_with_required_intervention')
158 return $this->ui_factory->link()->standard(
165 OrderedJobEntities::ORDER_BY_NAME
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)
177 array_unshift($components, $problematic_jobs_info);
186 return implode(
'_', array_merge(self::TABLE_ACTION_NAMESPACE, [self::TABLE_ACTION_IDENTIFIER_NAME]));
196 bool $force_retrieval =
false,
202 if ($force_retrieval || $this->http_wrapper->query()->has($key)) {
203 return $this->http_wrapper->query()->retrieve($key, $trafo);
210 if ($force_retrieval || $this->http_wrapper->post()->has($key)) {
211 return $this->http_wrapper->post()->retrieve($key, $trafo);
217 if ($force_retrieval && $exc) {
221 return $default ??
null;
227 $this->error->raiseError($this->
lng->txt(
'no_permission'), $this->error->WARNING);
230 $class = $this->
ctrl->getNextClass($this) ??
'';
232 switch (strtolower($class)) {
233 case strtolower(ilPropertyFormGUI::class):
237 $this->
ctrl->forwardCommand($form);
241 $cmd = $this->
ctrl->getCmd(
'render');
247 $action = $this->http_wrapper->query()->retrieve(
250 $this->refinery->kindlyTo()->string(),
255 'run' => $this->
run(),
258 'reset' => $this->
reset(),
259 'edit' => $this->
edit(),
260 default => $this->
render()
266 $tstamp = $this->
lng->txt(
'cronjob_last_start_unknown');
267 if ($this->
settings->get(
'last_cronjob_start_ts')) {
270 $this->
settings->get(
'last_cronjob_start_ts'),
276 $message = $this->ui_factory->messageBox()->info($this->
lng->txt(
'cronjob_last_start') .
': ' . $tstamp);
278 $cronJobs = $this->cron_repository->findAll();
286 $filter = $tableFilterMediator->filter(
287 $this->
ctrl->getFormAction(
295 $filtered_jobs = $tableFilterMediator->filteredJobs(
301 'handleTableActions',
302 self::TABLE_ACTION_NAMESPACE,
303 self::TABLE_ACTION_PARAM_NAME,
304 self::TABLE_ACTION_IDENTIFIER_NAME,
306 $this->
http->request(),
314 $this->tpl->setContent(
315 $this->ui_renderer->render(
316 $this->addProblematicItemsInfo(
319 [
$message, $filter, $tbl->getComponent()]
328 $this->error->raiseError($this->
lng->txt(
'no_permission'), $this->error->WARNING);
331 if ($form ===
null) {
333 if (count($job_ids) !== 1) {
334 $this->
ctrl->redirect($this,
'render');
337 $job_id = current($job_ids);
338 $job = $this->cron_repository->getJobInstanceById($job_id);
339 if ($job && $job->usesLegacyForms()) {
341 $this->
ctrl->redirect($this,
'editLegacy');
347 $this->tpl->setContent($this->ui_renderer->render($form));
353 $this->error->raiseError($this->
lng->txt(
'no_permission'), $this->error->WARNING);
356 if ($a_form ===
null) {
358 if (count($job_ids) !== 1) {
359 $this->
ctrl->redirect($this,
'render');
362 $job_id = current($job_ids);
363 $job = $this->cron_repository->getJobInstanceById($job_id);
367 $this->tpl->setContent($a_form->getHTML());
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'),
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'),
386 return match ($schedule_type) {
387 JobScheduleType::IN_MINUTES =>
'smini',
388 JobScheduleType::IN_HOURS =>
'shri',
389 JobScheduleType::IN_DAYS =>
'sdyi',
392 'The passed argument %s is invalid!',
393 var_export($schedule_type,
true)
401 return in_array($schedule_type, [
402 JobScheduleType::IN_MINUTES,
403 JobScheduleType::IN_HOURS,
404 JobScheduleType::IN_DAYS
410 if (!($job instanceof
CronJob)) {
411 $this->
ctrl->redirect($this,
'render');
416 $jobs_data = $this->cron_repository->getCronJobData($job->
getId());
417 $job_data = $jobs_data[0];
419 $section_inputs = [];
421 $schedule_type_groups = [];
427 $schedule_type_inputs = [];
429 $schedule_value_input = $this->ui_factory
433 $this->
lng->txt(
'cron_schedule_value')
436 $this->
refinery->int()->isGreaterThanOrEqual(1)
438 )->withRequired(
true);
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']
447 $schedule_type_inputs = [
452 $schedule_type_groups[self::FORM_PARAM_SCHEDULE_PREFIX . $schedule_type->value] = $this->ui_factory
456 $schedule_type_inputs,
459 ->withDedicatedName(self::FORM_PARAM_SCHEDULE_PREFIX . $schedule_type->value);
464 $section_inputs[
'schedule'] = $this->ui_factory
468 $schedule_type_groups,
469 $this->
lng->txt(
'cron_schedule_type')
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']
479 $main_section = $this->ui_factory->input()->field()->section(
481 $this->
lng->txt(
'cron_action_edit') .
': "' . $job->
getTitle() .
'"' 485 self::FORM_PARAM_MAIN_SECTION => $main_section
492 self::FORM_PARAM_JOB_INPUT =>
502 return $this->ui_factory
506 ->standard($this->
ctrl->getFormAction($this,
'update'),
$inputs)
507 ->withDedicatedName(
'cron_form');
513 #[\Deprecated('Will be removed without any alternative, KS/UI forms will be expected', since: '13.0')] 516 if (!($job instanceof
CronJob)) {
517 $this->
ctrl->redirect($this,
'render');
522 $jobs_data = $this->cron_repository->getCronJobData($job->
getId());
523 $job_data = $jobs_data[0];
526 $form->setFormAction($this->
ctrl->getFormAction($this,
'updateLegacy'));
527 $form->setTitle($this->
lng->txt(
'cron_action_edit') .
': "' . $job->
getTitle() .
'"');
532 $type->setValue($job_data[
'schedule_type'] ===
null ?
null : (
string) $job_data[
'schedule_type']);
541 (
string) $schedule_type->value
543 $type->addOption($option);
547 $this->
lng->txt(
'cron_schedule_value'),
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']
559 $option->addSubItem($scheduleValue);
563 $form->addItem($type);
570 $form->addCommandButton(
'updateLegacy', $this->
lng->txt(
'save'));
571 $form->addCommandButton(
'render', $this->
lng->txt(
'cancel'));
579 $this->error->raiseError($this->
lng->txt(
'no_permission'), $this->error->WARNING);
584 $this->
ctrl->redirect($this,
'render');
587 $job = $this->cron_repository->getJobInstanceById($job_id);
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;
604 if ($job->hasFlexibleSchedule()) {
605 $schedule_group = $form_data[self::FORM_PARAM_MAIN_SECTION][self::FORM_PARAM_GROUP_SCHEDULE];
608 (
int) ltrim($schedule_group[0], self::FORM_PARAM_SCHEDULE_PREFIX)
611 $value = match (
true) {
618 $this->cron_repository->updateJobSchedule($job, $type, $value);
621 if ($job->hasCustomSettings()) {
622 $job->saveCustomConfiguration($form_data[self::FORM_PARAM_JOB_INPUT]);
625 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
'cron_action_edit_success'),
true);
626 $this->
ctrl->redirect($this,
'render');
635 #[\Deprecated('Will be removed without any alternative, KS/UI forms will be expected', since: '12.0')] 639 $this->error->raiseError($this->
lng->txt(
'no_permission'), $this->error->WARNING);
644 $this->
ctrl->redirect($this,
'render');
647 $job = $this->cron_repository->getJobInstanceById($job_id);
650 if ($job instanceof
CronJob && $form->checkInput()) {
652 if ($job->hasCustomSettings() && !$job->saveCustomSettings($form)) {
656 if (
$valid && $job->hasFlexibleSchedule()) {
658 $value = match (
true) {
660 $this->getScheduleValueFormElementName($type)
665 $this->cron_repository->updateJobSchedule($job, $type, $value);
669 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
'cron_action_edit_success'),
true);
670 $this->
ctrl->redirect($this,
'render');
674 $form->setValuesByPost();
678 public function run(): void
686 $this->error->raiseError($this->
lng->txt(
'no_permission'), $this->error->WARNING);
690 if (count($job_ids) !== 1) {
691 $this->
ctrl->redirect($this,
'render');
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);
698 $this->tpl->setOnScreenMessage(
'failure', $this->
lng->txt(
'cron_action_run_fail'),
true);
701 $this->
ctrl->redirect($this,
'render');
712 $this->error->raiseError($this->
lng->txt(
'no_permission'), $this->error->WARNING);
717 foreach ($jobs as $job) {
718 if ($this->cron_manager->isJobInactive($job->getId())) {
719 $this->cron_manager->resetJob($job, $this->actor);
723 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
'cron_action_activate_success'),
true);
725 $this->tpl->setOnScreenMessage(
'info', $this->
lng->txt(
'no_checkbox'),
true);
728 $this->
ctrl->redirect($this,
'render');
739 $this->error->raiseError($this->
lng->txt(
'no_permission'), $this->error->WARNING);
744 foreach ($jobs as $job) {
745 if ($this->cron_manager->isJobActive($job->getId())) {
746 $this->cron_manager->deactivateJob($job, $this->actor,
true);
750 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
'cron_action_deactivate_success'),
true);
752 $this->tpl->setOnScreenMessage(
'info', $this->
lng->txt(
'no_checkbox'),
true);
755 $this->
ctrl->redirect($this,
'render');
766 $this->error->raiseError($this->
lng->txt(
'no_permission'), $this->error->WARNING);
771 foreach ($jobs as $job) {
772 $this->cron_manager->resetJob($job, $this->actor);
774 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
'cron_action_reset_success'),
true);
776 $this->tpl->setOnScreenMessage(
'info', $this->
lng->txt(
'no_checkbox'),
true);
779 $this->
ctrl->redirect($this,
'render');
795 foreach ($job_ids as $job_id) {
796 $job = $this->cron_repository->getJobInstanceById($job_id);
798 $res[$job_id] = $job;
805 protected function confirm(
string $a_action): void
808 $this->error->raiseError($this->
lng->txt(
'no_permission'), $this->error->WARNING);
813 $this->tpl->setOnScreenMessage(
'info', $this->
lng->txt(
'no_checkbox'),
true);
814 $this->
ctrl->redirect($this,
'render');
817 if ($a_action ===
'run') {
818 $jobs = array_filter($jobs,
static function (
CronJob $job):
bool {
823 $this->tpl->setOnScreenMessage(
'failure', $this->
lng->txt(
'cron_no_executable_job_selected'),
true);
824 $this->
ctrl->redirect($this,
'render');
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();
836 $title = preg_replace(
'[^A-Za-z0-9_\-]',
'', $job->getId());
839 $cgui->setHeaderText(
841 $this->
lng->txt(
'cron_action_' . $a_action .
'_sure'),
848 $cgui->setHeaderText($this->
lng->txt(
'cron_action_' . $a_action .
'_sure_multi'));
850 foreach ($jobs as $job_id => $job) {
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));
859 $this->tpl->setContent($cgui->getHTML());
869 $data = $this->cron_repository->getCronJobData();
870 foreach (
$data as $item) {
871 $job = $this->cron_repository->getJobInstance(
877 $job->addToExternalSettingsForm($a_form_id, $fields, (
bool) $item[
'job_status']);
881 if ($fields !== []) {
890 return $form_elements;
hasScheduleValue(JobScheduleType $schedule_type)
This class represents an option in a radio group.
const array TABLE_ACTION_NAMESPACE
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="")
initEditForm(?CronJob $job)
readonly JobManager $cron_manager
const string TABLE_ACTION_IDENTIFIER_NAME
readonly ilGlobalTemplateInterface $tpl
readonly ilSetting $settings
readonly ilErrorHandling $error
readonly ilUIService $ui_service
const string FORM_PARAM_SCHEDULE_PREFIX
confirm(string $a_action)
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
readonly WrapperFactory $http_wrapper
getCustomConfigurationInput(\ILIAS\UI\Factory $ui_factory, \ILIAS\Refinery\Factory $factory, \ilLanguage $lng)
editLegacy(?ilPropertyFormGUI $a_form=null)
addCustomSettingsToForm(\ilPropertyFormGUI $a_form)
static http()
Fetches the global http state from ILIAS.
readonly ilObjUser $actor
readonly Factory $ui_factory
getScheduleValueFormElementName(JobScheduleType $schedule_type)
const FORM_PARAM_MAIN_SECTION
This is how the factory for UI elements looks.
readonly ILIAS DI RBACServices $rbac
readonly ILIAS HTTP GlobalHttpState $http
getValidScheduleTypes()
Returns a collection of all valid schedule types for a specific job.
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()
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
const string TABLE_ACTION_PARAM_NAME
getAllScheduleTypes()
Get all available schedule types.
addProblematicItemsInfo(\ILIAS\Cron\Job\JobCollection $filtered_jobs, \ILIAS\UI\Component\MessageBox\MessageBox $message, array $components)
getTableActionParameterName()
initLegacyEditForm(?CronJob $job)
const FORM_PARAM_JOB_INPUT
retrieveTableActionJobIds()
const FORM_PARAM_GROUP_SCHEDULE