ILIAS  eassessment Revision 61809
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilTestExport.php
Go to the documentation of this file.
1 <?php
2 /*
3  +-----------------------------------------------------------------------------+
4  | ILIAS open source |
5  +-----------------------------------------------------------------------------+
6  | Copyright (c) 1998-2001 ILIAS open source, University of Cologne |
7  | |
8  | This program is free software; you can redistribute it and/or |
9  | modify it under the terms of the GNU General Public License |
10  | as published by the Free Software Foundation; either version 2 |
11  | of the License, or (at your option) any later version. |
12  | |
13  | This program is distributed in the hope that it will be useful, |
14  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16  | GNU General Public License for more details. |
17  | |
18  | You should have received a copy of the GNU General Public License |
19  | along with this program; if not, write to the Free Software |
20  | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21  +-----------------------------------------------------------------------------+
22 */
23 
24 include_once "./Modules/Test/classes/inc.AssessmentConstants.php";
25 
35 {
36  var $err; // error object
37  var $db; // database object
38  var $ilias; // ilias object
39  var $test_obj; // test object
40  var $inst_id; // installation id
41  var $mode;
42  private $lng;
43  private $resultsfile;
44 
49  function ilTestExport(&$a_test_obj, $a_mode = "xml")
50  {
51  global $ilErr, $ilDB, $ilias, $lng;
52 
53  $this->test_obj =& $a_test_obj;
54 
55  $this->err =& $ilErr;
56  $this->ilias =& $ilias;
57  $this->db =& $ilDB;
58  $this->mode = $a_mode;
59  $this->lng =& $lng;
60 
61  $settings = $this->ilias->getAllSettings();
62  $this->inst_id = IL_INST_ID;
63 
64  $date = time();
65  $this->export_dir = $this->test_obj->getExportDirectory();
66  switch($this->mode)
67  {
68  case "results":
69  $this->subdir = $date."__".$this->inst_id."__".
70  "test__results__".$this->test_obj->getId();
71  break;
72  case "aggregated":
73  $this->subdir = $date."__".$this->inst_id."__".
74  "test__aggregated__results__".$this->test_obj->getId();
75  break;
76  default:
77  $this->subdir = $date."__".$this->inst_id."__".
78  "test"."__".$this->test_obj->getId();
79  $this->filename = $this->subdir.".xml";
80  $this->resultsfile = $date."__".$this->inst_id."__".
81  "results"."__".$this->test_obj->getId().".xml";
82  $this->qti_filename = $date."__".$this->inst_id."__".
83  "qti"."__".$this->test_obj->getId().".xml";
84  break;
85  }
86  $this->filename = $this->subdir.".".$this->getExtension();
87  }
88 
89  function getExtension () {
90  switch ($this->mode) {
91  case "results":
92  return "csv"; break;
93  default:
94  return "xml"; break;
95  }
96  }
97 
98  function getInstId()
99  {
100  return $this->inst_id;
101  }
102 
103 
110  function buildExportFile()
111  {
112  switch ($this->mode)
113  {
114  case "results":
115  return $this->buildExportResultFile();
116  break;
117  default:
118  return $this->buildExportFileXML();
119  break;
120  }
121  }
122 
127  {
128  global $ilBench;
129  global $log;
130 
131  //get Log File
132  $expDir = $this->test_obj->getExportDirectory();
133  //$expLog = &$log;
134  $expLog = new ilLog($expDir, "export.log");
135  $expLog->delete();
136  $expLog->setLogFormat("");
137  $expLog->write(date("[y-m-d H:i:s] ")."Start Export Of Results");
138 
139  // make_directories
140  $this->test_obj->createExportDirectory();
141  include_once "./Services/Utilities/classes/class.ilUtil.php";
142  ilUtil::makeDir($this->export_dir);
143 
144  $data = $this->exportToCSV($deliver = FALSE);
145  $file = fopen($this->export_dir."/".$this->filename, "w");
146  fwrite($file, $data);
147  fclose($file);
148 
149  $excelfile = $this->exportToExcel($deliver = FALSE);
150  include_once "./Services/Excel/classes/class.ilExcelUtils.php";
151  $adapter = ilExcelUtils::ExcelAdapter();
152  @copy($excelfile, $this->export_dir . "/" . str_replace($this->getExtension(), $adapter->getFileExtension(), $this->filename));
153  @unlink($excelfile);
154  // end
155  $expLog->write(date("[y-m-d H:i:s] ")."Finished Export of Results");
156 
157  return $this->export_dir."/".$this->filename;
158  }
159 
165  protected function aggregatedResultsToExcel($deliver = TRUE)
166  {
167  $data = $this->test_obj->getAggregatedResultsData();
168  include_once "./Services/Excel/classes/class.ilExcelUtils.php";
169  $adapter = ilExcelUtils::ExcelAdapter();
170  $outputfilename = ilUtil::getASCIIFilename(preg_replace("/\s/", "_", $this->test_obj->getTitle())) . "-aggregated." . $adapter->getFileExtension();
171  $adapter->setWorksheetTitle($this->lng->txt("tst_results_aggregated"));
172  $additionalFields = $this->test_obj->getEvaluationAdditionalFields();
173  $row = 0;
174  $col = 0;
175  $adapter->setCellValue($row, $col++, $this->lng->txt("result"), CELL_FORMAT_TITLE);
176  $adapter->setCellValue($row, $col++, $this->lng->txt("value"), CELL_FORMAT_TITLE);
177  $row++;
178  foreach ($data["overview"] as $key => $value)
179  {
180  $col = 0;
181  $adapter->setCellValue($row, $col++, $key);
182  $adapter->setCellValue($row, $col++, $value);
183  $row++;
184  }
185  $row++;
186  $col = 0;
187  $adapter->setCellValue($row, $col++, $this->lng->txt("question_id"), CELL_FORMAT_TITLE);
188  $adapter->setCellValue($row, $col++, $this->lng->txt("question_title"), CELL_FORMAT_TITLE);
189  $adapter->setCellValue($row, $col++, $this->lng->txt("average_reached_points"), CELL_FORMAT_TITLE);
190  $adapter->setCellValue($row, $col++, $this->lng->txt("points"), CELL_FORMAT_TITLE);
191  $adapter->setCellValue($row, $col++, $this->lng->txt("percentage"), CELL_FORMAT_TITLE);
192  $adapter->setCellValue($row, $col++, $this->lng->txt("number_of_answers"), CELL_FORMAT_TITLE);
193  $row++;
194  foreach ($data["questions"] as $key => $value)
195  {
196  $col = 0;
197  $adapter->setCellValue($row, $col++, $key);
198  $adapter->setCellValue($row, $col++, $value[0]);
199  $adapter->setCellValue($row, $col++, $value[4]);
200  $adapter->setCellValue($row, $col++, $value[5]);
201  $adapter->setCellValue($row, $col++, $value[6], CELL_FORMAT_PERCENT);
202  $adapter->setCellValue($row, $col++, $value[3]);
203  $row++;
204  }
205  if ($deliver)
206  {
207  $adapter->deliver($outputfilename);
208  exit;
209  }
210  else
211  {
212  return $adapter->save();
213  }
214  }
215 
221  protected function aggregatedResultsToCSV($deliver = TRUE)
222  {
223  $data = $this->test_obj->getAggregatedResultsData();
224  $rows = array();
225  array_push($rows, array(
226  $this->lng->txt("result"),
227  $this->lng->txt("value")
228  ));
229  foreach ($data["overview"] as $key => $value)
230  {
231  array_push($rows, array(
232  $key,
233  $value
234  ));
235  }
236  array_push($rows, array(
237  $this->lng->txt("question_title"),
238  $this->lng->txt("average_reached_points"),
239  $this->lng->txt("points"),
240  $this->lng->txt("percentage"),
241  $this->lng->txt("number_of_answers")
242  ));
243  foreach ($data["questions"] as $key => $value)
244  {
245  array_push($rows, array(
246  $value[0],
247  $value[4],
248  $value[5],
249  $value[6],
250  $value[3]
251  ));
252  }
253  $csv = "";
254  $separator = ";";
255  foreach ($rows as $evalrow)
256  {
257  $csvrow =& $this->test_obj->processCSVRow($evalrow, TRUE, $separator);
258  $csv .= join($csvrow, $separator) . "\n";
259  }
260  if ($deliver)
261  {
262  ilUtil::deliverData($csv, ilUtil::getASCIIFilename($this->test_obj->getTitle() . "-aggregated.csv"));
263  exit;
264  }
265  else
266  {
267  return $csv;
268  }
269  }
270 
280  function compareQuestionsByOID($a, $b)
281  {
282  if ($a["id"] == $b["id"]) {
283  return 0;
284  }
285  return ($a["id"] < $b["id"]) ? -1 : 1;
286  }
287 
295  function exportToExcel($deliver = TRUE, $filterby = "", $filtertext = "", $passedonly = FALSE)
296  {
297  global $ilLog;
298 
299  if (strcmp($this->mode, "aggregated") == 0) return $this->aggregatedResultsToExcel($deliver);
300 
301  include_once "./Services/Excel/classes/class.ilExcelUtils.php";
302  $adapter = ilExcelUtils::ExcelAdapter();
303  $outputfilename = ilUtil::getASCIIFilename(preg_replace("/\s/", "_", $this->test_obj->getTitle())) . "-detailed." . $adapter->getFileExtension();
304  $adapter->setWorksheetTitle($this->lng->txt("tst_results"));
305  $additionalFields = $this->test_obj->getEvaluationAdditionalFields();
306  $row = 0;
307  $col = 0;
308 
309  if ($this->test_obj->getAnonymity())
310  {
311  $adapter->setCellValue($row, $col++, $this->lng->txt("counter"), CELL_FORMAT_TITLE);
312  }
313  else
314  {
315  $adapter->setCellValue($row, $col++, $this->lng->txt("name"), CELL_FORMAT_TITLE);
316  $adapter->setCellValue($row, $col++, $this->lng->txt("login"), CELL_FORMAT_TITLE);
317  }
318  if (count($additionalFields))
319  {
320  foreach ($additionalFields as $fieldname)
321  {
322  $adapter->setCellValue($row, $col++, $this->lng->txt($fieldname), CELL_FORMAT_TITLE);
323  }
324  }
325  $adapter->setCellValue($row, $col++, $this->lng->txt("tst_stat_result_resultspoints"), CELL_FORMAT_TITLE);
326  $adapter->setCellValue($row, $col++, $this->lng->txt("maximum_points"), CELL_FORMAT_TITLE);
327  $adapter->setCellValue($row, $col++, $this->lng->txt("tst_stat_result_resultsmarks"), CELL_FORMAT_TITLE);
328  if ($this->test_obj->ects_output)
329  {
330  $adapter->setCellValue($row, $col++, $this->lng->txt("ects_grade"), CELL_FORMAT_TITLE);
331  }
332  $adapter->setCellValue($row, $col++, $this->lng->txt("tst_stat_result_qworkedthrough"), CELL_FORMAT_TITLE);
333  $adapter->setCellValue($row, $col++, $this->lng->txt("tst_stat_result_qmax"), CELL_FORMAT_TITLE);
334  $adapter->setCellValue($row, $col++, $this->lng->txt("tst_stat_result_pworkedthrough"), CELL_FORMAT_TITLE);
335  $adapter->setCellValue($row, $col++, $this->lng->txt("tst_stat_result_timeofwork"), CELL_FORMAT_TITLE);
336  $adapter->setCellValue($row, $col++, $this->lng->txt("tst_stat_result_atimeofwork"), CELL_FORMAT_TITLE);
337  $adapter->setCellValue($row, $col++, $this->lng->txt("tst_stat_result_firstvisit"), CELL_FORMAT_TITLE);
338  $adapter->setCellValue($row, $col++, $this->lng->txt("tst_stat_result_lastvisit"), CELL_FORMAT_TITLE);
339  $adapter->setCellValue($row, $col++, $this->lng->txt("tst_stat_result_mark_median"), CELL_FORMAT_TITLE);
340  $adapter->setCellValue($row, $col++, $this->lng->txt("tst_stat_result_rank_participant"), CELL_FORMAT_TITLE);
341  $adapter->setCellValue($row, $col++, $this->lng->txt("tst_stat_result_rank_median"), CELL_FORMAT_TITLE);
342  $adapter->setCellValue($row, $col++, $this->lng->txt("tst_stat_result_total_participants"), CELL_FORMAT_TITLE);
343  $adapter->setCellValue($row, $col++, $this->lng->txt("tst_stat_result_median"), CELL_FORMAT_TITLE);
344  $adapter->setCellValue($row, $col++, $this->lng->txt("scored_pass"), CELL_FORMAT_TITLE);
345  $adapter->setCellValue($row, $col++, $this->lng->txt("pass"), CELL_FORMAT_TITLE);
346 
347  include_once "./Services/Excel/classes/class.ilExcelUtils.php";
348  $counter = 1;
349 
350  include_once "./Modules/Test/classes/class.ilTestEvaluationData.php";
351  include_once "./Modules/Test/classes/class.ilTestEvaluationPassData.php";
352  include_once "./Modules/Test/classes/class.ilTestEvaluationUserData.php";
353 
354  unset($this->test_obj->ilias);
355  unset($this->test_obj->lng);
356 
357  $data = new ilTestEvaluationData($this->test_obj);
358  $data->calculateStatistics();
359  $data->setFilter($filterby, $filtertext);
360 
361 // $data =& $this->test_obj->getCompleteEvaluationData(TRUE, $filterby, $filtertext);
362  $firstrowwritten = false;
363  $ilLog->write("Export Test Results");
364  foreach ($data->getParticipants() as $active_id => $userdata)
365  {
366  $data->getCompleteDataForParticipant($active_id); // do this by participant, otherwise memory usage is horrible for large tests and participants
367  $remove = FALSE;
368  if ($passedonly)
369  {
370  if ($data->getParticipant($active_id)->getPassed() == FALSE)
371  {
372  $remove = TRUE;
373  }
374  }
375  if (!$remove)
376  {
377  $row++;
378  if (($this->test_obj->isRandomTest() || $this->test_obj->getShuffleQuestions()) && $this->test_obj->getExportSettingsRespectShuffle())
379  {
380  $row++;
381  }
382  $col = 0;
383  if ($this->test_obj->getAnonymity())
384  {
385  $adapter->setCellValue($row, $col++, $counter);
386  }
387  else
388  {
389  $adapter->setCellValue($row, $col++, $data->getParticipant($active_id)->getName());
390  $adapter->setCellValue($row, $col++, $data->getParticipant($active_id)->getLogin());
391  }
392  //$ilLog->write($row . ". " . $data->getParticipant($active_id)->getName());
393  if (count($additionalFields))
394  {
395  $userfields = ilObjUser::_lookupFields($userdata->getUserID());
396  foreach ($additionalFields as $fieldname)
397  {
398  if (strcmp($fieldname, "gender") == 0)
399  {
400  $adapter->setCellValue($row, $col++, $this->lng->txt("gender_" . $userfields[$fieldname]));
401  }
402  else
403  {
404  $adapter->setCellValue($row, $col++, $userfields[$fieldname]);
405  }
406  }
407  }
408  $adapter->setCellValue($row, $col++, $data->getParticipant($active_id)->getReached());
409  $adapter->setCellValue($row, $col++, $data->getParticipant($active_id)->getMaxpoints());
410  $adapter->setCellValue($row, $col++, $data->getParticipant($active_id)->getMark());
411  if ($this->test_obj->ects_output)
412  {
413  $adapter->setCellValue($row, $col++, $data->getParticipant($active_id)->getECTSMark());
414  }
415  $adapter->setCellValue($row, $col++, $data->getParticipant($active_id)->getQuestionsWorkedThrough());
416  $adapter->setCellValue($row, $col++, $data->getParticipant($active_id)->getNumberOfQuestions());
417  $adapter->setCellValue($row, $col++, $data->getParticipant($active_id)->getQuestionsWorkedThroughInPercent() / 100.0, CELL_FORMAT_PERCENT);
418  $time = $data->getParticipant($active_id)->getTimeOfWork();
419  $time_seconds = $time;
420  $time_hours = floor($time_seconds/3600);
421  $time_seconds -= $time_hours * 3600;
422  $time_minutes = floor($time_seconds/60);
423  $time_seconds -= $time_minutes * 60;
424  $adapter->setCellValue($row, $col++, sprintf("%02d:%02d:%02d", $time_hours, $time_minutes, $time_seconds));
425  $time = $data->getParticipant($active_id)->getQuestionsWorkedThrough() ? $data->getParticipant($active_id)->getTimeOfWork() / $data->getParticipant($active_id)->getQuestionsWorkedThrough() : 0;
426  $time_seconds = $time;
427  $time_hours = floor($time_seconds/3600);
428  $time_seconds -= $time_hours * 3600;
429  $time_minutes = floor($time_seconds/60);
430  $time_seconds -= $time_minutes * 60;
431  $adapter->setCellValue($row, $col++, sprintf("%02d:%02d:%02d", $time_hours, $time_minutes, $time_seconds));
432  $fv = getdate($data->getParticipant($active_id)->getFirstVisit());
433  $firstvisit = ilUtil::excelTime(
434  $fv["year"],
435  $fv["mon"],
436  $fv["mday"],
437  $fv["hours"],
438  $fv["minutes"],
439  $fv["seconds"]
440  );
441  $adapter->setCellValue($row, $col++, $firstvisit, CELL_FORMAT_DATETIME);
442  $lv = getdate($data->getParticipant($active_id)->getLastVisit());
443  $lastvisit = ilUtil::excelTime(
444  $lv["year"],
445  $lv["mon"],
446  $lv["mday"],
447  $lv["hours"],
448  $lv["minutes"],
449  $lv["seconds"]
450  );
451  $adapter->setCellValue($row, $col++, $lastvisit, CELL_FORMAT_DATETIME);
452 
453  $median = $data->getStatistics()->getStatistics()->median();
454  $pct = $data->getParticipant($active_id)->getMaxpoints() ? $median / $data->getParticipant($active_id)->getMaxpoints() * 100.0 : 0;
455  $mark = $this->test_obj->mark_schema->getMatchingMark($pct);
456  $mark_short_name = "";
457  if (is_object($mark))
458  {
459  $mark_short_name = $mark->getShortName();
460  }
461  $adapter->setCellValue($row, $col++, $mark_short_name);
462  $adapter->setCellValue($row, $col++, $data->getStatistics()->getStatistics()->rank($data->getParticipant($active_id)->getReached()));
463  $adapter->setCellValue($row, $col++, $data->getStatistics()->getStatistics()->rank_median());
464  $adapter->setCellValue($row, $col++, $data->getStatistics()->getStatistics()->count());
465  $adapter->setCellValue($row, $col++, $median);
466  if ($this->test_obj->getPassScoring() == SCORE_BEST_PASS)
467  {
468  $adapter->setCellValue($row, $col++, $data->getParticipant($active_id)->getBestPass() + 1);
469  }
470  else
471  {
472  $adapter->setCellValue($row, $col++, $data->getParticipant($active_id)->getLastPass() + 1);
473  }
474  $startcol = $col;
475  $maxcol = $col;
476  for ($pass = 0; $pass <= $data->getParticipant($active_id)->getLastPass(); $pass++)
477  {
478  $col = $startcol;
479  $finishdate = $this->test_obj->getPassFinishDate($active_id, $pass);
480  if ($finishdate > 0)
481  {
482  if ($pass > 0)
483  {
484  $row++;
485  if (($this->test_obj->isRandomTest() || $this->test_obj->getShuffleQuestions()) && $this->test_obj->getExportSettingsRespectShuffle())
486  {
487  $row++;
488  }
489  }
490  $adapter->setCellValue($row, $col++, $pass+1);
491  if (is_object($data->getParticipant($active_id)) && is_array($data->getParticipant($active_id)->getQuestions($pass)))
492  {
493  $questions = $data->getParticipant($active_id)->getQuestions($pass);
494 
495  if (!$this->test_obj->getExportSettingsRespectShuffle())
496  {
497  usort($questions, array(&$this, "compareQuestionsByOID"));
498  }
499  foreach ($questions as $question)
500  {
501  $question_data = $data->getParticipant($active_id)->getPass($pass)->getAnsweredQuestionByQuestionId($question["id"]);
502  $adapter->setCellValue($row, $col, $question_data["reached"]);
503  if (($this->test_obj->isRandomTest() || $this->test_obj->getShuffleQuestions()) && $this->test_obj->getExportSettingsRespectShuffle())
504  {
505  $adapter->setCellValue($row-1, $col, preg_replace("/<.*?>/", "", "[" . $question["id"] . "] " . $data->getQuestionTitle($question["id"])), CELL_FORMAT_TITLE);
506  }
507  else
508  {
509  if ($pass == 0 && !$firstrowwritten)
510  {
511  $adapter->setCellValue(0, $col, preg_replace("/<.*?>/", "", "[" . $question["id"] . "] " . $data->getQuestionTitle($question["id"])), CELL_FORMAT_TITLE);
512  }
513  }
514  $col++;
515  }
516  $firstrowwritten = true;
517  }
518  }
519  if ($col > $maxcol) $maxcol = $col;
520  }
521  $counter++;
522  }
523  $data->getParticipant($active_id)->unsetPasses();
524  $data->getParticipant($active_id)->unsetQuestions();
525  }
526  for ($colnr = 0; $colnr <= $maxcol; $colnr++)
527  {
528  $adapter->setColumnWidth($colnr, 'auto');
529  }
530  if ($this->test_obj->getExportSettingsSingleChoiceShort() && !$this->test_obj->isRandomTest() && $this->test_obj->hasSingleChoiceQuestions())
531  {
532  unset($data);
533  $data = new ilTestEvaluationData($this->test_obj);
534  $data->calculateStatistics();
535  $data->setFilter($filterby, $filtertext);
536 
537  $ilLog->write("Export Single Choice Results");
538  // special tab for single choice tests
539  $titles =& $this->test_obj->getQuestionTitlesAndIndexes();
540  $positions = array();
541  $pos = 0;
542  $row = 0;
543  foreach ($titles as $id => $title)
544  {
545  $positions[$id] = $pos;
546  $pos++;
547  }
548 
549  $usernames = array();
550  $participantcount = count($data->getParticipants());
551  $allusersheet = false;
552  $pages = 0;
553  $adapter->addWorksheet($this->lng->txt("export_result_overview"));
554  $adapter->setActiveWorksheet($adapter->getWorksheetCount()-1);
555 
556  $col = 0;
557  $adapter->setCellValue($row, $col++, $this->lng->txt('name'), CELL_FORMAT_TITLE);
558  $adapter->setCellValue($row, $col++, $this->lng->txt('login'), CELL_FORMAT_TITLE);
559  if (count($additionalFields))
560  {
561  foreach ($additionalFields as $fieldname)
562  {
563  if (strcmp($fieldname, "matriculation") == 0)
564  {
565  $adapter->setCellValue($row, $col++, $this->lng->txt('matriculation'), CELL_FORMAT_TITLE);
566  }
567  }
568  }
569  $adapter->setCellValue($row, $col++, $this->lng->txt('test'), CELL_FORMAT_TITLE);
570  foreach ($titles as $aid => $title)
571  {
572  $adapter->setCellValue($row, $col+$positions[$aid], "[". $aid . "] " . $title, CELL_FORMAT_TITLE);
573  }
574  $row++;
575 
576  $maxcol = $col;
577  foreach ($data->getParticipants() as $active_id => $userdata)
578  {
579  $data->getCompleteDataForParticipant($active_id); // do this by participant, otherwise memory usage is horrible for large tests and participants
580  $username = (!is_null($userdata) && ilExcelUtils::_convert_text($userdata->getName())) ? ilExcelUtils::_convert_text($userdata->getName()) : "ID $active_id";
581  if (array_key_exists($username, $usernames))
582  {
583  $usernames[$username]++;
584  $username .= " ($i)";
585  }
586  else
587  {
588  $usernames[$username] = 1;
589  }
590  $col = 0;
591  //$ilLog->write($row . ". " . $data->getParticipant($active_id)->getName());
592  $adapter->setCellValue($row, $col++, $username);
593  $adapter->setCellValue($row, $col++, $userdata->getLogin());
594  if (count($additionalFields))
595  {
596  $userfields = ilObjUser::_lookupFields($userdata->getUserID());
597  foreach ($additionalFields as $fieldname)
598  {
599  if (strcmp($fieldname, "matriculation") == 0)
600  {
601  if (strlen($userfields[$fieldname]))
602  {
603  $adapter->setCellValue($row, $col++, $userfields[$fieldname]);
604  }
605  else
606  {
607  $col++;
608  }
609  }
610  }
611  }
612  $adapter->setCellValue($row, $col++, $this->test_obj->getTitle());
613  $pass = $userdata->getScoredPass();
614  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
615  include_once "./Modules/TestQuestionPool/classes/class.assSingleChoice.php";
616  if (is_object($userdata) && is_array($userdata->getQuestions($pass)))
617  {
618  foreach ($userdata->getQuestions($pass) as $question)
619  {
620  $solution = assQuestion::_getSolutionValues($active_id, $question["id"], $pass);
621  $answers = assSingleChoice::_getAnswerTexts($question["id"]);
622  $pos = $positions[$question["id"]];
623  $selectedanswer = "x";
624  foreach ($answers as $id => $answer)
625  {
626  if (strlen($solution[0]["value1"]) && $id == $solution[0]["value1"])
627  {
628  $selectedanswer = $answer;
629  break;
630  }
631  }
632  $adapter->setCellValue($row, $col+$pos, $selectedanswer);
633  if ($col+$pos > $maxcol) $maxcol = $col+$pos;
634  }
635  }
636  $row++;
637  $data->getParticipant($active_id)->unsetPasses();
638  $data->getParticipant($active_id)->unsetQuestions();
639  }
640  for ($colnr = 0; $colnr <= $maxcol; $colnr++)
641  {
642  $adapter->setColumnWidth($colnr, 'auto');
643  }
644  if ($this->test_obj->isSingleChoiceTestWithoutShuffle())
645  {
646  unset($data);
647  $ilLog->write("Export Compact Single Choice Results");
648  $data = new ilTestEvaluationData($this->test_obj);
649  $data->calculateStatistics();
650  $data->setFilter($filterby, $filtertext);
651  // special tab for single choice tests without shuffle option
652  $pos = 0;
653  $row = 0;
654  $usernames = array();
655  $allusersheet = false;
656  $pages = 0;
657  $adapter->addWorksheet($this->lng->txt("export_result_overview") . " (2)");
658  $adapter->setActiveWorksheet($adapter->getWorksheetCount()-1);
659 
660  $col = 0;
661  $adapter->setCellValue($row, $col++, $this->lng->txt('name'), CELL_FORMAT_TITLE);
662  $adapter->setCellValue($row, $col++, $this->lng->txt('login'), CELL_FORMAT_TITLE);
663  if (count($additionalFields))
664  {
665  foreach ($additionalFields as $fieldname)
666  {
667  if (strcmp($fieldname, "matriculation") == 0)
668  {
669  $adapter->setCellValue($row, $col++, $this->lng->txt('matriculation'), CELL_FORMAT_TITLE);
670  }
671  }
672  }
673  $adapter->setCellValue($row, $col++, $this->lng->txt('test'), CELL_FORMAT_TITLE);
674  foreach ($titles as $aid => $title)
675  { // M.W.
676  $adapter->setCellValue($row, $col+$positions[$aid], "[". $aid . "] " . $title, CELL_FORMAT_TITLE);
677  }
678  $row++;
679 
680  $maxcol = $col;
681  foreach ($data->getParticipants() as $active_id => $userdata)
682  {
683  $data->getCompleteDataForParticipant($active_id); // do this by participant, otherwise memory usage is horrible for large tests and participants
684  $username = (!is_null($userdata) && ilExcelUtils::_convert_text($userdata->getName())) ? ilExcelUtils::_convert_text($userdata->getName()) : "ID $active_id";
685  if (array_key_exists($username, $usernames))
686  {
687  $usernames[$username]++;
688  $username .= " ($i)";
689  }
690  else
691  {
692  $usernames[$username] = 1;
693  }
694  $col = 0;
695  //$ilLog->write($row . ". " . $data->getParticipant($active_id)->getName());
696  $adapter->setCellValue($row, $col++, $username);
697  $adapter->setCellValue($row, $col++, $userdata->getLogin());
698  if (count($additionalFields))
699  {
700  $userfields = ilObjUser::_lookupFields($userdata->getUserID());
701  foreach ($additionalFields as $fieldname)
702  {
703  if (strcmp($fieldname, "matriculation") == 0)
704  {
705  if (strlen($userfields[$fieldname]))
706  {
707  $adapter->setCellValue($row, $col++, $userfields[$fieldname]);
708  }
709  else
710  {
711  $col++;
712  }
713  }
714  }
715  }
716  $adapter->setCellValue($row, $col++, $this->test_obj->getTitle());
717  $pass = $userdata->getScoredPass();
718  if (is_object($userdata) && is_array($userdata->getQuestions($pass)))
719  {
720  foreach ($userdata->getQuestions($pass) as $question)
721  {
722  $solution = assQuestion::_getSolutionValues($active_id, $question["id"], $pass);
723  $pos = $positions[$question["id"]];
724  if (strlen($solution[0]["value1"]))
725  {
726  $selectedanswer = chr(65+$solution[0]["value1"]);
727  }
728  else
729  {
730  $selectedanswer = 'x';
731  }
732  $adapter->setCellValue($row, $col+$pos, $selectedanswer);
733  if ($col+$pos > $maxcol) $maxcol = $col+$pos;
734  }
735  }
736  $row++;
737  $data->getParticipant($active_id)->unsetPasses();
738  $data->getParticipant($active_id)->unsetQuestions();
739  }
740 
741  for ($colnr = 0; $colnr <= $maxcol; $colnr++)
742  {
743  $adapter->setColumnWidth($colnr, 'auto');
744  }
745  }
746  }
747 
748  $ilLog->write("Test participant result export");
749  unset($data);
750  $data = new ilTestEvaluationData($this->test_obj);
751  $data->calculateStatistics();
752  $data->setFilter($filterby, $filtertext);
753  $row = 0;
754  // test participant result export
755  $usernames = array();
756  $participantcount = count($data->getParticipants());
757  $allusersheet = false;
758  $pages = 0;
759  $pcounter = 1;
760  foreach ($data->getParticipants() as $active_id => $userdata)
761  {
762  $data->getCompleteDataForParticipant($active_id); // do this by participant, otherwise memory usage is horrible for large tests and participants
763  $username = (!is_null($userdata) && ilExcelUtils::_convert_text($userdata->getName())) ? ilExcelUtils::_convert_text($userdata->getName()) : "ID $active_id";
764  if (array_key_exists($username, $usernames))
765  {
766  $i=$usernames[$username]++;
767  $username .= " ($i)";
768  }
769  else
770  {
771  $usernames[$username] = 1;
772  }
773  //$ilLog->write($pcounter++ . ". " . $data->getParticipant($active_id)->getName());
774  if (strcmp($adapter->getFileExtension(), 'xls') == 0)
775  {
776  if ($participantcount > 250)
777  {
778  if (!$allusersheet || ($pages-1) < floor($row / 64000))
779  {
780  $adapter->addWorksheet($this->lng->txt("export_result_overview") . (($pages > 0) ? " (".($pages+1).")" : ""));
781  $adapter->setActiveWorksheet($adapter->getWorksheetCount()-1);
782  $allusersheet = true;
783  $row = 0;
784  $pages++;
785  }
786  }
787  else
788  {
789  $adapter->addWorksheet($username);
790  $adapter->setActiveWorksheet($adapter->getWorksheetCount()-1);
791  }
792  }
793  else
794  {
795  $adapter->addWorksheet($username);
796  $adapter->setActiveWorksheet($adapter->getWorksheetCount()-1);
797  }
798  $pass = $userdata->getScoredPass();
799  $row = ($allusersheet) ? $row : 0;
800  $adapter->setCellValue($row, 0, sprintf($this->lng->txt("tst_result_user_name_pass"), $pass+1, $userdata->getName()), CELL_FORMAT_BOLD);
801  $row += 2;
802  if (is_object($userdata) && is_array($userdata->getQuestions($pass)))
803  {
804  foreach ($userdata->getQuestions($pass) as $question)
805  {
806  $question =& $this->test_obj->_instanciateQuestion($question["id"]);
807  if (is_object($question))
808  {
809  $row = $question->setExportDetailsXLS($adapter, $row, $active_id, $pass);
810  }
811  }
812  }
813  $data->getParticipant($active_id)->unsetPasses();
814  $data->getParticipant($active_id)->unsetQuestions();
815  }
816  unset($data);
817  $this->writeQuestionUsageTimes($adapter);
818  if ($deliver)
819  {
820  $adapter->deliver($outputfilename);
821  exit;
822  }
823  else
824  {
825  return $adapter->save($outputfilename);
826  }
827  }
828 
829  private function writeQuestionUsageTimes($adapter)
830  {
831  global $ilLog;
832  $ilLog->write("Export Question Time Usage");
833  $adapter->addWorksheet($this->lng->txt('tst_question_time_usage'));
834  $adapter->setActiveWorksheet($adapter->getWorksheetCount()-1);
835  include_once "./Modules/Test/classes/class.ilTestEvaluationData.php";
836  $times = ilTestEvaluationData::_getTimeStatsForTest($this->test_obj->getTestId());
837  $titles =& $this->test_obj->getQuestionTitlesAndIndexes();
838 
839  $adapter->setCellValue(0, 0, $this->lng->txt('question_title'), CELL_FORMAT_TITLE);
840  $adapter->setCellValue(0, 1, $this->lng->txt('total_time'), CELL_FORMAT_TITLE);
841 
842  $row = 1;
843  foreach ($times as $question_id => $passes)
844  {
845  if ($question_id > 0)
846  {
847  $totaltime = 0;
848  $adapter->setCellValue($row, 0, "[" . $question_id . "] " . ilExcelUtils::_convert_text($titles[$question_id]), CELL_FORMAT_BOLD);
849  $col = 2;
850  foreach ($passes as $pass => $participants)
851  {
852  foreach ($participants as $active_id => $questiontimes)
853  {
854  foreach ($questiontimes as $timeInSeconds)
855  {
856  $totaltime += $timeInSeconds;
857  $adapter->setCellValue($row, $col, $timeInSeconds);
858  $col++;
859  }
860  }
861  }
862  $adapter->setCellValue($row, 1, $totaltime);
863  $row++;
864  }
865  }
866  }
867 
868 
878  function exportToCSV($deliver = TRUE, $filterby = "", $filtertext = "", $passedonly = FALSE)
879  {
880  global $ilLog;
881 
882  if (strcmp($this->mode, "aggregated") == 0) return $this->aggregatedResultsToCSV($deliver);
883 
884  $rows = array();
885  $datarow = array();
886  $col = 1;
887  if ($this->test_obj->getAnonymity())
888  {
889  array_push($datarow, $this->lng->txt("counter"));
890  $col++;
891  }
892  else
893  {
894  array_push($datarow, $this->lng->txt("name"));
895  $col++;
896  array_push($datarow, $this->lng->txt("login"));
897  $col++;
898  }
899  $additionalFields = $this->test_obj->getEvaluationAdditionalFields();
900  if (count($additionalFields))
901  {
902  foreach ($additionalFields as $fieldname)
903  {
904  array_push($datarow, $this->lng->txt($fieldname));
905  $col++;
906  }
907  }
908  array_push($datarow, $this->lng->txt("tst_stat_result_resultspoints"));
909  $col++;
910  array_push($datarow, $this->lng->txt("maximum_points"));
911  $col++;
912  array_push($datarow, $this->lng->txt("tst_stat_result_resultsmarks"));
913  $col++;
914  if ($this->test_obj->ects_output)
915  {
916  array_push($datarow, $this->lng->txt("ects_grade"));
917  $col++;
918  }
919  array_push($datarow, $this->lng->txt("tst_stat_result_qworkedthrough"));
920  $col++;
921  array_push($datarow, $this->lng->txt("tst_stat_result_qmax"));
922  $col++;
923  array_push($datarow, $this->lng->txt("tst_stat_result_pworkedthrough"));
924  $col++;
925  array_push($datarow, $this->lng->txt("tst_stat_result_timeofwork"));
926  $col++;
927  array_push($datarow, $this->lng->txt("tst_stat_result_atimeofwork"));
928  $col++;
929  array_push($datarow, $this->lng->txt("tst_stat_result_firstvisit"));
930  $col++;
931  array_push($datarow, $this->lng->txt("tst_stat_result_lastvisit"));
932  $col++;
933 
934  array_push($datarow, $this->lng->txt("tst_stat_result_mark_median"));
935  $col++;
936  array_push($datarow, $this->lng->txt("tst_stat_result_rank_participant"));
937  $col++;
938  array_push($datarow, $this->lng->txt("tst_stat_result_rank_median"));
939  $col++;
940  array_push($datarow, $this->lng->txt("tst_stat_result_total_participants"));
941  $col++;
942  array_push($datarow, $this->lng->txt("tst_stat_result_median"));
943  $col++;
944  array_push($datarow, $this->lng->txt("scored_pass"));
945  $col++;
946 
947  array_push($datarow, $this->lng->txt("pass"));
948  $col++;
949 
950  $data =& $this->test_obj->getCompleteEvaluationData(TRUE, $filterby, $filtertext);
951  $headerrow = $datarow;
952  $counter = 1;
953  foreach ($data->getParticipants() as $active_id => $userdata)
954  {
955  $datarow = $headerrow;
956  $remove = FALSE;
957  if ($passedonly)
958  {
959  if ($data->getParticipant($active_id)->getPassed() == FALSE)
960  {
961  $remove = TRUE;
962  }
963  }
964  if (!$remove)
965  {
966  $datarow2 = array();
967  if ($this->test_obj->getAnonymity())
968  {
969  array_push($datarow2, $counter);
970  }
971  else
972  {
973  array_push($datarow2, $data->getParticipant($active_id)->getName());
974  array_push($datarow2, $data->getParticipant($active_id)->getLogin());
975  }
976  if (count($additionalFields))
977  {
978  $userfields = ilObjUser::_lookupFields($userdata->getUserID());
979  foreach ($additionalFields as $fieldname)
980  {
981  if (strcmp($fieldname, "gender") == 0)
982  {
983  array_push($datarow2, $this->lng->txt("gender_" . $userfields[$fieldname]));
984  }
985  else
986  {
987  array_push($datarow2, $userfields[$fieldname]);
988  }
989  }
990  }
991  array_push($datarow2, $data->getParticipant($active_id)->getReached());
992  array_push($datarow2, $data->getParticipant($active_id)->getMaxpoints());
993  array_push($datarow2, $data->getParticipant($active_id)->getMark());
994  if ($this->test_obj->ects_output)
995  {
996  array_push($datarow2, $data->getParticipant($active_id)->getECTSMark());
997  }
998  array_push($datarow2, $data->getParticipant($active_id)->getQuestionsWorkedThrough());
999  array_push($datarow2, $data->getParticipant($active_id)->getNumberOfQuestions());
1000  array_push($datarow2, $data->getParticipant($active_id)->getQuestionsWorkedThroughInPercent() / 100.0);
1001  $time = $data->getParticipant($active_id)->getTimeOfWork();
1002  $time_seconds = $time;
1003  $time_hours = floor($time_seconds/3600);
1004  $time_seconds -= $time_hours * 3600;
1005  $time_minutes = floor($time_seconds/60);
1006  $time_seconds -= $time_minutes * 60;
1007  array_push($datarow2, sprintf("%02d:%02d:%02d", $time_hours, $time_minutes, $time_seconds));
1008  $time = $data->getParticipant($active_id)->getQuestionsWorkedThrough() ? $data->getParticipant($active_id)->getTimeOfWork() / $data->getParticipant($active_id)->getQuestionsWorkedThrough() : 0;
1009  $time_seconds = $time;
1010  $time_hours = floor($time_seconds/3600);
1011  $time_seconds -= $time_hours * 3600;
1012  $time_minutes = floor($time_seconds/60);
1013  $time_seconds -= $time_minutes * 60;
1014  array_push($datarow2, sprintf("%02d:%02d:%02d", $time_hours, $time_minutes, $time_seconds));
1015  $fv = getdate($data->getParticipant($active_id)->getFirstVisit());
1016  $firstvisit = ilUtil::excelTime(
1017  $fv["year"],
1018  $fv["mon"],
1019  $fv["mday"],
1020  $fv["hours"],
1021  $fv["minutes"],
1022  $fv["seconds"]
1023  );
1024  array_push($datarow2, $firstvisit);
1025  $lv = getdate($data->getParticipant($active_id)->getLastVisit());
1026  $lastvisit = ilUtil::excelTime(
1027  $lv["year"],
1028  $lv["mon"],
1029  $lv["mday"],
1030  $lv["hours"],
1031  $lv["minutes"],
1032  $lv["seconds"]
1033  );
1034  array_push($datarow2, $lastvisit);
1035 
1036  $median = $data->getStatistics()->getStatistics()->median();
1037  $pct = $data->getParticipant($active_id)->getMaxpoints() ? $median / $data->getParticipant($active_id)->getMaxpoints() * 100.0 : 0;
1038  $mark = $this->test_obj->mark_schema->getMatchingMark($pct);
1039  $mark_short_name = "";
1040  if (is_object($mark))
1041  {
1042  $mark_short_name = $mark->getShortName();
1043  }
1044  array_push($datarow2, $mark_short_name);
1045  array_push($datarow2, $data->getStatistics()->getStatistics()->rank($data->getParticipant($active_id)->getReached()));
1046  array_push($datarow2, $data->getStatistics()->getStatistics()->rank_median());
1047  array_push($datarow2, $data->getStatistics()->getStatistics()->count());
1048  array_push($datarow2, $median);
1049  if ($this->test_obj->getPassScoring() == SCORE_BEST_PASS)
1050  {
1051  array_push($datarow2, $data->getParticipant($active_id)->getBestPass() + 1);
1052  }
1053  else
1054  {
1055  array_push($datarow2, $data->getParticipant($active_id)->getLastPass() + 1);
1056  }
1057 
1058  for ($pass = 0; $pass <= $data->getParticipant($active_id)->getLastPass(); $pass++)
1059  {
1060  $finishdate = $this->test_obj->getPassFinishDate($active_id, $pass);
1061  if ($finishdate > 0)
1062  {
1063  if ($pass > 0)
1064  {
1065  for ($i = 1; $i < $col-1; $i++)
1066  {
1067  array_push($datarow2, "");
1068  array_push($datarow, "");
1069  }
1070  array_push($datarow, "");
1071  }
1072  array_push($datarow2, $pass+1);
1073  if (is_object($data->getParticipant($active_id)) && is_array($data->getParticipant($active_id)->getQuestions($pass)))
1074  {
1075  $questions = $data->getParticipant($active_id)->getQuestions($pass);
1076  if (!$this->test_obj->getExportSettingsRespectShuffle())
1077  {
1078  usort($questions, array(&$this, "compareQuestionsByOID"));
1079  }
1080  foreach ($questions as $question)
1081  {
1082  $question_data = $data->getParticipant($active_id)->getPass($pass)->getAnsweredQuestionByQuestionId($question["id"]);
1083  array_push($datarow2, $question_data["reached"]);
1084  array_push($datarow, preg_replace("/<.*?>/", "", $data->getQuestionTitle($question["id"])));
1085  }
1086  }
1087  if ((($this->test_obj->isRandomTest()
1088  || $this->test_obj->getShuffleQuestions())
1089  && $this->test_obj->getExportSettingsRespectShuffle())
1090  || ($counter == 1 && $pass == 0))
1091  {
1092  array_push($rows, $datarow);
1093  }
1094  $datarow = array();
1095  array_push($rows, $datarow2);
1096  $datarow2 = array();
1097  }
1098  }
1099  $counter++;
1100  }
1101  }
1102  $csv = "";
1103  $separator = ";";
1104  foreach ($rows as $evalrow)
1105  {
1106  $csvrow =& $this->test_obj->processCSVRow($evalrow, TRUE, $separator);
1107  $csv .= join($csvrow, $separator) . "\n";
1108  }
1109  if ($deliver)
1110  {
1111  ilUtil::deliverData($csv, ilUtil::getASCIIFilename($this->test_obj->getTitle() . "-detailed.csv"));
1112  exit;
1113  }
1114  else
1115  {
1116  return $csv;
1117  }
1118  }
1119 
1120 
1136  function exportToImsCSV($deliver = TRUE, $filterby = "", $filtertext = "", $passedonly = FALSE)
1137  {
1138  global $ilLog;
1139  include_once "./Services/Excel/classes/class.ilExcelUtils.php";
1140  $data =& $this->test_obj->getCompleteEvaluationData(TRUE, $filterby, $filtertext);
1141  $titles =& $this->test_obj->getQuestionTitlesAndIndexes();
1142  $oids =& $this->test_obj->getQuestions();//$this->test_obj->getQuestionOIDsByAID();
1143  asort($oids);
1144 
1145  $positions = array();
1146  $pos = 0;
1147  $row = 0;
1148  foreach ($oids as $aid => $oid)
1149  {
1150  $positions[$oid] = $pos;
1151  $pos++;
1152  }
1153 
1154  $usernames = array();
1155  $participantcount = count($data->getParticipants());
1156 
1157  // fill csv header
1158  $a_csv_header_row=array();
1159  $col = 0;
1160  $a_csv_header_row[$col++]=ilExcelUtils::_convert_text('last_name');
1161  $a_csv_header_row[$col++]=ilExcelUtils::_convert_text('first_name');
1162  $a_csv_header_row[$col++]=ilExcelUtils::_convert_text('Matrikel');
1163  $a_csv_header_row[$col++]=ilExcelUtils::_convert_text('user');
1164  //$a_csv_header_row[$col++]=ilExcelUtils::_convert_text($this->lng->txt('test'));
1165 
1166  foreach ($titles as $aid => $title)
1167  {
1168  $question=$this->test_obj->_instanciateQuestion($aid);
1169  $imsm_id=$question->getExternalID();
1170  $a_csv_header_row[$col+$positions[$aid]]=ilExcelUtils::_convert_text($imsm_id);
1171  }
1172  $a_csv_header_row[count($a_csv_header_row)]=ilExcelUtils::_convert_text('time');
1173 
1174  // fill csv body
1175  $a_csv_data_rows=array();
1176  $a_csv_data_rows[$row++]=$a_csv_header_row;
1177 
1178  foreach ($data->getParticipants() as $active_id => $userdata)
1179  {
1180  $a_csv_row=array();
1181  $col = 0;
1182  /*$tmp_obj = ilObjectFactory::getInstanceByObjId($userdata->user_id);
1183  $a_csv_row[$col++]=$tmp_obj->getLastName();
1184  $a_csv_row[$col++]=$tmp_obj->getFirstName();
1185  $a_csv_row[$col++]=$tmp_obj->getMatriculation();
1186  $a_csv_row[$col++]=$userdata->getLogin();
1187  */
1188  $anon_id=$row;
1189  $a_csv_row[$col++]="lastname_".$anon_id;
1190  $a_csv_row[$col++]="firstname_".$anon_id;
1191  $a_csv_row[$col++]="1111".$anon_id;
1192  $a_csv_row[$col++]="id_".$anon_id;
1193 
1194  //$a_csv_row[$col++]=ilExcelUtils::_convert_text($this->test_obj->getTitle());
1195 
1196  $pass = $userdata->getScoredPass();
1197  if (is_object($userdata) && is_array($userdata->getQuestions($pass)))
1198  {
1199  foreach ($userdata->getQuestions($pass) as $question)
1200  {
1201  $objQuestion =& $this->test_obj->_instanciateQuestion($question["id"]);
1202  $is_sc=strcmp($objQuestion->getQuestionType(), 'assSingleChoice')==0;
1203  $is_mc=strcmp($objQuestion->getQuestionType(), 'assMultipleChoice')==0;
1204  if (is_object($objQuestion) && ($is_sc || $is_mc))
1205  {
1206  $solutions = $objQuestion->getSolutionValues($active_id, $pass);
1207  $answers=array();
1208  for ($i=0;$i<count($solutions);$i++){
1209  $selectedanswer = chr(65+$solutions[$i]["value1"]);
1210  array_push($answers,$selectedanswer);
1211  }
1212  sort($answers);
1213  $pos = $positions[$question["id"]];
1214  $a_csv_row[$col+$pos]=implode($answers,",");
1215  }
1216  }
1217  }
1218  $lv = getdate($data->getParticipant($active_id)->getLastVisit());
1219  $tstamp=mktime($lv['hours'],$lv['minutes'],$lv['seconds'],$lv['mon'],$lv['mday'],$lv['year']);
1220  $lastvisit = date("d.m.Y G:i:s",$tstamp);
1221  $a_csv_row[count($a_csv_row)]=$lastvisit;
1222  ksort($a_csv_row);
1223  $a_csv_data_rows[$row]=$a_csv_row;
1224  $row++;
1225  }
1226 
1227  // write to file
1228  $csv = "";
1229  $separator = ";";
1230  foreach ($a_csv_data_rows as $evalrow)
1231  {
1232  $csvrow =& $this->test_obj->processCSVRow($evalrow, FALSE, $separator);
1233  $csv .= join($csvrow, $separator) . "\n";
1234  }
1235  if ($deliver)
1236  {
1237  ilUtil::deliverData($csv, ilUtil::getASCIIFilename($this->test_obj->getTitle() . "-detailed.csv"));
1238  exit;
1239  }
1240  else
1241  {
1242  return $csv;
1243  }
1244  }
1245 
1246 
1251  {
1252  global $ilBench;
1253 
1254  $ilBench->start("TestExport", "buildExportFile");
1255 
1256  include_once("./Services/Xml/classes/class.ilXmlWriter.php");
1257  $this->xml = new ilXmlWriter;
1258 
1259  // set dtd definition
1260  $this->xml->xmlSetDtdDef("<!DOCTYPE Test SYSTEM \"http://www.ilias.uni-koeln.de/download/dtd/ilias_co.dtd\">");
1261 
1262  // set generated comment
1263  $this->xml->xmlSetGenCmt("Export of ILIAS Test ".
1264  $this->test_obj->getId()." of installation ".$this->inst.".");
1265 
1266  // set xml header
1267  $this->xml->xmlHeader();
1268 
1269  // create directories
1270  $this->test_obj->createExportDirectory();
1271  include_once "./Services/Utilities/classes/class.ilUtil.php";
1272  ilUtil::makeDir($this->export_dir."/".$this->subdir);
1273  ilUtil::makeDir($this->export_dir."/".$this->subdir."/objects");
1274 
1275  // get Log File
1276  $expDir = $this->test_obj->getExportDirectory();
1277  include_once "./Services/Logging/classes/class.ilLog.php";
1278  $expLog = new ilLog($expDir, "export.log");
1279  $expLog->delete();
1280  $expLog->setLogFormat("");
1281  $expLog->write(date("[y-m-d H:i:s] ")."Start Export");
1282 
1283  // write qti file
1284  include_once "./Modules/Test/classes/class.ilTestExportQTI.php";
1285  $exportObject = new ilTestExportQTI($this->test_obj);
1286  $qti_file = fopen($this->export_dir."/".$this->subdir."/".$this->qti_filename, "w");
1287  fwrite($qti_file, $exportObject->toXML());
1288  fclose($qti_file);
1289 
1290  // get xml content
1291  $ilBench->start("TestExport", "buildExportFile_getXML");
1292  $this->test_obj->exportPagesXML($this->xml, $this->inst_id,
1293  $this->export_dir."/".$this->subdir, $expLog);
1294  $ilBench->stop("TestExport", "buildExportFile_getXML");
1295 
1296  // dump xml document to screen (only for debugging reasons)
1297  /*
1298  echo "<PRE>";
1299  echo htmlentities($this->xml->xmlDumpMem($format));
1300  echo "</PRE>";
1301  */
1302 
1303  // dump xml document to file
1304  $ilBench->start("TestExport", "buildExportFile_dumpToFile");
1305  $this->xml->xmlDumpFile($this->export_dir."/".$this->subdir."/".$this->filename
1306  , false);
1307  $ilBench->stop("TestExport", "buildExportFile_dumpToFile");
1308 
1309  // dump results xml document to file
1310  include_once "./Modules/Test/classes/class.ilTestResultsToXML.php";
1311  $resultwriter = new ilTestResultsToXML($this->test_obj->getTestId(), $this->test_obj->getAnonymity());
1312  $ilBench->start("TestExport", "buildExportFile_results");
1313  $resultwriter->xmlDumpFile($this->export_dir."/".$this->subdir."/".$this->resultsfile, false);
1314  $ilBench->stop("TestExport", "buildExportFile_results");
1315 
1316  // add media objects which were added with tiny mce
1317  $ilBench->start("QuestionpoolExport", "buildExportFile_saveAdditionalMobs");
1318  $this->exportXHTMLMediaObjects($this->export_dir."/".$this->subdir);
1319  $ilBench->stop("QuestionpoolExport", "buildExportFile_saveAdditionalMobs");
1320 
1321  // zip the file
1322  $ilBench->start("TestExport", "buildExportFile_zipFile");
1323  ilUtil::zip($this->export_dir."/".$this->subdir,
1324  $this->export_dir."/".$this->subdir.".zip");
1325  $ilBench->stop("TestExport", "buildExportFile_zipFile");
1326 
1327  // destroy writer object
1328  $this->xml->_XmlWriter;
1329 
1330  $expLog->write(date("[y-m-d H:i:s] ")."Finished Export");
1331  $ilBench->stop("TestExport", "buildExportFile");
1332 
1333  return $this->export_dir."/".$this->subdir.".zip";
1334  }
1335 
1336  function exportXHTMLMediaObjects($a_export_dir)
1337  {
1338  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
1339 
1340  $mobs = ilObjMediaObject::_getMobsOfObject("tst:html", $this->test_obj->getId());
1341  foreach ($mobs as $mob)
1342  {
1343  if (ilObjMediaObject::_exists($mob))
1344  {
1345  $mob_obj =& new ilObjMediaObject($mob);
1346  $mob_obj->exportFiles($a_export_dir);
1347  unset($mob_obj);
1348  }
1349  }
1350  foreach ($this->test_obj->questions as $question_id)
1351  {
1352  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $question_id);
1353  foreach ($mobs as $mob)
1354  {
1355  if (ilObjMediaObject::_exists($mob))
1356  {
1357  $mob_obj =& new ilObjMediaObject($mob);
1358  $mob_obj->exportFiles($a_export_dir);
1359  unset($mob_obj);
1360  }
1361  }
1362  }
1363  }
1364 
1365  public function singleChoiceExport($adapter = null, $deliver = true, $filterby = "", $filtertext = "", $passedonly = FALSE)
1366  {
1367  global $ilLog;
1368  include_once "./Services/Excel/classes/class.ilExcelUtils.php";
1369  if ($adapter == null)
1370  {
1371  $adapter = ilExcelUtils::ExcelAdapter();
1372  $adapter->setWorksheetTitle($this->lng->txt("export_result_overview"));
1373  }
1374  else
1375  {
1376  $adapter->addWorksheet($this->lng->txt("export_result_overview"));
1377  $adapter->setActiveWorksheet($adapter->getWorksheetCount()-1);
1378  }
1379  include_once "./Modules/Test/classes/class.ilTestEvaluationData.php";
1380  $data = new ilTestEvaluationData($this->test_obj);
1381  $data->calculateStatistics();
1382  $data->setFilter($filterby, $filtertext);
1383 
1384  $ilLog->write("Export Single Choice Results");
1385  // special tab for single choice tests
1386  $titles =& $this->test_obj->getQuestionTitlesAndIndexes();
1387  $positions = array();
1388  $pos = 0;
1389  $row = 0;
1390  foreach ($titles as $id => $title)
1391  {
1392  $positions[$id] = $pos;
1393  $pos++;
1394  }
1395 
1396  $usernames = array();
1397  $participantcount = count($data->getParticipants());
1398  $allusersheet = false;
1399  $pages = 0;
1400 
1401  $col = 0;
1402  $adapter->setCellValue($row, $col++, $this->lng->txt('name'), CELL_FORMAT_TITLE);
1403  $adapter->setCellValue($row, $col++, $this->lng->txt('login'), CELL_FORMAT_TITLE);
1404  if (count($additionalFields))
1405  {
1406  foreach ($additionalFields as $fieldname)
1407  {
1408  if (strcmp($fieldname, "matriculation") == 0)
1409  {
1410  $adapter->setCellValue($row, $col++, $this->lng->txt('matriculation'), CELL_FORMAT_TITLE);
1411  }
1412  }
1413  }
1414  $adapter->setCellValue($row, $col++, $this->lng->txt('test'), CELL_FORMAT_TITLE);
1415  foreach ($titles as $aid => $title)
1416  {
1417  $adapter->setCellValue($row, $col+$positions[$aid], "[". $aid . "] " . $title, CELL_FORMAT_TITLE);
1418  }
1419  $row++;
1420 
1421  $maxcol = $col;
1422  $rangefrom = 1;
1423  $rangeto = $participantcount;
1424  $rangecounter = 1;
1425  foreach ($data->getParticipants() as $active_id => $userdata)
1426  {
1427  if ($rangecounter >= $rangefrom && $rangecounter <= $rangeto)
1428  {
1429  $data->getCompleteDataForParticipant($active_id); // do this by participant, otherwise memory usage is horrible for large tests and participants
1430  $username = (!is_null($userdata) && ilExcelUtils::_convert_text($userdata->getName())) ? ilExcelUtils::_convert_text($userdata->getName()) : "ID $active_id";
1431  if (array_key_exists($username, $usernames))
1432  {
1433  $usernames[$username]++;
1434  $username .= " ($i)";
1435  }
1436  else
1437  {
1438  $usernames[$username] = 1;
1439  }
1440  $col = 0;
1441  //$ilLog->write($row . ". " . $data->getParticipant($active_id)->getName());
1442  $adapter->setCellValue($row, $col++, $username);
1443  $adapter->setCellValue($row, $col++, $userdata->getLogin());
1444  if (count($additionalFields))
1445  {
1446  $userfields = ilObjUser::_lookupFields($userdata->getUserID());
1447  foreach ($additionalFields as $fieldname)
1448  {
1449  if (strcmp($fieldname, "matriculation") == 0)
1450  {
1451  if (strlen($userfields[$fieldname]))
1452  {
1453  $adapter->setCellValue($row, $col++, $userfields[$fieldname]);
1454  }
1455  else
1456  {
1457  $col++;
1458  }
1459  }
1460  }
1461  }
1462  $adapter->setCellValue($row, $col++, $this->test_obj->getTitle());
1463  $pass = $userdata->getScoredPass();
1464  include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
1465  include_once "./Modules/TestQuestionPool/classes/class.assSingleChoice.php";
1466  if (is_object($userdata) && is_array($userdata->getQuestions($pass)))
1467  {
1468  foreach ($userdata->getQuestions($pass) as $question)
1469  {
1470  $solution = assQuestion::_getSolutionValues($active_id, $question["id"], $pass);
1471  $answers = assSingleChoice::_getAnswerTexts($question["id"]);
1472  $pos = $positions[$question["id"]];
1473  $selectedanswer = "x";
1474  foreach ($answers as $id => $answer)
1475  {
1476  if (strlen($solution[0]["value1"]) && $id == $solution[0]["value1"])
1477  {
1478  $selectedanswer = $answer;
1479  break;
1480  }
1481  }
1482  $adapter->setCellValue($row, $col+$pos, $selectedanswer);
1483  if ($col+$pos > $maxcol) $maxcol = $col+$pos;
1484  }
1485  }
1486  $row++;
1487  $data->getParticipant($active_id)->unsetPasses();
1488  $data->getParticipant($active_id)->unsetQuestions();
1489  }
1490  $rangecounter++;
1491  }
1492 
1493  for ($colnr = 0; $colnr <= $maxcol; $colnr++)
1494  {
1495  $adapter->setColumnWidth($colnr, 'auto');
1496  }
1497  if ($this->test_obj->isSingleChoiceTestWithoutShuffle())
1498  {
1499  $ilLog->write("Export Compact Single Choice Results");
1500  $data = new ilTestEvaluationData($this->test_obj);
1501  // special tab for single choice tests without shuffle option
1502  $pos = 0;
1503  $row = 0;
1504  $usernames = array();
1505  $allusersheet = false;
1506  $pages = 0;
1507  $adapter->addWorksheet($this->lng->txt("export_result_overview") . " (2)");
1508  $adapter->setActiveWorksheet($adapter->getWorksheetCount()-1);
1509 
1510  $col = 0;
1511  $adapter->setCellValue($row, $col++, $this->lng->txt('name'), CELL_FORMAT_TITLE);
1512  $adapter->setCellValue($row, $col++, $this->lng->txt('login'), CELL_FORMAT_TITLE);
1513  if (count($additionalFields))
1514  {
1515  foreach ($additionalFields as $fieldname)
1516  {
1517  if (strcmp($fieldname, "matriculation") == 0)
1518  {
1519  $adapter->setCellValue($row, $col++, $this->lng->txt('matriculation'), CELL_FORMAT_TITLE);
1520  }
1521  }
1522  }
1523  $adapter->setCellValue($row, $col++, $this->lng->txt('test'), CELL_FORMAT_TITLE);
1524  foreach ($titles as $aid => $title)
1525  { // M.W.
1526  $adapter->setCellValue($row, $col+$positions[$aid], "[". $aid . "] " . $title, CELL_FORMAT_TITLE);
1527  }
1528  $row++;
1529 
1530  $maxcol = $col;
1531  $rangecounter = 1;
1532  foreach ($data->getParticipants() as $active_id => $userdata)
1533  {
1534  if ($rangecounter >= $rangefrom && $rangecounter <= $rangeto)
1535  {
1536  $data->getCompleteDataForParticipant($active_id); // do this by participant, otherwise memory usage is horrible for large tests and participants
1537  $username = (!is_null($userdata) && ilExcelUtils::_convert_text($userdata->getName())) ? ilExcelUtils::_convert_text($userdata->getName()) : "ID $active_id";
1538  if (array_key_exists($username, $usernames))
1539  {
1540  $usernames[$username]++;
1541  $username .= " ($i)";
1542  }
1543  else
1544  {
1545  $usernames[$username] = 1;
1546  }
1547  $col = 0;
1548  //$ilLog->write($row . ". " . $data->getParticipant($active_id)->getName());
1549  $adapter->setCellValue($row, $col++, $username);
1550  $adapter->setCellValue($row, $col++, $userdata->getLogin());
1551  if (count($additionalFields))
1552  {
1553  $userfields = ilObjUser::_lookupFields($userdata->getUserID());
1554  foreach ($additionalFields as $fieldname)
1555  {
1556  if (strcmp($fieldname, "matriculation") == 0)
1557  {
1558  if (strlen($userfields[$fieldname]))
1559  {
1560  $adapter->setCellValue($row, $col++, $userfields[$fieldname]);
1561  }
1562  else
1563  {
1564  $col++;
1565  }
1566  }
1567  }
1568  }
1569  $adapter->setCellValue($row, $col++, $this->test_obj->getTitle());
1570  $pass = $userdata->getScoredPass();
1571  if (is_object($userdata) && is_array($userdata->getQuestions($pass)))
1572  {
1573  foreach ($userdata->getQuestions($pass) as $question)
1574  {
1575  $solution = assQuestion::_getSolutionValues($active_id, $question["id"], $pass);
1576  $pos = $positions[$question["id"]];
1577  if (strlen($solution[0]["value1"]))
1578  {
1579  $selectedanswer = chr(65+$solution[0]["value1"]);
1580  }
1581  else
1582  {
1583  $selectedanswer = 'x';
1584  }
1585  $adapter->setCellValue($row, $col+$pos, $selectedanswer);
1586  if ($col+$pos > $maxcol) $maxcol = $col+$pos;
1587  }
1588  }
1589  $row++;
1590  $data->getParticipant($active_id)->unsetPasses();
1591  $data->getParticipant($active_id)->unsetQuestions();
1592  }
1593  $rangecounter++;
1594  }
1595 
1596  for ($colnr = 0; $colnr <= $maxcol; $colnr++)
1597  {
1598  $adapter->setColumnWidth($colnr, 'auto');
1599  }
1600  }
1601  if ($deliver)
1602  {
1603  $outputfilename = ilUtil::getASCIIFilename(preg_replace("/\s/", "_", $this->test_obj->getTitle())) . "-singlechoice." . $adapter->getFileExtension();
1604  $adapter->deliver($outputfilename);
1605  exit;
1606  }
1607  }
1608 }
1609 
1610 ?>