ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.assOrderingQuestionGUI.php
Go to the documentation of this file.
1 <?php
2 
19 require_once './Modules/Test/classes/inc.AssessmentConstants.php';
20 
37 {
38  public const CMD_EDIT_NESTING = 'editNesting';
39  public const CMD_SAVE_NESTING = 'saveNesting';
40  public const CMD_SWITCH_TO_TERMS = 'changeToText';
41  public const CMD_SWITCH_TO_PICTURESS = 'changeToPictures';
42 
43  public const TAB_EDIT_QUESTION = 'edit_question';
44  public const TAB_EDIT_NESTING = 'edit_nesting';
45 
46  public const F_USE_NESTED = 'nested_answers';
47  public const F_NESTED_ORDER = 'order_elems';
48  public const F_NESTED_ORDER_ORDER = 'content';
49  public const F_NESTED_ORDER_INDENT = 'indentation';
51 
53 
54  public $old_ordering_depth = [];
55  public $leveled_ordering = [];
56 
64  public function __construct($id = -1)
65  {
67  $this->object = new assOrderingQuestion();
68  if ($id >= 0) {
69  $this->object->loadFromDb($id);
70  }
71  }
72 
73  public function changeToPictures(): void
74  {
75  $this->object->setContentType($this->object::OQ_CT_PICTURES);
76  $this->object->saveToDb();
77 
78  $values = $this->request->getParsedBody();
79  $values['thumb_geometry'] = $this->object->getThumbSize();
80  $this->buildEditFormAfterTypeChange($values);
81  }
82 
83  public function changeToText(): void
84  {
85  $ordering_element_list = $this->object->getOrderingElementList();
86  foreach ($ordering_element_list as $element) {
87  $this->object->dropImageFile($element->getContent());
88  }
89 
90  $this->object->setContentType($this->object::OQ_CT_TERMS);
91  $this->object->saveToDb();
92 
93  $this->buildEditFormAfterTypeChange($this->request->getParsedBody());
94  }
95 
96  private function buildEditFormAfterTypeChange(array $values): void
97  {
98  $form = $this->buildEditForm();
99 
100  $ordering_element_list = $this->object->getOrderingElementList();
101  $ordering_element_list->resetElements();
102 
104  $form->setValuesByArray($values);
105  $form->getItemByPostVar(assOrderingQuestion::ORDERING_ELEMENT_FORM_FIELD_POSTVAR)->setElementList($ordering_element_list);
106  $this->renderEditForm($form);
107  $this->addEditSubtabs();
108  }
109 
110  public function saveNesting()
111  {
112  $form = $this->buildNestingForm();
113  $form->setValuesByPost();
114  if ($form->checkInput()) {
115  $post = $this->request->raw(self::F_NESTED_ORDER);
116  $list = $this->object->getOrderingElementList();
117 
118  $ordered = [];
119  foreach (array_keys($post[self::F_NESTED_ORDER_ORDER]) as $idx => $identifier) {
120  $element_identifier = str_replace(self::F_NESTED_IDENTIFIER_PREFIX, '', $identifier);
121  $element = $list->getElementByRandomIdentifier($element_identifier);
122 
123  $ordered[] = $element
124  ->withPosition($idx)
125  ->withIndentation($post[self::F_NESTED_ORDER_INDENT][$identifier]);
126  }
127 
128  $list = $list->withElements($ordered);
129  $this->object->setOrderingElementList($list);
130  $this->tpl->setOnScreenMessage('success', $this->lng->txt('saved_successfully'), true);
131  } else {
132  $this->tpl->setOnScreenMessage('error', $this->lng->txt('form_input_not_valid'), true);
133  }
134 
135  $this->editNesting();
136  }
137 
138 
139  public function removeElementImage()
140  {
141  $this->uploadElementImage();
142  }
143 
144  public function uploadElementImage(): void
145  {
146  $form = $this->buildEditForm();
147  $form->setValuesByPost();
148 
149  $submitted_list = $this->fetchSolutionListFromSubmittedForm($form);
150 
151  $elements = [];
152  foreach ($submitted_list->getElements() as $submitted_element) {
153  if ($submitted_element->isImageUploadAvailable()) {
154  $filename = $this->object->storeImageFile(
155  $submitted_element->getUploadImageFile(),
156  $submitted_element->getUploadImageName()
157  );
158 
159  if (is_null($filename)) {
160  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('file_no_valid_file_type'));
161  } else {
162  $submitted_element = $submitted_element->withContent($filename);
163  }
164  }
165 
166  if ($submitted_element->isImageRemovalRequest()) {
167  $this->object->dropImageFile($submitted_element->getContent());
168  $submitted_element = $submitted_element->withContent('');
169  }
170 
171  $elements[] = $submitted_element;
172  }
173 
174  $list = $this->object->getOrderingElementList()->withElements($elements);
175  $this->object->setOrderingElementList($list);
176 
178  $this->writeQuestionSpecificPostData($form);
179 
180  $this->editQuestion();
181  }
182 
184  {
185  $thumb_size = $this->request->int('thumb_geometry');
186  if ($thumb_size !== 0
187  && $thumb_size !== $this->object->getThumbSize()) {
188  $this->object->setThumbSize($thumb_size);
189  $this->updateImageFiles();
190  }
191 
192  $points = (float) str_replace(',', '.', $this->request->raw('points'));
193 
194  $this->object->setPoints($points);
195 
196  $use_nested = $this->request->raw(self::F_USE_NESTED) === '1';
197  $this->object->setNestingType($use_nested);
198  }
199 
200 
202  {
204  ->getElementList($this->object->getId());
205 
206  $use_nested = $this->request->raw(self::F_USE_NESTED) === "1";
207 
208  if ($use_nested) {
209  $existing_list = $this->object->getOrderingElementList();
210 
211  $nu = [];
212  $parent_indent = -1;
213  foreach ($list->getElements() as $element) {
214  $element = $list->ensureValidIdentifiers($element);
215 
216  if ($existing = $existing_list->getElementByRandomIdentifier($element->getRandomIdentifier())) {
217  if ($existing->getIndentation() == $parent_indent + 1) {
218  $element = $element
219  ->withIndentation($existing->getIndentation());
220  }
221  }
222  $parent_indent = $element->getIndentation();
223  $nu[] = $element;
224  }
225  $list = $list->withElements($nu);
226  }
227 
228  return $list;
229  }
230 
231  protected function updateImageFiles(): void
232  {
233  $element_list = $this->object->getOrderingElementList();
234  $elements = [];
235  foreach ($element_list->getElements() as $element) {
236  if ($element->getContent() === '') {
237  continue;
238  }
239  $filename = $this->object->updateImageFile(
240  $element->getContent()
241  );
242 
243  $elements[] = $element->withContent($filename);
244  }
245 
246  $list = $this->object->getOrderingElementList()->withElements($elements);
247  $this->object->setOrderingElementList($list);
248  }
249 
250  public function writeAnswerSpecificPostData(ilPropertyFormGUI $form): void
251  {
252  $list = $this->fetchSolutionListFromSubmittedForm($form);
253  $this->object->setOrderingElementList($list);
254  return;
255  }
256 
258  {
259  $header = new ilFormSectionHeaderGUI();
260  $header->setTitle($this->lng->txt('oq_header_ordering_elements'));
261  $form->addItem($header);
262 
263  $orderingElementInput = $this->object->buildOrderingElementInputGui();
264  $orderingElementInput->setStylingDisabled($this->isRenderPurposePrintPdf());
265  $this->object->initOrderingElementAuthoringProperties($orderingElementInput);
266 
267  $list = $this->object->getOrderingElementList();
268  $orderingElementInput->setElementList($list);
269  $form->addItem($orderingElementInput);
270 
271  return $form;
272  }
273 
275  {
276  if ($this->object->isImageOrderingType()) {
277  $thumb_size = new ilNumberInputGUI($this->lng->txt('thumb_size'), 'thumb_geometry');
278  $thumb_size->setValue($this->object->getThumbSize());
279  $thumb_size->setRequired(true);
280  $thumb_size->setMaxLength(6);
281  $thumb_size->setMinValue($this->object->getMinimumThumbSize());
282  $thumb_size->setMaxValue($this->object->getMaximumThumbSize());
283  $thumb_size->setSize(6);
284  $thumb_size->setInfo($this->lng->txt('thumb_size_info'));
285  $form->addItem($thumb_size);
286  }
287 
288  // points
289  $points = new ilNumberInputGUI($this->lng->txt("points"), "points");
290  $points->allowDecimals(true);
291  $points->setValue($this->object->getPoints());
292  $points->setRequired(true);
293  $points->setSize(3);
294  $points->setMinValue(0);
295  $points->setMinvalueShouldBeGreater(true);
296  $form->addItem($points);
297 
298  if (!$this->isInLearningModuleContext()) {
299  $nested_answers = new ilSelectInputGUI(
300  $this->lng->txt('qst_use_nested_answers'),
301  self::F_USE_NESTED
302  );
303  $nested_answers_options = [
304  0 => $this->lng->txt('qst_nested_nested_answers_off'),
305  1 => $this->lng->txt('qst_nested_nested_answers_on')
306  ];
307  $nested_answers->setOptions($nested_answers_options);
308  $nested_answers->setValue($this->object->isOrderingTypeNested());
309  $form->addItem($nested_answers);
310  }
311 
312  return $form;
313  }
314 
321  protected function writePostData(bool $always = false): int
322  {
323  $form = $this->buildEditForm();
324  $form->setValuesByPost();
325 
326  if (!$form->checkInput()) {
327  $this->renderEditForm($form);
328  $this->addEditSubtabs(self::TAB_EDIT_QUESTION);
329  return 1; // return 1 = something went wrong, no saving happened
330  }
331 
332  $this->saveTaxonomyAssignments();
334  $this->writeAnswerSpecificPostData($form);
335  $this->writeQuestionSpecificPostData($form);
336 
337  return 0; // return 0 = all fine, was saved either forced or validated
338  }
339 
340  protected function addEditSubtabs($active = self::TAB_EDIT_QUESTION)
341  {
342  $tabs = $this->getTabs();
343  $tabs->addSubTab(
344  self::TAB_EDIT_QUESTION,
345  $this->lng->txt('edit_question'),
346  $this->ctrl->getLinkTarget($this, 'editQuestion')
347  );
348  if ($this->object->isOrderingTypeNested() && !$this->isInLearningModuleContext()) {
349  $tabs->addSubTab(
350  self::TAB_EDIT_NESTING,
351  $this->lng->txt('tab_nest_answers'),
352  $this->ctrl->getLinkTarget($this, self::CMD_EDIT_NESTING)
353  );
354  }
355  $tabs->setTabActive('edit_question');
356  $tabs->setSubTabActive($active);
357  }
358 
359  public function editQuestion($checkonly = false): void
360  {
361  $this->renderEditForm($this->buildEditForm());
362  $this->addEditSubtabs(self::TAB_EDIT_QUESTION);
363  }
364 
365  public function editNesting()
366  {
367  $this->renderEditForm($this->buildNestingForm());
368  $this->addEditSubtabs(self::TAB_EDIT_NESTING);
369  $this->tpl->addCss(ilObjStyleSheet::getContentStylePath(0));
370  $this->tpl->addCss(ilObjStyleSheet::getSyntaxStylePath());
371  }
372 
374  {
376  $form->setFormAction($this->ctrl->getFormAction($this));
377  $form->setTitle($this->outQuestionType());
378  $form->setMultipart($this->object->isImageOrderingType());
379  $form->setTableWidth("100%");
380  $form->setId("ordering");
381 
382  $this->addBasicQuestionFormProperties($form);
383  $this->populateQuestionSpecificFormPart($form);
384  $this->populateAnswerSpecificFormPart($form);
385  $this->populateTaxonomyFormSection($form);
386 
387  $form->addSpecificOrderingQuestionCommandButtons($this->object);
388  $form->addGenericAssessmentQuestionCommandButtons($this->object);
389 
390  return $form;
391  }
392 
393  protected function buildNestingForm()
394  {
396  $form->setFormAction($this->ctrl->getFormAction($this));
397  $form->setTitle($this->outQuestionType());
398  $form->setTableWidth("100%");
399 
400  $header = new ilFormSectionHeaderGUI();
401  $header->setTitle($this->lng->txt('oq_header_ordering_elements'));
402  $form->addItem($header);
403 
404  $orderingElementInput = $this->object->buildNestedOrderingElementInputGui();
405  $orderingElementInput->setStylingDisabled($this->isRenderPurposePrintPdf());
406 
407  $this->object->initOrderingElementAuthoringProperties($orderingElementInput);
408 
409  $list = $this->object->getOrderingElementList();
410  foreach ($list->getElements() as $element) {
411  $element = $list->ensureValidIdentifiers($element);
412  }
413 
414  $orderingElementInput->setElementList($list);
415 
416  $form->addItem($orderingElementInput);
417  $form->addCommandButton(self::CMD_SAVE_NESTING, $this->lng->txt("save"));
418  return $form;
419  }
420 
421 
428  {
429  return true;
430  }
431 
445  public function getSolutionOutput(
446  $active_id,
447  $pass = null,
448  $graphicalOutput = false,
449  $result_output = false,
450  $show_question_only = true,
451  $show_feedback = false,
452  $show_correct_solution = false,
453  $show_manual_scoring = false,
454  $show_question_text = true
455  ): string {
456  $solutionOrderingList = $this->object->getOrderingElementListForSolutionOutput(
457  $show_correct_solution,
458  $active_id,
459  $pass
460  );
461 
462  $show_inline_feedback = false;
463  return $this->renderSolutionOutput(
464  $solutionOrderingList,
465  $active_id,
466  $pass,
467  $graphicalOutput,
468  $result_output,
469  $show_question_only,
470  $show_feedback,
471  $show_correct_solution,
472  $show_manual_scoring,
473  $show_question_text,
474  false,
475  $show_inline_feedback,
476  );
477  }
478 
479  public function renderSolutionOutput(
480  mixed $user_solutions,
481  int $active_id,
482  ?int $pass,
483  bool $graphical_output = false,
484  bool $result_output = false,
485  bool $show_question_only = true,
486  bool $show_feedback = false,
487  bool $show_correct_solution = false,
488  bool $show_manual_scoring = false,
489  bool $show_question_text = true,
490  bool $show_autosave_title = false,
491  bool $show_inline_feedback = false,
492  ): ?string {
493  $solutionOrderingList = ($user_solutions instanceof ilAssOrderingElementList) ?
494  $user_solutions : $this->object->getSolutionOrderingElementList(
495  $this->object->fetchIndexedValuesFromValuePairs($user_solutions)
496  );
497  $answers_gui = $this->object->buildNestedOrderingElementInputGui();
498 
499  if ($show_correct_solution) {
501  } else {
503  }
504 
505  $answers_gui->setInteractionEnabled(false);
506  $answers_gui->setElementList($solutionOrderingList);
507  if ($graphical_output) {
508  $answers_gui->setShowCorrectnessIconsEnabled(true);
509  }
510  $answers_gui->setCorrectnessTrueElementList(
511  $solutionOrderingList->getParityTrueElementList($this->object->getOrderingElementList())
512  );
513  $solution_html = $answers_gui->getHTML();
514 
515  $template = new ilTemplate("tpl.il_as_qpl_nested_ordering_output_solution.html", true, true, "Modules/TestQuestionPool");
516  $template->setVariable('SOLUTION_OUTPUT', $solution_html);
517  if ($show_question_text == true) {
518  $template->setVariable("QUESTIONTEXT", $this->object->getQuestionForHTMLOutput());
519  }
520  $questionoutput = $template->get();
521 
522  $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html", true, true, "Modules/TestQuestionPool");
523  $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
524 
525  if ($show_feedback) {
526  $feedback = '';
527 
528  if (!$this->isTestPresentationContext()) {
529  $fb = $this->getGenericFeedbackOutput((int) $active_id, $pass);
530  $feedback .= strlen($fb) ? $fb : '';
531  }
532 
533  if (strlen($feedback)) {
534  $cssClass = (
535  $this->hasCorrectSolution($active_id, $pass) ?
537  );
538 
539  $solutiontemplate->setVariable("ILC_FB_CSS_CLASS", $cssClass);
540  $solutiontemplate->setVariable("FEEDBACK", ilLegacyFormElementsUtil::prepareTextareaOutput($feedback, true));
541  }
542  }
543 
544  if ($show_question_only) {
545  return $solutiontemplate->get();
546  }
547 
548  return $this->getILIASPage($solutiontemplate->get());
549 
550  // is this template still in use? it is not used at this point any longer!
551  // $template = new ilTemplate("tpl.il_as_qpl_ordering_output_solution.html", TRUE, TRUE, "Modules/TestQuestionPool");
552  }
553 
554  public function getPreview($show_question_only = false, $showInlineFeedback = false): string
555  {
556  if ($this->getPreviewSession() && $this->getPreviewSession()->hasParticipantSolution()) {
557  $solutionOrderingElementList = unserialize(
558  $this->getPreviewSession()->getParticipantsSolution(),
559  ["allowed_classes" => true]
560  );
561  } else {
562  $solutionOrderingElementList = $this->object->getShuffledOrderingElementList();
563  }
564 
565  $answers = $this->object->buildNestedOrderingElementInputGui();
566  $answers->setNestingEnabled($this->object->isOrderingTypeNested());
568  $answers->setInteractionEnabled($this->isInteractivePresentation());
569  $answers->setElementList($solutionOrderingElementList);
570 
571  $template = new ilTemplate("tpl.il_as_qpl_ordering_output.html", true, true, "Modules/TestQuestionPool");
572 
573  $template->setCurrentBlock('nested_ordering_output');
574  $template->setVariable('NESTED_ORDERING', $answers->getHTML());
575  $template->parseCurrentBlock();
576  $template->setVariable("QUESTIONTEXT", $this->object->getQuestionForHTMLOutput());
577 
578  if ($show_question_only) {
579  return $template->get();
580  }
581 
582  return $this->getILIASPage($template->get());
583  }
584 
585  public function getPresentationJavascripts(): array
586  {
587  global $DIC; /* @var ILIAS\DI\Container $DIC */
588 
589  $files = [];
590 
591  if ($DIC->http()->agent()->isMobile() || $DIC->http()->agent()->isIpad()) {
592  $files[] = './node_modules/@andxor/jquery-ui-touch-punch-fix/jquery.ui.touch-punch.js';
593  }
594 
595  return $files;
596  }
597 
598  // hey: prevPassSolutions - pass will be always available from now on
599  public function getTestOutput($activeId, $pass, $isPostponed = false, $userSolutionPost = false, $inlineFeedback = false): string
600  // hey.
601  {
602  // hey: prevPassSolutions - fixed variable type, makes phpstorm stop crying
603  $userSolutionPost = is_array($userSolutionPost) ? $userSolutionPost : [];
604  // hey.
605 
606  $orderingGUI = $this->object->buildNestedOrderingElementInputGui();
607  $orderingGUI->setNestingEnabled($this->object->isOrderingTypeNested());
608 
609  $solutionOrderingElementList = $this->object->getSolutionOrderingElementListForTestOutput(
610  $orderingGUI,
611  $userSolutionPost,
612  $activeId,
613  $pass
614  );
615 
616  $template = new ilTemplate('tpl.il_as_qpl_ordering_output.html', true, true, 'Modules/TestQuestionPool');
617 
619  $orderingGUI->setElementList($solutionOrderingElementList);
620 
621  $template->setCurrentBlock('nested_ordering_output');
622  $template->setVariable('NESTED_ORDERING', $orderingGUI->getHTML());
623  $template->parseCurrentBlock();
624 
625  $template->setVariable('QUESTIONTEXT', $this->object->getQuestionForHTMLOutput());
626 
627  $pageoutput = $this->outQuestionPage('', $isPostponed, $activeId, $template->get());
628 
629  return $pageoutput;
630  }
631 
632  protected function isInteractivePresentation(): bool
633  {
634  if ($this->isRenderPurposePlayback()) {
635  return true;
636  }
637 
638  if ($this->isRenderPurposeDemoplay()) {
639  return true;
640  }
641 
642  return false;
643  }
644 
645  protected function getTabs(): ilTabsGUI
646  {
647  global $DIC;
648  return $DIC['ilTabs'];
649  }
650 
651  public function getSpecificFeedbackOutput(array $userSolution): string
652  {
653  return '';
654  }
655 
666  {
667  return [];
668  }
669 
680  {
681  return [];
682  }
683 
690  public function getAggregatedAnswersView(array $relevant_answers): string
691  {
692  $aggView = $this->aggregateAnswers(
693  $relevant_answers,
694  $this->object->getOrderingElementList()
695  );
696 
697  return $this->renderAggregateView($aggView)->get();
698  }
699 
700  public function aggregateAnswers($relevant_answers_chosen, $answers_defined_on_question): array
701  {
702  $passdata = []; // Regroup answers into units of passes.
703  foreach ($relevant_answers_chosen as $answer_chosen) {
704  $passdata[$answer_chosen['active_fi'] . '-' . $answer_chosen['pass']][$answer_chosen['value2']] = $answer_chosen['value1'];
705  }
706 
707  $variants = []; // Determine unique variants.
708  foreach ($passdata as $key => $data) {
709  $hash = md5(implode('-', $data));
710  $value_set = false;
711  foreach ($variants as $vkey => $variant) {
712  if ($variant['hash'] == $hash) {
713  $variant['count']++;
714  $value_set = true;
715  }
716  }
717  if (!$value_set) {
718  $variants[$key]['hash'] = $hash;
719  $variants[$key]['count'] = 1;
720  }
721  }
722 
723  $aggregate = []; // Render aggregate from variant.
724  foreach ($variants as $key => $variant_entry) {
725  $variant = $passdata[$key];
726 
727  foreach ($variant as $variant_key => $variant_line) {
728  $i = 0;
729  $aggregated_info_for_answer['count'] = $variant_entry['count'];
730  foreach ($answers_defined_on_question as $element) {
731  $i++;
732 
733  if ($this->object->isImageOrderingType()) {
734  $element->setImageThumbnailPrefix($this->object->getThumbPrefix());
735  $element->setImagePathWeb($this->object->getImagePathWeb());
736  $element->setImagePathFs($this->object->getImagePath());
737 
738  $src = $element->getPresentationImageUrl();
739  $alt = $element->getContent();
740  $content = "<img src='{$src}' alt='{$alt}' title='{$alt}'/>";
741  } else {
742  $content = $element->getContent();
743  }
744 
745  $aggregated_info_for_answer[$i . ' - ' . $content]
746  = $passdata[$key][$i];
747  }
748  }
749  $aggregate[] = $aggregated_info_for_answer;
750  }
751  return $aggregate;
752  }
753 
759  public function renderAggregateView($aggregate): ilTemplate
760  {
761  $tpl = new ilTemplate('tpl.il_as_aggregated_answers_table.html', true, true, "Modules/TestQuestionPool");
762 
763  foreach ($aggregate as $line_data) {
764  $tpl->setCurrentBlock('aggregaterow');
765  $count = array_shift($line_data);
766  $html = '<ul>';
767  foreach ($line_data as $key => $line) {
768  $html .= '<li>' . ++$line . '&nbsp;-&nbsp;' . $key . '</li>';
769  }
770  $html .= '</ul>';
771  $tpl->setVariable('COUNT', $count);
772  $tpl->setVariable('OPTION', $html);
773 
775  }
776  return $tpl;
777  }
778 
779  protected function getAnswerStatisticOrderingElementHtml(ilAssOrderingElement $element): ?string
780  {
781  if ($this->object->isImageOrderingType()) {
782  $element->setImageThumbnailPrefix($this->object->getThumbPrefix());
783  $element->setImagePathWeb($this->object->getImagePathWeb());
784  $element->setImagePathFs($this->object->getImagePath());
785 
786  $src = $element->getPresentationImageUrl();
787  $alt = $element->getContent();
788  $content = "<img src='{$src}' alt='{$alt}' title='{$alt}'/>";
789  } else {
790  $content = $element->getContent();
791  }
792 
793  return $content;
794  }
795 
797  {
798  $html = '<ul>';
799 
800  $lastIndent = 0;
801  $firstElem = true;
802 
803  foreach ($list as $elem) {
804  if ($elem->getIndentation() > $lastIndent) {
805  $html .= '<ul><li>';
806  } elseif ($elem->getIndentation() < $lastIndent) {
807  $html .= '</li></ul><li>';
808  } elseif (!$firstElem) {
809  $html .= '</li><li>';
810  } else {
811  $html .= '<li>';
812  }
813 
814  $html .= $this->getAnswerStatisticOrderingElementHtml($elem);
815 
816  $firstElem = false;
817  $lastIndent = $elem->getIndentation();
818  }
819 
820  $html .= '</li>';
821 
822  for ($i = $lastIndent; $i > 0; $i--) {
823  $html .= '</ul></li>';
824  }
825 
826  $html .= '</ul>';
827 
828  return $html;
829  }
830 
831  public function getAnswersFrequency($relevantAnswers, $questionIndex): array
832  {
833  $answersByActiveAndPass = [];
834 
835  foreach ($relevantAnswers as $row) {
836  $key = $row['active_fi'] . ':' . $row['pass'];
837 
838  if (!isset($answersByActiveAndPass[$key])) {
839  $answersByActiveAndPass[$key] = [];
840  }
841 
842  $answersByActiveAndPass[$key][$row['value1']] = $row['value2'];
843  }
844 
845  $solutionLists = [];
846 
847  foreach ($answersByActiveAndPass as $indexedSolutions) {
848  $solutionLists[] = $this->object->getSolutionOrderingElementList($indexedSolutions);
849  }
850 
851  /* @var ilAssOrderingElementList[] $answers */
852  $answers = [];
853 
854  foreach ($solutionLists as $orderingElementList) {
855  $hash = $orderingElementList->getHash();
856 
857  if (!isset($answers[$hash])) {
858  $variantHtml = $this->getAnswerStatisticOrderingVariantHtml(
859  $orderingElementList
860  );
861 
862  $answers[$hash] = array(
863  'answer' => $variantHtml, 'frequency' => 0
864  );
865  }
866 
867  $answers[$hash]['frequency']++;
868  }
869 
870  return array_values($answers);
871  }
872 
877  {
879  $orderingInput->prepareReprintable($this->object);
880  }
881 
886  {
887  $points = new ilNumberInputGUI($this->lng->txt("points"), "points");
888  $points->allowDecimals(true);
889  $points->setValue($this->object->getPoints());
890  $points->setRequired(true);
891  $points->setSize(3);
892  $points->setMinValue(0);
893  $points->setMinvalueShouldBeGreater(true);
894  $form->addItem($points);
895 
896  $header = new ilFormSectionHeaderGUI();
897  $header->setTitle($this->lng->txt('oq_header_ordering_elements'));
898  $form->addItem($header);
899 
900  $orderingElementInput = $this->object->buildNestedOrderingElementInputGui();
901 
902  $this->object->initOrderingElementAuthoringProperties($orderingElementInput);
903 
904  $orderingElementInput->setElementList($this->object->getOrderingElementList());
905 
906  $form->addItem($orderingElementInput);
907  }
908 
913  {
914  $this->object->setPoints((float) str_replace(',', '.', $form->getInput('points')));
915 
916  $submittedElementList = $this->fetchSolutionListFromSubmittedForm($form);
917 
918  $curElementList = $this->object->getOrderingElementList();
919 
920  $newElementList = new ilAssOrderingElementList();
921  $newElementList->setQuestionId($this->object->getId());
922 
923  foreach ($submittedElementList as $submittedElement) {
924  if (!$curElementList->elementExistByRandomIdentifier($submittedElement->getRandomIdentifier())) {
925  continue;
926  }
927 
928  $curElement = $curElementList->getElementByRandomIdentifier($submittedElement->getRandomIdentifier());
929 
930  $curElement->setPosition($submittedElement->getPosition());
931 
932  if ($this->object->isOrderingTypeNested()) {
933  $curElement->setIndentation($submittedElement->getIndentation());
934  }
935 
936  $newElementList->addElement($curElement);
937  }
938 
939  $this->object->setOrderingElementList($newElementList);
940  }
941 }
__construct($id=-1)
assOrderingQuestionGUI constructor
populateQuestionSpecificFormPart(\ilPropertyFormGUI $form)
hasCorrectSolution($activeId, $passIndex)
getSpecificFeedbackOutput(array $userSolution)
prepareReprintableCorrectionsForm(ilPropertyFormGUI $form)
setCurrentBlock(string $blockname=self::DEFAULT_BLOCK)
Sets the template to the given block.
aggregateAnswers($relevant_answers_chosen, $answers_defined_on_question)
This class represents a selection list property in a property form.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getAnswerStatisticOrderingVariantHtml(ilAssOrderingElementList $list)
getItemByPostVar(string $a_post_var)
populateAnswerSpecificFormPart(ilPropertyFormGUI $form)
Adds the answer specific form parts to a question property form gui.
Abstract basic class which is to be extended by the concrete assessment question type classes...
getAggregatedAnswersView(array $relevant_answers)
Returns an html string containing a question specific representation of the answers so far given in t...
getSolutionOutput( $active_id, $pass=null, $graphicalOutput=false, $result_output=false, $show_question_only=true, $show_feedback=false, $show_correct_solution=false, $show_manual_scoring=false, $show_question_text=true)
Get the question solution output.
addBasicQuestionFormProperties(ilPropertyFormGUI $form)
parseCurrentBlock(string $blockname=self::DEFAULT_BLOCK)
Parses the given block.
writePostData(bool $always=false)
{}
setOptions(array $a_options)
ilGlobalPageTemplate $tpl
populateTaxonomyFormSection(ilPropertyFormGUI $form)
getInput(string $a_post_var, bool $ensureValidation=true)
Returns the input of an item, if item provides getInput method and as fallback the value of the HTTP-...
global $DIC
Definition: feed.php:28
fetchSolutionListFromSubmittedForm(ilPropertyFormGUI $form)
__construct(VocabulariesInterface $vocabularies)
writeAnswerSpecificPostData(ilPropertyFormGUI $form)
Extracts the answer specific values from $_POST and applies them to the data object.
getTestOutput($activeId, $pass, $isPostponed=false, $userSolutionPost=false, $inlineFeedback=false)
getAfterParticipationSuppressionAnswerPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
addEditSubtabs($active=self::TAB_EDIT_QUESTION)
string $key
Consumer key/client ID value.
Definition: System.php:193
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getAfterParticipationSuppressionQuestionPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
Basic GUI class for assessment questions.
static getContentStylePath(int $a_style_id, bool $add_random=true, bool $add_token=true)
get content style path static (to avoid full reading)
$filename
Definition: buildRTE.php:78
supportsIntermediateSolutionOutput()
Question type specific support of intermediate solution output The function getSolutionOutput respect...
setImageThumbnailPrefix($imageThumbnailPrefix)
saveCorrectionsFormProperties(ilPropertyFormGUI $form)
getILIASPage(string $html="")
Returns the ILIAS Page around a question.
outQuestionPage($a_temp_var, $a_postponed=false, $active_id="", $html="", $inlineFeedbackEnabled=false)
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
renderSolutionOutput(mixed $user_solutions, int $active_id, ?int $pass, bool $graphical_output=false, bool $result_output=false, bool $show_question_only=true, bool $show_feedback=false, bool $show_correct_solution=false, bool $show_manual_scoring=false, bool $show_question_text=true, bool $show_autosave_title=false, bool $show_inline_feedback=false,)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getPreview($show_question_only=false, $showInlineFeedback=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getAnswersFrequency($relevantAnswers, $questionIndex)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$post
Definition: ltitoken.php:49
static prepareTextareaOutput(string $txt_output, bool $prepare_for_latex_output=false, bool $omitNl2BrWhenTextArea=false)
Prepares a string for a text area output where latex code may be in it If the text is HTML-free...
getAnswerStatisticOrderingElementHtml(ilAssOrderingElement $element)
setVariable(string $variable, $value='')
Sets the given variable to the given value.
populateCorrectionsFormProperties(ilPropertyFormGUI $form)
writeQuestionSpecificPostData(ilPropertyFormGUI $form)
Extracts the question specific values from $_POST and applies them to the data object.
renderEditForm(ilPropertyFormGUI $form)
getGenericFeedbackOutput(int $active_id, ?int $pass)