ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5f
class.ilTestSequenceDynamicQuestionSet.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
4 require_once 'Modules/Test/interfaces/interface.ilTestSequenceSummaryProvider.php';
5 
17 {
21  private $db = null;
22 
26  private $questionSet = null;
27 
31  private $activeId = null;
32 
37 
41  private $questionTracking = array();
42 
47 
52 
56  private $postponedQuestions = array();
57 
62 
67 
72 
77 
81  private $correctAnsweredQuestions = array();
82 
86  private $wrongAnsweredQuestions = array();
87 
92 
97 
102 
109  {
110  $this->db = $db;
111  $this->questionSet = $questionSet;
112  $this->activeId = $activeId;
113 
114  $this->newlyTrackedQuestion = null;
115  $this->newlyTrackedQuestionsStatus = null;
116 
117  $this->newlyPostponedQuestion = null;
118  $this->newlyPostponedQuestionsCount = null;
119 
120  $this->newlyAnsweredQuestion = null;
121  $this->newlyAnsweredQuestionsAnswerStatus = null;
122 
123  $this->alreadyCheckedQuestions = array();
124  $this->newlyCheckedQuestion = null;
125 
126  $this->preventCheckedQuestionsFromComingUpEnabled = false;
127 
128  $this->currentQuestionId = null;
129  }
130 
131  public function getActiveId()
132  {
133  return $this->activeId;
134  }
135 
137  {
138  $this->preventCheckedQuestionsFromComingUpEnabled = $preventCheckedQuestionsFromComingUpEnabled;
139  }
140 
142  {
144  }
145 
149  public function getCurrentQuestionId()
150  {
152  }
153 
158  {
159  $this->currentQuestionId = $currentQuestionId;
160  }
161 
162  public function loadFromDb()
163  {
164  $this->loadQuestionTracking();
165  $this->loadAnswerStatus();
166  $this->loadPostponedQuestions();
167  $this->loadCheckedQuestions();
168  }
169 
170  private function loadQuestionTracking()
171  {
172  $query = "
173  SELECT question_fi, status
174  FROM tst_seq_qst_tracking
175  WHERE active_fi = %s
176  AND pass = %s
177  ORDER BY orderindex ASC
178  ";
179 
180  $res = $this->db->queryF($query, array('integer','integer'), array($this->activeId, 0));
181 
182  $this->questionTracking = array();
183 
184  while( $row = $this->db->fetchAssoc($res) )
185  {
186  $this->questionTracking[] = array(
187  'qid' => $row['question_fi'],
188  'status' => $row['status']
189  );
190  }
191  }
192 
193  private function loadAnswerStatus()
194  {
195  $query = "
196  SELECT question_fi, correctness
197  FROM tst_seq_qst_answstatus
198  WHERE active_fi = %s
199  AND pass = %s
200  ";
201 
202  $res = $this->db->queryF($query, array('integer','integer'), array($this->activeId, 0));
203 
204  $this->correctAnsweredQuestions = array();
205  $this->wrongAnsweredQuestions = array();
206 
207  while( $row = $this->db->fetchAssoc($res) )
208  {
209  if( $row['correctness'] )
210  {
211  $this->correctAnsweredQuestions[ $row['question_fi'] ] = $row['question_fi'];
212  }
213  else
214  {
215  $this->wrongAnsweredQuestions[ $row['question_fi'] ] = $row['question_fi'];
216  }
217  }
218  }
219 
220  private function loadPostponedQuestions()
221  {
222  $query = "
223  SELECT question_fi, cnt
224  FROM tst_seq_qst_postponed
225  WHERE active_fi = %s
226  AND pass = %s
227  ";
228 
229  $res = $this->db->queryF($query, array('integer','integer'), array($this->activeId, 0));
230 
231  $this->postponedQuestions = array();
232 
233  while( $row = $this->db->fetchAssoc($res) )
234  {
235  $this->postponedQuestions[ $row['question_fi'] ] = $row['cnt'];
236  }
237  }
238 
239  private function loadCheckedQuestions()
240  {
241  $res = $this->db->queryF("SELECT question_fi FROM tst_seq_qst_checked WHERE active_fi = %s AND pass = %s",
242  array('integer','integer'), array($this->getActiveId(), 0)
243  );
244 
245  while( $row = $this->db->fetchAssoc($res) )
246  {
247  $this->alreadyCheckedQuestions[ $row['question_fi'] ] = $row['question_fi'];
248  }
249  }
250 
251  public function saveToDb()
252  {
253  $this->db->manipulateF(
254  "DELETE FROM tst_sequence WHERE active_fi = %s AND pass = %s",
255  array('integer','integer'), array($this->getActiveId(), 0)
256  );
257 
258  $this->db->insert('tst_sequence', array(
259  'active_fi' => array('integer', $this->getActiveId()),
260  'pass' => array('integer', 0),
261  'sequence' => array('clob', null),
262  'postponed' => array('text', null),
263  'hidden' => array('text', null),
264  'tstamp' => array('integer', time())
265  ));
266 
267  $this->saveNewlyTrackedQuestion();
271  $this->saveNewlyCheckedQuestion();
273  }
274 
275  private function saveNewlyTrackedQuestion()
276  {
277  if( (int)$this->newlyTrackedQuestion )
278  {
279  $newOrderIndex = $this->getNewOrderIndexForQuestionTracking();
280 
281  $this->db->replace('tst_seq_qst_tracking',
282  array(
283  'active_fi' => array('integer', (int)$this->getActiveId()),
284  'pass' => array('integer', 0),
285  'question_fi' => array('integer', (int)$this->newlyTrackedQuestion)
286  ),
287  array(
288  'status' => array('text', $this->newlyTrackedQuestionsStatus),
289  'orderindex' => array('integer', $newOrderIndex)
290  )
291  );
292  }
293  }
294 
296  {
297  $query = "
298  SELECT (MAX(orderindex) + 1) new_order_index
299  FROM tst_seq_qst_tracking
300  WHERE active_fi = %s
301  AND pass = %s
302  ";
303 
304  $res = $this->db->queryF($query, array('integer','integer'), array($this->getActiveId(), 0));
305 
306  $row = $this->db->fetchAssoc($res);
307 
308  if( $row['new_order_index'] )
309  {
310  return $row['new_order_index'];
311  }
312 
313  return 1;
314  }
315 
317  {
318  if( (int)$this->newlyAnsweredQuestion )
319  {
320  $this->db->replace('tst_seq_qst_answstatus',
321  array(
322  'active_fi' => array('integer', (int)$this->getActiveId()),
323  'pass' => array('integer', 0),
324  'question_fi' => array('integer', (int)$this->newlyAnsweredQuestion)
325  ),
326  array(
327  'correctness' => array('integer', (int)$this->newlyAnsweredQuestionsAnswerStatus)
328  )
329  );
330  }
331  }
332 
333  private function saveNewlyPostponedQuestion()
334  {
335  if( (int)$this->newlyPostponedQuestion )
336  {
337  $this->db->replace('tst_seq_qst_postponed',
338  array(
339  'active_fi' => array('integer', (int)$this->getActiveId()),
340  'pass' => array('integer', 0),
341  'question_fi' => array('integer', (int)$this->newlyPostponedQuestion)
342  ),
343  array(
344  'cnt' => array('integer', (int)$this->newlyPostponedQuestionsCount)
345  )
346  );
347  }
348  }
349 
351  {
352  $INquestions = $this->db->in('question_fi', array_keys($this->postponedQuestions), true, 'integer');
353 
354  $query = "
355  DELETE FROM tst_seq_qst_postponed
356  WHERE active_fi = %s
357  AND pass = %s
358  AND $INquestions
359  ";
360 
361  $this->db->manipulateF($query, array('integer','integer'), array($this->getActiveId(), 0));
362  }
363 
364  private function saveNewlyCheckedQuestion()
365  {
366  if( (int)$this->newlyCheckedQuestion )
367  {
368  $this->db->replace('tst_seq_qst_checked', array(
369  'active_fi' => array('integer', (int)$this->getActiveId()),
370  'pass' => array('integer', 0),
371  'question_fi' => array('integer', (int)$this->newlyCheckedQuestion)
372  ), array());
373  }
374  }
375 
377  {
378  $NOT_IN_checkedQuestions = $this->db->in('question_fi', $this->alreadyCheckedQuestions, true, 'integer');
379 
380  // BEGIN: FIX IN QUERY
381  if($NOT_IN_checkedQuestions == ' 1=2 ') $NOT_IN_checkedQuestions = ' 1=1 ';
382  // END: FIX IN QUERY
383 
384  $query = "
385  DELETE FROM tst_seq_qst_checked
386  WHERE active_fi = %s
387  AND pass = %s
388  AND $NOT_IN_checkedQuestions
389  ";
390 
391  $this->db->manipulateF($query, array('integer', 'integer'), array((int)$this->getActiveId(), 0));
392  }
393 
394  public function loadQuestions(ilObjTestDynamicQuestionSetConfig $dynamicQuestionSetConfig, ilTestDynamicQuestionSetFilterSelection $filterSelection)
395  {
396  $this->questionSet->load($dynamicQuestionSetConfig, $filterSelection);
397 
398 // echo "<table><tr>";
399 // echo "<td width='200'><pre>".print_r($this->questionSet->getActualQuestionSequence(), 1)."</pre></td>";
400 // echo "<td width='200'><pre>".print_r($this->correctAnsweredQuestions, 1)."</pre></td>";
401 // echo "<td width='200'><pre>".print_r($this->wrongAnsweredQuestions, 1)."</pre></td>";
402 // echo "</tr></table>";
403  }
404 
405  // -----------------------------------------------------------------------------------------------------------------
406 
407  public function cleanupQuestions(ilTestSessionDynamicQuestionSet $testSession)
408  {
409  switch( true )
410  {
411  case !$this->questionSet->questionExists($testSession->getCurrentQuestionId()):
412  case !$this->isFilteredQuestion($testSession->getCurrentQuestionId()):
413 
414  $testSession->setCurrentQuestionId(null);
415  }
416 
417  foreach($this->postponedQuestions as $questionId)
418  {
419  if( !$this->questionSet->questionExists($questionId) )
420  {
421  unset($this->postponedQuestions[$questionId]);
422  }
423  }
424 
425  foreach($this->wrongAnsweredQuestions as $questionId)
426  {
427  if( !$this->questionSet->questionExists($questionId) )
428  {
429  unset($this->wrongAnsweredQuestions[$questionId]);
430  }
431  }
432 
433  foreach($this->correctAnsweredQuestions as $questionId)
434  {
435  if( !$this->questionSet->questionExists($questionId) )
436  {
437  unset($this->correctAnsweredQuestions[$questionId]);
438  }
439  }
440  }
441 
442  // -----------------------------------------------------------------------------------------------------------------
443 
444  public function getUpcomingQuestionId()
445  {
446  if( $questionId = $this->fetchUpcomingQuestionId(true, true) )
447  return $questionId;
448 
449  if( $questionId = $this->fetchUpcomingQuestionId(false, true) )
450  return $questionId;
451 
452  if( $questionId = $this->fetchUpcomingQuestionId(true, false) )
453  return $questionId;
454 
455  if( $questionId = $this->fetchUpcomingQuestionId(false, false) )
456  return $questionId;
457 
458  return null;
459  }
460 
461  private function fetchUpcomingQuestionId($excludePostponedQuestions, $forceNonAnsweredQuestion)
462  {
463  foreach($this->questionSet->getActualQuestionSequence() as $level => $questions)
464  {
465  $postponedQuestions = array();
466 
467  foreach($questions as $pos => $qId)
468  {
469  if( isset($this->correctAnsweredQuestions[$qId]) )
470  {
471  continue;
472  }
473 
475  {
476  continue;
477  }
478 
479  if( $forceNonAnsweredQuestion && isset($this->wrongAnsweredQuestions[$qId]) )
480  {
481  continue;
482  }
483 
484  if( isset($this->postponedQuestions[$qId]) )
485  {
486  $postponedQuestions[$qId] = $this->postponedQuestions[$qId];
487  continue;
488  }
489 
490  return $qId;
491  }
492 
493  if( !$excludePostponedQuestions && count($postponedQuestions) )
494  {
496  }
497  }
498 
499  return null;
500  }
501 
502  public function isAnsweredQuestion($questionId)
503  {
504  return (
505  isset($this->correctAnsweredQuestions[$questionId])
506  || isset($this->wrongAnsweredQuestions[$questionId])
507  );
508  }
509 
510  public function isPostponedQuestion($questionId)
511  {
512  return isset($this->postponedQuestions[$questionId]);
513  }
514 
515  public function isFilteredQuestion($questionId)
516  {
517  foreach($this->questionSet->getActualQuestionSequence() as $level => $questions)
518  {
519  if( in_array($questionId, $questions) )
520  {
521  return true;
522  }
523  }
524 
525  return false;
526  }
527 
528  public function trackedQuestionExists()
529  {
530  return (bool)count($this->questionTracking);
531  }
532 
534  {
535  $questionList = array();
536 
537  if( $currentQuestionId )
538  {
539  $questionList[$currentQuestionId] = $this->questionSet->getQuestionData($currentQuestionId);
540  }
541 
542  foreach( array_reverse($this->questionTracking) as $trackedQuestion)
543  {
544  if( !isset($questionList[ $trackedQuestion['qid'] ]) )
545  {
546  $questionList[ $trackedQuestion['qid'] ] = $this->questionSet->getQuestionData($trackedQuestion['qid']);
547  }
548  }
549 
550  return $questionList;
551  }
552 
553  public function resetTrackedQuestionList()
554  {
555  $this->questionTracking = array();
556  }
557 
558  public function openQuestionExists()
559  {
560  return count($this->getOpenQuestions()) > 0;
561  }
562 
563  public function getOpenQuestions()
564  {
565  $completeQuestionIds = array_keys( $this->questionSet->getAllQuestionsData() );
566 
567  $openQuestions = array_diff($completeQuestionIds, $this->correctAnsweredQuestions);
568 
569  return $openQuestions;
570  }
571 
572  public function getTrackedQuestionCount()
573  {
574  $uniqueQuestions = array();
575 
576  foreach($this->questionTracking as $trackedQuestion)
577  {
578  $uniqueQuestions[$trackedQuestion['qid']] = $trackedQuestion['qid'];
579  }
580 
581  return count($uniqueQuestions);
582  }
583 
584  public function getCurrentPositionIndex($questionId)
585  {
586  $i = 0;
587 
588  foreach($this->questionSet->getActualQuestionSequence() as $level => $questions)
589  {
590  foreach($questions as $pos => $qId)
591  {
592  $i++;
593 
594  if($qId == $questionId)
595  {
596  return $i;
597  }
598  }
599  }
600 
601  return null;
602  }
603 
604  public function getLastPositionIndex()
605  {
606  $count = 0;
607 
608  foreach($this->questionSet->getActualQuestionSequence() as $level => $questions)
609  {
610  $count += count($questions);
611  }
612 
613  return $count;
614  }
615 
616  // -----------------------------------------------------------------------------------------------------------------
617 
618  public function setQuestionUnchecked($questionId)
619  {
620  unset($this->alreadyCheckedQuestions[$questionId]);
621  }
622 
623  public function setQuestionChecked($questionId)
624  {
625  $this->newlyCheckedQuestion = $questionId;
626  $this->alreadyCheckedQuestions[$questionId] = $questionId;
627  }
628 
629  public function isQuestionChecked($questionId)
630  {
631  return isset($this->alreadyCheckedQuestions[$questionId]);
632  }
633 
634  public function setQuestionPostponed($questionId)
635  {
636  $this->trackQuestion($questionId, 'postponed');
637 
638  if( !isset($this->postponedQuestions[$questionId]) )
639  {
640  $this->postponedQuestions[$questionId] = 0;
641  }
642 
643  $this->postponedQuestions[$questionId]++;
644 
645  $this->newlyPostponedQuestion = $questionId;
646  $this->newlyPostponedQuestionsCount = $this->postponedQuestions[$questionId];
647  }
648 
649  public function unsetQuestionPostponed($questionId)
650  {
651  if( isset($this->postponedQuestions[$questionId]) )
652  unset($this->postponedQuestions[$questionId]);
653  }
654 
655  public function setQuestionAnsweredCorrect($questionId)
656  {
657  $this->trackQuestion($questionId, 'correct');
658 
659  $this->correctAnsweredQuestions[$questionId] = $questionId;
660 
661  if( isset($this->wrongAnsweredQuestions[$questionId]) )
662  unset($this->wrongAnsweredQuestions[$questionId]);
663 
664  $this->newlyAnsweredQuestion = $questionId;
665  $this->newlyAnsweredQuestionsAnswerStatus = true;
666  }
667 
668  public function setQuestionAnsweredWrong($questionId)
669  {
670  $this->trackQuestion($questionId, 'wrong');
671 
672  $this->wrongAnsweredQuestions[$questionId] = $questionId;
673 
674  if( isset($this->correctAnsweredQuestions[$questionId]) )
675  unset($this->correctAnsweredQuestions[$questionId]);
676 
677  $this->newlyAnsweredQuestion = $questionId;
678  $this->newlyAnsweredQuestionsAnswerStatus = false;
679  }
680 
681  private function trackQuestion($questionId, $answerStatus)
682  {
683  $this->questionTracking[] = array(
684  'qid' => $questionId, 'status' => $answerStatus
685  );
686 
687  $this->newlyTrackedQuestion = $questionId;
688  $this->newlyTrackedQuestionsStatus = $answerStatus;
689  }
690 
691  // -----------------------------------------------------------------------------------------------------------------
692 
693  public function hasStarted()
694  {
695  return $this->trackedQuestionExists();
696  }
697 
698  // -----------------------------------------------------------------------------------------------------------------
699 
700  public function getCompleteQuestionsData()
701  {
702  return $this->questionSet->getCompleteQuestionList()->getQuestionDataArray();
703  }
704 
705  public function getFilteredQuestionsData()
706  {
707  return $this->questionSet->getFilteredQuestionList()->getQuestionDataArray();
708  }
709 
710  // -----------------------------------------------------------------------------------------------------------------
711 
712  public function getUserSequenceQuestions()
713  {
714  //return array_keys( $this->getTrackedQuestionList() );
715 
716  $questionSequence = array();
717 
718  foreach( $this->questionSet->getActualQuestionSequence() as $level => $questions )
719  {
720  $questionSequence = array_merge($questionSequence, $questions);
721  }
722 
723  return $questionSequence;
724  }
725 
731  {
732  $minPostponeCount = null;
733  $minPostponeItem = null;
734 
735  foreach(array_reverse($postponedQuestions, true) as $qId => $postponeCount)
736  {
737  if($minPostponeCount === null || $postponeCount <= $minPostponeCount)
738  {
739  $minPostponeCount = $postponeCount;
740  $minPostponeItem = $qId;
741  }
742  }
743  return $minPostponeItem;
744  }
745 
746  public function getPass()
747  {
748  return 0;
749  }
750 
751  // -----------------------------------------------------------------------------------------------------------------
752 
754  {
755  $maxPostponeCount = max($postponedQuestions);
756 
757  $orderedSequence = array();
758  $postponedCountDomain = array_flip($postponedQuestions);
759 
760  for($i = 1; $i <= $maxPostponeCount; $i++)
761  {
762  if(!isset($postponedCountDomain[$i]))
763  {
764  continue;
765  }
766 
767  foreach($postponedQuestions as $qId => $postponeCount)
768  {
769  if($postponeCount == $i)
770  {
771  $orderedSequence[] = $qId;
772  }
773  }
774  }
775 
776  return $orderedSequence;
777  }
778 
779  private function fetchQuestionSequence($nonPostponedQuestions, $nonAnsweredQuestions, $excludeQuestionId)
780  {
781  $questionSequence = array();
782 
783  foreach($this->questionSet->getActualQuestionSequence() as $level => $questions)
784  {
785  $postponedQuestions = array();
786 
787  foreach($questions as $pos => $qId)
788  {
789  if( $qId == $excludeQuestionId )
790  {
791  continue;
792  }
793 
794  if( isset($this->correctAnsweredQuestions[$qId]) )
795  {
796  continue;
797  }
798 
799  if( $nonAnsweredQuestions && isset($this->wrongAnsweredQuestions[$qId]) )
800  {
801  continue;
802  }
803  elseif( !$nonAnsweredQuestions && !isset($this->wrongAnsweredQuestions[$qId]) )
804  {
805  continue;
806  }
807 
808  if( !$nonPostponedQuestions && isset($this->postponedQuestions[$qId]) )
809  {
810  $postponedQuestions[$qId] = $this->postponedQuestions[$qId];
811  continue;
812  }
813  elseif($nonPostponedQuestions && !isset($this->postponedQuestions[$qId]))
814  {
815  $questionSequence[] = $qId;
816  }
817  }
818 
819  if( !$nonPostponedQuestions && count($postponedQuestions) )
820  {
821  $questionSequence = array_merge(
822  $questionSequence, $this->orderQuestionsByPostponeCount($postponedQuestions)
823  );
824  }
825  }
826 
827  return $questionSequence;
828  }
829 
830  private function fetchTrackedCorrectAnsweredSequence($excludeQuestionId)
831  {
832  $questionSequence = array();
833 
834  foreach($this->questionTracking as $key => $question)
835  {
836  $qId = $question['qid'];
837 
838  if($qId == $excludeQuestionId)
839  {
840  continue;
841  }
842 
843  if( !isset($this->correctAnsweredQuestions[$qId]) )
844  {
845  continue;
846  }
847 
848  $questionSequence[] = $qId;
849  }
850 
851  return $questionSequence;
852  }
853 
854  private function getOrderedSequence()
855  {
857  $this->getCurrentQuestionId()
858  );
859 
860  $nonAnsweredQuestions = $this->fetchQuestionSequence(
861  true, true, $this->getCurrentQuestionId()
862  );
863 
864  $postponedNonAnsweredQuestions = $this->fetchQuestionSequence(
865  false, true, $this->getCurrentQuestionId()
866  );
867 
869  true, false, $this->getCurrentQuestionId()
870  );
871 
872  $postponedWrongAnsweredQuestions = $this->fetchQuestionSequence(
873  false, false, $this->getCurrentQuestionId()
874  );
875 
876  $questionOrder = array_merge(
878  $nonAnsweredQuestions, $postponedNonAnsweredQuestions,
879  $wrongAnsweredQuestions, $postponedWrongAnsweredQuestions
880  );
881 
882  return $questionOrder;
883  }
884 
885  public function getSequenceSummary($obligationsFilterEnabled = false)
886  {
887  $questionOrder = $this->getOrderedSequence();
888 
889  $solved_questions = ilObjTest::_getSolvedQuestions($this->getActiveId());
890 
891  $key = 1;
892 
893  foreach ($questionOrder as $qId)
894  {
895  $question =& ilObjTest::_instanciateQuestion($qId);
896  if(is_object($question))
897  {
898  $worked_through = $question->_isWorkedThrough($this->getActiveId(), $question->getId(), $this->getPass());
899  $solved = 0;
900  if(array_key_exists($question->getId(), $solved_questions))
901  {
902  $solved = $solved_questions[$question->getId()]["solved"];
903  }
904 
905  // do not show postponing, since this happens implicit on dircarding solutions (CTM only)
906  //$is_postponed = $this->isPostponedQuestion($question->getId());
907 
908  $row = array("nr" => "$key", "title" => $question->getTitle(), "qid" => $question->getId(), "visited" => $worked_through, "solved" => (($solved) ? "1" : "0"), "description" => $question->getComment(), "points" => $question->getMaximumPoints(), "worked_through" => $worked_through, "postponed" => $is_postponed, "sequence" => $qId, "obligatory" => ilObjTest::isQuestionObligatory($question->getId()), 'isAnswered' => $question->isAnswered($this->getActiveId(), $this->getPass()));
909 
910  if(!$obligationsFilterEnabled || $row['obligatory'])
911  {
912  $summary[] = $row;
913  }
914 
915  $key++;
916  }
917  }
918 
919  return $summary;
920  }
921 
923  {
924  $filteredQuestions = $this->questionSet->getFilteredQuestionList()->getQuestionDataArray();
925 
926  foreach($filteredQuestions as $filteredQuestion)
927  {
928  if( $this->isQuestionChecked($filteredQuestion['question_id']) )
929  {
930  return true;
931  }
932  }
933 
934  return false;
935  }
936 
938  {
939  $filteredQuestions = $this->questionSet->getFilteredQuestionList()->getQuestionDataArray();
940 
941  foreach($filteredQuestions as $filteredQuestion)
942  {
943  if( $this->isQuestionChecked($filteredQuestion['question_id']) )
944  {
945  $this->setQuestionUnchecked($filteredQuestion['question_id']);
946  }
947  }
948  }
949 }
950 
& _instanciateQuestion($question_id)
Creates an instance of a question with a given question id.
_getSolvedQuestions($active_id, $question_fi=null)
get solved questions
setPreventCheckedQuestionsFromComingUpEnabled($preventCheckedQuestionsFromComingUpEnabled)
cleanupQuestions(ilTestSessionDynamicQuestionSet $testSession)
loadQuestions(ilObjTestDynamicQuestionSetConfig $dynamicQuestionSetConfig, ilTestDynamicQuestionSetFilterSelection $filterSelection)
static isQuestionObligatory($question_id)
checks wether the question with given id is marked as obligatory or not
Database Wrapper.
Definition: class.ilDB.php:28
__construct(ilDB $db, ilTestDynamicQuestionSet $questionSet, $activeId)
Constructor.
fetchUpcomingQuestionId($excludePostponedQuestions, $forceNonAnsweredQuestion)
fetchQuestionSequence($nonPostponedQuestions, $nonAnsweredQuestions, $excludeQuestionId)