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