ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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 {
16  protected $db;
17 
21  protected $lng;
22 
26  protected $user;
27 
31  protected $app_event_handler;
32 
33  const TYPE_UPLOAD = 1;
34  const TYPE_BLOG = 2;
35  const TYPE_PORTFOLIO = 3;
36  const TYPE_UPLOAD_TEAM = 4;
37  const TYPE_TEXT = 5;
38 
41 
45 
46  protected $id;
47  protected $exc_id;
48  protected $type;
49  protected $start_time;
50  protected $deadline;
51  protected $deadline2;
52  protected $instruction;
53  protected $title;
54  protected $mandatory;
55  protected $order_nr;
56  protected $peer;
57  protected $peer_min;
58  protected $peer_unlock;
59  protected $peer_dl;
60  protected $peer_valid;
61  protected $peer_file;
62  protected $peer_personal;
63  protected $peer_char;
64  protected $peer_text;
65  protected $peer_rating;
66  protected $peer_crit_cat;
67  protected $feedback_file;
68  protected $feedback_cron;
69  protected $feedback_date;
70  protected $team_tutor = false;
71  protected $max_file;
73  protected $min_char_limit;
74  protected $max_char_limit;
75 
76  protected $member_status = array(); // [array]
77 
78  protected $log;
79 
83  public function __construct($a_id = 0)
84  {
85  global $DIC;
86 
87  $this->db = $DIC->database();
88  $this->lng = $DIC->language();
89  $this->user = $DIC->user();
90  $this->app_event_handler = $DIC["ilAppEventHandler"];
91  $this->setType(self::TYPE_UPLOAD);
92  $this->setFeedbackDate(self::FEEDBACK_DATE_DEADLINE);
93 
94  $this->log = ilLoggerFactory::getLogger("exc");
95 
96  if ($a_id > 0) {
97  $this->setId($a_id);
98  $this->read();
99  }
100  }
101 
102  public static function getInstancesByExercise($a_exc_id)
103  {
104  global $DIC;
105 
106  $ilDB = $DIC->database();
107 
108  $set = $ilDB->query("SELECT * FROM exc_assignment " .
109  " WHERE exc_id = " . $ilDB->quote($a_exc_id, "integer") .
110  " ORDER BY order_nr ASC");
111  $data = array();
112 
113  $order_val = 10;
114  while ($rec = $ilDB->fetchAssoc($set)) {
115  // ???
116  $rec["order_val"] = $order_val;
117 
118  $ass = new self();
119  $ass->initFromDB($rec);
120  $data[] = $ass;
121 
122  $order_val += 10;
123  }
124 
125  return $data;
126  }
127 
133  public static function instructionFileGetFileOrderData($a_file_data, $a_ass_id)
134  {
135  global $DIC;
136 
137  $db = $DIC->database();
138  $db->setLimit(1, 0);
139 
140  $result_order_val = $db->query("
141  SELECT id, order_nr
142  FROM exc_ass_file_order
143  WHERE assignment_id = {$db->quote($a_ass_id, 'integer')}
144  AND filename = {$db->quote($a_file_data['entry'], 'string')}
145  ");
146 
147  $order_val = 0;
148  $order_id = 0;
149  while ($row = $db->fetchAssoc($result_order_val)) {
150  $order_val = (int) $row['order_nr'];
151  $order_id = (int) $row['id'];
152  }
153  return array($order_val, $order_id);
154  }
155 
156  public function hasTeam()
157  {
158  return $this->type == self::TYPE_UPLOAD_TEAM;
159  }
160 
166  public function setId($a_val)
167  {
168  $this->id = $a_val;
169  }
170 
176  public function getId()
177  {
178  return $this->id;
179  }
180 
186  public function setExerciseId($a_val)
187  {
188  $this->exc_id = $a_val;
189  }
190 
196  public function getExerciseId()
197  {
198  return $this->exc_id;
199  }
200 
206  public function setStartTime($a_val)
207  {
208  $this->start_time = $a_val;
209  }
210 
216  public function getStartTime()
217  {
218  return $this->start_time;
219  }
220 
226  public function setDeadline($a_val)
227  {
228  $this->deadline = $a_val;
229  }
230 
236  public function getDeadline()
237  {
238  return $this->deadline;
239  }
240 
246  public function getPersonalDeadline($a_user_id)
247  {
248  $ilDB = $this->db;
249 
250  $is_team = false;
251  if ($this->getType() == self::TYPE_UPLOAD_TEAM) {
252  include_once("./Modules/Exercise/classes/class.ilExAssignmentTeam.php");
253  $team_id = ilExAssignmentTeam::getTeamId($this->getId(), $a_user_id);
254  if (!$team_id) {
255  // #0021043
256  $this->getDeadline();
257  }
258  $a_user_id = $team_id;
259  $is_team = true;
260  }
261 
262  $set = $ilDB->query("SELECT tstamp FROM exc_idl" .
263  " WHERE ass_id = " . $ilDB->quote($this->getId(), "integer") .
264  " AND member_id = " . $ilDB->quote($a_user_id, "integer") .
265  " AND is_team = " . $ilDB->quote($is_team, "integer"));
266  $row = $ilDB->fetchAssoc($set);
267 
268  // use assignment deadline if no direct personal
269  return max($row["tstamp"], $this->getDeadline());
270  }
271 
277  protected function getLastPersonalDeadline()
278  {
279  $ilDB = $this->db;
280 
281  $set = $ilDB->query("SELECT MAX(tstamp) FROM exc_idl" .
282  " WHERE ass_id = " . $ilDB->quote($this->getId(), "integer"));
283  $row = $ilDB->fetchAssoc($set);
284  return $row["tstamp"];
285  }
286 
292  public function setExtendedDeadline($a_val)
293  {
294  if ($a_val !== null) {
295  $a_val = (int) $a_val;
296  }
297  $this->deadline2 = $a_val;
298  }
299 
305  public function getExtendedDeadline()
306  {
307  return $this->deadline2;
308  }
309 
315  public function setInstruction($a_val)
316  {
317  $this->instruction = $a_val;
318  }
319 
325  public function getInstruction()
326  {
327  return $this->instruction;
328  }
329 
335  public function setTitle($a_val)
336  {
337  $this->title = $a_val;
338  }
339 
345  public function getTitle()
346  {
347  return $this->title;
348  }
349 
355  public function setMandatory($a_val)
356  {
357  $this->mandatory = $a_val;
358  }
359 
365  public function getMandatory()
366  {
367  return $this->mandatory;
368  }
369 
375  public function setOrderNr($a_val)
376  {
377  $this->order_nr = $a_val;
378  }
379 
385  public function getOrderNr()
386  {
387  return $this->order_nr;
388  }
389 
395  public function setType($a_value)
396  {
397  if ($this->isValidType($a_value)) {
398  $this->type = (int) $a_value;
399 
400  if ($this->type == self::TYPE_UPLOAD_TEAM) {
401  $this->setPeerReview(false);
402  }
403  }
404  }
405 
411  public function getType()
412  {
413  return $this->type;
414  }
415 
422  public function isValidType($a_value)
423  {
424  if (in_array((int) $a_value, array(self::TYPE_UPLOAD, self::TYPE_BLOG,
425  self::TYPE_PORTFOLIO, self::TYPE_UPLOAD_TEAM, self::TYPE_TEXT))) {
426  return true;
427  }
428  return false;
429  }
430 
436  public function setPeerReview($a_value)
437  {
438  $this->peer = (bool) $a_value;
439  }
440 
446  public function getPeerReview()
447  {
448  return (bool) $this->peer;
449  }
450 
456  public function setPeerReviewMin($a_value)
457  {
458  $this->peer_min = (int) $a_value;
459  }
460 
466  public function getPeerReviewMin()
467  {
468  return (int) $this->peer_min;
469  }
470 
476  public function setPeerReviewSimpleUnlock($a_value)
477  {
478  $this->peer_unlock = (bool) $a_value;
479  }
480 
486  public function getPeerReviewSimpleUnlock()
487  {
488  return (bool) $this->peer_unlock;
489  }
490 
496  public function setPeerReviewDeadline($a_val)
497  {
498  $this->peer_dl = $a_val;
499  }
500 
506  public function getPeerReviewDeadline()
507  {
508  return $this->peer_dl;
509  }
510 
516  public function setPeerReviewValid($a_value)
517  {
518  $this->peer_valid = (int) $a_value;
519  }
520 
526  public function getPeerReviewValid()
527  {
528  return (int) $this->peer_valid;
529  }
530 
536  public function setPeerReviewRating($a_val)
537  {
538  $this->peer_rating = (bool) $a_val;
539  }
540 
546  public function hasPeerReviewRating()
547  {
548  return $this->peer_rating;
549  }
550 
556  public function setPeerReviewText($a_val)
557  {
558  $this->peer_text = (bool) $a_val;
559  }
560 
566  public function hasPeerReviewText()
567  {
568  return $this->peer_text;
569  }
570 
576  public function setPeerReviewFileUpload($a_val)
577  {
578  $this->peer_file = (bool) $a_val;
579  }
580 
586  public function hasPeerReviewFileUpload()
587  {
588  return $this->peer_file;
589  }
590 
596  public function setPeerReviewPersonalized($a_val)
597  {
598  $this->peer_personal = (bool) $a_val;
599  }
600 
606  public function hasPeerReviewPersonalized()
607  {
608  return $this->peer_personal;
609  }
610 
616  public function setPeerReviewChars($a_value)
617  {
618  $a_value = (is_numeric($a_value) && (int) $a_value > 0)
619  ? (int) $a_value
620  : null;
621  $this->peer_char = $a_value;
622  }
623 
629  public function getPeerReviewChars()
630  {
631  return $this->peer_char;
632  }
633 
639  public function setPeerReviewCriteriaCatalogue($a_value)
640  {
641  $a_value = is_numeric($a_value)
642  ? (int) $a_value
643  : null;
644  $this->crit_cat = $a_value;
645  }
646 
653  {
654  return $this->crit_cat;
655  }
656 
658  {
659  include_once "Modules/Exercise/classes/class.ilExcCriteria.php";
660 
661  if ($this->crit_cat) {
662  return ilExcCriteria::getInstancesByParentId($this->crit_cat);
663  } else {
664  $res = array();
665 
666  if ($this->peer_rating) {
668  }
669 
670  if ($this->peer_text) {
671  $crit = ilExcCriteria::getInstanceByType("text");
672  if ($this->peer_char) {
673  $crit->setMinChars($this->peer_char);
674  }
675  $res[] = $crit;
676  }
677 
678  if ($this->peer_file) {
680  }
681 
682  return $res;
683  }
684  }
685 
691  public function setFeedbackFile($a_value)
692  {
693  $this->feedback_file = (string) $a_value;
694  }
695 
701  public function getFeedbackFile()
702  {
703  return (string) $this->feedback_file;
704  }
705 
711  public function setFeedbackCron($a_value)
712  {
713  $this->feedback_cron = (string) $a_value;
714  }
715 
721  public function hasFeedbackCron()
722  {
723  return (bool) $this->feedback_cron;
724  }
725 
731  public function setFeedbackDate($a_value)
732  {
733  $this->feedback_date = (int) $a_value;
734  }
735 
741  public function getFeedbackDate()
742  {
743  return (int) $this->feedback_date;
744  }
745 
751  public function setTeamTutor($a_value)
752  {
753  $this->team_tutor = (bool) $a_value;
754  }
755 
761  public function getTeamTutor()
762  {
763  return $this->team_tutor;
764  }
765 
771  public function setMaxFile($a_value)
772  {
773  if ($a_value !== null) {
774  $a_value = (int) $a_value;
775  }
776  $this->max_file = $a_value;
777  }
778 
784  public function getMaxFile()
785  {
786  return $this->max_file;
787  }
788 
794  public function setPortfolioTemplateId($a_val)
795  {
796  $this->portfolio_template = $a_val;
797  }
798 
804  public function getPortfolioTemplateId()
805  {
807  }
808 
809 
813  public function read()
814  {
815  $ilDB = $this->db;
816 
817  $set = $ilDB->query(
818  "SELECT * FROM exc_assignment " .
819  " WHERE id = " . $ilDB->quote($this->getId(), "integer")
820  );
821  $rec = $ilDB->fetchAssoc($set);
822 
823  // #16172 - might be deleted
824  if (is_array($rec)) {
825  $this->initFromDB($rec);
826  }
827  }
828 
835  protected function initFromDB(array $a_set)
836  {
837  $this->setId($a_set["id"]);
838  $this->setExerciseId($a_set["exc_id"]);
839  $this->setDeadline($a_set["time_stamp"]);
840  $this->setExtendedDeadline($a_set["deadline2"]);
841  $this->setInstruction($a_set["instruction"]);
842  $this->setTitle($a_set["title"]);
843  $this->setStartTime($a_set["start_time"]);
844  $this->setOrderNr($a_set["order_nr"]);
845  $this->setMandatory($a_set["mandatory"]);
846  $this->setType($a_set["type"]);
847  $this->setPeerReview($a_set["peer"]);
848  $this->setPeerReviewMin($a_set["peer_min"]);
849  $this->setPeerReviewSimpleUnlock($a_set["peer_unlock"]);
850  $this->setPeerReviewDeadline($a_set["peer_dl"]);
851  $this->setPeerReviewValid($a_set["peer_valid"]);
852  $this->setPeerReviewFileUpload($a_set["peer_file"]);
853  $this->setPeerReviewPersonalized($a_set["peer_prsl"]);
854  $this->setPeerReviewChars($a_set["peer_char"]);
855  $this->setPeerReviewText($a_set["peer_text"]);
856  $this->setPeerReviewRating($a_set["peer_rating"]);
857  $this->setPeerReviewCriteriaCatalogue($a_set["peer_crit_cat"]);
858  $this->setFeedbackFile($a_set["fb_file"]);
859  $this->setFeedbackDate($a_set["fb_date"]);
860  $this->setFeedbackCron($a_set["fb_cron"]);
861  $this->setTeamTutor($a_set["team_tutor"]);
862  $this->setMaxFile($a_set["max_file"]);
863  $this->setPortfolioTemplateId($a_set["portfolio_template"]);
864  $this->setMinCharLimit($a_set["min_char_limit"]);
865  $this->setMaxCharLimit($a_set["max_char_limit"]);
866  }
867 
871  public function save()
872  {
873  $ilDB = $this->db;
874 
875  if ($this->getOrderNr() == 0) {
876  $this->setOrderNr(
877  self::lookupMaxOrderNrForEx($this->getExerciseId())
878  + 10
879  );
880  }
881 
882  $next_id = $ilDB->nextId("exc_assignment");
883  $ilDB->insert("exc_assignment", array(
884  "id" => array("integer", $next_id),
885  "exc_id" => array("integer", $this->getExerciseId()),
886  "time_stamp" => array("integer", $this->getDeadline()),
887  "deadline2" => array("integer", $this->getExtendedDeadline()),
888  "instruction" => array("clob", $this->getInstruction()),
889  "title" => array("text", $this->getTitle()),
890  "start_time" => array("integer", $this->getStartTime()),
891  "order_nr" => array("integer", $this->getOrderNr()),
892  "mandatory" => array("integer", $this->getMandatory()),
893  "type" => array("integer", $this->getType()),
894  "peer" => array("integer", $this->getPeerReview()),
895  "peer_min" => array("integer", $this->getPeerReviewMin()),
896  "peer_unlock" => array("integer", $this->getPeerReviewSimpleUnlock()),
897  "peer_dl" => array("integer", $this->getPeerReviewDeadline()),
898  "peer_valid" => array("integer", $this->getPeerReviewValid()),
899  "peer_file" => array("integer", $this->hasPeerReviewFileUpload()),
900  "peer_prsl" => array("integer", $this->hasPeerReviewPersonalized()),
901  "peer_char" => array("integer", $this->getPeerReviewChars()),
902  "peer_text" => array("integer", (int) $this->hasPeerReviewText()),
903  "peer_rating" => array("integer", (int) $this->hasPeerReviewRating()),
904  "peer_crit_cat" => array("integer", $this->getPeerReviewCriteriaCatalogue()),
905  "fb_file" => array("text", $this->getFeedbackFile()),
906  "fb_date" => array("integer", $this->getFeedbackDate()),
907  "fb_cron" => array("integer", $this->hasFeedbackCron()),
908  "team_tutor" => array("integer", $this->getTeamTutor()),
909  "max_file" => array("integer", $this->getMaxFile()),
910  "portfolio_template" => array("integer", $this->getPortFolioTemplateId()),
911  "min_char_limit" => array("integer", $this->getMinCharLimit()),
912  "max_char_limit" => array("integer", $this->getMaxCharLimit())
913  ));
914  $this->setId($next_id);
915  $exc = new ilObjExercise($this->getExerciseId(), false);
916  $exc->updateAllUsersStatus();
917  self::createNewAssignmentRecords($next_id, $exc);
918 
919  $this->handleCalendarEntries("create");
920  }
921 
925  public function update()
926  {
927  $ilDB = $this->db;
928 
929  $ilDB->update(
930  "exc_assignment",
931  array(
932  "exc_id" => array("integer", $this->getExerciseId()),
933  "time_stamp" => array("integer", $this->getDeadline()),
934  "deadline2" => array("integer", $this->getExtendedDeadline()),
935  "instruction" => array("clob", $this->getInstruction()),
936  "title" => array("text", $this->getTitle()),
937  "start_time" => array("integer", $this->getStartTime()),
938  "order_nr" => array("integer", $this->getOrderNr()),
939  "mandatory" => array("integer", $this->getMandatory()),
940  "type" => array("integer", $this->getType()),
941  "peer" => array("integer", $this->getPeerReview()),
942  "peer_min" => array("integer", $this->getPeerReviewMin()),
943  "peer_unlock" => array("integer", $this->getPeerReviewSimpleUnlock()),
944  "peer_dl" => array("integer", $this->getPeerReviewDeadline()),
945  "peer_valid" => array("integer", $this->getPeerReviewValid()),
946  "peer_file" => array("integer", $this->hasPeerReviewFileUpload()),
947  "peer_prsl" => array("integer", $this->hasPeerReviewPersonalized()),
948  "peer_char" => array("integer", $this->getPeerReviewChars()),
949  "peer_text" => array("integer", (int) $this->hasPeerReviewText()),
950  "peer_rating" => array("integer", (int) $this->hasPeerReviewRating()),
951  "peer_crit_cat" => array("integer", $this->getPeerReviewCriteriaCatalogue()),
952  "fb_file" => array("text", $this->getFeedbackFile()),
953  "fb_date" => array("integer", $this->getFeedbackDate()),
954  "fb_cron" => array("integer", $this->hasFeedbackCron()),
955  "team_tutor" => array("integer", $this->getTeamTutor()),
956  "max_file" => array("integer", $this->getMaxFile()),
957  "portfolio_template" => array("integer", $this->getPortFolioTemplateId()),
958  "min_char_limit" => array("integer", $this->getMinCharLimit()),
959  "max_char_limit" => array("integer", $this->getMaxCharLimit())
960  ),
961  array(
962  "id" => array("integer", $this->getId()),
963  )
964  );
965  $exc = new ilObjExercise($this->getExerciseId(), false);
966  $exc->updateAllUsersStatus();
967 
968  $this->handleCalendarEntries("update");
969  }
970 
974  public function delete()
975  {
976  $ilDB = $this->db;
977 
978  $this->deleteGlobalFeedbackFile();
979 
980  $ilDB->manipulate(
981  "DELETE FROM exc_assignment WHERE " .
982  " id = " . $ilDB->quote($this->getId(), "integer")
983  );
984  $exc = new ilObjExercise($this->getExerciseId(), false);
985  $exc->updateAllUsersStatus();
986 
987  $this->handleCalendarEntries("delete");
988  }
989 
990 
994  public static function getAssignmentDataOfExercise($a_exc_id)
995  {
996  global $DIC;
997 
998  $ilDB = $DIC->database();
999 
1000  // should be changed to self::getInstancesByExerciseId()
1001 
1002  $set = $ilDB->query("SELECT * FROM exc_assignment " .
1003  " WHERE exc_id = " . $ilDB->quote($a_exc_id, "integer") .
1004  " ORDER BY order_nr ASC");
1005  $data = array();
1006 
1007  $order_val = 10;
1008  while ($rec = $ilDB->fetchAssoc($set)) {
1009  $data[] = array(
1010  "id" => $rec["id"],
1011  "exc_id" => $rec["exc_id"],
1012  "deadline" => $rec["time_stamp"],
1013  "deadline2" => $rec["deadline2"],
1014  "instruction" => $rec["instruction"],
1015  "title" => $rec["title"],
1016  "start_time" => $rec["start_time"],
1017  "order_val" => $order_val,
1018  "mandatory" => $rec["mandatory"],
1019  "type" => $rec["type"],
1020  "peer" => $rec["peer"],
1021  "peer_min" => $rec["peer_min"],
1022  "peer_dl" => $rec["peer_dl"],
1023  "peer_file" => $rec["peer_file"],
1024  "peer_prsl" => $rec["peer_prsl"],
1025  "fb_file" => $rec["fb_file"],
1026  "fb_date" => $rec["fb_date"],
1027  "fb_cron" => $rec["fb_cron"],
1028  );
1029  $order_val += 10;
1030  }
1031  return $data;
1032  }
1033 
1040  public static function cloneAssignmentsOfExercise($a_old_exc_id, $a_new_exc_id, array $a_crit_cat_map)
1041  {
1042  $ass_data = self::getInstancesByExercise($a_old_exc_id);
1043  foreach ($ass_data as $d) {
1044  // clone assignment
1045  $new_ass = new ilExAssignment();
1046  $new_ass->setExerciseId($a_new_exc_id);
1047  $new_ass->setTitle($d->getTitle());
1048  $new_ass->setDeadline($d->getDeadline());
1049  $new_ass->setExtendedDeadline($d->getExtendedDeadline());
1050  $new_ass->setInstruction($d->getInstruction());
1051  $new_ass->setMandatory($d->getMandatory());
1052  $new_ass->setOrderNr($d->getOrderNr());
1053  $new_ass->setStartTime($d->getStartTime());
1054  $new_ass->setType($d->getType());
1055  $new_ass->setPeerReview($d->getPeerReview());
1056  $new_ass->setPeerReviewMin($d->getPeerReviewMin());
1057  $new_ass->setPeerReviewDeadline($d->getPeerReviewDeadline());
1058  $new_ass->setPeerReviewFileUpload($d->hasPeerReviewFileUpload());
1059  $new_ass->setPeerReviewPersonalized($d->hasPeerReviewPersonalized());
1060  $new_ass->setPeerReviewValid($d->getPeerReviewValid());
1061  $new_ass->setPeerReviewChars($d->getPeerReviewChars());
1062  $new_ass->setPeerReviewText($d->hasPeerReviewText());
1063  $new_ass->setPeerReviewRating($d->hasPeerReviewRating());
1064  $new_ass->setPeerReviewCriteriaCatalogue($d->getPeerReviewCriteriaCatalogue());
1065  $new_ass->setPeerReviewSimpleUnlock($d->getPeerReviewSimpleUnlock());
1066  $new_ass->setFeedbackFile($d->getFeedbackFile());
1067  $new_ass->setFeedbackDate($d->getFeedbackDate());
1068  $new_ass->setFeedbackCron($d->hasFeedbackCron()); // #16295
1069  $new_ass->setTeamTutor($d->getTeamTutor());
1070  $new_ass->setMaxFile($d->getMaxFile());
1071  $new_ass->setMinCharLimit($d->getMinCharLimit());
1072  $new_ass->setMaxCharLimit($d->getMaxCharLimit());
1073  $new_ass->setPortfolioTemplateId($d->getPortfolioTemplateId());
1074 
1075 
1076  // criteria catalogue(s)
1077  if ($d->getPeerReviewCriteriaCatalogue() &&
1078  array_key_exists($d->getPeerReviewCriteriaCatalogue(), $a_crit_cat_map)) {
1079  $new_ass->setPeerReviewCriteriaCatalogue($a_crit_cat_map[$d->getPeerReviewCriteriaCatalogue()]);
1080  }
1081 
1082  $new_ass->save();
1083 
1084 
1085  // clone assignment files
1086  include_once("./Modules/Exercise/classes/class.ilFSWebStorageExercise.php");
1087  $old_web_storage = new ilFSWebStorageExercise($a_old_exc_id, (int) $d->getId());
1088  $new_web_storage = new ilFSWebStorageExercise($a_new_exc_id, (int) $new_ass->getId());
1089  $new_web_storage->create();
1090  if (is_dir($old_web_storage->getPath())) {
1091  ilUtil::rCopy($old_web_storage->getPath(), $new_web_storage->getPath());
1092  }
1093 
1094  // clone global feedback file
1095  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
1096  $old_storage = new ilFSStorageExercise($a_old_exc_id, (int) $d->getId());
1097  $new_storage = new ilFSStorageExercise($a_new_exc_id, (int) $new_ass->getId());
1098  $new_storage->create();
1099  if (is_dir($old_storage->getGlobalFeedbackPath())) {
1100  ilUtil::rCopy($old_storage->getGlobalFeedbackPath(), $new_storage->getGlobalFeedbackPath());
1101  }
1102  }
1103  }
1104 
1108  public function getFiles()
1109  {
1110  $this->log->debug("getting files from class.ilExAssignment using ilFSWebStorageExercise");
1111  include_once("./Modules/Exercise/classes/class.ilFSWebStorageExercise.php");
1112  $storage = new ilFSWebStorageExercise($this->getExerciseId(), $this->getId());
1113  return $storage->getFiles();
1114  }
1115 
1120  public function getInstructionFilesOrder()
1121  {
1122  $ilDB = $this->db;
1123 
1124  $set = $ilDB->query(
1125  "SELECT filename, order_nr, id FROM exc_ass_file_order " .
1126  " WHERE assignment_id = " . $ilDB->quote($this->getId(), "integer")
1127  );
1128 
1129  $data = array();
1130  while ($rec = $ilDB->fetchAssoc($set)) {
1131  $data[$rec['filename']] = $rec;
1132  }
1133 
1134  return $data;
1135  }
1136 
1140  public static function lookupMaxOrderNrForEx($a_exc_id)
1141  {
1142  global $DIC;
1143 
1144  $ilDB = $DIC->database();
1145 
1146  $set = $ilDB->query(
1147  "SELECT MAX(order_nr) mnr FROM exc_assignment " .
1148  " WHERE exc_id = " . $ilDB->quote($a_exc_id, "integer")
1149  );
1150  while ($rec = $ilDB->fetchAssoc($set)) {
1151  return (int) $rec["mnr"];
1152  }
1153  return 0;
1154  }
1155 
1161  public static function lookupAssignmentOnline($a_ass_id)
1162  {
1163  global $DIC;
1164 
1165  $ilDB = $DIC->database();
1166 
1167  $query = "SELECT id FROM exc_assignment " .
1168  "WHERE start_time <= " . $ilDB->quote(time(), 'integer') . ' ' .
1169  "AND time_stamp >= " . $ilDB->quote(time(), 'integer') . ' ' .
1170  "AND id = " . $ilDB->quote($a_ass_id, 'integer');
1171  $res = $ilDB->query($query);
1172 
1173  return $res->numRows() ? true : false;
1174  }
1175 
1182  public static function lookupExerciseId($a_ass_id)
1183  {
1184  global $DIC;
1185 
1186  $ilDB = $DIC->database();
1187 
1188  $query = "SELECT exc_id FROM exc_assignment " .
1189  "WHERE id = " . $ilDB->quote($a_ass_id, 'integer');
1190  $res = $ilDB->fetchAssoc($ilDB->query($query));
1191 
1192  return (int) $res["exc_id"];
1193  }
1194 
1198  private static function lookup($a_id, $a_field)
1199  {
1200  global $DIC;
1201 
1202  $ilDB = $DIC->database();
1203 
1204  $set = $ilDB->query(
1205  "SELECT " . $a_field . " FROM exc_assignment " .
1206  " WHERE id = " . $ilDB->quote($a_id, "integer")
1207  );
1208 
1209  $rec = $ilDB->fetchAssoc($set);
1210 
1211  return $rec[$a_field];
1212  }
1213 
1217  public static function lookupTitle($a_id)
1218  {
1219  return self::lookup($a_id, "title");
1220  }
1221 
1225  public static function lookupType($a_id)
1226  {
1227  return self::lookup($a_id, "type");
1228  }
1229 
1233  public static function saveAssOrderOfExercise($a_ex_id, $a_order)
1234  {
1235  global $DIC;
1236 
1237  $ilDB = $DIC->database();
1238 
1239  $result_order = array();
1240  asort($a_order);
1241  $nr = 10;
1242  foreach ($a_order as $k => $v) {
1243  // the check for exc_id is for security reasons. ass ids are unique.
1244  $ilDB->manipulate(
1245  $t = "UPDATE exc_assignment SET " .
1246  " order_nr = " . $ilDB->quote($nr, "integer") .
1247  " WHERE id = " . $ilDB->quote((int) $k, "integer") .
1248  " AND exc_id = " . $ilDB->quote((int) $a_ex_id, "integer")
1249  );
1250  $nr+=10;
1251  }
1252  }
1253 
1257  public static function orderAssByDeadline($a_ex_id)
1258  {
1259  global $DIC;
1260 
1261  $ilDB = $DIC->database();
1262 
1263  $set = $ilDB->query(
1264  "SELECT id FROM exc_assignment " .
1265  " WHERE exc_id = " . $ilDB->quote($a_ex_id, "integer") .
1266  " ORDER BY time_stamp ASC"
1267  );
1268  $nr = 10;
1269  while ($rec = $ilDB->fetchAssoc($set)) {
1270  $ilDB->manipulate(
1271  "UPDATE exc_assignment SET " .
1272  " order_nr = " . $ilDB->quote($nr, "integer") .
1273  " WHERE id = " . $ilDB->quote($rec["id"], "integer")
1274  );
1275  $nr += 10;
1276  }
1277  }
1278 
1282  public static function countMandatory($a_ex_id)
1283  {
1284  global $DIC;
1285 
1286  $ilDB = $DIC->database();
1287 
1288  $set = $ilDB->query(
1289  "SELECT count(*) cntm FROM exc_assignment " .
1290  " WHERE exc_id = " . $ilDB->quote($a_ex_id, "integer") .
1291  " AND mandatory = " . $ilDB->quote(1, "integer")
1292  );
1293  $rec = $ilDB->fetchAssoc($set);
1294  return $rec["cntm"];
1295  }
1296 
1298 
1302  public static function lookupUpdatedSubmission($ass_id, $member_id)
1303  {
1304  global $DIC;
1305 
1306  $ilDB = $DIC->database();
1307  $lng = $DIC->language();
1308 
1309  // team upload?
1310  $user_ids = self::getTeamMembersByAssignmentId($ass_id, $member_id);
1311  if (!$user_ids) {
1312  $user_ids = array($member_id);
1313  }
1314 
1315  $q="SELECT exc_mem_ass_status.status_time, exc_returned.ts " .
1316  "FROM exc_mem_ass_status, exc_returned " .
1317  "WHERE exc_mem_ass_status.status_time < exc_returned.ts " .
1318  "AND NOT exc_mem_ass_status.status_time IS NULL " .
1319  "AND exc_returned.ass_id = exc_mem_ass_status.ass_id " .
1320  "AND exc_returned.user_id = exc_mem_ass_status.usr_id " .
1321  "AND exc_returned.ass_id=" . $ilDB->quote($ass_id, "integer") .
1322  " AND " . $ilDB->in("exc_returned.user_id", $user_ids, "", "integer");
1323 
1324  $usr_set = $ilDB->query($q);
1325 
1326  $array = $ilDB->fetchAssoc($usr_set);
1327 
1328  if (count($array)==0) {
1329  return 0;
1330  } else {
1331  return 1;
1332  }
1333  }
1334 
1338  public function getMemberListData()
1339  {
1340  $ilDB = $this->db;
1341 
1342  $mem = array();
1343 
1344  // first get list of members from member table
1345  $set = $ilDB->query("SELECT ud.usr_id, ud.lastname, ud.firstname, ud.login" .
1346  " FROM exc_members excm" .
1347  " JOIN usr_data ud ON (ud.usr_id = excm.usr_id)" .
1348  " WHERE excm.obj_id = " . $ilDB->quote($this->getExerciseId(), "integer"));
1349  while ($rec = $ilDB->fetchAssoc($set)) {
1350  $mem[$rec["usr_id"]] =
1351  array(
1352  "name" => $rec["lastname"] . ", " . $rec["firstname"],
1353  "login" => $rec["login"],
1354  "usr_id" => $rec["usr_id"],
1355  "lastname" => $rec["lastname"],
1356  "firstname" => $rec["firstname"]
1357  );
1358  }
1359 
1360  include_once "Modules/Exercise/classes/class.ilExSubmission.php";
1361 
1362  $q = "SELECT * FROM exc_mem_ass_status " .
1363  "WHERE ass_id = " . $ilDB->quote($this->getId(), "integer");
1364  $set = $ilDB->query($q);
1365  while ($rec = $ilDB->fetchAssoc($set)) {
1366  if (isset($mem[$rec["usr_id"]])) {
1367  $sub = new ilExSubmission($this, $rec["usr_id"]);
1368 
1369  $mem[$rec["usr_id"]]["sent_time"] = $rec["sent_time"];
1370  $mem[$rec["usr_id"]]["submission"] = $sub->getLastSubmission();
1371  $mem[$rec["usr_id"]]["status_time"] = $rec["status_time"];
1372  $mem[$rec["usr_id"]]["feedback_time"] = $rec["feedback_time"];
1373  $mem[$rec["usr_id"]]["notice"] = $rec["notice"];
1374  $mem[$rec["usr_id"]]["status"] = $rec["status"];
1375  $mem[$rec["usr_id"]]["mark"] = $rec["mark"];
1376  $mem[$rec["usr_id"]]["comment"] = $rec["u_comment"];
1377  }
1378  }
1379  return $mem;
1380  }
1381 
1385  public static function createNewUserRecords($a_user_id, $a_exc_id)
1386  {
1387  global $DIC;
1388 
1389  $ilDB = $DIC->database();
1390 
1391  $ass_data = self::getAssignmentDataOfExercise($a_exc_id);
1392  foreach ($ass_data as $ass) {
1393  //echo "-".$ass["id"]."-".$a_user_id."-";
1394  $ilDB->replace("exc_mem_ass_status", array(
1395  "ass_id" => array("integer", $ass["id"]),
1396  "usr_id" => array("integer", $a_user_id)
1397  ), array(
1398  "status" => array("text", "notgraded")
1399  ));
1400  }
1401  }
1402 
1406  public static function createNewAssignmentRecords($a_ass_id, $a_exc)
1407  {
1408  global $DIC;
1409 
1410  $ilDB = $DIC->database();
1411 
1412  include_once("./Modules/Exercise/classes/class.ilExerciseMembers.php");
1413  $exmem = new ilExerciseMembers($a_exc);
1414  $mems = $exmem->getMembers();
1415 
1416  foreach ($mems as $mem) {
1417  $ilDB->replace("exc_mem_ass_status", array(
1418  "ass_id" => array("integer", $a_ass_id),
1419  "usr_id" => array("integer", $mem)
1420  ), array(
1421  "status" => array("text", "notgraded")
1422  ));
1423  }
1424  }
1425 
1430  public function uploadAssignmentFiles($a_files)
1431  {
1432  ilLoggerFactory::getLogger("exc")->debug("upload assignment files files = ", $a_files);
1433  include_once("./Modules/Exercise/classes/class.ilFSWebStorageExercise.php");
1434  $storage = new ilFSWebStorageExercise($this->getExerciseId(), $this->getId());
1435  $storage->create();
1436  $storage->uploadAssignmentFiles($a_files);
1437  }
1438 
1439 
1443 
1448  {
1449  global $DIC;
1450 
1451 
1452  // send and delete the zip file
1453  $deliverFilename = trim(str_replace(" ", "_", $this->getTitle() . "_" . $this->getId()));
1454  $deliverFilename = ilUtil::getASCIIFilename($deliverFilename);
1455  $deliverFilename = "multi_feedback_" . $deliverFilename;
1456 
1457  $exc = new ilObjExercise($this->getExerciseId(), false);
1458 
1459  $cdir = getcwd();
1460 
1461  // create temporary directoy
1462  $tmpdir = ilUtil::ilTempnam();
1463  ilUtil::makeDir($tmpdir);
1464  $mfdir = $tmpdir . "/" . $deliverFilename;
1465  ilUtil::makeDir($mfdir);
1466 
1467  // create subfolders <lastname>_<firstname>_<id> for each participant
1468  include_once("./Modules/Exercise/classes/class.ilExerciseMembers.php");
1469  $exmem = new ilExerciseMembers($exc);
1470  $mems = $exmem->getMembers();
1471 
1472  $mems = $DIC->access()->filterUserIdsByRbacOrPositionOfCurrentUser(
1473  'edit_submissions_grades',
1474  'edit_submissions_grades',
1475  $exercise->getRefId(),
1476  $mems
1477  );
1478  foreach ($mems as $mem) {
1479  $name = ilObjUser::_lookupName($mem);
1480  $subdir = $name["lastname"] . "_" . $name["firstname"] . "_" . $name["login"] . "_" . $name["user_id"];
1481  $subdir = ilUtil::getASCIIFilename($subdir);
1482  ilUtil::makeDir($mfdir . "/" . $subdir);
1483  }
1484 
1485  // create the zip file
1486  chdir($tmpdir);
1487  $tmpzipfile = $tmpdir . "/multi_feedback.zip";
1488  ilUtil::zip($tmpdir, $tmpzipfile, true);
1489  chdir($cdir);
1490 
1491 
1492  ilUtil::deliverFile($tmpzipfile, $deliverFilename . ".zip", "", false, true);
1493  }
1494 
1501  public function uploadMultiFeedbackFile($a_file)
1502  {
1503  $lng = $this->lng;
1504  $ilUser = $this->user;
1505 
1506  include_once("./Modules/Exercise/exceptions/class.ilExerciseException.php");
1507  if (!is_file($a_file["tmp_name"])) {
1508  throw new ilExerciseException($lng->txt("exc_feedback_file_could_not_be_uploaded"));
1509  }
1510 
1511  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
1512  $storage = new ilFSStorageExercise($this->getExerciseId(), $this->getId());
1513  $mfu = $storage->getMultiFeedbackUploadPath($ilUser->getId());
1514  ilUtil::delDir($mfu, true);
1515  ilUtil::moveUploadedFile($a_file["tmp_name"], "multi_feedback.zip", $mfu . "/" . "multi_feedback.zip");
1516  ilUtil::unzip($mfu . "/multi_feedback.zip", true);
1517  $subdirs = ilUtil::getDir($mfu);
1518  $subdir = "notfound";
1519  foreach ($subdirs as $s => $j) {
1520  if ($j["type"] == "dir" && substr($s, 0, 14) == "multi_feedback") {
1521  $subdir = $s;
1522  }
1523  }
1524 
1525  if (!is_dir($mfu . "/" . $subdir)) {
1526  throw new ilExerciseException($lng->txt("exc_no_feedback_dir_found_in_zip"));
1527  }
1528 
1529  return true;
1530  }
1531 
1538  public function getMultiFeedbackFiles($a_user_id = 0)
1539  {
1540  $ilUser = $this->user;
1541 
1542  if ($a_user_id == 0) {
1543  $a_user_id = $ilUser->getId();
1544  }
1545 
1546  $mf_files = array();
1547 
1548  // get members
1549  $exc = new ilObjExercise($this->getExerciseId(), false);
1550  include_once("./Modules/Exercise/classes/class.ilExerciseMembers.php");
1551  $exmem = new ilExerciseMembers($exc);
1552  $mems = $exmem->getMembers();
1553 
1554  // read mf directory
1555  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
1556  $storage = new ilFSStorageExercise($this->getExerciseId(), $this->getId());
1557  $mfu = $storage->getMultiFeedbackUploadPath($ilUser->getId());
1558 
1559  // get subdir that starts with multi_feedback
1560  $subdirs = ilUtil::getDir($mfu);
1561  $subdir = "notfound";
1562  foreach ($subdirs as $s => $j) {
1563  if ($j["type"] == "dir" && substr($s, 0, 14) == "multi_feedback") {
1564  $subdir = $s;
1565  }
1566  }
1567 
1568  $items = ilUtil::getDir($mfu . "/" . $subdir);
1569  foreach ($items as $k => $i) {
1570  // check directory
1571  if ($i["type"] == "dir" && !in_array($k, array(".", ".."))) {
1572  // check if valid member id is given
1573  $parts = explode("_", $i["entry"]);
1574  $user_id = (int) $parts[count($parts) - 1];
1575  if (in_array($user_id, $mems)) {
1576  // read dir of user
1577  $name = ilObjUser::_lookupName($user_id);
1578  $files = ilUtil::getDir($mfu . "/" . $subdir . "/" . $k);
1579  foreach ($files as $k2 => $f) {
1580  // append files to array
1581  if ($f["type"] == "file" && substr($k2, 0, 1) != ".") {
1582  $mf_files[] = array(
1583  "lastname" => $name["lastname"],
1584  "firstname" => $name["firstname"],
1585  "login" => $name["login"],
1586  "user_id" => $name["user_id"],
1587  "full_path" => $mfu . "/" . $subdir . "/" . $k . "/" . $k2,
1588  "file" => $k2);
1589  }
1590  }
1591  }
1592  }
1593  }
1594  return $mf_files;
1595  }
1596 
1604  {
1605  $lng = $this->lng;
1606  $ilUser = $this->user;
1607 
1608  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
1609  $storage = new ilFSStorageExercise($this->getExerciseId(), $this->getId());
1610  $mfu = $storage->getMultiFeedbackUploadPath($ilUser->getId());
1611  ilUtil::delDir($mfu);
1612  }
1613 
1620  public function saveMultiFeedbackFiles($a_files, ilObjExercise $a_exc)
1621  {
1622  if ($this->getExerciseId() != $a_exc->getId()) {
1623  return;
1624  }
1625 
1626  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
1627  $fstorage = new ilFSStorageExercise($this->getExerciseId(), $this->getId());
1628  $fstorage->create();
1629 
1630  $team_map = array();
1631 
1632  $mf_files = $this->getMultiFeedbackFiles();
1633  foreach ($mf_files as $f) {
1634  $user_id = $f["user_id"];
1635  $file_path = $f["full_path"];
1636  $file_name = $f["file"];
1637 
1638  // if checked in confirmation gui
1639  if ($a_files[$user_id][md5($file_name)] != "") {
1640  $submission = new ilExSubmission($this, $user_id);
1641  $feedback_id = $submission->getFeedbackId();
1642  $noti_rec_ids = $submission->getUserIds();
1643 
1644  if ($feedback_id) {
1645  $fb_path = $fstorage->getFeedbackPath($feedback_id);
1646  $target = $fb_path . "/" . $file_name;
1647  if (is_file($target)) {
1648  unlink($target);
1649  }
1650  // rename file
1651  rename($file_path, $target);
1652 
1653  if ($noti_rec_ids) {
1654  foreach ($noti_rec_ids as $user_id) {
1655  $member_status = $this->getMemberStatus($user_id);
1656  $member_status->setFeedback(true);
1657  $member_status->update();
1658  }
1659 
1661  $file_name,
1662  $noti_rec_ids,
1663  (int) $this->getId()
1664  );
1665  }
1666  }
1667  }
1668  }
1669 
1670  $this->clearMultiFeedbackDirectory();
1671  }
1672 
1673 
1674 
1675 
1681  protected function handleCalendarEntries($a_event)
1682  {
1683  $ilAppEventHandler = $this->app_event_handler;
1684 
1685  $dl_id = $this->getId() . "0";
1686  $fbdl_id = $this->getId() . "1";
1687 
1688  $context_ids = array($dl_id, $fbdl_id);
1689  $apps = array();
1690 
1691  if ($a_event != "delete") {
1692  include_once "Services/Calendar/classes/class.ilCalendarAppointmentTemplate.php";
1693 
1694  if ($this->getDeadline()) {
1695  $app = new ilCalendarAppointmentTemplate($dl_id);
1696  $app->setTranslationType(IL_CAL_TRANSLATION_SYSTEM);
1697  $app->setSubtitle("cal_exc_deadline");
1698  $app->setTitle($this->getTitle());
1699  $app->setFullday(false);
1700  $app->setStart(new ilDateTime($this->getDeadline(), IL_CAL_UNIX));
1701 
1702  $apps[] = $app;
1703  }
1704 
1705  if ($this->getPeerReview() &&
1706  $this->getPeerReviewDeadline()) {
1707  $app = new ilCalendarAppointmentTemplate($fbdl_id);
1708  $app->setTranslationType(IL_CAL_TRANSLATION_SYSTEM);
1709  $app->setSubtitle("cal_exc_peer_review_deadline");
1710  $app->setTitle($this->getTitle());
1711  $app->setFullday(false);
1712  $app->setStart(new ilDateTime($this->getPeerReviewDeadline(), IL_CAL_UNIX));
1713 
1714  $apps[] = $app;
1715  }
1716  }
1717 
1718  include_once "Modules/Exercise/classes/class.ilObjExercise.php";
1719  $exc = new ilObjExercise($this->getExerciseId(), false);
1720 
1721  $ilAppEventHandler->raise(
1722  'Modules/Exercise',
1723  $a_event . 'Assignment',
1724  array(
1725  'object' => $exc,
1726  'obj_id' => $exc->getId(),
1727  'context_ids' => $context_ids,
1728  'appointments' => $apps)
1729  );
1730  }
1731 
1732 
1733  public static function getPendingFeedbackNotifications()
1734  {
1735  global $DIC;
1736 
1737  $ilDB = $DIC->database();
1738 
1739  $res = array();
1740 
1741  $set = $ilDB->query("SELECT id,fb_file,time_stamp,deadline2 FROM exc_assignment" .
1742  " WHERE fb_cron = " . $ilDB->quote(1, "integer") .
1743  " AND fb_date = " . $ilDB->quote(self::FEEDBACK_DATE_DEADLINE, "integer") .
1744  " AND time_stamp IS NOT NULL" .
1745  " AND time_stamp > " . $ilDB->quote(0, "integer") .
1746  " AND time_stamp < " . $ilDB->quote(time(), "integer") .
1747  " AND fb_cron_done = " . $ilDB->quote(0, "integer"));
1748  while ($row = $ilDB->fetchAssoc($set)) {
1749  $max = max($row['time_stamp'], $row['deadline2']);
1750 
1751  if (trim($row["fb_file"]) && $max <= time()) {
1752  $res[] = $row["id"];
1753  }
1754  }
1755 
1756  return $res;
1757  }
1758 
1759  public static function sendFeedbackNotifications($a_ass_id, $a_user_id = null)
1760  {
1761  global $DIC;
1762 
1763  $ilDB = $DIC->database();
1764 
1765  $ass = new self($a_ass_id);
1766 
1767  // valid assignment?
1768  if (!$ass->hasFeedbackCron() || !$ass->getFeedbackFile()) {
1769  return false;
1770  }
1771 
1772  if (!$a_user_id) {
1773  // already done?
1774  $set = $ilDB->query("SELECT fb_cron_done" .
1775  " FROM exc_assignment" .
1776  " WHERE id = " . $ilDB->quote($a_ass_id, "integer"));
1777  $row = $ilDB->fetchAssoc($set);
1778  if ($row["fb_cron_done"]) {
1779  return false;
1780  }
1781  }
1782 
1783  include_once "./Services/Notification/classes/class.ilSystemNotification.php";
1784  $ntf = new ilSystemNotification();
1785  $ntf->setLangModules(array("exc"));
1786  $ntf->setObjId($ass->getExerciseId());
1787  $ntf->setSubjectLangId("exc_feedback_notification_subject");
1788  $ntf->setIntroductionLangId("exc_feedback_notification_body");
1789  $ntf->addAdditionalInfo("exc_assignment", $ass->getTitle());
1790  $ntf->setGotoLangId("exc_feedback_notification_link");
1791  $ntf->setReasonLangId("exc_feedback_notification_reason");
1792 
1793  if (!$a_user_id) {
1794  include_once "./Modules/Exercise/classes/class.ilExerciseMembers.php";
1795  $ntf->sendMail(ilExerciseMembers::_getMembers($ass->getExerciseId()));
1796 
1797  $ilDB->manipulate("UPDATE exc_assignment" .
1798  " SET fb_cron_done = " . $ilDB->quote(1, "integer") .
1799  " WHERE id = " . $ilDB->quote($a_ass_id, "integer"));
1800  } else {
1801  $ntf->sendMail(array($a_user_id));
1802  }
1803 
1804  return true;
1805  }
1806 
1807 
1808  // status
1809 
1810  public function afterDeadline()
1811  {
1812  $ilUser = $this->user;
1813 
1814  // :TODO: always current user?
1815  $idl = $this->getPersonalDeadline($ilUser->getId());
1816 
1817  // no deadline === true
1818  $deadline = max($this->deadline, $this->deadline2, $idl);
1819  return ($deadline - time() <= 0);
1820  }
1821 
1822  public function afterDeadlineStrict($a_include_personal = true)
1823  {
1824  // :TODO: this means that peer feedback, global feedback is available
1825  // after LAST personal deadline
1826  // team management is currently ignoring personal deadlines
1827  $idl = (bool) $a_include_personal
1828  ? $this->getLastPersonalDeadline()
1829  : null;
1830 
1831  // no deadline === false
1832  $deadline = max($this->deadline, $this->deadline2, $idl);
1833 
1834  // #18271 - afterDeadline() does not handle last personal deadline
1835  if ($idl && $deadline == $idl) {
1836  return ($deadline - time() <= 0);
1837  }
1838 
1839  return ($deadline > 0 &&
1840  $this->afterDeadline());
1841  }
1842 
1843  public function beforeDeadline()
1844  {
1845  // no deadline === true
1846  return !$this->afterDeadlineStrict();
1847  }
1848 
1849  public function notStartedYet()
1850  {
1851  return (time() - $this->start_time <= 0);
1852  }
1853 
1854 
1855  //
1856  // FEEDBACK FILES
1857  //
1858 
1860  {
1861  include_once("./Modules/Exercise/classes/class.ilFSStorageExercise.php");
1862  $storage = new ilFSStorageExercise($this->getExerciseId(), $this->getId());
1863  return $storage->getGlobalFeedbackPath();
1864  }
1865 
1866  public function deleteGlobalFeedbackFile()
1867  {
1869  }
1870 
1871  public function handleGlobalFeedbackFileUpload(array $a_file)
1872  {
1874  ilUtil::delDir($path, true);
1875  if (ilUtil::moveUploadedFile($a_file["tmp_name"], $a_file["name"], $path . "/" . $a_file["name"])) {
1876  $this->setFeedbackFile($a_file["name"]);
1877  return true;
1878  }
1879  return false;
1880  }
1881 
1882  public function getGlobalFeedbackFilePath()
1883  {
1884  $file = $this->getFeedbackFile();
1885  if ($file) {
1887  return $path . "/" . $file;
1888  }
1889  }
1890 
1895  public function getMemberStatus($a_user_id = null)
1896  {
1897  $ilUser = $this->user;
1898 
1899  if (!$a_user_id) {
1900  $a_user_id = $ilUser->getId();
1901  }
1902  if (!array_key_exists($a_user_id, $this->member_status)) {
1903  include_once "Modules/Exercise/classes/class.ilExAssignmentMemberStatus.php";
1904  $this->member_status[$a_user_id] = new ilExAssignmentMemberStatus($this->getId(), $a_user_id);
1905  }
1906  return $this->member_status[$a_user_id];
1907  }
1908 
1909  public function recalculateLateSubmissions()
1910  {
1911  $ilDB = $this->db;
1912 
1913  // see JF, 2015-05-11
1914 
1915  $ext_deadline = $this->getExtendedDeadline();
1916 
1917  include_once "Modules/Exercise/classes/class.ilExSubmission.php";
1918  foreach (ilExSubmission::getAllAssignmentFiles($this->exc_id, $this->getId()) as $file) {
1919  $id = $file["returned_id"];
1920  $uploaded = new ilDateTime($file["ts"], IL_CAL_DATETIME);
1921  $uploaded = $uploaded->get(IL_CAL_UNIX);
1922 
1923  $deadline = $this->getPersonalDeadline($file["user_id"]);
1924  $last_deadline = max($deadline, $this->getExtendedDeadline());
1925 
1926  $late = null;
1927 
1928  // upload is not late anymore
1929  if ($file["late"] &&
1930  (!$last_deadline ||
1931  !$ext_deadline ||
1932  $uploaded < $deadline)) {
1933  $late = false;
1934  }
1935  // upload is now late
1936  elseif (!$file["late"] &&
1937  $ext_deadline &&
1938  $deadline &&
1939  $uploaded > $deadline) {
1940  $late = true;
1941  } elseif ($last_deadline && $uploaded > $last_deadline) {
1942  // do nothing, we do not remove submissions?
1943  }
1944 
1945  if ($late !== null) {
1946  $ilDB->manipulate("UPDATE exc_returned" .
1947  " SET late = " . $ilDB->quote($late, "integer") .
1948  " WHERE returned_id = " . $ilDB->quote($id, "integer"));
1949  }
1950  }
1951  }
1952 
1953 
1954  //
1955  // individual deadlines
1956  //
1957 
1958  public function setIndividualDeadline($id, ilDateTime $date)
1959  {
1960  $ilDB = $this->db;
1961 
1962  $is_team = false;
1963  if (!is_numeric($id)) {
1964  $id = substr($id, 1);
1965  $is_team = true;
1966  }
1967 
1968  $ilDB->replace(
1969  "exc_idl",
1970  array(
1971  "ass_id" => array("integer", $this->getId()),
1972  "member_id" => array("integer", $id),
1973  "is_team" => array("integer", $is_team)
1974  ),
1975  array(
1976  "tstamp" => array("integer", $date->get(IL_CAL_UNIX))
1977  )
1978  );
1979  }
1980 
1981  public function getIndividualDeadlines()
1982  {
1983  $ilDB = $this->db;
1984 
1985  $res = array();
1986 
1987  $set = $ilDB->query("SELECT * FROM exc_idl" .
1988  " WHERE ass_id = " . $ilDB->quote($this->getId(), "integer"));
1989  while ($row = $ilDB->fetchAssoc($set)) {
1990  if ($row["is_team"]) {
1991  $row["member_id"] = "t" . $row["member_id"];
1992  }
1993 
1994  $res[$row["member_id"]] = $row["tstamp"];
1995  }
1996 
1997  return $res;
1998  }
1999 
2000  public function hasActiveIDl()
2001  {
2002  return (bool) $this->getDeadline();
2003  }
2004 
2005  public function hasReadOnlyIDl()
2006  {
2007  if ($this->getType() != ilExAssignment::TYPE_UPLOAD_TEAM &&
2008  $this->getPeerReview()) {
2009  // all deadlines are read-only if we have peer feedback
2010  include_once "Modules/Exercise/classes/class.ilExPeerReview.php";
2011  $peer_review = new ilExPeerReview($this);
2012  if ($peer_review->hasPeerReviewGroups()) {
2013  return true;
2014  }
2015  }
2016 
2017  return false;
2018  }
2019 
2025  public static function saveInstructionFilesOrderOfAssignment($a_ass_id, $a_order)
2026  {
2027  global $DIC;
2028 
2029  $db = $DIC->database();
2030 
2031  asort($a_order, SORT_NUMERIC);
2032 
2033  $nr = 10;
2034  foreach ($a_order as $k => $v) {
2035  // the check for exc_id is for security reasons. ass ids are unique.
2036  $db->manipulate(
2037  $t = "UPDATE exc_ass_file_order SET " .
2038  " order_nr = " . $db->quote($nr, "integer") .
2039  " WHERE id = " . $db->quote((int) $k, "integer") .
2040  " AND assignment_id = " . $db->quote((int) $a_ass_id, "integer")
2041  );
2042  $nr+=10;
2043  }
2044  }
2045 
2051  public static function instructionFileInsertOrder($a_filename, $a_ass_id, $a_order_nr = 0)
2052  {
2053  global $DIC;
2054 
2055  $db = $DIC->database();
2056 
2057  $order = 0;
2058  $order_val = 0;
2059 
2060  if ($a_ass_id) {
2061  //first of all check the suffix and change if necessary
2062  $filename = ilUtil::getSafeFilename($a_filename);
2063 
2064  if (!self::instructionFileExistsInDb($filename, $a_ass_id)) {
2065  if ($a_order_nr == 0) {
2066  $order_val = self::instructionFileOrderGetMax($a_ass_id);
2067  $order = $order_val + 10;
2068  } else {
2069  $order = $a_order_nr;
2070  }
2071 
2072  $id = $db->nextID('exc_ass_file_order');
2073  $db->manipulate("INSERT INTO exc_ass_file_order " .
2074  "(id, assignment_id, filename, order_nr) VALUES (" .
2075  $db->quote($id, "integer") . "," .
2076  $db->quote($a_ass_id, "integer") . "," .
2077  $db->quote($filename, "text") . "," .
2078  $db->quote($order, "integer") .
2079  ")");
2080  }
2081  }
2082  }
2083 
2084  public static function instructionFileDeleteOrder($a_ass_id, $a_file)
2085  {
2086  global $DIC;
2087 
2088  $db = $DIC->database();
2089 
2090  //now its done by filename. We need to figure how to get the order id in the confirmdelete method
2091  foreach ($a_file as $k => $v) {
2092  $db->manipulate(
2093  "DELETE FROM exc_ass_file_order " .
2094  //"WHERE id = " . $ilDB->quote((int)$k, "integer") .
2095  "WHERE filename = " . $db->quote($v, "string") .
2096  " AND assignment_id = " . $db->quote($a_ass_id, 'integer')
2097  );
2098  }
2099  }
2100 
2106  public static function renameInstructionFile($a_old_name, $a_new_name, $a_ass_id)
2107  {
2108  global $DIC;
2109 
2110  $db = $DIC->database();
2111 
2112  if ($a_ass_id) {
2113  $db->manipulate(
2114  "DELETE FROM exc_ass_file_order" .
2115  " WHERE assignment_id = " . $db->quote((int) $a_ass_id, 'integer') .
2116  " AND filename = " . $db->quote($a_new_name, 'string')
2117  );
2118 
2119  $db->manipulate(
2120  "UPDATE exc_ass_file_order SET" .
2121  " filename = " . $db->quote($a_new_name, 'string') .
2122  " WHERE assignment_id = " . $db->quote((int) $a_ass_id, 'integer') .
2123  " AND filename = " . $db->quote($a_old_name, 'string')
2124  );
2125  }
2126  }
2127 
2133  public static function instructionFileExistsInDb($a_filename, $a_ass_id)
2134  {
2135  global $DIC;
2136 
2137  $db = $DIC->database();
2138 
2139  if ($a_ass_id) {
2140  $result = $db->query(
2141  "SELECT id FROM exc_ass_file_order" .
2142  " WHERE assignment_id = " . $db->quote((int) $a_ass_id, 'integer') .
2143  " AND filename = " . $db->quote($a_filename, 'string')
2144  );
2145 
2146  return $db->numRows($result);
2147  }
2148  }
2149 
2150  public function fixInstructionFileOrdering()
2151  {
2152  global $DIC;
2153 
2154  $db = $DIC->database();
2155 
2156  $files = array_map(function ($v) {
2157  return $v["name"];
2158  }, $this->getFiles());
2159 
2160  $set = $db->query("SELECT * FROM exc_ass_file_order " .
2161  " WHERE assignment_id = " . $db->quote($this->getId(), "integer") .
2162  " ORDER BY order_nr");
2163  $order_nr = 10;
2164  $numbered_files = array();
2165  while ($rec = $db->fetchAssoc($set)) {
2166  // file exists, set correct order nr
2167  if (in_array($rec["filename"], $files)) {
2168  $db->manipulate(
2169  "UPDATE exc_ass_file_order SET " .
2170  " order_nr = " . $db->quote($order_nr, "integer") .
2171  " WHERE assignment_id = " . $db->quote($this->getId(), "integer") .
2172  " AND id = " . $db->quote($rec["id"], "integer")
2173  );
2174  $order_nr+=10;
2175  $numbered_files[] = $rec["filename"];
2176  } else { // file does not exist, delete entry
2177  $db->manipulate(
2178  "DELETE FROM exc_ass_file_order " .
2179  " WHERE assignment_id = " . $db->quote($this->getId(), "integer") .
2180  " AND id = " . $db->quote($rec["id"], "integer")
2181  );
2182  }
2183  }
2184  foreach ($files as $f) {
2185  if (!in_array($f, $numbered_files)) {
2186  self::instructionFileInsertOrder($f, $this->getId());
2187  }
2188  }
2189  }
2190 
2196  public function fileAddOrder($a_entries = array())
2197  {
2198  $this->fixInstructionFileOrdering();
2199 
2200  $order = $this->getInstructionFilesOrder();
2201  foreach ($a_entries as $k => $e) {
2202  $a_entries[$k]["order_val"] = $order[$e["file"]]["order_nr"];
2203  $a_entries[$k]["order_id"] = $order[$e["file"]]["id"];
2204  }
2205 
2206  return $a_entries;
2207  }
2208 
2213  public static function instructionFileOrderGetMax($a_ass_id)
2214  {
2215  global $DIC;
2216 
2217  $db = $DIC->database();
2218 
2219  //get max order number
2220  $result = $db->queryF(
2221  "SELECT max(order_nr) as max_order FROM exc_ass_file_order WHERE assignment_id = %s",
2222  array('integer'),
2223  array($db->quote($a_ass_id, 'integer'))
2224  );
2225 
2226  while ($row = $db->fetchAssoc($result)) {
2227  $order_val = (int) $row['max_order'];
2228  }
2229  return $order_val;
2230  }
2231 
2232 
2238  public function setMinCharLimit($a_val)
2239  {
2240  $this->min_char_limit = $a_val;
2241  }
2242 
2248  public function getMinCharLimit()
2249  {
2250  return $this->min_char_limit;
2251  }
2252 
2257  public function setMaxCharLimit($a_val)
2258  {
2259  $this->max_char_limit = $a_val;
2260  }
2261 
2266  public function getMaxCharLimit()
2267  {
2268  return $this->max_char_limit;
2269  }
2270 }
$files
Definition: add-vimline.php:18
getPortfolioTemplateId()
Get portfolio template id.
getLastPersonalDeadline()
Get last/final personal deadline (of assignment)
getPeerReview()
Get peer review status.
static getInstanceByType($a_type)
fileAddOrder($a_entries=array())
static _lookupName($a_user_id)
lookup user name
Exercise assignment member status.
Add rich text string
static getSafeFilename($a_initial_filename)
getMemberStatus($a_user_id=null)
getPersonalDeadline($a_user_id)
Get individual deadline.
saveMultiFeedbackFiles($a_files, ilObjExercise $a_exc)
Save multi feedback files.
static getAssignmentDataOfExercise($a_exc_id)
Get assignments data of an exercise in an array.
Exercise assignment.
static countMandatory($a_ex_id)
Order assignments by deadline date.
static sendFeedbackNotifications($a_ass_id, $a_user_id=null)
const IL_CAL_DATETIME
getMemberListData()
get member list data
Class ilExerciseMembers.
$result
setMaxFile($a_value)
Set max number of uploads.
getFeedbackDate()
Get (global) feedback file availability date.
setFeedbackFile($a_value)
Set (global) feedback file.
static rCopy($a_sdir, $a_tdir, $preserveTimeAttributes=false)
Copies content of a directory $a_sdir recursively to a directory $a_tdir.
setPeerReviewMin($a_value)
Set peer review minimum.
global $DIC
Definition: saml.php:7
setMaxCharLimit($a_val)
Set limit maximum characters.
const IL_CAL_TRANSLATION_SYSTEM
static getTeamId($a_assignment_id, $a_user_id, $a_create_on_demand=false)
Get team id for member id.
static getPendingFeedbackNotifications()
setTeamTutor($a_value)
Set team management by tutor.
setPortfolioTemplateId($a_val)
Set portfolio template id.
sendMultiFeedbackStructureFile(ilObjExercise $exercise)
Create member status record for a new assignment for all participants.
setPeerReviewFileUpload($a_val)
Set peer review file upload.
static instructionFileInsertOrder($a_filename, $a_ass_id, $a_order_nr=0)
Store the file order in the database.
getStartTime()
Get start time (timestamp)
getId()
Get assignment id.
static instructionFileOrderGetMax($a_ass_id)
initFromDB(array $a_set)
Import DB record.
setMinCharLimit($a_val)
Set limit minimum characters.
getMaxCharLimit()
get limit maximum characters return int max limit
setPeerReview($a_value)
Toggle peer review.
setPeerReviewDeadline($a_val)
Set peer review deadline (timestamp)
getDeadline()
Get deadline (timestamp)
static unzip($a_file, $overwrite=false, $a_flat=false)
unzip file
save()
Save assignment.
hasPeerReviewRating()
Get peer review rating status.
static getDir($a_dir, $a_rec=false, $a_sub_dir="")
get directory
hasFeedbackCron()
Get (global) feedback file cron status.
setPeerReviewValid($a_value)
Set peer review validation.
setType($a_value)
Set type.
Apointment templates are used for automatic generated apointments.
setTitle($a_val)
Set title.
$s
Definition: pwgen.php:45
const IL_CAL_UNIX
setOrderNr($a_val)
Set order nr.
static lookup($a_id, $a_field)
Private lookup.
static getASCIIFilename($a_filename)
convert utf8 to ascii filename
setInstruction($a_val)
Set instruction.
user()
Definition: user.php:4
handleCalendarEntries($a_event)
Handle calendar entries for deadline(s)
getTeamTutor()
Get team management by tutor.
uploadMultiFeedbackFile($a_file)
Upload multi feedback file.
static lookupAssignmentOnline($a_ass_id)
Check if assignment is online.
setStartTime($a_val)
Set start time (timestamp)
Exercise peer review.
if($format !==null) $name
Definition: metadata.php:146
getExerciseId()
Get exercise id.
getPeerReviewValid()
Get peer review validatiob.
Class ilObjExercise.
setDeadline($a_val)
Set deadline (timestamp)
foreach($_POST as $key=> $value) $res
static saveAssOrderOfExercise($a_ex_id, $a_order)
Save ordering of all assignments of an exercise.
hasPeerReviewPersonalized()
Get peer review personalized status.
getId()
get object id public
static getInstancesByParentId($a_parent_id)
setPeerReviewCriteriaCatalogue($a_value)
Set peer review criteria catalogue id.
static lookupUpdatedSubmission($ass_id, $member_id)
Check whether student has upload new files after tutor has set the exercise to another than notgraded...
setPeerReviewPersonalized($a_val)
Set peer review personalized.
setPeerReviewRating($a_val)
Set peer review rating.
static getInstancesByExercise($a_exc_id)
uploadAssignmentFiles($a_files)
Upload assignment files (from creation form)
setPeerReviewSimpleUnlock($a_value)
Set peer review simple unlock.
hasPeerReviewText()
Get peer review text status.
static instructionFileGetFileOrderData($a_file_data, $a_ass_id)
static instructionFileExistsInDb($a_filename, $a_ass_id)
Date and time handling
setPeerReviewText($a_val)
Set peer review text.
$ilUser
Definition: imgupload.php:18
handleGlobalFeedbackFileUpload(array $a_file)
$query
setExerciseId($a_val)
Set exercise id.
getFeedbackFile()
Get (global) feedback file.
get($a_format, $a_format_str='', $a_tz='')
get formatted date
static zip($a_dir, $a_file, $compress_content=false)
zips given directory/file into given zip.file
Create styles array
The data for the language used.
getMandatory()
Get mandatory.
getPeerReviewMin()
Get peer review minimum.
getExtendedDeadline()
Get extended deadline (timestamp)
sendFeedbackFileNotification($a_feedback_file, $a_user_id, $a_ass_id, $a_is_text_feedback=false)
Send feedback file notification to user.
static makeDir($a_dir)
creates a new directory and inherits all filesystem permissions of the parent directory You may pass ...
static cloneAssignmentsOfExercise($a_old_exc_id, $a_new_exc_id, array $a_crit_cat_map)
Clone assignments of exercise.
setFeedbackCron($a_value)
Toggle (global) feedback file cron.
static ilTempnam($a_temp_path=null)
Create a temporary file in an ILIAS writable directory.
afterDeadlineStrict($a_include_personal=true)
static lookupType($a_id)
Lookup type.
static saveInstructionFilesOrderOfAssignment($a_ass_id, $a_order)
Save ordering of instruction files for an assignment.
clearMultiFeedbackDirectory()
Clear multi feedback directory.
setFeedbackDate($a_value)
Set (global) feedback file availability date.
static lookupMaxOrderNrForEx($a_exc_id)
Select the maximum order nr for an exercise.
getMultiFeedbackFiles($a_user_id=0)
Get multi feedback files (of uploader)
getInstruction()
Get instruction.
getPeerReviewSimpleUnlock()
Get peer review simple unlock.
global $ilDB
setPeerReviewChars($a_value)
Set peer review minimum characters.
$i
Definition: disco.tpl.php:19
getRefId()
get reference id public
setId($a_val)
Set assignment id.
getPeerReviewDeadline()
Get peer review deadline (timestamp)
Exercise submission.
getMinCharLimit()
Get limit minimum characters.
hasPeerReviewFileUpload()
Get peer review file upload status.
static lookupExerciseId($a_ass_id)
Lookup excercise id for assignment id.
static getLogger($a_component_id)
Get component logger.
Add data(end) time
Method that wraps PHPs time in order to allow simulations with the workflow.
if(!file_exists("$old.txt")) if($old===$new) if(file_exists("$new.txt")) $file
getPeerReviewChars()
Get peer review minimum characters.
static getAllAssignmentFiles($a_exc_id, $a_ass_id)
getMaxFile()
Get max number of uploads.
static createNewUserRecords($a_user_id, $a_exc_id)
Create member status record for a new participant for all assignments.
setMandatory($a_val)
Set mandatory.
static orderAssByDeadline($a_ex_id)
Order assignments by deadline date.
setIndividualDeadline($id, ilDateTime $date)
static delDir($a_dir, $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
getPeerReviewCriteriaCatalogue()
Get peer review criteria catalogue id.
read()
Read from db.
Wrapper classes for system notifications.
setExtendedDeadline($a_val)
Set extended deadline (timestamp)
static renameInstructionFile($a_old_name, $a_new_name, $a_ass_id)
static instructionFileDeleteOrder($a_ass_id, $a_file)
static _getMembers($a_obj_id)
isValidType($a_value)
Is given type valid?
static createNewAssignmentRecords($a_ass_id, $a_exc)
Create member status record for a new assignment for all participants.
__construct($a_id=0)
Constructor.
for($i=6; $i< 13; $i++) for($i=1; $i< 13; $i++) $d
Definition: date.php:296
static lookupTitle($a_id)
Lookup title.
getOrderNr()
Get order nr.
static deliverFile( $a_file, $a_filename, $a_mime='', $isInline=false, $removeAfterDelivery=false, $a_exit_after=true)
deliver file for download via browser.
Exercise exceptions class.