ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
class.ilTestPlayerDynamicQuestionSetGUI.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 
30 {
34  private $dynamicQuestionSetConfig = null;
35 
39  protected $testSequence;
40 
44  protected $testSession;
45 
49  public function executeCommand()
50  {
51  global $DIC;
52  $ilDB = $DIC['ilDB'];
53  $lng = $DIC['lng'];
54  $ilPluginAdmin = $DIC['ilPluginAdmin'];
55  $ilTabs = $DIC['ilTabs'];
56  $tree = $DIC['tree'];
57 
58  $ilTabs->clearTargets();
59 
60  $this->ctrl->saveParameter($this, "sequence");
61  $this->ctrl->saveParameter($this, "active_id");
62 
63  $this->initAssessmentSettings();
64 
65  $DIC->globalScreen()->tool()->context()->current()->addAdditionalData(
67  $this->object->getKioskMode()
68  );
69 
70  require_once 'Modules/Test/classes/class.ilObjTestDynamicQuestionSetConfig.php';
71  $this->dynamicQuestionSetConfig = new ilObjTestDynamicQuestionSetConfig($tree, $ilDB, $ilPluginAdmin, $this->object);
72  $this->dynamicQuestionSetConfig->loadFromDb();
73 
74  $testSessionFactory = new ilTestSessionFactory($this->object);
75  $this->testSession = $testSessionFactory->getSession($_GET['active_id']);
76 
77  $this->ensureExistingTestSession($this->testSession);
78  $this->checkTestSessionUser($this->testSession);
79  $this->initProcessLocker($this->testSession->getActiveId());
80 
81  $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $this->object);
82  $this->testSequence = $testSequenceFactory->getSequenceByTestSession($this->testSession);
83  $this->testSequence->loadFromDb();
84 
85  if ($this->object->isInstantFeedbackAnswerFixationEnabled()) {
86  $this->testSequence->setPreventCheckedQuestionsFromComingUpEnabled(true);
87  }
88 
89  include_once 'Services/jQuery/classes/class.iljQueryUtil.php';
91  include_once "./Services/YUI/classes/class.ilYuiUtil.php";
93  if ($this->object->getKioskMode()) {
94  include_once 'Services/UIComponent/Overlay/classes/class.ilOverlayGUI.php';
96  }
97 
99 
100  $cmd = $this->ctrl->getCmd();
101  $nextClass = $this->ctrl->getNextClass($this);
102 
103  switch ($nextClass) {
104  case 'ilassquestionpagegui':
105 
106  $questionId = $this->testSession->getCurrentQuestionId();
107 
108  require_once "./Modules/TestQuestionPool/classes/class.ilAssQuestionPageGUI.php";
109  $page_gui = new ilAssQuestionPageGUI($questionId);
110  $ret = $this->ctrl->forwardCommand($page_gui);
111  break;
112 
113  case 'ilassquestionhintrequestgui':
114 
115  $this->ctrl->saveParameter($this, 'pmode');
116 
117  $questionGUI = $this->object->createQuestionGUI(
118  "",
119  $this->testSession->getCurrentQuestionId()
120  );
121 
122  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php';
123  $questionHintTracking = new ilAssQuestionHintTracking(
124  $questionGUI->object->getId(),
125  $this->testSession->getActiveId(),
126  $this->testSession->getPass()
127  );
128 
129  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintRequestGUI.php';
130  $gui = new ilAssQuestionHintRequestGUI(
131  $this,
133  $questionGUI,
134  $questionHintTracking
135  );
136 
137 // fau: testNav - save the 'answer changed status' for viewing hint requests
139 // fau.
140  $this->ctrl->forwardCommand($gui);
141 
142  break;
143 
144  case 'ildynamicquestionsetstatistictablegui':
145 
146  $this->ctrl->forwardCommand($this->buildQuestionSetFilteredStatisticTableGUI());
147 
148  break;
149 
150  case 'iltestpasswordprotectiongui':
151  require_once 'Modules/Test/classes/class.ilTestPasswordProtectionGUI.php';
152  $gui = new ilTestPasswordProtectionGUI($this->ctrl, $this->tpl, $this->lng, $this, $this->passwordChecker);
153  $ret = $this->ctrl->forwardCommand($gui);
154  break;
155 
156  default:
157 
158  $cmd .= 'Cmd';
159  $ret = &$this->$cmd();
160  break;
161  }
162 
163  return $ret;
164  }
165 
169  protected function getCurrentQuestionId()
170  {
171  return $this->testSession->getCurrentQuestionId();
172  }
173 
177  protected function resumePlayerCmd()
178  {
179  if ($this->object->checkMaximumAllowedUsers() == false) {
181  }
182 
183  $this->handleUserSettings();
184 
185  if ($this->dynamicQuestionSetConfig->isAnyQuestionFilterEnabled()) {
186  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION_SELECTION);
187  }
188 
189  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
190  }
191 
192  protected function startTestCmd()
193  {
194  $this->testSession->setCurrentQuestionId(null); // no question "came up" yet
195 
196  $this->testSession->saveToDb();
197 
198  $this->ctrl->setParameter($this, 'active_id', $this->testSession->getActiveId());
199 
200  assQuestion::_updateTestPassResults($this->testSession->getActiveId(), $this->testSession->getPass(), false, null, $this->object->id);
201 
202  $_SESSION['active_time_id'] = $this->object->startWorkingTime(
203  $this->testSession->getActiveId(),
204  $this->testSession->getPass()
205  );
206 
207  $this->ctrl->saveParameter($this, 'tst_javascript');
208 
209  if ($this->dynamicQuestionSetConfig->isAnyQuestionFilterEnabled()) {
210  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION_SELECTION);
211  }
212 
213  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
214  }
215 
216  protected function showQuestionSelectionCmd()
217  {
218  $this->prepareSummaryPage();
219 
220  $this->testSequence->loadQuestions(
221  $this->dynamicQuestionSetConfig,
222  $this->testSession->getQuestionSetFilterSelection()
223  );
224 
225  $this->testSequence->cleanupQuestions($this->testSession);
226 
227  $this->testSequence->saveToDb();
228 
229  require_once 'Services/UIComponent/Toolbar/classes/class.ilToolbarGUI.php';
230  $toolbarGUI = new ilToolbarGUI();
231 
232  require_once 'Services/UIComponent/Button/classes/class.ilLinkButton.php';
233  $button = ilLinkButton::getInstance();
234  $button->setUrl($this->getStartTestFromQuestionSelectionLink());
235  $button->setCaption($this->getEnterTestButtonLangVar());
236  $button->setPrimary(true);
237  $toolbarGUI->addButtonInstance($button);
238 
239  if ($this->object->getShowCancel()) {
240  $button = ilLinkButton::getInstance();
241  $button->setUrl($this->ctrl->getLinkTarget(
242  $this,
244  ));
245  $button->setCaption('cancel_test');
246  $toolbarGUI->addButtonInstance($button);
247  }
248 
249  if ($this->object->isPassDeletionAllowed()) {
250  require_once 'Modules/Test/classes/confirmations/class.ilTestPassDeletionConfirmationGUI.php';
251 
252  $toolbarGUI->addButton(
253  $this->lng->txt('tst_dyn_test_pass_deletion_button'),
255  );
256  }
257 
258  $filteredData = array($this->buildQuestionSetAnswerStatisticRowArray(
259  $this->testSequence->getFilteredQuestionsData(),
260  $this->testSequence->getTrackedQuestionList()
261  )); #vd($filteredData);
262  $filteredTableGUI = $this->buildQuestionSetFilteredStatisticTableGUI();
263  $filteredTableGUI->setData($filteredData);
264 
265  $completeData = array($this->buildQuestionSetAnswerStatisticRowArray(
266  $this->testSequence->getCompleteQuestionsData(),
267  $this->testSequence->getTrackedQuestionList()
268  )); #vd($completeData);
269  $completeTableGUI = $this->buildQuestionSetCompleteStatisticTableGUI();
270  $completeTableGUI->setData($completeData);
271 
272  $content = $this->ctrl->getHTML($toolbarGUI);
273  $content .= $this->ctrl->getHTML($filteredTableGUI);
274  $content .= $this->ctrl->getHTML($completeTableGUI);
275 
276  $this->tpl->setVariable('TABLE_LIST_OF_QUESTIONS', $content);
277 
278  if ($this->object->getEnableProcessingTime()) {
279  $this->outProcessingTime($this->testSession->getActiveId());
280  }
281  }
282 
283  protected function filterQuestionSelectionCmd()
284  {
285  $tableGUI = $this->buildQuestionSetFilteredStatisticTableGUI();
286  $tableGUI->writeFilterToSession();
287 
288  $taxFilterSelection = array();
289  $answerStatusFilterSelection = ilAssQuestionList::ANSWER_STATUS_FILTER_ALL_NON_CORRECT;
290 
291  foreach ($tableGUI->getFilterItems() as $item) {
292  if (strpos($item->getPostVar(), 'tax_') !== false) {
293  $taxId = substr($item->getPostVar(), strlen('tax_'));
294  $taxFilterSelection[$taxId] = $item->getValue();
295  } elseif ($item->getPostVar() == 'question_answer_status') {
296  $answerStatusFilterSelection = $item->getValue();
297  }
298  }
299 
300  $this->testSession->getQuestionSetFilterSelection()->setTaxonomySelection($taxFilterSelection);
301  $this->testSession->getQuestionSetFilterSelection()->setAnswerStatusSelection($answerStatusFilterSelection);
302  $this->testSession->saveToDb();
303 
304  $this->testSequence->resetTrackedQuestionList();
305  $this->testSequence->saveToDb();
306 
307 
308  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION_SELECTION);
309  }
310 
311  protected function resetQuestionSelectionCmd()
312  {
313  $tableGUI = $this->buildQuestionSetFilteredStatisticTableGUI();
314  $tableGUI->resetFilter();
315 
316  $this->testSession->getQuestionSetFilterSelection()->setTaxonomySelection(array());
317  $this->testSession->getQuestionSetFilterSelection()->setAnswerStatusSelection(null);
318  $this->testSession->saveToDb();
319 
320  $this->testSequence->resetTrackedQuestionList();
321  $this->testSequence->saveToDb();
322 
323  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION_SELECTION);
324  }
325 
326  protected function previousQuestionCmd()
327  {
328  // nothing to do, won't be called
329  }
330 
331  protected function fromPassDeletionCmd()
332  {
333  $this->resetCurrentQuestion();
334  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
335  }
336 
337  protected function nextQuestionCmd()
338  {
339  $isWorkedThrough = assQuestion::_isWorkedThrough(
340  $this->testSession->getActiveId(),
341  $this->testSession->getCurrentQuestionId(),
342  $this->testSession->getPass()
343  );
344 
345  if (!$isWorkedThrough) {
346  $this->testSequence->setQuestionPostponed($this->testSession->getCurrentQuestionId());
347  $this->testSequence->saveToDb();
348  }
349 
350  $this->resetCurrentQuestion();
351 
352  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
353  }
354 
355  protected function markQuestionCmd()
356  {
357  global $DIC;
358  $ilUser = $DIC['ilUser'];
359  $this->object->setQuestionSetSolved(1, $this->testSession->getCurrentQuestionId(), $ilUser->getId());
360 
361  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
362  }
363 
364  protected function unmarkQuestionCmd()
365  {
366  global $DIC;
367  $ilUser = $DIC['ilUser'];
368  $this->object->setQuestionSetSolved(0, $this->testSession->getCurrentQuestionId(), $ilUser->getId());
369 
370  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
371  }
372 
373  protected function editSolutionCmd()
374  {
375  $this->ctrl->setParameter($this, 'pmode', ilTestPlayerAbstractGUI::PRESENTATION_MODE_EDIT);
376  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
377  }
378 
379  protected function submitSolutionAndNextCmd()
380  {
381  if ($this->object->isForceInstantFeedbackEnabled()) {
382  return $this->submitSolutionCmd();
383  }
384 
385  if ($this->saveQuestionSolution(true, false)) {
386  $questionId = $this->testSession->getCurrentQuestionId();
387 
388  $this->getQuestionInstance($questionId)->removeIntermediateSolution(
389  $this->testSession->getActiveId(),
390  $this->testSession->getPass()
391  );
392 
394 
395  $this->ctrl->setParameter($this, 'pmode', '');
396 
397  $this->resetCurrentQuestion();
398  }
399 
400  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
401  }
402 
403  protected function submitSolutionCmd()
404  {
405  if ($this->saveQuestionSolution(true, false)) {
406  $questionId = $this->testSession->getCurrentQuestionId();
407 
408  $this->getQuestionInstance($questionId)->removeIntermediateSolution(
409  $this->testSession->getActiveId(),
410  $this->testSession->getPass()
411  );
412 
414 
415  if ($this->object->isForceInstantFeedbackEnabled()) {
416  $this->ctrl->setParameter($this, 'instresp', 1);
417 
418  $this->testSequence->unsetQuestionPostponed($questionId);
419  $this->testSequence->setQuestionChecked($questionId);
420  $this->testSequence->saveToDb();
421  }
422 
423  if ($this->getNextCommandParameter()) {
424  if ($this->getNextSequenceParameter()) {
425  $this->ctrl->setParameter($this, 'sequence', $this->getNextSequenceParameter());
426  $this->ctrl->setParameter($this, 'pmode', '');
427  }
428 
429  $this->ctrl->redirect($this, $this->getNextCommandParameter());
430  }
431 
432  $this->ctrl->setParameter($this, 'pmode', ilTestPlayerAbstractGUI::PRESENTATION_MODE_VIEW);
433  } else {
434  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
435  }
436 
437  // fau: testNav - remember to prevent the navigation confirmation
439  // fau.
440 
441  // fau: testNav - handle navigation after saving
442  if ($this->getNavigationUrlParameter()) {
444  } else {
445  $this->ctrl->saveParameter($this, 'sequence');
446  }
447  // fau.
448  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
449  }
450 
451  protected function discardSolutionCmd()
452  {
453  $questionId = $this->testSession->getCurrentQuestionId();
454 
455  $currentQuestionOBJ = $this->getQuestionInstance($questionId);
456 
457  $currentQuestionOBJ->resetUsersAnswer(
458  $this->testSession->getActiveId(),
459  $this->testSession->getPass()
460  );
461 
462  $this->ctrl->setParameter($this, 'pmode', ilTestPlayerAbstractGUI::PRESENTATION_MODE_VIEW);
463 
464  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
465  }
466 
467  protected function skipQuestionCmd()
468  {
469  $this->nextQuestionCmd();
470  }
471 
473  {
474  if (!$this->getResetCheckedParameter()) {
475  return false;
476  }
477 
478  if ($this->testSession->getQuestionSetFilterSelection()->isAnswerStatusSelectionWrongAnswered()) {
479  $this->testSequence->loadQuestions(
480  $this->dynamicQuestionSetConfig,
481  $this->testSession->getQuestionSetFilterSelection()
482  );
483 
484  if ($this->testSequence->hasFilteredQuestionListCheckedQuestions()) {
485  return true;
486  }
487  }
488 
489  return false;
490  }
491 
492  protected function showQuestionCmd()
493  {
494  $this->updateWorkingTime();
495 
496  $this->testSequence->loadQuestions(
497  $this->dynamicQuestionSetConfig,
498  $this->testSession->getQuestionSetFilterSelection()
499  );
500 
501  $this->testSequence->cleanupQuestions($this->testSession);
502 
505  return;
506  }
507 
508  if ($this->testSequence->getQuestionSet()->getSelectionQuestionList()->isInList($this->getQuestionIdParameter())) {
509  $this->testSession->setCurrentQuestionId($this->getQuestionIdParameter());
510  } else {
511  $this->resetQuestionIdParameter();
512  }
513 
514  if (!$this->testSession->getCurrentQuestionId()) {
515  $upComingQuestionId = $this->testSequence->getUpcomingQuestionId();
516 
517  $this->testSession->setCurrentQuestionId($upComingQuestionId);
518 
519  // seems to be a first try of freezing answers not too hard
520  /*if( $this->testSequence->isQuestionChecked($upComingQuestionId) )
521  {
522  $this->testSequence->setQuestionUnchecked($upComingQuestionId);
523  }*/
524  }
525 
526  $navigationToolbarGUI = $this->getTestNavigationToolbarGUI();
527  $navigationToolbarGUI->setQuestionSelectionButtonEnabled(true);
528 
529  if ($this->testSession->getCurrentQuestionId()) {
530  $questionGui = $this->getQuestionGuiInstance($this->testSession->getCurrentQuestionId());
531  $this->testSequence->setCurrentQuestionId($this->testSession->getCurrentQuestionId());
532 
533  $questionGui->setQuestionCount(
534  $this->testSequence->getLastPositionIndex()
535  );
536  $questionGui->setSequenceNumber(
537  $this->testSequence->getCurrentPositionIndex($this->testSession->getCurrentQuestionId())
538  );
539 
540  if (!($questionGui instanceof assQuestionGUI)) {
542  $this->testSession->getCurrentQuestionId(),
543  $this->testSession->getCurrentQuestionId()
544  );
545  }
546 
547  $isQuestionWorkedThrough = assQuestion::_isWorkedThrough(
548  $this->testSession->getActiveId(),
549  $this->testSession->getCurrentQuestionId(),
550  $this->testSession->getPass()
551  );
552 
553  require_once 'Modules/Test/classes/class.ilTestQuestionHeaderBlockBuilder.php';
554  $headerBlockBuilder = new ilTestQuestionHeaderBlockBuilder($this->lng);
555  $headerBlockBuilder->setHeaderMode(
556  // avoid legacy setting combination: ctm without question titles
557  $this->object->getTitleOutput() == 2 ? 1 : $this->object->getTitleOutput()
558  );
559  $headerBlockBuilder->setQuestionTitle($questionGui->object->getTitle());
560  $headerBlockBuilder->setQuestionPoints($questionGui->object->getPoints());
561  /* avoid showing Qst X of Y within CTMs
562  $headerBlockBuilder->setQuestionPosition(
563  $this->testSequence->getCurrentPositionIndex($this->testSession->getCurrentQuestionId())
564  );
565  $headerBlockBuilder->setQuestionCount($this->testSequence->getLastPositionIndex());
566  */
567  $headerBlockBuilder->setQuestionPostponed(
568  $this->testSequence->isPostponedQuestion(
569  $this->testSession->getCurrentQuestionId()
570  )
571  );
572  $headerBlockBuilder->setQuestionObligatory(
573  $this->object->areObligationsEnabled() && ilObjTest::isQuestionObligatory($this->object->getId())
574  );
575  $questionGui->setQuestionHeaderBlockBuilder($headerBlockBuilder);
576 
577  // fau: testNav - always use edit mode, except for fixed answer
578  if ($this->isParticipantsAnswerFixed($this->testSession->getCurrentQuestionId())) {
579  $instantResponse = true;
581  } else {
582  // #37025 don't show instant response if a request for it should fix the answer and answer is not yet fixed
583  if ($this->object->isInstantFeedbackAnswerFixationEnabled()) {
584  $instantResponse = false;
585  } else {
586  $instantResponse = $this->getInstantResponseParameter();
587  }
589  }
590  // fau.
591 
592  $this->prepareTestPage(
593  $presentationMode,
594  $this->testSession->getCurrentQuestionId(),
595  $this->testSession->getCurrentQuestionId()
596  );
597 
598  $this->ctrl->setParameter($this, 'sequence', $this->testSession->getCurrentQuestionId());
599  $this->ctrl->setParameter($this, 'pmode', $presentationMode);
600  $formAction = $this->ctrl->getFormAction($this, ilTestPlayerCommands::SUBMIT_INTERMEDIATE_SOLUTION);
601 
602  switch ($presentationMode) {
604 
605 // fau: testNav - enable navigation toolbar in edit mode
606  $navigationToolbarGUI->setDisabledStateEnabled(false);
607 // fau.
608  $this->showQuestionEditable($questionGui, $formAction, $isQuestionWorkedThrough, $instantResponse);
609 
610  break;
611 
613 
614  $this->showQuestionViewable($questionGui, $formAction, $isQuestionWorkedThrough, $instantResponse);
615 
616  break;
617 
618  default:
619 
620  require_once 'Modules/Test/exceptions/class.ilTestException.php';
621  throw new ilTestException('no presentation mode given');
622  }
623 
624  $navigationToolbarGUI->build();
625  $this->populateTestNavigationToolbar($navigationToolbarGUI);
626 
627  // fau: testNav - enable the question navigation in edit mode
629  $this->testSession->getCurrentQuestionId(),
630  false,
631  $this->object->isForceInstantFeedbackEnabled()
632  );
633  // fau.
634 
635  if ($instantResponse) {
636  // fau: testNav - always use authorized solution for instant feedback
638  $questionGui,
639  true
640  );
641  // fau.
642  $this->testSession->getQuestionSetFilterSelection()->setForcedQuestionIds(array());
643  }
644 
645  // fau: testNav - add feedback modal
646  if ($this->isForcedFeedbackNavUrlRegistered()) {
649  }
650  // fau.
651  } else {
653 
654  $navigationToolbarGUI->build();
655  $this->populateTestNavigationToolbar($navigationToolbarGUI);
656 
657  $this->outCurrentlyFinishedPage();
658  }
659 
660  $this->testSequence->saveToDb();
661  $this->testSession->saveToDb();
662  }
663 
664  protected function showInstantResponseCmd()
665  {
666  $questionId = $this->testSession->getCurrentQuestionId();
667 
668  $filterSelection = $this->testSession->getQuestionSetFilterSelection();
669 
670  $filterSelection->setForcedQuestionIds(array($this->testSession->getCurrentQuestionId()));
671 
672  $this->testSequence->loadQuestions($this->dynamicQuestionSetConfig, $filterSelection);
673  $this->testSequence->cleanupQuestions($this->testSession);
674  $this->testSequence->saveToDb();
675 
676  if (!$this->isParticipantsAnswerFixed($questionId)) {
677  if ($this->saveQuestionSolution(true)) {
680  $this->setAnswerChangedParameter(false);
681  } else {
682  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
683  }
684  $this->testSequence->unsetQuestionPostponed($questionId);
685  $this->testSequence->setQuestionChecked($questionId);
686  $this->testSequence->saveToDb();
687  }
688 
689  $this->ctrl->setParameter(
690  $this,
691  'sequence',
692  $this->testSession->getCurrentQuestionId()
693  );
694 
695  $this->ctrl->setParameter($this, 'instresp', 1);
696 
697  // fau: testNav - handle navigation after feedback
698  if ($this->getNavigationUrlParameter()) {
701  }
702  // fau.
703  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
704  }
705 
706  protected function handleQuestionActionCmd()
707  {
708  $questionId = $this->testSession->getCurrentQuestionId();
709 
710  if ($questionId && !$this->isParticipantsAnswerFixed($questionId)) {
711  $this->saveQuestionSolution(false);
712  // fau: testNav - add changed status of the question
713  $this->setAnswerChangedParameter(true);
714  // fau.
715  }
716 
717  $this->ctrl->setParameter(
718  $this,
719  'sequence',
720  $this->testSession->getCurrentQuestionId()
721  );
722 
723  $this->ctrl->saveParameter($this, 'pmode');
724 
725  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
726  }
727 
728  private function outCurrentlyFinishedPage()
729  {
730  if ($this->testSequence->openQuestionExists()) {
731  $message = $this->lng->txt('tst_dyn_test_msg_currently_finished_selection');
732  } else {
733  $message = $this->lng->txt('tst_dyn_test_msg_currently_finished_completely');
734  $message .= "<br /><br />{$this->buildFinishPagePassDeletionLink()}";
735  }
736 
738 
739  $tpl = new ilTemplate('tpl.test_currently_finished_msg.html', true, true, 'Modules/Test');
740  $tpl->setVariable('TEST_CURRENTLY_FINISHED_MSG', $msgHtml);
741 
742  $this->tpl->setVariable('QUESTION_OUTPUT', $tpl->get());
743  }
744 
745  protected function isFirstQuestionInSequence($sequenceElement)
746  {
747  return !$this->testSequence->trackedQuestionExists();
748  }
749 
750  protected function isLastQuestionInSequence($sequenceElement)
751  {
752  return false; // always
753  }
754 
760  protected function canSaveResult()
761  {
762  return !$this->object->endingTimeReached();
763  }
764 
768  public function saveQuestionSolution($authorized = true, $force = false)
769  {
770  // what is this formtimestamp ??
771  if (!$force) {
772  $formtimestamp = $_POST["formtimestamp"];
773  if (strlen($formtimestamp) == 0) {
774  $formtimestamp = $_GET["formtimestamp"];
775  }
776  if ($formtimestamp != $_SESSION["formtimestamp"]) {
777  $_SESSION["formtimestamp"] = $formtimestamp;
778  } else {
779  return false;
780  }
781  }
782 
783  // determine current question
784 
785  $qId = $this->testSession->getCurrentQuestionId();
786 
787  if (!$qId || $qId != $_GET["sequence"]) {
788  return false;
789  }
790 
791  // save question solution
792 
793  $this->saveResult = false;
794 
795  if ($this->canSaveResult($qId) || $force) {
796  $questionGUI = $this->object->createQuestionGUI("", $qId);
797 
798  if ($this->object->getJavaScriptOutput()) {
799  $questionGUI->object->setOutputType(OUTPUT_JAVASCRIPT);
800  }
801 
802  $activeId = $this->testSession->getActiveId();
803 
804  $this->saveResult = $questionGUI->object->persistWorkingState(
805  $activeId,
806  $pass = null,
807  $this->object->areObligationsEnabled(),
808  $authorized
809  );
810 
811  if ($authorized && $this->object->isSkillServiceToBeConsidered()) {
812  $this->handleSkillTriggering($this->testSession);
813  }
814  }
815 
816  if ($this->saveResult == false) {
817  $this->ctrl->setParameter($this, "save_error", "1");
818  $_SESSION["previouspost"] = $_POST;
819  }
820 
821  return $this->saveResult;
822  }
823 
824  private function isQuestionAnsweredCorrect($questionId, $activeId, $pass)
825  {
826  $questionGUI = $this->object->createQuestionGUI("", $questionId);
827 
828  $reachedPoints = assQuestion::_getReachedPoints($activeId, $questionId, $pass);
829  $maxPoints = $questionGUI->object->getMaximumPoints();
830 
831  if ($reachedPoints < $maxPoints) {
832  return false;
833  }
834 
835  return true;
836  }
837 
838  protected function buildQuestionsTableDataArray($questions, $marked_questions)
839  {
840  $data = array();
841 
842  foreach ($questions as $key => $value) {
843  $this->ctrl->setParameter($this, 'sequence', $value['question_id']);
844  $href = $this->ctrl->getLinkTarget($this, 'gotoQuestion');
845  $this->ctrl->setParameter($this, 'sequence', '');
846 
847  $description = "";
848  if ($this->object->getListOfQuestionsDescription()) {
849  $description = $value["description"];
850  }
851 
852  $marked = false;
853  if (count($marked_questions)) {
854  if (isset($marked_questions[$value["question_id"]])) {
855  if ($marked_questions[$value["question_id"]]["solved"] == 1) {
856  $marked = true;
857  }
858  }
859  }
860 
861  array_push($data, array(
862  'href' => $href,
863  'title' => $this->object->getQuestionTitle($value["title"]),
864  'description' => $description,
865  'worked_through' => $this->testSequence->isAnsweredQuestion($value["question_id"]),
866  'postponed' => $this->testSequence->isPostponedQuestion($value["question_id"]),
867  'marked' => $marked
868  ));
869  }
870 
871  return $data;
872  }
873 
874  protected function buildQuestionSetAnswerStatisticRowArray($questions, $trackedQuestions)
875  {
876  $questionAnswerStats = array(
877  'total_all' => count($questions),
878  'total_open' => 0,
879  'non_answered_notseen' => 0,
880  'non_answered_skipped' => 0,
881  'wrong_answered' => 0,
882  'correct_answered' => 0
883  );
884 
885  foreach ($questions as $key => $value) {
886  switch ($value['question_answer_status']) {
888  if (isset($trackedQuestions[$key])) {
889  $questionAnswerStats['non_answered_skipped']++;
890  } else {
891  $questionAnswerStats['non_answered_notseen']++;
892  }
893  $questionAnswerStats['total_open']++;
894  break;
896  $questionAnswerStats['wrong_answered']++;
897  $questionAnswerStats['total_open']++;
898  break;
900  $questionAnswerStats['correct_answered']++;
901  break;
902  }
903  }
904 
905  return $questionAnswerStats;
906  }
907 
909  {
910  require_once 'Modules/Test/classes/tables/class.ilTestDynamicQuestionSetStatisticTableGUI.php';
911  $gui = $this->buildQuestionSetStatisticTableGUI(
913  );
914 
915  $gui->initTitle('tst_dynamic_question_set_complete');
916  $gui->initColumns('tst_num_all_questions');
917 
918  return $gui;
919  }
920 
922  {
923  require_once 'Modules/Test/classes/tables/class.ilTestDynamicQuestionSetStatisticTableGUI.php';
924  $gui = $this->buildQuestionSetStatisticTableGUI(
926  );
927 
928  $gui->initTitle('tst_dynamic_question_set_selection');
929  $gui->initColumns('tst_num_selected_questions');
930 
931  require_once 'Services/Taxonomy/classes/class.ilObjTaxonomy.php';
932  $gui->setTaxIds(ilObjTaxonomy::getUsageOfObject(
933  $this->dynamicQuestionSetConfig->getSourceQuestionPoolId()
934  ));
935 
936  $gui->setTaxonomyFilterEnabled($this->dynamicQuestionSetConfig->isTaxonomyFilterEnabled());
937  $gui->setAnswerStatusFilterEnabled($this->dynamicQuestionSetConfig->isAnswerStatusFilterEnabled());
938 
939  $gui->setFilterSelection($this->testSession->getQuestionSetFilterSelection());
940  $gui->initFilter();
941  $gui->setFilterCommand('filterQuestionSelection');
942  $gui->setResetCommand('resetQuestionSelection');
943 
944  return $gui;
945  }
946 
947  private function buildQuestionSetStatisticTableGUI($tableId)
948  {
949  require_once 'Modules/Test/classes/tables/class.ilTestDynamicQuestionSetStatisticTableGUI.php';
951  $this->ctrl,
952  $this->lng,
953  $this,
955  $tableId
956  );
957 
958  return $gui;
959  }
960 
961  private function getEnterTestButtonLangVar()
962  {
963  if ($this->testSequence->trackedQuestionExists()) {
964  return 'tst_resume_dyn_test_with_cur_quest_sel';
965  }
966 
967  return 'tst_start_dyn_test_with_cur_quest_sel';
968  }
969 
970  protected function persistQuestionAnswerStatus()
971  {
972  $questionId = $this->testSession->getCurrentQuestionId();
973  $activeId = $this->testSession->getActiveId();
974  $pass = $this->testSession->getPass();
975 
976  if ($this->isQuestionAnsweredCorrect($questionId, $activeId, $pass)) {
977  $this->testSequence->setQuestionAnsweredCorrect($questionId);
978  } else {
979  $this->testSequence->setQuestionAnsweredWrong($questionId);
980  }
981 
982  $this->testSequence->saveToDb();
983  }
984 
985  private function resetCurrentQuestion()
986  {
987  $this->testSession->setCurrentQuestionId(null);
988  $this->testSession->saveToDb();
989 
990  $this->ctrl->setParameter($this, 'sequence', $this->testSession->getCurrentQuestionId());
991  $this->ctrl->setParameter($this, 'pmode', '');
992  }
993 
998  {
999  $href = $this->getPassDeletionTarget();
1000 
1001  $label = $this->lng->txt('tst_dyn_test_msg_pass_deletion_link');
1002 
1003  return "<a href=\"{$href}\">{$label}</a>";
1004  }
1005 
1009  private function getPassDeletionTarget()
1010  {
1011  require_once 'Modules/Test/classes/confirmations/class.ilTestPassDeletionConfirmationGUI.php';
1012 
1013  $this->ctrl->setParameterByClass('ilTestEvaluationGUI', 'context', ilTestPassDeletionConfirmationGUI::CONTEXT_DYN_TEST_PLAYER);
1014  $this->ctrl->setParameterByClass('ilTestEvaluationGUI', 'active_id', $this->testSession->getActiveId());
1015  $this->ctrl->setParameterByClass('ilTestEvaluationGUI', 'pass', $this->testSession->getPass());
1016 
1017  return $this->ctrl->getLinkTargetByClass('ilTestEvaluationGUI', 'confirmDeletePass');
1018  }
1019 
1020  protected function resetQuestionIdParameter()
1021  {
1023  }
1024 
1025  protected function getQuestionIdParameter()
1026  {
1027  return $this->getSequenceElementParameter();
1028  }
1029 
1030  protected function getResetCheckedParameter()
1031  {
1032  if (isset($_GET['reset_checked'])) {
1033  return $_GET['reset_checked'];
1034  }
1035 
1036  return null;
1037  }
1038 
1039  public function outQuestionSummaryCmd($fullpage = true, $contextFinishTest = false, $obligationsNotAnswered = false, $obligationsFilter = false)
1040  {
1041  $this->testSequence->loadQuestions(
1042  $this->dynamicQuestionSetConfig,
1043  $this->testSession->getQuestionSetFilterSelection()
1044  );
1045 
1046  $this->testSequence->setCurrentQuestionId($this->testSession->getCurrentQuestionId());
1047 
1048  parent::outQuestionSummaryCmd($fullpage, $contextFinishTest, $obligationsNotAnswered, $obligationsFilter);
1049  }
1050 
1052  {
1053  require_once 'Services/Utilities/classes/class.ilConfirmationGUI.php';
1054  $confirmation = new ilConfirmationGUI();
1055  $confirmation->setFormAction($this->ctrl->getFormAction($this));
1056  $confirmation->setHeaderText($this->lng->txt('tst_dyn_unfreeze_answers_confirmation'));
1057  $confirmation->setConfirm($this->lng->txt('tst_dyn_unfreeze_answers'), ilTestPlayerCommands::UNFREEZE_ANSWERS);
1058  $confirmation->setCancel($this->lng->txt('tst_dyn_keep_answ_freeze'), ilTestPlayerCommands::SHOW_QUESTION);
1059 
1060  $this->populateMessageContent($confirmation->getHtml());
1061  }
1062 
1064  {
1065  $this->testSequence->loadQuestions(
1066  $this->dynamicQuestionSetConfig,
1067  $this->testSession->getQuestionSetFilterSelection()
1068  );
1069 
1070  $this->testSequence->resetFilteredQuestionListsCheckedStatus();
1071  $this->testSequence->saveToDb();
1072 
1073  $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
1074  }
1075 
1076  protected function populateQuestionNavigation($sequenceElement, $disabled, $primaryNext)
1077  {
1078  if (!$this->isLastQuestionInSequence($sequenceElement)) {
1079  $this->populateNextButtons($disabled, $primaryNext);
1080  }
1081  }
1082 
1084  {
1085  $this->ctrl->setParameter($this, 'reset_checked', 1);
1086  $link = $this->ctrl->getLinkTarget($this, ilTestPlayerCommands::SHOW_QUESTION);
1087  $this->ctrl->setParameter($this, 'reset_checked', '');
1088 
1089  return $link;
1090  }
1091 
1092  protected function isShowingPostponeStatusReguired($questionId)
1093  {
1094  return false;
1095  }
1096 
1097  protected function buildTestPassQuestionList()
1098  {
1099  global $DIC;
1100  $ilPluginAdmin = $DIC['ilPluginAdmin'];
1101 
1102  require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionList.php';
1103  $questionList = new ilAssQuestionList($this->db, $this->lng, $ilPluginAdmin);
1104  $questionList->setParentObjId($this->dynamicQuestionSetConfig->getSourceQuestionPoolId());
1105  $questionList->setQuestionInstanceTypeFilter(ilAssQuestionList::QUESTION_INSTANCE_TYPE_ORIGINALS);
1106 
1107  return $questionList;
1108  }
1109 
1111  {
1112  return false;
1113  }
1114 
1115  protected function isOptionalQuestionAnsweringConfirmationRequired($sequenceKey)
1116  {
1117  return false;
1118  }
1119 }
checkTestSessionUser(ilTestSession $testSession)
vd()
shortcut for var_dump with enhanced debug information
Definition: inc.debug.php:42
getQuestionGuiInstance($question_id, $fromCache=true)
removeIntermediateSolution()
remove an auto-saved solution of the current question
setAnswerChangedParameter($changed=true)
Set the &#39;answer changed&#39; url parameter for generated links.
$data
Definition: storeScorm.php:23
$_SESSION["AccountId"]
static getUsageOfObject($a_obj_id, $a_include_titles=false)
Get usage of object.
$_GET["client_id"]
showQuestionEditable(assQuestionGUI $questionGui, $formAction, $isQuestionWorkedThrough, $instantResponse)
saveQuestionSolution($authorized=true, $force=false)
saves the user input of a question
static getSystemMessageHTML($a_txt, $a_type="info")
Get HTML for a system message.
updateWorkingTime()
updates working time and stores state saveresult to see if question has to be stored or not ...
handleUserSettings()
Handles some form parameters on starting and resuming a test.
const OUTPUT_JAVASCRIPT
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)
resumePlayerCmd()
Resume a test at the last position.
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)
populateQuestionNavigation($sequenceElement, $disabled, $primaryNext)
saveNavigationPreventConfirmation()
Save the save the switch to prevent the navigation confirmation.
populateTestNavigationToolbar(ilTestNavigationToolbarGUI $toolbarGUI)
$ilUser
Definition: imgupload.php:18
getAnswerChangedParameter()
Get the &#39;answer changed&#39; status from the current request It may be set by ilTestPlayerNavigationContr...
Basic GUI class for assessment questions.
outQuestionSummaryCmd($fullpage=true, $contextFinishTest=false, $obligationsNotAnswered=false, $obligationsFilter=false)
const ANSWER_STATUS_FILTER_ALL_NON_CORRECT
answer status filter value domain
registerForcedFeedbackNavUrl($forcedFeedbackNavUrl)
showQuestionViewable(assQuestionGUI $questionGui, $formAction, $isQuestionWorkedThrough, $instantResponse)
populateNextButtons($disabled, $primaryNext)
static initjQuery(ilGlobalTemplateInterface $a_tpl=null)
inits and adds the jQuery JS-File to the global or a passed template
populateInstantResponseModal(assQuestionGUI $questionGui, $navUrl)
buildQuestionSetAnswerStatisticRowArray($questions, $trackedQuestions)
global $ilDB
$ret
Definition: parser.php:6
$DIC
Definition: xapitoken.php:46
$message
Definition: xapiexit.php:14
getQuestionInstance($questionId, $fromCache=true)
canSaveResult()
Returns TRUE if the answers of the current user could be saved.
static _getReachedPoints($active_id, $question_id, $pass=null)
Returns the points, a learner has reached answering the question.
handleTearsAndAngerQuestionIsNull($questionId, $sequenceElement)
static redirect($a_script)
$_POST["username"]
static initConnectionWithAnimation()
Init YUI Connection module.
const QUESTION_ANSWER_STATUS_NON_ANSWERED
answer status domain for single questions
Output class for assessment test execution.
Confirmation screen class.
static initJavascript()
Init javascript.