ILIAS  Release_4_4_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilTestOutputGUI.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/classes/class.ilTestPlayerAbstractGUI.php';
5 
25 {
29  public function executeCommand()
30  {
31  global $ilUser, $ilDB, $ilPluginAdmin, $lng, $ilTabs;
32 
33  $ilTabs->clearTargets();
34 
35  $cmd = $this->ctrl->getCmd();
36  $next_class = $this->ctrl->getNextClass($this);
37 
38  $this->ctrl->saveParameter($this, "sequence");
39  $this->ctrl->saveParameter($this, "active_id");
40 
41  if (preg_match("/^gotoquestion_(\\d+)$/", $cmd, $matches))
42  {
43  $cmd = "gotoquestion";
44  if (strlen($matches[1]))
45  {
46  $this->ctrl->setParameter($this, 'gotosequence', $matches[1]);
47  }
48  }
49 
50  $testSessionFactory = new ilTestSessionFactory($this->object);
51  $this->testSession = $testSessionFactory->getSession($_GET['active_id']);
52 
53  $this->ensureExistingTestSession($this->testSession);
54 
55  $this->initProcessLocker($this->testSession->getActiveId());
56 
57  $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $this->object);
58  $this->testSequence = $testSequenceFactory->getSequence($this->testSession);
59  $this->testSequence->loadFromDb();
60  $this->testSequence->loadQuestions();
61 
62  include_once 'Services/jQuery/classes/class.iljQueryUtil.php';
64  include_once "./Services/YUI/classes/class.ilYuiUtil.php";
66 
67  $cmd = $this->getCommand($cmd);
68 
69  switch($next_class)
70  {
71  case 'ilassquestionpagegui':
72 
73  $questionId = $this->testSequence->getQuestionForSequence( $this->calculateSequence() );
74 
75  require_once "./Modules/TestQuestionPool/classes/class.ilAssQuestionPageGUI.php";
76  $page_gui = new ilAssQuestionPageGUI($questionId);
77  $ret = $this->ctrl->forwardCommand($page_gui);
78  break;
79 
80  case 'iltestsubmissionreviewgui':
81  require_once './Modules/Test/classes/class.ilTestSubmissionReviewGUI.php';
82  $gui = new ilTestSubmissionReviewGUI($this, $this->object);
83  $ret = $this->ctrl->forwardCommand($gui);
84  break;
85 
86  case 'ilassquestionhintrequestgui':
87 
88  $questionGUI = $this->object->createQuestionGUI(
89  "", $this->testSequence->getQuestionForSequence( $this->calculateSequence() )
90  );
91 
92  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintRequestGUI.php';
93  $gui = new ilAssQuestionHintRequestGUI($this, $this->testSession, $questionGUI);
94 
95  $ret = $this->ctrl->forwardCommand($gui);
96 
97  break;
98 
99  case 'iltestsignaturegui':
100  require_once './Modules/Test/classes/class.ilTestSignatureGUI.php';
101  $gui = new ilTestSignatureGUI($this);
102  $ret = $this->ctrl->forwardCommand($gui);
103  break;
104 
105  default:
106 
107  $cmd .= 'Cmd';
108  $ret =& $this->$cmd();
109  break;
110  }
111  return $ret;
112  }
113 
114  protected function startTestCmd()
115  {
116  $_GET['activecommand'] = 'start';
117  $this->redirectQuestionCmd();
118  }
119 
123  protected function nextQuestionCmd()
124  {
125  $this->saveQuestionSolution();
126  $this->ctrl->setParameter($this, "activecommand", "next");
127  $this->ctrl->redirect($this, "redirectQuestion");
128  }
129 
133  protected function previousQuestionCmd()
134  {
135  $this->saveQuestionSolution();
136  $this->ctrl->setParameter($this, "activecommand", "previous");
137  $this->ctrl->redirect($this, "redirectQuestion");
138  }
139 
147  protected function redirectQuestionCmd()
148  {
149  global $ilUser;
150 
151  // check the test restrictions to access the test in case one
152  // of the test navigation commands was called by an external script
153  // e.g. $ilNavigationHistory
154  $executable = $this->object->isExecutable($this->testSession, $ilUser->getId());
155  if (!$executable["executable"])
156  {
157  ilUtil::sendInfo($executable["errormessage"], TRUE);
158  $this->ctrl->redirectByClass("ilobjtestgui", "infoScreen");
159  }
160  switch ($_GET["activecommand"])
161  {
162  case "next":
163  $this->sequence = $this->calculateSequence();
164  if ($this->sequence === FALSE)
165  {
166  if ($this->object->getListOfQuestionsEnd())
167  {
168 
169  $allObligationsAnswered = ilObjTest::allObligationsAnswered(
170  $this->testSession->getTestId(),
171  $this->testSession->getActiveId(),
172  $this->testSession->getPass()
173  );
174 
175  if( $this->object->areObligationsEnabled() && !$allObligationsAnswered )
176  {
177  $this->ctrl->redirect($this, "outQuestionSummaryWithObligationsInfo");
178  }
179 
180  $this->outQuestionSummaryCmd();
181  }
182  else
183  {
184  $this->ctrl->redirect($this, "finishTest");
185  }
186  }
187  else
188  {
189  $this->testSession->setLastSequence($this->sequence);
190  $this->testSession->saveToDb();
191  $this->outTestPage(false);
192  }
193  break;
194  case "previous":
195  $this->sequence = $this->calculateSequence();
196  $this->testSession->setLastSequence($this->sequence);
197  $this->testSession->saveToDb();
198  if ($this->sequence === FALSE)
199  {
200  $this->ctrl->redirect($this, "outIntroductionPage");
201  }
202  else
203  {
204  $this->outTestPage(false);
205  }
206  break;
207  case "postpone":
208  $this->sequence = $this->calculateSequence();
209  $nextSequence = $this->testSequence->getNextSequence($this->sequence);
210  $this->testSequence->postponeSequence($this->sequence);
211  $this->testSequence->saveToDb();
212  $this->testSession->setLastSequence($nextSequence);
213  $this->testSession->saveToDb();
214  $this->sequence = $nextSequence;
215  $this->outTestPage(false);
216  break;
217  case "setmarked":
218  $this->sequence = $this->calculateSequence();
219  $this->testSession->setLastSequence($this->sequence);
220  $this->testSession->saveToDb();
221  $q_id = $this->testSequence->getQuestionForSequence($_GET["sequence"]);
222  $this->object->setQuestionSetSolved(1, $q_id, $ilUser->getId());
223  $this->outTestPage(false);
224  break;
225  case "resetmarked":
226  $this->sequence = $this->calculateSequence();
227  $this->testSession->setLastSequence($this->sequence);
228  $this->testSession->saveToDb();
229  $q_id = $this->testSequence->getQuestionForSequence($_GET["sequence"]);
230  $this->object->setQuestionSetSolved(0, $q_id, $ilUser->getId());
231  $this->outTestPage(false);
232  break;
233  case "directfeedback":
234  $this->sequence = $this->calculateSequence();
235  $this->testSession->setLastSequence($this->sequence);
236  $this->testSession->saveToDb();
237  $this->outTestPage(true);
238  break;
239  case "handleQuestionAction":
240  $this->sequence = $this->calculateSequence();
241  $this->testSession->setLastSequence($this->sequence);
242  $this->testSession->saveToDb();
243  $this->outTestPage(false);
244  break;
245  case "summary":
246  $this->ctrl->redirect($this, "outQuestionSummary");
247  break;
248  case "summary_obligations":
249  $this->ctrl->redirect($this, "outQuestionSummaryWithObligationsInfo");
250  break;
251  case "summary_obligations_only":
252  $this->ctrl->redirect($this, "outObligationsOnlySummary");
253  break;
254  case "start":
255  $_SESSION['tst_pass_finish'] = 0;
256 
257  // ensure existing test session
258  $this->testSession->setUserId($ilUser->getId());
259  $this->testSession->setAnonymousId($_SESSION["tst_access_code"][$this->object->getTestId()]);
260  $this->testSession->saveToDb();
261 
262  $active_id = $this->testSession->getActiveId();
263  $this->ctrl->setParameter($this, "active_id", $active_id);
264  $shuffle = $this->object->getShuffleQuestions();
265  if ($this->object->isRandomTest())
266  {
268 
269  $this->object->loadQuestions();
270  $shuffle = FALSE; // shuffle is already done during the creation of the random questions
271  }
272 
273  assQuestion::_updateTestPassResults(
274  $active_id, $this->testSession->getPass(), $this->object->areObligationsEnabled()
275  );
276 
277  // ensure existing test sequence
278  if( !$this->testSequence->hasSequence() )
279  {
280  $this->testSequence->createNewSequence($this->object->getQuestionCount(), $shuffle);
281  $this->testSequence->saveToDb();
282  }
283 
284  $active_time_id = $this->object->startWorkingTime($this->testSession->getActiveId(), $this->testSession->getPass());
285  $_SESSION["active_time_id"] = $active_time_id;
286  if ($this->object->getListOfQuestionsStart())
287  {
288  $this->ctrl->setParameter($this, "activecommand", "summary");
289  $this->ctrl->redirect($this, "redirectQuestion");
290  }
291  else
292  {
293  $this->ctrl->setParameter($this, "sequence", $this->sequence);
294  $this->ctrl->setParameter($this, "activecommand", "gotoquestion");
295  $this->ctrl->saveParameter($this, "tst_javascript");
296  $this->ctrl->redirect($this, "redirectQuestion");
297  }
298  break;
299  case "resume":
300  $_SESSION['tst_pass_finish'] = 0;
301  $active_id = $this->testSession->getActiveId();
302  $this->ctrl->setParameter($this, "active_id", $active_id);
303 
304  if ($this->object->isRandomTest())
305  {
306  if (!$this->testSequence->hasRandomQuestionsForPass($active_id, $this->testSession->getPass()))
307  {
308  // create a new set of random questions
310  }
311  }
312  $shuffle = $this->object->getShuffleQuestions();
313  if ($this->object->isRandomTest())
314  {
315  $shuffle = FALSE;
316  }
317 
318  assQuestion::_updateTestPassResults(
319  $active_id, $this->testSession->getPass(), $this->object->areObligationsEnabled()
320  );
321 
322  // ensure existing test sequence
323  if( !$this->testSequence->hasSequence() )
324  {
325  $this->testSequence->createNewSequence($this->object->getQuestionCount(), $shuffle);
326  $this->testSequence->saveToDb();
327  }
328 
329  $this->sequence = $this->testSession->getLastSequence();
330  $active_time_id = $this->object->startWorkingTime($active_id, $this->testSession->getPass());
331  $_SESSION["active_time_id"] = $active_time_id;
332  if ($this->object->getListOfQuestionsStart())
333  {
334  $this->ctrl->setParameter($this, "activecommand", "summary");
335  $this->ctrl->redirect($this, "redirectQuestion");
336  }
337  else
338  {
339  $this->ctrl->setParameter($this, "sequence", $this->sequence);
340  $this->ctrl->setParameter($this, "activecommand", "gotoquestion");
341  $this->ctrl->saveParameter($this, "tst_javascript");
342  $this->ctrl->redirect($this, "redirectQuestion");
343  }
344  break;
345 
346  case 'test_submission_overview':
347  require_once './Modules/Test/classes/class.ilTestSubmissionReviewGUI.php';
348  $this->ctrl->redirect(new ilTestSubmissionReviewGUI($this, $this->object), "show");
349  break;
350 
351  case "back":
352  case "gotoquestion":
353  default:
354  $_SESSION['tst_pass_finish'] = 0;
355  if (array_key_exists("tst_javascript", $_GET))
356  {
357  $ilUser->writePref("tst_javascript", $_GET["tst_javascript"]);
358  }
359  $this->sequence = $this->calculateSequence();
360  if (strlen($_GET['gotosequence'])) $this->sequence = $_GET['gotosequence'];
361  $this->testSession->setLastSequence($this->sequence);
362  $this->testSession->saveToDb();
363  $this->outTestPage(false);
364  break;
365  }
366  }
367 
368  private function isValidSequenceElement($sequenceElement)
369  {
370  if( $sequenceElement < 1 )
371  {
372  return false;
373  }
374 
375  if( !$this->testSequence->getPositionOfSequence($sequenceElement) )
376  {
377  return false;
378  }
379 
380  return true;
381  }
382 
386  protected function outWorkingForm($sequence = "", $test_id, $postpone_allowed, $directfeedback = false)
387  {
388  global $ilUser;
389 
390  if( !$this->isValidSequenceElement($sequence) )
391  {
392  $sequence = $this->testSequence->getFirstSequence();
393  }
394 
395  $_SESSION["active_time_id"]= $this->object->startWorkingTime($this->testSession->getActiveId(),
396  $this->testSession->getPass()
397  );
398 
399  $this->populateContentStyleBlock();
400  $this->populateSyntaxStyleBlock();
401 
402  if ($this->object->getListOfQuestions())
403  {
404  $this->showSideList();
405  }
406 
407  $questionId = $this->testSequence->getQuestionForSequence($sequence);
408  $question_gui = $this->object->createQuestionGUI("", $questionId);
409 
410  if( !is_object($question_gui) )
411  {
412  global $ilLog;
413 
414  $ilLog->write(
415  "INV SEQ: active={$this->testSession->getActiveId()} qId=$questionId seq=$sequence "
416  .serialize($this->testSequence)
417  );
418 
419  $ilLog->logStack('INV SEQ');
420 
421  $this->ctrl->setParameter($this, 'gotosequence', $this->testSequence->getFirstSequence());
422  $this->ctrl->setParameter($this, 'activecommand', 'gotoquestion');
423  $this->ctrl->redirect($this, 'redirectQuestion');
424  }
425 
426  $question_gui->setTargetGui($this);
427 
428  if ($this->object->getJavaScriptOutput())
429  {
430  $question_gui->object->setOutputType(OUTPUT_JAVASCRIPT);
431  }
432 
433  $is_postponed = $this->testSequence->isPostponedQuestion($question_gui->object->getId());
434  $this->ctrl->setParameter($this, "sequence", "$sequence");
435  $formaction = $this->ctrl->getFormAction($this, "gotoQuestion");
436 
437  $question_gui->setSequenceNumber($this->testSequence->getPositionOfSequence($sequence));
438  $question_gui->setQuestionCount($this->testSequence->getUserQuestionCount());
439 
440 
441  // output question
442  $user_post_solution = FALSE;
443  if (array_key_exists("previouspost", $_SESSION))
444  {
445  $user_post_solution = $_SESSION["previouspost"];
446  unset($_SESSION["previouspost"]);
447  }
448 
449  // Determine $answer_feedback: It should hold a boolean stating if answer-specific-feedback is to be given.
450  // It gets the parameter "Scoring and Results" -> "Instant Feedback" -> "Show Answer-Specific Feedback"
451  // $directfeedback holds a boolean stating if the instant feedback was requested using the "Check" button.
452  $answer_feedback = FALSE;
453  if (($directfeedback) && ($this->object->getSpecificAnswerFeedback()))
454  {
455  $answer_feedback = TRUE;
456  }
457 
458  // Answer specific feedback is rendered into the display of the test question with in the concrete question types outQuestionForTest-method.
459  // Notation of the params prior to getting rid of this crap in favor of a class
460  $question_gui->outQuestionForTest(
461  $formaction, #form_action
462  $this->testSession->getActiveId(), #active_id
463  NULL, #pass
464  $is_postponed, #is_postponed
465  $user_post_solution, #user_post_solution
466  $answer_feedback #answer_feedback == inline_specific_feedback
467  );
468  // The display of specific inline feedback and specific feedback in an own block is to honor questions, which
469  // have the possibility to embed the specific feedback into their output while maintaining compatibility to
470  // questions, which do not have such facilities. E.g. there can be no "specific inline feedback" for essay
471  // questions, while the multiple-choice questions do well.
472 
473  $this->fillQuestionRelatedNavigation($question_gui);
474 
475  if ($directfeedback)
476  {
477  // This controls if the solution should be shown.
478  // It gets the parameter "Scoring and Results" -> "Instant Feedback" -> "Show Solutions"
479  if ($this->object->getInstantFeedbackSolution())
480  {
481  $show_question_inline_score = $this->determineInlineScoreDisplay();
482 
483  // Notation of the params prior to getting rid of this crap in favor of a class
484  $solutionoutput = $question_gui->getSolutionOutput(
485  $this->testSession->getActiveId(), #active_id
486  NULL, #pass
487  FALSE, #graphical_output
488  $show_question_inline_score, #result_output
489  FALSE, #show_question_only
490  FALSE, #show_feedback
491  TRUE, #show_correct_solution
492  FALSE, #show_manual_scoring
493  FALSE #show_question_text
494  );
495  $this->populateSolutionBlock( $solutionoutput );
496  }
497 
498  // This controls if the score should be shown.
499  // It gets the parameter "Scoring and Results" -> "Instant Feedback" -> "Show Results (Only Points)"
500  if ($this->object->getAnswerFeedbackPoints())
501  {
502  $reachedPoints = $question_gui->object->getAdjustedReachedPoints($this->testSession->getActiveId(), NULL);
503  $maxPoints = $question_gui->object->getMaximumPoints();
504 
505  $this->populateScoreBlock( $reachedPoints, $maxPoints );
506  }
507 
508  // This controls if the generic feedback should be shown.
509  // It gets the parameter "Scoring and Results" -> "Instant Feedback" -> "Show Solutions"
510  if ($this->object->getGenericAnswerFeedback())
511  {
512  $this->populateGenericFeedbackBlock( $question_gui );
513  }
514 
515  // This controls if the specific feedback should be shown.
516  // It gets the parameter "Scoring and Results" -> "Instant Feedback" -> "Show Answer-Specific Feedback"
517  if ($this->object->getSpecificAnswerFeedback())
518  {
519  $this->populateSpecificFeedbackBlock( $question_gui );
520  }
521  }
522 
524 
525  if ($postpone_allowed && !$is_postponed)
526  {
527  $this->populatePostponeButtons();
528  }
529 
530  if ($this->object->getListOfQuestions())
531  {
532  $this->populateSummaryButtons();
533  }
534 
535  if ($this->object->getShowCancel())
536  {
537  $this->populateCancelButtonBlock();
538  }
539 
540  if ($this->isLastQuestionInSequence( $question_gui ))
541  {
542  if ($this->object->getListOfQuestionsEnd())
543  {
545  }
546  else
547  {
549  }
550  }
551  else
552  {
554  }
555 
556  if ($this->object->getShowMarker())
557  {
558  include_once "./Modules/Test/classes/class.ilObjTest.php";
559  $solved_array = ilObjTest::_getSolvedQuestions($this->testSession->getActiveId(), $question_gui->object->getId());
560  $solved = 0;
561 
562  if (count ($solved_array) > 0)
563  {
564  $solved = array_pop($solved_array);
565  $solved = $solved["solved"];
566  }
567 
568  if ($solved==1)
569  {
571  }
572  else
573  {
575  }
576  }
577 
578  $this->populateCharSelector();
579 
580  if ($this->object->getJavaScriptOutput())
581  {
582  $this->tpl->setVariable("JAVASCRIPT_IMAGE", ilUtil::getImagePath("javascript_disable.png"));
583  $this->tpl->setVariable("JAVASCRIPT_IMAGE_ALT", $this->lng->txt("disable_javascript"));
584  $this->tpl->setVariable("JAVASCRIPT_IMAGE_TITLE", $this->lng->txt("disable_javascript"));
585  $this->ctrl->setParameter($this, "tst_javascript", "0");
586  $this->tpl->setVariable("JAVASCRIPT_URL", $this->ctrl->getLinkTarget($this, "gotoQuestion"));
587  }
588  else
589  {
590  $this->tpl->setVariable("JAVASCRIPT_IMAGE", ilUtil::getImagePath("javascript.png"));
591  $this->tpl->setVariable("JAVASCRIPT_IMAGE_ALT", $this->lng->txt("enable_javascript"));
592  $this->tpl->setVariable("JAVASCRIPT_IMAGE_TITLE", $this->lng->txt("enable_javascript"));
593  $this->ctrl->setParameter($this, "tst_javascript", "1");
594  $this->tpl->setVariable("JAVASCRIPT_URL", $this->ctrl->getLinkTarget($this, "gotoQuestion"));
595  }
596 
597  if ($question_gui->object->requiresJsSwitch() && !$this->object->getForceJS())
598  {
599  $this->tpl->touchBlock("jsswitch");
600  }
601 
602  $this->tpl->addJavaScript(ilUtil::getJSLocation("autosave.js", "Modules/Test"));
603 
604  $this->tpl->setVariable("AUTOSAVE_URL", $this->ctrl->getFormAction($this, "autosave", "", true));
605 
606  if ($question_gui->isAutosaveable()&& $this->object->getAutosave())
607  {
608  $this->tpl->touchBlock('autosave');
609  //$this->tpl->setVariable("BTN_SAVE", "Zwischenspeichern");
610  //$this->tpl->setVariable("CMD_SAVE", "gotoquestion_{$sequence}");
611  //$this->tpl->setVariable("AUTOSAVEFORMACTION", str_replace("&amp;", "&", $this->ctrl->getFormAction($this)));
612  $this->tpl->setVariable("AUTOSAVEFORMACTION", str_replace("&amp;", "&", $this->ctrl->getLinkTarget($this, "autosave")));
613  $this->tpl->setVariable("AUTOSAVEINTERVAL", $this->object->getAutosaveIval());
614  }
615 
616  if( $this->object->areObligationsEnabled() && ilObjTest::isQuestionObligatory($question_gui->object->getId()) )
617  {
618  $this->tpl->touchBlock('question_obligatory');
619  $this->tpl->setVariable('QUESTION_OBLIGATORY', $this->lng->txt('required_field'));
620  }
621  }
622 
623  protected function isFirstPageInSequence($sequence)
624  {
625  return $sequence == $this->testSequence->getFirstSequence();
626  }
627 
628  protected function isLastQuestionInSequence(assQuestionGUI $question_gui)
629  {
630  return $this->testSequence->getQuestionForSequence($this->testSequence->getLastSequence()) == $question_gui->object->getId();
631  }
632 
638  protected function canSaveResult()
639  {
640  return !$this->object->endingTimeReached() && !$this->isMaxProcessingTimeReached() && !$this->isNrOfTriesReached();
641  }
642 
646  public function saveQuestionSolution($force = FALSE)
647  {
648  $this->updateWorkingTime();
649  $this->saveResult = FALSE;
650  if (!$force)
651  {
652  $formtimestamp = $_POST["formtimestamp"];
653  if (strlen($formtimestamp) == 0) $formtimestamp = $_GET["formtimestamp"];
654  if ($formtimestamp != $_SESSION["formtimestamp"])
655  {
656  $_SESSION["formtimestamp"] = $formtimestamp;
657  }
658  else
659  {
660  return FALSE;
661  }
662  }
663  // save question solution
664  if ($this->canSaveResult() || $force)
665  {
666  // but only if the ending time is not reached
667  $q_id = $this->testSequence->getQuestionForSequence($_GET["sequence"]);
668  if (is_numeric($q_id) && (int)$q_id)
669  {
670  global $ilUser;
671 
672  $question_gui = $this->object->createQuestionGUI("", $q_id);
673  if ($this->object->getJavaScriptOutput())
674  {
675  $question_gui->object->setOutputType(OUTPUT_JAVASCRIPT);
676  }
677  $pass = NULL;
678  $active_id = $this->testSession->getActiveId();
679  if ($this->object->isRandomTest())
680  {
681  $pass = $this->object->_getPass($active_id);
682  }
683  $this->saveResult = $question_gui->object->persistWorkingState(
684  $active_id, $pass, $this->object->areObligationsEnabled()
685  );
686 
687  // update learning progress (is done in ilTestSession)
688  //include_once("./Services/Tracking/classes/class.ilLPStatusWrapper.php");
689  //ilLPStatusWrapper::_updateStatus($this->object->getId(), $ilUser->getId());
690  }
691  }
692  if ($this->saveResult == FALSE)
693  {
694  $this->ctrl->setParameter($this, "save_error", "1");
695  $_SESSION["previouspost"] = $_POST;
696  }
697  return $this->saveResult;
698  }
699 
700  protected function showInstantResponseCmd()
701  {
702  $this->saveQuestionSolution();
703  $this->ctrl->setParameter($this, "activecommand", "directfeedback");
704  $this->ctrl->redirect($this, "redirectQuestion");
705  }
706 
707  protected function showQuestionListCmd()
708  {
709  $this->saveQuestionSolution();
710  if ($this->saveResult == FALSE)
711  {
712  $this->ctrl->setParameter($this, "activecommand", "");
713  $this->ctrl->redirect($this, "redirectQuestion");
714  }
715  else
716  {
717  $this->ctrl->setParameter($this, "activecommand", "summary");
718  $this->ctrl->redirect($this, "redirectQuestion");
719  }
720  }
721 
722  protected function showQuestionListWithoutSavingCmd()
723  {
724  $this->ctrl->setParameter($this, "activecommand", "summary");
725  $this->ctrl->redirect($this, "redirectQuestion");
726  }
727 
733  protected function postponeQuestionCmd()
734  {
735  $this->saveQuestionSolution();
736  $this->ctrl->setParameter($this, "activecommand", "postpone");
737  $this->ctrl->redirect($this, "redirectQuestion");
738  }
739 
740  protected function handleQuestionActionCmd()
741  {
742  $this->updateWorkingTime();
743 
744  $this->saveQuestionSolution();
745 
746  $this->ctrl->setParameter($this, 'activecommand', 'handleQuestionAction');
747  $this->ctrl->redirect($this, 'redirectQuestion');
748  }
749 
751  {
752  if ($this->testSession->getActiveId() > 0)
753  {
754  if ($this->testSequence->hasRandomQuestionsForPass($this->testSession->getActiveId(), $this->testSession->getPass()) > 0)
755  {
756  // Something went wrong. Maybe the user pressed the start button twice
757  // Questions already exist so there is no need to create new questions
758 
759  global $ilLog, $ilUser;
760 
761  $ilLog->write(
762  __METHOD__.' Random Questions allready exists for user '.
763  $ilUser->getId().' in test '.$this->object->getTestId()
764  );
765 
766  return true;
767  }
768  }
769  else
770  {
771  // This may not happen! If it happens, raise a fatal error...
772 
773  global $ilLog, $ilUser;
774 
775  $ilLog->write(__METHOD__.' '.sprintf(
776  $this->lng->txt("error_random_question_generation"), $ilUser->getId(), $this->object->getTestId()
777  ));
778 
779  return true;
780  };
781 
782  return false;
783  }
784 
786  {
787  global $tree, $ilDB, $ilPluginAdmin;
788 
789  require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetConfig.php';
790  $questionSetConfig = new ilTestRandomQuestionSetConfig($tree, $ilDB, $ilPluginAdmin, $this->object);
791  $questionSetConfig->loadFromDb();
792 
793  require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinitionFactory.php';
794  $sourcePoolDefinitionFactory = new ilTestRandomQuestionSetSourcePoolDefinitionFactory($ilDB, $this->object);
795 
796  require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinitionList.php';
797  $sourcePoolDefinitionList = new ilTestRandomQuestionSetSourcePoolDefinitionList($ilDB, $this->object, $sourcePoolDefinitionFactory);
798  $sourcePoolDefinitionList->loadDefinitions();
799 
800  $this->processLocker->requestRandomPassBuildLock($sourcePoolDefinitionList->hasTaxonomyFilters());
801 
803  {
804  require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetStagingPoolQuestionList.php';
805  $stagingPoolQuestionList = new ilTestRandomQuestionSetStagingPoolQuestionList($ilDB, $ilPluginAdmin);
806 
807  require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetBuilder.php';
808  $questionSetBuilder = ilTestRandomQuestionSetBuilder::getInstance($ilDB, $this->object, $questionSetConfig, $sourcePoolDefinitionList, $stagingPoolQuestionList);
809 
810  $questionSetBuilder->performBuild($this->testSession);
811  }
812 
813  $this->processLocker->releaseRandomPassBuildLock();
814  }
815 }