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
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 $ilDB, $lng, $ilPluginAdmin, $ilTabs, $tree;
52
53 $ilTabs->clearTargets();
54
55 $this->ctrl->saveParameter($this, "sequence");
56 $this->ctrl->saveParameter($this, "active_id");
57
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';
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 {
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 {
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 {
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
632 }
633 // fau.
634 } else {
636
637 $navigationToolbarGUI->build();
638 $this->populateTestNavigationToolbar($navigationToolbarGUI);
639
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';
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';
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
1098 {
1099 return false;
1100 }
1101}
$_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)
populateInstantResponseModal(assQuestionGUI $questionGui, $navUrl)
showQuestionEditable(assQuestionGUI $questionGui, $formAction, $isQuestionWorkedThrough, $instantResponse)
getQuestionGuiInstance($questionId, $fromCache=true)
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 initConnectionWithAnimation()
Init YUI Connection module.
static initjQuery($a_tpl=null)
inits and adds the jQuery JS-File to the global or a passed template
$key
Definition: croninfo.php:18
const OUTPUT_JAVASCRIPT
vd()
shortcut for var_dump with enhanced debug information
Definition: inc.debug.php:42
catch(Exception $e) $message
$ret
Definition: parser.php:6
global $ilDB
$ilUser
Definition: imgupload.php:18