ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
AttemptResultsTable.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
22
25use ILIAS\UI\Component\Table\Presentation as PresentationTable;
28use ILIAS\UI\Factory as UIFactory;
29use ILIAS\UI\Renderer as UIRenderer;
31use ILIAS\HTTP\Services as HTTPService;
32use ILIAS\Data\Factory as DataFactory;
34
36{
37 private const ENV = 'e';
38 private const LNG = 'l';
39 private const URL_NAMESPACE = ['taresult', 'vc'];
40 private const PARAM_MODE = 'm';
41 private const MODE_OPT_ALL = "all";
42 private const MODE_OPT_CORRECT = "ok";
43 private const MODE_OPT_INCORRECT = "fail";
44 private const PARAM_SORT = 's';
45 private const SORT_OPT_ORDEROFAPPEARANCE = 'ooa';
46 private const SORT_OPT_POSSIBLESCORE = 'ms';
47
48 protected PresentationTable $table;
49
50 public function __construct(
51 UIFactory $ui_factory,
52 private UIRenderer $ui_renderer,
53 private Refinery $refinery,
54 private HTTPService $http,
55 DataFactory $data_factory,
57 private AttemptSolutions $test_results,
58 Settings $settings,
59 string $title,
60 bool $for_print
61 ) {
62 list($mode, $sortation) = $this->getViewControlsParameter();
63 $results = $this->applyControls($mode, $sortation, $test_results->getQuestionResults());
64 $target = new URLBuilder($data_factory->uri($http->request()->getUri()->__toString()));
65
66 $this->table = $ui_factory->table()->presentation(
67 $title,
68 $for_print ? [] : $this->getViewControls($ui_factory, $lng, $target, $mode, $sortation),
69 $this->getMapping()
70 )
71 ->withEnvironment([
72 self::ENV => $settings,
73 self::LNG => $lng
74 ])
75 ->withData($results);
76 }
77
78 public function render(): string
79 {
80 return $this->ui_renderer->render($this->table);
81 }
82
83 public function getTableComponent(): PresentationTable
84 {
85 return $this->table;
86 }
87
91 private function applyControls(
92 string $mode,
93 string $sortation,
94 array $question_results
95 ) {
96 switch ($mode) {
98 $filter = static fn($qr) => $qr->getCorrect() === QuestionResult::CORRECT_FULL;
99 break;
101 $filter = static fn($qr) => $qr->getCorrect() !== QuestionResult::CORRECT_FULL;
102 break;
104 default:
105 $filter = static fn($qr) => true;
106 }
107 $question_results = array_filter($question_results, $filter);
108
109 if ($sortation === self::SORT_OPT_POSSIBLESCORE) {
110 usort(
111 $question_results,
112 static fn(QuestionResult $a, QuestionResult $b) => $a->getQuestionScore() <=> $b->getQuestionScore()
113 );
114 $question_results = array_reverse($question_results);
115 }
116 return $question_results;
117 }
118
119 private function getViewControlNamespace(): array
120 {
122 $namespace[] = (string) $this->test_results->getActiveId();
123 $namespace[] = (string) $this->test_results->getAttempt();
124 return $namespace;
125 }
126
127 private function getViewControlsParameter(): array
128 {
129 $request = $this->http->wrapper()->query();
131
132 $mode = $request->has($pre . self::PARAM_MODE) ?
133 $request->retrieve($pre . self::PARAM_MODE, $this->refinery->kindlyTo()->string()) : self::MODE_OPT_ALL;
134
135 $sortation = $request->has($pre . self::PARAM_SORT) ?
136 $request->retrieve($pre . self::PARAM_SORT, $this->refinery->kindlyTo()->string()) : self::SORT_OPT_ORDEROFAPPEARANCE;
137
138 return [$mode, $sortation];
139 }
140
144 private function getViewControls(
145 UIFactory $ui_factory,
147 URLBuilder $target,
148 string $mode,
149 string $sortation
150 ): array {
151 $builder = $target->acquireParameter($this->getViewControlNamespace(), self::PARAM_MODE);
152 [$target, $token] = $builder;
153
154 $modes = [
155 $lng->txt('resulttable_all') => $target->withParameter($token, self::MODE_OPT_ALL)->buildURI()->__toString(),
156 $lng->txt('resulttable_correct') => $target->withParameter($token, self::MODE_OPT_CORRECT)->buildURI()->__toString(),
157 $lng->txt('resulttable_incorrect') => $target->withParameter($token, self::MODE_OPT_INCORRECT)->buildURI()->__toString(),
158 ];
160 $active = array_search($mode, $check);
161
162 $vc_mode = $ui_factory->viewControl()->mode($modes, $lng->txt('ta_resulttable_vc_mode_aria'))
163 ->withActive(array_keys($modes)[$active]);
164
165 $options = [
166 self::SORT_OPT_ORDEROFAPPEARANCE => $lng->txt('resulttable_vc_sort_iooa'),
167 self::SORT_OPT_POSSIBLESCORE => $lng->txt('resulttable_vc_sort_posscore')
168 ];
169
171 $vc_sort = $ui_factory->viewControl()->sortation($options, $sortation)->withTargetURL(
172 $target->buildURI()->__toString(),
173 $pre . self::PARAM_SORT
174 );
175
176 return [
177 $vc_mode,
178 $vc_sort
179 ];
180 }
181
182 private function getMapping(): \Closure
183 {
184 return function (PresentationRow $row, QuestionResult $question, UIFactory $ui_factory, array $environment) {
185 $env = $environment[self::ENV];
186 $lng = $environment[self::LNG];
187
188 $title = $this->refinery->encode()->htmlSpecialCharsAsEntities()->transform(
189 $question->getTitle()
190 );
191
192 $important_fields = [
193 $lng->txt('position') => (string) ($question->getPosition() + 1),
194 $lng->txt('question_id') => (string) $question->getId(),
195 $lng->txt('question_type') => $lng->txt($question->getType()),
196 $lng->txt('points') => sprintf(
197 '%s/%s (%s%%)',
198 (string) $question->getUserScore(),
199 (string) $question->getQuestionScore(),
200 (string) $question->getUserScorePercent()
201 )
202 ];
203
204 $stats_fields = $important_fields;
205 $stats = $ui_factory->listing()->characteristicValue()->text($stats_fields);
206
207 $contents = [
208 $stats
209 ];
210
211 if ($recap = $question->getContentForRecapitulation()) {
212 $contents[] = $ui_factory->listing()->descriptive([
213 $lng->txt('suggested_solution') => $recap
214 ]);
215 }
216
217 $user_answer = $question->getUserAnswer();
218 $answer_contents = [
219 $ui_factory->listing()->descriptive([$lng->txt('tst_header_participant') => $user_answer])
220 ];
221 if ($env->getShowBestSolution()) {
222 $answer_contents[] = $ui_factory->listing()->descriptive([
223 $lng->txt('tst_header_solution') => $question->getBestSolution()
224 ]);
225 }
226
227 $answers = $ui_factory->layout()->alignment()->horizontal()->evenlyDistributed(...$answer_contents);
228 $contents[] = $answers;
229
230 $content = $ui_factory->layout()->alignment()->vertical(...$contents);
231
232 switch ($question->getCorrect()) {
234 $icon_name = 'icon_ok.svg';
235 $label = $lng->txt("answer_is_right");
236 break;
238 $icon_name = 'icon_mostly_ok.svg';
239 $label = $lng->txt("answer_is_not_correct_but_positive");
240 break;
242 $icon_name = 'icon_not_ok.svg';
243 $label = $lng->txt("answer_is_wrong");
244 break;
245 }
246 $path = \ilUtil::getImagePath('standard/' . $icon_name);
247 $correct_icon = $ui_factory->symbol()->icon()->custom(
248 $path,
249 $label
250 );
251
252 return $row
253 ->withHeadline($title)
254 ->withLeadingSymbol($correct_icon)
255 ->withImportantFields($important_fields)
256 ->withContent($content);
257 };
258 }
259}
$check
Definition: buildRTE.php:81
Builds a Color from either hex- or rgb values.
Definition: Factory.php:31
Builds data types.
Definition: Factory.php:36
Class Services.
Definition: Services.php:38
__construct(UIFactory $ui_factory, private UIRenderer $ui_renderer, private Refinery $refinery, private HTTPService $http, DataFactory $data_factory, Language $lng, private AttemptSolutions $test_results, Settings $settings, string $title, bool $for_print)
applyControls(string $mode, string $sortation, array $question_results)
getViewControls(UIFactory $ui_factory, Language $lng, URLBuilder $target, string $mode, string $sortation)
return array<\ILIAS\UI\ViewControl\ViewControl>
buildURI()
Get a URI representation of the full URL including query string and fragment/hash.
Definition: URLBuilder.php:214
withParameter(URLBuilderToken $token, string|array $value)
Change an acquired parameter's value if the supplied token is valid.
Definition: URLBuilder.php:166
const SEPARATOR
Separator for parts of a parameter's namespace.
Definition: URLBuilder.php:50
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
$http
Definition: deliver.php:30
if($err=$client->getError()) $namespace
This describes a Row used in Presentation Table.
withHeadline(string $headline)
Get a row like this with the given headline.
This describes a Presentation Table.
An entity that renders components to a string output.
Definition: Renderer.php:31
$path
Definition: ltiservices.php:30
static http()
Fetches the global http state from ILIAS.
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
global $lng
Definition: privfeed.php:31
$results
$token
Definition: xapitoken.php:70