ILIAS  release_10 Revision v10.1-43-ga1241a92c2f
class.SettingsMainGUI.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
22 
40 
49 {
50  public const CMD_SHOW_FORM = 'showForm';
51  public const CMD_SAVE_FORM = 'saveForm';
52  public const CMD_CONFIRMED_SAVE_FORM = 'confirmedSaveForm';
53  public const CMD_SHOW_RESET_TPL_CONFIRM = 'showResetTemplateConfirmation';
54  public const CMD_CONFIRMED_RESET_TPL = 'confirmedResetTemplate';
55 
56  private const GENERAL_SETTINGS_SECTION_LABEL = 'general_settings';
57  private const AVAILABILITY_SETTINGS_SECTION_LABEL = 'availability settings';
58  private const PRESENTATION_SETTINGS_SECTION_LABEL = 'presentation_settings';
59  private const INTRODUCTION_SETTINGS_SECTION_LABEL = 'introduction_settings';
60  private const ACCESS_SETTINGS_LABEL = 'access_settings';
61  private const TEST_BEHAVIOUR_SETTINGS_LABEL = 'test_behaviour_settings';
62  private const QUESTION_BEHAVIOUR_SETTINGS_LABEL = 'question_behaviour_settings';
63  private const PARTICIPANTS_FUNCTIONALITY_SETTINGS_LABEL = 'participants_functionality_settings';
64  private const FINISH_TEST_SETTINGS_LABEL = 'finish_test_settings';
65  private const ECS_FUNCTIONALITY_SETTINGS_LABEL = 'ecs_settings';
66  private const ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL = 'additional_functionality_settings';
67 
68  protected \ilObjectProperties $object_properties;
71 
72  private \ilTestQuestionSetConfigFactory $testQuestionSetConfigFactory;
73 
74  public function __construct(
75  private readonly \ilGlobalTemplateInterface $tpl,
76  private readonly \ilToolbarGUI $toolbar,
77  private readonly \ilCtrlInterface $ctrl,
78  private readonly \ilAccessHandler $access,
79  private readonly \ilLanguage $lng,
80  private readonly \ilTree $tree,
81  private readonly \ilDBInterface $db,
82  private readonly \ilObjectDataCache $object_data_cache,
83  private readonly \ilSetting $settings,
84  private readonly UIFactory $ui_factory,
85  private readonly UIRenderer $ui_renderer,
86  private readonly Refinery $refinery,
87  private readonly ServerRequestInterface $request,
88  private readonly \ilComponentRepository $component_repository,
89  private readonly \ilObjUser $active_user,
90  private readonly \ilObjTestGUI $test_gui,
91  private readonly TestLogger $logger,
92  private readonly GeneralQuestionPropertiesRepository $questionrepository
93  ) {
94  $this->object_properties = $this->test_gui->getTestObject()->getObjectProperties();
95  $this->main_settings = $this->test_gui->getTestObject()->getMainSettings();
96  $this->main_settings_repository = $this->test_gui->getTestObject()->getMainSettingsRepository();
97  $this->testQuestionSetConfigFactory = new \ilTestQuestionSetConfigFactory(
98  $this->tree,
99  $this->db,
100  $this->lng,
101  $this->logger,
102  $this->component_repository,
103  $this->test_gui->getTestObject(),
104  $this->questionrepository
105  );
106 
107  $this->lng->loadLanguageModule('validation');
108  $this->lng->loadLanguageModule('rep');
109 
110  parent::__construct($this->test_gui->getTestObject());
111  }
112 
116  public function executeCommand()
117  {
118  if (!$this->access->checkAccess('write', '', $this->test_gui->getRefId())) {
119  $this->tpl->setOnScreenMessage('info', $this->lng->txt('cannot_edit_test'), true);
120  $this->ctrl->redirectByClass([\ilRepositoryGUI::class, \ilObjTestGUI::class, \ilInfoScreenGUI::class]);
121  }
122 
123  $cmd = $this->ctrl->getCmd(self::CMD_SHOW_FORM);
124  $this->$cmd();
125 
126  $this->object_data_cache->deleteCachedEntry($this->test_object->getId());
127  }
128 
129  private function showOldIntroduction(): void
130  {
131  $this->toolbar->addComponent(
132  $this->ui_factory->link()->standard(
133  $this->lng->txt('back'),
134  $this->ctrl->getLinkTargetByClass(self::class, 'showForm')
135  )
136  );
137 
138  $this->tpl->setContent(
139  $this->main_settings->getIntroductionSettings()->getIntroductionText()
140  );
141  }
142 
143  private function showOldConcludingRemarks(): void
144  {
145  $this->toolbar->addComponent(
146  $this->ui_factory->link()->standard(
147  $this->lng->txt('back'),
148  $this->ctrl->getLinkTargetByClass(self::class, 'showForm')
149  )
150  );
151 
152  $this->tpl->setContent(
153  $this->main_settings->getFinishingSettings()->getConcludingRemarksText()
154  );
155  }
156 
157  private function showForm(StandardForm $form = null, InterruptiveModal $modal = null): void
158  {
159  if ($form === null) {
160  $form = $this->buildForm();
161  }
162 
163  if ($this->main_settings->getIntroductionSettings()->getIntroductionText() !== '') {
164  $this->toolbar->addComponent(
165  $this->ui_factory->link()->standard(
166  $this->lng->txt('show_old_introduction'),
167  $this->ctrl->getLinkTargetByClass(self::class, 'showOldIntroduction')
168  )
169  );
170  }
171 
172  if ($this->main_settings->getFinishingSettings()->getConcludingRemarksText() !== '') {
173  $this->toolbar->addComponent(
174  $this->ui_factory->link()->standard(
175  $this->lng->txt('show_old_concluding_remarks'),
176  $this->ctrl->getLinkTargetByClass(self::class, 'showOldConcludingRemarks')
177  )
178  );
179  }
180 
181  $rendered_modal = '';
182  if ($modal !== null) {
183  $rendered_modal = $this->ui_renderer->render($modal);
184  }
185 
186  $this->tpl->setContent($this->ui_renderer->render($form) . $rendered_modal);
187  }
188 
189  private function confirmedSaveForm(): void
190  {
191  $form = $this->buildForm()->withRequest($this->request);
192  $data = $form->getData();
193  if ($data === null) {
194  $this->showForm($form);
195  return;
196  }
197 
198  $current_question_set_type = $this->main_settings->getGeneralSettings()->getQuestionSetType();
199  $current_question_config = $this->testQuestionSetConfigFactory->getQuestionSetConfig();
200  $new_question_set_type = $data[self::GENERAL_SETTINGS_SECTION_LABEL]['question_set_type'];
201 
202  if ($new_question_set_type !== $current_question_set_type
203  && $current_question_config->doesQuestionSetRelatedDataExist()) {
204  $data[self::AVAILABILITY_SETTINGS_SECTION_LABEL]['is_online'] =
205  $this->test_object->getObjectProperties()->getPropertyIsOnline()->withOffline();
206  $this->testQuestionSetConfigFactory->getQuestionSetConfig()->removeQuestionSetRelatedData();
207  }
208 
209  if ($this->anonymityChanged($data[self::GENERAL_SETTINGS_SECTION_LABEL]['anonymity'])) {
210  $this->logger->deleteParticipantInteractionsForTest($this->test_object->getRefId());
211  }
212 
213  $this->finalizeSave($data);
214  }
215 
216 
217  private function saveForm(): void
218  {
219  $form = $this->buildForm()->withRequest($this->request);
220  $data = $form->getData();
221  if ($data === null) {
222  $this->showForm($form);
223  return;
224  }
225 
226  $current_question_set_type = $this->main_settings->getGeneralSettings()->getQuestionSetType();
227  $current_question_config = $this->testQuestionSetConfigFactory->getQuestionSetConfig();
228  $new_question_set_type = $data[self::GENERAL_SETTINGS_SECTION_LABEL]['question_set_type'];
229 
230  $question_set_modal_required = $new_question_set_type !== $current_question_set_type
231  && $current_question_config->doesQuestionSetRelatedDataExist();
232  $anonymity_modal_required = $this->anonymityChanged(
233  $data[self::GENERAL_SETTINGS_SECTION_LABEL]['anonymity']
234  );
235 
236  if ($question_set_modal_required || $anonymity_modal_required) {
237  $modal = $this->populateConfirmationModal(
238  $question_set_modal_required ? $current_question_set_type : null,
239  $question_set_modal_required ? $new_question_set_type : null,
240  $anonymity_modal_required
241  );
242  $this->showForm($form, $modal);
243  return;
244  }
245 
246  $this->finalizeSave($data);
247  }
248 
249  private function finalizeSave(array $data): void
250  {
251  $this->performSaveForm($data);
252  $additional_information = $this->getObjectDataArrayForLog()
253  + $this->main_settings->getArrayForLog($this->logger->getAdditionalInformationGenerator());
254  if ($this->logger->isLoggingEnabled()) {
255  $this->logger->logTestAdministrationInteraction(
256  $this->logger->getInteractionFactory()->buildTestAdministrationInteraction(
257  $this->test_object->getRefId(),
258  $this->active_user->getId(),
259  TestAdministrationInteractionTypes::MAIN_SETTINGS_MODIFIED,
260  $additional_information
261  )
262  );
263  }
264 
265  $this->tpl->setOnScreenMessage('success', $this->lng->txt('msg_obj_modified'), true);
266  $this->showForm();
267  }
268 
269  private function anonymityChanged(bool $anonymity_form_data): bool
270  {
271  return $this->main_settings->getGeneralSettings()->getAnonymity() === false
272  && $anonymity_form_data === true
273  && $this->logger->testHasParticipantInteractions($this->test_object->getRefId());
274  }
275 
276  private function getObjectDataArrayForLog(): array
277  {
278  $title_and_description = $this->object_properties->getPropertyTitleAndDescription();
279  $log_array = [
280  AdditionalInformationGenerator::KEY_TEST_TITLE => $title_and_description->getTitle(),
281  AdditionalInformationGenerator::KEY_TEST_DESCRIPTION => $title_and_description->getDescription(),
283  ->getAdditionalInformationGenerator()->getTrueFalseTagForBool(
284  $this->object_properties->getPropertyIsOnline()->getIsOnline()
285  )
286  ];
287 
288  if (!$this->test_object->isActivationLimited()) {
290  ->getAdditionalInformationGenerator()->getEnabledDisabledTagForBool(false);
291  return $log_array;
292  }
293 
294  $none_tag = $this->logger->getAdditionalInformationGenerator()->getNoneTag();
295  $from = $this->test_object->getActivationStartingTime() === null
296  ? $none_tag
297  : \DateTimeImmutable::createFromFormat('U', (string) $this->test_object->getActivationStartingTime())
299  $until = $this->test_object->getActivationEndingTime() === null
300  ? $none_tag
301  : \DateTimeImmutable::createFromFormat('U', (string) $this->test_object->getActivationEndingTime())
303 
307  ];
309  ->getAdditionalInformationGenerator()->getEnabledDisabledTagForBool(
310  $this->test_object->getActivationVisibility()
311  );
312  return $log_array;
313  }
314 
315  private function buildForm(): StandardForm
316  {
317  $lng = $this->lng;
318  $input_factory = $this->ui_factory->input();
320 
321  $environment['participant_data_exists'] = $this->test_object->participantDataExist();
322  $environment['user_date_format'] = $this->active_user->getDateTimeFormat();
323  $environment['user_time_zone'] = $this->active_user->getTimeZone();
324 
325  $main_inputs = [
326  self::GENERAL_SETTINGS_SECTION_LABEL => $this->getGeneralSettingsSection($environment),
327  self::AVAILABILITY_SETTINGS_SECTION_LABEL => $this->getAvailabilitySettingsSection(),
328  self::PRESENTATION_SETTINGS_SECTION_LABEL => $this->getPresentationSettingsSection(),
329  self::INTRODUCTION_SETTINGS_SECTION_LABEL => $this->main_settings->getIntroductionSettings()
330  ->toForm($lng, $input_factory->field(), $refinery),
331  self::ACCESS_SETTINGS_LABEL => $this->main_settings->getAccessSettings()
332  ->toForm($lng, $input_factory->field(), $refinery, $environment),
333  self::TEST_BEHAVIOUR_SETTINGS_LABEL => $this->main_settings->getTestBehaviourSettings()
334  ->toForm($lng, $input_factory->field(), $refinery, $environment),
335  self::QUESTION_BEHAVIOUR_SETTINGS_LABEL => $this->main_settings->getQuestionBehaviourSettings()
336  ->toForm($lng, $input_factory->field(), $refinery, $environment),
337  self::PARTICIPANTS_FUNCTIONALITY_SETTINGS_LABEL => $this->main_settings->getParticipantFunctionalitySettings()
338  ->toForm($lng, $input_factory->field(), $refinery, $environment),
339  self::FINISH_TEST_SETTINGS_LABEL => $this->main_settings->getFinishingSettings()
340  ->toForm($lng, $input_factory->field(), $refinery)
341  ];
342 
343  $inputs = array_merge($main_inputs, $this->getAdditionalFunctionalitySettingsSections($environment));
344 
345  return $input_factory->container()->form()->standard(
346  $this->ctrl->getFormActionByClass(self::class, self::CMD_SAVE_FORM),
347  $inputs
349  }
350 
351  private function getFormConstraints(): Constraint
352  {
353  return $this->refinery->custom()->constraint(
354  function (array $vs): bool {
355  if ($vs[self::PARTICIPANTS_FUNCTIONALITY_SETTINGS_LABEL]['postponed_questions_behaviour'] === true
356  && $vs[self::QUESTION_BEHAVIOUR_SETTINGS_LABEL]['lock_answers']['lock_answer_on_next_question']) {
357  return false;
358  }
359  return true;
360  },
361  $this->lng->txt('tst_settings_conflict_postpone_and_lock')
362  );
363  }
364 
365  private function populateConfirmationModal(
366  ?string $current_question_set_type,
367  ?string $new_question_set_type,
368  bool $anonymity_modal_required
369  ): InterruptiveModal {
370  $message = '';
371 
372  if ($current_question_set_type !== null) {
373  $message .= sprintf(
374  $this->lng->txt('tst_change_quest_set_type_from_old_to_new_with_conflict'),
375  $this->test_object->getQuestionSetTypeTranslation($this->lng, $current_question_set_type),
376  $this->test_object->getQuestionSetTypeTranslation($this->lng, $new_question_set_type)
377  );
378  }
379 
380  if ($current_question_set_type === \ilObjTest::QUESTION_SET_TYPE_FIXED
381  && $this->test_object->hasQuestionsWithoutQuestionpool()) {
382  $message .= '<br /><br />' . $this->lng->txt('tst_nonpool_questions_get_lost_warning');
383  }
384 
385  if ($anonymity_modal_required) {
386  if ($message !== '') {
387  $message .= '<br /><br />';
388  }
389  $message .= $this->lng->txt('log_participant_data_delete_warning');
390  }
391 
392  $this->tpl->addJavaScript('assets/js/settings_confirmation.js');
393  $on_load_code = static function (string $id): string {
394  return 'il.test.confirmSettings.init(' . $id . ')';
395  };
396 
397  $modal = $this->ui_factory->modal()->interruptive(
398  $this->lng->txt('confirm'),
399  $message,
400  $this->ctrl->getFormActionByClass(self::class, self::CMD_CONFIRMED_SAVE_FORM)
401  )->withActionButtonLabel($this->lng->txt('confirm'))
402  ->withAdditionalOnLoadCode($on_load_code);
403 
404  return $modal->withOnLoad($modal->getShowSignal());
405  }
406 
407  private function performSaveForm(array $data)
408  {
409  $old_online_status = $this->test_object->getObjectProperties()->getPropertyIsOnline()->getIsOnline();
410  $this->test_object->getObjectProperties()->storePropertyTitleAndDescription(
411  $data[self::GENERAL_SETTINGS_SECTION_LABEL]['title_and_description']
412  );
413  $general_settings = $this->getGeneralSettingsForStorage($data[self::GENERAL_SETTINGS_SECTION_LABEL]);
414 
415  $this->saveAvailabilitySettingsSection($data[self::AVAILABILITY_SETTINGS_SECTION_LABEL]);
416  $this->savePresentationSettingsSection($data[self::PRESENTATION_SETTINGS_SECTION_LABEL]);
417 
418  $introduction_settings = $this->getIntroductionSettingsForStorage(
419  $data[self::INTRODUCTION_SETTINGS_SECTION_LABEL]
420  );
421  $access_settings = $this->getAccessSettingsForStorage(
422  $data[self::ACCESS_SETTINGS_LABEL]
423  );
424  $test_behaviour_settings = $this->getTestBehaviourSettingsForStorage(
425  $data[self::TEST_BEHAVIOUR_SETTINGS_LABEL]
426  );
427  $question_behaviour_settings = $this->getQuestionBehaviourSettingsForStorage(
428  $data[self::QUESTION_BEHAVIOUR_SETTINGS_LABEL]
429  );
430  $participant_functionality_settings = $this->getParticipantsFunctionalitySettingsForStorage(
431  $data[self::PARTICIPANTS_FUNCTIONALITY_SETTINGS_LABEL]
432  );
433 
434  $finishing_settings = $this->getFinishingSettingsForStorage($data[self::FINISH_TEST_SETTINGS_LABEL]);
435 
436  if (array_key_exists(self::ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL, $data)
437  || array_key_exists(self::ECS_FUNCTIONALITY_SETTINGS_LABEL, $data)) {
439  }
440 
441  $additional_settings = $this->getAdditionalFunctionalitySettingsForStorage(
442  $data[self::ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL] ?? []
443  );
444 
445  $settings = new MainSettings(
446  $this->test_object->getTestId(),
447  $this->test_object->getId(),
448  $general_settings,
449  $introduction_settings,
450  $access_settings,
451  $test_behaviour_settings,
452  $question_behaviour_settings,
453  $participant_functionality_settings,
454  $finishing_settings,
455  $additional_settings
456  );
457  $this->main_settings_repository->store($settings);
458  $this->main_settings = $this->main_settings_repository->getFor($this->test_object->getTestId());
459  $this->test_object->read();
460  $this->test_object->addToNewsOnOnline(
461  $old_online_status,
462  $this->test_object->getObjectProperties()->getPropertyIsOnline()->getIsOnline()
463  );
464  }
465 
466  private function getGeneralSettingsSection(array $environment): Section
467  {
468  $field_factory = $this->ui_factory->input()->field();
469 
470  $inputs['title_and_description'] = $this->test_object->getObjectProperties()->getPropertyTitleAndDescription()
471  ->toForm($this->lng, $field_factory, $this->refinery);
472  $inputs += $this->main_settings->getGeneralSettings()
473  ->toForm($this->lng, $field_factory, $this->refinery, $environment);
474 
475  return $field_factory->section(
476  $inputs,
477  $this->lng->txt('tst_general_properties')
478  );
479  }
480 
484  private function getGeneralSettingsForStorage(array $section): SettingsGeneral
485  {
486  if ($this->test_object->participantDataExist()) {
487  return $this->main_settings->getGeneralSettings();
488  }
489 
490  return $this->main_settings->getGeneralSettings()
491  ->withQuestionSetType($section['question_set_type'])
492  ->withAnonymity($section['anonymity']);
493  }
494 
496  {
497  $input_factory = $this->ui_factory->input();
498 
499  $inputs['is_online'] = $this->getIsOnlineSettingInput();
500  $inputs['timebased_availability'] = $this->getTimebasedAvailabilityInputs();
501 
502  return $input_factory->field()->section(
503  $inputs,
504  $this->lng->txt('rep_activation_availability')
505  );
506  }
507 
508  private function getIsOnlineSettingInput(): Checkbox
509  {
510  $field_factory = $this->ui_factory->input()->field();
511 
512  $question_set_config_complete = $this->test_object->isComplete(
513  $this->testQuestionSetConfigFactory->getQuestionSetConfig()
514  );
515 
516  $is_online = $this->test_object->getObjectProperties()->getPropertyIsOnline()
517  ->toForm($this->lng, $field_factory, $this->refinery);
518 
519  if (sizeof(\ilObject::_getAllReferences($this->test_object->getId())) > 1) {
520  $is_online = $is_online->withByline(
521  $is_online->getByline() . ' ' . $this->lng->txt('rep_activation_online_object_info')
522  );
523  }
524 
525  if (!$question_set_config_complete) {
526  $is_online = $is_online
527  ->withByline($this->lng->txt('cannot_switch_to_online_no_questions_andor_no_mark_steps'))
528  ->withDisabled(true);
529  }
530 
531  return $is_online;
532  }
533 
535  {
536  $field_factory = $this->ui_factory->input()->field();
537 
540 
541  $inputs['time_span'] = $field_factory->duration($this->lng->txt('rep_time_period'))
542  ->withTimezone($this->active_user->getTimeZone())
543  ->withFormat($this->active_user->getDateTimeFormat())
544  ->withUseTime(true)
545  ->withRequired(true);
546  $inputs['activation_visibility'] = $field_factory->checkbox(
547  $this->lng->txt('rep_activation_limited_visibility'),
548  $this->lng->txt('tst_activation_limited_visibility_info')
549  );
550 
551  return $field_factory->optionalGroup(
552  $inputs,
553  $this->lng->txt('rep_time_based_availability')
555  ->withValue($value);
556  }
557 
559  {
560  return $this->refinery->custom()->transformation(
561  static function (?array $vs): array {
562  if ($vs === null) {
563  return [
564  'is_activation_limited' => false,
565  'activation_starting_time' => null,
566  'activation_ending_time' => null,
567  'activation_visibility' => false
568  ];
569  }
570 
571  $start = $vs['time_span']['start']->getTimestamp();
572  $end = $vs['time_span']['end']->getTimestamp();
573 
574  return [
575  'is_activation_limited' => true,
576  'activation_starting_time' => $start,
577  'activation_ending_time' => $end,
578  'activation_visibility' => $vs['activation_visibility']
579  ];
580  }
581  );
582  }
583 
584  private function getValueForActivationLimitedOptionalGroup(): ?array
585  {
586  $value = null;
587  if ($this->test_object->isActivationLimited()) {
588  $value = [
589  'time_span' => [
590  \DateTimeImmutable::createFromFormat(
591  'U',
592  (string) $this->test_object->getActivationStartingTime()
593  )->setTimezone(new \DateTimeZone($this->active_user->getTimeZone())),
594  \DateTimeImmutable::createFromFormat(
595  'U',
596  (string) $this->test_object->getActivationEndingTime()
597  )->setTimezone(new \DateTimeZone($this->active_user->getTimeZone())),
598  ],
599  'activation_visibility' => $this->test_object->getActivationVisibility()
600  ];
601  }
602  return $value;
603  }
604 
605  private function saveAvailabilitySettingsSection(array $section): void
606  {
607  $time_based_availability = $section['timebased_availability'];
608 
609  $participant_data_exists = $this->test_object->participantDataExist();
610  $this->test_object->storeActivationSettings(
611  $participant_data_exists
612  ? $this->test_object->isActivationLimited()
613  : $time_based_availability['is_activation_limited'],
614  $participant_data_exists
615  ? $this->test_object->getActivationStartingTime()
616  : $time_based_availability['activation_starting_time'],
617  $time_based_availability['activation_ending_time'],
618  $time_based_availability['activation_visibility']
619  );
620  $this->test_object->getObjectProperties()->storePropertyIsOnline($section['is_online']);
621  }
622 
624  {
625  $input_factory = $this->ui_factory->input();
626 
627  $custom_icon_input = $this->test_object->getObjectProperties()->getPropertyIcon()
628  ->toForm($this->lng, $input_factory->field(), $this->refinery);
629 
630  if ($custom_icon_input !== null) {
631  $inputs['custom_icon'] = $custom_icon_input;
632  }
633  $inputs['tile_image'] = $this->test_object->getObjectProperties()->getPropertyTileImage()
634  ->toForm($this->lng, $input_factory->field(), $this->refinery);
635 
636  return $input_factory->field()->section(
637  $inputs,
638  $this->lng->txt('tst_presentation_settings_section')
639  );
640  }
641 
642  protected function savePresentationSettingsSection(array $section): void
643  {
644  if (array_key_exists('custom_icon', $section)) {
645  $this->test_object->getObjectProperties()->storePropertyIcon($section['custom_icon']);
646  }
647  $this->test_object->getObjectProperties()->storePropertyTileImage($section['tile_image']);
648  }
649 
650  private function getIntroductionSettingsForStorage(array $section): SettingsIntroduction
651  {
652  return $this->main_settings->getIntroductionSettings()
653  ->withIntroductionEnabled($section['introduction_enabled'])
654  ->withExamConditionsCheckboxEnabled($section['conditions_checkbox_enabled']);
655  }
656 
657  private function getAccessSettingsForStorage(array $section): SettingsAccess
658  {
659  $access_settings = $this->main_settings->getAccessSettings()
660  ->withStartTimeEnabled($section['access_window']['start_time_enabled'])
661  ->withStartTime($section['access_window']['start_time'])
662  ->withEndTimeEnabled($section['access_window']['end_time_enabled'])
663  ->withEndTime($section['access_window']['end_time'])
664  ->withPasswordEnabled($section['test_password']['password_enabled'])
665  ->withPassword($section['test_password']['password_value'])
666  ->withIpRangeFrom($section['ip_range']['ip_range_from'])
667  ->withIpRangeTo($section['ip_range']['ip_range_to'])
668  ->withFixedParticipants($section['fixed_participants_enabled']);
669 
670  if ($this->test_object->participantDataExist()) {
671  return $access_settings;
672  }
673 
674  return $access_settings->withStartTimeEnabled($section['access_window']['start_time_enabled'])
675  ->withStartTime($section['access_window']['start_time']);
676  }
677 
679  {
680  $test_behaviour_settings = $this->main_settings->getTestBehaviourSettings()
681  ->withKioskMode($section['kiosk_mode'])
682  ->withExamIdInTestAttemptEnabled($section['show_exam_id']);
683 
684  if ($this->test_object->participantDataExist()) {
685  return $test_behaviour_settings;
686  }
687 
688  return $test_behaviour_settings
689  ->withNumberOfTries($section['limit_attempts']['number_of_available_attempts'])
690  ->withBlockAfterPassedEnabled($section['limit_attempts']['block_after_passed'])
691  ->withPassWaiting($section['force_waiting_between_attempts'])
692  ->withProcessingTimeEnabled($section['time_limit_for_completion']['processing_time_limit'])
693  ->withProcessingTime($section['time_limit_for_completion']['time_limit_for_completion_value'])
694  ->withResetProcessingTime($section['time_limit_for_completion']['reset_time_limit_for_completion_by_attempt']);
695  }
696 
698  {
699  $question_behaviour_settings = $this->main_settings->getQuestionBehaviourSettings()
700  ->withQuestionTitleOutputMode($section['title_output'])
701  ->withAutosaveEnabled($section['autosave']['autosave_enabled'])
702  ->withAutosaveInterval($section['autosave']['autosave_interval'])
703  ->withShuffleQuestions($section['shuffle_questions']);
704 
705  if ($this->test_object->participantDataExist()) {
706  return $question_behaviour_settings;
707  }
708 
709  return $question_behaviour_settings
710  ->withQuestionHintsEnabled($section['offer_hints'])
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...
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
withValue($value)
Get an input like this with another value displayed on the client side.
Definition: Group.php:59
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:24
__construct(Container $dic, ilPlugin $plugin)
global $lng
Definition: privfeed.php:32
const QUESTION_SET_TYPE_FIXED
showForm(StandardForm $form=null, InterruptiveModal $modal=null)
ilTestQuestionSetConfigFactory $testQuestionSetConfigFactory
ILIAS: ilPropertyFormGUI ILIAS: ilConfirmationGUI ILIAS: ilTestSettingsChangeConfirmationGUI ...