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