ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.SettingsMainGUI.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
29use ILIAS\UI\Factory as UIFactory;
30use ILIAS\UI\Renderer as UIRenderer;
31use ILIAS\ILIASObject\Properties\Properties as ObjectProperties;
32use ILIAS\UI\Component\Modal\Interruptive as InterruptiveModal;
38use ILIAS\Refinery\Transformation as TransformationInterface;
39use Psr\Http\Message\ServerRequestInterface;
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
69 protected ObjectProperties $object_properties;
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(
141 $this->main_settings->getIntroductionSettings()->getIntroductionText(),
142 1
143 )
144 );
145 }
146
147 private function showOldConcludingRemarks(): void
148 {
149 $this->toolbar->addComponent(
150 $this->ui_factory->link()->standard(
151 $this->lng->txt('back'),
152 $this->ctrl->getLinkTargetByClass(self::class, 'showForm')
153 )
154 );
155
156 $this->tpl->setContent(
158 $this->main_settings->getFinishingSettings()->getConcludingRemarksText(),
159 1
160 )
161 );
162 }
163
164 private function showForm(?StandardForm $form = null, ?InterruptiveModal $modal = null): void
165 {
166 if ($form === null) {
167 $form = $this->buildForm();
168 }
169
170 if ($this->main_settings->getIntroductionSettings()->getIntroductionText() !== '') {
171 $this->toolbar->addComponent(
172 $this->ui_factory->link()->standard(
173 $this->lng->txt('show_old_introduction'),
174 $this->ctrl->getLinkTargetByClass(self::class, 'showOldIntroduction')
175 )
176 );
177 }
178
179 if ($this->main_settings->getFinishingSettings()->getConcludingRemarksText() !== '') {
180 $this->toolbar->addComponent(
181 $this->ui_factory->link()->standard(
182 $this->lng->txt('show_old_concluding_remarks'),
183 $this->ctrl->getLinkTargetByClass(self::class, 'showOldConcludingRemarks')
184 )
185 );
186 }
187
188 $rendered_modal = '';
189 if ($modal !== null) {
190 $rendered_modal = $this->ui_renderer->render($modal);
191 }
192
193 $this->tpl->setContent($this->ui_renderer->render($form) . $rendered_modal);
194 }
195
196 private function confirmedSaveForm(): void
197 {
198 $form = $this->buildForm()->withRequest($this->request);
199 $data = $form->getData();
200 if ($data === null) {
201 $this->showForm($form);
202 return;
203 }
204
205 $current_question_set_type = $this->main_settings->getGeneralSettings()->getQuestionSetType();
206 $current_question_config = $this->testQuestionSetConfigFactory->getQuestionSetConfig();
207 $new_question_set_type = $data[self::GENERAL_SETTINGS_SECTION_LABEL]['question_set_type'];
208
209 if ($new_question_set_type !== $current_question_set_type
210 && $current_question_config->doesQuestionSetRelatedDataExist()) {
212 $this->test_object->getObjectProperties()->getPropertyIsOnline()->withOffline();
213 $this->testQuestionSetConfigFactory->getQuestionSetConfig()->removeQuestionSetRelatedData();
214 }
215
216 if ($this->anonymityChanged($data[self::GENERAL_SETTINGS_SECTION_LABEL]['anonymity'])) {
217 $this->logger->deleteParticipantInteractionsForTest($this->test_object->getRefId());
218 }
219
220 $this->finalizeSave($data);
221 }
222
223
224 private function saveForm(): void
225 {
226 try {
227 $form = $this->buildForm()->withRequest($this->request);
228 $data = $form->getData();
229 } catch (InvalidArgumentException) {
230 $this->ctrl->redirect($this, self::CMD_SHOW_FORM);
231 return;
232 }
233
234 if ($data === null) {
235 $this->showForm($form);
236 return;
237 }
238
239 $current_question_set_type = $this->main_settings->getGeneralSettings()->getQuestionSetType();
240 $current_question_config = $this->testQuestionSetConfigFactory->getQuestionSetConfig();
241 $new_question_set_type = $data[self::GENERAL_SETTINGS_SECTION_LABEL]['question_set_type'];
242
243 if ($new_question_set_type === null) {
244 $this->tpl->setOnScreenMessage('info', $this->lng->txt('tst_settings_form_reload_needed'));
245 $this->ctrl->redirect($this, self::CMD_SHOW_FORM);
246 return;
247 }
248
249 $question_set_modal_required = $new_question_set_type !== $current_question_set_type
250 && $current_question_config->doesQuestionSetRelatedDataExist();
251 $anonymity_modal_required = $this->anonymityChanged(
252 $data[self::GENERAL_SETTINGS_SECTION_LABEL]['anonymity']
253 );
254
255 if ($question_set_modal_required || $anonymity_modal_required) {
256 $modal = $this->populateConfirmationModal(
257 $question_set_modal_required ? $current_question_set_type : null,
258 $question_set_modal_required ? $new_question_set_type : null,
259 $anonymity_modal_required
260 );
261 $this->showForm($form, $modal);
262 return;
263 }
264
265 $this->finalizeSave($data);
266 }
267
268 private function finalizeSave(array $data): void
269 {
270 $this->performSaveForm($data);
271 $additional_information = $this->getObjectDataArrayForLog()
272 + $this->main_settings->getArrayForLog($this->logger->getAdditionalInformationGenerator());
273 if ($this->logger->isLoggingEnabled()) {
274 $this->logger->logTestAdministrationInteraction(
275 $this->logger->getInteractionFactory()->buildTestAdministrationInteraction(
276 $this->test_object->getRefId(),
277 $this->active_user->getId(),
278 TestAdministrationInteractionTypes::MAIN_SETTINGS_MODIFIED,
279 $additional_information
280 )
281 );
282 }
283
284 $this->tpl->setOnScreenMessage('success', $this->lng->txt('msg_obj_modified'), true);
285 $this->ctrl->redirect($this, self::CMD_SHOW_FORM);
286 }
287
288 private function anonymityChanged(bool $anonymity_form_data): bool
289 {
290 return $this->main_settings->getGeneralSettings()->getAnonymity() === false
291 && $anonymity_form_data === true
292 && $this->logger->testHasParticipantInteractions($this->test_object->getRefId());
293 }
294
295 private function getObjectDataArrayForLog(): array
296 {
297 $title_and_description = $this->object_properties->getPropertyTitleAndDescription();
298 $log_array = [
299 AdditionalInformationGenerator::KEY_TEST_TITLE => $title_and_description->getTitle(),
300 AdditionalInformationGenerator::KEY_TEST_DESCRIPTION => $title_and_description->getDescription(),
302 ->getAdditionalInformationGenerator()->getTrueFalseTagForBool(
303 $this->object_properties->getPropertyIsOnline()->getIsOnline()
304 )
305 ];
306
307 return $log_array;
308 }
309
310 private function buildForm(): StandardForm
311 {
313 $input_factory = $this->ui_factory->input();
315
316 $environment['participant_data_exists'] = $this->test_object->participantDataExist();
317 $environment['user_date_format'] = $this->active_user->getDateTimeFormat();
318 $environment['user_time_zone'] = $this->active_user->getTimeZone();
319
320 $main_inputs = [
321 self::GENERAL_SETTINGS_SECTION_LABEL => $this->getGeneralSettingsSection($environment),
322 self::AVAILABILITY_SETTINGS_SECTION_LABEL => $this->getAvailabilitySettingsSection(),
323 self::PRESENTATION_SETTINGS_SECTION_LABEL => $this->getPresentationSettingsSection(),
324 self::INTRODUCTION_SETTINGS_SECTION_LABEL => $this->main_settings->getIntroductionSettings()
325 ->toForm($lng, $input_factory->field(), $refinery),
326 self::ACCESS_SETTINGS_LABEL => $this->main_settings->getAccessSettings()
327 ->toForm($lng, $input_factory->field(), $refinery, $environment),
328 self::TEST_BEHAVIOUR_SETTINGS_LABEL => $this->main_settings->getTestBehaviourSettings()
329 ->toForm($lng, $input_factory->field(), $refinery, $environment),
330 self::QUESTION_BEHAVIOUR_SETTINGS_LABEL => $this->main_settings->getQuestionBehaviourSettings()
331 ->toForm($lng, $input_factory->field(), $refinery, $environment),
332 self::PARTICIPANTS_FUNCTIONALITY_SETTINGS_LABEL => $this->main_settings->getParticipantFunctionalitySettings()
333 ->toForm($lng, $input_factory->field(), $refinery, $environment),
334 self::FINISH_TEST_SETTINGS_LABEL => $this->main_settings->getFinishingSettings()
335 ->toForm($lng, $input_factory->field(), $refinery)
336 ];
337
338 $inputs = array_merge($main_inputs, $this->getAdditionalFunctionalitySettingsSections($environment));
339
340 return $input_factory->container()->form()->standard(
341 $this->ctrl->getFormActionByClass(self::class, self::CMD_SAVE_FORM),
342 $inputs
343 )->withAdditionalTransformation($this->getFormConstraints());
344 }
345
346 private function getFormConstraints(): Constraint
347 {
348 return $this->refinery->custom()->constraint(
349 function (array $vs): bool {
350 if ($vs[self::PARTICIPANTS_FUNCTIONALITY_SETTINGS_LABEL]['postponed_questions_behaviour'] === true
351 && $vs[self::QUESTION_BEHAVIOUR_SETTINGS_LABEL]['lock_answers']['lock_answer_on_next_question']) {
352 return false;
353 }
354 return true;
355 },
356 $this->lng->txt('tst_settings_conflict_postpone_and_lock')
357 );
358 }
359
361 ?string $current_question_set_type,
362 ?string $new_question_set_type,
363 bool $anonymity_modal_required
364 ): InterruptiveModal {
365 $message = '';
366
367 if ($current_question_set_type !== null) {
368 $message .= sprintf(
369 $this->lng->txt('tst_change_quest_set_type_from_old_to_new_with_conflict'),
370 $this->test_object->getQuestionSetTypeTranslation($this->lng, $current_question_set_type),
371 $this->test_object->getQuestionSetTypeTranslation($this->lng, $new_question_set_type)
372 );
373 }
374
375 if ($current_question_set_type === \ilObjTest::QUESTION_SET_TYPE_FIXED
376 && $this->test_object->hasQuestionsWithoutQuestionpool()) {
377 $message .= '<br /><br />' . $this->lng->txt('tst_nonpool_questions_get_lost_warning');
378 }
379
380 if ($anonymity_modal_required) {
381 if ($message !== '') {
382 $message .= '<br /><br />';
383 }
384 $message .= $this->lng->txt('log_participant_data_delete_warning');
385 }
386
387 $this->tpl->addJavaScript('assets/js/settings_confirmation.js');
388 $on_load_code = static function (string $id): string {
389 return 'il.test.confirmSettings.init(' . $id . ')';
390 };
391
392 $modal = $this->ui_factory->modal()->interruptive(
393 $this->lng->txt('confirm'),
394 $message,
395 $this->ctrl->getFormActionByClass(self::class, self::CMD_CONFIRMED_SAVE_FORM)
396 )->withActionButtonLabel($this->lng->txt('confirm'))
397 ->withAdditionalOnLoadCode($on_load_code);
398
399 return $modal->withOnLoad($modal->getShowSignal());
400 }
401
402 private function performSaveForm(array $data)
403 {
404 $old_online_status = $this->test_object->getObjectProperties()->getPropertyIsOnline()->getIsOnline();
405 $this->test_object->getObjectProperties()->storePropertyTitleAndDescription(
406 $data[self::GENERAL_SETTINGS_SECTION_LABEL]['title_and_description']
407 );
408 $general_settings = $this->getGeneralSettingsForStorage($data[self::GENERAL_SETTINGS_SECTION_LABEL]);
409
410 $this->saveAvailabilitySettingsSection($data[self::AVAILABILITY_SETTINGS_SECTION_LABEL]);
411 $this->savePresentationSettingsSection($data[self::PRESENTATION_SETTINGS_SECTION_LABEL]);
412
413 $introduction_settings = $this->getIntroductionSettingsForStorage(
414 $data[self::INTRODUCTION_SETTINGS_SECTION_LABEL]
415 );
416 $access_settings = $this->getAccessSettingsForStorage(
417 $data[self::ACCESS_SETTINGS_LABEL]
418 );
419 $test_behaviour_settings = $this->getTestBehaviourSettingsForStorage(
420 $data[self::TEST_BEHAVIOUR_SETTINGS_LABEL]
421 );
422 $question_behaviour_settings = $this->getQuestionBehaviourSettingsForStorage(
423 $data[self::QUESTION_BEHAVIOUR_SETTINGS_LABEL]
424 );
425 $participant_functionality_settings = $this->getParticipantsFunctionalitySettingsForStorage(
426 $data[self::PARTICIPANTS_FUNCTIONALITY_SETTINGS_LABEL]
427 );
428
429 $finishing_settings = $this->getFinishingSettingsForStorage($data[self::FINISH_TEST_SETTINGS_LABEL]);
430
431 if (array_key_exists(self::ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL, $data)
432 || array_key_exists(self::ECS_FUNCTIONALITY_SETTINGS_LABEL, $data)) {
433 $this->saveAdditionalFunctionalitySettingsSection($data);
434 }
435
436 $additional_settings = $this->getAdditionalFunctionalitySettingsForStorage(
437 $data[self::ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL] ?? []
438 );
439
440 $settings = new MainSettings(
441 $this->test_object->getTestId(),
442 $this->test_object->getId(),
443 $general_settings,
444 $introduction_settings,
445 $access_settings,
446 $test_behaviour_settings,
447 $question_behaviour_settings,
448 $participant_functionality_settings,
449 $finishing_settings,
450 $additional_settings
451 );
452 $this->main_settings_repository->store($settings);
453 $this->main_settings = $this->main_settings_repository->getFor($this->test_object->getTestId());
454 $this->test_object->read();
455 $this->test_object->addToNewsOnOnline(
456 $old_online_status,
457 $this->test_object->getObjectProperties()->getPropertyIsOnline()->getIsOnline()
458 );
459 }
460
461 private function getGeneralSettingsSection(array $environment): Section
462 {
463 $field_factory = $this->ui_factory->input()->field();
464
465 $inputs['title_and_description'] = $this->test_object->getObjectProperties()->getPropertyTitleAndDescription()
466 ->toForm($this->lng, $field_factory, $this->refinery);
467 $inputs += $this->main_settings->getGeneralSettings()
468 ->toForm($this->lng, $field_factory, $this->refinery, $environment);
469
470 return $field_factory->section(
471 $inputs,
472 $this->lng->txt('tst_general_properties')
473 );
474 }
475
479 private function getGeneralSettingsForStorage(array $section): SettingsGeneral
480 {
481 if ($this->test_object->participantDataExist()) {
482 return $this->main_settings->getGeneralSettings();
483 }
484
485 return $this->main_settings->getGeneralSettings()
486 ->withQuestionSetType($section['question_set_type'])
487 ->withAnonymity($section['anonymity']);
488 }
489
491 {
492 $input_factory = $this->ui_factory->input();
493
494 $inputs['is_online'] = $this->getIsOnlineSettingInput();
495
496 return $input_factory->field()->section(
497 $inputs,
498 $this->lng->txt('rep_activation_availability')
499 );
500 }
501
503 {
504 $field_factory = $this->ui_factory->input()->field();
505
506 $question_set_config_complete = $this->test_object->isComplete(
507 $this->testQuestionSetConfigFactory->getQuestionSetConfig()
508 );
509
510 $is_online = $this->test_object->getObjectProperties()->getPropertyIsOnline()
511 ->toForm($this->lng, $field_factory, $this->refinery);
512
513 if (sizeof(\ilObject::_getAllReferences($this->test_object->getId())) > 1) {
514 $is_online = $is_online->withByline(
515 $is_online->getByline() . ' ' . $this->lng->txt('rep_activation_online_object_info')
516 );
517 }
518
519 if (!$question_set_config_complete) {
520 $is_online = $is_online
521 ->withByline($this->lng->txt('cannot_switch_to_online_no_questions_andor_no_mark_steps'))
522 ->withDisabled(true);
523 }
524
525 return $is_online;
526 }
527
528 private function saveAvailabilitySettingsSection(array $section): void
529 {
530 $this->test_object->getObjectProperties()->storePropertyIsOnline($section['is_online']);
531 }
532
534 {
535 $input_factory = $this->ui_factory->input();
536
537 $custom_icon_input = $this->test_object->getObjectProperties()->getPropertyIcon()
538 ->toForm($this->lng, $input_factory->field(), $this->refinery);
539
540 if ($custom_icon_input !== null) {
541 $inputs['custom_icon'] = $custom_icon_input;
542 }
543 $inputs['tile_image'] = $this->test_object->getObjectProperties()->getPropertyTileImage()
544 ->toForm($this->lng, $input_factory->field(), $this->refinery);
545
546 return $input_factory->field()->section(
547 $inputs,
548 $this->lng->txt('tst_presentation_settings_section')
549 );
550 }
551
552 protected function savePresentationSettingsSection(array $section): void
553 {
554 if (array_key_exists('custom_icon', $section)) {
555 $this->test_object->getObjectProperties()->storePropertyIcon($section['custom_icon']);
556 }
557 $this->test_object->getObjectProperties()->storePropertyTileImage($section['tile_image']);
558 }
559
561 {
562 return $this->main_settings->getIntroductionSettings()
563 ->withIntroductionEnabled($section['introduction_enabled'])
564 ->withExamConditionsCheckboxEnabled($section['conditions_checkbox_enabled']);
565 }
566
567 private function getAccessSettingsForStorage(array $section): SettingsAccess
568 {
569 $access_settings = $this->main_settings->getAccessSettings()
570 ->withStartTimeEnabled($section['access_window']['start_time_enabled'])
571 ->withStartTime($section['access_window']['start_time'])
572 ->withEndTimeEnabled($section['access_window']['end_time_enabled'])
573 ->withEndTime($section['access_window']['end_time'])
574 ->withPasswordEnabled($section['test_password']['password_enabled'])
575 ->withPassword($section['test_password']['password_value'])
576 ->withIpRangeFrom($section['ip_range']['ip_range_from'])
577 ->withIpRangeTo($section['ip_range']['ip_range_to'])
578 ->withFixedParticipants($section['fixed_participants_enabled']);
579
580 if ($this->test_object->participantDataExist()) {
581 return $access_settings;
582 }
583
584 return $access_settings->withStartTimeEnabled($section['access_window']['start_time_enabled'])
585 ->withStartTime($section['access_window']['start_time']);
586 }
587
589 {
590 $test_behaviour_settings = $this->main_settings->getTestBehaviourSettings()
591 ->withKioskMode($section['kiosk_mode'])
592 ->withExamIdInTestAttemptEnabled($section['show_exam_id']);
593
594 if ($this->test_object->participantDataExist()) {
595 return $test_behaviour_settings;
596 }
597
598 return $test_behaviour_settings
599 ->withNumberOfTries($section['limit_attempts']['number_of_available_attempts'])
600 ->withBlockAfterPassedEnabled($section['limit_attempts']['block_after_passed'])
601 ->withPassWaiting($section['force_waiting_between_attempts'])
602 ->withProcessingTimeEnabled($section['time_limit_for_completion']['processing_time_limit'])
603 ->withProcessingTime($section['time_limit_for_completion']['time_limit_for_completion_value'])
604 ->withResetProcessingTime($section['time_limit_for_completion']['reset_time_limit_for_completion_by_attempt']);
605 }
606
608 {
609 $question_behaviour_settings = $this->main_settings->getQuestionBehaviourSettings()
610 ->withQuestionTitleOutputMode($section['title_output'])
611 ->withAutosaveEnabled($section['autosave']['autosave_enabled'])
612 ->withAutosaveInterval($section['autosave']['autosave_interval'])
613 ->withShuffleQuestions($section['shuffle_questions']);
614
615 if ($this->test_object->participantDataExist()) {
616 return $question_behaviour_settings;
617 }
618
619 return $question_behaviour_settings
620 ->withInstantFeedbackPointsEnabled($section['instant_feedback']['enabled_feedback_types']['instant_feedback_points'])
621 ->withInstantFeedbackGenericEnabled($section['instant_feedback']['enabled_feedback_types']['instant_feedback_generic'])
622 ->withInstantFeedbackSpecificEnabled($section['instant_feedback']['enabled_feedback_types']['instant_feedback_specific'])
623 ->withInstantFeedbackSolutionEnabled($section['instant_feedback']['enabled_feedback_types']['instant_feedback_solution'])
624 ->withForceInstantFeedbackOnNextQuestion($section['instant_feedback']['feedback_on_next_question'])
625 ->withLockAnswerOnInstantFeedbackEnabled($section['lock_answers']['lock_answer_on_instant_feedback'])
626 ->withLockAnswerOnNextQuestionEnabled($section['lock_answers']['lock_answer_on_next_question']);
627 }
628
629
631 {
632 return $this->main_settings->getParticipantFunctionalitySettings()
633 ->withUsePreviousAnswerAllowed($section['use_previous_answers'])
634 ->withSuspendTestAllowed($section['allow_suspend_test'])
635 ->withPostponedQuestionsMoveToEnd($section['postponed_questions_behaviour'])
636 ->withUsrPassOverviewMode($section['usr_pass_overview'])
637 ->withQuestionMarkingEnabled($section['enable_question_marking'])
638 ->withQuestionListEnabled($section['enable_question_list']);
639 }
640
641 private function getFinishingSettingsForStorage(array $section): SettingsFinishing
642 {
643 $redirect_after_finish = $section['redirect_after_finish'];
644 $finish_notification = $section['finish_notification'];
645 return $this->main_settings->getFinishingSettings()
646 ->withShowAnswerOverview($section['show_answer_overview'])
647 ->withConcludingRemarksEnabled($section['show_concluding_remarks'])
648 ->withRedirectionMode($redirect_after_finish['redirect_mode'])
649 ->withRedirectionUrl($redirect_after_finish['redirect_url'])
650 ->withMailNotificationContentType($finish_notification['notification_content_type'])
651 ->withAlwaysSendMailNotification($finish_notification['always_notify']);
652 }
653
654 protected function getAdditionalFunctionalitySettingsSections(array $environment): array
655 {
656 $sections = [];
657
658 $ecs = new \ilECSTestSettings($this->test_object);
659 $ecs_section = $ecs->getSettingsSection(
660 $this->ui_factory->input()->field(),
661 $this->refinery
662 );
663
664 if ($ecs_section !== null) {
665 $sections[self::ECS_FUNCTIONALITY_SETTINGS_LABEL] = $ecs_section;
666 }
667
668 $inputs['organisational_units_activation'] = $this->getOrganisationalUnitsActivationInput();
669
670 $inputs += $this->main_settings->getAdditionalSettings()->toForm(
671 $this->lng,
672 $this->ui_factory->input()->field(),
673 $this->refinery,
674 $environment
675 );
676
677 $inputs = array_filter($inputs, fn($v) => $v !== null);
678
679 if (count($inputs) > 0) {
680 $sections[self::ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL] = $this->ui_factory->input()->field()
681 ->section($inputs, $this->lng->txt('obj_features'));
682 }
683
684 return $sections;
685 }
686
688 {
689 $position_settings = \ilOrgUnitGlobalSettings::getInstance()->getObjectPositionSettingsByType(
690 $this->test_object->getType()
691 );
692 if (!$position_settings->isActive()) {
693 return null;
694 }
695
696 $enable_organisational_units_access = $this->ui_factory->input()->field()
697 ->checkbox(
698 $this->lng->txt('obj_orgunit_positions'),
699 $this->lng->txt('obj_orgunit_positions_info')
700 )->withValue(
701 (new \ilOrgUnitObjectPositionSetting($this->test_object->getId()))->isActive()
702 ?? $position_settings->getActivationDefault() === \ilOrgUnitObjectTypePositionSetting::DEFAULT_ON
703 );
704 if (!$position_settings->isChangeableForObject()) {
705 return $enable_organisational_units_access->withDisabled(true);
706 }
707 return $enable_organisational_units_access;
708 }
709
710 protected function saveAdditionalFunctionalitySettingsSection(array $sections): void
711 {
712 if (array_key_exists(self::ECS_FUNCTIONALITY_SETTINGS_LABEL, $sections)) {
713 $ecs = new \ilECSTestSettings($this->test_object);
714 $ecs->saveSettingsSection($sections[self::ECS_FUNCTIONALITY_SETTINGS_LABEL]);
715 }
716
717 if (!array_key_exists(self::ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL, $sections)) {
718 return;
719 }
720
721 $additional_settings_section = $sections[self::ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL];
722 if (array_key_exists('organisational_units_activation', $additional_settings_section)) {
723 $this->saveOrganisationalUnitsActivation($additional_settings_section['organisational_units_activation']);
724 }
725 }
726
727 protected function saveOrganisationalUnitsActivation(bool $activation): void
728 {
729 $position_settings = \ilOrgUnitGlobalSettings::getInstance()->getObjectPositionSettingsByType(
730 $this->test_object->getType()
731 );
732
733 if ($position_settings->isActive() && $position_settings->isChangeableForObject()) {
734 $orgu_object_settings = new \ilOrgUnitObjectPositionSetting($this->test_object->getId());
735 $orgu_object_settings->setActive(
736 $activation
737 );
738 $orgu_object_settings->update();
739 }
740 }
741
743 {
744 $additional_settings = $this->main_settings->getAdditionalSettings()->withHideInfoTab($section['hide_info_tab']);
745
746 if ($this->test_object->participantDataExist()) {
747 return $additional_settings;
748 }
749
750 if (!(new \ilSkillManagementSettings())->isActivated()) {
751 return $additional_settings->withSkillsServiceEnabled(false);
752 }
753
754 return $additional_settings->withSkillsServiceEnabled($section['skills_service_activation']);
755 }
756
757 private function buildDateOrNullFromILIASValue(?int $value): ?\DateTimeImmutable
758 {
759 if ($value === null || $value === 0) {
760 return null;
761 }
762
763 return \DateTimeImmutable::createFromFormat(
764 'U',
765 (string) $value
766 )->setTimezone(new \DateTimeZone($this->active_user->getTimeZone()));
767 }
768}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
Builds a Color from either hex- or rgb values.
Definition: Factory.php:31
Builds data types.
Definition: Factory.php:36
@ilCtrl_Calls ILIAS\Test\Settings\MainSettings\SettingsMainGUI: ilPropertyFormGUI @ilCtrl_Calls ILIAS...
ilTestQuestionSetConfigFactory $testQuestionSetConfigFactory
populateConfirmationModal(?string $current_question_set_type, ?string $new_question_set_type, bool $anonymity_modal_required)
showForm(?StandardForm $form=null, ?InterruptiveModal $modal=null)
__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)
language handling
Class ilObjTestGUI.
const QUESTION_SET_TYPE_FIXED
User class.
class ilObjectDataCache
static _getAllReferences(int $id)
get all reference ids for object ID
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _replaceMediaObjectImageSrc(string $a_text, int $a_direction=0, string $nic='')
Replaces image source from mob image urls with the mob id or replaces mob id with the correct image s...
ILIAS Setting Class.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Tree class data representation in hierachical trees using the Nested Set Model with Gaps by Joe Celco...
A constraint encodes some resrtictions on values.
Definition: Constraint.php:32
A transformation is a function from one datatype to another.
withByline(string $byline)
Get an input like this, but with an additional/replaced label.
This describes a standard form.
Definition: Standard.php:29
This describes checkbox inputs.
Definition: Checkbox.php:29
This describes optional group inputs.
This describes section inputs.
Definition: Section.php:29
An entity that renders components to a string output.
Definition: Renderer.php:31
Interface ilAccessHandler This interface combines all available interfaces which can be called via gl...
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...
Interface ilDBInterface.
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
global $lng
Definition: privfeed.php:31
$message
Definition: xapiexit.php:31