ILIAS  Release_4_4_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilExAssignment.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_UPLOAD = 1;
14  const TYPE_BLOG = 2;
15  const TYPE_PORTFOLIO = 3;
16  const TYPE_UPLOAD_TEAM = 4;
17  const TYPE_TEXT = 5;
18 
22  const TEAM_LOG_ADD_FILE = 4;
24 
25  protected $id;
26  protected $exc_id;
27  protected $type;
28  protected $start_time;
29  protected $deadline;
30  protected $instruction;
31  protected $title;
32  protected $mandatory;
33  protected $order_nr;
34  protected $peer;
35  protected $peer_min;
36  protected $peer_dl;
37  protected $feedback_file;
38  protected $feedback_cron;
39 
43  function __construct($a_id = 0)
44  {
45  $this->setType(self::TYPE_UPLOAD);
46 
47  if ($a_id > 0)
48  {
49  $this->setId($a_id);
50  $this->read();
51  }
52  }
53 
59  function setId($a_val)
60  {
61  $this->id = $a_val;
62  }
63 
69  function getId()
70  {
71  return $this->id;
72  }
73 
79  function setExerciseId($a_val)
80  {
81  $this->exc_id = $a_val;
82  }
83 
89  function getExerciseId()
90  {
91  return $this->exc_id;
92  }
93 
99  function setStartTime($a_val)
100  {
101  $this->start_time = $a_val;
102  }
103 
109  function getStartTime()
110  {
111  return $this->start_time;
112  }
113 
119  function setDeadline($a_val)
120  {
121  $this->deadline = $a_val;
122  }
123 
129  function getDeadline()
130  {
131  return $this->deadline;
132  }
133 
139  function setInstruction($a_val)
140  {
141  $this->instruction = $a_val;
142  }
143 
149  function getInstruction()
150  {
151  return $this->instruction;
152  }
153 
159  function setTitle($a_val)
160  {
161  $this->title = $a_val;
162  }
163 
169  function getTitle()
170  {
171  return $this->title;
172  }
173 
179  function setMandatory($a_val)
180  {
181  $this->mandatory = $a_val;
182  }
183 
189  function getMandatory()
190  {
191  return $this->mandatory;
192  }
193 
199  function setOrderNr($a_val)
200  {
201  $this->order_nr = $a_val;
202  }
203 
209  function getOrderNr()
210  {
211  return $this->order_nr;
212  }
213 
219  function setType($a_value)
220  {
221  if($this->isValidType($a_value))
222  {
223  $this->type = (int)$a_value;
224 
225  if($this->type == self::TYPE_UPLOAD_TEAM)
226  {
227  $this->setPeerReview(false);
228  }
229  }
230  }
231 
237  function getType()
238  {
239  return $this->type;
240  }
241 
248  function isValidType($a_value)
249  {
250  if(in_array((int)$a_value, array(self::TYPE_UPLOAD, self::TYPE_BLOG,
251  self::TYPE_PORTFOLIO, self::TYPE_UPLOAD_TEAM, self::TYPE_TEXT)))
252  {
253  return true;
254  }
255  return false;
256  }
257 
263  function setPeerReview($a_value)
264  {
265  $this->peer = (bool)$a_value;
266  }
267 
273  function getPeerReview()
274  {
275  return (bool)$this->peer;
276  }
277 
283  function setPeerReviewMin($a_value)
284  {
285  $this->peer_min = (int)$a_value;
286  }
287 
293  function getPeerReviewMin()
294  {
295  return (int)$this->peer_min;
296  }
297 
303  function setPeerReviewDeadline($a_val)
304  {
305  $this->peer_dl = $a_val;
306  }
307 
314  {
315  return $this->peer_dl;
316  }
317 
323  function setFeedbackFile($a_value)
324  {
325  $this->feedback_file = (string)$a_value;
326  }
327 
333  function getFeedbackFile()
334  {
335  return (string)$this->feedback_file;
336  }
337 
343  function setFeedbackCron($a_value)
344  {
345  $this->feedback_cron = (string)$a_value;
346  }
347 
353  function hasFeedbackCron()
354  {
355  return (bool)$this->feedback_cron;
356  }
357 
361  function read()
362  {
363  global $ilDB;
364 
365  $set = $ilDB->query("SELECT * FROM exc_assignment ".
366  " WHERE id = ".$ilDB->quote($this->getId(), "integer")
367  );
368  while ($rec = $ilDB->fetchAssoc($set))
369  {
370  $this->setExerciseId($rec["exc_id"]);
371  $this->setDeadline($rec["time_stamp"]);
372  $this->setInstruction($rec["instruction"]);
373  $this->setTitle($rec["title"]);
374  $this->setStartTime($rec["start_time"]);
375  $this->setOrderNr($rec["order_nr"]);
376  $this->setMandatory($rec["mandatory"]);
377  $this->setType($rec["type"]);
378  $this->setPeerReview($rec["peer"]);
379  $this->setPeerReviewMin($rec["peer_min"]);
380  $this->setPeerReviewDeadline($rec["peer_dl"]);
381  $this->setFeedbackFile($rec["fb_file"]);
382  $this->setFeedbackCron($rec["fb_cron"]);
383  }
384  }
385 
389  function save()
390  {
391  global $ilDB;
392 
393  if ($this->getOrderNr() == 0)
394  {
395  $this->setOrderNr(
397  + 10);
398  }
399 
400  $next_id = $ilDB->nextId("exc_assignment");
401  $ilDB->insert("exc_assignment", array(
402  "id" => array("integer", $next_id),
403  "exc_id" => array("integer", $this->getExerciseId()),
404  "time_stamp" => array("integer", $this->getDeadline()),
405  "instruction" => array("clob", $this->getInstruction()),
406  "title" => array("text", $this->getTitle()),
407  "start_time" => array("integer", $this->getStartTime()),
408  "order_nr" => array("integer", $this->getOrderNr()),
409  "mandatory" => array("integer", $this->getMandatory()),
410  "type" => array("integer", $this->getType()),
411  "peer" => array("integer", $this->getPeerReview()),
412  "peer_min" => array("integer", $this->getPeerReviewMin()),
413  "peer_dl" => array("integer", $this->getPeerReviewDeadline()),
414  "fb_file" => array("text", $this->getFeedbackFile()),
415  "fb_cron" => array("integer", $this->hasFeedbackCron()))
416  );
417  $this->setId($next_id);
418  $exc = new ilObjExercise($this->getExerciseId(), false);
419  $exc->updateAllUsersStatus();
421  }
422 
426  function update()
427  {
428  global $ilDB;
429 
430  $ilDB->update("exc_assignment",
431  array(
432  "exc_id" => array("integer", $this->getExerciseId()),
433  "time_stamp" => array("integer", $this->getDeadline()),
434  "instruction" => array("clob", $this->getInstruction()),
435  "title" => array("text", $this->getTitle()),
436  "start_time" => array("integer", $this->getStartTime()),
437  "order_nr" => array("integer", $this->getOrderNr()),
438  "mandatory" => array("integer", $this->getMandatory()),
439  "type" => array("integer", $this->getType()),
440  "peer" => array("integer", $this->getPeerReview()),
441  "peer_min" => array("integer", $this->getPeerReviewMin()),
442  "peer_dl" => array("integer", $this->getPeerReviewDeadline()),
443  "fb_file" => array("text", $this->getFeedbackFile()),
444  "fb_cron" => array("integer", $this->hasFeedbackCron())
445  ),
446  array(
447  "id" => array("integer", $this->getId()),
448  ));
449  $exc = new ilObjExercise($this->getExerciseId(), false);
450  $exc->updateAllUsersStatus();
451  }
452 
456  function delete()
457  {
458  global $ilDB;
459 
460  $this->deleteFeedbackFile();
461 
462  $ilDB->manipulate("DELETE FROM exc_assignment WHERE ".
463  " id = ".$ilDB->quote($this->getId(), "integer")
464  );
465  $exc = new ilObjExercise($this->getExerciseId(), false);
466  $exc->updateAllUsersStatus();
467  }
468 
470  {
471  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
472  $storage = new ilFSStorageExercise($this->getExerciseId(), $this->getId());
473  $path = $storage->getGlobalFeedbackPath();
475  }
476 
477  function handleFeedbackFileUpload(array $a_file)
478  {
479  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
480  $storage = new ilFSStorageExercise($this->getExerciseId(), $this->getId());
481  $path = $storage->getGlobalFeedbackPath();
482  ilUtil::delDir($path, true);
483  if(@move_uploaded_file($a_file["tmp_name"], $path."/".$a_file["name"]))
484  {
485  $this->setFeedbackFile($a_file["name"]);
486  return true;
487  }
488  return false;
489  }
490 
492  {
493  $file = $this->getFeedbackFile();
494  if($file)
495  {
496  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
497  $storage = new ilFSStorageExercise($this->getExerciseId(), $this->getId());
498  $path = $storage->getGlobalFeedbackPath();
499  return $path."/".$file;
500  }
501  }
502 
506  static function getAssignmentDataOfExercise($a_exc_id)
507  {
508  global $ilDB;
509 
510  $set = $ilDB->query("SELECT * FROM exc_assignment ".
511  " WHERE exc_id = ".$ilDB->quote($a_exc_id, "integer").
512  " ORDER BY order_nr ASC");
513  $data = array();
514 
515  $order_val = 10;
516  while ($rec = $ilDB->fetchAssoc($set))
517  {
518 
519  $data[] = array(
520  "id" => $rec["id"],
521  "exc_id" => $rec["exc_id"],
522  "deadline" => $rec["time_stamp"],
523  "instruction" => $rec["instruction"],
524  "title" => $rec["title"],
525  "start_time" => $rec["start_time"],
526  "order_val" => $order_val,
527  "mandatory" => $rec["mandatory"],
528  "type" => $rec["type"],
529  "peer" => $rec["peer"],
530  "peer_min" => $rec["peer_min"],
531  "peer_dl" => $rec["peer_dl"],
532  "fb_file" => $rec["fb_file"],
533  "fb_cron" => $rec["fb_cron"],
534  );
535  $order_val += 10;
536  }
537  return $data;
538  }
539 
546  function cloneAssignmentsOfExercise($a_old_exc_id, $a_new_exc_id)
547  {
548  $ass_data = ilExAssignment::getAssignmentDataOfExercise($a_old_exc_id);
549  foreach ($ass_data as $d)
550  {
551  // clone assignment
552  $new_ass = new ilExAssignment();
553  $new_ass->setExerciseId($a_new_exc_id);
554  $new_ass->setTitle($d["title"]);
555  $new_ass->setDeadline($d["deadline"]);
556  $new_ass->setInstruction($d["instruction"]);
557  $new_ass->setMandatory($d["mandatory"]);
558  $new_ass->setOrderNr($d["order_val"]);
559  $new_ass->setStartTime($d["start_time"]);
560  $new_ass->setType($d["type"]);
561  $new_ass->setPeerReview($d["peer"]);
562  $new_ass->setPeerReviewMin($d["peer_min"]);
563  $new_ass->setPeerReviewDeadline($d["peer_dl"]);
564  $new_ass->setFeedbackFile($d["fb_file"]);
565  $new_ass->setFeedbackCron($d["fb_cron"]);
566  $new_ass->save();
567 
568  // clone assignment files
569  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
570  $old_storage = new ilFSStorageExercise($a_old_exc_id, (int) $d["id"]);
571  $new_storage = new ilFSStorageExercise($a_new_exc_id, (int) $new_ass->getId());
572  $new_storage->create();
573 
574  if (is_dir($old_storage->getPath()))
575  {
576  ilUtil::rCopy($old_storage->getPath(), $new_storage->getPath());
577  }
578  }
579  }
580 
584  static function getFiles($a_exc_id, $a_ass_id)
585  {
586  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
587  $storage = new ilFSStorageExercise($a_exc_id, $a_ass_id);
588  return $storage->getFiles();
589  }
590 
594  static function lookupMaxOrderNrForEx($a_exc_id)
595  {
596  global $ilDB;
597 
598  $set = $ilDB->query("SELECT MAX(order_nr) mnr FROM exc_assignment ".
599  " WHERE exc_id = ".$ilDB->quote($a_exc_id, "integer")
600  );
601  while ($rec = $ilDB->fetchAssoc($set))
602  {
603  return (int) $rec["mnr"];
604  }
605  return 0;
606  }
607 
613  public static function lookupAssignmentOnline($a_ass_id)
614  {
615  global $ilDB;
616 
617  $query = "SELECT id FROM exc_assignment ".
618  "WHERE start_time <= ".$ilDB->quote(time(),'integer').' '.
619  "AND time_stamp >= ".$ilDB->quote(time(),'integer').' '.
620  "AND id = ".$ilDB->quote($a_ass_id,'integer');
621  $res = $ilDB->query($query);
622 
623  return $res->numRows() ? true : false;
624  }
625 
626 
630  private static function lookup($a_id, $a_field)
631  {
632  global $ilDB;
633 
634  $set = $ilDB->query("SELECT ".$a_field." FROM exc_assignment ".
635  " WHERE id = ".$ilDB->quote($a_id, "integer")
636  );
637 
638  $rec = $ilDB->fetchAssoc($set);
639 
640  return $rec[$a_field];
641  }
642 
646  static function lookupTitle($a_id)
647  {
648  return ilExAssignment::lookup($a_id, "title");
649  }
650 
654  static function lookupType($a_id)
655  {
656  return ilExAssignment::lookup($a_id, "type");
657  }
658 
662  function saveAssOrderOfExercise($a_ex_id, $a_order)
663  {
664  global $ilDB;
665 
666  $result_order = array();
667  asort($a_order);
668  $nr = 10;
669  foreach ($a_order as $k => $v)
670  {
671  // the check for exc_id is for security reasons. ass ids are unique.
672  $ilDB->manipulate($t = "UPDATE exc_assignment SET ".
673  " order_nr = ".$ilDB->quote($nr, "integer").
674  " WHERE id = ".$ilDB->quote((int) $k, "integer").
675  " AND exc_id = ".$ilDB->quote((int) $a_ex_id, "integer")
676  );
677  $nr+=10;
678  }
679  }
680 
684  function orderAssByDeadline($a_ex_id)
685  {
686  global $ilDB;
687 
688  $set = $ilDB->query("SELECT id FROM exc_assignment ".
689  " WHERE exc_id = ".$ilDB->quote($a_ex_id, "integer").
690  " ORDER BY time_stamp ASC"
691  );
692  $nr = 10;
693  while ($rec = $ilDB->fetchAssoc($set))
694  {
695  $ilDB->manipulate("UPDATE exc_assignment SET ".
696  " order_nr = ".$ilDB->quote($nr, "integer").
697  " WHERE id = ".$ilDB->quote($rec["id"], "integer")
698  );
699  $nr += 10;
700  }
701  }
702 
706  function countMandatory($a_ex_id)
707  {
708  global $ilDB;
709 
710  $set = $ilDB->query("SELECT count(*) cntm FROM exc_assignment ".
711  " WHERE exc_id = ".$ilDB->quote($a_ex_id, "integer").
712  " AND mandatory = ".$ilDB->quote(1, "integer")
713  );
714  $rec = $ilDB->fetchAssoc($set);
715  return $rec["cntm"];
716  }
717 
721 
725  private function lookupAssMemberField($a_ass_id, $a_user_id, $a_field)
726  {
727  global $ilDB;
728 
729  $set = $ilDB->query("SELECT ".$a_field." FROM exc_mem_ass_status ".
730  " WHERE ass_id = ".$ilDB->quote($a_ass_id, "integer").
731  " AND usr_id = ".$ilDB->quote($a_user_id, "integer")
732  );
733  $rec = $ilDB->fetchAssoc($set);
734 
735  return $rec[$a_field];
736  }
737 
741  private function updateAssMemberField($a_ass_id, $a_user_id, $a_field, $a_value, $a_type)
742  {
743  global $ilDB;
744 
745  $ilDB->manipulate("UPDATE exc_mem_ass_status SET ".
746  " ".$a_field." = ".$ilDB->quote($a_value, $a_type).
747  " WHERE ass_id = ".$ilDB->quote($a_ass_id, "integer").
748  " AND usr_id = ".$ilDB->quote($a_user_id, "integer")
749  );
750  }
751 
752 
753 /* function setStatus($a_status)
754  {
755  if(is_array($a_status))
756  {
757  $this->status = $a_status;
758  return true;
759  }
760  }
761  function getStatus()
762  {
763  return $this->status ? $this->status : array();
764  }*/
765 
769  function lookupCommentForUser($a_ass_id, $a_user_id)
770  {
771  return ilExAssignment::lookupAssMemberField($a_ass_id, $a_user_id, "u_comment");
772  }
773 
777  function updateCommentForUser($a_ass_id, $a_user_id, $a_value)
778  {
779  ilExAssignment::updateAssMemberField($a_ass_id, $a_user_id,
780  "u_comment", $a_value, "text");
781  }
782 
786  function lookupMarkOfUser($a_ass_id, $a_user_id)
787  {
788  return ilExAssignment::lookupAssMemberField($a_ass_id, $a_user_id, "mark");
789  }
790 
794  function updateMarkOfUser($a_ass_id, $a_user_id, $a_value)
795  {
796  ilExAssignment::updateAssMemberField($a_ass_id, $a_user_id,
797  "mark", $a_value, "text");
798  }
799 
803  function lookupStatusOfUser($a_ass_id, $a_user_id)
804  {
805  $stat = ilExAssignment::lookupAssMemberField($a_ass_id, $a_user_id, "status");
806  if ($stat == "")
807  {
808  $stat = "notgraded";
809  }
810  return $stat;
811  }
812 
816  function updateStatusOfUser($a_ass_id, $a_user_id, $a_status)
817  {
818  global $ilDB;
819 
820  $ilDB->manipulateF("UPDATE exc_mem_ass_status ".
821  "SET status = %s, status_time= %s ".
822  " WHERE ass_id = %s AND usr_id = %s AND status <> %s ",
823  array("text", "timestamp", "integer", "integer", "text"),
824  array($a_status, ilUtil::now(), $a_ass_id, $a_user_id, $a_status));
825 
826  $ass = new ilExAssignment($a_ass_id);
827  $exc = new ilObjExercise($ass->getExerciseId(), false);
828  $exc->updateUserStatus($a_user_id);
829  }
830 
834  function updateStatusTimeOfUser($a_ass_id, $a_user_id)
835  {
836  ilExAssignment::updateAssMemberField($a_ass_id, $a_user_id,
837  "status_time", ilUtil::now(), "timestamp");
838  }
839 
840 
841  /*function setStatusSent($a_status)
842  {
843  if(is_array($a_status))
844  {
845  $this->status_sent = $a_status;
846  return true;
847  }
848  }
849  function getStatusSent()
850  {
851  return $this->status_sent ? $this->status_sent : array(0 => 0);
852  }*/
853 
857  function lookupStatusSentOfUser($a_ass_id, $a_user_id)
858  {
859  return ilExAssignment::lookupAssMemberField($a_ass_id, $a_user_id, "sent");
860  }
861 
865  function updateStatusSentForUser($a_ass_id, $a_user_id, $a_status)
866  {
867  global $ilDB;
868 
869  $ilDB->manipulateF("UPDATE exc_mem_ass_status ".
870  "SET sent = %s, status_time= %s, sent_time = %s ".
871  " WHERE ass_id = %s AND usr_id = %s ",
872  array("integer", "timestamp", "timestamp", "integer", "integer"),
873  array((int) $a_status, ilUtil::now(), ($a_status ? ilUtil::now() : null),
874  $a_ass_id, $a_user_id));
875  }
876 
877  /*function getStatusReturned()
878  {
879  return $this->status_returned ? $this->status_returned : array(0 => 0);
880  }
881  function setStatusReturned($a_status)
882  {
883  if(is_array($a_status))
884  {
885  $this->status_returned = $a_status;
886  return true;
887  }
888  return false;
889  }*/
890 
894  function lookupStatusReturnedOfUser($a_ass_id, $a_user_id)
895  {
896  return ilExAssignment::lookupAssMemberField($a_ass_id, $a_user_id, "returned");
897  }
898 
902  function updateStatusReturnedForUser($a_ass_id, $a_user_id, $a_status)
903  {
904  global $ilDB;
905 
906  $ilDB->manipulateF("UPDATE exc_mem_ass_status ".
907  "SET returned = %s, status_time= %s ".
908  " WHERE ass_id = %s AND usr_id = %s",
909  array("integer", "timestamp", "integer", "integer"),
910  array((int) $a_status, ilUtil::now(),
911  $a_ass_id, $a_user_id));
912  }
913 
914 /* // feedback functions
915  function setStatusFeedback($a_status)
916  {
917  if(is_array($a_status))
918  {
919  $this->status_feedback = $a_status;
920  return true;
921  }
922  }
923  function getStatusFeedback()
924  {
925  return $this->status_feedback ? $this->status_feedback : array(0 => 0);
926  }*/
927 
931  function lookupStatusFeedbackOfUser($a_ass_id, $a_user_id)
932  {
933  return ilExAssignment::lookupAssMemberField($a_ass_id, $a_user_id, "feedback");
934  }
935 
939  function updateStatusFeedbackForUser($a_ass_id, $a_user_id, $a_status)
940  {
941  global $ilDB;
942 
943  $ilDB->manipulateF("UPDATE exc_mem_ass_status ".
944  "SET feedback = %s, status_time= %s, feedback_time = %s ".
945  " WHERE ass_id = %s AND usr_id = %s",
946  array("integer", "timestamp", "timestamp", "integer", "integer"),
947  array((int) $a_status, ilUtil::now(), ($a_status ? ilUtil::now() : null),
948  $a_ass_id, $a_user_id));
949  }
950 
954  static function lookupSentTimeOfUser($a_ass_id, $a_user_id)
955  {
957  ilExAssignment::lookupAssMemberField($a_ass_id, $a_user_id, "sent_time"));
958  }
959 
963  static function lookupFeedbackTimeOfUser($a_ass_id, $a_user_id)
964  {
966  ilExAssignment::lookupAssMemberField($a_ass_id, $a_user_id, "feedback_time"));
967  }
968 
972  static function lookupStatusTimeOfUser($a_ass_id, $a_user_id)
973  {
975  ilExAssignment::lookupAssMemberField($a_ass_id, $a_user_id, "status_time"));
976  }
977 
978  /*function getNotice()
979  {
980  return $this->notice ? $this->notice : array(0 => 0);
981  }
982 
983  function setNotice($a_notice)
984  {
985  if(is_array($a_notice))
986  {
987  $this->notice = $a_notice;
988  return true;
989  }
990  return false;
991  }*/
992 
996  function lookupNoticeOfUser($a_ass_id, $a_user_id)
997  {
998  return ilExAssignment::lookupAssMemberField($a_ass_id, $a_user_id, "notice");
999  }
1000 
1004  function hasReturned($a_ass_id, $a_user_id)
1005  {
1006  global $ilDB;
1007 
1008  $user_ids = self::getTeamMembersByAssignmentId($a_ass_id, $a_user_id);
1009  if(!$user_ids)
1010  {
1011  $user_ids = array($a_user_id);
1012  }
1013 
1014  $result = $ilDB->query("SELECT returned_id FROM exc_returned".
1015  " WHERE ass_id = ".$ilDB->quote($a_ass_id, "integer").
1016  " AND ".$ilDB->in("user_id", $user_ids, "", "integer"));
1017  return $ilDB->numRows($result);
1018  }
1019 
1023  function getAllDeliveredFiles($a_exc_id, $a_ass_id)
1024  {
1025  global $ilDB;
1026 
1027  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
1028  $fs = new ilFSStorageExercise($a_exc_id, $a_ass_id);
1029 
1030  $query = "SELECT * FROM exc_returned WHERE ass_id = ".
1031  $ilDB->quote($a_ass_id, "integer");
1032 
1033  $res = $ilDB->query($query);
1034  while($row = $ilDB->fetchAssoc($res))
1035  {
1036  $row["timestamp"] = $row["ts"];
1037  $row["filename"] = $fs->getAbsoluteSubmissionPath().
1038  "/".$row["user_id"]."/".basename($row["filename"]);
1039  $delivered[] = $row;
1040  }
1041 
1042  //$delivered = ilObjExercise::_fixFilenameArray($delivered);
1043 
1044  return $delivered ? $delivered : array();
1045  }
1046 
1050  function getDeliveredFiles($a_exc_id, $a_ass_id, $a_user_id, $a_filter_empty_filename = false)
1051  {
1052  global $ilDB;
1053 
1054  $user_ids = self::getTeamMembersByAssignmentId($a_ass_id, $a_user_id);
1055  if(!$user_ids)
1056  {
1057  $user_ids = array($a_user_id);
1058  }
1059 
1060  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
1061  $fs = new ilFSStorageExercise($a_exc_id, $a_ass_id);
1062 
1063  $result = $ilDB->query("SELECT * FROM exc_returned".
1064  " WHERE ass_id = ".$ilDB->quote($a_ass_id, "integer").
1065  " AND ".$ilDB->in("user_id", $user_ids, "", "integer"));
1066 
1067  $delivered_files = array();
1068  if ($ilDB->numRows($result))
1069  {
1070  while ($row = $ilDB->fetchAssoc($result))
1071  {
1072  if($a_filter_empty_filename && !$row["filename"])
1073  {
1074  continue;
1075  }
1076  $row["owner_id"] = $row["user_id"];
1077  $row["timestamp"] = $row["ts"];
1078  $row["timestamp14"] = substr($row["ts"], 0, 4).
1079  substr($row["ts"], 5, 2).substr($row["ts"], 8, 2).
1080  substr($row["ts"], 11, 2).substr($row["ts"], 14, 2).
1081  substr($row["ts"], 17, 2);
1082  $row["filename"] = $fs->getAbsoluteSubmissionPath().
1083  "/".$row["user_id"]."/".basename($row["filename"]);
1084  array_push($delivered_files, $row);
1085  }
1086  }
1087 
1088  //$delivered_files = ilObjExercise::_fixFilenameArray($delivered_files);
1089  return $delivered_files;
1090  }
1091 
1095  function deleteDeliveredFiles($a_exc_id, $a_ass_id, $file_id_array, $a_user_id)
1096  {
1097  global $ilDB;
1098 
1099  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
1100  $fs = new ilFSStorageExercise($a_exc_id, $a_ass_id);
1101 
1102  if (count($file_id_array))
1103  {
1104  $team_id = self::getTeamIdByAssignment($a_ass_id, $a_user_id);
1105  if($team_id)
1106  {
1107  // #11733
1108  $user_ids = self::getTeamMembersByAssignmentId($a_ass_id, $a_user_id);
1109  if(!$user_ids)
1110  {
1111  return;
1112  }
1113  }
1114  else
1115  {
1116  $user_ids = array($a_user_id);
1117  }
1118 
1119  $result = $ilDB->query("SELECT * FROM exc_returned".
1120  " WHERE ".$ilDB->in("returned_id", $file_id_array, false, "integer").
1121  " AND ".$ilDB->in("user_id", $user_ids, "", "integer"));
1122 
1123  if ($ilDB->numRows($result))
1124  {
1125  $result_array = array();
1126  while ($row = $ilDB->fetchAssoc($result))
1127  {
1128  $row["timestamp"] = $row["ts"];
1129  array_push($result_array, $row);
1130  }
1131 
1132  // delete the entries in the database
1133  $ilDB->manipulate("DELETE FROM exc_returned".
1134  " WHERE ".$ilDB->in("returned_id", $file_id_array, false, "integer").
1135  " AND ".$ilDB->in("user_id", $user_ids, "", "integer"));
1136 
1137  // delete the files
1138  foreach ($result_array as $key => $value)
1139  {
1140  if($value["filename"])
1141  {
1142  if($team_id)
1143  {
1144  ilExAssignment::writeTeamLog($team_id,
1145  ilExAssignment::TEAM_LOG_REMOVE_FILE, $value["filetitle"]);
1146  }
1147 
1148  $filename = $fs->getAbsoluteSubmissionPath().
1149  "/".$value["user_id"]."/".basename($value["filename"]);
1150  unlink($filename);
1151  }
1152  }
1153  }
1154  }
1155  }
1156 
1163  static function deleteAllDeliveredFilesOfUser($a_exc_id, $a_user_id)
1164  {
1165  global $ilDB;
1166 
1167  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
1168 
1169  $delete_ids = array();
1170 
1171  // get the files and...
1172  $set = $ilDB->query("SELECT * FROM exc_returned ".
1173  " WHERE obj_id = ".$ilDB->quote($a_exc_id, "integer").
1174  " AND user_id = ".$ilDB->quote($a_user_id, "integer")
1175  );
1176  while ($rec = $ilDB->fetchAssoc($set))
1177  {
1178  $ass = new self($rec["ass_id"]);
1179  if($ass->getType() == self::TYPE_UPLOAD_TEAM)
1180  {
1181  // switch upload to other team member
1182  $team = self::getTeamMembersByAssignmentId($ass->getId(), $a_user_id);
1183  if(sizeof($team) > 1)
1184  {
1185  $new_owner = array_pop($team);
1186  while($new_owner == $a_user_id && sizeof($team))
1187  {
1188  $new_owner = array_pop($team);
1189  }
1190 
1191  $ilDB->manipulate("UPDATE exc_returned".
1192  " SET user_id = ".$ilDB->quote($new_owner, "integer").
1193  " WHERE returned_id = ".$ilDB->quote($rec["returned_id"], "integer")
1194  );
1195 
1196  // no need to delete
1197  continue;
1198  }
1199  }
1200 
1201  $delete_ids[] = $rec["returned_id"];
1202 
1203  $fs = new ilFSStorageExercise($a_exc_id, $rec["ass_id"]);
1204 
1205  // ...delete files
1206  $filename = $fs->getAbsoluteSubmissionPath().
1207  "/".$a_user_id."/".basename($rec["filename"]);
1208  if (is_file($filename))
1209  {
1210  unlink($filename);
1211  }
1212  }
1213 
1214  // delete exc_returned records
1215  if($delete_ids)
1216  {
1217  $ilDB->manipulate("DELETE FROM exc_returned".
1218  " WHERE ".$ilDB->in("returned_id", $delete_ids, "", "integer"));
1219  }
1220 
1221  // delete il_exc_team records
1222  $ass_ids = array();
1223  foreach(self::getAssignmentDataOfExercise($a_exc_id) as $item)
1224  {
1225  self::updateStatusOfUser($item["id"], $a_user_id, "notgraded"); // #14900
1226 
1227  $ass_ids[] = $item["id"];
1228  }
1229  if($ass_ids)
1230  {
1231  $ilDB->manipulate($d = "DELETE FROM il_exc_team WHERE ".
1232  "user_id = ".$ilDB->quote($a_user_id, "integer").
1233  " AND ".$ilDB->in("ass_id", $ass_ids, "", "integer")
1234  );
1235  }
1236  }
1237 
1238 
1242  function deliverReturnedFiles($a_exc_id, $a_ass_id, $a_user_id, $a_only_new = false, $a_peer_review_mask_filename = false)
1243  {
1244  global $ilUser, $ilDB;
1245 
1246  // #11000 / #11785
1247  $is_team = true;
1248  $user_ids = self::getTeamMembersByAssignmentId($a_ass_id, $a_user_id);
1249  if(!$user_ids)
1250  {
1251  $is_team = false;
1252  $user_ids = array($a_user_id);
1253  }
1254 
1255  // get last download time
1256  $and_str = "";
1257  if ($a_only_new)
1258  {
1259  $q = "SELECT download_time FROM exc_usr_tutor WHERE ".
1260  " ass_id = ".$ilDB->quote($a_ass_id, "integer")." AND ".
1261  $ilDB->in("usr_id", $user_ids, "", "integer")." AND ".
1262  " tutor_id = ".$ilDB->quote($ilUser->getId(), "integer");
1263  $lu_set = $ilDB->query($q);
1264  if ($lu_rec = $ilDB->fetchAssoc($lu_set))
1265  {
1266  if ($lu_rec["download_time"] > 0)
1267  {
1268  $and_str = " AND ts > ".$ilDB->quote($lu_rec["download_time"], "timestamp");
1269  }
1270  }
1271  }
1272 
1273  foreach($user_ids as $user_id)
1274  {
1275  ilExAssignment::updateTutorDownloadTime($a_exc_id, $a_ass_id, $user_id);
1276  }
1277 
1278  if($a_peer_review_mask_filename)
1279  {
1280  // process peer review sequence id
1281  $peer_id = null;
1282  foreach($this->ass->getPeerReviewsByGiver($ilUser->getId()) as $idx => $item)
1283  {
1284  if($item["peer_id"] == $a_user_id)
1285  {
1286  $peer_id = $idx+1;
1287  break;
1288  }
1289  }
1290  }
1291 
1292  $query = "SELECT * FROM exc_returned".
1293  " WHERE ass_id = ".$ilDB->quote($a_ass_id, "integer").
1294  " AND ".$ilDB->in("user_id", $user_ids, "", "integer").
1295  $and_str;
1296 
1297  $result = $ilDB->query($query);
1298  $count = $ilDB->numRows($result);
1299  if ($count == 1)
1300  {
1301  $row = $ilDB->fetchAssoc($result);
1302 
1303  switch(self::lookupType($a_ass_id))
1304  {
1305  case self::TYPE_BLOG:
1306  case self::TYPE_PORTFOLIO:
1307  $row["filetitle"] = ilObjUser::_lookupName($row["user_id"]);
1308  $row["filetitle"] = ilObject::_lookupTitle($a_exc_id)." - ".
1309  self::lookupTitle($a_ass_id)." - ".
1310  $row["filetitle"]["firstname"]." ".
1311  $row["filetitle"]["lastname"]." (".
1312  $row["filetitle"]["login"].").zip";
1313  break;
1314 
1315  default:
1316  break;
1317  }
1318 
1319  if($a_peer_review_mask_filename)
1320  {
1321  $suffix = array_pop(explode(".", $row["filetitle"]));
1322  $row["filetitle"] = self::lookupTitle($a_ass_id)."_peer".$peer_id.".".$suffix;
1323  }
1324 
1325  ilExAssignment::downloadSingleFile($a_exc_id, $a_ass_id, $row["user_id"],
1326  $row["filename"], $row["filetitle"]);
1327  }
1328  else if ($count > 0)
1329  {
1330  $array_files = array();
1331  $seq = 0;
1332  while ($row = $ilDB->fetchAssoc($result))
1333  {
1334  $src = basename($row["filename"]);
1335  if($a_peer_review_mask_filename)
1336  {
1337  $suffix = array_pop(explode(".", $src));
1338  $tgt = self::lookupTitle($a_ass_id)."_peer".$peer_id.
1339  "_".(++$seq).".".$suffix;
1340 
1341  $array_files[$row["user_id"]][] = array($src, $tgt);
1342  }
1343  else
1344  {
1345  $array_files[$row["user_id"]][] = $src;
1346  }
1347  }
1348  ilExAssignment::downloadMultipleFiles($a_exc_id, $a_ass_id, $array_files,
1349  ($is_team ? null : $a_user_id), $is_team);
1350  }
1351  else
1352  {
1353  return false;
1354  }
1355 
1356  return true;
1357  }
1358 
1359  // Update the timestamp of the last download of current user (=tutor)
1363  function updateTutorDownloadTime($a_exc_id, $a_ass_id, $a_user_id)
1364  {
1365  global $ilUser, $ilDB;
1366 
1367  $ilDB->manipulateF("DELETE FROM exc_usr_tutor ".
1368  "WHERE ass_id = %s AND usr_id = %s AND tutor_id = %s",
1369  array("integer", "integer", "integer"),
1370  array($a_ass_id, $a_user_id, $ilUser->getId()));
1371 
1372  $ilDB->manipulateF("INSERT INTO exc_usr_tutor (ass_id, obj_id, usr_id, tutor_id, download_time) VALUES ".
1373  "(%s, %s, %s, %s, %s)",
1374  array("integer", "integer", "integer", "integer", "timestamp"),
1375  array($a_ass_id, $a_exc_id, $a_user_id, $ilUser->getId(), ilUtil::now()));
1376  }
1377 
1381  function downloadSelectedFiles($a_exc_id, $a_ass_id, $a_user_id, $array_file_id)
1382  {
1383  global $ilDB;
1384 
1385  if (count($array_file_id))
1386  {
1387  // #11785
1388  $is_team = true;
1389  $user_ids = self::getTeamMembersByAssignmentId($a_ass_id, $a_user_id);
1390  if(!$user_ids)
1391  {
1392  $is_team = false;
1393  $user_ids = array($a_user_id);
1394  }
1395 
1396  $result = $ilDB->query("SELECT * FROM exc_returned WHERE ".
1397  $ilDB->in("returned_id", $array_file_id, false, "integer").
1398  " AND ".$ilDB->in("user_id", $user_ids, "", "integer"));
1399  if ($ilDB->numRows($result))
1400  {
1401  $array_found = array();
1402  while ($row = $ilDB->fetchAssoc($result))
1403  {
1404  $row["timestamp"] = $row["ts"];
1405  array_push($array_found, $row);
1406  }
1407  if (count($array_found) == 1)
1408  {
1409  // blog/portfolio submission
1410  if(is_numeric($array_found[0]["filetitle"]))
1411  {
1412  $ass = new ilExAssignment($array_found[0]["ass_id"]);
1413  if($ass->getType() == ilExAssignment::TYPE_BLOG ||
1414  $ass->getType() == ilExAssignment::TYPE_PORTFOLIO)
1415  {
1416  $user_data = ilObjUser::_lookupName($array_found[0]["user_id"]);
1417  $array_found[0]["filetitle"] = ilObject::_lookupTitle($array_found[0]["obj_id"])." - ".
1418  $ass->getTitle()." - ".
1419  $user_data["firstname"]." ".
1420  $user_data["lastname"]." (".
1421  $user_data["login"].").zip";
1422  }
1423  }
1424 
1425  ilExAssignment::downloadSingleFile($a_exc_id, $a_ass_id, $array_found[0]["user_id"],
1426  $array_found[0]["filename"], $array_found[0]["filetitle"]);
1427  }
1428  else
1429  {
1430  $filenames = array();
1431  foreach ($array_found as $value)
1432  {
1433  $filenames[$value["user_id"]][] = basename($value["filename"]);
1434  }
1435  ilExAssignment::downloadMultipleFiles($a_exc_id, $a_ass_id,
1436  $filenames, ($is_team ? null : $a_user_id), $is_team);
1437  }
1438  }
1439  }
1440  }
1441 
1445  function downloadSingleFile($a_exc_id, $a_ass_id, $a_user_id, $filename, $filetitle)
1446  {
1447  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
1448  $fs = new ilFSStorageExercise($a_exc_id, $a_ass_id);
1449 
1450  $filename = $fs->getAbsoluteSubmissionPath().
1451  "/".$a_user_id."/".basename($filename);
1452 
1453  require_once "./Services/Utilities/classes/class.ilUtil.php";
1454  ilUtil::deliverFile($filename, $filetitle);
1455  }
1456 
1460 // @todo: check whether files of multiple users are downloaded this way
1461  function downloadMultipleFiles($a_exc_id, $a_ass_id, $array_filenames,
1462  $a_user_id, $a_multi_user = false)
1463  {
1464  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
1465  $fs = new ilFSStorageExercise($a_exc_id, $a_ass_id);
1466 
1467  require_once "./Services/Utilities/classes/class.ilUtil.php";
1468  $cdir = getcwd();
1469 
1470  $zip = PATH_TO_ZIP;
1471  $tmpdir = ilUtil::ilTempnam();
1472  $tmpfile = ilUtil::ilTempnam();
1473  $tmpzipfile = $tmpfile . ".zip";
1474 
1475  ilUtil::makeDir($tmpdir);
1476  chdir($tmpdir);
1477 
1478  $assTitle = ilExAssignment::lookupTitle($a_ass_id);
1479  $deliverFilename = str_replace(" ", "_", $assTitle);
1480  if ($a_user_id > 0 && !$a_multi_user)
1481  {
1482  $userName = ilObjUser::_lookupName($a_user_id);
1483  $deliverFilename .= "_".$userName["lastname"]."_".$userName["firstname"];
1484  }
1485  else
1486  {
1487  $deliverFilename .= "_files";
1488  }
1489  $orgDeliverFilename = trim($deliverFilename);
1490  $deliverFilename = ilUtil::getASCIIFilename($orgDeliverFilename);
1491  ilUtil::makeDir($tmpdir."/".$deliverFilename);
1492  chdir($tmpdir."/".$deliverFilename);
1493 
1494  //copy all files to a temporary directory and remove them afterwards
1495  $parsed_files = $duplicates = array();
1496  foreach ($array_filenames as $user_id => $files)
1497  {
1498  $pathname = $fs->getAbsoluteSubmissionPath()."/".$user_id;
1499 
1500  foreach($files as $filename)
1501  {
1502  // peer review masked filenames, see deliverReturnedFiles()
1503  if(is_array($filename))
1504  {
1505  $newFilename = $filename[1];
1506  $filename = $filename[0];
1507  }
1508  else
1509  {
1510  // remove timestamp
1511  $newFilename = trim($filename);
1512  $pos = strpos($newFilename , "_");
1513  if ($pos !== false)
1514  {
1515  $newFilename = substr($newFilename, $pos + 1);
1516  }
1517  // #11070
1518  $chkName = strtolower($newFilename);
1519  if(array_key_exists($chkName, $duplicates))
1520  {
1521  $suffix = strrpos($newFilename, ".");
1522  $newFilename = substr($newFilename, 0, $suffix).
1523  " (".(++$duplicates[$chkName]).")".
1524  substr($newFilename, $suffix);
1525  }
1526  else
1527  {
1528  $duplicates[$chkName] = 1;
1529  }
1530  }
1531  $newFilename = $tmpdir.DIRECTORY_SEPARATOR.$deliverFilename.DIRECTORY_SEPARATOR.$newFilename;
1532  // copy to temporal directory
1533  $oldFilename = $pathname.DIRECTORY_SEPARATOR.$filename;
1534  if (!copy ($oldFilename, $newFilename))
1535  {
1536  echo 'Could not copy '.$oldFilename.' to '.$newFilename;
1537  }
1538  touch($newFilename, filectime($oldFilename));
1539  $parsed_files[] = ilUtil::escapeShellArg($deliverFilename.DIRECTORY_SEPARATOR.basename($newFilename));
1540  }
1541  }
1542 
1543  chdir($tmpdir);
1544  $zipcmd = $zip." ".ilUtil::escapeShellArg($tmpzipfile)." ".join($parsed_files, " ");
1545 
1546  exec($zipcmd);
1547  ilUtil::delDir($tmpdir);
1548 
1549  chdir($cdir);
1550  ilUtil::deliverFile($tmpzipfile, $orgDeliverFilename.".zip", "", false, true);
1551  exit;
1552  }
1553 
1559  function downloadAllDeliveredFiles($a_exc_id, $a_ass_id, $members)
1560  {
1561  global $lng, $ilObjDataCache, $ilias;
1562 
1563  include_once "./Services/Utilities/classes/class.ilUtil.php";
1564  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
1565 
1566  $storage = new ilFSStorageExercise($a_exc_id, $a_ass_id);
1567  $storage->create();
1568 
1569  ksort($members);
1570  //$savepath = $this->getExercisePath() . "/" . $this->obj_id . "/";
1571  $savepath = $storage->getAbsoluteSubmissionPath();
1572  $cdir = getcwd();
1573 
1574 
1575  // important check: if the directory does not exist
1576  // ILIAS stays in the current directory (echoing only a warning)
1577  // and the zip command below archives the whole ILIAS directory
1578  // (including the data directory) and sends a mega file to the user :-o
1579  if (!is_dir($savepath))
1580  {
1581  return;
1582  }
1583  // Safe mode fix
1584 // chdir($this->getExercisePath());
1585  chdir($storage->getTempPath());
1586  $zip = PATH_TO_ZIP;
1587 
1588  // check first, if we have enough free disk space to copy all files to temporary directory
1589  $tmpdir = ilUtil::ilTempnam();
1590  ilUtil::makeDir($tmpdir);
1591  chdir($tmpdir);
1592 
1593 
1594  $dirsize = 0;
1595  foreach ($members as $id => $object) {
1596  $directory = $savepath.DIRECTORY_SEPARATOR.$id;
1597  $dirsize += ilUtil::dirsize($directory);
1598  }
1599  if ($dirsize > disk_free_space($tmpdir)) {
1600  return -1;
1601  }
1602 
1603  $ass_type = self::lookupType($a_ass_id);
1604 
1605  // copy all member directories to the temporary folder
1606  // switch from id to member name and append the login if the member name is double
1607  // ensure that no illegal filenames will be created
1608  // remove timestamp from filename
1609  $cache = array();
1610  foreach ($members as $id => $user)
1611  {
1612  $sourcedir = $savepath.DIRECTORY_SEPARATOR.$id;
1613  if (!is_dir($sourcedir))
1614  continue;
1615  $userName = ilObjUser::_lookupName($id);
1616  //$directory = ilUtil::getASCIIFilename(trim($userName["lastname"])."_".trim($userName["firstname"]));
1617  $directory = ilUtil::getASCIIFilename(trim($userName["lastname"])."_".
1618  trim($userName["firstname"])."_".trim($userName["login"])."_".$userName["user_id"]);
1619  /*if (array_key_exists($directory, $cache))
1620  {
1621  // first try is to append the login;
1622  $directory = ilUtil::getASCIIFilename($directory."_".trim(ilObjUser::_lookupLogin($id)));
1623  if (array_key_exists($directory, $cache)) {
1624  // second and secure: append the user id as well.
1625  $directory .= "_".$id;
1626  }
1627  }*/
1628 
1629  $cache[$directory] = $directory;
1630  ilUtil::makeDir ($directory);
1631  $sourcefiles = scandir($sourcedir);
1632  $duplicates = array();
1633  foreach ($sourcefiles as $sourcefile) {
1634  if ($sourcefile == "." || $sourcefile == "..")
1635  {
1636  continue;
1637  }
1638 
1639  $targetfile = trim(basename($sourcefile));
1640  $pos = strpos($targetfile, "_");
1641  if ($pos !== false)
1642  {
1643  $targetfile= substr($targetfile, $pos + 1);
1644  }
1645 
1646  // #14536
1647  if(array_key_exists($targetfile, $duplicates))
1648  {
1649  $suffix = strrpos($targetfile, ".");
1650  $targetfile = substr($targetfile, 0, $suffix).
1651  " (".(++$duplicates[$targetfile]).")".
1652  substr($targetfile, $suffix);
1653  }
1654  else
1655  {
1656  $duplicates[$targetfile] = 1;
1657  }
1658 
1659  $targetfile = $directory.DIRECTORY_SEPARATOR.$targetfile;
1660  $sourcefile = $sourcedir.DIRECTORY_SEPARATOR.$sourcefile;
1661 
1662  if (!copy ($sourcefile, $targetfile))
1663  {
1664  //echo 'Could not copy '.$sourcefile.' to '.$targetfile;
1665  $ilias->raiseError('Could not copy '.basename($sourcefile)." to '".$targetfile."'.",
1666  $ilias->error_obj->MESSAGE);
1667  }
1668  else
1669  {
1670  // preserve time stamp
1671  touch($targetfile, filectime($sourcefile));
1672 
1673  // blogs and portfolios are stored as zip and have to be unzipped
1674  if($ass_type == ilExAssignment::TYPE_PORTFOLIO ||
1675  $ass_type == ilExAssignment::TYPE_BLOG)
1676  {
1677  ilUtil::unzip($targetfile);
1678  unlink($targetfile);
1679  }
1680  }
1681 
1682  }
1683  }
1684 
1685  $tmpfile = ilUtil::ilTempnam();
1686  $tmpzipfile = $tmpfile . ".zip";
1687  // Safe mode fix
1688  $zipcmd = $zip." -r ".ilUtil::escapeShellArg($tmpzipfile)." .";
1689  exec($zipcmd);
1690  ilUtil::delDir($tmpdir);
1691 
1692  $assTitle = ilExAssignment::lookupTitle($a_ass_id)."_".$a_ass_id;
1693  chdir($cdir);
1694  ilUtil::deliverFile($tmpzipfile, (strlen($assTitle) == 0
1695  ? strtolower($lng->txt("exc_assignment"))
1696  : $assTitle). ".zip", "", false, true);
1697  }
1698 
1702  function updateNoticeForUser($a_ass_id, $a_user_id, $a_notice)
1703  {
1704  global $ilDB;
1705 
1706  // #12181
1707  $ilDB->manipulate("UPDATE exc_mem_ass_status".
1708  " SET notice = ".$ilDB->quote($a_notice, "text").
1709  ",status_time= ".$ilDB->quote(ilUtil::now(), "timestamp").
1710  " WHERE ass_id = ".$ilDB->quote($a_ass_id, "integer").
1711  " AND usr_id = ".$ilDB->quote($a_user_id, "integer").
1712  " AND ".$ilDB->equalsNot("notice", $a_notice, "text", true));
1713  }
1714 
1718  function _getReturned($a_ass_id)
1719  {
1720  global $ilDB;
1721 
1722  $query = "SELECT DISTINCT(usr_id) as ud FROM exc_mem_ass_status ".
1723  "WHERE ass_id = ".$ilDB->quote($a_ass_id, "integer")." ".
1724  "AND returned = 1";
1725 
1726  $res = $ilDB->query($query);
1727  while($row = $ilDB->fetchObject($res))
1728  {
1729  $usr_ids[] = $row->ud;
1730  }
1731 
1732  return $usr_ids ? $usr_ids : array();
1733  }
1734 
1742  static function getLastSubmission($a_ass_id, $a_user_id)
1743  {
1744  global $ilDB, $lng;
1745 
1746  // team upload?
1747  $user_ids = self::getTeamMembersByAssignmentId($a_ass_id, $a_user_id);
1748  if(!$user_ids)
1749  {
1750  $user_ids = array($a_user_id);
1751  }
1752 
1753  $ilDB->setLimit(1);
1754 
1755  $q = "SELECT obj_id,user_id,ts FROM exc_returned".
1756  " WHERE ass_id = ".$ilDB->quote($a_ass_id, "integer").
1757  " AND ".$ilDB->in("user_id", $user_ids, "", "integer").
1758  " ORDER BY ts DESC";
1759 
1760  $usr_set = $ilDB->query($q);
1761 
1762  $array = $ilDB->fetchAssoc($usr_set);
1763  if ($array["ts"]==NULL)
1764  {
1765  return false;
1766  }
1767  else
1768  {
1769  return ilUtil::getMySQLTimestamp($array["ts"]);
1770  }
1771  }
1772 
1776  static function lookupAnyExerciseSent($a_exc_id, $a_ass_id)
1777  {
1778  global $ilDB;
1779 
1780  $q = "SELECT count(*) AS cnt FROM exc_mem_ass_status".
1781  " WHERE NOT sent_time IS NULL".
1782  " AND ass_id = ".$ilDB->quote($a_ass_id, "integer")." ".
1783  " ";
1784  $set = $ilDB->query($q);
1785  $rec = $ilDB->fetchAssoc($set);
1786 
1787  if ($rec["cnt"] > 0)
1788  {
1789  return true;
1790  }
1791  else
1792  {
1793  return false;
1794  }
1795  }
1796 
1801  static function lookupUpdatedSubmission($ass_id, $member_id)
1802  {
1803  global $ilDB, $lng;
1804 
1805  // team upload?
1806  $user_ids = self::getTeamMembersByAssignmentId($ass_id, $member_id);
1807  if(!$user_ids)
1808  {
1809  $user_ids = array($member_id);
1810  }
1811 
1812  $q="SELECT exc_mem_ass_status.status_time, exc_returned.ts ".
1813  "FROM exc_mem_ass_status, exc_returned ".
1814  "WHERE exc_mem_ass_status.status_time < exc_returned.ts ".
1815  "AND NOT exc_mem_ass_status.status_time IS NULL ".
1816  "AND exc_returned.ass_id = exc_mem_ass_status.ass_id ".
1817  "AND exc_returned.user_id = exc_mem_ass_status.usr_id ".
1818  "AND exc_returned.ass_id=".$ilDB->quote($ass_id, "integer").
1819  " AND ".$ilDB->in("exc_returned.user_id", $user_ids, "", "integer");
1820 
1821  $usr_set = $ilDB->query($q);
1822 
1823  $array = $ilDB->fetchAssoc($usr_set);
1824 
1825  if (count($array)==0)
1826  {
1827  return 0;
1828  }
1829  else
1830  {
1831  return 1;
1832  }
1833 
1834  }
1835 
1840  static function lookupNewFiles($ass_id, $member_id)
1841  {
1842  global $ilDB, $ilUser;
1843 
1844  // team upload?
1845  $user_ids = self::getTeamMembersByAssignmentId($ass_id, $member_id);
1846  if(!$user_ids)
1847  {
1848  $user_ids = array($member_id);
1849  }
1850 
1851  $q = "SELECT exc_returned.returned_id AS id ".
1852  "FROM exc_usr_tutor, exc_returned ".
1853  "WHERE exc_returned.ass_id = exc_usr_tutor.ass_id ".
1854  " AND exc_returned.user_id = exc_usr_tutor.usr_id ".
1855  " AND exc_returned.ass_id = ".$ilDB->quote($ass_id, "integer").
1856  " AND ".$ilDB->in("exc_returned.user_id", $user_ids, "", "integer").
1857  " AND exc_usr_tutor.tutor_id = ".$ilDB->quote($ilUser->getId(), "integer").
1858  " AND exc_usr_tutor.download_time < exc_returned.ts ";
1859 
1860  $new_up_set = $ilDB->query($q);
1861 
1862  $new_up = array();
1863  while ($new_up_rec = $ilDB->fetchAssoc($new_up_set))
1864  {
1865  $new_up[] = $new_up_rec["id"];
1866  }
1867 
1868  return $new_up;
1869  }
1870 
1874  function getMemberListData($a_exc_id, $a_ass_id)
1875  {
1876  global $ilDB;
1877 
1878  $mem = array();
1879 
1880  // first get list of members from member table
1881  $set = $ilDB->query("SELECT ud.usr_id, ud.lastname, ud.firstname, ud.login".
1882  " FROM exc_members excm".
1883  " JOIN usr_data ud ON (ud.usr_id = excm.usr_id)".
1884  " WHERE excm.obj_id = ".$ilDB->quote($a_exc_id, "integer"));
1885  while($rec = $ilDB->fetchAssoc($set))
1886  {
1887  $mem[$rec["usr_id"]] =
1888  array(
1889  "name" => $rec["lastname"].", ".$rec["firstname"],
1890  "login" => $rec["login"],
1891  "usr_id" => $rec["usr_id"],
1892  "lastname" => $rec["lastname"],
1893  "firstname" => $rec["firstname"]
1894  );
1895  }
1896 
1897  $q = "SELECT * FROM exc_mem_ass_status ".
1898  "WHERE ass_id = ".$ilDB->quote($a_ass_id, "integer");
1899  $set = $ilDB->query($q);
1900  while($rec = $ilDB->fetchAssoc($set))
1901  {
1902  if (isset($mem[$rec["usr_id"]]))
1903  {
1904  $mem[$rec["usr_id"]]["sent_time"] = $rec["sent_time"];
1905  $mem[$rec["usr_id"]]["submission"] = ilExAssignment::getLastSubmission($a_ass_id, $rec["usr_id"]);
1906  $mem[$rec["usr_id"]]["status_time"] = $rec["status_time"];
1907  $mem[$rec["usr_id"]]["feedback_time"] = $rec["feedback_time"];
1908  $mem[$rec["usr_id"]]["notice"] = $rec["notice"];
1909  $mem[$rec["usr_id"]]["status"] = $rec["status"];
1910  }
1911  }
1912  return $mem;
1913  }
1914 
1918  static function createNewUserRecords($a_user_id, $a_exc_id)
1919  {
1920  global $ilDB;
1921 
1922  $ass_data = ilExAssignment::getAssignmentDataOfExercise($a_exc_id);
1923  foreach ($ass_data as $ass)
1924  {
1925 //echo "-".$ass["id"]."-".$a_user_id."-";
1926  $ilDB->replace("exc_mem_ass_status", array(
1927  "ass_id" => array("integer", $ass["id"]),
1928  "usr_id" => array("integer", $a_user_id)
1929  ), array(
1930  "status" => array("text", "notgraded")
1931  ));
1932  }
1933  }
1934 
1938  static function createNewAssignmentRecords($a_ass_id, $a_exc)
1939  {
1940  global $ilDB;
1941 
1942  include_once("./Modules/Exercise/classes/class.ilExerciseMembers.php");
1943  $exmem = new ilExerciseMembers($a_exc);
1944  $mems = $exmem->getMembers();
1945 
1946  foreach ($mems as $mem)
1947  {
1948  $ilDB->replace("exc_mem_ass_status", array(
1949  "ass_id" => array("integer", $a_ass_id),
1950  "usr_id" => array("integer", $mem)
1951  ), array(
1952  "status" => array("text", "notgraded")
1953  ));
1954  }
1955  }
1956 
1961  function uploadAssignmentFiles($a_files)
1962  {
1963  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
1964  $storage = new ilFSStorageExercise($this->getExerciseId(), $this->getId());
1965  $storage->create();
1966  $storage->uploadAssignmentFiles($a_files);
1967  }
1968 
1969  //
1970  // TEAM UPLOAD
1971  //
1972 
1982  function getTeamId($a_user_id, $a_create_on_demand = false)
1983  {
1984  global $ilDB;
1985 
1986  $sql = "SELECT id FROM il_exc_team".
1987  " WHERE ass_id = ".$ilDB->quote($this->getId(), "integer").
1988  " AND user_id = ".$ilDB->quote($a_user_id, "integer");
1989  $set = $ilDB->query($sql);
1990  $row = $ilDB->fetchAssoc($set);
1991  $id = $row["id"];
1992 
1993  if(!$id && $a_create_on_demand)
1994  {
1995  $id = $ilDB->nextId("il_exc_team");
1996 
1997  $fields = array("id" => array("integer", $id),
1998  "ass_id" => array("integer", $this->getId()),
1999  "user_id" => array("integer", $a_user_id));
2000  $ilDB->insert("il_exc_team", $fields);
2001 
2002  self::writeTeamLog($id, self::TEAM_LOG_CREATE_TEAM);
2003  self::writeTeamLog($id, self::TEAM_LOG_ADD_MEMBER,
2004  ilObjUser::_lookupFullname($a_user_id));
2005  }
2006 
2007  return $id;
2008  }
2009 
2016  function getTeamMembers($a_team_id)
2017  {
2018  global $ilDB;
2019 
2020  $ids = array();
2021 
2022  $sql = "SELECT user_id".
2023  " FROM il_exc_team".
2024  " WHERE ass_id = ".$ilDB->quote($this->getId(), "integer").
2025  " AND id = ".$ilDB->quote($a_team_id, "integer");
2026  $set = $ilDB->query($sql);
2027  while($row = $ilDB->fetchAssoc($set))
2028  {
2029  $ids[] = $row["user_id"];
2030  }
2031 
2032  return $ids;
2033  }
2034 
2041  {
2042  global $ilDB;
2043 
2044  $ids = array();
2045 
2046  $sql = "SELECT user_id".
2047  " FROM il_exc_team".
2048  " WHERE ass_id = ".$ilDB->quote($this->getId(), "integer");
2049  $set = $ilDB->query($sql);
2050  while($row = $ilDB->fetchAssoc($set))
2051  {
2052  $ids[] = $row["user_id"];
2053  }
2054 
2055  return $ids;
2056  }
2057 
2065  function addTeamMember($a_team_id, $a_user_id, $a_exc_ref_id)
2066  {
2067  global $ilDB;
2068 
2069  $members = $this->getTeamMembers($a_team_id);
2070  if(!in_array($a_user_id, $members))
2071  {
2072  $fields = array("id" => array("integer", $a_team_id),
2073  "ass_id" => array("integer", $this->getId()),
2074  "user_id" => array("integer", $a_user_id));
2075  $ilDB->insert("il_exc_team", $fields);
2076 
2077  $this->sendNotification($a_exc_ref_id, $a_user_id, "add");
2078 
2079  self::writeTeamLog($a_team_id, self::TEAM_LOG_ADD_MEMBER,
2080  ilObjUser::_lookupFullname($a_user_id));
2081  }
2082  }
2083 
2091  function removeTeamMember($a_team_id, $a_user_id, $a_exc_ref_id)
2092  {
2093  global $ilDB;
2094 
2095  $sql = "DELETE FROM il_exc_team".
2096  " WHERE ass_id = ".$ilDB->quote($this->getId(), "integer").
2097  " AND id = ".$ilDB->quote($a_team_id, "integer").
2098  " AND user_id = ".$ilDB->quote($a_user_id, "integer");
2099  $ilDB->manipulate($sql);
2100 
2101  $this->sendNotification($a_exc_ref_id, $a_user_id, "rmv");
2102 
2103  self::writeTeamLog($a_team_id, self::TEAM_LOG_REMOVE_MEMBER,
2104  ilObjUser::_lookupFullname($a_user_id));
2105  }
2106 
2114  public static function getTeamMembersByAssignmentId($a_ass_id, $a_user_id)
2115  {
2116  global $ilDB;
2117 
2118  $ids = array();
2119 
2120  $team_id = self::getTeamIdByAssignment($a_ass_id, $a_user_id);
2121  if($team_id)
2122  {
2123  $set = $ilDB->query("SELECT user_id".
2124  " FROM il_exc_team".
2125  " WHERE ass_id = ".$ilDB->quote($a_ass_id, "integer").
2126  " AND id = ". $ilDB->quote($team_id, "integer"));
2127  while($row = $ilDB->fetchAssoc($set))
2128  {
2129  $ids[] = $row["user_id"];
2130  }
2131  }
2132 
2133  return $ids;
2134  }
2135 
2143  public static function getTeamIdByAssignment($a_ass_id, $a_user_id)
2144  {
2145  global $ilDB;
2146 
2147  $result = $ilDB->query("SELECT type".
2148  " FROM exc_assignment".
2149  " WHERE id = ".$ilDB->quote($a_ass_id, "integer"));
2150  $type = $ilDB->fetchAssoc($result);
2151 
2152  if($type["type"] == self::TYPE_UPLOAD_TEAM)
2153  {
2154  $set = $ilDB->query("SELECT id".
2155  " FROM il_exc_team".
2156  " WHERE ass_id = ".$ilDB->quote($a_ass_id, "integer").
2157  " AND user_id = ".$ilDB->quote($a_user_id, "integer"));
2158  $team_id = $ilDB->fetchAssoc($set);
2159  return $team_id["id"];
2160  }
2161  }
2162 
2169  public static function getAssignmentTeamMap($a_ass_id)
2170  {
2171  global $ilDB;
2172 
2173  $map = array();
2174 
2175  $sql = "SELECT * FROM il_exc_team".
2176  " WHERE ass_id = ".$ilDB->quote($a_ass_id, "integer");
2177  $set = $ilDB->query($sql);
2178  while($row = $ilDB->fetchAssoc($set))
2179  {
2180  $map[$row["user_id"]] = $row["id"];
2181  }
2182 
2183  return $map;
2184  }
2185 
2193  public static function writeTeamLog($a_team_id, $a_action, $a_details = null)
2194  {
2195  global $ilDB, $ilUser;
2196 
2197  $fields = array(
2198  "team_id" => array("integer", $a_team_id),
2199  "user_id" => array("integer", $ilUser->getId()),
2200  "action" => array("integer", $a_action),
2201  "details" => array("text", $a_details),
2202  "tstamp" => array("integer", time())
2203  );
2204 
2205  $ilDB->insert("il_exc_team_log", $fields);
2206  }
2207 
2214  public static function getTeamLog($a_team_id)
2215  {
2216  global $ilDB;
2217 
2218  $res = array();
2219 
2220  $sql = "SELECT * FROM il_exc_team_log".
2221  " WHERE team_id = ".$ilDB->quote($a_team_id, "integer").
2222  " ORDER BY tstamp DESC";
2223  $set = $ilDB->query($sql);
2224  while($row = $ilDB->fetchAssoc($set))
2225  {
2226  $res[] = $row;
2227  }
2228  return $res;
2229  }
2230 
2238  public function sendNotification($a_exc_ref_id, $a_user_id, $a_action)
2239  {
2240  global $ilUser;
2241 
2242  // no need to notify current user
2243  if($ilUser->getId() == $a_user_id)
2244  {
2245  return;
2246  }
2247 
2248  include_once "./Services/Notification/classes/class.ilSystemNotification.php";
2249  $ntf = new ilSystemNotification();
2250  $ntf->setLangModules(array("exc"));
2251  $ntf->setRefId($a_exc_ref_id);
2252  $ntf->setChangedByUserId($ilUser->getId());
2253  $ntf->setSubjectLangId('exc_team_notification_subject_'.$a_action);
2254  $ntf->setIntroductionLangId('exc_team_notification_body_'.$a_action);
2255  $ntf->addAdditionalInfo("exc_assignment", $this->getTitle());
2256  $ntf->setGotoLangId('exc_team_notification_link');
2257  $ntf->setReasonLangId('exc_team_notification_reason');
2258  $ntf->sendMail(array($a_user_id));
2259  }
2260 
2261  public static function getDownloadedFilesInfoForTableGUIS($a_parent_obj, $a_exercise_id, $a_ass_type, $a_ass_id, $a_user_id, $a_parent_cmd = null)
2262  {
2263  global $lng, $ilCtrl;
2264 
2265  $result = array();
2266  $result["files"]["count"] = "---";
2267 
2268  $ilCtrl->setParameter($a_parent_obj, "ass_id", $a_ass_id);
2269 
2270  // submission:
2271  // see if files have been resubmmited after solved
2272  $last_sub = self::getLastSubmission($a_ass_id, $a_user_id);
2273  if ($last_sub)
2274  {
2275  $last_sub = ilDatePresentation::formatDate(new ilDateTime($last_sub,IL_CAL_DATETIME));
2276  }
2277  else
2278  {
2279  $last_sub = "---";
2280  }
2281  if (ilExAssignment::lookupUpdatedSubmission($a_ass_id, $a_user_id) == 1)
2282  {
2283  $last_sub = "<b>".$last_sub."</b>";
2284  }
2285  $result["last_submission"]["txt"] = $lng->txt("exc_last_submission");
2286  $result["last_submission"]["value"] = $last_sub;
2287 
2288  // assignment type specific
2289  switch($a_ass_type)
2290  {
2292  // data is merged by team - see above
2293  // fallthrough
2294 
2296  // nr of submitted files
2297  $result["files"]["txt"] = $lng->txt("exc_files_returned");
2298  $sub_cnt = count(ilExAssignment::getDeliveredFiles($a_exercise_id, $a_ass_id, $a_user_id));
2299  $new = ilExAssignment::lookupNewFiles($a_ass_id, $a_user_id);
2300  if (count($new) > 0)
2301  {
2302  $sub_cnt.= " ".sprintf($lng->txt("cnt_new"),count($new));
2303  }
2304  $result["files"]["count"] = $sub_cnt;
2305 
2306  // download command
2307  $ilCtrl->setParameter($a_parent_obj, "member_id", $a_user_id);
2308 
2309  if ($sub_cnt > 0)
2310  {
2311  $result["files"]["download_url"] =
2312  $ilCtrl->getLinkTarget($a_parent_obj, "downloadReturned");
2313 
2314  if (count($new) <= 0)
2315  {
2316  $result["files"]["download_txt"] = $lng->txt("exc_download_files");
2317  }
2318  else
2319  {
2320  $result["files"]["download_txt"] = $lng->txt("exc_download_all");
2321  }
2322 
2323  // download new files only
2324  if (count($new) > 0)
2325  {
2326  $result["files"]["download_new_url"] =
2327  $ilCtrl->getLinkTarget($a_parent_obj, "downloadNewReturned");
2328 
2329  $result["files"]["download_new_txt"] = $lng->txt("exc_download_new");
2330  }
2331  }
2332  break;
2333 
2335  $result["files"]["txt"] =$lng->txt("exc_blog_returned");
2336  $blogs = ilExAssignment::getDeliveredFiles($a_exercise_id, $a_ass_id, $a_user_id);
2337  if($blogs)
2338  {
2339  $blogs = array_pop($blogs);
2340  if($blogs && substr($blogs["filename"], -1) != "/")
2341  {
2342  $result["files"]["count"] = 1;
2343 
2344  $ilCtrl->setParameter($a_parent_obj, "member_id", $a_user_id);
2345  $result["files"]["download_url"] =
2346  $ilCtrl->getLinkTarget($a_parent_obj, "downloadReturned");
2347  $ilCtrl->setParameter($a_parent_obj, "member_id", "");
2348 
2349  $result["files"]["download_txt"] = $lng->txt("exc_download_files");
2350  }
2351  }
2352  break;
2353 
2355  $result["files"]["txt"] = $lng->txt("exc_portfolio_returned");
2356  $portfolios = ilExAssignment::getDeliveredFiles($a_exercise_id, $a_ass_id, $a_user_id);
2357  if($portfolios)
2358  {
2359  $portfolios = array_pop($portfolios);
2360  if($portfolios && substr($portfolios["filename"], -1) != "/")
2361  {
2362  $result["files"]["count"] = 1;
2363 
2364  $ilCtrl->setParameter($a_parent_obj, "member_id", $a_user_id);
2365  $result["files"]["download_url"] =
2366  $ilCtrl->getLinkTarget($a_parent_obj, "downloadReturned");
2367  $ilCtrl->setParameter($a_parent_obj, "member_id", "");
2368 
2369  $result["files"]["download_txt"] = $lng->txt("exc_download_files");
2370  }
2371  }
2372  break;
2373 
2375  $result["files"]["txt"] = $lng->txt("exc_files_returned_text");
2376  $files = ilExAssignment::getDeliveredFiles($a_exercise_id, $a_ass_id, $a_user_id);
2377  if($files)
2378  {
2379  $result["files"]["count"] = 1;
2380 
2381  $files = array_shift($files);
2382  if(trim($files["atext"]))
2383  {
2384  // #11397
2385  if($a_parent_cmd)
2386  {
2387  $ilCtrl->setParameter($a_parent_obj, "grd", (($a_parent_cmd == "members") ? 1 : 2));
2388  }
2389  $ilCtrl->setParameter($a_parent_obj, "member_id", $a_user_id);
2390  $result["files"]["download_url"] =
2391  $ilCtrl->getLinkTarget($a_parent_obj, "showAssignmentText");
2392  $ilCtrl->setParameter($a_parent_obj, "member_id", "");
2393  $ilCtrl->setParameter($a_parent_obj, "grd", "");
2394 
2395  $result["files"]["download_txt"] = $lng->txt("exc_text_assignment_show");
2396  }
2397  }
2398  break;
2399  }
2400 
2401  return $result;
2402  }
2403 
2404  protected function initPeerReviews()
2405  {
2406  global $ilDB;
2407 
2408  // only if assignment is through
2409  if(!$this->getDeadline() || $this->getDeadline() > time())
2410  {
2411  return false;
2412  }
2413 
2414  $set = $ilDB->query("SELECT count(*) cnt".
2415  " FROM exc_assignment_peer".
2416  " WHERE ass_id = ".$ilDB->quote($this->getId(), "integer"));
2417  $cnt = $ilDB->fetchAssoc($set);
2418  if(!$cnt["cnt"])
2419  {
2420  $user_ids = array();
2421  $set = $ilDB->query("SELECT DISTINCT(user_id)".
2422  " FROM exc_returned".
2423  " WHERE ass_id = ".$ilDB->quote($this->getId(), "integer"));
2424  while($row = $ilDB->fetchAssoc($set))
2425  {
2426  $user_ids[] = $row["user_id"];
2427  }
2428 
2429  // forever alone
2430  if(sizeof($user_ids) < 2)
2431  {
2432  return false;
2433  }
2434 
2435  $rater_ids = $user_ids;
2436  $matrix = array();
2437 
2438  $max = min(sizeof($user_ids)-1, $this->getPeerReviewMin());
2439  for($loop = 0; $loop < $max; $loop++)
2440  {
2441  $run_ids = array_combine($user_ids, $user_ids);
2442 
2443  foreach($rater_ids as $rater_id)
2444  {
2445  $possible_peer_ids = $run_ids;
2446 
2447  // may not rate himself
2448  unset($possible_peer_ids[$rater_id]);
2449 
2450  // already has linked peers
2451  if(array_key_exists($rater_id, $matrix))
2452  {
2453  $possible_peer_ids = array_diff($possible_peer_ids, $matrix[$rater_id]);
2454  }
2455 
2456  // #15665 / #15883
2457  if(!sizeof($possible_peer_ids))
2458  {
2459  // no more possible peers left? start over with all valid users
2460  $run_ids = array_combine($user_ids, $user_ids);
2461 
2462  // see above
2463  $possible_peer_ids = $run_ids;
2464 
2465  // may not rate himself
2466  unset($possible_peer_ids[$rater_id]);
2467 
2468  // already has linked peers
2469  if(array_key_exists($rater_id, $matrix))
2470  {
2471  $possible_peer_ids = array_diff($possible_peer_ids, $matrix[$rater_id]);
2472  }
2473  }
2474 
2475  // #14947
2476  if(sizeof($possible_peer_ids))
2477  {
2478  $peer_id = array_rand($possible_peer_ids);
2479  if(!array_key_exists($rater_id, $matrix))
2480  {
2481  $matrix[$rater_id] = array();
2482  }
2483  $matrix[$rater_id][] = $peer_id;
2484  }
2485 
2486  // remove peer_id from possible ids in this run
2487  unset($run_ids[$peer_id]);
2488  }
2489  }
2490 
2491  foreach($matrix as $rater_id => $peer_ids)
2492  {
2493  foreach($peer_ids as $peer_id)
2494  {
2495  $ilDB->manipulate("INSERT INTO exc_assignment_peer".
2496  " (ass_id, giver_id, peer_id)".
2497  " VALUES (".$ilDB->quote($this->getId(), "integer").
2498  ", ".$ilDB->quote($rater_id, "integer").
2499  ", ".$ilDB->quote($peer_id, "integer").")");
2500  }
2501  }
2502 
2503  }
2504  return true;
2505  }
2506 
2507  public function getPeerReviewsByGiver($a_user_id)
2508  {
2509  global $ilDB;
2510 
2511  $res = array();
2512 
2513  if($this->initPeerReviews())
2514  {
2515  $set = $ilDB->query("SELECT *".
2516  " FROM exc_assignment_peer".
2517  " WHERE giver_id = ".$ilDB->quote($a_user_id, "integer").
2518  " AND ass_id = ".$ilDB->quote($this->getId(), "integer").
2519  " ORDER BY peer_id");
2520  while($row = $ilDB->fetchAssoc($set))
2521  {
2522  $res[] = $row;
2523  }
2524  }
2525 
2526  return $res;
2527  }
2528 
2529  public function getPeerReviewsByPeerId($a_user_id, $a_only_valid = false)
2530  {
2531  global $ilDB;
2532 
2533  $res = array();
2534 
2535  include_once './Services/Rating/classes/class.ilRating.php';
2536 
2537  $set = $ilDB->query("SELECT *".
2538  " FROM exc_assignment_peer".
2539  " WHERE peer_id = ".$ilDB->quote($a_user_id, "integer").
2540  " AND ass_id = ".$ilDB->quote($this->getId(), "integer").
2541  " ORDER BY peer_id");
2542  while($row = $ilDB->fetchAssoc($set))
2543  {
2544  $valid = true;
2545  if($a_only_valid)
2546  {
2547  $valid = false;
2548  if(trim($row["pcomment"]))
2549  {
2550  $valid = true;
2551  }
2552  else
2553  {
2554  $valid = (bool)round(ilRating::getRatingForUserAndObject($this->getId(),
2555  "ass", $row["peer_id"], "peer", $row["giver_id"]));
2556  }
2557  }
2558  if($valid)
2559  {
2560  $res[] = $row;
2561  }
2562  }
2563 
2564  return $res;
2565  }
2566 
2567  public function getAllPeerReviews()
2568  {
2569  global $ilDB;
2570 
2571  $res = array();
2572 
2573  include_once './Services/Rating/classes/class.ilRating.php';
2574 
2575  $set = $ilDB->query("SELECT *".
2576  " FROM exc_assignment_peer".
2577  " WHERE ass_id = ".$ilDB->quote($this->getId(), "integer").
2578  " ORDER BY peer_id");
2579  while($row = $ilDB->fetchAssoc($set))
2580  {
2581  $rating = round(ilRating::getRatingForUserAndObject($this->getId(),
2582  "ass", $row["peer_id"], "peer", $row["giver_id"]));
2583 
2584  $comment = $row["pcomment"];
2585 
2586  if($comment || $rating)
2587  {
2588  $res[$row["peer_id"]][$row["giver_id"]] = array($comment, $rating);
2589  }
2590  }
2591 
2592  return $res;
2593  }
2594 
2595  public function hasPeerReviewAccess($a_peer_id)
2596  {
2597  global $ilDB, $ilUser;
2598 
2599  $set = $ilDB->query("SELECT ass_id".
2600  " FROM exc_assignment_peer".
2601  " WHERE giver_id = ".$ilDB->quote($ilUser->getId(), "integer").
2602  " AND peer_id = ".$ilDB->quote($a_peer_id, "integer").
2603  " AND ass_id = ".$ilDB->quote($this->getId(), "integer"));
2604  $row = $ilDB->fetchAssoc($set);
2605  return (bool)$row["ass_id"];
2606  }
2607 
2608  public function updatePeerReviewTimestamp($a_peer_id)
2609  {
2610  global $ilDB, $ilUser;
2611 
2612  $ilDB->manipulate("UPDATE exc_assignment_peer".
2613  " SET tstamp = ".$ilDB->quote(ilUtil::now(), "timestamp").
2614  " WHERE giver_id = ".$ilDB->quote($ilUser->getId(), "integer").
2615  " AND peer_id = ".$ilDB->quote($a_peer_id, "integer").
2616  " AND ass_id = ".$ilDB->quote($this->getId(), "integer"));
2617  }
2618 
2619  public function updatePeerReviewComment($a_peer_id, $a_comment)
2620  {
2621  global $ilDB, $ilUser;
2622 
2623  $ilDB->manipulate("UPDATE exc_assignment_peer".
2624  " SET tstamp = ".$ilDB->quote(ilUtil::now(), "timestamp").
2625  ", pcomment = ".$ilDB->quote($a_comment, "text").
2626  " WHERE giver_id = ".$ilDB->quote($ilUser->getId(), "integer").
2627  " AND peer_id = ".$ilDB->quote($a_peer_id, "integer").
2628  " AND ass_id = ".$ilDB->quote($this->getId(), "integer"));
2629  }
2630 
2631  public static function countGivenFeedback($a_ass_id)
2632  {
2633  global $ilDB, $ilUser;
2634 
2635  $cnt = 0;
2636 
2637  include_once './Services/Rating/classes/class.ilRating.php';
2638 
2639  $set = $ilDB->query("SELECT *".
2640  " FROM exc_assignment_peer".
2641  " WHERE ass_id = ".$ilDB->quote($a_ass_id, "integer").
2642  " AND giver_id = ".$ilDB->quote($ilUser->getId(), "integer"));
2643  while($row = $ilDB->fetchAssoc($set))
2644  {
2645  if(trim($row["pcomment"]))
2646  {
2647  $cnt++;
2648  }
2649  else
2650  {
2651  $mark = (int)round(ilRating::getRatingForUserAndObject($a_ass_id,
2652  "ass", $row["peer_id"], "peer", $row["giver_id"]));
2653  if($mark)
2654  {
2655  $cnt++;
2656  }
2657  }
2658  }
2659 
2660  return $cnt;
2661  }
2662 
2663  public static function getNumberOfMissingFeedbacks($a_ass_id, $a_min)
2664  {
2665  global $ilDB;
2666 
2667  // check if number of returned assignments is lower than assignment peer min
2668  $set = $ilDB->query("SELECT COUNT(DISTINCT(user_id)) cnt".
2669  " FROM exc_returned".
2670  " WHERE ass_id = ".$ilDB->quote($a_ass_id, "integer"));
2671  $cnt = $ilDB->fetchAssoc($set);
2672  $cnt = (int)$cnt["cnt"];
2673 
2674  // forever alone
2675  if($cnt < 2)
2676  {
2677  return;
2678  }
2679 
2680  $a_min = min($cnt-1, $a_min);
2681 
2682  return max(0, $a_min-self::countGivenFeedback($a_ass_id));
2683  }
2684 
2685  public static function getPendingFeedbackNotifications()
2686  {
2687  global $ilDB;
2688 
2689  $res = array();
2690 
2691  $set = $ilDB->query("SELECT id,fb_file FROM exc_assignment".
2692  " WHERE fb_cron = ".$ilDB->quote(1, "integer").
2693  " AND time_stamp IS NOT NULL".
2694  " AND time_stamp > ".$ilDB->quote(0, "integer").
2695  " AND time_stamp < ".$ilDB->quote(time(), "integer").
2696  " AND fb_cron_done = ".$ilDB->quote(0, "integer"));
2697  while($row = $ilDB->fetchAssoc($set))
2698  {
2699  if(trim($row["fb_file"]))
2700  {
2701  $res[] = $row["id"];
2702  }
2703  }
2704 
2705  return $res;
2706  }
2707 
2708  public function sendFeedbackNotifications($a_ass_id)
2709  {
2710  global $ilDB;
2711 
2712  $ass = new self($a_ass_id);
2713 
2714  // valid assignment?
2715  if(!$ass->hasFeedbackCron() || !$ass->getFeedbackFile())
2716  {
2717  return false;
2718  }
2719 
2720  // already done?
2721  $set = $ilDB->query("SELECT fb_cron_done".
2722  " FROM exc_assignment".
2723  " WHERE id = ".$ilDB->quote($a_ass_id, "integer"));
2724  $row = $ilDB->fetchAssoc($set);
2725  if($row["fb_cron_done"])
2726  {
2727  return false;
2728  }
2729 
2730  include_once "./Services/Notification/classes/class.ilSystemNotification.php";
2731  $ntf = new ilSystemNotification();
2732  $ntf->setLangModules(array("exc"));
2733  $ntf->setObjId($ass->getExerciseId());
2734  $ntf->setSubjectLangId("exc_feedback_notification_subject");
2735  $ntf->setIntroductionLangId("exc_feedback_notification_body");
2736  $ntf->addAdditionalInfo("exc_assignment", $ass->getTitle());
2737  $ntf->setGotoLangId("exc_feedback_notification_link");
2738  $ntf->setReasonLangId("exc_feedback_notification_reason");
2739 
2740  include_once "./Modules/Exercise/classes/class.ilExerciseMembers.php";
2741  $ntf->sendMail(ilExerciseMembers::_getMembers($ass->getExerciseId()));
2742 
2743  $ilDB->manipulate("UPDATE exc_assignment".
2744  " SET fb_cron_done = ".$ilDB->quote(1, "integer").
2745  " WHERE id = ".$ilDB->quote($a_ass_id, "integer"));
2746  return true;
2747  }
2748 
2752 
2757  {
2758  global $ilDB;
2759 
2760 
2761  // send and delete the zip file
2762  $deliverFilename = trim(str_replace(" ", "_", $this->getTitle()."_".$this->getId()));
2763  $deliverFilename = ilUtil::getASCIIFilename($deliverFilename);
2764  $deliverFilename = "multi_feedback_".$deliverFilename;
2765 
2766  $exc = new ilObjExercise($this->getExerciseId(), false);
2767 
2768  $cdir = getcwd();
2769 
2770  // create temporary directoy
2771  $tmpdir = ilUtil::ilTempnam();
2772  ilUtil::makeDir($tmpdir);
2773  $mfdir = $tmpdir."/".$deliverFilename;
2774  ilUtil::makeDir($mfdir);
2775 
2776  // create subfolders <lastname>_<firstname>_<id> for each participant
2777  include_once("./Modules/Exercise/classes/class.ilExerciseMembers.php");
2778  $exmem = new ilExerciseMembers($exc);
2779  $mems = $exmem->getMembers();
2780 
2781  foreach ($mems as $mem)
2782  {
2783  $name = ilObjUser::_lookupName($mem);
2784  $subdir = $name["lastname"]."_".$name["firstname"]."_".$name["login"]."_".$name["user_id"];
2785  $subdir = ilUtil::getASCIIFilename($subdir);
2786  ilUtil::makeDir($mfdir."/".$subdir);
2787  }
2788 
2789  // create the zip file
2790  chdir($tmpdir);
2791  $tmpzipfile = $tmpdir."/multi_feedback.zip";
2792  ilUtil::zip($tmpdir, $tmpzipfile, true);
2793  chdir($cdir);
2794 
2795 
2796  ilUtil::deliverFile($tmpzipfile, $deliverFilename.".zip", "", false, true);
2797  }
2798 
2805  function uploadMultiFeedbackFile($a_file)
2806  {
2807  global $lng, $ilUser;
2808 
2809  include_once("./Modules/Exercise/exceptions/class.ilExerciseException.php");
2810  if (!is_file($a_file["tmp_name"]))
2811  {
2812  throw new ilExerciseException($lng->txt("exc_feedback_file_could_not_be_uploaded"));
2813  }
2814 
2815  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
2816  $storage = new ilFSStorageExercise($this->getExerciseId(), $this->getId());
2817  $mfu = $storage->getMultiFeedbackUploadPath($ilUser->getId());
2818  ilUtil::delDir($mfu, true);
2819  ilUtil::moveUploadedFile($a_file["tmp_name"], "multi_feedback.zip", $mfu."/"."multi_feedback.zip");
2820  ilUtil::unzip($mfu."/multi_feedback.zip", true);
2821  $subdirs = ilUtil::getDir($mfu);
2822  $subdir = "notfound";
2823  foreach ($subdirs as $s => $j)
2824  {
2825  if ($j["type"] == "dir" && substr($s, 0, 14) == "multi_feedback")
2826  {
2827  $subdir = $s;
2828  }
2829  }
2830 
2831  if (!is_dir($mfu."/".$subdir))
2832  {
2833  throw new ilExerciseException($lng->txt("exc_no_feedback_dir_found_in_zip"));
2834  }
2835 
2836  return true;
2837  }
2838 
2845  function getMultiFeedbackFiles($a_user_id = 0)
2846  {
2847  global $ilUser;
2848 
2849  if ($a_user_id == 0)
2850  {
2851  $a_user_id = $ilUser->getId();
2852  }
2853 
2854  $mf_files = array();
2855 
2856  // get members
2857  $exc = new ilObjExercise($this->getExerciseId(), false);
2858  include_once("./Modules/Exercise/classes/class.ilExerciseMembers.php");
2859  $exmem = new ilExerciseMembers($exc);
2860  $mems = $exmem->getMembers();
2861 
2862  // read mf directory
2863  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
2864  $storage = new ilFSStorageExercise($this->getExerciseId(), $this->getId());
2865  $mfu = $storage->getMultiFeedbackUploadPath($ilUser->getId());
2866 
2867  // get subdir that starts with multi_feedback
2868  $subdirs = ilUtil::getDir($mfu);
2869  $subdir = "notfound";
2870  foreach ($subdirs as $s => $j)
2871  {
2872  if ($j["type"] == "dir" && substr($s, 0, 14) == "multi_feedback")
2873  {
2874  $subdir = $s;
2875  }
2876  }
2877 
2878  $items = ilUtil::getDir($mfu."/".$subdir);
2879  foreach ($items as $k => $i)
2880  {
2881  // check directory
2882  if ($i["type"] == "dir" && !in_array($k, array(".", "..")))
2883  {
2884  // check if valid member id is given
2885  $parts = explode("_", $i["entry"]);
2886  $user_id = (int) $parts[count($parts) - 1];
2887  if (in_array($user_id, $mems))
2888  {
2889  // read dir of user
2890  $name = ilObjUser::_lookupName($user_id);
2891  $files = ilUtil::getDir($mfu."/".$subdir."/".$k);
2892  foreach ($files as $k2 => $f)
2893  {
2894  // append files to array
2895  if ($f["type"] == "file" && substr($k2, 0, 1) != ".")
2896  {
2897  $mf_files[] = array(
2898  "lastname" => $name["lastname"],
2899  "firstname" => $name["firstname"],
2900  "login" => $name["login"],
2901  "user_id" => $name["user_id"],
2902  "full_path" => $mfu."/".$subdir."/".$k."/".$k2,
2903  "file" => $k2);
2904  }
2905  }
2906  }
2907  }
2908  }
2909  return $mf_files;
2910  }
2911 
2919  {
2920  global $lng, $ilUser;
2921 
2922  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
2923  $storage = new ilFSStorageExercise($this->getExerciseId(), $this->getId());
2924  $mfu = $storage->getMultiFeedbackUploadPath($ilUser->getId());
2925  ilUtil::delDir($mfu);
2926  }
2927 
2934  function saveMultiFeedbackFiles($a_files)
2935  {
2936  $exc = new ilObjExercise($this->getExerciseId(), false);
2937 
2938  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
2939  $fstorage = new ilFSStorageExercise($this->getExerciseId(), $this->getId());
2940  $fstorage->create();
2941 
2942  $team_map = array();
2943 
2944  $mf_files = $this->getMultiFeedbackFiles();
2945  foreach ($mf_files as $f)
2946  {
2947  $user_id = $f["user_id"];
2948  $file_path = $f["full_path"];
2949  $file_name = $f["file"];
2950 
2951  // if checked in confirmation gui
2952  if ($a_files[$user_id][md5($file_name)] != "")
2953  {
2954  // #14294 - team assignment
2955  if ($this->getType() == ilExAssignment::TYPE_UPLOAD_TEAM)
2956  {
2957  // just once for each user
2958  if (!array_key_exists($user_id, $team_map))
2959  {
2960  $team_id = $this->getTeamId($user_id);
2961  $team_map[$user_id]["team_id"] = "t".$team_id;
2962 
2963  $team_map[$user_id]["noti_rec_ids"] = array();
2964  foreach ($this->getTeamMembers($team_id) as $team_user_id)
2965  {
2966  $team_map[$user_id]["noti_rec_ids"][] = $team_user_id;
2967  }
2968  }
2969 
2970  $feedback_id = $team_map[$user_id]["team_id"];
2971  $noti_rec_ids = $team_map[$user_id]["noti_rec_ids"];
2972  }
2973  else
2974  {
2975  $feedback_id = $user_id;
2976  $noti_rec_ids = array($user_id);
2977  }
2978 
2979  if ($feedback_id)
2980  {
2981  $fb_path = $fstorage->getFeedbackPath($feedback_id);
2982  $target = $fb_path."/".$file_name;
2983  if (is_file($target))
2984  {
2985  unlink($target);
2986  }
2987  // rename file
2988  rename($file_path, $target);
2989  }
2990 
2991  if ($noti_rec_ids)
2992  {
2993  $exc->sendFeedbackFileNotification($file_name, $noti_rec_ids,
2994  (int) $this->getId());
2995  }
2996  }
2997  }
2998 
2999  $this->clearMultiFeedbackDirectory();
3000  }
3001 
3002 }
3003 
3004 ?>