ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.assSingleChoiceGUI.php
Go to the documentation of this file.
1<?php
2
34{
35 private bool $rebuild_thumbnails = false;
43 public function __construct(int $id = -1)
44 {
46 $this->object = new assSingleChoice();
47 if ($id >= 0) {
48 $this->object->loadFromDb($id);
49 }
50 }
51
55 public function hasInlineFeedback(): bool
56 {
57 return $this->object->feedbackOBJ->isSpecificAnswerFeedbackAvailable($this->object->getId());
58 }
59
63 protected function writePostData(bool $always = false): int
64 {
65 if ($always || !$this->editQuestion(true)) {
70 return 0;
71 }
72 return 1;
73 }
74
82 protected function getEditAnswersSingleLine(bool $checkonly = false): bool
83 {
84 if ($this->object->getSelfAssessmentEditingMode()) {
85 return $this->object->isSingleline();
86 }
87
88 if ($checkonly) {
89 return $this->request_data_collector->int('types') === 0;
90 }
91
92 if (empty($this->object->getLastChange())
93 && !$this->request_data_collector->isset('types')) {
94 // a new question is edited
95 return $this->object->getMultilineAnswerSetting() === 0;
96 }
97 // a saved question is edited
98 return $this->object->isSingleline();
99 }
100
101 public function editQuestion(
102 bool $checkonly = false,
103 ?bool $is_save_cmd = null
104 ): bool {
105 $save = $is_save_cmd ?? $this->isSaveCommand();
106
107 $form = new ilPropertyFormGUI();
108 $this->editForm = $form;
109
110 $form->setFormAction($this->ctrl->getFormAction($this));
111 $form->setTitle($this->outQuestionType());
112 $is_singleline = $this->getEditAnswersSingleLine($checkonly);
113 if ($is_singleline) {
114 $form->setMultipart(true);
115 } else {
116 $form->setMultipart(false);
117 }
118 $form->setTableWidth('100%');
119 $form->setId('asssinglechoice');
120
121 $this->addBasicQuestionFormProperties($form);
122 $this->populateQuestionSpecificFormPart($form, $is_singleline);
123 $this->populateAnswerSpecificFormPart($form, $is_singleline);
124
125 $this->populateTaxonomyFormSection($form);
126
127 $this->addQuestionFormCommandButtons($form);
128
129 $errors = false;
130
131 if ($save) {
132 foreach ($this->request_data_collector->getParsedBody() as $key => $value) {
133 $item = $form->getItemByPostVar($key);
134 if ($item === null) {
135 continue;
136 }
137 switch (get_class($item)) {
138 case 'ilDurationInputGUI':
139 $item->setHours($value['hh']);
140 $item->setMinutes($value['mm']);
141 $item->setSeconds($value['ss']);
142 break;
143 default:
144 $item->setValue($value);
145 }
146 }
147
148 $errors = !$form->checkInput();
149 if ($errors) {
150 $checkonly = false;
151 }
152 }
153
154 if (!$checkonly) {
155 $this->renderEditForm($form);
156 }
157 return $errors;
158 }
159
160 public function uploadchoice(): void
161 {
162 $this->setAdditionalContentEditingModeFromPost();
163 $this->writePostData(true);
164 $this->editQuestion();
165 }
166
167 public function removeimagechoice(): void
168 {
169 $this->setAdditionalContentEditingModeFromPost();
170 $this->writePostData(true);
171 $position = key($this->request_data_collector->raw('cmd')['removeimagechoice']);
172 $this->object->removeAnswerImage($position);
173 $this->editQuestion();
174 }
175
176 public function addchoice(): void
177 {
178 $this->writePostData(true);
179 $position = key($this->request_data_collector->raw('cmd')['addchoice']);
180 $this->object->addAnswer('', 0, $position + 1);
181 $this->editQuestion();
182 }
183
184 public function removechoice(): void
185 {
186 $this->writePostData(true);
187 $position = key($this->request_data_collector->raw('cmd')['removechoice']);
188 $this->object->deleteAnswer($position);
189 $this->editQuestion();
190 }
191
192 public function getSolutionOutput(
193 int $active_id,
194 ?int $pass = null,
195 bool $graphical_output = false,
196 bool $result_output = false,
197 bool $show_question_only = true,
198 bool $show_feedback = false,
199 bool $show_correct_solution = false,
200 bool $show_manual_scoring = false,
201 bool $show_question_text = true,
202 bool $show_inline_feedback = true
203 ): string {
204
205 if (($active_id > 0) && (!$show_correct_solution)) {
206 $user_solutions = $this->object->getSolutionValues($active_id, $pass);
207
208 } else {
209 $found_index = -1;
210 $max_points = 0;
211 foreach ($this->object->answers as $index => $answer) {
212 if ($answer->getPoints() > $max_points) {
213 $max_points = $answer->getPoints();
214 $found_index = $index;
215 }
216 }
217 $user_solutions = [['value1' => $found_index]];
218 }
219
220 return $this->renderSolutionOutput(
221 $user_solutions,
222 $active_id,
223 $pass,
224 $graphical_output,
225 $result_output,
226 $show_question_only,
227 $show_feedback,
228 $show_correct_solution,
229 $show_manual_scoring,
230 $show_question_text,
231 false,
232 $show_inline_feedback,
233 );
234 }
235
236 public function renderSolutionOutput(
237 mixed $user_solutions,
238 int $active_id,
239 ?int $pass,
240 bool $graphical_output = false,
241 bool $result_output = false,
242 bool $show_question_only = true,
243 bool $show_feedback = false,
244 bool $show_correct_solution = false,
245 bool $show_manual_scoring = false,
246 bool $show_question_text = true,
247 bool $show_autosave_title = false,
248 bool $show_inline_feedback = false,
249 ): ?string {
250 $user_solution = '';
251 foreach ($user_solutions as $idx => $solution_value) {
252 $user_solution = $solution_value['value1'];
253 }
254
255 $template = new ilTemplate('tpl.il_as_qpl_mc_sr_output_solution.html', true, true, 'components/ILIAS/TestQuestionPool');
256 $solutiontemplate = new ilTemplate('tpl.il_as_tst_solution_output.html', true, true, 'components/ILIAS/TestQuestionPool');
257
258 $keys = $this->getChoiceKeys();
259 foreach ($keys as $answer_id) {
260 $answer = $this->object->answers[$answer_id];
261 if ($active_id > 0 && !$show_correct_solution && $graphical_output) {
262 $correctness = $this->generateCorrectness(
263 (string) $user_solution,
264 (string) $answer_id,
265 $answer->getPoints(),
266 $this->object->getMaximumPoints()
267 );
268 $template->setCurrentBlock('icon_ok');
269 $template->setVariable('ICON_OK', $this->generateCorrectnessIconsForCorrectness($correctness));
270 $template->parseCurrentBlock();
271 }
272 if ($answer->hasImage()) {
273 $template->setCurrentBlock('answer_image');
274 if ($this->object->getThumbSize()) {
275 $template->setVariable('ANSWER_IMAGE_URL', $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $answer->getImage());
276 } else {
277 $template->setVariable('ANSWER_IMAGE_URL', $this->object->getImagePathWeb() . $answer->getImage());
278 }
279 $alt = $answer->getImage();
280 if (strlen($answer->getAnswertext())) {
281 $alt = $answer->getAnswertext();
282 }
283 $alt = preg_replace('/<[^>]*?>/', '', $alt);
284 $template->setVariable('ANSWER_IMAGE_ALT', ilLegacyFormElementsUtil::prepareFormOutput($alt));
285 $template->setVariable('ANSWER_IMAGE_TITLE', ilLegacyFormElementsUtil::prepareFormOutput($alt));
286 $template->parseCurrentBlock();
287 }
288
289 if (($show_feedback || !$this->isTestPresentationContext()) && $show_inline_feedback) {
290 $this->populateInlineFeedback($template, $answer_id, $user_solution);
291 }
292 $template->setCurrentBlock('answer_row');
293 $template->setVariable('ANSWER_TEXT', $this->renderLatex(
294 ilLegacyFormElementsUtil::prepareTextareaOutput($answer->getAnswertext(), true)
295 ));
296
297 if ($this->renderPurposeSupportsFormHtml() || $this->isRenderPurposePrintPdf()) {
298 if ((string) $user_solution === (string) $answer_id) {
299 $template->setVariable('SOLUTION_IMAGE', ilUtil::getHtmlPath(ilUtil::getImagePath('object/radiobutton_checked.png')));
300 $template->setVariable('SOLUTION_ALT', $this->lng->txt('checked'));
301 } else {
302 $template->setVariable('SOLUTION_IMAGE', ilUtil::getHtmlPath(ilUtil::getImagePath('object/radiobutton_unchecked.png')));
303 $template->setVariable('SOLUTION_ALT', $this->lng->txt('unchecked'));
304 }
305 } else {
306 $template->setVariable('QID', $this->object->getId());
307 $template->setVariable('SUFFIX', $show_correct_solution ? 'bestsolution' : 'usersolution');
308 $template->setVariable('SOLUTION_VALUE', $answer_id);
309 if ((string) $user_solution === (string) $answer_id) {
310 $template->setVariable('SOLUTION_CHECKED', 'checked');
311 }
312 }
313
314 if ($result_output) {
315 $points = $this->object->answers[$answer_id]->getPoints();
316 $resulttext = ($points == 1) ? "(%s {$this->lng->txt('point')})" : "(%s {$this->lng->txt('points')})";
317 $template->setVariable('RESULT_OUTPUT', sprintf($resulttext, $points));
318 }
319 $template->parseCurrentBlock();
320 }
321
322 $questiontext = $this->object->getQuestionForHTMLOutput();
323 if ($show_inline_feedback && $this->hasInlineFeedback()) {
324 $questiontext .= $this->buildFocusAnchorHtml();
325 }
326 if ($show_question_text === true) {
327 $template->setVariable('QUESTIONTEXT', $this->renderLatex(
329 ));
330 }
331 $questionoutput = $template->get();
332 $feedback = ($show_feedback && !$this->isTestPresentationContext()) ? $this->getGenericFeedbackOutput((int) $active_id, $pass) : '';
333 if ($feedback !== '') {
334 $cssClass = (
335 $this->hasCorrectSolution($active_id, $pass) ?
337 );
338
339 $solutiontemplate->setVariable('ILC_FB_CSS_CLASS', $cssClass);
340 $solutiontemplate->setVariable('FEEDBACK', ilLegacyFormElementsUtil::prepareTextareaOutput($feedback, true));
341 }
342 $solutiontemplate->setVariable('SOLUTION_OUTPUT', $questionoutput);
343
344 $solutionoutput = $solutiontemplate->get();
345
346 if (!$show_question_only) {
347 // get page object output
348 $solutionoutput = $this->getILIASPage($solutionoutput);
349 }
350 return $solutionoutput;
351 }
352
353 private function generateCorrectness(
354 string $user_solution,
355 string $answer_id,
356 float $answer_points,
357 float $maximum_points
358 ): int {
359 if ($user_solution === $answer_id
360 && $answer_points === $maximum_points
361 || $user_solution !== $answer_id
362 && $answer_points === 0.0
363 ) {
364 return self::CORRECTNESS_OK;
365 }
366
367 if ($user_solution === $answer_id
368 && $answer_points > 0.0) {
369 return self::CORRECTNESS_MOSTLY_OK;
370 }
371
372 return self::CORRECTNESS_NOT_OK;
373 }
374
375 public function getPreview(
376 bool $show_question_only = false,
377 bool $show_inline_feedback = false
378 ): string {
379 $keys = $this->getChoiceKeys();
380
381 $template = new ilTemplate('tpl.il_as_qpl_mc_sr_output.html', true, true, 'components/ILIAS/TestQuestionPool');
382 foreach ($keys as $answer_id) {
383 $answer = $this->object->answers[$answer_id];
384 if ($answer->hasImage()) {
385 if ($this->object->getThumbSize()) {
386 $template->setCurrentBlock('preview');
387 $template->setVariable('URL_PREVIEW', $this->object->getImagePathWeb() . $answer->getImage());
388 $template->setVariable('TEXT_PREVIEW', $this->lng->txt('preview'));
389 $template->setVariable('IMG_PREVIEW', ilUtil::getImagePath('media/enlarge.svg'));
390 $template->setVariable('ANSWER_IMAGE_URL', $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $answer->getImage());
391 list($width, $height, $type, $attr) = getimagesize($this->object->getImagePath() . $answer->getImage());
392 $alt = $answer->getImage();
393 if (strlen($answer->getAnswertext())) {
394 $alt = $answer->getAnswertext();
395 }
396 $alt = preg_replace('/<[^>]*?>/', '', $alt);
397 $template->setVariable('ANSWER_IMAGE_ALT', ilLegacyFormElementsUtil::prepareFormOutput($alt));
398 $template->setVariable('ANSWER_IMAGE_TITLE', ilLegacyFormElementsUtil::prepareFormOutput($alt));
399 $template->parseCurrentBlock();
400 } else {
401 $template->setCurrentBlock('answer_image');
402 $template->setVariable('ANSWER_IMAGE_URL', $this->object->getImagePathWeb() . $answer->getImage());
403 list($width, $height, $type, $attr) = getimagesize($this->object->getImagePath() . $answer->getImage());
404 $alt = $answer->getImage();
405 if (strlen($answer->getAnswertext())) {
406 $alt = $answer->getAnswertext();
407 }
408 $alt = preg_replace('/<[^>]*?>/', '', $alt);
409 $template->setVariable('ATTR', $attr);
410 $template->setVariable('ANSWER_IMAGE_ALT', ilLegacyFormElementsUtil::prepareFormOutput($alt));
411 $template->setVariable('ANSWER_IMAGE_TITLE', ilLegacyFormElementsUtil::prepareFormOutput($alt));
412 $template->parseCurrentBlock();
413 }
414 }
415 if ($show_inline_feedback && is_object($this->getPreviewSession())) {
416 $this->populateInlineFeedback($template, $answer_id, $this->getPreviewSession()->getParticipantsSolution());
417 }
418 $template->setCurrentBlock('answer_row');
419 $template->setVariable('QID', $this->object->getId() . 'ID');
420 $template->setVariable('ANSWER_ID', $answer_id);
421 $template->setVariable('ANSWER_TEXT', $this->renderLatex(
422 ilLegacyFormElementsUtil::prepareTextareaOutput($answer->getAnswertext(), true)
423 ));
424
425 if (is_object($this->getPreviewSession())) {
426 $user_solution = $this->getPreviewSession()->getParticipantsSolution();
427 if ((string) $user_solution === (string) $answer_id) {
428 $template->setVariable('CHECKED_ANSWER', ' checked="checked"');
429 }
430 }
431
432 $template->parseCurrentBlock();
433 }
434 $questiontext = $this->object->getQuestionForHTMLOutput();
435 if ($show_inline_feedback && $this->hasInlineFeedback()) {
436 $questiontext .= $this->buildFocusAnchorHtml();
437 }
438 $template->setVariable('QUESTIONTEXT', $this->renderLatex(
440 ));
441 $questionoutput = $template->get();
442 if (!$show_question_only) {
443 // get page object output
444 $questionoutput = $this->getILIASPage($questionoutput);
445 }
446 return $questionoutput;
447 }
448
449 public function getTestOutput(
450 int $active_id,
451 int $pass,
452 bool $is_question_postponed = false,
453 array|bool $user_post_solutions = false,
454 bool $show_specific_inline_feedback = false
455 ): string {
456 $keys = $this->getChoiceKeys();
457
458 $user_solution = '';
459 if ($active_id !== 0) {
460 $solutions = $this->object->getTestOutputSolutions($active_id, $pass);
461 foreach ($solutions as $solution_value) {
462 $user_solution = $solution_value['value1'];
463 }
464 }
465
466 $template = new ilTemplate('tpl.il_as_qpl_mc_sr_output.html', true, true, 'components/ILIAS/TestQuestionPool');
467 foreach ($keys as $answer_id) {
468 $answer = $this->object->answers[$answer_id];
469 if ($answer->hasImage()) {
470 if ($this->object->getThumbSize()) {
471 $template->setCurrentBlock('preview');
472 $template->setVariable('URL_PREVIEW', $this->object->getImagePathWeb() . $answer->getImage());
473 $template->setVariable('TEXT_PREVIEW', $this->lng->txt('preview'));
474 $template->setVariable('IMG_PREVIEW', ilUtil::getImagePath('media/enlarge.svg'));
475 $template->setVariable('ANSWER_IMAGE_URL', $this->object->getImagePathWeb() . $this->object->getThumbPrefix() . $answer->getImage());
476 list($width, $height, $type, $attr) = getimagesize($this->object->getImagePath() . $answer->getImage());
477 $alt = $answer->getImage();
478 if (strlen($answer->getAnswertext())) {
479 $alt = $answer->getAnswertext();
480 }
481 $alt = preg_replace('/<[^>]*?>/', '', $alt);
482 $template->setVariable('ANSWER_IMAGE_ALT', ilLegacyFormElementsUtil::prepareFormOutput($alt));
483 $template->setVariable('ANSWER_IMAGE_TITLE', ilLegacyFormElementsUtil::prepareFormOutput($alt));
484 $template->parseCurrentBlock();
485 } else {
486 $template->setCurrentBlock('answer_image');
487 $template->setVariable('ANSWER_IMAGE_URL', $this->object->getImagePathWeb() . $answer->getImage());
488 list($width, $height, $type, $attr) = getimagesize($this->object->getImagePath() . $answer->getImage());
489 $alt = $answer->getImage();
490 if (strlen($answer->getAnswertext())) {
491 $alt = $answer->getAnswertext();
492 }
493 $alt = preg_replace('/<[^>]*?>/', '', $alt);
494 $template->setVariable('ATTR', $attr);
495 $template->setVariable('ANSWER_IMAGE_ALT', ilLegacyFormElementsUtil::prepareFormOutput($alt));
496 $template->setVariable('ANSWER_IMAGE_TITLE', ilLegacyFormElementsUtil::prepareFormOutput($alt));
497 $template->parseCurrentBlock();
498 }
499 }
500
501 if ($show_specific_inline_feedback) {
502 $this->populateInlineFeedback($template, $answer_id, $user_solution);
503 }
504 $template->setCurrentBlock('answer_row');
505 $template->setVariable('ANSWER_ID', $answer_id);
506 $template->setVariable('ANSWER_TEXT', $this->renderLatex(
507 ilLegacyFormElementsUtil::prepareTextareaOutput($answer->getAnswertext(), true)
508 ));
509 if ($user_solution === (string) $answer_id) {
510 $template->setVariable('CHECKED_ANSWER', ' checked="checked"');
511 }
512 $template->parseCurrentBlock();
513 }
514 $template->setVariable('QUESTIONTEXT', $this->renderLatex(
515 $this->object->getQuestionForHTMLOutput()
516 ));
517 $questionoutput = $template->get();
518 $pageoutput = $this->outQuestionPage('', $is_question_postponed, $active_id, $questionoutput, $show_specific_inline_feedback);
519 return $pageoutput;
520 }
521
522 /*
523 * Create the key index numbers for the array of choices
524 *
525 * @return array
526 */
527 public function getChoiceKeys()
528 {
529 $choice_keys = array_keys($this->object->answers);
530
531 if ($this->object->getShuffle()) {
532 $choice_keys = $this->object->getShuffler()->transform($choice_keys);
533 }
534
535 return $choice_keys;
536 }
537
538 public function getSpecificFeedbackOutput(array $user_solution): string
539 {
540 // No return value, this question type supports inline specific feedback.
541 $output = '';
543 }
544
546 {
547 $is_multi_line = $this->request_data_collector->string('types');
548 if ($is_multi_line === '') {
549 $is_multi_line = '0';
550 }
551 $this->object->setMultilineAnswerSetting($is_multi_line);
552 $this->object->setShuffle($this->request_data_collector->bool('shuffle') ?? false);
553
554 $choice = $this->request_data_collector->raw('choice');
555 if (isset($choice['imagename']) && is_array($choice['imagename']) && $is_multi_line === '1') {
556 $this->object->setIsSingleline(true);
557 $this->tpl->setOnScreenMessage('info', $this->lng->txt('info_answer_type_change'), true);
558 } else {
559 $this->object->setIsSingleline($is_multi_line === '0');
560 }
561
562 $object_thumb_size = $this->object->getThumbSize();
563 $thumb_size = $this->request_data_collector->int('thumb_size') ?? $object_thumb_size;
564 if ($thumb_size !== $object_thumb_size) {
565 $this->object->setThumbSize($thumb_size);
566 $this->rebuild_thumbnails = true;
567 }
568 }
569
570 public function populateQuestionSpecificFormPart(\ilPropertyFormGUI $form, bool $is_singleline = false): ilPropertyFormGUI
571 {
572 // shuffle
573 $shuffle = new ilCheckboxInputGUI($this->lng->txt('shuffle_answers'), 'shuffle');
574 $shuffle->setValue(1);
575 $shuffle->setChecked($this->object->getShuffle());
576 $shuffle->setRequired(false);
577 $form->addItem($shuffle);
578
579 if (!$this->object->getSelfAssessmentEditingMode()) {
580 // Answer types
581 $types = new ilSelectInputGUI($this->lng->txt('answer_types'), 'types');
582 $types->setRequired(false);
583 $types->setOptions(
584 [
585 0 => $this->lng->txt('answers_singleline'),
586 1 => $this->lng->txt('answers_multiline'),
587 ]
588 );
589 $types->setValue($is_singleline ? 0 : 1);
590 $form->addItem($types);
591 }
592
593 if ($is_singleline) {
594 // thumb size
595 $thumb_size = new ilNumberInputGUI($this->lng->txt('thumb_size'), 'thumb_size');
596 $thumb_size->setSuffix($this->lng->txt('thumb_size_unit_pixel'));
597 $thumb_size->setMinValue($this->object->getMinimumThumbSize());
598 $thumb_size->setMaxValue($this->object->getMaximumThumbSize());
599 $thumb_size->setDecimals(0);
600 $thumb_size->setSize(6);
601 $thumb_size->setInfo($this->lng->txt('thumb_size_info'));
602 $thumb_size->setValue($this->object->getThumbSize());
603 $thumb_size->setRequired(true);
604 } else {
605 $thumb_size = new ilHiddenInputGUI('thumb_size');
606 $thumb_size->setValue($this->object->getThumbSize());
607 }
608 $form->addItem($thumb_size);
609
610 return $form;
611 }
612
623 {
624 return [];
625 }
626
628 {
629 // Delete all existing answers and create new answers from the form data
630 $this->object->flushAnswers();
631 $choice = $this->cleanupAnswerText(
632 $this->request_data_collector->raw('choice') ?? [],
633 $this->object->isSingleline() === false
634 );
635
636 if ($choice === []) {
637 return;
638 }
639
640 if (!$this->object->isSingleline()) {
641 foreach ($choice['answer'] as $index => $answer) {
642 $answertext = $answer;
643 $this->object->addAnswer(
644 $answertext,
645 $this->refinery->kindlyTo()->float()->transform($choice['points'][$index]),
646 $index,
647 null,
648 $choice['answer_id'][$index]
649 );
650 }
651
652 return;
653 }
654
655 foreach ($choice['answer'] as $index => $answertext) {
656 $answertext = htmlentities($answertext);
657 $picturefile = $choice['imagename'][$index] ?? null;
658 $file_org_name = $_FILES['choice']['name']['image'][$index] ?? '';
659 $file_temp_name = $_FILES['choice']['tmp_name']['image'][$index] ?? '';
660
661 if ($file_temp_name !== '') {
662 // check suffix
663 $file_name_parts = explode('.', $file_org_name);
664 $suffix = strtolower(array_pop($file_name_parts));
665 if (in_array($suffix, ['jpg', 'jpeg', 'png', 'gif'])) {
666 // upload image
667 $filename = $this->object->buildHashedImageFilename($file_org_name);
668 if ($this->object->setImageFile($filename, $file_temp_name) == 0) {
669 $picturefile = $filename;
670 }
671 }
672 }
673
674 $points = (float) str_replace(',', '.', $choice['points'][$index]);
675 $this->object->addAnswer(
676 $answertext,
677 $points,
678 $index,
679 $picturefile,
680 $choice['answer_id'][$index]
681 );
682 }
683
684 if ($this->rebuild_thumbnails) {
685 $this->object->setAnswers(
686 $this->object->rebuildThumbnails(
687 $this->object->isSingleline(),
688 $this->object->getThumbSize(),
689 $this->object->getImagePath(),
690 $this->object->getAnswers()
691 )
692 );
693 }
694 }
695
696 public function populateAnswerSpecificFormPart(\ilPropertyFormGUI $form, bool $is_singleline = false): ilPropertyFormGUI
697 {
698 $choices = new ilSingleChoiceWizardInputGUI($this->lng->txt('answers'), 'choice');
699 $choices->setRequired(true);
700 $choices->setQuestionObject($this->object);
701 $choices->setSingleline($is_singleline);
702 $choices->setAllowMove(false);
703 if ($this->object->getSelfAssessmentEditingMode()) {
704 $choices->setSize(40);
705 }
706 if ($this->object->getAnswerCount() == 0) {
707 $this->object->addAnswer('', 0, 0);
708 }
709 $choices->setValues(array_map(
710 function (ASS_AnswerBinaryStateImage $value) {
711 $value->setAnswerText(html_entity_decode($value->getAnswerText()));
712 return $value;
713 },
714 $this->object->getAnswers()
715 ));
716 $choices->setInfo($choices->getInfo() . ' ' . $this->lng->txt('latex_edit_info'));
717 $form->addItem($choices);
718 return $form;
719 }
720
731 {
732 return [];
733 }
734
735 private function aggregateAnswers($relevant_answers_chosen, $answers_defined_on_question): array
736 {
737 $aggregate = [];
738 foreach ($answers_defined_on_question as $answer) {
739 $aggregated_info_for_answer = [];
740 $aggregated_info_for_answer['answertext'] = $answer->getAnswerText();
741 $aggregated_info_for_answer['count_checked'] = 0;
742
743 foreach ($relevant_answers_chosen as $relevant_answer) {
744 if ($relevant_answer['value1'] == $answer->getOrder()) {
745 $aggregated_info_for_answer['count_checked']++;
746 }
747 }
748 $aggregated_info_for_answer['count_unchecked'] =
749 ceil(count($relevant_answers_chosen) / count($answers_defined_on_question))
750 - $aggregated_info_for_answer['count_checked'];
751
752 $aggregate[] = $aggregated_info_for_answer;
753 }
754 return $aggregate;
755 }
756
762 public function renderAggregateView($aggregate): ilTemplate
763 {
764 $tpl = new ilTemplate('tpl.il_as_aggregated_answers_table.html', true, true, 'components/ILIAS/TestQuestionPool');
765
766 $tpl->setCurrentBlock('headercell');
767 $tpl->setVariable('HEADER', $this->lng->txt('tst_answer_aggr_answer_header'));
768 $tpl->parseCurrentBlock();
769
770 $tpl->setCurrentBlock('headercell');
771 $tpl->setVariable('HEADER', $this->lng->txt('tst_answer_aggr_frequency_header'));
772 $tpl->parseCurrentBlock();
773
774 foreach ($aggregate as $line_data) {
775 $tpl->setCurrentBlock('aggregaterow');
776 $tpl->setVariable('OPTION', $line_data['answertext']);
777 $tpl->setVariable('COUNT', $line_data['count_checked']);
778 $tpl->parseCurrentBlock();
779 }
780 return $tpl;
781 }
782
783 private function populateInlineFeedback($template, $answer_id, $user_solution): void
784 {
785 $feedbackOutputRequired = false;
786
787 switch ($this->object->getSpecificFeedbackSetting()) {
788 case 1:
789 $feedbackOutputRequired = true;
790 break;
791
792 case 2:
793 if ((string) $user_solution === (string) $answer_id) {
794 $feedbackOutputRequired = true;
795 }
796 break;
797
798 case 3:
799 if ($this->object->getAnswer($answer_id)->getPoints() > 0) {
800 $feedbackOutputRequired = true;
801 }
802 break;
803 }
804
805 if ($feedbackOutputRequired) {
806 $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation($this->object->getId(), 0, $answer_id);
807 if (strlen($fb)) {
808 $template->setCurrentBlock('feedback');
809 $template->setVariable('FEEDBACK', $this->renderLatex(
811 ));
812 $template->parseCurrentBlock();
813 }
814 }
815 }
816
817 public function getAnswersFrequency($relevantAnswers, $questionIndex): array
818 {
819 $agg = $this->aggregateAnswers($relevantAnswers, $this->object->getAnswers());
820
821 $answers = [];
822
823 foreach ($agg as $ans) {
824 $answers[] = [
825 'answer' => $ans['answertext'],
826 'frequency' => $ans['count_checked']
827 ];
828 }
829
830 return $answers;
831 }
832
834 {
835 $choices = new ilAssSingleChoiceCorrectionsInputGUI($this->lng->txt('answers'), 'choice');
836 $choices->setRequired(true);
837 $choices->setQuestionObject($this->object);
838 $choices->setValues($this->object->getAnswers());
839 $form->addItem($choices);
840 }
841
846 {
847 $input = $form->getItemByPostVar('choice');
848 $values = $input->getValues();
849
850 foreach ($this->object->getAnswers() as $index => $answer) {
851 /* @var ASS_AnswerMultipleResponseImage $answer */
852 $points = (float) str_replace(',', '.', $values[$index]->getPoints());
853 $answer->setPoints($points);
854 }
855 }
856}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
$filename
Definition: buildRTE.php:78
Class for answers with a binary state indicator.
populateTaxonomyFormSection(ilPropertyFormGUI $form)
addBasicQuestionFormProperties(ilPropertyFormGUI $form)
renderEditForm(ilPropertyFormGUI $form)
addQuestionFormCommandButtons(ilPropertyFormGUI $form)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
writeAnswerSpecificPostData(ilPropertyFormGUI $form)
Extracts the answer specific values from the request and applies them to the data object.
getTestOutput(int $active_id, int $pass, bool $is_question_postponed=false, array|bool $user_post_solutions=false, bool $show_specific_inline_feedback=false)
populateAnswerSpecificFormPart(\ilPropertyFormGUI $form, bool $is_singleline=false)
populateCorrectionsFormProperties(ilPropertyFormGUI $form)
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)
populateInlineFeedback($template, $answer_id, $user_solution)
writePostData(bool $always=false)
{Evaluates a posted edit form and writes the form data in the question object.integer A positive valu...
getEditAnswersSingleLine(bool $checkonly=false)
Get the single/multiline editing of answers.
getAfterParticipationSuppressionAnswerPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
getPreview(bool $show_question_only=false, bool $show_inline_feedback=false)
populateQuestionSpecificFormPart(\ilPropertyFormGUI $form, bool $is_singleline=false)
writeQuestionSpecificPostData(ilPropertyFormGUI $form)
Extracts the question specific values from the request and applies them to the data object.
editQuestion(bool $checkonly=false, ?bool $is_save_cmd=null)
generateCorrectness(string $user_solution, string $answer_id, float $answer_points, float $maximum_points)
__construct(int $id=-1)
assSingleChoiceGUI constructor
getAfterParticipationSuppressionQuestionPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
aggregateAnswers($relevant_answers_chosen, $answers_defined_on_question)
getSpecificFeedbackOutput(array $user_solution)
Returns the answer specific feedback for the question.
saveCorrectionsFormProperties(ilPropertyFormGUI $form)
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,)
getAnswersFrequency($relevantAnswers, $questionIndex)
Class for single choice questions.
This class represents a checkbox property 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,...
static prepareFormOutput($a_str, bool $a_strip=false)
This class represents a number property in a property form.
This class represents a property form user interface.
getItemByPostVar(string $a_post_var)
This class represents a selection list property in a property form.
This class represents a single choice wizard property in a property form.
special template class to simplify handling of ITX/PEAR
static getHtmlPath(string $relative_path)
get url of path
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
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'))