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(
125 static function (
JobEntity $entity):
string {
128 $tableFilterMediator->filteredJobs(
139 return implode(
'_', array_merge(self::TABLE_ACTION_NAMESPACE, [self::TABLE_ACTION_PARAM_NAME]));
147 \
ILIAS\Cron\Job\JobCollection $filtered_jobs,
151 $problematic_jobs = $filtered_jobs->filter(
static function (
JobEntity $entity):
bool {
154 if (count($problematic_jobs) > 0) {
155 $problematic_jobs_info = $this->ui_factory->messageBox()->info(
156 $this->
lng->txt(
'cron_jobs_with_required_intervention')
160 return $this->ui_factory->link()->standard(
167 OrderedJobEntities::ORDER_BY_NAME
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)
179 array_unshift($components, $problematic_jobs_info);
188 return implode(
'_', array_merge(self::TABLE_ACTION_NAMESPACE, [self::TABLE_ACTION_IDENTIFIER_NAME]));
198 bool $force_retrieval =
false,
204 if ($force_retrieval || $this->http_wrapper->query()->has($key)) {
205 return $this->http_wrapper->query()->retrieve($key, $trafo);
212 if ($force_retrieval || $this->http_wrapper->post()->has($key)) {
213 return $this->http_wrapper->post()->retrieve($key, $trafo);
219 if ($force_retrieval && $exc) {
223 return $default ??
null;
229 $this->error->raiseError($this->
lng->txt(
'no_permission'), $this->error->WARNING);
232 $class = $this->
ctrl->getNextClass($this);
234 switch (strtolower($class)) {
235 case strtolower(ilPropertyFormGUI::class):
239 $this->
ctrl->forwardCommand($form);
243 $cmd = $this->
ctrl->getCmd(
'render');
249 $action = $this->http_wrapper->query()->retrieve(
252 $this->refinery->kindlyTo()->string(),
257 'run' => $this->
run(),
260 'reset' => $this->
reset(),
261 'edit' => $this->
edit(),
262 default => $this->
render()
268 $tstamp = $this->
lng->txt(
'cronjob_last_start_unknown');
269 if ($this->
settings->get(
'last_cronjob_start_ts')) {
272 $this->
settings->get(
'last_cronjob_start_ts'),
278 $message = $this->ui_factory->messageBox()->info($this->
lng->txt(
'cronjob_last_start') .
': ' . $tstamp);
280 $cronJobs = $this->cron_repository->findAll();
288 $filter = $tableFilterMediator->filter(
289 $this->
ctrl->getFormAction(
297 $filtered_jobs = $tableFilterMediator->filteredJobs(
303 'handleTableActions',
304 self::TABLE_ACTION_NAMESPACE,
305 self::TABLE_ACTION_PARAM_NAME,
306 self::TABLE_ACTION_IDENTIFIER_NAME,
308 $this->
http->request(),
316 $this->tpl->setContent(
317 $this->ui_renderer->render(
318 $this->addProblematicItemsInfo(
321 [
$message, $filter, $tbl->getComponent()]
330 $this->error->raiseError($this->
lng->txt(
'no_permission'), $this->error->WARNING);
333 if ($form ===
null) {
335 if (count($job_ids) !== 1) {
336 $this->
ctrl->redirect($this,
'render');
339 $job_id = current($job_ids);
340 $job = $this->cron_repository->getJobInstanceById($job_id);
341 if ($job && $job->usesLegacyForms()) {
343 $this->
ctrl->redirect($this,
'editLegacy');
349 $this->tpl->setContent($this->ui_renderer->render($form));
355 $this->error->raiseError($this->
lng->txt(
'no_permission'), $this->error->WARNING);
358 if ($a_form ===
null) {
360 if (count($job_ids) !== 1) {
361 $this->
ctrl->redirect($this,
'render');
364 $job_id = current($job_ids);
365 $job = $this->cron_repository->getJobInstanceById($job_id);
369 $this->tpl->setContent($a_form->getHTML());
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'),
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'),
388 return match ($schedule_type) {
389 JobScheduleType::IN_MINUTES =>
'smini',
390 JobScheduleType::IN_HOURS =>
'shri',
391 JobScheduleType::IN_DAYS =>
'sdyi',
394 'The passed argument %s is invalid!',
395 var_export($schedule_type,
true)
403 return in_array($schedule_type, [
404 JobScheduleType::IN_MINUTES,
405 JobScheduleType::IN_HOURS,
406 JobScheduleType::IN_DAYS
412 if (!($job instanceof
CronJob)) {
413 $this->
ctrl->redirect($this,
'render');
418 $jobs_data = $this->cron_repository->getCronJobData($job->
getId());
419 $job_data = $jobs_data[0];
421 $section_inputs = [];
423 $schedule_type_groups = [];
429 $schedule_type_inputs = [];
431 $schedule_value_input = $this->ui_factory
435 $this->
lng->txt(
'cron_schedule_value')
438 $this->
refinery->int()->isGreaterThanOrEqual(1)
440 )->withRequired(
true);
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']
449 $schedule_type_inputs = [
454 $schedule_type_groups[self::FORM_PARAM_SCHEDULE_PREFIX . $schedule_type->value] = $this->ui_factory
458 $schedule_type_inputs,
461 ->withDedicatedName(self::FORM_PARAM_SCHEDULE_PREFIX . $schedule_type->value);
466 $section_inputs[
'schedule'] = $this->ui_factory
470 $schedule_type_groups,
471 $this->
lng->txt(
'cron_schedule_type')
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']
481 $main_section = $this->ui_factory->input()->field()->section(
483 $this->
lng->txt(
'cron_action_edit') .
': "' . $job->
getTitle() .
'"' 487 self::FORM_PARAM_MAIN_SECTION => $main_section
494 self::FORM_PARAM_JOB_INPUT =>
504 return $this->ui_factory
508 ->standard($this->
ctrl->getFormAction($this,
'update'),
$inputs)
509 ->withDedicatedName(
'cron_form');
515 #[\Deprecated('Will be removed without any alternative, KS/UI forms will be expected', since: '13.0')] 518 if (!($job instanceof
CronJob)) {
519 $this->
ctrl->redirect($this,
'render');
524 $jobs_data = $this->cron_repository->getCronJobData($job->
getId());
525 $job_data = $jobs_data[0];
528 $form->setFormAction($this->
ctrl->getFormAction($this,
'updateLegacy'));
529 $form->setTitle($this->
lng->txt(
'cron_action_edit') .
': "' . $job->
getTitle() .
'"');
534 $type->setValue($job_data[
'schedule_type'] ===
null ?
null : (
string) $job_data[
'schedule_type']);
543 (
string) $schedule_type->value
545 $type->addOption($option);
549 $this->
lng->txt(
'cron_schedule_value'),
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']
561 $option->addSubItem($scheduleValue);
565 $form->addItem($type);
572 $form->addCommandButton(
'updateLegacy', $this->
lng->txt(
'save'));
573 $form->addCommandButton(
'render', $this->
lng->txt(
'cancel'));
581 $this->error->raiseError($this->
lng->txt(
'no_permission'), $this->error->WARNING);
586 $this->
ctrl->redirect($this,
'render');
589 $job = $this->cron_repository->getJobInstanceById($job_id);
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;
606 if ($job->hasFlexibleSchedule()) {
607 $schedule_group = $form_data[self::FORM_PARAM_MAIN_SECTION][self::FORM_PARAM_GROUP_SCHEDULE];
610 (
int) ltrim($schedule_group[0], self::FORM_PARAM_SCHEDULE_PREFIX)
613 $value = match (
true) {
620 $this->cron_repository->updateJobSchedule($job, $type, $value);
623 if ($job->hasCustomSettings()) {
624 $job->saveCustomConfiguration($form_data[self::FORM_PARAM_JOB_INPUT]);
627 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
'cron_action_edit_success'),
true);
628 $this->
ctrl->redirect($this,
'render');
637 #[\Deprecated('Will be removed without any alternative, KS/UI forms will be expected', since: '12.0')] 641 $this->error->raiseError($this->
lng->txt(
'no_permission'), $this->error->WARNING);
646 $this->
ctrl->redirect($this,
'render');
649 $job = $this->cron_repository->getJobInstanceById($job_id);
652 if ($job instanceof
CronJob && $form->checkInput()) {
654 if ($job->hasCustomSettings() && !$job->saveCustomSettings($form)) {
658 if (
$valid && $job->hasFlexibleSchedule()) {
660 $value = match (
true) {
662 $this->getScheduleValueFormElementName($type)
667 $this->cron_repository->updateJobSchedule($job, $type, $value);
671 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
'cron_action_edit_success'),
true);
672 $this->
ctrl->redirect($this,
'render');
676 $form->setValuesByPost();
680 public function run(): void
688 $this->error->raiseError($this->
lng->txt(
'no_permission'), $this->error->WARNING);
692 if (count($job_ids) !== 1) {
693 $this->
ctrl->redirect($this,
'render');
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);
700 $this->tpl->setOnScreenMessage(
'failure', $this->
lng->txt(
'cron_action_run_fail'),
true);
703 $this->
ctrl->redirect($this,
'render');
714 $this->error->raiseError($this->
lng->txt(
'no_permission'), $this->error->WARNING);
719 foreach ($jobs as $job) {
720 if ($this->cron_manager->isJobInactive($job->getId())) {
721 $this->cron_manager->resetJob($job, $this->actor);
725 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
'cron_action_activate_success'),
true);
727 $this->tpl->setOnScreenMessage(
'info', $this->
lng->txt(
'no_checkbox'),
true);
730 $this->
ctrl->redirect($this,
'render');
741 $this->error->raiseError($this->
lng->txt(
'no_permission'), $this->error->WARNING);
746 foreach ($jobs as $job) {
747 if ($this->cron_manager->isJobActive($job->getId())) {
748 $this->cron_manager->deactivateJob($job, $this->actor,
true);
752 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
'cron_action_deactivate_success'),
true);
754 $this->tpl->setOnScreenMessage(
'info', $this->
lng->txt(
'no_checkbox'),
true);
757 $this->
ctrl->redirect($this,
'render');
768 $this->error->raiseError($this->
lng->txt(
'no_permission'), $this->error->WARNING);
773 foreach ($jobs as $job) {
774 $this->cron_manager->resetJob($job, $this->actor);
776 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
'cron_action_reset_success'),
true);
778 $this->tpl->setOnScreenMessage(
'info', $this->
lng->txt(
'no_checkbox'),
true);
781 $this->
ctrl->redirect($this,
'render');
797 foreach ($job_ids as $job_id) {
798 $job = $this->cron_repository->getJobInstanceById($job_id);
800 $res[$job_id] = $job;
807 protected function confirm(
string $a_action): void
810 $this->error->raiseError($this->
lng->txt(
'no_permission'), $this->error->WARNING);
815 $this->tpl->setOnScreenMessage(
'info', $this->
lng->txt(
'no_checkbox'),
true);
816 $this->
ctrl->redirect($this,
'render');
819 if ($a_action ===
'run') {
820 $jobs = array_filter($jobs,
static function (
CronJob $job):
bool {
825 $this->tpl->setOnScreenMessage(
'failure', $this->
lng->txt(
'cron_no_executable_job_selected'),
true);
826 $this->
ctrl->redirect($this,
'render');
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();
838 $title = preg_replace(
'[^A-Za-z0-9_\-]',
'', $job->getId());
841 $cgui->setHeaderText(
843 $this->
lng->txt(
'cron_action_' . $a_action .
'_sure'),
850 $cgui->setHeaderText($this->
lng->txt(
'cron_action_' . $a_action .
'_sure_multi'));
852 foreach ($jobs as $job_id => $job) {
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));
861 $this->tpl->setContent($cgui->getHTML());
871 $data = $this->cron_repository->getCronJobData();
872 foreach (
$data as $item) {
873 $job = $this->cron_repository->getJobInstance(
879 $job->addToExternalSettingsForm($a_form_id, $fields, (
bool) $item[
'job_status']);
883 if ($fields !== []) {
892 return $form_elements;
hasScheduleValue(JobScheduleType $schedule_type)
This class represents an option in a radio group.
const TABLE_ACTION_PARAM_NAME
readonly ilCtrlInterface $ctrl
getScheduleTypeFormElementName(JobScheduleType $schedule_type)
const FORM_PARAM_SCHEDULE_PREFIX
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
readonly ilGlobalTemplateInterface $tpl
readonly ilSetting $settings
readonly ilErrorHandling $error
readonly ilUIService $ui_service
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
const TABLE_ACTION_IDENTIFIER_NAME
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,)
const TABLE_ACTION_NAMESPACE
ilCronManagerGUI: ilPropertyFormGUI ilCronManagerGUI: ilAdministrationGUI
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