1<?php 2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */ 3 4require_once './Modules/Test/classes/inc.AssessmentConstants.php'; 5require_once 'Modules/TestQuestionPool/classes/class.assQuestion.php'; 6/** 7 * Export class for tests 8 * 9 * @author Helmut Schottmüller <helmut.schottmueller@mac.com> 10 * @author Maximilian Becker <mbecker@databay.de> 11 * @author Björn Heyser <bheyser@databay.de> 12 * 13 * @version $Id$ 14 * 15 * @ingroup ModulesTest 16 */ 17abstract class ilTestExport 18{ 19 /** @var ilErrorHandling $err */ 20 public $err; // error object 21 22 /** @var ilDBInterface $db */ 23 public $db; // database object 24 25 /** @var ILIAS $ilias */ 26 public $ilias; // ilias object 27 28 /** @var ilObjTest $test_obj */ 29 public $test_obj; // test object 30 31 public $inst_id; // installation id 32 public $mode; 33 34 /** @var ilLanguage $lng */ 35 private $lng; 36 37 private $resultsfile; 38 39 protected $resultExportingEnabledForTestExport = false; 40 41 /** 42 * @var ilTestParticipantList 43 */ 44 protected $forcedAccessFilteredParticipantList = null; 45 46 /** 47 * Constructor 48 */ 49 public function __construct(&$a_test_obj, $a_mode = "xml") 50 { 51 global $DIC; 52 $ilErr = $DIC['ilErr']; 53 $ilDB = $DIC['ilDB']; 54 $ilias = $DIC['ilias']; 55 $lng = $DIC['lng']; 56 57 $this->test_obj = &$a_test_obj; 58 59 $this->err = &$ilErr; 60 $this->ilias = &$ilias; 61 $this->db = &$ilDB; 62 $this->mode = $a_mode; 63 $this->lng = &$lng; 64 65 $this->inst_id = IL_INST_ID; 66 67 $date = time(); 68 $this->export_dir = $this->test_obj->getExportDirectory(); 69 switch ($this->mode) { 70 case "results": 71 $this->subdir = $date . "__" . $this->inst_id . "__" . 72 "tst__results_" . $this->test_obj->getId(); 73 break; 74 case "aggregated": 75 $this->subdir = $date . "__" . $this->inst_id . "__" . 76 "test__aggregated__results_" . $this->test_obj->getId(); 77 break; 78 default: 79 $this->subdir = $date . "__" . $this->inst_id . "__" . 80 "tst" . "_" . $this->test_obj->getId(); 81 $this->filename = $this->subdir . ".xml"; 82 $this->resultsfile = $date . "__" . $this->inst_id . "__" . 83 "results" . "_" . $this->test_obj->getId() . ".xml"; 84 $this->qti_filename = $date . "__" . $this->inst_id . "__" . 85 "qti" . "_" . $this->test_obj->getId() . ".xml"; 86 break; 87 } 88 $this->filename = $this->subdir . "." . $this->getExtension(); 89 } 90 91 /** 92 * @return boolean 93 */ 94 public function isResultExportingEnabledForTestExport() 95 { 96 return $this->resultExportingEnabledForTestExport; 97 } 98 99 /** 100 * @param boolean $resultExprtingEnabledForTestExport 101 */ 102 public function setResultExportingEnabledForTestExport($resultExprtingEnabledForTestExport) 103 { 104 $this->resultExportingEnabledForTestExport = $resultExprtingEnabledForTestExport; 105 } 106 107 /** 108 * @return ilTestParticipantList 109 */ 110 public function getForcedAccessFilteredParticipantList() 111 { 112 return $this->forcedAccessFilteredParticipantList; 113 } 114 115 /** 116 * @param ilTestParticipantList $forcedAccessFilteredParticipantList 117 */ 118 public function setForcedAccessFilteredParticipantList(ilTestParticipantList $forcedAccessFilteredParticipantList) 119 { 120 $this->forcedAccessFilteredParticipantList = $forcedAccessFilteredParticipantList; 121 } 122 123 /** 124 * @return ilTestParticipantList 125 */ 126 public function getAccessFilteredParticipantList() 127 { 128 if ($this->getForcedAccessFilteredParticipantList() instanceof ilTestParticipantList) { 129 return $this->getForcedAccessFilteredParticipantList(); 130 } 131 132 return $this->test_obj->buildStatisticsAccessFilteredParticipantList(); 133 } 134 135 public function getExtension() 136 { 137 switch ($this->mode) { 138 case "results": 139 return "csv"; break; 140 default: 141 return "xml"; break; 142 } 143 } 144 145 public function getInstId() 146 { 147 return $this->inst_id; 148 } 149 150 151 /** 152 * build export file (complete zip file) 153 * 154 * @access public 155 * @return 156 */ 157 public function buildExportFile() 158 { 159 switch ($this->mode) { 160 case "results": 161 return $this->buildExportResultFile(); 162 break; 163 default: 164 return $this->buildExportFileXML(); 165 break; 166 } 167 } 168 169 /** 170 * build xml export file 171 */ 172 public function buildExportResultFile() 173 { 174 global $DIC; 175 $ilBench = $DIC['ilBench']; 176 $log = $DIC['log']; 177 178 //get Log File 179 $expDir = $this->test_obj->getExportDirectory(); 180 181 // make_directories 182 $this->test_obj->createExportDirectory(); 183 include_once "./Services/Utilities/classes/class.ilUtil.php"; 184 ilUtil::makeDir($this->export_dir); 185 186 include_once './Services/Logging/classes/class.ilLog.php'; 187 $expLog = new ilLog($expDir, "export.log"); 188 $expLog->delete(); 189 $expLog->setLogFormat(""); 190 $expLog->write(date("[y-m-d H:i:s] ") . "Start Export Of Results"); 191 192 $data = $this->exportToCSV($deliver = false); 193 $file = fopen($this->export_dir . "/" . $this->filename, "w"); 194 fwrite($file, $data); 195 fclose($file); 196 197 $excelfile = $this->exportToExcel($deliver = false); 198 @copy($excelfile, $this->export_dir . "/" . str_replace($this->getExtension(), "xlsx", $this->filename)); 199 @unlink($excelfile); 200 // end 201 $expLog->write(date("[y-m-d H:i:s] ") . "Finished Export of Results"); 202 203 return $this->export_dir . "/" . $this->filename; 204 } 205 206 /** 207 * Exports the aggregated results to the Microsoft Excel file format 208 * @param boolean $deliver TRUE to directly deliver the file, FALSE to return the binary data 209 * @return string 210 */ 211 protected function aggregatedResultsToExcel($deliver = true) 212 { 213 $data = $this->test_obj->getAggregatedResultsData(); 214 215 require_once 'Modules/TestQuestionPool/classes/class.ilAssExcelFormatHelper.php'; 216 $worksheet = new ilAssExcelFormatHelper(); 217 $worksheet->addSheet($this->lng->txt('tst_results_aggregated')); 218 219 $row = 1; 220 $col = 0; 221 $worksheet->setCell($row, $col++, $this->lng->txt('result')); 222 $worksheet->setCell($row, $col++, $this->lng->txt('value')); 223 224 $worksheet->setBold('A' . $row . ':' . $worksheet->getColumnCoord($col - 1) . $row); 225 226 $row++; 227 foreach ($data['overview'] as $key => $value) { 228 $col = 0; 229 $worksheet->setCell($row, $col++, $key); 230 $worksheet->setCell($row, $col++, $value); 231 $row++; 232 } 233 234 $row++; 235 $col = 0; 236 237 $worksheet->setCell($row, $col++, $this->lng->txt('question_id')); 238 $worksheet->setCell($row, $col++, $this->lng->txt('question_title')); 239 $worksheet->setCell($row, $col++, $this->lng->txt('average_reached_points')); 240 $worksheet->setCell($row, $col++, $this->lng->txt('points')); 241 $worksheet->setCell($row, $col++, $this->lng->txt('percentage')); 242 $worksheet->setCell($row, $col++, $this->lng->txt('number_of_answers')); 243 244 $worksheet->setBold('A' . $row . ':' . $worksheet->getColumnCoord($col - 1) . $row); 245 246 $row++; 247 foreach ($data['questions'] as $key => $value) { 248 $col = 0; 249 $worksheet->setCell($row, $col++, $key); 250 $worksheet->setCell($row, $col++, $value[0]); 251 $worksheet->setCell($row, $col++, $value[4]); 252 $worksheet->setCell($row, $col++, $value[5]); 253 $worksheet->setCell($row, $col++, $value[6]); 254 $worksheet->setCell($row, $col++, $value[3]); 255 $row++; 256 } 257 258 if ($deliver) { 259 $worksheet->sendToClient( 260 ilUtil::getASCIIFilename(preg_replace("/\s/", '_', $this->test_obj->getTitle() . '_aggregated')) . '.xlsx' 261 ); 262 } else { 263 $excelfile = ilUtil::ilTempnam(); 264 $worksheet->writeToFile($excelfile); 265 return $excelfile . '.xlsx'; 266 } 267 } 268 269 /** 270 * Exports the aggregated results to CSV 271 * 272 * @param boolean $deliver TRUE to directly deliver the file, FALSE to return the data 273 */ 274 protected function aggregatedResultsToCSV($deliver = true) 275 { 276 $data = $this->test_obj->getAggregatedResultsData(); 277 $rows = array(); 278 array_push($rows, array( 279 $this->lng->txt("result"), 280 $this->lng->txt("value") 281 )); 282 foreach ($data["overview"] as $key => $value) { 283 array_push($rows, array( 284 $key, 285 $value 286 )); 287 } 288 array_push($rows, array( 289 $this->lng->txt("question_id"), 290 $this->lng->txt("question_title"), 291 $this->lng->txt("average_reached_points"), 292 $this->lng->txt("points"), 293 $this->lng->txt("percentage"), 294 $this->lng->txt("number_of_answers") 295 )); 296 foreach ($data["questions"] as $key => $value) { 297 array_push($rows, array( 298 $key, 299 $value[0], 300 $value[4], 301 $value[5], 302 $value[6], 303 $value[3] 304 )); 305 } 306 $csv = ""; 307 $separator = ";"; 308 foreach ($rows as $evalrow) { 309 $csvrow = &$this->test_obj->processCSVRow($evalrow, true, $separator); 310 $csv .= join($separator, $csvrow) . "\n"; 311 } 312 if ($deliver) { 313 ilUtil::deliverData($csv, ilUtil::getASCIIFilename($this->test_obj->getTitle() . "_aggregated.csv")); 314 exit; 315 } else { 316 return $csv; 317 } 318 } 319 320 /** 321 * Exports the evaluation data to the Microsoft Excel file format 322 * 323 * @param bool $deliver 324 * @param string $filterby 325 * @param string $filtertext Filter text for the user data 326 * @param boolean $passedonly TRUE if only passed user datasets should be exported, FALSE otherwise 327 * 328 * @return string 329 */ 330 public function exportToExcel($deliver = true, $filterby = "", $filtertext = "", $passedonly = false) 331 { 332 $this->test_obj->setAccessFilteredParticipantList($this->getAccessFilteredParticipantList()); 333 334 if (strcmp($this->mode, "aggregated") == 0) { 335 return $this->aggregatedResultsToExcel($deliver); 336 } 337 338 require_once 'Modules/TestQuestionPool/classes/class.ilAssExcelFormatHelper.php'; 339 340 $worksheet = new ilAssExcelFormatHelper(); 341 $worksheet->addSheet($this->lng->txt('tst_results')); 342 343 $additionalFields = $this->test_obj->getEvaluationAdditionalFields(); 344 345 $row = 1; 346 $col = 0; 347 348 if ($this->test_obj->getAnonymity()) { 349 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('counter')); 350 } else { 351 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('name')); 352 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('login')); 353 } 354 355 if (count($additionalFields)) { 356 foreach ($additionalFields as $fieldname) { 357 if (strcmp($fieldname, "exam_id") == 0) { 358 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('exam_id_label')); 359 continue; 360 } 361 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt($fieldname)); 362 } 363 } 364 365 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('tst_stat_result_resultspoints')); 366 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('maximum_points')); 367 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('tst_stat_result_resultsmarks')); 368 369 if ($this->test_obj->getECTSOutput()) { 370 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('ects_grade')); 371 } 372 373 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('tst_stat_result_qworkedthrough')); 374 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('tst_stat_result_qmax')); 375 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('tst_stat_result_pworkedthrough')); 376 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('tst_stat_result_timeofwork')); 377 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('tst_stat_result_atimeofwork')); 378 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('tst_stat_result_firstvisit')); 379 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('tst_stat_result_lastvisit')); 380 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('tst_stat_result_mark_median')); 381 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('tst_stat_result_rank_participant')); 382 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('tst_stat_result_rank_median')); 383 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('tst_stat_result_total_participants')); 384 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('tst_stat_result_median')); 385 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('scored_pass')); 386 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('pass')); 387 388 $worksheet->setBold('A' . $row . ':' . $worksheet->getColumnCoord($col - 1) . $row); 389 390 $counter = 1; 391 $data = $this->test_obj->getCompleteEvaluationData(true, $filterby, $filtertext); 392 $firstrowwritten = false; 393 foreach ($data->getParticipants() as $active_id => $userdata) { 394 if ($passedonly && $data->getParticipant($active_id)->getPassed() == false) { 395 continue; 396 } 397 398 $row++; 399 $col = 0; 400 401 // each participant gets an own row for question column headers 402 if ($this->test_obj->isRandomTest()) { 403 $row++; 404 } 405 406 if ($this->test_obj->getAnonymity()) { 407 $worksheet->setCell($row, $col++, $counter); 408 } else { 409 $worksheet->setCell($row, $col++, $data->getParticipant($active_id)->getName()); 410 $worksheet->setCell($row, $col++, $data->getParticipant($active_id)->getLogin()); 411 } 412 413 if (count($additionalFields)) { 414 $userfields = ilObjUser::_lookupFields($userdata->getUserId()); 415 foreach ($additionalFields as $fieldname) { 416 if (strcmp($fieldname, 'gender') == 0) { 417 $worksheet->setCell($row, $col++, $this->lng->txt('gender_' . $userfields[$fieldname])); 418 } elseif (strcmp($fieldname, "exam_id") == 0) { 419 $worksheet->setCell($row, $col++, $userdata->getExamIdFromScoredPass()); 420 } else { 421 $worksheet->setCell($row, $col++, $userfields[$fieldname]); 422 } 423 } 424 } 425 426 $worksheet->setCell($row, $col++, $data->getParticipant($active_id)->getReached()); 427 $worksheet->setCell($row, $col++, $data->getParticipant($active_id)->getMaxpoints()); 428 $worksheet->setCell($row, $col++, $data->getParticipant($active_id)->getMark()); 429 430 if ($this->test_obj->getECTSOutput()) { 431 $worksheet->setCell($row, $col++, $data->getParticipant($active_id)->getECTSMark()); 432 } 433 434 $worksheet->setCell($row, $col++, $data->getParticipant($active_id)->getQuestionsWorkedThrough()); 435 $worksheet->setCell($row, $col++, $data->getParticipant($active_id)->getNumberOfQuestions()); 436 $worksheet->setCell($row, $col++, $data->getParticipant($active_id)->getQuestionsWorkedThroughInPercent() . '%'); 437 438 $time = $data->getParticipant($active_id)->getTimeOfWork(); 439 $time_seconds = $time; 440 $time_hours = floor($time_seconds / 3600); 441 $time_seconds -= $time_hours * 3600; 442 $time_minutes = floor($time_seconds / 60); 443 $time_seconds -= $time_minutes * 60; 444 $worksheet->setCell($row, $col++, sprintf("%02d:%02d:%02d", $time_hours, $time_minutes, $time_seconds)); 445 $time = $data->getParticipant($active_id)->getQuestionsWorkedThrough() ? $data->getParticipant($active_id)->getTimeOfWork() / $data->getParticipant($active_id)->getQuestionsWorkedThrough() : 0; 446 $time_seconds = $time; 447 $time_hours = floor($time_seconds / 3600); 448 $time_seconds -= $time_hours * 3600; 449 $time_minutes = floor($time_seconds / 60); 450 $time_seconds -= $time_minutes * 60; 451 $worksheet->setCell($row, $col++, sprintf("%02d:%02d:%02d", $time_hours, $time_minutes, $time_seconds)); 452 $worksheet->setCell($row, $col++, new ilDateTime($data->getParticipant($active_id)->getFirstVisit(), IL_CAL_UNIX)); 453 $worksheet->setCell($row, $col++, new ilDateTime($data->getParticipant($active_id)->getLastVisit(), IL_CAL_UNIX)); 454 455 $median = $data->getStatistics()->getStatistics()->median(); 456 $pct = $data->getParticipant($active_id)->getMaxpoints() ? $median / $data->getParticipant($active_id)->getMaxpoints() * 100.0 : 0; 457 $mark = $this->test_obj->mark_schema->getMatchingMark($pct); 458 $mark_short_name = ""; 459 460 if (is_object($mark)) { 461 $mark_short_name = $mark->getShortName(); 462 } 463 464 $worksheet->setCell($row, $col++, $mark_short_name); 465 $worksheet->setCell($row, $col++, $data->getStatistics()->getStatistics()->rank($data->getParticipant($active_id)->getReached())); 466 $worksheet->setCell($row, $col++, $data->getStatistics()->getStatistics()->rank_median()); 467 $worksheet->setCell($row, $col++, $data->getStatistics()->getStatistics()->count()); 468 $worksheet->setCell($row, $col++, $median); 469 470 if ($this->test_obj->getPassScoring() == SCORE_BEST_PASS) { 471 $worksheet->setCell($row, $col++, $data->getParticipant($active_id)->getBestPass() + 1); 472 } else { 473 $worksheet->setCell($row, $col++, $data->getParticipant($active_id)->getLastPass() + 1); 474 } 475 476 $startcol = $col; 477 478 for ($pass = 0; $pass <= $data->getParticipant($active_id)->getLastPass(); $pass++) { 479 $col = $startcol; 480 $finishdate = ilObjTest::lookupPassResultsUpdateTimestamp($active_id, $pass); 481 if ($finishdate > 0) { 482 if ($pass > 0) { 483 $row++; 484 if ($this->test_obj->isRandomTest()) { 485 $row++; 486 } 487 } 488 $worksheet->setCell($row, $col++, $pass + 1); 489 if (is_object($data->getParticipant($active_id)) && is_array($data->getParticipant($active_id)->getQuestions($pass))) { 490 $evaluatedQuestions = $data->getParticipant($active_id)->getQuestions($pass); 491 492 if ($this->test_obj->getShuffleQuestions()) { 493 // reorder questions according to general fixed sequence, 494 // so participant rows can share single questions header 495 $questions = array(); 496 foreach ($this->test_obj->getQuestions() as $qId) { 497 foreach ($evaluatedQuestions as $evaledQst) { 498 if ($evaledQst['id'] != $qId) { 499 continue; 500 } 501 502 $questions[] = $evaledQst; 503 } 504 } 505 } else { 506 $questions = $evaluatedQuestions; 507 } 508 509 foreach ($questions as $question) { 510 $question_data = $data->getParticipant($active_id)->getPass($pass)->getAnsweredQuestionByQuestionId($question["id"]); 511 $worksheet->setCell($row, $col, $question_data["reached"]); 512 if ($this->test_obj->isRandomTest()) { 513 // random test requires question headers for every participant 514 // and we allready skipped a row for that reason ( --> row - 1) 515 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col) . ($row - 1), preg_replace("/<.*?>/", "", $data->getQuestionTitle($question["id"]))); 516 } else { 517 if ($pass == 0 && !$firstrowwritten) { 518 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col) . 1, $data->getQuestionTitle($question["id"])); 519 } 520 } 521 $col++; 522 } 523 $firstrowwritten = true; 524 } 525 } 526 } 527 $counter++; 528 } 529 530 if ($this->test_obj->getExportSettingsSingleChoiceShort() && !$this->test_obj->isRandomTest() && $this->test_obj->hasSingleChoiceQuestions()) { 531 // special tab for single choice tests 532 $titles = $this->test_obj->getQuestionTitlesAndIndexes(); 533 $positions = array(); 534 $pos = 0; 535 $row = 1; 536 foreach ($titles as $id => $title) { 537 $positions[$id] = $pos; 538 $pos++; 539 } 540 541 $usernames = array(); 542 $participantcount = count($data->getParticipants()); 543 $allusersheet = false; 544 $pages = 0; 545 546 $worksheet->addSheet($this->lng->txt('eval_all_users')); 547 548 $col = 0; 549 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('name')); 550 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('login')); 551 if (count($additionalFields)) { 552 foreach ($additionalFields as $fieldname) { 553 if (strcmp($fieldname, "matriculation") == 0) { 554 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('matriculation')); 555 } 556 if (strcmp($fieldname, "exam_id") == 0) { 557 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('exam_id_label')); 558 } 559 } 560 } 561 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('test')); 562 foreach ($titles as $title) { 563 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $title); 564 } 565 $worksheet->setBold('A' . $row . ':' . $worksheet->getColumnCoord($col - 1) . $row); 566 567 $row++; 568 foreach ($data->getParticipants() as $active_id => $userdata) { 569 $username = (!is_null($userdata) && $userdata->getName()) ? $userdata->getName() : "ID $active_id"; 570 if (array_key_exists($username, $usernames)) { 571 $usernames[$username]++; 572 $username .= " ($usernames[$username])"; 573 } else { 574 $usernames[$username] = 1; 575 } 576 $col = 0; 577 $worksheet->setCell($row, $col++, $username); 578 $worksheet->setCell($row, $col++, $userdata->getLogin()); 579 if (count($additionalFields)) { 580 $userfields = ilObjUser::_lookupFields($userdata->getUserID()); 581 foreach ($additionalFields as $fieldname) { 582 if (strcmp($fieldname, "matriculation") == 0) { 583 if (strlen($userfields[$fieldname])) { 584 $worksheet->setCell($row, $col++, $userfields[$fieldname]); 585 } else { 586 $col++; 587 } 588 } 589 if (strcmp($fieldname, "exam_id") == 0) { 590 if (strlen($userfields[$fieldname])) { 591 $worksheet->setCell($row, $col++, $userdata->getExamIdFromScoredPass()); 592 } else { 593 $col++; 594 } 595 } 596 } 597 } 598 $worksheet->setCell($row, $col++, $this->test_obj->getTitle()); 599 $pass = $userdata->getScoredPass(); 600 if (is_object($userdata) && is_array($userdata->getQuestions($pass))) { 601 foreach ($userdata->getQuestions($pass) as $question) { 602 $objQuestion = assQuestion::_instantiateQuestion($question["id"]); 603 if (is_object($objQuestion) && strcmp($objQuestion->getQuestionType(), 'assSingleChoice') == 0) { 604 $solution = $objQuestion->getSolutionValues($active_id, $pass); 605 $pos = $positions[$question["id"]]; 606 $selectedanswer = "x"; 607 foreach ($objQuestion->getAnswers() as $id => $answer) { 608 if (strlen($solution[0]["value1"]) && $id == $solution[0]["value1"]) { 609 $selectedanswer = $answer->getAnswertext(); 610 } 611 } 612 $worksheet->setCell($row, $col + $pos, $selectedanswer); 613 } 614 } 615 } 616 $row++; 617 } 618 619 if ($this->test_obj->isSingleChoiceTestWithoutShuffle()) { 620 // special tab for single choice tests without shuffle option 621 $pos = 0; 622 $row = 1; 623 $usernames = array(); 624 $allusersheet = false; 625 $pages = 0; 626 627 $worksheet->addSheet($this->lng->txt('eval_all_users') . ' (2)'); 628 629 $col = 0; 630 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('name')); 631 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('login')); 632 if (count($additionalFields)) { 633 foreach ($additionalFields as $fieldname) { 634 if (strcmp($fieldname, "matriculation") == 0) { 635 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('matriculation')); 636 } 637 if (strcmp($fieldname, "exam_id") == 0) { 638 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('exam_id_label')); 639 } 640 } 641 } 642 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $this->lng->txt('test')); 643 foreach ($titles as $title) { 644 $worksheet->setFormattedExcelTitle($worksheet->getColumnCoord($col++) . $row, $title); 645 } 646 $worksheet->setBold('A' . $row . ':' . $worksheet->getColumnCoord($col - 1) . $row); 647 648 $row++; 649 foreach ($data->getParticipants() as $active_id => $userdata) { 650 $username = (!is_null($userdata) && $userdata->getName()) ? $userdata->getName() : "ID $active_id"; 651 if (array_key_exists($username, $usernames)) { 652 $usernames[$username]++; 653 $username .= " ($usernames[$username])"; 654 } else { 655 $usernames[$username] = 1; 656 } 657 $col = 0; 658 $worksheet->setCell($row, $col++, $username); 659 $worksheet->setCell($row, $col++, $userdata->getLogin()); 660 if (count($additionalFields)) { 661 $userfields = ilObjUser::_lookupFields($userdata->getUserId()); 662 foreach ($additionalFields as $fieldname) { 663 if (strcmp($fieldname, "matriculation") == 0) { 664 if (strlen($userfields[$fieldname])) { 665 $worksheet->setCell($row, $col++, $userfields[$fieldname]); 666 } else { 667 $col++; 668 } 669 } 670 if (strcmp($fieldname, "exam_id") == 0) { 671 if (strlen($userfields[$fieldname])) { 672 $worksheet->setCell($row, $col++, $userdata->getExamIdFromScoredPass()); 673 } else { 674 $col++; 675 } 676 } 677 } 678 } 679 $worksheet->setCell($row, $col++, $this->test_obj->getTitle()); 680 $pass = $userdata->getScoredPass(); 681 if (is_object($userdata) && is_array($userdata->getQuestions($pass))) { 682 foreach ($userdata->getQuestions($pass) as $question) { 683 $objQuestion = ilObjTest::_instanciateQuestion($question["aid"]); 684 if (is_object($objQuestion) && strcmp($objQuestion->getQuestionType(), 'assSingleChoice') == 0) { 685 $solution = $objQuestion->getSolutionValues($active_id, $pass); 686 $pos = $positions[$question["aid"]]; 687 $selectedanswer = chr(65 + $solution[0]["value1"]); 688 $worksheet->setCell($row, $col + $pos, $selectedanswer); 689 } 690 } 691 } 692 $row++; 693 } 694 } 695 } else { 696 // test participant result export 697 $usernames = array(); 698 $participantcount = count($data->getParticipants()); 699 $allusersheet = false; 700 $pages = 0; 701 $i = 0; 702 foreach ($data->getParticipants() as $active_id => $userdata) { 703 $i++; 704 705 $username = (!is_null($userdata) && $userdata->getName()) ? $userdata->getName() : "ID $active_id"; 706 if (array_key_exists($username, $usernames)) { 707 $usernames[$username]++; 708 $username .= " ($i)"; 709 } else { 710 $usernames[$username] = 1; 711 } 712 713 if ($participantcount > 250) { 714 if (!$allusersheet || ($pages - 1) < floor($row / 64000)) { 715 $worksheet->addSheet($this->lng->txt("eval_all_users") . (($pages > 0) ? " (" . ($pages + 1) . ")" : "")); 716 $allusersheet = true; 717 $row = 1; 718 $pages++; 719 } 720 } else { 721 $resultsheet = $worksheet->addSheet($username); 722 } 723 724 $pass = $userdata->getScoredPass(); 725 $row = ($allusersheet) ? $row : 1; 726 $worksheet->setCell($row, 0, sprintf($this->lng->txt("tst_result_user_name_pass"), $pass + 1, $userdata->getName())); 727 $worksheet->setBold($worksheet->getColumnCoord(0) . $row); 728 $row += 2; 729 if (is_object($userdata) && is_array($userdata->getQuestions($pass))) { 730 foreach ($userdata->getQuestions($pass) as $question) { 731 require_once "./Modules/TestQuestionPool/classes/class.assQuestion.php"; 732 $question = assQuestion::_instanciateQuestion($question["id"]); 733 if (is_object($question)) { 734 $row = $question->setExportDetailsXLS($worksheet, $row, $active_id, $pass); 735 } 736 } 737 } 738 } 739 } 740 741 if ($deliver) { 742 $testname = $this->test_obj->getTitle(); 743 switch ($this->mode) { 744 case 'results': 745 $testname .= '_results'; 746 break; 747 } 748 $testname = ilUtil::getASCIIFilename(preg_replace("/\s/", "_", $testname)) . '.xlsx'; 749 $worksheet->sendToClient($testname); 750 } else { 751 $excelfile = ilUtil::ilTempnam(); 752 $worksheet->writeToFile($excelfile); 753 return $excelfile . '.xlsx'; 754 } 755 } 756 757 758 759 /** 760 * Exports the evaluation data to the CSV file format 761 * 762 * Exports the evaluation data to the CSV file format 763 * 764 * @param string $filtertext Filter text for the user data 765 * @param boolean $passedonly TRUE if only passed user datasets should be exported, FALSE otherwise 766 * @access public 767 */ 768 public function exportToCSV($deliver = true, $filterby = "", $filtertext = "", $passedonly = false) 769 { 770 $this->test_obj->setAccessFilteredParticipantList( 771 $this->test_obj->buildStatisticsAccessFilteredParticipantList() 772 ); 773 774 if (strcmp($this->mode, "aggregated") == 0) { 775 return $this->aggregatedResultsToCSV($deliver); 776 } 777 778 $rows = array(); 779 $datarow = array(); 780 $col = 1; 781 if ($this->test_obj->getAnonymity()) { 782 array_push($datarow, $this->lng->txt("counter")); 783 $col++; 784 } else { 785 array_push($datarow, $this->lng->txt("name")); 786 $col++; 787 array_push($datarow, $this->lng->txt("login")); 788 $col++; 789 } 790 $additionalFields = $this->test_obj->getEvaluationAdditionalFields(); 791 if (count($additionalFields)) { 792 foreach ($additionalFields as $fieldname) { 793 if (strcmp($fieldname, "exam_id") == 0) { 794 array_push($datarow, $this->lng->txt('exam_id_label')); 795 $col++; 796 continue; 797 } 798 array_push($datarow, $this->lng->txt($fieldname)); 799 $col++; 800 } 801 } 802 array_push($datarow, $this->lng->txt("tst_stat_result_resultspoints")); 803 $col++; 804 array_push($datarow, $this->lng->txt("maximum_points")); 805 $col++; 806 array_push($datarow, $this->lng->txt("tst_stat_result_resultsmarks")); 807 $col++; 808 if ($this->test_obj->getECTSOutput()) { 809 array_push($datarow, $this->lng->txt("ects_grade")); 810 $col++; 811 } 812 array_push($datarow, $this->lng->txt("tst_stat_result_qworkedthrough")); 813 $col++; 814 array_push($datarow, $this->lng->txt("tst_stat_result_qmax")); 815 $col++; 816 array_push($datarow, $this->lng->txt("tst_stat_result_pworkedthrough")); 817 $col++; 818 array_push($datarow, $this->lng->txt("tst_stat_result_timeofwork")); 819 $col++; 820 array_push($datarow, $this->lng->txt("tst_stat_result_atimeofwork")); 821 $col++; 822 array_push($datarow, $this->lng->txt("tst_stat_result_firstvisit")); 823 $col++; 824 array_push($datarow, $this->lng->txt("tst_stat_result_lastvisit")); 825 $col++; 826 827 array_push($datarow, $this->lng->txt("tst_stat_result_mark_median")); 828 $col++; 829 array_push($datarow, $this->lng->txt("tst_stat_result_rank_participant")); 830 $col++; 831 array_push($datarow, $this->lng->txt("tst_stat_result_rank_median")); 832 $col++; 833 array_push($datarow, $this->lng->txt("tst_stat_result_total_participants")); 834 $col++; 835 array_push($datarow, $this->lng->txt("tst_stat_result_median")); 836 $col++; 837 array_push($datarow, $this->lng->txt("scored_pass")); 838 $col++; 839 840 array_push($datarow, $this->lng->txt("pass")); 841 $col++; 842 843 $data = &$this->test_obj->getCompleteEvaluationData(true, $filterby, $filtertext); 844 $headerrow = $datarow; 845 $counter = 1; 846 foreach ($data->getParticipants() as $active_id => $userdata) { 847 $datarow = $headerrow; 848 $remove = false; 849 if ($passedonly) { 850 if ($data->getParticipant($active_id)->getPassed() == false) { 851 $remove = true; 852 } 853 } 854 if (!$remove) { 855 $datarow2 = array(); 856 if ($this->test_obj->getAnonymity()) { 857 array_push($datarow2, $counter); 858 } else { 859 array_push($datarow2, $data->getParticipant($active_id)->getName()); 860 array_push($datarow2, $data->getParticipant($active_id)->getLogin()); 861 } 862 if (count($additionalFields)) { 863 $userfields = ilObjUser::_lookupFields($userdata->getUserID()); 864 foreach ($additionalFields as $fieldname) { 865 if (strcmp($fieldname, "gender") == 0) { 866 array_push($datarow2, $this->lng->txt("gender_" . $userfields[$fieldname])); 867 } elseif (strcmp($fieldname, "exam_id") == 0) { 868 array_push($datarow2, $userdata->getExamIdFromScoredPass()); 869 } else { 870 array_push($datarow2, $userfields[$fieldname]); 871 } 872 } 873 } 874 array_push($datarow2, $data->getParticipant($active_id)->getReached()); 875 array_push($datarow2, $data->getParticipant($active_id)->getMaxpoints()); 876 array_push($datarow2, $data->getParticipant($active_id)->getMark()); 877 if ($this->test_obj->getECTSOutput()) { 878 array_push($datarow2, $data->getParticipant($active_id)->getECTSMark()); 879 } 880 array_push($datarow2, $data->getParticipant($active_id)->getQuestionsWorkedThrough()); 881 array_push($datarow2, $data->getParticipant($active_id)->getNumberOfQuestions()); 882 array_push($datarow2, $data->getParticipant($active_id)->getQuestionsWorkedThroughInPercent() / 100.0); 883 $time = $data->getParticipant($active_id)->getTimeOfWork(); 884 $time_seconds = $time; 885 $time_hours = floor($time_seconds / 3600); 886 $time_seconds -= $time_hours * 3600; 887 $time_minutes = floor($time_seconds / 60); 888 $time_seconds -= $time_minutes * 60; 889 array_push($datarow2, sprintf("%02d:%02d:%02d", $time_hours, $time_minutes, $time_seconds)); 890 $time = $data->getParticipant($active_id)->getQuestionsWorkedThrough() ? $data->getParticipant($active_id)->getTimeOfWork() / $data->getParticipant($active_id)->getQuestionsWorkedThrough() : 0; 891 $time_seconds = $time; 892 $time_hours = floor($time_seconds / 3600); 893 $time_seconds -= $time_hours * 3600; 894 $time_minutes = floor($time_seconds / 60); 895 $time_seconds -= $time_minutes * 60; 896 array_push($datarow2, sprintf("%02d:%02d:%02d", $time_hours, $time_minutes, $time_seconds)); 897 898 $fv = $data->getParticipant($active_id)->getFirstVisit(); 899 $lv = $data->getParticipant($active_id)->getLastVisit(); 900 foreach (array($fv, $lv) as $ts) { 901 if ($ts) { 902 $visit = ilDatePresentation::formatDate(new ilDateTime($ts, IL_CAL_UNIX)); 903 array_push($datarow2, $visit); 904 } else { 905 array_push($datarow2, ""); 906 } 907 } 908 909 $median = $data->getStatistics()->getStatistics()->median(); 910 $pct = $data->getParticipant($active_id)->getMaxpoints() ? $median / $data->getParticipant($active_id)->getMaxpoints() * 100.0 : 0; 911 $mark = $this->test_obj->mark_schema->getMatchingMark($pct); 912 $mark_short_name = ""; 913 if (is_object($mark)) { 914 $mark_short_name = $mark->getShortName(); 915 } 916 array_push($datarow2, $mark_short_name); 917 array_push($datarow2, $data->getStatistics()->getStatistics()->rank($data->getParticipant($active_id)->getReached())); 918 array_push($datarow2, $data->getStatistics()->getStatistics()->rank_median()); 919 array_push($datarow2, $data->getStatistics()->getStatistics()->count()); 920 array_push($datarow2, $median); 921 if ($this->test_obj->getPassScoring() == SCORE_BEST_PASS) { 922 array_push($datarow2, $data->getParticipant($active_id)->getBestPass() + 1); 923 } else { 924 array_push($datarow2, $data->getParticipant($active_id)->getLastPass() + 1); 925 } 926 for ($pass = 0; $pass <= $data->getParticipant($active_id)->getLastPass(); $pass++) { 927 $finishdate = ilObjTest::lookupPassResultsUpdateTimestamp($active_id, $pass); 928 if ($finishdate > 0) { 929 if ($pass > 0) { 930 for ($i = 1; $i < $col - 1; $i++) { 931 array_push($datarow2, ""); 932 array_push($datarow, ""); 933 } 934 array_push($datarow, ""); 935 } 936 array_push($datarow2, $pass + 1); 937 if (is_object($data->getParticipant($active_id)) && is_array($data->getParticipant($active_id)->getQuestions($pass))) { 938 foreach ($data->getParticipant($active_id)->getQuestions($pass) as $question) { 939 $question_data = $data->getParticipant($active_id)->getPass($pass)->getAnsweredQuestionByQuestionId($question["id"]); 940 array_push($datarow2, $question_data["reached"]); 941 array_push($datarow, preg_replace("/<.*?>/", "", $data->getQuestionTitle($question["id"]))); 942 } 943 } 944 if ($this->test_obj->isRandomTest() || $this->test_obj->getShuffleQuestions() || ($counter == 1 && $pass == 0)) { 945 array_push($rows, $datarow); 946 } 947 $datarow = array(); 948 array_push($rows, $datarow2); 949 $datarow2 = array(); 950 } 951 } 952 $counter++; 953 } 954 } 955 $csv = ""; 956 $separator = ";"; 957 foreach ($rows as $evalrow) { 958 $csvrow = &$this->test_obj->processCSVRow($evalrow, true, $separator); 959 $csv .= join($separator, $csvrow) . "\n"; 960 } 961 if ($deliver) { 962 ilUtil::deliverData($csv, ilUtil::getASCIIFilename($this->test_obj->getTitle() . "_results.csv")); 963 exit; 964 } else { 965 return $csv; 966 } 967 } 968 969 abstract protected function initXmlExport(); 970 971 abstract protected function getQuestionIds(); 972 973 /** 974 * build xml export file 975 */ 976 public function buildExportFileXML() 977 { 978 global $DIC; 979 $ilBench = $DIC['ilBench']; 980 981 $ilBench->start("TestExport", "buildExportFile"); 982 983 $this->initXmlExport(); 984 985 include_once("./Services/Xml/classes/class.ilXmlWriter.php"); 986 $this->xml = new ilXmlWriter; 987 988 // set dtd definition 989 $this->xml->xmlSetDtdDef("<!DOCTYPE Test SYSTEM \"http://www.ilias.uni-koeln.de/download/dtd/ilias_co.dtd\">"); 990 991 // set generated comment 992 $this->xml->xmlSetGenCmt("Export of ILIAS Test " . 993 $this->test_obj->getId() . " of installation " . $this->inst . "."); 994 995 // set xml header 996 $this->xml->xmlHeader(); 997 998 $this->xml->xmlStartTag("ContentObject", array('Type' => 'Test')); 999 1000 // create directories 1001 $this->test_obj->createExportDirectory(); 1002 include_once "./Services/Utilities/classes/class.ilUtil.php"; 1003 ilUtil::makeDir($this->export_dir . "/" . $this->subdir); 1004 ilUtil::makeDir($this->export_dir . "/" . $this->subdir . "/objects"); 1005 1006 // get Log File 1007 $expDir = $this->test_obj->getExportDirectory(); 1008 include_once "./Services/Logging/classes/class.ilLog.php"; 1009 $expLog = new ilLog($expDir, "export.log"); 1010 $expLog->delete(); 1011 $expLog->setLogFormat(""); 1012 $expLog->write(date("[y-m-d H:i:s] ") . "Start Export"); 1013 1014 // write qti file 1015 $qti_file = fopen($this->export_dir . "/" . $this->subdir . "/" . $this->qti_filename, "w"); 1016 fwrite($qti_file, $this->getQtiXml()); 1017 fclose($qti_file); 1018 1019 // get xml content 1020 $ilBench->start("TestExport", "buildExportFile_getXML"); 1021 $this->test_obj->exportPagesXML( 1022 $this->xml, 1023 $this->inst_id, 1024 $this->export_dir . "/" . $this->subdir, 1025 $expLog 1026 ); 1027 $ilBench->stop("TestExport", "buildExportFile_getXML"); 1028 1029 $this->populateQuestionSetConfigXml($this->xml); 1030 1031 $assignmentList = $this->buildQuestionSkillAssignmentList(); 1032 $this->populateQuestionSkillAssignmentsXml($this->xml, $assignmentList, $this->getQuestionIds()); 1033 $this->populateSkillLevelThresholdsXml($this->xml, $assignmentList); 1034 1035 $this->xml->xmlEndTag("ContentObject"); 1036 1037 // dump xml document to screen (only for debugging reasons) 1038 /* 1039 echo "<PRE>"; 1040 echo htmlentities($this->xml->xmlDumpMem($format)); 1041 echo "</PRE>"; 1042 */ 1043 1044 // dump xml document to file 1045 $ilBench->start("TestExport", "buildExportFile_dumpToFile"); 1046 $this->xml->xmlDumpFile($this->export_dir . "/" . $this->subdir . "/" . $this->filename, false); 1047 $ilBench->stop("TestExport", "buildExportFile_dumpToFile"); 1048 1049 if ($this->isResultExportingEnabledForTestExport() && @file_exists("./Modules/Test/classes/class.ilTestResultsToXML.php")) { 1050 // dump results xml document to file 1051 include_once "./Modules/Test/classes/class.ilTestResultsToXML.php"; 1052 $resultwriter = new ilTestResultsToXML($this->test_obj->getTestId(), $this->test_obj->getAnonymity()); 1053 $resultwriter->setIncludeRandomTestQuestionsEnabled($this->test_obj->isRandomTest()); 1054 $ilBench->start("TestExport", "buildExportFile_results"); 1055 $resultwriter->xmlDumpFile($this->export_dir . "/" . $this->subdir . "/" . $this->resultsfile, false); 1056 $ilBench->stop("TestExport", "buildExportFile_results"); 1057 } 1058 1059 // add media objects which were added with tiny mce 1060 $ilBench->start("QuestionpoolExport", "buildExportFile_saveAdditionalMobs"); 1061 $this->exportXHTMLMediaObjects($this->export_dir . "/" . $this->subdir); 1062 $ilBench->stop("QuestionpoolExport", "buildExportFile_saveAdditionalMobs"); 1063 1064 // zip the file 1065 $ilBench->start("TestExport", "buildExportFile_zipFile"); 1066 ilUtil::zip( 1067 $this->export_dir . "/" . $this->subdir, 1068 $this->export_dir . "/" . $this->subdir . ".zip" 1069 ); 1070 $ilBench->stop("TestExport", "buildExportFile_zipFile"); 1071 1072 // destroy writer object 1073 $this->xml->_XmlWriter; 1074 1075 $expLog->write(date("[y-m-d H:i:s] ") . "Finished Export"); 1076 $ilBench->stop("TestExport", "buildExportFile"); 1077 1078 return $this->export_dir . "/" . $this->subdir . ".zip"; 1079 } 1080 1081 abstract protected function populateQuestionSetConfigXml(ilXmlWriter $xmlWriter); 1082 1083 protected function getQtiXml() 1084 { 1085 $tstQtiXml = $this->test_obj->toXML(); 1086 $qstQtiXml = $this->getQuestionsQtiXml(); 1087 1088 if (strpos($tstQtiXml, "</section>") !== false) { 1089 $qtiXml = str_replace("</section>", "$qstQtiXml</section>", $tstQtiXml); 1090 } else { 1091 $qtiXml = str_replace("<section ident=\"1\"/>", "<section ident=\"1\">\n$qstQtiXml</section>", $tstQtiXml); 1092 } 1093 1094 return $qtiXml; 1095 } 1096 1097 abstract protected function getQuestionsQtiXml(); 1098 1099 protected function getQuestionQtiXml($questionId) 1100 { 1101 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php"; 1102 $questionOBJ = assQuestion::_instantiateQuestion($questionId); 1103 $xml = $questionOBJ->toXML(false); 1104 1105 // still neccessary? there is an include header flag!? 1106 $xml = preg_replace("/<questestinterop>/", "", $xml); 1107 $xml = preg_replace("/<\/questestinterop>/", "", $xml); 1108 1109 return $xml; 1110 } 1111 1112 public function exportXHTMLMediaObjects($a_export_dir) 1113 { 1114 include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php"); 1115 1116 $mobs = ilObjMediaObject::_getMobsOfObject("tst:html", $this->test_obj->getId()); 1117 foreach ($mobs as $mob) { 1118 if (ilObjMediaObject::_exists($mob)) { 1119 $mob_obj = new ilObjMediaObject($mob); 1120 $mob_obj->exportFiles($a_export_dir); 1121 unset($mob_obj); 1122 } 1123 } 1124 foreach ($this->getQuestionIds() as $question_id) { 1125 $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $question_id); 1126 foreach ($mobs as $mob) { 1127 if (ilObjMediaObject::_exists($mob)) { 1128 $mob_obj = new ilObjMediaObject($mob); 1129 $mob_obj->exportFiles($a_export_dir); 1130 unset($mob_obj); 1131 } 1132 } 1133 } 1134 } 1135 1136 /** 1137 * @param ilXmlWriter $a_xml_writer 1138 * @param $questions 1139 */ 1140 protected function populateQuestionSkillAssignmentsXml(ilXmlWriter $a_xml_writer, ilAssQuestionSkillAssignmentList $assignmentList, $questions) 1141 { 1142 require_once 'Modules/TestQuestionPool/classes/questions/class.ilAssQuestionSkillAssignmentExporter.php'; 1143 $skillQuestionAssignmentExporter = new ilAssQuestionSkillAssignmentExporter(); 1144 $skillQuestionAssignmentExporter->setXmlWriter($a_xml_writer); 1145 $skillQuestionAssignmentExporter->setQuestionIds($questions); 1146 $skillQuestionAssignmentExporter->setAssignmentList($assignmentList); 1147 $skillQuestionAssignmentExporter->export(); 1148 } 1149 1150 protected function populateSkillLevelThresholdsXml(ilXmlWriter $a_xml_writer, ilAssQuestionSkillAssignmentList $assignmentList) 1151 { 1152 global $DIC; 1153 $ilDB = $DIC['ilDB']; 1154 1155 require_once 'Modules/Test/classes/class.ilTestSkillLevelThresholdList.php'; 1156 $thresholdList = new ilTestSkillLevelThresholdList($ilDB); 1157 $thresholdList->setTestId($this->test_obj->getTestId()); 1158 $thresholdList->loadFromDb(); 1159 1160 require_once 'Modules/Test/classes/class.ilTestSkillLevelThresholdExporter.php'; 1161 $skillLevelThresholdExporter = new ilTestSkillLevelThresholdExporter(); 1162 $skillLevelThresholdExporter->setXmlWriter($a_xml_writer); 1163 $skillLevelThresholdExporter->setAssignmentList($assignmentList); 1164 $skillLevelThresholdExporter->setThresholdList($thresholdList); 1165 $skillLevelThresholdExporter->export(); 1166 } 1167 1168 /** 1169 * @return ilAssQuestionSkillAssignmentList 1170 */ 1171 protected function buildQuestionSkillAssignmentList() 1172 { 1173 global $DIC; 1174 $ilDB = $DIC['ilDB']; 1175 1176 require_once 'Modules/TestQuestionPool/classes/class.ilAssQuestionSkillAssignmentList.php'; 1177 $assignmentList = new ilAssQuestionSkillAssignmentList($ilDB); 1178 $assignmentList->setParentObjId($this->test_obj->getId()); 1179 $assignmentList->loadFromDb(); 1180 $assignmentList->loadAdditionalSkillData(); 1181 1182 return $assignmentList; 1183 } 1184} 1185