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