ILIAS  release_8 Revision v8.24
class.ilExAssignment.php
Go to the documentation of this file.
1<?php
2
22
29{
33 public const TYPE_UPLOAD = 1;
34 public const TYPE_BLOG = 2;
35 public const TYPE_PORTFOLIO = 3;
36 public const TYPE_UPLOAD_TEAM = 4;
37 public const TYPE_TEXT = 5;
38 public const TYPE_WIKI_TEAM = 6;
39
40 public const FEEDBACK_DATE_DEADLINE = 1;
41 public const FEEDBACK_DATE_SUBMISSION = 2;
42 public const FEEDBACK_DATE_CUSTOM = 3;
43
44 public const PEER_REVIEW_VALID_NONE = 1;
45 public const PEER_REVIEW_VALID_ONE = 2;
46 public const PEER_REVIEW_VALID_ALL = 3;
47
49 public const TEAMS_FORMED_BY_TUTOR = 1;
50 public const TEAMS_FORMED_BY_RANDOM = 2;
52
53 public const DEADLINE_ABSOLUTE = 0;
54 public const DEADLINE_RELATIVE = 1;
56
57 protected ilDBInterface $db;
58 protected ilLanguage $lng;
59 protected ilObjUser $user;
62
63 protected int $id = 0;
64 protected int $exc_id = 0;
65 protected int $type = 0;
66 protected ?int $start_time = null;
67 protected ?int $deadline = null;
68 protected ?int $deadline2 = null;
69 protected string $instruction = "";
70 protected string $title = "";
71 protected bool $mandatory = false;
72 protected int $order_nr = 0;
73 protected bool $peer = false; // peer review activated
74 protected int $peer_min = 0;
75 protected bool $peer_unlock = false;
76 protected int $peer_dl = 0;
77 protected int $peer_valid; // passed after submission, one or all peer feedbacks
78 protected bool $peer_file = false;
79 protected bool $peer_personal = false; // personalised peer review
80 protected ?int $peer_char = null; // minimun number of characters for peer review
81 protected bool $peer_text = false;
82 protected bool $peer_rating = false;
83 protected int $peer_crit_cat = 0;
84 protected ?string $feedback_file = null;
85 protected bool $feedback_cron = false;
86 protected int $feedback_date = 0;
87 protected int $feedback_date_custom = 0;
88 protected bool $team_tutor = false;
89 protected ?int $max_file = null;
90 protected int $portfolio_template = 0;
91 protected int $min_char_limit = 0;
92 protected int $max_char_limit = 0;
95 protected int $deadline_mode = 0;
96 protected int $relative_deadline = 0;
97 protected int $rel_deadline_last_subm = 0;
98 protected array $member_status = [];
99 protected ilLogger $log;
100 protected ?int $crit_cat = 0;
101
106 public function __construct($a_id = 0)
107 {
108 global $DIC;
109
110 $this->db = $DIC->database();
111 $this->lng = $DIC->language();
112 $this->user = $DIC->user();
113 $this->app_event_handler = $DIC["ilAppEventHandler"];
114 $this->types = ilExAssignmentTypes::getInstance();
115 $this->access = $DIC->access();
116
117 $this->setType(self::TYPE_UPLOAD);
118 $this->setFeedbackDate(self::FEEDBACK_DATE_DEADLINE);
119
120 $this->log = ilLoggerFactory::getLogger("exc");
121
122 if ($a_id > 0) {
123 $this->setId($a_id);
124 $this->read();
125 }
126 $this->string_transform = $DIC->refinery()
127 ->string();
128 }
129
135 public static function getInstancesByExercise(int $a_exc_id): array
136 {
137 global $DIC;
138
139 $ilDB = $DIC->database();
140
141 $set = $ilDB->query("SELECT * FROM exc_assignment " .
142 " WHERE exc_id = " . $ilDB->quote($a_exc_id, "integer") .
143 " ORDER BY order_nr");
144 $data = array();
145
146 $order_val = 10;
147 while ($rec = $ilDB->fetchAssoc($set)) {
148 // ???
149 $rec["order_val"] = $order_val;
150
151 $ass = new self();
152 $ass->initFromDB($rec);
153 $data[] = $ass;
154
155 $order_val += 10;
156 }
157
158 return $data;
159 }
160
166 public static function instructionFileGetFileOrderData(
167 array $a_file_data,
168 int $a_ass_id
169 ): array {
170 global $DIC;
171
172 $db = $DIC->database();
173 $db->setLimit(1, 0);
174
175 $result_order_val = $db->query("
176 SELECT id, order_nr
177 FROM exc_ass_file_order
178 WHERE assignment_id = {$db->quote($a_ass_id, 'integer')}
179 AND filename = {$db->quote($a_file_data['entry'], 'text')}
180 ");
181
182 $order_val = 0;
183 $order_id = 0;
184 while ($row = $db->fetchAssoc($result_order_val)) {
185 $order_val = (int) $row['order_nr'];
186 $order_id = (int) $row['id'];
187 }
188 return array($order_val, $order_id);
189 }
190
191 public function hasTeam(): bool
192 {
193 return $this->ass_type->usesTeams();
194 }
195
196 public function setId(int $a_val): void
197 {
198 $this->id = $a_val;
199 }
200
201 public function getId(): int
202 {
203 return $this->id;
204 }
205
206 public function setExerciseId(int $a_val): void
207 {
208 $this->exc_id = $a_val;
209 }
210
211 public function getExerciseId(): int
212 {
213 return $this->exc_id;
214 }
215
216 public function setStartTime(?int $a_val): void
217 {
218 $this->start_time = $a_val;
219 }
220
221 public function getStartTime(): ?int
222 {
223 return $this->start_time;
224 }
225
226 public function setDeadline(?int $a_val): void
227 {
228 $this->deadline = $a_val;
229 }
230
231 public function getDeadline(): ?int
232 {
233 return $this->deadline;
234 }
235
240 public function setDeadlineMode(int $a_val): void
241 {
242 $this->deadline_mode = $a_val;
243 }
244
245 public function getDeadlineMode(): int
246 {
247 return $this->deadline_mode;
248 }
249
250 public function setRelativeDeadline(int $a_val): void
251 {
252 $this->relative_deadline = $a_val;
253 }
254
255 public function getRelativeDeadline(): int
256 {
257 return $this->relative_deadline;
258 }
259
260 public function setRelDeadlineLastSubmission(int $a_val): void
261 {
262 $this->rel_deadline_last_subm = $a_val;
263 }
264
266 {
267 return $this->rel_deadline_last_subm;
268 }
269
270
271 // Get individual deadline (max of common or idl (team) deadline = Official Deadline)
272 public function getPersonalDeadline(int $a_user_id): int
273 {
274 $ilDB = $this->db;
275
276 $is_team = false;
277 if ($this->ass_type->usesTeams()) {
278 $team_id = ilExAssignmentTeam::getTeamId($this->getId(), $a_user_id);
279 if (!$team_id) {
280 // #0021043
281 return $this->getDeadline();
282 }
283 $a_user_id = $team_id;
284 $is_team = true;
285 }
286
287 $set = $ilDB->query("SELECT tstamp FROM exc_idl" .
288 " WHERE ass_id = " . $ilDB->quote($this->getId(), "integer") .
289 " AND member_id = " . $ilDB->quote($a_user_id, "integer") .
290 " AND is_team = " . $ilDB->quote($is_team, "integer"));
291 $row = $ilDB->fetchAssoc($set);
292
293 // use assignment deadline if no direct personal
294 return max(($row["tstamp"] ?? 0), $this->getDeadline());
295 }
296
297 // Get last/final personal deadline (of assignment)
298 public function getLastPersonalDeadline(): int
299 {
300 $ilDB = $this->db;
301
302 $set = $ilDB->query("SELECT MAX(tstamp) FROM exc_idl" .
303 " WHERE ass_id = " . $ilDB->quote($this->getId(), "integer"));
304 $row = $ilDB->fetchAssoc($set);
305 return $row["tstamp"] ?? 0;
306 }
307
308 // Set extended deadline (timestamp)
309 public function setExtendedDeadline(?int $a_val): void
310 {
311 $this->deadline2 = $a_val;
312 }
313
314 public function getExtendedDeadline(): ?int
315 {
316 return $this->deadline2;
317 }
318
319 public function setInstruction(string $a_val): void
320 {
321 $this->instruction = $a_val;
322 }
323
324 public function getInstruction(): string
325 {
326 return $this->instruction;
327 }
328
329 public function getInstructionPresentation(): string
330 {
331 $inst = $this->getInstruction();
332 if (trim($inst)) {
333 $is_html = (strlen($inst) != strlen(strip_tags($inst)));
334 if (!$is_html) {
335 $inst = nl2br(
336 $this->string_transform->makeClickable()->transform($inst)
337 );
338 }
339 }
340 return $inst;
341 }
342
343 public function setTitle(string $a_val): void
344 {
345 $this->title = $a_val;
346 }
347
348 public function getTitle(): string
349 {
350 return $this->title;
351 }
352
353 public function setMandatory(bool $a_val): void
354 {
355 $this->mandatory = $a_val;
356 }
357
358 public function getMandatory(): bool
359 {
360 return $this->mandatory;
361 }
362
363 public function setOrderNr(int $a_val): void
364 {
365 $this->order_nr = $a_val;
366 }
367
368 public function getOrderNr(): int
369 {
370 return $this->order_nr;
371 }
372
378 public function setType(int $a_value): void
379 {
380 if ($this->isValidType($a_value)) {
381 $this->type = $a_value;
382
383 $this->ass_type = $this->types->getById($a_value);
384
385 if ($this->ass_type->usesTeams()) {
386 $this->setPeerReview(false);
387 }
388 }
389 }
390
392 {
393 return $this->ass_type;
394 }
395
396
401 public function getType(): int
402 {
403 return $this->type;
404 }
405
406 public function isValidType(int $a_value): bool
407 {
408 return $this->types->isValidId($a_value);
409 }
410
411 public function setPeerReview(bool $a_value): void
412 {
413 $this->peer = $a_value;
414 }
415
416 public function getPeerReview(): bool
417 {
418 return $this->peer;
419 }
420
421 public function setPeerReviewMin(int $a_value): void
422 {
423 $this->peer_min = $a_value;
424 }
425
426 public function getPeerReviewMin(): int
427 {
428 return $this->peer_min;
429 }
430
431 public function setPeerReviewSimpleUnlock(bool $a_value)
432 {
433 $this->peer_unlock = $a_value;
434 }
435
436 public function getPeerReviewSimpleUnlock(): bool
437 {
438 return $this->peer_unlock;
439 }
440
444 public function setPeerReviewDeadline(int $a_val): void
445 {
446 $this->peer_dl = $a_val;
447 }
448
449 public function getPeerReviewDeadline(): int
450 {
451 return $this->peer_dl;
452 }
453
459 public function setPeerReviewValid(int $a_value): void
460 {
461 $this->peer_valid = $a_value;
462 }
463
464 public function getPeerReviewValid(): int
465 {
466 return $this->peer_valid;
467 }
468
469 public function setPeerReviewRating(bool $a_val): void
470 {
471 $this->peer_rating = $a_val;
472 }
473
474 public function hasPeerReviewRating(): bool
475 {
476 return $this->peer_rating;
477 }
478
479 public function setPeerReviewText(bool $a_val): void
480 {
481 $this->peer_text = $a_val;
482 }
483
484 public function hasPeerReviewText(): bool
485 {
486 return $this->peer_text;
487 }
488
489 public function setPeerReviewFileUpload(bool $a_val): void
490 {
491 $this->peer_file = $a_val;
492 }
493
494 public function hasPeerReviewFileUpload(): bool
495 {
496 return $this->peer_file;
497 }
498
499 public function setPeerReviewPersonalized(bool $a_val): void
500 {
501 $this->peer_personal = $a_val;
502 }
503
504 public function hasPeerReviewPersonalized(): bool
505 {
506 return $this->peer_personal;
507 }
508
509 public function setPeerReviewChars(?int $a_value): void
510 {
511 $a_value = (is_numeric($a_value) && (int) $a_value > 0)
512 ? (int) $a_value
513 : null;
514 $this->peer_char = $a_value;
515 }
516
517 public function getPeerReviewChars(): ?int
518 {
519 return $this->peer_char;
520 }
521
522 public function setPeerReviewCriteriaCatalogue(?int $a_value): void
523 {
524 $this->crit_cat = $a_value;
525 }
526
528 {
529 return $this->crit_cat;
530 }
531
532 public function getPeerReviewCriteriaCatalogueItems(): array
533 {
534 if ($this->crit_cat) {
535 return ilExcCriteria::getInstancesByParentId($this->crit_cat);
536 } else {
537 $res = array();
538
539 if ($this->peer_rating) {
541 }
542
543 if ($this->peer_text) {
545 $crit = ilExcCriteria::getInstanceByType("text");
546 if ($this->peer_char) {
547 $crit->setMinChars($this->peer_char);
548 }
549 $res[] = $crit;
550 }
551
552 if ($this->peer_file) {
554 }
555
556 return $res;
557 }
558 }
559
560 public function setFeedbackFile(?string $a_value): void
561 {
562 $this->feedback_file = $a_value;
563 }
564
565 public function getFeedbackFile(): ?string
566 {
567 return $this->feedback_file;
568 }
569
573 public function setFeedbackCron(bool $a_value): void
574 {
575 $this->feedback_cron = $a_value;
576 }
577
578 public function hasFeedbackCron(): bool
579 {
580 return $this->feedback_cron;
581 }
582
583 // Set (global) feedback file availability date
584 public function setFeedbackDate(int $a_value): void
585 {
586 $this->feedback_date = $a_value;
587 }
588
589 public function getFeedbackDate(): int
590 {
591 return $this->feedback_date;
592 }
593
598 public function setFeedbackDateCustom(int $a_value): void
599 {
600 $this->feedback_date_custom = $a_value;
601 }
602
603 public function getFeedbackDateCustom(): int
604 {
605 return $this->feedback_date_custom;
606 }
607
608 // Set team management by tutor
609 public function setTeamTutor(bool $a_value): void
610 {
611 $this->team_tutor = $a_value;
612 }
613
614 public function getTeamTutor(): bool
615 {
616 return $this->team_tutor;
617 }
618
619 // Set max number of uploads
620 public function setMaxFile(?int $a_value): void
621 {
622 $this->max_file = $a_value;
623 }
624
625 public function getMaxFile(): ?int
626 {
627 return $this->max_file;
628 }
629
630 // Set portfolio template id
631 public function setPortfolioTemplateId(int $a_val): void
632 {
633 $this->portfolio_template = $a_val;
634 }
635
636 public function getPortfolioTemplateId(): int
637 {
638 return $this->portfolio_template;
639 }
640
644 public function read(): void
645 {
646 $ilDB = $this->db;
647
648 $set = $ilDB->query(
649 "SELECT * FROM exc_assignment " .
650 " WHERE id = " . $ilDB->quote($this->getId(), "integer")
651 );
652 $rec = $ilDB->fetchAssoc($set);
653
654 // #16172 - might be deleted
655 if (is_array($rec)) {
656 $this->initFromDB($rec);
657 }
658 }
659
665 protected function initFromDB(array $a_set): void
666 {
667 $this->setId((int) $a_set["id"]);
668 $this->setExerciseId((int) $a_set["exc_id"]);
669 $this->setDeadline((int) $a_set["time_stamp"]);
670 $this->setExtendedDeadline((int) $a_set["deadline2"]);
671 $this->setInstruction((string) $a_set["instruction"]);
672 $this->setTitle((string) $a_set["title"]);
673 $this->setStartTime((int) $a_set["start_time"]);
674 $this->setOrderNr((int) $a_set["order_nr"]);
675 $this->setMandatory((bool) $a_set["mandatory"]);
676 $this->setType((int) $a_set["type"]);
677 $this->setPeerReview((bool) $a_set["peer"]);
678 $this->setPeerReviewMin((int) $a_set["peer_min"]);
679 $this->setPeerReviewSimpleUnlock((bool) $a_set["peer_unlock"]);
680 $this->setPeerReviewDeadline((int) $a_set["peer_dl"]);
681 $this->setPeerReviewValid((int) $a_set["peer_valid"]);
682 $this->setPeerReviewFileUpload((bool) $a_set["peer_file"]);
683 $this->setPeerReviewPersonalized((bool) $a_set["peer_prsl"]);
684 $this->setPeerReviewChars((int) $a_set["peer_char"]);
685 $this->setPeerReviewText((bool) $a_set["peer_text"]);
686 $this->setPeerReviewRating((bool) $a_set["peer_rating"]);
687 $this->setPeerReviewCriteriaCatalogue((int) $a_set["peer_crit_cat"]);
688 $this->setFeedbackFile((string) $a_set["fb_file"]);
689 $this->setFeedbackDate((int) $a_set["fb_date"]);
690 $this->setFeedbackDateCustom((int) $a_set["fb_date_custom"]);
691 $this->setFeedbackCron((bool) $a_set["fb_cron"]);
692 $this->setTeamTutor((bool) $a_set["team_tutor"]);
693 $this->setMaxFile((int) $a_set["max_file"]);
694 $this->setPortfolioTemplateId((int) $a_set["portfolio_template"]);
695 $this->setMinCharLimit((int) $a_set["min_char_limit"]);
696 $this->setMaxCharLimit((int) $a_set["max_char_limit"]);
697 $this->setDeadlineMode((int) $a_set["deadline_mode"]);
698 $this->setRelativeDeadline((int) $a_set["relative_deadline"]);
699 $this->setRelDeadlineLastSubmission((int) $a_set["rel_deadline_last_subm"]);
700 }
701
705 public function save(): void
706 {
707 $ilDB = $this->db;
708
709 if ($this->getOrderNr() == 0) {
710 $this->setOrderNr(
711 self::lookupMaxOrderNrForEx($this->getExerciseId())
712 + 10
713 );
714 }
715
716 $next_id = $ilDB->nextId("exc_assignment");
717 $ilDB->insert("exc_assignment", array(
718 "id" => array("integer", $next_id),
719 "exc_id" => array("integer", $this->getExerciseId()),
720 "time_stamp" => array("integer", $this->getDeadline()),
721 "deadline2" => array("integer", $this->getExtendedDeadline()),
722 "instruction" => array("clob", $this->getInstruction()),
723 "title" => array("text", $this->getTitle()),
724 "start_time" => array("integer", $this->getStartTime()),
725 "order_nr" => array("integer", $this->getOrderNr()),
726 "mandatory" => array("integer", $this->getMandatory()),
727 "type" => array("integer", $this->getType()),
728 "peer" => array("integer", $this->getPeerReview()),
729 "peer_min" => array("integer", $this->getPeerReviewMin()),
730 "peer_unlock" => array("integer", $this->getPeerReviewSimpleUnlock()),
731 "peer_dl" => array("integer", $this->getPeerReviewDeadline()),
732 "peer_valid" => array("integer", $this->getPeerReviewValid()),
733 "peer_file" => array("integer", $this->hasPeerReviewFileUpload()),
734 "peer_prsl" => array("integer", $this->hasPeerReviewPersonalized()),
735 "peer_char" => array("integer", $this->getPeerReviewChars()),
736 "peer_text" => array("integer", (int) $this->hasPeerReviewText()),
737 "peer_rating" => array("integer", (int) $this->hasPeerReviewRating()),
738 "peer_crit_cat" => array("integer", $this->getPeerReviewCriteriaCatalogue()),
739 "fb_file" => array("text", $this->getFeedbackFile()),
740 "fb_date" => array("integer", $this->getFeedbackDate()),
741 "fb_date_custom" => array("integer", $this->getFeedbackDateCustom()),
742 "fb_cron" => array("integer", $this->hasFeedbackCron()),
743 "team_tutor" => array("integer", $this->getTeamTutor()),
744 "max_file" => array("integer", $this->getMaxFile()),
745 "portfolio_template" => array("integer", $this->getPortfolioTemplateId()),
746 "min_char_limit" => array("integer", $this->getMinCharLimit()),
747 "max_char_limit" => array("integer", $this->getMaxCharLimit()),
748 "relative_deadline" => array("integer", $this->getRelativeDeadline()),
749 "rel_deadline_last_subm" => array("integer", $this->getRelDeadlineLastSubmission()),
750 "deadline_mode" => array("integer", $this->getDeadlineMode())
751 ));
752 $this->setId($next_id);
753 $exc = new ilObjExercise($this->getExerciseId(), false);
754 $exc->updateAllUsersStatus();
755 self::createNewAssignmentRecords($next_id, $exc);
756
757 $this->handleCalendarEntries("create", $exc);
758 }
759
763 public function update(): void
764 {
765 $ilDB = $this->db;
766
767 $ilDB->update(
768 "exc_assignment",
769 array(
770 "exc_id" => array("integer", $this->getExerciseId()),
771 "time_stamp" => array("integer", $this->getDeadline()),
772 "deadline2" => array("integer", $this->getExtendedDeadline()),
773 "instruction" => array("clob", $this->getInstruction()),
774 "title" => array("text", $this->getTitle()),
775 "start_time" => array("integer", $this->getStartTime()),
776 "order_nr" => array("integer", $this->getOrderNr()),
777 "mandatory" => array("integer", $this->getMandatory()),
778 "type" => array("integer", $this->getType()),
779 "peer" => array("integer", $this->getPeerReview()),
780 "peer_min" => array("integer", $this->getPeerReviewMin()),
781 "peer_unlock" => array("integer", $this->getPeerReviewSimpleUnlock()),
782 "peer_dl" => array("integer", $this->getPeerReviewDeadline()),
783 "peer_valid" => array("integer", $this->getPeerReviewValid()),
784 "peer_file" => array("integer", $this->hasPeerReviewFileUpload()),
785 "peer_prsl" => array("integer", $this->hasPeerReviewPersonalized()),
786 "peer_char" => array("integer", $this->getPeerReviewChars()),
787 "peer_text" => array("integer", (int) $this->hasPeerReviewText()),
788 "peer_rating" => array("integer", (int) $this->hasPeerReviewRating()),
789 "peer_crit_cat" => array("integer", $this->getPeerReviewCriteriaCatalogue()),
790 "fb_file" => array("text", $this->getFeedbackFile()),
791 "fb_date" => array("integer", $this->getFeedbackDate()),
792 "fb_date_custom" => array("integer", $this->getFeedbackDateCustom()),
793 "fb_cron" => array("integer", $this->hasFeedbackCron()),
794 "team_tutor" => array("integer", $this->getTeamTutor()),
795 "max_file" => array("integer", $this->getMaxFile()),
796 "portfolio_template" => array("integer", $this->getPortfolioTemplateId()),
797 "min_char_limit" => array("integer", $this->getMinCharLimit()),
798 "max_char_limit" => array("integer", $this->getMaxCharLimit()),
799 "deadline_mode" => array("integer", $this->getDeadlineMode()),
800 "relative_deadline" => array("integer", $this->getRelativeDeadline()),
801 "rel_deadline_last_subm" => array("integer", $this->getRelDeadlineLastSubmission())
802 ),
803 array(
804 "id" => array("integer", $this->getId()),
805 )
806 );
807 $exc = new ilObjExercise($this->getExerciseId(), false);
808 $exc->updateAllUsersStatus();
809
810 $this->handleCalendarEntries("update", $exc);
811 }
812
816 public function delete(
817 ilObjExercise $exc,
818 bool $update_status = true
819 ): void {
820 $ilDB = $this->db;
821
822 // delete submissions
823 $exc_members = new ilExerciseMembers($exc);
824 foreach ($exc_members->getMembers() as $mem) {
825 $submission = new ilExSubmission($this, $mem);
826 $submission->deleteAllFiles();
827 }
828
829 $ilDB->manipulateF(
830 "DELETE FROM exc_usr_tutor " .
831 "WHERE ass_id = %s",
832 array("integer"),
833 array($this->getId())
834 );
835
836 $this->deleteGlobalFeedbackFile();
837
838 // remove peer review data
839 if ($this->getPeerReview()) {
840 $peer_review = new ilExPeerReview($this);
841 $peer_review->resetPeerReviews();
842 }
843
844 $ilDB->manipulate(
845 "DELETE FROM exc_ass_file_order" .
846 " WHERE assignment_id = " . $ilDB->quote($this->getId(), 'integer')
847 );
848
849 $ilDB->manipulate(
850 "DELETE FROM exc_mem_ass_status" .
851 " WHERE ass_id = " . $ilDB->quote($this->getId(), 'integer')
852 );
853
854 $ilDB->manipulate(
855 "DELETE FROM exc_assignment WHERE " .
856 " id = " . $ilDB->quote($this->getId(), "integer")
857 );
858
859 if ($update_status) {
860 $exc = new ilObjExercise($this->getExerciseId(), false);
861 $exc->updateAllUsersStatus();
862 }
863
864 $this->handleCalendarEntries("delete", $exc);
865
866 $reminder = new ilExAssignmentReminder();
867 $reminder->deleteReminders($this->getId());
868 }
869
870
871 // Get assignments data of an exercise in an array
872 public static function getAssignmentDataOfExercise(int $a_exc_id): array
873 {
874 global $DIC;
875
876 $ilDB = $DIC->database();
877
878 // should be changed to self::getInstancesByExerciseId()
879
880 $set = $ilDB->query("SELECT * FROM exc_assignment " .
881 " WHERE exc_id = " . $ilDB->quote($a_exc_id, "integer") .
882 " ORDER BY order_nr");
883 $data = array();
884
885 $order_val = 10;
886 while ($rec = $ilDB->fetchAssoc($set)) {
887 $data[] = array(
888 "id" => (int) $rec["id"],
889 "exc_id" => (int) $rec["exc_id"],
890 "deadline" => (int) $rec["time_stamp"],
891 "deadline2" => (int) $rec["deadline2"],
892 "instruction" => (string) $rec["instruction"],
893 "title" => (string) $rec["title"],
894 "start_time" => (int) $rec["start_time"],
895 "order_val" => $order_val,
896 "mandatory" => (bool) $rec["mandatory"],
897 "type" => (int) $rec["type"],
898 "peer" => (bool) $rec["peer"],
899 "peer_min" => (int) $rec["peer_min"],
900 "peer_dl" => (int) $rec["peer_dl"],
901 "peer_file" => (bool) $rec["peer_file"],
902 "peer_prsl" => (bool) $rec["peer_prsl"],
903 "fb_file" => (string) $rec["fb_file"],
904 "fb_date" => (int) $rec["fb_date"],
905 "fb_cron" => (bool) $rec["fb_cron"],
906 "deadline_mode" => (int) $rec["deadline_mode"],
907 "relative_deadline" => (int) $rec["relative_deadline"],
908 "rel_deadline_last_subm" => (int) $rec["rel_deadline_last_subm"]
909 );
910 $order_val += 10;
911 }
912 return $data;
913 }
914
922 public static function cloneAssignmentsOfExercise(
923 int $a_old_exc_id,
924 int $a_new_exc_id,
925 array $a_crit_cat_map
926 ): void {
927 $ass_data = self::getInstancesByExercise($a_old_exc_id);
928 foreach ($ass_data as $d) {
929 // clone assignment
930 $new_ass = new ilExAssignment();
931 $new_ass->setExerciseId($a_new_exc_id);
932 $new_ass->setTitle($d->getTitle());
933 $new_ass->setDeadline($d->getDeadline());
934 $new_ass->setExtendedDeadline($d->getExtendedDeadline());
935 $new_ass->setInstruction($d->getInstruction());
936 $new_ass->setMandatory($d->getMandatory());
937 $new_ass->setOrderNr($d->getOrderNr());
938 $new_ass->setStartTime($d->getStartTime());
939 $new_ass->setType($d->getType());
940 $new_ass->setPeerReview($d->getPeerReview());
941 $new_ass->setPeerReviewMin($d->getPeerReviewMin());
942 $new_ass->setPeerReviewDeadline($d->getPeerReviewDeadline());
943 $new_ass->setPeerReviewFileUpload($d->hasPeerReviewFileUpload());
944 $new_ass->setPeerReviewPersonalized($d->hasPeerReviewPersonalized());
945 $new_ass->setPeerReviewValid($d->getPeerReviewValid());
946 $new_ass->setPeerReviewChars($d->getPeerReviewChars());
947 $new_ass->setPeerReviewText($d->hasPeerReviewText());
948 $new_ass->setPeerReviewRating($d->hasPeerReviewRating());
949 $new_ass->setPeerReviewCriteriaCatalogue($d->getPeerReviewCriteriaCatalogue());
950 $new_ass->setPeerReviewSimpleUnlock($d->getPeerReviewSimpleUnlock());
951 $new_ass->setFeedbackFile($d->getFeedbackFile());
952 $new_ass->setFeedbackDate($d->getFeedbackDate());
953 $new_ass->setFeedbackDateCustom($d->getFeedbackDateCustom());
954 $new_ass->setFeedbackCron($d->hasFeedbackCron()); // #16295
955 $new_ass->setTeamTutor($d->getTeamTutor());
956 $new_ass->setMaxFile($d->getMaxFile());
957 $new_ass->setMinCharLimit($d->getMinCharLimit());
958 $new_ass->setMaxCharLimit($d->getMaxCharLimit());
959 $new_ass->setPortfolioTemplateId($d->getPortfolioTemplateId());
960 $new_ass->setDeadlineMode($d->getDeadlineMode());
961 $new_ass->setRelativeDeadline($d->getRelativeDeadline());
962 $new_ass->setRelDeadlineLastSubmission($d->getRelDeadlineLastSubmission());
963
964 // criteria catalogue(s)
965 if ($d->getPeerReviewCriteriaCatalogue() &&
966 array_key_exists($d->getPeerReviewCriteriaCatalogue(), $a_crit_cat_map)) {
967 $new_ass->setPeerReviewCriteriaCatalogue($a_crit_cat_map[$d->getPeerReviewCriteriaCatalogue()]);
968 }
969
970 $new_ass->save();
971
972
973 // clone assignment files
974 $old_web_storage = new ilFSWebStorageExercise($a_old_exc_id, $d->getId());
975 $new_web_storage = new ilFSWebStorageExercise($a_new_exc_id, $new_ass->getId());
976 $new_web_storage->create();
977 if (is_dir($old_web_storage->getAbsolutePath())) {
978 ilFileUtils::rCopy($old_web_storage->getAbsolutePath(), $new_web_storage->getAbsolutePath());
979 }
980 $order = $d->getInstructionFilesOrder();
981 foreach ($order as $file) {
982 ilExAssignment::insertFileOrderNr($new_ass->getId(), $file["filename"], $file["order_nr"]);
983 }
984
985 // clone global feedback file
986 $old_storage = new ilFSStorageExercise($a_old_exc_id, $d->getId());
987 $new_storage = new ilFSStorageExercise($a_new_exc_id, $new_ass->getId());
988 $new_storage->create();
989 if (is_dir($old_storage->getGlobalFeedbackPath())) {
990 ilFileUtils::rCopy($old_storage->getGlobalFeedbackPath(), $new_storage->getGlobalFeedbackPath());
991 }
992
993 // clone reminders
997 $rmd_sub = new ilExAssignmentReminder($a_old_exc_id, $d->getId(), $rem_type);
998 if ($rmd_sub->getReminderStatus()) {
999 $new_rmd_sub = new ilExAssignmentReminder($a_new_exc_id, $new_ass->getId(), $rem_type);
1000 $new_rmd_sub->setReminderStatus($rmd_sub->getReminderStatus());
1001 $new_rmd_sub->setReminderStart($rmd_sub->getReminderStart());
1002 $new_rmd_sub->setReminderEnd($rmd_sub->getReminderEnd());
1003 $new_rmd_sub->setReminderFrequency($rmd_sub->getReminderFrequency());
1004 $new_rmd_sub->setReminderMailTemplate($rmd_sub->getReminderMailTemplate());
1005 $new_rmd_sub->save();
1006 }
1007 }
1008
1009
1010 // type specific properties
1011 $ass_type = $d->getAssignmentType();
1012 $ass_type->cloneSpecificProperties($d, $new_ass);
1013 }
1014 }
1015
1016 public function getFiles(): array
1017 {
1018 $this->log->debug("getting files from class.ilExAssignment using ilFSWebStorageExercise");
1019 $storage = new ilFSWebStorageExercise($this->getExerciseId(), $this->getId());
1020 return $storage->getFiles();
1021 }
1022
1023 public function getInstructionFilesOrder(): array
1024 {
1025 $ilDB = $this->db;
1026
1027 $set = $ilDB->query(
1028 "SELECT filename, order_nr, id FROM exc_ass_file_order " .
1029 " WHERE assignment_id = " . $ilDB->quote($this->getId(), "integer")
1030 );
1031
1032 $data = array();
1033 while ($rec = $ilDB->fetchAssoc($set)) {
1034 $data[$rec['filename']] = $rec;
1035 }
1036
1037 return $data;
1038 }
1039
1040 // Select the maximum order nr for an exercise
1041 public static function lookupMaxOrderNrForEx(int $a_exc_id): int
1042 {
1043 global $DIC;
1044
1045 $ilDB = $DIC->database();
1046
1047 $set = $ilDB->query(
1048 "SELECT MAX(order_nr) mnr FROM exc_assignment " .
1049 " WHERE exc_id = " . $ilDB->quote($a_exc_id, "integer")
1050 );
1051 if ($rec = $ilDB->fetchAssoc($set)) {
1052 return (int) $rec["mnr"];
1053 }
1054 return 0;
1055 }
1056
1057 public static function lookupAssignmentOnline(int $a_ass_id): bool
1058 {
1059 global $DIC;
1060
1061 $ilDB = $DIC->database();
1062
1063 $query = "SELECT id FROM exc_assignment " .
1064 "WHERE start_time <= " . $ilDB->quote(time(), 'integer') . ' ' .
1065 "AND time_stamp >= " . $ilDB->quote(time(), 'integer') . ' ' .
1066 "AND id = " . $ilDB->quote($a_ass_id, 'integer');
1067 $res = $ilDB->query($query);
1068
1069 return (bool) $res->numRows();
1070 }
1071
1072 public static function lookupExerciseId(int $a_ass_id): int
1073 {
1074 global $DIC;
1075
1076 $ilDB = $DIC->database();
1077 $query = "SELECT exc_id FROM exc_assignment " .
1078 "WHERE id = " . $ilDB->quote($a_ass_id, 'integer');
1079 $res = $ilDB->fetchAssoc($ilDB->query($query));
1080
1081 return (int) ($res["exc_id"] ?? 0);
1082 }
1083
1084 private static function lookup(int $a_id, string $a_field): string
1085 {
1086 global $DIC;
1087
1088 $ilDB = $DIC->database();
1089
1090 $set = $ilDB->query(
1091 "SELECT " . $a_field . " FROM exc_assignment " .
1092 " WHERE id = " . $ilDB->quote($a_id, "integer")
1093 );
1094
1095 $rec = $ilDB->fetchAssoc($set);
1096
1097 return $rec[$a_field] ?? "";
1098 }
1099
1100 public static function lookupTitle(int $a_id): string
1101 {
1102 return self::lookup($a_id, "title");
1103 }
1104
1105 public static function lookupType(int $a_id): string
1106 {
1107 return self::lookup($a_id, "type");
1108 }
1109
1110 // Save ordering of all assignments of an exercise
1111 public static function saveAssOrderOfExercise(int $a_ex_id, array $a_order): void
1112 {
1113 global $DIC;
1114
1115 $ilDB = $DIC->database();
1116
1117 asort($a_order);
1118 $nr = 10;
1119 foreach ($a_order as $k => $v) {
1120 // the check for exc_id is for security reasons. ass ids are unique.
1121 $ilDB->manipulate(
1122 "UPDATE exc_assignment SET " .
1123 " order_nr = " . $ilDB->quote($nr, "integer") .
1124 " WHERE id = " . $ilDB->quote((int) $k, "integer") .
1125 " AND exc_id = " . $ilDB->quote($a_ex_id, "integer")
1126 );
1127 $nr += 10;
1128 }
1129 }
1130
1131 // Order assignments by deadline date
1132 public static function orderAssByDeadline(int $a_ex_id): void
1133 {
1134 global $DIC;
1135 $ilDB = $DIC->database();
1136
1137 $set = $ilDB->query(
1138 "SELECT id FROM exc_assignment " .
1139 " WHERE exc_id = " . $ilDB->quote($a_ex_id, "integer") .
1140 " ORDER BY time_stamp"
1141 );
1142 $nr = 10;
1143 while ($rec = $ilDB->fetchAssoc($set)) {
1144 $ilDB->manipulate(
1145 "UPDATE exc_assignment SET " .
1146 " order_nr = " . $ilDB->quote($nr, "integer") .
1147 " WHERE id = " . $ilDB->quote($rec["id"], "integer")
1148 );
1149 $nr += 10;
1150 }
1151 }
1152
1153 // Count the number of mandatory assignments
1154 public static function countMandatory(int $a_ex_id): int
1155 {
1156 global $DIC;
1157
1158 $ilDB = $DIC->database();
1159
1160 $set = $ilDB->query(
1161 "SELECT count(*) cntm FROM exc_assignment " .
1162 " WHERE exc_id = " . $ilDB->quote($a_ex_id, "integer") .
1163 " AND mandatory = " . $ilDB->quote(1, "integer")
1164 );
1165 $rec = $ilDB->fetchAssoc($set);
1166 return (int) $rec["cntm"];
1167 }
1168
1169 // Count assignments
1170 public static function count(int $a_ex_id): int
1171 {
1172 global $DIC;
1173
1174 $ilDB = $DIC->database();
1175
1176 $set = $ilDB->query(
1177 "SELECT count(*) cntm FROM exc_assignment " .
1178 " WHERE exc_id = " . $ilDB->quote($a_ex_id, "integer")
1179 );
1180 $rec = $ilDB->fetchAssoc($set);
1181 return $rec["cntm"];
1182 }
1183
1184 // Is assignment in exercise?
1185 public static function isInExercise(int $a_ass_id, int $a_ex_id): bool
1186 {
1187 global $DIC;
1188
1189 $ilDB = $DIC->database();
1190
1191 $set = $ilDB->query(
1192 "SELECT * FROM exc_assignment " .
1193 " WHERE exc_id = " . $ilDB->quote($a_ex_id, "integer") .
1194 " AND id = " . $ilDB->quote($a_ass_id, "integer")
1195 );
1196 if ($ilDB->fetchAssoc($set)) {
1197 return true;
1198 }
1199 return false;
1200 }
1201
1202 public function getMemberListData(): array
1203 {
1204 $ilDB = $this->db;
1205
1206 $mem = array();
1207
1208 // first get list of members from member table
1209 $set = $ilDB->query("SELECT ud.usr_id, ud.lastname, ud.firstname, ud.login" .
1210 " FROM exc_members excm" .
1211 " JOIN usr_data ud ON (ud.usr_id = excm.usr_id)" .
1212 " WHERE excm.obj_id = " . $ilDB->quote($this->getExerciseId(), "integer"));
1213 while ($rec = $ilDB->fetchAssoc($set)) {
1214 $mem[$rec["usr_id"]] =
1215 array(
1216 "name" => $rec["lastname"] . ", " . $rec["firstname"],
1217 "login" => $rec["login"],
1218 "usr_id" => $rec["usr_id"],
1219 "lastname" => $rec["lastname"],
1220 "firstname" => $rec["firstname"]
1221 );
1222 }
1223
1224 // users in idl may already exist before occuring in the members db table
1225 // if user starts an assignment with relative deadline
1226 $idl = $this->getIndividualDeadlines();
1227 if (!$this->ass_type->usesTeams()) {
1228 foreach ($idl as $user_id => $v) {
1229 if (!isset($mem[$user_id])) {
1230 if (ilObjUser::_exists((int) $user_id)) {
1231 $name = ilObjUser::_lookupName($user_id);
1232 $mem[$user_id] =
1233 array(
1234 "name" => $name["lastname"] . ", " . $name["firstname"],
1235 "login" => $name["login"],
1236 "usr_id" => $user_id,
1237 "lastname" => $name["lastname"],
1238 "firstname" => $name["firstname"]
1239 );
1240 }
1241 }
1242 }
1243 }
1244
1245 $q = "SELECT * FROM exc_mem_ass_status " .
1246 "WHERE ass_id = " . $ilDB->quote($this->getId(), "integer");
1247 $set = $ilDB->query($q);
1248 while ($rec = $ilDB->fetchAssoc($set)) {
1249 if (isset($mem[$rec["usr_id"]])) {
1250 $sub = new ilExSubmission($this, $rec["usr_id"]);
1251
1252 $mem[$rec["usr_id"]]["sent_time"] = $rec["sent_time"];
1253 $mem[$rec["usr_id"]]["submission"] = $sub->getLastSubmission();
1254 $mem[$rec["usr_id"]]["status_time"] = $rec["status_time"];
1255 $mem[$rec["usr_id"]]["feedback_time"] = $rec["feedback_time"];
1256 $mem[$rec["usr_id"]]["notice"] = $rec["notice"];
1257 $mem[$rec["usr_id"]]["status"] = $rec["status"];
1258 $mem[$rec["usr_id"]]["mark"] = $rec["mark"];
1259 $mem[$rec["usr_id"]]["comment"] = $rec["u_comment"];
1260 }
1261 }
1262 return $mem;
1263 }
1264
1270 int $a_user_id,
1271 string $a_grade = ""
1272 ): ?array {
1273 global $DIC;
1274 $ilDB = $DIC->database();
1275
1276 $and_grade = "";
1277 if (in_array($a_grade, array("notgraded", "passed", "failed"))) {
1278 $and_grade = " AND status = " . $ilDB->quote($a_grade, "text");
1279 }
1280
1281 $q = "SELECT * FROM exc_mem_ass_status " .
1282 "WHERE ass_id = " . $ilDB->quote($this->getId(), "integer") .
1283 " AND usr_id = " . $ilDB->quote($a_user_id, "integer") .
1284 $and_grade;
1285
1286 $set = $ilDB->query($q);
1287
1288 $data = null;
1289 while ($rec = $ilDB->fetchAssoc($set)) {
1290 $sub = new ilExSubmission($this, $a_user_id);
1291
1292 $data["sent_time"] = $rec["sent_time"];
1293 $data["submission"] = $sub->getLastSubmission();
1294 $data["status_time"] = $rec["status_time"];
1295 $data["feedback_time"] = $rec["feedback_time"];
1296 $data["notice"] = $rec["notice"];
1297 $data["status"] = $rec["status"];
1298 $data["mark"] = $rec["mark"];
1299 $data["comment"] = $rec["u_comment"];
1300 }
1301
1302 return $data;
1303 }
1304
1305 // Create member status record for a new participant for all assignments
1306 public static function createNewUserRecords(
1307 int $a_user_id,
1308 int $a_exc_id
1309 ): void {
1310 global $DIC;
1311
1312 $ilDB = $DIC->database();
1313
1314 $ass_data = self::getAssignmentDataOfExercise($a_exc_id);
1315 foreach ($ass_data as $ass) {
1316 //echo "-".$ass["id"]."-".$a_user_id."-";
1317 $ilDB->replace("exc_mem_ass_status", array(
1318 "ass_id" => array("integer", $ass["id"]),
1319 "usr_id" => array("integer", $a_user_id)
1320 ), array(
1321 "status" => array("text", "notgraded")
1322 ));
1323 }
1324 }
1325
1326 // Create member status record for a new assignment for all participants
1327 public static function createNewAssignmentRecords(
1328 int $a_ass_id,
1329 ilObjExercise $a_exc
1330 ): void {
1331 global $DIC;
1332
1333 $ilDB = $DIC->database();
1334
1335 $exmem = new ilExerciseMembers($a_exc);
1336 $mems = $exmem->getMembers();
1337
1338 foreach ($mems as $mem) {
1339 $ilDB->replace("exc_mem_ass_status", array(
1340 "ass_id" => array("integer", $a_ass_id),
1341 "usr_id" => array("integer", $mem)
1342 ), array(
1343 "status" => array("text", "notgraded")
1344 ));
1345 }
1346 }
1347
1352 public function uploadAssignmentFiles(array $a_files): void
1353 {
1354 ilLoggerFactory::getLogger("exc")->debug("upload assignment files files = ", $a_files);
1355 $storage = new ilFSWebStorageExercise($this->getExerciseId(), $this->getId());
1356 $storage->create();
1357 $storage->uploadAssignmentFiles($a_files);
1358 }
1359
1360
1364
1369 {
1370 $access = $this->access;
1371
1372 // send and delete the zip file
1373 $deliverFilename = trim(str_replace(" ", "_", $this->getTitle() . "_" . $this->getId()));
1374 $deliverFilename = ilFileUtils::getASCIIFilename($deliverFilename);
1375 $deliverFilename = "multi_feedback_" . $deliverFilename;
1376
1377 $exc = new ilObjExercise($this->getExerciseId(), false);
1378
1379 $cdir = getcwd();
1380
1381 // create temporary directoy
1382 $tmpdir = ilFileUtils::ilTempnam();
1383 ilFileUtils::makeDir($tmpdir);
1384 $mfdir = $tmpdir . "/" . $deliverFilename;
1385 ilFileUtils::makeDir($mfdir);
1386
1387 // create subfolders <lastname>_<firstname>_<id> for each participant
1388 $exmem = new ilExerciseMembers($exc);
1389 $mems = $exmem->getMembers();
1390
1392 'edit_submissions_grades',
1393 'edit_submissions_grades',
1394 $exercise->getRefId(),
1395 $mems
1396 );
1397 foreach ($mems as $mem) {
1399 $subdir = $name["lastname"] . "_" . $name["firstname"] . "_" . $name["login"] . "_" . $name["user_id"];
1400 $subdir = ilFileUtils::getASCIIFilename($subdir);
1401 ilFileUtils::makeDir($mfdir . "/" . $subdir);
1402 }
1403
1404 // create the zip file
1405 chdir($tmpdir);
1406 $tmpzipfile = $tmpdir . "/multi_feedback.zip";
1407 ilFileUtils::zip($tmpdir, $tmpzipfile, true);
1408 chdir($cdir);
1409
1410
1411 ilFileDelivery::deliverFileLegacy($tmpzipfile, $deliverFilename . ".zip", "", false, true);
1412 }
1413
1418 public function uploadMultiFeedbackFile(array $a_file): void
1419 {
1420 $lng = $this->lng;
1421 $ilUser = $this->user;
1422
1423 if (!is_file($a_file["tmp_name"])) {
1424 throw new ilExerciseException($lng->txt("exc_feedback_file_could_not_be_uploaded"));
1425 }
1426
1427 $storage = new ilFSStorageExercise($this->getExerciseId(), $this->getId());
1428 $mfu = $storage->getMultiFeedbackUploadPath($ilUser->getId());
1429 ilFileUtils::delDir($mfu, true);
1430 ilFileUtils::moveUploadedFile($a_file["tmp_name"], "multi_feedback.zip", $mfu . "/" . "multi_feedback.zip");
1431 ilFileUtils::unzip($mfu . "/multi_feedback.zip", true);
1432 $subdirs = ilFileUtils::getDir($mfu);
1433 $subdir = "notfound";
1434 foreach ($subdirs as $s => $j) {
1435 if ($j["type"] == "dir" && substr($s, 0, 14) == "multi_feedback") {
1436 $subdir = $s;
1437 }
1438 }
1439
1440 if (!is_dir($mfu . "/" . $subdir)) {
1441 throw new ilExerciseException($lng->txt("exc_no_feedback_dir_found_in_zip"));
1442 }
1443 }
1444
1451 public function getMultiFeedbackFiles(int $a_user_id = 0): array
1452 {
1453 $ilUser = $this->user;
1454
1455 if ($a_user_id == 0) {
1456 $a_user_id = $ilUser->getId();
1457 }
1458
1459 $mf_files = array();
1460
1461 // get members
1462 $exc = new ilObjExercise($this->getExerciseId(), false);
1463 $exmem = new ilExerciseMembers($exc);
1464 $mems = $exmem->getMembers();
1465
1466 // read mf directory
1467 $storage = new ilFSStorageExercise($this->getExerciseId(), $this->getId());
1468 $mfu = $storage->getMultiFeedbackUploadPath($a_user_id);
1469
1470 // get subdir that starts with multi_feedback
1471 $subdirs = ilFileUtils::getDir($mfu);
1472 $subdir = "notfound";
1473 foreach ($subdirs as $s => $j) {
1474 if ($j["type"] == "dir" && substr($s, 0, 14) == "multi_feedback") {
1475 $subdir = $s;
1476 }
1477 }
1478
1479 $items = ilFileUtils::getDir($mfu . "/" . $subdir);
1480 foreach ($items as $k => $i) {
1481 // check directory
1482 if ($i["type"] == "dir" && !in_array($k, array(".", ".."))) {
1483 // check if valid member id is given
1484 $parts = explode("_", $i["entry"]);
1485 $user_id = (int) $parts[count($parts) - 1];
1486 if (in_array($user_id, $mems)) {
1487 // read dir of user
1488 $name = ilObjUser::_lookupName($user_id);
1489 $files = ilFileUtils::getDir($mfu . "/" . $subdir . "/" . $k);
1490 foreach ($files as $k2 => $f) {
1491 // append files to array
1492 if ($f["type"] == "file" && substr($k2, 0, 1) != ".") {
1493 $mf_files[] = array(
1494 "lastname" => $name["lastname"],
1495 "firstname" => $name["firstname"],
1496 "login" => $name["login"],
1497 "user_id" => $name["user_id"],
1498 "full_path" => $mfu . "/" . $subdir . "/" . $k . "/" . $k2,
1499 "file" => $k2);
1500 }
1501 }
1502 }
1503 }
1504 }
1505 return $mf_files;
1506 }
1507
1511 public function clearMultiFeedbackDirectory(): void
1512 {
1513 $ilUser = $this->user;
1514
1515 $storage = new ilFSStorageExercise($this->getExerciseId(), $this->getId());
1516 $mfu = $storage->getMultiFeedbackUploadPath($ilUser->getId());
1517 ilFileUtils::delDir($mfu);
1518 }
1519
1523 public function saveMultiFeedbackFiles(
1524 array $a_files,
1525 ilObjExercise $a_exc
1526 ): void {
1527 if ($this->getExerciseId() != $a_exc->getId()) {
1528 return;
1529 }
1530
1531 $fstorage = new ilFSStorageExercise($this->getExerciseId(), $this->getId());
1532 $fstorage->create();
1533
1534 $mf_files = $this->getMultiFeedbackFiles();
1535 foreach ($mf_files as $f) {
1536 $user_id = $f["user_id"];
1537 $file_path = $f["full_path"];
1538 $file_name = $f["file"];
1539
1540 // if checked in confirmation gui
1541 if (is_array($a_files[$user_id] ?? false) && in_array(md5($file_name), $a_files[$user_id])) {
1542 $submission = new ilExSubmission($this, $user_id);
1543 $feedback_id = $submission->getFeedbackId();
1544 $noti_rec_ids = $submission->getUserIds();
1545
1546 if ($feedback_id) {
1547 $fb_path = $fstorage->getFeedbackPath($feedback_id);
1548 $target = $fb_path . "/" . $file_name;
1549 if (is_file($target)) {
1550 unlink($target);
1551 }
1552 // rename file
1553 ilFileUtils::rename($file_path, $target);
1554
1555 if ($noti_rec_ids) {
1556 foreach ($noti_rec_ids as $user_id) {
1557 $member_status = $this->getMemberStatus($user_id);
1558 $member_status->setFeedback(true);
1559 $member_status->update();
1560 }
1561
1563 $file_name,
1564 $noti_rec_ids,
1565 $this->getId()
1566 );
1567 }
1568 }
1569 }
1570 }
1571
1572 $this->clearMultiFeedbackDirectory();
1573 }
1574
1579 protected function handleCalendarEntries(
1580 string $a_event,
1581 ilObjExercise $exc
1582 ): void {
1583 $ilAppEventHandler = $this->app_event_handler;
1584
1585 $dl_id = $this->getId() . "0";
1586 $fbdl_id = $this->getId() . "1";
1587
1588 $context_ids = array($dl_id, $fbdl_id);
1589 $apps = array();
1590
1591 if ($a_event != "delete") {
1592 // deadline or relative deadline given
1593 if ($this->getDeadline() || $this->getDeadlineMode() == ilExAssignment::DEADLINE_RELATIVE) {
1594 $app = new ilCalendarAppointmentTemplate($dl_id);
1595 $app->setTranslationType(ilCalendarEntry::TRANSLATION_SYSTEM);
1596 $app->setSubtitle("cal_exc_deadline");
1597 $app->setTitle($this->getTitle());
1598 $app->setFullday(false);
1599 // note: in the case of a relative deadline this will be set to 0 / 1970...)
1600 // see ilCalendarScheduleFilterExercise for appointment modification
1601 $app->setStart(new ilDateTime($this->getDeadline(), IL_CAL_UNIX));
1602
1603 $apps[] = $app;
1604 }
1605
1606 if ($this->getPeerReview() &&
1607 $this->getPeerReviewDeadline()) {
1608 $app = new ilCalendarAppointmentTemplate($fbdl_id);
1609 $app->setTranslationType(ilCalendarEntry::TRANSLATION_SYSTEM);
1610 $app->setSubtitle("cal_exc_peer_review_deadline");
1611 $app->setTitle($this->getTitle());
1612 $app->setFullday(false);
1613 $app->setStart(new ilDateTime($this->getPeerReviewDeadline(), IL_CAL_UNIX));
1614
1615 $apps[] = $app;
1616 }
1617 }
1618
1619 $ilAppEventHandler->raise(
1620 'Modules/Exercise',
1621 $a_event . 'Assignment',
1622 array(
1623 'object' => $exc,
1624 'obj_id' => $exc->getId(),
1625 'context_ids' => $context_ids,
1626 'appointments' => $apps)
1627 );
1628 }
1629
1630 public static function getPendingFeedbackNotifications(): array
1631 {
1632 global $DIC;
1633
1634 $ilDB = $DIC->database();
1635
1636 $res = array();
1637
1638 $set = $ilDB->query("SELECT id,fb_file,time_stamp,deadline2,fb_date FROM exc_assignment" .
1639 " WHERE fb_cron = " . $ilDB->quote(1, "integer") .
1640 " AND (fb_date = " . $ilDB->quote(self::FEEDBACK_DATE_DEADLINE, "integer") .
1641 " AND time_stamp IS NOT NULL" .
1642 " AND time_stamp > " . $ilDB->quote(0, "integer") .
1643 " AND time_stamp < " . $ilDB->quote(time(), "integer") .
1644 " AND fb_cron_done = " . $ilDB->quote(0, "integer") .
1645 ") OR (fb_date = " . $ilDB->quote(self::FEEDBACK_DATE_CUSTOM, "integer") .
1646 " AND fb_date_custom IS NOT NULL" .
1647 " AND fb_date_custom > " . $ilDB->quote(0, "integer") .
1648 " AND fb_date_custom < " . $ilDB->quote(time(), "integer") .
1649 " AND fb_cron_done = " . $ilDB->quote(0, "integer") . ")");
1650
1651
1652
1653 while ($row = $ilDB->fetchAssoc($set)) {
1654 if ($row['fb_date'] == self::FEEDBACK_DATE_DEADLINE) {
1655 $max = max($row['time_stamp'], $row['deadline2']);
1656 if (trim($row["fb_file"]) && $max <= time()) {
1657 $res[] = $row["id"];
1658 }
1659 } elseif ($row['fb_date'] == self::FEEDBACK_DATE_CUSTOM) {
1660 if (trim($row["fb_file"] ?? "") && ($row['fb_date_custom'] ?? 0) <= time()) {
1661 $res[] = $row["id"];
1662 }
1663 }
1664 }
1665
1666 return $res;
1667 }
1668
1672 public static function sendFeedbackNotifications(
1673 int $a_ass_id,
1674 int $a_user_id = null
1675 ): bool {
1676 global $DIC;
1677
1678 $ilDB = $DIC->database();
1679
1680 $ass = new self($a_ass_id);
1681
1682 // valid assignment?
1683 if (!$ass->hasFeedbackCron() || !$ass->getFeedbackFile()) {
1684 return false;
1685 }
1686
1687 if (!$a_user_id) {
1688 // already done?
1689 $set = $ilDB->query("SELECT fb_cron_done" .
1690 " FROM exc_assignment" .
1691 " WHERE id = " . $ilDB->quote($a_ass_id, "integer"));
1692 $row = $ilDB->fetchAssoc($set);
1693 if ($row["fb_cron_done"]) {
1694 return false;
1695 }
1696 }
1697
1698 $ntf = new ilSystemNotification();
1699 $ntf->setLangModules(array("exc"));
1700 $ntf->setObjId($ass->getExerciseId());
1701 $ntf->setSubjectLangId("exc_feedback_notification_subject");
1702 $ntf->setIntroductionLangId("exc_feedback_notification_body");
1703 $ntf->addAdditionalInfo("exc_assignment", $ass->getTitle());
1704 $ntf->setGotoLangId("exc_feedback_notification_link");
1705 $ntf->setReasonLangId("exc_feedback_notification_reason");
1706
1707 if (!$a_user_id) {
1708 $ntf->sendMail(ilExerciseMembers::_getMembers($ass->getExerciseId()));
1709
1710 $ilDB->manipulate("UPDATE exc_assignment" .
1711 " SET fb_cron_done = " . $ilDB->quote(1, "integer") .
1712 " WHERE id = " . $ilDB->quote($a_ass_id, "integer"));
1713 } else {
1714 $ntf->sendMail(array($a_user_id));
1715 }
1716
1717 return true;
1718 }
1719
1720
1721 // status
1722
1723 // like: after effective deadline (for single user), no deadline: true
1724 public function afterDeadline(): bool
1725 {
1726 $ilUser = $this->user;
1727
1728 // :TODO: always current user?
1729 $idl = $this->getPersonalDeadline($ilUser->getId()); // official deadline
1730
1731 // no deadline === true
1732 $deadline = max($this->deadline, $this->deadline2, $idl); // includes grace period
1733 return ($deadline - time() <= 0);
1734 }
1735
1736 public function afterDeadlineStrict(bool $a_include_personal = true): bool
1737 {
1738 // :TODO: this means that peer feedback, global feedback is available
1739 // after LAST personal deadline
1740 // team management is currently ignoring personal deadlines
1741 $idl = $a_include_personal
1742 ? $this->getLastPersonalDeadline()
1743 : null;
1744
1745 // no deadline === false
1746 $deadline = max($this->deadline, $this->deadline2, $idl);
1747
1748 // #18271 - afterDeadline() does not handle last personal deadline
1749 // after effective deadline of all users
1750 if ($idl && $deadline == $idl) {
1751 return ($deadline - time() <= 0);
1752 }
1753
1754 // like: after effective deadline (for single user), except: no deadline false
1755 return ($deadline > 0 &&
1756 $this->afterDeadline());
1757 }
1758
1762 public function afterCustomDate(): bool
1763 {
1764 $date_custom = $this->getFeedbackDateCustom();
1765 //if the solution will be displayed only after reach all the deadlines.
1766 //$final_deadline = $this->afterDeadlineStrict();
1767 //$dl = max($final_deadline, time());
1768 //return ($date_custom - $dl <= 0);
1769 return ($date_custom - time() <= 0);
1770 }
1771
1772 // like: before effective deadline (for all users), no deadline: true
1773 public function beforeDeadline(): bool
1774 {
1775 // no deadline === true
1776 return !$this->afterDeadlineStrict();
1777 }
1778
1779 public function notStartedYet(): bool
1780 {
1781 return (time() - $this->start_time <= 0);
1782 }
1783
1784
1785 //
1786 // FEEDBACK FILES
1787 //
1788
1789 public function getGlobalFeedbackFileStoragePath(): string
1790 {
1791 $storage = new ilFSStorageExercise($this->getExerciseId(), $this->getId());
1792 return $storage->getGlobalFeedbackPath();
1793 }
1794
1795 public function deleteGlobalFeedbackFile(): void
1796 {
1797 ilFileUtils::delDir($this->getGlobalFeedbackFileStoragePath());
1798 }
1799
1803 public function handleGlobalFeedbackFileUpload(array $a_file): bool
1804 {
1805 $path = $this->getGlobalFeedbackFileStoragePath();
1807 if (ilFileUtils::moveUploadedFile($a_file["tmp_name"], $a_file["name"], $path . "/" . $a_file["name"])) {
1808 $this->setFeedbackFile($a_file["name"]);
1809 return true;
1810 }
1811 return false;
1812 }
1813
1814 public function getGlobalFeedbackFilePath(): string
1815 {
1816 $file = $this->getFeedbackFile();
1817 if ($file) {
1818 $path = $this->getGlobalFeedbackFileStoragePath();
1819 return $path . "/" . $file;
1820 }
1821 return "";
1822 }
1823
1824 public function getMemberStatus(?int $a_user_id = null): ilExAssignmentMemberStatus
1825 {
1826 $ilUser = $this->user;
1827
1828 if (!$a_user_id) {
1829 $a_user_id = $ilUser->getId();
1830 }
1831 if (!array_key_exists($a_user_id, $this->member_status)) {
1832 $this->member_status[$a_user_id] = new ilExAssignmentMemberStatus($this->getId(), $a_user_id);
1833 }
1834 return $this->member_status[$a_user_id];
1835 }
1836
1840 public function recalculateLateSubmissions(): void
1841 {
1842 $ilDB = $this->db;
1843
1844 // see JF, 2015-05-11
1845
1846 $ext_deadline = $this->getExtendedDeadline();
1847
1848 foreach (ilExSubmission::getAllAssignmentFiles($this->exc_id, $this->getId()) as $file) {
1849 $id = $file["returned_id"];
1850 $uploaded = new ilDateTime($file["ts"], IL_CAL_DATETIME);
1851 $uploaded = $uploaded->get(IL_CAL_UNIX);
1852
1853 $deadline = $this->getPersonalDeadline($file["user_id"]);
1854 $last_deadline = max($deadline, $this->getExtendedDeadline());
1855
1856 $late = null;
1857
1858 // upload is not late anymore
1859 if ($file["late"] &&
1860 (!$last_deadline ||
1861 !$ext_deadline ||
1862 $uploaded < $deadline)) {
1863 $late = false;
1864 }
1865 // upload is now late
1866 elseif (!$file["late"] &&
1867 $ext_deadline &&
1868 $deadline &&
1869 $uploaded > $deadline) {
1870 $late = true;
1871 }
1872
1873 if ($late !== null) {
1874 $ilDB->manipulate("UPDATE exc_returned" .
1875 " SET late = " . $ilDB->quote($late, "integer") .
1876 " WHERE returned_id = " . $ilDB->quote($id, "integer"));
1877 }
1878 }
1879 }
1880
1881
1882 //
1883 // individual deadlines
1884 //
1885
1886 public function setIndividualDeadline(
1887 string $id,
1888 ilDateTime $date
1889 ): void {
1890 $is_team = false;
1891 if (!is_numeric($id)) {
1892 $id = substr($id, 1);
1893 $is_team = true;
1894 }
1895
1896 $idl = ilExcIndividualDeadline::getInstance($this->getId(), (int) $id, $is_team);
1897 $idl->setIndividualDeadline($date->get(IL_CAL_UNIX));
1898 $idl->save();
1899 }
1900
1901 public function getIndividualDeadlines(): array
1902 {
1903 $ilDB = $this->db;
1904
1905 $res = array();
1906
1907 $set = $ilDB->query("SELECT * FROM exc_idl" .
1908 " WHERE ass_id = " . $ilDB->quote($this->getId(), "integer"));
1909 while ($row = $ilDB->fetchAssoc($set)) {
1910 if ($row["is_team"]) {
1911 $row["member_id"] = "t" . $row["member_id"];
1912 }
1913
1914 $res[$row["member_id"]] = $row["tstamp"];
1915 }
1916
1917 return $res;
1918 }
1919
1920 public function hasActiveIDl(): bool
1921 {
1922 return (bool) $this->getDeadline() || (bool) $this->getRelativeDeadline();
1923 }
1924
1925 public function hasReadOnlyIDl(): bool
1926 {
1927 if (!$this->ass_type->usesTeams() &&
1928 $this->getPeerReview()) {
1929 // all deadlines are read-only if we have peer feedback
1930 $peer_review = new ilExPeerReview($this);
1931 if ($peer_review->hasPeerReviewGroups()) {
1932 return true;
1933 }
1934 }
1935
1936 return false;
1937 }
1938
1940 int $a_ass_id,
1941 array $a_order
1942 ): void {
1943 global $DIC;
1944
1945 $db = $DIC->database();
1946
1947 asort($a_order, SORT_NUMERIC);
1948
1949 $nr = 10;
1950 foreach (array_keys($a_order) as $k) {
1951 // the check for exc_id is for security reasons. ass ids are unique.
1952 $db->manipulate(
1953 "UPDATE exc_ass_file_order SET " .
1954 " order_nr = " . $db->quote($nr, "integer") .
1955 " WHERE id = " . $db->quote((int) $k, "integer") .
1956 " AND assignment_id = " . $db->quote($a_ass_id, "integer")
1957 );
1958 $nr += 10;
1959 }
1960 }
1961
1962 public static function insertFileOrderNr(
1963 int $a_ass_id,
1964 string $a_filename,
1965 int $a_order_nr
1966 ): void {
1967 global $DIC;
1968 $db = $DIC->database();
1969 $id = $db->nextId("exc_ass_file_order");
1970 $db->insert(
1971 "exc_ass_file_order",
1972 [
1973 "id" => ["integer", $id],
1974 "order_nr" => ["integer", $a_order_nr],
1975 "assignment_id" => ["integer", $a_ass_id],
1976 "filename" => ["text", $a_filename]
1977 ]
1978 );
1979 }
1980
1981 // Store the order nr of a file in the database
1982 public static function instructionFileInsertOrder(
1983 string $a_filename,
1984 int $a_ass_id,
1985 int $a_order_nr = 0
1986 ): void {
1987 global $DIC;
1988
1989 $db = $DIC->database();
1990
1991 if ($a_ass_id) {
1992 //first of all check the suffix and change if necessary
1994
1995 if (self::instructionFileExistsInDb($filename, $a_ass_id) == 0) {
1996 if ($a_order_nr == 0) {
1997 $order_val = self::instructionFileOrderGetMax($a_ass_id);
1998 $order = $order_val + 10;
1999 } else {
2000 $order = $a_order_nr;
2001 }
2002
2003 $id = $db->nextID('exc_ass_file_order');
2004 $db->manipulate("INSERT INTO exc_ass_file_order " .
2005 "(id, assignment_id, filename, order_nr) VALUES (" .
2006 $db->quote($id, "integer") . "," .
2007 $db->quote($a_ass_id, "integer") . "," .
2008 $db->quote($filename, "text") . "," .
2009 $db->quote($order, "integer") .
2010 ")");
2011 }
2012 }
2013 }
2014
2018 public static function instructionFileDeleteOrder(
2019 int $a_ass_id,
2020 array $a_file
2021 ): void {
2022 global $DIC;
2023
2024 $db = $DIC->database();
2025
2026 //now its done by filename. We need to figure how to get the order id in the confirmdelete method
2027 foreach ($a_file as $v) {
2028 $db->manipulate(
2029 "DELETE FROM exc_ass_file_order " .
2030 "WHERE filename = " . $db->quote($v, 'text') .
2031 " AND assignment_id = " . $db->quote($a_ass_id, 'integer')
2032 );
2033 }
2034 }
2035
2036 public static function renameInstructionFile(
2037 string $a_old_name,
2038 string $a_new_name,
2039 int $a_ass_id
2040 ): void {
2041 global $DIC;
2042
2043 $db = $DIC->database();
2044
2045 if ($a_ass_id) {
2046 $db->manipulate(
2047 "DELETE FROM exc_ass_file_order" .
2048 " WHERE assignment_id = " . $db->quote($a_ass_id, 'integer') .
2049 " AND filename = " . $db->quote($a_new_name, 'text')
2050 );
2051
2052 $db->manipulate(
2053 "UPDATE exc_ass_file_order SET" .
2054 " filename = " . $db->quote($a_new_name, 'text') .
2055 " WHERE assignment_id = " . $db->quote($a_ass_id, 'integer') .
2056 " AND filename = " . $db->quote($a_old_name, 'text')
2057 );
2058 }
2059 }
2060
2061 public static function instructionFileExistsInDb(
2062 string $a_filename,
2063 int $a_ass_id
2064 ): int {
2065 global $DIC;
2066
2067 $db = $DIC->database();
2068
2069 if ($a_ass_id) {
2070 $result = $db->query(
2071 "SELECT id FROM exc_ass_file_order" .
2072 " WHERE assignment_id = " . $db->quote($a_ass_id, 'integer') .
2073 " AND filename = " . $db->quote($a_filename, 'text')
2074 );
2075
2076 return $db->numRows($result);
2077 }
2078
2079 return 0;
2080 }
2081
2082 public function fixInstructionFileOrdering(): void
2083 {
2084 $db = $this->db;
2085
2086 $files = array_map(function ($v) {
2087 return $v["name"];
2088 }, $this->getFiles());
2089
2090 $set = $db->query("SELECT * FROM exc_ass_file_order " .
2091 " WHERE assignment_id = " . $db->quote($this->getId(), "integer") .
2092 " ORDER BY order_nr");
2093 $order_nr = 10;
2094 $numbered_files = array();
2095 while ($rec = $db->fetchAssoc($set)) {
2096 // file exists, set correct order nr
2097 if (in_array($rec["filename"], $files)) {
2098 $db->manipulate(
2099 "UPDATE exc_ass_file_order SET " .
2100 " order_nr = " . $db->quote($order_nr, "integer") .
2101 " WHERE assignment_id = " . $db->quote($this->getId(), "integer") .
2102 " AND id = " . $db->quote($rec["id"], "integer")
2103 );
2104 $order_nr += 10;
2105 $numbered_files[] = $rec["filename"];
2106 } else { // file does not exist, delete entry
2107 $db->manipulate(
2108 "DELETE FROM exc_ass_file_order " .
2109 " WHERE assignment_id = " . $db->quote($this->getId(), "integer") .
2110 " AND id = " . $db->quote($rec["id"], "integer")
2111 );
2112 }
2113 }
2114 foreach ($files as $f) {
2115 if (!in_array($f, $numbered_files)) {
2116 self::instructionFileInsertOrder($f, $this->getId());
2117 }
2118 }
2119 }
2120
2121 public function fileAddOrder(
2122 array $a_entries = array()
2123 ): array {
2124 $this->fixInstructionFileOrdering();
2125
2126 $order = $this->getInstructionFilesOrder();
2127 foreach ($a_entries as $k => $e) {
2128 $a_entries[$k]["order_val"] = $order[$e["file"]]["order_nr"] ?? 0;
2129 $a_entries[$k]["order_id"] = $order[$e["file"]]["id"] ?? "";
2130 }
2131
2132 return $a_entries;
2133 }
2134
2135 public static function instructionFileOrderGetMax(int $a_ass_id): int
2136 {
2137 global $DIC;
2138
2139 $db = $DIC->database();
2140
2141 //get max order number
2142 $result = $db->queryF(
2143 "SELECT max(order_nr) as max_order FROM exc_ass_file_order WHERE assignment_id = %s",
2144 array('integer'),
2145 array($db->quote($a_ass_id, 'integer'))
2146 );
2147
2148 $order_val = 0;
2149 while ($row = $db->fetchAssoc($result)) {
2150 $order_val = (int) $row['max_order'];
2151 }
2152 return $order_val;
2153 }
2154
2155
2156 // Set limit minimum characters
2157 public function setMinCharLimit(int $a_val): void
2158 {
2159 $this->min_char_limit = $a_val;
2160 }
2161
2162 public function getMinCharLimit(): int
2163 {
2164 return $this->min_char_limit;
2165 }
2166
2167 // Set limit maximum characters
2168 public function setMaxCharLimit(int $a_val): void
2169 {
2170 $this->max_char_limit = $a_val;
2171 }
2172
2173 public function getMaxCharLimit(): int
2174 {
2175 return $this->max_char_limit;
2176 }
2177
2186 public function getCalculatedDeadlines(): array
2187 {
2188 $calculated_deadlines = array(
2189 "user" => array(),
2190 "team" => array()
2191 );
2192
2193 if ($this->getRelativeDeadline() && $this->getDeadlineMode() == self::DEADLINE_RELATIVE) {
2194 foreach (ilExcIndividualDeadline::getStartingTimestamps($this->getId()) as $ts) {
2195 $type = $ts["is_team"]
2196 ? "team"
2197 : "user";
2198
2199 $calculated_deadlines[$type][$ts["member_id"]] = array(
2200 "calculated_deadline" => $ts["starting_ts"] + ($this->getRelativeDeadline() * 24 * 60 * 60)
2201 );
2202 }
2203 }
2204 return $calculated_deadlines;
2205 }
2206
2207 // see bug #36253
2208 public function canParticipantReceiveFeedback(int $part_id): bool
2209 {
2210 if ($this->hasTeam()) {
2211 if (!ilExAssignmentTeam::getTeamId($this->getId(), $part_id)) {
2212 return false;
2213 }
2214 }
2215 return true;
2216 }
2217}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
$filename
Definition: buildRTE.php:78
const IL_CAL_UNIX
const IL_CAL_DATETIME
return true
Global event handler.
Apointment templates are used for automatic generated apointments.
@classDescription Date and time handling
get(int $a_format, string $a_format_str='', string $a_tz='')
get formatted date
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getTeamId(int $a_assignment_id, int $a_user_id, bool $a_create_on_demand=false)
Exercise assignment.
ILIAS Refinery String Group $string_transform
saveMultiFeedbackFiles(array $a_files, ilObjExercise $a_exc)
static getAssignmentDataOfExercise(int $a_exc_id)
static lookupExerciseId(int $a_ass_id)
ilAppEventHandler $app_event_handler
setTeamTutor(bool $a_value)
static lookupMaxOrderNrForEx(int $a_exc_id)
ilExAssignmentTypes $types
static saveInstructionFilesOrderOfAssignment(int $a_ass_id, array $a_order)
static lookup(int $a_id, string $a_field)
clearMultiFeedbackDirectory()
Clear multi feedback directory.
static saveAssOrderOfExercise(int $a_ex_id, array $a_order)
uploadAssignmentFiles(array $a_files)
Upload assignment files (from creation form)
setRelativeDeadline(int $a_val)
setPeerReviewMin(int $a_value)
ilExAssignmentTypeInterface $ass_type
static instructionFileOrderGetMax(int $a_ass_id)
static instructionFileGetFileOrderData(array $a_file_data, int $a_ass_id)
static count(int $a_ex_id)
static lookupType(int $a_id)
setDeadline(?int $a_val)
setExtendedDeadline(?int $a_val)
static cloneAssignmentsOfExercise(int $a_old_exc_id, int $a_new_exc_id, array $a_crit_cat_map)
Clone assignments of exercise.
setPeerReviewText(bool $a_val)
setPeerReviewCriteriaCatalogue(?int $a_value)
static countMandatory(int $a_ex_id)
setPeerReview(bool $a_value)
isValidType(int $a_value)
static instructionFileDeleteOrder(int $a_ass_id, array $a_file)
getType()
Get type this will most probably become an non public function in the future (or become obsolete)
static isInExercise(int $a_ass_id, int $a_ex_id)
handleCalendarEntries(string $a_event, ilObjExercise $exc)
Handle calendar entries for deadline(s)
static insertFileOrderNr(int $a_ass_id, string $a_filename, int $a_order_nr)
handleGlobalFeedbackFileUpload(array $a_file)
setStartTime(?int $a_val)
setDeadlineMode(int $a_val)
Set deadline mode.
setFeedbackCron(bool $a_value)
Toggle (global) feedback file cron.
static sendFeedbackNotifications(int $a_ass_id, int $a_user_id=null)
getCalculatedDeadlines()
Get calculated deadlines for user/team members.
static renameInstructionFile(string $a_old_name, string $a_new_name, int $a_ass_id)
setPeerReviewValid(int $a_value)
Set peer review validation.
static instructionFileInsertOrder(string $a_filename, int $a_ass_id, int $a_order_nr=0)
static getInstancesByExercise(int $a_exc_id)
setPeerReviewPersonalized(bool $a_val)
static createNewUserRecords(int $a_user_id, int $a_exc_id)
getExerciseMemberAssignmentData(int $a_user_id, string $a_grade="")
Get submission data for an specific user,exercise and assignment.
static getPendingFeedbackNotifications()
initFromDB(array $a_set)
Import DB record.
__construct($a_id=0)
Constructor.
sendMultiFeedbackStructureFile(ilObjExercise $exercise)
Create member status record for a new assignment for all participants.
setInstruction(string $a_val)
setPortfolioTemplateId(int $a_val)
setTitle(string $a_val)
const TYPE_UPLOAD
direct checks against const should be avoided, use type objects instead
static createNewAssignmentRecords(int $a_ass_id, ilObjExercise $a_exc)
getPersonalDeadline(int $a_user_id)
setRelDeadlineLastSubmission(int $a_val)
getMemberStatus(?int $a_user_id=null)
setFeedbackFile(?string $a_value)
setPeerReviewSimpleUnlock(bool $a_value)
ilAccessHandler $access
setPeerReviewChars(?int $a_value)
uploadMultiFeedbackFile(array $a_file)
setPeerReviewRating(bool $a_val)
setType(int $a_value)
Set type this will most probably become an non public function in the future (or become obsolete)
static orderAssByDeadline(int $a_ex_id)
setPeerReviewDeadline(int $a_val)
fileAddOrder(array $a_entries=array())
setFeedbackDateCustom(int $a_value)
Set (global) feedback file availability using a custom date.
setFeedbackDate(int $a_value)
setIndividualDeadline(string $id, ilDateTime $date)
canParticipantReceiveFeedback(int $part_id)
setMaxFile(?int $a_value)
getMultiFeedbackFiles(int $a_user_id=0)
Get multi feedback files (of uploader)
static lookupAssignmentOnline(int $a_ass_id)
setMandatory(bool $a_val)
setPeerReviewFileUpload(bool $a_val)
static instructionFileExistsInDb(string $a_filename, int $a_ass_id)
static lookupTitle(int $a_id)
afterDeadlineStrict(bool $a_include_personal=true)
Exercise peer review.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getAllAssignmentFiles(int $a_exc_id, int $a_ass_id)
static getInstancesByParentId(int $a_parent_id)
static getInstanceByType(string $a_type)
static getStartingTimestamps(int $a_ass_id)
Get starting timestamp data for an assignment.
static getInstance(int $a_ass_id, int $a_participant_id, bool $a_is_team=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _getMembers(int $a_obj_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static deliverFileLegacy(string $a_file, ?string $a_filename=null, ?string $a_mime=null, ?bool $isInline=false, ?bool $removeAfterDelivery=false, ?bool $a_exit_after=true)
static unzip(string $path_to_zip_file, bool $overwrite_existing=false, bool $unpack_flat=false)
static getASCIIFilename(string $a_filename)
static getDir(string $a_dir, bool $a_rec=false, ?string $a_sub_dir="")
get directory
static zip(string $a_dir, string $a_file, bool $compress_content=false)
zips given directory/file into given zip.file
static makeDir(string $a_dir)
creates a new directory and inherits all filesystem permissions of the parent directory You may pass ...
static ilTempnam(?string $a_temp_path=null)
Returns a unique and non existing Path for e temporary file or directory.
static rename(string $a_source, string $a_target)
static delDir(string $a_dir, bool $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
static getSafeFilename(string $a_initial_filename)
static moveUploadedFile(string $a_file, string $a_name, string $a_target, bool $a_raise_errors=true, string $a_mode="move_uploaded")
move uploaded file
static rCopy(string $a_sdir, string $a_tdir, bool $preserveTimeAttributes=false)
Copies content of a directory $a_sdir recursively to a directory $a_tdir.
language handling
static getLogger(string $a_component_id)
Get component logger.
Component logger with individual log levels by component id.
Class ilObjExercise.
updateAllUsersStatus()
Update status of all users.
sendFeedbackFileNotification(string $a_feedback_file, array $user_ids, int $a_ass_id, bool $a_is_text_feedback=false)
User class.
static _lookupName(int $a_user_id)
lookup user name
static _exists(int $id, bool $reference=false, ?string $type=null)
checks if an object exists in object_data
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$app
Definition: cli.php:39
if(!file_exists(getcwd() . '/ilias.ini.php'))
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Definition: confirmReg.php:20
for( $i=6;$i< 13;$i++) for($i=1; $i< 13; $i++) $d
Definition: date.php:296
global $DIC
Definition: feed.php:28
$ilUser
Definition: imgupload.php:34
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Interface ilDBInterface.
insert(string $table_name, array $values)
nextId(string $table_name)
setLimit(int $limit, int $offset=0)
numRows(ilDBStatement $statement)
quote($value, string $type)
manipulate(string $query)
Run a (write) Query on the database.
query(string $query)
Run a (read-only) Query on the database.
fetchAssoc(ilDBStatement $statement)
queryF(string $query, array $types, array $values)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
cloneSpecificProperties(ilExAssignment $source, ilExAssignment $target)
filterUserIdsByRbacOrPositionOfCurrentUser(string $rbac_perm, string $pos_perm, int $ref_id, array $user_ids)
$path
Definition: ltiservices.php:32
$res
Definition: ltiservices.php:69
if($clientAssertionType !='urn:ietf:params:oauth:client-assertion-type:jwt-bearer'|| $grantType !='client_credentials') $parts
Definition: ltitoken.php:64
if($format !==null) $name
Definition: metadata.php:247
$i
Definition: metadata.php:41
$query
$type
$lng