ILIAS  release_8 Revision v8.24
class.assLongMenu.php
Go to the documentation of this file.
1<?php
2
19require_once './Modules/Test/classes/inc.AssessmentConstants.php';
20
22{
23 private $answerType;
26 private $ilDB;
30
31 public const ANSWER_TYPE_SELECT_VAL = 0;
32 public const ANSWER_TYPE_TEXT_VAL = 1;
33 public const GAP_PLACEHOLDER = 'Longmenu';
34 public const MIN_LENGTH_AUTOCOMPLETE = 3;
35 public const MAX_INPUT_FIELDS = 500;
36
37 protected const HAS_SPECIFIC_FEEDBACK = false;
38
40 private $correct_answers = [];
41
43 private $answers = [];
44
45 public function __construct(
46 $title = "",
47 $comment = "",
48 $author = "",
49 $owner = -1,
50 $question = ""
51 ) {
52 global $DIC;
53 require_once 'Modules/TestQuestionPool/classes/feedback/class.ilAssConfigurableMultiOptionQuestionFeedback.php';
55 $this->minAutoComplete = self::MIN_LENGTH_AUTOCOMPLETE;
57 $this->ilDB = $DIC->database();
58 $this->identical_scoring = 1;
59 }
60
64 public function getAnswerType()
65 {
66 return $this->answerType;
67 }
68
72 public function setAnswerType($answerType): void
73 {
74 $this->answerType = $answerType;
75 }
76
80 public function getCorrectAnswers()
81 {
83 }
84
85
86 public function setCorrectAnswers($correct_answers): void
87 {
88 $this->correct_answers = $correct_answers;
89 }
90
91 private function buildFolderName(): string
92 {
93 return ilFileUtils::getDataDir() . '/assessment/longMenuQuestion/' . $this->getId() . '/' ;
94 }
95
96 public function getAnswerTableName(): string
97 {
98 return "qpl_a_lome";
99 }
100
101 private function buildFileName($gap_id): ?string
102 {
103 try {
104 $this->assertDirExists();
105 return $this->buildFolderName() . $gap_id . '.txt';
106 } catch (ilException $e) {
107 }
108 return null;
109 }
110
111 public function setLongMenuTextValue($long_menu_text = ""): void
112 {
113 $this->long_menu_text = $this->getHtmlQuestionContentPurifier()->purify($long_menu_text);
114 }
115
116 public function getLongMenuTextValue()
117 {
119 }
120
121 public function setAnswers($answers): void
122 {
123 $this->answers = $answers;
124 }
125
126 public function getAnswers(): array
127 {
128 return $this->answers;
129 }
130
134 public function getJsonStructure()
135 {
137 }
138
142 public function setJsonStructure($json_structure): void
143 {
144 $this->json_structure = $json_structure;
145 }
146
148 {
149 $this->specificFeedbackSetting = $specificFeedbackSetting;
150 }
151
153 {
155 }
156
158 {
159 $this->minAutoComplete = $minAutoComplete;
160 }
161
162 public function getMinAutoComplete(): int
163 {
164 return $this->minAutoComplete ? $this->minAutoComplete : self::MIN_LENGTH_AUTOCOMPLETE;
165 }
166
167 public function isComplete(): bool
168 {
169 if (strlen($this->title)
170 && $this->author
171 && $this->long_menu_text
172 && sizeof($this->answers) > 0
173 && sizeof($this->correct_answers) > 0
174 && $this->getPoints() > 0
175 ) {
176 return true;
177 }
178 return false;
179 }
180
181 public function saveToDb(int $original_id = -1): void
182 {
186 parent::saveToDb();
187 }
188
193 public function checkQuestionCustomPart($form = null): bool
194 {
195 $hidden_text_files = $this->getAnswers();
197 $points = array();
198 if ($correct_answers === null || sizeof($correct_answers) == 0 || $hidden_text_files === null || sizeof($hidden_text_files) == 0) {
199 return false;
200 }
201 if (sizeof($correct_answers) != sizeof($hidden_text_files)) {
202 return false;
203 }
204 foreach ($correct_answers as $key => $correct_answers_row) {
205 if ($this->correctAnswerDoesNotExistInAnswerOptions($correct_answers_row, $hidden_text_files[$key])) {
206 return false;
207 }
208 if (!is_array($correct_answers_row[0]) || sizeof($correct_answers_row[0]) == 0) {
209 return false;
210 }
211 if ($correct_answers_row[1] > 0) {
212 array_push($points, $correct_answers_row[1]);
213 }
214 }
215 if (sizeof($correct_answers) != sizeof($points)) {
216 return false;
217 }
218
219 foreach ($points as $row) {
220 if ($row <= 0) {
221 return false;
222 }
223 }
224 return true;
225 }
226
232 private function correctAnswerDoesNotExistInAnswerOptions($answers, $answer_options): bool
233 {
234 foreach ($answers[0] as $key => $answer) {
235 if (!in_array($answer, $answer_options)) {
236 return true;
237 }
238 }
239 return false;
240 }
241
242
249 public function getMaximumPoints(): float
250 {
251 $sum = 0;
252 $points = $this->getCorrectAnswers();
253 if ($points) {
254 foreach ($points as $add) {
255 $sum += (float) $add[1];
256 }
257 }
258 return $sum;
259 }
260
262 {
263 // save additional data
264 $this->ilDB->manipulateF(
265 "DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
266 array( "integer" ),
267 array( $this->getId() )
268 );
269 $this->ilDB->manipulateF(
270 "INSERT INTO " . $this->getAdditionalTableName(
271 ) . " (question_fi, long_menu_text, feedback_setting, min_auto_complete, identical_scoring) VALUES (%s, %s, %s, %s, %s)",
272 array( "integer", "text", "integer", "integer", "integer"),
273 array(
274 $this->getId(),
275 $this->getLongMenuTextValue(),
277 $this->getMinAutoComplete(),
278 $this->getIdenticalScoring()
279 )
280 );
281
282 $this->createFileFromArray();
283 }
284
285 public function saveAnswerSpecificDataToDb(): void
286 {
287 $this->clearAnswerSpecificDataFromDb($this->getId());
288 $type_array = $this->getAnswerType();
289 $points = 0;
290 foreach ($this->getCorrectAnswers() as $gap_number => $gap) {
291 foreach ($gap[0] as $position => $answer) {
292 if ($type_array == null) {
293 $type = $gap[2];
294 } else {
295 $type = $type_array[$gap_number];
296 }
297 $this->db->replace(
298 $this->getAnswerTableName(),
299 array(
300 'question_fi' => array('integer', $this->getId()),
301 'gap_number' => array('integer', (int) $gap_number),
302 'position' => array('integer', (int) $position)
303 ),
304 array(
305 'answer_text' => array('text', $answer),
306 'points' => array('float', (float) str_replace(',', '.', $gap[1])),
307 'type' => array('integer', (int) $type)
308 )
309 );
310 }
311 $points += (float) str_replace(',', '.', $gap[1]);
312 }
313 $this->setPoints($points);
314 }
315
316 private function createFileFromArray(): void
317 {
318 $array = $this->getAnswers();
319 $this->clearFolder();
320 foreach ($array as $gap => $values) {
321 $file_content = '';
322 if (is_array($values)) {
323 foreach ($values as $key => $value) {
324 $file_content .= $value . "\n";
325 }
326 $file_content = rtrim($file_content, "\n");
327 $file = fopen($this->buildFileName($gap), "w");
328 fwrite($file, $file_content);
329 fclose($file);
330 }
331 }
332 }
333
334 private function createArrayFromFile(): array
335 {
336 $files = glob($this->buildFolderName() . '*.txt');
337
338 if ($files === false) {
339 $files = array();
340 }
341
342 $answers = array();
343
344 foreach ($files as $file) {
345 $gap = str_replace('.txt', '', basename($file));
346 $answers[(int) $gap] = explode("\n", file_get_contents($file));
347 }
348 // Sort by gap keys, to ensure the numbers are in ascending order.
349 // Glob will report the keys in files order like 0, 1, 10, 11, 2,...
350 // json_encoding the array with keys in order 0,1,10,11,2,.. will create
351 // a json_object instead of a list when keys are numeric, sorted and start with 0
352 ksort($answers);
353 $this->setAnswers($answers);
354 return $answers;
355 }
356
357 private function clearFolder($let_folder_exists = true): void
358 {
359 ilFileUtils::delDir($this->buildFolderName(), $let_folder_exists);
360 }
361
362 private function assertDirExists(): void
363 {
364 $folder_name = $this->buildFolderName();
365 if (!ilFileUtils::makeDirParents($folder_name)) {
366 throw new ilException('Cannot create export directory');
367 }
368
369 if (
370 !is_dir($folder_name) ||
371 !is_readable($folder_name) ||
372 !is_writable($folder_name)
373 ) {
374 throw new ilException('Cannot create export directory');
375 }
376 }
377
378 public function loadFromDb($question_id): void
379 {
380 $result = $this->ilDB->queryF(
381 "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",
382 array("integer"),
383 array($question_id)
384 );
385 if ($result->numRows() == 1) {
386 $data = $this->ilDB->fetchAssoc($result);
387 $this->setId($question_id);
388 $this->setObjId($data["obj_fi"]);
389 $this->setNrOfTries($data['nr_of_tries']);
390 $this->setTitle((string) $data["title"]);
391 $this->setComment((string) $data["description"]);
392 $this->setOriginalId($data["original_id"]);
393 $this->setAuthor($data["author"]);
394 $this->setPoints($data["points"]);
395 $this->setIdenticalScoring($data["identical_scoring"]);
396 $this->setOwner($data["owner"]);
397 include_once("./Services/RTE/classes/class.ilRTE.php");
398 $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc((string) $data['question_text'], 1));
399 $this->setLongMenuTextValue(ilRTE::_replaceMediaObjectImageSrc((string) $data['long_menu_text'], 1));
400 $this->loadCorrectAnswerData($question_id);
401 $this->setMinAutoComplete($data["min_auto_complete"]);
402 if (isset($data['feedback_setting'])) {
403 $this->setSpecificFeedbackSetting((int) $data['feedback_setting']);
404 }
405
406 try {
407 $this->setLifecycle(ilAssQuestionLifecycle::getInstance($data['lifecycle']));
410 }
411
412 try {
413 $this->setAdditionalContentEditingMode($data['add_cont_edit_mode']);
415 }
416 }
417
418 $this->loadCorrectAnswerData($question_id);
419 $this->createArrayFromFile();
420 parent::loadFromDb($question_id);
421 }
422
423 private function loadCorrectAnswerData($question_id): void
424 {
425 $res = $this->db->queryF(
426 "SELECT * FROM {$this->getAnswerTableName()} WHERE question_fi = %s ORDER BY gap_number, position ASC",
427 array('integer'),
428 array($question_id)
429 );
430
431 $correct_answers = array();
432 while ($data = $this->ilDB->fetchAssoc($res)) {
433 $correct_answers[$data['gap_number']][0][$data['position']] = rtrim($data['answer_text']);
434 $correct_answers[$data['gap_number']][1] = $data['points'];
435 $correct_answers[$data['gap_number']][2] = $data['type'];
436 }
437 $this->setJsonStructure(json_encode($correct_answers));
439 }
440
441 public function getCorrectAnswersForQuestionSolution($question_id): array
442 {
443 $correct_answers = array();
444 $res = $this->db->queryF(
445 'SELECT gap_number, answer_text FROM ' . $this->getAnswerTableName() . ' WHERE question_fi = %s',
446 array('integer'),
447 array($question_id)
448 );
449 while ($data = $this->ilDB->fetchAssoc($res)) {
450 if (array_key_exists($data['gap_number'], $correct_answers)) {
451 $correct_answers[$data['gap_number']] .= ' ' . $this->lng->txt("or") . ' ';
452 $correct_answers[$data['gap_number']] .= rtrim($data['answer_text']);
453 } else {
454 $correct_answers[$data['gap_number']] = rtrim($data['answer_text']);
455 }
456 }
457 return $correct_answers;
458 }
459
460 private function getCorrectAnswersForGap($question_id, $gap_id): array
461 {
462 $correct_answers = array();
463 $res = $this->db->queryF(
464 'SELECT answer_text FROM ' . $this->getAnswerTableName() . ' WHERE question_fi = %s AND gap_number = %s',
465 array('integer', 'integer'),
466 array($question_id, $gap_id)
467 );
468 while ($data = $this->ilDB->fetchAssoc($res)) {
469 $correct_answers[] = rtrim($data['answer_text']);
470 }
471 return $correct_answers;
472 }
473
474 private function getPointsForGap($question_id, $gap_id): float
475 {
476 $points = 0.0;
477 $res = $this->db->queryF(
478 'SELECT points FROM ' . $this->getAnswerTableName() . ' WHERE question_fi = %s AND gap_number = %s GROUP BY gap_number, points',
479 array('integer', 'integer'),
480 array($question_id, $gap_id)
481 );
482 while ($data = $this->ilDB->fetchAssoc($res)) {
483 $points = (float) $data['points'];
484 }
485 return $points;
486 }
487
488
489 public function getAnswersObject()
490 {
491 return json_encode($this->createArrayFromFile());
492 }
493
494 public function getCorrectAnswersAsJson()
495 {
496 $this->loadCorrectAnswerData($this->getId());
497 return $this->getJsonStructure();
498 }
499
500 public function duplicate(bool $for_test = true, string $title = "", string $author = "", string $owner = "", $testObjId = null): int
501 {
502 if ($this->id <= 0) {
503 // The question has not been saved. It cannot be duplicated
504 return -1;
505 }
506
507 // duplicate the question in database
508 $this_id = $this->getId();
509 $thisObjId = $this->getObjId();
510
511 $clone = $this;
512 include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
514 $clone->id = -1;
515
516 if ((int) $testObjId > 0) {
517 $clone->setObjId($testObjId);
518 }
519
520 if ($title) {
521 $clone->setTitle($title);
522 }
523
524 if ($author) {
525 $clone->setAuthor($author);
526 }
527 if ($owner) {
528 $clone->setOwner($owner);
529 }
530
531 if ($for_test) {
532 $clone->saveToDb($original_id);
533 } else {
534 $clone->saveToDb();
535 }
536
537 $clone->copyPageOfQuestion($this_id);
538 $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
539 $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
540
541 return $clone->id;
542 }
543
544 public function copyObject($target_questionpool_id, $title = ""): int
545 {
546 if ($this->getId() <= 0) {
547 throw new RuntimeException('The question has not been saved. It cannot be duplicated');
548 }
549 // duplicate the question in database
550 $clone = $this;
551 include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
553 $clone->id = -1;
554 $source_questionpool_id = $this->getObjId();
555 $clone->setObjId($target_questionpool_id);
556 if ($title) {
557 $clone->setTitle($title);
558 }
559 $clone->saveToDb();
560
561 $clone->copyPageOfQuestion($original_id);
562 $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
563
564 $clone->onCopy($source_questionpool_id, $original_id, $clone->getObjId(), $clone->getId());
565
566 return $clone->id;
567 }
568
569 public function createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle = ""): int
570 {
571 if ($this->getId() <= 0) {
572 throw new RuntimeException('The question has not been saved. It cannot be duplicated');
573 }
574
575 include_once("./Modules/TestQuestionPool/classes/class.assQuestion.php");
576
577 $sourceQuestionId = $this->id;
578 $sourceParentId = $this->getObjId();
579
580 // duplicate the question in database
581 $clone = $this;
582 $clone->id = -1;
583
584 $clone->setObjId($targetParentId);
585
586 if ($targetQuestionTitle) {
587 $clone->setTitle($targetQuestionTitle);
588 }
589
590 $clone->saveToDb();
591 $clone->copyPageOfQuestion($sourceQuestionId);
592 $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
593
594 $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
595
596 return $clone->id;
597 }
598
599
611 public function calculateReachedPoints($active_id, $pass = null, $authorizedSolution = true, $returndetails = false)
612 {
613 if ($returndetails) {
614 throw new ilTestException('return details not implemented for ' . __METHOD__);
615 }
616
617 $found_values = array();
618 if (is_null($pass)) {
619 $pass = $this->getSolutionMaxPass($active_id);
620 }
621 $result = $this->getCurrentSolutionResultSet($active_id, $pass, $authorizedSolution);
622 while ($data = $this->ilDB->fetchAssoc($result)) {
623 $found_values[(int) $data['value1']] = $data['value2'];
624 }
625
626 return $this->calculateReachedPointsForSolution($found_values, $active_id);
627 }
628
629 protected function calculateReachedPointsForSolution($found_values, $active_id = 0)
630 {
631 if ($found_values == null) {
632 $found_values = [];
633 }
634 $points = 0.0;
635 $solution_values_text = array();
636 foreach ($found_values as $key => $answer) {
637 if ($answer != '') {
638 $correct_answers = $this->getCorrectAnswersForGap($this->id, $key);
639 if (in_array($answer, $correct_answers)) {
640 $points_gap = $this->getPointsForGap($this->id, $key);
641 if (!$this->getIdenticalScoring()) {
642 // check if the same solution text was already entered
643 if ((in_array($answer, $solution_values_text)) && ($points > 0)) {
644 $points_gap = 0;
645 }
646 }
647 $points += $points_gap;
648 array_push($solution_values_text, $answer);
649 }
650 }
651 }
652 return $points;
653 }
654
655 public function saveWorkingData(int $active_id, int $pass = null, bool $authorized = true): bool
656 {
657 if (is_null($pass)) {
658 include_once "./Modules/Test/classes/class.ilObjTest.php";
659 $pass = ilObjTest::_getPass($active_id);
660 }
661
662 $entered_values = 0;
663
664 $this->getProcessLocker()->executeUserSolutionUpdateLockOperation(function () use (&$entered_values, $active_id, $pass, $authorized) {
665 $this->removeCurrentSolution($active_id, $pass, $authorized);
666
667 foreach ($this->getSolutionSubmit() as $val1 => $val2) {
668 $value = ilUtil::stripSlashes(trim($val2), false);
669 if (strlen($value)) {
670 $this->saveCurrentSolution($active_id, $pass, $val1, $value, $authorized);
671 $entered_values++;
672 }
673 }
674 });
675
676 if ($entered_values) {
677 include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
679 assQuestion::logAction($this->lng->txtlng(
680 "assessment",
681 "log_user_entered_values",
683 ), $active_id, $this->getId());
684 }
685 } else {
686 include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
688 assQuestion::logAction($this->lng->txtlng(
689 "assessment",
690 "log_user_not_entered_values",
692 ), $active_id, $this->getId());
693 }
694 }
695 return true;
696 }
697
698 // fau: testNav - overridden function lookupForExistingSolutions (specific for long menu question: ignore unselected values)
703 public function lookupForExistingSolutions(int $activeId, int $pass): array
704 {
705 global $DIC;
706 $ilDB = $DIC['ilDB'];
707
708 $return = array(
709 'authorized' => false,
710 'intermediate' => false
711 );
712
713 $query = "
714 SELECT authorized, COUNT(*) cnt
715 FROM tst_solutions
716 WHERE active_fi = " . $ilDB->quote($activeId, 'integer') . "
717 AND question_fi = " . $ilDB->quote($this->getId(), 'integer') . "
718 AND pass = " . $ilDB->quote($pass, 'integer') . "
719 AND value2 <> '-1'
720 ";
721
722 if ($this->getStep() !== null) {
723 $query .= " AND step = " . $ilDB->quote((int) $this->getStep(), 'integer') . " ";
724 }
725
726 $query .= "
727 GROUP BY authorized
728 ";
729
730 $result = $ilDB->query($query);
731
732 while ($row = $ilDB->fetchAssoc($result)) {
733 if ($row['authorized']) {
734 $return['authorized'] = $row['cnt'] > 0;
735 } else {
736 $return['intermediate'] = $row['cnt'] > 0;
737 }
738 }
739 return $return;
740 }
741 // fau.
742
743
744 public function getSolutionSubmit(): array
745 {
746 $solutionSubmit = array();
747 $answer = ilArrayUtil::stripSlashesRecursive($_POST['answer']);
748
749 foreach ($answer as $key => $value) {
750 $solutionSubmit[$key] = $value;
751 }
752
753 return $solutionSubmit;
754 }
755
756 protected function savePreviewData(ilAssQuestionPreviewSession $previewSession): void
757 {
758 $answer = $_POST['answer'] ?? null;
759 if (is_array($answer)) {
760 $answer = array_map(function ($value) {
761 return trim($value);
762 }, $answer);
763 }
764 $previewSession->setParticipantsSolution($answer);
765 }
766
772 public function getQuestionType(): string
773 {
774 return "assLongMenu";
775 }
776
777 public function getAdditionalTableName(): string
778 {
779 return 'qpl_qst_lome';
780 }
781
786 public function getRTETextWithMediaObjects(): string
787 {
788 return parent::getRTETextWithMediaObjects() . $this->getLongMenuTextValue();
789 }
790
794 public function setExportDetailsXLS(ilAssExcelFormatHelper $worksheet, int $startrow, int $active_id, int $pass): int
795 {
796 parent::setExportDetailsXLS($worksheet, $startrow, $active_id, $pass);
797
798 $solution = $this->getSolutionValues($active_id, $pass);
799
800 $i = 1;
801 foreach ($this->getCorrectAnswers() as $gap_index => $gap) {
802 $worksheet->setCell($startrow + $i, 0, $this->lng->txt('assLongMenu') . " $i");
803 $worksheet->setBold($worksheet->getColumnCoord(0) . ($startrow + $i));
804 foreach ($solution as $solutionvalue) {
805 if ($gap_index == $solutionvalue["value1"]) {
806 switch ($gap[2]) {
808 $value = $solutionvalue["value2"];
809 if ($value == -1) {
810 $value = '';
811 }
812 $worksheet->setCell($startrow + $i, 2, $value);
813 break;
815 $worksheet->setCell($startrow + $i, 2, $solutionvalue["value2"]);
816 break;
817 }
818 }
819 }
820 $i++;
821 }
822
823 return $startrow + $i + 1;
824 }
825
834 public function getUserQuestionResult($active_id, $pass): ilUserQuestionResult
835 {
836 $result = new ilUserQuestionResult($this, $active_id, $pass);
837
838 $points = $this->calculateReachedPoints($active_id, $pass);
839 $max_points = $this->getMaximumPoints();
840
841 $result->setReachedPercentage(($points / $max_points) * 100);
842
843 return $result;
844 }
845
854 public function getAvailableAnswerOptions($index = null)
855 {
856 return $this->createArrayFromFile();
857 }
858
859 public function isShuffleAnswersEnabled(): bool
860 {
861 return false;
862 }
863
864 public function clearAnswerSpecificDataFromDb($question_id): void
865 {
866 $this->ilDB->manipulateF(
867 'DELETE FROM ' . $this->getAnswerTableName() . ' WHERE question_fi = %s',
868 array( 'integer' ),
869 array( $question_id )
870 );
871 }
872
873 public function delete(int $question_id): void
874 {
875 parent::delete($question_id);
876 $this->clearFolder(false);
877 }
878
883 {
884 $this->setLongMenuTextValue($migrator->migrateToLmContent($this->getLongMenuTextValue()));
885 }
886
890 public function toJSON(): string
891 {
892 include_once("./Services/RTE/classes/class.ilRTE.php");
893 $result = array();
894 $result['id'] = $this->getId();
895 $result['type'] = (string) $this->getQuestionType();
896 $result['title'] = $this->getTitleForHTMLOutput();
897 $replaced_quesiton_text = $this->getLongMenuTextValue();
898 $result['question'] = $this->formatSAQuestion($this->getQuestion());
899 $result['lmtext'] = $this->formatSAQuestion($replaced_quesiton_text);
900 $result['nr_of_tries'] = $this->getNrOfTries();
901 $result['shuffle'] = $this->getShuffle();
902 $result['feedback'] = array(
903 'onenotcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), false)),
904 'allcorrect' => $this->formatSAQuestion($this->feedbackOBJ->getGenericFeedbackTestPresentation($this->getId(), true))
905 );
906
907 $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $this->getId());
908 $result['answers'] = $this->getAnswers();
909 $result['correct_answers'] = $this->getCorrectAnswers();
910 $result['mobs'] = $mobs;
911 return json_encode($result);
912 }
913
914 public function getIdenticalScoring(): int
915 {
916 return ($this->identical_scoring) ? 1 : 0;
917 }
918
922 public function setIdenticalScoring($a_identical_scoring): void
923 {
924 $this->identical_scoring = ($a_identical_scoring) ? 1 : 0;
925 }
926}
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
lmMigrateQuestionTypeSpecificContent(ilAssSelfAssessmentMigrator $migrator)
loadCorrectAnswerData($question_id)
getMaximumPoints()
Returns the maximum points, a learner can reach answering the question.
duplicate(bool $for_test=true, string $title="", string $author="", string $owner="", $testObjId=null)
getRTETextWithMediaObjects()
Collects all text in the question which could contain media objects which were created with the Rich ...
createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle="")
checkQuestionCustomPart($form=null)
const MIN_LENGTH_AUTOCOMPLETE
copyObject($target_questionpool_id, $title="")
getAvailableAnswerOptions($index=null)
If index is null, the function returns an array with all anwser options Else it returns the specific ...
getUserQuestionResult($active_id, $pass)
Get the user solution for a question by active_id and the test pass.
calculateReachedPointsForSolution($found_values, $active_id=0)
saveAdditionalQuestionDataToDb()
Saves a record to the question types additional data table.
setIdenticalScoring($a_identical_scoring)
getCorrectAnswersForGap($question_id, $gap_id)
setLongMenuTextValue($long_menu_text="")
isComplete()
Returns true, if a question is complete for use.
const ANSWER_TYPE_TEXT_VAL
buildFileName($gap_id)
getQuestionType()
Returns the question type of the question.
const ANSWER_TYPE_SELECT_VAL
toJSON()
Returns a JSON representation of the question.
getPointsForGap($question_id, $gap_id)
clearFolder($let_folder_exists=true)
loadFromDb($question_id)
saveToDb(int $original_id=-1)
setMinAutoComplete($minAutoComplete)
clearAnswerSpecificDataFromDb($question_id)
setAnswerType($answerType)
__construct( $title="", $comment="", $author="", $owner=-1, $question="")
setSpecificFeedbackSetting($specificFeedbackSetting)
saveWorkingData(int $active_id, int $pass=null, bool $authorized=true)
Saves the learners input of the question to the database.
const HAS_SPECIFIC_FEEDBACK
setCorrectAnswers($correct_answers)
correctAnswerDoesNotExistInAnswerOptions($answers, $answer_options)
setExportDetailsXLS(ilAssExcelFormatHelper $worksheet, int $startrow, int $active_id, int $pass)
{}
getCorrectAnswersForQuestionSolution($question_id)
lookupForExistingSolutions(int $activeId, int $pass)
Lookup if an authorized or intermediate solution exists.
savePreviewData(ilAssQuestionPreviewSession $previewSession)
setJsonStructure($json_structure)
setAnswers($answers)
calculateReachedPoints($active_id, $pass=null, $authorizedSolution=true, $returndetails=false)
Returns the points, a learner has reached answering the question.
Abstract basic class which is to be extended by the concrete assessment question type classes.
float $points
The maximum available points for the question.
setOriginalId(?int $original_id)
string $question
The question text.
static logAction(string $logtext, int $active_id, int $question_id)
setId(int $id=-1)
setAdditionalContentEditingMode(?string $additionalContentEditingMode)
saveCurrentSolution(int $active_id, int $pass, $value1, $value2, bool $authorized=true, $tstamp=0)
getSolutionValues($active_id, $pass=null, bool $authorized=true)
Loads solutions of a given user from the database an returns it.
setQuestion(string $question="")
getCurrentSolutionResultSet(int $active_id, int $pass, bool $authorized=true)
static _getOriginalId(int $question_id)
saveQuestionDataToDb(int $original_id=-1)
setAuthor(string $author="")
setComment(string $comment="")
setObjId(int $obj_id=0)
getSolutionMaxPass(int $active_id)
setOwner(int $owner=-1)
setNrOfTries(int $a_nr_of_tries)
setLifecycle(ilAssQuestionLifecycle $lifecycle)
setTitle(string $title="")
removeCurrentSolution(int $active_id, int $pass, bool $authorized=true)
setPoints(float $points)
static stripSlashesRecursive($a_data, bool $a_strip_html=true, string $a_allow="")
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setCell($a_row, $a_col, $a_value, $datatype=null)
setBold(string $a_coords)
Set cell(s) to bold.
getColumnCoord(int $a_col)
Get column "name" from number.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static makeDirParents(string $a_dir)
Create a new directory and all parent directories.
static delDir(string $a_dir, bool $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
static getDataDir()
get data directory (outside webspace)
static _getMobsOfObject(string $a_type, int $a_id, int $a_usage_hist_nr=0, string $a_lang="-")
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test.
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...
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
global $DIC
Definition: feed.php:28
$mobs
Definition: imgupload.php:70
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...
$res
Definition: ltiservices.php:69
$index
Definition: metadata.php:145
$i
Definition: metadata.php:41
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
string $key
Consumer key/client ID value.
Definition: System.php:193
$query
$type