Skip to content

Commit 07ce3ce

Browse files
committed
Adds auto open of exam modal if test password is wrong
1 parent 4d76c59 commit 07ce3ce

File tree

3 files changed

+79
-95
lines changed

3 files changed

+79
-95
lines changed

components/ILIAS/Test/src/Presentation/class.TestScreenGUI.php

Lines changed: 66 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
use ILIAS\Data\Link;
2828
use ILIAS\Data\Result;
2929
use ILIAS\Data\Password;
30+
use ILIAS\UI\Implementation\Component\Launcher\Inline;
3031
use ILIAS\UI\Component\Launcher\Launcher;
3132
use ILIAS\UI\Component\Launcher\Factory as LauncherFactory;
3233
use ILIAS\UI\Component\MessageBox\MessageBox;
@@ -315,6 +316,7 @@ function (Result $result) {
315316
&& $request->getQueryParams()[$key] === 'exam_modal') {
316317
$launcher = $launcher->withRequest($request);
317318
}
319+
318320
return $launcher;
319321
}
320322

@@ -330,7 +332,15 @@ private function getModalLauncherInputs(): array
330332
$modal_inputs['exam_conditions'] = $this->ui_factory->input()->field()->checkbox(
331333
$this->lng->txt('tst_exam_conditions'),
332334
$this->lng->txt('tst_exam_conditions_label')
333-
)->withRequired(true);
335+
)->withRequired(true)
336+
->withAdditionalTransformation(
337+
$this->refinery->custom()->constraint(
338+
function (bool $value): bool {
339+
return $value === true;
340+
},
341+
fn($lng_closure, $value) => $this->lng->txt('tst_exam_conditions_not_checked_message'),
342+
)
343+
);
334344
}
335345

