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