1<?php 2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */ 3 4include_once "./Modules/Test/classes/inc.AssessmentConstants.php"; 5include_once 'Modules/Test/classes/class.ilTestService.php'; 6 7/** 8* Service GUI class for tests. This class is the parent class for all 9* service classes which are called from ilObjTestGUI. This is mainly 10* done to reduce the size of ilObjTestGUI to put command service functions 11* into classes that could be called by ilCtrl. 12* 13* @ilCtrl_IsCalledBy ilTestServiceGUI: ilObjTestGUI 14* 15* @author Helmut Schottmüller <helmut.schottmueller@mac.com> 16* @author Björn Heyser <bheyser@databay.de> 17* @version $Id$ 18* 19* @ingroup ModulesTest 20*/ 21class ilTestServiceGUI 22{ 23 /** 24 * @var ilObjTest 25 */ 26 public $object = null; 27 28 /** 29 * @var ilTestService 30 */ 31 public $service = null; 32 33 /** 34 * @var ilDBInterface 35 */ 36 protected $db; 37 38 public $lng; 39 /** @var ilGlobalTemplateInterface */ 40 public $tpl; 41 42 /** 43 * @var ilCtrl 44 */ 45 public $ctrl; 46 47 /** 48 * @var ilTabsGUI 49 */ 50 protected $tabs; 51 52 /** 53 * @var ilObjectDataCache 54 */ 55 protected $objCache; 56 57 public $ilias; 58 public $tree; 59 public $ref_id; 60 61 /** 62 * factory for test session 63 * 64 * @var ilTestSessionFactory 65 */ 66 protected $testSessionFactory = null; 67 68 /** 69 * factory for test sequence 70 * 71 * @var ilTestSequenceFactory 72 */ 73 protected $testSequenceFactory = null; 74 75 /** 76 * @var ilTestParticipantData 77 */ 78 protected $participantData; 79 80 /** 81 * @var ilTestObjectiveOrientedContainer 82 */ 83 private $objectiveOrientedContainer; 84 85 private $contextResultPresentation = true; 86 87 /** 88 * @return boolean 89 */ 90 public function isContextResultPresentation() 91 { 92 return $this->contextResultPresentation; 93 } 94 95 /** 96 * @param boolean $contextResultPresentation 97 */ 98 public function setContextResultPresentation($contextResultPresentation) 99 { 100 $this->contextResultPresentation = $contextResultPresentation; 101 } 102 103 /** 104 * The constructor takes the test object reference as parameter 105 * 106 * @param object $a_object Associated ilObjTest class 107 * @access public 108 */ 109 public function __construct(ilObjTest $a_object) 110 { 111 global $DIC; 112 $lng = $DIC['lng']; 113 $tpl = $DIC['tpl']; 114 $ilCtrl = $DIC['ilCtrl']; 115 $ilias = $DIC['ilias']; 116 $tree = $DIC['tree']; 117 $ilDB = $DIC['ilDB']; 118 $ilPluginAdmin = $DIC['ilPluginAdmin']; 119 $ilTabs = $DIC['ilTabs']; 120 $ilObjDataCache = $DIC['ilObjDataCache']; 121 122 $lng->loadLanguageModule('cert'); 123 124 $this->db = $ilDB; 125 $this->lng = &$lng; 126 $this->tpl = &$tpl; 127 $this->ctrl = &$ilCtrl; 128 $this->tabs = $ilTabs; 129 $this->objCache = $ilObjDataCache; 130 $this->ilias = &$ilias; 131 $this->object = &$a_object; 132 $this->tree = &$tree; 133 $this->ref_id = $a_object->ref_id; 134 135 $this->service = new ilTestService($a_object); 136 137 require_once 'Modules/Test/classes/class.ilTestSessionFactory.php'; 138 $this->testSessionFactory = new ilTestSessionFactory($this->object); 139 140 require_once 'Modules/Test/classes/class.ilTestSequenceFactory.php'; 141 $this->testSequenceFactory = new ilTestSequenceFactory($ilDB, $lng, $ilPluginAdmin, $this->object); 142 143 $this->objectiveOrientedContainer = null; 144 } 145 146 /** 147 * @param \ilTestParticipantData $participantData 148 */ 149 public function setParticipantData($participantData) 150 { 151 $this->participantData = $participantData; 152 } 153 154 /** 155 * @return \ilTestParticipantData 156 */ 157 public function getParticipantData() 158 { 159 return $this->participantData; 160 } 161 162 /** 163 * @param ilTestSession $testSession 164 * @param $short 165 * @return array 166 */ 167 public function getPassOverviewTableData(ilTestSession $testSession, $passes, $withResults) 168 { 169 $data = array(); 170 171 if ($this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired()) { 172 $considerHiddenQuestions = false; 173 174 require_once 'Modules/Course/classes/Objectives/class.ilLOTestQuestionAdapter.php'; 175 $objectivesAdapter = ilLOTestQuestionAdapter::getInstance($testSession); 176 } else { 177 $considerHiddenQuestions = true; 178 } 179 180 $scoredPass = $this->object->_getResultPass($testSession->getActiveId()); 181 182 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionHintTracking.php'; 183 $questionHintRequestRegister = ilAssQuestionHintTracking::getRequestRequestStatisticDataRegisterByActiveId( 184 $testSession->getActiveId() 185 ); 186 187 foreach ($passes as $pass) { 188 $row = array(); 189 190 $considerOptionalQuestions = true; 191 192 if ($this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired()) { 193 $testSequence = $this->testSequenceFactory->getSequenceByActiveIdAndPass($testSession->getActiveId(), $pass); 194 195 $testSequence->loadFromDb(); 196 $testSequence->loadQuestions(); 197 198 if ($this->object->isRandomTest() && !$testSequence->isAnsweringOptionalQuestionsConfirmed()) { 199 $considerOptionalQuestions = false; 200 } 201 202 $testSequence->setConsiderHiddenQuestionsEnabled($considerHiddenQuestions); 203 $testSequence->setConsiderOptionalQuestionsEnabled($considerOptionalQuestions); 204 205 $objectivesList = $this->buildQuestionRelatedObjectivesList($objectivesAdapter, $testSequence); 206 $objectivesList->loadObjectivesTitles(); 207 208 $row['objectives'] = $objectivesList->getUniqueObjectivesStringForQuestions($testSequence->getUserSequenceQuestions()); 209 } 210 211 if ($withResults) { 212 $result_array = $this->object->getTestResult($testSession->getActiveId(), $pass, false, $considerHiddenQuestions, $considerOptionalQuestions); 213 214 foreach ($result_array as $resultStructKEY => $question) { 215 if ($resultStructKEY === 'test' || $resultStructKEY === 'pass') { 216 continue; 217 } 218 219 $requestData = $questionHintRequestRegister->getRequestByTestPassIndexAndQuestionId($pass, $question['qid']); 220 221 if ($requestData instanceof ilAssQuestionHintRequestStatisticData && $result_array[$resultStructKEY]['requested_hints'] === null) { 222 $result_array['pass']['total_requested_hints'] += $requestData->getRequestsCount(); 223 224 $result_array[$resultStructKEY]['requested_hints'] = $requestData->getRequestsCount(); 225 $result_array[$resultStructKEY]['hint_points'] = $requestData->getRequestsPoints(); 226 } 227 } 228 229 if (!$result_array['pass']['total_max_points']) { 230 $percentage = 0; 231 } else { 232 $percentage = ($result_array['pass']['total_reached_points'] / $result_array['pass']['total_max_points']) * 100; 233 } 234 $total_max = $result_array['pass']['total_max_points']; 235 $total_reached = $result_array['pass']['total_reached_points']; 236 $total_requested_hints = $result_array['pass']['total_requested_hints']; 237 } 238 239 if ($withResults) { 240 $row['scored'] = ($pass == $scoredPass); 241 } 242 243 $row['pass'] = $pass; 244 $row['date'] = ilObjTest::lookupLastTestPassAccess($testSession->getActiveId(), $pass); 245 if ($withResults) { 246 $row['num_workedthrough_questions'] = $result_array['pass']['num_workedthrough']; 247 $row['num_questions_total'] = $result_array['pass']['num_questions_total']; 248 249 if ($this->object->isOfferingQuestionHintsEnabled()) { 250 $row['hints'] = $total_requested_hints; 251 } 252 253 $row['reached_points'] = $total_reached; 254 $row['max_points'] = $total_max; 255 $row['percentage'] = $percentage; 256 } 257 258 $data[] = $row; 259 } 260 261 return $data; 262 } 263 264 /** 265 * @param ilTestObjectiveOrientedContainer $objectiveOrientedContainer 266 */ 267 public function setObjectiveOrientedContainer(ilTestObjectiveOrientedContainer $objectiveOrientedContainer) 268 { 269 $this->objectiveOrientedContainer = $objectiveOrientedContainer; 270 } 271 272 /** 273 * @return ilTestObjectiveOrientedContainer 274 */ 275 public function getObjectiveOrientedContainer() 276 { 277 return $this->objectiveOrientedContainer; 278 } 279 280 /** 281 * execute command 282 */ 283 public function executeCommand() 284 { 285 $cmd = $this->ctrl->getCmd(); 286 $next_class = $this->ctrl->getNextClass($this); 287 288 $cmd = $this->getCommand($cmd); 289 switch ($next_class) { 290 default: 291 $ret = &$this->$cmd(); 292 break; 293 } 294 return $ret; 295 } 296 297 /** 298 * Retrieves the ilCtrl command 299 * 300 * @access public 301 */ 302 public function getCommand($cmd) 303 { 304 return $cmd; 305 } 306 307 /** 308 * @return bool 309 */ 310 protected function isPdfDeliveryRequest() 311 { 312 if (!isset($_GET['pdf'])) { 313 return false; 314 } 315 316 if (!(bool) $_GET['pdf']) { 317 return false; 318 } 319 320 return true; 321 } 322 323 /** 324 * @return ilTestPassOverviewTableGUI $tableGUI 325 */ 326 public function buildPassOverviewTableGUI($targetGUI) 327 { 328 require_once 'Modules/Test/classes/tables/class.ilTestPassOverviewTableGUI.php'; 329 330 $table = new ilTestPassOverviewTableGUI($targetGUI, ''); 331 332 $table->setPdfPresentationEnabled( 333 isset($_GET['pdf']) && $_GET['pdf'] == 1 334 ); 335 336 $table->setObjectiveOrientedPresentationEnabled( 337 $this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired() 338 ); 339 340 return $table; 341 } 342 343 /** 344 * Returns the list of answers of a users test pass 345 * 346 * @param array $result_array An array containing the results of the users test pass (generated by ilObjTest::getTestResult) 347 * @param integer $active_id Active ID of the active user 348 * @param integer $pass Test pass 349 * @param boolean $show_solutions TRUE, if the solution output should be shown in the answers, FALSE otherwise 350 * @return string HTML code of the list of answers 351 * @access public 352 */ 353 public function getPassListOfAnswers(&$result_array, $active_id, $pass, $show_solutions = false, $only_answered_questions = false, $show_question_only = false, $show_reached_points = false, $anchorNav = false, ilTestQuestionRelatedObjectivesList $objectivesList = null, ilTestResultHeaderLabelBuilder $testResultHeaderLabelBuilder = null) 354 { 355 $maintemplate = new ilTemplate("tpl.il_as_tst_list_of_answers.html", true, true, "Modules/Test"); 356 357 $counter = 1; 358 // output of questions with solutions 359 foreach ($result_array as $question_data) { 360 if (($question_data["workedthrough"] == 1) || ($only_answered_questions == false)) { 361 $template = new ilTemplate("tpl.il_as_qpl_question_printview.html", true, true, "Modules/TestQuestionPool"); 362 $question = $question_data["qid"]; 363 if (is_numeric($question)) { 364 $maintemplate->setCurrentBlock("printview_question"); 365 $question_gui = $this->object->createQuestionGUI("", $question); 366 if (is_object($question_gui)) { 367 if ($this->isPdfDeliveryRequest()) { 368 $question_gui->setRenderPurpose(assQuestionGUI::RENDER_PURPOSE_PRINT_PDF); 369 } 370 371 if ($anchorNav) { 372 $template->setCurrentBlock('block_id'); 373 $template->setVariable('BLOCK_ID', "detailed_answer_block_act_{$active_id}_qst_{$question}"); 374 $template->parseCurrentBlock(); 375 376 $template->setCurrentBlock('back_anchor'); 377 $template->setVariable('HREF_BACK_ANCHOR', "#pass_details_tbl_row_act_{$active_id}_qst_{$question}"); 378 $template->setVariable('TXT_BACK_ANCHOR', $this->lng->txt('tst_back_to_question_list')); 379 $template->parseCurrentBlock(); 380 } 381 382 if ($show_reached_points) { 383 $template->setCurrentBlock("result_points"); 384 $template->setVariable("RESULT_POINTS", $this->lng->txt("tst_reached_points") . ": " . $question_gui->object->getReachedPoints($active_id, $pass) . " " . $this->lng->txt("of") . " " . $question_gui->object->getMaximumPoints()); 385 $template->parseCurrentBlock(); 386 } 387 $template->setVariable("COUNTER_QUESTION", $counter . ". "); 388 $template->setVariable("TXT_QUESTION_ID", $this->lng->txt('question_id_short')); 389 $template->setVariable("QUESTION_ID", $question_gui->object->getId()); 390 $template->setVariable("QUESTION_TITLE", $this->object->getQuestionTitle($question_gui->object->getTitle())); 391 392 if ($objectivesList !== null) { 393 $objectives = $this->lng->txt('tst_res_lo_objectives_header') . ': '; 394 $objectives .= $objectivesList->getQuestionRelatedObjectiveTitles($question_gui->object->getId()); 395 $template->setVariable("OBJECTIVES", $objectives); 396 } 397 398 $show_question_only = ($this->object->getShowSolutionAnswersOnly()) ? true : false; 399 400 $showFeedback = $this->isContextResultPresentation() && $this->object->getShowSolutionFeedback(); 401 $show_solutions = $this->isContextResultPresentation() && $show_solutions; 402 403 if ($show_solutions) { 404 $compare_template = new ilTemplate('tpl.il_as_tst_answers_compare.html', true, true, 'Modules/Test'); 405 $compare_template->setVariable("HEADER_PARTICIPANT", $this->lng->txt('tst_header_participant')); 406 $compare_template->setVariable("HEADER_SOLUTION", $this->lng->txt('tst_header_solution')); 407 $result_output = $question_gui->getSolutionOutput($active_id, $pass, $show_solutions, false, $show_question_only, $showFeedback); 408 $best_output = $question_gui->getSolutionOutput($active_id, $pass, false, false, $show_question_only, false, true); 409 410 $compare_template->setVariable('PARTICIPANT', $result_output); 411 $compare_template->setVariable('SOLUTION', $best_output); 412 if ($question_gui->supportsIntermediateSolutionOutput() && $question_gui->hasIntermediateSolution($active_id, $pass)) { 413 $question_gui->setUseIntermediateSolution(true); 414 $intermediate_output = $question_gui->getSolutionOutput($active_id, $pass, $show_solutions, false, true, $showFeedback); 415 $question_gui->setUseIntermediateSolution(false); 416 $compare_template->setVariable('TXT_INTERMEDIATE', $this->lng->txt('autosavecontent')); 417 $compare_template->setVariable('INTERMEDIATE', $intermediate_output); 418 } 419 $template->setVariable('SOLUTION_OUTPUT', $compare_template->get()); 420 } else { 421 $result_output = $question_gui->getSolutionOutput($active_id, $pass, $show_solutions, false, $show_question_only, $showFeedback); 422 if ($question_gui->supportsIntermediateSolutionOutput() && $question_gui->hasIntermediateSolution($active_id, $pass)) { 423 $question_gui->setUseIntermediateSolution(true); 424 $intermediate_output = $question_gui->getSolutionOutput($active_id, $pass, $show_solutions, false, true, $showFeedback); 425 $question_gui->setUseIntermediateSolution(false); 426 $template->setVariable('TXT_INTERMEDIATE', $this->lng->txt('autosavecontent')); 427 $template->setVariable('INTERMEDIATE', $intermediate_output); 428 } 429 $template->setVariable('SOLUTION_OUTPUT', $result_output); 430 } 431 432 $maintemplate->setCurrentBlock("printview_question"); 433 $maintemplate->setVariable("QUESTION_PRINTVIEW", $template->get()); 434 $maintemplate->parseCurrentBlock(); 435 $counter++; 436 } 437 } 438 } 439 } 440 441 if ($testResultHeaderLabelBuilder !== null) { 442 if ($pass !== null) { 443 $headerText = $testResultHeaderLabelBuilder->getListOfAnswersHeaderLabel($pass + 1); 444 } else { 445 $headerText = $testResultHeaderLabelBuilder->getVirtualListOfAnswersHeaderLabel(); 446 } 447 } else { 448 $headerText = ''; 449 } 450 451 $maintemplate->setVariable("RESULTS_OVERVIEW", $headerText); 452 return $maintemplate->get(); 453 } 454 455 /** 456 * Returns the list of answers of a users test pass and offers a scoring option 457 * 458 * @param array $result_array An array containing the results of the users test pass (generated by ilObjTest::getTestResult) 459 * @param integer $active_id Active ID of the active user 460 * @param integer $pass Test pass 461 * @param boolean $show_solutions TRUE, if the solution output should be shown in the answers, FALSE otherwise 462 * @return string HTML code of the list of answers 463 * @access public 464 * 465 * @deprecated 466 */ 467 public function getPassListOfAnswersWithScoring(&$result_array, $active_id, $pass, $show_solutions = false) 468 { 469 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php"; 470 471 $maintemplate = new ilTemplate("tpl.il_as_tst_list_of_answers.html", true, true, "Modules/Test"); 472 473 include_once "./Modules/Test/classes/class.ilObjAssessmentFolder.php"; 474 $scoring = ilObjAssessmentFolder::_getManualScoring(); 475 476 $counter = 1; 477 // output of questions with solutions 478 foreach ($result_array as $question_data) { 479 $question = $question_data["qid"]; 480 if (is_numeric($question)) { 481 $question_gui = $this->object->createQuestionGUI("", $question); 482 if (in_array($question_gui->object->getQuestionTypeID(), $scoring)) { 483 $template = new ilTemplate("tpl.il_as_qpl_question_printview.html", true, true, "Modules/TestQuestionPool"); 484 $scoretemplate = new ilTemplate("tpl.il_as_tst_manual_scoring_points.html", true, true, "Modules/Test"); 485 #mbecker: No such block. $this->tpl->setCurrentBlock("printview_question"); 486 $template->setVariable("COUNTER_QUESTION", $counter . ". "); 487 $template->setVariable("QUESTION_TITLE", $this->object->getQuestionTitle($question_gui->object->getTitle())); 488 $points = $question_gui->object->getMaximumPoints(); 489 if ($points == 1) { 490 $template->setVariable("QUESTION_POINTS", $points . " " . $this->lng->txt("point")); 491 } else { 492 $template->setVariable("QUESTION_POINTS", $points . " " . $this->lng->txt("points")); 493 } 494 495 $show_question_only = ($this->object->getShowSolutionAnswersOnly()) ? true : false; 496 $result_output = $question_gui->getSolutionOutput($active_id, $pass, $show_solutions, false, $show_question_only, $this->object->getShowSolutionFeedback(), false, true); 497 498 $solout = $question_gui->object->getSuggestedSolutionOutput(); 499 if (strlen($solout)) { 500 $scoretemplate->setCurrentBlock("suggested_solution"); 501 $scoretemplate->setVariable("TEXT_SUGGESTED_SOLUTION", $this->lng->txt("solution_hint")); 502 $scoretemplate->setVariable("VALUE_SUGGESTED_SOLUTION", $solout); 503 $scoretemplate->parseCurrentBlock(); 504 } 505 506 $scoretemplate->setCurrentBlock("feedback"); 507 $scoretemplate->setVariable("FEEDBACK_NAME_INPUT", $question); 508 $feedback = $this->object->getSingleManualFeedback($active_id, $question, $pass)['feedback']; 509 $scoretemplate->setVariable("VALUE_FEEDBACK", ilUtil::prepareFormOutput($this->object->prepareTextareaOutput($feedback, true))); 510 $scoretemplate->setVariable("TEXT_MANUAL_FEEDBACK", $this->lng->txt("set_manual_feedback")); 511 $scoretemplate->parseCurrentBlock(); 512 513 $scoretemplate->setVariable("NAME_INPUT", $question); 514 $this->ctrl->setParameter($this, "active_id", $active_id); 515 $this->ctrl->setParameter($this, "pass", $pass); 516 $scoretemplate->setVariable("FORMACTION", $this->ctrl->getFormAction($this, "manscoring")); 517 $scoretemplate->setVariable("LABEL_INPUT", $this->lng->txt("tst_change_points_for_question")); 518 $scoretemplate->setVariable("VALUE_INPUT", " value=\"" . assQuestion::_getReachedPoints($active_id, $question_data["qid"], $pass) . "\""); 519 $scoretemplate->setVariable("VALUE_SAVE", $this->lng->txt("save")); 520 521 $template->setVariable("SOLUTION_OUTPUT", $result_output); 522 $maintemplate->setCurrentBlock("printview_question"); 523 $maintemplate->setVariable("QUESTION_PRINTVIEW", $template->get()); 524 $maintemplate->setVariable("QUESTION_SCORING", $scoretemplate->get()); 525 $maintemplate->parseCurrentBlock(); 526 } 527 $counter++; 528 } 529 } 530 if ($counter == 1) { 531 // no scorable questions found 532 $maintemplate->setVariable("NO_QUESTIONS_FOUND", $this->lng->txt("manscoring_questions_not_found")); 533 } 534 $maintemplate->setVariable("RESULTS_OVERVIEW", sprintf($this->lng->txt("manscoring_results_pass"), $pass + 1)); 535 536 include_once "./Services/YUI/classes/class.ilYuiUtil.php"; 537 ilYuiUtil::initDomEvent(); 538 539 return $maintemplate->get(); 540 } 541 542 protected function getPassDetailsOverviewTableGUI($result_array, $active_id, $pass, $targetGUI, $targetCMD, $questionDetailsCMD, $questionAnchorNav, ilTestQuestionRelatedObjectivesList $objectivesList = null, $multipleObjectivesInvolved = true) 543 { 544 $this->ctrl->setParameter($targetGUI, 'active_id', $active_id); 545 $this->ctrl->setParameter($targetGUI, 'pass', $pass); 546 547 $tableGUI = $this->buildPassDetailsOverviewTableGUI($targetGUI, $targetCMD); 548 549 if (!$this->isPdfDeliveryRequest()) { 550 $tableGUI->setAnswerListAnchorEnabled($questionAnchorNav); 551 } 552 553 $tableGUI->setSingleAnswerScreenCmd($questionDetailsCMD); 554 $tableGUI->setShowHintCount($this->object->isOfferingQuestionHintsEnabled()); 555 556 if ($objectivesList !== null) { 557 $tableGUI->setQuestionRelatedObjectivesList($objectivesList); 558 $tableGUI->setObjectiveOrientedPresentationEnabled(true); 559 } 560 561 $tableGUI->setMultipleObjectivesInvolved($multipleObjectivesInvolved); 562 563 $tableGUI->setActiveId($active_id); 564 $tableGUI->setShowSuggestedSolution(false); 565 566 $usersQuestionSolutions = array(); 567 568 foreach ($result_array as $key => $val) { 569 if ($key === 'test' || $key === 'pass') { 570 continue; 571 } 572 573 if ($this->object->getShowSolutionSuggested() && strlen($val['solution'])) { 574 $tableGUI->setShowSuggestedSolution(true); 575 } 576 577 if (isset($val['pass'])) { 578 $tableGUI->setPassColumnEnabled(true); 579 } 580 581 $usersQuestionSolutions[$key] = $val; 582 } 583 584 $tableGUI->initColumns()->initFilter(); 585 586 $tableGUI->setFilterCommand($targetCMD . 'SetTableFilter'); 587 $tableGUI->setResetCommand($targetCMD . 'ResetTableFilter'); 588 589 $tableGUI->setData($usersQuestionSolutions); 590 591 return $tableGUI; 592 } 593 594 /** 595 * Returns HTML code for a signature field 596 * 597 * @return string HTML code of the date and signature field for the test results 598 * @access public 599 */ 600 public function getResultsSignature() 601 { 602 if ($this->object->getShowSolutionSignature() && !$this->object->getAnonymity()) { 603 $template = new ilTemplate("tpl.il_as_tst_results_userdata_signature.html", true, true, "Modules/Test"); 604 $template->setVariable("TXT_DATE", $this->lng->txt("date")); 605 $old_value = ilDatePresentation::useRelativeDates(); 606 ilDatePresentation::setUseRelativeDates(false); 607 $template->setVariable("VALUE_DATE", ilDatePresentation::formatDate(new ilDate(time(), IL_CAL_UNIX))); 608 ilDatePresentation::setUseRelativeDates($old_value); 609 $template->setVariable("TXT_SIGNATURE", $this->lng->txt("tst_signature")); 610 $template->setVariable("IMG_SPACER", ilUtil::getImagePath("spacer.png")); 611 return $template->get(); 612 } else { 613 return ""; 614 } 615 } 616 617 /** 618 * Returns the user data for a test results output 619 * 620 * @param ilTestSession|ilTestSessionDynamicQuestionSet 621 * @param integer $user_id The user ID of the user 622 * @param boolean $overwrite_anonymity TRUE if the anonymity status should be overwritten, FALSE otherwise 623 * @return string HTML code of the user data for the test results 624 * @access public 625 */ 626 public function getAdditionalUsrDataHtmlAndPopulateWindowTitle($testSession, $active_id, $overwrite_anonymity = false) 627 { 628 if (!is_object($testSession)) { 629 throw new TestException(); 630 } 631 $template = new ilTemplate("tpl.il_as_tst_results_userdata.html", true, true, "Modules/Test"); 632 include_once './Services/User/classes/class.ilObjUser.php'; 633 $user_id = $this->object->_getUserIdFromActiveId($active_id); 634 if (strlen(ilObjUser::_lookupLogin($user_id)) > 0) { 635 $user = new ilObjUser($user_id); 636 } else { 637 $user = new ilObjUser(); 638 $user->setLastname($this->lng->txt("deleted_user")); 639 } 640 $t = $testSession->getSubmittedTimestamp(); 641 if (!$t) { 642 $t = $this->object->_getLastAccess($testSession->getActiveId()); 643 } 644 645 if ($this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired()) { 646 $uname = $this->object->userLookupFullName($user_id, $overwrite_anonymity); 647 $template->setCurrentBlock("name"); 648 $template->setVariable('TXT_USR_NAME', $this->lng->txt("name")); 649 $template->setVariable('VALUE_USR_NAME', $uname); 650 $template->parseCurrentBlock(); 651 } 652 653 $title_matric = ""; 654 if (strlen($user->getMatriculation()) && (($this->object->getAnonymity() == false) || ($overwrite_anonymity))) { 655 $template->setCurrentBlock("matriculation"); 656 $template->setVariable("TXT_USR_MATRIC", $this->lng->txt("matriculation")); 657 $template->setVariable("VALUE_USR_MATRIC", $user->getMatriculation()); 658 $template->parseCurrentBlock(); 659 $title_matric = " - " . $this->lng->txt("matriculation") . ": " . $user->getMatriculation(); 660 } 661 662 $invited_user = array_pop($this->object->getInvitedUsers($user_id)); 663 if (strlen($invited_user["clientip"])) { 664 $template->setCurrentBlock("client_ip"); 665 $template->setVariable("TXT_CLIENT_IP", $this->lng->txt("client_ip")); 666 $template->setVariable("VALUE_CLIENT_IP", $invited_user["clientip"]); 667 $template->parseCurrentBlock(); 668 $title_client = " - " . $this->lng->txt("clientip") . ": " . $invited_user["clientip"]; 669 } 670 671 $template->setVariable("TXT_TEST_TITLE", $this->lng->txt("title")); 672 $template->setVariable("VALUE_TEST_TITLE", $this->object->getTitle()); 673 674 // change the pagetitle (tab title or title in title bar of window) 675 $pagetitle = $this->object->getTitle() . $title_matric . $title_client; 676 $this->tpl->setHeaderPageTitle($pagetitle); 677 678 return $template->get(); 679 } 680 681 /** 682 * Returns an output of the solution to an answer compared to the correct solution 683 * 684 * @param integer $question_id Database ID of the question 685 * @param integer $active_id Active ID of the active user 686 * @param integer $pass Test pass 687 * @return string HTML code of the correct solution comparison 688 * @access public 689 */ 690 public function getCorrectSolutionOutput($question_id, $active_id, $pass, ilTestQuestionRelatedObjectivesList $objectivesList = null) 691 { 692 global $DIC; 693 $ilUser = $DIC['ilUser']; 694 695 $test_id = $this->object->getTestId(); 696 $question_gui = $this->object->createQuestionGUI("", $question_id); 697 698 if ($this->isPdfDeliveryRequest()) { 699 $question_gui->setRenderPurpose(assQuestionGUI::RENDER_PURPOSE_PRINT_PDF); 700 } 701 702 $template = new ilTemplate("tpl.il_as_tst_correct_solution_output.html", true, true, "Modules/Test"); 703 $show_question_only = ($this->object->getShowSolutionAnswersOnly()) ? true : false; 704 $result_output = $question_gui->getSolutionOutput($active_id, $pass, true, false, $show_question_only, $this->object->getShowSolutionFeedback(), false, false, true); 705 $best_output = $question_gui->getSolutionOutput($active_id, $pass, false, false, $show_question_only, false, true, false, false); 706 if ($this->object->getShowSolutionFeedback() && $_GET['cmd'] != 'outCorrectSolution') { 707 $specificAnswerFeedback = $question_gui->getSpecificFeedbackOutput( 708 $question_gui->object->fetchIndexedValuesFromValuePairs( 709 $question_gui->object->getSolutionValues($active_id, $pass) 710 ) 711 ); 712 if (strlen($specificAnswerFeedback)) { 713 $template->setCurrentBlock("outline_specific_feedback"); 714 $template->setVariable("OUTLINE_SPECIFIC_FEEDBACK", $specificAnswerFeedback); 715 $template->parseCurrentBlock(); 716 } 717 } 718 if ($this->object->isBestSolutionPrintedWithResult() && strlen($best_output)) { 719 $template->setCurrentBlock("best_solution"); 720 $template->setVariable("TEXT_BEST_SOLUTION", $this->lng->txt("tst_best_solution_is")); 721 $template->setVariable("BEST_OUTPUT", $best_output); 722 $template->parseCurrentBlock(); 723 } 724 $template->setVariable("TEXT_YOUR_SOLUTION", $this->lng->txt("tst_your_answer_was")); 725 $template->setVariable("TEXT_SOLUTION_OUTPUT", $this->lng->txt("tst_your_answer_was")); // Mantis 28646. I don't really know why Ingmar renamed the placeholder, so 726 // I set both old and new since the old one is set as well in several places. 727 $maxpoints = $question_gui->object->getMaximumPoints(); 728 if ($maxpoints == 1) { 729 $template->setVariable("QUESTION_TITLE", $this->object->getQuestionTitle($question_gui->object->getTitle()) . " (" . $maxpoints . " " . $this->lng->txt("point") . ")"); 730 } else { 731 $template->setVariable("QUESTION_TITLE", $this->object->getQuestionTitle($question_gui->object->getTitle()) . " (" . $maxpoints . " " . $this->lng->txt("points") . ")"); 732 } 733 if ($objectivesList !== null) { 734 $objectives = $this->lng->txt('tst_res_lo_objectives_header') . ': '; 735 $objectives .= $objectivesList->getQuestionRelatedObjectiveTitles($question_gui->object->getId()); 736 $template->setVariable('OBJECTIVES', $objectives); 737 } 738 $template->setVariable("SOLUTION_OUTPUT", $result_output); 739 $template->setVariable("RECEIVED_POINTS", sprintf($this->lng->txt("you_received_a_of_b_points"), $question_gui->object->getReachedPoints($active_id, $pass), $maxpoints)); 740 $template->setVariable("FORMACTION", $this->ctrl->getFormAction($this)); 741 $template->setVariable("BACKLINK_TEXT", "<< " . $this->lng->txt("back")); 742 return $template->get(); 743 } 744 745 /** 746 * Output of the pass overview for a test called by a test participant 747 * 748 * @param ilTestSession|ilTestSessionDynamicQuestionSet $testSession 749 * @param integer $active_id 750 * @param integer $pass 751 * @param boolean $show_pass_details 752 * @param boolean $show_answers 753 * @param boolean $show_question_only 754 * @param boolean $show_reached_points 755 * @access public 756 */ 757 public function getResultsOfUserOutput($testSession, $active_id, $pass, $targetGUI, $show_pass_details = true, $show_answers = true, $show_question_only = false, $show_reached_points = false) 758 { 759 global $DIC; 760 $ilObjDataCache = $DIC['ilObjDataCache']; 761 762 include_once("./Services/UICore/classes/class.ilTemplate.php"); 763 $template = new ilTemplate("tpl.il_as_tst_results_participant.html", true, true, "Modules/Test"); 764 765 if ($this->participantData instanceof ilTestParticipantData) { 766 $user_id = $this->participantData->getUserIdByActiveId($active_id); 767 $uname = $this->participantData->getConcatedFullnameByActiveId($active_id, false); 768 } else { 769 $user_id = $this->object->_getUserIdFromActiveId($active_id); 770 $uname = $this->object->userLookupFullName($user_id, true); 771 } 772 773 if (((array_key_exists("pass", $_GET)) && (strlen($_GET["pass"]) > 0)) || (!is_null($pass))) { 774 if (is_null($pass)) { 775 $pass = $_GET["pass"]; 776 } 777 } 778 779 if (!is_null($pass)) { 780 require_once 'Modules/Test/classes/class.ilTestResultHeaderLabelBuilder.php'; 781 $testResultHeaderLabelBuilder = new ilTestResultHeaderLabelBuilder($this->lng, $ilObjDataCache); 782 783 $objectivesList = null; 784 785 if ($this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired()) { 786 $testSequence = $this->testSequenceFactory->getSequenceByActiveIdAndPass($active_id, $pass); 787 $testSequence->loadFromDb(); 788 $testSequence->loadQuestions(); 789 790 require_once 'Modules/Course/classes/Objectives/class.ilLOTestQuestionAdapter.php'; 791 $objectivesAdapter = ilLOTestQuestionAdapter::getInstance($testSession); 792 793 $objectivesList = $this->buildQuestionRelatedObjectivesList($objectivesAdapter, $testSequence); 794 $objectivesList->loadObjectivesTitles(); 795 796 $testResultHeaderLabelBuilder->setObjectiveOrientedContainerId($testSession->getObjectiveOrientedContainerId()); 797 $testResultHeaderLabelBuilder->setUserId($testSession->getUserId()); 798 $testResultHeaderLabelBuilder->setTestObjId($this->object->getId()); 799 $testResultHeaderLabelBuilder->setTestRefId($this->object->getRefId()); 800 $testResultHeaderLabelBuilder->initObjectiveOrientedMode(); 801 } 802 803 $result_array = $this->object->getTestResult( 804 $active_id, 805 $pass, 806 false, 807 !$this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired() 808 ); 809 810 $user_id = $this->object->_getUserIdFromActiveId($active_id); 811 $showAllAnswers = true; 812 if ($this->object->isExecutable($testSession, $user_id)) { 813 $showAllAnswers = false; 814 } 815 if ($show_answers) { 816 $list_of_answers = $this->getPassListOfAnswers( 817 $result_array, 818 $active_id, 819 $pass, 820 $_SESSION['tst_results_show_best_solutions'], 821 $showAllAnswers, 822 $show_question_only, 823 $show_reached_points, 824 $show_pass_details, 825 $objectivesList, 826 $testResultHeaderLabelBuilder 827 ); 828 $template->setVariable("LIST_OF_ANSWERS", $list_of_answers); 829 } 830 831 if ($show_pass_details) { 832 $overviewTableGUI = $this->getPassDetailsOverviewTableGUI($result_array, $active_id, $pass, $targetGUI, "getResultsOfUserOutput", '', $show_answers, $objectivesList); 833 $overviewTableGUI->setTitle($testResultHeaderLabelBuilder->getPassDetailsHeaderLabel($pass + 1)); 834 $template->setVariable("PASS_DETAILS", $overviewTableGUI->getHTML()); 835 } 836 837 $signature = $this->getResultsSignature(); 838 $template->setVariable("SIGNATURE", $signature); 839 840 if ($this->object->isShowExamIdInTestResultsEnabled()) { 841 $template->setCurrentBlock('exam_id_footer'); 842 $template->setVariable('EXAM_ID_VAL', ilObjTest::lookupExamId( 843 $testSession->getActiveId(), 844 $pass 845 )); 846 $template->setVariable('EXAM_ID_TXT', $this->lng->txt('exam_id')); 847 $template->parseCurrentBlock(); 848 } 849 } 850 851 $template->setCurrentBlock('participant_back_anchor'); 852 $template->setVariable("HREF_PARTICIPANT_BACK_ANCHOR", "#tst_results_toolbar"); 853 $template->setVariable("TXT_PARTICIPANT_BACK_ANCHOR", $this->lng->txt('tst_back_to_top')); 854 $template->parseCurrentBlock(); 855 856 $template->setCurrentBlock('participant_block_id'); 857 $template->setVariable("PARTICIPANT_BLOCK_ID", "participant_active_{$active_id}"); 858 $template->parseCurrentBlock(); 859 860 if ($this->isGradingMessageRequired()) { 861 $gradingMessageBuilder = $this->getGradingMessageBuilder($active_id); 862 $gradingMessageBuilder->buildList(); 863 864 $template->setCurrentBlock('grading_message'); 865 $template->setVariable('GRADING_MESSAGE', $gradingMessageBuilder->getList()); 866 $template->parseCurrentBlock(); 867 } 868 869 870 $user_data = $this->getAdditionalUsrDataHtmlAndPopulateWindowTitle($testSession, $active_id, true); 871 $template->setVariable("TEXT_HEADING", sprintf($this->lng->txt("tst_result_user_name"), $uname)); 872 $template->setVariable("USER_DATA", $user_data); 873 874 $this->populateExamId($template, (int) $active_id, (int) $pass); 875 $this->populatePassFinishDate($template, ilObjTest::lookupLastTestPassAccess($active_id, $pass)); 876 877 return $template->get(); 878 } 879 880 /** 881 * Returns the user and pass data for a test results output 882 * 883 * @param integer $active_id The active ID of the user 884 * @return string HTML code of the user data for the test results 885 * @access public 886 */ 887 public function getResultsHeadUserAndPass($active_id, $pass) 888 { 889 $template = new ilTemplate("tpl.il_as_tst_results_head_user_pass.html", true, true, "Modules/Test"); 890 include_once './Services/User/classes/class.ilObjUser.php'; 891 $user_id = $this->object->_getUserIdFromActiveId($active_id); 892 if (strlen(ilObjUser::_lookupLogin($user_id)) > 0) { 893 $user = new ilObjUser($user_id); 894 } else { 895 $user = new ilObjUser(); 896 $user->setLastname($this->lng->txt("deleted_user")); 897 } 898 $title_matric = ""; 899 if (strlen($user->getMatriculation()) && (($this->object->getAnonymity() == false))) { 900 $template->setCurrentBlock("user_matric"); 901 $template->setVariable("TXT_USR_MATRIC", $this->lng->txt("matriculation")); 902 $template->parseCurrentBlock(); 903 $template->setCurrentBlock("user_matric_value"); 904 $template->setVariable("VALUE_USR_MATRIC", $user->getMatriculation()); 905 $template->parseCurrentBlock(); 906 $template->touchBlock("user_matric_separator"); 907 $title_matric = " - " . $this->lng->txt("matriculation") . ": " . $user->getMatriculation(); 908 } 909 910 $invited_user = array_pop($this->object->getInvitedUsers($user_id)); 911 if (strlen($invited_user["clientip"])) { 912 $template->setCurrentBlock("user_clientip"); 913 $template->setVariable("TXT_CLIENT_IP", $this->lng->txt("client_ip")); 914 $template->parseCurrentBlock(); 915 $template->setCurrentBlock("user_clientip_value"); 916 $template->setVariable("VALUE_CLIENT_IP", $invited_user["clientip"]); 917 $template->parseCurrentBlock(); 918 $template->touchBlock("user_clientip_separator"); 919 $title_client = " - " . $this->lng->txt("clientip") . ": " . $invited_user["clientip"]; 920 } 921 922 $template->setVariable("TXT_USR_NAME", $this->lng->txt("name")); 923 $uname = $this->object->userLookupFullName($user_id, false); 924 $template->setVariable("VALUE_USR_NAME", $uname); 925 $template->setVariable("TXT_PASS", $this->lng->txt("scored_pass")); 926 $template->setVariable("VALUE_PASS", $pass); 927 return $template->get(); 928 } 929 930 /** 931 * Creates a HTML representation for the results of a given question in a test 932 * 933 * @param integer $question_id The original id of the question 934 * @param integer $test_id The test id 935 * @return string HTML code of the question results 936 */ 937 public function getQuestionResultForTestUsers($question_id, $test_id) 938 { 939 // prepare generation before contents are processed (for mathjax) 940 ilPDFGeneratorUtils::prepareGenerationRequest("Test", PDF_USER_RESULT); 941 942 // REQUIRED, since we call this object regardless of the loop 943 $question_gui = $this->object->createQuestionGUI("", $question_id); 944 945 $this->object->setAccessFilteredParticipantList( 946 $this->object->buildStatisticsAccessFilteredParticipantList() 947 ); 948 949 $foundusers = $this->object->getParticipantsForTestAndQuestion($test_id, $question_id); 950 $output = ''; 951 foreach ($foundusers as $active_id => $passes) { 952 $resultpass = $this->object->_getResultPass($active_id); 953 for ($i = 0; $i < count($passes); $i++) { 954 if (($resultpass !== null) && ($resultpass == $passes[$i]["pass"])) { 955 if ($output) { 956 $output .= "<br /><br /><br />"; 957 } 958 959 // check if re-instantiation is really neccessary 960 $question_gui = $this->object->createQuestionGUI("", $passes[$i]["qid"]); 961 $output .= $this->getResultsHeadUserAndPass($active_id, $resultpass + 1); 962 $question_gui->setRenderPurpose(assQuestionGUI::RENDER_PURPOSE_PRINT_PDF); 963 $output .= $question_gui->getSolutionOutput( 964 $active_id, 965 $resultpass, 966 $graphicalOutput = false, 967 $result_output = false, 968 $show_question_only = false, 969 $show_feedback = false 970 ); 971 } 972 } 973 } 974 975 require_once './Modules/Test/classes/class.ilTestPDFGenerator.php'; 976 ilTestPDFGenerator::generatePDF($output, ilTestPDFGenerator::PDF_OUTPUT_DOWNLOAD, $question_gui->object->getTitleFilenameCompliant(), PDF_USER_RESULT); 977 } 978 979 /** 980 * @return ilTestPassDetailsOverviewTableGUI 981 */ 982 protected function buildPassDetailsOverviewTableGUI($targetGUI, $targetCMD) 983 { 984 if (!isset($targetGUI->object) && method_exists($targetGUI, 'getTestObj')) { 985 $targetGUI->object = $targetGUI->getTestObj(); 986 } 987 988 require_once 'Modules/Test/classes/tables/class.ilTestPassDetailsOverviewTableGUI.php'; 989 $tableGUI = new ilTestPassDetailsOverviewTableGUI($this->ctrl, $targetGUI, $targetCMD); 990 $tableGUI->setIsPdfGenerationRequest($this->isPdfDeliveryRequest()); 991 return $tableGUI; 992 } 993 994 protected function isGradingMessageRequired() 995 { 996 if ($this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired()) { 997 return false; 998 } 999 1000 if ($this->object->isShowGradingStatusEnabled()) { 1001 return true; 1002 } 1003 1004 if ($this->object->isShowGradingMarkEnabled()) { 1005 return true; 1006 } 1007 1008 if ($this->object->areObligationsEnabled()) { 1009 return true; 1010 } 1011 1012 return false; 1013 } 1014 1015 /** 1016 * @param integer $activeId 1017 * @return ilTestGradingMessageBuilder 1018 */ 1019 protected function getGradingMessageBuilder($activeId) 1020 { 1021 require_once 'Modules/Test/classes/class.ilTestGradingMessageBuilder.php'; 1022 $gradingMessageBuilder = new ilTestGradingMessageBuilder($this->lng, $this->object); 1023 1024 $gradingMessageBuilder->setActiveId($activeId); 1025 1026 return $gradingMessageBuilder; 1027 } 1028 1029 protected function buildQuestionRelatedObjectivesList(ilLOTestQuestionAdapter $objectivesAdapter, ilTestQuestionSequence $testSequence) 1030 { 1031 require_once 'Modules/Test/classes/class.ilTestQuestionRelatedObjectivesList.php'; 1032 $questionRelatedObjectivesList = new ilTestQuestionRelatedObjectivesList(); 1033 1034 $objectivesAdapter->buildQuestionRelatedObjectiveList($testSequence, $questionRelatedObjectivesList); 1035 1036 return $questionRelatedObjectivesList; 1037 } 1038 1039 protected function getFilteredTestResult($active_id, $pass, $considerHiddenQuestions, $considerOptionalQuestions) 1040 { 1041 global $DIC; 1042 $ilDB = $DIC['ilDB']; 1043 $ilPluginAdmin = $DIC['ilPluginAdmin']; 1044 1045 $table_gui = $this->buildPassDetailsOverviewTableGUI($this, 'outUserPassDetails'); 1046 $table_gui->initFilter(); 1047 1048 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionList.php'; 1049 $questionList = new ilAssQuestionList($ilDB, $this->lng, $ilPluginAdmin); 1050 1051 $questionList->setParentObjIdsFilter(array($this->object->getId())); 1052 $questionList->setQuestionInstanceTypeFilter(ilAssQuestionList::QUESTION_INSTANCE_TYPE_DUPLICATES); 1053 1054 foreach ($table_gui->getFilterItems() as $item) { 1055 if (substr($item->getPostVar(), 0, strlen('tax_')) == 'tax_') { 1056 $v = $item->getValue(); 1057 1058 if (is_array($v) && count($v) && !(int) $v[0]) { 1059 continue; 1060 } 1061 1062 $taxId = substr($item->getPostVar(), strlen('tax_')); 1063 $questionList->addTaxonomyFilter($taxId, $item->getValue(), $this->object->getId(), 'tst'); 1064 } elseif ($item->getValue() !== false) { 1065 $questionList->addFieldFilter($item->getPostVar(), $item->getValue()); 1066 } 1067 } 1068 1069 $questionList->load(); 1070 1071 $filteredTestResult = array(); 1072 1073 $resultData = $this->object->getTestResult($active_id, $pass, false, $considerHiddenQuestions, $considerOptionalQuestions); 1074 1075 foreach ($resultData as $resultItemKey => $resultItemValue) { 1076 if ($resultItemKey === 'test' || $resultItemKey === 'pass') { 1077 continue; 1078 } 1079 1080 if (!$questionList->isInList($resultItemValue['qid'])) { 1081 continue; 1082 } 1083 1084 $filteredTestResult[] = $resultItemValue; 1085 } 1086 1087 return $filteredTestResult; 1088 } 1089 1090 /** 1091 * @param string $content 1092 */ 1093 protected function populateContent($content) 1094 { 1095 if ($this->isPdfDeliveryRequest()) { 1096 ilTestPDFGenerator::generatePDF( 1097 $content, 1098 ilTestPDFGenerator::PDF_OUTPUT_DOWNLOAD, 1099 $this->object->getTitleFilenameCompliant(), 1100 PDF_USER_RESULT 1101 ); 1102 } else { 1103 $this->tpl->setContent($content); 1104 } 1105 } 1106 1107 /** 1108 * @return ilTestResultsToolbarGUI 1109 */ 1110 protected function buildUserTestResultsToolbarGUI() 1111 { 1112 require_once 'Modules/Test/classes/toolbars/class.ilTestResultsToolbarGUI.php'; 1113 $toolbar = new ilTestResultsToolbarGUI($this->ctrl, $this->tpl, $this->lng); 1114 1115 return $toolbar; 1116 } 1117 1118 protected function outCorrectSolutionCmd() 1119 { 1120 $this->outCorrectSolution(); // cannot be named xxxCmd, because it's also called from context without Cmd in names 1121 } 1122 1123 /** 1124 * Creates an output of the solution of an answer compared to the correct solution 1125 * 1126 * @access public 1127 */ 1128 protected function outCorrectSolution() 1129 { 1130 if (!$this->object->getShowSolutionDetails()) { 1131 ilUtil::sendInfo($this->lng->txt("no_permission"), true); 1132 $this->ctrl->redirectByClass("ilobjtestgui", "infoScreen"); 1133 } 1134 1135 $testSession = $this->testSessionFactory->getSession(); 1136 $activeId = $testSession->getActiveId(); 1137 1138 if (!($activeId > 0)) { 1139 $this->ctrl->redirectByClass("ilobjtestgui", "infoScreen"); 1140 } 1141 1142 $this->ctrl->saveParameter($this, "pass"); 1143 $pass = (int) $_GET['pass']; 1144 1145 $questionId = (int) $_GET['evaluation']; 1146 1147 $testSequence = $this->testSequenceFactory->getSequenceByActiveIdAndPass($activeId, $pass); 1148 $testSequence->loadFromDb(); 1149 $testSequence->loadQuestions(); 1150 1151 if (!$testSequence->questionExists($questionId)) { 1152 ilObjTestGUI::accessViolationRedirect(); 1153 } 1154 1155 if ($this->getObjectiveOrientedContainer()->isObjectiveOrientedPresentationRequired()) { 1156 $testSequence = $this->testSequenceFactory->getSequenceByActiveIdAndPass($activeId, $pass); 1157 $testSequence->loadFromDb(); 1158 $testSequence->loadQuestions(); 1159 1160 require_once 'Modules/Course/classes/Objectives/class.ilLOTestQuestionAdapter.php'; 1161 $objectivesAdapter = ilLOTestQuestionAdapter::getInstance($testSession); 1162 $objectivesList = $this->buildQuestionRelatedObjectivesList($objectivesAdapter, $testSequence); 1163 $objectivesList->loadObjectivesTitles(); 1164 } else { 1165 $objectivesList = null; 1166 } 1167 1168 global $DIC; 1169 $ilTabs = $DIC['ilTabs']; 1170 1171 if ($this instanceof ilTestEvalObjectiveOrientedGUI) { 1172 $ilTabs->setBackTarget( 1173 $this->lng->txt("tst_back_to_virtual_pass"), 1174 $this->ctrl->getLinkTarget($this, 'showVirtualPass') 1175 ); 1176 } else { 1177 $ilTabs->setBackTarget( 1178 $this->lng->txt("tst_back_to_pass_details"), 1179 $this->ctrl->getLinkTarget($this, 'outUserPassDetails') 1180 ); 1181 } 1182 $ilTabs->clearSubTabs(); 1183 1184 include_once("./Services/Style/Content/classes/class.ilObjStyleSheet.php"); 1185 $this->tpl->setCurrentBlock("ContentStyle"); 1186 $this->tpl->setVariable("LOCATION_CONTENT_STYLESHEET", ilObjStyleSheet::getContentStylePath(0)); 1187 $this->tpl->parseCurrentBlock(); 1188 1189 $this->tpl->setCurrentBlock("SyntaxStyle"); 1190 $this->tpl->setVariable("LOCATION_SYNTAX_STYLESHEET", ilObjStyleSheet::getSyntaxStylePath()); 1191 $this->tpl->parseCurrentBlock(); 1192 1193 $this->tpl->addCss(ilUtil::getStyleSheetLocation("output", "test_print.css", "Modules/Test"), "print"); 1194 if ($this->object->getShowSolutionAnswersOnly()) { 1195 $this->tpl->addCss(ilUtil::getStyleSheetLocation("output", "test_print_hide_content.css", "Modules/Test"), "print"); 1196 } 1197 1198 $solution = $this->getCorrectSolutionOutput($questionId, $activeId, $pass, $objectivesList); 1199 1200 $this->tpl->setContent($solution); 1201 } 1202 1203 /** 1204 * @param ilTemplate $tpl 1205 * @param int $passFinishDate 1206 */ 1207 public function populatePassFinishDate($tpl, $passFinishDate) 1208 { 1209 $oldValue = ilDatePresentation::useRelativeDates(); 1210 ilDatePresentation::setUseRelativeDates(false); 1211 $passFinishDate = ilDatePresentation::formatDate(new ilDateTime($passFinishDate, IL_CAL_UNIX)); 1212 ilDatePresentation::setUseRelativeDates($oldValue); 1213 $tpl->setVariable("PASS_FINISH_DATE_LABEL", $this->lng->txt('tst_pass_finished_on')); 1214 $tpl->setVariable("PASS_FINISH_DATE_VALUE", $passFinishDate); 1215 } 1216 1217 /** 1218 * @param ilTemplate $tpl 1219 * @param int $activeId 1220 * @param int $pass 1221 */ 1222 public function populateExamId(ilTemplate $tpl, int $activeId, int $pass) 1223 { 1224 if ($this->object->isShowExamIdInTestResultsEnabled()) { 1225 $tpl->setVariable("EXAM_ID_TXT", $this->lng->txt('exam_id')); 1226 $tpl->setVariable('EXAM_ID', ilObjTest::lookupExamId( 1227 $activeId, 1228 $pass 1229 )); 1230 } 1231 } 1232} 1233 1234// internal sort function to sort the result array 1235function sortResults($a, $b) 1236{ 1237 $sort = ($_GET["sort"]) ? ($_GET["sort"]) : "nr"; 1238 $sortorder = ($_GET["sortorder"]) ? ($_GET["sortorder"]) : "asc"; 1239 if (strcmp($sortorder, "asc")) { 1240 $smaller = 1; 1241 $greater = -1; 1242 } else { 1243 $smaller = -1; 1244 $greater = 1; 1245 } 1246 if ($a[$sort] == $b[$sort]) { 1247 return 0; 1248 } 1249 return ($a[$sort] < $b[$sort]) ? $smaller : $greater; 1250} 1251