ILIAS  release_4-3 Revision
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilTestSequence.php
Go to the documentation of this file.
1 <?php
2  /*
3  +----------------------------------------------------------------------------+
4  | ILIAS open source |
5  +----------------------------------------------------------------------------+
6  | Copyright (c) 1998-2001 ILIAS open source, University of Cologne |
7  | |
8  | This program is free software; you can redistribute it and/or |
9  | modify it under the terms of the GNU General Public License |
10  | as published by the Free Software Foundation; either version 2 |
11  | of the License, or (at your option) any later version. |
12  | |
13  | This program is distributed in the hope that it will be useful, |
14  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16  | GNU General Public License for more details. |
17  | |
18  | You should have received a copy of the GNU General Public License |
19  | along with this program; if not, write to the Free Software |
20  | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21  +----------------------------------------------------------------------------+
22 */
23 
34 {
41 
48 
55 
61  var $pass;
62 
69 
79  function ilTestSequence($active_id, $pass, $randomtest)
80  {
81  $this->active_id = $active_id;
82  $this->pass = $pass;
83  $this->isRandomTest = $randomtest;
84  $this->sequencedata = array(
85  "sequence" => array(),
86  "postponed" => array(),
87  "hidden" => array()
88  );
89  $this->loadFromDb();
90  $this->loadQuestions();
91  }
92 
93  function getActiveId()
94  {
95  return $this->active_id;
96  }
97 
98  function createNewSequence($max, $shuffle)
99  {
100  $newsequence = array();
101  if ($max > 0)
102  {
103  for ($i = 1; $i <= $max; $i++)
104  {
105  array_push($newsequence, $i);
106  }
107  if ($shuffle) $newsequence = $this->pcArrayShuffle($newsequence);
108  }
109  $this->sequencedata["sequence"] = $newsequence;
110  }
111 
117  private function loadQuestions()
118  {
119  global $ilDB;
120 
121  $this->questions = array();
122  if ($this->isRandomTest)
123  {
124  $result = $ilDB->queryF("SELECT tst_test_rnd_qst.* FROM tst_test_rnd_qst, qpl_questions WHERE tst_test_rnd_qst.active_fi = %s AND qpl_questions.question_id = tst_test_rnd_qst.question_fi AND tst_test_rnd_qst.pass = %s ORDER BY sequence",
125  array('integer','integer'),
126  array($this->active_id, $this->pass)
127  );
128  // The following is a fix for random tests prior to ILIAS 3.8. If someone started a random test in ILIAS < 3.8, there
129  // is only one test pass (pass = 0) in tst_test_rnd_qst while with ILIAS 3.8 there are questions for every test pass.
130  // To prevent problems with tests started in an older version and continued in ILIAS 3.8, the first pass should be taken if
131  // no questions are present for a newer pass.
132  if ($result->numRows() == 0)
133  {
134  $result = $ilDB->queryF("SELECT tst_test_rnd_qst.* FROM tst_test_rnd_qst, qpl_questions WHERE tst_test_rnd_qst.active_fi = %s AND qpl_questions.question_id = tst_test_rnd_qst.question_fi AND tst_test_rnd_qst.pass = 0 ORDER BY sequence",
135  array('integer'),
136  array($this->active_id)
137  );
138  }
139  }
140  else
141  {
142  $result = $ilDB->queryF("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",
143  array('integer'),
144  array($this->active_id)
145  );
146  }
147  $index = 1;
148  while ($data = $ilDB->fetchAssoc($result))
149  {
150  $this->questions[$index++] = $data["question_fi"];
151  }
152  }
153 
160  private function loadFromDb()
161  {
162  global $ilDB;
163  $result = $ilDB->queryF("SELECT * FROM tst_sequence WHERE active_fi = %s AND pass = %s",
164  array('integer','integer'),
165  array($this->active_id, $this->pass)
166  );
167  if ($result->numRows())
168  {
169  $row = $ilDB->fetchAssoc($result);
170  $this->sequencedata = array(
171  "sequence" => unserialize($row["sequence"]),
172  "postponed" => unserialize($row["postponed"]),
173  "hidden" => unserialize($row["hidden"])
174  );
175  if (!is_array($this->sequencedata["sequence"])) $this->sequencedata["sequence"] = array();
176  if (!is_array($this->sequencedata["postponed"])) $this->sequencedata["postponed"] = array();
177  if (!is_array($this->sequencedata["hidden"])) $this->sequencedata["hidden"] = array();
178  }
179  }
180 
186  public function saveToDb()
187  {
188  global $ilDB;
189 
190  $postponed = NULL;
191  if ((is_array($this->sequencedata["postponed"])) && (count($this->sequencedata["postponed"])))
192  {
193  $postponed = serialize($this->sequencedata["postponed"]);
194  }
195  $hidden = NULL;
196  if ((is_array($this->sequencedata["hidden"])) && (count($this->sequencedata["hidden"])))
197  {
198  $hidden = serialize($this->sequencedata["hidden"]);
199  }
200 
201  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_sequence WHERE active_fi = %s AND pass = %s",
202  array('integer','integer'),
203  array($this->active_id, $this->pass)
204  );
205 
206  $affectedRows = $ilDB->insert("tst_sequence", array(
207  "active_fi" => array("integer", $this->active_id),
208  "pass" => array("integer", $this->pass),
209  "sequence" => array("clob", serialize($this->sequencedata["sequence"])),
210  "postponed" => array("text", $postponed),
211  "hidden" => array("text", $hidden),
212  "tstamp" => array("integer", time())
213  ));
214  }
215 
216  function postponeQuestion($question_id)
217  {
218  if (!$this->isPostponedQuestion($question_id))
219  {
220  array_push($this->sequencedata["postponed"], intval($question_id));
221  }
222  }
223 
224  function hideQuestion($question_id)
225  {
226  if (!$this->isHiddenQuestion($question_id))
227  {
228  array_push($this->sequencedata["hidden"], intval($question_id));
229  }
230  }
231 
232  function isPostponedQuestion($question_id)
233  {
234  if (!is_array($this->sequencedata["postponed"])) return FALSE;
235  if (!in_array($question_id, $this->sequencedata["postponed"]))
236  {
237  return FALSE;
238  }
239  else
240  {
241  return TRUE;
242  }
243  }
244 
245  function isHiddenQuestion($question_id)
246  {
247  if (!is_array($this->sequencedata["hidden"])) return FALSE;
248  if (!in_array($question_id, $this->sequencedata["hidden"]))
249  {
250  return FALSE;
251  }
252  else
253  {
254  return TRUE;
255  }
256  }
257 
258  function isPostponedSequence($sequence)
259  {
260  if (!array_key_exists($sequence, $this->questions)) return FALSE;
261  if (!is_array($this->sequencedata["postponed"])) return FALSE;
262  if (!in_array($this->questions[$sequence], $this->sequencedata["postponed"]))
263  {
264  return FALSE;
265  }
266  else
267  {
268  return TRUE;
269  }
270  }
271 
272  function isHiddenSequence($sequence)
273  {
274  if (!array_key_exists($sequence, $this->questions)) return FALSE;
275  if (!is_array($this->sequencedata["hidden"])) return FALSE;
276  if (!in_array($this->questions[$sequence], $this->sequencedata["hidden"]))
277  {
278  return FALSE;
279  }
280  else
281  {
282  return TRUE;
283  }
284  }
285 
286  function postponeSequence($sequence)
287  {
288  if (!$this->isPostponedSequence($sequence))
289  {
290  if (array_key_exists($sequence, $this->questions))
291  {
292  if (!is_array($this->sequencedata["postponed"])) $this->sequencedata["postponed"] = array();
293  array_push($this->sequencedata["postponed"], intval($this->questions[$sequence]));
294  }
295  }
296  }
297 
298  function hideSequence($sequence)
299  {
300  if (!$this->isHiddenSequence($sequence))
301  {
302  if (array_key_exists($sequence, $this->questions))
303  {
304  if (!is_array($this->sequencedata["hidden"])) $this->sequencedata["hidden"] = array();
305  array_push($this->sequencedata["hidden"], intval($this->questions[$sequence]));
306  }
307  }
308  }
309 
310  function getPositionOfSequence($sequence)
311  {
312  $correctedsequence = $this->getCorrectedSequence();
313  $sequencekey = array_search($sequence, $correctedsequence);
314  if ($sequencekey !== FALSE)
315  {
316  return $sequencekey + 1;
317  }
318  else
319  {
320  return "";
321  }
322  }
323 
325  {
326  return count($this->getCorrectedSequence());
327  }
328 
330  {
331  return array_keys($this->questions);
332  }
333 
335  {
336  return $this->questions;
337  }
338 
339  function getUserSequence()
340  {
341  return $this->getCorrectedSequence(TRUE);
342  }
343 
345  {
346  $seq = $this->getCorrectedSequence(TRUE);
347  $found = array();
348  foreach ($seq as $sequence)
349  {
350  array_push($found, $this->getQuestionForSequence($sequence));
351  }
352  return $found;
353  }
354 
355  protected function getCorrectedSequence($with_hidden_questions = FALSE)
356  {
357  $correctedsequence = $this->sequencedata["sequence"];
358  if (!$with_hidden_questions)
359  {
360  if (is_array($this->sequencedata["hidden"]))
361  {
362  foreach ($this->sequencedata["hidden"] as $question_id)
363  {
364  $foundsequence = array_search($question_id, $this->questions);
365  if ($foundsequence !== FALSE)
366  {
367  $sequencekey = array_search($foundsequence, $correctedsequence);
368  if ($sequencekey !== FALSE)
369  {
370  unset($correctedsequence[$sequencekey]);
371  }
372  }
373  }
374  }
375  }
376  if (is_array($this->sequencedata["postponed"]))
377  {
378  foreach ($this->sequencedata["postponed"] as $question_id)
379  {
380  $foundsequence = array_search($question_id, $this->questions);
381  if ($foundsequence !== FALSE)
382  {
383  $sequencekey = array_search($foundsequence, $correctedsequence);
384  if ($sequencekey !== FALSE)
385  {
386  unset($correctedsequence[$sequencekey]);
387  array_push($correctedsequence, $foundsequence);
388  }
389  }
390  }
391  }
392  return array_values($correctedsequence);
393  }
394 
395  function getSequenceForQuestion($question_id)
396  {
397  return array_search($question_id, $this->questions);
398  }
399 
400  function getFirstSequence()
401  {
402  $correctedsequence = $this->getCorrectedSequence();
403  if (count($correctedsequence))
404  {
405  return reset($correctedsequence);
406  }
407  else
408  {
409  return FALSE;
410  }
411  }
412 
413  function getLastSequence()
414  {
415  $correctedsequence = $this->getCorrectedSequence();
416  if (count($correctedsequence))
417  {
418  return end($correctedsequence);
419  }
420  else
421  {
422  return FALSE;
423  }
424  }
425 
426  function getNextSequence($sequence)
427  {
428  $correctedsequence = $this->getCorrectedSequence();
429  $sequencekey = array_search($sequence, $correctedsequence);
430  if ($sequencekey !== FALSE)
431  {
432  $nextsequencekey = $sequencekey + 1;
433  if (array_key_exists($nextsequencekey, $correctedsequence))
434  {
435  return $correctedsequence[$nextsequencekey];
436  }
437  }
438  return FALSE;
439  }
440 
441  function getPreviousSequence($sequence)
442  {
443  $correctedsequence = $this->getCorrectedSequence();
444  $sequencekey = array_search($sequence, $correctedsequence);
445  if ($sequencekey !== FALSE)
446  {
447  $prevsequencekey = $sequencekey - 1;
448  if (($prevsequencekey >= 0) && (array_key_exists($prevsequencekey, $correctedsequence)))
449  {
450  return $correctedsequence[$prevsequencekey];
451  }
452  }
453  return FALSE;
454  }
455 
464  function pcArrayShuffle($array)
465  {
466  $keys = array_keys($array);
467  shuffle($keys);
468  $result = array();
469  foreach ($keys as $key)
470  {
471  $result[$key] = $array[$key];
472  }
473  return $result;
474  }
475 
476  function getQuestionForSequence($sequence)
477  {
478  if ($sequence < 1) return FALSE;
479  if (array_key_exists($sequence, $this->questions))
480  {
481  return $this->questions[$sequence];
482  }
483  else
484  {
485  return FALSE;
486  }
487  }
488 
489  function &getSequenceSummary($obligationsFilter = false)
490  {
491  $correctedsequence = $this->getCorrectedSequence();
492  $result_array = array();
493  include_once "./Modules/Test/classes/class.ilObjTest.php";
494  $solved_questions = ilObjTest::_getSolvedQuestions($this->active_id);
495  $key = 1;
496  foreach ($correctedsequence as $sequence)
497  {
498  $question =& ilObjTest::_instanciateQuestion($this->getQuestionForSequence($sequence));
499  if (is_object($question))
500  {
501  $worked_through = $question->_isWorkedThrough($this->active_id, $question->getId(), $this->pass);
502  $solved = 0;
503  if (array_key_exists($question->getId(), $solved_questions))
504  {
505  $solved = $solved_questions[$question->getId()]["solved"];
506  }
507  $is_postponed = $this->isPostponedQuestion($question->getId());
508 
509  $row = array(
510  "nr" => "$key",
511  "title" => $question->getTitle(),
512  "qid" => $question->getId(),
513  "visited" => $worked_through,
514  "solved" => (($solved)?"1":"0"),
515  "description" => $question->getComment(),
516  "points" => $question->getMaximumPoints(),
517  "worked_through" => $worked_through,
518  "postponed" => $is_postponed,
519  "sequence" => $sequence,
520  "obligatory" => ilObjTest::isQuestionObligatory($question->getId()),
521  'isAnswered' => $question->isAnswered($this->active_id, $this->pass)
522  );
523 
524  if( !$obligationsFilter || $row['obligatory'] )
525  {
526  array_push($result_array, $row);
527  }
528 
529  $key++;
530  }
531  }
532  return $result_array;
533  }
534 
535  function getPass()
536  {
537  return $this->pass;
538  }
539 
540  function setPass($pass)
541  {
542  $this->pass = $pass;
543  }
544 
545  function hasSequence()
546  {
547  if ((is_array($this->sequencedata["sequence"])) && (count($this->sequencedata["sequence"]) > 0))
548  {
549  return TRUE;
550  }
551  else
552  {
553  return FALSE;
554  }
555  }
556 
558  {
559  if ((is_array($this->sequencedata["hidden"])) && (count($this->sequencedata["hidden"]) > 0))
560  {
561  return TRUE;
562  }
563  else
564  {
565  return FALSE;
566  }
567  }
568 
570  {
571  $this->sequencedata["hidden"] = array();
572  }
573 
574  public function questionExists($questionId)
575  {
576  return in_array($questionId, $this->questions);
577  }
578 }
579 
580 ?>