ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
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->raw('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($this->trimArrayRecursive($this->stripSlashesRecursive(json_decode($hidden_correct_answers))));
89 $this->object->setAnswerType(ilArrayUtil::stripSlashesRecursive($long_menu_type));
90 $this->object->setQuestion($this->request_data_collector->string('question'));
91 $this->object->setMinAutoComplete($min_auto_complete);
92 $this->object->setIdenticalScoring($this->request_data_collector->int('identical_scoring'));
93
95 }
96
97 private function verifyAnswerOptions(): bool
98 {
99 $longmenu_text = $this->request_data_collector->raw('longmenu_text') ?? '';
100 $hidden_text_files = $this->request_data_collector->raw('hidden_text_files') ?? '';
101 $answer_options_from_text = preg_split(
102 "/\\[" . assLongMenu::GAP_PLACEHOLDER . " (\\d+)\\]/",
103 $longmenu_text
104 );
105
106 $answer_options_from_files = $this->stripSlashesRecursive(json_decode($hidden_text_files));
107 if (count($answer_options_from_text) - 1 !== count($answer_options_from_files)) {
108 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('longmenu_answeroptions_differ'));
109 return false;
110 }
111
112 $correct_answers = $this->stripSlashesRecursive(json_decode($this->request_data_collector->raw('hidden_correct_answers')));
113 foreach ($correct_answers as $answer) {
114 if (!is_numeric(str_replace(',', '.', $answer[1]))) {
115 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('points_non_numeric_or_negative_msg'));
116 return false;
117 }
118 }
119 return true;
120 }
121
122 private function stripSlashesRecursive(array $data): array
123 {
124 return array_map(
125 function (string|array $v): string|array {
126 if (is_array($v)) {
127 return $this->stripSlashesRecursive($v);
128 }
129 return ilUtil::stripSlashes($v);
130 },
131 $data
132 );
133 }
134
135 private function trimArrayRecursive(array $data): array
136 {
137 return array_map(
138 function (string|array $v): string|array {
139 if (is_array($v)) {
140 return $this->trimArrayRecursive($v);
141 }
142 return trim($v);
143 },
144 $data
145 );
146 }
147
148 public function editQuestion(
149 bool $checkonly = false,
150 ?bool $is_save_cmd = null
151 ): bool {
152 $form = $this->editForm;
153 if ($form === null) {
154 $form = $this->buildEditForm();
155 }
156
157 /*
158 * sk 29.01.2025: This is a god aw-ful hack and one more sign,
159 * that the flow here needs to change, but we need this to set the
160 * question id on question creation (see: https://mantis.ilias.de/view.php?id=43705)
161 */
162 if ($this->object->getId() > 0) {
163 $this->ctrl->setParameterByClass(self::class, 'q_id', $this->object->getId());
164 }
165 $form->setFormAction($this->ctrl->getFormActionByClass(self::class));
166 $this->renderEditForm($form);
167 return false;
168 }
172 protected function buildEditForm(): ilPropertyFormGUI
173 {
174 $form = $this->buildBasicEditFormObject();
175 $this->addQuestionFormCommandButtons($form);
176 $this->addBasicQuestionFormProperties($form);
177 $this->populateQuestionSpecificFormPart($form);
178 $this->populateTaxonomyFormSection($form);
179
180 return $form;
181 }
182
184 {
185 $long_menu_text = new ilTextAreaInputGUI($this->lng->txt("longmenu_text"), 'longmenu_text');
186 $long_menu_text->setRequired(true);
187 $long_menu_text->setRows(10);
188 $long_menu_text->setCols(80);
189 if (!$this->object->getSelfAssessmentEditingMode()) {
190 if ($this->object->getAdditionalContentEditingMode() == assQuestion::ADDITIONAL_CONTENT_EDITING_MODE_RTE) {
191 $long_menu_text->setRteTags(ilRTESettings::_getUsedHTMLTags("assessment"));
192 $long_menu_text->setRTESupport($this->object->getId(), "qpl", "assessment");
193 $long_menu_text->setUseRte(true);
194 }
195 } else {
197 $long_menu_text->setUseTagsForRteOnly(false);
198 }
199
200 $long_menu_text->setValue($this->object->getLongMenuTextValue());
201 $form->addItem($long_menu_text);
202
203 $tpl = new ilTemplate('tpl.il_as_qpl_longmenu_question_gap_button_code.html', true, true, 'components/ILIAS/TestQuestionPool');
204 $tpl->setVariable('INSERT_GAP', $this->lng->txt('insert_gap'));
205 $tpl->parseCurrentBlock();
206 $button = new ilCustomInputGUI('&nbsp;', '');
207 $button->setHtml($tpl->get());
208 $form->addItem($button);
209
210 $min_auto_complete = new ilNumberInputGUI($this->lng->txt('min_auto_complete'), 'min_auto_complete');
211
212 $auto_complete = $this->object->getMinAutoComplete();
213 if ($auto_complete === 0) {
215 }
216 $min_auto_complete->setDecimals(0);
217 $min_auto_complete->setValue($auto_complete);
218 $min_auto_complete->setMinValue(1);
219 $min_auto_complete->setMaxValue(99);
220 $min_auto_complete->setSize(5);
221 $form->addItem($min_auto_complete);
222 // identical scoring
223 $identical_scoring = new ilCheckboxInputGUI($this->lng->txt('identical_scoring'), 'identical_scoring');
224 $identical_scoring->setValue(1);
225 $identical_scoring->setChecked($this->object->getIdenticalScoring());
226 $identical_scoring->setInfo($this->lng->txt('identical_scoring_desc'));
227 $identical_scoring->setRequired(false);
228 $form->addItem($identical_scoring);
229 $hidden_text = new ilHiddenInputGUI('hidden_text_files');
230 $form->addItem($hidden_text);
231
232 $hidden_correct = new ilHiddenInputGUI('hidden_correct_answers');
233 $form->addItem($hidden_correct);
234
235 $long_menu_language = [
236 'edit' => '[' . $this->lng->txt('edit') . ']',
237 'type' => $this->lng->txt('type'),
238 'answers' => $this->lng->txt('answers'),
239 'answer_options' => $this->lng->txt('answer_options'),
240 'correct_answers' => $this->lng->txt('correct_answers') . ':',
241 'add_answers' => '[' . $this->lng->txt('add_answers') . ']',
242 'manual_editing' => $this->lng->txt('manual_editing')
243 ];
244
245 $question_parts = [
246 'list' => json_decode($this->object->getJsonStructure()) ?? [],
247 'gap_placeholder' => assLongMenu::GAP_PLACEHOLDER,
248 'last_updated_element' => 0,
249 'replacement_word' => '',
250 'filereader_usable' => false,
251 'max_input_fields' => assLongMenu::MAX_INPUT_FIELDS
252 ];
253 $answers = $this->object->getAnswersObject();
254
255 if ($this->request_data_collector->isset('hidden_text_files')) {
256 $question_parts['list'] = json_decode($this->request_data_collector->raw('hidden_correct_answers')) ?? [];
257 $answers = $this->request_data_collector->raw('hidden_text_files');
258 }
259
260 $this->tpl->addJavaScript('assets/js/longMenuQuestionGapBuilder.js');
261 $this->tpl->addJavaScript('assets/js/longMenuQuestion.js');
262 $tpl = new ilTemplate("tpl.il_as_qpl_longmenu_question_gap.html", true, true, "components/ILIAS/TestQuestionPool");
263 $tpl->setVariable('MAX_INPUT_FIELDS', assLongMenu::MAX_INPUT_FIELDS);
264 $tpl->setVariable('GAP_PLACEHOLDER', assLongMenu::GAP_PLACEHOLDER);
265 $tpl->setVariable('SELECT_BOX', $this->lng->txt('insert_gap'));
266 $tpl->setVariable("SELECT", $this->lng->txt('answers_select'));
267 $tpl->setVariable("TEXT", $this->lng->txt('answers_text_box'));
268 $tpl->setVariable("POINTS", $this->lng->txt('points'));
269 $tpl->setVariable("INFO_TEXT_UPLOAD", $this->lng->txt('info_text_upload'));
270 $tpl->setVariable("TXT_BROWSE", $this->lng->txt('select_file'));
271 $tpl->setVariable('POINTS_ERROR', $this->lng->txt('enter_enough_positive_points'));
272 $tpl->setVariable('AUTOCOMPLETE_ERROR', $this->lng->txt('autocomplete_error'));
273 $tpl->setVariable('MISSING_VALUE', $this->lng->txt('msg_input_is_required'));
274 $tpl->setVariable('SAVE', $this->lng->txt('save'));
275 $tpl->setVariable('CANCEL', $this->lng->txt('cancel'));
276 $tpl->setVariable('ADD_BUTTON', $this->ui_renderer->render(
277 $this->ui_factory->symbol()->glyph()->add()->withAction('#')
278 ));
279 $tpl->setVariable('REMOVE_BUTTON', $this->ui_renderer->render(
280 $this->ui_factory->symbol()->glyph()->remove()->withAction('#')
281 ));
282 $tag_input = new ilTagInputGUI();
283 $tag_input->setPostVar('taggable');
284 $tag_input->setJsSelfInit(false);
285 $tag_input->setTypeAheadMinLength(1);
286 $tpl->setVariable('TAGGING_PROTOTYPE', $tag_input->render(''));
287
288 $modal_id = self::DEFAULT_MODAL_ID;
289 $tpl->setVariable('MY_MODAL', $this->getModalHtml($modal_id));
290 $tpl->parseCurrentBlock();
291 $this->tpl->addOnLoadCode(
292 'longMenuQuestion.Init(' .
293 implode(', ', [
294 json_encode($long_menu_language),
295 json_encode($question_parts),
296 $answers === '' ? '{}' : $answers,
297 json_encode($modal_id)
298 ])
299 . ');'
300 );
301
302 $button = new ilCustomInputGUI('&nbsp;', '');
303 $button->setHtml($tpl->get());
304 $form->addItem($button);
305 return $form;
306 }
307
308 private function getModalHtml(string &$modal_id): string
309 {
310 $modal = $this->ui_factory->modal()->interruptive('', '', '');
311 $doc = new DOMDocument();
312 @$doc->loadHTML($this->ui_renderer->render($modal));
313 $dialogs = $doc->getElementsByTagName('dialog');
314 $modal_id = $dialogs->item(0)->attributes->getNamedItem('id')->nodeValue ?? self::DEFAULT_MODAL_ID;
315 return $doc->saveHTML();
316 }
317
323 {
324 return $form;
325 }
326
327 public function getSolutionOutput(
328 int $active_id,
329 ?int $pass = null,
330 bool $graphical_output = false,
331 bool $result_output = false,
332 bool $show_question_only = true,
333 bool $show_feedback = false,
334 bool $show_correct_solution = false,
335 bool $show_manual_scoring = false,
336 bool $show_question_text = true,
337 bool $show_inline_feedback = true
338 ): string {
339 if (($active_id > 0) && (!$show_correct_solution)) {
340 $user_solutions = $this->object->getSolutionValues($active_id, $pass, true);
341 } else {
342 $user_solutions = [];
343 foreach ($this->object->getCorrectAnswersForQuestionSolution($this->object->getId()) as $idx => $val) {
344 $user_solutions[] = [
345 'value1' => $idx,
346 'value2' => $val,
347 ];
348 }
349 }
350
351 return $this->renderSolutionOutput(
352 $user_solutions,
353 $active_id,
354 $pass,
355 $graphical_output,
356 $result_output,
357 $show_question_only,
358 $show_feedback,
359 $show_correct_solution,
360 $show_manual_scoring,
361 $show_question_text,
362 false,
363 $show_inline_feedback
364 );
365 }
366
367 public function renderSolutionOutput(
368 mixed $user_solutions,
369 int $active_id,
370 ?int $pass,
371 bool $graphical_output = false,
372 bool $result_output = false,
373 bool $show_question_only = true,
374 bool $show_feedback = false,
375 bool $show_correct_solution = false,
376 bool $show_manual_scoring = false,
377 bool $show_question_text = true,
378 bool $show_autosave_title = false,
379 bool $show_inline_feedback = false,
380 ): ?string {
381
382 $user_solution = [];
383 foreach ($user_solutions as $idx => $solution_value) {
384 $user_solution[$solution_value["value1"]] = $solution_value["value2"];
385 }
386
387 $template = new ilTemplate("tpl.il_as_qpl_longmenu_question_output_solution.html", true, true, "components/ILIAS/TestQuestionPool");
388 if ($show_question_text) {
389 $template->setVariable("QUESTIONTEXT", $this->renderLatex($this->object->getQuestionForHTMLOutput()));
390 }
391 $template->setVariable('LONGMENU_TEXT_SOLUTION', $this->getLongMenuTextWithInputFieldsInsteadOfGaps($user_solution, true, $graphical_output));
392
393 $solution_template = new ilTemplate("tpl.il_as_tst_solution_output.html", true, true, "components/ILIAS/TestQuestionPool");
394 $question_output = $template->get();
395 $feedback = '';
396 if ($show_feedback) {
397 if (!$this->isTestPresentationContext()) {
398 $fb = $this->getGenericFeedbackOutput((int) $active_id, $pass);
399 $feedback .= strlen($fb) ? $fb : '';
400 }
401
402 $fb = $this->getSpecificFeedbackOutput([]);
403 $feedback .= strlen($fb) ? $fb : '';
404 }
405 if (strlen($feedback)) {
406 $cssClass = (
407 $this->hasCorrectSolution($active_id, $pass) ?
409 );
410
411 $solution_template->setVariable("ILC_FB_CSS_CLASS", $cssClass);
412 $solution_template->setVariable("FEEDBACK", ilLegacyFormElementsUtil::prepareTextareaOutput($feedback, true));
413 }
414
415 $solution_template->setVariable("SOLUTION_OUTPUT", $question_output);
416
417 $solution_output = $solution_template->get();
418
419 if (!$show_question_only) {
420 $solution_output = $this->getILIASPage($solution_output);
421 }
422
423 return $solution_output;
424 }
425
426 public function getPreview(
427 bool $show_question_only = false,
428 bool $show_inline_feedback = false
429 ): string {
430 $user_solution = is_object($this->getPreviewSession()) ? (array) $this->getPreviewSession()->getParticipantsSolution() : [];
431 $user_solution = array_values($user_solution);
432
433 $template = $this->getTemplateForPreviewAndTest($user_solution);
434
435 $question_output = $template->get();
436 if (!$show_question_only) {
437 $question_output = $this->getILIASPage($question_output);
438 }
439 return $question_output;
440 }
441
442 public function getTestOutput(
443 int $active_id,
444 int $pass,
445 bool $is_question_postponed = false,
446 array|bool $user_post_solutions = false,
447 bool $show_specific_inline_feedback = false
448 ): string {
449 $user_solution = [];
450 if ($active_id) {
451 $solutions = $this->object->getUserSolutionPreferingIntermediate($active_id, $pass);
452 foreach ($solutions as $idx => $solution_value) {
453 $user_solution[$solution_value['value1']] = $solution_value['value2'];
454 }
455 }
456
457 $template = $this->getTemplateForPreviewAndTest($user_solution);
458
459 $question_output = $template->get();
460 $page_output = $this->outQuestionPage('', $is_question_postponed, $active_id, $question_output);
461 return $page_output;
462 }
463
464 protected function getTemplateForPreviewAndTest(array $user_solution): ilTemplate
465 {
466 $template = new ilTemplate('tpl.il_as_qpl_longmenu_question_output.html', true, true, 'components/ILIAS/TestQuestionPool');
467 $this->tpl->addJavaScript('assets/js/longMenuQuestionPlayer.js');
468 $this->tpl->addOnLoadCode('il.test.player.longmenu.init('
469 . $this->object->getMinAutoComplete() . ', '
470 . json_encode($this->object->getAvailableAnswerOptions())
471 . ')');
472
473 $template->setVariable('QUESTIONTEXT', $this->renderLatex($this->renderLatex($this->object->getQuestionForHTMLOutput())));
474 $template->setVariable('LONGMENU_TEXT', $this->getLongMenuTextWithInputFieldsInsteadOfGaps($user_solution));
475 return $template;
476 }
477
478 public function getSpecificFeedbackOutput(array $userSolution): string
479 {
480 if (!$this->object->feedbackOBJ->specificAnswerFeedbackExists()) {
481 return '';
482 }
483
484 $feedback = '<table class="test_specific_feedback"><tbody>';
485 $gaps = $this->object->getCorrectAnswers();
486 foreach ($gaps as $index => $answer) {
487 $caption = assLongMenu::GAP_PLACEHOLDER . ' ';
488 $caption .= $index + 1 . ': ';
489
490 $feedback .= '<tr><td>';
491
492 $feedback .= $caption . '</td><td>';
493 $feedback .= $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
494 $this->object->getId(),
495 0,
496 $index
497 ) . '</td> </tr>';
498 }
499 $feedback .= '</tbody></table>';
501 }
502
503
514 {
515 return [];
516 }
517
518 public function getLongMenuTextWithInputFieldsInsteadOfGaps($user_solution = [], $solution = false, $graphical = false): string
519 {
520 $return_value = '';
521 $text_array = preg_split("/\\[" . assLongMenu::GAP_PLACEHOLDER . " (\\d+)\\]/", $this->object->getLongMenuTextValue());
522 $correct_answers = $this->object->getCorrectAnswers();
523 $answers = $this->object->getAnswers();
524 foreach ($text_array as $key => $value) {
525 $answer_is_correct = false;
526 $user_value = '';
527 $return_value .= ilLegacyFormElementsUtil::prepareTextareaOutput($value, true);
528 if ($key < sizeof($text_array) - 1) {
529 if (!array_key_exists($key, $correct_answers)) {
530 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('longmenu_answeroptions_differ'));
531 continue;
532 }
533 if ($correct_answers[$key][2] === assLongMenu::ANSWER_TYPE_TEXT_VAL) {
534 if (array_key_exists($key, $user_solution)) {
535 $user_value = $user_solution[$key];
536 if (in_array($user_value, $correct_answers[$key][0])) {
537 $answer_is_correct = true;
538 }
539 }
540
541 $return_value .= $this->getTextGapTemplate($key, $user_value, $solution, $answer_is_correct, $graphical);
542 } elseif ($correct_answers[$key][2] === assLongMenu::ANSWER_TYPE_SELECT_VAL) {
543 if (array_key_exists($key, $user_solution)) {
544 $user_value = $user_solution[$key];
545 if (in_array($user_value, $correct_answers[$key][0])) {
546 $answer_is_correct = true;
547 }
548 }
549 $return_value .= $this->getSelectGapTemplate($key, $answers[$key], $user_value, $solution, $answer_is_correct, $graphical);
550 }
551 }
552 }
553 return $return_value;
554 }
555
556 private function getTextGapTemplate($key, $value, $solution, $ok = false, $graphical = false): string
557 {
558 $tpl = new ilTemplate('tpl.il_as_qpl_longmenu_question_text_gap.html', true, true, 'components/ILIAS/TestQuestionPool');
559 if ($solution) {
560 $tpl->setVariable('DISABLED', 'disabled');
561 $tpl->setVariable('JS_IGNORE', '_ignore');
562 if ($graphical) {
563 $correctness_icon = $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_NOT_OK);
564 if ($ok) {
565 $correctness_icon = $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_OK);
566 }
567 $tpl->setVariable("ICON_OK", $correctness_icon);
568 }
569 }
570 if ($solution) {
571 $tpl->setVariable('SIZE', 'size="' . mb_strlen($value) . '"');
572 }
573 $tpl->setVariable('VALUE', htmlentities($value));
574 $tpl->setVariable('KEY', $key);
575
576 return $tpl->get();
577 }
578
579 private function getSelectGapTemplate($key, $answers, $user_value, $solution, $ok = false, $graphical = false): string
580 {
581 $tpl = new ilTemplate("tpl.il_as_qpl_longmenu_question_select_gap.html", true, true, "components/ILIAS/TestQuestionPool");
582 $tpl->setVariable('KEY', $key);
583 if ($solution) {
584 $tpl->setVariable('DISABLED', 'disabled');
585 $tpl->setVariable('JS_IGNORE', '_ignore');
586 $tpl->setCurrentBlock('best_solution');
587 if ($user_value == -1) {
588 $tpl->setVariable("SOLUTION", $this->lng->txt("please_select"));
589 } else {
590 $tpl->setVariable('SOLUTION', $user_value);
591 }
592 if ($graphical) {
593 $correctness_icon = $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_NOT_OK);
594 if ($ok) {
595 $correctness_icon = $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_OK);
596 }
597 $tpl->setVariable("ICON_OK", $correctness_icon);
598 }
599 $tpl->parseCurrentBlock();
600 } else {
601 $tpl->setVariable("PLEASE_SELECT", $this->lng->txt("please_select"));
602 foreach ($answers as $value) {
603 $tpl->setCurrentBlock('select_option');
604 $tpl->setVariable('VALUE', $value);
605 if ($value == $user_value) {
606 $tpl->setVariable('SELECTED', 'selected');
607 }
608 $tpl->parseCurrentBlock();
609 }
610 }
611 return $tpl->get();
612 }
613
614 public function getSubQuestionsIndex(): array
615 {
616 return array_keys($this->object->getAnswers());
617 }
618
619 public function getAnswersFrequency($relevantAnswers, $questionIndex): array
620 {
621 $answers = [];
622
623 foreach ($relevantAnswers as $row) {
624 if ($row['value1'] != $questionIndex) {
625 continue;
626 }
627
628 if (!isset($answers[$row['value2']])) {
629 //$label = $this->getAnswerTextLabel($row['value1'], $row['value2']);
630
631 $answers[$row['value2']] = [
632 'answer' => $row['value2'], 'frequency' => 0
633 ];
634 }
635
636 $answers[$row['value2']]['frequency']++;
637 }
638
639 return $answers;
640 }
641
642 public function getAnswerFrequencyTableGUI($parentGui, $parentCmd, $relevantAnswers, $questionIndex): ilAnswerFrequencyStatisticTableGUI
643 {
644 global $DIC; /* @var ILIAS\DI\Container $DIC */
645
646 $table = parent::getAnswerFrequencyTableGUI(
647 $parentGui,
648 $parentCmd,
649 $relevantAnswers,
650 $questionIndex
651 );
652
653 $table->setTitle(
654 sprintf(
655 $DIC->language()->txt('tst_corrections_answers_tbl_subindex'),
656 $DIC->language()->txt('longmenu') . ' ' . ($questionIndex + 1)
657 )
658 );
659
660 return $table;
661 }
662
664 {
665 $correct_answers = $this->object->getCorrectAnswers();
666
667 foreach ($this->object->getAnswers() as $lm_index => $lm) {
668 $lm_values = [
669 'answers_all' => [0 => $lm],
670 'answers_all_count' => count($lm),
671 'answers_correct' => $correct_answers[$lm_index][0]
672 ];
673
674 $lm_points = $correct_answers[$lm_index][1];
675
676 $section = new ilFormSectionHeaderGUI();
677 $section->setTitle($this->lng->txt('longmenu') . ' ' . ($lm_index + 1));
678 $form->addItem($section);
679
680 $lm_input = new ilAssLongmenuCorrectionsInputGUI(
681 $this->lng->txt('answers'),
682 'longmenu_' . $lm_index
683 );
684
685 $lm_input->setRequired(true);
686
687 $lm_input->setValues($lm_values);
688
689 $form->addItem($lm_input);
690
691 $points_inp = new ilNumberInputGUI($this->lng->txt("points"), 'points_' . $lm_index);
692 $points_inp->setRequired(true);
693 $points_inp->allowDecimals(true);
694 $points_inp->setSize(4);
695 $points_inp->setMinValue(0);
696 $points_inp->setMinvalueShouldBeGreater(false);
697 $points_inp->setValue($lm_points);
698 $form->addItem($points_inp);
699 }
700 }
701
703 {
704 $correct_answers = $this->object->getCorrectAnswers();
705
706 foreach ($this->object->getAnswers() as $lm_index => $lm) {
707 $points_input = (float) str_replace(',', '.', $form->getInput('points_' . $lm_index));
708 $correct_answers_input = (array) $form->getInput('longmenu_' . $lm_index . '_tags');
709
710 foreach ($correct_answers_input as $idx => $answer) {
711 if (in_array($answer, $lm)) {
712 continue;
713 }
714
715 unset($correct_answers_input[$idx]);
716 }
717
718 $correct_answers[$lm_index][0] = array_values($correct_answers_input);
719 $correct_answers[$lm_index][1] = $points_input;
720 }
721
722 $this->object->setCorrectAnswers($correct_answers);
723 }
724}
$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
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
renderEditForm(ilPropertyFormGUI $form)
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="")
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