diff --git a/components/ILIAS/Test/classes/class.ilTestSession.php b/components/ILIAS/Test/classes/class.ilTestSession.php index 813d083d24cb..45b2e9a1a0c1 100755 --- a/components/ILIAS/Test/classes/class.ilTestSession.php +++ b/components/ILIAS/Test/classes/class.ilTestSession.php @@ -456,15 +456,11 @@ public function createNewAccessCode(): string public function isAccessCodeUsed(string $code): bool { - $query = "SELECT anonymous_id FROM tst_active WHERE test_fi = %s AND anonymous_id = %s"; - - $result = $this->db->queryF( - $query, - ['integer', 'text'], + return $this->db->queryF( + 'SELECT anonymous_id FROM tst_active WHERE test_fi = %s AND anonymous_id = %s', + [ilDBConstants::T_INTEGER, ilDBConstants::T_TEXT], [$this->getTestId(), $code] - ); - - return ($result->numRows() > 0); + )->rowCount() > 0; } private function buildAccessCode(): string diff --git a/components/ILIAS/Test/src/Presentation/class.TestScreenGUI.php b/components/ILIAS/Test/src/Presentation/class.TestScreenGUI.php index c5033369bc96..9c00a1a76842 100755 --- a/components/ILIAS/Test/src/Presentation/class.TestScreenGUI.php +++ b/components/ILIAS/Test/src/Presentation/class.TestScreenGUI.php @@ -27,6 +27,7 @@ use ILIAS\Data\Link; use ILIAS\Data\Result; use ILIAS\Data\Password; +use ILIAS\UI\Implementation\Component\Launcher\Inline; use ILIAS\UI\Component\Launcher\Launcher; use ILIAS\UI\Component\Launcher\Factory as LauncherFactory; use ILIAS\UI\Component\MessageBox\MessageBox; @@ -315,6 +316,7 @@ function (Result $result) { && $request->getQueryParams()[$key] === 'exam_modal') { $launcher = $launcher->withRequest($request); } + return $launcher; } @@ -330,7 +332,13 @@ private function getModalLauncherInputs(): array $modal_inputs['exam_conditions'] = $this->ui_factory->input()->field()->checkbox( $this->lng->txt('tst_exam_conditions'), $this->lng->txt('tst_exam_conditions_label') - )->withRequired(true); + )->withRequired(true) + ->withAdditionalTransformation( + $this->refinery->custom()->constraint( + static fn(bool $value): bool => $value, + $this->lng->txt('tst_exam_conditions_not_checked_message'), + ) + ); } if ($this->main_settings->getAccessSettings()->getPasswordEnabled()) { @@ -340,10 +348,9 @@ private function getModalLauncherInputs(): array )->withRevelation(true) ->withRequired(true) ->withAdditionalTransformation( - $this->refinery->custom()->transformation( - static function (Password $value): string { - return $value->toString(); - } + $this->refinery->custom()->constraint( + fn(Password $value): bool => $value->toString() === $this->main_settings->getAccessSettings()->getPassword(), + $this->lng->txt('tst_exam_password_invalid_message'), ) ); } @@ -352,6 +359,11 @@ static function (Password $value): string { $access_code_input = $this->ui_factory->input()->field()->text( $this->lng->txt('tst_exam_access_code'), $this->lng->txt('tst_exam_access_code_label') + )->withAdditionalTransformation( + $this->refinery->custom()->constraint( + fn(string $value): bool => $value === '' || $this->test_session->isAccessCodeUsed($value), + $this->lng->txt('tst_exam_access_code_required_message'), + ) ); $access_code_from_session = $this->test_session->getAccessCodeFromSession(); @@ -362,11 +374,17 @@ static function (Password $value): string { $modal_inputs['exam_access_code'] = $access_code_input; } - if ($this->main_settings->getParticipantFunctionalitySettings()->getUsePreviousAnswerAllowed() - && $this->test_passes_selector->getLastFinishedPass() >= 0) { + if ( + $this->test_passes_selector->getLastFinishedPass() >= 0 + && $this->main_settings->getParticipantFunctionalitySettings()->getUsePreviousAnswerAllowed() + ) { $modal_inputs['exam_use_previous_answers'] = $this->ui_factory->input()->field()->checkbox( $this->lng->txt('tst_exam_use_previous_answers'), $this->lng->txt('tst_exam_use_previous_answers_label') + )->withAdditionalTransformation( + $this->refinery->custom()->transformation( + static fn(bool $value): string => $value ? '1' : '0' + ) ); } @@ -400,95 +418,43 @@ private function getStartLauncherLink(): Link private function evaluateLauncherModalForm(Result $result): void { - if ($result->isOK()) { - $conditions_met = true; - $message = ''; - $access_settings_password = $this->main_settings->getAccessSettings()->getPassword(); - $anonymous = $this->user->isAnonymous(); - foreach ($result->value() as $key => $value) { - - switch ($key) { - case 'exam_conditions': - $exam_conditions_value = (bool) $value; - if (!$exam_conditions_value) { - $conditions_met = false; - $message .= $this->lng->txt('tst_exam_conditions_not_checked_message') . '
'; - } - break; - case 'exam_password': - $password = $value; - $exam_password_valid = ($password === $access_settings_password); - if (!$exam_password_valid) { - $conditions_met = false; - $message .= $this->lng->txt('tst_exam_password_invalid_message') . '
'; - if ($this->object->getTestLogger()->isLoggingEnabled() - && !$this->object->getAnonymity()) { - $logger = $this->object->getTestLogger(); - $logger->logParticipantInteraction( - $logger->getInteractionFactory()->buildParticipantInteraction( - $this->ref_id, - null, - $this->user->getId(), - $_SERVER['REMOTE_ADDR'], - TestParticipantInteractionTypes::WRONG_TEST_PASSWORD_PROVIDED, - [] - ) - ); - } - } - $this->password_checker->setUserEnteredPassword($password); - break; - case 'exam_access_code': - if ($anonymous && !empty($value)) { - $this->test_session->setAccessCodeToSession($value); - } else { - $this->test_session->unsetAccessCodeInSession(); - } - break; - case 'exam_use_previous_answers': - $exam_use_previous_answers_value = (string) (int) $value; - break; - } - } + if ($result->isError()) { + return; + } - if ($message !== '') { - $this->tpl->setOnScreenMessage(\ilGlobalTemplateInterface::MESSAGE_TYPE_FAILURE, $message, true); + $anonymous = $this->user->isAnonymous(); + if (array_key_exists('exam_access_code', $result->value())) { + $value = $result->value()['exam_access_code']; + if ($anonymous && !empty($value)) { + $this->test_session->setAccessCodeToSession($value); + } else { + $this->test_session->unsetAccessCodeInSession(); } + } - if (empty($result->value())) { - $this->tpl->setOnScreenMessage( - \ilGlobalTemplateInterface::MESSAGE_TYPE_FAILURE, - $this->lng->txt('tst_exam_required_fields_not_filled_message'), - true - ); - } elseif ($conditions_met) { - if ( - !$anonymous && - $this->main_settings->getParticipantFunctionalitySettings()->getUsePreviousAnswerAllowed() - ) { - $this->user->setPref('tst_use_previous_answers', $exam_use_previous_answers_value ?? '0'); - $this->user->update(); - } - - if (isset($password) && $password === $access_settings_password) { - \ilSession::set('tst_password_' . $this->object->getTestId(), $password); - } else { - \ilSession::set('tst_password_' . $this->object->getTestId(), ''); - $this->test_session->setPasswordChecked(false); - } + if ( + !$anonymous && + $this->main_settings->getParticipantFunctionalitySettings()->getUsePreviousAnswerAllowed() + ) { + $this->user->setPref( + 'tst_use_previous_answers', + $result->value()['exam_use_previous_answers'] ?? '0' + ); + $this->user->update(); + } - $this->ctrl->redirectByClass( - (new \ilTestPlayerFactory($this->object))->getPlayerGUI()::class, - \ilTestPlayerCommands::INIT_TEST - ); - } + $password = $result->value()['exam_password']->toString() ?? ''; + if ($password === $this->main_settings->getAccessSettings()->getPassword()) { + \ilSession::set('tst_password_' . $this->object->getTestId(), $password); } else { - $this->tpl->setOnScreenMessage( - \ilGlobalTemplateInterface::MESSAGE_TYPE_FAILURE, - $this->lng->txt('tst_exam_required_fields_not_filled_message'), - true - ); + \ilSession::set('tst_password_' . $this->object->getTestId(), ''); + $this->test_session->setPasswordChecked(false); } + + $this->ctrl->redirectByClass( + (new \ilTestPlayerFactory($this->object))->getPlayerGUI()::class, + \ilTestPlayerCommands::INIT_TEST + ); } private function testCanBeStarted(): bool