ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.assImagemapQuestionGUI.php
Go to the documentation of this file.
1<?php
2
34{
35 private string $linecolor;
37
45 public function __construct(int $id = -1)
46 {
48 $this->object = new assImagemapQuestion();
49 if ($id >= 0) {
50 $this->object->loadFromDb($id);
51 }
52 $this->linecolor = '#' . (new ilSetting('assessment'))->get('imap_line_color') ?? 'FF0000';
53 }
54
55 public function deleteImage(): void
56 {
57 $this->object->deleteImage();
58 $this->object->saveToDb();
59 $this->tpl->setOnScreenMessage('success', $this->lng->txt('saved_successfully'), true);
60 $this->ctrl->redirect($this, 'editQuestion');
61 }
62
66 protected function writePostData(bool $always = false): int
67 {
68 $form = $this->buildEditForm();
69 $form->setValuesByPost();
70
71 if (!$always && !$form->checkInput()) {
72 $this->edit_form = $form;
73 $this->editQuestion();
74 return 1;
75 }
76
79 $this->writeAnswerSpecificPostData($form);
81
82 return 0;
83 }
84
86 {
87 if ($this->ctrl->getCmd() !== 'deleteImage') {
88 $this->object->flushAnswers();
89
90 $image = $this->request_data_collector->raw('image', 4);
91 if (isset($image['coords']['name'])) {
92 foreach ($image['coords']['name'] as $idx => $name) {
93 if ($this->object->getIsMultipleChoice() && isset($image['coords']['points_unchecked'])) {
94 $points_unchecked = $this->refinery->kindlyTo()->float()->transform($image['coords']['points_unchecked'][$idx]);
95 } else {
96 $points_unchecked = 0.0;
97 }
98
99 $this->object->addAnswer(
100 $name,
101 $image['coords']['points'][$idx],
102 $idx,
103 $image['coords']['coords'][$idx],
104 $image['coords']['shape'][$idx],
105 $points_unchecked
106 );
107 }
108 }
109
110 if ($_FILES['imagemapfile']['tmp_name'] !== '') {
111 if ($this->object->getId() < 1) {
112 $this->object->createNewQuestion();
113 }
114
115 $this->object->uploadImagemap($form->getItemByPostVar('imagemapfile')?->getShapes());
116 }
117 }
118 }
119
121 {
122 if ($this->ctrl->getCmd() !== 'deleteImage' && $_FILES['image']['tmp_name'] === '') {
123 $this->object->setImageFilename($this->request_data_collector->string('image_name'));
124 }
125 if ($_FILES['image']['tmp_name'] !== '') {
126 if ($this->object->getId() < 1) {
127 $this->object->createNewQuestion();
128 }
129 $this->object->setImageFilename($_FILES['image']['name'], $_FILES['image']['tmp_name']);
130 }
131
132 $is_multiple_choice = $this->request_data_collector->int('is_multiple_choice') ?? assImagemapQuestion::MODE_SINGLE_CHOICE;
133 $this->object->setIsMultipleChoice($is_multiple_choice === assImagemapQuestion::MODE_MULTIPLE_CHOICE);
134 }
135
139 protected function buildEditForm(): ilPropertyFormGUI
140 {
141 $form = $this->buildBasicEditFormObject();
142
143 $this->addBasicQuestionFormProperties($form);
145 $this->populateTaxonomyFormSection($form);
146 $this->addQuestionFormCommandButtons($form);
147
148 return $form;
149 }
150
151 public function editQuestion(
152 bool $checkonly = false,
153 ?bool $is_save_cmd = null
154 ): bool {
155 $form = $this->edit_form;
156 if ($form === null) {
157 $form = $this->buildEditForm();
158 }
159
160 $this->renderEditForm($form);
161 return false;
162 }
163
165 {
166 return $form; // Nothing to do here since selectable areas are handled in question-specific-form part
167 // due to their immediate dependency to the image. I decide to not break up the interfaces
168 // more just to support this very rare case. tl;dr: See the issue, ignore it.
169 }
170
172 {
173 $radioGroup = new ilRadioGroupInputGUI($this->lng->txt('tst_imap_qst_mode'), 'is_multiple_choice');
174 $radioGroup->setValue((string) ((int) ($this->object->getIsMultipleChoice())));
175 $modeSingleChoice = new ilRadioOption(
176 $this->lng->txt('tst_imap_qst_mode_sc'),
178 );
179 $modeMultipleChoice = new ilRadioOption(
180 $this->lng->txt('tst_imap_qst_mode_mc'),
182 );
183 $radioGroup->addOption($modeSingleChoice);
184 $radioGroup->addOption($modeMultipleChoice);
185 $form->addItem($radioGroup);
186
187 $image = new ilImagemapFileInputGUI($this->lng->txt('image'), 'image');
188 $image->setPointsUncheckedFieldEnabled($this->object->getIsMultipleChoice());
189 $image->setRequired(true);
190
191 if ($this->object->getImageFilename() !== '') {
192 $image->setImage($this->object->getImagePathWeb() . $this->object->getImageFilename());
193 $image->setValue($this->object->getImageFilename());
194 $image->setAreas($this->object->getAnswers());
195 $assessmentSetting = new ilSetting("assessment");
196 $linecolor = $assessmentSetting->get("imap_line_color") !== null
197 ? '"#' . $assessmentSetting->get('imap_line_color') . '"' : '"#FF0000"';
198 $image->setLineColor($linecolor);
199 $image->setImagePath($this->object->getImagePath());
200 $image->setImagePathWeb($this->object->getImagePathWeb());
201 }
202 $form->addItem($image);
203
204 $imagemapfile = new ilHtmlImageMapFileInputGUI($this->lng->txt('add_imagemap'), 'imagemapfile');
205 $imagemapfile->setRequired(false);
206 $form->addItem($imagemapfile);
207 return $form;
208 }
209
210 public function addRect(): void
211 {
212 $this->areaEditor('rect');
213 }
214
215 public function addCircle(): void
216 {
217 $this->areaEditor('circle');
218 }
219
220 public function addPoly(): void
221 {
222 $this->areaEditor('poly');
223 }
224
225 public function saveShape(): void
226 {
227 $coords = '';
228
229 $shape = $this->request_data_collector->string('shape');
230 $shape_title = $this->request_data_collector->string('shapetitle');
231 $image = $this->request_data_collector->raw('image', 2);
232
233 switch ($shape) {
235 $coords = implode(',', $image['mapcoords']);
236 $this->tpl->setOnScreenMessage('success', $this->lng->txt('msg_rect_added'), true);
237 break;
239 if (preg_match("/(\d+)\s*,\s*(\d+)\s+(\d+)\s*,\s*(\d+)/", $image['mapcoords'][0] . ' ' . $image['mapcoords'][1], $matches)) {
240 $coords = "$matches[1],$matches[2]," . (int) sqrt((($matches[3] - $matches[1]) * ($matches[3] - $matches[1])) + (($matches[4] - $matches[2]) * ($matches[4] - $matches[2])));
241 }
242 $this->tpl->setOnScreenMessage('success', $this->lng->txt('msg_circle_added'), true);
243 break;
245 $coords = implode(',', $image['mapcoords']);
246 $this->tpl->setOnScreenMessage('success', $this->lng->txt('msg_poly_added'), true);
247 break;
248 }
249
250 $this->object->addAnswer($shape_title, 0, count($this->object->getAnswers()), $coords, $shape);
251 $this->object->saveToDb();
252 $this->ctrl->redirect($this, 'editQuestion');
253 }
254
255 public function areaEditor(string $shape = ''): void
256 {
257 $this->getQuestionTemplate();
258 $editor_tpl = new ilTemplate('tpl.il_as_qpl_imagemap_question.html', true, true, 'components/ILIAS/TestQuestionPool');
259
260 $shape = $shape !== '' ? $shape : $this->request_data_collector->string('shape');
261 $shape_title = $this->request_data_collector->string('shapetitle');
262 $image = $this->request_data_collector->raw('image', 2);
263 $coords = $image['mapcoords'] ?? [];
264
265 $cmd = $this->request_data_collector->raw('cmd');
266 if ($cmd !== null && array_key_exists('areaEditor', $cmd) && is_array($cmd['areaEditor']['image'])) {
267 $coords[] = $cmd['areaEditor']['image'][0] . ',' . $cmd['areaEditor']['image'][1];
268 }
269 foreach ($coords as $value) {
270 $editor_tpl->setCurrentBlock('hidden');
271 $editor_tpl->setVariable('HIDDEN_NAME', 'image[mapcoords][]');
272 $editor_tpl->setVariable('HIDDEN_VALUE', $value);
273 $editor_tpl->parseCurrentBlock();
274 }
275
276 $editor_tpl->setCurrentBlock('hidden');
277 $editor_tpl->setVariable('HIDDEN_NAME', 'shape');
278 $editor_tpl->setVariable(
279 'HIDDEN_VALUE',
280 $shape
281 );
282 $editor_tpl->parseCurrentBlock();
283
284 $preview = new ilImagemapPreview($this->object->getImagePath() . $this->object->getImageFilename());
285 foreach ($this->object->answers as $index => $answer) {
286 $preview->addArea($index, $answer->getArea(), $answer->getCoords(), $answer->getAnswertext(), '', '', true, $this->linecolor);
287 }
288 $hidearea = false;
289 $disabled_save = ' disabled=\"disabled\"';
290 $c = '';
291 $coords_count = count($coords);
292 switch ($shape) {
294 switch ($coords_count) {
295 case 0:
296 $this->tpl->setOnScreenMessage('info', $this->lng->txt('rectangle_click_tl_corner'));
297 break;
298 case 1:
299 $this->tpl->setOnScreenMessage('info', $this->lng->txt('rectangle_click_br_corner'));
300 $preview->addPoint($preview->getAreaCount(), implode(',', $coords), true, 'blue');
301 break;
302 case 2:
303 $c = implode(',', $coords);
304 $hidearea = true;
305 $disabled_save = '';
306 break;
307 }
308 break;
310 switch ($coords_count) {
311 case 0:
312 $this->tpl->setOnScreenMessage('info', $this->lng->txt('circle_click_center'));
313 break;
314 case 1:
315 $this->tpl->setOnScreenMessage('info', $this->lng->txt('circle_click_circle'));
316 $preview->addPoint($preview->getAreaCount(), implode(',', $coords), true, 'blue');
317 break;
318 case 2:
319 if (preg_match("/(\d+)\s*,\s*(\d+)\s+(\d+)\s*,\s*(\d+)/", $coords[0] . ' ' . $coords[1], $matches)) {
320 $c = "$matches[1],$matches[2]," . (int) sqrt((($matches[3] - $matches[1]) * ($matches[3] - $matches[1])) + (($matches[4] - $matches[2]) * ($matches[4] - $matches[2])));
321 }
322 $hidearea = true;
323 $disabled_save = '';
324 break;
325 }
326 break;
328 switch ($coords_count) {
329 case 0:
330 $this->tpl->setOnScreenMessage('info', $this->lng->txt('polygon_click_starting_point'));
331 break;
332 case 1:
333 $this->tpl->setOnScreenMessage('info', $this->lng->txt('polygon_click_next_point'));
334 $preview->addPoint($preview->getAreaCount(), implode(',', $coords), true, 'blue');
335 break;
336 default:
337 $this->tpl->setOnScreenMessage('info', $this->lng->txt('polygon_click_next_or_save'));
338 $disabled_save = '';
339 $c = implode(',', $coords);
340 break;
341 }
342 break;
343 }
344
345 if ($c !== '') {
346 $preview->addArea($preview->getAreaCount(), $shape, $c, $shape_title, '', '', true, 'blue');
347 }
348 $preview->createPreview();
349 $image_path = $this->object->getImagePathWeb() . $preview->getPreviewFilename($this->object->getImagePath(), $this->object->getImageFilename()) . '?img=' . time();
350 if (!$hidearea) {
351 $editor_tpl->setCurrentBlock('maparea');
352 $editor_tpl->setVariable('IMAGEMAP_NAME', 'image');
353 } else {
354 $editor_tpl->setCurrentBlock('imagearea');
355 $editor_tpl->setVariable('ALT_IMAGE', $this->lng->txt('imagemap'));
356 }
357 try {
358 $editor_tpl->setVariable('IMAGE_SOURCE', ilWACSignedPath::signFile($image_path));
359 } catch (ilWACException $e) {
360
361 }
362 $editor_tpl->parseCurrentBlock();
363
364 if ($shape_title !== '') {
365 $editor_tpl->setCurrentBlock('shapetitle');
366 $editor_tpl->setVariable('VALUE_SHAPETITLE', $shape_title);
367 $editor_tpl->parseCurrentBlock();
368 }
369
370 $editor_tpl->setVariable('TEXT_IMAGEMAP', $this->lng->txt('imagemap'));
371 $editor_tpl->setVariable('TEXT_SHAPETITLE', $this->lng->txt('ass_imap_hint'));
372 $editor_tpl->setVariable('CANCEL', $this->lng->txt('cancel'));
373 $editor_tpl->setVariable('SAVE', $this->lng->txt('save'));
374 $editor_tpl->setVariable('DISABLED_SAVE', $disabled_save);
375
376 if (in_array($shape, assImagemapQuestion::AVAILABLE_SHAPES, true)) {
377 $editor_tpl->setVariable('FORMACTION', $this->ctrl->getFormaction($this, 'add' . ucfirst($shape)));
378 }
379
380 $this->tpl->setVariable('QUESTION_DATA', $editor_tpl->get());
381 }
382
383 public function back(): void
384 {
385 $this->tpl->setOnScreenMessage('info', $this->lng->txt('msg_cancel'), true);
386 $this->ctrl->redirect($this, 'editQuestion');
387 }
388
390 string $form_action,
391 int $active_id,
392 int $pass
393 ): string {
394 $info = $this->object->getTestOutputSolutions($active_id, $pass);
395 return $form_action . (($info !== [] && $info[0]['value1'] !== '') ? '&selImage=' . $info[0]['value1'] : '');
396 }
397
398 public function getSolutionOutput(
399 int $active_id,
400 ?int $pass = null,
401 bool $graphical_output = false,
402 bool $result_output = false,
403 bool $show_question_only = true,
404 bool $show_feedback = false,
405 bool $show_correct_solution = false,
406 bool $show_manual_scoring = false,
407 bool $show_question_text = true,
408 bool $show_inline_feedback = true
409 ): string {
410 $user_solutions = [];
411 if (($active_id > 0) && (!$show_correct_solution)) {
412 $user_solutions = $this->object->getSolutionValues($active_id, $pass);
413 } else {
414 if (!$this->object->getIsMultipleChoice()) {
415 $found_index = -1;
416 $max_points = 0;
417 foreach ($this->object->answers as $index => $answer) {
418 if ($answer->getPoints() > $max_points) {
419 $max_points = $answer->getPoints();
420 $found_index = $index;
421 }
422 }
423 array_push($user_solutions, ["value1" => $found_index]);
424 } else {
425 // take the correct solution instead of the user solution
426 foreach ($this->object->answers as $index => $answer) {
427 $points_checked = $answer->getPoints();
428 $points_unchecked = $answer->getPointsUnchecked();
429 if ($points_checked > $points_unchecked) {
430 if ($points_checked > 0) {
431 array_push($user_solutions, ["value1" => $index]);
432 }
433 }
434 }
435 }
436 }
437
438 return $this->renderSolutionOutput(
439 $user_solutions,
440 $active_id,
441 $pass,
442 $graphical_output,
443 $result_output,
444 $show_question_only,
445 $show_feedback,
446 $show_correct_solution,
447 $show_manual_scoring,
448 $show_question_text,
449 false,
450 $show_inline_feedback,
451 );
452 }
453
454 public function renderSolutionOutput(
455 mixed $user_solutions,
456 int $active_id,
457 ?int $pass,
458 bool $graphical_output = false,
459 bool $result_output = false,
460 bool $show_question_only = true,
461 bool $show_feedback = false,
462 bool $show_correct_solution = false,
463 bool $show_manual_scoring = false,
464 bool $show_question_text = true,
465 bool $show_autosave_title = false,
466 bool $show_inline_feedback = false,
467 ): ?string {
468 $imagepath = $this->object->getImagePathWeb() . $this->object->getImageFilename();
469 $solution_id = -1;
470 if (is_array($user_solutions)) {
471 $preview = new ilImagemapPreview($this->object->getImagePath() . $this->object->getImageFilename());
472 foreach ($user_solutions as $idx => $solution_value) {
473 $value1 = $solution_value["value1"];
474 if (
475 $value1 === '' ||
476 !isset($this->object->answers[$value1])
477 ) {
478 continue;
479 }
480
482 $shape = $this->object->answers[$value1];
483 $preview->addArea(
484 $value1,
485 $shape->getArea(),
486 $shape->getCoords(),
487 $shape->getAnswertext(),
488 '',
489 '',
490 true,
491 $this->linecolor
492 );
493
494 $solution_id = $value1;
495 }
496 $preview->createPreview();
497 $imagepath = implode('', [
498 $this->object->getImagePathWeb(),
499 $preview->getPreviewFilename(
500 $this->object->getImagePath(),
501 $this->object->getImageFilename()
502 ),
503 ]);
504 }
505
506 // generate the question output
507 $template = new ilTemplate("tpl.il_as_qpl_imagemap_question_output_solution.html", true, true, "components/ILIAS/TestQuestionPool");
508 $solutiontemplate = new ilTemplate("tpl.il_as_tst_solution_output.html", true, true, "components/ILIAS/TestQuestionPool");
509 if ($show_question_text == true) {
510 $template->setVariable("QUESTIONTEXT", $this->renderLatex(
511 $this->object->getQuestionForHTMLOutput()
512 ));
513 }
514
515 try {
516 $template->setVariable("IMG_SRC", ilWACSignedPath::signFile($imagepath));
517 } catch (ilWACException $e) {
518
519 }
520 $template->setVariable("IMG_ALT", $this->lng->txt("imagemap"));
521 $template->setVariable("IMG_TITLE", $this->lng->txt("imagemap"));
522 if (($active_id > 0) && (!$show_correct_solution)) {
523 if ($graphical_output) {
524 $correctness_icon = $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_NOT_OK);
525 $reached_points = $this->object->getReachedPoints($active_id, $pass);
526 if ($reached_points == $this->object->getMaximumPoints()) {
527 $correctness_icon = $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_OK);
528 }
529
530 if ($reached_points > 0) {
531 $correctness_icon = $this->generateCorrectnessIconsForCorrectness(self::CORRECTNESS_MOSTLY_OK);
532 }
533 $template->setCurrentBlock("icon_ok");
534 $template->setVariable("ICON_OK", $correctness_icon);
535 $template->parseCurrentBlock();
536 }
537 }
538
539 if ($show_feedback) {
540 $fb = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
541 $this->object->getId(),
542 0,
543 $solution_id
544 );
545
546 if (strlen($fb)) {
547 $template->setCurrentBlock("feedback");
548 $template->setVariable("FEEDBACK", $fb);
549 $template->parseCurrentBlock();
550 }
551 }
552
553 $questionoutput = $template->get();
554 $feedback = ($show_feedback && !$this->isTestPresentationContext()) ? $this->getGenericFeedbackOutput((int) $active_id, $pass) : "";
555 if (strlen($feedback)) {
556 $cssClass = (
557 $this->hasCorrectSolution($active_id, $pass) ?
559 );
560
561 $solutiontemplate->setVariable("ILC_FB_CSS_CLASS", $cssClass);
562 $solutiontemplate->setVariable("FEEDBACK", ilLegacyFormElementsUtil::prepareTextareaOutput($feedback, true));
563 }
564 $solutiontemplate->setVariable("SOLUTION_OUTPUT", $questionoutput);
565
566 $solutionoutput = $solutiontemplate->get();
567 if (!$show_question_only) {
568 // get page object output
569 $solutionoutput = $this->getILIASPage($solutionoutput);
570 }
571 return $solutionoutput;
572 }
573
574 public function getPreview(
575 bool $show_question_only = false,
576 bool $show_inline_feedback = false
577 ): string {
578 if (is_object($this->getPreviewSession())) {
579 $user_solution = [];
580
581 if (is_array($this->getPreviewSession()->getParticipantsSolution())) {
582 $user_solution = array_values($this->getPreviewSession()->getParticipantsSolution());
583 }
584
585 $preview = new ilImagemapPreview($this->object->getImagePath() . $this->object->getImageFilename());
586 foreach ($user_solution as $idx => $solution_value) {
587 if ($solution_value !== '') {
588 $preview->addArea($solution_value, $this->object->answers[$solution_value]->getArea(), $this->object->answers[$solution_value]->getCoords(), $this->object->answers[$solution_value]->getAnswertext(), "", "", true, $this->linecolor);
589 }
590 }
591 $preview->createPreview();
592 $imagepath = $this->object->getImagePathWeb() . $preview->getPreviewFilename($this->object->getImagePath(), $this->object->getImageFilename());
593 } else {
594 $user_solution = [];
595 $imagepath = $this->object->getImagePathWeb() . $this->object->getImageFilename();
596 }
597
598 // generate the question output
599 $template = new ilTemplate("tpl.il_as_qpl_imagemap_question_output.html", true, true, "components/ILIAS/TestQuestionPool");
600
601 if ($this->getQuestionActionCmd() && !is_null($this->getTargetGuiClass())) {
602 $hrefArea = $this->ctrl->getLinkTargetByClass($this->getTargetGuiClass(), $this->getQuestionActionCmd());
603 } else {
604 $hrefArea = null;
605 }
606
607 foreach ($this->object->answers as $answer_id => $answer) {
608 $parameter = "&amp;selImage=$answer_id";
609 if (is_array($user_solution) && in_array($answer_id, $user_solution)) {
610 $parameter = "&amp;remImage=$answer_id";
611 }
612
613 if ($hrefArea) {
614 $template->setCurrentBlock("imagemap_area_href");
615 $template->setVariable("HREF_AREA", $hrefArea . $parameter);
616 $template->parseCurrentBlock();
617 }
618
619 $template->setCurrentBlock("imagemap_area");
620 $template->setVariable("SHAPE", $answer->getArea());
621 $template->setVariable("COORDS", $answer->getCoords());
622 $template->setVariable("ALT", ilLegacyFormElementsUtil::prepareFormOutput($answer->getAnswertext()));
623 $template->setVariable("TITLE", ilLegacyFormElementsUtil::prepareFormOutput($answer->getAnswertext()));
624 $template->parseCurrentBlock();
625 }
626 $template->setVariable("QUESTIONTEXT", $this->renderLatex($this->object->getQuestionForHTMLOutput()));
627 try {
628 $template->setVariable("IMG_SRC", ilWACSignedPath::signFile($imagepath));
629 } catch (ilWACException $e) {
630
631 }
632 $template->setVariable("IMG_ALT", $this->lng->txt("imagemap"));
633 $template->setVariable("IMG_TITLE", $this->lng->txt("imagemap"));
634 $questionoutput = $template->get();
635 if (!$show_question_only) {
636 $questionoutput = $this->getILIASPage($questionoutput);
637 }
638 return $questionoutput;
639 }
640
641 public function getTestOutput(
642 int $active_id,
643 int $pass,
644 bool $is_question_postponed = false,
645 array|bool $user_post_solutions = false,
646 bool $show_specific_inline_feedback = false
647 ): string {
648 if ($active_id) {
649 $solutions = $this->object->getTestOutputSolutions($active_id, $pass);
650 // hey.
651
652 $userSelection = [];
653 $selectionIndex = 0;
654
655 $preview = new ilImagemapPreview($this->object->getImagePath() . $this->object->getImageFilename());
656
657 foreach ($solutions as $idx => $solution_value) {
658 if ($solution_value["value1"] !== null) {
659 $preview->addArea($solution_value["value1"], $this->object->answers[$solution_value["value1"]]->getArea(), $this->object->answers[$solution_value["value1"]]->getCoords(), $this->object->answers[$solution_value["value1"]]->getAnswertext(), "", "", true, $this->linecolor);
660 $userSelection[$selectionIndex] = $solution_value["value1"];
661
662 $selectionIndex = $this->object->getIsMultipleChoice() ? ++$selectionIndex : $selectionIndex;
663 }
664 }
665
666 $preview->createPreview();
667
668 $imagepath = $this->object->getImagePathWeb() . $preview->getPreviewFilename($this->object->getImagePath(), $this->object->getImageFilename());
669 } else {
670 $imagepath = $this->object->getImagePathWeb() . $this->object->getImageFilename();
671 }
672
673 // generate the question output
674 $template = new ilTemplate("tpl.il_as_qpl_imagemap_question_output.html", true, true, "components/ILIAS/TestQuestionPool");
675 $this->ctrl->setParameterByClass($this->getTargetGuiClass(), "formtimestamp", time());
676 foreach ($this->object->answers as $answer_id => $answer) {
677 $template->setCurrentBlock("imagemap_area");
678 $template->setVariable("HREF_AREA", $this->buildAreaLinkTarget($userSelection, $answer_id));
679 $template->setVariable("SHAPE", $answer->getArea());
680 $template->setVariable("COORDS", $answer->getCoords());
681 $template->setVariable("ALT", ilLegacyFormElementsUtil::prepareFormOutput($answer->getAnswertext()));
682 $template->setVariable("TITLE", ilLegacyFormElementsUtil::prepareFormOutput($answer->getAnswertext()));
683 $template->parseCurrentBlock();
684 if ($show_specific_inline_feedback) {
685 if (!$this->object->getIsMultipleChoice() && count($userSelection) && current($userSelection) == $answer_id) {
686 $feedback = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
687 $this->object->getId(),
688 0,
689 $answer_id
690 );
691 if ($feedback !== '') {
692 $template->setCurrentBlock("feedback");
693 $template->setVariable("FEEDBACK", $feedback);
694 $template->parseCurrentBlock();
695 }
696 }
697 }
698 }
699 $template->setVariable("QUESTIONTEXT", $this->renderLatex(
700 $this->object->getQuestionForHTMLOutput()
701 ));
702 try {
703 $template->setVariable("IMG_SRC", ilWACSignedPath::signFile($imagepath));
704 } catch (ilWACException $e) {
705
706 }
707 $template->setVariable("IMG_ALT", $this->lng->txt("imagemap"));
708 $template->setVariable("IMG_TITLE", $this->lng->txt("imagemap"));
709 $questionoutput = $template->get();
710 $pageoutput = $this->outQuestionPage("", $is_question_postponed, $active_id, $questionoutput);
711 return $pageoutput;
712 }
713
714 // hey: prevPassSolutions - fixed confusing handling of not reusing, but modifying the previous solution
715 protected function buildAreaLinkTarget($currentSelection, $areaIndex): string
716 {
717 $href = $this->ctrl->getLinkTargetByClass(
718 $this->getTargetGuiClass(),
719 $this->getQuestionActionCmd()
720 );
721
723 $href,
724 $this->buildSelectionParameter($currentSelection, $areaIndex)
725 );
726
727 return $href;
728 }
729
730 protected function buildSelectionParameter($currentSelection, $areaIndex = null): string
731 {
732 if ($this->object->getTestPresentationConfig()->isSolutionInitiallyPrefilled()) {
733 $reuseSelection = [];
734
735 if ($areaIndex === null) {
736 $reuseSelection = $currentSelection;
737 } elseif ($this->object->getIsMultipleChoice()) {
738 if (!in_array($areaIndex, $currentSelection)) {
739 $reuseSelection[] = $areaIndex;
740 }
741
742 foreach (array_diff($currentSelection, [$areaIndex]) as $otherSelectedArea) {
743 $reuseSelection[] = $otherSelectedArea;
744 }
745 } else {
746 $reuseSelection[] = $areaIndex;
747 }
748
749 $selection = assQuestion::implodeKeyValues($reuseSelection);
750 $action = 'reuseSelection';
751 } elseif ($areaIndex !== null) {
752 if (!$this->object->getIsMultipleChoice() || !in_array($areaIndex, $currentSelection)) {
753 $areaAction = 'selImage';
754 } else {
755 $areaAction = 'remImage';
756 }
757
758 $selection = $areaIndex;
759 $action = $areaAction;
760 } else {
761 return '';
762 }
763
764 return "{$action}={$selection}";
765 }
766
767 public function getSpecificFeedbackOutput(array $userSolution): string
768 {
769 if (!$this->object->feedbackOBJ->specificAnswerFeedbackExists()) {
770 return '';
771 }
772
773 $output = '<table class="test_specific_feedback"><tbody>';
774
775 foreach ($this->object->getAnswers() as $idx => $answer) {
776 $feedback = $this->object->feedbackOBJ->getSpecificAnswerFeedbackTestPresentation(
777 $this->object->getId(),
778 0,
779 $idx
780 );
781
782 $output .= "<tr><td>{$answer->getAnswerText()}</td><td>{$feedback}</td></tr>";
783 }
784
785 $output .= '</tbody></table>';
786
787 return $this->renderLatex(ilLegacyFormElementsUtil::prepareTextareaOutput($output, true));
788 }
789
800 {
801 return [];
802 }
803
814 {
815 return [];
816 }
817
818 private function aggregateAnswers($givenSolutionRows, $existingAnswerOptions): array
819 {
820 $answeringFequencies = [];
821
822 foreach ($existingAnswerOptions as $answerIndex => $answerOption) {
823 $answeringFequencies[$answerIndex] = 0;
824 }
825
826 foreach ($givenSolutionRows as $solutionRow) {
827 $answeringFequencies[$solutionRow['value1']]++;
828 }
829
830 return $answeringFequencies;
831 }
832
834 {
835 if (!count($this->object->currentSolution)) {
836 return '';
837 }
838
839 global $DIC;
840 $button = $DIC->ui()->factory()->link()->standard(
841 $this->lng->txt('use_previous_solution'),
843 $this->ctrl->getLinkTargetByClass($this->getTargetGuiClass(), $this->getQuestionActionCmd()),
844 $this->buildSelectionParameter($this->object->currentSolution, null)
845 )
846 );
847
848 $tpl = new ilTemplate('tpl.tst_question_additional_behaviour_checkbox.html', true, true, 'components/ILIAS/TestQuestionPool');
849 $tpl->setVariable('BUTTON', $DIC->ui()->renderer()->render($button));
850
851 return $tpl->get();
852 }
853
854 public function getAnswersFrequency($relevantAnswers, $questionIndex): array
855 {
856 $agg = $this->aggregateAnswers($relevantAnswers, $this->object->getAnswers());
857
858 $answers = [];
859
860 foreach ($this->object->getAnswers() as $answerIndex => $ans) {
861 $answers[] = [
862 'answer' => $ans->getAnswerText(),
863 'frequency' => $agg[$answerIndex]
864 ];
865 }
866
867 return $answers;
868 }
869
871 {
872 $image = new ilImagemapCorrectionsInputGUI($this->lng->txt('image'), 'image');
873 $image->setPointsUncheckedFieldEnabled($this->object->getIsMultipleChoice());
874 $image->setRequired(true);
875
876 if (strlen($this->object->getImageFilename())) {
877 $image->setImage($this->object->getImagePathWeb() . $this->object->getImageFilename());
878 $image->setValue($this->object->getImageFilename());
879 $image->setAreas($this->object->getAnswers());
880 $assessmentSetting = new ilSetting("assessment");
881 $linecolor = (strlen(
882 $assessmentSetting->get("imap_line_color")
883 )) ? "\"#" . $assessmentSetting->get("imap_line_color") . "\"" : "\"#FF0000\"";
884 $image->setLineColor($linecolor);
885 $image->setImagePath($this->object->getImagePath());
886 $image->setImagePathWeb($this->object->getImagePathWeb());
887 }
888 $form->addItem($image);
889 }
890
895 {
896 $areas = $form->getItemByPostVar('image')->getAreas();
897
898 foreach ($this->object->getAnswers() as $index => $answer) {
899 if ($this->object->getIsMultipleChoice()) {
900 $answer->setPointsUnchecked((float) $areas[$index]->getPointsUnchecked());
901 }
902
903 $answer->setPoints((float) $areas[$index]->getPoints());
904 }
905 }
906}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
writePostData(bool $always=false)
{Evaluates a posted edit form and writes the form data in the question object.integer A positive valu...
populateQuestionSpecificFormPart(\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)
getAfterParticipationSuppressionAnswerPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
aggregateAnswers($givenSolutionRows, $existingAnswerOptions)
buildSelectionParameter($currentSelection, $areaIndex=null)
populateAnswerSpecificFormPart(\ilPropertyFormGUI $form)
getAnswersFrequency($relevantAnswers, $questionIndex)
writeAnswerSpecificPostData(ilPropertyFormGUI $form)
Extracts the answer specific values from the request and applies them to the data object.
buildAreaLinkTarget($currentSelection, $areaIndex)
saveCorrectionsFormProperties(ilPropertyFormGUI $form)
completeTestOutputFormAction(string $form_action, int $active_id, int $pass)
getTestOutput(int $active_id, int $pass, bool $is_question_postponed=false, array|bool $user_post_solutions=false, bool $show_specific_inline_feedback=false)
editQuestion(bool $checkonly=false, ?bool $is_save_cmd=null)
__construct(int $id=-1)
assImagemapQuestionGUI constructor
getPreview(bool $show_question_only=false, bool $show_inline_feedback=false)
populateCorrectionsFormProperties(ilPropertyFormGUI $form)
getAfterParticipationSuppressionQuestionPostVars()
Returns a list of postvars which will be suppressed in the form output when used in scoring adjustmen...
getSpecificFeedbackOutput(array $userSolution)
Returns the answer specific feedback for the question.
writeQuestionSpecificPostData(ilPropertyFormGUI $form)
Extracts the question specific values from the request and applies them to the data object.
Class for image map questions.
populateTaxonomyFormSection(ilPropertyFormGUI $form)
addBasicQuestionFormProperties(ilPropertyFormGUI $form)
renderEditForm(ilPropertyFormGUI $form)
addQuestionFormCommandButtons(ilPropertyFormGUI $form)
static implodeKeyValues(array $keyValues)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This class represents an image map file property in a property form.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
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 property form user interface.
getItemByPostVar(string $a_post_var)
This class represents a property in a property form.
This class represents an option in a radio group.
ILIAS Setting Class.
special template class to simplify handling of ITX/PEAR
static appendUrlParameterString(string $a_url, string $a_par, bool $xml_style=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static signFile(string $path_to_file)
$c
Definition: deliver.php:25
$info
Definition: entry_point.php:21
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'))
global $DIC
Definition: shib_login.php:26