ILIAS  release_8 Revision v8.24
class.ilTestSequence.php
Go to the documentation of this file.
1<?php
2
29{
36
42 public $questions;
43
49 public $active_id;
50
56 public $pass;
57
64
68 protected $alreadyPresentedQuestions = array();
69
74
79
84
89
94
99
104
114 public function __construct($active_id, $pass, $randomtest)
115 {
116 $this->active_id = $active_id;
117 $this->pass = $pass;
118 $this->isRandomTest = $randomtest;
119 $this->sequencedata = array(
120 "sequence" => array(),
121 "postponed" => array(),
122 "hidden" => array()
123 );
124
125 $this->alreadyCheckedQuestions = array();
126 $this->newlyCheckedQuestion = null;
127
128 $this->optionalQuestions = array();
129 $this->answeringOptionalQuestionsConfirmed = false;
130
131 $this->considerHiddenQuestionsEnabled = false;
132 $this->considerOptionalQuestionsEnabled = true;
133 }
134
135 public function getActiveId(): int
136 {
137 return $this->active_id;
138 }
139
140 public function createNewSequence($max, $shuffle)
141 {
142 $newsequence = array();
143 if ($max > 0) {
144 for ($i = 1; $i <= $max; $i++) {
145 array_push($newsequence, $i);
146 }
147 if ($shuffle) {
148 $newsequence = $this->pcArrayShuffle($newsequence);
149 }
150 }
151 $this->sequencedata["sequence"] = $newsequence;
152 }
153
157 public function loadQuestions(ilTestQuestionSetConfig $testQuestionSetConfig = null, $taxonomyFilterSelection = array())
158 {
159 global $DIC;
160 $ilDB = $DIC['ilDB'];
161
162 $this->questions = array();
163
164 $result = $ilDB->queryF(
165 "SELECT tst_test_question.* FROM tst_test_question, qpl_questions, tst_active WHERE tst_active.active_id = %s AND tst_test_question.test_fi = tst_active.test_fi AND qpl_questions.question_id = tst_test_question.question_fi ORDER BY tst_test_question.sequence",
166 array('integer'),
167 array($this->active_id)
168 );
169
170 $index = 1;
171
172 // TODO bheyser: There might be "sequence" gaps which lead to issues with tst_sequence when deleting/adding questions before any participant starts the test
173 while ($data = $ilDB->fetchAssoc($result)) {
174 $this->questions[$index++] = $data["question_fi"];
175 }
176 }
177
181 public function loadFromDb()
182 {
183 $this->loadQuestionSequence();
184 $this->loadPresentedQuestions();
185 $this->loadCheckedQuestions();
186 $this->loadOptionalQuestions();
187 }
188
189 private function loadQuestionSequence()
190 {
191 global $DIC;
192 $ilDB = $DIC['ilDB'];
193 $result = $ilDB->queryF(
194 "SELECT * FROM tst_sequence WHERE active_fi = %s AND pass = %s",
195 array('integer','integer'),
196 array($this->active_id, $this->pass)
197 );
198 if ($result->numRows()) {
199 $row = $ilDB->fetchAssoc($result);
200 $this->sequencedata = array(
201 "sequence" => unserialize($row["sequence"]),
202 "postponed" => unserialize($row["postponed"]),
203 "hidden" => unserialize($row["hidden"])
204 );
205 if (!is_array($this->sequencedata["sequence"])) {
206 $this->sequencedata["sequence"] = array();
207 }
208 if (!is_array($this->sequencedata["postponed"])) {
209 $this->sequencedata["postponed"] = array();
210 }
211 if (!is_array($this->sequencedata["hidden"])) {
212 $this->sequencedata["hidden"] = array();
213 }
214
215 $this->setAnsweringOptionalQuestionsConfirmed((bool) $row['ans_opt_confirmed']);
216 }
217 }
218
219 protected function loadPresentedQuestions()
220 {
221 global $DIC; /* @var ILIAS\DI\Container $DIC */
222
223 $res = $DIC->database()->queryF(
224 "SELECT question_fi FROM tst_seq_qst_presented WHERE active_fi = %s AND pass = %s",
225 array('integer','integer'),
226 array($this->active_id, $this->pass)
227 );
228
229 while ($row = $DIC->database()->fetchAssoc($res)) {
230 $this->alreadyPresentedQuestions[ $row['question_fi'] ] = $row['question_fi'];
231 }
232 }
233
234 private function loadCheckedQuestions()
235 {
236 global $DIC;
237 $ilDB = $DIC['ilDB'];
238
239 $res = $ilDB->queryF(
240 "SELECT question_fi FROM tst_seq_qst_checked WHERE active_fi = %s AND pass = %s",
241 array('integer','integer'),
242 array($this->active_id, $this->pass)
243 );
244
245 while ($row = $ilDB->fetchAssoc($res)) {
246 $this->alreadyCheckedQuestions[ $row['question_fi'] ] = $row['question_fi'];
247 }
248 }
249
250 private function loadOptionalQuestions()
251 {
252 global $DIC;
253 $ilDB = $DIC['ilDB'];
254
255 $res = $ilDB->queryF(
256 "SELECT question_fi FROM tst_seq_qst_optional WHERE active_fi = %s AND pass = %s",
257 array('integer','integer'),
258 array($this->active_id, $this->pass)
259 );
260
261 while ($row = $ilDB->fetchAssoc($res)) {
262 $this->optionalQuestions[ $row['question_fi'] ] = $row['question_fi'];
263 }
264 }
265
271 public function saveToDb()
272 {
273 $this->saveQuestionSequence();
276 $this->saveOptionalQuestions();
277 }
278
279 private function saveQuestionSequence()
280 {
281 global $DIC;
282 $ilDB = $DIC['ilDB'];
283
284 $postponed = null;
285 if ((is_array($this->sequencedata["postponed"])) && (count($this->sequencedata["postponed"]))) {
286 $postponed = serialize($this->sequencedata["postponed"]);
287 }
288 $hidden = null;
289 if ((is_array($this->sequencedata["hidden"])) && (count($this->sequencedata["hidden"]))) {
290 $hidden = serialize($this->sequencedata["hidden"]);
291 }
292
293 $affectedRows = $ilDB->manipulateF(
294 "DELETE FROM tst_sequence WHERE active_fi = %s AND pass = %s",
295 array('integer','integer'),
296 array($this->active_id, $this->pass)
297 );
298
299 $affectedRows = $ilDB->insert("tst_sequence", array(
300 "active_fi" => array("integer", $this->active_id),
301 "pass" => array("integer", $this->pass),
302 "sequence" => array("clob", serialize($this->sequencedata["sequence"])),
303 "postponed" => array("text", $postponed),
304 "hidden" => array("text", $hidden),
305 "tstamp" => array("integer", time()),
306 'ans_opt_confirmed' => array('integer', (int) $this->isAnsweringOptionalQuestionsConfirmed())
307 ));
308 }
309
310 protected function saveNewlyPresentedQuestion()
311 {
312 if ($this->newlyPresentedQuestion) {
313 global $DIC; /* @var ILIAS\DI\Container $DIC */
314
315 $DIC->database()->replace('tst_seq_qst_presented', array(
316 'active_fi' => array('integer', $this->active_id),
317 'pass' => array('integer', $this->pass),
318 'question_fi' => array('integer', $this->newlyPresentedQuestion)
319 ), array());
320 }
321 }
322
326 private function saveNewlyCheckedQuestion()
327 {
328 if ((int) $this->newlyCheckedQuestion) {
329 global $DIC;
330 $ilDB = $DIC['ilDB'];
331
332 $ilDB->replace('tst_seq_qst_checked', array(
333 'active_fi' => array('integer', $this->active_id),
334 'pass' => array('integer', $this->pass),
335 'question_fi' => array('integer', (int) $this->newlyCheckedQuestion)
336 ), array());
337 }
338 }
339
343 private function saveOptionalQuestions()
344 {
345 global $DIC;
346 $ilDB = $DIC['ilDB'];
347
348 $NOT_IN_questions = $ilDB->in('question_fi', $this->optionalQuestions, true, 'integer');
349
350 $ilDB->queryF(
351 "DELETE FROM tst_seq_qst_optional WHERE active_fi = %s AND pass = %s AND $NOT_IN_questions",
352 array('integer', 'integer'),
353 array($this->active_id, $this->pass)
354 );
355
356 foreach ($this->optionalQuestions as $questionId) {
357 $ilDB->replace('tst_seq_qst_optional', array(
358 'active_fi' => array('integer', $this->active_id),
359 'pass' => array('integer', $this->pass),
360 'question_fi' => array('integer', (int) $questionId)
361 ), array());
362 }
363 }
364
365 public function postponeQuestion($question_id)
366 {
367 if (!$this->isPostponedQuestion($question_id)) {
368 array_push($this->sequencedata["postponed"], intval($question_id));
369 }
370 }
371
372 public function hideQuestion($question_id)
373 {
374 if (!$this->isHiddenQuestion($question_id)) {
375 array_push($this->sequencedata["hidden"], intval($question_id));
376 }
377 }
378
379 public function isPostponedQuestion($question_id): bool
380 {
381 if (!is_array($this->sequencedata["postponed"])) {
382 return false;
383 }
384 if (!in_array($question_id, $this->sequencedata["postponed"])) {
385 return false;
386 } else {
387 return true;
388 }
389 }
390
391 public function isHiddenQuestion($question_id): bool
392 {
393 if (!is_array($this->sequencedata["hidden"])) {
394 return false;
395 }
396 if (!in_array($question_id, $this->sequencedata["hidden"])) {
397 return false;
398 } else {
399 return true;
400 }
401 }
402
403 public function isPostponedSequence($sequence): bool
404 {
405 if (!array_key_exists($sequence, $this->questions)) {
406 return false;
407 }
408 if (!is_array($this->sequencedata["postponed"])) {
409 return false;
410 }
411 if (!in_array($this->questions[$sequence], $this->sequencedata["postponed"])) {
412 return false;
413 } else {
414 return true;
415 }
416 }
417
418 public function isHiddenSequence($sequence): bool
419 {
420 if (!array_key_exists($sequence, $this->questions)) {
421 return false;
422 }
423 if (!is_array($this->sequencedata["hidden"])) {
424 return false;
425 }
426 if (!in_array($this->questions[$sequence], $this->sequencedata["hidden"])) {
427 return false;
428 } else {
429 return true;
430 }
431 }
432
433 public function postponeSequence($sequence)
434 {
435 if (!$this->isPostponedSequence($sequence)) {
436 if (array_key_exists($sequence, $this->questions)) {
437 if (!is_array($this->sequencedata["postponed"])) {
438 $this->sequencedata["postponed"] = array();
439 }
440 array_push($this->sequencedata["postponed"], intval($this->questions[$sequence]));
441 }
442 }
443 }
444
445 public function hideSequence($sequence)
446 {
447 if (!$this->isHiddenSequence($sequence)) {
448 if (array_key_exists($sequence, $this->questions)) {
449 if (!is_array($this->sequencedata["hidden"])) {
450 $this->sequencedata["hidden"] = array();
451 }
452 array_push($this->sequencedata["hidden"], intval($this->questions[$sequence]));
453 }
454 }
455 }
456
457 public function setQuestionPresented($questionId)
458 {
459 $this->newlyPresentedQuestion = $questionId;
460 }
461
462 public function isQuestionPresented($questionId): bool
463 {
464 return (
465 $this->newlyPresentedQuestion == $questionId || in_array($questionId, $this->alreadyPresentedQuestions)
466 );
467 }
468
469 public function isNextQuestionPresented($questionId): bool
470 {
471 $nextQstId = $this->getQuestionForSequence(
472 $this->getNextSequence($this->getSequenceForQuestion($questionId))
473 );
474
475 if (!$nextQstId) {
476 return false;
477 }
478
479 if ($this->newlyPresentedQuestion == $nextQstId) {
480 return true;
481 }
482
483 if (in_array($nextQstId, $this->alreadyPresentedQuestions)) {
484 return true;
485 }
486
487 return false;
488 }
489
490 public function setQuestionChecked($questionId)
491 {
492 $this->newlyCheckedQuestion = $questionId;
493 }
494
495 public function isQuestionChecked($questionId): bool
496 {
497 return isset($this->alreadyCheckedQuestions[$questionId]);
498 }
499
500 public function getPositionOfSequence($sequence)
501 {
502 $correctedsequence = $this->getCorrectedSequence();
503 $sequencekey = array_search($sequence, $correctedsequence);
504 if ($sequencekey !== false) {
505 return $sequencekey + 1;
506 } else {
507 return "";
508 }
509 }
510
511 public function getUserQuestionCount(): int
512 {
513 return count($this->getCorrectedSequence());
514 }
515
516 public function getOrderedSequence(): array
517 {
518 $sequenceKeys = array();
519
520 foreach (array_keys($this->questions) as $sequenceKey) {
521 if ($this->isHiddenSequence($sequenceKey) && !$this->isConsiderHiddenQuestionsEnabled()) {
522 continue;
523 }
524
525 /* Doesn't seem to ever work, commenting out for future forensic
526 if ($this->isSequenceOptional($sequenceKey) && !$this->isConsiderOptionalQuestionsEnabled()) {
527 continue;
528 }
529 */
530
531 $sequenceKeys[] = $sequenceKey;
532 }
533
534 return $sequenceKeys;
535 }
536
537 public function getOrderedSequenceQuestions(): array
538 {
539 $questions = array();
540
541 foreach ($this->questions as $questionId) {
542 if ($this->isHiddenQuestion($questionId) && !$this->isConsiderHiddenQuestionsEnabled()) {
543 continue;
544 }
545
546 if ($this->isQuestionOptional($questionId) && !$this->isConsiderOptionalQuestionsEnabled()) {
547 continue;
548 }
549
550 $questions[] = $questionId;
551 }
552
553 return $questions;
554 }
555
556 public function getUserSequence()
557 {
558 return $this->getCorrectedSequence();
559 }
560
561 public function getUserSequenceQuestions(): array
562 {
563 $seq = $this->getCorrectedSequence();
564 $found = array();
565 foreach ($seq as $sequence) {
566 array_push($found, $this->getQuestionForSequence($sequence));
567 }
568 return $found;
569 }
570
571 private function ensureQuestionNotInSequence($sequence, $questionId)
572 {
573 $questionKey = array_search($questionId, $this->questions);
574
575 if ($questionKey === false) {
576 return $sequence;
577 }
578
579 $sequenceKey = array_search($questionKey, $sequence);
580
581 if ($sequenceKey === false) {
582 return $sequence;
583 }
584
585 unset($sequence[$sequenceKey]);
586
587 return $sequence;
588 }
589
590 protected function getCorrectedSequence()
591 {
592 $correctedsequence = $this->sequencedata["sequence"];
593 if (!$this->isConsiderHiddenQuestionsEnabled()) {
594 if (is_array($this->sequencedata["hidden"])) {
595 foreach ($this->sequencedata["hidden"] as $question_id) {
596 $correctedsequence = $this->ensureQuestionNotInSequence($correctedsequence, $question_id);
597 }
598 }
599 }
601 foreach ($this->optionalQuestions as $questionId) {
602 $correctedsequence = $this->ensureQuestionNotInSequence($correctedsequence, $questionId);
603 }
604 }
605 if (is_array($this->sequencedata["postponed"])) {
606 foreach ($this->sequencedata["postponed"] as $question_id) {
607 $foundsequence = array_search($question_id, $this->questions);
608 if ($foundsequence !== false) {
609 $sequencekey = array_search($foundsequence, $correctedsequence);
610 if ($sequencekey !== false) {
611 unset($correctedsequence[$sequencekey]);
612 array_push($correctedsequence, $foundsequence);
613 }
614 }
615 }
616 }
617 return array_values($correctedsequence);
618 }
619
620 public function getSequenceForQuestion($question_id)
621 {
622 return array_search($question_id, $this->questions);
623 }
624
625 public function getFirstSequence()
626 {
627 $correctedsequence = $this->getCorrectedSequence();
628 if (count($correctedsequence)) {
629 return reset($correctedsequence);
630 } else {
631 return false;
632 }
633 }
634
635 public function getLastSequence()
636 {
637 $correctedsequence = $this->getCorrectedSequence();
638 if (count($correctedsequence)) {
639 return end($correctedsequence);
640 } else {
641 return false;
642 }
643 }
644
645 public function getNextSequence($sequence)
646 {
647 $correctedsequence = $this->getCorrectedSequence();
648 $sequencekey = array_search($sequence, $correctedsequence);
649 if ($sequencekey !== false) {
650 $nextsequencekey = $sequencekey + 1;
651 if (array_key_exists($nextsequencekey, $correctedsequence)) {
652 return $correctedsequence[$nextsequencekey];
653 }
654 }
655 return false;
656 }
657
658 public function getPreviousSequence($sequence)
659 {
660 $correctedsequence = $this->getCorrectedSequence();
661 $sequencekey = array_search($sequence, $correctedsequence);
662 if ($sequencekey !== false) {
663 $prevsequencekey = $sequencekey - 1;
664 if (($prevsequencekey >= 0) && (array_key_exists($prevsequencekey, $correctedsequence))) {
665 return $correctedsequence[$prevsequencekey];
666 }
667 }
668 return false;
669 }
670
679 public function pcArrayShuffle($array): array
680 {
681 $keys = array_keys($array);
682 shuffle($keys);
683 $result = array();
684 foreach ($keys as $key) {
685 $result[$key] = $array[$key];
686 }
687 return $result;
688 }
689
690 public function getQuestionForSequence($sequence)
691 {
692 if ($sequence < 1) {
693 return false;
694 }
695 if (array_key_exists($sequence, $this->questions)) {
696 return $this->questions[$sequence];
697 } else {
698 return false;
699 }
700 }
701
702 public function getSequenceSummary($obligationsFilterEnabled = false): array
703 {
704 $correctedsequence = $this->getCorrectedSequence();
705 $result_array = array();
706 include_once "./Modules/Test/classes/class.ilObjTest.php";
707 $solved_questions = ilObjTest::_getSolvedQuestions($this->active_id);
708 $key = 1;
709 foreach ($correctedsequence as $sequence) {
710 $question = ilObjTest::_instanciateQuestion($this->getQuestionForSequence($sequence));
711 if (is_object($question)) {
712 $worked_through = $question->_isWorkedThrough($this->active_id, $question->getId(), $this->pass);
713 $solved = 0;
714 if (array_key_exists($question->getId(), $solved_questions)) {
715 $solved = $solved_questions[$question->getId()]["solved"];
716 }
717 $is_postponed = $this->isPostponedQuestion($question->getId());
718
719 $row = array(
720 "nr" => "$key",
721 "title" => $question->getTitle(),
722 "qid" => $question->getId(),
723 "presented" => $this->isQuestionPresented($question->getId()),
724 "visited" => $worked_through,
725 "solved" => (($solved) ? "1" : "0"),
726 "description" => $question->getComment(),
727 "points" => $question->getMaximumPoints(),
728 "worked_through" => $worked_through,
729 "postponed" => $is_postponed,
730 "sequence" => $sequence,
731 "obligatory" => ilObjTest::isQuestionObligatory($question->getId()),
732 'isAnswered' => $question->isAnswered($this->active_id, $this->pass)
733 );
734
735 if (!$obligationsFilterEnabled || $row['obligatory']) {
736 array_push($result_array, $row);
737 }
738
739 $key++;
740 }
741 }
742 return $result_array;
743 }
744
745 public function getPass(): int
746 {
747 return $this->pass;
748 }
749
750 public function setPass($pass)
751 {
752 $this->pass = $pass;
753 }
754
755 public function hasSequence(): bool
756 {
757 if ((is_array($this->sequencedata["sequence"])) && (count($this->sequencedata["sequence"]) > 0)) {
758 return true;
759 } else {
760 return false;
761 }
762 }
763
764 public function hasHiddenQuestions(): bool
765 {
766 if ((is_array($this->sequencedata["hidden"])) && (count($this->sequencedata["hidden"]) > 0)) {
767 return true;
768 } else {
769 return false;
770 }
771 }
772
773 public function clearHiddenQuestions()
774 {
775 $this->sequencedata["hidden"] = array();
776 }
777
778 private function hideCorrectAnsweredQuestions(ilObjTest $testOBJ, $activeId, $pass)
779 {
780 if ($activeId > 0) {
781 $result = $testOBJ->getTestResult($activeId, $pass, true);
782
783 foreach ($result as $sequence => $question) {
784 if (is_numeric($sequence)) {
785 if ($question['reached'] == $question['max']) {
786 $this->hideQuestion($question['qid']);
787 }
788 }
789 }
790
791 $this->saveToDb();
792 }
793 }
794
795 public function hasStarted(ilTestSession $testSession): bool
796 {
797 if ($testSession->getLastSequence() < 1) {
798 return false;
799 }
800
801 // WTF ?? heard about tests with only one question !?
802 if ($testSession->getLastSequence() == $this->getFirstSequence()) {
803 return false;
804 }
805
806 return true;
807 }
808
809 public function openQuestionExists(): bool
810 {
811 return $this->getFirstSequence() !== false;
812 }
813
814 public function getQuestionIds(): array
815 {
816 return array_values($this->questions);
817 }
818
819 public function questionExists($questionId): bool
820 {
821 return in_array($questionId, $this->questions);
822 }
823
824 public function setQuestionOptional($questionId)
825 {
826 $this->optionalQuestions[$questionId] = $questionId;
827 }
828
829 public function isQuestionOptional($questionId): bool
830 {
831 return isset($this->optionalQuestions[$questionId]);
832 }
833
834 public function hasOptionalQuestions(): bool
835 {
836 return (bool) count($this->optionalQuestions);
837 }
838
839 public function getOptionalQuestions(): array
840 {
842 }
843
844 public function clearOptionalQuestions()
845 {
846 $this->optionalQuestions = array();
847 }
848
850 {
851 $optionalSequenceKeys = array();
852
853 foreach ($this->sequencedata['sequence'] as $index => $sequenceKey) {
854 if ($this->isQuestionOptional($this->getQuestionForSequence($sequenceKey))) {
855 $optionalSequenceKeys[$index] = $sequenceKey;
856 unset($this->sequencedata['sequence'][$index]);
857 }
858 }
859
860 foreach ($optionalSequenceKeys as $index => $sequenceKey) {
861 $this->sequencedata['sequence'][$index] = $sequenceKey;
862 }
863 }
864
869 {
871 }
872
877 {
878 $this->answeringOptionalQuestionsConfirmed = $answeringOptionalQuestionsConfirmed;
879 }
880
884 public function isConsiderHiddenQuestionsEnabled(): bool
885 {
887 }
888
893 {
894 $this->considerHiddenQuestionsEnabled = $considerHiddenQuestionsEnabled;
895 }
896
901 {
903 }
904
909 {
910 $this->considerOptionalQuestionsEnabled = $considerOptionalQuestionsEnabled;
911 }
912}
static _instanciateQuestion($question_id)
Creates an instance of a question with a given question id.
& getTestResult( $active_id, $pass=null, bool $ordered_sequence=false, bool $considerHiddenQuestions=true, bool $considerOptionalQuestions=true)
Calculates the results of a test for a given user and returns an array with all test results.
static _getSolvedQuestions($active_id, $question_fi=null)
get solved questions
static isQuestionObligatory($question_id)
checks wether the question with given id is marked as obligatory or not
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
questionExists($questionId)
isHiddenQuestion($question_id)
setAnsweringOptionalQuestionsConfirmed($answeringOptionalQuestionsConfirmed)
isPostponedSequence($sequence)
pcArrayShuffle($array)
Shuffles the values of a given array.
getQuestionForSequence($sequence)
setQuestionPresented($questionId)
hideQuestion($question_id)
getSequenceSummary($obligationsFilterEnabled=false)
setQuestionChecked($questionId)
isQuestionChecked($questionId)
postponeQuestion($question_id)
loadQuestions(ilTestQuestionSetConfig $testQuestionSetConfig=null, $taxonomyFilterSelection=array())
Loads the question mapping.
isQuestionPresented($questionId)
saveToDb()
Saves the sequence data for a given pass to the database.
saveNewlyCheckedQuestion()
@global ilDBInterface $ilDB
isQuestionOptional($questionId)
saveOptionalQuestions()
@global ilDBInterface $ilDB
hasStarted(ilTestSession $testSession)
__construct($active_id, $pass, $randomtest)
ilTestSequence constructor
hideCorrectAnsweredQuestions(ilObjTest $testOBJ, $activeId, $pass)
getPositionOfSequence($sequence)
createNewSequence($max, $shuffle)
getPreviousSequence($sequence)
setQuestionOptional($questionId)
setConsiderOptionalQuestionsEnabled($considerOptionalQuestionsEnabled)
loadFromDb()
Loads the sequence data for a given active id.
isNextQuestionPresented($questionId)
getSequenceForQuestion($question_id)
ensureQuestionNotInSequence($sequence, $questionId)
isPostponedQuestion($question_id)
setConsiderHiddenQuestionsEnabled($considerHiddenQuestionsEnabled)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
global $DIC
Definition: feed.php:28
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
$keys
Definition: metadata.php:204
string $key
Consumer key/client ID value.
Definition: System.php:193