ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
class.ilAssNestedOrderingElementsInputGUI.php
Go to the documentation of this file.
1 <?php
2 
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;
38  private string $thumbnail_filename_prefix = self::DEFAULT_THUMBNAIL_PREFIX;
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;
46 
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  {
121  return $this->unique_prefix;
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  {
136  return $this->ordering_type;
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 
159  public function setShowCorrectnessIconsEnabled(bool $show_correctness_icons_enabled): void
160  {
161  $this->show_correctness_icons_enabled = $show_correctness_icons_enabled;
162  }
163 
164  public function isShowCorrectnessIconsEnabled(): bool
165  {
167  }
168 
170  {
172  }
173 
174  public function setCorrectnessTrueElementList(ilAssOrderingElementList $correctness_true_element_list): void
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 }
__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...
setShowCorrectnessIconsEnabled(bool $show_correctness_icons_enabled)
static prepareFormOutput($a_str, bool $a_strip=false)
$c
Definition: deliver.php:25
renderListItem(array $value, string $identifier, string $children)
$path
Definition: ltiservices.php:29
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
$GLOBALS["DIC"]
Definition: wac.php:53
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)
global $DIC
Definition: shib_login.php:26
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
setCorrectnessTrueElementList(ilAssOrderingElementList $correctness_true_element_list)
getMultiValuePostVarSubField($identifier, $sub_field_index)
__construct(Container $dic, ilPlugin $plugin)
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
addFormValuesManipulator(ilFormValuesManipulator $manipulator)