/**
  * Called when a user answered a question to perform a redirect after POST.
  * This is called for security reasons to prevent users sending a form twice.
  * --> description up to date ??
  *
  * @access public
  */
 protected function redirectQuestionCmd()
 {
     global $ilUser;
     // check the test restrictions to access the test in case one
     // of the test navigation commands was called by an external script
     // e.g. $ilNavigationHistory
     $executable = $this->object->isExecutable($this->testSession, $ilUser->getId());
     if (!$executable["executable"]) {
         ilUtil::sendInfo($executable["errormessage"], TRUE);
         $this->ctrl->redirectByClass("ilobjtestgui", "infoScreen");
     }
     switch ($_GET["activecommand"]) {
         case "next":
             $this->sequence = $this->calculateSequence();
             if ($this->sequence === FALSE) {
                 if ($this->object->getListOfQuestionsEnd()) {
                     $allObligationsAnswered = ilObjTest::allObligationsAnswered($this->testSession->getTestId(), $this->testSession->getActiveId(), $this->testSession->getPass());
                     if ($this->object->areObligationsEnabled() && !$allObligationsAnswered) {
                         $this->ctrl->redirect($this, "outQuestionSummaryWithObligationsInfo");
                     }
                     $this->outQuestionSummaryCmd();
                 } else {
                     $this->ctrl->redirect($this, "finishTest");
                 }
             } else {
                 $this->testSession->setLastSequence($this->sequence);
                 $this->testSession->saveToDb();
                 $this->outTestPage(false);
             }
             break;
         case "previous":
             $this->sequence = $this->calculateSequence();
             $this->testSession->setLastSequence($this->sequence);
             $this->testSession->saveToDb();
             if ($this->sequence === FALSE) {
                 $this->ctrl->redirect($this, "outIntroductionPage");
             } else {
                 $this->outTestPage(false);
             }
             break;
         case "postpone":
             $this->sequence = $this->calculateSequence();
             $nextSequence = $this->testSequence->getNextSequence($this->sequence);
             $this->testSequence->postponeSequence($this->sequence);
             $this->testSequence->saveToDb();
             $this->testSession->setLastSequence($nextSequence);
             $this->testSession->saveToDb();
             $this->sequence = $nextSequence;
             $this->outTestPage(false);
             break;
         case "setmarked":
             $this->sequence = $this->calculateSequence();
             $this->testSession->setLastSequence($this->sequence);
             $this->testSession->saveToDb();
             $q_id = $this->testSequence->getQuestionForSequence($_GET["sequence"]);
             $this->object->setQuestionSetSolved(1, $q_id, $ilUser->getId());
             $this->outTestPage(false);
             break;
         case "resetmarked":
             $this->sequence = $this->calculateSequence();
             $this->testSession->setLastSequence($this->sequence);
             $this->testSession->saveToDb();
             $q_id = $this->testSequence->getQuestionForSequence($_GET["sequence"]);
             $this->object->setQuestionSetSolved(0, $q_id, $ilUser->getId());
             $this->outTestPage(false);
             break;
         case "directfeedback":
             $this->sequence = $this->calculateSequence();
             $this->testSession->setLastSequence($this->sequence);
             $this->testSession->saveToDb();
             $this->outTestPage(true);
             break;
         case "handleQuestionAction":
             $this->sequence = $this->calculateSequence();
             $this->testSession->setLastSequence($this->sequence);
             $this->testSession->saveToDb();
             $this->outTestPage(false);
             break;
         case "summary":
             $this->ctrl->redirect($this, "outQuestionSummary");
             break;
         case "summary_obligations":
             $this->ctrl->redirect($this, "outQuestionSummaryWithObligationsInfo");
             break;
         case "summary_obligations_only":
             $this->ctrl->redirect($this, "outObligationsOnlySummary");
             break;
         case "start":
             $_SESSION['tst_pass_finish'] = 0;
             // ensure existing test session
             $this->testSession->setUserId($ilUser->getId());
             $this->testSession->setAnonymousId($_SESSION["tst_access_code"][$this->object->getTestId()]);
             $this->testSession->setObjectiveOrientedContainerId($this->getObjectiveOrientedContainerId());
             $this->testSession->saveToDb();
             $active_id = $this->testSession->getActiveId();
             $this->ctrl->setParameter($this, "active_id", $active_id);
             $shuffle = $this->object->getShuffleQuestions();
             if ($this->object->isRandomTest()) {
                 $this->generateRandomTestPassForActiveUser();
                 $this->object->loadQuestions();
                 $shuffle = FALSE;
                 // shuffle is already done during the creation of the random questions
             }
             assQuestion::_updateTestPassResults($active_id, $this->testSession->getPass(), $this->object->areObligationsEnabled(), null, $this->object->id);
             // ensure existing test sequence
             if (!$this->testSequence->hasSequence()) {
                 $this->testSequence->createNewSequence($this->object->getQuestionCount(), $shuffle);
                 $this->testSequence->saveToDb();
             }
             if ($this->testSession->isObjectiveOriented()) {
                 $this->testSequence->loadFromDb();
                 $this->testSequence->loadQuestions();
                 $this->filterTestSequenceByObjectives($this->testSession, $this->testSequence);
             }
             $active_time_id = $this->object->startWorkingTime($this->testSession->getActiveId(), $this->testSession->getPass());
             $_SESSION["active_time_id"] = $active_time_id;
             if ($this->object->getListOfQuestionsStart()) {
                 $this->ctrl->setParameter($this, "activecommand", "summary");
                 $this->ctrl->redirect($this, "redirectQuestion");
             } else {
                 $this->ctrl->setParameter($this, "sequence", $this->sequence);
                 $this->ctrl->setParameter($this, "activecommand", "gotoquestion");
                 $this->ctrl->saveParameter($this, "tst_javascript");
                 $this->ctrl->redirect($this, "redirectQuestion");
             }
             break;
         case "resume":
             $_SESSION['tst_pass_finish'] = 0;
             $active_id = $this->testSession->getActiveId();
             $this->ctrl->setParameter($this, "active_id", $active_id);
             if ($this->object->isRandomTest()) {
                 if (!$this->testSequence->hasRandomQuestionsForPass($active_id, $this->testSession->getPass())) {
                     // create a new set of random questions
                     $this->generateRandomTestPassForActiveUser();
                 }
             }
             $shuffle = $this->object->getShuffleQuestions();
             if ($this->object->isRandomTest()) {
                 $shuffle = FALSE;
             }
             assQuestion::_updateTestPassResults($active_id, $this->testSession->getPass(), $this->object->areObligationsEnabled(), null, $this->object->id);
             // ensure existing test sequence
             if (!$this->testSequence->hasSequence()) {
                 $this->testSequence->createNewSequence($this->object->getQuestionCount(), $shuffle);
                 $this->testSequence->saveToDb();
             }
             $this->sequence = $this->testSession->getLastSequence();
             $active_time_id = $this->object->startWorkingTime($active_id, $this->testSession->getPass());
             $_SESSION["active_time_id"] = $active_time_id;
             if ($this->object->getListOfQuestionsStart()) {
                 $this->ctrl->setParameter($this, "activecommand", "summary");
                 $this->ctrl->redirect($this, "redirectQuestion");
             } else {
                 $this->ctrl->setParameter($this, "sequence", $this->sequence);
                 $this->ctrl->setParameter($this, "activecommand", "gotoquestion");
                 $this->ctrl->saveParameter($this, "tst_javascript");
                 $this->ctrl->redirect($this, "redirectQuestion");
             }
             break;
         case 'test_submission_overview':
             require_once './Modules/Test/classes/class.ilTestSubmissionReviewGUI.php';
             $this->ctrl->redirectByClass('ilTestSubmissionReviewGUI', "show");
             break;
         case "back":
         case "gotoquestion":
         default:
             $_SESSION['tst_pass_finish'] = 0;
             if (array_key_exists("tst_javascript", $_GET)) {
                 $ilUser->writePref("tst_javascript", $_GET["tst_javascript"]);
             }
             $this->sequence = $this->calculateSequence();
             if (strlen($_GET['gotosequence'])) {
                 $this->sequence = $_GET['gotosequence'];
             }
             $this->testSession->setLastSequence($this->sequence);
             $this->testSession->saveToDb();
             $this->outTestPage(false);
             break;
     }
 }
 /**
 * Finish the test
 *
 * Finish the test
 *
 * @access public
 */
 function finishTest($confirm = true)
 {
     global $ilUser;
     global $ilias;
     global $ilAuth;
     unset($_SESSION["tst_next"]);
     $active_id = $this->object->getTestSession()->getActiveId();
     $actualpass = $this->object->_getPass($active_id);
     $allObligationsAnswered = ilObjTest::allObligationsAnswered($this->object->getTestSession()->getTestId(), $active_id, $actualpass);
     if ($this->object->areObligationsEnabled() && !$allObligationsAnswered) {
         if ($this->object->getListOfQuestions()) {
             $_GET['activecommand'] = 'summary_obligations';
         } else {
             $_GET['activecommand'] = 'summary_obligations_only';
         }
         $this->redirectQuestion();
         return;
     }
     if ($actualpass == $this->object->getNrOfTries() - 1 && !$confirm) {
         $this->object->setActiveTestSubmitted($ilUser->getId());
         $ilAuth->setIdle(ilSession::getIdleValue(), false);
         $ilAuth->setExpire(0);
         switch ($this->object->getMailNotification()) {
             case 1:
                 $this->object->sendSimpleNotification($active_id);
                 break;
             case 2:
                 $this->object->sendAdvancedNotification($active_id);
                 break;
         }
     }
     if ($confirm && $actualpass == $this->object->getNrOfTries() - 1) {
         if ($this->object->canShowSolutionPrintview($ilUser->getId())) {
             $template = new ilTemplate("tpl.il_as_tst_finish_navigation.html", TRUE, TRUE, "Modules/Test");
             $template->setVariable("BUTTON_FINISH", $this->lng->txt("btn_next"));
             $template->setVariable("BUTTON_CANCEL", $this->lng->txt("btn_previous"));
             $template_top = new ilTemplate("tpl.il_as_tst_list_of_answers_topbuttons.html", TRUE, TRUE, "Modules/Test");
             $template_top->setCurrentBlock("button_print");
             $template_top->setVariable("BUTTON_PRINT", $this->lng->txt("print"));
             $template_top->parseCurrentBlock();
             $this->showListOfAnswers($active_id, NULL, $template_top->get(), $template->get());
             return;
         } else {
             // show confirmation page
             return $this->confirmFinishTest();
         }
     }
     if (!$_SESSION['tst_pass_finish']) {
         if (!$_SESSION['tst_pass_finish']) {
             $_SESSION['tst_pass_finish'] = 1;
         }
         if ($this->object->getMailNotificationType() == 1) {
             switch ($this->object->getMailNotification()) {
                 case 1:
                     $this->object->sendSimpleNotification($active_id);
                     break;
                 case 2:
                     $this->object->sendAdvancedNotification($active_id);
                     break;
             }
         }
         $this->object->getTestSession()->increaseTestPass();
     }
     $this->redirectBack();
 }
 function finishTestCmd($requires_confirmation = true)
 {
     global $ilUser, $ilAuth;
     unset($_SESSION["tst_next"]);
     $active_id = $this->testSession->getActiveId();
     $actualpass = $this->object->_getPass($active_id);
     $allObligationsAnswered = ilObjTest::allObligationsAnswered($this->testSession->getTestId(), $active_id, $actualpass);
     /*
      * The following "endgames" are possible prior to actually finishing the test:
      * - Obligations (Ability to finish the test.)
      *      If not all obligatory questions are answered, the user is presented a list
      *      showing the deficits.
      * - Examview (Will to finish the test.)
      *      With the examview, the participant can review all answers given in ILIAS or a PDF prior to
      *      commencing to the finished test.
      * - Last pass allowed (Reassuring the will to finish the test.)
      *      If passes are limited, on the last pass, an additional confirmation is to be displayed.
      */
     // Obligations fulfilled? redirectQuestion : one or the other summary -> no finish
     if ($this->object->areObligationsEnabled() && !$allObligationsAnswered) {
         if ($this->object->getListOfQuestions()) {
             $_GET['activecommand'] = 'summary_obligations';
         } else {
             $_GET['activecommand'] = 'summary_obligations_only';
         }
         $this->redirectQuestionCmd();
         return;
     }
     // Examview enabled & !reviewed & requires_confirmation? test_submission_overview (review gui)
     if ($this->object->getEnableExamview() && !isset($_GET['reviewed']) && $requires_confirmation) {
         $_GET['activecommand'] = 'test_submission_overview';
         $this->redirectQuestionCmd();
         return;
     }
     // Last try in limited tries & !confirmed
     if ($requires_confirmation && $actualpass == $this->object->getNrOfTries() - 1) {
         // show confirmation page
         return $this->confirmFinishTestCmd();
     }
     // Last try in limited tries & confirmed?
     if ($actualpass == $this->object->getNrOfTries() - 1 && !$requires_confirmation) {
         $ilAuth->setIdle(ilSession::getIdleValue(), false);
         $ilAuth->setExpire(0);
         switch ($this->object->getMailNotification()) {
             case 1:
                 $this->object->sendSimpleNotification($active_id);
                 break;
             case 2:
                 $this->object->sendAdvancedNotification($active_id);
                 break;
         }
     }
     // Non-last try finish
     if (!$_SESSION['tst_pass_finish']) {
         if (!$_SESSION['tst_pass_finish']) {
             $_SESSION['tst_pass_finish'] = 1;
         }
         if ($this->object->getMailNotificationType() == 1) {
             switch ($this->object->getMailNotification()) {
                 case 1:
                     $this->object->sendSimpleNotification($active_id);
                     break;
                 case 2:
                     $this->object->sendAdvancedNotification($active_id);
                     break;
             }
         }
     }
     // no redirect request loops after test pass finished tasks has been performed
     $this->performTestPassFinishedTasks($actualpass);
     $this->testSession->setLastFinishedPass($this->testSession->getPass());
     $this->testSession->increaseTestPass();
     $this->ctrl->redirect($this, 'afterTestPassFinished');
 }
 function finishTestCmd($requires_confirmation = true)
 {
     global $ilUser, $ilAuth;
     unset($_SESSION["tst_next"]);
     $active_id = $this->testSession->getActiveId();
     $actualpass = $this->object->_getPass($active_id);
     $allObligationsAnswered = ilObjTest::allObligationsAnswered($this->testSession->getTestId(), $active_id, $actualpass);
     /*
      * The following "endgames" are possible prior to actually finishing the test:
      * - Obligations (Ability to finish the test.)
      *      If not all obligatory questions are answered, the user is presented a list
      *      showing the deficits.
      * - Examview (Will to finish the test.)
      *      With the examview, the participant can review all answers given in ILIAS or a PDF prior to
      *      commencing to the finished test.
      * - Last pass allowed (Reassuring the will to finish the test.)
      *      If passes are limited, on the last pass, an additional confirmation is to be displayed.
      */
     // Obligations fulfilled? redirectQuestion : one or the other summary -> no finish
     if ($this->object->areObligationsEnabled() && !$allObligationsAnswered) {
         if ($this->object->getListOfQuestions()) {
             $_GET['activecommand'] = 'summary_obligations';
         } else {
             $_GET['activecommand'] = 'summary_obligations_only';
         }
         $this->redirectQuestion();
         return;
     }
     // Examview enabled & !reviewed & requires_confirmation? test_submission_overview (review gui)
     if ($this->object->getEnableExamview() && !isset($_GET['reviewed']) && $requires_confirmation) {
         $_GET['activecommand'] = 'test_submission_overview';
         $this->redirectQuestionCmd();
         return;
     }
     // Last try in limited tries & !confirmed
     if ($requires_confirmation && $actualpass == $this->object->getNrOfTries() - 1) {
         if ($this->object->canShowSolutionPrintview($ilUser->getId())) {
             $template = new ilTemplate("tpl.il_as_tst_finish_navigation.html", TRUE, TRUE, "Modules/Test");
             $template->setVariable("BUTTON_FINISH", $this->lng->txt("btn_next"));
             $template->setVariable("BUTTON_CANCEL", $this->lng->txt("btn_previous"));
             $template_top = new ilTemplate("tpl.il_as_tst_list_of_answers_topbuttons.html", TRUE, TRUE, "Modules/Test");
             $template_top->setCurrentBlock("button_print");
             $template_top->setVariable("BUTTON_PRINT", $this->lng->txt("print"));
             $template_top->parseCurrentBlock();
             $this->showListOfAnswers($active_id, NULL, $template_top->get(), $template->get());
             return;
         } else {
             // show confirmation page
             return $this->confirmFinishTestCmd();
         }
     }
     // Last try in limited tries & confirmed?
     if ($actualpass == $this->object->getNrOfTries() - 1 && !$requires_confirmation) {
         $this->object->setActiveTestSubmitted($ilUser->getId());
         $ilAuth->setIdle(ilSession::getIdleValue(), false);
         $ilAuth->setExpire(0);
         switch ($this->object->getMailNotification()) {
             case 1:
                 $this->object->sendSimpleNotification($active_id);
                 break;
             case 2:
                 $this->object->sendAdvancedNotification($active_id);
                 break;
         }
     }
     // Non-last try finish
     if (!$_SESSION['tst_pass_finish']) {
         if (!$_SESSION['tst_pass_finish']) {
             $_SESSION['tst_pass_finish'] = 1;
         }
         if ($this->object->getMailNotificationType() == 1) {
             switch ($this->object->getMailNotification()) {
                 case 1:
                     $this->object->sendSimpleNotification($active_id);
                     break;
                 case 2:
                     $this->object->sendAdvancedNotification($active_id);
                     break;
             }
         }
         $this->testSession->increaseTestPass();
         ilSession::set('passincreased', $actualpass);
     }
     if ($this->object->getEnableArchiving()) {
         $this->archiveParticipantSubmission($active_id, $actualpass);
     }
     /** @var $ilPluginAdmin ilPluginAdmin */
     global $ilPluginAdmin, $ilCtrl;
     if ($this->object->getSignSubmission() && count($ilPluginAdmin->getActivePluginsForSlot(IL_COMP_MODULE, 'Test', 'tsig')) != 0) {
         $key = 'signed_' . $active_id . '_' . $actualpass;
         if (ilSession::get('passincreased') != null) {
             $key = 'signed_' . $active_id . '_' . ilSession::get('passincreased');
         }
         $val = ilSession::get($key);
         if (is_null($val)) {
             /** @var $ilCtrl ilCtrl */
             $ilCtrl->redirectByClass('ilTestSignatureGUI', 'invokeSignaturePlugin');
         }
     }
     // Redirect after test
     $redirection_mode = $this->object->getRedirectionMode();
     $redirection_url = $this->object->getRedirectionUrl();
     if ($redirection_url && $redirection_mode && !$this->object->canViewResults()) {
         if ($redirection_mode == REDIRECT_KIOSK) {
             if ($this->object->getKioskMode()) {
                 ilUtil::redirect($redirection_url);
             }
         } else {
             ilUtil::redirect($redirection_url);
         }
     }
     $this->redirectBackCmd();
 }