19declare(strict_types=1);
37use Psr\Http\Message\ServerRequestInterface;
78 private readonly \
ilTree $tree,
82 private readonly UIFactory $ui_factory,
83 private readonly UIRenderer $ui_renderer,
85 private readonly ServerRequestInterface $request,
92 $this->object_properties = $this->test_gui->getTestObject()->getObjectProperties();
93 $this->main_settings = $this->test_gui->getTestObject()->getMainSettings();
94 $this->main_settings_repository = $this->test_gui->getTestObject()->getMainSettingsRepository();
95 $this->testQuestionSetConfigFactory = new \ilTestQuestionSetConfigFactory(
100 $this->component_repository,
101 $this->test_gui->getTestObject(),
102 $this->questionrepository
105 $this->
lng->loadLanguageModule(
'validation');
106 $this->
lng->loadLanguageModule(
'rep');
116 if (!$this->
access->checkAccess(
'write',
'', $this->test_gui->getRefId())) {
117 $this->tpl->setOnScreenMessage(
'info', $this->
lng->txt(
'cannot_edit_test'),
true);
118 $this->
ctrl->redirectByClass([\ilRepositoryGUI::class, \ilObjTestGUI::class, \ilInfoScreenGUI::class]);
121 $cmd = $this->
ctrl->getCmd(self::CMD_SHOW_FORM);
124 $this->object_data_cache->deleteCachedEntry($this->test_object->getId());
127 private function showForm(?StandardForm $form =
null, ?InterruptiveModal $modal =
null): void
129 if ($form ===
null) {
133 $rendered_modal =
'';
134 if ($modal !==
null) {
135 $rendered_modal = $this->ui_renderer->render($modal);
138 $this->tpl->setContent($this->ui_renderer->render($form) . $rendered_modal);
143 $form = $this->
buildForm()->withRequest($this->request);
144 $data = $form->getData();
145 if (
$data ===
null) {
150 $current_question_set_type = $this->main_settings->getGeneralSettings()->getQuestionSetType();
151 $current_question_config = $this->testQuestionSetConfigFactory->getQuestionSetConfig();
154 if ($new_question_set_type !== $current_question_set_type
155 && $current_question_config->doesQuestionSetRelatedDataExist()) {
157 $this->test_object->getObjectProperties()->getPropertyIsOnline()->withOffline();
158 $this->testQuestionSetConfigFactory->getQuestionSetConfig()->removeQuestionSetRelatedData();
162 $this->
logger->deleteParticipantInteractionsForTest($this->test_object->getRefId());
172 $form = $this->
buildForm()->withRequest($this->request);
173 $data = $form->getData();
174 }
catch (InvalidArgumentException) {
175 $this->
ctrl->redirect($this, self::CMD_SHOW_FORM);
179 if (
$data ===
null) {
184 $current_question_set_type = $this->main_settings->getGeneralSettings()->getQuestionSetType();
185 $current_question_config = $this->testQuestionSetConfigFactory->getQuestionSetConfig();
188 if ($new_question_set_type ===
null) {
189 $this->tpl->setOnScreenMessage(
'info', $this->
lng->txt(
'tst_settings_form_reload_needed'));
190 $this->
ctrl->redirect($this, self::CMD_SHOW_FORM);
194 $question_set_modal_required = $new_question_set_type !== $current_question_set_type
195 && $current_question_config->doesQuestionSetRelatedDataExist();
197 $data[self::GENERAL_SETTINGS_SECTION_LABEL][
'anonymity']
200 if ($question_set_modal_required || $anonymity_modal_required) {
202 $question_set_modal_required ? $current_question_set_type :
null,
203 $question_set_modal_required ? $new_question_set_type :
null,
204 $anonymity_modal_required
217 + $this->main_settings->getArrayForLog($this->
logger->getAdditionalInformationGenerator());
218 if ($this->
logger->isLoggingEnabled()) {
219 $this->
logger->logTestAdministrationInteraction(
220 $this->
logger->getInteractionFactory()->buildTestAdministrationInteraction(
221 $this->test_object->getRefId(),
222 $this->active_user->getId(),
223 TestAdministrationInteractionTypes::MAIN_SETTINGS_MODIFIED,
224 $additional_information
229 $this->tpl->setOnScreenMessage(
'success', $this->
lng->txt(
'msg_obj_modified'),
true);
230 $this->
ctrl->redirect($this, self::CMD_SHOW_FORM);
235 return $this->main_settings->getGeneralSettings()->getAnonymity() ===
false
236 && $anonymity_form_data ===
true
237 && $this->
logger->testHasParticipantInteractions($this->test_object->getRefId());
242 $title_and_description = $this->object_properties->getPropertyTitleAndDescription();
247 ->getAdditionalInformationGenerator()->getTrueFalseTagForBool(
248 $this->object_properties->getPropertyIsOnline()->getIsOnline()
258 $input_factory = $this->ui_factory->input();
261 $environment[
'participant_data_exists'] = $this->test_object->participantDataExist();
262 $environment[
'user_date_format'] = $this->active_user->getDateTimeFormat();
263 $environment[
'user_time_zone'] = $this->active_user->getTimeZone();
269 self::INTRODUCTION_SETTINGS_SECTION_LABEL => $this->main_settings->getIntroductionSettings()
271 self::ACCESS_SETTINGS_LABEL => $this->main_settings->getAccessSettings()
272 ->toForm(
$lng, $input_factory->field(),
$refinery, $environment),
273 self::TEST_BEHAVIOUR_SETTINGS_LABEL => $this->main_settings->getTestBehaviourSettings()
274 ->toForm(
$lng, $input_factory->field(),
$refinery, $environment),
275 self::QUESTION_BEHAVIOUR_SETTINGS_LABEL => $this->main_settings->getQuestionBehaviourSettings()
276 ->toForm(
$lng, $input_factory->field(),
$refinery, $environment),
277 self::PARTICIPANTS_FUNCTIONALITY_SETTINGS_LABEL => $this->main_settings->getParticipantFunctionalitySettings()
278 ->toForm(
$lng, $input_factory->field(),
$refinery, $environment),
279 self::FINISH_TEST_SETTINGS_LABEL => $this->main_settings->getFinishingSettings()
285 return $input_factory->container()->form()->standard(
286 $this->
ctrl->getFormActionByClass(self::class, self::CMD_SAVE_FORM),
293 return $this->
refinery->custom()->constraint(
294 function (array $vs):
bool {
297 ?? $this->main_settings->getQuestionBehaviourSettings()->getLockAnswerOnNextQuestionEnabled());
299 $this->
lng->txt(
'tst_settings_conflict_postpone_and_lock')
304 ?
string $current_question_set_type,
305 ?
string $new_question_set_type,
306 bool $anonymity_modal_required
307 ): InterruptiveModal {
310 if ($current_question_set_type !==
null) {
312 $this->
lng->txt(
'tst_change_quest_set_type_from_old_to_new_with_conflict'),
313 $this->test_object->getQuestionSetTypeTranslation($this->lng, $current_question_set_type),
314 $this->test_object->getQuestionSetTypeTranslation($this->lng, $new_question_set_type)
319 && $this->test_object->hasQuestionsWithoutQuestionpool()) {
320 $message .=
'<br /><br />' . $this->
lng->txt(
'tst_nonpool_questions_get_lost_warning');
323 if ($anonymity_modal_required) {
324 if ($message !==
'') {
325 $message .=
'<br /><br />';
327 $message .= $this->
lng->txt(
'log_participant_data_delete_warning');
330 $this->tpl->addJavaScript(
'assets/js/settings_confirmation.js');
331 $on_load_code =
static function (
string $id):
string {
332 return 'il.test.confirmSettings.init(' .
$id .
')';
335 $modal = $this->ui_factory->modal()->interruptive(
336 $this->
lng->txt(
'confirm'),
338 $this->
ctrl->getFormActionByClass(self::class, self::CMD_CONFIRMED_SAVE_FORM)
339 )->withActionButtonLabel($this->
lng->txt(
'confirm'))
342 return $modal->withOnLoad($modal->getShowSignal());
347 $old_online_status = $this->test_object->getObjectProperties()->getPropertyIsOnline()->getIsOnline();
348 $this->test_object->getObjectProperties()->storePropertyTitleAndDescription(
349 $data[self::GENERAL_SETTINGS_SECTION_LABEL][
'title_and_description']
351 $general_settings = $this->getGeneralSettingsForStorage(
$data[self::GENERAL_SETTINGS_SECTION_LABEL]);
353 $this->saveAvailabilitySettingsSection(
$data[self::AVAILABILITY_SETTINGS_SECTION_LABEL]);
354 $this->savePresentationSettingsSection(
$data[self::PRESENTATION_SETTINGS_SECTION_LABEL]);
356 $introduction_settings = $this->getIntroductionSettingsForStorage(
357 $data[self::INTRODUCTION_SETTINGS_SECTION_LABEL]
359 $access_settings = $this->getAccessSettingsForStorage(
360 $data[self::ACCESS_SETTINGS_LABEL]
362 $test_behaviour_settings = $this->getTestBehaviourSettingsForStorage(
363 $data[self::TEST_BEHAVIOUR_SETTINGS_LABEL]
365 $question_behaviour_settings = $this->getQuestionBehaviourSettingsForStorage(
366 $data[self::QUESTION_BEHAVIOUR_SETTINGS_LABEL]
368 $participant_functionality_settings = $this->getParticipantsFunctionalitySettingsForStorage(
369 $data[self::PARTICIPANTS_FUNCTIONALITY_SETTINGS_LABEL]
372 $finishing_settings = $this->getFinishingSettingsForStorage(
$data[self::FINISH_TEST_SETTINGS_LABEL]);
374 if (array_key_exists(self::ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL,
$data)
375 || array_key_exists(self::ECS_FUNCTIONALITY_SETTINGS_LABEL,
$data)) {
376 $this->saveAdditionalFunctionalitySettingsSection(
$data);
379 $additional_settings = $this->getAdditionalFunctionalitySettingsForStorage(
380 $data[self::ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL] ?? []
384 $this->main_settings->getId(),
386 $introduction_settings,
388 $test_behaviour_settings,
389 $question_behaviour_settings,
390 $participant_functionality_settings,
394 $this->main_settings_repository->store($settings);
395 $this->main_settings = $this->main_settings_repository->getFor($this->test_object->getTestId());
396 $this->test_object->read();
397 $this->test_object->addToNewsOnOnline(
399 $this->test_object->getObjectProperties()->getPropertyIsOnline()->getIsOnline()
405 $field_factory = $this->ui_factory->input()->field();
407 $inputs[
'title_and_description'] = $this->test_object->getObjectProperties()->getPropertyTitleAndDescription()
408 ->toForm($this->
lng, $field_factory, $this->
refinery);
409 $inputs += $this->main_settings->getGeneralSettings()
410 ->toForm($this->
lng, $field_factory, $this->
refinery, $environment);
412 return $field_factory->section(
414 $this->
lng->txt(
'tst_general_properties')
423 if ($this->test_object->participantDataExist()) {
424 return $this->main_settings->getGeneralSettings();
427 return $this->main_settings->getGeneralSettings()
429 ->withAnonymity($section[
'anonymity']);
434 $input_factory = $this->ui_factory->input();
436 $inputs[
'is_online'] = $this->getIsOnlineSettingInput();
438 return $input_factory->field()->section(
440 $this->
lng->txt(
'rep_activation_availability')
446 $field_factory = $this->ui_factory->input()->field();
448 $question_set_config_complete = $this->test_object->isComplete(
449 $this->testQuestionSetConfigFactory->getQuestionSetConfig()
452 $is_online = $this->test_object->getObjectProperties()->getPropertyIsOnline()
453 ->toForm($this->
lng, $field_factory, $this->
refinery);
457 $is_online->getByline() .
' ' . $this->lng->txt(
'rep_activation_online_object_info')
461 if (!$question_set_config_complete) {
462 $is_online = $is_online
463 ->withByline($this->
lng->txt(
'cannot_switch_to_online_no_questions_andor_no_mark_steps'))
464 ->withDisabled(
true);
472 $this->test_object->getObjectProperties()->storePropertyIsOnline($section[
'is_online']);
477 $input_factory = $this->ui_factory->input();
479 $custom_icon_input = $this->test_object->getObjectProperties()->getPropertyIcon()
480 ->toForm($this->
lng, $input_factory->field(), $this->refinery);
482 if ($custom_icon_input !==
null) {
483 $inputs[
'custom_icon'] = $custom_icon_input;
485 $inputs[
'tile_image'] = $this->test_object->getObjectProperties()->getPropertyTileImage()
486 ->toForm($this->
lng, $input_factory->field(), $this->refinery);
488 return $input_factory->field()->section(
490 $this->
lng->txt(
'tst_presentation_settings_section')
496 if (array_key_exists(
'custom_icon', $section)) {
497 $this->test_object->getObjectProperties()->storePropertyIcon($section[
'custom_icon']);
499 $this->test_object->getObjectProperties()->storePropertyTileImage($section[
'tile_image']);
504 return $this->main_settings->getIntroductionSettings()
506 ->withExamConditionsCheckboxEnabled($section[
'conditions_checkbox_enabled']);
511 $access_settings = $this->main_settings->getAccessSettings()
513 ->withStartTime($section[
'access_window'][
'start_time'])
514 ->withEndTimeEnabled($section[
'access_window'][
'end_time_enabled'])
515 ->withEndTime($section[
'access_window'][
'end_time'])
516 ->withPasswordEnabled($section[
'test_password'][
'password_enabled'])
517 ->withPassword($section[
'test_password'][
'password_value'])
518 ->withIpRangeFrom($section[
'ip_range'][
'ip_range_from'])
519 ->withIpRangeTo($section[
'ip_range'][
'ip_range_to'])
520 ->withFixedParticipants($section[
'fixed_participants_enabled']);
522 if ($this->test_object->participantDataExist()) {
523 return $access_settings;
526 return $access_settings->withStartTimeEnabled($section[
'access_window'][
'start_time_enabled'])
527 ->withStartTime($section[
'access_window'][
'start_time']);
532 $test_behaviour_settings = $this->main_settings->getTestBehaviourSettings()
534 ->withExamIdInTestAttemptEnabled($section[
'show_exam_id']);
536 if ($this->test_object->participantDataExist()) {
537 return $test_behaviour_settings;
540 return $test_behaviour_settings
541 ->withNumberOfTries($section[
'limit_attempts'][
'number_of_available_attempts'])
542 ->withBlockAfterPassedEnabled($section[
'limit_attempts'][
'block_after_passed'])
543 ->withPassWaiting($section[
'force_waiting_between_attempts'])
544 ->withProcessingTimeEnabled($section[
'time_limit_for_completion'][
'processing_time_limit'])
545 ->withProcessingTime($section[
'time_limit_for_completion'][
'time_limit_for_completion_value'])
546 ->withResetProcessingTime($section[
'time_limit_for_completion'][
'reset_time_limit_for_completion_by_attempt']);
551 $question_behaviour_settings = $this->main_settings->getQuestionBehaviourSettings()
553 ->withAutosaveEnabled($section[
'autosave'][
'autosave_enabled'])
554 ->withAutosaveInterval($section[
'autosave'][
'autosave_interval'])
555 ->withShuffleQuestions($section[
'shuffle_questions']);
557 if ($this->test_object->participantDataExist()) {
558 return $question_behaviour_settings;
561 return $question_behaviour_settings
562 ->withInstantFeedbackPointsEnabled($section[
'instant_feedback'][
'enabled_feedback_types'][
'instant_feedback_points'])
563 ->withInstantFeedbackGenericEnabled($section[
'instant_feedback'][
'enabled_feedback_types'][
'instant_feedback_generic'])
564 ->withInstantFeedbackSpecificEnabled($section[
'instant_feedback'][
'enabled_feedback_types'][
'instant_feedback_specific'])
565 ->withInstantFeedbackSolutionEnabled($section[
'instant_feedback'][
'enabled_feedback_types'][
'instant_feedback_solution'])
566 ->withForceInstantFeedbackOnNextQuestion($section[
'instant_feedback'][
'feedback_on_next_question'])
567 ->withLockAnswerOnInstantFeedbackEnabled($section[
'lock_answers'][
'lock_answer_on_instant_feedback'])
568 ->withLockAnswerOnNextQuestionEnabled($section[
'lock_answers'][
'lock_answer_on_next_question']);
574 return $this->main_settings->getParticipantFunctionalitySettings()
576 ->withSuspendTestAllowed($section[
'allow_suspend_test'])
577 ->withPostponedQuestionsMoveToEnd($section[
'postponed_questions_behaviour'])
578 ->withUsrPassOverviewMode($section[
'usr_pass_overview'])
579 ->withQuestionMarkingEnabled($section[
'enable_question_marking'])
580 ->withQuestionListEnabled($section[
'enable_question_list']);
585 $redirect_after_finish = $section[
'redirect_after_finish'];
586 return $this->main_settings->getFinishingSettings()
588 ->withConcludingRemarksEnabled($section[
'show_concluding_remarks'])
589 ->withRedirectionMode($redirect_after_finish[
'redirect_mode'])
590 ->withRedirectionUrl($redirect_after_finish[
'redirect_url']);
597 $ecs = new \ilECSTestSettings($this->test_object);
598 $ecs_section = $ecs->getSettingsSection(
599 $this->ui_factory->input()->field(),
603 if ($ecs_section !==
null) {
604 $sections[self::ECS_FUNCTIONALITY_SETTINGS_LABEL] = $ecs_section;
607 $inputs[
'organisational_units_activation'] = $this->getOrganisationalUnitsActivationInput();
609 $inputs += $this->main_settings->getAdditionalSettings()->toForm(
611 $this->ui_factory->input()->field(),
619 $sections[self::ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL] = $this->ui_factory->input()->field()
620 ->section(
$inputs, $this->
lng->txt(
'obj_features'));
629 $this->test_object->getType()
631 if (!$position_settings->isActive()) {
635 $enable_organisational_units_access = $this->ui_factory->input()->field()
637 $this->
lng->txt(
'obj_orgunit_positions'),
638 $this->lng->txt(
'obj_orgunit_positions_info')
643 if (!$position_settings->isChangeableForObject()) {
644 return $enable_organisational_units_access->withDisabled(
true);
646 return $enable_organisational_units_access;
651 if (array_key_exists(self::ECS_FUNCTIONALITY_SETTINGS_LABEL, $sections)) {
652 $ecs = new \ilECSTestSettings($this->test_object);
653 $ecs->saveSettingsSection($sections[self::ECS_FUNCTIONALITY_SETTINGS_LABEL]);
656 if (!array_key_exists(self::ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL, $sections)) {
660 $additional_settings_section = $sections[self::ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL];
661 if (array_key_exists(
'organisational_units_activation', $additional_settings_section)) {
662 $this->saveOrganisationalUnitsActivation($additional_settings_section[
'organisational_units_activation']);
669 $this->test_object->getType()
672 if ($position_settings->isActive() && $position_settings->isChangeableForObject()) {
673 $orgu_object_settings = new \ilOrgUnitObjectPositionSetting($this->test_object->getId());
674 $orgu_object_settings->setActive(
677 $orgu_object_settings->update();
683 $additional_settings = $this->main_settings->getAdditionalSettings()->
withHideInfoTab($section[
'hide_info_tab']);
685 if ($this->test_object->participantDataExist()) {
686 return $additional_settings;
690 return $additional_settings->withSkillsServiceEnabled(
false);
693 return $additional_settings->withSkillsServiceEnabled($section[
'skills_service_activation']);
698 if ($value ===
null || $value === 0) {
702 return \DateTimeImmutable::createFromFormat(
705 )->setTimezone(
new \DateTimeZone($this->active_user->getTimeZone()));
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Builds a Color from either hex- or rgb values.
withStartTimeEnabled(bool $start_time_enabled)
withHideInfoTab(bool $hide_info_tab)
withShowAnswerOverview(bool $show_answer_overview)
withQuestionSetType(string $question_set_type)
withIntroductionEnabled(bool $introduction_enabled)
@ilCtrl_Calls ILIAS\Test\Settings\MainSettings\SettingsMainGUI: ilPropertyFormGUI @ilCtrl_Calls ILIAS...
ilTestQuestionSetConfigFactory $testQuestionSetConfigFactory
const FINISH_TEST_SETTINGS_LABEL
anonymityChanged(bool $anonymity_form_data)
getGeneralSettingsSection(array $environment)
__construct(private readonly \ilGlobalTemplateInterface $tpl, 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)
getPresentationSettingsSection()
getParticipantsFunctionalitySettingsForStorage(array $section)
getQuestionBehaviourSettingsForStorage(array $section)
ObjectProperties $object_properties
const ACCESS_SETTINGS_LABEL
getObjectDataArrayForLog()
getFinishingSettingsForStorage(array $section)
const QUESTION_BEHAVIOUR_SETTINGS_LABEL
populateConfirmationModal(?string $current_question_set_type, ?string $new_question_set_type, bool $anonymity_modal_required)
getTestBehaviourSettingsForStorage(array $section)
showForm(?StandardForm $form=null, ?InterruptiveModal $modal=null)
getIntroductionSettingsForStorage(array $section)
const GENERAL_SETTINGS_SECTION_LABEL
const INTRODUCTION_SETTINGS_SECTION_LABEL
finalizeSave(array $data)
const CMD_CONFIRMED_SAVE_FORM
performSaveForm(array $data)
const PARTICIPANTS_FUNCTIONALITY_SETTINGS_LABEL
const CMD_SHOW_RESET_TPL_CONFIRM
buildDateOrNullFromILIASValue(?int $value)
getGeneralSettingsForStorage(array $section)
const PRESENTATION_SETTINGS_SECTION_LABEL
getAdditionalFunctionalitySettingsSections(array $environment)
saveAvailabilitySettingsSection(array $section)
getOrganisationalUnitsActivationInput()
saveOrganisationalUnitsActivation(bool $activation)
MainSettingsRepository $main_settings_repository
const ADDITIONAL_FUNCTIONALITY_SETTINGS_LABEL
getAccessSettingsForStorage(array $section)
savePresentationSettingsSection(array $section)
getIsOnlineSettingInput()
saveAdditionalFunctionalitySettingsSection(array $sections)
executeCommand()
Command Execution.
getAdditionalFunctionalitySettingsForStorage(array $section)
MainSettings $main_settings
const TEST_BEHAVIOUR_SETTINGS_LABEL
const CMD_CONFIRMED_RESET_TPL
const ECS_FUNCTIONALITY_SETTINGS_LABEL
const AVAILABILITY_SETTINGS_SECTION_LABEL
getAvailabilitySettingsSection()
withUsePreviousAnswerAllowed(bool $use_previous_answers_allowed)
withQuestionTitleOutputMode(int $question_title_output_mode)
withKioskMode(int $kiosk_mode)
const QUESTION_SET_TYPE_FIXED
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...
Skill management settings.
Tree class data representation in hierachical trees using the Nested Set Model with Gaps by Joe Celco...
A constraint encodes some resrtictions on values.
An entity that renders components to a string output.
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...
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
TestAdministrationInteractionTypes
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
withAdditionalOnLoadCode(Closure $binder)