336346
if ($this->main_settings->getAccessSettings()->getPasswordEnabled()) {
@@ -340,10 +350,12 @@ private function getModalLauncherInputs(): array
340350
)->withRevelation(true)
341351
->withRequired(true)
342352
->withAdditionalTransformation(
343-
$this->refinery->custom()->transformation(
344-
static function (Password $value): string {
345-
return $value->toString();
346-
}
353+
$this->refinery->custom()->constraint(
354+
function (Password $value): bool {
355+
$access_settings_password = $this->main_settings->getAccessSettings()->getPassword();
356+
return $value->toString() === $access_settings_password;
357+
},
358+
fn($lng_closure, $value) => $this->lng->txt('tst_exam_password_invalid_message'),
347359
)
348360
);
349361
}
@@ -352,6 +364,11 @@ static function (Password $value): string {
352364
$access_code_input = $this->ui_factory->input()->field()->text(
353365
$this->lng->txt('tst_exam_access_code'),
354366
$this->lng->txt('tst_exam_access_code_label')
367+
)->withAdditionalTransformation(
368+
$this->refinery->custom()->constraint(
369+
fn(string $value): bool => !empty($value),
370+
fn($lng_closure, $value) => $this->lng->txt('tst_exam_access_code_required_message'),
371+
)
355372
);
356373

357374
$access_code_from_session = $this->test_session->getAccessCodeFromSession();
@@ -362,11 +379,17 @@ static function (Password $value): string {
362379
$modal_inputs['exam_access_code'] = $access_code_input;
363380
}
364381

365-
if ($this->main_settings->getParticipantFunctionalitySettings()->getUsePreviousAnswerAllowed()
366-
&& $this->test_passes_selector->getLastFinishedPass() >= 0) {
382+
if (
383+
$this->test_passes_selector->getLastFinishedPass() >= 0
384+
&& $this->main_settings->getParticipantFunctionalitySettings()->getUsePreviousAnswerAllowed()
385+
) {
367386
$modal_inputs['exam_use_previous_answers'] = $this->ui_factory->input()->field()->checkbox(
368387
$this->lng->txt('tst_exam_use_previous_answers'),
369388
$this->lng->txt('tst_exam_use_previous_answers_label')
389+
)->withAdditionalTransformation(
390+
$this->refinery->custom()->transformation(
391+
fn($value) => (string) (int) ($value ?? false)
392+
)
370393
);
371394
}
372395

@@ -400,95 +423,48 @@ private function getStartLauncherLink(): Link
400423

401424
private function evaluateLauncherModalForm(Result $result): void
402425
{
403-
if ($result->isOK()) {
404-
$conditions_met = true;
405-
$message = '';
406-
$access_settings_password = $this->main_settings->getAccessSettings()->getPassword();
407-
$anonymous = $this->user->isAnonymous();
408-
foreach ($result->value() as $key => $value) {
409-
410-
switch ($key) {
411-
case 'exam_conditions':
412-
$exam_conditions_value = (bool) $value;
413-
if (!$exam_conditions_value) {
414-
$conditions_met = false;
415-
$message .= $this->lng->txt('tst_exam_conditions_not_checked_message') . '<br>';
416-
}
417-
break;
418-
case 'exam_password':
419-
$password = $value;
420-
$exam_password_valid = ($password === $access_settings_password);
421-
if (!$exam_password_valid) {
422-
$conditions_met = false;
423-
$message .= $this->lng->txt('tst_exam_password_invalid_message') . '<br>';
424-
if ($this->object->getTestLogger()->isLoggingEnabled()
425-
&& !$this->object->getAnonymity()) {
426-
$logger = $this->object->getTestLogger();
427-
$logger->logParticipantInteraction(
428-
$logger->getInteractionFactory()->buildParticipantInteraction(
429-
$this->ref_id,
430-
null,
431-
$this->user->getId(),
432-
$_SERVER['REMOTE_ADDR'],
433-
TestParticipantInteractionTypes::WRONG_TEST_PASSWORD_PROVIDED,
434-
[]
435-
)
436-
);
437-
}
438-
}
439-
$this->password_checker->setUserEnteredPassword($password);
440-
break;
441-
case 'exam_access_code':
442-
if ($anonymous && !empty($value)) {
443-
$this->test_session->setAccessCodeToSession($value);
444-
} else {
445-
$this->test_session->unsetAccessCodeInSession();
446-
}
447-
break;
448-
case 'exam_use_previous_answers':
449-
$exam_use_previous_answers_value = (string) (int) $value;
450-
break;
451-
}
452-
}
453-
454-
if ($message !== '') {
455-
$this->tpl->setOnScreenMessage(\ilGlobalTemplateInterface::MESSAGE_TYPE_FAILURE, $message, true);
456-
}
457-
458-
if (empty($result->value())) {
459-
$this->tpl->setOnScreenMessage(
460-
\ilGlobalTemplateInterface::MESSAGE_TYPE_FAILURE,
461-
$this->lng->txt('tst_exam_required_fields_not_filled_message'),
462-
true
463-
);
464-
} elseif ($conditions_met) {
465-
if (
466-
!$anonymous &&
467-
$this->main_settings->getParticipantFunctionalitySettings()->getUsePreviousAnswerAllowed()
468-
) {
469-
$this->user->setPref('tst_use_previous_answers', $exam_use_previous_answers_value ?? '0');
470-
$this->user->update();
471-
}
472-
473-
if (isset($password) && $password === $access_settings_password) {
474-
\ilSession::set('tst_password_' . $this->object->getTestId(), $password);
475-
} else {
476-
\ilSession::set('tst_password_' . $this->object->getTestId(), '');
477-
$this->test_session->setPasswordChecked(false);
478-
}
479-
480-
$this->ctrl->redirectByClass(
481-
(new \ilTestPlayerFactory($this->object))->getPlayerGUI()::class,
482-
\ilTestPlayerCommands::INIT_TEST
483-
);
484-
}
485-
} else {
426+
if (empty($result->value()) || $result->isError()) {
486427
$this->tpl->setOnScreenMessage(
487428
\ilGlobalTemplateInterface::MESSAGE_TYPE_FAILURE,
488429
$this->lng->txt('tst_exam_required_fields_not_filled_message'),
489430
true
490431
);
432+
return;
433+
}
434+
435+
$anonymous = $this->user->isAnonymous();
436+
if (array_key_exists('exam_access_code', $result->value())) {
437+
$value = $result->value()['exam_access_code'];
438+
if ($anonymous && !empty($value)) {
439+
$this->test_session->setAccessCodeToSession($value);
440+
} else {
441+
$this->test_session->unsetAccessCodeInSession();
442+
}
443+
}
444+
445+
if (
446+
!$anonymous &&
447+
$this->main_settings->getParticipantFunctionalitySettings()->getUsePreviousAnswerAllowed()
448+
) {
449+
$this->user->setPref(
450+
'tst_use_previous_answers',
451+
$result->value()['exam_use_previous_answers'] ?? '0'
452+
);
453+
$this->user->update();
491454
}
455+
456+
$password = $result->value()['exam_password']->toString() ?? '';
457+
if ($password === $this->main_settings->getAccessSettings()->getPassword()) {
458+
\ilSession::set('tst_password_' . $this->object->getTestId(), $password);
459+
} else {
460+
\ilSession::set('tst_password_' . $this->object->getTestId(), '');
461+
$this->test_session->setPasswordChecked(false);
462+
}
463+
464+
$this->ctrl->redirectByClass(
465+
(new \ilTestPlayerFactory($this->object))->getPlayerGUI()::class,
466+
\ilTestPlayerCommands::INIT_TEST
467+
);
492468
}
493469

494470
private function testCanBeStarted(): bool

components/ILIAS/UI/src/Implementation/Component/Launcher/Inline.php

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -135,17 +135,21 @@ public function withRequest(ServerRequestInterface $request): self
135135
{
136136
$clone = clone $this;
137137
$clone->request = $request;
138+
139+
if ($request->getMethod() === 'POST') {
140+
$clone->modal = $clone->modal->withRequest($request);
141+
}
142+
138143
return $clone;
139144
}
140145

141146
public function getResult(): ?Result
142147
{
143-
if ($this->request && $this->request->getMethod() == "POST") {
144-
$modal = $this->modal->withRequest($this->request);
145-
$result = $modal->getForm()->getInputGroup()->getContent();
146-
return $result;
148+
try {
149+
return $this->modal?->getForm()?->getInputGroup()?->getContent();
150+
} catch (\Throwable) {
151+
return null;
147152
}
148-
return null;
149153
}
150154

151155
public function getModal(): ?Modal\Roundtrip

components/ILIAS/UI/src/Implementation/Component/Launcher/Renderer.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,10 @@ public function renderInline(Inline $component, RendererInterface $default_rende
5252
$start_button = $ui_factory->button()->bulky($launch_glyph, $label, (string) $target);
5353

5454
if ($modal = $component->getModal()) {
55+
if ($result && $result->isError()) {
56+
$modal = $modal->withOnLoad($modal->getShowSignal());
57+
}
58+
5559
if ($modal_submit_lable = $component->getModalSubmitLabel()) {
5660
$modal = $modal->withSubmitLabel($modal_submit_lable);
5761
}

0 commit comments

Comments
 (0)