ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
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 
21 {
26 
30  public function executeCommand()
31  {
32  global $DIC;
33  $ilDB = $DIC['ilDB'];
34  $ilPluginAdmin = $DIC['ilPluginAdmin'];
35  $lng = $DIC['lng'];
36  $ilTabs = $DIC['ilTabs'];
37 
38  $this->checkReadAccess();
39 
40  $ilTabs->clearTargets();
41 
42  $cmd = $this->ctrl->getCmd();
43  $next_class = $this->ctrl->getNextClass($this);
44 
45  $this->ctrl->saveParameter($this, "sequence");
46  $this->ctrl->saveParameter($this, "pmode");
47  $this->ctrl->saveParameter($this, "active_id");
48 
49  $this->initAssessmentSettings();
50 
51  $testSessionFactory = new ilTestSessionFactory($this->object);
52  $this->testSession = $testSessionFactory->getSession($_GET['active_id']);
53 
54  $this->ensureExistingTestSession($this->testSession);
55  $this->checkTestSessionUser($this->testSession);
56 
57  $this->initProcessLocker($this->testSession->getActiveId());
58 
59  $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $this->object);
60  $this->testSequence = $testSequenceFactory->getSequenceByTestSession($this->testSession);
61  $this->testSequence->loadFromDb();
62  $this->testSequence->loadQuestions();
63 
64  require_once 'Modules/Test/classes/class.ilTestQuestionRelatedObjectivesList.php';
65  $this->questionRelatedObjectivesList = new ilTestQuestionRelatedObjectivesList();
66 
67  include_once 'Services/jQuery/classes/class.iljQueryUtil.php';
69  include_once "./Services/YUI/classes/class.ilYuiUtil.php";
71 
73 
74  $cmd = $this->getCommand($cmd);
75 
76  switch ($next_class) {
77  case 'ilassquestionpagegui':
78 
79  $this->checkTestExecutable();
80 
81  $questionId = $this->testSequence->getQuestionForSequence($this->getCurrentSequenceElement());
82 
83  require_once "./Modules/TestQuestionPool/classes/class.ilAssQuestionPageGUI.php";
84  $page_gui = new ilAssQuestionPageGUI($questionId);
85  $ret = $this->ctrl->forwardCommand($page_gui);
86  break;
87 
88  case 'iltestsubmissionreviewgui':
89 
90  $this->checkTestExecutable();
91 
92  require_once './Modules/Test/classes/class.ilTestSubmissionReviewGUI.php';
93  $gui = new ilTestSubmissionReviewGUI($this, $this->object, $this->testSession);
94  $gui->setObjectiveOrientedContainer($this->getObjectiveOrientedContainer());
95  $ret = $this->ctrl->forwardCommand($gui);
96  break;
97 
98  case 'ilassquestionhintrequestgui':
99 
100  $this->checkTestExecutable();
101 
102  $questionGUI = $this->object->createQuestionGUI(
103  "",
104  $this->testSequence->getQuestionForSequence($this->getCurrentSequenceElement())
105  );
106 
107  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
108  $questionHintTracking = new ilAssQuestionHintTracking(
109  $questionGUI->object->getId(),
110  $this->testSession->getActiveId(),
111  $this->testSession->getPass()
112  );
113 
114  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintRequestGUI.php';
115  $gui = new ilAssQuestionHintRequestGUI($this, ilTestPlayerCommands::SHOW_QUESTION, $questionGUI, $questionHintTracking);
116 
117 // fau: testNav - save the 'answer changed' status for viewing hint requests
119 // fau.
120  $ret = $this->ctrl->forwardCommand($gui);
121 
122  break;
123 
124  case 'iltestsignaturegui':
125 
126  $this->checkTestExecutable();
127 
128  require_once './Modules/Test/classes/class.ilTestSignatureGUI.php';
129  $gui = new ilTestSignatureGUI($this);
130  $ret = $this->ctrl->forwardCommand($gui);
131  break;
132 
133  case 'iltestpasswordprotectiongui':
134 
135  $this->checkTestExecutable();
136 
137  require_once 'Modules/Test/classes/class.ilTestPasswordProtectionGUI.php';
138  $gui = new ilTestPasswordProtectionGUI($this->ctrl, $this->tpl, $this->lng, $this, $this->passwordChecker);
139  $ret = $this->ctrl->forwardCommand($gui);
140  break;
141 
142  default:
143 
145  $this->checkTestExecutable();
146  }
147 
148  $cmd .= 'Cmd';
149  $ret = &$this->$cmd();
150  break;
151  }
152  return $ret;
153  }
154 
155  protected function startTestCmd()
156  {
157  global $DIC;
158  $ilUser = $DIC['ilUser'];
159 
160  $_SESSION['tst_pass_finish'] = 0;
161 
162  // ensure existing test session
163  $this->testSession->setUserId($ilUser->getId());
164  $this->testSession->setAnonymousId($_SESSION["tst_access_code"][$this->object->getTestId()]);
165  $this->testSession->setObjectiveOrientedContainerId($this->getObjectiveOrientedContainer()->getObjId());
166  $this->testSession->saveToDb();
167 
168  $active_id = $this->testSession->getActiveId();
169  $this->ctrl->setParameter($this, "active_id", $active_id);
170 
171  $shuffle = $this->object->getShuffleQuestions();
172  if ($this->object->isRandomTest()) {
174 
175  $this->object->loadQuestions();
176  $shuffle = false; // shuffle is already done during the creation of the random questions
177  }
178 
179  assQuestion::_updateTestPassResults(
180  $active_id,
181  $this->testSession->getPass(),
182  $this->object->areObligationsEnabled(),
183  null,
184  $this->object->id
185  );
186 
187  // ensure existing test sequence
188  if (!$this->testSequence->hasSequence()) {
189  $this->testSequence->createNewSequence($this->object->getQuestionCount(), $shuffle);
190  $this->testSequence->saveToDb();
191  }
192 
193  $this->testSequence->loadFromDb();
194  $this->testSequence->loadQuestions();
195 
196  if ($this->testSession->isObjectiveOriented()) {
197  require_once 'Modules/Course/classes/Objectives/class.ilLOTestQuestionAdapter.php';
198  $objectivesAdapter = ilLOTestQuestionAdapter::getInstance($this->testSession);
199 
200  $objectivesAdapter->notifyTestStart($this->testSession, $this->object->getId());
201  $objectivesAdapter->prepareTestPass($this->testSession, $this->testSequence);
202 
203  $objectivesAdapter->buildQuestionRelatedObjectiveList(
204  $this->testSequence,
205  $this->questionRelatedObjectivesList
206  );
207 
208  if ($this->testSequence->hasOptionalQuestions()) {
210 
211  $this->testSequence->reorderOptionalQuestionsToSequenceEnd();
212  $this->testSequence->saveToDb();
213  }
214  }
215 
216  $active_time_id = $this->object->startWorkingTime(
217  $this->testSession->getActiveId(),
218  $this->testSession->getPass()
219  );
220  $_SESSION["active_time_id"] = $active_time_id;
221 
223 
224  $sequenceElement = $this->testSequence->getFirstSequence();
225 
226  $this->ctrl->setParameter($this, 'sequence', $sequenceElement);
227  $this->ctrl->setParameter($this, 'pmode', '');
228 
229  if ($this->object->getListOfQuestionsStart()) {
230  $this->ctrl->redirect($this, ilTestPlayerCommands::QUESTION_SUMMARY);
231  }
232 
233  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
234  }
235 
237  {
238  global $DIC;
239  $ilUser = $DIC['ilUser'];
240 
241  require_once('./Modules/Test/classes/class.ilObjTestAccess.php');
242  require_once('./Services/Tracking/classes/class.ilLPStatusWrapper.php');
243  ilLPStatusWrapper::_updateStatus($this->object->getId(), $ilUser->getId());
244  }
245 
246  private function isValidSequenceElement($sequenceElement)
247  {
248  if ($sequenceElement === false) {
249  return false;
250  }
251 
252  if ($sequenceElement < 1) {
253  return false;
254  }
255 
256  if (!$this->testSequence->getPositionOfSequence($sequenceElement)) {
257  return false;
258  }
259 
260  return true;
261  }
262 
263  protected function showQuestionCmd()
264  {
265  $_SESSION['tst_pass_finish'] = 0;
266 
267  $_SESSION["active_time_id"] = $this->object->startWorkingTime(
268  $this->testSession->getActiveId(),
269  $this->testSession->getPass()
270  );
271 
272  $sequenceElement = $this->getCurrentSequenceElement();
273 
274  if (!$this->isValidSequenceElement($sequenceElement)) {
275  $sequenceElement = $this->testSequence->getFirstSequence();
276  }
277 
278  $this->testSession->setLastSequence($sequenceElement);
279  $this->testSession->saveToDb();
280 
281 
282  $questionId = $this->testSequence->getQuestionForSequence($sequenceElement);
283 
284  if (!(int) $questionId && $this->testSession->isObjectiveOriented()) {
286  }
287 
288  if (!$this->testSequence->isQuestionPresented($questionId)) {
289  $this->testSequence->setQuestionPresented($questionId);
290  $this->testSequence->saveToDb();
291  }
292 
293  $isQuestionWorkedThrough = assQuestion::_isWorkedThrough(
294  $this->testSession->getActiveId(),
295  $questionId,
296  $this->testSession->getPass()
297  );
298 
299  // fau: testNav - always use edit mode, except for fixed answer
300  if ($this->isParticipantsAnswerFixed($questionId)) {
302  $instantResponse = true;
303  } else {
305  $instantResponse = $this->getInstantResponseParameter();
306  }
307  // fau.
308 
309  $questionGui = $this->getQuestionGuiInstance($questionId);
310 
311  if (!($questionGui instanceof assQuestionGUI)) {
312  $this->handleTearsAndAngerQuestionIsNull($questionId, $sequenceElement);
313  }
314 
315  $questionGui->setSequenceNumber($this->testSequence->getPositionOfSequence($sequenceElement));
316  $questionGui->setQuestionCount($this->testSequence->getUserQuestionCount());
317 
318  require_once 'Modules/Test/classes/class.ilTestQuestionHeaderBlockBuilder.php';
319  $headerBlockBuilder = new ilTestQuestionHeaderBlockBuilder($this->lng);
320  $headerBlockBuilder->setHeaderMode($this->object->getTitleOutput());
321  $headerBlockBuilder->setQuestionTitle($questionGui->object->getTitle());
322  $headerBlockBuilder->setQuestionPoints($questionGui->object->getPoints());
323  $headerBlockBuilder->setQuestionPosition($this->testSequence->getPositionOfSequence($sequenceElement));
324  $headerBlockBuilder->setQuestionCount($this->testSequence->getUserQuestionCount());
325  $headerBlockBuilder->setQuestionPostponed($this->testSequence->isPostponedQuestion($questionId));
326  $headerBlockBuilder->setQuestionObligatory(
327  $this->object->areObligationsEnabled() && ilObjTest::isQuestionObligatory($questionGui->object->getId())
328  );
329  if ($this->testSession->isObjectiveOriented()) {
330  require_once 'Modules/Course/classes/Objectives/class.ilLOTestQuestionAdapter.php';
331  $objectivesAdapter = ilLOTestQuestionAdapter::getInstance($this->testSession);
332  $objectivesAdapter->buildQuestionRelatedObjectiveList($this->testSequence, $this->questionRelatedObjectivesList);
333  $this->questionRelatedObjectivesList->loadObjectivesTitles();
334 
335  $objectivesString = $this->questionRelatedObjectivesList->getQuestionRelatedObjectiveTitles($questionId);
336  $headerBlockBuilder->setQuestionRelatedObjectives($objectivesString);
337  }
338  $questionGui->setQuestionHeaderBlockBuilder($headerBlockBuilder);
339 
340  $this->prepareTestPage($presentationMode, $sequenceElement, $questionId);
341 
342  $navigationToolbarGUI = $this->getTestNavigationToolbarGUI();
343  $navigationToolbarGUI->setFinishTestButtonEnabled(true);
344 
345  $isNextPrimary = $this->handlePrimaryButton($navigationToolbarGUI, $questionId);
346 
347  $this->ctrl->setParameter($this, 'sequence', $sequenceElement);
348  $this->ctrl->setParameter($this, 'pmode', $presentationMode);
349  $formAction = $this->ctrl->getFormAction($this, ilTestPlayerCommands::SUBMIT_INTERMEDIATE_SOLUTION);
350 
351  switch ($presentationMode) {
353 
354 // fau: testNav - enable navigation toolbar in edit mode
355  $navigationToolbarGUI->setDisabledStateEnabled(false);
356 // fau.
357  $this->showQuestionEditable($questionGui, $formAction, $isQuestionWorkedThrough, $instantResponse);
358 
359  break;
360 
362 
363  if ($this->testSequence->isQuestionOptional($questionGui->object->getId())) {
365  }
366 
367  $this->showQuestionViewable($questionGui, $formAction, $isQuestionWorkedThrough, $instantResponse);
368 
369  break;
370 
371  default:
372 
373  require_once 'Modules/Test/exceptions/class.ilTestException.php';
374  throw new ilTestException('no presentation mode given');
375  }
376 
377  $navigationToolbarGUI->build();
378  $this->populateTestNavigationToolbar($navigationToolbarGUI);
379 
380  // fau: testNav - enable the question navigation in edit mode
381  $this->populateQuestionNavigation($sequenceElement, false, $isNextPrimary);
382  // fau.
383 
384  if ($instantResponse) {
385  // fau: testNav - always use authorized solution for instant feedback
387  $questionGui,
388  true
389  );
390  // fau.
391  }
392 
393  // fau: testNav - add feedback modal
394  if ($this->isForcedFeedbackNavUrlRegistered()) {
397  }
398  // fau.
399  }
400 
401  protected function editSolutionCmd()
402  {
403  $this->ctrl->setParameter($this, 'pmode', ilTestPlayerAbstractGUI::PRESENTATION_MODE_EDIT);
404  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
405  }
406 
407  protected function submitSolutionAndNextCmd()
408  {
409  if ($this->object->isForceInstantFeedbackEnabled()) {
410  return $this->submitSolutionCmd();
411  }
412 
413  if ($this->saveQuestionSolution(true, false)) {
414  $questionId = $this->testSequence->getQuestionForSequence(
416  );
417 
419 
420  $nextSequenceElement = $this->testSequence->getNextSequence($this->getCurrentSequenceElement());
421 
422  if (!$this->isValidSequenceElement($nextSequenceElement)) {
423  $nextSequenceElement = $this->testSequence->getFirstSequence();
424  }
425 
426  $this->testSession->setLastSequence($nextSequenceElement);
427  $this->testSession->saveToDb();
428 
429  $this->ctrl->setParameter($this, 'sequence', $nextSequenceElement);
430  $this->ctrl->setParameter($this, 'pmode', '');
431  }
432 
433  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
434  }
435 
436  protected function submitSolutionCmd()
437  {
438  if ($this->saveQuestionSolution(true, false)) {
439  $questionId = $this->testSequence->getQuestionForSequence(
441  );
442 
444 
445  if ($this->object->isForceInstantFeedbackEnabled()) {
446  $this->ctrl->setParameter($this, 'instresp', 1);
447 
448  $this->testSequence->setQuestionChecked($questionId);
449  $this->testSequence->saveToDb();
450  }
451 
452  if ($this->getNextCommandParameter()) {
453  if ($this->getNextSequenceParameter()) {
454  $this->ctrl->setParameter($this, 'sequence', $this->getNextSequenceParameter());
455  $this->ctrl->setParameter($this, 'pmode', '');
456  }
457 
458  $this->ctrl->redirect($this, $this->getNextCommandParameter());
459  }
460 
461  $this->ctrl->setParameter($this, 'pmode', ilTestPlayerAbstractGUI::PRESENTATION_MODE_VIEW);
462  } else {
463  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
464  }
465 
466  // fau: testNav - remember to prevent the navigation confirmation
468  // fau.
469 
470  // fau: testNav - handle navigation after saving
471  if ($this->getNavigationUrlParameter()) {
473  } else {
474  $this->ctrl->saveParameter($this, 'sequence');
475  }
476  // fau.
477  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
478  }
479 
480  protected function discardSolutionCmd()
481  {
482  $currentSequenceElement = $this->getCurrentSequenceElement();
483 
484  $currentQuestionOBJ = $this->getQuestionInstance(
485  $this->testSequence->getQuestionForSequence($currentSequenceElement)
486  );
487 
488  $currentQuestionOBJ->resetUsersAnswer(
489  $this->testSession->getActiveId(),
490  $this->testSession->getPass()
491  );
492 
493  $this->ctrl->saveParameter($this, 'sequence');
494 
495  $this->ctrl->setParameter($this, 'pmode', ilTestPlayerAbstractGUI::PRESENTATION_MODE_VIEW);
496 
497  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
498  }
499 
500  protected function skipQuestionCmd()
501  {
502  $curSequenceElement = $this->getCurrentSequenceElement();
503  $nextSequenceElement = $this->testSequence->getNextSequence($curSequenceElement);
504 
505  if (!$this->isValidSequenceElement($nextSequenceElement)) {
506  $nextSequenceElement = $this->testSequence->getFirstSequence();
507  }
508 
509  if ($this->object->isPostponingEnabled()) {
510  $this->testSequence->postponeSequence($curSequenceElement);
511  $this->testSequence->saveToDb();
512  }
513 
514  $this->ctrl->setParameter($this, 'sequence', $nextSequenceElement);
515  $this->ctrl->setParameter($this, 'pmode', '');
516 
517  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
518  }
519 
520  protected function handleQuestionPostponing($sequenceElement)
521  {
522  $questionId = $this->testSequence->getQuestionForSequence($sequenceElement);
523 
524  $isQuestionWorkedThrough = assQuestion::_isWorkedThrough(
525  $this->testSession->getActiveId(),
526  $questionId,
527  $this->testSession->getPass()
528  );
529 
530  if (!$isQuestionWorkedThrough) {
531  $this->testSequence->postponeQuestion($questionId);
532  $this->testSequence->saveToDb();
533  }
534  }
535 
536  protected function nextQuestionCmd()
537  {
538  $lastSequenceElement = $this->getCurrentSequenceElement();
539  $nextSequenceElement = $this->testSequence->getNextSequence($lastSequenceElement);
540 
541  if ($this->object->isPostponingEnabled()) {
542  $this->handleQuestionPostponing($lastSequenceElement);
543  }
544 
545  if (!$this->isValidSequenceElement($nextSequenceElement)) {
546  $nextSequenceElement = $this->testSequence->getFirstSequence();
547  }
548 
549  $this->ctrl->setParameter($this, 'sequence', $nextSequenceElement);
550  $this->ctrl->setParameter($this, 'pmode', '');
551 
552  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
553  }
554 
555  protected function previousQuestionCmd()
556  {
557  $sequenceElement = $this->testSequence->getPreviousSequence(
559  );
560 
561  if (!$this->isValidSequenceElement($sequenceElement)) {
562  $sequenceElement = $this->testSequence->getLastSequence();
563  }
564 
565  $this->ctrl->setParameter($this, 'sequence', $sequenceElement);
566  $this->ctrl->setParameter($this, 'pmode', '');
567 
568  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
569  }
570 
571  protected function isFirstQuestionInSequence($sequenceElement)
572  {
573  return $sequenceElement == $this->testSequence->getFirstSequence();
574  }
575 
576  protected function isLastQuestionInSequence($sequenceElement)
577  {
578  return $sequenceElement == $this->testSequence->getLastSequence();
579  }
580 
586  protected function canSaveResult()
587  {
588  return !$this->object->endingTimeReached() && !$this->isMaxProcessingTimeReached() && !$this->isNrOfTriesReached();
589  }
590 
594  protected function getCurrentQuestionId()
595  {
596  return $this->testSequence->getQuestionForSequence($_GET["sequence"]);
597  }
598 
602  public function saveQuestionSolution($authorized = true, $force = false)
603  {
604  $this->updateWorkingTime();
605  $this->saveResult = false;
606  if (!$force) {
607  $formtimestamp = $_POST["formtimestamp"];
608  if (strlen($formtimestamp) == 0) {
609  $formtimestamp = $_GET["formtimestamp"];
610  }
611  if ($formtimestamp != $_SESSION["formtimestamp"]) {
612  $_SESSION["formtimestamp"] = $formtimestamp;
613  } else {
614  return false;
615  }
616  }
617  // save question solution
618  if ($this->canSaveResult() || $force) {
619  // but only if the ending time is not reached
620  $q_id = $this->testSequence->getQuestionForSequence($_GET["sequence"]);
621 
622  if ($this->isParticipantsAnswerFixed($q_id)) {
623  // should only be reached by firebugging the disabled form in ui
624  throw new ilTestException('not allowed request');
625  }
626 
627  if (is_numeric($q_id) && (int) $q_id) {
628  $questionOBJ = $this->getQuestionInstance($q_id);
629  $pass = null;
630  $active_id = $this->testSession->getActiveId();
631  if ($this->object->isRandomTest()) {
632  $pass = ilObjTest::_getPass($active_id);
633  }
634  $this->saveResult = $questionOBJ->persistWorkingState(
635  $active_id,
636  $pass,
637  $this->object->areObligationsEnabled(),
638  $authorized
639  );
640 
641  if ($authorized && $this->testSession->isObjectiveOriented()) {
642  require_once 'Modules/Course/classes/Objectives/class.ilLOTestQuestionAdapter.php';
643  $objectivesAdapter = ilLOTestQuestionAdapter::getInstance($this->testSession);
644  $objectivesAdapter->updateQuestionResult($this->testSession, $questionOBJ);
645  }
646 
647  if ($authorized && $this->object->isSkillServiceToBeConsidered()) {
648  $this->handleSkillTriggering($this->testSession);
649  }
650  }
651  }
652 
653  if ($this->saveResult == false || (!$questionOBJ->validateSolutionSubmit() && $questionOBJ->savePartial()) ) {
654  $this->ctrl->setParameter($this, "save_error", "1");
655  $_SESSION["previouspost"] = $_POST;
656  }
657 
658  return $this->saveResult;
659  }
660 
661  protected function showInstantResponseCmd()
662  {
663  $questionId = $this->testSequence->getQuestionForSequence(
665  );
666 
667  if ($this->getAnswerChangedParameter() && !$this->isParticipantsAnswerFixed($questionId)) {
668  if ($this->saveQuestionSolution(true)) {
670  $this->setAnswerChangedParameter(false);
671  } else {
672  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
673  }
674  $this->testSequence->setQuestionChecked($questionId);
675  $this->testSequence->saveToDb();
676  }
677 
678  $this->ctrl->setParameter($this, 'instresp', 1);
679 
680  // fau: testNav - handle navigation after feedback
681  if ($this->getNavigationUrlParameter()) {
684  }
685  // fau.
686  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
687  }
688 
689  protected function handleQuestionActionCmd()
690  {
691  $questionId = $this->testSequence->getQuestionForSequence(
693  );
694 
695  if (!$this->isParticipantsAnswerFixed($questionId)) {
696  $this->updateWorkingTime();
697  $this->saveQuestionSolution(false);
698  // fau: testNav - add changed status of the question
699  $this->setAnswerChangedParameter(true);
700  // fau.
701  }
702 
703  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
704  }
705 
707  {
708  if ($this->testSession->getActiveId() > 0) {
709  if ($this->testSequence->hasRandomQuestionsForPass($this->testSession->getActiveId(), $this->testSession->getPass()) > 0) {
710  // Something went wrong. Maybe the user pressed the start button twice
711  // Questions already exist so there is no need to create new questions
712 
713  global $DIC;
714  $ilLog = $DIC['ilLog'];
715  $ilUser = $DIC['ilUser'];
716 
717  $ilLog->write(
718  __METHOD__ . ' Random Questions allready exists for user ' .
719  $ilUser->getId() . ' in test ' . $this->object->getTestId()
720  );
721 
722  return true;
723  }
724  } else {
725  // This may not happen! If it happens, raise a fatal error...
726 
727  global $DIC;
728  $ilLog = $DIC['ilLog'];
729  $ilUser = $DIC['ilUser'];
730 
731  $ilLog->write(__METHOD__ . ' ' . sprintf(
732  $this->lng->txt("error_random_question_generation"),
733  $ilUser->getId(),
734  $this->object->getTestId()
735  ));
736 
737  return true;
738  };
739 
740  return false;
741  }
742 
744  {
745  global $DIC;
746  $tree = $DIC['tree'];
747  $ilDB = $DIC['ilDB'];
748  $ilPluginAdmin = $DIC['ilPluginAdmin'];
749 
750  require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetConfig.php';
751  $questionSetConfig = new ilTestRandomQuestionSetConfig($tree, $ilDB, $ilPluginAdmin, $this->object);
752  $questionSetConfig->loadFromDb();
753 
754  require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinitionFactory.php';
755  $sourcePoolDefinitionFactory = new ilTestRandomQuestionSetSourcePoolDefinitionFactory($ilDB, $this->object);
756 
757  require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinitionList.php';
758  $sourcePoolDefinitionList = new ilTestRandomQuestionSetSourcePoolDefinitionList($ilDB, $this->object, $sourcePoolDefinitionFactory);
759  $sourcePoolDefinitionList->loadDefinitions();
760 
761  $this->processLocker->executeRandomPassBuildOperation(function () use ($ilDB, $ilPluginAdmin, $questionSetConfig, $sourcePoolDefinitionList) {
763  require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetStagingPoolQuestionList.php';
764  $stagingPoolQuestionList = new ilTestRandomQuestionSetStagingPoolQuestionList($ilDB, $ilPluginAdmin);
765 
766  require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetBuilder.php';
767  $questionSetBuilder = ilTestRandomQuestionSetBuilder::getInstance($ilDB, $this->object, $questionSetConfig, $sourcePoolDefinitionList, $stagingPoolQuestionList);
768 
769  $questionSetBuilder->performBuild($this->testSession);
770  }
771  }, $sourcePoolDefinitionList->hasTaxonomyFilters());
772  }
773 
777  protected function resumePlayerCmd()
778  {
779  $this->handleUserSettings();
780 
781  $active_id = $this->testSession->getActiveId();
782  $this->ctrl->setParameter($this, "active_id", $active_id);
783 
784  $active_time_id = $this->object->startWorkingTime($active_id, $this->testSession->getPass());
785  $_SESSION["active_time_id"] = $active_time_id;
786  $_SESSION['tst_pass_finish'] = 0;
787 
788  if ($this->object->isRandomTest()) {
789  if (!$this->testSequence->hasRandomQuestionsForPass($active_id, $this->testSession->getPass())) {
790  // create a new set of random questions
792  }
793  }
794 
795  $shuffle = $this->object->getShuffleQuestions();
796  if ($this->object->isRandomTest()) {
797  $shuffle = false;
798  }
799 
800  assQuestion::_updateTestPassResults(
801  $active_id,
802  $this->testSession->getPass(),
803  $this->object->areObligationsEnabled(),
804  null,
805  $this->object->id
806  );
807 
808  // ensure existing test sequence
809  if (!$this->testSequence->hasSequence()) {
810  $this->testSequence->createNewSequence($this->object->getQuestionCount(), $shuffle);
811  $this->testSequence->saveToDb();
812  }
813 
814  if ($this->object->getListOfQuestionsStart()) {
815  $this->ctrl->redirect($this, ilTestPlayerCommands::QUESTION_SUMMARY);
816  }
817 
818  $this->ctrl->setParameter($this, 'sequence', $this->testSession->getLastSequence());
819  $this->ctrl->setParameter($this, 'pmode', '');
820  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
821  }
822 
823  protected function isShowingPostponeStatusReguired($questionId)
824  {
825  return $this->testSequence->isPostponedQuestion($questionId);
826  }
827 
829  {
830  global $DIC;
831  $ilDB = $DIC['ilDB'];
832  $ilUser = $DIC['ilUser'];
833 
834  $assSettings = new ilSetting('assessment');
835 
836  include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
837  $isAssessmentLogEnabled = ilObjAssessmentFolder::_enabledAssessmentLogging();
838 
839  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionUserSolutionAdopter.php';
840  $userSolutionAdopter = new ilAssQuestionUserSolutionAdopter($ilDB, $assSettings, $isAssessmentLogEnabled);
841 
842  $userSolutionAdopter->setUserId($ilUser->getId());
843  $userSolutionAdopter->setActiveId($this->testSession->getActiveId());
844  $userSolutionAdopter->setTargetPass($this->testSequence->getPass());
845  $userSolutionAdopter->setQuestionIds($this->testSequence->getOptionalQuestions());
846 
847  $userSolutionAdopter->perform();
848  }
849 
850  abstract protected function populateQuestionOptionalMessage();
851 
852  protected function isOptionalQuestionAnsweringConfirmationRequired($sequenceKey)
853  {
854  if ($this->testSequence->isAnsweringOptionalQuestionsConfirmed()) {
855  return false;
856  }
857 
858  $questionId = $this->testSequence->getQuestionForSequence($sequenceKey);
859 
860  if (!$this->testSequence->isQuestionOptional($questionId)) {
861  return false;
862  }
863 
864  return true;
865  }
866 
868  {
869  return true;
870  }
871 
873  {
874  ilUtil::sendFailure(sprintf($this->lng->txt('tst_objective_oriented_test_pass_without_questions'), $this->object->getTitle()), true);
875 
876  $this->backToInfoScreenCmd();
877  }
878 
882  protected function handlePrimaryButton(ilTestNavigationToolbarGUI $navigationToolbarGUI, $currentQuestionId)
883  {
884  $isNextPrimary = true;
885 
886  if ($this->object->isForceInstantFeedbackEnabled()) {
887  $isNextPrimary = false;
888  }
889 
890  $questionsMissingResult = assQuestion::getQuestionsMissingResultRecord(
891  $this->testSession->getActiveId(),
892  $this->testSession->getPass(),
893  $this->testSequence->getOrderedSequenceQuestions()
894  );
895 
896  if (!count($questionsMissingResult)) {
897  $navigationToolbarGUI->setFinishTestButtonPrimary(true);
898  $isNextPrimary = false;
899  } elseif (count($questionsMissingResult) == 1) {
900  $lastOpenQuestion = current($questionsMissingResult);
901 
902  if ($currentQuestionId == $lastOpenQuestion) {
903  $navigationToolbarGUI->setFinishTestButtonPrimary(true);
904  $isNextPrimary = false;
905  }
906  }
907 
908  return $isNextPrimary;
909  }
910 }
isShowingPostponeStatusReguired($questionId)
checkTestSessionUser(ilTestSession $testSession)
isValidSequenceElement($sequenceElement)
removeIntermediateSolution()
remove an auto-saved solution of the current question
populateQuestionOptionalMessage()
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test.
setAnswerChangedParameter($changed=true)
Set the &#39;answer changed&#39; url parameter for generated links.
$_SESSION["AccountId"]
Signature Plugin Class.
global $DIC
Definition: saml.php:7
$_GET["client_id"]
static getQuestionsMissingResultRecord($activeId, $pass, $questionIds)
showQuestionEditable(assQuestionGUI $questionGui, $formAction, $isQuestionWorkedThrough, $instantResponse)
Output class for assessment test execution.
static _updateStatus($a_obj_id, $a_usr_id, $a_obj=null, $a_percentage=false, $a_force_raise=false)
Update status.
updateWorkingTime()
updates working time and stores state saveresult to see if question has to be stored or not ...
isLastQuestionInSequence($sequenceElement)
isFirstQuestionInSequence($sequenceElement)
executeCommand()
Execute Command.
resumePlayerCmd()
Resume a test at the last position.
handleUserSettings()
Handles some form parameters on starting and resuming a test.
Question page GUI class.
Base Exception for all Exceptions relating to Modules/Test.
prepareTestPage($presentationMode, $sequenceElement, $questionId)
populateInstantResponseBlocks(assQuestionGUI $questionGui, $authorizedSolution)
static isQuestionObligatory($question_id)
checks wether the question with given id is marked as obligatory or not
ensureExistingTestSession(ilTestSession $testSession)
populateQuestionNavigation($sequenceElement, $disabled, $primaryNext)
static getInstance(ilTestSession $a_test_session)
static _enabledAssessmentLogging()
check wether assessment logging is enabled or not
isOptionalQuestionAnsweringConfirmationRequired($sequenceKey)
static _isWorkedThrough($active_id, $question_id, $pass=null)
Returns true if the question was worked through in the given pass Worked through means that the user ...
handleSkillTriggering(ilTestSession $testSession)
Class ilTestSubmissionReviewGUI.
handleQuestionPostponing($sequenceElement)
getCommand($cmd)
Retrieves the ilCtrl command.
saveNavigationPreventConfirmation()
Save the save the switch to prevent the navigation confirmation.
populateTestNavigationToolbar(ilTestNavigationToolbarGUI $toolbarGUI)
$ilUser
Definition: imgupload.php:18
static getInstance(ilDBInterface $db, ilObjTest $testOBJ, ilTestRandomQuestionSetConfig $questionSetConfig, ilTestRandomQuestionSetSourcePoolDefinitionList $sourcePoolDefinitionList, ilTestRandomQuestionSetStagingPoolQuestionList $stagingPoolQuestionList)
handlePrimaryButton(ilTestNavigationToolbarGUI $navigationToolbarGUI, $currentQuestionId)
getAnswerChangedParameter()
Get the &#39;answer changed&#39; status from the current request It may be set by ilTestPlayerNavigationContr...
Basic GUI class for assessment questions.
static sendFailure($a_info="", $a_keep=false)
Send Failure Message to Screen.
setFinishTestButtonPrimary($finishTestButtonPrimary)
registerForcedFeedbackNavUrl($forcedFeedbackNavUrl)
saveQuestionSolution($authorized=true, $force=false)
saves the user input of a question
showQuestionViewable(assQuestionGUI $questionGui, $formAction, $isQuestionWorkedThrough, $instantResponse)
populateInstantResponseModal(assQuestionGUI $questionGui, $navUrl)
global $ilDB
$ret
Definition: parser.php:6
getQuestionGuiInstance($questionId, $fromCache=true)
static initjQuery($a_tpl=null)
inits and adds the jQuery JS-File to the global or a passed template
getQuestionInstance($questionId, $fromCache=true)
handleTearsAndAngerQuestionIsNull($questionId, $sequenceElement)
isMaxProcessingTimeReached()
Checks wheather the maximum processing time is reached or not.
static redirect($a_script)
$_POST["username"]
static initConnectionWithAnimation()
Init YUI Connection module.
canSaveResult()
Returns TRUE if the answers of the current user could be saved.
Output class for assessment test execution.