ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.ilExPeerReviewGUI.php
Go to the documentation of this file.
1 <?php
2 
28 {
29  protected int $requested_giver_id;
30  protected \ILIAS\Exercise\Notification\NotificationManager $notification;
32  protected \ILIAS\Notes\Service $notes;
33  protected \ILIAS\Exercise\InternalGUIService $gui;
34  protected \ILIAS\Exercise\InternalDomainService $domain;
35  protected ilCtrl $ctrl;
36  protected ilTabsGUI $tabs_gui;
37  protected ilLanguage $lng;
39  protected ilObjUser $user;
40  protected ilExAssignment $ass;
42  protected int $requested_review_giver_id = 0;
43  protected int $requested_review_peer_id = 0;
44  protected string $requested_review_crit_id = "";
45  protected int $requested_peer_id = 0;
46  protected string $requested_crit_id = "";
47 
48  public function __construct(
49  ilExAssignment $a_ass,
50  ilExSubmission $a_submission = null
51  ) {
52  global $DIC;
53 
54  $service = $DIC->exercise()->internal();
55  $this->domain = $service->domain();
56  $this->gui = $service->gui();
57  $this->user = $this->domain->user();
58  $this->ctrl = $this->gui->ctrl();
59  $this->tabs_gui = $this->gui->tabs();
60  $this->lng = $this->domain->lng();
61  $this->tpl = $this->gui->ui()->mainTemplate();
62 
63  $this->ass = $a_ass;
64  $this->submission = $a_submission;
65 
66  $request = $DIC->exercise()->internal()->gui()->request();
67  $this->requested_review_giver_id = $request->getReviewGiverId();
68  $this->requested_review_peer_id = $request->getReviewPeerId();
69  $this->requested_review_crit_id = $request->getReviewCritId();
70  $this->requested_peer_id = $request->getPeerId();
71  $this->requested_giver_id = $request->getGiverId();
72  $this->requested_crit_id = $request->getCritId();
73  $this->gui = $DIC->exercise()->internal()->gui();
74  $this->notes = $DIC->notes();
75  $this->ctrl->saveParameter($this, array("peer_id"));
76  $this->notification = $this->domain->notification($request->getRefId());
77  }
78 
82  public function executeCommand(): void
83  {
84  $ilCtrl = $this->ctrl;
85  $lng = $this->lng;
86  $ilTabs = $this->tabs_gui;
87 
88  if (!$this->ass->getPeerReview()) {
89  $this->returnToParentObject();
90  }
91 
92  $class = $ilCtrl->getNextClass($this);
93  $cmd = $ilCtrl->getCmd("showpeerreviewoverview");
94 
95  switch ($class) {
96  case "ilfilesystemgui":
97  $ilCtrl->saveParameter($this, array("fu"));
98 
99  // see self::downloadPeerReview()
102 
103  if (!$this->canGive()) {
104  $this->returnToParentObject();
105  }
106 
107  $valid = false;
108  $peer_items = $this->submission->getPeerReview()->getPeerReviewsByPeerId($peer_id, true);
109  if (is_array($peer_items)) {
110  foreach ($peer_items as $item) {
111  if ($item["giver_id"] == $giver_id) {
112  $valid = true;
113  }
114  }
115  }
116  if (!$valid) {
117  $ilCtrl->redirect($this, "editPeerReview");
118  }
119 
120  $ilTabs->clearTargets();
121  $ilTabs->setBackTarget(
122  $lng->txt("back"),
123  $ilCtrl->getLinkTarget($this, "editPeerReview")
124  );
125 
126  $fstorage = new ilFSStorageExercise($this->ass->getExerciseId(), $this->ass->getId());
127  $fstorage->create();
128 
129  $fs_gui = new ilFileSystemGUI($fstorage->getPeerReviewUploadPath($peer_id, $giver_id));
130  $fs_gui->setTableId("excfbpeer");
131  $fs_gui->setAllowDirectories(false);
132  $fs_gui->setTitle($this->ass->getTitle() . ": " .
133  $lng->txt("exc_peer_review") . " - " .
134  $lng->txt("exc_peer_review_give"));
135  $this->ctrl->forwardCommand($fs_gui);
136  break;
137 
138  case "ilratinggui":
139  $peer_review = new ilExPeerReview($this->ass);
140  $peer_review->updatePeerReviewTimestamp($this->requested_peer_id);
141 
142  $rating_gui = new ilRatingGUI();
143  $rating_gui->setObject(
144  $this->ass->getId(),
145  "ass",
147  "peer"
148  );
149  $this->ctrl->forwardCommand($rating_gui);
150  $ilCtrl->redirect($this, "editPeerReview");
151  break;
152 
153  case "ilexsubmissiontextgui":
154  $ilTabs->clearTargets();
155  if (!$this->submission->isTutor()) {
156  $ilTabs->setBackTarget(
157  $lng->txt("back"),
158  $ilCtrl->getLinkTarget($this, "editPeerReview")
159  );
160  $this->ctrl->setReturn($this, "editPeerReview");
161  } else {
162  $ilTabs->setBackTarget(
163  $lng->txt("back"),
164  $ilCtrl->getLinkTarget($this, "showGivenPeerReview")
165  );
166  $this->ctrl->setReturn($this, "showGivenPeerReview");
167  }
168  $gui = new ilExSubmissionTextGUI(new ilObjExercise($this->ass->getExerciseId(), false), $this->submission);
169  $ilCtrl->forwardCommand($gui);
170  break;
171 
172  case "ilmessagegui":
173  $gui = $this->getMessagesGUI(
174  $this->requested_giver_id,
175  $this->requested_peer_id
176  );
177  $ilCtrl->forwardCommand($gui);
178  break;
179 
180  default:
181  $this->{$cmd . "Object"}();
182  break;
183  }
184  }
185 
186  public function returnToParentObject(): void
187  {
188  $this->ctrl->returnToParent($this);
189  }
190 
194  public static function getOverviewContent(
195  ilInfoScreenGUI $a_info,
196  ilExSubmission $a_submission
197  ): void {
198  global $DIC;
199 
200  $lng = $DIC->language();
201  $ilCtrl = $DIC->ctrl();
202  $gui = $DIC->exercise()
203  ->internal()
204  ->gui();
205 
206  $state = ilExcAssMemberState::getInstanceByIds($a_submission->getAssignment()->getId(), $a_submission->getUserId());
207 
208  $ass = $a_submission->getAssignment();
209 
210  $view_pc = "";
211  $edit_pc = "";
212 
213 
214  //if($ass->afterDeadlineStrict() &&
215  // $ass->getPeerReview())
216  if ($state->hasSubmissionEndedForAllUsers() &&
217  $ass->getPeerReview()) {
218  $ilCtrl->setParameterByClass("ilExPeerReviewGUI", "ass_id", $a_submission->getAssignment()->getId());
219 
220  $nr_missing_fb = $a_submission->getPeerReview()->getNumberOfMissingFeedbacksForReceived();
221 
222  // before deadline (if any)
223  // if(!$ass->getPeerReviewDeadline() ||
224  // $ass->getPeerReviewDeadline() > time())
225  if ($state->isPeerReviewAllowed()) {
226  $dl_info = "";
227  if ($ass->getPeerReviewDeadline()) {
228  $dl_info = " (" . sprintf(
229  $lng->txt("exc_peer_review_deadline_info_button"),
230  $state->getPeerReviewDeadlinePresentation()
231  ) . ")";
232  }
233 
234  $b = $gui->link(
235  $lng->txt("exc_peer_review_give"),
236  $ilCtrl->getLinkTargetByClass(array(ilAssignmentPresentationGUI::class, "ilExSubmissionGUI", "ilExPeerReviewGUI"), "editPeerReview")
237  )->emphasised();
238  if ($nr_missing_fb) {
239  $b = $b->primary();
240  }
241  $edit_pc = $b->render();
242  } elseif ($ass->getPeerReviewDeadline()) {
243  $edit_pc = $lng->txt("exc_peer_review_deadline_reached");
244  }
245 
246  // after deadline (if any)
247  if ((!$ass->getPeerReviewDeadline() ||
248  $ass->getPeerReviewDeadline() < time())) {
249  // given peer review should be accessible at all times (read-only when not editable - see above)
250  if ($ass->getPeerReviewDeadline() &&
251  $a_submission->getPeerReview()->countGivenFeedback(false)) {
252  $b = $gui->link(
253  $lng->txt("exc_peer_review_given"),
254  $ilCtrl->getLinkTargetByClass(array(ilAssignmentPresentationGUI::class, "ilExSubmissionGUI", "ilExPeerReviewGUI"), "showGivenPeerReview")
255  )->emphasised();
256  $view_pc = $b->render() . " ";
257  }
258 
259  // did give enough feedback
260  if (!$nr_missing_fb) {
261  // received any?
262  $received = (bool) sizeof($a_submission->getPeerReview()->getPeerReviewsByPeerId($a_submission->getUserId(), true));
263  if ($received) {
264  $b = $gui->link(
265  $lng->txt("exc_peer_review_show"),
266  $ilCtrl->getLinkTargetByClass(array(ilAssignmentPresentationGUI::class, "ilExSubmissionGUI", "ilExPeerReviewGUI"), "showReceivedPeerReview")
267  )->emphasised();
268  $view_pc .= $b->render();
269  }
270  // received none
271  else {
272  $view_pc .= $lng->txt("exc_peer_review_show_received_none");
273  }
274  }
275  // did not give enough
276  else {
277  $view_pc .= $lng->txt("exc_peer_review_show_missing");
278  }
279  }
280  /* must give before showing received
281  else
282  {
283  $view_pc = $lng->txt("exc_peer_review_show_not_rated_yet");
284  }
285  */
286 
287  $sep = ($edit_pc != "" && $view_pc != "")
288  ? "<br><br>"
289  : "";
290 
291  $a_info->addProperty($lng->txt("exc_peer_review"), $edit_pc . $sep . $view_pc);
292 
293  $ilCtrl->setParameterByClass("ilExPeerReviewGUI", "ass_id", "");
294  }
295  }
296 
297  public function buildSubmissionPropertiesAndActions(\ILIAS\Exercise\Assignment\PropertyAndActionBuilderUI $builder): void
298  {
299  $f = $this->gui->ui()->factory();
300  $lng = $this->lng;
301  $ilCtrl = $this->ctrl;
302  $submission = $this->submission;
303  $ass = $submission->getAssignment();
304  $state = $this->domain->assignment()->state($ass->getId(), $submission->getUserId());
305 
306  $view_pc = "";
307  $edit_pc = "";
308 
309 
310  //if($ass->afterDeadlineStrict() &&
311  // $ass->getPeerReview())
312  if ($state->hasSubmissionEndedForAllUsers() &&
313  $ass->getPeerReview()) {
314  $ilCtrl->setParameterByClass("ilExPeerReviewGUI", "ass_id", $submission->getAssignment()->getId());
315 
316  $nr_missing_fb = $submission->getPeerReview()->getNumberOfMissingFeedbacksForReceived();
317 
318  $builder->addAdditionalHeadProperty(
319  $this->lng->txt("exc_given_feedback"),
320  $submission->getPeerReview()->countGivenFeedback() . " " .
321  $this->lng->txt("exc_x_of_y") . " " .
322  $submission->getAssignment()->getPeerReviewMin()
323  );
324 
325  $builder->addAdditionalHeadProperty(
326  $this->lng->txt("exc_received_feedback"),
327  $submission->getPeerReview()->countReceivedFeedbacks($submission->getUserid())
328  );
329 
330  // before deadline (if any)
331  // if(!$ass->getPeerReviewDeadline() ||
332  // $ass->getPeerReviewDeadline() > time())
333  if ($state->isPeerReviewAllowed()) {
334  $url = $ilCtrl->getLinkTargetByClass(array(ilAssignmentPresentationGUI::class, "ilExSubmissionGUI", "ilExPeerReviewGUI"), "editPeerReview");
335  $button = $f->button()->primary(
336  $lng->txt("exc_peer_review_give"),
337  $url
338  );
339  $builder->addView(
340  "give_feedback",
341  $this->lng->txt("exc_given_feedback"),
342  $url
343  );
344  $builder->setMainAction(
345  $builder::SEC_PEER_FEEDBACK,
346  $button
347  );
348  if ($ass->getPeerReviewDeadline()) {
349  $deadline = $state->getPeerReviewDeadlinePresentation();
350  } else {
351  $deadline = $lng->txt("exc_no_peer_feedback_deadline");
352  }
353  $builder->addProperty(
354  $builder::SEC_PEER_FEEDBACK,
355  $lng->txt("exc_peer_review_deadline"),
356  $deadline
357  );
358  } elseif ($ass->getPeerReviewDeadline()) {
359  $edit_pc = $lng->txt("exc_peer_review_deadline_reached");
360  $builder->addProperty(
361  $builder::SEC_PEER_FEEDBACK,
362  $lng->txt("exc_peer_review_deadline"),
363  $lng->txt("exc_peer_review_deadline_reached")
364  );
365  }
366  if ($ass->getPeerReviewDeadline()) {
367  $builder->addProperty(
368  $builder::SEC_SCHEDULE,
369  $lng->txt("exc_peer_review_deadline"),
370  $state->getPeerReviewDeadlinePresentation()
371  );
372  }
373 
374  // after deadline (if any)
375  if ((!$ass->getPeerReviewDeadline() ||
376  $ass->getPeerReviewDeadline() < time())) {
377  // given peer review should be accessible at all times (read-only when not editable - see above)
378  if ($ass->getPeerReviewDeadline() &&
379  $submission->getPeerReview()->countGivenFeedback(false)) {
380  $url = $ilCtrl->getLinkTargetByClass(array(ilAssignmentPresentationGUI::class, "ilExSubmissionGUI", "ilExPeerReviewGUI"), "showGivenPeerReview");
381  $link = $f->link()->standard(
382  $lng->txt("exc_peer_review_given"),
383  $url
384  );
385  $builder->addAction(
386  $builder::SEC_PEER_FEEDBACK,
387  $link
388  );
389  $builder->addView(
390  "give_feedback",
391  $this->lng->txt("exc_given_feedback"),
392  $url
393  );
394  }
395 
396  if ($nr_missing_fb <= 0) {
397  // received any?
398  $received = (bool) sizeof($submission->getPeerReview()->getPeerReviewsByPeerId($submission->getUserId(), true));
399  if ($received) {
400  $url = $ilCtrl->getLinkTargetByClass(array(ilAssignmentPresentationGUI::class, "ilExSubmissionGUI", "ilExPeerReviewGUI"), "showReceivedPeerReview");
401  $link = $f->link()->standard(
402  $lng->txt("exc_peer_review_show"),
403  $url
404  );
405  $builder->addAction(
406  $builder::SEC_PEER_FEEDBACK,
407  $link
408  );
409  $builder->addView(
410  "receive_feedback",
411  $this->lng->txt("exc_received_feedback"),
412  $url
413  );
414  }
415  // received none
416  else {
417  $builder->addProperty(
418  $builder::SEC_PEER_FEEDBACK,
419  $lng->txt("exc_received_peer_feedback"),
420  $lng->txt("exc_peer_review_show_received_none")
421  );
422  }
423  }
424  // did not give enough
425  else {
426  $builder->addProperty(
427  $builder::SEC_PEER_FEEDBACK,
428  $lng->txt("exc_peer_feedback_status"),
429  $lng->txt("exc_peer_review_show_missing")
430  );
431  }
432  }
433  $ilCtrl->setParameterByClass("ilExPeerReviewGUI", "ass_id", "");
434  }
435  }
436 
437  protected function canGive(): bool
438  {
439  return ($this->submission->isOwner() &&
440  $this->ass->afterDeadlineStrict() &&
441  (!$this->ass->getPeerReviewDeadline() ||
442  $this->ass->getPeerReviewDeadline() > time()));
443  }
444 
445  protected function canView(): bool
446  {
447  return ($this->submission->isTutor() ||
448  ($this->submission->isOwner() &&
449  $this->ass->afterDeadlineStrict() &&
450  (!$this->ass->getPeerReviewDeadline() ||
451  $this->ass->getPeerReviewDeadline() < time())));
452  }
453 
460  public function showGivenPeerReviewObject(): void
461  {
462  $tpl = $this->tpl;
463  $lng = $this->lng;
464 
465  $this->tabs_gui->activateTab("give_feedback");
466 
467  if (!$this->canView()) {
468  $this->returnToParentObject();
469  }
470 
471  $peer_items = $this->submission->getPeerReview()->getPeerReviewsByGiver($this->submission->getUserId());
472  if ($peer_items === []) {
473  $this->tpl->setOnScreenMessage('failure', $this->lng->txt("exc_peer_review_no_peers"), true);
474  $this->returnToParentObject();
475  }
476 
477  $tpl->setTitle($this->ass->getTitle() . ": " . $lng->txt("exc_peer_review_given"));
478 
479  $this->gui->permanentLink()->setGivenFeedbackPermanentLink();
480 
481  $panel = $this->getReceivedFeedbackPanel($peer_items);
482 
483  $tpl->setContent($this->gui->ui()->renderer()->render($panel));
484  }
485 
492  public function showReceivedPeerReviewObject(): void
493  {
494  $ilCtrl = $this->ctrl;
495  $tpl = $this->tpl;
496  $lng = $this->lng;
497  $this->tabs_gui->activateTab("receive_feedback");
498 
499  if (!$this->canView() ||
500  (!$this->submission->isTutor() &&
501  $this->submission->getPeerReview()->getNumberOfMissingFeedbacksForReceived())) {
502  $this->returnToParentObject();
503  }
504 
505  $this->gui->permanentLink()->setReceivedFeedbackPermanentLink();
506 
507  /*
508  $this->tabs_gui->clearTargets();
509  $this->tabs_gui->setBackTarget($this->lng->txt("back"), $this->ctrl->getLinkTarget($this, "returnToParent"));*/
510 
511  $peer_items = $this->submission->getPeerReview()->getPeerReviewsByPeerId($this->submission->getUserId(), !$this->submission->isTutor());
512  if ($peer_items === []) {
513  // #11373
514  $this->tpl->setOnScreenMessage('failure', $this->lng->txt("exc_peer_review_no_peers_reviewed_yet"), true);
515  $ilCtrl->redirect($this, "returnToParent");
516  }
517 
518  $tpl->setTitle($this->ass->getTitle() . ": " . $lng->txt("exc_peer_review_show"));
519 
520  $info_widget = new ilInfoScreenGUI($this);
521 
522  $panel = $this->getReceivedFeedbackPanel($peer_items, true);
523 
524  $tpl->setContent($this->gui->ui()->renderer()->render($panel));
525  }
526 
527  protected function getReceivedFeedbackPanel(
528  array $a_peer_items,
529  bool $a_by_peer = false
530  ): \ILIAS\UI\Component\Panel\Standard {
531  $lng = $this->lng;
532 
533  $sub_panels = [];
534  if ($this->submission->isTutor()) {
535  $props = [];
536  $user_title = $a_by_peer
537  ? $lng->txt("exc_peer_review_recipient")
538  : $lng->txt("exc_peer_review_giver");
539  $props[] = [
540  "prop" => $lng->txt("name"),
541  "value" => ilUserUtil::getNamePresentation($this->submission->getUserId(), false, false, "", true)
542  ];
543  $sub_panels[] = $this->getSubPanel(
544  $user_title,
545  $props
546  );
547  }
548 
549  if ($a_by_peer) {
550 
551  // list received feedbacks
552 
553  // submission
554  $props = [];
555  $submission = new ilExSubmission($this->ass, $this->submission->getUserId());
556  $file_info = $submission->getDownloadedFilesInfoForTableGUIS();
557 
558  $props[] = [
559  "prop" => $file_info["last_submission"]["txt"],
560  "value" => $file_info["last_submission"]["value"] .
561  $this->getLateSubmissionInfo($submission)
562  ];
563 
564  $sub_data = $this->getSubmissionContent($submission);
565  if ($sub_data === '' || $sub_data === '0') {
566  $sub_data = '<a href="' . $file_info["files"]["download_url"] . '">' . $lng->txt("download") . '</a>';
567  }
568  $props[] = [
569  "prop" => $lng->txt("exc_submission"),
570  "value" => $sub_data
571  ];
572 
573  $sub_panels[] = $this->getSubPanel(
574  $lng->txt("exc_your_submission"),
575  $props
576  );
577  }
578 
579  foreach ($a_peer_items as $peer) {
580  $props = [];
581  if (!$a_by_peer) {
582  $giver_id = $this->submission->getUserId();
583  $peer_id = $peer["peer_id"];
584  $id_title = $lng->txt("exc_peer_review_recipient");
585  $user_id = $peer_id;
586  } else {
587 
588  // list received feedbacks
589 
590  $giver_id = $peer["giver_id"];
591  $peer_id = $this->submission->getUserId();
592  $id_title = $lng->txt("exc_peer_review_giver");
593  $user_id = $giver_id;
594  }
595 
596  // peer info
597  if ($this->submission->isTutor()) {
598  $id_value = ilUserUtil::getNamePresentation($user_id, "", "", false, true);
599  } elseif (!$this->ass->hasPeerReviewPersonalized()) {
600  $id_value = $peer["seq"];
601  } else {
602  $id_value = ilUserUtil::getNamePresentation($user_id);
603  }
604 
605  $mess_gui = $this->getMessagesGUI(
606  $giver_id,
607  $peer_id
608  );
609 
610  // submission info
611 
612  if (!$a_by_peer) {
613  $submission = new ilExSubmission($this->ass, $peer_id);
614  $file_info = $submission->getDownloadedFilesInfoForTableGUIS();
615 
616  $props[] = [
617  "prop" => $file_info["last_submission"]["txt"],
618  "value" => $file_info["last_submission"]["value"] .
619  $this->getLateSubmissionInfo($submission)
620  ];
621 
622  $sub_data = $this->getSubmissionContent($submission);
623  if ($sub_data === '' || $sub_data === '0') {
624  if (isset($file_info["files"]["download_url"])) {
625  $sub_data = '<a href="' . $file_info["files"]["download_url"] . '">' . $lng->txt("download") . '</a>';
626  }
627  }
628  $props[] = [
629  "prop" => $lng->txt("exc_submission"),
630  "value" => $sub_data
631  ];
632  }
633 
634 
635  // peer review items
636 
637  $values = $this->submission->getPeerReview()->getPeerReviewValues($giver_id, $peer_id);
638 
639  foreach ($this->ass->getPeerReviewCriteriaCatalogueItems() as $item) {
640  $crit_id = $item->getId()
641  ? $item->getId()
642  : $item->getType();
643 
644  $item->setPeerReviewContext(
645  $this->ass,
646  $giver_id,
647  $peer_id
648  );
649 
650  $title = $item->getTitle();
651  $html = $item->getHTML($values[$crit_id] ?? null);
652  $props[] = [
653  "prop" => $title ?: "&nbsp;",
654  "value" => $html ?: "&nbsp;"
655  ];
656  }
657  $sub_panels[] = $this->getSubPanel(
658  $id_title . ": " . $id_value,
659  $props,
660  $mess_gui
661  );
662  }
663  return $this->gui->ui()->factory()->panel()->standard(
664  $a_by_peer
665  ? $this->lng->txt("exc_received_feedback")
666  : $this->lng->txt("exc_given_feedback"),
667  $sub_panels
668  );
669  }
670 
671  protected function getSubPanel(
672  string $title,
673  array $props,
674  ?ilMessageGUI $mess_gui = null
675  ): \ILIAS\UI\Component\Panel\Sub {
676  $f = $this->gui->ui()->factory();
677  $r = $this->gui->ui()->renderer();
678  $tpl = new \ilTemplate("tpl.panel_items.html", true, true, "Modules/Exercise/PeerReview");
679  foreach ($props as $prop) {
680  $tpl->setCurrentBlock("entry");
681  $tpl->setVariable("LABEL", $prop["prop"]);
682  $tpl->setVariable("VALUE", $prop["value"]);
683  $tpl->parseCurrentBlock();
684  }
685  $mess_html = "";
686  if ($mess_gui) {
687  $mess_html = $r->render($f->divider()->horizontal()) .
688  $mess_gui->getWidget();
689  }
690 
691  return $f->panel()->sub(
692  $title,
693  $f->legacy($tpl->get() . $mess_html)
694  );
695  }
696 
697  protected function getLateSubmissionInfo(
698  ilExSubmission $a_submission
699  ): string {
700  $lng = $this->lng;
701 
702  // #18966 - late files info
703  foreach ($a_submission->getFiles() as $file) {
704  if ($file["late"]) {
705  return '<div class="warning">' . $lng->txt("exc_late_submission") . '</div>';
706  }
707  }
708  return "";
709  }
710 
714  public function editPeerReviewObject(): void
715  {
716  $tpl = $this->tpl;
717 
718  $this->tabs_gui->activateTab("give_feedback");
719  if (!$this->canGive()) {
720  $this->returnToParentObject();
721  }
722 
723  $peer_items = $this->submission->getPeerReview()->getPeerReviewsByGiver($this->submission->getUserId());
724  if ($peer_items === []) {
725  $this->tpl->setOnScreenMessage('failure', $this->lng->txt("exc_peer_review_no_peers"), true);
726  $this->returnToParentObject();
727  }
728 
729  $missing = $this->submission->getPeerReview()->getNumberOfMissingFeedbacksForReceived();
730  if ($missing !== 0) {
731  $dl = $this->ass->getPeerReviewDeadline();
732  if (!$dl || $dl < time()) {
733  $this->tpl->setOnScreenMessage('info', sprintf($this->lng->txt("exc_peer_review_missing_info"), $missing));
734  } else {
735  $this->tpl->setOnScreenMessage('info', sprintf(
736  $this->lng->txt("exc_peer_review_missing_info_deadline"),
737  $missing,
739  ));
740  }
741  }
742 
743  /*$tbl = new ilExAssignmentPeerReviewTableGUI(
744  $this,
745  "editPeerReview",
746  $this->ass,
747  $this->submission->getUserId(),
748  $peer_items
749  );*/
750  $panel = $this->getPeerReviewReceiverPanel(
751  $this->ass,
752  $this->submission->getUserId(),
753  $peer_items
754  );
755  $tpl->setContent($this->gui->ui()->renderer()->render($panel));
756  }
757 
758  protected function getPeerReviewReceiverPanel(
759  ilExAssignment $ass,
760  int $user_id,
761  array $peer_data
762  ): \ILIAS\UI\Component\Panel\Listing\Standard {
763  if ($ass->hasPeerReviewFileUpload()) {
764  $this->fstorage = new ilFSStorageExercise($ass->getExerciseId(), $ass->getId());
765  $this->fstorage->create();
766  }
767  $personal = $ass->hasPeerReviewPersonalized();
768  $f = $this->gui->ui()->factory();
769  $lng = $this->lng;
770  $items = [];
771  foreach ($peer_data as $item) {
772  $row = array();
773 
774  if (\ilObject::_lookupType($item["peer_id"]) !== "usr") {
775  continue;
776  }
777 
778  $row["giver_id"] = $item["giver_id"];
779  $row["peer_id"] = $item["peer_id"];
780  $row["tstamp"] = $item["tstamp"];
781 
782  if (!$personal) {
783  $row["seq"] = $item["seq"];
784  } else {
785  $row["name"] = ilUserUtil::getNamePresentation($item["peer_id"]);
786  }
787 
788  // validate
789  $row["valid"] = $all_empty = true;
790  $submission = new ilExSubmission($ass, $item["peer_id"]);
791  $values = $submission->getPeerReview()->getPeerReviewValues($item["giver_id"], $item["peer_id"]);
792  foreach ($this->ass->getPeerReviewCriteriaCatalogueItems() as $crit) {
793  $crit_id = $crit->getId()
794  ? $crit->getId()
795  : $crit->getType();
796  $crit->setPeerReviewContext(
797  $this->ass,
798  $item["giver_id"],
799  $item["peer_id"]
800  );
801  if (!$crit->validate($values[$crit_id] ?? null)) {
802  $row["valid"] = false;
803  }
804  if ($crit->hasValue($values[$crit_id] ?? null)) {
805  $all_empty = false;
806  }
807  }
808  if ($all_empty) {
809  $row["valid"] = false;
810  }
811  if (!$row["valid"]) {
812  // $this->invalid++;
813  }
814 
815  $ilCtrl = $this->ctrl;
816 
817  if (isset($row["seq"])) {
818  $title = $this->lng->txt("exc_peer_review_recipient") . " " . $row["seq"];
819  } else {
820  $title = $row["name"];
821  }
822 
823  if ($row["tstamp"]) {
824  $row["tstamp"] = ilDatePresentation::formatDate(new ilDateTime($row["tstamp"], IL_CAL_DATETIME));
825  }
826  $props = [];
827  $props[$lng->txt("last_update")] = $row["tstamp"];
828 
829  $props[$lng->txt("valid")] = $row["valid"]
830  ? $this->lng->txt("yes")
831  : $this->lng->txt("no");
832 
833  $ilCtrl->setParameter($this, "peer_id", $row["peer_id"]);
834  $actions = [
835  $f->button()->shy(
836  $this->lng->txt("edit"),
837  $ilCtrl->getLinkTarget($this, "editPeerReviewItem")
838  )
839  ];
840  $ilCtrl->setParameter($this, "pid", "");
841 
842  $items[] = $f->item()->standard(
843  $title
844  )->withProperties($props)
845  ->withActions($f->dropdown()->standard($actions));
846  }
847 
848  $group = $f->item()->group("", $items);
849  return $f->panel()->listing()->standard(
850  $this->lng->txt("exc_peer_review_give"),
851  [$group]
852  );
853  }
854 
855  public function editPeerReviewItemObject(
856  ilPropertyFormGUI $a_form = null
857  ): void {
858  $tpl = $this->tpl;
859 
860  $this->tabs_gui->activateTab("give_feedback");
861 
862  if (!$this->canGive() && $this->canView()) {
863  $this->ctrl->redirectByClass(self::class, "showGivenPeerReview");
864  }
865 
866  if (!$this->canGive() ||
867  !$this->isValidPeer($this->requested_peer_id)) {
868  $this->returnToParentObject();
869  }
870 
871  if ($a_form === null) {
872  $a_form = $this->initPeerReviewItemForm($this->requested_peer_id);
873  }
874 
875  $sep = $this->gui->ui()->renderer()->render($this->gui->ui()->factory()->divider()->horizontal());
876  $peer_state = ilExcAssMemberState::getInstanceByIds($this->ass->getId(), $this->requested_peer_id);
877  $message_html = "";
878 
879  // show only message gui, if peer is able to access received feedback
880  if ($peer_state->isReceivedFeedbackAccessible()) {
881  $message_gui = $this->getMessagesGUI(
882  $this->user->getId(),
884  );
885  $message_html = $sep . $message_gui->getListHTML();
886  }
887 
888  $this->gui->permanentLink()->setGivenFeedbackPermanentLink();
889 
890  $tpl->setContent($a_form->getHTML() . $message_html);
891  }
892 
893  protected function getMessagesGUI(int $giver_id, int $peer_id): ilMessageGUI
894  {
895  $this->ctrl->setParameter($this, "giver_id", $giver_id);
896  $this->ctrl->setParameter($this, "peer_id", $peer_id);
897  $pr = $this->domain->peerReview($this->ass);
898  $gui = $this->notes->gui()->getMessagesGUI(
899  $peer_id,
900  $this->ass->getExerciseId(),
901  $pr->getReviewId($giver_id, $peer_id),
902  "excpf"
903  );
904  if (!$this->ass->hasPeerReviewPersonalized()) {
905  if ($giver_id === $this->user->getId()) {
906  $counterpart_name = $this->lng->txt("exc_peer_review_recipient");
907  } else {
908  $counterpart_name = $this->lng->txt("exc_peer_review_giver");
909  }
910  $gui->setAnonymised(true, $counterpart_name);
911  }
912 
913  $gui->addObserver(function (
914  int $exc_id,
915  int $pf_id,
916  string $type,
917  string $action,
918  int $note_id
919  ) use ($giver_id, $peer_id) {
920  $this->observeMessageAction(
921  $giver_id,
922  $peer_id,
923  $note_id,
924  $action
925  );
926  });
927 
928  return $gui;
929  }
930 
931  public function observeMessageAction(
932  int $giver_id,
933  int $peer_id,
934  int $note_id,
935  string $action
936  ): void {
937  if ($action !== "new") {
938  return;
939  }
940  $note = $this->notes->domain()->getById($note_id);
941  $text = $note->getText();
942 
943  if ($note->getAuthor() === $giver_id) {
944  $this->notification->sendMessageFromPeerfeedbackGiverNotification(
945  $this->ass->getId(),
946  $peer_id,
947  $text
948  );
949  } else {
950  $this->notification->sendMessageFromPeerfeedbackRecipientNotification(
951  $this->ass->getId(),
952  $peer_id,
953  $giver_id,
954  $text
955  );
956  }
957  }
958 
959 
960  protected function isValidPeer(int $a_peer_id): bool
961  {
962  $peer_items = $this->submission->getPeerReview()->getPeerReviewsByGiver($this->submission->getUserId());
963  foreach ($peer_items as $item) {
964  if ($item["peer_id"] == $a_peer_id) {
965  return true;
966  }
967  }
968  return false;
969  }
970 
971  protected function getSubmissionContent(
972  ilExSubmission $a_submission
973  ): string {
974  if ($this->ass->getType() != ilExAssignment::TYPE_TEXT) {
975  return "";
976  }
977 
978  $text = $a_submission->getFiles();
979  if ($text !== []) {
980  $text = array_shift($text);
981  if (trim($text["atext"]) !== '' && trim($text["atext"]) !== '0') {
982  // mob id to mob src
983  return nl2br(ilRTE::_replaceMediaObjectImageSrc($text["atext"], 1));
984  }
985  }
986  return "";
987  }
988 
992  protected function initPeerReviewItemForm(
993  int $a_peer_id
994  ): ilPropertyFormGUI {
995  $ilCtrl = $this->ctrl;
996  $lng = $this->lng;
997 
998  // get peer data
999  $peer_items = $this->submission->getPeerReview()->getPeerReviewsByGiver($this->submission->getUserId());
1000  $peer = [];
1001  foreach ($peer_items as $item) {
1002  if ($item["peer_id"] == $a_peer_id) {
1003  $peer = $item;
1004  break;
1005  }
1006  }
1007 
1008  $ilCtrl->saveParameter($this, "peer_id");
1009 
1010  $form = new ilPropertyFormGUI();
1011  $form->setFormAction($ilCtrl->getFormAction($this, "updatePeerReview"));
1012 
1013  $form->setTitle($this->ass->getTitle() . ": " . $lng->txt("exc_peer_review_give"));
1014 
1015  // peer info
1016  if (!$this->ass->hasPeerReviewPersonalized()) {
1017  $id_title = $lng->txt("id");
1018  $id_value = $peer["seq"];
1019  } else {
1020  $id_title = $lng->txt("exc_peer_review_recipient");
1021  $id_value = ilUserUtil::getNamePresentation($peer["peer_id"]);
1022  }
1023  $id = new ilNonEditableValueGUI($id_title);
1024  $id->setValue($id_value);
1025  $form->addItem($id);
1026 
1027  // submission info
1028 
1029  $submission = new ilExSubmission($this->ass, $peer["peer_id"]);
1030  $file_info = $submission->getDownloadedFilesInfoForTableGUIS();
1031 
1032  $last_sub = new ilNonEditableValueGUI($file_info["last_submission"]["txt"], "", true);
1033  $last_sub->setValue($file_info["last_submission"]["value"] .
1034  $this->getLateSubmissionInfo($submission));
1035  $form->addItem($last_sub);
1036 
1037  $sub_data = $this->getSubmissionContent($submission);
1038  if (($sub_data === '' || $sub_data === '0') && isset($file_info["files"]["download_url"])) {
1039  $sub_data = '<a href="' . $file_info["files"]["download_url"] . '">' . $lng->txt("download") . '</a>';
1040  }
1041 
1042  $sub = new ilNonEditableValueGUI($lng->txt("exc_submission"), "", true);
1043  $sub->setValue($sub_data);
1044  $form->addItem($sub);
1045 
1046  // peer review items
1047 
1048  $input = new ilFormSectionHeaderGUI();
1049  $input->setTitle($lng->txt("exc_peer_review"));
1050  $form->addItem($input);
1051 
1052  $values = $this->submission->getPeerReview()->getPeerReviewValues($this->submission->getUserId(), $a_peer_id);
1053 
1054  foreach ($this->ass->getPeerReviewCriteriaCatalogueItems() as $item) {
1055  $crit_id = $item->getId()
1056  ? $item->getId()
1057  : $item->getType();
1058 
1059  $item->setPeerReviewContext(
1060  $this->ass,
1061  $this->submission->getUserId(),
1062  $peer["peer_id"],
1063  $form
1064  );
1065  $item->addToPeerReviewForm($values[$crit_id] ?? null);
1066  }
1067 
1068  $form->addCommandButton("updatePeerReview", $lng->txt("save"));
1069  $form->addCommandButton("editPeerReview", $lng->txt("cancel"));
1070 
1071  return $form;
1072  }
1073 
1074  public function updateCritAjaxObject(): void
1075  {
1076  $ilCtrl = $this->ctrl;
1077  $ilUser = $this->user;
1078  $tpl = $this->tpl;
1079 
1080  if (!$this->canGive() ||
1081  !$this->requested_peer_id ||
1082  !$this->requested_crit_id ||
1083  !$ilCtrl->isAsynch()) {
1084  exit();
1085  }
1086 
1087  $peer_id = $this->requested_peer_id;
1088  $crit_id = $this->requested_crit_id;
1089  $giver_id = $ilUser->getId();
1090 
1091  if (!is_numeric($crit_id)) {
1092  $crit = ilExcCriteria::getInstanceByType($crit_id);
1093  } else {
1094  $crit = ilExcCriteria::getInstanceById($crit_id);
1095  }
1096  $crit->setPeerReviewContext($this->ass, $giver_id, $peer_id);
1097  $html = $crit->updateFromAjax();
1098 
1099  $this->handlePeerReviewChange();
1100 
1101  echo $html;
1102  echo $tpl->getOnLoadCodeForAsynch();
1103  exit();
1104  }
1105 
1106  public function updatePeerReviewObject(): void
1107  {
1108  $lng = $this->lng;
1109  $ilCtrl = $this->ctrl;
1110 
1111  if (!$this->canGive() ||
1112  !$this->isValidPeer($this->requested_peer_id)) {
1113  $this->returnToParentObject();
1114  }
1115 
1116  $peer_id = $this->requested_peer_id;
1117 
1118  $form = $this->initPeerReviewItemForm($peer_id);
1119  if ($form->checkInput()) {
1120  $valid = true;
1121 
1122  $values = array();
1123  foreach ($this->ass->getPeerReviewCriteriaCatalogueItems() as $item) {
1124  $item->setPeerReviewContext(
1125  $this->ass,
1126  $this->submission->getUserId(),
1127  $peer_id,
1128  $form
1129  );
1130  $value = $item->importFromPeerReviewForm();
1131  if ($value !== null) {
1132  $crit_id = $item->getId()
1133  ? $item->getId()
1134  : $item->getType();
1135  $values[$crit_id] = $value;
1136  }
1137  if (!$item->validate($value)) {
1138  $valid = false;
1139  }
1140  }
1141 
1142  if ($valid) {
1143  $this->submission->getPeerReview()->updatePeerReview($peer_id, $values);
1144 
1145  $this->handlePeerReviewChange();
1146 
1147  $this->tpl->setOnScreenMessage('success', $this->lng->txt("exc_peer_review_updated"), true);
1148  $ilCtrl->redirect($this, "editPeerReview");
1149  } else {
1150  $this->tpl->setOnScreenMessage('failure', $lng->txt("form_input_not_valid"));
1151  }
1152  }
1153 
1154  $form->setValuesByPost();
1155  $this->editPeerReviewItemObject($form);
1156  }
1157 
1158  protected function handlePeerReviewChange(): void
1159  {
1160  // (in)valid peer reviews could change assignment status
1161  $exercise = new ilObjExercise($this->ass->getExerciseId(), false);
1162  $exercise->processExerciseStatus(
1163  $this->ass,
1164  $this->submission->getUserIds(),
1165  $this->submission->hasSubmitted(),
1166  $this->submission->validatePeerReviews()
1167  );
1168  }
1169 
1170  public function downloadPeerReviewObject(): void
1171  {
1172  $ilCtrl = $this->ctrl;
1173 
1174  if (!$this->canView() &&
1175  !$this->canGive()) {
1176  $this->returnToParentObject();
1177  }
1178 
1182 
1183  if (!is_numeric($crit_id)) {
1184  $crit = ilExcCriteria::getInstanceByType($crit_id);
1185  } else {
1186  $crit = ilExcCriteria::getInstanceById($crit_id);
1187  }
1188 
1189  $crit->setPeerReviewContext($this->ass, $giver_id, $peer_id);
1190  $file = $crit->getFileByHash();
1191  if ($file) {
1192  ilFileDelivery::deliverFileLegacy($file, basename($file));
1193  }
1194 
1195  $ilCtrl->redirect($this, "returnToParent");
1196  }
1197 
1198 
1199 
1200  //
1201  // ADMIN
1202  //
1203 
1204  public function showPeerReviewOverviewObject(): void
1205  {
1206  $tpl = $this->tpl;
1207 
1208  if (!$this->ass ||
1209  !$this->ass->getPeerReview()) {
1210  $this->returnToParentObject();
1211  }
1212 
1214  $this,
1215  "showPeerReviewOverview",
1216  $this->ass
1217  );
1218 
1219  $panel = "";
1220  $panel_data = $tbl->getPanelInfo();
1221  if (is_array($panel_data) && count($panel_data) > 0) {
1222  $ptpl = new ilTemplate("tpl.exc_peer_review_overview_panel.html", true, true, "Modules/Exercise");
1223  foreach ($panel_data as $item) {
1224  $ptpl->setCurrentBlock("user_bl");
1225  foreach ($item["value"] as $user) {
1226  $ptpl->setVariable("USER", $user);
1227  $ptpl->parseCurrentBlock();
1228  }
1229 
1230  $ptpl->setCurrentBlock("item_bl");
1231  $ptpl->setVariable("TITLE", $item["title"]);
1232  $ptpl->parseCurrentBlock();
1233  }
1234 
1235  $f = $this->gui->ui()->factory();
1236  $r = $this->gui->ui()->renderer();
1237  $p = $f->panel()->standard(
1238  $this->lng->txt("exc_peer_review_overview_invalid_users"),
1239  $f->legacy($ptpl->get())
1240  );
1241 
1242  $panel = $r->render($p);
1243  }
1244 
1245  $tpl->setContent($tbl->getHTML() . $panel);
1246  }
1247 
1248  public function confirmResetPeerReviewObject(): void
1249  {
1250  $ilCtrl = $this->ctrl;
1251  $tpl = $this->tpl;
1252  $ilTabs = $this->tabs_gui;
1253 
1254  if (!$this->ass ||
1255  !$this->ass->getPeerReview()) {
1256  $this->returnToParentObject();
1257  }
1258 
1259  $ilTabs->clearTargets();
1260 
1261  $cgui = new ilConfirmationGUI();
1262  $cgui->setFormAction($ilCtrl->getFormAction($this));
1263  $cgui->setHeaderText(sprintf($this->lng->txt("exc_peer_review_reset_sure"), $this->ass->getTitle()));
1264  $cgui->setCancel($this->lng->txt("cancel"), "showPeerReviewOverview");
1265  $cgui->setConfirm($this->lng->txt("delete"), "resetPeerReview");
1266 
1267  $tpl->setContent($cgui->getHTML());
1268  }
1269 
1270  public function resetPeerReviewObject(): void
1271  {
1272  $ilCtrl = $this->ctrl;
1273 
1274  if (!$this->ass ||
1275  !$this->ass->getPeerReview()) {
1276  $this->returnToParentObject();
1277  }
1278 
1279  $peer_review = new ilExPeerReview($this->ass);
1280  $all_giver_ids = $peer_review->resetPeerReviews();
1281 
1282  if (is_array($all_giver_ids)) {
1283  // if peer review is valid for completion, we have to re-calculate all assignment members
1284  $exercise = new ilObjExercise($this->ass->getExerciseId(), false);
1285  if ($exercise->isCompletionBySubmissionEnabled() &&
1286  $this->ass->getPeerReviewValid() != ilExAssignment::PEER_REVIEW_VALID_NONE) {
1287  foreach ($all_giver_ids as $user_id) {
1288  $submission = new ilExSubmission($this->ass, $user_id);
1289  $pgui = new self($this->ass, $submission);
1290  $pgui->handlePeerReviewChange();
1291  }
1292  }
1293  }
1294 
1295  $this->tpl->setOnScreenMessage('success', $this->lng->txt("exc_peer_review_reset_done"), true);
1296  $ilCtrl->redirect($this, "showPeerReviewOverview");
1297  }
1298 }
static _replaceMediaObjectImageSrc(string $a_text, int $a_direction=0, string $nic='')
Replaces image source from mob image urls with the mob id or replaces mob id with the correct image s...
ILIAS Exercise InternalGUIService $gui
editPeerReviewItemObject(ilPropertyFormGUI $a_form=null)
static getOverviewContent(ilInfoScreenGUI $a_info, ilExSubmission $a_submission)
getFiles(array $a_file_ids=null, bool $a_only_valid=false, string $a_min_timestamp=null, bool $print_versions=false)
Get submission items (not only files)
exit
Definition: login.php:29
Class ilInfoScreenGUI.
Exercise assignment.
setCurrentBlock(string $blockname=self::DEFAULT_BLOCK)
Sets the template to the given block.
const IL_CAL_DATETIME
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
txt(string $a_topic, string $a_default_lang_fallback_mod="")
gets the text for a given topic if the topic is not in the list, the topic itself with "-" will be re...
getReceivedFeedbackPanel(array $a_peer_items, bool $a_by_peer=false)
ILIAS Exercise InternalDomainService $domain
setTitle(string $a_title, bool $hidden=false)
Sets title in standard template.
Class ChatMainBarProvider .
$valid
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
addProperty(string $a_name, string $a_value, string $a_link="")
add a property to current section
static formatDate(ilDateTime $date, bool $a_skip_day=false, bool $a_include_wd=false, bool $include_seconds=false)
parseCurrentBlock(string $blockname=self::DEFAULT_BLOCK)
Parses the given block.
ILIAS Notes Service $notes
getPeerReviewUploadPath(int $a_peer_id, int $a_giver_id, ?int $a_crit_id=null)
Get pear review upload path (each peer handled in a separate path)
static getInstanceByType(string $a_type)
const IL_CAL_UNIX
static deliverFileLegacy(string $a_file, ?string $a_filename=null, ?string $a_mime=null, ?bool $isInline=false, ?bool $removeAfterDelivery=false, ?bool $a_exit_after=true)
global $DIC
Definition: feed.php:28
getMessagesGUI(int $giver_id, int $peer_id)
Exercise peer review.
getSubPanel(string $title, array $props, ?ilMessageGUI $mess_gui=null)
Class ilObjExercise.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
get(string $part=self::DEFAULT_BLOCK)
Renders the given block and returns the html string.
static getNamePresentation( $a_user_id, bool $a_user_image=false, bool $a_profile_link=false, string $a_profile_back_link='', bool $a_force_first_lastname=false, bool $a_omit_login=false, bool $a_sortable=true, bool $a_return_data_array=false, $a_ctrl_path='ilpublicuserprofilegui')
Default behaviour is:
getLateSubmissionInfo(ilExSubmission $a_submission)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getInstanceByIds(int $a_ass_id, int $a_user_id=0)
$url
Definition: ltiregstart.php:35
getSubmissionContent(ilExSubmission $a_submission)
__construct(ilExAssignment $a_ass, ilExSubmission $a_submission=null)
getOnLoadCodeForAsynch()
Get js onload code for ajax calls.
buildSubmissionPropertiesAndActions(\ILIAS\Exercise\Assignment\PropertyAndActionBuilderUI $builder)
getPeerReviewReceiverPanel(ilExAssignment $ass, int $user_id, array $peer_data)
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...
observeMessageAction(int $giver_id, int $peer_id, int $note_id, string $action)
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Message GUI.
File System Explorer GUI class.
ilFSStorageExercise $fstorage
static _lookupType(int $id, bool $reference=false)
ILIAS Exercise Notification NotificationManager $notification
$service
Definition: ltiservices.php:43
setVariable(string $variable, $value='')
Sets the given variable to the given value.
ilGlobalPageTemplate $tpl
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
setContent(string $a_html)
Sets content for standard template.
initPeerReviewItemForm(int $a_peer_id)
setTableId(string $a_val)
$r
static getInstanceById(int $a_id)