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/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 5072dafaf681..2aeb8e128ea8 100644 --- a/components/ILIAS/Test/src/Participants/ParticipantTable.php +++ b/components/ILIAS/Test/src/Participants/ParticipantTable.php @@ -39,12 +39,15 @@ class ParticipantTable implements DataRetrieval { private const ID = 'pt'; + private ?iterable $records = null; + 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, @@ -55,6 +58,7 @@ public function __construct( private readonly \ilObjTest $test_object, private readonly ParticipantTableActions $table_actions ) { + $this->attempt_specifier = AttemptSpecifiers::tryFrom($this->test_request->getViewMode()) ?? AttemptSpecifiers::LastAttempt; } public function execute(URLBuilder $url_builder): ?Modal @@ -83,6 +87,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))) ]; @@ -443,10 +448,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( @@ -457,14 +462,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; } @@ -496,11 +518,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 454e70194012..6aea5e2afb2e 100755 --- a/components/ILIAS/Test/src/RequestDataCollector.php +++ b/components/ILIAS/Test/src/RequestDataCollector.php @@ -26,8 +26,6 @@ use ILIAS\Repository\BaseGUIRequest; use Psr\Http\Message\ServerRequestInterface; -use function array_map; - class RequestDataCollector { use BaseGUIRequest; @@ -97,6 +95,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 a0d9df74637f..41982a0240f1 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; @@ -131,36 +132,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 ); diff --git a/lang/ilias_de.lang b/lang/ilias_de.lang index 25bf1a56d9a1..7c97f1eec83d 100644 --- a/lang/ilias_de.lang +++ b/lang/ilias_de.lang @@ -1696,6 +1696,8 @@ assessment#:#tst_optional_questions_confirmation_non_fixed_test#:#Fragen zu b assessment#:#tst_out_of_time_message#:#Sie haben die maximal erlaubte Bearbeitungszeit des Tests erreicht! assessment#:#tst_participant#:#Teilnehmer assessment#:#tst_participant_fullname_pattern#:#%2$s, %1$s +assessment#:#tst_participant_last_attempts#:#Letzte Versuche +assessment#:#tst_participant_scored_attempts#:#Bewertete Versuche assessment#:#tst_participant_status#:#Teilnehmerstatus assessment#:#tst_participating_users#:#Teilnehmende Benutzer assessment#:#tst_pass_best_pass#:#Besten Durchlauf des Tests bewerten diff --git a/lang/ilias_en.lang b/lang/ilias_en.lang index f0b0e40da4b1..f916c2a10aee 100755 --- a/lang/ilias_en.lang +++ b/lang/ilias_en.lang @@ -1696,6 +1696,8 @@ assessment#:#tst_optional_questions_confirmation_non_fixed_test#:#Questions f assessment#:#tst_out_of_time_message#:#You have reached the maximum allowed processing time of the test! assessment#:#tst_participant#:#Participant assessment#:#tst_participant_fullname_pattern#:#%2$s, %1$s +assessment#:#tst_participant_last_attempts#:#Last Attempts +assessment#:#tst_participant_scored_attempts#:#Scored Attempts assessment#:#tst_participant_status#:#Participant Status assessment#:#tst_participating_users#:#Participating Users assessment#:#tst_pass_best_pass#:#Score the Best Attempt