ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
class.ilTestOutputGUI.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
21{
26
30 public function executeCommand()
31 {
32 global $DIC;
33 $ilDB = $DIC['ilDB'];
34 $ilPluginAdmin = $DIC['ilPluginAdmin'];
35 $lng = $DIC['lng'];
36 $ilTabs = $DIC['ilTabs'];
37
38 $this->checkReadAccess();
39
40 $ilTabs->clearTargets();
41
42 $cmd = $this->ctrl->getCmd();
43 $next_class = $this->ctrl->getNextClass($this);
44
45 $this->ctrl->saveParameter($this, "sequence");
46 $this->ctrl->saveParameter($this, "pmode");
47 $this->ctrl->saveParameter($this, "active_id");
48
50
51 $DIC->globalScreen()->tool()->context()->current()->addAdditionalData(
53 $this->object->getKioskMode()
54 );
55
56 $testSessionFactory = new ilTestSessionFactory($this->object);
57 $this->testSession = $testSessionFactory->getSession($_GET['active_id']);
58
59 $this->ensureExistingTestSession($this->testSession);
60 $this->checkTestSessionUser($this->testSession);
61
62 $this->initProcessLocker($this->testSession->getActiveId());
63
64 $testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $this->object);
65 $this->testSequence = $testSequenceFactory->getSequenceByTestSession($this->testSession);
66 $this->testSequence->loadFromDb();
67 $this->testSequence->loadQuestions();
68
69 require_once 'Modules/Test/classes/class.ilTestQuestionRelatedObjectivesList.php';
70 $this->questionRelatedObjectivesList = new ilTestQuestionRelatedObjectivesList();
71
72 include_once 'Services/jQuery/classes/class.iljQueryUtil.php';
74 include_once "./Services/YUI/classes/class.ilYuiUtil.php";
76
78
79 $cmd = $this->getCommand($cmd);
80
81 switch ($next_class) {
82 case 'ilassquestionpagegui':
83
84 $this->checkTestExecutable();
85
86 $questionId = $this->testSequence->getQuestionForSequence($this->getCurrentSequenceElement());
87
88 require_once "./Modules/TestQuestionPool/classes/class.ilAssQuestionPageGUI.php";
89 $page_gui = new ilAssQuestionPageGUI($questionId);
90 $ret = $this->ctrl->forwardCommand($page_gui);
91 break;
92
93 case 'iltestsubmissionreviewgui':
94
95 $this->checkTestExecutable();
96
97 require_once './Modules/Test/classes/class.ilTestSubmissionReviewGUI.php';
98 $gui = new ilTestSubmissionReviewGUI($this, $this->object, $this->testSession);
99 $gui->setObjectiveOrientedContainer($this->getObjectiveOrientedContainer());
100 $ret = $this->ctrl->forwardCommand($gui);
101 break;
102
103 case 'ilassquestionhintrequestgui':
104
105 $this->checkTestExecutable();
106
107 $questionGUI = $this->object->createQuestionGUI(
108 "",
109 $this->testSequence->getQuestionForSequence($this->getCurrentSequenceElement())
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($this, ilTestPlayerCommands::SHOW_QUESTION, $questionGUI, $questionHintTracking);
121
122// fau: testNav - save the 'answer changed' status for viewing hint requests
124// fau.
125 $ret = $this->ctrl->forwardCommand($gui);
126
127 break;
128
129 case 'iltestsignaturegui':
130
131 $this->checkTestExecutable();
132
133 require_once './Modules/Test/classes/class.ilTestSignatureGUI.php';
134 $gui = new ilTestSignatureGUI($this);
135 $ret = $this->ctrl->forwardCommand($gui);
136 break;
137
138 case 'iltestpasswordprotectiongui':
139
140 $this->checkTestExecutable();
141
142 require_once 'Modules/Test/classes/class.ilTestPasswordProtectionGUI.php';
143 $gui = new ilTestPasswordProtectionGUI($this->ctrl, $this->tpl, $this->lng, $this, $this->passwordChecker);
144 $ret = $this->ctrl->forwardCommand($gui);
145 break;
146
147 default:
148
150 $this->checkTestExecutable();
151 }
152
153 $cmd .= 'Cmd';
154 $ret = &$this->$cmd();
155 break;
156 }
157 return $ret;
158 }
159
160 protected function startTestCmd()
161 {
162 global $DIC;
163 $ilUser = $DIC['ilUser'];
164
165 $_SESSION['tst_pass_finish'] = 0;
166
167 // ensure existing test session
168 $this->testSession->setUserId($ilUser->getId());
169 $this->testSession->setAnonymousId($_SESSION["tst_access_code"][$this->object->getTestId()]);
170 $this->testSession->setObjectiveOrientedContainerId($this->getObjectiveOrientedContainer()->getObjId());
171 $this->testSession->saveToDb();
172
173 $active_id = $this->testSession->getActiveId();
174 $this->ctrl->setParameter($this, "active_id", $active_id);
175
176 $shuffle = $this->object->getShuffleQuestions();
177 if ($this->object->isRandomTest()) {
179
180 $this->object->loadQuestions();
181 $shuffle = false; // shuffle is already done during the creation of the random questions
182 }
183
184 assQuestion::_updateTestPassResults(
185 $active_id,
186 $this->testSession->getPass(),
187 $this->object->areObligationsEnabled(),
188 null,
189 $this->object->id
190 );
191
192 // ensure existing test sequence
193 if (!$this->testSequence->hasSequence()) {
194 $this->testSequence->createNewSequence($this->object->getQuestionCount(), $shuffle);
195 $this->testSequence->saveToDb();
196 }
197
198 $this->testSequence->loadFromDb();
199 $this->testSequence->loadQuestions();
200
201 if ($this->testSession->isObjectiveOriented()) {
202 require_once 'Modules/Course/classes/Objectives/class.ilLOTestQuestionAdapter.php';
203 $objectivesAdapter = ilLOTestQuestionAdapter::getInstance($this->testSession);
204
205 $objectivesAdapter->notifyTestStart($this->testSession, $this->object->getId());
206 $objectivesAdapter->prepareTestPass($this->testSession, $this->testSequence);
207
208 $objectivesAdapter->buildQuestionRelatedObjectiveList(
209 $this->testSequence,
210 $this->questionRelatedObjectivesList
211 );
212
213 if ($this->testSequence->hasOptionalQuestions()) {
215
216 $this->testSequence->reorderOptionalQuestionsToSequenceEnd();
217 $this->testSequence->saveToDb();
218 }
219 }
220
221 $active_time_id = $this->object->startWorkingTime(
222 $this->testSession->getActiveId(),
223 $this->testSession->getPass()
224 );
225 $_SESSION["active_time_id"] = $active_time_id;
226
228
229 $sequenceElement = $this->testSequence->getFirstSequence();
230
231 $this->ctrl->setParameter($this, 'sequence', $sequenceElement);
232 $this->ctrl->setParameter($this, 'pmode', '');
233
234 if ($this->object->getListOfQuestionsStart()) {
235 $this->ctrl->redirect($this, ilTestPlayerCommands::QUESTION_SUMMARY);
236 }
237
238 $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
239 }
240
242 {
243 global $DIC;
244 $ilUser = $DIC['ilUser'];
245
246 require_once('./Modules/Test/classes/class.ilObjTestAccess.php');
247 require_once('./Services/Tracking/classes/class.ilLPStatusWrapper.php');
248 ilLPStatusWrapper::_updateStatus($this->object->getId(), $ilUser->getId());
249 }
250
251 private function isValidSequenceElement($sequenceElement)
252 {
253 if ($sequenceElement === false) {
254 return false;
255 }
256
257 if ($sequenceElement < 1) {
258 return false;
259 }
260
261 if (!$this->testSequence->getPositionOfSequence($sequenceElement)) {
262 return false;
263 }
264
265 return true;
266 }
267
268 protected function showQuestionCmd()
269 {
270 $_SESSION['tst_pass_finish'] = 0;
271
272 $_SESSION["active_time_id"] = $this->object->startWorkingTime(
273 $this->testSession->getActiveId(),
274 $this->testSession->getPass()
275 );
276
277 $sequenceElement = $this->getCurrentSequenceElement();
278
279 if (!$this->isValidSequenceElement($sequenceElement)) {
280 $sequenceElement = $this->testSequence->getFirstSequence();
281 }
282
283 $this->testSession->setLastSequence($sequenceElement);
284 $this->testSession->saveToDb();
285
286
287 $questionId = $this->testSequence->getQuestionForSequence($sequenceElement);
288
289 if (!(int) $questionId && $this->testSession->isObjectiveOriented()) {
291 }
292
293 if (!$this->testSequence->isQuestionPresented($questionId)) {
294 $this->testSequence->setQuestionPresented($questionId);
295 $this->testSequence->saveToDb();
296 }
297
298 $isQuestionWorkedThrough = assQuestion::_isWorkedThrough(
299 $this->testSession->getActiveId(),
300 $questionId,
301 $this->testSession->getPass()
302 );
303
304 // fau: testNav - always use edit mode, except for fixed answer
305 if ($this->isParticipantsAnswerFixed($questionId)) {
307 $instantResponse = true;
308 } else {
310 // #37025 don't show instant response if a request for it should fix the answer and answer is not yet fixed
311 if ($this->object->isInstantFeedbackAnswerFixationEnabled()) {
312 $instantResponse = false;
313 } else {
314 $instantResponse = $this->getInstantResponseParameter();
315 }
316 }
317 // fau.
318
319 $questionGui = $this->getQuestionGuiInstance($questionId);
320
321 if (!($questionGui instanceof assQuestionGUI)) {
322 $this->handleTearsAndAngerQuestionIsNull($questionId, $sequenceElement);
323 }
324
325 $questionGui->setSequenceNumber($this->testSequence->getPositionOfSequence($sequenceElement));
326 $questionGui->setQuestionCount($this->testSequence->getUserQuestionCount());
327
328 require_once 'Modules/Test/classes/class.ilTestQuestionHeaderBlockBuilder.php';
329 $headerBlockBuilder = new ilTestQuestionHeaderBlockBuilder($this->lng);
330 $headerBlockBuilder->setHeaderMode($this->object->getTitleOutput());
331 $headerBlockBuilder->setQuestionTitle($questionGui->object->getTitle());
332 $headerBlockBuilder->setQuestionPoints($questionGui->object->getPoints());
333 $headerBlockBuilder->setQuestionPosition($this->testSequence->getPositionOfSequence($sequenceElement));
334 $headerBlockBuilder->setQuestionCount($this->testSequence->getUserQuestionCount());
335 $headerBlockBuilder->setQuestionPostponed($this->testSequence->isPostponedQuestion($questionId));
336 $headerBlockBuilder->setQuestionObligatory(
337 $this->object->areObligationsEnabled() && ilObjTest::isQuestionObligatory($questionGui->object->getId())
338 );
339 if ($this->testSession->isObjectiveOriented()) {
340 require_once 'Modules/Course/classes/Objectives/class.ilLOTestQuestionAdapter.php';
341 $objectivesAdapter = ilLOTestQuestionAdapter::getInstance($this->testSession);
342 $objectivesAdapter->buildQuestionRelatedObjectiveList($this->testSequence, $this->questionRelatedObjectivesList);
343 $this->questionRelatedObjectivesList->loadObjectivesTitles();
344
345 $objectivesString = $this->questionRelatedObjectivesList->getQuestionRelatedObjectiveTitles($questionId);
346 $headerBlockBuilder->setQuestionRelatedObjectives($objectivesString);
347 }
348 $questionGui->setQuestionHeaderBlockBuilder($headerBlockBuilder);
349
350 $this->prepareTestPage($presentationMode, $sequenceElement, $questionId);
351
352 $navigationToolbarGUI = $this->getTestNavigationToolbarGUI();
353 $navigationToolbarGUI->setFinishTestButtonEnabled(true);
354
355 $isNextPrimary = $this->handlePrimaryButton($navigationToolbarGUI, $questionId);
356
357 $this->ctrl->setParameter($this, 'sequence', $sequenceElement);
358 $this->ctrl->setParameter($this, 'pmode', $presentationMode);
359 $formAction = $this->ctrl->getFormAction($this, ilTestPlayerCommands::SUBMIT_INTERMEDIATE_SOLUTION);
360
361 switch ($presentationMode) {
363
364// fau: testNav - enable navigation toolbar in edit mode
365 $navigationToolbarGUI->setDisabledStateEnabled(false);
366// fau.
367 $this->showQuestionEditable($questionGui, $formAction, $isQuestionWorkedThrough, $instantResponse);
368
369 break;
370
372
373 if ($this->testSequence->isQuestionOptional($questionGui->object->getId())) {
375 }
376
377 $this->showQuestionViewable($questionGui, $formAction, $isQuestionWorkedThrough, $instantResponse);
378
379 break;
380
381 default:
382
383 require_once 'Modules/Test/exceptions/class.ilTestException.php';
384 throw new ilTestException('no presentation mode given');
385 }
386
387 $navigationToolbarGUI->build();
388 $this->populateTestNavigationToolbar($navigationToolbarGUI);
389
390 // fau: testNav - enable the question navigation in edit mode
391 $this->populateQuestionNavigation($sequenceElement, false, $isNextPrimary);
392 // fau.
393
394 if ($instantResponse) {
395 // fau: testNav - always use authorized solution for instant feedback
397 $questionGui,
398 true
399 );
400 // fau.
401 }
402
403 // fau: testNav - add feedback modal
407 }
408 // fau.
409 }
410
411 protected function editSolutionCmd()
412 {
413 $this->ctrl->setParameter($this, 'pmode', ilTestPlayerAbstractGUI::PRESENTATION_MODE_EDIT);
414 $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
415 }
416
417 protected function submitSolutionAndNextCmd()
418 {
419 if ($this->object->isForceInstantFeedbackEnabled()) {
420 return $this->submitSolutionCmd();
421 }
422
423 if ($this->saveQuestionSolution(true, false)) {
424 $questionId = $this->testSequence->getQuestionForSequence(
426 );
427
429
430 $nextSequenceElement = $this->testSequence->getNextSequence($this->getCurrentSequenceElement());
431
432 if (!$this->isValidSequenceElement($nextSequenceElement)) {
433 $nextSequenceElement = $this->testSequence->getFirstSequence();
434 }
435
436 $this->testSession->setLastSequence($nextSequenceElement);
437 $this->testSession->saveToDb();
438
439 $this->ctrl->setParameter($this, 'sequence', $nextSequenceElement);
440 $this->ctrl->setParameter($this, 'pmode', '');
441 }
442
443 $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
444 }
445
446 protected function submitSolutionCmd()
447 {
448 if ($this->saveQuestionSolution(true, false)) {
449 $questionId = $this->testSequence->getQuestionForSequence(
451 );
452
454
455 if ($this->object->isForceInstantFeedbackEnabled()) {
456 $this->ctrl->setParameter($this, 'instresp', 1);
457
458 $this->testSequence->setQuestionChecked($questionId);
459 $this->testSequence->saveToDb();
460 }
461
462 if ($this->getNextCommandParameter()) {
463 if ($this->getNextSequenceParameter()) {
464 $this->ctrl->setParameter($this, 'sequence', $this->getNextSequenceParameter());
465 $this->ctrl->setParameter($this, 'pmode', '');
466 }
467
468 $this->ctrl->redirect($this, $this->getNextCommandParameter());
469 }
470
471 $this->ctrl->setParameter($this, 'pmode', ilTestPlayerAbstractGUI::PRESENTATION_MODE_VIEW);
472 } else {
473 $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
474 }
475
476 // fau: testNav - remember to prevent the navigation confirmation
478 // fau.
479
480 // fau: testNav - handle navigation after saving
481 if ($this->getNavigationUrlParameter()) {
483 } else {
484 $this->ctrl->saveParameter($this, 'sequence');
485 }
486 // fau.
487 $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
488 }
489
490 protected function discardSolutionCmd()
491 {
492 $currentSequenceElement = $this->getCurrentSequenceElement();
493
494 $currentQuestionOBJ = $this->getQuestionInstance(
495 $this->testSequence->getQuestionForSequence($currentSequenceElement)
496 );
497
498 $currentQuestionOBJ->resetUsersAnswer(
499 $this->testSession->getActiveId(),
500 $this->testSession->getPass()
501 );
502
503 $this->ctrl->saveParameter($this, 'sequence');
504
505 $this->ctrl->setParameter($this, 'pmode', ilTestPlayerAbstractGUI::PRESENTATION_MODE_VIEW);
506
507 $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
508 }
509
510 protected function skipQuestionCmd()
511 {
512 $curSequenceElement = $this->getCurrentSequenceElement();
513 $nextSequenceElement = $this->testSequence->getNextSequence($curSequenceElement);
514
515 if (!$this->isValidSequenceElement($nextSequenceElement)) {
516 $nextSequenceElement = $this->testSequence->getFirstSequence();
517 }
518
519 if ($this->object->isPostponingEnabled()) {
520 $this->testSequence->postponeSequence($curSequenceElement);
521 $this->testSequence->saveToDb();
522 }
523
524 $this->ctrl->setParameter($this, 'sequence', $nextSequenceElement);
525 $this->ctrl->setParameter($this, 'pmode', '');
526
527 $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
528 }
529
530 protected function handleQuestionPostponing($sequenceElement)
531 {
532 $questionId = $this->testSequence->getQuestionForSequence($sequenceElement);
533
534 $isQuestionWorkedThrough = assQuestion::_isWorkedThrough(
535 $this->testSession->getActiveId(),
536 $questionId,
537 $this->testSession->getPass()
538 );
539
540 if (!$isQuestionWorkedThrough) {
541 $this->testSequence->postponeQuestion($questionId);
542 $this->testSequence->saveToDb();
543 }
544 }
545
546 protected function nextQuestionCmd()
547 {
548 $lastSequenceElement = $this->getCurrentSequenceElement();
549 $nextSequenceElement = $this->testSequence->getNextSequence($lastSequenceElement);
550
551 if ($this->object->isPostponingEnabled()) {
552 $this->handleQuestionPostponing($lastSequenceElement);
553 }
554
555 if (!$this->isValidSequenceElement($nextSequenceElement)) {
556 $nextSequenceElement = $this->testSequence->getFirstSequence();
557 }
558
559 $this->ctrl->setParameter($this, 'sequence', $nextSequenceElement);
560 $this->ctrl->setParameter($this, 'pmode', '');
561
562 $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
563 }
564
565 protected function previousQuestionCmd()
566 {
567 $sequenceElement = $this->testSequence->getPreviousSequence(
569 );
570
571 if (!$this->isValidSequenceElement($sequenceElement)) {
572 $sequenceElement = $this->testSequence->getLastSequence();
573 }
574
575 $this->ctrl->setParameter($this, 'sequence', $sequenceElement);
576 $this->ctrl->setParameter($this, 'pmode', '');
577
578 $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
579 }
580
581 protected function isFirstQuestionInSequence($sequenceElement)
582 {
583 return $sequenceElement == $this->testSequence->getFirstSequence();
584 }
585
586 protected function isLastQuestionInSequence($sequenceElement)
587 {
588 return $sequenceElement == $this->testSequence->getLastSequence();
589 }
590
596 protected function canSaveResult()
597 {
598 return !$this->object->endingTimeReached() && !$this->isMaxProcessingTimeReached() && !$this->isNrOfTriesReached();
599 }
600
604 protected function getCurrentQuestionId()
605 {
606 return $this->testSequence->getQuestionForSequence($_GET["sequence"]);
607 }
608
612 public function saveQuestionSolution($authorized = true, $force = false)
613 {
614 $this->updateWorkingTime();
615 $this->saveResult = false;
616 if (!$force) {
617 $formtimestamp = $_POST["formtimestamp"];
618 if (strlen($formtimestamp) == 0) {
619 $formtimestamp = $_GET["formtimestamp"];
620 }
621 if ($formtimestamp != $_SESSION["formtimestamp"]) {
622 $_SESSION["formtimestamp"] = $formtimestamp;
623 } else {
624 return false;
625 }
626 }
627
628 /*
629 #21097 - exceed maximum passes
630 this is a battle of conditions; e.g. ilTestPlayerAbstractGUI::autosaveOnTimeLimitCmd forces saving of results.
631 However, if an admin has finished the pass in the meantime, a new pass should not be created.
632 */
633 if ($force && $this->isNrOfTriesReached()) {
634 $force = false;
635 }
636
637 // save question solution
638 if ($this->canSaveResult() || $force) {
639 // but only if the ending time is not reached
640 $q_id = $this->testSequence->getQuestionForSequence($_GET["sequence"]);
641
642 if ($this->isParticipantsAnswerFixed($q_id)) {
643 // should only be reached by firebugging the disabled form in ui
644 throw new ilTestException('not allowed request');
645 }
646
647 if (is_numeric($q_id) && (int) $q_id) {
648 $questionOBJ = $this->getQuestionInstance($q_id);
649 $pass = null;
650 $active_id = $this->testSession->getActiveId();
651 if ($this->object->isRandomTest()) {
652 $pass = ilObjTest::_getPass($active_id);
653 }
654 $this->saveResult = $questionOBJ->persistWorkingState(
655 $active_id,
656 $pass,
657 $this->object->areObligationsEnabled(),
658 $authorized
659 );
660
661 if ($authorized && $this->testSession->isObjectiveOriented()) {
662 require_once 'Modules/Course/classes/Objectives/class.ilLOTestQuestionAdapter.php';
663 $objectivesAdapter = ilLOTestQuestionAdapter::getInstance($this->testSession);
664 $objectivesAdapter->updateQuestionResult($this->testSession, $questionOBJ);
665 }
666
667 if ($authorized && $this->object->isSkillServiceToBeConsidered()) {
668 $this->handleSkillTriggering($this->testSession);
669 }
670 }
671 }
672
673 if ($this->saveResult == false || (!$questionOBJ->validateSolutionSubmit() && $questionOBJ->savePartial())) {
674 $this->ctrl->setParameter($this, "save_error", "1");
675 $_SESSION["previouspost"] = $_POST;
676 }
677
678 return $this->saveResult;
679 }
680
681 protected function showInstantResponseCmd()
682 {
683 $questionId = $this->testSequence->getQuestionForSequence(
685 );
686
687 if ($this->getAnswerChangedParameter() && !$this->isParticipantsAnswerFixed($questionId)) {
688 if ($this->saveQuestionSolution(true)) {
690 $this->setAnswerChangedParameter(false);
691 } else {
692 $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
693 }
694 $this->testSequence->setQuestionChecked($questionId);
695 $this->testSequence->saveToDb();
696 } elseif ($this->object->isForceInstantFeedbackEnabled()) {
697 $this->testSequence->setQuestionChecked($questionId);
698 $this->testSequence->saveToDb();
699 }
700
701 $this->ctrl->setParameter($this, 'instresp', 1);
702
703 // fau: testNav - handle navigation after feedback
704 if ($this->getNavigationUrlParameter()) {
707 }
708 // fau.
709 $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
710 }
711
712 protected function handleQuestionActionCmd()
713 {
714 $questionId = $this->testSequence->getQuestionForSequence(
716 );
717
718 if (!$this->isParticipantsAnswerFixed($questionId)) {
719 $this->updateWorkingTime();
720 $this->saveQuestionSolution(false);
721 // fau: testNav - add changed status of the question
722 $this->setAnswerChangedParameter(true);
723 // fau.
724 }
725
726 $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
727 }
728
730 {
731 if ($this->testSession->getActiveId() > 0) {
732 if ($this->testSequence->hasRandomQuestionsForPass($this->testSession->getActiveId(), $this->testSession->getPass()) > 0) {
733 // Something went wrong. Maybe the user pressed the start button twice
734 // Questions already exist so there is no need to create new questions
735
736 global $DIC;
737 $ilLog = $DIC['ilLog'];
738 $ilUser = $DIC['ilUser'];
739
740 $ilLog->write(
741 __METHOD__ . ' Random Questions allready exists for user ' .
742 $ilUser->getId() . ' in test ' . $this->object->getTestId()
743 );
744
745 return true;
746 }
747 } else {
748 // This may not happen! If it happens, raise a fatal error...
749
750 global $DIC;
751 $ilLog = $DIC['ilLog'];
752 $ilUser = $DIC['ilUser'];
753
754 $ilLog->write(__METHOD__ . ' ' . sprintf(
755 $this->lng->txt("error_random_question_generation"),
756 $ilUser->getId(),
757 $this->object->getTestId()
758 ));
759
760 return true;
761 };
762
763 return false;
764 }
765
767 {
768 global $DIC;
769 $tree = $DIC['tree'];
770 $ilDB = $DIC['ilDB'];
771 $ilPluginAdmin = $DIC['ilPluginAdmin'];
772
773 require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetConfig.php';
774 $questionSetConfig = new ilTestRandomQuestionSetConfig($tree, $ilDB, $ilPluginAdmin, $this->object);
775 $questionSetConfig->loadFromDb();
776
777 require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinitionFactory.php';
778 $sourcePoolDefinitionFactory = new ilTestRandomQuestionSetSourcePoolDefinitionFactory($ilDB, $this->object);
779
780 require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetSourcePoolDefinitionList.php';
781 $sourcePoolDefinitionList = new ilTestRandomQuestionSetSourcePoolDefinitionList($ilDB, $this->object, $sourcePoolDefinitionFactory);
782 $sourcePoolDefinitionList->loadDefinitions();
783
784 $this->processLocker->executeRandomPassBuildOperation(function () use ($ilDB, $ilPluginAdmin, $questionSetConfig, $sourcePoolDefinitionList) {
786 require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetStagingPoolQuestionList.php';
787 $stagingPoolQuestionList = new ilTestRandomQuestionSetStagingPoolQuestionList($ilDB, $ilPluginAdmin);
788
789 require_once 'Modules/Test/classes/class.ilTestRandomQuestionSetBuilder.php';
790 $questionSetBuilder = ilTestRandomQuestionSetBuilder::getInstance($ilDB, $this->object, $questionSetConfig, $sourcePoolDefinitionList, $stagingPoolQuestionList);
791
792 $questionSetBuilder->performBuild($this->testSession);
793 }
794 }, $sourcePoolDefinitionList->hasTaxonomyFilters());
795 }
796
800 protected function resumePlayerCmd()
801 {
802 $this->handleUserSettings();
803
804 $active_id = $this->testSession->getActiveId();
805 $this->ctrl->setParameter($this, "active_id", $active_id);
806
807 $active_time_id = $this->object->startWorkingTime($active_id, $this->testSession->getPass());
808 $_SESSION["active_time_id"] = $active_time_id;
809 $_SESSION['tst_pass_finish'] = 0;
810
811 if ($this->object->isRandomTest()) {
812 if (!$this->testSequence->hasRandomQuestionsForPass($active_id, $this->testSession->getPass())) {
813 // create a new set of random questions
815 }
816 }
817
818 $shuffle = $this->object->getShuffleQuestions();
819 if ($this->object->isRandomTest()) {
820 $shuffle = false;
821 }
822
823 assQuestion::_updateTestPassResults(
824 $active_id,
825 $this->testSession->getPass(),
826 $this->object->areObligationsEnabled(),
827 null,
828 $this->object->id
829 );
830
831 // ensure existing test sequence
832 if (!$this->testSequence->hasSequence()) {
833 $this->testSequence->createNewSequence($this->object->getQuestionCount(), $shuffle);
834 $this->testSequence->saveToDb();
835 }
836
837 if ($this->object->getListOfQuestionsStart()) {
838 $this->ctrl->redirect($this, ilTestPlayerCommands::QUESTION_SUMMARY);
839 }
840
841 $this->ctrl->setParameter($this, 'sequence', $this->testSession->getLastSequence());
842 $this->ctrl->setParameter($this, 'pmode', '');
843 $this->ctrl->redirect($this, ilTestPlayerCommands::SHOW_QUESTION);
844 }
845
846 protected function isShowingPostponeStatusReguired($questionId)
847 {
848 return $this->testSequence->isPostponedQuestion($questionId);
849 }
850
852 {
853 global $DIC;
854 $ilDB = $DIC['ilDB'];
855 $ilUser = $DIC['ilUser'];
856
857 $assSettings = new ilSetting('assessment');
858
859 include_once("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
860 $isAssessmentLogEnabled = ilObjAssessmentFolder::_enabledAssessmentLogging();
861
862 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionUserSolutionAdopter.php';
863 $userSolutionAdopter = new ilAssQuestionUserSolutionAdopter($ilDB, $assSettings, $isAssessmentLogEnabled);
864
865 $userSolutionAdopter->setUserId($ilUser->getId());
866 $userSolutionAdopter->setActiveId($this->testSession->getActiveId());
867 $userSolutionAdopter->setTargetPass($this->testSequence->getPass());
868 $userSolutionAdopter->setQuestionIds($this->testSequence->getOptionalQuestions());
869
870 $userSolutionAdopter->perform();
871 }
872
873 abstract protected function populateQuestionOptionalMessage();
874
875 protected function isOptionalQuestionAnsweringConfirmationRequired($sequenceKey)
876 {
877 if ($this->testSequence->isAnsweringOptionalQuestionsConfirmed()) {
878 return false;
879 }
880
881 $questionId = $this->testSequence->getQuestionForSequence($sequenceKey);
882
883 if (!$this->testSequence->isQuestionOptional($questionId)) {
884 return false;
885 }
886
887 return true;
888 }
889
891 {
892 return true;
893 }
894
896 {
897 ilUtil::sendFailure(sprintf($this->lng->txt('tst_objective_oriented_test_pass_without_questions'), $this->object->getTitle()), true);
898
899 $this->backToInfoScreenCmd();
900 }
901
905 protected function handlePrimaryButton(ilTestNavigationToolbarGUI $navigationToolbarGUI, $currentQuestionId)
906 {
907 $isNextPrimary = true;
908
909 if ($this->object->isForceInstantFeedbackEnabled()) {
910 $isNextPrimary = false;
911 }
912
913 $questionsMissingResult = assQuestion::getQuestionsMissingResultRecord(
914 $this->testSession->getActiveId(),
915 $this->testSession->getPass(),
916 $this->testSequence->getOrderedSequenceQuestions()
917 );
918
919 if (!count($questionsMissingResult)) {
920 $navigationToolbarGUI->setFinishTestButtonPrimary(true);
921 $isNextPrimary = false;
922 } elseif (count($questionsMissingResult) == 1) {
923 $lastOpenQuestion = current($questionsMissingResult);
924
925 if ($currentQuestionId == $lastOpenQuestion) {
926 $navigationToolbarGUI->setFinishTestButtonPrimary(true);
927 $isNextPrimary = false;
928 }
929 }
930
931 return $isNextPrimary;
932 }
933}
$_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 _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 ...
static getQuestionsMissingResultRecord($activeId, $pass, $questionIds)
Question page GUI class.
static getInstance(ilTestSession $a_test_session)
static _updateStatus($a_obj_id, $a_usr_id, $a_obj=null, $a_percentage=false, $a_force_raise=false)
Update status.
static _enabledAssessmentLogging()
check wether assessment logging is enabled or not
static _getPass($active_id)
Retrieves the actual pass of a given user for a given test.
static isQuestionObligatory($question_id)
checks wether the question with given id is marked as obligatory or not
ILIAS Setting Class.
Base Exception for all Exceptions relating to Modules/Test.
setFinishTestButtonPrimary($finishTestButtonPrimary)
Output class for assessment test execution.
isLastQuestionInSequence($sequenceElement)
handleQuestionPostponing($sequenceElement)
isOptionalQuestionAnsweringConfirmationRequired($sequenceKey)
canSaveResult()
Returns TRUE if the answers of the current user could be saved.
handlePrimaryButton(ilTestNavigationToolbarGUI $navigationToolbarGUI, $currentQuestionId)
resumePlayerCmd()
Resume a test at the last position.
populateQuestionOptionalMessage()
isShowingPostponeStatusReguired($questionId)
executeCommand()
Execute Command.
isValidSequenceElement($sequenceElement)
isFirstQuestionInSequence($sequenceElement)
saveQuestionSolution($authorized=true, $force=false)
saves the user input of a question
Output class for assessment test execution.
handleSkillTriggering(ilTestSession $testSession)
checkTestSessionUser(ilTestSession $testSession)
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...
isMaxProcessingTimeReached()
Checks wheather the maximum processing time is reached or not.
saveNavigationPreventConfirmation()
Save the save the switch to prevent the navigation confirmation.
registerForcedFeedbackNavUrl($forcedFeedbackNavUrl)
populateQuestionNavigation($sequenceElement, $disabled, $primaryNext)
showQuestionViewable(assQuestionGUI $questionGui, $formAction, $isQuestionWorkedThrough, $instantResponse)
static getInstance(ilDBInterface $db, ilObjTest $testOBJ, ilTestRandomQuestionSetConfig $questionSetConfig, ilTestRandomQuestionSetSourcePoolDefinitionList $sourcePoolDefinitionList, ilTestRandomQuestionSetStagingPoolQuestionList $stagingPoolQuestionList)
getCommand($cmd)
Retrieves the ilCtrl command.
Signature Plugin Class.
Class ilTestSubmissionReviewGUI.
static redirect($a_script)
static sendFailure($a_info="", $a_keep=false)
Send Failure Message to Screen.
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
$ret
Definition: parser.php:6
global $ilDB
$ilUser
Definition: imgupload.php:18
$DIC
Definition: xapitoken.php:46