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