/**
  * Creates the learners output of a question
  */
 protected function outWorkingForm($sequence = "", $test_id, $postpone_allowed, $directfeedback = false)
 {
     global $ilUser;
     if (!$this->isValidSequenceElement($sequence)) {
         $sequence = $this->testSequence->getFirstSequence();
     }
     $_SESSION["active_time_id"] = $this->object->startWorkingTime($this->testSession->getActiveId(), $this->testSession->getPass());
     $this->populateContentStyleBlock();
     $this->populateSyntaxStyleBlock();
     if ($this->object->getListOfQuestions()) {
         $this->showSideList();
     }
     $questionId = $this->testSequence->getQuestionForSequence($sequence);
     if (!(int) $questionId && $this->testSession->isObjectiveOriented()) {
         ilUtil::sendFailure(sprintf($this->lng->txt('tst_objective_oriented_test_pass_without_questions'), $this->object->getTitle()), true);
         $this->performCustomRedirect();
     }
     $question_gui = $this->object->createQuestionGUI("", $questionId);
     if (!is_object($question_gui)) {
         global $ilLog;
         $ilLog->write("INV SEQ: active={$this->testSession->getActiveId()} qId={$questionId} seq={$sequence} " . serialize($this->testSequence));
         $ilLog->logStack('INV SEQ');
         $this->ctrl->setParameter($this, 'gotosequence', $this->testSequence->getFirstSequence());
         $this->ctrl->setParameter($this, 'activecommand', 'gotoquestion');
         $this->ctrl->redirect($this, 'redirectQuestion');
     }
     $question_gui->setTargetGui($this);
     if ($this->object->getJavaScriptOutput()) {
         $question_gui->object->setOutputType(OUTPUT_JAVASCRIPT);
     }
     $is_postponed = $this->testSequence->isPostponedQuestion($question_gui->object->getId());
     $this->ctrl->setParameter($this, "sequence", "{$sequence}");
     $formaction = $this->ctrl->getFormAction($this, "gotoQuestion");
     $question_gui->setSequenceNumber($this->testSequence->getPositionOfSequence($sequence));
     $question_gui->setQuestionCount($this->testSequence->getUserQuestionCount());
     // output question
     $user_post_solution = FALSE;
     if (array_key_exists("previouspost", $_SESSION)) {
         $user_post_solution = $_SESSION["previouspost"];
         unset($_SESSION["previouspost"]);
     }
     // Determine $answer_feedback: It should hold a boolean stating if answer-specific-feedback is to be given.
     // It gets the parameter "Scoring and Results" -> "Instant Feedback" -> "Show Answer-Specific Feedback"
     // $directfeedback holds a boolean stating if the instant feedback was requested using the "Check" button.
     $answer_feedback = FALSE;
     if ($directfeedback && $this->object->getSpecificAnswerFeedback()) {
         $answer_feedback = TRUE;
     }
     if ($this->isParticipantsAnswerFixed($questionId)) {
         $solutionoutput = $question_gui->getSolutionOutput($this->testSession->getActiveId(), NULL, FALSE, false, true, $answer_feedback, false, FALSE, true);
         $pageoutput = $question_gui->outQuestionPage("", $this->testSequence->isPostponedQuestion($questionId), $this->testSession->getActiveId(), $solutionoutput);
         $this->tpl->setVariable("QUESTION_OUTPUT", $pageoutput);
         $this->tpl->setVariable("FORMACTION", $formaction);
         $directfeedback = true;
     } else {
         // Answer specific feedback is rendered into the display of the test question with in the concrete question types outQuestionForTest-method.
         // Notation of the params prior to getting rid of this crap in favor of a class
         $question_gui->outQuestionForTest($formaction, $this->testSession->getActiveId(), NULL, $is_postponed, $user_post_solution, $answer_feedback);
         // The display of specific inline feedback and specific feedback in an own block is to honor questions, which
         // have the possibility to embed the specific feedback into their output while maintaining compatibility to
         // questions, which do not have such facilities. E.g. there can be no "specific inline feedback" for essay
         // questions, while the multiple-choice questions do well.
         $this->fillQuestionRelatedNavigation($question_gui);
     }
     if ($directfeedback) {
         // This controls if the solution should be shown.
         // It gets the parameter "Scoring and Results" -> "Instant Feedback" -> "Show Solutions"
         if ($this->object->getInstantFeedbackSolution()) {
             $show_question_inline_score = $this->determineInlineScoreDisplay();
             // Notation of the params prior to getting rid of this crap in favor of a class
             $solutionoutput = $question_gui->getSolutionOutput($this->testSession->getActiveId(), NULL, FALSE, $show_question_inline_score, FALSE, FALSE, TRUE, FALSE, FALSE);
             $this->populateSolutionBlock($solutionoutput);
         }
         // This controls if the score should be shown.
         // It gets the parameter "Scoring and Results" -> "Instant Feedback" -> "Show Results (Only Points)"
         if ($this->object->getAnswerFeedbackPoints()) {
             $reachedPoints = $question_gui->object->getAdjustedReachedPoints($this->testSession->getActiveId(), NULL);
             $maxPoints = $question_gui->object->getMaximumPoints();
             $this->populateScoreBlock($reachedPoints, $maxPoints);
         }
         // This controls if the generic feedback should be shown.
         // It gets the parameter "Scoring and Results" -> "Instant Feedback" -> "Show Solutions"
         if ($this->object->getGenericAnswerFeedback()) {
             $this->populateGenericFeedbackBlock($question_gui);
         }
         // This controls if the specific feedback should be shown.
         // It gets the parameter "Scoring and Results" -> "Instant Feedback" -> "Show Answer-Specific Feedback"
         if ($this->object->getSpecificAnswerFeedback()) {
             $this->populateSpecificFeedbackBlock($question_gui);
         }
     }
     $this->populatePreviousButtons($sequence);
     if ($postpone_allowed && !$is_postponed) {
         $this->populatePostponeButtons();
     }
     if ($this->object->getListOfQuestions()) {
         $this->populateSummaryButtons();
     }
     if ($this->object->getShowCancel()) {
         $this->populateCancelButtonBlock();
     }
     if ($this->isLastQuestionInSequence($question_gui)) {
         if ($this->object->getListOfQuestionsEnd()) {
             $this->populateNextButtonsLeadingToSummary();
         } else {
             $this->populateNextButtonsLeadingToEndOfTest();
         }
     } else {
         $this->populateNextButtonsLeadingToQuestion();
     }
     if ($this->object->getShowMarker()) {
         include_once "./Modules/Test/classes/class.ilObjTest.php";
         $solved_array = ilObjTest::_getSolvedQuestions($this->testSession->getActiveId(), $question_gui->object->getId());
         $solved = 0;
         if (count($solved_array) > 0) {
             $solved = array_pop($solved_array);
             $solved = $solved["solved"];
         }
         if ($solved == 1) {
             $this->populateQuestionMarkingBlockAsMarked();
         } else {
             $this->populateQuestionMarkingBlockAsUnmarked();
         }
     }
     $this->populateCharSelector();
     if ($this->object->getJavaScriptOutput()) {
         $this->tpl->setVariable("JAVASCRIPT_TITLE", $this->lng->txt("disable_javascript"));
         $this->ctrl->setParameter($this, "tst_javascript", "0");
         $this->tpl->setVariable("JAVASCRIPT_URL", $this->ctrl->getLinkTarget($this, "gotoQuestion"));
     } else {
         $this->tpl->setVariable("JAVASCRIPT_TITLE", $this->lng->txt("enable_javascript"));
         $this->ctrl->setParameter($this, "tst_javascript", "1");
         $this->tpl->setVariable("JAVASCRIPT_URL", $this->ctrl->getLinkTarget($this, "gotoQuestion"));
     }
     if ($question_gui->object->requiresJsSwitch() && !$this->object->getForceJS()) {
         $this->tpl->touchBlock("jsswitch");
     }
     $this->tpl->addJavaScript(ilUtil::getJSLocation("autosave.js", "Modules/Test"));
     $this->tpl->setVariable("AUTOSAVE_URL", $this->ctrl->getFormAction($this, "autosave", "", true));
     if ($question_gui->isAutosaveable() && $this->object->getAutosave()) {
         $this->tpl->touchBlock('autosave');
         //$this->tpl->setVariable("BTN_SAVE", "Zwischenspeichern");
         //$this->tpl->setVariable("CMD_SAVE", "gotoquestion_{$sequence}");
         //$this->tpl->setVariable("AUTOSAVEFORMACTION", str_replace("&", "&", $this->ctrl->getFormAction($this)));
         $this->tpl->setVariable("AUTOSAVEFORMACTION", str_replace("&", "&", $this->ctrl->getLinkTarget($this, "autosave")));
         $this->tpl->setVariable("AUTOSAVEINTERVAL", $this->object->getAutosaveIval());
     }
     if ($this->object->areObligationsEnabled() && ilObjTest::isQuestionObligatory($question_gui->object->getId())) {
         $this->tpl->touchBlock('question_obligatory');
         $this->tpl->setVariable('QUESTION_OBLIGATORY', $this->lng->txt('required_field'));
     }
 }
 function &getSequenceSummary($obligationsFilter = false)
 {
     $correctedsequence = $this->getCorrectedSequence();
     $result_array = array();
     include_once "./Modules/Test/classes/class.ilObjTest.php";
     $solved_questions = ilObjTest::_getSolvedQuestions($this->active_id);
     $key = 1;
     foreach ($correctedsequence as $sequence) {
         $question =& ilObjTest::_instanciateQuestion($this->getQuestionForSequence($sequence));
         if (is_object($question)) {
             $worked_through = $question->_isWorkedThrough($this->active_id, $question->getId(), $this->pass);
             $solved = 0;
             if (array_key_exists($question->getId(), $solved_questions)) {
                 $solved = $solved_questions[$question->getId()]["solved"];
             }
             $is_postponed = $this->isPostponedQuestion($question->getId());
             $row = array("nr" => "{$key}", "title" => $question->getTitle(), "qid" => $question->getId(), "visited" => $worked_through, "solved" => $solved ? "1" : "0", "description" => $question->getComment(), "points" => $question->getMaximumPoints(), "worked_through" => $worked_through, "postponed" => $is_postponed, "sequence" => $sequence, "obligatory" => ilObjTest::isQuestionObligatory($question->getId()), 'isAnswered' => $question->isAnswered($this->active_id, $this->pass));
             if (!$obligationsFilter || $row['obligatory']) {
                 array_push($result_array, $row);
             }
             $key++;
         }
     }
     return $result_array;
 }
 /**
  * Output of a summary of all test questions for test participants
  */
 public function outQuestionSummary($fullpage = true, $contextFinishTest = false, $obligationsNotAnswered = false, $obligationsFilter = false)
 {
     if ($fullpage) {
         $this->tpl->addBlockFile($this->getContentBlockName(), "adm_content", "tpl.il_as_tst_question_summary.html", "Modules/Test");
     }
     if ($obligationsNotAnswered) {
         ilUtil::sendFailure($this->lng->txt('not_all_obligations_answered'));
     }
     $active_id = $this->object->getTestSession()->getActiveId();
     $result_array =& $this->object->getTestSequence()->getSequenceSummary($obligationsFilter);
     $marked_questions = array();
     if ($this->object->getKioskMode() && $fullpage) {
         $head = $this->getKioskHead();
         if (strlen($head)) {
             $this->tpl->setCurrentBlock("kiosk_options");
             $this->tpl->setVariable("KIOSK_HEAD", $head);
             $this->tpl->parseCurrentBlock();
         }
     }
     if ($this->object->getShowMarker()) {
         include_once "./Modules/Test/classes/class.ilObjTest.php";
         $marked_questions = ilObjTest::_getSolvedQuestions($active_id);
     }
     $data = array();
     foreach ($result_array as $key => $value) {
         $this->ctrl->setParameter($this, "sequence", $value["sequence"]);
         $href = $this->ctrl->getLinkTargetByClass(get_class($this), "gotoQuestion");
         $this->tpl->setVariable("VALUE_QUESTION_TITLE", "<a href=\"" . $this->ctrl->getLinkTargetByClass(get_class($this), "gotoQuestion") . "\">" . $this->object->getQuestionTitle($value["title"]) . "</a>");
         $this->ctrl->setParameter($this, "sequence", $_GET["sequence"]);
         $description = "";
         if ($this->object->getListOfQuestionsDescription()) {
             $description = $value["description"];
         }
         $points = "";
         if (!$this->object->getTitleOutput()) {
             $points = $value["points"] . "&nbsp;" . $this->lng->txt("points_short");
         }
         $marked = false;
         if (count($marked_questions)) {
             if (array_key_exists($value["qid"], $marked_questions)) {
                 $obj = $marked_questions[$value["qid"]];
                 if ($obj["solved"] == 1) {
                     $marked = true;
                 }
             }
         }
         array_push($data, array('order' => $value["nr"], 'href' => $href, 'title' => $this->object->getQuestionTitle($value["title"]), 'description' => $description, 'worked_through' => $value["worked_through"] ? true : false, 'postponed' => $value["postponed"] ? $this->lng->txt("postponed") : '', 'points' => $points, 'marked' => $marked, 'sequence' => $value["sequence"], 'obligatory' => $value['obligatory']));
     }
     $this->ctrl->setParameter($this, "sequence", $_GET["sequence"]);
     if ($fullpage) {
         include_once "./Modules/Test/classes/tables/class.ilListOfQuestionsTableGUI.php";
         $table_gui = new ilListOfQuestionsTableGUI($this, 'backFromSummary', !$this->object->getTitleOutput(), $this->object->getShowMarker(), $obligationsNotAnswered, $obligationsFilter);
         $table_gui->setData($data);
         $this->tpl->setVariable('TABLE_LIST_OF_QUESTIONS', $table_gui->getHTML());
         if ($this->object->getEnableProcessingTime()) {
             $this->outProcessingTime($active_id);
         }
     } else {
         $template = new ilTemplate('tpl.il_as_tst_list_of_questions_short.html', true, true, 'Modules/Test');
         foreach ($data as $row) {
             if (strlen($row['description'])) {
                 $template->setCurrentBlock('description');
                 $template->setVariable("DESCRIPTION", $row['description']);
                 $template->parseCurrentBlock();
             }
             $active = $row['sequence'] == $this->sequence ? ' active' : '';
             $template->setCurrentBlock('item');
             $template->setVariable('CLASS', $row['walked_through'] ? 'answered' . $active : 'unanswered' . $active);
             $template->setVariable('ITEM', ilUtil::prepareFormOutput($row['title']));
             $template->setVariable('SEQUENCE', $row['sequence']);
             $template->parseCurrentBlock();
         }
         $template->setVariable('LIST_OF_QUESTIONS', $this->lng->txt('list_of_questions'));
         $this->tpl->setVariable('LIST_OF_QUESTIONS', $template->get());
     }
 }
 protected function getMarkedQuestions()
 {
     if ($this->object->getShowMarker()) {
         include_once "./Modules/Test/classes/class.ilObjTest.php";
         $marked_questions = ilObjTest::_getSolvedQuestions($this->testSession->getActiveId());
     } else {
         $marked_questions = array();
     }
     return $marked_questions;
 }
 /**
  * Creates the learners output of a question
  */
 protected function outWorkingForm($sequence = "", $test_id, $postpone_allowed, $directfeedback = false)
 {
     global $ilUser;
     $_SESSION["active_time_id"] = $this->object->startWorkingTime($this->testSession->getActiveId(), $this->testSession->getPass());
     $this->populateContentStyleBlock();
     $this->populateSyntaxStyleBlock();
     $question_gui = $this->object->createQuestionGUI("", $this->testSession->getCurrentQuestionId());
     $question_gui->setTargetGui($this);
     $question_gui->setQuestionCount($this->testSequence->getLastPositionIndex());
     $question_gui->setSequenceNumber($this->testSequence->getCurrentPositionIndex($this->testSession->getCurrentQuestionId()));
     $this->ctrl->setParameter($this, 'sequence', $this->testSession->getCurrentQuestionId());
     if ($this->object->getJavaScriptOutput()) {
         $question_gui->object->setOutputType(OUTPUT_JAVASCRIPT);
     }
     $is_postponed = $this->testSequence->isPostponedQuestion($question_gui->object->getId());
     $formaction = $this->ctrl->getFormAction($this);
     // output question
     $user_post_solution = FALSE;
     if (isset($_SESSION['previouspost'])) {
         $user_post_solution = $_SESSION['previouspost'];
         unset($_SESSION['previouspost']);
     }
     global $ilNavigationHistory;
     $ilNavigationHistory->addItem($_GET["ref_id"], $this->ctrl->getLinkTarget($this, "resumePlayer"), "tst");
     // Determine $answer_feedback: It should hold a boolean stating if answer-specific-feedback is to be given.
     // It gets the parameter "Scoring and Results" -> "Instant Feedback" -> "Show Answer-Specific Feedback"
     // $directfeedback holds a boolean stating if the instant feedback was requested using the "Check" button.
     $answer_feedback = FALSE;
     if ($directfeedback && $this->object->getSpecificAnswerFeedback()) {
         $answer_feedback = TRUE;
     }
     // Answer specific feedback is rendered into the display of the test question with in the concrete question types outQuestionForTest-method.
     // Notation of the params prior to getting rid of this crap in favor of a class
     $question_gui->outQuestionForTest($formaction, $this->testSession->getActiveId(), NULL, $is_postponed, $user_post_solution, $answer_feedback);
     // The display of specific inline feedback and specific feedback in an own block is to honor questions, which
     // have the possibility to embed the specific feedback into their output while maintaining compatibility to
     // questions, which do not have such facilities. E.g. there can be no "specific inline feedback" for essay
     // questions, while the multiple-choice questions do well.
     $this->fillQuestionRelatedNavigation($question_gui);
     if ($directfeedback) {
         // This controls if the solution should be shown.
         // It gets the parameter "Scoring and Results" -> "Instant Feedback" -> "Show Solutions"
         if ($this->object->getInstantFeedbackSolution()) {
             $show_question_inline_score = $this->determineInlineScoreDisplay();
             // Notation of the params prior to getting rid of this crap in favor of a class
             $solutionoutput = $question_gui->getSolutionOutput($this->testSession->getActiveId(), NULL, TRUE, $show_question_inline_score, FALSE, FALSE, TRUE, FALSE, FALSE);
             $this->populateSolutionBlock($solutionoutput);
         }
         // This controls if the score should be shown.
         // It gets the parameter "Scoring and Results" -> "Instant Feedback" -> "Show Results (Only Points)"
         if ($this->object->getAnswerFeedbackPoints()) {
             $reachedPoints = $question_gui->object->getAdjustedReachedPoints($this->testSession->getActiveId(), NULL);
             $maxPoints = $question_gui->object->getMaximumPoints();
             $this->populateScoreBlock($reachedPoints, $maxPoints);
         }
         // This controls if the generic feedback should be shown.
         // It gets the parameter "Scoring and Results" -> "Instant Feedback" -> "Show Solutions"
         if ($this->object->getGenericAnswerFeedback()) {
             $this->populateGenericFeedbackBlock($question_gui);
         }
         // This controls if the specific feedback should be shown.
         // It gets the parameter "Scoring and Results" -> "Instant Feedback" -> "Show Answer-Specific Feedback"
         if ($this->object->getSpecificAnswerFeedback()) {
             $this->populateSpecificFeedbackBlock($question_gui);
         }
     }
     $this->populatePreviousButtons($this->testSession->getCurrentQuestionId());
     if ($postpone_allowed) {
         $this->populatePostponeButtons();
     }
     if ($this->object->getShowCancel()) {
         $this->populateCancelButtonBlock();
     }
     if ($this->isLastQuestionInSequence($question_gui)) {
         if ($this->object->getListOfQuestionsEnd()) {
             $this->populateNextButtonsLeadingToSummary();
         } else {
             $this->populateNextButtonsLeadingToEndOfTest();
         }
     } else {
         $this->populateNextButtonsLeadingToQuestion();
     }
     if ($this->dynamicQuestionSetConfig->isTaxonomyFilterEnabled()) {
         $this->populateQuestionSelectionButtons();
     }
     if ($this->object->getShowMarker()) {
         include_once "./Modules/Test/classes/class.ilObjTest.php";
         $solved_array = ilObjTest::_getSolvedQuestions($this->testSession->getActiveId(), $question_gui->object->getId());
         $solved = 0;
         if (count($solved_array) > 0) {
             $solved = array_pop($solved_array);
             $solved = $solved["solved"];
         }
         if ($solved == 1) {
             $this->populateQuestionMarkingBlockAsMarked();
         } else {
             $this->populateQuestionMarkingBlockAsUnmarked();
         }
     }
     if ($this->object->getJavaScriptOutput()) {
         $this->tpl->setVariable("JAVASCRIPT_IMAGE", ilUtil::getImagePath("javascript_disable.png"));
         $this->tpl->setVariable("JAVASCRIPT_IMAGE_ALT", $this->lng->txt("disable_javascript"));
         $this->tpl->setVariable("JAVASCRIPT_IMAGE_TITLE", $this->lng->txt("disable_javascript"));
         $this->ctrl->setParameter($this, "tst_javascript", "0");
         $this->tpl->setVariable("JAVASCRIPT_URL", $this->ctrl->getLinkTarget($this, "gotoQuestion"));
     } else {
         $this->tpl->setVariable("JAVASCRIPT_IMAGE", ilUtil::getImagePath("javascript.png"));
         $this->tpl->setVariable("JAVASCRIPT_IMAGE_ALT", $this->lng->txt("enable_javascript"));
         $this->tpl->setVariable("JAVASCRIPT_IMAGE_TITLE", $this->lng->txt("enable_javascript"));
         $this->ctrl->setParameter($this, "tst_javascript", "1");
         $this->tpl->setVariable("JAVASCRIPT_URL", $this->ctrl->getLinkTarget($this, "gotoQuestion"));
     }
     if ($question_gui->object->supportsJavascriptOutput()) {
         $this->tpl->touchBlock("jsswitch");
     }
     $this->tpl->addJavaScript(ilUtil::getJSLocation("autosave.js", "Modules/Test"));
     $this->tpl->setVariable("AUTOSAVE_URL", $this->ctrl->getFormAction($this, "autosave", "", true));
     if ($question_gui->isAutosaveable() && $this->object->getAutosave()) {
         $this->tpl->touchBlock('autosave');
         //$this->tpl->setVariable("BTN_SAVE", "Zwischenspeichern");
         //$this->tpl->setVariable("CMD_SAVE", "gotoquestion_{$sequence}");
         //$this->tpl->setVariable("AUTOSAVEFORMACTION", str_replace("&amp;", "&", $this->ctrl->getFormAction($this)));
         $this->tpl->setVariable("AUTOSAVEFORMACTION", str_replace("&amp;", "&", $this->ctrl->getLinkTarget($this, "autosave")));
         $this->tpl->setVariable("AUTOSAVEINTERVAL", $this->object->getAutosaveIval());
     }
     if ($this->object->areObligationsEnabled() && ilObjTest::isQuestionObligatory($question_gui->object->getId())) {
         $this->tpl->touchBlock('question_obligatory');
         $this->tpl->setVariable('QUESTION_OBLIGATORY', $this->lng->txt('required_field'));
     }
 }