ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.ilObjTestSettingsMainGUI.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
34 
43 {
47  public const CMD_SHOW_FORM = 'showForm';
48  public const CMD_SAVE_FORM = 'saveForm';
49  public const CMD_CONFIRMED_SAVE_FORM = 'confirmedSaveForm';
50  public const CMD_SHOW_RESET_TPL_CONFIRM = 'showResetTemplateConfirmation';
51  public const CMD_CONFIRMED_RESET_TPL = 'confirmedResetTemplate';
52 
53  private const GENERAL_SETTINGS_SECTION_LABEL = 'general_settings';
54  private const AVAILABILITY_SETTINGS_SECTION_LABEL = 'availability settings';
55  private const PRESENTATION_SETTINGS_SECTION_LABEL = 'presentation_settings';
56  private const INTRODUCTION_SETTINGS_SECTION_LABEL = 'introduction_settings';
57  private const ACCESS_SETTINGS_LABEL = 'access_settings';
58  private const TEST_BEHAVIOUR_SETTINGS_LABEL = 'test_behaviour_settings';
59  private const QUESTION_BEHAVIOUR_SETTINGS_LABEL = 'question_behaviour_settings';
60  private const PARTICIPANTS_FUNCTIONALITY_SETTINGS_LABEL = 'participants_functionality_settings';
61  private const FINISH_TEST_SETTINGS_LABEL = 'finish_test_settings';
62  private const ECS_FUNCTIONALITY_SETTINGS_LABEL = 'ecs_settings';
63  private const ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL = 'additional_functionality_settings';
64 
65 
66  protected ilTabsGUI $tabs;
68  protected UIServices $ui;
72  protected Refinery $refinery;
73  protected ServerRequestInterface $request;
75  protected ilSetting $settings;
76 
78 
79  public function __construct(
80  protected ilCtrlInterface $ctrl,
81  protected ilAccessHandler $access,
82  protected ilLanguage $lng,
83  protected ilTree $tree,
84  protected ilDBInterface $db,
85  protected ilComponentRepository $component_repository,
86  protected ilObjUser $activeUser,
87  protected ilObjTestGUI $test_gui,
88  protected QuestionInfoService $questioninfo
89  ) {
91  global $DIC;
92 
93  $this->tabs = $DIC->tabs();
94  $this->toolbar = $DIC['ilToolbar'];
95  $this->ui = $DIC->ui();
96  $this->tpl = $DIC->ui()->mainTemplate();
97  $this->refinery = $DIC->refinery();
98  $this->request = $DIC->http()->request();
99  $this->object_data_cache = $DIC['ilObjDataCache'];
100  $this->settings = $DIC['ilSetting'];
101 
102  $this->main_settings = $this->test_gui->getTestObject()->getMainSettings();
103  $this->main_settings_repository = $this->test_gui->getTestObject()->getMainSettingsRepository();
104  $this->testQuestionSetConfigFactory = new ilTestQuestionSetConfigFactory(
105  $this->tree,
106  $this->db,
107  $this->lng,
108  $DIC['ilLog'],
109  $this->component_repository,
110  $this->test_gui->getTestObject(),
111  $this->questioninfo
112  );
113 
114  $this->lng->loadLanguageModule('validation');
115 
116  parent::__construct($this->test_gui->getTestObject());
117  }
118 
122  public function executeCommand()
123  {
124  if (!$this->access->checkAccess('write', '', $this->test_gui->getRefId())) {
125  $this->tpl->setOnScreenMessage('info', $this->lng->txt('cannot_edit_test'), true);
126  $this->ctrl->redirect($this->test_gui, 'infoScreen');
127  }
128 
129  $cmd = $this->ctrl->getCmd(self::CMD_SHOW_FORM);
130  $this->$cmd();
131 
132  $this->object_data_cache->deleteCachedEntry($this->test_object->getId());
133  $this->test_gui->prepareOutput();
134  $this->tabs->activateTab(ilTestTabsManager::TAB_ID_SETTINGS);
135  $this->tabs->activateSubTab(ilTestTabsManager::SUBTAB_ID_GENERAL_SETTINGS);
136  }
137 
138  private function showOldIntroduction(): void
139  {
140  $this->toolbar->addComponent(
141  $this->ui->factory()->link()->standard(
142  $this->lng->txt('back'),
143  $this->ctrl->getLinkTargetByClass(self::class, 'showForm')
144  )
145  );
146 
147  $this->tpl->setContent(
148  $this->main_settings->getIntroductionSettings()->getIntroductionText()
149  );
150  }
151 
152  private function showOldConcludingRemarks(): void
153  {
154  $this->toolbar->addComponent(
155  $this->ui->factory()->link()->standard(
156  $this->lng->txt('back'),
157  $this->ctrl->getLinkTargetByClass(self::class, 'showForm')
158  )
159  );
160 
161  $this->tpl->setContent(
162  $this->main_settings->getFinishingSettings()->getConcludingRemarksText()
163  );
164  }
165 
166  private function showForm(StandardForm $form = null, InterruptiveModal $modal = null): void
167  {
168  if ($form === null) {
169  $form = $this->buildForm();
170  }
171 
172  if ($this->main_settings->getIntroductionSettings()->getIntroductionText() !== '') {
173  $this->toolbar->addComponent(
174  $this->ui->factory()->link()->standard(
175  $this->lng->txt('show_old_introduction'),
176  $this->ctrl->getLinkTargetByClass(self::class, 'showOldIntroduction')
177  )
178  );
179  }
180 
181  if ($this->main_settings->getFinishingSettings()->getConcludingRemarksText() !== '') {
182  $this->toolbar->addComponent(
183  $this->ui->factory()->link()->standard(
184  $this->lng->txt('show_old_concluding_remarks'),
185  $this->ctrl->getLinkTargetByClass(self::class, 'showOldConcludingRemarks')
186  )
187  );
188  }
189 
190  $rendered_modal = '';
191  if ($modal !== null) {
192  $rendered_modal = $this->ui->renderer()->render($modal);
193  }
194 
195  $this->tpl->setContent($this->ui->renderer()->render($form) . $rendered_modal);
196  }
197 
198  private function confirmedSaveForm(): void
199  {
200  $form = $this->buildForm()->withRequest($this->request);
201  $data = $form->getData();
202  if ($data === null) {
203  $this->showForm($form);
204  return;
205  }
206 
207  $data[self::AVAILABILITY_SETTINGS_SECTION_LABEL]['is_online'] =
208  $this->test_object->getObjectProperties()->getPropertyIsOnline()->withOffline();
209  $this->testQuestionSetConfigFactory->getQuestionSetConfig()->removeQuestionSetRelatedData();
210 
211  $this->finalizeSave($data);
212  }
213 
214 
215  private function saveForm(): void
216  {
217  $form = $this->buildForm()->withRequest($this->request);
218  $data = $form->getData();
219  if ($data === null) {
220  $this->showForm($form);
221  return;
222  }
223 
224  $current_question_set_type = $this->main_settings->getGeneralSettings()->getQuestionSetType();
225  $current_question_config = $this->testQuestionSetConfigFactory->getQuestionSetConfig();
226  $new_question_set_type = $data[self::GENERAL_SETTINGS_SECTION_LABEL]['question_set_type'];
227 
228  if ($new_question_set_type !== $current_question_set_type
229  && $current_question_config->doesQuestionSetRelatedDataExist()) {
230  $modal = $this->populateConfirmationModal($current_question_set_type, $new_question_set_type);
231  $this->showForm($form, $modal);
232  return;
233  }
234 
235  $this->finalizeSave($data);
236  }
237 
238  private function finalizeSave(array $data): void
239  {
240  $this->performSaveForm($data);
242 
243  $this->tpl->setOnScreenMessage('success', $this->lng->txt('msg_obj_modified'), true);
244  $this->showForm();
245  }
246 
247  private function buildForm(): StandardForm
248  {
249  $lng = $this->lng;
250  $input_factory = $this->ui->factory()->input();
251  $refinery = $this->refinery;
252 
253  $data_factory = new DataFactory();
254  $user_format = $this->activeUser->getDateFormat();
255 
256  $environment['participant_data_exists'] = $this->test_object->participantDataExist();
257  $environment['user_date_format'] = $data_factory->dateFormat()->withTime24($user_format);
258  $environment['user_time_zone'] = $this->activeUser->getTimeZone();
259 
260  $main_inputs = [
261  self::GENERAL_SETTINGS_SECTION_LABEL => $this->getGeneralSettingsSection($environment),
262  self::AVAILABILITY_SETTINGS_SECTION_LABEL => $this->getAvailabilitySettingsSection(),
263  self::PRESENTATION_SETTINGS_SECTION_LABEL => $this->getPresentationSettingsSection(),
264  self::INTRODUCTION_SETTINGS_SECTION_LABEL => $this->main_settings->getIntroductionSettings()
265  ->toForm($lng, $input_factory->field(), $refinery),
266  self::ACCESS_SETTINGS_LABEL => $this->main_settings->getAccessSettings()
267  ->toForm($lng, $input_factory->field(), $refinery, $environment),
268  self::TEST_BEHAVIOUR_SETTINGS_LABEL => $this->main_settings->getTestBehaviourSettings()
269  ->toForm($lng, $input_factory->field(), $refinery, $environment),
270  self::QUESTION_BEHAVIOUR_SETTINGS_LABEL => $this->main_settings->getQuestionBehaviourSettings()
271  ->toForm($lng, $input_factory->field(), $refinery, $environment),
272  self::PARTICIPANTS_FUNCTIONALITY_SETTINGS_LABEL => $this->main_settings->getParticipantFunctionalitySettings()
273  ->toForm($lng, $input_factory->field(), $refinery, $environment),
274  self::FINISH_TEST_SETTINGS_LABEL => $this->main_settings->getFinishingSettings()
275  ->toForm($lng, $input_factory->field(), $refinery)
276  ];
277 
278  $inputs = array_merge($main_inputs, $this->getAdditionalFunctionalitySettingsSections($environment));
279 
280  return $input_factory->container()->form()->standard(
281  $this->ctrl->getFormActionByClass(self::class, self::CMD_SAVE_FORM),
282  $inputs
284  }
285 
286  private function getFormConstraints(): Constraint
287  {
288  return $this->refinery->custom()->constraint(
289  function (array $vs): bool {
290  if ($vs[self::PARTICIPANTS_FUNCTIONALITY_SETTINGS_LABEL]['postponed_questions_behaviour'] === true
291  && $vs[self::QUESTION_BEHAVIOUR_SETTINGS_LABEL]['lock_answers']['lock_answer_on_next_question']) {
292  return false;
293  }
294  return true;
295  },
296  $this->lng->txt('tst_settings_conflict_postpone_and_lock')
297  );
298  }
299 
300  private function populateConfirmationModal(
301  string $current_question_set_type,
302  string $new_question_set_type
303  ): InterruptiveModal {
304  $message = sprintf(
305  $this->lng->txt('tst_change_quest_set_type_from_old_to_new_with_conflict'),
306  $this->test_object->getQuestionSetTypeTranslation($this->lng, $current_question_set_type),
307  $this->test_object->getQuestionSetTypeTranslation($this->lng, $new_question_set_type)
308  );
309 
310  if ($current_question_set_type === ilObjTest::QUESTION_SET_TYPE_FIXED
311  && $this->test_object->hasQuestionsWithoutQuestionpool()) {
312  $message .= '<br /><br />' . $this->lng->txt('tst_nonpool_questions_get_lost_warning');
313  }
314 
315  $this->tpl->addJavaScript('./Modules/Test/templates/default/settings_confirmation.js');
316  $on_load_code = static function (string $id): string {
317  return 'il.test.confirmSettings.init(' . $id . ')';
318  };
319 
320  $modal = $this->ui->factory()->modal()->interruptive(
321  $this->lng->txt('confirm'),
322  $message,
323  $this->ctrl->getFormActionByClass(self::class, self::CMD_CONFIRMED_SAVE_FORM)
324  )->withActionButtonLabel($this->lng->txt('confirm'))
325  ->withAdditionalOnLoadCode($on_load_code);
326 
327  return $modal->withOnLoad($modal->getShowSignal());
328  }
329 
330  private function performSaveForm(array $data)
331  {
332  $old_online_status = $this->test_object->getObjectProperties()->getPropertyIsOnline()->getIsOnline();
333  $this->test_object->getObjectProperties()->storePropertyTitleAndDescription(
334  $data[self::GENERAL_SETTINGS_SECTION_LABEL]['title_and_description']
335  );
336  $general_settings = $this->getGeneralSettingsForStorage($data[self::GENERAL_SETTINGS_SECTION_LABEL]);
337 
338  $this->saveAvailabilitySettingsSection($data[self::AVAILABILITY_SETTINGS_SECTION_LABEL]);
339  $this->savePresentationSettingsSection($data[self::PRESENTATION_SETTINGS_SECTION_LABEL]);
340 
341  $introduction_settings = $this->getIntroductionSettingsForStorage(
342  $data[self::INTRODUCTION_SETTINGS_SECTION_LABEL]
343  );
344  $access_settings = $this->getAccessSettingsForStorage(
345  $data[self::ACCESS_SETTINGS_LABEL]
346  );
347  $test_behaviour_settings = $this->getTestBehaviourSettingsForStorage(
348  $data[self::TEST_BEHAVIOUR_SETTINGS_LABEL]
349  );
350  $question_behaviour_settings = $this->getQuestionBehaviourSettingsForStorage(
351  $data[self::QUESTION_BEHAVIOUR_SETTINGS_LABEL]
352  );
353  $participant_functionality_settings = $this->getParticipantsFunctionalitySettingsForStorage(
354  $data[self::PARTICIPANTS_FUNCTIONALITY_SETTINGS_LABEL]
355  );
356 
357  $finishing_settings = $this->getFinishingSettingsForStorage($data[self::FINISH_TEST_SETTINGS_LABEL]);
358 
359  if (array_key_exists(self::ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL, $data)
360  || array_key_exists(self::ECS_FUNCTIONALITY_SETTINGS_LABEL, $data)) {
362  }
363 
364  $additional_settings = $this->getAdditionalFunctionalitySettingsForStorage(
365  $data[self::ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL] ?? []
366  );
367 
368  $settings = new ilObjTestMainSettings(
369  $this->test_object->getTestId(),
370  $general_settings,
371  $introduction_settings,
372  $access_settings,
373  $test_behaviour_settings,
374  $question_behaviour_settings,
375  $participant_functionality_settings,
376  $finishing_settings,
377  $additional_settings
378  );
379  $this->main_settings_repository->store($settings);
380  $this->main_settings = $this->main_settings_repository->getFor($this->test_object->getTestId());
381  $this->test_object->read();
382  $this->test_object->addToNewsOnOnline(
383  $old_online_status,
384  $this->test_object->getObjectProperties()->getPropertyIsOnline()->getIsOnline()
385  );
386  }
387 
388  private function removeAllParticipantsIfRequired(): void
389  {
390  if (!$this->test_object->participantDataExist() && !$this->test_object->getFixedParticipants()) {
391  foreach ($this->test_object->getInvitedUsers() as $usr_id => $usr_data) {
392  $this->test_object->disinviteUser($usr_id);
393  }
394  }
395  }
396 
397  private function getGeneralSettingsSection(array $environment): Section
398  {
399  $field_factory = $this->ui->factory()->input()->field();
400 
401  $inputs['title_and_description'] = $this->test_object->getObjectProperties()->getPropertyTitleAndDescription()
402  ->toForm($this->lng, $field_factory, $this->refinery);
403  $inputs += $this->main_settings->getGeneralSettings()
404  ->toForm($this->lng, $field_factory, $this->refinery, $environment);
405 
406  return $field_factory->section(
407  $inputs,
408  $this->lng->txt('tst_general_properties')
409  );
410  }
411 
415  private function getGeneralSettingsForStorage(array $section): ilObjTestSettingsGeneral
416  {
417  if ($this->test_object->participantDataExist()) {
418  return $this->main_settings->getGeneralSettings();
419  }
420 
421  return $this->main_settings->getGeneralSettings()
422  ->withQuestionSetType($section['question_set_type'])
423  ->withAnonymity($section['anonymity']);
424  }
425 
427  {
428  $input_factory = $this->ui->factory()->input();
429 
430  $inputs['is_online'] = $this->getIsOnlineSettingInput();
431  $inputs['timebased_availability'] = $this->getTimebasedAvailabilityInputs();
432 
433  return $input_factory->field()->section(
434  $inputs,
435  $this->lng->txt('rep_activation_availability')
436  );
437  }
438 
439  private function getIsOnlineSettingInput(): Checkbox
440  {
441  $field_factory = $this->ui->factory()->input()->field();
442 
443  $question_set_config_complete = $this->test_object->isComplete(
444  $this->testQuestionSetConfigFactory->getQuestionSetConfig()
445  );
446 
447  $is_online = $this->test_object->getObjectProperties()->getPropertyIsOnline()
448  ->toForm($this->lng, $field_factory, $this->refinery);
449 
450  if (sizeof(ilObject::_getAllReferences($this->test_object->getId())) > 1) {
451  $is_online = $is_online->withByline(
452  $is_online->getByline() . ' ' . $this->lng->txt('rep_activation_online_object_info')
453  );
454  }
455 
456  if (!$question_set_config_complete) {
457  $is_online = $is_online
458  ->withByline($this->lng->txt('cannot_switch_to_online_no_questions_andor_no_mark_steps'))
459  ->withDisabled(true);
460  }
461 
462  return $is_online;
463  }
464 
466  {
467  $field_factory = $this->ui->factory()->input()->field();
468 
471 
472  $data_factory = new DataFactory();
473  $user_format = $this->activeUser->getDateFormat();
474  $format = $data_factory->dateFormat()->withTime24($user_format);
475 
476  $inputs['time_span'] = $field_factory->duration($this->lng->txt('rep_time_period'))
477  ->withTimezone($this->activeUser->getTimeZone())
478  ->withFormat($format)
479  ->withUseTime(true)
480  ->withRequired(true);
481  $inputs['activation_visibility'] = $field_factory->checkbox(
482  $this->lng->txt('rep_activation_limited_visibility'),
483  $this->lng->txt('tst_activation_limited_visibility_info')
484  );
485 
486  return $field_factory->optionalGroup(
487  $inputs,
488  $this->lng->txt('rep_time_based_availability')
490  ->withValue($value);
491  }
492 
494  {
495  return $this->refinery->custom()->transformation(
496  static function (?array $vs): array {
497  if ($vs === null) {
498  return [
499  'is_activation_limited' => false,
500  'activation_starting_time' => null,
501  'activation_ending_time' => null,
502  'activation_visibility' => false
503  ];
504  }
505 
506  $start = $vs['time_span']['start']->getTimestamp();
507  $end = $vs['time_span']['end']->getTimestamp();
508 
509  return [
510  'is_activation_limited' => true,
511  'activation_starting_time' => $start,
512  'activation_ending_time' => $end,
513  'activation_visibility' => $vs['activation_visibility']
514  ];
515  }
516  );
517  }
518 
519  private function getValueForActivationLimitedOptionalGroup(): ?array
520  {
521  $value = null;
522  if ($this->test_object->isActivationLimited()) {
523  $value = [
524  'time_span' => [
525  DateTimeImmutable::createFromFormat(
526  'U',
527  (string) $this->test_object->getActivationStartingTime()
528  )->setTimezone(new DateTimeZone($this->activeUser->getTimeZone())),
529  DateTimeImmutable::createFromFormat(
530  'U',
531  (string) $this->test_object->getActivationEndingTime()
532  )->setTimezone(new DateTimeZone($this->activeUser->getTimeZone())),
533  ],
534  'activation_visibility' => $this->test_object->getActivationVisibility()
535  ];
536  }
537  return $value;
538  }
539 
540  private function saveAvailabilitySettingsSection(array $section): void
541  {
542  $time_based_availability = $section['timebased_availability'];
543 
544  $participant_data_exists = $this->test_object->participantDataExist();
545  $this->test_object->storeActivationSettings(
546  $participant_data_exists
547  ? $this->test_object->isActivationLimited()
548  : $time_based_availability['is_activation_limited'],
549  $participant_data_exists
550  ? $this->test_object->getActivationStartingTime()
551  : $time_based_availability['activation_starting_time'],
552  $time_based_availability['activation_ending_time'],
553  $time_based_availability['activation_visibility']
554  );
555  $this->test_object->getObjectProperties()->storePropertyIsOnline($section['is_online']);
556  }
557 
559  {
560  $input_factory = $this->ui->factory()->input();
561 
562  $custom_icon_input = $this->test_object->getObjectProperties()->getPropertyIcon()
563  ->toForm($this->lng, $input_factory->field(), $this->refinery);
564 
565  if ($custom_icon_input !== null) {
566  $inputs['custom_icon'] = $custom_icon_input;
567  }
568  $inputs['tile_image'] = $this->test_object->getObjectProperties()->getPropertyTileImage()
569  ->toForm($this->lng, $input_factory->field(), $this->refinery);
570 
571  return $input_factory->field()->section(
572  $inputs,
573  $this->lng->txt('tst_presentation_settings_section')
574  );
575  }
576 
577  protected function savePresentationSettingsSection(array $section): void
578  {
579  if (array_key_exists('custom_icon', $section)) {
580  $this->test_object->getObjectProperties()->storePropertyIcon($section['custom_icon']);
581  }
582  $this->test_object->getObjectProperties()->storePropertyTileImage($section['tile_image']);
583  }
584 
586  {
587  return $this->main_settings->getIntroductionSettings()
588  ->withIntroductionEnabled($section['introduction_enabled'])
589  ->withExamConditionsCheckboxEnabled($section['conditions_checkbox_enabled']);
590  }
591 
592  private function getAccessSettingsForStorage(array $section): ilObjTestSettingsAccess
593  {
594  $access_settings = $this->main_settings->getAccessSettings()
595  ->withStartTimeEnabled($section['access_window']['start_time_enabled'])
596  ->withStartTime($section['access_window']['start_time'])
597  ->withEndTimeEnabled($section['access_window']['end_time_enabled'])
598  ->withEndTime($section['access_window']['end_time'])
599  ->withPasswordEnabled($section['test_password']['password_enabled'])
600  ->withPassword($section['test_password']['password_value'])
601  ->withFixedParticipants($section['fixed_participants_enabled']);
602 
603  if ($this->test_object->participantDataExist()) {
604  return $access_settings;
605  }
606 
607  return $access_settings->withStartTimeEnabled($section['access_window']['start_time_enabled'])
608  ->withStartTime($section['access_window']['start_time']);
609  }
610 
612  {
613  $test_behaviour_settings = $this->main_settings->getTestBehaviourSettings()
614  ->withKioskMode($section['kiosk_mode'])
615  ->withExamIdInTestPassEnabled($section['show_exam_id']);
616 
617  if ($this->test_object->participantDataExist()) {
618  return $test_behaviour_settings;
619  }
620 
621  return $test_behaviour_settings
622  ->withNumberOfTries($section['limit_attempts']['number_of_available_attempts'])
623  ->withBlockAfterPassedEnabled($section['limit_attempts']['block_after_passed'])
624  ->withPassWaiting($section['force_waiting_between_attempts'])
625  ->withProcessingTimeEnabled($section['time_limit_for_completion']['processing_time_limit'])
626  ->withProcessingTime($section['time_limit_for_completion']['time_limit_for_completion_value'])
627  ->withResetProcessingTime($section['time_limit_for_completion']['reset_time_limit_for_completion_by_attempt']);
628  }
629 
631  {
632  $question_behaviour_settings = $this->main_settings->getQuestionBehaviourSettings()
633  ->withQuestionTitleOutputMode($section['title_output'])
634  ->withAutosaveEnabled($section['autosave']['autosave_enabled'])
635  ->withAutosaveInterval($section['autosave']['autosave_interval'])
636  ->withShuffleQuestions($section['shuffle_questions']);
637 
638  if ($this->test_object->participantDataExist()) {
639  return $question_behaviour_settings;
640  }
641 
642  return $question_behaviour_settings
643  ->withQuestionHintsEnabled($section['offer_hints'])
644  ->withInstantFeedbackPointsEnabled($section['instant_feedback']['enabled_feedback_types']['instant_feedback_points'])
645  ->withInstantFeedbackGenericEnabled($section['instant_feedback']['enabled_feedback_types']['instant_feedback_generic'])
646  ->withInstantFeedbackSpecificEnabled($section['instant_feedback']['enabled_feedback_types']['instant_feedback_specific'])
647  ->withInstantFeedbackSolutionEnabled($section['instant_feedback']['enabled_feedback_types']['instant_feedback_solution'])
648  ->withForceInstantFeedbackOnNextQuestion($section['instant_feedback']['feedback_on_next_question'])
649  ->withLockAnswerOnInstantFeedbackEnabled($section['lock_answers']['lock_answer_on_instant_feedback'])
650  ->withLockAnswerOnNextQuestionEnabled($section['lock_answers']['lock_answer_on_next_question'])
651  ->withCompulsoryQuestionsEnabled($section['enable_compulsory_questions']);
652  }
653 
654 
656  {
657  return $this->main_settings->getParticipantFunctionalitySettings()
658  ->withUsePreviousAnswerAllowed($section['use_previous_answers'])
659  ->withSuspendTestAllowed($section['allow_suspend_test'])
660  ->withPostponedQuestionsMoveToEnd($section['postponed_questions_behaviour'])
661  ->withUsrPassOverviewMode($section['usr_pass_overview'])
662  ->withQuestionMarkingEnabled($section['enable_question_marking'])
663  ->withQuestionListEnabled($section['enable_question_list']);
664  }
665 
667  {
668  $redirect_after_finish = $section['redirect_after_finish'];
669  $finish_notification = $section['finish_notification'];
670  return $this->main_settings->getFinishingSettings()
671  ->withShowAnswerOverview($section['show_answer_overview'])
672  ->withConcludingRemarksEnabled($section['show_concluding_remarks'])
673  ->withRedirectionMode($redirect_after_finish['redirect_mode'])
674  ->withRedirectionUrl($redirect_after_finish['redirect_url'])
675  ->withMailNotificationContentType($finish_notification['notification_content_type'])
676  ->withAlwaysSendMailNotification($finish_notification['always_notify']);
677  }
678 
679  protected function getAdditionalFunctionalitySettingsSections(array $environment): array
680  {
681  $sections = [];
682 
683  $ecs = new ilECSTestSettings($this->test_object);
684  $ecs_section = $ecs->getSettingsSection(
685  $this->ui->factory()->input()->field(),
687  );
688 
689  if ($ecs_section !== null) {
690  $sections[self::ECS_FUNCTIONALITY_SETTINGS_LABEL] = $ecs_section;
691  }
692 
693  $inputs['organisational_units_activation'] = $this->getOrganisationalUnitsActivationInput();
694 
695  $inputs += $this->main_settings->getAdditionalSettings()->toForm(
696  $this->lng,
697  $this->ui->factory()->input()->field(),
699  $environment
700  );
701 
702  $inputs = array_filter($inputs, fn($v) => $v !== null);
703 
704  if (count($inputs) > 0) {
705  $sections[self::ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL] = $this->ui->factory()->input()->field()
706  ->section($inputs, $this->lng->txt('obj_features'));
707  }
708 
709  return $sections;
710  }
711 
713  {
714  $position_settings = ilOrgUnitGlobalSettings::getInstance()->getObjectPositionSettingsByType(
715  $this->test_object->getType()
716  );
717  if (!$position_settings->isActive()) {
718  return null;
719  }
720 
721  $enable_organisational_units_access = $this->ui->factory()->input()->field()
722  ->checkbox(
723  $this->lng->txt('obj_orgunit_positions'),
724  $this->lng->txt('obj_orgunit_positions_info')
725  )->withValue(
726  (new \ilOrgUnitObjectPositionSetting($this->test_object->getId()))->isActive()
727  ?? $position_settings->getActivationDefault() === \ilOrgUnitObjectTypePositionSetting::DEFAULT_ON
728  );
729  if (!$position_settings->isChangeableForObject()) {
730  return $enable_organisational_units_access->withDisabled(true);
731  }
732  return $enable_organisational_units_access;
733  }
734 
735  protected function saveAdditionalFunctionalitySettingsSection(array $sections): void
736  {
737  if (array_key_exists(self::ECS_FUNCTIONALITY_SETTINGS_LABEL, $sections)) {
738  $ecs = new ilECSTestSettings($this->test_object);
739  $ecs->saveSettingsSection($sections[self::ECS_FUNCTIONALITY_SETTINGS_LABEL]);
740  }
741 
742  if (!array_key_exists(self::ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL, $sections)) {
743  return;
744  }
745 
746  $additional_settings_section = $sections[self::ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL];
747  if (array_key_exists('organisational_units_activation', $additional_settings_section)) {
748  $this->saveOrganisationalUnitsActivation($additional_settings_section['organisational_units_activation']);
749  }
750  }
751 
752  protected function saveOrganisationalUnitsActivation(bool $activation): void
753  {
754  $position_settings = ilOrgUnitGlobalSettings::getInstance()->getObjectPositionSettingsByType(
755  $this->test_object->getType()
756  );
757 
758  if ($position_settings->isActive() && $position_settings->isChangeableForObject()) {
759  $orgu_object_settings = new ilOrgUnitObjectPositionSetting($this->test_object->getId());
760  $orgu_object_settings->setActive(
761  $activation
762  );
763  $orgu_object_settings->update();
764  }
765  }
766 
768  {
769  $additional_settings = $this->main_settings->getAdditionalSettings()->withHideInfoTab($section['hide_info_tab']);
770 
771  if ($this->test_object->participantDataExist()) {
772  return $additional_settings;
773  }
774 
775  if (!(new ilSkillManagementSettings())->isActivated()) {
776  return $additional_settings->withSkillsServiceEnabled(false);
777  }
778 
779  return $additional_settings->withSkillsServiceEnabled($section['skills_service_activation']);
780  }
781 }
setActive(bool $a_status)
Set active for object.
This describes section inputs.
Definition: Section.php:28
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...
Class ilObjTestGUI.
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...
getParticipantsFunctionalitySettingsForStorage(array $section)
static _getAllReferences(int $id)
get all reference ids for object ID
withIntroductionEnabled(bool $introduction_enabled)
A constraint encodes some resrtictions on values.
Definition: Constraint.php:31
populateConfirmationModal(string $current_question_set_type, string $new_question_set_type)
This describes optional group inputs.
This describes checkbox inputs.
Definition: Checkbox.php:28
saveAdditionalFunctionalitySettingsSection(array $sections)
getAdditionalFunctionalitySettingsForStorage(array $section)
__construct(protected ilObjTest $test_object)
global $DIC
Definition: feed.php:28
Provides fluid interface to RBAC services.
Definition: UIServices.php:23
__construct(VocabulariesInterface $vocabularies)
ilObjTestSettingsMainGUI: ilPropertyFormGUI ilObjTestSettingsMainGUI: ilConfirmationGUI ilObjTestSe...
withQuestionSetType(string $question_set_type)
$lng
Class ilECSTestSettings.
withValue($value)
Get an input like this with another value displayed on the client side.
Definition: Group.php:58
withQuestionTitleOutputMode(int $question_title_output_mode)
ilTestQuestionSetConfigFactory $testQuestionSetConfigFactory
showForm(StandardForm $form=null, InterruptiveModal $modal=null)
withShowAnswerOverview(bool $show_answer_overview)
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
const QUESTION_SET_TYPE_FIXED
$message
Definition: xapiexit.php:32
getAdditionalFunctionalitySettingsSections(array $environment)
withStartTimeEnabled(bool $start_time_enabled)
MainSettingsRepository $main_settings_repository