ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
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 bool $styling_disabled = false;
45 private ?ilTemplate $list_tpl = null;
46
47 private UIFactory $ui_factory;
48 private UIRenderer $ui_renderer;
49
50 public function __construct(ilAssOrderingFormValuesObjectsConverter $converter, $postVar)
51 {
52 global $DIC;
53 $this->ui_factory = $DIC['ui.factory'];
54 $this->ui_renderer = $DIC['ui.renderer'];
55 $manipulator = new ilAssOrderingDefaultElementFallback();
56 $this->addFormValuesManipulator($manipulator);
57
58 parent::__construct('', $postVar);
59
60 $this->addFormValuesManipulator($converter);
61 }
62
63 public function setInteractionEnabled(bool $interaction_enabled): void
64 {
65 $this->interaction_enabled = $interaction_enabled;
66 }
67
68 public function setNestingEnabled(bool $nesting_enabled): void
69 {
70 $this->nesting_enabled = $nesting_enabled;
71 }
72
73 public function setStylingDisabled(bool $styling_disabled): void
74 {
75 $this->styling_disabled = $styling_disabled;
76 }
77
78 private function getGlobalTpl()
79 {
80 return isset($GLOBALS['DIC']) ? $GLOBALS['DIC']['tpl'] : $GLOBALS['tpl'];
81 }
82
83 private function initListTemplate(): void
84 {
85 $this->list_tpl = new ilTemplate('tpl.prop_nested_ordering_list.html', true, true, 'components/ILIAS/TestQuestionPool');
86 }
87
88 public function setElementList(ilAssOrderingElementList $elementList): void
89 {
91 }
92
93 public function getElementList(int $questionId): ilAssOrderingElementList
94 {
96 }
97
98 public function prepareReprintable(assQuestion $question): void
99 {
100 $elementList = $this->getElementList($question->getId());
101
102 $elementList->completeContentsFromElementList(
103 $question->getOrderingElementList()
104 );
105
106 $this->setElementList($elementList);
107 }
108
109 public function getContext(): ?string
110 {
111 return $this->context;
112 }
113
114 public function setContext(string $context): void
115 {
116 $this->context = $context;
117 }
118
119 public function getUniquePrefix(): int
120 {
122 }
123
124 public function setUniquePrefix(int $unique_prefix): void
125 {
126 $this->unique_prefix = $unique_prefix;
127 }
128
129 public function setOrderingType(int $ordering_type): void
130 {
131 $this->ordering_type = $ordering_type;
132 }
133
134 public function getOrderingType(): ?int
135 {
137 }
138
139 public function setElementImagePath(string $element_image_path): void
140 {
141 $this->element_image_path = $element_image_path;
142 }
143
144 public function getElementImagePath(): ?string
145 {
147 }
148
149 public function setThumbPrefix(string $thumbnail_filename_prefix): void
150 {
151 $this->thumbnail_filename_prefix = $thumbnail_filename_prefix;
152 }
153
154 public function getThumbPrefix(): string
155 {
157 }
158
160 {
161 $this->show_correctness_icons_enabled = $show_correctness_icons_enabled;
162 }
163
164 public function isShowCorrectnessIconsEnabled(): bool
165 {
167 }
168
170 {
172 }
173
175 {
176 $this->correctness_true_element_list = $correctness_true_element_list;
177 }
178
179 private function getCorrectness(int $identifier): bool
180 {
181 return $this->getCorrectnessTrueElementList()->elementExistByRandomIdentifier($identifier);
182 }
183
184 private function getCorrectnessIcon($correctness): string
185 {
186 $icon_name = 'standard/icon_not_ok.svg';
187 $label = $this->lng->txt("answer_is_wrong");
188 if ($correctness === 'correct') {
189 $icon_name = 'standard/icon_ok.svg';
190 $label = $this->lng->txt("answer_is_right");
191 }
192 $path = ilUtil::getImagePath($icon_name);
193 $icon = $this->ui_factory->symbol()->icon()->custom(
194 $path,
195 $label
196 );
197 return $this->ui_renderer->render($icon);
198 }
199
200 private function getItemTemplate(): ilTemplate
201 {
202 return new ilTemplate('tpl.prop_ass_nested_order_elem.html', true, true, 'components/ILIAS/TestQuestionPool');
203 }
204
205 private function getThumbnailFilename($element): string
206 {
207 return $this->getThumbPrefix() . $element['content'];
208 }
209
210 private function getThumbnailSource($element): string
211 {
212 return $this->getElementImagePath() . $this->getThumbnailFilename($element);
213 }
214
215 private function getItemHtml(
216 array $element,
217 string $identifier,
218 string $content_post_var,
219 string $position_post_var,
220 string $indentation_post_var
221 ): string {
222 $tpl = $this->getItemTemplate();
223
224 switch ($this->getOrderingType()) {
227
228 $tpl->setCurrentBlock('item_text');
229 $tpl->setVariable('ITEM_CONTENT', ilLegacyFormElementsUtil::prepareFormOutput($element['content']));
230 $tpl->parseCurrentBlock();
231 break;
232
235
236 $tpl->setCurrentBlock('item_image');
237 $tpl->setVariable('ITEM_SOURCE', $this->getThumbnailSource($element));
238 $tpl->setVariable('ITEM_CONTENT', $this->getThumbnailFilename($element));
239 $tpl->parseCurrentBlock();
240 break;
241 }
242
243 if ($this->isShowCorrectnessIconsEnabled()) {
244 $correctness = 'not_correct';
245 if ($this->getCorrectness($identifier)) {
246 $correctness = 'correct';
247 }
248 $tpl->setCurrentBlock('correctness_icon');
249
250 $tpl->setVariable('ICON_OK', $this->getCorrectnessIcon($correctness));
251 $tpl->parseCurrentBlock();
252 }
253
254 $tpl->setCurrentBlock('item');
255 $tpl->setVariable('ITEM_CONTENT_POSTVAR', $content_post_var);
256 $tpl->setVariable('ITEM_CONTENT', ilLegacyFormElementsUtil::prepareFormOutput($element['content']));
257 $tpl->setVariable('ITEM_POSITION_POSTVAR', $position_post_var);
258 $tpl->setVariable('ITEM_POSITION', $element['ordering_position']);
259 $tpl->setVariable('ITEM_INDENTATION_POSTVAR', $indentation_post_var);
260 $tpl->setVariable('ITEM_INDENTATION', $element['ordering_indentation']);
261 $tpl->parseCurrentBlock();
262
263 return $tpl->get();
264 }
265
266 public function isPostSubmit($data): bool
267 {
268 if (!is_array($data)) {
269 return false;
270 }
271
272 if (!isset($data[$this->getPostVar()])) {
273 return false;
274 }
275
276 if (!count($data[$this->getPostVar()])) {
277 return false;
278 }
279
280 return true;
281 }
282
283 private function renderListItem(array $value, string $identifier, string $children): string
284 {
285 $list_item_tpl = new ilTemplate('tpl.prop_nested_ordering_list_item.html', true, true, 'components/ILIAS/TestQuestionPool');
286 $content_post_var = $this->getMultiValuePostVarSubField($identifier, self::POSTVAR_CONTENT);
287 $position_post_var = $this->getMultiValuePostVarSubField($identifier, self::POSTVAR_POSITION);
288 $indentation_post_var = $this->getMultiValuePostVarSubField($identifier, self::POSTVAR_INDENTATION);
289
290 $list_item_tpl->setVariable('LIST_ITEM_VALUE', $this->getItemHtml(
291 $value,
292 $identifier,
293 $content_post_var,
294 $position_post_var,
295 $indentation_post_var
296 ));
297
298 if ($this->nesting_enabled) {
299 $list_item_tpl->setCurrentBlock('nested_list');
300 $list_item_tpl->setVariable('SUB_LIST', $children);
301 $list_item_tpl->parseCurrentBlock();
302 }
303 return $list_item_tpl->get();
304 }
305
306 private function renderMainList(): string
307 {
308 $this->initListTemplate();
309
310 $values = $this->addIdentifierToValues($this->getIdentifiedMultiValues());
311 if ($this->nesting_enabled) {
312 $values = $this->buildHierarchicalTreeFromDBValues($values);
313 }
314
315 $this->list_tpl->setVariable(
316 'LIST_ITEMS',
317 $this->buildHTMLView(
318 $values,
319 static fn(array $a, array $b): int => $a['ordering_position'] - $b['ordering_position']
320 )
321 );
322
323 return $this->list_tpl->get();
324 }
325
326 private function addIdentifierToValues(array $values): array
327 {
328 foreach (array_keys($values) as $k) {
329 $values[$k]['identifier'] = str_replace(assOrderingQuestionGUI::F_NESTED_IDENTIFIER_PREFIX, '', $k);
330 }
331 return $values;
332 }
333
334 private function buildHierarchicalTreeFromDBValues(array $values): array
335 {
336 $values_with_parent = [];
337 $levels_array = [];
338 foreach ($values as $k => $v) {
339 $v['parent'] = null;
340 $v['children'] = [];
341
342 if ($v['ordering_indentation'] > 0) {
343 $v['parent'] = $levels_array[$v['ordering_indentation'] - 1];
344 }
345 $levels_array[$v['ordering_indentation']] = $k;
346 $values_with_parent[$k] = $v;
347 }
348
349 uasort(
350 $values_with_parent,
351 static fn(array $a, array $b): int => $b['ordering_indentation'] - $a['ordering_indentation']
352 );
353
354 foreach (array_keys($values_with_parent) as $k) {
355 $v = $values_with_parent[$k];
356 if ($v['parent'] !== null) {
357 $values_with_parent[$v['parent']]['children'][$k] = $v;
358 }
359 }
360
361 return array_filter(
362 $values_with_parent,
363 static fn(array $v): bool => $v['ordering_indentation'] === 0
364 );
365 }
366
367 private function buildHTMLView(array $array, \Closure $sort_closure): string
368 {
369 usort($array, $sort_closure);
370 return array_reduce(
371 $array,
372 function (string $c, array $v) use ($sort_closure): string {
373 $children = '';
374 if ($this->nesting_enabled && $v['children'] !== []) {
375 $children = $this->buildHTMLView($v['children'], $sort_closure);
376 }
377 $c .= $this->renderListItem($v, $v['identifier'], $children);
378 return $c;
379 },
380 ''
381 );
382 }
383
384 public function render(string $a_mode = ''): string
385 {
386 if (!$this->styling_disabled) {
387 $this->getGlobalTpl()->addCss('assets/css/content.css');
388 }
389
390 if ($this->interaction_enabled) {
391 $this->initializePlayerJS();
392 }
393
394 return $this->renderMainList();
395 }
396
397 public function onCheckInput(): bool
398 {
399 return true;
400 }
401
402 public function getHTML(): string
403 {
404 return $this->render();
405 }
406
407 private function initializePlayerJS(): void
408 {
409 $this->getGlobalTpl()->addJavascript('assets/js/orderingvertical.js');
410 $this->getGlobalTpl()->addOnLoadCode(
411 'il.test.orderingvertical.init(document.querySelector("#nestable_ordering"));'
412 );
413 }
414}
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