diff --git a/components/ILIAS/Test/src/Settings/MainSettings/SettingsQuestionBehaviour.php b/components/ILIAS/Test/src/Settings/MainSettings/SettingsQuestionBehaviour.php index 89acfcdd8b7a..c61b38d5b9f0 100755 --- a/components/ILIAS/Test/src/Settings/MainSettings/SettingsQuestionBehaviour.php +++ b/components/ILIAS/Test/src/Settings/MainSettings/SettingsQuestionBehaviour.php @@ -24,19 +24,17 @@ use ILIAS\Test\Logging\AdditionalInformationGenerator; use ILIAS\UI\Component\Input\Field\Factory as FieldFactory; use ILIAS\UI\Component\Input\Container\Form\FormInput; -use ILIAS\UI\Component\Input\Field\Radio; use ILIAS\UI\Component\Input\Field\OptionalGroup; use ILIAS\Refinery\Factory as Refinery; use ILIAS\Refinery\Transformation; use ILIAS\Refinery\Constraint; +use ILIAS\UI\Implementation\Component\Input\Field\SwitchableGroup; class SettingsQuestionBehaviour extends TestSettings { private const DEFAULT_AUTOSAVE_INTERVAL = 30000; public const ANSWER_FIXATION_NONE = 'none'; - public const ANSWER_FIXATION_ON_INSTANT_FEEDBACK = 'instant_feedback'; - public const ANSWER_FIXATION_ON_FOLLOWUP_QUESTION = 'followup_question'; public const ANSWER_FIXATION_ON_IFB_OR_FUQST = 'ifb_or_fuqst'; public function __construct( @@ -271,65 +269,45 @@ private function getInputLockAnswers( FieldFactory $f, Refinery $refinery, array $environment - ): Radio { - $lock_answers = $f->radio( - $lng->txt('tst_answer_fixation_handling') - )->withOption( - self::ANSWER_FIXATION_NONE, - $lng->txt('tst_answer_fixation_none'), - $lng->txt('tst_answer_fixation_none_desc') - )->withOption( - self::ANSWER_FIXATION_ON_INSTANT_FEEDBACK, - $lng->txt('tst_answer_fixation_on_instant_feedback'), - $lng->txt('tst_answer_fixation_on_instant_feedback_desc') - )->withOption( - self::ANSWER_FIXATION_ON_FOLLOWUP_QUESTION, - $lng->txt('tst_answer_fixation_on_followup_question'), - $lng->txt('tst_answer_fixation_on_followup_question_desc') - )->withOption( - self::ANSWER_FIXATION_ON_IFB_OR_FUQST, - $lng->txt('tst_answer_fixation_on_instantfb_or_followupqst'), - $lng->txt('tst_answer_fixation_on_instantfb_or_followupqst_desc') - )->withValue( - $this->getAnswerFixationSettingsAsFormValue() - )->withAdditionalTransformation($this->getTransformationLockAnswers($refinery)); + ): SwitchableGroup { + $constraint = $refinery->custom()->constraint( + static fn(?array $vs): bool => $vs === null || array_filter($vs[1]) !== [], + $lng->txt('select_at_least_one_lock_answer_type') + ); - if (!$environment['participant_data_exists']) { - return $lock_answers; - } + $group1 = $f->group([], $lng->txt('tst_answer_fixation_none')); + + $group2 = $f->group( + [ + 'lock_answer_on_instant_feedback' => $f->checkbox( + $lng->txt('tst_answer_fixation_on_instant_feedback'), + $lng->txt('tst_answer_fixation_on_instant_feedback_desc') + ), + 'lock_answer_on_next_question' => $f->checkbox( + $lng->txt('tst_answer_fixation_on_followup_question'), + $lng->txt('tst_answer_fixation_on_followup_question_desc') + ) + ], + $lng->txt('tst_answer_fixation'), + $lng->txt('tst_answer_fixation_on_instantfb_or_followupqst_desc') + )->withRequired(true); - return $lock_answers->withDisabled(true); + return $f->switchableGroup( + [self::ANSWER_FIXATION_NONE => $group1, self::ANSWER_FIXATION_ON_IFB_OR_FUQST => $group2], + $lng->txt('tst_answer_fixation_handling') + ) + ->withAdditionalTransformation($constraint) + ->withAdditionalTransformation($this->getTransformationLockAnswers($refinery)) + ->withValue($this->getAnswerFixationSettingsAsFormValue()) + ->withDisabled($environment['participant_data_exists']); } private function getTransformationLockAnswers(Refinery $refinery): Transformation { return $refinery->custom()->transformation( - static function (?string $v): array { - if ($v === null || $v === self::ANSWER_FIXATION_NONE) { - return [ - 'lock_answer_on_instant_feedback' => false, - 'lock_answer_on_next_question' => false - ]; - } - - if ($v === self::ANSWER_FIXATION_ON_INSTANT_FEEDBACK) { - return [ - 'lock_answer_on_instant_feedback' => true, - 'lock_answer_on_next_question' => false - ]; - } - if ($v === self::ANSWER_FIXATION_ON_FOLLOWUP_QUESTION) { - return [ - 'lock_answer_on_instant_feedback' => false, - 'lock_answer_on_next_question' => true - ]; - } - - return [ - 'lock_answer_on_instant_feedback' => true, - 'lock_answer_on_next_question' => true - ]; - } + static fn(?array $v): array => ($v[0] ?? null) === self::ANSWER_FIXATION_ON_IFB_OR_FUQST + ? $v[1] + : ['lock_answer_on_instant_feedback' => false, 'lock_answer_on_next_question' => false] ); } @@ -577,21 +555,18 @@ public function withLockAnswerOnNextQuestionEnabled(bool $lock_answer_on_next_qu return $clone; } - private function getAnswerFixationSettingsAsFormValue(): string + private function getAnswerFixationSettingsAsFormValue(): array { - if ($this->getLockAnswerOnInstantFeedbackEnabled() - && $this->getLockAnswerOnNextQuestionEnabled()) { - return self::ANSWER_FIXATION_ON_IFB_OR_FUQST; - } - - if ($this->getLockAnswerOnInstantFeedbackEnabled()) { - return self::ANSWER_FIXATION_ON_INSTANT_FEEDBACK; - } - - if ($this->getLockAnswerOnNextQuestionEnabled()) { - return self::ANSWER_FIXATION_ON_FOLLOWUP_QUESTION; + if ($this->getLockAnswerOnInstantFeedbackEnabled() || $this->getLockAnswerOnNextQuestionEnabled()) { + return [ + 0 => self::ANSWER_FIXATION_ON_IFB_OR_FUQST, + 1 => [ + 'lock_answer_on_instant_feedback' => $this->getLockAnswerOnInstantFeedbackEnabled(), + 'lock_answer_on_next_question' => $this->getLockAnswerOnNextQuestionEnabled() + ] + ]; } - return self::ANSWER_FIXATION_NONE; + return [0 => self::ANSWER_FIXATION_NONE, 1 => []]; } } diff --git a/lang/ilias_de.lang b/lang/ilias_de.lang index 46d1bbe16e62..02bde36448a0 100644 --- a/lang/ilias_de.lang +++ b/lang/ilias_de.lang @@ -1233,6 +1233,7 @@ assessment#:#search_groups#:#nach Gruppen assessment#:#search_roles#:#nach Rollen assessment#:#search_term#:#Suchbegriff assessment#:#select_at_least_one_feedback_type_and_trigger#:#Bitte mindestens eine Art der Rückmeldung und einen Auslöser auswählen. +assessment#:#select_at_least_one_lock_answer_type#:#Bitte mindestens eine Art der Antwort Festschreibung auswählen. assessment#:#select_gap#:#Auswahl-Lücke assessment#:#select_max_one_item#:#Bitte wählen Sie nur ein Objekt aus! assessment#:#select_one_user#:#Bitte wählen Sie mindestens einen Benutzer aus! @@ -1364,6 +1365,7 @@ assessment#:#tst_anonymity_no_anonymization#:#Testergebnisse mit Namen assessment#:#tst_answer_aggr_answer_header#:#Antwort assessment#:#tst_answer_aggr_frequency_header#:#Häufigkeit assessment#:#tst_answer_details#:#Antwortdetails +assessment#:#tst_answer_fixation#:#Antworten festschreiben assessment#:#tst_answer_fixation_handling#:#Teilnehmerantworten assessment#:#tst_answer_fixation_none#:#Antworten während des Testdurchlaufs nicht festschreiben assessment#:#tst_answer_fixation_none_desc#:#Solange ein Testdurchlauf nicht beendet ist, können Teilnehmer ihre Antworten beliebig verändern. diff --git a/lang/ilias_en.lang b/lang/ilias_en.lang index 248fc4923eb2..0852826081e3 100755 --- a/lang/ilias_en.lang +++ b/lang/ilias_en.lang @@ -1233,6 +1233,7 @@ assessment#:#search_groups#:#Search Groups assessment#:#search_roles#:#Search Roles assessment#:#search_term#:#Search Term assessment#:#select_at_least_one_feedback_type_and_trigger#:#Please Select at least one type of feedback and a trigger. +assessment#:#select_at_least_one_lock_answer_type#:#Please select at least one type of answer lock. assessment#:#select_gap#:#Select Gap assessment#:#select_max_one_item#:#Please select one item only assessment#:#select_one_user#:#Please select at least one user. @@ -1364,6 +1365,7 @@ assessment#:#tst_anonymity_no_anonymization#:#Results With Names assessment#:#tst_answer_aggr_answer_header#:#Answer assessment#:#tst_answer_aggr_frequency_header#:#Frequency assessment#:#tst_answer_details#:#Answer Details +assessment#:#tst_answer_fixation#:#Lock Answers assessment#:#tst_answer_fixation_handling#:#Answer Lock assessment#:#tst_answer_fixation_none#:#Do Not Lock Answers assessment#:#tst_answer_fixation_none_desc#:#As long as a participant has not finished a test attempt (i.e. by clicking on ‘Finish the Test’), they can change their answers at any time.