ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilExerciseManagementGUI.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
16 {
20  protected $ctrl;
21 
25  protected $tabs_gui;
26 
30  protected $lng;
31 
35  protected $tpl;
36 
40  protected $ui_factory;
41 
45  protected $ui_renderer;
46 
50  protected $filter;
51 
55  protected $toolbar;
56 
57  protected $exercise; // [ilObjExercise]
58  protected $assignment; // [ilExAssignment]
59 
63  protected $task_factory;
64 
68  protected $log;
69 
73  protected $user;
74 
75  const VIEW_ASSIGNMENT = 1;
76  const VIEW_PARTICIPANT = 2;
77  const VIEW_GRADES = 3;
78 
79  const FEEDBACK_ONLY_SUBMISSION = "submission_only";
80  const FEEDBACK_FULL_SUBMISSION = "submission_feedback";
81 
82  const GRADE_NOT_GRADED = "notgraded";
83  const GRADE_PASSED = "passed";
84  const GRADE_FAILED = "failed";
85 
89  protected $service;
90 
98  {
99  global $DIC;
100 
101  $this->ui_factory = $DIC->ui()->factory();
102  $this->ui_renderer = $DIC->ui()->renderer();
103  $this->user = $DIC->user();
104  $this->toolbar = $DIC->toolbar();
105  $this->log = ilLoggerFactory::getLogger("exc");
106 
107  $this->ctrl = $DIC->ctrl();
108  $this->tabs_gui = $DIC->tabs();
109  $this->lng = $DIC->language();
110  $this->tpl = $DIC["tpl"];
111 
112  $this->task_factory = $DIC->backgroundTasks()->taskFactory();
113 
114  $request = $DIC->exercise()->internal()->request();
115 
116  $this->service = $service;
117 
118  $this->exercise = $request->getRequestedExercise();
119  if ($a_ass) {
120  $this->assignment = $a_ass;
121  $this->ass_id = $this->assignment->getId();
122  }
123 
124  $this->ctrl->saveParameter($this, array("vw", "member_id"));
125  }
126 
127  public function executeCommand()
128  {
130  $lng = $this->lng;
131  $ilTabs = $this->tabs_gui;
132 
133  $class = $ilCtrl->getNextClass($this);
134  //$cmd = $ilCtrl->getCmd("listPublicSubmissions");
135 
136  switch ($class) {
137  case "ilfilesystemgui":
138  $ilTabs->clearTargets();
139  $ilTabs->setBackTarget(
140  $lng->txt("back"),
141  $ilCtrl->getLinkTarget($this, $this->getViewBack())
142  );
143 
144  ilUtil::sendInfo($lng->txt("exc_fb_tutor_info"));
145 
146  $fstorage = new ilFSStorageExercise($this->exercise->getId(), $this->assignment->getId());
147  $fstorage->create();
148 
149  $submission = new ilExSubmission($this->assignment, (int) $_GET["member_id"]);
150  $feedback_id = $submission->getFeedbackId();
151  $noti_rec_ids = $submission->getUserIds();
152 
153  $fs_title = array();
154  foreach ($noti_rec_ids as $rec_id) {
155  $fs_title[] = ilUserUtil::getNamePresentation($rec_id, false, false, "", true);
156  }
157  $fs_title = implode(" / ", $fs_title);
158 
159  $fs_gui = new ilFileSystemGUI($fstorage->getFeedbackPath($feedback_id));
160  $fs_gui->setTableId("excfbfil" . $this->assignment->getId() . "_" . $feedback_id);
161  $fs_gui->setAllowDirectories(false);
162  $fs_gui->setTitle($lng->txt("exc_fb_files") . " - " .
163  $this->assignment->getTitle() . " - " .
164  $fs_title);
165  $pcommand = $fs_gui->getLastPerformedCommand();
166  if (is_array($pcommand) && $pcommand["cmd"] == "create_file") {
167  foreach ($noti_rec_ids as $user_id) {
168  $member_status = $this->assignment->getMemberStatus($user_id);
169  $member_status->setFeedback(true);
170  $member_status->update();
171  }
172 
173  $this->exercise->sendFeedbackFileNotification(
174  $pcommand["name"],
175  $noti_rec_ids,
176  $this->assignment->getId()
177  );
178  }
179  $this->ctrl->forwardCommand($fs_gui);
180  break;
181 
182  case 'ilrepositorysearchgui':
183  $rep_search = new ilRepositorySearchGUI();
184  $ref_id = $this->exercise->getRefId();
185  $rep_search->addUserAccessFilterCallable(function ($a_user_ids) use ($ref_id) {
186  return $GLOBALS['DIC']->access()->filterUserIdsByRbacOrPositionOfCurrentUser(
187  'edit_submissions_grades',
188  'edit_submissions_grades',
189  $ref_id,
190  $a_user_ids
191  );
192  });
193  $rep_search->setTitle($this->lng->txt("exc_add_participant"));
194  $rep_search->setCallback($this, 'addMembersObject');
195 
196  // Set tabs
197  $this->addSubTabs("assignment");
198  $this->ctrl->setReturn($this, 'members');
199 
200  $this->ctrl->forwardCommand($rep_search);
201  break;
202 
203  case "ilexsubmissionteamgui":
204  $gui = new ilExSubmissionTeamGUI($this->exercise, $this->initSubmission());
205  $ilCtrl->forwardCommand($gui);
206  break;
207 
208  case "ilexsubmissionfilegui":
209  $gui = new ilExSubmissionFileGUI($this->exercise, $this->initSubmission());
210  $ilCtrl->forwardCommand($gui);
211  break;
212 
213  case "ilexsubmissiontextgui":
214  $ilCtrl->saveParameter($this, array("part_id"));
215  $gui = new ilExSubmissionTextGUI($this->exercise, $this->initSubmission());
216  $ilCtrl->forwardCommand($gui);
217  break;
218 
219  case "ilexpeerreviewgui":
220  $gui = new ilExPeerReviewGUI($this->assignment, $this->initSubmission());
221  $ilCtrl->forwardCommand($gui);
222  break;
223 
224  default:
225  $cmd = $ilCtrl->getCmd();
226  switch ($cmd) {
227  case 'downloadSubmissions':
228  $cmd = $ilCtrl->getCmd("downloadSubmissions");
229  break;
230  default:
231  $cmd = $ilCtrl->getCmd("listPublicSubmissions");
232  break;
233  }
234  $this->{$cmd . "Object"}();
235  break;
236  }
237  }
238 
239  protected function getViewBack()
240  {
241  switch ($_REQUEST["vw"]) {
242  case self::VIEW_PARTICIPANT:
243  $back_cmd = "showParticipant";
244  break;
245 
246  case self::VIEW_GRADES:
247  $back_cmd = "showGradesOverview";
248  break;
249 
250  default:
251  // case self::VIEW_ASSIGNMENT:
252  $back_cmd = "members";
253  break;
254  }
255  return $back_cmd;
256  }
257 
258  protected function initSubmission()
259  {
260  $back_cmd = $this->getViewBack();
261  $this->ctrl->setReturn($this, $back_cmd);
262 
263  $this->tabs_gui->clearTargets();
264  $this->tabs_gui->setBackTarget(
265  $this->lng->txt("back"),
266  $this->ctrl->getLinkTarget($this, $back_cmd)
267  );
268 
269  return new ilExSubmission($this->assignment, $_REQUEST["member_id"], null, true);
270  }
271 
277  public function addSubTabs($a_activate)
278  {
279  $ilTabs = $this->tabs_gui;
280  $lng = $this->lng;
282 
283  $ass_id = $_GET["ass_id"];
284  $part_id = $_GET["part_id"];
285 
286  $ilCtrl->setParameter($this, "vw", "");
287  $ilCtrl->setParameter($this, "member_id", "");
288  $ilCtrl->setParameter($this, "ass_id", "");
289  $ilCtrl->setParameter($this, "part_id", "");
290 
291  $ilTabs->addSubTab(
292  "assignment",
293  $lng->txt("exc_assignment_view"),
294  $ilCtrl->getLinkTarget($this, "members")
295  );
296  $ilTabs->addSubTab(
297  "participant",
298  $lng->txt("exc_participant_view"),
299  $ilCtrl->getLinkTarget($this, "showParticipant")
300  );
301  $ilTabs->addSubTab(
302  "grades",
303  $lng->txt("exc_grades_overview"),
304  $ilCtrl->getLinkTarget($this, "showGradesOverview")
305  );
306  $ilTabs->activateSubTab($a_activate);
307 
308  $ilCtrl->setParameter($this, "ass_id", $ass_id);
309  $ilCtrl->setParameter($this, "part_id", $part_id);
310  }
311 
312  public function waitingDownloadObject()
313  {
314  $lng = $this->lng;
316 
317  $ilCtrl->setParameterByClass("ilExSubmissionFileGUI", "member_id", (int) $_GET["member_id"]);
318  $url = $ilCtrl->getLinkTargetByClass(array("ilRepositoryGUI", "ilExerciseHandlerGUI", "ilObjExerciseGUI", "ilExerciseManagementGUI", "ilExSubmissionFileGUI"), "downloadNewReturned");
319  $js_url = $ilCtrl->getLinkTargetByClass(array("ilRepositoryGUI", "ilExerciseHandlerGUI", "ilObjExerciseGUI", "ilExerciseManagementGUI", "ilExSubmissionFileGUI"), "downloadNewReturned", "", "", false);
320  ilUtil::sendInfo($lng->txt("exc_wait_for_files") . "<a href='$url'> " . $lng->txt('exc_download_files') . "</a><script>window.location.href ='" . $js_url . "';</script>");
321  $this->membersObject();
322  }
323 
327  public function membersObject()
328  {
329  $tpl = $this->tpl;
330  $ilToolbar = $this->toolbar;
332  $lng = $this->lng;
333 
334  $this->addSubTabs("assignment");
335 
336  // assignment selection
337  $ass = ilExAssignment::getInstancesByExercise($this->exercise->getId());
338 
339  if (!$this->assignment) {
340  $this->assignment = current($ass);
341  }
342 
343  reset($ass);
344  if (count($ass) > 1) {
345  $options = array();
346  foreach ($ass as $a) {
347  $options[$a->getId()] = $a->getTitle();
348  }
349  $si = new ilSelectInputGUI($this->lng->txt(""), "ass_id");
350  $si->setOptions($options);
351  $si->setValue($this->assignment->getId());
352  $ilToolbar->addStickyItem($si);
353 
354  $button = ilSubmitButton::getInstance();
355  $button->setCaption("exc_select_ass");
356  $button->setCommand("selectAssignment");
357  $ilToolbar->addStickyItem($button);
358 
359  $ilToolbar->addSeparator();
360  }
361  // #16165 - if only 1 assignment dropdown is not displayed;
362  elseif ($this->assignment) {
363  $ilCtrl->setParameter($this, "ass_id", $this->assignment->getId());
364  }
365 
366  // add member
367  // is only shown if 'edit_submissions_grades' is granted by rbac. positions
368  // access is not sufficient.
369  $has_rbac_access = $GLOBALS['DIC']->access()->checkAccess(
370  'edit_submissions_grades',
371  '',
372  $this->exercise->getRefId()
373  );
374  if ($has_rbac_access) {
376  $this,
377  $ilToolbar,
378  array(
379  'auto_complete_name' => $lng->txt('user'),
380  'submit_name' => $lng->txt('add'),
381  'add_search' => true,
382  'add_from_container' => $this->exercise->getRefId()
383  )
384  );
385  }
386 
387  // #16168 - no assignments
388  if (count($ass) > 0) {
389  if ($has_rbac_access) {
390  $ilToolbar->addSeparator();
391  }
392 
393  // we do not want the ilRepositorySearchGUI form action
394  $ilToolbar->setFormAction($ilCtrl->getFormAction($this));
395 
396  $ilCtrl->setParameter($this, "ass_id", $this->assignment->getId());
397 
398  if ($this->assignment->getType() == ilExAssignment::TYPE_UPLOAD_TEAM) {
399  if (ilExAssignmentTeam::getAdoptableGroups($this->exercise->getRefId())) {
400  $ilToolbar->addButton(
401  $this->lng->txt("exc_adopt_group_teams"),
402  $this->ctrl->getLinkTarget($this, "adoptTeamsFromGroup")
403  );
404 
405  $ilToolbar->addSeparator();
406  }
407  } elseif ($this->exercise->hasTutorFeedbackFile()) {
408  if (!$this->assignment->getAssignmentType()->usesTeams()) {
409  // multi-feedback
410  $ilToolbar->addButton(
411  $this->lng->txt("exc_multi_feedback"),
412  $this->ctrl->getLinkTarget($this, "showMultiFeedback")
413  );
414 
415  $ilToolbar->addSeparator();
416  }
417  }
418 
419  $submission_repository = new ilExcSubmissionRepository($this->db);
420 
421  if ($submission_repository->hasSubmissions($this->assignment->getId())) {
422  $ass_type = $this->assignment->getType();
423  //todo change addFormButton for addButtonInstance
424  if ($ass_type == ilExAssignment::TYPE_TEXT) {
425  $ilToolbar->addFormButton($lng->txt("exc_list_text_assignment"), "listTextAssignment");
426  }
427  $ilToolbar->addFormButton($lng->txt("download_all_returned_files"), "downloadSubmissions");
428  }
429  $this->ctrl->setParameter($this, "vw", self::VIEW_ASSIGNMENT);
430 
431  $exc_tab = new ilExerciseMemberTableGUI($this, "members", $this->exercise, $this->assignment->getId());
432  $tpl->setContent(
433  $exc_tab->getHTML() .
435  );
436  } else {
437  ilUtil::sendInfo($lng->txt("exc_no_assignments_available"));
438  }
439 
440  $ilCtrl->setParameter($this, "ass_id", "");
441 
442  return;
443  }
444 
445  public function downloadSubmissionsObject()
446  {
447  $participant_id = $_REQUEST['part_id'];
448 
449  $download_task = new ilDownloadSubmissionsBackgroundTask(
450  (int) $GLOBALS['DIC']->user()->getId(),
451  (int) $this->exercise->getRefId(),
452  (int) $this->exercise->getId(),
453  (int) $this->ass_id,
454  (int) $participant_id
455  );
456 
457  if ($download_task->run()) {
458  ilUtil::sendSuccess($this->lng->txt('exc_down_files_started_bg'), true);
459  }
460 
461  if ($this->assignment) {
462  $this->ctrl->redirect($this, "members");
463  } else {
464  $this->ctrl->redirect($this, "showParticipant");
465  }
466  }
467 
468  public function membersApplyObject()
469  {
470  $this->saveStatusAllObject(null, false);
471  $exc_tab = new ilExerciseMemberTableGUI($this, "members", $this->exercise, $this->assignment->getId());
472  $exc_tab->resetOffset();
473  $exc_tab->writeFilterToSession();
474 
475  $this->membersObject();
476  }
477 
478  public function membersResetObject()
479  {
480  $exc_tab = new ilExerciseMemberTableGUI($this, "members", $this->exercise, $this->assignment->getId());
481  $exc_tab->resetOffset();
482  $exc_tab->resetFilter();
483 
484  $this->membersObject();
485  }
486 
490  public function saveGradesObject()
491  {
493  $lng = $this->lng;
494 
495  if (is_array($_POST["lcomment"])) {
496  foreach ($_POST["lcomment"] as $k => $v) {
497  $marks_obj = new ilLPMarks($this->exercise->getId(), (int) $k);
498  $marks_obj->setComment(ilUtil::stripSlashes($v));
499  $marks_obj->setMark(ilUtil::stripSlashes($_POST["mark"][$k]));
500  $marks_obj->update();
501  }
502  }
503  ilUtil::sendSuccess($lng->txt("exc_msg_saved_grades"), true);
504  $ilCtrl->redirect($this, "showGradesOverview");
505  }
506 
507 
508  // TEXT ASSIGNMENT ?!
509 
513  public function listTextAssignmentObject()
514  {
515  $this->initFilter();
516 
517  $this->setBackToMembers();
518 
519  $button_print = $this->ui_factory->button()->standard($this->lng->txt('print'), "#")
520  ->withOnLoadCode(function ($id) {
521  return "$('#{$id}').click(function() { window.print(); return false; });";
522  });
523  $this->toolbar->addSeparator();
524  $this->toolbar->addComponent($button_print);
525 
526  $group_panels_tpl = new ilTemplate("tpl.exc_group_report_panels.html", true, true, "Modules/Exercise");
527  $group_panels_tpl->setVariable('TITLE', $this->lng->txt("exc_list_text_assignment") . ": " . $this->assignment->getTitle());
528 
529  $report_html = "";
530  $total_reports = 0;
531 
532  $members = ilExSubmission::getAssignmentParticipants($this->exercise->getId(), $this->ass_id);
533  $members_filter = new ilExerciseMembersFilter($this->exercise->getRefId(), $members, $this->user->getId());
534  $members = $members_filter->filterParticipantsByAccess();
535 
536  foreach (ilExSubmission::getAssignmentFilesByUsers($this->exercise->getId(), $this->assignment->getId(), $members) as $file) {
537  if (trim($file["atext"]) && ilObjUser::_exists($file["user_id"])) {
538  $feedback_data = $this->collectFeedbackDataFromPeer($file);
539  $submission_data = $this->assignment->getExerciseMemberAssignmentData($file["user_id"], $this->filter["status"]);
540 
541  if (is_array($submission_data)) {
542  $data = array_merge($feedback_data, $submission_data);
543  $report_html .= $this->getReportPanel($data);
544  $total_reports++;
545  }
546  }
547  }
548  if ($total_reports == 0) {
549  $mtpl = new ilTemplate("tpl.message.html", true, true, "Services/Utilities");
550  $mtpl->setCurrentBlock("info_message");
551  $mtpl->setVariable("TEXT", $this->lng->txt("fiter_no_results"));
552  $mtpl->parseCurrentBlock();
553  $report_html .= $mtpl->get();
554  }
555 
556  $group_panels_tpl->setVariable('CONTENT', $report_html);
557  $this->tpl->setContent($group_panels_tpl->get());
558  }
559 
566  {
567  $this->setBackToMembers();
568 
569  $group_panels_tpl = new ilTemplate("tpl.exc_group_report_panels.html", true, true, "Modules/Exercise");
570  $group_panels_tpl->setVariable('TITLE', $this->lng->txt("exc_compare_selected_submissions"));
571 
572  $report_html = "";
573  //participant ids selected via checkboxes
574  $participants = array_keys($this->getMultiActionUserIds());
575 
576  foreach ($participants as $participant_id) {
577  $submission = new ilExSubmission($this->assignment, $participant_id);
578 
579  //submission data array
580  $file = reset($submission->getFiles());
581 
582  if (!$file) {
583  $file = [
584  "user_id" => $participant_id,
585  "ts" => null,
586  "atext" => null
587  ];
588  }
589 
590  $feedback_data = $this->collectFeedbackDataFromPeer($file);
591 
592  $submission_data = $this->assignment->getExerciseMemberAssignmentData($file["user_id"], $this->filter["status"]);
593 
594  if (is_array($submission_data)) {
595  $data = array_merge($feedback_data, $submission_data);
596  $report_html .= $this->getReportPanel($data);
597  $total_reports++;
598  }
599  }
600 
601  $group_panels_tpl->setVariable('CONTENT', $report_html);
602  $this->tpl->setContent($group_panels_tpl->get());
603  }
604 
605  public function getReportPanel($a_data)
606  {
607  $modal = $this->getEvaluationModal($a_data);
608 
609  $this->ctrl->setParameter($this, "member_id", $a_data['uid']);
610  $actions = array(
611  $this->ui_factory->button()->shy($this->lng->txt("grade_evaluate"), "#")->withOnClick($modal->getShowSignal())
612  );
613  if ($this->exercise->hasTutorFeedbackMail()) {
614  $actions[] = $this->ui_factory->button()->shy(
615  $this->lng->txt("exc_tbl_action_feedback_mail"),
616  $this->ctrl->getLinkTarget($this, "redirectFeedbackMail")
617  );
618  }
619  if ($this->exercise->hasTutorFeedbackFile()) {
620  $actions[] = $this->ui_factory->button()->shy(
621  $this->lng->txt("exc_tbl_action_feedback_file"),
622  $this->ctrl->getLinkTargetByClass("ilFileSystemGUI", "listFiles")
623  );
624  }
625 
626  $this->ctrl->setParameter($this, "member_id", "");
627 
628  $actions_dropdown = $this->ui_factory->dropdown()->standard($actions);
629 
630  if ($a_data['status'] == self::GRADE_NOT_GRADED) {
631  $str_status_key = $this->lng->txt('exc_tbl_status');
632  $str_status_value = $this->lng->txt('not_yet');
633  } else {
634  $str_status_key = $this->lng->txt('exc_tbl_status_time');
635  $str_status_value = ilDatePresentation::formatDate(new ilDateTime($a_data["status_time"], IL_CAL_DATETIME));
636  }
637 
638  $str_mark_key = $this->lng->txt("exc_tbl_mark");
639  $str_mark_value = $this->lng->txt('not_yet');
640 
641  if (($a_data['mark'] != "")) {
642  $str_mark_value = $a_data['mark'];
643  }
644 
645  if ($a_data['feedback_time']) {
646  $str_evaluation_key = $this->lng->txt('exc_tbl_feedback_time');
647  $str_evaluation_value = ilDatePresentation::formatDate(new ilDateTime($a_data["feedback_time"], IL_CAL_DATETIME));
648  } else {
649  $str_evaluation_key = $this->lng->txt('exc_settings_feedback');
650  $str_evaluation_value = $this->lng->txt('not_yet');
651  }
652 
653  $card_content = array(
654  $this->lng->txt("exc_tbl_submission_date") => ilDatePresentation::formatDate(new ilDateTime($a_data["udate"], IL_CAL_DATETIME)),
655  $str_status_key => $str_status_value,
656  $str_mark_key => $str_mark_value,
657  $str_evaluation_key => $str_evaluation_value,
658  $this->lng->txt('feedback_given') => $a_data['fb_given'],
659  $this->lng->txt('feedback_received') => $a_data['fb_received']
660  );
661  $card_tpl = new ilTemplate("tpl.exc_report_details_card.html", true, true, "Modules/Exercise");
662  foreach ($card_content as $key => $value) {
663  $card_tpl->setCurrentBlock("assingment_card");
664  $card_tpl->setVariable("ROW_KEY", $key);
665  $card_tpl->setVariable("ROW_VALUE", $value);
666  $card_tpl->parseCurrentBlock();
667  }
668 
669  $main_panel = $this->ui_factory->panel()->sub($a_data['uname'], $this->ui_factory->legacy($a_data['utext']))
670  ->withCard($this->ui_factory->card()->standard($this->lng->txt('text_assignment'))->withSections(array($this->ui_factory->legacy($card_tpl->get()))))->withActions($actions_dropdown);
671 
672  $feedback_tpl = new ilTemplate("tpl.exc_report_feedback.html", true, true, "Modules/Exercise");
673  //if no feedback filter the feedback is displayed. Can be list submissions or compare submissions.
674  if (array_key_exists("peer", $a_data) && ($this->filter["feedback"] == self::FEEDBACK_FULL_SUBMISSION) || $this->filter["feedback"] == "") {
675  $feedback_tpl->setCurrentBlock("feedback");
676  foreach ($a_data["peer"] as $peer_id) {
677  if (ilObject::_lookupType($peer_id) == "usr") {
678  $user = new ilObjUser($peer_id);
679  $peer_name = $user->getFirstname() . " " . $user->getLastname();
680  } else {
681  $peer_name = $this->lng->txt("exc_deleted_user");
682  }
683 
684  $feedback_tpl->setCurrentBlock("peer_feedback");
685  $feedback_tpl->setVariable("PEER_NAME", $peer_name);
686 
687  $submission = new ilExSubmission($this->assignment, $a_data["uid"]);
688  $values = $submission->getPeerReview()->getPeerReviewValues($peer_id, $a_data["uid"]);
689 
690  $review_html = "";
691  foreach ($this->assignment->getPeerReviewCriteriaCatalogueItems() as $crit) {
692  $crit_id = $crit->getId()
693  ? $crit->getId()
694  : $crit->getType();
695  $crit->setPeerReviewContext($this->assignment, $peer_id, $a_data["uid"]);
696 
697  $review_html .=
698  '<div class="ilBlockPropertyCaption">' . $crit->getTitle() . '</div>' .
699  '<div style="margin:2px 0;">' . $crit->getHTML($values[$crit_id]) . '</div>';
700  }
701  $feedback_tpl->setVariable("PEER_FEEDBACK", $review_html);
702  $feedback_tpl->parseCurrentBlock();
703  }
704  $feedback_tpl->parseCurrentBlock();
705  }
706  $feedback_tpl->setVariable("GRADE", $this->lng->txt('grade') . ": " . $this->lng->txt('exc_' . $a_data['status']));
707  $feedback_tpl->setVariable("COMMENT", $this->lng->txt('exc_comment') . "<br>" . $a_data['comment']);
708 
709  $feedback_panel = $this->ui_factory->panel()->sub("", $this->ui_factory->legacy($feedback_tpl->get()));
710 
711  $report = $this->ui_factory->panel()->report("", array($main_panel, $feedback_panel));
712 
713  return $this->ui_renderer->render([$modal,$report]);
714  }
715 
716  public function getEvaluationModal($a_data)
717  {
718  $modal_tpl = new ilTemplate("tpl.exc_report_evaluation_modal.html", true, true, "Modules/Exercise");
719  $modal_tpl->setVariable("USER_NAME", $a_data['uname']);
720 
721  $form = new ilPropertyFormGUI();
722  $form->setFormAction($this->ctrl->getFormAction($this, "saveEvaluationFromModal"));
723  $form->setId(uniqid('form'));
724 
725  //Grade
726  $options = array(
727  self::GRADE_NOT_GRADED => $this->lng->txt("exc_notgraded"),
728  self::GRADE_PASSED => $this->lng->txt("exc_passed"),
729  self::GRADE_FAILED => $this->lng->txt("exc_failed")
730  );
731  $si = new ilSelectInputGUI($this->lng->txt("exc_tbl_status"), "grade");
732  $si->setOptions($options);
733  $si->setValue($a_data['status']);
734  $form->addItem($si);
735 
736  //Mark
737  $mark_input = new ilTextInputGUI($this->lng->txt("exc_tbl_mark"), "mark");
738  $mark_input->setValue($a_data['mark']);
739  $mark_input->setMaxLength(32);
740  $mark_input->setSize(4);
741  $form->addItem($mark_input);
742 
743  $item = new ilHiddenInputGUI('mem_id');
744  $item->setValue($a_data['uid']);
745  $form->addItem($item);
746 
747  //TODO: CHECK ilias string utils. ilUtil shortenText with net blank.
748  if ($this->exercise->hasTutorFeedbackText()) {
749  $max_chars = 500;
750 
751  $u_text = strip_tags($a_data["utext"]); //otherwise will get open P
752  $text = $u_text;
753  //show more
754  if (strlen($u_text) > $max_chars) {
755  $text = "<input type='checkbox' class='read-more-state' id='post-1' />";
756  $text .= "<div class='read-more-wrap'>";
757  $text .= mb_substr($u_text, 0, $max_chars);
758  $text .= "<span class='read-more-target'>";
759  $text .= mb_substr($u_text, $max_chars);
760  $text .= "</span></div>";
761  $text .= "<label for='post-1' class='read-more-trigger'></label>";
762  }
763  $modal_tpl->setVariable("USER_TEXT", $text);
764 
765  $ta = new ilTextAreaInputGUI($this->lng->txt("exc_comment"), 'comment');
766  $ta->setInfo($this->lng->txt("exc_comment_for_learner_info"));
767  $ta->setValue($a_data['comment']);
768  $ta->setRows(10);
769  $form->addItem($ta);
770  }
771 
772  $modal_tpl->setVariable("FORM", $form->getHTML());
773 
774  $form_id = 'form_' . $form->getId();
775  $submit_btn = $this->ui_factory->button()->primary($this->lng->txt("save"), '#')
776  ->withOnLoadCode(function ($id) use ($form_id) {
777  return "$('#{$id}').click(function() { $('#{$form_id}').submit(); return false; });";
778  });
779 
780  return $this->ui_factory->modal()->roundtrip(strtoupper($this->lng->txt("grade_evaluate")), $this->ui_factory->legacy($modal_tpl->get()))->withActionButtons([$submit_btn]);
781  }
782 
787  {
788  $comment = trim($_POST['comment']);
789  $user_id = (int) $_POST['mem_id'];
790  $grade = trim($_POST["grade"]);
791  $mark = trim($_POST['mark']);
792 
793  if ($this->assignment->getId() && $user_id) {
794  $member_status = $this->assignment->getMemberStatus($user_id);
795  $member_status->setComment(ilUtil::stripSlashes($comment));
796  $member_status->setStatus($grade);
797  $member_status->setMark($mark);
798  if ($comment != "") {
799  $member_status->setFeedback(true);
800  }
801  $member_status->update();
802  }
803  ilUtil::sendSuccess($this->lng->txt("exc_status_saved"), true);
804  $this->ctrl->redirect($this, "listTextAssignment");
805  }
806 
811  {
812  if (!strlen(trim($_POST['user_login']))) {
813  ilUtil::sendFailure($this->lng->txt('msg_no_search_string'));
814  $this->membersObject();
815  return false;
816  }
817  $users = explode(',', $_POST['user_login']);
818 
819  $user_ids = array();
820  foreach ($users as $user) {
821  $user_id = ilObjUser::_lookupId($user);
822 
823  if (!$user_id) {
824  ilUtil::sendFailure($this->lng->txt('user_not_known'));
825  return $this->membersObject();
826  }
827 
828  $user_ids[] = $user_id;
829  }
830 
831  if (!$this->addMembersObject($user_ids)) {
832  $this->membersObject();
833  return false;
834  }
835  return true;
836  }
837 
841  public function addMembersObject($a_user_ids = array())
842  {
843  if (!count($a_user_ids)) {
844  ilUtil::sendFailure($this->lng->txt("no_checkbox"));
845  return false;
846  }
847 
848  if (!$this->exercise->members_obj->assignMembers($a_user_ids)) {
849  ilUtil::sendFailure($this->lng->txt("exc_members_already_assigned"));
850  return false;
851  } else {
852  /* #16921
853  // #9946 - create team for new user(s) for each team upload assignment
854  foreach(ilExAssignment::getInstancesByExercise($this->exercise->getId()) as $ass)
855  {
856  if($ass->hasTeam())
857  {
858  foreach($a_user_ids as $user_id)
859  {
860  // #15915
861  ilExAssignmentTeam::getTeamId($ass->getId(), $user_id, true);
862  }
863  }
864  }
865  */
866 
867  ilUtil::sendSuccess($this->lng->txt("exc_members_assigned"), true);
868  }
869 
870  $this->ctrl->redirect($this, "members");
871  return true;
872  }
873 
874 
878  public function selectAssignmentObject()
879  {
880  $_GET["ass_id"] = ilUtil::stripSlashes($_POST["ass_id"]);
881  $this->membersObject();
882  }
883 
887  public function showParticipantObject()
888  {
889  $tpl = $this->tpl;
890  $ilToolbar = $this->toolbar;
892  $lng = $this->lng;
893 
894  $this->addSubTabs("participant");
895  $this->ctrl->setParameter($this, "ass_id", "");
896 
897  // participant selection
898  $ass = ilExAssignment::getAssignmentDataOfExercise($this->exercise->getId());
899  $members = $this->exercise->members_obj->getMembers();
900 
901  $members = $GLOBALS['DIC']->access()->filterUserIdsByRbacOrPositionOfCurrentUser(
902  'edit_submissions_grades',
903  'edit_submissions_grades',
904  $this->exercise->getRefId(),
905  $members
906  );
907 
908 
909  if (count($members) == 0) {
910  ilUtil::sendInfo($lng->txt("exc_no_participants"));
911  return;
912  }
913 
914  $mems = array();
915  foreach ($members as $mem_id) {
916  if (ilObject::_lookupType($mem_id) == "usr") {
917  $name = ilObjUser::_lookupName($mem_id);
918  if (trim($name["login"]) != "") { // #20073
919  $mems[$mem_id] = $name;
920  }
921  }
922  }
923 
924  $mems = ilUtil::sortArray($mems, "lastname", "asc", false, true);
925 
926  if ($_GET["part_id"] == "" && count($mems) > 0) {
927  $_GET["part_id"] = key($mems);
928  }
929 
930  $current_participant = $_GET["part_id"];
931 
932  reset($mems);
933  if (count($mems) > 1) {
934  $options = array();
935  foreach ($mems as $k => $m) {
936  $options[$k] =
937  $m["lastname"] . ", " . $m["firstname"] . " [" . $m["login"] . "]";
938  }
939  $si = new ilSelectInputGUI($this->lng->txt(""), "part_id");
940  $si->setOptions($options);
941  $si->setValue($current_participant);
942  $ilToolbar->addStickyItem($si);
943 
944  $button = ilSubmitButton::getInstance();
945  $button->setCaption("exc_select_part");
946  $button->setCommand("selectParticipant");
947  $ilToolbar->addStickyItem($button);
948  }
949 
950  if (count($mems) > 0) {
951  $this->ctrl->setParameter($this, "vw", self::VIEW_PARTICIPANT);
952  $this->ctrl->setParameter($this, "part_id", $current_participant);
953 
954  $ilToolbar->setFormAction($ilCtrl->getFormAction($this));
955  $ilToolbar->addFormButton($lng->txt("download_all_returned_files"), "downloadSubmissions");
956 
957  $part_tab = new ilExParticipantTableGUI(
958  $this,
959  "showParticipant",
960  $this->exercise,
961  $current_participant
962  );
963  $tpl->setContent($part_tab->getHTML() .
964  $this->initIndividualDeadlineModal());
965  } else {
966  ilUtil::sendInfo($this->lng->txt("exc_no_assignments_available"));
967  }
968  }
969 
970  public function showParticipantApplyObject()
971  {
972  $exc_tab = new ilExParticipantTableGUI($this, "showParticipant", $this->exercise, $_GET["part_id"]);
973  $exc_tab->resetOffset();
974  $exc_tab->writeFilterToSession();
975 
976  $this->showParticipantObject();
977  }
978 
979  public function showParticipantResetObject()
980  {
981  $exc_tab = new ilExParticipantTableGUI($this, "showParticipant", $this->exercise, $_GET["part_id"]);
982  $exc_tab->resetOffset();
983  $exc_tab->resetFilter();
984 
985  $this->showParticipantObject();
986  }
987 
991  public function selectParticipantObject()
992  {
993  $_GET["part_id"] = ilUtil::stripSlashes($_POST["part_id"]);
994  $this->showParticipantObject();
995  }
996 
1000  public function showGradesOverviewObject()
1001  {
1002  $tpl = $this->tpl;
1003  $ilToolbar = $this->toolbar;
1004  $ilCtrl = $this->ctrl;
1005  $lng = $this->lng;
1006 
1007  $this->addSubTabs("grades");
1008 
1009  $mem_obj = new ilExerciseMembers($this->exercise);
1010  $mems = $mem_obj->getMembers();
1011 
1012  $mems = $GLOBALS['DIC']->access()->filterUserIdsByRbacOrPositionOfCurrentUser(
1013  'edit_submissions_grades',
1014  'edit_submissions_grades',
1015  $this->exercise->getRefId(),
1016  $mems
1017  );
1018  if (count($mems) > 0) {
1019  $ilToolbar->addButton(
1020  $lng->txt("exc_export_excel"),
1021  $ilCtrl->getLinkTarget($this, "exportExcel")
1022  );
1023  }
1024 
1025  $this->ctrl->setParameter($this, "vw", self::VIEW_GRADES);
1026 
1027  $grades_tab = new ilExGradesTableGUI(
1028  $this,
1029  "showGradesOverview",
1030  $this->service,
1031  $mem_obj
1032  );
1033  $tpl->setContent($grades_tab->getHTML());
1034  }
1035 
1039  public function redirectFeedbackMailObject()
1040  {
1041  $members = array();
1042 
1043  if ($_GET["member_id"] != "") {
1044  $submission = new ilExSubmission($this->assignment, $_GET["member_id"]);
1045  $members = $submission->getUserIds();
1046  } elseif ($members = $this->getMultiActionUserIds()) {
1047  $members = array_keys($members);
1048  }
1049 
1050  if ($members) {
1051  $logins = array();
1052  foreach ($members as $user_id) {
1053  $member_status = $this->assignment->getMemberStatus($user_id);
1054  $member_status->setFeedback(true);
1055  $member_status->update();
1056 
1057  $logins[] = ilObjUser::_lookupLogin($user_id);
1058  }
1059  $logins = implode(",", $logins);
1060 
1061  // #16530 - see ilObjCourseGUI::createMailSignature
1062  $sig = chr(13) . chr(10) . chr(13) . chr(10);
1063  $sig .= $this->lng->txt('exc_mail_permanent_link');
1064  $sig .= chr(13) . chr(10) . chr(13) . chr(10);
1065  $sig .= ilLink::_getLink($this->exercise->getRefId());
1066  $sig = rawurlencode(base64_encode($sig));
1067 
1069  $this,
1070  $this->getViewBack(),
1071  array(),
1072  array(
1073  'type' => 'new',
1074  'rcp_to' => $logins,
1076  )
1077  ));
1078  }
1079  }
1080 
1084  public function downloadAllObject()
1085  {
1086  $members = array();
1087 
1088  foreach ($this->exercise->members_obj->getMembers() as $member_id) {
1089  $submission = new ilExSubmission($this->assignment, $member_id);
1090  $submission->updateTutorDownloadTime();
1091 
1092  // get member object (ilObjUser)
1093  if (ilObject::_exists($member_id)) {
1094  $storage_id = "";
1095  // adding file metadata
1096  foreach ($submission->getFiles() as $file) {
1097  if ($this->assignment->getAssignmentType()->isSubmissionAssignedToTeam()) {
1098  $storage_id = $file["team_id"];
1099  } else {
1100  $storage_id = $file["user_id"];
1101  }
1102 
1103  $members[$storage_id]["files"][$file["returned_id"]] = $file;
1104  }
1105  if ($this->assignment->getAssignmentType()->isSubmissionAssignedToTeam()) {
1106  $name = "Team " . $submission->getTeam()->getId();
1107  } else {
1108  $tmp_obj = ilObjectFactory::getInstanceByObjId($member_id);
1109  $name = $tmp_obj->getFirstname() . " " . $tmp_obj->getLastname();
1110  }
1111  if ($storage_id > 0) {
1112  $members[$storage_id]["name"] = $name;
1113  }
1114  unset($tmp_obj);
1115  }
1116  }
1117 
1118  ilExSubmission::downloadAllAssignmentFiles($this->assignment, $members);
1119  }
1120 
1121  protected function getMultiActionUserIds($a_keep_teams = false)
1122  {
1123  // multi-user
1124  if ($this->assignment) {
1125  if (!$_POST["member"]) {
1126  ilUtil::sendFailure($this->lng->txt("no_checkbox"), true);
1127  $this->ctrl->redirect($this, "members");
1128  }
1129 
1130  foreach (array_keys($_POST["member"]) as $user_id) {
1131  $submission = new ilExSubmission($this->assignment, $user_id);
1132  $tmembers = $submission->getUserIds();
1133  if (!(bool) $a_keep_teams) {
1134  foreach ($tmembers as $tuser_id) {
1135  $members[$tuser_id] = 1;
1136  }
1137  } else {
1138  if ($tmembers) {
1139  $members[] = $tmembers;
1140  } else {
1141  // no team yet
1142  $members[] = $user_id;
1143  }
1144  }
1145  }
1146  }
1147  // multi-ass
1148  else {
1149  if (!$_POST["ass"]) {
1150  ilUtil::sendFailure($this->lng->txt("no_checkbox"), true);
1151  $this->ctrl->redirect($this, "showParticipant");
1152  }
1153 
1154  $user_id = $_GET["part_id"];
1155 
1156  foreach (array_keys($_POST["ass"]) as $ass_id) {
1157  $submission = new ilExSubmission(new ilExAssignment($ass_id), $user_id);
1158  $tmembers = $submission->getUserIds();
1159  if (!(bool) $a_keep_teams) {
1160  foreach ($tmembers as $tuser_id) {
1161  $members[$ass_id][] = $tuser_id;
1162  }
1163  } else {
1164  if ($tmembers) {
1165  $members[$ass_id][] = $tmembers;
1166  } else {
1167  // no team yet
1168  $members[$ass_id][] = $user_id;
1169  }
1170  }
1171  }
1172  }
1173 
1174  return $members;
1175  }
1176 
1180  public function sendMembersObject()
1181  {
1182  $members = $this->getMultiActionUserIds();
1183 
1184  ilUtil::sendSuccess($this->lng->txt("exc_sent"), true);
1185  if ($this->assignment) {
1186  $this->exercise->sendAssignment($this->assignment, array_keys($members));
1187  $this->ctrl->redirect($this, "members");
1188  } else {
1189  foreach ($members as $ass_id => $users) {
1190  $this->exercise->sendAssignment(new ilExAssignment($ass_id), $users);
1191  }
1192  $this->ctrl->setParameter($this, "part_id", $_GET["part_id"]); // #17629
1193  $this->ctrl->redirect($this, "showParticipant");
1194  }
1195  }
1196 
1201  {
1202  $ilCtrl = $this->ctrl;
1203  $tpl = $this->tpl;
1204  $lng = $this->lng;
1205 
1206  $members = $this->getMultiActionUserIds();
1207 
1208  $cgui = new ilConfirmationGUI();
1209  $cgui->setFormAction($ilCtrl->getFormAction($this));
1210  $cgui->setHeaderText($lng->txt("exc_msg_sure_to_deassign_participant"));
1211  $cgui->setCancel($lng->txt("cancel"), "members");
1212  $cgui->setConfirm($lng->txt("remove"), "deassignMembers");
1213 
1214  foreach ($members as $k => $m) {
1215  $cgui->addItem(
1216  "member[$k]",
1217  $m,
1218  ilUserUtil::getNamePresentation((int) $k, false, false, "", true)
1219  );
1220  }
1221 
1222  $tpl->setContent($cgui->getHTML());
1223  }
1224 
1228  public function deassignMembersObject()
1229  {
1230  $ilCtrl = $this->ctrl;
1231  $lng = $this->lng;
1232 
1233  $members = $this->getMultiActionUserIds();
1234 
1235  foreach (array_keys($members) as $usr_id) {
1236  $this->exercise->members_obj->deassignMember((int) $usr_id);
1237  $this->removeUserSubmissionFilesFromWebDir((int) $usr_id);
1238  }
1239  ilUtil::sendSuccess($lng->txt("exc_msg_participants_removed"), true);
1240  $ilCtrl->redirect($this, "members");
1241  }
1242 
1243  public function removeUserSubmissionFilesFromWebDir(int $user_id) : void
1244  {
1245  $storage = new ilFSWebStorageExercise($this->exercise->getId(), $this->ass_id);
1246  $storage->deleteUserSubmissionDirectory($user_id);
1247  }
1248 
1249  public function saveCommentsObject()
1250  {
1251  if (!isset($_POST['comments_value'])) {
1252  return;
1253  }
1254 
1255  $this->exercise->members_obj->setNoticeForMember(
1256  $_GET["member_id"],
1257  ilUtil::stripSlashes($_POST["comments_value"])
1258  );
1259  ilUtil::sendSuccess($this->lng->txt("exc_members_comments_saved"));
1260  $this->membersObject();
1261  }
1262 
1266  public function saveStatusParticipantObject(array $a_selected = null)
1267  {
1268  $ilCtrl = $this->ctrl;
1269 
1270  $member_id = (int) $_GET["part_id"];
1271  $data = array();
1272  foreach (array_keys($_POST["id"]) as $ass_id) {
1273  if (is_array($a_selected) &&
1274  !in_array($ass_id, $a_selected)) {
1275  continue;
1276  }
1277 
1278  $data[$ass_id][$member_id] = array(
1279  "status" => ilUtil::stripSlashes($_POST["status"][$ass_id])
1280  );
1281 
1282  if (array_key_exists("mark", $_POST)) {
1283  $data[$ass_id][$member_id]["mark"] = ilUtil::stripSlashes($_POST["mark"][$ass_id]);
1284  }
1285  if (array_key_exists("notice", $_POST)) {
1286  $data[$ass_id][$member_id]["notice"] = ilUtil::stripSlashes($_POST["notice"][$ass_id]);
1287  }
1288  }
1289 
1290  $ilCtrl->setParameter($this, "part_id", $member_id); // #17629
1291  $this->saveStatus($data);
1292  }
1293 
1294 
1295  public function saveStatusAllObject(array $a_selected = null, $a_redirect = true)
1296  {
1297  $user_ids = (array) array_keys((array) $_POST['id']);
1298  $filtered_user_ids = $GLOBALS['DIC']->access()->filterUserIdsByRbacOrPositionOfCurrentUser(
1299  'edit_submissions_grades',
1300  'edit_submissions_grades',
1301  $this->exercise->getRefId(),
1302  $user_ids
1303  );
1304 
1305  $data = array();
1306  foreach ($filtered_user_ids as $user_id) {
1307  if (is_array($a_selected) &&
1308  !in_array($user_id, $a_selected)) {
1309  continue;
1310  }
1311 
1312  $data[-1][$user_id] = array(
1313  "status" => ilUtil::stripSlashes($_POST["status"][$user_id])
1314  );
1315 
1316  if (array_key_exists("mark", $_POST)) {
1317  $data[-1][$user_id]["mark"] = ilUtil::stripSlashes($_POST["mark"][$user_id]);
1318  }
1319  if (array_key_exists("notice", $_POST)) {
1320  $data[-1][$user_id]["notice"] = ilUtil::stripSlashes($_POST["notice"][$user_id]);
1321  }
1322  }
1323  $this->saveStatus($data, $a_redirect);
1324  }
1325 
1326  public function saveStatusSelectedObject()
1327  {
1328  $members = $this->getMultiActionUserIds();
1329 
1330  if ($this->assignment) {
1331  $this->saveStatusAllObject(array_keys($members));
1332  } else {
1333  $this->saveStatusParticipantObject(array_keys($members));
1334  }
1335  }
1336 
1340  protected function saveStatus(array $a_data, $a_redirect = true)
1341  {
1342  $ilCtrl = $this->ctrl;
1343 
1344  $saved_for = array();
1345  foreach ($a_data as $ass_id => $users) {
1346  $ass = ($ass_id < 0)
1347  ? $this->assignment
1348  : new ilExAssignment($ass_id);
1349  foreach ($users as $user_id => $values) {
1350  // this will add team members if available
1351  $submission = new ilExSubmission($ass, $user_id);
1352  foreach ($submission->getUserIds() as $sub_user_id) {
1353  $uname = ilObjUser::_lookupName($sub_user_id);
1354  $saved_for[$sub_user_id] = $uname["lastname"] . ", " . $uname["firstname"];
1355 
1356  $member_status = $ass->getMemberStatus($sub_user_id);
1357 
1358  // see bug #22566
1359  $status = $values["status"];
1360  if ($status == "") {
1361  $status = self::GRADE_NOT_GRADED;
1362  }
1363  $member_status->setStatus($status);
1364  if (array_key_exists("mark", $values)) {
1365  $member_status->setMark($values["mark"]);
1366  }
1367  if (array_key_exists("notice", $values)) {
1368  $member_status->setNotice($values["notice"]);
1369  }
1370  $member_status->update();
1371  }
1372  }
1373  }
1374 
1375  if (count($saved_for) > 0) {
1376  $save_for_str = "(" . implode(" - ", $saved_for) . ")";
1377  }
1378 
1379  if ($a_redirect) {
1380  ilUtil::sendSuccess($this->lng->txt("exc_status_saved") . " " . $save_for_str, true);
1381  $ilCtrl->redirect($this, $this->getViewBack());
1382  }
1383  }
1384 
1389  {
1390  $res = array("result" => false);
1391 
1392  if ($this->ctrl->isAsynch()) {
1393  $ass_id = (int) $_POST["ass_id"];
1394  $user_id = (int) $_POST["mem_id"];
1395  $comment = trim($_POST["comm"]);
1396 
1397  if ($ass_id && $user_id) {
1398  $submission = new ilExSubmission($this->assignment, $user_id);
1399  $user_ids = $submission->getUserIds();
1400 
1401  $all_members = new ilExerciseMembers($this->exercise);
1402  $all_members = $all_members->getMembers();
1403 
1404  $reci_ids = array();
1405  foreach ($user_ids as $user_id) {
1406  if (in_array($user_id, $all_members)) {
1407  $member_status = $this->assignment->getMemberStatus($user_id);
1408  $member_status->setComment(ilUtil::stripSlashes($comment));
1409  $member_status->setFeedback(true);
1410  $member_status->update();
1411 
1412  if (trim($comment)) {
1413  $reci_ids[] = $user_id;
1414  }
1415  }
1416  }
1417 
1418  if (sizeof($reci_ids)) {
1419  // send notification
1420  $this->exercise->sendFeedbackFileNotification(
1421  null,
1422  $reci_ids,
1423  $ass_id,
1424  true
1425  );
1426  }
1427 
1428  $res = array("result" => true, "snippet" => nl2br($comment));
1429  }
1430  }
1431 
1432  echo(json_encode($res));
1433  exit();
1434  }
1435 
1439  public function exportExcelObject()
1440  {
1441  $this->exercise->exportGradesExcel();
1442  exit;
1443  }
1444 
1445 
1446  //
1447  // TEAM
1448  //
1449 
1450  public function createTeamsObject()
1451  {
1452  $ilCtrl = $this->ctrl;
1453 
1454  $members = $this->getMultiActionUserIds(true);
1455 
1456  $new_members = array();
1457 
1458  foreach ($members as $group) {
1459  if (is_array($group)) {
1460  $new_members = array_merge($new_members, $group);
1461 
1462  $first_user = $group;
1463  $first_user = array_shift($first_user);
1464  $team = ilExAssignmentTeam::getInstanceByUserId($this->assignment->getId(), $first_user);
1465  foreach ($group as $user_id) {
1466  $team->removeTeamMember($user_id);
1467  }
1468  } else {
1469  $new_members[] = $group;
1470  }
1471  }
1472 
1473  if (sizeof($new_members)) {
1474  // see ilExSubmissionTeamGUI::addTeamMemberActionObject()
1475 
1476  $first_user = array_shift($new_members);
1477  $team = ilExAssignmentTeam::getInstanceByUserId($this->assignment->getId(), $first_user, true);
1478  if (sizeof($new_members)) {
1479  foreach ($new_members as $user_id) {
1480  $team->addTeamMember($user_id);
1481  }
1482  }
1483 
1484  // re-evaluate complete team, as some members might have had submitted
1485  $submission = new ilExSubmission($this->assignment, $first_user);
1486  $this->exercise->processExerciseStatus(
1487  $this->assignment,
1488  $team->getMembers(),
1489  $submission->hasSubmitted(),
1490  $submission->validatePeerReviews()
1491  );
1492  }
1493 
1494  ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
1495  $ilCtrl->redirect($this, "members");
1496  }
1497 
1498  public function dissolveTeamsObject()
1499  {
1500  $ilCtrl = $this->ctrl;
1501 
1502  $members = $this->getMultiActionUserIds(true);
1503 
1504  foreach ($members as $group) {
1505  // if single member - nothing to do
1506  if (is_array($group)) {
1507  // see ilExSubmissionTeamGUI::removeTeamMemberObject()
1508 
1509  $first_user = $group;
1510  $first_user = array_shift($first_user);
1511  $team = ilExAssignmentTeam::getInstanceByUserId($this->assignment->getId(), $first_user);
1512  foreach ($group as $user_id) {
1513  $team->removeTeamMember($user_id);
1514  }
1515 
1516  // reset ex team members, as any submission is not valid without team
1517  $this->exercise->processExerciseStatus(
1518  $this->assignment,
1519  $group,
1520  false
1521  );
1522  }
1523  }
1524 
1525  ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
1526  $ilCtrl->redirect($this, "members");
1527  }
1528 
1529  public function adoptTeamsFromGroupObject(ilPropertyFormGUI $a_form = null)
1530  {
1531  $ilCtrl = $this->ctrl;
1532  $ilTabs = $this->tabs_gui;
1533  $lng = $this->lng;
1534  $tpl = $this->tpl;
1535 
1536  $ilTabs->clearTargets();
1537  $ilTabs->setBackTarget(
1538  $lng->txt("back"),
1539  $ilCtrl->getLinkTarget($this, $this->getViewBack())
1540  );
1541 
1542  if (!$a_form) {
1543  $a_form = $this->initGroupForm();
1544  }
1545  $tpl->setContent($a_form->getHTML());
1546  }
1547 
1548  protected function initGroupForm()
1549  {
1550  $lng = $this->lng;
1551 
1552  $form = new ilPropertyFormGUI();
1553  $form->setTitle($lng->txt("exc_adopt_group_teams") . " - " . $this->assignment->getTitle());
1554  $form->setFormAction($this->ctrl->getFormAction($this, "createTeamsFromGroups"));
1555 
1556  $all_members = array();
1557  foreach (ilExAssignmentTeam::getGroupMembersMap($this->exercise->getRefId()) as $grp_id => $group) {
1558  if (sizeof($group["members"])) {
1559  $grp_team = new ilCheckboxGroupInputGUI($lng->txt("obj_grp") . " \"" . $group["title"] . "\"", "grpt_" . $grp_id);
1560  $grp_value = $options = array();
1561  foreach ($group["members"] as $user_id) {
1562  $user_name = ilUserUtil::getNamePresentation($user_id, false, false, "", true);
1563  $options[$user_id] = $user_name;
1564  if (!in_array($user_id, $all_members)) {
1565  $grp_value[] = $user_id;
1566  $all_members[] = $user_id;
1567  }
1568  }
1569  asort($options);
1570  foreach ($options as $user_id => $user_name) {
1571  $grp_team->addOption(new ilCheckboxOption($user_name, $user_id));
1572  }
1573  $grp_team->setValue($grp_value);
1574  $form->addItem($grp_team);
1575  } else {
1576  $grp_team = new ilNonEditableValueGUI($group["title"]);
1577  $grp_team->setValue($lng->txt("exc_adopt_group_teams_no_members"));
1578  $form->addItem($grp_team);
1579  }
1580  }
1581 
1582  if (sizeof($all_members)) {
1583  $form->addCommandButton("createTeamsFromGroups", $lng->txt("save"));
1584  }
1585  $form->addCommandButton("members", $lng->txt("cancel"));
1586 
1587  return $form;
1588  }
1589 
1591  {
1592  $lng = $this->lng;
1593 
1594  $form = $this->initGroupForm();
1595  if ($form->checkInput()) {
1596  $map = ilExAssignmentTeam::getGroupMembersMap($this->exercise->getRefId());
1597  $all_members = $teams = array();
1598  $valid = true;
1599  foreach (array_keys($map) as $grp_id) {
1600  $postvar = "grpt_" . $grp_id;
1601  $members = $_POST[$postvar];
1602  if (is_array($members)) {
1603  $teams[] = $members;
1604  $invalid_team_members = array();
1605 
1606  foreach ($members as $user_id) {
1607  if (!array_key_exists($user_id, $all_members)) {
1608  $all_members[$user_id] = $grp_id;
1609  } else {
1610  // user is selected in multiple groups
1611  $invalid_team_members[] = $user_id;
1612  }
1613  }
1614 
1615  if (sizeof($invalid_team_members)) {
1616  $valid = false;
1617 
1618  $alert = array();
1619  foreach ($invalid_team_members as $user_id) {
1620  $user_name = ilUserUtil::getNamePresentation($user_id, false, false, "", true);
1621  $grp_title = $map[$all_members[$user_id]]["title"];
1622  $alert[] = sprintf($lng->txt("exc_adopt_group_teams_conflict"), $user_name, $grp_title);
1623  }
1624  $input = $form->getItemByPostVar($postvar);
1625  $input->setAlert(implode("<br/>", $alert));
1626  }
1627  }
1628  }
1629  if ($valid) {
1630  if (sizeof($teams)) {
1631  $existing_users = array_keys(ilExAssignmentTeam::getAssignmentTeamMap($this->assignment->getId()));
1632 
1633  // create teams from group selections
1634  $sum = array("added" => 0, "blocked" => 0);
1635  foreach ($teams as $members) {
1636  foreach ($members as $user_id) {
1637  if (!$this->exercise->members_obj->isAssigned($user_id)) {
1638  $this->exercise->members_obj->assignMember($user_id);
1639  }
1640 
1641  if (!in_array($user_id, $existing_users)) {
1642  $sum["added"]++;
1643  } else {
1644  $sum["blocked"]++;
1645  }
1646  }
1647 
1648  $first = array_shift($members);
1649  $team = ilExAssignmentTeam::getInstanceByUserId($this->assignment->getId(), $first, true);
1650 
1651  // getTeamId() does NOT send notification
1652  // $team->sendNotification($this->exercise->getRefId(), $first, "add");
1653 
1654  if (sizeof($members)) {
1655  foreach ($members as $user_id) {
1656  $team->addTeamMember($user_id);
1657  }
1658  }
1659  }
1660 
1661  $mess = array();
1662  if ($sum["added"]) {
1663  $mess[] = sprintf($lng->txt("exc_adopt_group_teams_added"), $sum["added"]);
1664  }
1665  if ($sum["blocked"]) {
1666  $mess[] = sprintf($lng->txt("exc_adopt_group_teams_blocked"), $sum["blocked"]);
1667  }
1668  if ($sum["added"]) {
1669  ilUtil::sendSuccess(implode(" ", $mess), true);
1670  } else {
1671  ilUtil::sendFailure(implode(" ", $mess), true);
1672  }
1673  }
1674  $this->ctrl->redirect($this, "members");
1675  } else {
1676  ilUtil::sendFailure($lng->txt("form_input_not_valid"));
1677  }
1678  }
1679 
1680  $form->setValuesByPost();
1681  $this->adoptTeamsFromGroupObject($form);
1682  }
1683 
1684 
1688 
1689  public function initMultiFeedbackForm($a_ass_id)
1690  {
1691  $lng = $this->lng;
1692 
1693  $form = new ilPropertyFormGUI();
1694  $form->addCommandButton("uploadMultiFeedback", $lng->txt("upload"));
1695  $form->addCommandButton("members", $lng->txt("cancel"));
1696 
1697  // multi feedback file
1698  $fi = new ilFileInputGUI($lng->txt("exc_multi_feedback_file"), "mfzip");
1699  $fi->setSuffixes(array("zip"));
1700  $fi->setRequired(true);
1701  $form->addItem($fi);
1702 
1703  $form->setTitle(ilExAssignment::lookupTitle($a_ass_id));
1704  $form->setFormAction($this->ctrl->getFormAction($this, "uploadMultiFeedback"));
1705 
1706  return $form;
1707  }
1708 
1715  public function showMultiFeedbackObject(ilPropertyFormGUI $a_form = null)
1716  {
1717  $ilToolbar = $this->toolbar;
1718  $lng = $this->lng;
1719  $tpl = $this->tpl;
1720 
1721  ilUtil::sendInfo($lng->txt("exc_multi_feedb_info"));
1722 
1723  $this->addSubTabs("assignment");
1724 
1725  // #13719
1726  $button = ilLinkButton::getInstance();
1727  $button->setCaption("exc_download_zip_structure");
1728  $button->setUrl($this->ctrl->getLinkTarget($this, "downloadMultiFeedbackZip"));
1729  $button->setOmitPreventDoubleSubmission(true);
1730  $ilToolbar->addButtonInstance($button);
1731 
1732  if (!$a_form) {
1733  $a_form = $this->initMultiFeedbackForm($this->assignment->getId());
1734  }
1735 
1736  $tpl->setContent($a_form->getHTML());
1737  }
1738 
1743  {
1744  $this->assignment->sendMultiFeedbackStructureFile($this->exercise);
1745  }
1746 
1750  public function uploadMultiFeedbackObject()
1751  {
1752  // #11983
1753  $form = $this->initMultiFeedbackForm($this->assignment->getId());
1754  if ($form->checkInput()) {
1755  try {
1756  $this->assignment->uploadMultiFeedbackFile(ilUtil::stripSlashesArray($_FILES["mfzip"]));
1757  $this->ctrl->redirect($this, "showMultiFeedbackConfirmationTable");
1758  } catch (ilExerciseException $e) {
1759  ilUtil::sendFailure($e->getMessage(), true);
1760  $this->ctrl->redirect($this, "showMultiFeedback");
1761  }
1762  }
1763 
1764  $form->setValuesByPost();
1765  $this->showMultiFeedbackObject($form);
1766  }
1767 
1775  {
1776  $tpl = $this->tpl;
1777 
1778  $this->addSubTabs("assignment");
1779 
1780  $tab = new ilFeedbackConfirmationTable2GUI($this, "showMultiFeedbackConfirmationTable", $this->assignment);
1781  $tpl->setContent($tab->getHTML());
1782  }
1783 
1787  public function cancelMultiFeedbackObject()
1788  {
1789  $this->assignment->clearMultiFeedbackDirectory();
1790  $this->ctrl->redirect($this, "members");
1791  }
1792 
1796  public function saveMultiFeedbackObject()
1797  {
1798  $this->assignment->saveMultiFeedbackFiles($_POST["file"], $this->exercise);
1799 
1800  ilUtil::sendSuccess($this->lng->txt("msg_obj_modified"), true);
1801  $this->ctrl->redirect($this, "members");
1802  }
1803 
1804 
1805  //
1806  // individual deadlines
1807  //
1808 
1809  protected function initIndividualDeadlineModal()
1810  {
1811  $lng = $this->lng;
1812  $tpl = $this->tpl;
1813 
1814  // prepare modal+
1815  $modal = ilModalGUI::getInstance();
1816  $modal->setHeading($lng->txt("exc_individual_deadline"));
1817  $modal->setId("ilExcIDl");
1818  $modal->setBody('<div id="ilExcIDlBody"></div>');
1819  $modal = $modal->getHTML();
1820 
1821  $ajax_url = $this->ctrl->getLinkTarget($this, "handleIndividualDeadlineCalls", "", true, false);
1822 
1823  $tpl->addJavaScript("./Modules/Exercise/js/ilExcIDl.js", true, 3);
1824  $tpl->addOnloadCode('il.ExcIDl.init("' . $ajax_url . '");');
1825 
1827 
1828  return $modal;
1829  }
1830 
1831  protected function parseIndividualDeadlineData(array $a_data)
1832  {
1833  if ($a_data) {
1834  $map = array();
1835  $ass_tmp = array();
1836  foreach ($a_data as $item) {
1837  $item = explode("_", $item);
1838  $ass_id = $item[0];
1839  $user_id = $item[1];
1840 
1841  if (!array_key_exists($ass_id, $ass_tmp)) {
1842  if ($this->assignment &&
1843  $ass_id == $this->assignment->getId()) {
1844  $ass_tmp[$ass_id] = $this->assignment;
1845  } else {
1846  $ass_tmp[$ass_id] = new ilExAssignment($ass_id);
1847  }
1848  }
1849 
1850  $map[$ass_id][] = $user_id;
1851  }
1852 
1853  return array($map, $ass_tmp);
1854  }
1855  }
1856 
1858  {
1859  $tpl = $this->tpl;
1860 
1861  $this->ctrl->saveParameter($this, "part_id");
1862 
1863  // we are done
1864  if ((bool) $_GET["dn"]) {
1865  ilUtil::sendSuccess($this->lng->txt("settings_saved"), true);
1866  $this->ctrl->redirect($this, $this->assignment
1867  ? "members"
1868  : "showParticipant");
1869  }
1870 
1871  // initial form call
1872  if ($_GET["idlid"]) {
1873  $tmp = $this->parseIndividualDeadlineData(explode(",", $_GET["idlid"]));
1874  if (is_array($tmp)) {
1875  $form = $this->initIndividualDeadlineForm($tmp[1], $tmp[0]);
1876  echo $form->getHTML() .
1877  $tpl->getOnLoadCodeForAsynch();
1878  }
1879  }
1880  // form "submit"
1881  else {
1882  $tmp = array();
1883  foreach (array_keys($_POST) as $id) {
1884  if (substr($id, 0, 3) == "dl_") {
1885  $tmp[] = substr($id, 3);
1886  }
1887  }
1888  $tmp = $this->parseIndividualDeadlineData($tmp);
1889  $ass_map = $tmp[1];
1890  $users = $tmp[0];
1891  unset($tmp);
1892 
1893  $form = $this->initIndividualDeadlineForm($ass_map, $users);
1894  $res = array();
1895  if ($valid = $form->checkInput()) {
1896  foreach ($users as $ass_id => $users) {
1897  $ass = $ass_map[$ass_id];
1898 
1899  // :TODO: should individual deadlines BEFORE extended be possible?
1900  $dl = new ilDateTime($ass->getDeadline(), IL_CAL_UNIX);
1901 
1902  foreach ($users as $user_id) {
1903  $date_field = $form->getItemByPostVar("dl_" . $ass_id . "_" . $user_id);
1904  if (ilDate::_before($date_field->getDate(), $dl)) {
1905  $date_field->setAlert(sprintf($this->lng->txt("exc_individual_deadline_before_global"), ilDatePresentation::formatDate($dl)));
1906  $valid = false;
1907  } else {
1908  $res[$ass_id][$user_id] = $date_field->getDate();
1909  }
1910  }
1911  }
1912  }
1913 
1914  if (!$valid) {
1915  $form->setValuesByPost();
1916  echo $form->getHTML() .
1917  $tpl->getOnLoadCodeForAsynch();
1918  } else {
1919  foreach ($res as $ass_id => $users) {
1920  $ass = $ass_map[$ass_id];
1921 
1922  foreach ($users as $id => $date) {
1923  $ass->setIndividualDeadline($id, $date);
1924  }
1925 
1926  $ass->recalculateLateSubmissions();
1927  }
1928 
1929  echo "ok";
1930  }
1931  }
1932 
1933  exit();
1934  }
1935 
1936  protected function initIndividualDeadlineForm(array $a_ass_map, array $ids)
1937  {
1938  $form = new ilPropertyFormGUI();
1939  $form->setFormAction($this->ctrl->getFormAction($this));
1940  $form->setName("ilExcIDlForm");
1941 
1942  foreach ($ids as $ass_id => $users) {
1943  $ass = $a_ass_map[$ass_id];
1944 
1946  $section->setTitle($ass->getTitle());
1947  $form->addItem($section);
1948 
1949  $teams = ilExAssignmentTeam::getInstancesFromMap($ass->getId());
1950 
1951  $values = $ass->getIndividualDeadlines();
1952 
1953  foreach ($users as $id) {
1954  // single user
1955  if (is_numeric($id)) {
1957  $name = $name["lastname"] . ", " . $name["firstname"];
1958  }
1959  // team
1960  else {
1961  $name = "";
1962  $team_id = (int) substr($id, 1);
1963  if (array_key_exists($team_id, $teams)) {
1964  $name = array();
1965  foreach ($teams[$team_id]->getMembers() as $member_id) {
1966  $uname = ilObjUser::_lookupName($member_id);
1967  $name[] = $uname["lastname"] . ", " . $uname["firstname"];
1968  }
1969  asort($name);
1970  $name = implode("<br />", $name);
1971  }
1972  }
1973 
1974  $dl = new ilDateTimeInputGUI($name, "dl_" . $ass_id . "_" . $id);
1975  $dl->setShowTime(true);
1976  $dl->setRequired(true);
1977  $form->addItem($dl);
1978 
1979  if (array_key_exists($id, $values)) {
1980  $dl->setDate(new ilDateTime($values[$id], IL_CAL_UNIX));
1981  }
1982  }
1983  }
1984 
1985  $form->addCommandButton("", $this->lng->txt("save"));
1986 
1987  return $form;
1988  }
1989 
1990  protected function setIndividualDeadlineObject()
1991  {
1992  // this will only get called if no selection
1993  ilUtil::sendFailure($this->lng->txt("select_one"));
1994 
1995  if ($this->assignment) {
1996  $this->membersObject();
1997  } else {
1998  $this->showParticipantObject();
1999  }
2000  }
2001 
2002  public function initFilter()
2003  {
2004  if ($_POST["filter_status"]) {
2005  $this->filter["status"] = trim(ilUtil::stripSlashes($_POST["filter_status"]));
2006  }
2007 
2008  if ($_POST["filter_feedback"]) {
2009  $this->filter["feedback"] = trim(ilUtil::stripSlashes($_POST["filter_feedback"]));
2010  }
2011 
2012  $this->lng->loadLanguageModule("search");
2013 
2014  $this->toolbar->setFormAction($this->ctrl->getFormAction($this, "listTextAssignment"));
2015 
2016  // Status
2017 
2018  if ($_POST["filter_status"]) {
2019  $this->filter["status"] = trim(ilUtil::stripSlashes($_POST["filter_status"]));
2020  }
2021 
2022  $si_status = new ilSelectInputGUI($this->lng->txt("exc_tbl_status"), "filter_status");
2023  $options = array(
2024  "" => $this->lng->txt("search_any"),
2025  self::GRADE_NOT_GRADED => $this->lng->txt("exc_notgraded"),
2026  self::GRADE_PASSED => $this->lng->txt("exc_passed"),
2027  self::GRADE_FAILED => $this->lng->txt("exc_failed")
2028  );
2029  $si_status->setOptions($options);
2030  $si_status->setValue($this->filter["status"]);
2031 
2032  $si_feedback = new ilSelectInputGUI($this->lng->txt("feedback"), "filter_feedback");
2033  $options = array(
2034  self::FEEDBACK_FULL_SUBMISSION => $this->lng->txt("submissions_feedback"),
2035  self::FEEDBACK_ONLY_SUBMISSION => $this->lng->txt("submissions_only")
2036  );
2037  $si_feedback->setOptions($options);
2038  $si_feedback->setValue($this->filter["feedback"]);
2039 
2040  $this->toolbar->addInputItem($si_status, true);
2041 
2042  // Submissions and Feedback
2043  #24713
2044  if ($this->assignment->getPeerReview()) {
2045  if ($_POST["filter_feedback"]) {
2046  $this->filter["feedback"] = trim(ilUtil::stripSlashes($_POST["filter_feedback"]));
2047  } else {
2048  $this->filter["feedback"] = "submission_feedback";
2049  }
2050 
2051  $si_feedback = new ilSelectInputGUI($this->lng->txt("feedback"), "filter_feedback");
2052  $options = array(
2053  "submission_feedback" => $this->lng->txt("submissions_feedback"),
2054  "submission_only" => $this->lng->txt("submissions_only")
2055  );
2056  $si_feedback->setOptions($options);
2057  $si_feedback->setValue($this->filter["feedback"]);
2058 
2059  $this->toolbar->addInputItem($si_feedback, true);
2060  }
2061 
2062  //todo: old school here.
2063  $submit = ilSubmitButton::getInstance();
2064  $submit->setCaption("filter");
2065  $submit->setCommand("listTextAssignment");
2066  $this->toolbar->addButtonInstance($submit);
2067  }
2068 
2072  public function openSubmissionViewObject()
2073  {
2074  global $DIC;
2075 
2076  $ass_id = (int) $_GET["ass_id"];
2077  $member_id = (int) $_GET["member_id"];
2078 
2079  $submission = new ilExSubmission($this->assignment, $member_id);
2080 
2081  $last_opening = $submission->getLastOpeningHTMLView();
2082 
2083  $submission_time = $submission->getLastSubmission();
2084 
2085  $zip_original_full_path = $this->getSubmissionZipFilePath($submission);
2086 
2087  $zip_internal_path = $this->getWebFilePathFromExternalFilePath($zip_original_full_path);
2088 
2089  list($obj_date, $obj_id) = explode("_", basename($zip_original_full_path));
2090 
2091  $obj_dir = $this->assignment->getAssignmentType()->getStringIdentifier() . "_" . $obj_id;
2092 
2093  $index_html_file = ILIAS_WEB_DIR .
2094  DIRECTORY_SEPARATOR .
2095  CLIENT_ID .
2096  DIRECTORY_SEPARATOR .
2097  dirname($zip_internal_path) .
2098  DIRECTORY_SEPARATOR .
2099  $obj_dir .
2100  DIRECTORY_SEPARATOR .
2101  "index.html";
2102 
2103  ilWACSignedPath::signFolderOfStartFile($index_html_file);
2104 
2105  $web_filesystem = $DIC->filesystem()->web();
2106 
2107  if ($last_opening > $submission_time && $web_filesystem->has($index_html_file)) {
2108  ilUtil::redirect($index_html_file);
2109  }
2110  if ($zip_original_full_path) {
2111  $file_copied = $this->copyFileToWebDir($zip_original_full_path, $zip_internal_path);
2112 
2113  if ($file_copied) {
2114  ilUtil::unzip($file_copied, true);
2115 
2116  $web_filesystem->delete($zip_internal_path);
2117 
2118  $submission_repository = new ilExcSubmissionRepository();
2119  $submission_repository->updateWebDirAccessTime($this->assignment->getId(), $member_id);
2120 
2121  ilUtil::redirect($index_html_file);
2122  }
2123 
2124  $error_msg = $this->lng->txt("exc_copy_zip_error");
2125  }
2126 
2127  if (!$error_msg) {
2128  $error_msg = $this->lng->txt("exc_find_zip_error");
2129  }
2130 
2131  ilUtil::sendFailure($error_msg);
2132  }
2133 
2139  protected function getSubmissionZipFilePath(ilExSubmission $submission) : ?string
2140  {
2141  $submitted = $submission->getFiles();
2142 
2143  if (count($submitted) > 0) {
2144  $submitted = array_pop($submitted);
2145 
2146  return $submitted['filename'];
2147  }
2148 
2149  return null;
2150  }
2151 
2158  protected function copyFileToWebDir(string $origin_path_filename, string $internal_file_path) : ?string
2159  {
2160  global $DIC;
2161 
2162  $web_filesystem = $DIC->filesystem()->web();
2163  $data_filesystem = $DIC->filesystem()->storage();
2164 
2165  $internal_dirs = dirname($internal_file_path);
2166  $zip_file = basename($internal_file_path);
2167 
2168  if ($data_filesystem->has($internal_file_path)) {
2169  if (!$web_filesystem->hasDir($internal_dirs)) {
2170  $web_filesystem->createDir($internal_dirs);
2171  }
2172 
2173  if (!$web_filesystem->has($internal_file_path)) {
2174  $stream = $data_filesystem->readStream($internal_file_path);
2175  $web_filesystem->writeStream($internal_file_path, $stream);
2176 
2177  return ILIAS_ABSOLUTE_PATH .
2178  DIRECTORY_SEPARATOR .
2179  ILIAS_WEB_DIR .
2180  DIRECTORY_SEPARATOR .
2181  CLIENT_ID .
2182  DIRECTORY_SEPARATOR .
2183  $internal_dirs .
2184  DIRECTORY_SEPARATOR .
2185  $zip_file;
2186  }
2187  }
2188 
2189  return null;
2190  }
2191 
2197  protected function getWebFilePathFromExternalFilePath(string $external_file_path) : string
2198  {
2199  list($external_path, $internal_file_path) = explode(CLIENT_ID . "/", $external_file_path);
2200 
2201  return $internal_file_path;
2202  }
2203 
2204  /*
2205  * Add the Back link to the tabs. (used in submission list and submission compare)
2206  */
2207  protected function setBackToMembers()
2208  {
2209  //tabs
2210  $this->tabs_gui->clearTargets();
2211  $this->tabs_gui->setBackTarget(
2212  $this->lng->txt("back"),
2213  $this->ctrl->getLinkTarget($this, "members")
2214  );
2215  }
2216 
2221  public function collectFeedbackDataFromPeer(array $a_data) : array
2222  {
2223  $user = new ilObjUser($a_data["user_id"]);
2224  $uname = $user->getFirstname() . " " . $user->getLastname();
2225 
2226  $data = array(
2227  "uid" => $a_data["user_id"],
2228  "uname" => $uname,
2229  "udate" => $a_data["ts"],
2230  "utext" => ilRTE::_replaceMediaObjectImageSrc($a_data["atext"], 1) // mob id to mob src
2231  );
2232 
2233  //get data peer and assign it
2234  $peer_review = new ilExPeerReview($this->assignment);
2235  $data["peer"] = array();
2236  foreach ($peer_review->getPeerReviewsByPeerId($a_data['user_id']) as $key => $value) {
2237  $data["peer"][] = $value['giver_id'];
2238  }
2239 
2240  $data["fb_received"] = count($data["peer"]);
2241  $data["fb_given"] = $peer_review->countGivenFeedback(true, $a_data["user_id"]);
2242 
2243  return $data;
2244  }
2245 }
addMembersObject($a_user_ids=array())
Add new partipant.
static _lookupLogin($a_user_id)
lookup login
static sortArray( $array, $a_array_sortby, $a_array_sortorder=0, $a_numeric=false, $a_keep_keys=false)
sortArray
static _lookupName($a_user_id)
lookup user name
deassignMembersObject()
Deassign members from exercise.
exit
Definition: login.php:29
showGradesOverviewObject()
Show grades overview.
static getAssignmentDataOfExercise($a_exc_id)
Get assignments data of an exercise in an array.
Exercise assignment.
$data
Definition: storeScorm.php:23
const IL_CAL_DATETIME
This class represents an option in a checkbox group.
Class ilExerciseMembers.
static getAdoptableGroups($a_exc_ref_id)
static getGroupMembersMap($a_exc_ref_id)
This class represents a property form user interface.
static getAssignmentTeamMap($a_ass_id)
Get team structure for assignment.
static _exists($a_id, $a_reference=false, $a_type=null)
checks if an object exists in object_data
$_GET["client_id"]
static getInstancesFromMap($a_assignment_id)
saveStatusParticipantObject(array $a_selected=null)
Save assignment status (participant view)
This class represents a section header in a property form.
This class represents a file property in a property form.
$valid
static _before(ilDateTime $start, ilDateTime $end, $a_compare_field='', $a_tz='')
compare two dates and check start is before end This method does not consider tz offsets.
Exercise participant table.
saveStatusAllObject(array $a_selected=null, $a_redirect=true)
resetOffset($a_in_determination=false)
Reset offset.
static unzip($a_file, $overwrite=false, $a_flat=false)
unzip file
static downloadAllAssignmentFiles(ilExAssignment $a_ass, array $members, $to_path)
Download all submitted files of an assignment (all user)
getWebFilePathFromExternalFilePath(string $external_file_path)
Get the object specific file path from an external full file path.
static _lookupId($a_user_str)
Lookup id by login.
openSubmissionViewObject()
Open HTML view for portfolio submissions.
showMultiFeedbackObject(ilPropertyFormGUI $a_form=null)
Show multi-feedback screen.
addUserFromAutoCompleteObject()
Add user as member.
Class ilExerciseMembersFilter.
const IL_CAL_UNIX
filterParticipantsByAccess()
Filter manageable members by position or rbac access.
static _replaceMediaObjectImageSrc($a_text, $a_direction=0, $nic=IL_INST_ID)
Replaces image source from mob image urls with the mob id or replaces mob id with the correct image s...
static formatDate(ilDateTime $date, $a_skip_day=false, $a_include_wd=false, $include_seconds=false)
Format a date public.
static getAssignmentParticipants(int $a_exercise_id, int $a_ass_id)
user()
Definition: user.php:4
This class represents a date/time property in a property form.
global $ilCtrl
Definition: ilias.php:18
selectParticipantObject()
Select participant.
setInfo($a_info)
Set Information Text.
static sendInfo($a_info="", $a_keep=false)
Send Info Message to Screen.
$section
Definition: Utf8Test.php:83
static signFolderOfStartFile($start_file_path)
setTableId($a_val)
Set table id.
if($format !==null) $name
Definition: metadata.php:230
This class represents a hidden form property in a property form.
Exercise peer review.
redirectFeedbackMailObject()
set feedback status for member and redirect to mail screen
compareTextAssignmentsObject()
TODO -> Deal with the redirection after update the grade via action button.
saveStatus(array $a_data, $a_redirect=true)
Save status of selecte members.
addSubTabs($a_activate)
adds tabs to tab gui object
foreach($_POST as $key=> $value) $res
Download submissions and feedback for exercises.
static getInstanceByUserId($a_assignment_id, $a_user_id, $a_create_on_demand=false)
Class ilExPeerReviewGUI.
uploadMultiFeedbackObject()
Upload multi feedback file.
static getInstancesByExercise($a_exc_id)
if(!defined('PATH_SEPARATOR')) $GLOBALS['_PEAR_default_error_mode']
Definition: PEAR.php:64
copyFileToWebDir(string $origin_path_filename, string $internal_file_path)
Generate the directories and copy the file if necessary.
downloadMultiFeedbackZipObject()
Download multi-feedback structrue file.
This class represents a property in a property form.
static stripSlashes($a_str, $a_strip_html=true, $a_allow="")
strip slashes if magic qoutes is enabled
static getNamePresentation( $a_user_id, $a_user_image=false, $a_profile_link=false, $a_profile_back_link="", $a_force_first_lastname=false, $a_omit_login=false, $a_sortable=true, $a_return_data_array=false, $a_ctrl_path="ilpublicuserprofilegui")
Default behaviour is:
setOptions($a_options)
Set Options.
static getAssignmentFilesByUsers(int $a_exc_id, int $a_ass_id, array $a_users)
static getInstanceByObjId($a_obj_id, $stop_on_error=true)
get an instance of an Ilias object by object id
$comment
Definition: buildRTE.php:83
static _lookupType($a_id, $a_reference=false)
lookup object type
static sendFailure($a_info="", $a_keep=false)
Send Failure Message to Screen.
const SIGNATURE_KEY
Session parameter for the hash.
static stripSlashesArray($a_arr, $a_strip_html=true, $a_allow="")
Strip slashes from array.
Class ilExerciseManagementGUI.
confirmDeassignMembersObject()
Confirm deassigning members.
static getInstance()
Get instance.
cancelMultiFeedbackObject()
Cancel Multi Feedback.
sendMembersObject()
Send assignment per mail to participants.
This class represents a non editable value in a property form.
membersObject()
All participants and submission of one assignment.
saveEvaluationFromModalObject()
Save assignment submission grade(status) and comment from the roundtrip modal.
static getRedirectTarget($gui, $cmd, array $gui_params=array(), array $mail_params=array(), array $context_params=array())
saveCommentForLearnersObject()
Save comment for learner (asynch)
getSubmissionZipFilePath(ilExSubmission $submission)
Returns the ZIP file path from outside web directory.
This class represents a text area property in a property form.
$DIC
Definition: xapitoken.php:46
$a
thx to https://mlocati.github.io/php-cs-fixer-configurator for the examples
adoptTeamsFromGroupObject(ilPropertyFormGUI $a_form=null)
showMultiFeedbackConfirmationTableObject()
Show multi feedback confirmation table.
Exercise submission //TODO: This class has to much static methods related to delivered "files"...
static getLogger($a_component_id)
Get component logger.
$url
static fillAutoCompleteToolbar($parent_object, ilToolbarGUI $toolbar=null, $a_options=array(), $a_sticky=false)
fill toolbar with
saveMultiFeedbackObject()
Save multi feedback.
File System Explorer GUI class.
static redirect($a_script)
Exercise participant table.
setSuffixes($a_suffixes)
Set Accepted Suffixes.
getFiles(array $a_file_ids=null, $a_only_valid=false, $a_min_timestamp=null)
Get submission items (not only files)
__construct(ilExerciseInternalService $service, ilExAssignment $a_ass=null)
Constructor.
$_POST["username"]
Object-based submissions (ends up as static file)
initIndividualDeadlineForm(array $a_ass_map, array $ids)
static lookupTitle($a_id)
Lookup title.
downloadAllObject()
Download all submitted files (of all members).
Confirmation screen class.
Exercise exceptions class.