ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
class.SettingsMainGUI.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
22 
41 
50 {
51  public const CMD_SHOW_FORM = 'showForm';
52  public const CMD_SAVE_FORM = 'saveForm';
53  public const CMD_CONFIRMED_SAVE_FORM = 'confirmedSaveForm';
54  public const CMD_SHOW_RESET_TPL_CONFIRM = 'showResetTemplateConfirmation';
55  public const CMD_CONFIRMED_RESET_TPL = 'confirmedResetTemplate';
56 
57  private const GENERAL_SETTINGS_SECTION_LABEL = 'general_settings';
58  private const AVAILABILITY_SETTINGS_SECTION_LABEL = 'availability settings';
59  private const PRESENTATION_SETTINGS_SECTION_LABEL = 'presentation_settings';
60  private const INTRODUCTION_SETTINGS_SECTION_LABEL = 'introduction_settings';
61  private const ACCESS_SETTINGS_LABEL = 'access_settings';
62  private const TEST_BEHAVIOUR_SETTINGS_LABEL = 'test_behaviour_settings';
63  private const QUESTION_BEHAVIOUR_SETTINGS_LABEL = 'question_behaviour_settings';
64  private const PARTICIPANTS_FUNCTIONALITY_SETTINGS_LABEL = 'participants_functionality_settings';
65  private const FINISH_TEST_SETTINGS_LABEL = 'finish_test_settings';
66  private const ECS_FUNCTIONALITY_SETTINGS_LABEL = 'ecs_settings';
67  private const ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL = 'additional_functionality_settings';
68 
72 
73  private \ilTestQuestionSetConfigFactory $testQuestionSetConfigFactory;
74 
75  public function __construct(
76  private readonly \ilGlobalTemplateInterface $tpl,
77  private readonly \ilToolbarGUI $toolbar,
78  private readonly \ilCtrlInterface $ctrl,
79  private readonly \ilAccessHandler $access,
80  private readonly \ilLanguage $lng,
81  private readonly \ilTree $tree,
82  private readonly \ilDBInterface $db,
83  private readonly \ilObjectDataCache $object_data_cache,
84  private readonly \ilSetting $settings,
85  private readonly UIFactory $ui_factory,
86  private readonly UIRenderer $ui_renderer,
87  private readonly Refinery $refinery,
88  private readonly ServerRequestInterface $request,
89  private readonly \ilComponentRepository $component_repository,
90  private readonly \ilObjUser $active_user,
91  private readonly \ilObjTestGUI $test_gui,
92  private readonly TestLogger $logger,
93  private readonly GeneralQuestionPropertiesRepository $questionrepository
94  ) {
95  $this->object_properties = $this->test_gui->getTestObject()->getObjectProperties();
96  $this->main_settings = $this->test_gui->getTestObject()->getMainSettings();
97  $this->main_settings_repository = $this->test_gui->getTestObject()->getMainSettingsRepository();
98  $this->testQuestionSetConfigFactory = new \ilTestQuestionSetConfigFactory(
99  $this->tree,
100  $this->db,
101  $this->lng,
102  $this->logger,
103  $this->component_repository,
104  $this->test_gui->getTestObject(),
105  $this->questionrepository
106  );
107 
108  $this->lng->loadLanguageModule('validation');
109  $this->lng->loadLanguageModule('rep');
110 
111  parent::__construct($this->test_gui->getTestObject());
112  }
113 
117  public function executeCommand()
118  {
119  if (!$this->access->checkAccess('write', '', $this->test_gui->getRefId())) {
120  $this->tpl->setOnScreenMessage('info', $this->lng->txt('cannot_edit_test'), true);
121  $this->ctrl->redirectByClass([\ilRepositoryGUI::class, \ilObjTestGUI::class, \ilInfoScreenGUI::class]);
122  }
123 
124  $cmd = $this->ctrl->getCmd(self::CMD_SHOW_FORM);
125  $this->$cmd();
126 
127  $this->object_data_cache->deleteCachedEntry($this->test_object->getId());
128  }
129 
130  private function showOldIntroduction(): void
131  {
132  $this->toolbar->addComponent(
133  $this->ui_factory->link()->standard(
134  $this->lng->txt('back'),
135  $this->ctrl->getLinkTargetByClass(self::class, 'showForm')
136  )
137  );
138 
139  $this->tpl->setContent(
140  $this->main_settings->getIntroductionSettings()->getIntroductionText()
141  );
142  }
143 
144  private function showOldConcludingRemarks(): void
145  {
146  $this->toolbar->addComponent(
147  $this->ui_factory->link()->standard(
148  $this->lng->txt('back'),
149  $this->ctrl->getLinkTargetByClass(self::class, 'showForm')
150  )
151  );
152 
153  $this->tpl->setContent(
154  $this->main_settings->getFinishingSettings()->getConcludingRemarksText()
155  );
156  }
157 
158  private function showForm(?StandardForm $form = null, ?InterruptiveModal $modal = null): void
159  {
160  if ($form === null) {
161  $form = $this->buildForm();
162  }
163 
164  if ($this->main_settings->getIntroductionSettings()->getIntroductionText() !== '') {
165  $this->toolbar->addComponent(
166  $this->ui_factory->link()->standard(
167  $this->lng->txt('show_old_introduction'),
168  $this->ctrl->getLinkTargetByClass(self::class, 'showOldIntroduction')
169  )
170  );
171  }
172 
173  if ($this->main_settings->getFinishingSettings()->getConcludingRemarksText() !== '') {
174  $this->toolbar->addComponent(
175  $this->ui_factory->link()->standard(
176  $this->lng->txt('show_old_concluding_remarks'),
177  $this->ctrl->getLinkTargetByClass(self::class, 'showOldConcludingRemarks')
178  )
179  );
180  }
181 
182  $rendered_modal = '';
183  if ($modal !== null) {
184  $rendered_modal = $this->ui_renderer->render($modal);
185  }
186 
187  $this->tpl->setContent($this->ui_renderer->render($form) . $rendered_modal);
188  }
189 
190  private function confirmedSaveForm(): void
191  {
192  $form = $this->buildForm()->withRequest($this->request);
193  $data = $form->getData();
194  if ($data === null) {
195  $this->showForm($form);
196  return;
197  }
198 
199  $current_question_set_type = $this->main_settings->getGeneralSettings()->getQuestionSetType();
200  $current_question_config = $this->testQuestionSetConfigFactory->getQuestionSetConfig();
201  $new_question_set_type = $data[self::GENERAL_SETTINGS_SECTION_LABEL]['question_set_type'];
202 
203  if ($new_question_set_type !== $current_question_set_type
204  && $current_question_config->doesQuestionSetRelatedDataExist()) {
205  $data[self::AVAILABILITY_SETTINGS_SECTION_LABEL]['is_online'] =
206  $this->test_object->getObjectProperties()->getPropertyIsOnline()->withOffline();
207  $this->testQuestionSetConfigFactory->getQuestionSetConfig()->removeQuestionSetRelatedData();
208  }
209 
210  if ($this->anonymityChanged($data[self::GENERAL_SETTINGS_SECTION_LABEL]['anonymity'])) {
211  $this->logger->deleteParticipantInteractionsForTest($this->test_object->getRefId());
212  }
213 
214  $this->finalizeSave($data);
215  }
216 
217 
218  private function saveForm(): void
219  {
220  $form = $this->buildForm()->withRequest($this->request);
221  $data = $form->getData();
222  if ($data === null) {
223  $this->showForm($form);
224  return;
225  }
226 
227  $current_question_set_type = $this->main_settings->getGeneralSettings()->getQuestionSetType();
228  $current_question_config = $this->testQuestionSetConfigFactory->getQuestionSetConfig();
229  $new_question_set_type = $data[self::GENERAL_SETTINGS_SECTION_LABEL]['question_set_type'];
230 
231  $question_set_modal_required = $new_question_set_type !== $current_question_set_type
232  && $current_question_config->doesQuestionSetRelatedDataExist();
233  $anonymity_modal_required = $this->anonymityChanged(
234  $data[self::GENERAL_SETTINGS_SECTION_LABEL]['anonymity']
235  );
236 
237  if ($question_set_modal_required || $anonymity_modal_required) {
238  $modal = $this->populateConfirmationModal(
239  $question_set_modal_required ? $current_question_set_type : null,
240  $question_set_modal_required ? $new_question_set_type : null,
241  $anonymity_modal_required
242  );
243  $this->showForm($form, $modal);
244  return;
245  }
246 
247  $this->finalizeSave($data);
248  }
249 
250  private function finalizeSave(array $data): void
251  {
252  $this->performSaveForm($data);
253  $additional_information = $this->getObjectDataArrayForLog()
254  + $this->main_settings->getArrayForLog($this->logger->getAdditionalInformationGenerator());
255  if ($this->logger->isLoggingEnabled()) {
256  $this->logger->logTestAdministrationInteraction(
257  $this->logger->getInteractionFactory()->buildTestAdministrationInteraction(
258  $this->test_object->getRefId(),
259  $this->active_user->getId(),
260  TestAdministrationInteractionTypes::MAIN_SETTINGS_MODIFIED,
261  $additional_information
262  )
263  );
264  }
265 
266  $this->tpl->setOnScreenMessage('success', $this->lng->txt('msg_obj_modified'), true);
267  $this->showForm();
268  }
269 
270  private function anonymityChanged(bool $anonymity_form_data): bool
271  {
272  return $this->main_settings->getGeneralSettings()->getAnonymity() === false
273  && $anonymity_form_data === true
274  && $this->logger->testHasParticipantInteractions($this->test_object->getRefId());
275  }
276 
277  private function getObjectDataArrayForLog(): array
278  {
279  $title_and_description = $this->object_properties->getPropertyTitleAndDescription();
280  $log_array = [
281  AdditionalInformationGenerator::KEY_TEST_TITLE => $title_and_description->getTitle(),
282  AdditionalInformationGenerator::KEY_TEST_DESCRIPTION => $title_and_description->getDescription(),
284  ->getAdditionalInformationGenerator()->getTrueFalseTagForBool(
285  $this->object_properties->getPropertyIsOnline()->getIsOnline()
286  )
287  ];
288 
289  if (!$this->test_object->isActivationLimited()) {
291  ->getAdditionalInformationGenerator()->getEnabledDisabledTagForBool(false);
292  return $log_array;
293  }
294 
295  $none_tag = $this->logger->getAdditionalInformationGenerator()->getNoneTag();
296  $from = $this->test_object->getActivationStartingTime() === null
297  ? $none_tag
298  : \DateTimeImmutable::createFromFormat('U', (string) $this->test_object->getActivationStartingTime())
300  $until = $this->test_object->getActivationEndingTime() === null
301  ? $none_tag
302  : \DateTimeImmutable::createFromFormat('U', (string) $this->test_object->getActivationEndingTime())
304 
308  ];
310  ->getAdditionalInformationGenerator()->getEnabledDisabledTagForBool(
311  $this->test_object->getActivationVisibility()
312  );
313  return $log_array;
314  }
315 
316  private function buildForm(): StandardForm
317  {
318  $lng = $this->lng;
319  $input_factory = $this->ui_factory->input();
321 
322  $environment['participant_data_exists'] = $this->test_object->participantDataExist();
323  $environment['user_date_format'] = $this->active_user->getDateTimeFormat();
324  $environment['user_time_zone'] = $this->active_user->getTimeZone();
325 
326  $main_inputs = [
327  self::GENERAL_SETTINGS_SECTION_LABEL => $this->getGeneralSettingsSection($environment),
328  self::AVAILABILITY_SETTINGS_SECTION_LABEL => $this->getAvailabilitySettingsSection(),
329  self::PRESENTATION_SETTINGS_SECTION_LABEL => $this->getPresentationSettingsSection(),
330  self::INTRODUCTION_SETTINGS_SECTION_LABEL => $this->main_settings->getIntroductionSettings()
331  ->toForm($lng, $input_factory->field(), $refinery),
332  self::ACCESS_SETTINGS_LABEL => $this->main_settings->getAccessSettings()
333  ->toForm($lng, $input_factory->field(), $refinery, $environment),
334  self::TEST_BEHAVIOUR_SETTINGS_LABEL => $this->main_settings->getTestBehaviourSettings()
335  ->toForm($lng, $input_factory->field(), $refinery, $environment),
336  self::QUESTION_BEHAVIOUR_SETTINGS_LABEL => $this->main_settings->getQuestionBehaviourSettings()
337  ->toForm($lng, $input_factory->field(), $refinery, $environment),
338  self::PARTICIPANTS_FUNCTIONALITY_SETTINGS_LABEL => $this->main_settings->getParticipantFunctionalitySettings()
339  ->toForm($lng, $input_factory->field(), $refinery, $environment),
340  self::FINISH_TEST_SETTINGS_LABEL => $this->main_settings->getFinishingSettings()
341  ->toForm($lng, $input_factory->field(), $refinery)
342  ];
343 
344  $inputs = array_merge($main_inputs, $this->getAdditionalFunctionalitySettingsSections($environment));
345 
346  return $input_factory->container()->form()->standard(
347  $this->ctrl->getFormActionByClass(self::class, self::CMD_SAVE_FORM),
348  $inputs
350  }
351 
352  private function getFormConstraints(): Constraint
353  {
354  return $this->refinery->custom()->constraint(
355  function (array $vs): bool {
356  if ($vs[self::PARTICIPANTS_FUNCTIONALITY_SETTINGS_LABEL]['postponed_questions_behaviour'] === true
357  && $vs[self::QUESTION_BEHAVIOUR_SETTINGS_LABEL]['lock_answers']['lock_answer_on_next_question']) {
358  return false;
359  }
360  return true;
361  },
362  $this->lng->txt('tst_settings_conflict_postpone_and_lock')
363  );
364  }
365 
366  private function populateConfirmationModal(
367  ?string $current_question_set_type,
368  ?string $new_question_set_type,
369  bool $anonymity_modal_required
370  ): InterruptiveModal {
371  $message = '';
372 
373  if ($current_question_set_type !== null) {
374  $message .= sprintf(
375  $this->lng->txt('tst_change_quest_set_type_from_old_to_new_with_conflict'),
376  $this->test_object->getQuestionSetTypeTranslation($this->lng, $current_question_set_type),
377  $this->test_object->getQuestionSetTypeTranslation($this->lng, $new_question_set_type)
378  );
379  }
380 
381  if ($current_question_set_type === \ilObjTest::QUESTION_SET_TYPE_FIXED
382  && $this->test_object->hasQuestionsWithoutQuestionpool()) {
383  $message .= '<br /><br />' . $this->lng->txt('tst_nonpool_questions_get_lost_warning');
384  }
385 
386  if ($anonymity_modal_required) {
387  if ($message !== '') {
388  $message .= '<br /><br />';
389  }
390  $message .= $this->lng->txt('log_participant_data_delete_warning');
391  }
392 
393  $this->tpl->addJavaScript('assets/js/settings_confirmation.js');
394  $on_load_code = static function (string $id): string {
395  return 'il.test.confirmSettings.init(' . $id . ')';
396  };
397 
398  $modal = $this->ui_factory->modal()->interruptive(
399  $this->lng->txt('confirm'),
400  $message,
401  $this->ctrl->getFormActionByClass(self::class, self::CMD_CONFIRMED_SAVE_FORM)
402  )->withActionButtonLabel($this->lng->txt('confirm'))
403  ->withAdditionalOnLoadCode($on_load_code);
404 
405  return $modal->withOnLoad($modal->getShowSignal());
406  }
407 
408  private function performSaveForm(array $data)
409  {
410  $old_online_status = $this->test_object->getObjectProperties()->getPropertyIsOnline()->getIsOnline();
411  $this->test_object->getObjectProperties()->storePropertyTitleAndDescription(
412  $data[self::GENERAL_SETTINGS_SECTION_LABEL]['title_and_description']
413  );
414  $general_settings = $this->getGeneralSettingsForStorage($data[self::GENERAL_SETTINGS_SECTION_LABEL]);
415 
416  $this->saveAvailabilitySettingsSection($data[self::AVAILABILITY_SETTINGS_SECTION_LABEL]);
417  $this->savePresentationSettingsSection($data[self::PRESENTATION_SETTINGS_SECTION_LABEL]);
418 
419  $introduction_settings = $this->getIntroductionSettingsForStorage(
420  $data[self::INTRODUCTION_SETTINGS_SECTION_LABEL]
421  );
422  $access_settings = $this->getAccessSettingsForStorage(
423  $data[self::ACCESS_SETTINGS_LABEL]
424  );
425  $test_behaviour_settings = $this->getTestBehaviourSettingsForStorage(
426  $data[self::TEST_BEHAVIOUR_SETTINGS_LABEL]
427  );
428  $question_behaviour_settings = $this->getQuestionBehaviourSettingsForStorage(
429  $data[self::QUESTION_BEHAVIOUR_SETTINGS_LABEL]
430  );
431  $participant_functionality_settings = $this->getParticipantsFunctionalitySettingsForStorage(
432  $data[self::PARTICIPANTS_FUNCTIONALITY_SETTINGS_LABEL]
433  );
434 
435  $finishing_settings = $this->getFinishingSettingsForStorage($data[self::FINISH_TEST_SETTINGS_LABEL]);
436 
437  if (array_key_exists(self::ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL, $data)
438  || array_key_exists(self::ECS_FUNCTIONALITY_SETTINGS_LABEL, $data)) {
440  }
441 
442  $additional_settings = $this->getAdditionalFunctionalitySettingsForStorage(
443  $data[self::ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL] ?? []
444  );
445 
446  $settings = new MainSettings(
447  $this->test_object->getTestId(),
448  $this->test_object->getId(),
449  $general_settings,
450  $introduction_settings,
451  $access_settings,
452  $test_behaviour_settings,
453  $question_behaviour_settings,
454  $participant_functionality_settings,
455  $finishing_settings,
456  $additional_settings
457  );
458  $this->main_settings_repository->store($settings);
459  $this->main_settings = $this->main_settings_repository->getFor($this->test_object->getTestId());
460  $this->test_object->read();
461  $this->test_object->addToNewsOnOnline(
462  $old_online_status,
463  $this->test_object->getObjectProperties()->getPropertyIsOnline()->getIsOnline()
464  );
465  }
466 
467  private function getGeneralSettingsSection(array $environment): Section
468  {
469  $field_factory = $this->ui_factory->input()->field();
470 
471  $inputs['title_and_description'] = $this->test_object->getObjectProperties()->getPropertyTitleAndDescription()
472  ->toForm($this->lng, $field_factory, $this->refinery);
473  $inputs += $this->main_settings->getGeneralSettings()
474  ->toForm($this->lng, $field_factory, $this->refinery, $environment);
475 
476  return $field_factory->section(
477  $inputs,
478  $this->lng->txt('tst_general_properties')
479  );
480  }
481 
485  private function getGeneralSettingsForStorage(array $section): SettingsGeneral
486  {
487  if ($this->test_object->participantDataExist()) {
488  return $this->main_settings->getGeneralSettings();
489  }
490 
491  return $this->main_settings->getGeneralSettings()
492  ->withQuestionSetType($section['question_set_type'])
493  ->withAnonymity($section['anonymity']);
494  }
495 
497  {
498  $input_factory = $this->ui_factory->input();
499 
500  $inputs['is_online'] = $this->getIsOnlineSettingInput();
501  $inputs['timebased_availability'] = $this->getTimebasedAvailabilityInputs();
502 
503  return $input_factory->field()->section(
504  $inputs,
505  $this->lng->txt('rep_activation_availability')
506  );
507  }
508 
509  private function getIsOnlineSettingInput(): Checkbox
510  {
511  $field_factory = $this->ui_factory->input()->field();
512 
513  $question_set_config_complete = $this->test_object->isComplete(
514  $this->testQuestionSetConfigFactory->getQuestionSetConfig()
515  );
516 
517  $is_online = $this->test_object->getObjectProperties()->getPropertyIsOnline()
518  ->toForm($this->lng, $field_factory, $this->refinery);
519 
520  if (sizeof(\ilObject::_getAllReferences($this->test_object->getId())) > 1) {
521  $is_online = $is_online->withByline(
522  $is_online->getByline() . ' ' . $this->lng->txt('rep_activation_online_object_info')
523  );
524  }
525 
526  if (!$question_set_config_complete) {
527  $is_online = $is_online
528  ->withByline($this->lng->txt('cannot_switch_to_online_no_questions_andor_no_mark_steps'))
529  ->withDisabled(true);
530  }
531 
532  return $is_online;
533  }
534 
536  {
537  $field_factory = $this->ui_factory->input()->field();
538 
541 
542  $inputs['time_span'] = $field_factory->duration($this->lng->txt('rep_time_period'))
543  ->withTimezone($this->active_user->getTimeZone())
544  ->withFormat($this->active_user->getDateTimeFormat())
545  ->withUseTime(true)
546  ->withRequired(true);
547  $inputs['activation_visibility'] = $field_factory->checkbox(
548  $this->lng->txt('rep_activation_limited_visibility'),
549  $this->lng->txt('tst_activation_limited_visibility_info')
550  );
551 
552  return $field_factory->optionalGroup(
553  $inputs,
554  $this->lng->txt('rep_time_based_availability')
556  ->withValue($value);
557  }
558 
560  {
561  return $this->refinery->custom()->transformation(
562  static function (?array $vs): array {
563  if ($vs === null) {
564  return [
565  'is_activation_limited' => false,
566  'activation_starting_time' => null,
567  'activation_ending_time' => null,
568  'activation_visibility' => false
569  ];
570  }
571 
572  $start = $vs['time_span']['start']->getTimestamp();
573  $end = $vs['time_span']['end']->getTimestamp();
574 
575  return [
576  'is_activation_limited' => true,
577  'activation_starting_time' => $start,
578  'activation_ending_time' => $end,
579  'activation_visibility' => $vs['activation_visibility']
580  ];
581  }
582  );
583  }
584 
585  private function getValueForActivationLimitedOptionalGroup(): ?array
586  {
587  $value = null;
588  if ($this->test_object->isActivationLimited()) {
589  $value = [
590  'time_span' => [
591  \DateTimeImmutable::createFromFormat(
592  'U',
593  (string) $this->test_object->getActivationStartingTime()
594  )->setTimezone(new \DateTimeZone($this->active_user->getTimeZone())),
595  \DateTimeImmutable::createFromFormat(
596  'U',
597  (string) $this->test_object->getActivationEndingTime()
598  )->setTimezone(new \DateTimeZone($this->active_user->getTimeZone())),
599  ],
600  'activation_visibility' => $this->test_object->getActivationVisibility()
601  ];
602  }
603  return $value;
604  }
605 
606  private function saveAvailabilitySettingsSection(array $section): void
607  {
608  $time_based_availability = $section['timebased_availability'];
609 
610  $participant_data_exists = $this->test_object->participantDataExist();
611  $this->test_object->storeActivationSettings(
612  $participant_data_exists
613  ? $this->test_object->isActivationLimited()
614  : $time_based_availability['is_activation_limited'],
615  $participant_data_exists
616  ? $this->test_object->getActivationStartingTime()
617  : $time_based_availability['activation_starting_time'],
618  $time_based_availability['activation_ending_time'],
619  $time_based_availability['activation_visibility']
620  );
621  $this->test_object->getObjectProperties()->storePropertyIsOnline($section['is_online']);
622  }
623 
625  {
626  $input_factory = $this->ui_factory->input();
627 
628  $custom_icon_input = $this->test_object->getObjectProperties()->getPropertyIcon()
629  ->toForm($this->lng, $input_factory->field(), $this->refinery);
630 
631  if ($custom_icon_input !== null) {
632  $inputs['custom_icon'] = $custom_icon_input;
633  }
634  $inputs['tile_image'] = $this->test_object->getObjectProperties()->getPropertyTileImage()
635  ->toForm($this->lng, $input_factory->field(), $this->refinery);
636 
637  return $input_factory->field()->section(
638  $inputs,
639  $this->lng->txt('tst_presentation_settings_section')
640  );
641  }
642 
643  protected function savePresentationSettingsSection(array $section): void
644  {
645  if (array_key_exists('custom_icon', $section)) {
646  $this->test_object->getObjectProperties()->storePropertyIcon($section['custom_icon']);
647  }
648  $this->test_object->getObjectProperties()->storePropertyTileImage($section['tile_image']);
649  }
650 
651  private function getIntroductionSettingsForStorage(array $section): SettingsIntroduction
652  {
653  return $this->main_settings->getIntroductionSettings()
654  ->withIntroductionEnabled($section['introduction_enabled'])
655  ->withExamConditionsCheckboxEnabled($section['conditions_checkbox_enabled']);
656  }
657 
658  private function getAccessSettingsForStorage(array $section): SettingsAccess
659  {
660  $access_settings = $this->main_settings->getAccessSettings()
661  ->withStartTimeEnabled($section['access_window']['start_time_enabled'])
662  ->withStartTime($section['access_window']['start_time'])
663  ->withEndTimeEnabled($section['access_window']['end_time_enabled'])
664  ->withEndTime($section['access_window']['end_time'])
665  ->withPasswordEnabled($section['test_password']['password_enabled'])
666  ->withPassword($section['test_password']['password_value'])
667  ->withIpRangeFrom($section['ip_range']['ip_range_from'])
668  ->withIpRangeTo($section['ip_range']['ip_range_to'])
669  ->withFixedParticipants($section['fixed_participants_enabled']);
670 
671  if ($this->test_object->participantDataExist()) {
672  return $access_settings;
673  }
674 
675  return $access_settings->withStartTimeEnabled($section['access_window']['start_time_enabled'])
676  ->withStartTime($section['access_window']['start_time']);
677  }
678 
680  {
681  $test_behaviour_settings = $this->main_settings->getTestBehaviourSettings()
682  ->withKioskMode($section['kiosk_mode'])
683  ->withExamIdInTestAttemptEnabled($section['show_exam_id']);
684 
685  if ($this->test_object->participantDataExist()) {
686  return $test_behaviour_settings;
687  }
688 
689  return $test_behaviour_settings
690  ->withNumberOfTries($section['limit_attempts']['number_of_available_attempts'])
691  ->withBlockAfterPassedEnabled($section['limit_attempts']['block_after_passed'])
692  ->withPassWaiting($section['force_waiting_between_attempts'])
693  ->withProcessingTimeEnabled($section['time_limit_for_completion']['processing_time_limit'])
694  ->withProcessingTime($section['time_limit_for_completion']['time_limit_for_completion_value'])
695  ->withResetProcessingTime($section['time_limit_for_completion']['reset_time_limit_for_completion_by_attempt']);
696  }
697 
699  {
700  $question_behaviour_settings = $this->main_settings->getQuestionBehaviourSettings()
701  ->withQuestionTitleOutputMode($section['title_output'])
702  ->withAutosaveEnabled($section['autosave']['autosave_enabled'])
703  ->withAutosaveInterval($section['autosave']['autosave_interval'])
704  ->withShuffleQuestions($section['shuffle_questions']);
705 
706  if ($this->test_object->participantDataExist()) {
707  return $question_behaviour_settings;
708  }
709 
710  return $question_behaviour_settings
711  ->withInstantFeedbackPointsEnabled($section['instant_feedback']['enabled_feedback_types']['instant_feedback_points'])
712  ->withInstantFeedbackGenericEnabled($section['instant_feedback']['enabled_feedback_types']['instant_feedback_generic'])
713  ->withInstantFeedbackSpecificEnabled($section['instant_feedback']['enabled_feedback_types']['instant_feedback_specific'])
714  ->withInstantFeedbackSolutionEnabled($section['instant_feedback']['enabled_feedback_types']['instant_feedback_solution'])
715  ->withForceInstantFeedbackOnNextQuestion($section['instant_feedback']['feedback_on_next_question'])
716  ->withLockAnswerOnInstantFeedbackEnabled($section['lock_answers']['lock_answer_on_instant_feedback'])
717  ->withLockAnswerOnNextQuestionEnabled($section['lock_answers']['lock_answer_on_next_question']);
718  }
719 
720 
722  {
723  return $this->main_settings->getParticipantFunctionalitySettings()
724  ->withUsePreviousAnswerAllowed($section['use_previous_answers'])
725  ->withSuspendTestAllowed($section['allow_suspend_test'])
726  ->withPostponedQuestionsMoveToEnd($section['postponed_questions_behaviour'])
727  ->withUsrPassOverviewMode($section['usr_pass_overview'])
728  ->withQuestionMarkingEnabled($section['enable_question_marking'])
729  ->withQuestionListEnabled($section['enable_question_list']);
730  }
731 
732  private function getFinishingSettingsForStorage(array $section): SettingsFinishing
733  {
734  $redirect_after_finish = $section['redirect_after_finish'];
735  $finish_notification = $section['finish_notification'];
736  return $this->main_settings->getFinishingSettings()
737  ->withShowAnswerOverview($section['show_answer_overview'])
738  ->withConcludingRemarksEnabled($section['show_concluding_remarks'])
739  ->withRedirectionMode($redirect_after_finish['redirect_mode'])
740  ->withRedirectionUrl($redirect_after_finish['redirect_url'])
741  ->withMailNotificationContentType($finish_notification['notification_content_type'])
742  ->withAlwaysSendMailNotification($finish_notification['always_notify']);
743  }
744 
745  protected function getAdditionalFunctionalitySettingsSections(array $environment): array
746  {
747  $sections = [];
748 
749  $ecs = new \ilECSTestSettings($this->test_object);
750  $ecs_section = $ecs->getSettingsSection(
751  $this->ui_factory->input()->field(),
753  );
754 
755  if ($ecs_section !== null) {
756  $sections[self::ECS_FUNCTIONALITY_SETTINGS_LABEL] = $ecs_section;
757  }
758 
759  $inputs['organisational_units_activation'] = $this->getOrganisationalUnitsActivationInput();
760 
761  $inputs += $this->main_settings->getAdditionalSettings()->toForm(
762  $this->lng,
763  $this->ui_factory->input()->field(),
765  $environment
766  );
767 
768  $inputs = array_filter($inputs, fn($v) => $v !== null);
769 
770  if (count($inputs) > 0) {
771  $sections[self::ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL] = $this->ui_factory->input()->field()
772  ->section($inputs, $this->lng->txt('obj_features'));
773  }
774 
775  return $sections;
776  }
777 
779  {
780  $position_settings = \ilOrgUnitGlobalSettings::getInstance()->getObjectPositionSettingsByType(
781  $this->test_object->getType()
782  );
783  if (!$position_settings->isActive()) {
784  return null;
785  }
786 
787  $enable_organisational_units_access = $this->ui_factory->input()->field()
788  ->checkbox(
789  $this->lng->txt('obj_orgunit_positions'),
790  $this->lng->txt('obj_orgunit_positions_info')
791  )->withValue(
792  (new \ilOrgUnitObjectPositionSetting($this->test_object->getId()))->isActive()
793  ?? $position_settings->getActivationDefault() === \ilOrgUnitObjectTypePositionSetting::DEFAULT_ON
794  );
795  if (!$position_settings->isChangeableForObject()) {
796  return $enable_organisational_units_access->withDisabled(true);
797  }
798  return $enable_organisational_units_access;
799  }
800 
801  protected function saveAdditionalFunctionalitySettingsSection(array $sections): void
802  {
803  if (array_key_exists(self::ECS_FUNCTIONALITY_SETTINGS_LABEL, $sections)) {
804  $ecs = new \ilECSTestSettings($this->test_object);
805  $ecs->saveSettingsSection($sections[self::ECS_FUNCTIONALITY_SETTINGS_LABEL]);
806  }
807 
808  if (!array_key_exists(self::ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL, $sections)) {
809  return;
810  }
811 
812  $additional_settings_section = $sections[self::ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL];
813  if (array_key_exists('organisational_units_activation', $additional_settings_section)) {
814  $this->saveOrganisationalUnitsActivation($additional_settings_section['organisational_units_activation']);
815  }
816  }
817 
818  protected function saveOrganisationalUnitsActivation(bool $activation): void
819  {
820  $position_settings = \ilOrgUnitGlobalSettings::getInstance()->getObjectPositionSettingsByType(
821  $this->test_object->getType()
822  );
823 
824  if ($position_settings->isActive() && $position_settings->isChangeableForObject()) {
825  $orgu_object_settings = new \ilOrgUnitObjectPositionSetting($this->test_object->getId());
826  $orgu_object_settings->setActive(
827  $activation
828  );
829  $orgu_object_settings->update();
830  }
831  }
832 
834  {
835  $additional_settings = $this->main_settings->getAdditionalSettings()->withHideInfoTab($section['hide_info_tab']);
836 
837  if ($this->test_object->participantDataExist()) {
838  return $additional_settings;
839  }
840 
841  if (!(new \ilSkillManagementSettings())->isActivated()) {
842  return $additional_settings->withSkillsServiceEnabled(false);
843  }
844 
845  return $additional_settings->withSkillsServiceEnabled($section['skills_service_activation']);
846  }
847 }
withByline(string $byline)
Get an input like this, but with an additional/replaced label.
Readable part of repository interface to ilComponentDataDB.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
__construct(private readonly \ilGlobalTemplateInterface $tpl, private readonly \ilToolbarGUI $toolbar, private readonly \ilCtrlInterface $ctrl, private readonly \ilAccessHandler $access, private readonly \ilLanguage $lng, private readonly \ilTree $tree, private readonly \ilDBInterface $db, private readonly \ilObjectDataCache $object_data_cache, private readonly \ilSetting $settings, private readonly UIFactory $ui_factory, private readonly UIRenderer $ui_renderer, private readonly Refinery $refinery, private readonly ServerRequestInterface $request, private readonly \ilComponentRepository $component_repository, private readonly \ilObjUser $active_user, private readonly \ilObjTestGUI $test_gui, private readonly TestLogger $logger, private readonly GeneralQuestionPropertiesRepository $questionrepository)
static _getAllReferences(int $id)
get all reference ids for object ID
A constraint encodes some resrtictions on values.
Definition: Constraint.php:31
This describes optional group inputs.
populateConfirmationModal(?string $current_question_set_type, ?string $new_question_set_type, bool $anonymity_modal_required)
This describes checkbox inputs.
Definition: Checkbox.php:28
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
showForm(?StandardForm $form=null, ?InterruptiveModal $modal=null)
withValue($value)
Get an input like this with another value displayed on the client side.
Definition: Group.php:61
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
__construct(Container $dic, ilPlugin $plugin)
global $lng
Definition: privfeed.php:31
const QUESTION_SET_TYPE_FIXED
$message
Definition: xapiexit.php:31
ilTestQuestionSetConfigFactory $testQuestionSetConfigFactory
ILIAS: ilPropertyFormGUI ILIAS: ilConfirmationGUI ILIAS: ilTestSettingsChangeConfirmationGUI ...