ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.assImagemapQuestion.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
25
40{
41 private RequestDataCollector $request; // Hate it.
42
43 // hey: prevPassSolutions - wtf is imagemap ^^
44 public $currentSolution = [];
45 // hey.
46
47 public const MODE_SINGLE_CHOICE = 0;
48 public const MODE_MULTIPLE_CHOICE = 1;
49
50 public const AVAILABLE_SHAPES = [
51 'RECT' => 'rect',
52 'CIRCLE' => 'circle',
53 'POLY' => 'poly'];
54
56 public $answers;
57
60
63
65 public $coords;
66
68 protected $is_multiple_choice = false;
69
83 public function __construct(
84 $title = '',
85 $comment = '',
86 $author = '',
87 $owner = -1,
88 $question = '',
90 ) {
92 $this->image_filename = $image_filename;
93 $this->answers = [];
94 $this->coords = [];
95
96 $local_dic = QuestionPoolDIC::dic();
97 $this->request = $local_dic['request_data_collector'];
98 }
99
106 {
107 $this->is_multiple_choice = $is_multiple_choice;
108 }
109
115 public function getIsMultipleChoice(): bool
116 {
118 }
119
120 public function isComplete(): bool
121 {
122 if ($this->title !== ''
123 && $this->author
124 && $this->question
125 && $this->image_filename
126 && $this->answers !== []
127 && $this->getMaximumPoints() > 0
128 ) {
129 return true;
130 }
131 return false;
132 }
133
134 public function saveToDb(?int $original_id = null): void
135 {
139 parent::saveToDb($original_id);
140 }
141
142 public function saveAnswerSpecificDataToDb(): void
143 {
144 $this->db->manipulateF(
145 'DELETE FROM qpl_a_imagemap WHERE question_fi = %s',
146 [ 'integer' ],
147 [ $this->getId() ]
148 );
149
150 // Anworten wegschreiben
151 foreach ($this->answers as $key => $value) {
152 $answer_obj = $this->answers[$key];
153 $answer_obj->setOrder($key);
154 $next_id = $this->db->nextId('qpl_a_imagemap');
155 $this->db->manipulateF(
156 'INSERT INTO qpl_a_imagemap (answer_id, question_fi, answertext, points, aorder, coords, area, points_unchecked) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)',
157 [ 'integer', 'integer', 'text', 'float', 'integer', 'text', 'text', 'float' ],
158 [ $next_id, $this->id, $answer_obj->getAnswertext(
159 ), $answer_obj->getPoints(), $answer_obj->getOrder(
160 ), $answer_obj->getCoords(), $answer_obj->getArea(
161 ), $answer_obj->getPointsUnchecked() ]
162 );
163 }
164 }
165
166 public function saveAdditionalQuestionDataToDb(): void
167 {
168 $this->db->manipulateF(
169 'DELETE FROM ' . $this->getAdditionalTableName() . ' WHERE question_fi = %s',
170 [ 'integer' ],
171 [ $this->getId() ]
172 );
173
174 $this->db->manipulateF(
175 'INSERT INTO ' . $this->getAdditionalTableName(
176 ) . ' (question_fi, image_file, is_multiple_choice) VALUES (%s, %s, %s)',
177 [ 'integer', 'text', 'integer' ],
178 [
179 $this->getId(),
180 $this->image_filename,
181 (int) $this->is_multiple_choice
182 ]
183 );
184 }
185
187 \assQuestion $target
188 ): \assQuestion {
189 $this->copyImagemapFiles($this->getId(), $this->getObjId(), $target->getId(), $target->getObjId());
190 return $target;
191 }
192
193 public function copyImagemapFiles(
194 int $source_question_id,
195 int $source_parent_id,
196 int $target_question_id,
197 int $target_parent_id
198 ): void {
199 $image_source_path = $this->getImagePath($source_question_id, $source_parent_id);
200 $image_target_path = $this->getImagePath($target_question_id, $target_parent_id);
201
202 if (!file_exists($image_target_path)) {
203 ilFileUtils::makeDirParents($image_target_path);
204 } else {
205 $this->removeAllImageFiles($image_target_path);
206 }
207
208 $src = opendir($image_source_path);
209 while ($src_file = readdir($src)) {
210 if ($src_file === '.' || $src_file === '..') {
211 continue;
212 }
213 copy(
214 $image_source_path . DIRECTORY_SEPARATOR . $src_file,
215 $image_target_path . DIRECTORY_SEPARATOR . $src_file
216 );
217 }
218 }
219
220 public function loadFromDb(int $question_id): void
221 {
222 $result = $this->db->queryF(
223 'SELECT qpl_questions.*, ' . $this->getAdditionalTableName() . '.* FROM qpl_questions LEFT JOIN ' . $this->getAdditionalTableName() . ' ON ' . $this->getAdditionalTableName() . '.question_fi = qpl_questions.question_id WHERE qpl_questions.question_id = %s',
224 ['integer'],
225 [$question_id]
226 );
227 if ($result->numRows() == 1) {
228 $data = $this->db->fetchAssoc($result);
229 $this->setId($question_id);
230 $this->setObjId($data['obj_fi']);
231 $this->setTitle((string) $data['title']);
232 $this->setComment((string) $data['description']);
233 $this->setOriginalId($data['original_id']);
234 $this->setNrOfTries($data['nr_of_tries']);
235 $this->setAuthor($data['author']);
236 $this->setPoints($data['points']);
237 $this->setOwner($data['owner']);
238 $this->setIsMultipleChoice($data['is_multiple_choice'] == self::MODE_MULTIPLE_CHOICE);
239 $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc((string) $data['question_text'], 1));
240 $this->setImageFilename($data['image_file'] ?? '');
241
242 try {
243 $this->setLifecycle(ilAssQuestionLifecycle::getInstance($data['lifecycle']));
245 $this->setLifecycle(ilAssQuestionLifecycle::getDraftInstance());
246 }
247
248 try {
249 $this->setAdditionalContentEditingMode($data['add_cont_edit_mode']);
251 }
252
253 $result = $this->db->queryF(
254 'SELECT * FROM qpl_a_imagemap WHERE question_fi = %s ORDER BY aorder ASC',
255 ['integer'],
256 [$question_id]
257 );
258 if ($result->numRows() > 0) {
259 while ($data = $this->db->fetchAssoc($result)) {
260 $image_map_question = new ASS_AnswerImagemap($data['answertext'] ?? '', $data['points'], $data['aorder']);
261 $image_map_question->setCoords($data['coords']);
262 $image_map_question->setArea($data['area']);
263 $image_map_question->setPointsUnchecked($data['points_unchecked']);
264 array_push($this->answers, $image_map_question);
265 }
266 }
267 }
268 parent::loadFromDb($question_id);
269 }
270
271 public function uploadImagemap(array $shapes): int
272 {
273 $added = 0;
274
275 if (count($shapes) > 0) {
276 foreach ($shapes as $shape) {
277 $this->addAnswer($shape->getAnswertext(), 0.0, count($this->answers), $shape->getCoords(), $shape->getArea());
278 $added++;
279 }
280 }
281
282 return $added;
283 }
284
285 public function getImageFilename(): string
286 {
287 return $this->image_filename;
288 }
289
290 public function setImageFilename(
291 string $image_filename,
292 string $image_tempfilename = ''
293 ): void {
294 if (!empty($image_filename)) {
295 $image_filename = str_replace(' ', '_', $image_filename);
296 $this->image_filename = $image_filename;
297 }
298 if (!empty($image_tempfilename)) {
299 $imagepath = $this->getImagePath();
300 if (!file_exists($imagepath)) {
301 ilFileUtils::makeDirParents($imagepath);
302 }
303 if (!ilFileUtils::moveUploadedFile($image_tempfilename, $image_filename, $imagepath . $image_filename)) {
304 $this->tpl->setOnScreenMessage('failure', 'The image could not be uploaded!');
305 return;
306 }
307 $this->log->write('gespeichert: ' . $imagepath . $image_filename);
308 }
309 }
310
311 public function get_imagemap_contents(string $href = '#'): string
312 {
313 $imagemap_contents = '<map name=\'' . $this->title . '\'> ';
314 for ($i = 0; $i < count($this->answers); $i++) {
315 $imagemap_contents .= '<area alt=\'' . $this->answers[$i]->getAnswertext() . '\' ';
316 $imagemap_contents .= 'shape=\'' . $this->answers[$i]->getArea() . '\' ';
317 $imagemap_contents .= 'coords=\'' . $this->answers[$i]->getCoords() . '\' ';
318 $imagemap_contents .= "href=\"{$href}&selimage=" . $this->answers[$i]->getOrder() . "\" /> ";
319 }
320 $imagemap_contents .= '</map>';
321 return $imagemap_contents;
322 }
323
324 public function addAnswer(
325 string $answertext = '',
326 float $points = 0.0,
327 int $order = 0,
328 string $coords = '',
329 string $area = '',
330 float $points_unchecked = 0.0
331 ): void {
332 if (array_key_exists($order, $this->answers)) {
333 // Insert answer
334 $answer = new ASS_AnswerImagemap($answertext, $points, $order, 0, -1);
335 $answer->setCoords($coords);
336 $answer->setArea($area);
337 $answer->setPointsUnchecked($points_unchecked);
338 for ($i = count($this->answers) - 1; $i >= $order; $i--) {
339 $this->answers[$i + 1] = $this->answers[$i];
340 $this->answers[$i + 1]->setOrder($i + 1);
341 }
342 $this->answers[$order] = $answer;
343 } else {
344 // Append answer
345 $answer = new ASS_AnswerImagemap($answertext, $points, count($this->answers), 0, -1);
346 $answer->setCoords($coords);
347 $answer->setArea($area);
348 $answer->setPointsUnchecked($points_unchecked);
349 array_push($this->answers, $answer);
350 }
351 }
352
353 public function getAnswerCount(): int
354 {
355 return count($this->answers);
356 }
357
358 public function getAnswer(int $index = 0): ?ASS_AnswerImagemap
359 {
360 if ($index < 0) {
361 return null;
362 }
363 if (count($this->answers) < 1) {
364 return null;
365 }
366 if ($index >= count($this->answers)) {
367 return null;
368 }
369 return $this->answers[$index];
370 }
371
372 public function &getAnswers(): array
373 {
374 return $this->answers;
375 }
376
377 public function deleteArea(int $index = 0): void
378 {
379 if ($index < 0) {
380 return;
381 }
382 if (count($this->answers) < 1) {
383 return;
384 }
385 if ($index >= count($this->answers)) {
386 return;
387 }
388 unset($this->answers[$index]);
389 $this->answers = array_values($this->answers);
390 for ($i = 0; $i < count($this->answers); $i++) {
391 if ($this->answers[$i]->getOrder() > $index) {
392 $this->answers[$i]->setOrder($i);
393 }
394 }
395 }
396
397 public function flushAnswers(): void
398 {
399 $this->answers = [];
400 }
401
402 public function getMaximumPoints(): float
403 {
404 $points = 0;
405 foreach ($this->answers as $key => $value) {
406 if ($this->is_multiple_choice) {
407 if ($value->getPoints() > $value->getPointsUnchecked()) {
408 $points += $value->getPoints();
409 } else {
410 $points += $value->getPointsUnchecked();
411 }
412 } else {
413 if ($value->getPoints() > $points) {
414 $points = $value->getPoints();
415 }
416 }
417 }
418 return $points;
419 }
420
421 public function calculateReachedPoints(
422 int $active_id,
423 ?int $pass = null,
424 bool $authorized_solution = true
425 ): float {
426 if ($pass === null) {
427 $pass = $this->getSolutionMaxPass($active_id);
428 }
429 $result = $this->getCurrentSolutionResultSet($active_id, $pass, $authorized_solution);
430 $found_values = [];
431 while ($data = $this->db->fetchAssoc($result)) {
432 if ($data['value1'] !== '') {
433 $found_values[] = $data['value1'];
434 }
435 }
436
437 $points = $this->calculateReachedPointsForSolution($found_values);
438
439 return $points;
440 }
441
442 public function calculateReachedPointsFromPreviewSession(ilAssQuestionPreviewSession $preview_session): float
443 {
444 $solution_data = $preview_session->getParticipantsSolution();
445
446 $reached_points = $this->calculateReachedPointsForSolution(is_array($solution_data) ? array_values($solution_data) : []);
447
448 return $this->ensureNonNegativePoints($reached_points);
449 }
450
459 public function saveWorkingData(
460 int $active_id,
461 ?int $pass = null,
462 bool $authorized = true
463 ): bool {
464 if (is_null($pass)) {
465 $pass = ilObjTest::_getPass($active_id);
466 }
467
468 $this->getProcessLocker()->executeUserSolutionUpdateLockOperation(
469 function () use ($active_id, $pass, $authorized) {
470 if ($authorized) {
471 // remove the dummy record of the intermediate solution
472 $this->deleteDummySolutionRecord($active_id, $pass);
473
474 // delete the authorized solution and make the intermediate solution authorized (keeping timestamps)
475 $this->removeCurrentSolution($active_id, $pass, true);
476 $this->updateCurrentSolutionsAuthorization($active_id, $pass, true, true);
477 return;
478 }
479
480 $this->forceExistingIntermediateSolution(
481 $active_id,
482 $pass,
483 $this->is_multiple_choice
484 );
485
486 if ($this->isReuseSolutionSelectionRequest()) {
487 $selection = $this->getReuseSolutionSelectionParameter();
488
489 foreach ($selection as $selectedIndex) {
490 $this->saveCurrentSolution($active_id, $pass, (int) $selectedIndex, null, $authorized);
491 }
492 return;
493 }
494
495 if ($this->isRemoveSolutionSelectionRequest()) {
496 $selection = $this->getRemoveSolutionSelectionParameter();
497 $this->deleteSolutionRecordByValues($active_id, $pass, $authorized, [
498 'value1' => (int) $selection
499 ]);
500 return;
501 }
502
503 if (!$this->isAddSolutionSelectionRequest()) {
504 return;
505 }
506 $selection = $this->getAddSolutionSelectionParameter();
507
508 if ($this->is_multiple_choice) {
509 $this->deleteSolutionRecordByValues($active_id, $pass, $authorized, [
510 'value1' => (int) $this->request->raw('selImage')
511 ]);
512 } else {
513 $this->removeCurrentSolution($active_id, $pass, $authorized);
514 }
515
516 $this->saveCurrentSolution($active_id, $pass, $this->request->raw('selImage'), null, $authorized);
517 }
518 );
519
520 return true;
521 }
522
523 protected function savePreviewData(ilAssQuestionPreviewSession $previewSession): void
524 {
525 $solution = $previewSession->getParticipantsSolution();
526
527 if ($this->is_multiple_choice
528 && $this->request->isset('remImage')) {
529 unset($solution[$this->request->int('remImage')]);
530 }
531
532 if ($this->request->isset('selImage')) {
533 if (!$this->is_multiple_choice) {
534 $solution = [];
535 }
536
537 $solution[$this->request->int('selImage')] = $this->request->int('selImage');
538 }
539
540 $previewSession->setParticipantsSolution($solution);
541 }
542
551 public function getQuestionType(): string
552 {
553 return 'assImagemapQuestion';
554 }
555
564 public function getAdditionalTableName(): string
565 {
566 return 'qpl_qst_imagemap';
567 }
568
577 public function getAnswerTableName(): string
578 {
579 return 'qpl_a_imagemap';
580 }
581
586 public function getRTETextWithMediaObjects(): string
587 {
588 $text = parent::getRTETextWithMediaObjects();
589 foreach ($this->answers as $index => $answer) {
590 $text .= $this->feedbackOBJ->getSpecificAnswerFeedbackContent($this->getId(), 0, $index);
591 }
592 return $text;
593 }
594
598 public function deleteImage(): void
599 {
600 $file = $this->getImagePath() . $this->getImageFilename();
601 @unlink($file);
602 $this->flushAnswers();
603 $this->image_filename = '';
604 }
605
609 public function toJSON(): string
610 {
611 $result = [];
612 $result['id'] = $this->getId();
613 $result['type'] = (string) $this->getQuestionType();
614 $result['title'] = $this->getTitleForHTMLOutput();
615 $result['question'] = $this->formatSAQuestion($this->getQuestion());
616 $result['nr_of_tries'] = $this->getNrOfTries();
617 $result['shuffle'] = $this->getShuffle();
618 $result['is_multiple'] = $this->getIsMultipleChoice();
619 $result['feedback'] = [
620 'onenotcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), false)),
621 'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), true))
622 ];
623 $result['image'] = $this->getImagePathWeb() . $this->getImageFilename();
624
625 $answers = [];
626 $order = 0;
627 foreach ($this->getAnswers() as $key => $answer_obj) {
628 array_push($answers, [
629 'answertext' => (string) $answer_obj->getAnswertext(),
630 'points' => (float) $answer_obj->getPoints(),
631 'points_unchecked' => (float) $answer_obj->getPointsUnchecked(),
632 'order' => $order,
633 'coords' => $answer_obj->getCoords(),
634 'state' => $answer_obj->getState(),
635 'area' => $answer_obj->getArea(),
636 'feedback' => $this->formatSAQuestion(
637 $this->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->getId(), 0, $key)
638 )
639 ]);
640 $order++;
641 }
642 $result['answers'] = $answers;
643
644 $mobs = ilObjMediaObject::_getMobsOfObject('qpl:html', $this->getId());
645 $result['mobs'] = $mobs;
646
647 return json_encode($result);
648 }
649
650 protected function calculateReachedPointsForSolution(?array $found_values): float
651 {
652 if ($found_values === null) {
653 $found_values = [];
654 }
655 $points = 0;
656 if (count($found_values) > 0) {
657 foreach ($this->answers as $key => $answer) {
658 if (in_array($key, $found_values)) {
659 $points += $answer->getPoints();
660 } elseif ($this->getIsMultipleChoice()) {
661 $points += $answer->getPointsUnchecked();
662 }
663 }
664 return $points;
665 }
666 return $points;
667 }
668
669 public function getOperators(string $expression): array
670 {
671 return ilOperatorsExpressionMapping::getOperatorsByExpression($expression);
672 }
673
674 public function getExpressionTypes(): array
675 {
676 return [
677 iQuestionCondition::PercentageResultExpression,
678 iQuestionCondition::NumberOfResultExpression,
679 iQuestionCondition::EmptyAnswerExpression,
680 iQuestionCondition::ExclusiveResultExpression
681 ];
682 }
683
684 public function getUserQuestionResult(
685 int $active_id,
686 int $pass
687 ): ilUserQuestionResult {
688 $result = new ilUserQuestionResult($this, $active_id, $pass);
689
690 $maxStep = $this->lookupMaxStep($active_id, $pass);
691 if ($maxStep > 0) {
692 $data = $this->db->queryF(
693 'SELECT value1+1 as value1 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step = %s',
694 ['integer', 'integer', 'integer', 'integer'],
695 [$active_id, $pass, $this->getId(), $maxStep]
696 );
697 } else {
698 $data = $this->db->queryF(
699 'SELECT value1+1 as value1 FROM tst_solutions WHERE active_fi = %s AND pass = %s AND question_fi = %s AND step IS NULL',
700 ['integer', 'integer', 'integer'],
701 [$active_id, $pass, $this->getId()]
702 );
703 }
704
705 while ($row = $this->db->fetchAssoc($data)) {
706 $result->addKeyValue($row['value1'], $row['value1']);
707 }
708
709 $points = $this->calculateReachedPoints($active_id, $pass);
710 $max_points = $this->getMaximumPoints();
711
712 $result->setReachedPercentage(($points / $max_points) * 100);
713
714 return $result;
715 }
716
724 public function getAvailableAnswerOptions($index = null)
725 {
726 if ($index !== null) {
727 return $this->getAnswer($index);
728 } else {
729 return $this->getAnswers();
730 }
731 }
732
733 public function getTestOutputSolutions($activeId, $pass): array
734 {
735 $solution = parent::getTestOutputSolutions($activeId, $pass);
736
737 $this->currentSolution = [];
738 foreach ($solution as $record) {
739 $this->currentSolution[] = $record['value1'];
740 }
741
742 return $solution;
743 }
744 protected function getAddSolutionSelectionParameter()
745 {
746 if (!$this->isAddSolutionSelectionRequest()) {
747 return null;
748 }
749
750 return $this->request->raw('selImage');
751 }
752 protected function isAddSolutionSelectionRequest(): bool
753 {
754 if (!$this->request->isset('selImage')) {
755 return false;
756 }
757
758 if (!strlen($this->request->raw('selImage'))) {
759 return false;
760 }
761
762 return true;
763 }
764 protected function getRemoveSolutionSelectionParameter()
765 {
766 if (!$this->isRemoveSolutionSelectionRequest()) {
767 return null;
768 }
769
770 return $this->request->raw('remImage');
771 }
772 protected function isRemoveSolutionSelectionRequest(): bool
773 {
774 if (!$this->is_multiple_choice) {
775 return false;
776 }
777
778 if (!$this->request->isset('remImage')) {
779 return false;
780 }
781
782 if (!strlen($this->request->raw('remImage'))) {
783 return false;
784 }
785
786 return true;
787 }
788 protected function getReuseSolutionSelectionParameter(): ?array
789 {
790 if (!$this->isReuseSolutionSelectionRequest()) {
791 return null;
792 }
793
794 return assQuestion::explodeKeyValues($this->request->raw('reuseSelection'));
795 }
796 protected function isReuseSolutionSelectionRequest(): bool
797 {
798 if (!$this->getTestPresentationConfig()->isPreviousPassSolutionReuseAllowed()) {
799 return false;
800 }
801
802 if (!$this->request->isset('reuseSelection')) {
803 return false;
804 }
805
806 if (!strlen($this->request->raw('reuseSelection'))) {
807 return false;
808 }
809
810 if (!preg_match('/\d(,\d)*/', $this->request->raw('reuseSelection'))) {
811 return false;
812 }
813
814 return true;
815 }
816
817 public function toLog(AdditionalInformationGenerator $additional_info): array
818 {
819 $result = [
820 AdditionalInformationGenerator::KEY_QUESTION_TYPE => (string) $this->getQuestionType(),
821 AdditionalInformationGenerator::KEY_QUESTION_TITLE => $this->getTitleForHTMLOutput(),
822 AdditionalInformationGenerator::KEY_QUESTION_TEXT => $this->formatSAQuestion($this->getQuestion()),
823 AdditionalInformationGenerator::KEY_QUESTION_SHUFFLE_ANSWER_OPTIONS => $additional_info
824 ->getTrueFalseTagForBool($this->getShuffle()),
825 AdditionalInformationGenerator::KEY_QUESTION_IMAGEMAP_MODE => $this->getIsMultipleChoice()
826 ? $additional_info->getTagForLangVar('tst_imap_qst_mode_mc')
827 : $additional_info->getTagForLangVar('tst_imap_qst_mode_sc'),
828 AdditionalInformationGenerator::KEY_QUESTION_IMAGEMAP_IMAGE => $this->getImagePathWeb() . $this->getImageFilename(),
829 AdditionalInformationGenerator::KEY_FEEDBACK => [
830 AdditionalInformationGenerator::KEY_QUESTION_FEEDBACK_ON_INCOMPLETE => $this->formatSAQuestion(
831 $this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), false)
832 ),
833 AdditionalInformationGenerator::KEY_QUESTION_FEEDBACK_ON_COMPLETE => $this->formatSAQuestion(
834 $this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), true)
835 )
836 ]
837 ];
838
839 $answers = [];
840 $order = 0;
841 foreach ($this->getAnswers() as $key => $answer_obj) {
842 array_push($answers, [
843 AdditionalInformationGenerator::KEY_QUESTION_ANSWER_OPTION => (string) $answer_obj->getAnswertext(),
844 AdditionalInformationGenerator::KEY_QUESTION_POINTS_CHECKED => (float) $answer_obj->getPoints(),
845 AdditionalInformationGenerator::KEY_QUESTION_POINTS_UNCHECKED => (float) $answer_obj->getPointsUnchecked(),
846 AdditionalInformationGenerator::KEY_QUESTION_ANSWER_OPTION_ORDER => $order,
847 AdditionalInformationGenerator::KEY_QUESTION_IMAGEMAP_ANSWER_OPTION_COORDS => $answer_obj->getCoords(),
848 AdditionalInformationGenerator::KEY_FEEDBACK => $this->formatSAQuestion(
849 $this->feedbackOBJ->getSpecificAnswerFeedbackExportPresentation($this->getId(), 0, $key)
850 )
851 ]);
852 $order++;
853 }
854 $result[AdditionalInformationGenerator::KEY_QUESTION_ANSWER_OPTIONS] = $answers;
855
856 return $result;
857 }
858
859 protected function solutionValuesToLog(
860 AdditionalInformationGenerator $additional_info,
861 array $solution_values
862 ): array {
863 $parsed_solution = [];
864 foreach ($this->getAnswers() as $id => $answer) {
865 $value = $additional_info->getTagForLangVar('unchecked');
866 foreach ($solution_values as $solution) {
867 if ($solution['value1'] == $id) {
868 $value = $additional_info->getTagForLangVar('checked');
869 break;
870 }
871 }
872 $parsed_solution["{$answer->getArea()}: {$answer->getCoords()}"] = $value;
873 }
874 return $parsed_solution;
875 }
876
877 public function solutionValuesToText(array $solution_values): array
878 {
879 $parsed_solution = [];
880 foreach ($this->getAnswers() as $id => $answer) {
881 $value = $this->lng->txt('unchecked');
882 foreach ($solution_values as $solution) {
883 if ($solution['value1'] == $id) {
884 $value = $this->lng->txt('checked');
885 break;
886 }
887 }
888 $parsed_solution[] = "{$answer->getArea()}: {$answer->getCoords()} ({$value})";
889 }
890 return $parsed_solution;
891 }
892
893 public function getCorrectSolutionForTextOutput(int $active_id, int $pass): array
894 {
895 return array_map(
896 fn(ASS_AnswerImagemap $v): string => "{$v->getArea()}: {$v->getCoords()}"
897 . "({$this->lng->txt('points')} "
898 . "{$this->lng->txt('checked')}: {$v->getPoints()}, "
899 . "{$this->lng->txt('unchecked')}: {$v->getPointsUnchecked()})",
900 $this->getAnswers()
901 );
902 }
903}
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Class for image map questions.
setIsMultipleChoice($is_multiple_choice)
Set true if the Imagemapquestion is a multiplechoice Question.
__construct( $title='', $comment='', $author='', $owner=-1, $question='', $image_filename='')
assImagemapQuestion constructor
RequestDataCollector $request
copyImagemapFiles(int $source_question_id, int $source_parent_id, int $target_question_id, int $target_parent_id)
setImageFilename(string $image_filename, string $image_tempfilename='')
saveAdditionalQuestionDataToDb()
Saves a record to the question types additional data table.
saveToDb(?int $original_id=null)
getAdditionalTableName()
Returns the name of the additional question data table in the database.
cloneQuestionTypeSpecificProperties(\assQuestion $target)
saveAnswerSpecificDataToDb()
Saves the answer specific records into a question types answer table.
get_imagemap_contents(string $href='#')
getIsMultipleChoice()
Returns true, if the imagemap question is a multiplechoice question.
saveQuestionDataToDb(?int $original_id=null)
static makeDirParents(string $a_dir)
Create a new directory and all parent directories.
static moveUploadedFile(string $a_file, string $a_name, string $a_target, bool $a_raise_errors=true, string $a_mode="move_uploaded")
move uploaded file
static _replaceMediaObjectImageSrc(string $a_text, int $a_direction=0, string $nic='')
Replaces image source from mob image urls with the mob id or replaces mob id with the correct image s...
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...
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
if(!file_exists('../ilias.ini.php'))