ILIAS  release_4-3 Revision
 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 include_once "Services/Utilities/classes/class.ilFormat.php";
26 
36 {
37  var $err; // error object
38  var $db; // database object
39  var $ilias; // ilias object
40  var $test_obj; // test object
41  var $inst_id; // installation id
42  var $mode;
43  private $lng;
44  private $resultsfile;
45 
50  function ilTestExport(&$a_test_obj, $a_mode = "xml")
51  {
52  global $ilErr, $ilDB, $ilias, $lng;
53 
54  $this->test_obj =& $a_test_obj;
55 
56  $this->err =& $ilErr;
57  $this->ilias =& $ilias;
58  $this->db =& $ilDB;
59  $this->mode = $a_mode;
60  $this->lng =& $lng;
61 
62  $settings = $this->ilias->getAllSettings();
63  $this->inst_id = IL_INST_ID;
64 
65  $date = time();
66  $this->export_dir = $this->test_obj->getExportDirectory();
67  switch($this->mode)
68  {
69  case "results":
70  $this->subdir = $date."__".$this->inst_id."__".
71  "tst__results_".$this->test_obj->getId();
72  break;
73  case "aggregated":
74  $this->subdir = $date."__".$this->inst_id."__".
75  "test__aggregated__results_".$this->test_obj->getId();
76  break;
77  default:
78  $this->subdir = $date."__".$this->inst_id."__".
79  "tst"."_".$this->test_obj->getId();
80  $this->filename = $this->subdir.".xml";
81  $this->resultsfile = $date."__".$this->inst_id."__".
82  "results"."_".$this->test_obj->getId().".xml";
83  $this->qti_filename = $date."__".$this->inst_id."__".
84  "qti"."_".$this->test_obj->getId().".xml";
85  break;
86  }
87  $this->filename = $this->subdir.".".$this->getExtension();
88  }
89 
90  function getExtension () {
91  switch ($this->mode) {
92  case "results":
93  return "csv"; break;
94  default:
95  return "xml"; break;
96  }
97  }
98 
99  function getInstId()
100  {
101  return $this->inst_id;
102  }
103 
104 
111  function buildExportFile()
112  {
113  switch ($this->mode)
114  {
115  case "results":
116  return $this->buildExportResultFile();
117  break;
118  default:
119  return $this->buildExportFileXML();
120  break;
121  }
122  }
123 
128  {
129  global $ilBench;
130  global $log;
131 
132  //get Log File
133  $expDir = $this->test_obj->getExportDirectory();
134 
135  // make_directories
136  $this->test_obj->createExportDirectory();
137  include_once "./Services/Utilities/classes/class.ilUtil.php";
138  ilUtil::makeDir($this->export_dir);
139 
140  $expLog = new ilLog($expDir, "export.log");
141  $expLog->delete();
142  $expLog->setLogFormat("");
143  $expLog->write(date("[y-m-d H:i:s] ")."Start Export Of Results");
144 
145  $data = $this->exportToCSV($deliver = FALSE);
146  $file = fopen($this->export_dir."/".$this->filename, "w");
147  fwrite($file, $data);
148  fclose($file);
149 
150  $excelfile = $this->exportToExcel($deliver = FALSE);
151  @copy($excelfile, $this->export_dir . "/" . str_replace($this->getExtension(), "xls", $this->filename));
152  @unlink($excelfile);
153  // end
154  $expLog->write(date("[y-m-d H:i:s] ")."Finished Export of Results");
155 
156  return $this->export_dir."/".$this->filename;
157  }
158 
164  protected function aggregatedResultsToExcel($deliver = TRUE)
165  {
166  $data = $this->test_obj->getAggregatedResultsData();
167  include_once "./Services/Excel/classes/class.ilExcelWriterAdapter.php";
168  $excelfile = ilUtil::ilTempnam();
169  $adapter = new ilExcelWriterAdapter($excelfile, FALSE);
170  $testname = ilUtil::getASCIIFilename(preg_replace("/\s/", "_", $this->test_obj->getTitle() . '_aggregated')) . ".xls";
171  $workbook = $adapter->getWorkbook();
172  $workbook->setVersion(8); // Use Excel97/2000 Format
173  // Creating a worksheet
174  $format_percent =& $workbook->addFormat();
175  $format_percent->setNumFormat("0.00%");
176  $format_title =& $workbook->addFormat();
177  $format_title->setBold();
178  $format_title->setColor('black');
179  $format_title->setPattern(1);
180  $format_title->setFgColor('silver');
181  include_once "./Services/Excel/classes/class.ilExcelUtils.php";
182  $worksheet =& $workbook->addWorksheet(ilExcelUtils::_convert_text($this->lng->txt("tst_results_aggregated")));
183  $row = 0;
184  $col = 0;
185  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("result")), $format_title);
186  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("value")), $format_title);
187  $row++;
188  foreach ($data["overview"] as $key => $value)
189  {
190  $col = 0;
191  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($key));
192  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($value));
193  $row++;
194  }
195  $row++;
196  $col = 0;
197  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("question_title")), $format_title);
198  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("average_reached_points")), $format_title);
199  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("points")), $format_title);
200  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("percentage")), $format_title);
201  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("number_of_answers")), $format_title);
202  $row++;
203  foreach ($data["questions"] as $key => $value)
204  {
205  $col = 0;
206  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($value[0]));
207  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($value[4]));
208  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($value[5]));
209  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($value[6]), $format_percent);
210  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($value[3]));
211  $row++;
212  }
213  $workbook->close();
214  if ($deliver)
215  {
216  ilUtil::deliverFile($excelfile, $testname, "application/vnd.ms-excel", false, true);
217  exit;
218  }
219  else
220  {
221  return $excelfile;
222  }
223  }
224 
230  protected function aggregatedResultsToCSV($deliver = TRUE)
231  {
232  $data = $this->test_obj->getAggregatedResultsData();
233  $rows = array();
234  array_push($rows, array(
235  $this->lng->txt("result"),
236  $this->lng->txt("value")
237  ));
238  foreach ($data["overview"] as $key => $value)
239  {
240  array_push($rows, array(
241  $key,
242  $value
243  ));
244  }
245  array_push($rows, array(
246  $this->lng->txt("question_title"),
247  $this->lng->txt("average_reached_points"),
248  $this->lng->txt("points"),
249  $this->lng->txt("percentage"),
250  $this->lng->txt("number_of_answers")
251  ));
252  foreach ($data["questions"] as $key => $value)
253  {
254  array_push($rows, array(
255  $value[0],
256  $value[4],
257  $value[5],
258  $value[6],
259  $value[3]
260  ));
261  }
262  $csv = "";
263  $separator = ";";
264  foreach ($rows as $evalrow)
265  {
266  $csvrow =& $this->test_obj->processCSVRow($evalrow, TRUE, $separator);
267  $csv .= join($csvrow, $separator) . "\n";
268  }
269  if ($deliver)
270  {
271  ilUtil::deliverData($csv, ilUtil::getASCIIFilename($this->test_obj->getTitle() . "_aggregated.csv"));
272  exit;
273  }
274  else
275  {
276  return $csv;
277  }
278  }
279 
287  function exportToExcel($deliver = TRUE, $filterby = "", $filtertext = "", $passedonly = FALSE)
288  {
289  global $ilLog;
290 
291  if (strcmp($this->mode, "aggregated") == 0) return $this->aggregatedResultsToExcel($deliver);
292 
293  include_once "./Services/Excel/classes/class.ilExcelWriterAdapter.php";
294  $excelfile = ilUtil::ilTempnam();
295  $adapter = new ilExcelWriterAdapter($excelfile, FALSE);
296  $testname = $this->test_obj->getTitle();
297  switch($this->mode)
298  {
299  case 'results':
300  $testname .= '_results';
301  break;
302  }
303  $testname = ilUtil::getASCIIFilename(preg_replace("/\s/", "_", $testname)) . ".xls";
304  $workbook = $adapter->getWorkbook();
305  $workbook->setVersion(8); // Use Excel97/2000 Format
306  // Creating a worksheet
307  $format_bold =& $workbook->addFormat();
308  $format_bold->setBold();
309  $format_percent =& $workbook->addFormat();
310  $format_percent->setNumFormat("0.00%");
311  $format_datetime =& $workbook->addFormat();
312  $format_datetime->setNumFormat("DD/MM/YYYY hh:mm:ss");
313  $format_title =& $workbook->addFormat();
314  $format_title->setBold();
315  $format_title->setColor('black');
316  $format_title->setPattern(1);
317  $format_title->setFgColor('silver');
318  include_once "./Services/Excel/classes/class.ilExcelUtils.php";
319  $worksheet =& $workbook->addWorksheet(ilExcelUtils::_convert_text($this->lng->txt("tst_results")));
320  $additionalFields = $this->test_obj->getEvaluationAdditionalFields();
321  $row = 0;
322  $col = 0;
323 
324  if ($this->test_obj->getAnonymity())
325  {
326  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("counter")), $format_title);
327  }
328  else
329  {
330  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("name")), $format_title);
331  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("login")), $format_title);
332  }
333  if (count($additionalFields))
334  {
335  foreach ($additionalFields as $fieldname)
336  {
337  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt($fieldname)), $format_title);
338  }
339  }
340  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("tst_stat_result_resultspoints")), $format_title);
341  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("maximum_points")), $format_title);
342  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("tst_stat_result_resultsmarks")), $format_title);
343  if ($this->test_obj->ects_output)
344  {
345  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("ects_grade")), $format_title);
346  }
347  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("tst_stat_result_qworkedthrough")), $format_title);
348  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("tst_stat_result_qmax")), $format_title);
349  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("tst_stat_result_pworkedthrough")), $format_title);
350  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("tst_stat_result_timeofwork")), $format_title);
351  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("tst_stat_result_atimeofwork")), $format_title);
352  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("tst_stat_result_firstvisit")), $format_title);
353  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("tst_stat_result_lastvisit")), $format_title);
354 
355  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("tst_stat_result_mark_median")), $format_title);
356  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("tst_stat_result_rank_participant")), $format_title);
357  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("tst_stat_result_rank_median")), $format_title);
358  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("tst_stat_result_total_participants")), $format_title);
359  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("tst_stat_result_median")), $format_title);
360  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("scored_pass")), $format_title);
361 
362  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("pass")), $format_title);
363 
364  include_once "./Services/Excel/classes/class.ilExcelUtils.php";
365  $counter = 1;
366  $data =& $this->test_obj->getCompleteEvaluationData(TRUE, $filterby, $filtertext);
367  $firstrowwritten = false;
368  foreach ($data->getParticipants() as $active_id => $userdata)
369  {
370  $remove = FALSE;
371  if ($passedonly)
372  {
373  if ($data->getParticipant($active_id)->getPassed() == FALSE)
374  {
375  $remove = TRUE;
376  }
377  }
378  if (!$remove)
379  {
380  $row++;
381  if ($this->test_obj->isRandomTest() || $this->test_obj->getShuffleQuestions())
382  {
383  $row++;
384  }
385  $col = 0;
386  if ($this->test_obj->getAnonymity())
387  {
388  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($counter));
389  }
390  else
391  {
392  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($data->getParticipant($active_id)->getName()));
393  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($data->getParticipant($active_id)->getLogin()));
394  }
395  if (count($additionalFields))
396  {
397  $userfields = ilObjUser::_lookupFields($userdata->getUserID());
398  foreach ($additionalFields as $fieldname)
399  {
400  if (strcmp($fieldname, "gender") == 0)
401  {
402  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt("gender_" . $userfields[$fieldname])));
403  }
404  else
405  {
406  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($userfields[$fieldname]));
407  }
408  }
409  }
410  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($data->getParticipant($active_id)->getReached()));
411  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($data->getParticipant($active_id)->getMaxpoints()));
412  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($data->getParticipant($active_id)->getMark()));
413  if ($this->test_obj->ects_output)
414  {
415  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($data->getParticipant($active_id)->getECTSMark()));
416  }
417  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($data->getParticipant($active_id)->getQuestionsWorkedThrough()));
418  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($data->getParticipant($active_id)->getNumberOfQuestions()));
419  $worksheet->write($row, $col++, $data->getParticipant($active_id)->getQuestionsWorkedThroughInPercent() / 100.0, $format_percent);
420  $time = $data->getParticipant($active_id)->getTimeOfWork();
421  $time_seconds = $time;
422  $time_hours = floor($time_seconds/3600);
423  $time_seconds -= $time_hours * 3600;
424  $time_minutes = floor($time_seconds/60);
425  $time_seconds -= $time_minutes * 60;
426  $worksheet->write($row, $col++, ilExcelUtils::_convert_text(sprintf("%02d:%02d:%02d", $time_hours, $time_minutes, $time_seconds)));
427  $time = $data->getParticipant($active_id)->getQuestionsWorkedThrough() ? $data->getParticipant($active_id)->getTimeOfWork() / $data->getParticipant($active_id)->getQuestionsWorkedThrough() : 0;
428  $time_seconds = $time;
429  $time_hours = floor($time_seconds/3600);
430  $time_seconds -= $time_hours * 3600;
431  $time_minutes = floor($time_seconds/60);
432  $time_seconds -= $time_minutes * 60;
433  $worksheet->write($row, $col++, ilExcelUtils::_convert_text(sprintf("%02d:%02d:%02d", $time_hours, $time_minutes, $time_seconds)));
434  $fv = getdate($data->getParticipant($active_id)->getFirstVisit());
435  $firstvisit = ilUtil::excelTime(
436  $fv["year"],
437  $fv["mon"],
438  $fv["mday"],
439  $fv["hours"],
440  $fv["minutes"],
441  $fv["seconds"]
442  );
443  $worksheet->write($row, $col++, $firstvisit, $format_datetime);
444  $lv = getdate($data->getParticipant($active_id)->getLastVisit());
445  $lastvisit = ilUtil::excelTime(
446  $lv["year"],
447  $lv["mon"],
448  $lv["mday"],
449  $lv["hours"],
450  $lv["minutes"],
451  $lv["seconds"]
452  );
453  $worksheet->write($row, $col++, $lastvisit, $format_datetime);
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  if (is_object($mark))
460  {
461  $mark_short_name = $mark->getShortName();
462  }
463  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($mark_short_name));
464  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($data->getStatistics()->getStatistics()->rank($data->getParticipant($active_id)->getReached())));
465  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($data->getStatistics()->getStatistics()->rank_median()));
466  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($data->getStatistics()->getStatistics()->count()));
467  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($median));
468  if ($this->test_obj->getPassScoring() == SCORE_BEST_PASS)
469  {
470  $worksheet->write($row, $col++, $data->getParticipant($active_id)->getBestPass() + 1);
471  }
472  else
473  {
474  $worksheet->write($row, $col++, $data->getParticipant($active_id)->getLastPass() + 1);
475  }
476  $startcol = $col;
477  for ($pass = 0; $pass <= $data->getParticipant($active_id)->getLastPass(); $pass++)
478  {
479  $col = $startcol;
480  $finishdate = $this->test_obj->getPassFinishDate($active_id, $pass);
481  if ($finishdate > 0)
482  {
483  if ($pass > 0)
484  {
485  $row++;
486  if ($this->test_obj->isRandomTest() || $this->test_obj->getShuffleQuestions())
487  {
488  $row++;
489  }
490  }
491  $worksheet->write($row, $col++, ilExcelUtils::_convert_text($pass+1));
492  if (is_object($data->getParticipant($active_id)) && is_array($data->getParticipant($active_id)->getQuestions($pass)))
493  {
494  foreach ($data->getParticipant($active_id)->getQuestions($pass) as $question)
495  {
496  $question_data = $data->getParticipant($active_id)->getPass($pass)->getAnsweredQuestionByQuestionId($question["id"]);
497  $worksheet->write($row, $col, ilExcelUtils::_convert_text($question_data["reached"]));
498  if ($this->test_obj->isRandomTest() || $this->test_obj->getShuffleQuestions())
499  {
500  $worksheet->write($row-1, $col, ilExcelUtils::_convert_text(preg_replace("/<.*?>/", "", $data->getQuestionTitle($question["id"]))), $format_title);
501  }
502  else
503  {
504  if ($pass == 0 && !$firstrowwritten)
505  {
506  $worksheet->write(0, $col, ilExcelUtils::_convert_text(preg_replace("/<.*?>/", "", $data->getQuestionTitle($question["id"]))), $format_title);
507  }
508  }
509  $col++;
510  }
511  $firstrowwritten = true;
512  }
513  }
514  }
515  $counter++;
516  }
517  }
518  if ($this->test_obj->getExportSettingsSingleChoiceShort() && !$this->test_obj->isRandomTest() && $this->test_obj->hasSingleChoiceQuestions())
519  {
520  // special tab for single choice tests
521  $titles =& $this->test_obj->getQuestionTitlesAndIndexes();
522  $positions = array();
523  $pos = 0;
524  $row = 0;
525  foreach ($titles as $id => $title)
526  {
527  $positions[$id] = $pos;
528  $pos++;
529  }
530  $usernames = array();
531  $participantcount = count($data->getParticipants());
532  $allusersheet = false;
533  $pages = 0;
534  $resultsheet =& $workbook->addWorksheet($this->lng->txt("eval_all_users"));
535 
536  $col = 0;
537  $resultsheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt('name')), $format_title);
538  $resultsheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt('login')), $format_title);
539  if (count($additionalFields))
540  {
541  foreach ($additionalFields as $fieldname)
542  {
543  if (strcmp($fieldname, "matriculation") == 0)
544  {
545  $resultsheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt('matriculation')), $format_title);
546  }
547  }
548  }
549  $resultsheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt('test')), $format_title);
550  foreach ($titles as $title)
551  {
552  $resultsheet->write($row, $col++, ilExcelUtils::_convert_text($title), $format_title);
553  }
554  $row++;
555 
556  foreach ($data->getParticipants() as $active_id => $userdata)
557  {
558  $username = (!is_null($userdata) && ilExcelUtils::_convert_text($userdata->getName())) ? ilExcelUtils::_convert_text($userdata->getName()) : "ID $active_id";
559  if (array_key_exists($username, $usernames))
560  {
561  $usernames[$username]++;
562  $username .= " ($i)";
563  }
564  else
565  {
566  $usernames[$username] = 1;
567  }
568  $col = 0;
569  $resultsheet->write($row, $col++, $username);
570  $resultsheet->write($row, $col++, $userdata->getLogin());
571  if (count($additionalFields))
572  {
573  $userfields = ilObjUser::_lookupFields($userdata->getUserID());
574  foreach ($additionalFields as $fieldname)
575  {
576  if (strcmp($fieldname, "matriculation") == 0)
577  {
578  if (strlen($userfields[$fieldname]))
579  {
580  $resultsheet->write($row, $col++, ilExcelUtils::_convert_text($userfields[$fieldname]));
581  }
582  else
583  {
584  $col++;
585  }
586  }
587  }
588  }
589  $resultsheet->write($row, $col++, ilExcelUtils::_convert_text($this->test_obj->getTitle()));
590  $pass = $userdata->getScoredPass();
591  if (is_object($userdata) && is_array($userdata->getQuestions($pass)))
592  {
593  foreach ($userdata->getQuestions($pass) as $question)
594  {
595  $objQuestion =& $this->test_obj->_instanciateQuestion($question["aid"]);
596  if (is_object($objQuestion) && strcmp($objQuestion->getQuestionType(), 'assSingleChoice') == 0)
597  {
598  $solution = $objQuestion->getSolutionValues($active_id, $pass);
599  $pos = $positions[$question["aid"]];
600  $selectedanswer = "x";
601  foreach ($objQuestion->getAnswers() as $id => $answer)
602  {
603  if (strlen($solution[0]["value1"]) && $id == $solution[0]["value1"])
604  {
605  $selectedanswer = $answer->getAnswertext();
606  }
607  }
608  $resultsheet->write($row, $col+$pos, ilExcelUtils::_convert_text($selectedanswer));
609  }
610  }
611  }
612  $row++;
613  }
614  if ($this->test_obj->isSingleChoiceTestWithoutShuffle())
615  {
616  // special tab for single choice tests without shuffle option
617  $pos = 0;
618  $row = 0;
619  $usernames = array();
620  $allusersheet = false;
621  $pages = 0;
622  $resultsheet =& $workbook->addWorksheet($this->lng->txt("eval_all_users") . " (2)");
623 
624  $col = 0;
625  $resultsheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt('name')), $format_title);
626  $resultsheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt('login')), $format_title);
627  if (count($additionalFields))
628  {
629  foreach ($additionalFields as $fieldname)
630  {
631  if (strcmp($fieldname, "matriculation") == 0)
632  {
633  $resultsheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt('matriculation')), $format_title);
634  }
635  }
636  }
637  $resultsheet->write($row, $col++, ilExcelUtils::_convert_text($this->lng->txt('test')), $format_title);
638  foreach ($titles as $title)
639  {
640  $resultsheet->write($row, $col++, ilExcelUtils::_convert_text($title), $format_title);
641  }
642  $row++;
643 
644  foreach ($data->getParticipants() as $active_id => $userdata)
645  {
646  $username = (!is_null($userdata) && ilExcelUtils::_convert_text($userdata->getName())) ? ilExcelUtils::_convert_text($userdata->getName()) : "ID $active_id";
647  if (array_key_exists($username, $usernames))
648  {
649  $usernames[$username]++;
650  $username .= " ($i)";
651  }
652  else
653  {
654  $usernames[$username] = 1;
655  }
656  $col = 0;
657  $resultsheet->write($row, $col++, $username);
658  $resultsheet->write($row, $col++, $userdata->getLogin());
659  if (count($additionalFields))
660  {
661  $userfields = ilObjUser::_lookupFields($userdata->getUserID());
662  foreach ($additionalFields as $fieldname)
663  {
664  if (strcmp($fieldname, "matriculation") == 0)
665  {
666  if (strlen($userfields[$fieldname]))
667  {
668  $resultsheet->write($row, $col++, ilExcelUtils::_convert_text($userfields[$fieldname]));
669  }
670  else
671  {
672  $col++;
673  }
674  }
675  }
676  }
677  $resultsheet->write($row, $col++, ilExcelUtils::_convert_text($this->test_obj->getTitle()));
678  $pass = $userdata->getScoredPass();
679  if (is_object($userdata) && is_array($userdata->getQuestions($pass)))
680  {
681  foreach ($userdata->getQuestions($pass) as $question)
682  {
683  $objQuestion =& $this->test_obj->_instanciateQuestion($question["aid"]);
684  if (is_object($objQuestion) && strcmp($objQuestion->getQuestionType(), 'assSingleChoice') == 0)
685  {
686  $solution = $objQuestion->getSolutionValues($active_id, $pass);
687  $pos = $positions[$question["aid"]];
688  $selectedanswer = chr(65+$solution[0]["value1"]);
689  $resultsheet->write($row, $col+$pos, ilExcelUtils::_convert_text($selectedanswer));
690  }
691  }
692  }
693  $row++;
694  }
695  }
696  }
697  else
698  {
699  // test participant result export
700  $usernames = array();
701  $participantcount = count($data->getParticipants());
702  $allusersheet = false;
703  $pages = 0;
704  $i = 0;
705  foreach ($data->getParticipants() as $active_id => $userdata)
706  {
707  $i++;
708 
709  $username = (!is_null($userdata) && ilExcelUtils::_convert_text($userdata->getName())) ? ilExcelUtils::_convert_text($userdata->getName()) : "ID $active_id";
710  if (array_key_exists($username, $usernames))
711  {
712  $usernames[$username]++;
713  $username .= " ($i)";
714  }
715  else
716  {
717  $usernames[$username] = 1;
718  }
719  if ($participantcount > 250) {
720  if (!$allusersheet || ($pages-1) < floor($row / 64000)) {
721  $resultsheet =& $workbook->addWorksheet($this->lng->txt("eval_all_users") . (($pages > 0) ? " (".($pages+1).")" : ""));
722  $allusersheet = true;
723  $row = 0;
724  $pages++;
725  }
726  } else {
727  $resultsheet =& $workbook->addWorksheet(utf8_decode($username));
728  }
729  if (method_exists($resultsheet, "writeString"))
730  {
731  $pass = $userdata->getScoredPass();
732  $row = ($allusersheet) ? $row : 0;
733  $resultsheet->writeString($row, 0, ilExcelUtils::_convert_text(sprintf($this->lng->txt("tst_result_user_name_pass"), $pass+1, $userdata->getName())), $format_bold);
734  $row += 2;
735  if (is_object($userdata) && is_array($userdata->getQuestions($pass)))
736  {
737  foreach ($userdata->getQuestions($pass) as $question)
738  {
739  $question =& $this->test_obj->_instanciateQuestion($question["id"]);
740  if (is_object($question))
741  {
742  $row = $question->setExportDetailsXLS($resultsheet, $row, $active_id, $pass, $format_title, $format_bold);
743  }
744  }
745  }
746  }
747  }
748  }
749  $workbook->close();
750  if ($deliver)
751  {
752  ilUtil::deliverFile($excelfile, $testname, "application/vnd.ms-excel", false, true);
753  exit;
754  }
755  else
756  {
757  return $excelfile;
758  }
759  }
760 
770  function exportToCSV($deliver = TRUE, $filterby = "", $filtertext = "", $passedonly = FALSE)
771  {
772  global $ilLog;
773 
774  if (strcmp($this->mode, "aggregated") == 0) return $this->aggregatedResultsToCSV($deliver);
775 
776  $rows = array();
777  $datarow = array();
778  $col = 1;
779  if ($this->test_obj->getAnonymity())
780  {
781  array_push($datarow, $this->lng->txt("counter"));
782  $col++;
783  }
784  else
785  {
786  array_push($datarow, $this->lng->txt("name"));
787  $col++;
788  array_push($datarow, $this->lng->txt("login"));
789  $col++;
790  }
791  $additionalFields = $this->test_obj->getEvaluationAdditionalFields();
792  if (count($additionalFields))
793  {
794  foreach ($additionalFields as $fieldname)
795  {
796  array_push($datarow, $this->lng->txt($fieldname));
797  $col++;
798  }
799  }
800  array_push($datarow, $this->lng->txt("tst_stat_result_resultspoints"));
801  $col++;
802  array_push($datarow, $this->lng->txt("maximum_points"));
803  $col++;
804  array_push($datarow, $this->lng->txt("tst_stat_result_resultsmarks"));
805  $col++;
806  if ($this->test_obj->ects_output)
807  {
808  array_push($datarow, $this->lng->txt("ects_grade"));
809  $col++;
810  }
811  array_push($datarow, $this->lng->txt("tst_stat_result_qworkedthrough"));
812  $col++;
813  array_push($datarow, $this->lng->txt("tst_stat_result_qmax"));
814  $col++;
815  array_push($datarow, $this->lng->txt("tst_stat_result_pworkedthrough"));
816  $col++;
817  array_push($datarow, $this->lng->txt("tst_stat_result_timeofwork"));
818  $col++;
819  array_push($datarow, $this->lng->txt("tst_stat_result_atimeofwork"));
820  $col++;
821  array_push($datarow, $this->lng->txt("tst_stat_result_firstvisit"));
822  $col++;
823  array_push($datarow, $this->lng->txt("tst_stat_result_lastvisit"));
824  $col++;
825 
826  array_push($datarow, $this->lng->txt("tst_stat_result_mark_median"));
827  $col++;
828  array_push($datarow, $this->lng->txt("tst_stat_result_rank_participant"));
829  $col++;
830  array_push($datarow, $this->lng->txt("tst_stat_result_rank_median"));
831  $col++;
832  array_push($datarow, $this->lng->txt("tst_stat_result_total_participants"));
833  $col++;
834  array_push($datarow, $this->lng->txt("tst_stat_result_median"));
835  $col++;
836  array_push($datarow, $this->lng->txt("scored_pass"));
837  $col++;
838 
839  array_push($datarow, $this->lng->txt("pass"));
840  $col++;
841 
842  $data =& $this->test_obj->getCompleteEvaluationData(TRUE, $filterby, $filtertext);
843  $headerrow = $datarow;
844  $counter = 1;
845  foreach ($data->getParticipants() as $active_id => $userdata)
846  {
847  $datarow = $headerrow;
848  $remove = FALSE;
849  if ($passedonly)
850  {
851  if ($data->getParticipant($active_id)->getPassed() == FALSE)
852  {
853  $remove = TRUE;
854  }
855  }
856  if (!$remove)
857  {
858  $datarow2 = array();
859  if ($this->test_obj->getAnonymity())
860  {
861  array_push($datarow2, $counter);
862  }
863  else
864  {
865  array_push($datarow2, $data->getParticipant($active_id)->getName());
866  array_push($datarow2, $data->getParticipant($active_id)->getLogin());
867  }
868  if (count($additionalFields))
869  {
870  $userfields = ilObjUser::_lookupFields($userdata->getUserID());
871  foreach ($additionalFields as $fieldname)
872  {
873  if (strcmp($fieldname, "gender") == 0)
874  {
875  array_push($datarow2, $this->lng->txt("gender_" . $userfields[$fieldname]));
876  }
877  else
878  {
879  array_push($datarow2, $userfields[$fieldname]);
880  }
881  }
882  }
883  array_push($datarow2, $data->getParticipant($active_id)->getReached());
884  array_push($datarow2, $data->getParticipant($active_id)->getMaxpoints());
885  array_push($datarow2, $data->getParticipant($active_id)->getMark());
886  if ($this->test_obj->ects_output)
887  {
888  array_push($datarow2, $data->getParticipant($active_id)->getECTSMark());
889  }
890  array_push($datarow2, $data->getParticipant($active_id)->getQuestionsWorkedThrough());
891  array_push($datarow2, $data->getParticipant($active_id)->getNumberOfQuestions());
892  array_push($datarow2, $data->getParticipant($active_id)->getQuestionsWorkedThroughInPercent() / 100.0);
893  $time = $data->getParticipant($active_id)->getTimeOfWork();
894  $time_seconds = $time;
895  $time_hours = floor($time_seconds/3600);
896  $time_seconds -= $time_hours * 3600;
897  $time_minutes = floor($time_seconds/60);
898  $time_seconds -= $time_minutes * 60;
899  array_push($datarow2, sprintf("%02d:%02d:%02d", $time_hours, $time_minutes, $time_seconds));
900  $time = $data->getParticipant($active_id)->getQuestionsWorkedThrough() ? $data->getParticipant($active_id)->getTimeOfWork() / $data->getParticipant($active_id)->getQuestionsWorkedThrough() : 0;
901  $time_seconds = $time;
902  $time_hours = floor($time_seconds/3600);
903  $time_seconds -= $time_hours * 3600;
904  $time_minutes = floor($time_seconds/60);
905  $time_seconds -= $time_minutes * 60;
906  array_push($datarow2, sprintf("%02d:%02d:%02d", $time_hours, $time_minutes, $time_seconds));
907 
908  $fv = $data->getParticipant($active_id)->getFirstVisit();
909  $lv = $data->getParticipant($active_id)->getLastVisit();
910  foreach(array($fv, $lv) as $ts)
911  {
912  if($ts)
913  {
914  $visit = ilFormat::formatDate(date('Y-m-d H:i:s', $ts), "datetime", false, false);
915  array_push($datarow2, $visit);
916  }
917  else
918  {
919  array_push($datarow2, "");
920  }
921  }
922 
923  $median = $data->getStatistics()->getStatistics()->median();
924  $pct = $data->getParticipant($active_id)->getMaxpoints() ? $median / $data->getParticipant($active_id)->getMaxpoints() * 100.0 : 0;
925  $mark = $this->test_obj->mark_schema->getMatchingMark($pct);
926  $mark_short_name = "";
927  if (is_object($mark))
928  {
929  $mark_short_name = $mark->getShortName();
930  }
931  array_push($datarow2, $mark_short_name);
932  array_push($datarow2, $data->getStatistics()->getStatistics()->rank($data->getParticipant($active_id)->getReached()));
933  array_push($datarow2, $data->getStatistics()->getStatistics()->rank_median());
934  array_push($datarow2, $data->getStatistics()->getStatistics()->count());
935  array_push($datarow2, $median);
936  if ($this->test_obj->getPassScoring() == SCORE_BEST_PASS)
937  {
938  array_push($datarow2, $data->getParticipant($active_id)->getBestPass() + 1);
939  }
940  else
941  {
942  array_push($datarow2, $data->getParticipant($active_id)->getLastPass() + 1);
943  }
944  for ($pass = 0; $pass <= $data->getParticipant($active_id)->getLastPass(); $pass++)
945  {
946  $finishdate = $this->test_obj->getPassFinishDate($active_id, $pass);
947  if ($finishdate > 0)
948  {
949  if ($pass > 0)
950  {
951  for ($i = 1; $i < $col-1; $i++)
952  {
953  array_push($datarow2, "");
954  array_push($datarow, "");
955  }
956  array_push($datarow, "");
957  }
958  array_push($datarow2, $pass+1);
959  if (is_object($data->getParticipant($active_id)) && is_array($data->getParticipant($active_id)->getQuestions($pass)))
960  {
961  foreach ($data->getParticipant($active_id)->getQuestions($pass) as $question)
962  {
963  $question_data = $data->getParticipant($active_id)->getPass($pass)->getAnsweredQuestionByQuestionId($question["id"]);
964  array_push($datarow2, $question_data["reached"]);
965  array_push($datarow, preg_replace("/<.*?>/", "", $data->getQuestionTitle($question["id"])));
966  }
967  }
968  if ($this->test_obj->isRandomTest() || $this->test_obj->getShuffleQuestions() || ($counter == 1 && $pass == 0))
969  {
970  array_push($rows, $datarow);
971  }
972  $datarow = array();
973  array_push($rows, $datarow2);
974  $datarow2 = array();
975  }
976  }
977  $counter++;
978  }
979  }
980  $csv = "";
981  $separator = ";";
982  foreach ($rows as $evalrow)
983  {
984  $csvrow =& $this->test_obj->processCSVRow($evalrow, TRUE, $separator);
985  $csv .= join($csvrow, $separator) . "\n";
986  }
987  if ($deliver)
988  {
989  ilUtil::deliverData($csv, ilUtil::getASCIIFilename($this->test_obj->getTitle() . "_results.csv"));
990  exit;
991  }
992  else
993  {
994  return $csv;
995  }
996  }
997 
1002  {
1003  global $ilBench;
1004 
1005  $ilBench->start("TestExport", "buildExportFile");
1006 
1007  include_once("./Services/Xml/classes/class.ilXmlWriter.php");
1008  $this->xml = new ilXmlWriter;
1009 
1010  // set dtd definition
1011  $this->xml->xmlSetDtdDef("<!DOCTYPE Test SYSTEM \"http://www.ilias.uni-koeln.de/download/dtd/ilias_co.dtd\">");
1012 
1013  // set generated comment
1014  $this->xml->xmlSetGenCmt("Export of ILIAS Test ".
1015  $this->test_obj->getId()." of installation ".$this->inst.".");
1016 
1017  // set xml header
1018  $this->xml->xmlHeader();
1019 
1020  // create directories
1021  $this->test_obj->createExportDirectory();
1022  include_once "./Services/Utilities/classes/class.ilUtil.php";
1023  ilUtil::makeDir($this->export_dir."/".$this->subdir);
1024  ilUtil::makeDir($this->export_dir."/".$this->subdir."/objects");
1025 
1026  // get Log File
1027  $expDir = $this->test_obj->getExportDirectory();
1028  include_once "./Services/Logging/classes/class.ilLog.php";
1029  $expLog = new ilLog($expDir, "export.log");
1030  $expLog->delete();
1031  $expLog->setLogFormat("");
1032  $expLog->write(date("[y-m-d H:i:s] ")."Start Export");
1033 
1034  // write qti file
1035  $qti_file = fopen($this->export_dir."/".$this->subdir."/".$this->qti_filename, "w");
1036  fwrite($qti_file, $this->test_obj->toXML());
1037  fclose($qti_file);
1038 
1039  // get xml content
1040  $ilBench->start("TestExport", "buildExportFile_getXML");
1041  $this->test_obj->exportPagesXML($this->xml, $this->inst_id,
1042  $this->export_dir."/".$this->subdir, $expLog);
1043  $ilBench->stop("TestExport", "buildExportFile_getXML");
1044 
1045  // dump xml document to screen (only for debugging reasons)
1046  /*
1047  echo "<PRE>";
1048  echo htmlentities($this->xml->xmlDumpMem($format));
1049  echo "</PRE>";
1050  */
1051 
1052  // dump xml document to file
1053  $ilBench->start("TestExport", "buildExportFile_dumpToFile");
1054  $this->xml->xmlDumpFile($this->export_dir."/".$this->subdir."/".$this->filename
1055  , false);
1056  $ilBench->stop("TestExport", "buildExportFile_dumpToFile");
1057 
1058  if (@file_exists("./Modules/Test/classes/class.ilTestResultsToXML.php"))
1059  {
1060  // dump results xml document to file
1061  include_once "./Modules/Test/classes/class.ilTestResultsToXML.php";
1062  $resultwriter = new ilTestResultsToXML($this->test_obj->getTestId(), $this->test_obj->getAnonymity());
1063  $ilBench->start("TestExport", "buildExportFile_results");
1064  $resultwriter->xmlDumpFile($this->export_dir."/".$this->subdir."/".$this->resultsfile, false);
1065  $ilBench->stop("TestExport", "buildExportFile_results");
1066  }
1067 
1068  // add media objects which were added with tiny mce
1069  $ilBench->start("QuestionpoolExport", "buildExportFile_saveAdditionalMobs");
1070  $this->exportXHTMLMediaObjects($this->export_dir."/".$this->subdir);
1071  $ilBench->stop("QuestionpoolExport", "buildExportFile_saveAdditionalMobs");
1072 
1073  // zip the file
1074  $ilBench->start("TestExport", "buildExportFile_zipFile");
1075  ilUtil::zip($this->export_dir."/".$this->subdir,
1076  $this->export_dir."/".$this->subdir.".zip");
1077  $ilBench->stop("TestExport", "buildExportFile_zipFile");
1078 
1079  // destroy writer object
1080  $this->xml->_XmlWriter;
1081 
1082  $expLog->write(date("[y-m-d H:i:s] ")."Finished Export");
1083  $ilBench->stop("TestExport", "buildExportFile");
1084 
1085  return $this->export_dir."/".$this->subdir.".zip";
1086  }
1087 
1088  function exportXHTMLMediaObjects($a_export_dir)
1089  {
1090  include_once("./Services/MediaObjects/classes/class.ilObjMediaObject.php");
1091 
1092  $mobs = ilObjMediaObject::_getMobsOfObject("tst:html", $this->test_obj->getId());
1093  foreach ($mobs as $mob)
1094  {
1095  if (ilObjMediaObject::_exists($mob))
1096  {
1097  $mob_obj =& new ilObjMediaObject($mob);
1098  $mob_obj->exportFiles($a_export_dir);
1099  unset($mob_obj);
1100  }
1101  }
1102  foreach ($this->test_obj->questions as $question_id)
1103  {
1104  $mobs = ilObjMediaObject::_getMobsOfObject("qpl:html", $question_id);
1105  foreach ($mobs as $mob)
1106  {
1107  if (ilObjMediaObject::_exists($mob))
1108  {
1109  $mob_obj =& new ilObjMediaObject($mob);
1110  $mob_obj->exportFiles($a_export_dir);
1111  unset($mob_obj);
1112  }
1113  }
1114  }
1115  }
1116 
1117 }
1118 
1119 ?>