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