diff --git a/components/ILIAS/Test/classes/class.ilTestParticipantsGUI.php b/components/ILIAS/Test/classes/class.ilTestParticipantsGUI.php index d95218e7aeec..642502e92453 100755 --- a/components/ILIAS/Test/classes/class.ilTestParticipantsGUI.php +++ b/components/ILIAS/Test/classes/class.ilTestParticipantsGUI.php @@ -198,6 +198,7 @@ private function getParticipantTable(): ParticipantTable $this->ui_factory, $this->ui_service, $this->lng, + $this->ctrl, $this->test_access, $this->testrequest, $this->participant_access_filter, diff --git a/components/ILIAS/Test/lang/assessment.pot b/components/ILIAS/Test/lang/assessment.pot index fbb760820262..eaade01c0060 100644 --- a/components/ILIAS/Test/lang/assessment.pot +++ b/components/ILIAS/Test/lang/assessment.pot @@ -3812,6 +3812,12 @@ msgstr "" msgid "tst_participant_fullname_pattern" msgstr "" +msgid "tst_participant_last_attempts" +msgstr "" + +msgid "tst_participant_scored_attempts" +msgstr "" + msgid "tst_participant_status" msgstr "" diff --git a/components/ILIAS/Test/lang/assessment_de.po b/components/ILIAS/Test/lang/assessment_de.po index 8d5c2e3066f2..b3ea85bafd48 100644 --- a/components/ILIAS/Test/lang/assessment_de.po +++ b/components/ILIAS/Test/lang/assessment_de.po @@ -3815,6 +3815,12 @@ msgstr "Teilnehmer" msgid "tst_participant_fullname_pattern" msgstr "%2$s, %1$s" +msgid "tst_participant_last_attempts" +msgstr "Letzte Versuche" + +msgid "tst_participant_scored_attempts" +msgstr "Bewertete Versuche" + msgid "tst_participant_status" msgstr "Teilnehmerstatus" diff --git a/components/ILIAS/Test/lang/assessment_en.po b/components/ILIAS/Test/lang/assessment_en.po index 297eb90717db..0ba9595be24a 100644 --- a/components/ILIAS/Test/lang/assessment_en.po +++ b/components/ILIAS/Test/lang/assessment_en.po @@ -3815,6 +3815,12 @@ msgstr "Participant" msgid "tst_participant_fullname_pattern" msgstr "%2$s, %1$s" +msgid "tst_participant_last_attempts" +msgstr "Last Attempts" + +msgid "tst_participant_scored_attempts" +msgstr "Scored Attempts" + msgid "tst_participant_status" msgstr "Participant Status" diff --git a/components/ILIAS/Test/src/Participants/AttemptSpecifiers.php b/components/ILIAS/Test/src/Participants/AttemptSpecifiers.php new file mode 100644 index 000000000000..bc5c2f897ada --- /dev/null +++ b/components/ILIAS/Test/src/Participants/AttemptSpecifiers.php @@ -0,0 +1,57 @@ + null, + self::LastAttempt => $participant->getLastStartedAttempt(), + }; + } + + public function buildViewControl(\ilCtrl $ctrl, Language $lng, UIFactory $ui_factory): Mode + { + $target_class = \ilTestParticipantsGUI::class; + $actions = []; + + foreach (self::cases() as $case) { + $ctrl->setParameterByClass($target_class, 'view_mode', $case->value); + $actions[$lng->txt($case->value)] = $ctrl->getLinkTargetByClass($target_class); + } + + $ctrl->clearParametersByClass($target_class); + + return $ui_factory->viewControl()->mode( + $actions, + $lng->txt('participant_view_control_aria') + )->withActive($lng->txt($this->value)); + } +} diff --git a/components/ILIAS/Test/src/Participants/ParticipantTable.php b/components/ILIAS/Test/src/Participants/ParticipantTable.php index bf412493d1d5..78f3a7192cd9 100644 --- a/components/ILIAS/Test/src/Participants/ParticipantTable.php +++ b/components/ILIAS/Test/src/Participants/ParticipantTable.php @@ -39,13 +39,16 @@ class ParticipantTable implements DataRetrieval { private const ID = 'pt'; + private ?iterable $records = null; private bool $scoring_enabled = false; + private AttemptSpecifiers $attempt_specifier; public function __construct( private readonly UIFactory $ui_factory, private readonly \ilUIService $ui_service, private readonly Language $lng, + private readonly \ilCtrl $ctrl, private readonly \ilTestAccess $test_access, private readonly RequestDataCollector $test_request, private readonly \ilTestParticipantAccessFilterFactory $participant_access_filter, @@ -57,6 +60,7 @@ public function __construct( private readonly ParticipantTableActions $table_actions ) { $this->scoring_enabled = $this->test_object->getGlobalSettings()->isManualScoringEnabled(); + $this->attempt_specifier = AttemptSpecifiers::tryFrom($this->test_request->getViewMode()) ?? AttemptSpecifiers::LastAttempt; } public function execute(URLBuilder $url_builder): ?Modal @@ -85,6 +89,7 @@ public function getComponents(URLBuilder $url_builder, string $filter_url): arra return [ $summary_information, + $this->attempt_specifier->buildViewControl($this->ctrl, $this->lng, $this->ui_factory), $filter, $table->withActions($this->table_actions->getEnabledActions(...$this->acquireParameters($url_builder))) ]; @@ -479,10 +484,10 @@ private function getColumns(): array return $columns; } - private function loadRecords(?array $filter, Order $order): iterable + private function loadRecords(?array $filter, Order $order): void { if ($this->records !== null) { - return $this->records; + return; } $records = iterator_to_array( @@ -493,14 +498,31 @@ private function loadRecords(?array $filter, Order $order): iterable $order ) ); - - $this->records = array_filter( - $records, - fn(Participant $participant) => in_array( - $participant->getUserId(), - $this->buildAccessFilteredParticipantsList($records) - ) + $accessible_user_ids = $this->buildAccessFilteredParticipantsList($records); + + $this->records = $this->results_data_factory->addAttemptOverviewInformationToParticipants( + $this->results_presentation_settings, + $this->test_object, + array_filter( + $records, + static fn(Participant $participant): bool => in_array( + $participant->getUserId(), + $accessible_user_ids, + true + ) + ), + $this->attempt_specifier ); + } + + /** + * @return iterable + */ + private function retrieveRecords(?array $filter, Order $order): iterable + { + if ($this->records === null) { + $this->loadRecords($filter, $order); + } return $this->records; } @@ -532,11 +554,7 @@ private function getViewControlledRecords(?array $filter_data, Range $range, Ord return $this->limitRecords( $this->orderRecords( $this->filterRecords( - $this->results_data_factory->addAttemptOverviewInformationToParticipants( - $this->results_presentation_settings, - $this->test_object, - $this->loadRecords($filter_data, $order) - ), + $this->retrieveRecords($filter_data, $order), $filter_data ), $order diff --git a/components/ILIAS/Test/src/RequestDataCollector.php b/components/ILIAS/Test/src/RequestDataCollector.php index 900688853024..489931b4ebaa 100755 --- a/components/ILIAS/Test/src/RequestDataCollector.php +++ b/components/ILIAS/Test/src/RequestDataCollector.php @@ -96,6 +96,11 @@ public function getPassId(): int return $this->int('pass_id'); } + public function getViewMode(): string + { + return $this->str('view_mode'); + } + public function retrieveBoolFromPost(string $key): ?bool { if (!$this->http->wrapper()->post()->has($key)) { diff --git a/components/ILIAS/Test/src/Results/Data/Factory.php b/components/ILIAS/Test/src/Results/Data/Factory.php index bc62db91dcf7..0cdf30501e67 100644 --- a/components/ILIAS/Test/src/Results/Data/Factory.php +++ b/components/ILIAS/Test/src/Results/Data/Factory.php @@ -21,6 +21,7 @@ namespace ILIAS\Test\Results\Data; use ILIAS\Test\Results\Presentation\Settings as ResultPresentationSettings; +use ILIAS\Test\Participants\AttemptSpecifiers; use ILIAS\Test\Participants\Participant; use ILIAS\UI\Factory as UIFactory; use ILIAS\UI\Renderer as UIRenderer; @@ -130,36 +131,37 @@ public function getAttemptOverviewFor( /** * - * @param array $participants - * @return array + * @param array $participants + * @return array */ public function addAttemptOverviewInformationToParticipants( ResultPresentationSettings $settings, \ilObjTest $test_obj, - array $participants + array $participants, + AttemptSpecifiers $attempt_specifier ): array { return array_map( - function (Participant $v) use ($settings, $test_obj, $participants): Participant { + function (Participant $v) use ($settings, $test_obj, $attempt_specifier): Participant { if ($v->getActiveId() === null) { return $v; } - $scored_attempt = $this->getAttemptOverviewFor( + $attempt_overview = $this->getAttemptOverviewFor( $settings, $test_obj, $v->getActiveId(), - null + $attempt_specifier->getAttemptId($v) ); - if ($scored_attempt !== null - && $scored_attempt->getStatusOfAttempt() === StatusOfAttempt::RUNNING - && $scored_attempt->getStartedDate() !== null) { - $v = $v->withRunningAttemptStart($scored_attempt->getStartedDate()); + if ( + $attempt_overview !== null + && $attempt_overview->getStatusOfAttempt() === StatusOfAttempt::RUNNING + && $attempt_overview->getStartedDate() !== null + ) { + $v = $v->withRunningAttemptStart($attempt_overview->getStartedDate()); } - return $v->withAttemptOverviewInformation( - $scored_attempt - ); + return $v->withAttemptOverviewInformation($attempt_overview); }, $participants );