ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
AttemptResultsTable.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
22 
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 
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,
56  Language $lng,
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 
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) {
97  case self::MODE_OPT_CORRECT:
98  $filter = static fn($qr) => $qr->getCorrect() === QuestionResult::CORRECT_FULL;
99  break;
100  case self::MODE_OPT_INCORRECT:
101  $filter = static fn($qr) => $qr->getCorrect() !== QuestionResult::CORRECT_FULL;
102  break;
103  case self::MODE_OPT_ALL:
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  {
121  $namespace = self::URL_NAMESPACE;
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,
146  Language $lng,
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  ];
159  $check = [self::MODE_OPT_ALL, self::MODE_OPT_CORRECT, self::MODE_OPT_INCORRECT];
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 
208  $feedback = $ui_factory->listing()->descriptive([
209  $lng->txt('tst_feedback') => $question->getFeedback()
210  ]);
211 
212  $contents = [];
213 
214  $contents[] = $stats;
215  if ($env->getShowFeedback()) {
216  $contents[] = $feedback;
217  }
218 
219  if ($recap = $question->getContentForRecapitulation()) {
220  $contents[] = $ui_factory->listing()->descriptive([
221  $lng->txt('suggested_solution') => $recap
222  ]);
223  }
224 
225  $user_answer = $question->getUserAnswer();
226  $answer_contents = [
227  $ui_factory->listing()->descriptive([$lng->txt('tst_header_participant') => $user_answer])
228  ];
229  if ($env->getShowBestSolution()) {
230  $answer_contents[] = $ui_factory->listing()->descriptive([
231  $lng->txt('tst_header_solution') => $question->getBestSolution()
232  ]);
233  }
234 
235  $answers = $ui_factory->layout()->alignment()->horizontal()->evenlyDistributed(...$answer_contents);
236  $contents[] = $answers;
237 
238  $content = $ui_factory->layout()->alignment()->vertical(...$contents);
239 
240  switch ($question->getCorrect()) {
242  $icon_name = 'icon_ok.svg';
243  $label = $lng->txt("answer_is_right");
244  break;
246  $icon_name = 'icon_mostly_ok.svg';
247  $label = $lng->txt("answer_is_not_correct_but_positive");
248  break;
250  $icon_name = 'icon_not_ok.svg';
251  $label = $lng->txt("answer_is_wrong");
252  break;
253  }
254  $path = \ilUtil::getImagePath('standard/' . $icon_name);
255  $correct_icon = $ui_factory->symbol()->icon()->custom(
256  $path,
257  $label
258  );
259 
260  return $row
261  ->withHeadline($title)
262  ->withLeadingSymbol($correct_icon)
263  ->withImportantFields($important_fields)
264  ->withContent($content);
265  };
266  }
267 }
if($err=$client->getError()) $namespace
buildURI()
Get a URI representation of the full URL including query string and fragment/hash.
Definition: URLBuilder.php:214
const SEPARATOR
Separator for parts of a parameter&#39;s namespace.
Definition: URLBuilder.php:50
$http
Definition: deliver.php:30
$path
Definition: ltiservices.php:29
txt(string $a_topic, string $a_default_lang_fallback_mod="")
applyControls(string $mode, string $sortation, array $question_results)
static http()
Fetches the global http state from ILIAS.
$token
Definition: xapitoken.php:70
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
withHeadline(string $headline)
Get a row like this with the given headline.
$results
This describes a Row used in Presentation Table.
getViewControls(UIFactory $ui_factory, Language $lng, URLBuilder $target, string $mode, string $sortation)
return array<>
withParameter(URLBuilderToken $token, string|array $value)
Change an acquired parameter&#39;s value if the supplied token is valid.
Definition: URLBuilder.php:166
global $lng
Definition: privfeed.php:31
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
$check
Definition: buildRTE.php:81
acquireParameter(array $namespace, string $name, ?string $initial_value=null)
Add a new parameter with a namespace and get its token for subsequent changes.
Definition: URLBuilder.php:119
__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)
URLBuilder.
Definition: URLBuilder.php:40