19 declare(strict_types=1);
68 protected int $active_id,
72 $this->sequencedata = [
81 return $this->active_id;
88 for ($i = 1; $i <= $max; $i++) {
95 $this->sequencedata[
"sequence"] = $newsequence;
103 $this->questions = [];
105 $result = $this->db->queryF(
106 "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",
108 array($this->active_id)
114 while (
$data = $this->db->fetchAssoc($result)) {
115 $this->questions[$index++] =
$data[
"question_fi"];
132 $result = $this->db->queryF(
133 "SELECT * FROM tst_sequence WHERE active_fi = %s AND pass = %s",
134 array(
'integer',
'integer'),
135 array($this->active_id, $this->pass)
137 if ($result->numRows()) {
138 $row = $this->db->fetchAssoc($result);
139 $this->sequencedata = [
140 "sequence" => unserialize($row[
"sequence"] ??
'', [
'allowed_classes' =>
false]),
141 "postponed" => unserialize($row[
"postponed"] ??
'', [
'allowed_classes' =>
false]),
142 "hidden" => unserialize($row[
"hidden"] ??
'', [
'allowed_classes' =>
false])
145 if (!is_array($this->sequencedata[
"sequence"])) {
146 $this->sequencedata[
"sequence"] = [];
148 if (!is_array($this->sequencedata[
"postponed"])) {
149 $this->sequencedata[
"postponed"] = [];
151 if (!is_array($this->sequencedata[
"hidden"])) {
152 $this->sequencedata[
"hidden"] = [];
161 $res = $this->db->queryF(
162 "SELECT question_fi FROM tst_seq_qst_presented WHERE active_fi = %s AND pass = %s",
163 array(
'integer',
'integer'),
164 array($this->active_id, $this->pass)
167 while ($row = $this->db->fetchAssoc(
$res)) {
168 $this->alreadyPresentedQuestions[ $row[
'question_fi'] ] = $row[
'question_fi'];
174 $res = $this->db->queryF(
175 "SELECT question_fi FROM tst_seq_qst_checked WHERE active_fi = %s AND pass = %s",
176 array(
'integer',
'integer'),
177 array($this->active_id, $this->pass)
180 while ($row = $this->db->fetchAssoc(
$res)) {
181 $this->alreadyCheckedQuestions[ $row[
'question_fi'] ] = $row[
'question_fi'];
187 $res = $this->db->queryF(
188 "SELECT question_fi FROM tst_seq_qst_optional WHERE active_fi = %s AND pass = %s",
189 array(
'integer',
'integer'),
190 array($this->active_id, $this->pass)
193 while ($row = $this->db->fetchAssoc(
$res)) {
194 $this->optionalQuestions[ $row[
'question_fi'] ] = $row[
'question_fi'];
214 if ((is_array($this->sequencedata[
"postponed"])) && (count($this->sequencedata[
"postponed"]))) {
215 $postponed = serialize($this->sequencedata[
"postponed"]);
218 if ((is_array($this->sequencedata[
"hidden"])) && (count($this->sequencedata[
"hidden"]))) {
219 $hidden = serialize($this->sequencedata[
"hidden"]);
222 $this->db->manipulateF(
223 "DELETE FROM tst_sequence WHERE active_fi = %s AND pass = %s",
224 array(
'integer',
'integer'),
225 array($this->active_id, $this->pass)
228 $this->db->insert(
"tst_sequence", array(
229 "active_fi" => array(
"integer", $this->active_id),
230 "pass" => array(
"integer", $this->pass),
231 "sequence" => array(
"clob", serialize($this->sequencedata[
"sequence"])),
232 "postponed" => array(
"text", $postponed),
233 "hidden" => array(
"text", $hidden),
234 "tstamp" => array(
"integer", time()),
241 if ($this->newlyPresentedQuestion) {
242 $this->db->replace(
'tst_seq_qst_presented', array(
243 'active_fi' => array(
'integer', $this->active_id),
244 'pass' => array(
'integer', $this->pass),
245 'question_fi' => array(
'integer', $this->newlyPresentedQuestion)
252 if ((
int) $this->newlyCheckedQuestion) {
253 $this->db->replace(
'tst_seq_qst_checked', array(
254 'active_fi' => array(
'integer', $this->active_id),
255 'pass' => array(
'integer', $this->pass),
256 'question_fi' => array(
'integer', (
int) $this->newlyCheckedQuestion)
263 $NOT_IN_questions = $this->db->in(
'question_fi', $this->optionalQuestions,
true,
'integer');
266 "DELETE FROM tst_seq_qst_optional WHERE active_fi = %s AND pass = %s AND $NOT_IN_questions",
267 array(
'integer',
'integer'),
268 array($this->active_id, $this->pass)
271 foreach ($this->optionalQuestions as $questionId) {
272 $this->db->replace(
'tst_seq_qst_optional', array(
273 'active_fi' => array(
'integer', $this->active_id),
274 'pass' => array(
'integer', $this->pass),
275 'question_fi' => array(
'integer', (
int) $questionId)
283 $this->sequencedata[
"postponed"][] = $question_id;
290 $this->sequencedata[
"hidden"][] = $question_id;
296 if (!is_array($this->sequencedata[
"postponed"])) {
299 if (!in_array($question_id, $this->sequencedata[
"postponed"])) {
308 if (!is_array($this->sequencedata[
"hidden"])) {
311 if (!in_array($question_id, $this->sequencedata[
"hidden"])) {
320 if (!array_key_exists($sequence, $this->questions)) {
323 if (!is_array($this->sequencedata[
"postponed"])) {
326 if (!in_array($this->questions[$sequence], $this->sequencedata[
"postponed"])) {
335 if (!array_key_exists($sequence, $this->questions)) {
338 if (!is_array($this->sequencedata[
"hidden"])) {
341 if (!in_array($this->questions[$sequence], $this->sequencedata[
"hidden"])) {
350 if (array_key_exists($sequence, $this->questions)) {
351 if (!is_array($this->sequencedata[
"postponed"])) {
352 $this->sequencedata[
"postponed"] = [];
354 $this->sequencedata[
"postponed"][] = (
int) $this->questions[$sequence];
362 if (array_key_exists($sequence, $this->questions)) {
363 if (!is_array($this->sequencedata[
"hidden"])) {
364 $this->sequencedata[
"hidden"] = [];
366 $this->sequencedata[
"hidden"][] = (
int) $this->questions[$sequence];
373 $this->newlyPresentedQuestion = $question_id;
379 $this->newlyPresentedQuestion == $question_id || in_array($question_id, $this->alreadyPresentedQuestions)
389 if ($next_question_id === null) {
393 if ($this->newlyPresentedQuestion === $next_question_id) {
397 if (in_array($next_question_id, $this->alreadyPresentedQuestions)) {
406 $this->newlyCheckedQuestion = $question_id;
411 return isset($this->alreadyCheckedQuestions[$question_id]);
417 $sequence_key = array_search($sequence, $corrected_sequence);
418 if ($sequence_key !==
false) {
419 return $sequence_key + 1;
433 foreach (array_keys($this->questions) as $sequenceKey) {
438 $sequenceKeys[] = $sequenceKey;
441 return $sequenceKeys;
448 foreach ($this->questions as $questionId) {
457 $questions[] = $questionId;
472 foreach ($seq as $sequence) {
480 $question_key = array_search($question_id, $this->questions);
482 if ($question_key ===
false) {
486 $sequence_key = array_search($question_key, $sequence);
488 if ($sequence_key ===
false) {
492 unset($sequence[$sequence_key]);
499 $corrected_sequence = $this->sequencedata[
"sequence"];
501 && is_array($this->sequencedata[
"hidden"])) {
502 foreach ($this->sequencedata[
"hidden"] as $question_id) {
507 foreach ($this->optionalQuestions as $question_id) {
511 if (is_array($this->sequencedata[
"postponed"])) {
512 foreach ($this->sequencedata[
"postponed"] as $question_id) {
513 $found_sequence = array_search($question_id, $this->questions);
514 if ($found_sequence ===
false) {
517 $sequence_key = array_search($found_sequence, $corrected_sequence);
518 if ($sequence_key !==
false) {
519 unset($corrected_sequence[$sequence_key]);
520 $corrected_sequence[] = $found_sequence;
524 return array_values($corrected_sequence);
529 return array_search($question_id, $this->questions) ?: null;
535 if (count($correctedsequence)) {
536 return reset($correctedsequence);
545 if (count($correctedsequence)) {
546 return end($correctedsequence);
555 $sequence_key = array_search($sequence, $corrected_sequence);
556 if ($sequence_key !==
false) {
557 $next_sequence_key = $sequence_key + 1;
558 if (array_key_exists($next_sequence_key, $corrected_sequence)) {
559 return $corrected_sequence[$next_sequence_key];
568 $sequencekey = array_search($sequence, $correctedsequence);
569 if ($sequencekey !==
false) {
570 $prevsequencekey = $sequencekey - 1;
571 if (($prevsequencekey >= 0) && (array_key_exists($prevsequencekey, $correctedsequence))) {
572 return $correctedsequence[$prevsequencekey];
584 $keys = array_keys($array);
587 foreach ($keys as
$key) {
598 if (array_key_exists($sequence, $this->questions)) {
599 return $this->questions[$sequence];
611 foreach ($correctedsequence as $sequence) {
613 if (is_object($question)) {
614 $worked_through = $this->questioninfo->lookupResultRecordExist($this->active_id, $question->getId(), $this->pass);
616 if (array_key_exists($question->getId(), $solved_questions)) {
617 $solved = $solved_questions[$question->getId()][
"solved"];
623 "title" => $question->getTitleForHTMLOutput(),
624 "qid" => $question->getId(),
626 "visited" => $worked_through,
627 "solved" => (($solved) ?
"1" :
"0"),
628 "description" => $question->getComment(),
629 "points" => $question->getMaximumPoints(),
630 "worked_through" => $worked_through,
631 "postponed" => $is_postponed,
632 "sequence" => $sequence,
634 'isAnswered' => $question->isAnswered($this->active_id, $this->pass),
635 'has_authorized_answer' => $question->authorizedSolutionExists($this->active_id, $this->pass)
639 if (!$obligationsFilterEnabled || $row[
'obligatory']) {
640 $result_array[] = $row;
646 return $result_array;
661 if ((is_array($this->sequencedata[
"sequence"])) && (count($this->sequencedata[
"sequence"]) > 0)) {
670 if ((is_array($this->sequencedata[
"hidden"])) && (count($this->sequencedata[
"hidden"]) > 0)) {
679 $this->sequencedata[
"hidden"] = [];
703 return array_values($this->questions);
708 return in_array($question_id, $this->questions);
720 $this->optionalQuestions[$question_id] = $question_id;
725 return isset($this->optionalQuestions[$question_id]);
730 return (
bool) count($this->optionalQuestions);
740 $this->optionalQuestions = [];
745 $optionalSequenceKeys = [];
747 foreach ($this->sequencedata[
'sequence'] as $index => $sequenceKey) {
749 $optionalSequenceKeys[$index] = $sequenceKey;
750 unset($this->sequencedata[
'sequence'][$index]);
754 foreach ($optionalSequenceKeys as $index => $sequenceKey) {
755 $this->sequencedata[
'sequence'][$index] = $sequenceKey;
loadFromDb()
Loads the sequence data for a given active id.
bool $answeringOptionalQuestionsConfirmed
hideQuestion(int $question_id)
setConsiderHiddenQuestionsEnabled(bool $considerHiddenQuestionsEnabled)
bool $considerHiddenQuestionsEnabled
postponeQuestion(int $question_id)
isConsiderOptionalQuestionsEnabled()
getPositionOfSequence(int $sequence)
getQuestionForSequence(int $sequence)
getSequenceForQuestion(int $question_id)
isPostponedQuestion(int $question_id)
int $newlyPresentedQuestion
isHiddenQuestion(int $question_id)
array $questions
The mapping of the sequence numbers to the questions.
getPreviousSequence(int $sequence)
isPostponedSequence(int $sequence)
saveNewlyPresentedQuestion()
getUserSequenceQuestions()
static isQuestionObligatory($question_id)
checks wether the question with given id is marked as obligatory or not
setQuestionPresented(int $question_id)
saveToDb()
Saves the sequence data for a given pass to the database.
setConsiderOptionalQuestionsEnabled(bool $considerOptionalQuestionsEnabled)
pcArrayShuffle(array $array)
Shuffles the values of a given array.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setAnsweringOptionalQuestionsConfirmed(bool $answeringOptionalQuestionsConfirmed)
static instantiateQuestion(int $question_id)
isHiddenSequence(int $sequence)
setQuestionOptional(int $question_id)
hasStarted(ilTestSession $testSession)
bool $considerOptionalQuestionsEnabled
isConsiderHiddenQuestionsEnabled()
isQuestionPresented(int $question_id)
isNextQuestionPresented(int $question_id)
static _getSolvedQuestions($active_id, $question_fi=null)
get solved questions
getOrderedSequenceQuestions()
__construct(protected ilDBInterface $db, protected int $active_id, protected int $pass, protected QuestionInfoService $questioninfo)
ilTestSequence constructor
ensureQuestionNotInSequence(array $sequence, int $question_id)
array $alreadyPresentedQuestions
questionExists(int $question_id)
reorderOptionalQuestionsToSequenceEnd()
isQuestionChecked(int $question_id)
getSequenceSummary(bool $obligationsFilterEnabled=false)
array $sequencedata
An array containing the sequence data.
saveNewlyCheckedQuestion()
postponeSequence(int $sequence)
hideSequence(int $sequence)
setQuestionChecked(int $question_id)
getNextSequence(int $sequence)
isAnsweringOptionalQuestionsConfirmed()
isQuestionOptional(int $question_id)
loadQuestions()
Loads the question mapping.
int $newlyCheckedQuestion
array $alreadyCheckedQuestions
createNewSequence(int $max, bool $shuffle)