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