ILIAS  Release_4_4_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.assFileUpload.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
4 require_once './Modules/TestQuestionPool/classes/class.assQuestion.php';
5 require_once './Modules/Test/classes/inc.AssessmentConstants.php';
6 require_once './Modules/TestQuestionPool/interfaces/interface.ilObjQuestionScoringAdjustable.php';
7 require_once './Modules/TestQuestionPool/interfaces/interface.ilObjFileHandlingQuestionType.php';
8 
20 class assFileUpload extends assQuestion implements ilObjFileHandlingQuestionType // ilObjQuestionScoringAdjustable
21 {
22  protected $maxsize;
23 
24  protected $allowedextensions;
25 
27  protected $completion_by_submission = false;
28 
42  function __construct(
43  $title = "",
44  $comment = "",
45  $author = "",
46  $owner = -1,
47  $question = ""
48  )
49  {
51  }
52 
58  public function isComplete()
59  {
60  if (
61  strlen($this->title)
62  && ($this->author)
63  && ($this->question)
64  && ($this->getMaximumPoints() >= 0)
65  && is_numeric($this->getMaximumPoints()))
66  {
67  return true;
68  }
69  return false;
70  }
71 
75  public function saveToDb($original_id = "")
76  {
80  }
81 
83  {
84  global $ilDB;
85  $ilDB->manipulateF( "DELETE FROM " . $this->getAdditionalTableName() . " WHERE question_fi = %s",
86  array( "integer" ),
87  array( $this->getId() )
88  );
89  $ilDB->manipulateF( "INSERT INTO " . $this->getAdditionalTableName(
90  ) . " (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  );
99  }
100 
106  public function loadFromDb($question_id)
107  {
108  global $ilDB;
109  $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",
110  array("integer"),
111  array($question_id)
112  );
113  if ($result->numRows() == 1)
114  {
115  $data = $ilDB->fetchAssoc($result);
116  $this->setId($question_id);
117  $this->setTitle($data["title"]);
118  $this->setComment($data["description"]);
119  $this->setNrOfTries($data['nr_of_tries']);
120  $this->setSuggestedSolution($data["solution_hint"]);
121  $this->setOriginalId($data["original_id"]);
122  $this->setObjId($data["obj_fi"]);
123  $this->setAuthor($data["author"]);
124  $this->setOwner($data["owner"]);
125  $this->setPoints($data["points"]);
126 
127  include_once("./Services/RTE/classes/class.ilRTE.php");
128  $this->setQuestion(ilRTE::_replaceMediaObjectImageSrc($data["question_text"], 1));
129  $this->setEstimatedWorkingTime(substr($data["working_time"], 0, 2), substr($data["working_time"], 3, 2), substr($data["working_time"], 6, 2));
130  $this->setMaxSize($data["maxsize"]);
131  $this->setAllowedExtensions($data["allowedextensions"]);
132  $this->setCompletionBySubmission($data['compl_by_submission'] == 1 ? true : false);
133 
134  try
135  {
136  $this->setAdditionalContentEditingMode($data['add_cont_edit_mode']);
137  }
139  {
140  }
141  }
142  parent::loadFromDb($question_id);
143  }
144 
148  public function duplicate($for_test = true, $title = "", $author = "", $owner = "", $testObjId = null)
149  {
150  if ($this->id <= 0)
151  {
152  // The question has not been saved. It cannot be duplicated
153  return;
154  }
155  // duplicate the question in database
156  $this_id = $this->getId();
157  $thisObjId = $this->getObjId();
158 
159  $clone = $this;
160  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
162  $clone->id = -1;
163 
164  if( (int)$testObjId > 0 )
165  {
166  $clone->setObjId($testObjId);
167  }
168 
169  if ($title)
170  {
171  $clone->setTitle($title);
172  }
173 
174  if ($author)
175  {
176  $clone->setAuthor($author);
177  }
178  if ($owner)
179  {
180  $clone->setOwner($owner);
181  }
182 
183  if ($for_test)
184  {
185  $clone->saveToDb($original_id);
186  }
187  else
188  {
189  $clone->saveToDb();
190  }
191 
192  // copy question page content
193  $clone->copyPageOfQuestion($this_id);
194  // copy XHTML media objects
195  $clone->copyXHTMLMediaObjectsOfQuestion($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_id, $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_id = $this->getObjId();
218  $clone->setObjId($target_questionpool_id);
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 
230  $clone->onCopy($source_questionpool_id, $original_id, $clone->getObjId(), $clone->getId());
231 
232  return $clone->id;
233  }
234 
235  public function createNewOriginalFromThisDuplicate($targetParentId, $targetQuestionTitle = "")
236  {
237  if ($this->id <= 0)
238  {
239  // The question has not been saved. It cannot be duplicated
240  return;
241  }
242 
243  include_once ("./Modules/TestQuestionPool/classes/class.assQuestion.php");
244 
245  $sourceQuestionId = $this->id;
246  $sourceParentId = $this->getObjId();
247 
248  // duplicate the question in database
249  $clone = $this;
250  $clone->id = -1;
251 
252  $clone->setObjId($targetParentId);
253 
254  if ($targetQuestionTitle)
255  {
256  $clone->setTitle($targetQuestionTitle);
257  }
258 
259  $clone->saveToDb();
260  // copy question page content
261  $clone->copyPageOfQuestion($sourceQuestionId);
262  // copy XHTML media objects
263  $clone->copyXHTMLMediaObjectsOfQuestion($sourceQuestionId);
264 
265  $clone->onCopy($sourceParentId, $sourceQuestionId, $clone->getObjId(), $clone->getId());
266 
267  return $clone->id;
268  }
269 
275  public function getMaximumPoints()
276  {
277  return $this->getPoints();
278  }
279 
290  public function calculateReachedPoints($active_id, $pass = NULL, $returndetails = FALSE)
291  {
292  if( $returndetails )
293  {
294  throw new ilTestException('return details not implemented for '.__METHOD__);
295  }
296 
297  global $ilDB;
298 
299  if (is_null($pass))
300  {
301  $pass = $this->getSolutionMaxPass($active_id);
302  }
303  $points = 0;
304  return $points;
305  }
306 
312  function checkUpload()
313  {
314  $this->lng->loadLanguageModule("form");
315  // remove trailing '/'
316  while (substr($_FILES["upload"]["name"],-1) == '/')
317  {
318  $_FILES["upload"]["name"] = substr($_FILES["upload"]["name"],0,-1);
319  }
320 
321  $filename = $_FILES["upload"]["name"];
322  $filename_arr = pathinfo($_FILES["upload"]["name"]);
323  $suffix = $filename_arr["extension"];
324  $mimetype = $_FILES["upload"]["type"];
325  $size_bytes = $_FILES["upload"]["size"];
326  $temp_name = $_FILES["upload"]["tmp_name"];
327  $error = $_FILES["upload"]["error"];
328 
329  if ($size_bytes > $this->getMaxFilesizeInBytes())
330  {
331  ilUtil::sendFailure($this->lng->txt("form_msg_file_size_exceeds"), true);
332  return false;
333  }
334 
335  // error handling
336  if ($error > 0)
337  {
338  switch ($error)
339  {
340  case UPLOAD_ERR_INI_SIZE:
341  ilUtil::sendFailure($this->lng->txt("form_msg_file_size_exceeds"), true);
342  return false;
343  break;
344 
345  case UPLOAD_ERR_FORM_SIZE:
346  ilUtil::sendFailure($this->lng->txt("form_msg_file_size_exceeds"), true);
347  return false;
348  break;
349 
350  case UPLOAD_ERR_PARTIAL:
351  ilUtil::sendFailure($this->lng->txt("form_msg_file_partially_uploaded"), true);
352  return false;
353  break;
354 
355  case UPLOAD_ERR_NO_FILE:
356  ilUtil::sendFailure($this->lng->txt("form_msg_file_no_upload"), true);
357  return false;
358  break;
359 
360  case UPLOAD_ERR_NO_TMP_DIR:
361  ilUtil::sendFailure($this->lng->txt("form_msg_file_missing_tmp_dir"), true);
362  return false;
363  break;
364 
365  case UPLOAD_ERR_CANT_WRITE:
366  ilUtil::sendFailure($this->lng->txt("form_msg_file_cannot_write_to_disk"), true);
367  return false;
368  break;
369 
370  case UPLOAD_ERR_EXTENSION:
371  ilUtil::sendFailure($this->lng->txt("form_msg_file_upload_stopped_ext"), true);
372  return false;
373  break;
374  }
375  }
376 
377  // check suffixes
378  if (strlen($suffix) && count($this->getAllowedExtensionsArray()))
379  {
380  if (!in_array(strtolower($suffix), $this->getAllowedExtensionsArray()))
381  {
382  ilUtil::sendFailure($this->lng->txt("form_msg_file_wrong_file_type"), true);
383  return false;
384  }
385  }
386 
387  // virus handling
388  if (strlen($temp_name))
389  {
390  $vir = ilUtil::virusHandling($temp_name, $filename);
391  if ($vir[0] == false)
392  {
393  ilUtil::sendFailure($this->lng->txt("form_msg_file_virus_found")."<br />".$vir[1], true);
394  return false;
395  }
396  }
397  return true;
398  }
399 
403  protected function getFileUploadPath($test_id, $active_id, $question_id = null)
404  {
405  if (is_null($question_id)) $question_id = $this->getId();
406  return CLIENT_WEB_DIR . "/assessment/tst_$test_id/$active_id/$question_id/files/";
407  }
408 
414  function getFileUploadPathWeb($test_id, $active_id, $question_id = null)
415  {
416  if (is_null($question_id)) $question_id = $this->getId();
417  include_once "./Services/Utilities/classes/class.ilUtil.php";
418  $webdir = ilUtil::removeTrailingPathSeparators(CLIENT_WEB_DIR) . "/assessment/tst_$test_id/$active_id/$question_id/files/";
420  }
421 
427  public function getUploadedFiles($active_id, $pass = null)
428  {
429  global $ilDB;
430  if (is_null($pass))
431  {
432  $pass = $this->getSolutionMaxPass($active_id);
433  }
434  $result = $ilDB->queryF("SELECT * FROM tst_solutions WHERE active_fi = %s AND question_fi = %s AND pass = %s ORDER BY tstamp",
435  array("integer", "integer", "integer"),
436  array($active_id, $this->getId(), $pass)
437  );
438  $found = array();
439  while ($data = $ilDB->fetchAssoc($result))
440  {
441  array_push($found, $data);
442  }
443  return $found;
444  }
445 
451  public function getUploadedFilesForWeb($active_id, $pass)
452  {
453  global $ilDB;
454 
455  $found = $this->getUploadedFiles($active_id, $pass);
456  $result = $ilDB->queryF("SELECT test_fi FROM tst_active WHERE active_id = %s",
457  array('integer'),
458  array($active_id)
459  );
460  if ($result->numRows() == 1)
461  {
462  $row = $ilDB->fetchAssoc($result);
463  $test_id = $row["test_fi"];
464  $path = $this->getFileUploadPathWeb($test_id, $active_id);
465  foreach ($found as $idx => $data)
466  {
467  $found[$idx]['webpath'] = $path;
468  }
469  }
470  return $found;
471  }
472 
478  protected function deleteUploadedFiles($files, $test_id, $active_id)
479  {
480  global $ilDB;
481 
482  $pass = null;
483  $active_id = null;
484  foreach ($files as $solution_id)
485  {
486  $result = $ilDB->queryF("SELECT * FROM tst_solutions WHERE solution_id = %s",
487  array("integer"),
488  array($solution_id)
489  );
490  if ($result->numRows() == 1)
491  {
492  $data = $ilDB->fetchAssoc($result);
493  $pass = $data['pass'];
494  $active_id = $data['active_fi'];
495  @unlink($this->getFileUploadPath($test_id, $active_id) . $data['value1']);
496  }
497  }
498  foreach ($files as $solution_id)
499  {
500  $affectedRows = $ilDB->manipulateF("DELETE FROM tst_solutions WHERE solution_id = %s",
501  array("integer"),
502  array($solution_id)
503  );
504  }
505  }
506 
512  public function getMaxFilesizeAsString()
513  {
514  $size = $this->getMaxFilesizeInBytes();
515  if ($size < 1024)
516  {
517  $max_filesize = sprintf("%d Bytes",$size);
518  }
519  else if ($size < 1024*1024)
520  {
521  $max_filesize = sprintf("%.1f KB",$size/1024);
522  }
523  else
524  {
525  $max_filesize = sprintf("%.1f MB",$size/1024/1024);
526  }
527 
528  return $max_filesize;
529  }
530 
536  public function getMaxFilesizeInBytes()
537  {
538  if (strlen($this->getMaxSize()))
539  {
540  return $this->getMaxSize();
541  }
542  else
543  {
544  // get the value for the maximal uploadable filesize from the php.ini (if available)
545  $umf = get_cfg_var("upload_max_filesize");
546  // get the value for the maximal post data from the php.ini (if available)
547  $pms = get_cfg_var("post_max_size");
548 
549  //convert from short-string representation to "real" bytes
550  $multiplier_a=array("K"=>1024, "M"=>1024*1024, "G"=>1024*1024*1024);
551 
552  $umf_parts=preg_split("/(\d+)([K|G|M])/", $umf, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
553  $pms_parts=preg_split("/(\d+)([K|G|M])/", $pms, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
554 
555  if (count($umf_parts) == 2) { $umf = $umf_parts[0]*$multiplier_a[$umf_parts[1]]; }
556  if (count($pms_parts) == 2) { $pms = $pms_parts[0]*$multiplier_a[$pms_parts[1]]; }
557 
558  // use the smaller one as limit
559  $max_filesize = min($umf, $pms);
560 
561  if (!$max_filesize) $max_filesize=max($umf, $pms);
562  return $max_filesize;
563  }
564  }
565 
574  public function saveWorkingData($active_id, $pass = NULL)
575  {
576  global $ilDB;
577  global $ilUser;
578 
579  if (is_null($pass))
580  {
581  include_once "./Modules/Test/classes/class.ilObjTest.php";
582  $pass = ilObjTest::_getPass($active_id);
583  }
584 
585  if( $_POST['cmd']['handleQuestionAction'] != $this->lng->txt('delete')
586  && strlen($_FILES["upload"]["tmp_name"]) )
587  {
588  $checkUploadResult = $this->checkUpload();
589  }
590  else
591  {
592  $checkUploadResult = false;
593  }
594 
595  $result = $ilDB->queryF("SELECT test_fi FROM tst_active WHERE active_id = %s",
596  array('integer'),
597  array($active_id)
598  );
599  $test_id = 0;
600  if ($result->numRows() == 1)
601  {
602  $row = $ilDB->fetchAssoc($result);
603  $test_id = $row["test_fi"];
604  }
605 
606  $this->getProcessLocker()->requestUserSolutionUpdateLock();
607 
608  $entered_values = false;
609  if( $_POST['cmd']['handleQuestionAction'] == $this->lng->txt('delete') )
610  {
611  if (is_array($_POST['deletefiles']) && count($_POST['deletefiles']) > 0)
612  {
613  $this->deleteUploadedFiles($_POST['deletefiles'], $test_id, $active_id);
614  }
615  else
616  {
617  ilUtil::sendInfo($this->lng->txt('no_checkbox'), true);
618  }
619  }
620  elseif( $checkUploadResult )
621  {
622  if (!@file_exists($this->getFileUploadPath($test_id, $active_id))) ilUtil::makeDirParents($this->getFileUploadPath($test_id, $active_id));
623  $version = time();
624  $filename_arr = pathinfo($_FILES["upload"]["name"]);
625  $extension = $filename_arr["extension"];
626  $newfile = "file_" . $active_id . "_" . $pass . "_" . $version . "." . $extension;
627  ilUtil::moveUploadedFile($_FILES["upload"]["tmp_name"], $_FILES["upload"]["name"], $this->getFileUploadPath($test_id, $active_id) . $newfile);
628  $next_id = $ilDB->nextId('tst_solutions');
629  $affectedRows = $ilDB->insert("tst_solutions", array(
630  "solution_id" => array("integer", $next_id),
631  "active_fi" => array("integer", $active_id),
632  "question_fi" => array("integer", $this->getId()),
633  "value1" => array("clob", $newfile),
634  "value2" => array("clob", $_FILES['upload']['name']),
635  "pass" => array("integer", $pass),
636  "tstamp" => array("integer", time())
637  ));
638  $entered_values = true;
639  }
640 
641  $this->getProcessLocker()->releaseUserSolutionUpdateLock();
642 
643  if ($entered_values)
644  {
645  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
647  {
648  $this->logAction($this->lng->txtlng("assessment", "log_user_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
649  }
650  }
651  else
652  {
653  include_once ("./Modules/Test/classes/class.ilObjAssessmentFolder.php");
655  {
656  $this->logAction($this->lng->txtlng("assessment", "log_user_not_entered_values", ilObjAssessmentFolder::_getLogLanguage()), $active_id, $this->getId());
657  }
658  }
659 
660  return true;
661  }
662 
671  protected function reworkWorkingData($active_id, $pass, $obligationsAnswered)
672  {
673  $this->handleSubmission($active_id, $pass, $obligationsAnswered);
674  }
675 
685  protected function handleSubmission($active_id, $pass, $obligationsAnswered)
686  {
687  global $ilObjDataCache;
688 
690  {
691  $maxpoints = assQuestion::_getMaximumPoints($this->getId());
692 
693  if($this->getUploadedFiles($active_id, $pass))
694  {
695  $points = $maxpoints;
696  }
697  else
698  {
699  $points = 0;
700  }
701 
702  assQuestion::_setReachedPoints($active_id, $this->getId(), $points, $maxpoints, $pass, 1, $obligationsAnswered);
703 
704  // update learning progress
705  include_once 'Modules/Test/classes/class.ilObjTestAccess.php';
706  include_once 'Services/Tracking/classes/class.ilLPStatusWrapper.php';
708  ilObjTest::_getObjectIDFromActiveID((int)$active_id),
709  ilObjTestAccess::_getParticipantId((int) $active_id)
710  );
711  }
712  }
713 
719  public function getQuestionType()
720  {
721  return "assFileUpload";
722  }
723 
729  public function getAdditionalTableName()
730  {
731  return "qpl_qst_fileupload";
732  }
733 
739  public function getAnswerTableName()
740  {
741  return "";
742  }
743 
749  public function deleteAnswers($question_id)
750  {
751  }
752 
757  public function getRTETextWithMediaObjects()
758  {
760  return $text;
761  }
762 
774  public function setExportDetailsXLS(&$worksheet, $startrow, $active_id, $pass, &$format_title, &$format_bold)
775  {
776  include_once ("./Services/Excel/classes/class.ilExcelUtils.php");
777  $worksheet->writeString($startrow, 0, ilExcelUtils::_convert_text($this->lng->txt($this->getQuestionType())), $format_title);
778  $worksheet->writeString($startrow, 1, ilExcelUtils::_convert_text($this->getTitle()), $format_title);
779  $i = 1;
780  $solutions = $this->getSolutionValues($active_id, $pass);
781  foreach ($solutions as $solution)
782  {
783  $worksheet->writeString($startrow + $i, 0, ilExcelUtils::_convert_text($this->lng->txt("result")), $format_bold);
784  if (strlen($solution["value1"]))
785  {
786  $worksheet->write($startrow + $i, 1, ilExcelUtils::_convert_text($solution["value1"]));
787  $worksheet->write($startrow + $i, 2, ilExcelUtils::_convert_text($solution["value2"]));
788  }
789  $i++;
790  }
791  return $startrow + $i + 1;
792  }
793 
806  public function fromXML(&$item, &$questionpool_id, &$tst_id, &$tst_object, &$question_counter, &$import_mapping)
807  {
808  include_once "./Modules/TestQuestionPool/classes/import/qti12/class.assFileUploadImport.php";
809  $import = new assFileUploadImport($this);
810  $import->fromXML($item, $questionpool_id, $tst_id, $tst_object, $question_counter, $import_mapping);
811  }
812 
819  public function toXML($a_include_header = true, $a_include_binary = true, $a_shuffle = false, $test_output = false, $force_image_references = false)
820  {
821  include_once "./Modules/TestQuestionPool/classes/export/qti12/class.assFileUploadExport.php";
822  $export = new assFileUploadExport($this);
823  return $export->toXML($a_include_header, $a_include_binary, $a_shuffle, $test_output, $force_image_references);
824  }
825 
831  public function getBestSolution($active_id, $pass)
832  {
833  $user_solution = array();
834  return $user_solution;
835  }
836 
842  public function getMaxSize()
843  {
844  return $this->maxsize;
845  }
846 
852  public function setMaxSize($a_value)
853  {
854  $this->maxsize = $a_value;
855  }
856 
862  public function getAllowedExtensionsArray()
863  {
864  if (strlen($this->allowedextensions))
865  {
866  return array_filter(array_map('trim', explode(",", $this->allowedextensions)));
867  }
868  return array();
869  }
870 
876  public function getAllowedExtensions()
877  {
879  }
880 
886  public function setAllowedExtensions($a_value)
887  {
888  $this->allowedextensions = strtolower(trim($a_value));
889  }
890 
894  public function __get($value)
895  {
896  switch ($value)
897  {
898  case "maxsize":
899  return $this->getMaxSize();
900  break;
901  case "allowedextensions":
902  return $this->getAllowedExtensions();
903  break;
904  case 'completion_by_submission':
905  return $this->isCompletionBySubmissionEnabled();
906  break;
907  default:
908  return parent::__get($value);
909  break;
910  }
911  }
912 
916  public function __set($key, $value)
917  {
918  switch ($key)
919  {
920  case "maxsize":
921  $this->setMaxSize($value);
922  break;
923  case "allowedextensions":
924  $this->setAllowedExtensions($value);
925  break;
926  case 'completion_by_submission':
927  $this->setCompletionBySubmission($value);
928  break;
929  default:
930  parent::__set($key, $value);
931  break;
932  }
933  }
934 
942  public function hasFileUploads($test_id)
943  {
944  global $ilDB;
945  $query = "
946  SELECT tst_solutions.solution_id
947  FROM tst_solutions, tst_active, qpl_questions
948  WHERE tst_solutions.active_fi = tst_active.active_id
949  AND tst_solutions.question_fi = qpl_questions.question_id
950  AND tst_solutions.question_fi = %s AND tst_active.test_fi = %s";
951  $result = $ilDB->queryF( $query,
952  array("integer", "integer"),
953  array($this->getId(), $test_id)
954  );
955  if ($result->numRows() > 0)
956  {
957  return true;
958  }
959  else
960  {
961  return false;
962  }
963  }
964 
970  public function getFileUploadZIPFile($test_id)
971  {
973  global $ilDB;
974  $query = "
975  SELECT
976  tst_solutions.solution_id, tst_solutions.pass, tst_solutions.active_fi, tst_solutions.question_fi,
977  tst_solutions.value1, tst_solutions.value2, tst_solutions.tstamp
978  FROM tst_solutions, tst_active, qpl_questions
979  WHERE tst_solutions.active_fi = tst_active.active_id
980  AND tst_solutions.question_fi = qpl_questions.question_id
981  AND tst_solutions.question_fi = %s
982  AND tst_active.test_fi = %s
983  ORDER BY tst_solutions.active_fi, tst_solutions.tstamp";
984 
985  $result = $ilDB->queryF( $query,
986  array("integer", "integer"),
987  array($this->getId(), $test_id)
988  );
989  $zipfile = ilUtil::ilTempnam() . ".zip";
990  $tempdir = ilUtil::ilTempnam();
991  if ($result->numRows())
992  {
993  $userdata = array();
994  $data .= "<html><head>";
995  $data .= '<meta http-equiv="content-type" content="text/html; charset=UTF-8" />';
996  $data .= '<style>
997  table { border: 1px #333 solid; border-collapse:collapse;}
998  td, th { border: 1px #333 solid; padding: 0.25em;}
999  th { color: #fff; background-color: #666;}
1000  </style>
1001  ';
1002  $data .= "<title>" . $this->getTitle() . "</title></head><body>\n";
1003  $data .= "<h1>" . $this->getTitle() . "</h1>\n";
1004  $data .= "<table><thead>\n";
1005  $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";
1006  while ($row = $ilDB->fetchAssoc($result))
1007  {
1008  ilUtil::makeDirParents($tempdir . "/" . $row["active_fi"]."/".$row["question_fi"]);
1009  @copy($this->getFileUploadPath($test_id, $row["active_fi"], $row["question_fi"]) . $row["value1"], $tempdir . "/" . $row["active_fi"]."/".$row["question_fi"] . "/" . $row["value1"]);
1010  if (!array_key_exists($row["active_fi"], $userdata))
1011  {
1012  include_once "./Modules/Test/classes/class.ilObjTestAccess.php";
1013  $userdata[$row["active_fi"]] = ilObjTestAccess::_getParticipantData($row["active_fi"]);
1014  }
1015  $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>";
1016  $data .= "<td>" . ilFormat::fmtDateTime(ilFormat::unixtimestamp2datetime($row["tstamp"]), $this->lng->txt("lang_dateformat"), $this->lng->txt("lang_timeformat"), "datetime", FALSE) . "</td>";
1017  $data .= "</tr>\n";
1018  }
1019  $data .= "</tbody></table>\n";
1020  $data .= "</body></html>\n";
1021 
1022  $indexfile = $tempdir . "/index.html";
1023  $fh = fopen($indexfile, 'w');
1024  fwrite($fh, $data);
1025  fclose($fh);
1026  }
1027  ilUtil::zip($tempdir, $zipfile);
1028  ilUtil::delDir($tempdir);
1029  ilUtil::deliverFile($zipfile, ilUtil::getASCIIFilename($this->getTitle().".zip"), "application/zip", false, true);
1030  }
1031 
1041  {
1043  }
1044 
1054  public function setCompletionBySubmission($bool)
1055  {
1056  $this->completion_by_submission = (bool)$bool;
1057  return $this;
1058  }
1059 
1071  public function isAnswered($active_id, $pass)
1072  {
1073  $answered = assQuestion::doesSolutionRecordsExist($active_id, $pass, $this->getId());
1074 
1075  return $answered;
1076  }
1077 
1088  public static function isObligationPossible($questionId)
1089  {
1090  return true;
1091  }
1092 
1093  public function isAutosaveable()
1094  {
1095  return FALSE;
1096  }
1097 }