ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilExSubmission.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2009 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
12 {
13  const TYPE_FILE = "File";
14  const TYPE_OBJECT = "Object"; // Blogs in WSP/Portfolio
15  const TYPE_TEXT = "Text";
16  const TYPE_REPO_OBJECT = "RepoObject"; // Wikis
17 
21  protected $user;
22 
26  protected $db;
27 
31  protected $lng;
32 
36  protected $ctrl;
37 
38  protected $assignment; // [ilExAssignment]
39  protected $user_id; // [int]
40  protected $team; // [ilExAssignmentTeam]
41  protected $peer_review; // [ilExPeerReview]
42  protected $is_tutor; // [bool]
43  protected $public_submissions; // [bool]
44 
48  protected $ass_type;
49 
53  protected $ass_types;
54 
55  public function __construct(ilExAssignment $a_ass, $a_user_id, ilExAssignmentTeam $a_team = null, $a_is_tutor = false, $a_public_submissions = false)
56  {
57  global $DIC;
58 
59  $this->user = $DIC->user();
60  $this->db = $DIC->database();
61  $this->lng = $DIC->language();
62  $this->ctrl = $DIC->ctrl();
63  $ilUser = $DIC->user();
64 
65  $this->assignment = $a_ass;
66  $this->ass_type = $this->assignment->getAssignmentType();
67  $this->ass_types = ilExAssignmentTypes::getInstance();
68 
69  $this->user_id = $a_user_id;
70  $this->is_tutor = (bool) $a_is_tutor;
71  $this->public_submissions = (bool) $a_public_submissions;
72 
73  $this->state = ilExcAssMemberState::getInstanceByIds($a_ass->getId(), $a_user_id);
74 
75  if ($a_ass->hasTeam()) {
76  if (!$a_team) {
77  $this->team = ilExAssignmentTeam::getInstanceByUserId($this->assignment->getId(), $this->user_id);
78  } else {
79  $this->team = $a_team;
80  }
81  }
82 
83  if ($this->assignment->getPeerReview()) {
84  $this->peer_review = new ilExPeerReview($this->assignment);
85  }
86  }
87 
88  public function getSubmissionType()
89  {
90  return $this->assignment->getAssignmentType()->getSubmissionType();
91  /*switch($this->assignment->getType())
92  {
93  case ilExAssignment::TYPE_UPLOAD_TEAM:
94  case ilExAssignment::TYPE_UPLOAD:
95  return "File";
96 
97  case ilExAssignment::TYPE_BLOG:
98  case ilExAssignment::TYPE_PORTFOLIO:
99  return "Object";
100 
101  case ilExAssignment::TYPE_TEXT:
102  return "Text";
103  };*/
104  }
105 
106 
110  public function getAssignment()
111  {
112  return $this->assignment;
113  }
114 
118  public function getTeam()
119  {
120  return $this->team;
121  }
122 
126  public function getPeerReview()
127  {
128  return $this->peer_review;
129  }
130 
131  public function validatePeerReviews()
132  {
133  $res = array();
134  foreach ($this->getUserIds() as $user_id) {
135  $valid = true;
136 
137  // no peer review == valid
138  if ($this->peer_review) {
139  $valid = $this->peer_review->isFeedbackValidForPassed($user_id);
140  }
141 
142  $res[$user_id] = $valid;
143  }
144  return $res;
145  }
146 
147  public function getUserId()
148  {
149  return $this->user_id;
150  }
151 
152  public function getUserIds()
153  {
154  if ($this->team &&
155  !$this->hasNoTeamYet()) {
156  return $this->team->getMembers();
157  }
158 
159  // if has no team currently there still might be uploads attached
160  return array($this->user_id);
161  }
162 
163  public function getFeedbackId()
164  {
165  if ($this->team) {
166  return "t" . $this->team->getId();
167  } else {
168  return $this->getUserId();
169  }
170  }
171 
172  public function hasSubmitted()
173  {
174  return (bool) sizeof($this->getFiles(null, true));
175  }
176 
177  public function getSelectedObject()
178  {
179  $files = $this->getFiles();
180  if (sizeof($files)) {
181  return array_pop($files);
182  }
183  }
184 
185  public function canSubmit()
186  {
187  return ($this->isOwner() &&
188  $this->state->isSubmissionAllowed());
189  }
190 
191  public function canView()
192  {
194 
195  if ($this->canSubmit() ||
196  $this->isTutor() ||
197  $this->isInTeam() ||
198  $this->public_submissions) {
199  return true;
200  }
201 
202  // #16115
203  if ($this->peer_review) {
204  // peer review givers may view peer submissions
205  foreach ($this->peer_review->getPeerReviewsByPeerId($this->getUserId()) as $giver) {
206  if ($giver["giver_id"] == $ilUser->getId()) {
207  return true;
208  }
209  }
210  }
211 
212  return false;
213  }
214 
215  public function isTutor()
216  {
217  return $this->is_tutor;
218  }
219 
220  public function hasNoTeamYet()
221  {
222  if ($this->assignment->hasTeam() &&
223  !$this->team->getId()) {
224  return true;
225  }
226  return false;
227  }
228 
229  public function isInTeam($a_user_id = null)
230  {
232 
233  if (!$a_user_id) {
234  $a_user_id = $ilUser->getId();
235  }
236  return in_array($a_user_id, $this->getUserIds());
237  }
238 
239  public function isOwner()
240  {
242 
243  return ($ilUser->getId() == $this->getUserId());
244  }
245 
246  public function hasPeerReviewAccess()
247  {
248  return ($this->peer_review &&
249  $this->peer_review->hasPeerReviewAccess($this->user_id));
250  }
251 
252  public function canAddFile()
253  {
254  if (!$this->canSubmit()) {
255  return false;
256  }
257 
258  $max = $this->getAssignment()->getMaxFile();
259  if ($max &&
260  $max <= sizeof($this->getFiles())) {
261  return false;
262  }
263 
264  return true;
265  }
266 
267 
268  //
269  // FILES
270  //
271 
272  protected function isLate()
273  {
274  $dl = $this->state->getOfficialDeadline();
275  //$dl = $this->assignment->getPersonalDeadline($this->getUserId());
276  return ($dl && $dl < time());
277  }
278 
279  protected function initStorage()
280  {
281  return new ilFSStorageExercise($this->assignment->getExerciseId(), $this->assignment->getId());
282  }
283 
289  protected function getStorageId()
290  {
291  if ($this->ass_type->isSubmissionAssignedToTeam()) {
292  $storage_id = $this->getTeam()->getId();
293  } else {
294  $storage_id = $this->getUserId();
295  }
296  return $storage_id;
297  }
298 
299 
303  public function uploadFile($a_http_post_files, $unzip = false)
304  {
305  $ilDB = $this->db;
306 
307  if (!$this->canAddFile()) {
308  return false;
309  }
310 
311  if ($this->ass_type->isSubmissionAssignedToTeam()) {
312  $team_id = $this->getTeam()->getId();
313  $user_id = 0;
314  if ($team_id == 0) {
315  return false;
316  }
317  } else {
318  $team_id = 0;
319  $user_id = $this->getUserId();
320  }
321  $storage_id = $this->getStorageId();
322 
323  $deliver_result = $this->initStorage()->uploadFile($a_http_post_files, $storage_id, $unzip);
324 
325  if ($deliver_result) {
326  $next_id = $ilDB->nextId("exc_returned");
327  $query = sprintf(
328  "INSERT INTO exc_returned " .
329  "(returned_id, obj_id, user_id, filename, filetitle, mimetype, ts, ass_id, late, team_id) " .
330  "VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)",
331  $ilDB->quote($next_id, "integer"),
332  $ilDB->quote($this->assignment->getExerciseId(), "integer"),
333  $ilDB->quote($user_id, "integer"),
334  $ilDB->quote($deliver_result["fullname"], "text"),
335  $ilDB->quote(ilFileUtils::getValidFilename($a_http_post_files["name"]), "text"),
336  $ilDB->quote($deliver_result["mimetype"], "text"),
337  $ilDB->quote(ilUtil::now(), "timestamp"),
338  $ilDB->quote($this->assignment->getId(), "integer"),
339  $ilDB->quote($this->isLate(), "integer"),
340  $ilDB->quote($team_id, "integer")
341  );
342  $ilDB->manipulate($query);
343 
344  if ($this->team) {
345  $this->team->writeLog(
347  $a_http_post_files["name"]
348  );
349  }
350 
351  return true;
352  }
353  return false;
354  }
355 
360  public function processUploadedZipFile($fileTmp)
361  {
362  $lng = $this->lng;
363 
364  // Create unzip-directory
365  $newDir = ilUtil::ilTempnam();
366  ilUtil::makeDir($newDir);
367 
368  $success = true;
369 
370  try {
371  ilFileUtils::processZipFile($newDir, $fileTmp, false);
372  ilFileUtils::recursive_dirscan($newDir, $filearray);
373 
374  // #18441 - check number of files in zip
375  $max_num = $this->assignment->getMaxFile();
376  if ($max_num) {
377  $current_num = sizeof($this->getFiles());
378  $zip_num = sizeof($filearray["file"]);
379  if ($current_num + $zip_num > $max_num) {
380  $success = false;
381  ilUtil::sendFailure($lng->txt("exc_upload_error") . " [Zip1]", true);
382  }
383  }
384 
385  if ($success) {
386  foreach ($filearray["file"] as $key => $filename) {
387  $a_http_post_files["name"] = ilFileUtils::utf8_encode($filename);
388  $a_http_post_files["type"] = "other";
389  $a_http_post_files["tmp_name"] = $filearray["path"][$key] . "/" . $filename;
390  $a_http_post_files["error"] = 0;
391  $a_http_post_files["size"] = filesize($filearray["path"][$key] . "/" . $filename);
392 
393  if (!$this->uploadFile($a_http_post_files, true)) {
394  $success = false;
395  ilUtil::sendFailure($lng->txt("exc_upload_error") . " [Zip2]", true);
396  }
397  }
398  }
399  } catch (ilFileUtilsException $e) {
400  $success = false;
401  ilUtil::sendFailure($e->getMessage());
402  }
403 
404  ilUtil::delDir($newDir);
405  return $success;
406  }
407 
408  public static function getAllAssignmentFiles($a_exc_id, $a_ass_id)
409  {
410  global $DIC;
411 
412  $ilDB = $DIC->database();
413 
414  $storage = new ilFSStorageExercise($a_exc_id, $a_ass_id);
415  $path = $storage->getAbsoluteSubmissionPath();
416 
418 
419  $query = "SELECT * FROM exc_returned WHERE ass_id = " .
420  $ilDB->quote($a_ass_id, "integer");
421 
422  $res = $ilDB->query($query);
423  while ($row = $ilDB->fetchAssoc($res)) {
424  if ($ass_type->isSubmissionAssignedToTeam()) {
425  $storage_id = $row["team_id"];
426  } else {
427  $storage_id = $row["user_id"];
428  }
429 
430  $row["timestamp"] = $row["ts"];
431  $row["filename"] = $path . "/" . $storage_id . "/" . basename($row["filename"]);
432  $delivered[] = $row;
433  }
434 
435  return $delivered ? $delivered : array();
436  }
437 
438  public static function getAssignmentFilesByUsers(int $a_exc_id, int $a_ass_id, array $a_users) : array
439  {
440  global $DIC;
441 
442  $ilDB = $DIC->database();
443 
444  $storage = new ilFSStorageExercise($a_exc_id, $a_ass_id);
445  $path = $storage->getAbsoluteSubmissionPath();
446 
448 
449  $query = "SELECT * FROM exc_returned WHERE ass_id = " .
450  $ilDB->quote($a_ass_id, "integer") .
451  " AND user_id IN (" . implode(',', $a_users) . ")";
452 
453  $res = $ilDB->query($query);
454  while ($row = $ilDB->fetchAssoc($res)) {
455  if ($ass_type->isSubmissionAssignedToTeam()) {
456  $storage_id = $row["team_id"];
457  } else {
458  $storage_id = $row["user_id"];
459  }
460 
461  $row["timestamp"] = $row["ts"];
462  $row["filename"] = $path . "/" . $storage_id . "/" . basename($row["filename"]);
463  $delivered[] = $row;
464  }
465 
466  return $delivered ? $delivered : array();
467  }
468 
477  public function getFiles(array $a_file_ids = null, $a_only_valid = false, $a_min_timestamp = null)
478  {
479  $ilDB = $this->db;
480 
481  $sql = "SELECT * FROM exc_returned" .
482  " WHERE ass_id = " . $ilDB->quote($this->getAssignment()->getId(), "integer");
483 
484  $sql .= " AND " . $this->getTableUserWhere(true);
485 
486 
487  if ($a_file_ids) {
488  $sql .= " AND " . $ilDB->in("returned_id", $a_file_ids, false, "integer");
489  }
490 
491  if ($a_min_timestamp) {
492  $sql .= " AND ts > " . $ilDB->quote($a_min_timestamp, "timestamp");
493  }
494 
495  $result = $ilDB->query($sql);
496 
497  $delivered_files = array();
498  if ($ilDB->numRows($result)) {
499  $path = $this->initStorage()->getAbsoluteSubmissionPath();
500 
501  while ($row = $ilDB->fetchAssoc($result)) {
502  // blog/portfolio/text submissions
503  if ($a_only_valid &&
504  !$row["filename"] &&
505  !(trim($row["atext"]))) {
506  continue;
507  }
508 
509  $row["owner_id"] = $row["user_id"];
510  $row["timestamp"] = $row["ts"];
511  $row["timestamp14"] = substr($row["ts"], 0, 4) .
512  substr($row["ts"], 5, 2) . substr($row["ts"], 8, 2) .
513  substr($row["ts"], 11, 2) . substr($row["ts"], 14, 2) .
514  substr($row["ts"], 17, 2);
515 
516  if ($this->getAssignment()->getAssignmentType()->isSubmissionAssignedToTeam()) {
517  $storage_id = $row["team_id"];
518  } else {
519  $storage_id = $row["user_id"];
520  }
521 
522 
523  $row["filename"] = $path .
524  "/" . $storage_id . "/" . basename($row["filename"]);
525 
526  // see 22301, 22719
527  if (is_file($row["filename"]) || (!$this->assignment->getAssignmentType()->usesFileUpload())) {
528  array_push($delivered_files, $row);
529  }
530  }
531  }
532 
533  return $delivered_files;
534  }
535 
542  public function lookupNewFiles($a_tutor = null)
543  {
544  $ilDB = $this->db;
546 
547  $tutor = ($a_tutor)
548  ? $a_tutor
549  : $ilUser->getId();
550 
551  $where = " AND " . $this->getTableUserWhere(true);
552 
553  $q = "SELECT exc_returned.returned_id AS id " .
554  "FROM exc_usr_tutor, exc_returned " .
555  "WHERE exc_returned.ass_id = exc_usr_tutor.ass_id " .
556  " AND exc_returned.user_id = exc_usr_tutor.usr_id " .
557  " AND exc_returned.ass_id = " . $ilDB->quote($this->getAssignment()->getId(), "integer") .
558  $where .
559  " AND exc_usr_tutor.tutor_id = " . $ilDB->quote($tutor, "integer") .
560  " AND exc_usr_tutor.download_time < exc_returned.ts ";
561 
562  $new_up_set = $ilDB->query($q);
563 
564  $new_up = array();
565  while ($new_up_rec = $ilDB->fetchAssoc($new_up_set)) {
566  $new_up[] = $new_up_rec["id"];
567  }
568 
569  return $new_up;
570  }
571 
578  public static function lookupExerciseIdForReturnedId($a_returned_id)
579  {
580  global $DIC;
581 
582  $ilDB = $DIC->database();
583 
584  $set = $ilDB->query("SELECT obj_id" .
585  " FROM exc_returned" .
586  " WHERE returned_id = " . $ilDB->quote($a_returned_id, "integer"));
587  $row = $ilDB->fetchAssoc($set);
588  return (int) $row["obj_id"];
589  }
590 
599  public static function findUserFiles($a_user_id, $a_filetitle)
600  {
601  global $DIC;
602 
603  $ilDB = $DIC->database();
604 
605  $set = $ilDB->query("SELECT obj_id, ass_id" .
606  " FROM exc_returned" .
607  " WHERE user_id = " . $ilDB->quote($a_user_id, "integer") .
608  " AND filetitle = " . $ilDB->quote($a_filetitle, "text"));
609  $res = array();
610  while ($row = $ilDB->fetchAssoc($set)) {
611  $res[$row["ass_id"]] = $row;
612  }
613  return $res;
614  }
615 
616  public function deleteAllFiles()
617  {
618  $files = array();
619  foreach ($this->getFiles() as $item) {
620  $files[] = $item["returned_id"];
621  }
622  if (sizeof($files)) {
623  $this->deleteSelectedFiles($files);
624  }
625  }
626 
633  public function deleteSelectedFiles(array $file_id_array)
634  {
635  $ilDB = $this->db;
636 
637 
638  $where = " AND " . $this->getTableUserWhere(true);
639 
640 
641  if (!sizeof($file_id_array)) {
642  return;
643  }
644 
645  if (count($file_id_array)) {
646  $result = $ilDB->query("SELECT * FROM exc_returned" .
647  " WHERE " . $ilDB->in("returned_id", $file_id_array, false, "integer") .
648  $where);
649 
650  if ($ilDB->numRows($result)) {
651  $result_array = array();
652  while ($row = $ilDB->fetchAssoc($result)) {
653  $row["timestamp"] = $row["ts"];
654  array_push($result_array, $row);
655  }
656 
657  // delete the entries in the database
658  $ilDB->manipulate("DELETE FROM exc_returned" .
659  " WHERE " . $ilDB->in("returned_id", $file_id_array, false, "integer") .
660  $where);
661 
662  // delete the files
663  $path = $this->initStorage()->getAbsoluteSubmissionPath();
664  foreach ($result_array as $key => $value) {
665  if ($value["filename"]) {
666  if ($this->team) {
667  $this->team->writeLog(
669  $value["filetitle"]
670  );
671  }
672 
673  if ($this->getAssignment()->getAssignmentType()->isSubmissionAssignedToTeam()) {
674  $storage_id = $value["team_id"];
675  } else {
676  $storage_id = $value["user_id"];
677  }
678 
679  $filename = $path . "/" . $storage_id . "/" . basename($value["filename"]);
680  if (file_exists($filename)) {
681  unlink($filename);
682  }
683  }
684  }
685  }
686  }
687  }
688 
695  public static function deleteUser($a_exc_id, $a_user_id)
696  {
697  foreach (ilExAssignment::getInstancesByExercise($a_exc_id) as $ass) {
698  $submission = new self($ass, $a_user_id);
699  $submission->deleteAllFiles();
700 
701  // remove from any team
702  $team = $submission->getTeam();
703  if ($team) {
704  $team->removeTeamMember($a_user_id);
705  }
706 
707  // #14900
708  $member_status = $ass->getMemberStatus($a_user_id);
709  $member_status->setStatus("notgraded");
710  $member_status->update();
711  }
712  }
713 
714  protected function getLastDownloadTime(array $a_user_ids)
715  {
716  $ilDB = $this->db;
718 
719  $q = "SELECT download_time FROM exc_usr_tutor WHERE " .
720  " ass_id = " . $ilDB->quote($this->getAssignment()->getId(), "integer") . " AND " .
721  $ilDB->in("usr_id", $a_user_ids, "", "integer") . " AND " .
722  " tutor_id = " . $ilDB->quote($ilUser->getId(), "integer");
723  $lu_set = $ilDB->query($q);
724  $lu_rec = $ilDB->fetchAssoc($lu_set);
725  return $lu_rec["download_time"];
726  }
727 
728  public function downloadFiles(array $a_file_ids = null, $a_only_new = false, $a_peer_review_mask_filename = false)
729  {
731  $lng = $this->lng;
732 
733  $user_ids = $this->getUserIds();
734  $is_team = $this->assignment->hasTeam();
735 
736  // get last download time
737  $download_time = null;
738  if ($a_only_new) {
739  $download_time = $this->getLastDownloadTime($user_ids);
740  }
741 
742  if ($this->is_tutor) {
743  $this->updateTutorDownloadTime();
744  }
745 
746  if ($a_peer_review_mask_filename) {
747  // process peer review sequence id
748  $peer_id = null;
749  foreach ($this->peer_review->getPeerReviewsByGiver($ilUser->getId()) as $idx => $item) {
750  if ($item["peer_id"] == $this->getUserId()) {
751  $peer_id = $idx + 1;
752  break;
753  }
754  }
755 
756  // this will remove personal info from zip-filename
757  $is_team = true;
758  }
759 
760  $files = $this->getFiles($a_file_ids, false, $download_time);
761  if ($files) {
762  if (sizeof($files) == 1) {
763  $file = array_pop($files);
764 
765  switch ($this->assignment->getType()) {
768  $file["filetitle"] = ilObjUser::_lookupName($file["user_id"]);
769  $file["filetitle"] = ilObject::_lookupTitle($this->assignment->getExerciseId()) . " - " .
770  $this->assignment->getTitle() . " - " .
771  $file["filetitle"]["firstname"] . " " .
772  $file["filetitle"]["lastname"] . " (" .
773  $file["filetitle"]["login"] . ").zip";
774  break;
775 
776  // @todo: generalize
778  $file["filetitle"] = ilObject::_lookupTitle($this->assignment->getExerciseId()) . " - " .
779  $this->assignment->getTitle() . " (Team " . $this->getTeam()->getId() . ").zip";
780  break;
781 
782  default:
783  break;
784  }
785 
786  if ($a_peer_review_mask_filename) {
787  $suffix = array_pop(explode(".", $file["filetitle"]));
788  $file["filetitle"] = $this->assignment->getTitle() . "_peer" . $peer_id . "." . $suffix;
789  } elseif ($file["late"]) {
790  $file["filetitle"] = $lng->txt("exc_late_submission") . " - " .
791  $file["filetitle"];
792  }
793 
794  $this->downloadSingleFile($file["user_id"], $file["filename"], $file["filetitle"], $file["team_id"]);
795  } else {
796  $array_files = array();
797  foreach ($files as $seq => $file) {
798  if ($this->assignment->getAssignmentType()->isSubmissionAssignedToTeam()) {
799  $storage_id = $file["team_id"];
800  } else {
801  $storage_id = $file["user_id"];
802  }
803 
804  $src = basename($file["filename"]);
805  if ($a_peer_review_mask_filename) {
806  $suffix = array_pop(explode(".", $src));
807  $tgt = $this->assignment->getTitle() . "_peer" . $peer_id .
808  "_" . (++$seq) . "." . $suffix;
809 
810  $array_files[$storage_id][] = array(
811  "src" => $src,
812  "tgt" => $tgt
813  );
814  } else {
815  $array_files[$storage_id][] = array(
816  "src" => $src,
817  "late" => $file["late"]
818  );
819  }
820  }
821 
822  $this->downloadMultipleFiles(
823  $array_files,
824  ($is_team ? null : $this->getUserId()),
825  $is_team
826  );
827  }
828  } else {
829  return false;
830  }
831 
832  return true;
833  }
834 
835  // Update the timestamp of the last download of current user (=tutor)
836  public function updateTutorDownloadTime()
837  {
839  $ilDB = $this->db;
840 
841  $exc_id = $this->assignment->getExerciseId();
842  $ass_id = $this->assignment->getId();
843 
844  foreach ($this->getUserIds() as $user_id) {
845  $ilDB->manipulateF(
846  "DELETE FROM exc_usr_tutor " .
847  "WHERE ass_id = %s AND usr_id = %s AND tutor_id = %s",
848  array("integer", "integer", "integer"),
849  array($ass_id, $user_id, $ilUser->getId())
850  );
851 
852  $ilDB->manipulateF(
853  "INSERT INTO exc_usr_tutor (ass_id, obj_id, usr_id, tutor_id, download_time) VALUES " .
854  "(%s, %s, %s, %s, %s)",
855  array("integer", "integer", "integer", "integer", "timestamp"),
856  array($ass_id, $exc_id, $user_id, $ilUser->getId(), ilUtil::now())
857  );
858  }
859  }
860 
861  protected function downloadSingleFile($a_user_id, $filename, $filetitle, $a_team_id)
862  {
863  if ($this->ass_type->isSubmissionAssignedToTeam()) {
864  $storage_id = $a_team_id;
865  } else {
866  $storage_id = $a_user_id;
867  }
868 
869  $filename = $this->initStorage()->getAbsoluteSubmissionPath() .
870  "/" . $storage_id . "/" . basename($filename);
871 
872  ilUtil::deliverFile($filename, $filetitle);
873  }
874 
875  protected function downloadMultipleFiles($a_filenames, $a_user_id, $a_multi_user = false)
876  {
877  $lng = $this->lng;
878 
879  $path = $this->initStorage()->getAbsoluteSubmissionPath();
880 
881  $cdir = getcwd();
882 
883  $zip = PATH_TO_ZIP;
884  $tmpdir = ilUtil::ilTempnam();
885  $tmpfile = ilUtil::ilTempnam();
886  $tmpzipfile = $tmpfile . ".zip";
887 
888  ilUtil::makeDir($tmpdir);
889  chdir($tmpdir);
890 
891  $assTitle = ilExAssignment::lookupTitle($this->assignment->getId());
892  $deliverFilename = str_replace(" ", "_", $assTitle);
893  if ($a_user_id > 0 && !$a_multi_user) {
894  $userName = ilObjUser::_lookupName($a_user_id);
895  $deliverFilename .= "_" . $userName["lastname"] . "_" . $userName["firstname"];
896  } else {
897  $deliverFilename .= "_files";
898  }
899  $orgDeliverFilename = trim($deliverFilename);
900  $deliverFilename = ilUtil::getASCIIFilename($orgDeliverFilename);
901  ilUtil::makeDir($tmpdir . "/" . $deliverFilename);
902  chdir($tmpdir . "/" . $deliverFilename);
903 
904  //copy all files to a temporary directory and remove them afterwards
905  $parsed_files = $duplicates = array();
906  foreach ($a_filenames as $storage_id => $files) {
907  $pathname = $path . "/" . $storage_id;
908 
909  foreach ($files as $filename) {
910  // peer review masked filenames, see deliverReturnedFiles()
911  if (isset($filename["tgt"])) {
912  $newFilename = $filename["tgt"];
913  $filename = $filename["src"];
914  } else {
915  $late = $filename["late"];
916  $filename = $filename["src"];
917 
918  // remove timestamp
919  $newFilename = trim($filename);
920  $pos = strpos($newFilename, "_");
921  if ($pos !== false) {
922  $newFilename = substr($newFilename, $pos + 1);
923  }
924  // #11070
925  $chkName = strtolower($newFilename);
926  if (array_key_exists($chkName, $duplicates)) {
927  $suffix = strrpos($newFilename, ".");
928  $newFilename = substr($newFilename, 0, $suffix) .
929  " (" . (++$duplicates[$chkName]) . ")" .
930  substr($newFilename, $suffix);
931  } else {
932  $duplicates[$chkName] = 1;
933  }
934 
935  if ($late) {
936  $newFilename = $lng->txt("exc_late_submission") . " - " .
937  $newFilename;
938  }
939  }
940 
941  $newFilename = ilUtil::getASCIIFilename($newFilename);
942  $newFilename = $tmpdir . DIRECTORY_SEPARATOR . $deliverFilename . DIRECTORY_SEPARATOR . $newFilename;
943  // copy to temporal directory
944  $oldFilename = $pathname . DIRECTORY_SEPARATOR . $filename;
945  if (!copy($oldFilename, $newFilename)) {
946  echo 'Could not copy ' . $oldFilename . ' to ' . $newFilename;
947  }
948  touch($newFilename, filectime($oldFilename));
949  $parsed_files[] = ilUtil::escapeShellArg($deliverFilename . DIRECTORY_SEPARATOR . basename($newFilename));
950  }
951  }
952 
953  chdir($tmpdir);
954  $zipcmd = $zip . " " . ilUtil::escapeShellArg($tmpzipfile) . " " . join(" ", $parsed_files);
955 
956  exec($zipcmd);
957  ilUtil::delDir($tmpdir);
958 
959  chdir($cdir);
960  ilUtil::deliverFile($tmpzipfile, $orgDeliverFilename . ".zip", "", false, true);
961  exit;
962  }
963 
972  public static function downloadAllAssignmentFiles(ilExAssignment $a_ass, array $members, $to_path)
973  {
974  global $DIC;
975 
976  $lng = $DIC->language();
977 
978  $storage = new ilFSStorageExercise($a_ass->getExerciseId(), $a_ass->getId());
979  $storage->create();
980 
981  ksort($members);
982  //$savepath = $this->getExercisePath() . "/" . $this->obj_id . "/";
983  $savepath = $storage->getAbsoluteSubmissionPath();
984  $cdir = getcwd();
985 
986 
987  // important check: if the directory does not exist
988  // ILIAS stays in the current directory (echoing only a warning)
989  // and the zip command below archives the whole ILIAS directory
990  // (including the data directory) and sends a mega file to the user :-o
991  if (!is_dir($savepath)) {
992  return;
993  }
994  // Safe mode fix
995  // chdir($this->getExercisePath());
996 
997  $tmpdir = $storage->getTempPath();
998  chdir($tmpdir);
999  $zip = PATH_TO_ZIP;
1000 
1001  // check free diskspace
1002  $dirsize = 0;
1003  foreach (array_keys($members) as $id) {
1004  $directory = $savepath . DIRECTORY_SEPARATOR . $id;
1005  $dirsize += ilUtil::dirsize($directory);
1006  }
1007  if ($dirsize > disk_free_space($tmpdir)) {
1008  return -1;
1009  }
1010 
1011  $ass_type = $a_ass->getType();
1012 
1013  // copy all member directories to the temporary folder
1014  // switch from id to member name and append the login if the member name is double
1015  // ensure that no illegal filenames will be created
1016  // remove timestamp from filename
1017  if ($a_ass->hasTeam()) {
1018  $team_dirs = array();
1019  $team_map = ilExAssignmentTeam::getAssignmentTeamMap($a_ass->getId());
1020  }
1021  foreach ($members as $id => $item) {
1022  $user = $item["name"];
1023  $user_files = $item["files"];
1024  $sourcedir = $savepath . DIRECTORY_SEPARATOR . $id;
1025  if (!is_dir($sourcedir)) {
1026  continue;
1027  }
1028 
1029  // group by teams
1030  $team_dir = "";
1031  if (is_array($team_map) &&
1032  array_key_exists($id, $team_map)) {
1033  $team_id = $team_map[$id];
1034  if (!array_key_exists($team_id, $team_dirs)) {
1035  $team_dir = $lng->txt("exc_team") . " " . $team_id;
1036  ilUtil::makeDir($team_dir);
1037  $team_dirs[$team_id] = $team_dir;
1038  }
1039  $team_dir = $team_dirs[$team_id] . DIRECTORY_SEPARATOR;
1040  }
1041 
1042  if ($a_ass->getAssignmentType()->isSubmissionAssignedToTeam()) {
1043  $targetdir = $team_dir . ilUtil::getASCIIFilename(
1044  $item["name"]
1045  );
1046  if ($targetdir == "") {
1047  continue;
1048  }
1049  } else {
1050  $targetdir = self::getDirectoryNameFromUserData($id);
1051  if ($a_ass->getAssignmentType()->usesTeams()) {
1052  $targetdir = $team_dir . $targetdir;
1053  }
1054  }
1055  ilUtil::makeDir($targetdir);
1056 
1057  $sourcefiles = scandir($sourcedir);
1058  $duplicates = array();
1059  foreach ($sourcefiles as $sourcefile) {
1060  if ($sourcefile == "." || $sourcefile == "..") {
1061  continue;
1062  }
1063 
1064  $targetfile = trim(basename($sourcefile));
1065  $pos = strpos($targetfile, "_");
1066  if ($pos !== false) {
1067  $targetfile = substr($targetfile, $pos + 1);
1068  }
1069 
1070  if ($a_ass->getAssignmentType()->getSubmissionType() == self::TYPE_REPO_OBJECT) {
1071  $obj_id = ilObject::_lookupObjId($targetfile);
1072  $obj_type = ilObject::_lookupType($obj_id);
1073  $targetfile = $obj_type . "_" . $obj_id . ".zip";
1074  }
1075 
1076 
1077  // #14536
1078  if (array_key_exists($targetfile, $duplicates)) {
1079  $suffix = strrpos($targetfile, ".");
1080  $targetfile = substr($targetfile, 0, $suffix) .
1081  " (" . (++$duplicates[$targetfile]) . ")" .
1082  substr($targetfile, $suffix);
1083  } else {
1084  $duplicates[$targetfile] = 1;
1085  }
1086 
1087  // late submission?
1088  if (is_array($user_files)) { // see #23900
1089  foreach ($user_files as $file) {
1090  if (basename($file["filename"]) == $sourcefile) {
1091  if ($file["late"]) {
1092  $targetfile = $lng->txt("exc_late_submission") . " - " .
1093  $targetfile;
1094  }
1095  break;
1096  }
1097  }
1098  }
1099 
1100  $targetfile = ilUtil::getASCIIFilename($targetfile);
1101  $targetfile = $targetdir . DIRECTORY_SEPARATOR . $targetfile;
1102  $sourcefile = $sourcedir . DIRECTORY_SEPARATOR . $sourcefile;
1103 
1104  if (!copy($sourcefile, $targetfile)) {
1105  throw new ilExerciseException("Could not copy " . basename($sourcefile) . " to '" . $targetfile . "'.");
1106  } else {
1107  // preserve time stamp
1108  touch($targetfile, filectime($sourcefile));
1109 
1110  // blogs and portfolios are stored as zip and have to be unzipped
1113  ilUtil::unzip($targetfile);
1114  unlink($targetfile);
1115  }
1116  }
1117  }
1118  }
1119  $tmpzipfile = ilUtil::getASCIIFilename($lng->txt("exc_ass_submission_zip")) . ".zip";
1120  // Safe mode fix
1121  $zipcmd = $zip . " -r " . ilUtil::escapeShellArg($tmpzipfile) . " .";
1122  exec($zipcmd);
1123  //$path_final_zip_file = $to_path.DIRECTORY_SEPARATOR."Submissions/".$tmpzipfile;
1124  $path_final_zip_file = $to_path . DIRECTORY_SEPARATOR . $tmpzipfile;
1125 
1126  if (file_exists($tmpdir . DIRECTORY_SEPARATOR . $tmpzipfile)) {
1127  copy($tmpzipfile, $path_final_zip_file);
1128  ilUtil::delDir($tmpdir);
1129 
1130  //unzip the submissions zip file.(decided to unzip to allow the excel link the files more obvious when blog/portfolio)
1131  chdir($to_path);
1132  //TODO Bug in ilUtil -> if flat unzip fails. We can get rid of creating Submissions directory
1133  //ilUtil::unzip($path_final_zip_file,FALSE, TRUE);
1134  ilUtil::unzip($path_final_zip_file);
1135  unlink($path_final_zip_file);
1136  }
1137 
1138  chdir($cdir);
1139  }
1140 
1141 
1148  public function getTableUserWhere($a_team_mode = false)
1149  {
1150  $ilDB = $this->db;
1151 
1152  if ($this->getAssignment()->getAssignmentType()->isSubmissionAssignedToTeam()) {
1153  $team_id = $this->getTeam()->getId();
1154  $where = " team_id = " . $ilDB->quote($team_id, "integer") . " ";
1155  } else {
1156  if ($a_team_mode) {
1157  $where = " " . $ilDB->in("user_id", $this->getUserIds(), "", "integer") . " ";
1158  } else {
1159  $where = " user_id = " . $ilDB->quote($this->getUserId(), "integer");
1160  }
1161  }
1162  return $where;
1163  }
1164 
1165 
1172  public function getLastSubmission()
1173  {
1174  $ilDB = $this->db;
1175 
1176  $ilDB->setLimit(1);
1177 
1178  $q = "SELECT obj_id,user_id,ts FROM exc_returned" .
1179  " WHERE ass_id = " . $ilDB->quote($this->assignment->getId(), "integer") .
1180  " AND " . $this->getTableUserWhere(true) .
1181  " AND (filename IS NOT NULL OR atext IS NOT NULL)" .
1182  " AND ts IS NOT NULL" .
1183  " ORDER BY ts DESC";
1184  $usr_set = $ilDB->query($q);
1185  $array = $ilDB->fetchAssoc($usr_set);
1186  return ilUtil::getMySQLTimestamp($array["ts"]);
1187  }
1188 
1193  public function getLastOpeningHTMLView()
1194  {
1195  $this->db->setLimit(1);
1196 
1197  $q = "SELECT web_dir_access_time FROM exc_returned" .
1198  " WHERE ass_id = " . $this->db->quote($this->assignment->getId(), "integer") .
1199  " AND (filename IS NOT NULL OR atext IS NOT NULL)" .
1200  " AND web_dir_access_time IS NOT NULL" .
1201  " AND " . $this->getTableUserWhere(true) .
1202  " ORDER BY web_dir_access_time DESC";
1203 
1204  $res = $this->db->query($q);
1205 
1206  $data = $this->db->fetchAssoc($res);
1207 
1208  return ilUtil::getMySQLTimestamp($data["web_dir_access_time"]);
1209  }
1210 
1211 
1212  //
1213  // OBJECTS
1214  //
1215 
1224  public function addResourceObject($a_wsp_id, $a_text = null)
1225  {
1226  $ilDB = $this->db;
1227 
1228  if ($this->getAssignment()->getAssignmentType()->isSubmissionAssignedToTeam()) {
1229  $user_id = 0;
1230  $team_id = $this->getTeam()->getId();
1231  } else {
1232  $user_id = $this->getUserId();
1233  $team_id = 0;
1234  }
1235 
1236  // repository objects must be unique in submissions
1237  // the same repo object cannot be used in different submissions or even different assignment/exercises
1238  // why? -> the access handling would fail, since the access depends e.g. on teams or even phase of the
1239  // assignment
1240  if ($this->getAssignment()->getAssignmentType()->getSubmissionType() == ilExSubmission::TYPE_REPO_OBJECT) {
1241  $repos_ass_type_ids = $this->ass_types->getIdsForSubmissionType(ilExSubmission::TYPE_REPO_OBJECT);
1242  $subs = $this->getSubmissionsForFilename($a_wsp_id, $repos_ass_type_ids);
1243  if (count($subs) > 0) {
1244  throw new ilExerciseException("Repository object $a_wsp_id is already assigned to another assignment.");
1245  }
1246  }
1247 
1248  $next_id = $ilDB->nextId("exc_returned");
1249  $query = sprintf(
1250  "INSERT INTO exc_returned " .
1251  "(returned_id, obj_id, user_id, filetitle, ass_id, ts, atext, late, team_id) " .
1252  "VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)",
1253  $ilDB->quote($next_id, "integer"),
1254  $ilDB->quote($this->assignment->getExerciseId(), "integer"),
1255  $ilDB->quote($user_id, "integer"),
1256  $ilDB->quote($a_wsp_id, "text"),
1257  $ilDB->quote($this->assignment->getId(), "integer"),
1258  $ilDB->quote(ilUtil::now(), "timestamp"),
1259  $ilDB->quote($a_text, "text"),
1260  $ilDB->quote($this->isLate(), "integer"),
1261  $ilDB->quote($team_id, "integer")
1262  );
1263  $ilDB->manipulate($query);
1264 
1265  return $next_id;
1266  }
1267 
1273  public function deleteResourceObject($a_returned_id)
1274  {
1275  $ilDB = $this->db;
1276 
1277  $ilDB->manipulate("DELETE FROM exc_returned" .
1278  " WHERE obj_id = " . $ilDB->quote($this->assignment->getExerciseId(), "integer") .
1279  " AND " . $this->getTableUserWhere(false) .
1280  " AND ass_id = " . $ilDB->quote($this->assignment->getId(), "integer") .
1281  " AND returned_id = " . $ilDB->quote($a_returned_id, "integer"));
1282  }
1283 
1290  public function updateTextSubmission($a_text)
1291  {
1292  $ilDB = $this->db;
1293 
1294  $files = $this->getFiles();
1295 
1296  // no text = remove submission
1297  if (!trim($a_text)) {
1298  $this->deleteAllFiles();
1299  return;
1300  }
1301 
1302  if (!$files) {
1303  return $this->addResourceObject("TEXT", $a_text);
1304  } else {
1305  $files = array_shift($files);
1306  $id = $files["returned_id"];
1307  if ($id) {
1308  $ilDB->manipulate("UPDATE exc_returned" .
1309  " SET atext = " . $ilDB->quote($a_text, "text") .
1310  ", ts = " . $ilDB->quote(ilUtil::now(), "timestamp") .
1311  ", late = " . $ilDB->quote($this->isLate(), "integer") .
1312  " WHERE returned_id = " . $ilDB->quote($id, "integer"));
1313  return $id;
1314  }
1315  }
1316  }
1317 
1318  //
1319  // GUI helper
1320  //
1321 
1322  // :TODO:
1323 
1324  public function getDownloadedFilesInfoForTableGUIS($a_parent_obj, $a_parent_cmd = null)
1325  {
1326  $lng = $this->lng;
1327  $ilCtrl = $this->ctrl;
1328 
1329  $result = array();
1330  $result["files"]["count"] = "---";
1331 
1332  // submission:
1333  // see if files have been resubmmited after solved
1334  $last_sub = $this->getLastSubmission();
1335  if ($last_sub) {
1336  $last_sub = ilDatePresentation::formatDate(new ilDateTime($last_sub, IL_CAL_DATETIME));
1337  } else {
1338  $last_sub = "---";
1339  }
1340  /* #13741 - status_time has been reduced to grading (mark/status)
1341  if (self::lookupUpdatedSubmission($a_ass_id, $a_user_id) == 1)
1342  {
1343  $last_sub = "<b>".$last_sub."</b>";
1344  }
1345  */
1346  $result["last_submission"]["txt"] = $lng->txt("exc_last_submission");
1347  $result["last_submission"]["value"] = $last_sub;
1348 
1349  // #16994
1350  $ilCtrl->setParameterByClass("ilexsubmissionfilegui", "member_id", $this->getUserId());
1351 
1352  // assignment type specific
1353  switch ($this->assignment->getType()) {
1355  // data is merged by team - see above
1356  // fallthrough
1357 
1359  $all_files = $this->getFiles();
1360  $late_files = 0;
1361  foreach ($all_files as $file) {
1362  if ($file["late"]) {
1363  $late_files++;
1364  }
1365  }
1366 
1367  // nr of submitted files
1368  $result["files"]["txt"] = $lng->txt("exc_files_returned");
1369  if ($late_files) {
1370  $result["files"]["txt"] .= ' - <span class="warning">' . $lng->txt("exc_late_submission") . " (" . $late_files . ")</span>";
1371  }
1372  $sub_cnt = count($all_files);
1373  $new = $this->lookupNewFiles();
1374  if (count($new) > 0) {
1375  $sub_cnt .= " " . sprintf($lng->txt("cnt_new"), count($new));
1376  }
1377 
1378  $result["files"]["count"] = $sub_cnt;
1379 
1380  // download command
1381  if ($sub_cnt > 0) {
1382  $result["files"]["download_url"] =
1383  $ilCtrl->getLinkTargetByClass("ilexsubmissionfilegui", "downloadReturned");
1384 
1385  if (count($new) <= 0) {
1386  $result["files"]["download_txt"] = $lng->txt("exc_tbl_action_download_files");
1387  } else {
1388  $result["files"]["download_txt"] = $lng->txt("exc_tbl_action_download_all_files");
1389  }
1390 
1391  // download new files only
1392  if (count($new) > 0) {
1393  $result["files"]["download_new_url"] =
1394  $ilCtrl->getLinkTargetByClass("ilexsubmissionfilegui", "downloadNewReturned");
1395 
1396  $result["files"]["download_new_txt"] = $lng->txt("exc_tbl_action_download_new_files");
1397  }
1398  }
1399  break;
1400 
1402  $result["files"]["txt"] = $lng->txt("exc_blog_returned");
1403  $blogs = $this->getFiles();
1404  if ($blogs) {
1405  $blogs = array_pop($blogs);
1406  if ($blogs && substr($blogs["filename"], -1) != "/") {
1407  if ($blogs["late"]) {
1408  $result["files"]["txt"] .= ' - <span class="warning">' . $lng->txt("exc_late_submission") . "</span>";
1409  }
1410 
1411  $result["files"]["count"] = 1;
1412 
1413  $result["files"]["download_url"] =
1414  $ilCtrl->getLinkTargetByClass("ilexsubmissionfilegui", "downloadReturned");
1415 
1416  $result["files"]["download_txt"] = $lng->txt("exc_tbl_action_download_files");
1417  }
1418  }
1419  break;
1420 
1422  $result["files"]["txt"] = $lng->txt("exc_portfolio_returned");
1423  $portfolios = $this->getFiles();
1424  if ($portfolios) {
1425  $portfolios = array_pop($portfolios);
1426  if ($portfolios && substr($portfolios["filename"], -1) != "/") {
1427  if ($portfolios["late"]) {
1428  $result["files"]["txt"] .= ' - <span class="warning">' . $lng->txt("exc_late_submission") . "</span>";
1429  }
1430 
1431  $result["files"]["count"] = 1;
1432 
1433  $result["files"]["download_url"] =
1434  $ilCtrl->getLinkTargetByClass("ilexsubmissionfilegui", "downloadReturned");
1435 
1436  $result["files"]["download_txt"] = $lng->txt("exc_tbl_action_download_files");
1437  }
1438  }
1439  break;
1440 
1442  $result["files"]["txt"] = $lng->txt("exc_files_returned_text");
1443  $files = $this->getFiles();
1444  if ($files) {
1445  $result["files"]["count"] = 1;
1446 
1447  $files = array_shift($files);
1448  if (trim($files["atext"])) {
1449  if ($files["late"]) {
1450  $result["files"]["txt"] .= ' - <span class="warning">' . $lng->txt("exc_late_submission") . "</span>";
1451  }
1452 
1453  $result["files"]["download_url"] =
1454  $ilCtrl->getLinkTargetByClass("ilexsubmissiontextgui", "showAssignmentText");
1455 
1456  $result["files"]["download_txt"] = $lng->txt("exc_tbl_action_text_assignment_show");
1457  }
1458  }
1459  break;
1460 
1462  $result["files"]["txt"] = $lng->txt("exc_wiki_returned");
1463  $objs = $this->getFiles();
1464  if ($objs) {
1465  $objs = array_pop($objs);
1466  if ($objs && substr($objs["filename"], -1) != "/") {
1467  if ($objs["late"]) {
1468  $result["files"]["txt"] .= ' - <span class="warning">' . $lng->txt("exc_late_submission") . "</span>";
1469  }
1470 
1471  $result["files"]["count"] = 1;
1472 
1473  $result["files"]["download_url"] =
1474  $ilCtrl->getLinkTargetByClass("ilexsubmissionfilegui", "downloadReturned");
1475 
1476  $result["files"]["download_txt"] = $lng->txt("exc_tbl_action_download_files");
1477  }
1478  }
1479  break;
1480  }
1481 
1482  $ilCtrl->setParameterByClass("ilexsubmissionfilegui", "member_id", "");
1483 
1484  return $result;
1485  }
1486 
1494  public static function getSubmissionsForFilename($a_filename, $a_assignment_types = array())
1495  {
1496  global $DIC;
1497 
1498  $db = $DIC->database();
1499 
1500  $query = "SELECT * FROM exc_returned r LEFT JOIN exc_assignment a" .
1501  " ON (r.ass_id = a.id) " .
1502  " WHERE r.filetitle = " . $db->quote($a_filename, "string");
1503 
1504  if (is_array($a_assignment_types) && count($a_assignment_types) > 0) {
1505  $query .= " AND " . $db->in("a.type", $a_assignment_types, false, "integer");
1506  }
1507 
1508  $set = $db->query($query);
1509  $rets = array();
1510  while ($rec = $db->fetchAssoc($set)) {
1511  $rets[] = $rec;
1512  }
1513 
1514 
1515  return $rets;
1516  }
1517 
1518  /*
1519  * @param $a_user_id
1520  * @return string
1521  */
1522  public static function getDirectoryNameFromUserData($a_user_id)
1523  {
1524  $userName = ilObjUser::_lookupName($a_user_id);
1525  $targetdir = ilUtil::getASCIIFilename(
1526  trim($userName["lastname"]) . "_" .
1527  trim($userName["firstname"]) . "_" .
1528  trim($userName["login"]) . "_" .
1529  $userName["user_id"]
1530  );
1531 
1532  return $targetdir;
1533  }
1534 
1540  public static function getAssignmentParticipants(int $a_exercise_id, int $a_ass_id) : array
1541  {
1542  global $DIC;
1543 
1544  $ilDB = $DIC->database();
1545 
1546  $participants = array();
1547  $query = "SELECT user_id FROM exc_returned WHERE ass_id = " .
1548  $ilDB->quote($a_ass_id, "integer") .
1549  " AND obj_id = " .
1550  $ilDB->quote($a_exercise_id, "integer");
1551 
1552  $res = $ilDB->query($query);
1553 
1554  while ($row = $ilDB->fetchAssoc($res)) {
1555  $participants[] = $row['user_id'];
1556  }
1557 
1558  return $participants;
1559  }
1560 }
static _lookupName($a_user_id)
lookup user name
getStorageId()
Get storage id.
static deleteUser($a_exc_id, $a_user_id)
Delete all delivered files of user.
exit
Definition: login.php:29
Exercise assignment.
addResourceObject($a_wsp_id, $a_text=null)
Add personal resource or repository object (ref_id) to assigment.
$data
Definition: storeScorm.php:23
const IL_CAL_DATETIME
$result
lookupNewFiles($a_tutor=null)
Check how much files have been uploaded by the learner after the last download of the tutor...
static getAssignmentTeamMap($a_ass_id)
Get team structure for assignment.
getId()
Get assignment id.
static getMySQLTimestamp($a_ts)
Get MySQL timestamp in 4.1.x or higher format (yyyy-mm-dd hh:mm:ss) This function converts a timestam...
$valid
static unzip($a_file, $overwrite=false, $a_flat=false)
unzip file
static downloadAllAssignmentFiles(ilExAssignment $a_ass, array $members, $to_path)
Download all submitted files of an assignment (all user)
Exercise assignment team.
static _lookupTitle($a_id)
lookup object title
static lookupExerciseIdForReturnedId($a_returned_id)
Get exercise from submission id (used in ilObjMediaObject)
static now()
Return current timestamp in Y-m-d H:i:s format.
static getASCIIFilename($a_filename)
convert utf8 to ascii filename
downloadSingleFile($a_user_id, $filename, $filetitle, $a_team_id)
static getDirectoryNameFromUserData($a_user_id)
static formatDate(ilDateTime $date, $a_skip_day=false, $a_include_wd=false, $include_seconds=false)
Format a date public.
getLastDownloadTime(array $a_user_ids)
static getAssignmentParticipants(int $a_exercise_id, int $a_ass_id)
user()
Definition: user.php:4
static getInstanceByIds($a_ass_id, $a_user_id=0)
Get instance by IDs (recommended for consumer code)
global $ilCtrl
Definition: ilias.php:18
Exercise peer review.
getExerciseId()
Get exercise id.
__construct(ilExAssignment $a_ass, $a_user_id, ilExAssignmentTeam $a_team=null, $a_is_tutor=false, $a_public_submissions=false)
$success
Definition: Utf8Test.php:86
foreach($_POST as $key=> $value) $res
uploadFile($a_http_post_files, $unzip=false)
Save submitted file of user.
isInTeam($a_user_id=null)
static getInstanceByUserId($a_assignment_id, $a_user_id, $a_create_on_demand=false)
static getInstance()
Get instance.
static _lookupObjId($a_id)
static getInstancesByExercise($a_exc_id)
getLastSubmission()
TODO -> get rid of getTableUserWhere and move to repository class Get the date of the last submission...
static processZipFile($a_directory, $a_file, $structure, $ref_id=null, $containerType=null, $tree=null, $access_handler=null)
unzips in given directory and processes uploaded zip for use as single files
$ilUser
Definition: imgupload.php:18
$query
downloadFiles(array $a_file_ids=null, $a_only_new=false, $a_peer_review_mask_filename=false)
static getSubmissionsForFilename($a_filename, $a_assignment_types=array())
Get assignment return entries for a filename.
static getAssignmentFilesByUsers(int $a_exc_id, int $a_ass_id, array $a_users)
static _lookupType($a_id, $a_reference=false)
lookup object type
static findUserFiles($a_user_id, $a_filetitle)
Check if given file was assigned.
getLastOpeningHTMLView()
TODO -> get rid of getTableUserWhere and move to repository class Get a mysql timestamp from the last...
static sendFailure($a_info="", $a_keep=false)
Send Failure Message to Screen.
$filename
Definition: buildRTE.php:89
static makeDir($a_dir)
creates a new directory and inherits all filesystem permissions of the parent directory You may pass ...
static ilTempnam($a_temp_path=null)
Returns a unique and non existing Path for e temporary file or directory.
static dirsize($directory)
get size of a directory or a file.
static utf8_encode($string)
utf8-encodes string if it is not a valid utf8-string.
downloadMultipleFiles($a_filenames, $a_user_id, $a_multi_user=false)
static lookupType($a_id)
Lookup type.
processUploadedZipFile($fileTmp)
processes errorhandling etc for uploaded archive
static escapeShellArg($a_arg)
deleteResourceObject($a_returned_id)
Remove personal resource to assigment.
global $ilDB
$DIC
Definition: xapitoken.php:46
getTableUserWhere($a_team_mode=false)
Get user/team where clause.
Exercise submission //TODO: This class has to much static methods related to delivered "files"...
static recursive_dirscan($dir, &$arr)
Recursively scans a given directory and writes path and filename into referenced array.
static getAllAssignmentFiles($a_exc_id, $a_ass_id)
getAssignmentType()
Get assignment type.
static delDir($a_dir, $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
getFiles(array $a_file_ids=null, $a_only_valid=false, $a_min_timestamp=null)
Get submission items (not only files)
getDownloadedFilesInfoForTableGUIS($a_parent_obj, $a_parent_cmd=null)
updateTextSubmission($a_text)
Handle text assignment submissions.
static getValidFilename($a_filename)
Get valid filename.
static lookupTitle($a_id)
Lookup title.
static deliverFile( $a_file, $a_filename, $a_mime='', $isInline=false, $removeAfterDelivery=false, $a_exit_after=true)
deliver file for download via browser.
Class to report exception.
deleteSelectedFiles(array $file_id_array)
Deletes already delivered files.
Exercise exceptions class.