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