ILIAS  trunk Revision v12.0_alpha-1338-g8f7e531aa3c
class.assLongMenuGUI.php
Go to the documentation of this file.
1<?php
2
19use ILIAS\UI\Factory as UIFactory;
20use ILIAS\UI\Renderer as UIRenderer;
21
30{
31 private const DEFAULT_MODAL_ID = 'ilGapModal';
32
33 private readonly UIFactory $ui_factory;
34 private readonly UIRenderer $ui_renderer;
35
36 public function __construct($id = -1)
37 {
39 $this->object = new assLongMenu();
40 if ($id >= 0) {
41 $this->object->loadFromDb($id);
42 }
44 global $DIC;
45 $this->lng = $DIC['lng'];
46 $this->ui_factory = $DIC['ui.factory'];
47 $this->ui_renderer = $DIC['ui.renderer'];
48 }
49
50 public function getCommand($cmd)
51 {
52 return $cmd;
53 }
54
58 protected function writePostData(bool $always = false): int
59 {
60 $this->editForm = $this->buildEditForm();
61 $this->editForm->setValuesByPost();
62 $check = $this->editForm->checkInput() && $this->verifyAnswerOptions();
63
64 if (!$check) {
65 $this->editQuestion();
66 return 1;
67 }
69 $this->writeQuestionSpecificPostData($this->editForm);
70 $custom_check = $this->object->checkQuestionCustomPart($this->editForm);
71 if (!$custom_check) {
72 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('form_input_not_valid'));
73 $this->editQuestion();
74 return 1;
75 }
77 return 0;
78 }
79
81 {
82 $min_auto_complete = (int) ($form->getInput('min_auto_complete') ?? assLongMenu::MIN_LENGTH_AUTOCOMPLETE);
83 $hidden_text_files = $this->request_data_collector->string('hidden_text_files');
84 $hidden_correct_answers = $this->request_data_collector->string('hidden_correct_answers');
85 $long_menu_type = $this->request_data_collector->intArray('long_menu_type');
86 $this->object->setLongMenuTextValue($this->request_data_collector->string('longmenu_text'));
87 $this->object->setAnswers($this->trimArrayRecursive($this->stripSlashesRecursive(json_decode($hidden_text_files))));
88 $this->object->setCorrectAnswers(
90 $this->trimArrayRecursive(
92 json_decode($hidden_correct_answers)
93 )
94 )
95 )
96 );
97 $this->object->setAnswerType(ilArrayUtil::stripSlashesRecursive($long_menu_type));
98 $this->object->setQuestion($this->request_data_collector->string('question'));
99 $this->object->setMinAutoComplete($min_auto_complete);
100 $this->object->setIdenticalScoring($this->request_data_collector->int('identical_scoring'));
101
103 }
104
105 private function verifyAnswerOptions(): bool
106 {
107 $longmenu_text = $this->request_data_collector->raw('longmenu_text') ?? '';
108 $hidden_text_files = $this->request_data_collector->raw('hidden_text_files') ?? '';
109 $answer_options_from_text = preg_split(
110 "/\\[" . assLongMenu::GAP_PLACEHOLDER . " (\\d+)\\]/",
111 $longmenu_text
112 );
113
114 $answer_options_from_files = $this->stripSlashesRecursive(json_decode($hidden_text_files));
115 if (count($answer_options_from_text) - 1 !== count($answer_options_from_files)) {
116 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('longmenu_answeroptions_differ'));
117 return false;
118 }
119
120 $correct_answers = $this->stripSlashesRecursive(json_decode($this->request_data_collector->raw('hidden_correct_answers')));
121 foreach ($correct_answers as $answer) {
122 if (!is_numeric(str_replace(',', '.', $answer[1]))) {
123 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('points_non_numeric_or_negative_msg'));
124 return false;
125 }
126 }
127 return true;
128 }
129
130 private function stripSlashesRecursive(array $data): array
131 {
132 return array_map(
133 function (int|float|string|array $v): int|float|string|array {
134 if (is_array($v)) {
135 return $this->stripSlashesRecursive($v);
136 }
137 if (is_int($v) || is_float($v)) {
138 return $v;
139 }
140 return ilUtil::stripSlashes($v);
141 },
142 $data
143 );
144 }
145
146 private function trimArrayRecursive(array $data): array
147 {
148 return array_map(
149 function (int|float|string|array $v): int|float|string|array {
150 if (is_array($v)) {
151 return $this->trimArrayRecursive($v);
152 }
153 if (is_int($v) || is_float($v)) {
154 return $v;
155 }
156 return trim($v);
157 },
158 $data
159 );
160 }
161
162 private function convertPointsToFloat(
163 array $correct_answers
164 ): array {
165 return array_map(
166 function (array $v): array {
167 $v[1] = $this->refinery->kindlyTo()->float()->transform($v[1]);
168 return $v;
169 },
170 $correct_answers
171 );
172 }
173
174 public function editQuestion(
175 bool $checkonly = false,
176 ?bool $is_save_cmd = null
177 ): bool {
178 $form = $this->editForm;
179 if ($form === null) {
180 $form = $this->buildEditForm();
181 }
182
183 /*
184 * sk 29.01.2025: This is a god aw-ful hack and one more sign,
185 * that the flow here needs to change, but we need this to set the
186 * question id on question creation (see: https://mantis.ilias.de/view.php?id=43705)
187 */
188 if ($this->object->getId() > 0) {
189 $this->ctrl->setParameterByClass(self::class, 'q_id', $this->object->getId());
190 }
191 $form->setFormAction($this->ctrl->getFormActionByClass(self::class));
192 $this->renderEditForm($form);
193 return false;
194 }
198 protected function buildEditForm(): ilPropertyFormGUI
199 {
200 $form = $this->buildBasicEditFormObject();
201 $this->addQuestionFormCommandButtons($form);
202 $this->addBasicQuestionFormProperties($form);
203 $this->populateQuestionSpecificFormPart($form);
204 $this->populateTaxonomyFormSection($form);
205
206 return $form;
207 }
208
210 {
211 $long_menu_text = new ilTextAreaInputGUI($this->lng->txt("longmenu_text"), 'longmenu_text');
212 $long_menu_text->setRequired(true);
213 $long_menu_text->setRows(10);
214 $long_menu_text->setCols(80);
215 if (!$this->object->getSelfAssessmentEditingMode()) {
216 if ($this->object->getAdditionalContentEditingMode() == assQuestion::ADDITIONAL_CONTENT_EDITING_MODE_RTE) {
217 $long_menu_text->setRteTags(ilRTESettings::_getUsedHTMLTags("assessment"));
218 $long_menu_text->setRTESupport($this->object->getId(), "qpl", "assessment");
219 $long_menu_text->setUseRte(true);
220 }
221 } else {
223 $long_menu_text->setUseTagsForRteOnly(false);
224 }
225
226 $long_menu_text->setValue($this->object->getLongMenuTextValue());
227 $form->addItem($long_menu_text);
228
229 $tpl = new ilTemplate('tpl.il_as_qpl_longmenu_question_gap_button_code.html', true, true, 'components/ILIAS/TestQuestionPool');
230 $tpl->setVariable('INSERT_GAP', $this->lng->txt('insert_gap'));
231 $tpl->parseCurrentBlock();
232 $button = new ilCustomInputGUI('&nbsp;', '');
233 $button->setHtml($tpl->get());
234 $form->addItem($button);
235
236 $min_auto_complete = new ilNumberInputGUI($this->lng->txt('min_auto_complete'), 'min_auto_complete');
237
238 $auto_complete = $this->object->getMinAutoComplete();
239 if ($auto_complete === 0) {
241 }
242 $min_auto_complete->setDecimals(0);
243 $min_auto_complete->setValue($auto_complete);
244 $min_auto_complete->setMinValue(1);
245 $min_auto_complete->setMaxValue(99);
246 $min_auto_complete->setSize(5);
247 $form->addItem($min_auto_complete);
248 // identical scoring
249 $identical_scoring = new ilCheckboxInputGUI($this->lng->txt('identical_scoring'), 'identical_scoring');
250 $identical_scoring->setValue(1);
251 $identical_scoring->setChecked($this->object->getIdenticalScoring());
252 $identical_scoring->setInfo($this->lng->txt('identical_scoring_desc'));
253 $identical_scoring->setRequired(false);
254 $form->addItem($identical_scoring);
255 $hidden_text = new ilHiddenInputGUI('hidden_text_files');
256 $form->addItem($hidden_text);
257
258 $hidden_correct = new ilHiddenInputGUI('hidden_correct_answers');
259 $form->addItem($hidden_correct);
260
261 $long_menu_language = [
262 'edit' => '[' . $this->lng->txt('edit') . ']',
263 'type' => $this->lng->txt('type'),
264 'answers' => $this->lng->txt('answers'),
265 'answer_options' => $this->lng->txt('answer_options'),
266 'correct_answers' => $this->lng->txt('correct_answers') . ':',
267 'add_answers' => '[' . $this->lng->txt('add_answers') . ']',
268 'manual_editing' => $this->lng->txt('manual_editing')
269 ];
270
271 $question_parts = [
272 'list' => json_decode($this->object->getJsonStructure()) ?? [],
273 'gap_placeholder' => assLongMenu::GAP_PLACEHOLDER,
274 'last_updated_element' => 0,
275 'replacement_word' => '',
276 'filereader_usable' => false,
277 'max_input_fields' => assLongMenu::MAX_INPUT_FIELDS
278 ];
279 $answers = $this->object->getAnswersObject();
280
281 if ($this->request_data_collector->isset('hidden_text_files')) {
282 $question_parts['list'] = $this->trimArrayRecursive(
283 $this->stripSlashesRecursive(
284 json_decode(
285 $this->request_data_collector->string('hidden_correct_answers')
286 ) ?? []
287 )
288 );
289 $answers = $this->request_data_collector->string('hidden_text_files');
290 }
291
292 $this->tpl->addJavaScript('assets/js/longMenuQuestionGapBuilder.js');
293 $this->tpl->addJavaScript('assets/js/longMenuQuestion.js');
294 $tpl = new ilTemplate("tpl.il_as_qpl_longmenu_question_gap.html", true, true, "components/ILIAS/TestQuestionPool");
295 $tpl->setVariable('MAX_INPUT_FIELDS', assLongMenu::MAX_INPUT_FIELDS);
296 $tpl->setVariable('GAP_PLACEHOLDER', assLongMenu::GAP_PLACEHOLDER);
297 $tpl->setVariable('SELECT_BOX', $this->lng->txt('insert_gap'));
298 $tpl->setVariable("SELECT", $this->lng->txt('answers_select'));
299 $tpl->setVariable("TEXT", $this->lng->txt('answers_text_box'));
300 $tpl->setVariable("POINTS", $this->lng->txt('points'));
301 $tpl->setVariable("INFO_TEXT_UPLOAD", $this->lng->txt('info_text_upload'));
302 $tpl->setVariable("TXT_BROWSE", $this->lng->txt('select_file'));
303 $tpl->setVariable('POINTS_ERROR', $this->lng->txt('enter_enough_positive_points'));
304 $tpl->setVariable('AUTOCOMPLETE_ERROR', $this->lng->txt('autocomplete_error'));
305 $tpl->setVariable('MISSING_VALUE', $this->lng->txt('msg_input_is_required'));
306 $tpl->setVariable('SAVE', $this->lng->txt('save'));
307 $tpl->setVariable('CANCEL', $this->lng->txt('cancel'));
308 $tpl->setVariable('ADD_BUTTON', $this->ui_renderer->render(
309 $this->ui_factory->button()->shy('', '')->withSymbol($this->ui_factory->symbol()->glyph()->add())
310 ));
311 $tpl->setVariable('REMOVE_BUTTON', $this->ui_renderer->render(
312 $this->ui_factory->button()->shy('', '')->withSymbol($this->ui_factory->symbol()->glyph()->remove())
313 ));
314 $tag_input = new ilTagInputGUI();
315 $tag_input->setPostVar('taggable');
316 $tag_input->setJsSelfInit(false);
317 $tag_input->setTypeAheadMinLength(1);
318 $tpl->setVariable('TAGGING_PROTOTYPE', $tag_input->render(''));
319
320 $modal_id = self::DEFAULT_MODAL_ID;
321 $tpl->setVariable('MY_MODAL', $this->getModalHtml($modal_id));
322 $tpl->parseCurrentBlock();
323 $this->tpl->addOnLoadCode(
324 'longMenuQuestion.Init(' .
325 implode(', ', [
326 json_encode($long_menu_language),
327 json_encode($question_parts),
328 $answers === '' ? '{}' : $answers,
329 json_encode($modal_id)
330 ])
331 . ');'
332 );
333
334 $button = new ilCustomInputGUI('&nbsp;', '');
335 $button->setHtml($tpl->get());
336 $form->addItem($button);
337 return $form;
338 }
339
340 private function getModalHtml(string &$modal_id): string
341 {
342 $modal = $this->ui_factory->modal()->interruptive('', '', '');
343 $doc = new DOMDocument();
344 @$doc->loadHTML($this->ui_renderer->render($modal));
345 $dialogs = $doc->getElementsByTagName('dialog');
346 $modal_id = $dialogs->item(0)->attributes->getNamedItem('id')->nodeValue ?? self::DEFAULT_MODAL_ID;
347 return $doc->saveHTML();
348 }
349
355 {
356 return $form;
357 }
358
359 public function getSolutionOutput(
360 int $active_id,
361 ?int $pass = null,
362 bool $graphical_output = false,
363 bool $result_output = false,
364 bool $show_question_only = true,
365 bool $show_feedback = false,
366 bool $show_correct_solution = false,
367 bool $show_manual_scoring = false,
368 bool $show_question_text = true,
369 bool $show_inline_feedback = true
370 ): string {
371 if (($active_id > 0) && (!$show_correct_solution)) {
372 $user_solutions = $this->object->getSolutionValues($active_id, $pass, true);
373 } else {
374 $user_solutions = [];
375 foreach ($this->object->getCorrectAnswersForQuestionSolution($this->object->getId()) as $idx => $val) {
376 $user_solutions[] = [
377 'value1' => $idx,
378 'value2' => $val,
379 ];
380 }
381 }
382
383 return $this->renderSolutionOutput(
384 $user_solutions,
385 $active_id,
386 $pass,
387 $graphical_output,
388 $result_output,
389 $show_question_only,
390 $show_feedback,
391 $show_correct_solution,
392 $show_manual_scoring,
393 $show_question_text,
394 false,
395 $show_inline_feedback
396 );
397 }
398
399 public function renderSolutionOutput(
400 mixed $user_solutions,
401 int $active_id,
402 ?int $pass,
403 bool $graphical_output = false,
404 bool $result_output = false,
405 bool $show_question_only = true,
406 bool $show_feedback = false,
407 bool $show_correct_solution = false,
408 bool $show_manual_scoring = false,
409 bool $show_question_text = true,
410 bool $show_autosave_title = false,
411 bool $show_inline_feedback = false,
412 ): ?string {
413
414 $user_solution = [];
415 foreach ($user_solutions as $idx => $solution_value) {
416 $user_solution[$solution_value["value1"]] = $solution_value["value2"];
417 }
418
419 $template = new ilTemplate("tpl.il_as_qpl_longmenu_question_output_solution.html", true, true, "components/ILIAS/TestQuestionPool");
420 if ($show_question_text) {
421 $template->setVariable("QUESTIONTEXT", $this->renderLatex($this->object->getQuestionForHTMLOutput()));
422 }
423 $template->setVariable('LONGMENU_TEXT_SOLUTION', $this->getLongMenuTextWithInputFieldsInsteadOfGaps($user_solution, true, $graphical_output));
424
425 $solution_template = new ilTemplate("tpl.il_as_tst_solution_output.html", true, true, "components/ILIAS/TestQuestionPool");
426 $question_output = $template->get();
427 $feedback = '';
428 if ($show_feedback) {
429 if (!$this->isTestPresentationContext()) {
430 $fb = $this->getGenericFeedbackOutput((int) $active_id, $pass);
431 $feedback .= strlen($fb) ? $fb : '';
432 }
433
434 $fb = $this->getSpecificFeedbackOutput([]);
435 $feedback .= strlen($fb) ? $fb : '';
436 }
437 if (strlen($feedback)) {
438 $cssClass = (
439 $this->hasCorrectSolution($active_id, $pass) ?
441 );
442
443 $solution_template->setVariable("ILC_FB_CSS_CLASS", $cssClass);
444 $solution_template->setVariable("FEEDBACK", ilLegacyFormElementsUtil::prepareTextareaOutput($feedback, true));
445 }
446
447 $solution_template->setVariable("SOLUTION_OUTPUT", $question_output);
448
449 $solution_output = $solution_template->get();
450
451 if (!$show_question_only) {
452 $solution_output = $this->getILIASPage($solution_output);
453 }
454
455 return $solution_output;
456 }
457
458 public function getPreview(
459 bool $show_question_only = false,
460 bool $show_inline_feedback = false
461 ): string {
462 $user_solution = is_object($this->getPreviewSession()) ? (array) $this->getPreviewSession()->getParticipantsSolution() : [];
463 $user_solution = array_values($user_solution);
464
465 $template = $this->getTemplateForPreviewAndTest($user_solution);
466
467 $question_output = $template->get();
468 if (!$show_question_only) {
469 $question_output = $this->getILIASPage($question_output);
470 }
471 return $question_output;
472 }
473
474 public function getTestOutput(
475 int $active_id,
476 int $pass,
477 bool $is_question_postponed = false,
478 array|bool $user_post_solutions = false,
479 bool $show_specific_inline_feedback = false
480 ): string {
481 $user_solution = [];
482 if ($active_id) {
483 $solutions = $this->object->getUserSolutionPreferingIntermediate($active_id, $pass);
484 foreach ($solutions as $idx => $solution_value) {
485 $user_solution[$solution_value['value1']] = $solution_value['value2'];
486 }
487 }
488
489 $template = $this->getTemplateForPreviewAndTest($user_solution);
490
491 $question_output = $template->get();
492 $page_output = $this->outQuestionPage('', $is_question_postponed, $active_id, $question_output);
493 return $page_output;
494 }
495
496 protected function getTemplateForPreviewAndTest(array $user_solution): ilTemplate
497 {
498 $template = new ilTemplate('tpl.il_as_qpl_longmenu_question_output.html', true, true, 'components/ILIAS/TestQuestionPool');
499 $this->tpl->addJavaScript('assets/js/longMenuQuestionPlayer.js');
500 $this->tpl->addOnLoadCode('il.test.player.longmenu.init('
501 . $this->object->getMinAutoComplete() . ', '
502 . json_encode($this->object->getAvailableAnswerOptions())
503 . ')');
504
505 $template->setVariable('QUESTIONTEXT', $this->renderLatex($this->renderLatex($this->object->getQuestionForHTMLOutput())));
506 $template->setVariable('LONGMENU_TEXT', $this->getLongMenuTextWithInputFieldsInsteadOfGaps($user_solution));
507 return $template;
508 }
509
510 public function getSpecificFeedbackOutput(array $userSolution): string
511 {
512 if (!$this->object->feedbackOBJ->specificAnswerFeedbackExists()) {
513 return '';
514 }
515
516 $feedback = '<table class="test_specific_feedback"><tbody>';
517 $gaps = $this->object->getCorrectAnswers();
518 foreach ($gaps as $index => $answer) {
519 $caption = assLongMenu::GAP_PLACEHOLDER . ' ';
520 $caption .= $index + 1 . ': ';
521
522 $feedback .= '<tr><td>';
523
524 $feedback .= $caption . '</td><td>';
525 $feedback .= $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
526 $this->object->getId(),
527 0,
528 $index
529 ) . '</td> </tr>';
530 }
531 $feedback .= '</tbody></table>';
533 }
534
535
546 {
547 return [];
548 }
549
550 public function getLongMenuTextWithInputFieldsInsteadOfGaps($user_solution = [], $solution = false, $graphical = false): string
551 {
552 $return_value = '';
553 $text_array = preg_split("/\\[" . assLongMenu::GAP_PLACEHOLDER . " (\\d+)\\]/", $this->object->getLongMenuTextValue());
554 $correct_answers = $this->object->getCorrectAnswers();
555 $answers = $this->object->getAnswers();
556 foreach ($text_array as $key => $value) {
557 $answer_is_correct = false;
558 $user_value = '';
559 $return_value .= ilLegacyFormElementsUtil::prepareTextareaOutput($value, true);
560 if ($key < sizeof($text_array) - 1) {
561 if (!array_key_exists($key, $correct_answers)) {
562 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('longmenu_answeroptions_differ'));
563 continue;
564 }
565 if ($correct_answers[$key][2] === assLongMenu::ANSWER_TYPE_TEXT_VAL) {
566 if (array_key_exists($key, $user_solution)) {
567 $user_value = $user_solution[$key];
568 if (in_array($user_value, $correct_answers[$key][0])) {
569 $answer_is_correct = true;
570 }
571 }
572
573 $return_value .= $this->getTextGapTemplate($key, $user_value, $solution, $answer_is_correct, $graphical);
574 } elseif ($correct_answers[$key][2] === assLongMenu::ANSWER_TYPE_SELECT_VAL) {
575 if (array_key_exists($key, $user_solution)) {
576 $user_value = $user_solution[$key];
577 if (in_array($user_value, $correct_answers[$key][0])) {
578 $answer_is_correct = true;
579 }
580 }
581 $return_value .= $this->getSelectGapTemplate($key, $answers[$key], $user_value, $solution, $answer_is_correct, $graphical);
582 }
583 }
584 }
585 return $return_value;
586 }
587
588 private function getTextGapTemplate($key, $value, $solution, $ok = false, $graphical = false): string
589 {
590 $tpl = new ilTemplate('tpl.il_as_qpl_longmenu_question_text_gap.html', true, true, 'components/ILIAS/TestQuestionPool');
591 if ($solution) {
592 $tpl->setVariable('DISABLED', 'disabled');
593 $tpl->setVariable('JS_IGNORE', '_ignore');
594 if ($graphical) {
595 $correctness_icon = $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_NOT_OK);
596 if ($ok) {
597 $correctness_icon = $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_OK);
598 }
599 $tpl->setVariable("ICON_OK", $correctness_icon);
600 }
601 }
602 if ($solution) {
603 $tpl->setVariable('SIZE', 'size="' . mb_strlen($value) . '"');
604 }
605 $tpl->setVariable('VALUE', htmlentities($value));
606 $tpl->setVariable('KEY', $key);
607
608 return $tpl->get();
609 }
610
611 private function getSelectGapTemplate($key, $answers, $user_value, $solution, $ok = false, $graphical = false): string
612 {
613 $tpl = new ilTemplate("tpl.il_as_qpl_longmenu_question_select_gap.html", true, true, "components/ILIAS/TestQuestionPool");
614 $tpl->setVariable('KEY', $key);
615 if ($solution) {
616 $tpl->setVariable('DISABLED', 'disabled');
617 $tpl->setVariable('JS_IGNORE', '_ignore');
618 $tpl->setCurrentBlock('best_solution');
619 if ($user_value == -1) {
620 $tpl->setVariable("SOLUTION", $this->lng->txt("please_select"));
621 } else {
622 $tpl->setVariable('SOLUTION', $user_value);
623 }
624 if ($graphical) {
625 $correctness_icon = $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_NOT_OK);
626 if ($ok) {
627 $correctness_icon = $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_OK);
628 }
629 $tpl->setVariable("ICON_OK", $correctness_icon);
630 }
631 $tpl->parseCurrentBlock();
632 } else {
633 $tpl->setVariable("PLEASE_SELECT", $this->lng->txt("please_select"));
634 foreach ($answers as $value) {
635 $tpl->setCurrentBlock('select_option');
636 $tpl->setVariable('VALUE', $value);
637 if ($value == $user_value) {
638 $tpl->setVariable('SELECTED', 'selected');
639 }
640 $tpl->parseCurrentBlock();
641 }
642 }
643 return $tpl->get();
644 }
645
646 public function getSubQuestionsIndex(): array
647 {
648 return array_keys($this->object->getAnswers());
649 }
650
651 public function getAnswersFrequency($relevantAnswers, $questionIndex): array
652 {
653 $answers = [];
654
655 foreach ($relevantAnswers as $row) {
656 if ($row['value1'] != $questionIndex) {
657 continue;
658 }
659
660 if (!isset($answers[$row['value2']])) {
661 //$label = $this->getAnswerTextLabel($row['value1'], $row['value2']);
662
663 $answers[$row['value2']] = [
664 'answer' => $row['value2'], 'frequency' => 0
665 ];
666 }
667
668 $answers[$row['value2']]['frequency']++;
669 }
670
671 return $answers;
672 }
673
674 public function getAnswerFrequencyTableGUI($parentGui, $parentCmd, $relevantAnswers, $questionIndex): ilAnswerFrequencyStatisticTableGUI
675 {
676 global $DIC; /* @var ILIAS\DI\Container $DIC */
677
678 $table = parent::getAnswerFrequencyTableGUI(
679 $parentGui,
680 $parentCmd,
681 $relevantAnswers,
682 $questionIndex
683 );
684
685 $table->setTitle(
686 sprintf(
687 $DIC->language()->txt('tst_corrections_answers_tbl_subindex'),
688 $DIC->language()->txt('longmenu') . ' ' . ($questionIndex + 1)
689 )
690 );
691
692 return $table;
693 }
694
696 {
697 $correct_answers = $this->object->getCorrectAnswers();
698
699 foreach ($this->object->getAnswers() as $lm_index => $lm) {
700 $lm_values = [
701 'answers_all' => [0 => $lm],
702 'answers_all_count' => count($lm),
703 'answers_correct' => $correct_answers[$lm_index][0]
704 ];
705
706 $lm_points = $correct_answers[$lm_index][1];
707
708 $section = new ilFormSectionHeaderGUI();
709 $section->setTitle($this->lng->txt('longmenu') . ' ' . ($lm_index + 1));
710 $form->addItem($section);
711
712 $lm_input = new ilAssLongmenuCorrectionsInputGUI(
713 $this->lng->txt('answers'),
714 'longmenu_' . $lm_index
715 );
716
717 $lm_input->setRequired(true);
718
719 $lm_input->setValues($lm_values);
720
721 $form->addItem($lm_input);
722
723 $points_inp = new ilNumberInputGUI($this->lng->txt("points"), 'points_' . $lm_index);
724 $points_inp->setRequired(true);
725 $points_inp->allowDecimals(true);
726 $points_inp->setSize(4);
727 $points_inp->setMinValue(0);
728 $points_inp->setMinvalueShouldBeGreater(false);
729 $points_inp->setValue($lm_points);
730 $form->addItem($points_inp);
731 }
732 }
733
735 {
736 $correct_answers = $this->object->getCorrectAnswers();
737
738 foreach ($this->object->getAnswers() as $lm_index => $lm) {
739 $points_input = $this->refinery->kindlyTo()->float()->transform(
740 $form->getInput('points_' . $lm_index)
741 );
742 $correct_answers_input = (array) $form->getInput('longmenu_' . $lm_index . '_tags');
743
744 foreach ($correct_answers_input as $idx => $answer) {
745 if (in_array($answer, $lm)) {
746 continue;
747 }
748
749 unset($correct_answers_input[$idx]);
750 }
751
752 $correct_answers[$lm_index][0] = array_values($correct_answers_input);
753 $correct_answers[$lm_index][1] = $points_input;
754 }
755
756 $this->object->setCorrectAnswers($correct_answers);
757 }
758}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
$check
Definition: buildRTE.php:81
Builds a Color from either hex- or rgb values.
Definition: Factory.php:31
trimArrayRecursive(array $data)
getModalHtml(string &$modal_id)
getSolutionOutput(int $active_id, ?int $pass=null, 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_inline_feedback=true)
getSelectGapTemplate($key, $answers, $user_value, $solution, $ok=false, $graphical=false)
getAnswersFrequency($relevantAnswers, $questionIndex)
getAfterParticipationSuppressionQuestionPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
getTemplateForPreviewAndTest(array $user_solution)
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,)
saveCorrectionsFormProperties(ilPropertyFormGUI $form)
getAnswerFrequencyTableGUI($parentGui, $parentCmd, $relevantAnswers, $questionIndex)
readonly UIRenderer $ui_renderer
convertPointsToFloat(array $correct_answers)
writePostData(bool $always=false)
{Evaluates a posted edit form and writes the form data in the question object.integer A positive valu...
readonly UIFactory $ui_factory
populateCorrectionsFormProperties(ilPropertyFormGUI $form)
populateQuestionSpecificFormPart(ilPropertyFormGUI $form)
Adds the question specific forms parts to a question property form gui.
getTestOutput(int $active_id, int $pass, bool $is_question_postponed=false, array|bool $user_post_solutions=false, bool $show_specific_inline_feedback=false)
getLongMenuTextWithInputFieldsInsteadOfGaps($user_solution=[], $solution=false, $graphical=false)
getTextGapTemplate($key, $value, $solution, $ok=false, $graphical=false)
editQuestion(bool $checkonly=false, ?bool $is_save_cmd=null)
stripSlashesRecursive(array $data)
writeQuestionSpecificPostData(ilPropertyFormGUI $form)
Extracts the question specific values from the request and applies them to the data object.
getPreview(bool $show_question_only=false, bool $show_inline_feedback=false)
populateAnswerSpecificFormPart(ilPropertyFormGUI $form)
getSpecificFeedbackOutput(array $userSolution)
Returns the answer specific feedback for the question.
const MIN_LENGTH_AUTOCOMPLETE
const ANSWER_TYPE_TEXT_VAL
const ANSWER_TYPE_SELECT_VAL
const ADDITIONAL_CONTENT_EDITING_MODE_RTE
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static stripSlashesRecursive($a_data, bool $a_strip_html=true, string $a_allow="")
static getSelfAssessmentTags()
Get tags allowed in question tags in self assessment mode.
This class represents a checkbox property in a property form.
This class represents a custom property in a property form.
This class represents a section header in a property form.
This class represents a hidden form property in a property form.
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,...
This class represents a number property in a property form.
This class represents a property form user interface.
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-...
static _getUsedHTMLTags(string $module='')
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
special template class to simplify handling of ITX/PEAR
This class represents a text area property in a property form.
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
return['delivery_method'=> 'php',]
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
An entity that renders components to a string output.
Definition: Renderer.php:31
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
if(!file_exists('../ilias.ini.php'))
global $DIC
Definition: shib_login.php:26