ILIAS  release_4-3 Revision
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.assFileUpload.php
Go to the documentation of this file.
1 <?php
2 
3 /* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
4 
5 include_once "./Modules/TestQuestionPool/classes/class.assQuestion.php";
6 include_once "./Modules/Test/classes/inc.AssessmentConstants.php";
7 
20 {
21  protected $maxsize;
22  protected $allowedextensions;
23 
32  protected $completion_by_submission = false;
33 
46  function __construct(
47  $title = "",
48  $comment = "",
49  $author = "",
50  $owner = -1,
51  $question = ""
52  )
53  {
55  }
56 
62  public function isComplete()
63  {
64  if (strlen($this->title) and ($this->author) and ($this->question) and ($this->getMaximumPoints() >= 0) and is_numeric($this->getMaximumPoints()))
65  {
66  return true;
67  }
68  else
69  {
70  return false;
71  }
72  }
73 
78  public function saveToDb($original_id = "")
79  {
80  global $ilDB;
81 
83 
84  // save additional data
85 
86  $affectedRows = $ilDB->manipulateF("DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
87  array("integer"),
88  array($this->getId())
89  );
90  $affectedRows = $ilDB->manipulateF("INSERT INTO " . $this->getAdditionalTableName() . " (question_fi, maxsize, allowedextensions, compl_by_submission) VALUES (%s, %s, %s, %s)",
91  array("integer", "float", "text", "integer"),
92  array(
93  $this->getId(),
94  (strlen($this->getMaxSize())) ? $this->getMaxSize() : NULL,
95  (strlen($this->getAllowedExtensions())) ? $this->getAllowedExtensions() : NULL,
97  )
98  );
100  }
101 
108  public function loadFromDb($question_id)
109  {
110  global $ilDB;
111  $result = $ilDB->queryF("SELECT qpl_questions.*, " . $this->getAdditionalTableName() . ".* FROM qpl_questions LEFT JOIN " . $this->getAdditionalTableName() . " ON " . $this->getAdditionalTableName() . ".question_fi = qpl_questions.question_id WHERE qpl_questions.question_id = %s",
112  array("integer"),
113  array($question_id)
114  );
115  if ($result->numRows() == 1)
116  {
117  $data = $ilDB->fetchAssoc($result);
118  $this->setId($question_id);
119  $this->setTitle($data["title"]);
120  $this->setComment($data["description"]);
121  $this->setNrOfTries($data['nr_of_tries']);
122  $this->setSuggestedSolution($data["solution_hint"]);
123  $this->setOriginalId($data["original_id"]);
124  $this->setObjId($data["obj_fi"]);
125  $this->setAuthor($data["author"]);
126  $this->setOwner($data["owner"]);
127  $this->setPoints($data["points"]);
128 
129  include_once("./Services/RTE/classes/class.ilRTE.php");
130  $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc($data["question_text"], 1));
131  $this->setEstimatedWorkingTime(substr($data["working_time"], 0, 2), substr($data["working_time"], 3, 2), substr($data["working_time"], 6, 2));
132  $this->setMaxSize($data["maxsize"]);
133  $this->setAllowedExtensions($data["allowedextensions"]);
134  $this->setCompletionBySubmission($data['compl_by_submission'] == 1 ? true : false);
135  }
136  parent::loadFromDb($question_id);
137  }
138 
142  public function duplicate($for_test = true, $title = "", $author = "", $owner = "", $testObjId = null)
143  {
144  if ($this->id <= 0)
145  {
146  // The question has not been saved. It cannot be duplicated
147  return;
148  }
149  // duplicate the question in database
150  $this_id = $this->getId();
151 
152  if( (int)$testObjId > 0 )
153  {
154  $thisObjId = $this->getObjId();
155  }
156 
157  $clone = $this;
158  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
160  $clone->id = -1;
161 
162  if( (int)$testObjId > 0 )
163  {
164  $clone->setObjId($testObjId);
165  }
166 
167  if ($title)
168  {
169  $clone->setTitle($title);
170  }
171 
172  if ($author)
173  {
174  $clone->setAuthor($author);
175  }
176  if ($owner)
177  {
178  $clone->setOwner($owner);
179  }
180 
181  if ($for_test)
182  {
183  $clone->saveToDb($original_id);
184  }
185  else
186  {
187  $clone->saveToDb();
188  }
189 
190  // copy question page content
191  $clone->copyPageOfQuestion($this_id);
192  // copy XHTML media objects
193  $clone->copyXHTMLMediaObjectsOfQuestion($this_id);
194  // duplicate the generic feedback
195  $clone->duplicateGenericFeedback($this_id);
196 
197  $clone->onDuplicate($thisObjId, $this_id, $clone->getObjId(), $clone->getId());
198 
199  return $clone->id;
200  }
201 
205  public function copyObject($target_questionpool, $title = "")
206  {
207  if ($this->id <= 0)
208  {
209  // The question has not been saved. It cannot be duplicated
210  return;
211  }
212  // duplicate the question in database
213  $clone = $this;
214  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
216  $clone->id = -1;
217  $source_questionpool = $this->getObjId();
218  $clone->setObjId($target_questionpool);
219  if ($title)
220  {
221  $clone->setTitle($title);
222  }
223  $clone->saveToDb();
224 
225  // copy question page content
226  $clone->copyPageOfQuestion($original_id);
227  // copy XHTML media objects
228  $clone->copyXHTMLMediaObjectsOfQuestion($original_id);
229  // duplicate the generic feedback
230  $clone->duplicateGenericFeedback($original_id);
231 
232  $clone->onCopy($this->getObjId(), $this->getId());
233 
234  return $clone->id;
235  }
236 
242  public function getMaximumPoints()
243  {
244  return $this->getPoints();
245  }
246 
257  public function calculateReachedPoints($active_id, $pass = NULL, $returndetails = FALSE)
258  {
259  if( $returndetails )
260  {
261  throw new ilTestException('return details not implemented for '.__METHOD__);
262  }
263 
264  global $ilDB;
265 
266  if (is_null($pass))
267  {
268  $pass = $this->getSolutionMaxPass($active_id);
269  }
270  $points = 0;
271  return $points;
272  }
273 
279  function checkUpload()
280  {
281  $this->lng->loadLanguageModule("form");
282  // remove trailing '/'
283  while (substr($_FILES["upload"]["name"],-1) == '/')
284  {
285  $_FILES["upload"]["name"] = substr($_FILES["upload"]["name"],0,-1);
286  }
287 
288  $filename = $_FILES["upload"]["name"];
289  $filename_arr = pathinfo($_FILES["upload"]["name"]);
290  $suffix = $filename_arr["extension"];
291  $mimetype = $_FILES["upload"]["type"];
292  $size_bytes = $_FILES["upload"]["size"];
293  $temp_name = $_FILES["upload"]["tmp_name"];
294  $error = $_FILES["upload"]["error"];
295 
296  if ($size_bytes > $this->getMaxFilesizeInBytes())
297  {
298  ilUtil::sendInfo($this->lng->txt("form_msg_file_size_exceeds"), true);
299  return false;
300  }
301 
302  // error handling
303  if ($error > 0)
304  {
305  switch ($error)
306  {
307  case UPLOAD_ERR_INI_SIZE:
308  ilUtil::sendInfo($this->lng->txt("form_msg_file_size_exceeds"), true);
309  return false;
310  break;
311 
312  case UPLOAD_ERR_FORM_SIZE:
313  ilUtil::sendInfo($this->lng->txt("form_msg_file_size_exceeds"), true);
314  return false;
315  break;
316 
317  case UPLOAD_ERR_PARTIAL:
318  ilUtil::sendInfo($this->lng->txt("form_msg_file_partially_uploaded"), true);
319  return false;
320  break;
321 
322  case UPLOAD_ERR_NO_FILE:
323  ilUtil::sendInfo($this->lng->txt("form_msg_file_no_upload"), true);
324  return false;
325  break;
326 
327  case UPLOAD_ERR_NO_TMP_DIR:
328  ilUtil::sendInfo($this->lng->txt("form_msg_file_missing_tmp_dir"), true);
329  return false;
330  break;
331 
332  case UPLOAD_ERR_CANT_WRITE:
333  ilUtil::sendInfo($this->lng->txt("form_msg_file_cannot_write_to_disk"), true);
334  return false;
335  break;
336 
337  case UPLOAD_ERR_EXTENSION:
338  ilUtil::sendInfo($this->lng->txt("form_msg_file_upload_stopped_ext"), true);
339  return false;
340  break;
341  }
342  }
343 
344  // check suffixes
345  if (strlen($suffix) && count($this->getAllowedExtensionsArray()))
346  {
347  if (!in_array(strtolower($suffix), $this->getAllowedExtensionsArray()))
348  {
349  ilUtil::sendInfo($this->lng->txt("form_msg_file_wrong_file_type"), true);
350  return false;
351  }
352  }
353 
354  // virus handling
355  if (strlen($temp_name))
356  {
357  $vir = ilUtil::virusHandling($temp_name, $filename);
358  if ($vir[0] == false)
359  {
360  ilUtil::sendInfo($this->lng->txt("form_msg_file_virus_found")."<br />".$vir[1], true);
361  return false;
362  }
363  }
364  return true;
365  }
366 
370  protected function getFileUploadPath($test_id, $active_id, $question_id = null)
371  {
372  if (is_null($question_id)) $question_id = $this->getId();
373  return CLIENT_WEB_DIR . "/assessment/tst_$test_id/$active_id/$question_id/files/";
374  }
375 
381  function getFileUploadPathWeb($test_id, $active_id, $question_id = null)
382  {
383  if (is_null($question_id)) $question_id = $this->getId();
384  include_once "./Services/Utilities/classes/class.ilUtil.php";
385  $webdir = ilUtil::removeTrailingPathSeparators(CLIENT_WEB_DIR) . "/assessment/tst_$test_id/$active_id/$question_id/files/";
387  }
388 
394  public function getUploadedFiles($active_id, $pass = null)
395  {
396  global $ilDB;
397  if (is_null($pass))
398  {
399  $pass = $this->getSolutionMaxPass($active_id);
400  }
401  $result = $ilDB->queryF("SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s ORDER BY tstamp",
402  array("integer", "integer", "integer"),
403  array($active_id, $this->getId(), $pass)
404  );
405  $found = array();
406  while ($data = $ilDB->fetchAssoc($result))
407  {
408  array_push($found, $data);
409  }
410  return $found;
411  }
412 
418  public function getUploadedFilesForWeb($active_id, $pass)
419  {
420  global $ilDB;
421 
422  $found = $this->getUploadedFiles($active_id, $pass);
423  $result = $ilDB->queryF("SELECT test_fi FROM tst_active WHERE active_id = %s",
424  array('integer'),
425  array($active_id)
426  );
427  if ($result->numRows() == 1)
428  {
429  $row = $ilDB->fetchAssoc($result);
430  $test_id = $row["test_fi"];
431  $path = $this->getFileUploadPathWeb($test_id, $active_id);
432  foreach ($found as $idx => $data)
433  {
434  $found[$idx]['webpath'] = $path;
435  }
436  }
437  return $found;
438  }
439 
445  protected function deleteUploadedFiles($files, $test_id, $active_id)
446  {
447  global $ilDB;
448 
449  $pass = null;
450  $active_id = null;
451  foreach ($files as $solution_id)
452  {
453  $result = $ilDB->queryF("SELECT * FROM tst_solutions WHERE solution_id = %s",
454  array("integer"),
455  array($solution_id)
456  );
457  if ($result->numRows() == 1)
458  {
459  $data = $ilDB->fetchAssoc($result);
460  $pass = $data['pass'];
461  $active_id = $data['active_fi'];
462  @unlink($this->getFileUploadPath($test_id, $active_id) . $data['value1']);
463  }
464  }
465  foreach ($files as $solution_id)
466  {
467  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE solution_id = %s",
468  array("integer"),
469  array($solution_id)
470  );
471  }
472  }
473 
479  public function getMaxFilesizeAsString()
480  {
481  $size = $this->getMaxFilesizeInBytes();
482  if ($size < 1024)
483  {
484  $max_filesize = sprintf("%.1f Bytes",$size);
485  }
486  else if ($size < 1024*1024)
487  {
488  $max_filesize = sprintf("%.1f KB",$size/1024);
489  }
490  else
491  {
492  $max_filesize = sprintf("%.1f MB",$size/1024/1024);
493  }
494 
495  return $max_filesize;
496  }
497 
503  public function getMaxFilesizeInBytes()
504  {
505  if (strlen($this->getMaxSize()))
506  {
507  return $this->getMaxSize();
508  }
509  else
510  {
511  // get the value for the maximal uploadable filesize from the php.ini (if available)
512  $umf = get_cfg_var("upload_max_filesize");
513  // get the value for the maximal post data from the php.ini (if available)
514  $pms = get_cfg_var("post_max_size");
515 
516  //convert from short-string representation to "real" bytes
517  $multiplier_a=array("K"=>1024, "M"=>1024*1024, "G"=>1024*1024*1024);
518 
519  $umf_parts=preg_split("/(\d+)([K|G|M])/", $umf, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
520  $pms_parts=preg_split("/(\d+)([K|G|M])/", $pms, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
521 
522  if (count($umf_parts) == 2) { $umf = $umf_parts[0]*$multiplier_a[$umf_parts[1]]; }
523  if (count($pms_parts) == 2) { $pms = $pms_parts[0]*$multiplier_a[$pms_parts[1]]; }
524 
525  // use the smaller one as limit
526  $max_filesize = min($umf, $pms);
527 
528  if (!$max_filesize) $max_filesize=max($umf, $pms);
529  return $max_filesize;
530  }
531  }
532 
541  public function saveWorkingData($active_id, $pass = NULL)
542  {
543  global $ilDB;
544  global $ilUser;
545 
546  if (is_null($pass))
547  {
548  include_once "./Modules/Test/classes/class.ilObjTest.php";
549  $pass = ilObjTest::_getPass($active_id);
550  }
551 
552  $result = $ilDB->queryF("SELECT test_fi FROM tst_active WHERE active_id = %s",
553  array('integer'),
554  array($active_id)
555  );
556  $test_id = 0;
557  if ($result->numRows() == 1)
558  {
559  $row = $ilDB->fetchAssoc($result);
560  $test_id = $row["test_fi"];
561  }
562 
563  $entered_values = false;
564  if (strcmp($_POST['cmd']['gotoquestion'], $this->lng->txt('delete')) == 0)
565  {
566  $deletefiles = $_POST['file'];
567  if (is_array($deletefiles) && count($deletefiles) > 0)
568  {
569  $this->deleteUploadedFiles($deletefiles, $test_id, $active_id);
570  }
571  else
572  {
573  ilUtil::sendInfo($this->lng->txt('no_checkbox'), true);
574  }
575  }
576  else
577  {
578  if (strlen($_FILES["upload"]["tmp_name"]))
579  {
580  if ($this->checkUpload())
581  {
582  if (!@file_exists($this->getFileUploadPath($test_id, $active_id))) ilUtil::makeDirParents($this->getFileUploadPath($test_id, $active_id));
583  $version = time();
584  $filename_arr = pathinfo($_FILES["upload"]["name"]);
585  $extension = $filename_arr["extension"];
586  $newfile = "file_" . $active_id . "_" . $pass . "_" . $version . "." . $extension;
587  ilUtil::moveUploadedFile($_FILES["upload"]["tmp_name"], $_FILES["upload"]["name"], $this->getFileUploadPath($test_id, $active_id) . $newfile);
588  $next_id = $ilDB->nextId('tst_solutions');
589  $affectedRows = $ilDB->insert("tst_solutions", array(
590  "solution_id" => array("integer", $next_id),
591  "active_fi" => array("integer", $active_id),
592  "question_fi" => array("integer", $this->getId()),
593  "value1" => array("clob", $newfile),
594  "value2" => array("clob", $_FILES['upload']['name']),
595  "pass" => array("integer", $pass),
596  "tstamp" => array("integer", time())
597  ));
598  $entered_values = true;
599  }
600  }
601  }
602  if ($entered_values)
603  {
604  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
606  {
607  $this->logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
608  }
609  }
610  else
611  {
612  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
614  {
615  $this->logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
616  }
617  }
618 
619  return true;
620  }
621 
630  protected function reworkWorkingData($active_id, $pass, $obligationsAnswered)
631  {
632  $this->handleSubmission($active_id, $pass, $obligationsAnswered);
633  }
634 
644  protected function handleSubmission($active_id, $pass, $obligationsAnswered)
645  {
646  global $ilObjDataCache;
647 
649  {
650  $maxpoints = assQuestion::_getMaximumPoints($this->getId());
651 
652  if($this->getUploadedFiles($active_id, $pass))
653  {
654  $points = $maxpoints;
655  }
656  else
657  {
658  $points = 0;
659  }
660 
661  assQuestion::_setReachedPoints($active_id, $this->getId(), $points, $maxpoints, $pass, 1, $obligationsAnswered);
662 
663  // update learning progress
664  include_once 'Modules/Test/classes/class.ilObjTestAccess.php';
665  include_once 'Services/Tracking/classes/class.ilLPStatusWrapper.php';
667  ilObjTest::_getObjectIDFromActiveID((int)$active_id),
668  ilObjTestAccess::_getParticipantId((int) $active_id)
669  );
670  }
671  }
672 
678  public function getQuestionType()
679  {
680  return "assFileUpload";
681  }
682 
688  public function getAdditionalTableName()
689  {
690  return "qpl_qst_fileupload";
691  }
692 
698  public function getAnswerTableName()
699  {
700  return "";
701  }
702 
708  public function deleteAnswers($question_id)
709  {
710  }
711 
716  public function getRTETextWithMediaObjects()
717  {
719  return $text;
720  }
721 
733  public function setExportDetailsXLS(&$worksheet, $startrow, $active_id, $pass, &$format_title, &$format_bold)
734  {
735  include_once ("./Services/Excel/classes/class.ilExcelUtils.php");
736  $worksheet->writeString($startrow, 0, ilExcelUtils::_convert_text($this->lng->txt($this->getQuestionType())), $format_title);
737  $worksheet->writeString($startrow, 1, ilExcelUtils::_convert_text($this->getTitle()), $format_title);
738  $i = 1;
739  $solutions = $this->getSolutionValues($active_id, $pass);
740  foreach ($solutions as $solution)
741  {
742  $worksheet->writeString($startrow + $i, 0, ilExcelUtils::_convert_text($this->lng->txt("result")), $format_bold);
743  if (strlen($solution["value1"]))
744  {
745  $worksheet->write($startrow + $i, 1, ilExcelUtils::_convert_text($solution["value1"]));
746  $worksheet->write($startrow + $i, 2, ilExcelUtils::_convert_text($solution["value2"]));
747  }
748  $i++;
749  }
750  return $startrow + $i + 1;
751  }
752 
765  public function fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
766  {
767  include_once "./Modules/TestQuestionPool/classes/import/qti12/class.assFileUploadImport.php";
768  $import = new assFileUploadImport($this);
769  $import->fromXML($item, $questionpool_id, $tst_id, $tst_object, $question_counter, $import_mapping);
770  }
771 
778  public function toXML($a_include_header = true, $a_include_binary = true, $a_shuffle = false, $test_output = false, $force_image_references = false)
779  {
780  include_once "./Modules/TestQuestionPool/classes/export/qti12/class.assFileUploadExport.php";
781  $export = new assFileUploadExport($this);
782  return $export->toXML($a_include_header, $a_include_binary, $a_shuffle, $test_output, $force_image_references);
783  }
784 
790  public function getBestSolution($active_id, $pass)
791  {
792  $user_solution = array();
793  return $user_solution;
794  }
795 
801  public function getMaxSize()
802  {
803  return $this->maxsize;
804  }
805 
811  public function setMaxSize($a_value)
812  {
813  $this->maxsize = $a_value;
814  }
815 
821  public function getAllowedExtensionsArray()
822  {
823  if (strlen($this->allowedextensions))
824  {
825  return array_filter(array_map('trim', explode(",", $this->allowedextensions)));
826  }
827  return array();
828  }
829 
835  public function getAllowedExtensions()
836  {
838  }
839 
845  public function setAllowedExtensions($a_value)
846  {
847  $this->allowedextensions = strtolower(trim($a_value));
848  }
849 
853  public function __get($value)
854  {
855  switch ($value)
856  {
857  case "maxsize":
858  return $this->getMaxSize();
859  break;
860  case "allowedextensions":
861  return $this->getAllowedExtensions();
862  break;
863  case 'completion_by_submission':
864  return $this->isCompletionBySubmissionEnabled();
865  break;
866  default:
867  return parent::__get($value);
868  break;
869  }
870  }
871 
875  public function __set($key, $value)
876  {
877  switch ($key)
878  {
879  case "maxsize":
880  $this->setMaxSize($value);
881  break;
882  case "allowedextensions":
883  $this->setAllowedExtensions($value);
884  break;
885  case 'completion_by_submission':
886  $this->setCompletionBySubmission($value);
887  break;
888  default:
889  parent::__set($key, $value);
890  break;
891  }
892  }
893 
899  public function hasFileUploads($test_id)
900  {
901  global $ilDB;
902  $result = $ilDB->queryF("
903  SELECT tst_solutions.solution_id
904  FROM tst_solutions, tst_active, qpl_questions
905  WHERE tst_solutions.active_fi = tst_active.active_id
906  AND tst_solutions.question_fi = qpl_questions.question_id
907  AND qpl_questions.question_id = %s
908  AND tst_active.test_fi = %s",
909  array("integer", "integer"),
910  array($this->getId(), $test_id)
911  );
912  if ($result->numRows() > 0)
913  {
914  return true;
915  }
916  else
917  {
918  return false;
919  }
920  }
921 
925  public function getFileUploadZIPFile($test_id)
926  {
928  global $ilDB;
929  $query = "
930  SELECT
931  tst_solutions.solution_id, tst_solutions.pass, tst_solutions.active_fi, tst_solutions.question_fi,
932  tst_solutions.value1, tst_solutions.value2, tst_solutions.tstamp
933  FROM tst_solutions, tst_active, qpl_questions
934  WHERE tst_solutions.active_fi = tst_active.active_id
935  AND tst_solutions.question_fi = qpl_questions.question_id
936  AND tst_solutions.question_fi = %s
937  AND tst_active.test_fi = %s
938  ORDER BY tst_solutions.active_fi, tst_solutions.tstamp";
939 
940  $result = $ilDB->queryF( $query,
941  array("integer", "integer"),
942  array($this->getId(), $test_id)
943  );
944 
945  $zipfile = ilUtil::ilTempnam() . ".zip";
946  $tempdir = ilUtil::ilTempnam();
947  if ($result->numRows())
948  {
949  $userdata = array();
950  $data .= "<html><head>";
951  $data .= '<meta http-equiv="content-type" content="text/html; charset=UTF-8" />';
952  $data .= '<style>
953  table { border: 1px #333 solid; border-collapse:collapse;}
954  td, th { border: 1px #333 solid; padding: 0.25em;}
955  th { color: #fff; background-color: #666;}
956  </style>
957  ';
958  $data .= "<title>" . $this->getTitle() . "</title></head><body>\n";
959  $data .= "<h1>" . $this->getTitle() . "</h1>\n";
960  $data .= "<table><thead>\n";
961  $data .= "<tr><th>" . $this->lng->txt("name") . "</th><th>" . $this->lng->txt("filename") . "</th><th>" . $this->lng->txt("pass") . "</th><th>" . $this->lng->txt("location") . "</th><th>" . $this->lng->txt("date") . "</th></tr></thead><tbody>\n";
962  while ($row = $ilDB->fetchAssoc($result))
963  {
964  ilUtil::makeDirParents($tempdir . "/" . $row["active_fi"]."/".$row["question_fi"]);
965  @copy($this->getFileUploadPath($test_id, $row["active_fi"], $row["question_fi"]) . $row["value1"], $tempdir . "/" . $row["active_fi"]."/".$row["question_fi"] . "/" . $row["value1"]);
966  if (!array_key_exists($row["active_fi"], $userdata))
967  {
968  include_once "./Modules/Test/classes/class.ilObjTestAccess.php";
969  $userdata[$row["active_fi"]] = ilObjTestAccess::_getParticipantData($row["active_fi"]);
970  }
971  $data .= "<tr><td>".$userdata[$row["active_fi"]]."</td><td><a href=\"".$row["active_fi"]."/".$row["question_fi"]."/".$row["value1"]."\" target=\"_blank\">".$row["value2"]."</a></td><td>".$row["pass"]."</td><td>".$row["active_fi"]."/".$row["question_fi"]."/".$row["value1"]."</td>";
972  $data .= "<td>" . ilFormat::fmtDateTime(ilFormat::unixtimestamp2datetime($row["tstamp"]), $this->lng->txt("lang_dateformat"), $this->lng->txt("lang_timeformat"), "datetime", FALSE) . "</td>";
973  $data .= "</tr>\n";
974  }
975  $data .= "</tbody></table>\n";
976  $data .= "</body></html>\n";
977 
978  $indexfile = $tempdir . "/index.html";
979  $fh = fopen($indexfile, 'w');
980  fwrite($fh, $data);
981  fclose($fh);
982  }
983  ilUtil::zip($tempdir, $zipfile);
984  ilUtil::delDir($tempdir);
985  ilUtil::deliverFile($zipfile, ilUtil::getASCIIFilename($this->getTitle().".zip"), "application/zip", false, true);
986  }
987 
997  {
999  }
1000 
1010  public function setCompletionBySubmission($bool)
1011  {
1012  $this->completion_by_submission = (bool)$bool;
1013  return $this;
1014  }
1015 
1027  public function isAnswered($active_id, $pass)
1028  {
1029  $answered = assQuestion::doesSolutionRecordsExist($active_id, $pass, $this->getId());
1030 
1031  return $answered;
1032  }
1033 
1044  public static function isObligationPossible($questionId)
1045  {
1046  return true;
1047  }
1048 
1049  public function isAutosaveable()
1050  {
1051  return FALSE;
1052  }
1053 }