ILIAS  trunk Revision v12.0_alpha-1221-g4e438232683
class.ilAssNestedOrderingElementsInputGUI.php
Go to the documentation of this file.
1<?php
2
19use ILIAS\UI\Factory as UIFactory;
20use ILIAS\UI\Renderer as UIRenderer;
21
23{
24 private const POSTVAR_CONTENT = 'content';
25 private const POSTVAR_POSITION = 'position';
26 private const POSTVAR_INDENTATION = 'indentation';
27
28 public const CONTEXT_QUESTION_PREVIEW = 'QuestionPreview';
29 public const CONTEXT_CORRECT_SOLUTION_PRESENTATION = 'CorrectSolutionPresent';
30 public const CONTEXT_USER_SOLUTION_PRESENTATION = 'UserSolutionPresent';
31 public const CONTEXT_USER_SOLUTION_SUBMISSION = 'UserSolutionSubmit';
32
33 private const DEFAULT_THUMBNAIL_PREFIX = 'thumb.';
34
35 private ?string $context = null;
36 private ?int $unique_prefix = null;
37 private ?int $ordering_type = null;
39 private ?string $element_image_path = null;
40 private bool $show_correctness_icons_enabled = false;
42 private bool $interaction_enabled = true;
43 private bool $nesting_enabled = true;
44 private ?ilTemplate $list_tpl = null;
45
46 private UIFactory $ui_factory;
47 private UIRenderer $ui_renderer;
48
49 public function __construct(ilAssOrderingFormValuesObjectsConverter $converter, $postVar)
50 {
51 global $DIC;
52 $this->ui_factory = $DIC['ui.factory'];
53 $this->ui_renderer = $DIC['ui.renderer'];
54 $manipulator = new ilAssOrderingDefaultElementFallback();
55 $this->addFormValuesManipulator($manipulator);
56
57 parent::__construct('', $postVar);
58
59 $this->addFormValuesManipulator($converter);
60 }
61
62 public function setInteractionEnabled(bool $interaction_enabled): void
63 {
64 $this->interaction_enabled = $interaction_enabled;
65 }
66
67 public function setNestingEnabled(bool $nesting_enabled): void
68 {
69 $this->nesting_enabled = $nesting_enabled;
70 }
71
72 private function getGlobalTpl()
73 {
74 return isset($GLOBALS['DIC']) ? $GLOBALS['DIC']['tpl'] : $GLOBALS['tpl'];
75 }
76
77 private function initListTemplate(): void
78 {
79 $this->list_tpl = new ilTemplate('tpl.prop_nested_ordering_list.html', true, true, 'components/ILIAS/TestQuestionPool');
80 }
81
82 public function setElementList(ilAssOrderingElementList $elementList): void
83 {
85 }
86
87 public function getElementList(int $questionId): ilAssOrderingElementList
88 {
90 }
91
92 public function prepareReprintable(assQuestion $question): void
93 {
94 $elementList = $this->getElementList($question->getId());
95
96 $elementList->completeContentsFromElementList(
97 $question->getOrderingElementList()
98 );
99
100 $this->setElementList($elementList);
101 }
102
103 public function getContext(): ?string
104 {
105 return $this->context;
106 }
107
108 public function setContext(string $context): void
109 {
110 $this->context = $context;
111 }
112
113 public function getUniquePrefix(): int
114 {
116 }
117
118 public function setUniquePrefix(int $unique_prefix): void
119 {
120 $this->unique_prefix = $unique_prefix;
121 }
122
123 public function setOrderingType(int $ordering_type): void
124 {
125 $this->ordering_type = $ordering_type;
126 }
127
128 public function getOrderingType(): ?int
129 {
131 }
132
133 public function setElementImagePath(string $element_image_path): void
134 {
135 $this->element_image_path = $element_image_path;
136 }
137
138 public function getElementImagePath(): ?string
139 {
141 }
142
143 public function setThumbPrefix(string $thumbnail_filename_prefix): void
144 {
145 $this->thumbnail_filename_prefix = $thumbnail_filename_prefix;
146 }
147
148 public function getThumbPrefix(): string
149 {
151 }
152
154 {
155 $this->show_correctness_icons_enabled = $show_correctness_icons_enabled;
156 }
157
158 public function isShowCorrectnessIconsEnabled(): bool
159 {
161 }
162
164 {
166 }
167
169 {
170 $this->correctness_true_element_list = $correctness_true_element_list;
171 }
172
173 private function getCorrectness(int $identifier): bool
174 {
175 return $this->getCorrectnessTrueElementList()->elementExistByRandomIdentifier($identifier);
176 }
177
178 private function getCorrectnessIcon($correctness): string
179 {
180 $icon_name = 'standard/icon_not_ok.svg';
181 $label = $this->lng->txt("answer_is_wrong");
182 if ($correctness === 'correct') {
183 $icon_name = 'standard/icon_ok.svg';
184 $label = $this->lng->txt("answer_is_right");
185 }
186 $path = ilUtil::getImagePath($icon_name);
187 $icon = $this->ui_factory->symbol()->icon()->custom(
188 $path,
189 $label
190 );
191 return $this->ui_renderer->render($icon);
192 }
193
194 private function getItemTemplate(): ilTemplate
195 {
196 return new ilTemplate('tpl.prop_ass_nested_order_elem.html', true, true, 'components/ILIAS/TestQuestionPool');
197 }
198
199 private function getThumbnailFilename($element): string
200 {
201 return $this->getThumbPrefix() . $element['content'];
202 }
203
204 private function getThumbnailSource($element): string
205 {
206 return $this->getElementImagePath() . $this->getThumbnailFilename($element);
207 }
208
209 private function getItemHtml(
210 array $element,
211 string $identifier,
212 string $content_post_var,
213 string $position_post_var,
214 string $indentation_post_var
215 ): string {
216 $tpl = $this->getItemTemplate();
217
218 switch ($this->getOrderingType()) {
221
222 $tpl->setCurrentBlock('item_text');
223 $tpl->setVariable('ITEM_CONTENT', ilLegacyFormElementsUtil::prepareFormOutput($element['content']));
224 $tpl->parseCurrentBlock();
225 break;
226
229
230 $tpl->setCurrentBlock('item_image');
231 $tpl->setVariable('ITEM_SOURCE', $this->getThumbnailSource($element));
232 $tpl->setVariable('ITEM_CONTENT', $this->getThumbnailFilename($element));
233 $tpl->parseCurrentBlock();
234 break;
235 }
236
237 if ($this->isShowCorrectnessIconsEnabled()) {
238 $correctness = 'not_correct';
239 if ($this->getCorrectness($identifier)) {
240 $correctness = 'correct';
241 }
242 $tpl->setCurrentBlock('correctness_icon');
243
244 $tpl->setVariable('ICON_OK', $this->getCorrectnessIcon($correctness));
245 $tpl->parseCurrentBlock();
246 }
247
248 $tpl->setCurrentBlock('item');
249 $tpl->setVariable('ITEM_CONTENT_POSTVAR', $content_post_var);
250 $tpl->setVariable('ITEM_CONTENT', ilLegacyFormElementsUtil::prepareFormOutput($element['content']));
251 $tpl->setVariable('ITEM_POSITION_POSTVAR', $position_post_var);
252 $tpl->setVariable('ITEM_POSITION', $element['ordering_position']);
253 $tpl->setVariable('ITEM_INDENTATION_POSTVAR', $indentation_post_var);
254 $tpl->setVariable('ITEM_INDENTATION', $element['ordering_indentation']);
255 $tpl->parseCurrentBlock();
256
257 return $tpl->get();
258 }
259
260 public function isPostSubmit($data): bool
261 {
262 if (!is_array($data)) {
263 return false;
264 }
265
266 if (!isset($data[$this->getPostVar()])) {
267 return false;
268 }
269
270 if (!count($data[$this->getPostVar()])) {
271 return false;
272 }
273
274 return true;
275 }
276
277 private function renderListItem(array $value, string $identifier, string $children): string
278 {
279 $list_item_tpl = new ilTemplate('tpl.prop_nested_ordering_list_item.html', true, true, 'components/ILIAS/TestQuestionPool');
280 $content_post_var = $this->getMultiValuePostVarSubField($identifier, self::POSTVAR_CONTENT);
281 $position_post_var = $this->getMultiValuePostVarSubField($identifier, self::POSTVAR_POSITION);
282 $indentation_post_var = $this->getMultiValuePostVarSubField($identifier, self::POSTVAR_INDENTATION);
283
284 $list_item_tpl->setVariable('LIST_ITEM_VALUE', $this->getItemHtml(
285 $value,
286 $identifier,
287 $content_post_var,
288 $position_post_var,
289 $indentation_post_var
290 ));
291
292 if ($this->nesting_enabled) {
293 $list_item_tpl->setCurrentBlock('nested_list');
294 $list_item_tpl->setVariable('SUB_LIST', $children);
295 $list_item_tpl->parseCurrentBlock();
296 }
297 return $list_item_tpl->get();
298 }
299
300 private function renderMainList(): string
301 {
302 $this->initListTemplate();
303
304 $values = $this->addIdentifierToValues($this->getIdentifiedMultiValues());
305 if ($this->nesting_enabled) {
306 $values = $this->buildHierarchicalTreeFromDBValues($values);
307 }
308
309 $this->list_tpl->setVariable(
310 'LIST_ITEMS',
311 $this->buildHTMLView(
312 $values,
313 static fn(array $a, array $b): int => $a['ordering_position'] - $b['ordering_position']
314 )
315 );
316
317 return $this->list_tpl->get();
318 }
319
320 private function addIdentifierToValues(array $values): array
321 {
322 foreach (array_keys($values) as $k) {
323 $values[$k]['identifier'] = str_replace(assOrderingQuestionGUI::F_NESTED_IDENTIFIER_PREFIX, '', $k);
324 }
325 return $values;
326 }
327
328 private function buildHierarchicalTreeFromDBValues(array $values): array
329 {
330 $values_with_parent = [];
331 $levels_array = [];
332 foreach ($values as $k => $v) {
333 $v['parent'] = null;
334 $v['children'] = [];
335
336 if ($v['ordering_indentation'] > 0) {
337 $v['parent'] = $levels_array[$v['ordering_indentation'] - 1];
338 }
339 $levels_array[$v['ordering_indentation']] = $k;
340 $values_with_parent[$k] = $v;
341 }
342
343 uasort(
344 $values_with_parent,
345 static fn(array $a, array $b): int => $b['ordering_indentation'] - $a['ordering_indentation']
346 );
347
348 foreach (array_keys($values_with_parent) as $k) {
349 $v = $values_with_parent[$k];
350 if ($v['parent'] !== null) {
351 $values_with_parent[$v['parent']]['children'][$k] = $v;
352 }
353 }
354
355 return array_filter(
356 $values_with_parent,
357 static fn(array $v): bool => $v['ordering_indentation'] === 0
358 );
359 }
360
361 private function buildHTMLView(array $array, \Closure $sort_closure): string
362 {
363 usort($array, $sort_closure);
364 return array_reduce(
365 $array,
366 function (string $c, array $v) use ($sort_closure): string {
367 $children = '';
368 if ($this->nesting_enabled && $v['children'] !== []) {
369 $children = $this->buildHTMLView($v['children'], $sort_closure);
370 }
371 $c .= $this->renderListItem($v, $v['identifier'], $children);
372 return $c;
373 },
374 ''
375 );
376 }
377
378 public function render(string $a_mode = ''): string
379 {
380 if ($this->interaction_enabled) {
381 $this->initializePlayerJS();
382 }
383
384 return $this->renderMainList();
385 }
386
387 public function onCheckInput(): bool
388 {
389 return true;
390 }
391
392 public function getHTML(): string
393 {
394 return $this->render();
395 }
396
397 private function initializePlayerJS(): void
398 {
399 $this->getGlobalTpl()->addJavascript('assets/js/orderingvertical.js');
400 $this->getGlobalTpl()->addOnLoadCode(
401 'il.test.orderingvertical.init(document.querySelector("#nestable_ordering"));'
402 );
403 }
404}
Builds a Color from either hex- or rgb values.
Definition: Factory.php:31
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getItemHtml(array $element, string $identifier, string $content_post_var, string $position_post_var, string $indentation_post_var)
renderListItem(array $value, string $identifier, string $children)
setCorrectnessTrueElementList(ilAssOrderingElementList $correctness_true_element_list)
setShowCorrectnessIconsEnabled(bool $show_correctness_icons_enabled)
__construct(ilAssOrderingFormValuesObjectsConverter $converter, $postVar)
static buildInstance(int $question_id, array $elements=[])
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
addFormValuesManipulator(ilFormValuesManipulator $manipulator)
static prepareFormOutput($a_str, bool $a_strip=false)
special template class to simplify handling of ITX/PEAR
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
$c
Definition: deliver.php:25
An entity that renders components to a string output.
Definition: Renderer.php:31
$path
Definition: ltiservices.php:30
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
global $DIC
Definition: shib_login.php:26
$GLOBALS["DIC"]
Definition: wac.php:54