ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.ilExAssignmentGUI.php
Go to the documentation of this file.
1 <?php
2 
22 
29 {
30  protected \ILIAS\Exercise\InternalGUIService $gui;
31  protected \ILIAS\MediaObjects\MediaType\MediaTypeManager $media_type;
32  protected ilLanguage $lng;
33  protected ilObjUser $user;
34  protected ilCtrl $ctrl;
35  protected ilObjExercise $exc;
36  protected int $current_ass_id;
39  protected UIServices $ui;
40  protected int $requested_ass_id;
41 
42 
46  public function __construct(
47  ilObjExercise $a_exc,
48  InternalService $service
49  ) {
51  global $DIC;
52 
53  $request = $DIC->exercise()->internal()->gui()->request();
54  $this->requested_ass_id = $request->getAssId();
55 
56  $this->lng = $DIC->language();
57  $this->user = $DIC->user();
58  $this->ctrl = $DIC->ctrl();
59  $this->ui = $DIC->ui();
60 
61  $this->exc = $a_exc;
62  $this->service = $service;
63  $this->mandatory_manager = $service->domain()->assignment()->mandatoryAssignments($this->exc);
64  $this->media_type = $DIC->mediaObjects()->internal()->domain()->mediaType();
65  $this->gui = $DIC->exercise()
66  ->internal()
67  ->gui();
68  }
69 
74  public function getOverviewHeader(ilExAssignment $a_ass): string
75  {
76  $lng = $this->lng;
77  $ilUser = $this->user;
78 
79  $lng->loadLanguageModule("exc");
80 
81  $state = ilExcAssMemberState::getInstanceByIds($a_ass->getId(), $ilUser->getId());
82 
83  $tpl = new ilTemplate("tpl.assignment_head.html", true, true, "Modules/Exercise");
84 
85  // we are completely ignoring the extended deadline here
86 
87  // :TODO: meaning of "ended on"
88  if ($state->exceededOfficialDeadline()) {
89  $tpl->setCurrentBlock("prop");
90  $tpl->setVariable("PROP", $lng->txt("exc_ended_on"));
91  $tpl->setVariable("PROP_VAL", $state->getCommonDeadlinePresentation());
92  $tpl->parseCurrentBlock();
93 
94  // #14077 // this currently shows the feedback deadline during grace period
95  if ($state->getPeerReviewDeadline()) {
96  $tpl->setCurrentBlock("prop");
97  $tpl->setVariable("PROP", $lng->txt("exc_peer_review_deadline"));
98  $tpl->setVariable("PROP_VAL", $state->getPeerReviewDeadlinePresentation());
99  $tpl->parseCurrentBlock();
100  }
101  } elseif (!$state->hasGenerallyStarted()) {
102  $tpl->setCurrentBlock("prop");
103  if ($state->getRelativeDeadline()) {
104  $tpl->setVariable("PROP", $lng->txt("exc_earliest_start_time"));
105  } else {
106  $tpl->setVariable("PROP", $lng->txt("exc_starting_on"));
107  }
108  $tpl->setVariable("PROP_VAL", $state->getGeneralStartPresentation());
109  $tpl->parseCurrentBlock();
110  } else {
111  if ($state->getCommonDeadline() > 0) {
112  $tpl->setCurrentBlock("prop");
113  $tpl->setVariable("PROP", $lng->txt("exc_time_to_send"));
114  $tpl->setVariable("PROP_VAL", $state->getRemainingTimePresentation());
115  $tpl->parseCurrentBlock();
116 
117  $tpl->setCurrentBlock("prop");
118  $tpl->setVariable("PROP", $lng->txt("exc_edit_until"));
119  $tpl->setVariable("PROP_VAL", $state->getCommonDeadlinePresentation());
120  $tpl->parseCurrentBlock();
121  } elseif ($state->getRelativeDeadline()) { // if we only have a relative deadline (not started yet)
122  $tpl->setCurrentBlock("prop");
123  $tpl->setVariable("PROP", $lng->txt("exc_rem_time_after_start"));
124  $tpl->setVariable("PROP_VAL", $state->getRelativeDeadlinePresentation());
125  $tpl->parseCurrentBlock();
126 
127  if ($state->getLastSubmissionOfRelativeDeadline()) { // if we only have a relative deadline (not started yet)
128  $tpl->setCurrentBlock("prop");
129  $tpl->setVariable("PROP", $lng->txt("exc_rel_last_submission"));
130  $tpl->setVariable("PROP_VAL", $state->getLastSubmissionOfRelativeDeadlinePresentation());
131  $tpl->parseCurrentBlock();
132  }
133  }
134 
135 
136  if ($state->getIndividualDeadline() > 0) {
137  $tpl->setCurrentBlock("prop");
138  $tpl->setVariable("PROP", $lng->txt("exc_individual_deadline"));
139  $tpl->setVariable("PROP_VAL", $state->getIndividualDeadlinePresentation());
140  $tpl->parseCurrentBlock();
141  }
142  }
143 
144  $mand = "";
145  if ($this->mandatory_manager->isMandatoryForUser($a_ass->getId(), $this->user->getId())) {
146  $mand = " (" . $lng->txt("exc_mandatory") . ")";
147  }
148  $tpl->setVariable("TITLE", $a_ass->getTitle() . $mand);
149 
150  // status icon
151  $tpl->setVariable(
152  "ICON_STATUS",
153  $this->getIconForStatus(
154  $a_ass->getMemberStatus()->getStatus(),
156  )
157  );
158 
159  return $tpl->get();
160  }
161 
169  public function getOverviewBody(ilExAssignment $a_ass): string
170  {
171  global $DIC;
172 
173  $ilUser = $DIC->user();
174 
175  $this->current_ass_id = $a_ass->getId();
176 
177  $tpl = new ilTemplate("tpl.assignment_body.html", true, true, "Modules/Exercise");
178 
179  $state = ilExcAssMemberState::getInstanceByIds($a_ass->getId(), $ilUser->getId());
180 
181  $info = new ilInfoScreenGUI(null);
182  $info->setTableClass("");
183  if ($state->areInstructionsVisible()) {
184  $this->addInstructions($info, $a_ass);
185  $this->addFiles($info, $a_ass);
186  }
187 
188  $this->addSchedule($info, $a_ass);
189 
190  if ($state->hasSubmissionStarted()) {
191  $this->addSubmission($info, $a_ass);
192  }
193 
194  $tpl->setVariable("CONTENT", $info->getHTML());
195 
196  return $tpl->get();
197  }
198 
199 
200  protected function addInstructions(
201  ilInfoScreenGUI $a_info,
202  ilExAssignment $a_ass
203  ): void {
204  $ilUser = $this->user;
205  $info = new ilExAssignmentInfo($a_ass->getId(), $ilUser->getId());
206  $inst = $info->getInstructionInfo();
207  if (count($inst) > 0) {
208  $a_info->addSection($inst["instruction"]["txt"]);
209  $a_info->addProperty("", $inst["instruction"]["value"]);
210  }
211  }
212 
216  protected function addSchedule(
217  ilInfoScreenGUI $a_info,
218  ilExAssignment $a_ass
219  ): void {
220  $lng = $this->lng;
221  $ilUser = $this->user;
222  $ilCtrl = $this->ctrl;
223 
224  $info = new ilExAssignmentInfo($a_ass->getId(), $ilUser->getId());
225  $schedule = $info->getScheduleInfo();
226 
227  $state = ilExcAssMemberState::getInstanceByIds($a_ass->getId(), $ilUser->getId());
228 
229  $a_info->addSection($lng->txt("exc_schedule"));
230  if ($state->getGeneralStart() > 0) {
231  $a_info->addProperty($schedule["start_time"]["txt"], $schedule["start_time"]["value"]);
232  }
233 
234 
235  if ($state->getCommonDeadline()) { // if we have a common deadline (target timestamp)
236  $a_info->addProperty($schedule["until"]["txt"], $schedule["until"]["value"]);
237  } elseif ($state->getRelativeDeadline()) { // if we only have a relative deadline (not started yet)
238  $but = "";
239  if ($state->hasGenerallyStarted()) {
240  $ilCtrl->setParameterByClass("ilobjexercisegui", "ass_id", $a_ass->getId());
241  $but = $this->ui->factory()->button()->primary($lng->txt("exc_start_assignment"), $ilCtrl->getLinkTargetByClass("ilobjexercisegui", "startAssignment"));
242  $ilCtrl->setParameterByClass("ilobjexercisegui", "ass_id", $this->requested_ass_id);
243  $but = $this->ui->renderer()->render($but);
244  }
245 
246  $a_info->addProperty($schedule["time_after_start"]["txt"], $schedule["time_after_start"]["value"] . " " . $but);
247  if ($state->getLastSubmissionOfRelativeDeadline()) { // if we only have a relative deadline (not started yet)
248  $a_info->addProperty(
249  $lng->txt("exc_rel_last_submission"),
250  $state->getLastSubmissionOfRelativeDeadlinePresentation()
251  );
252  }
253  }
254 
255  if ($state->getOfficialDeadline() > $state->getCommonDeadline()) {
256  $a_info->addProperty($schedule["individual_deadline"]["txt"], $schedule["individual_deadline"]["value"]);
257  }
258 
259  if ($state->hasSubmissionStarted()) {
260  $a_info->addProperty($schedule["time_to_send"]["txt"], $schedule["time_to_send"]["value"]);
261  }
262  }
263 
264  protected function addPublicSubmissions(
265  ilInfoScreenGUI $a_info,
266  ilExAssignment $a_ass
267  ): void {
268  $lng = $this->lng;
269  $ilUser = $this->user;
270 
271  $state = ilExcAssMemberState::getInstanceByIds($a_ass->getId(), $ilUser->getId());
272 
273  // submissions are visible, even if other users may still have a larger individual deadline
274  if ($state->hasSubmissionEnded()) {
275  $b = $this->gui->link(
276  $lng->txt("exc_list_submission"),
277  $this->getSubmissionLink("listPublicSubmissions")
278  )->emphasised()
279  ->render();
280  $a_info->addProperty($lng->txt("exc_public_submission"), $b);
281  } else {
282  $a_info->addProperty(
283  $lng->txt("exc_public_submission"),
284  $lng->txt("exc_msg_public_submission")
285  );
286  }
287  }
288 
289  protected function addFiles(
290  ilInfoScreenGUI $a_info,
291  ilExAssignment $a_ass
292  ): void {
293  $lng = $this->lng;
294  $lng->loadLanguageModule("exc");
295  $files = $a_ass->getFiles();
296  if (count($files) > 0) {
297  $a_info->addSection($lng->txt("exc_files"));
298 
299  global $DIC;
300 
301  //file has -> name,fullpath,size,ctime
302  $cnt = 0;
303  foreach ($files as $file) {
304  $cnt++;
305  // get mime type
306  $mime = $file['mime'] ?? ilObjMediaObject::getMimeType($file['fullpath']);
307 
308  $ui_factory = $DIC->ui()->factory();
309  $ui_renderer = $DIC->ui()->renderer();
310 
311  $output_filename = htmlspecialchars($file['name']);
312 
313  if ($this->media_type->isImage($mime)) {
314  $item_id = "il-ex-modal-img-" . $a_ass->getId() . "-" . $cnt;
315 
316 
317  $image = $ui_renderer->render($ui_factory->image()->responsive($file['fullpath'], $output_filename));
318  $image_lens = ilUtil::getImagePath("media/enlarge.svg");
319 
320  $modal = ilModalGUI::getInstance();
321  $modal->setId($item_id);
322  $modal->setType(ilModalGUI::TYPE_LARGE);
323  $modal->setBody($image);
324  $modal->setHeading($output_filename);
325  $modal = $modal->getHTML();
326 
327  $img_tpl = new ilTemplate("tpl.image_file.html", true, true, "Modules/Exercise");
328  $img_tpl->setCurrentBlock("image_content");
329  $img_tpl->setVariable("MODAL", $modal);
330  $img_tpl->setVariable("ITEM_ID", $item_id);
331  $img_tpl->setVariable("IMAGE", $image);
332  $img_tpl->setvariable("IMAGE_LENS", $image_lens);
333  $img_tpl->setvariable("ALT_LENS", $lng->txt("exc_fullscreen"));
334  $img_tpl->parseCurrentBlock();
335 
336  $a_info->addProperty($output_filename, $img_tpl->get());
337  } elseif ($this->media_type->isAudio($mime) || $this->media_type->isVideo($mime)) {
338  $media_tpl = new ilTemplate("tpl.media_file.html", true, true, "Modules/Exercise");
339 
340  if ($this->media_type->isAudio($mime)) {
341  $p = $ui_factory->player()->audio($file['fullpath']);
342  } else {
343  $p = $ui_factory->player()->video($file['fullpath']);
344  }
345  $media_tpl->setVariable("MEDIA", $ui_renderer->render($p));
346 
347  $but = $ui_factory->button()->shy(
348  $lng->txt("download"),
349  $this->getSubmissionLink("downloadFile", array("file" => urlencode($file["name"])))
350  );
351  $media_tpl->setVariable("DOWNLOAD_BUTTON", $ui_renderer->render($but));
352  $a_info->addProperty($output_filename, $media_tpl->get());
353  } else {
354  $a_info->addProperty($output_filename, $lng->txt("download"), $this->getSubmissionLink("downloadFile", array("file" => urlencode($file["name"]))));
355  }
356  }
357  }
358  }
359 
364  protected function addSubmission(
365  ilInfoScreenGUI $a_info,
366  ilExAssignment $a_ass
367  ): void {
368  $lng = $this->lng;
369  $ilUser = $this->user;
370 
371  $state = ilExcAssMemberState::getInstanceByIds($a_ass->getId(), $ilUser->getId());
372 
373  $a_info->addSection($lng->txt("exc_your_submission"));
374 
375  $submission = new ilExSubmission($a_ass, $ilUser->getId());
376 
377  ilExSubmissionGUI::getOverviewContent($a_info, $submission, $this->exc);
378 
379  $last_sub = null;
380  if ($submission->hasSubmitted()) {
381  $last_sub = $submission->getLastSubmission();
382  if ($last_sub) {
383  $last_sub = ilDatePresentation::formatDate(new ilDateTime($last_sub, IL_CAL_DATETIME));
384  $a_info->addProperty($lng->txt("exc_last_submission"), $last_sub);
385  }
386  }
387 
388  if ($this->exc->getShowSubmissions()) {
389  $this->addPublicSubmissions($a_info, $a_ass);
390  }
391 
392  ilExPeerReviewGUI::getOverviewContent($a_info, $submission);
393 
394  // global feedback / sample solution
396  $show_global_feedback = ($state->hasSubmissionEndedForAllUsers() && $a_ass->getFeedbackFile());
397  }
398  //If it is not well configured...(e.g. show solution before deadline)
399  //the user can get the solution before he summit it.
400  //we can check in the elseif $submission->hasSubmitted()
402  $show_global_feedback = ($a_ass->afterCustomDate() && $a_ass->getFeedbackFile());
403  } else {
404  $show_global_feedback = ($last_sub && $a_ass->getFeedbackFile());
405  }
406  $this->addSubmissionFeedback($a_info, $a_ass, $submission->getFeedbackId(), $show_global_feedback);
407  }
408 
409  protected function addSubmissionFeedback(
410  ilInfoScreenGUI $a_info,
411  ilExAssignment $a_ass,
412  string $a_feedback_id,
413  bool $a_show_global_feedback
414  ): void {
415  $lng = $this->lng;
416 
417  $feedback_file_manager = $this->service->domain()->assignment()->tutorFeedbackFile($a_ass->getId());
418  $cnt_files = $feedback_file_manager->count($this->user->getId());
419  $lpcomment = $a_ass->getMemberStatus()->getComment();
420  $mark = $a_ass->getMemberStatus()->getMark();
421  $status = $a_ass->getMemberStatus()->getStatus();
422 
423  if ($lpcomment != "" ||
424  $mark != "" ||
425  $status != "notgraded" ||
426  $cnt_files > 0 ||
427  $a_show_global_feedback) {
428  $a_info->addSection($lng->txt("exc_feedback_from_tutor"));
429  if ($lpcomment != "") {
430  $a_info->addProperty(
431  $lng->txt("exc_comment"),
432  nl2br($lpcomment)
433  );
434  }
435  if ($mark != "") {
436  $a_info->addProperty(
437  $lng->txt("exc_mark"),
438  $mark
439  );
440  }
441 
442  if ($status != "" && $status != "notgraded") {
443  $img = $this->getIconForStatus($status);
444  $a_info->addProperty(
445  $lng->txt("status"),
446  $img . " " . $lng->txt("exc_" . $status)
447  );
448  }
449 
450  if ($cnt_files > 0) {
451  $a_info->addSection($lng->txt("exc_fb_files") .
452  '<a id="fb' . $a_ass->getId() . '"></a>');
453 
454  if ($cnt_files > 0) {
455  $files = $feedback_file_manager->getFiles($this->user->getId());
456  foreach ($files as $file) {
457  $a_info->addProperty(
458  $file,
459  $lng->txt("download"),
460  $this->getSubmissionLink("downloadFeedbackFile", array("file" => urlencode($file)))
461  );
462  }
463  }
464  }
465 
466  // #15002 - global feedback
467  if ($a_show_global_feedback) {
468  $a_info->addSection($lng->txt("exc_global_feedback_file"));
469 
470  $a_info->addProperty(
471  $a_ass->getFeedbackFile(),
472  $lng->txt("download"),
473  $this->getSubmissionLink("downloadGlobalFeedbackFile")
474  );
475  }
476  }
477  }
478 
483  public function getTimeString(int $a_deadline): string
484  {
485  $lng = $this->lng;
486 
487  if ($a_deadline == 0) {
488  return $lng->txt("exc_submit_convenience_no_deadline");
489  }
490 
491  if ($a_deadline - time() <= 0) {
492  $time_str = $lng->txt("exc_time_over_short");
493  } else {
494  $time_str = ilLegacyFormElementsUtil::period2String(new ilDateTime($a_deadline, IL_CAL_UNIX));
495  }
496 
497  return $time_str;
498  }
499 
500  protected function getSubmissionLink(
501  string $a_cmd,
502  array $a_params = null
503  ): string {
504  $ilCtrl = $this->ctrl;
505 
506  if (is_array($a_params)) {
507  foreach ($a_params as $name => $value) {
508  $ilCtrl->setParameterByClass("ilexsubmissiongui", $name, $value);
509  }
510  }
511 
512  $ilCtrl->setParameterByClass("ilexsubmissiongui", "ass_id", $this->current_ass_id);
513  $url = $ilCtrl->getLinkTargetByClass([ilAssignmentPresentationGUI::class, "ilexsubmissiongui"], $a_cmd);
514  $ilCtrl->setParameterByClass("ilexsubmissiongui", "ass_id", "");
515 
516  if (is_array($a_params)) {
517  foreach ($a_params as $name => $value) {
518  $ilCtrl->setParameterByClass("ilexsubmissiongui", $name, "");
519  }
520  }
521 
522  return $url;
523  }
524 
528  protected function getIconForStatus(string $status, int $variant = ilLPStatusIcons::ICON_VARIANT_LONG): string
529  {
530  $icons = ilLPStatusIcons::getInstance($variant);
531  $lng = $this->lng;
532 
533  switch ($status) {
534  case "passed":
535  return $icons->renderIcon(
536  $icons->getImagePathCompleted(),
537  $lng->txt("exc_" . $status)
538  );
539 
540  case "failed":
541  return $icons->renderIcon(
542  $icons->getImagePathFailed(),
543  $lng->txt("exc_" . $status)
544  );
545 
546  default:
547  return $icons->renderIcon(
548  $icons->getImagePathNotAttempted(),
549  $lng->txt("exc_" . $status)
550  );
551  }
552  }
553 
557 }
addSubmissionFeedback(ilInfoScreenGUI $a_info, ilExAssignment $a_ass, string $a_feedback_id, bool $a_show_global_feedback)
static getOverviewContent(ilInfoScreenGUI $a_info, ilExSubmission $a_submission)
ILIAS Exercise InternalGUIService $gui
Class ilInfoScreenGUI.
Exercise assignment.
const IL_CAL_DATETIME
addPublicSubmissions(ilInfoScreenGUI $a_info, ilExAssignment $a_ass)
txt(string $a_topic, string $a_default_lang_fallback_mod="")
gets the text for a given topic if the topic is not in the list, the topic itself with "-" will be re...
static getImagePath(string $img, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
getMemberStatus(?int $a_user_id=null)
addProperty(string $a_name, string $a_value, string $a_link="")
add a property to current section
MandatoryAssignmentsManager $mandatory_manager
static formatDate(ilDateTime $date, bool $a_skip_day=false, bool $a_include_wd=false, bool $include_seconds=false)
static period2String(ilDateTime $a_from, $a_to=null)
Return a string of time period.
static getInstance(int $variant=ilLPStatusIcons::ICON_VARIANT_DEFAULT, ?\ILIAS\UI\Renderer $renderer=null, ?\ILIAS\UI\Factory $factory=null)
Exercise internal service.
addInstructions(ilInfoScreenGUI $a_info, ilExAssignment $a_ass)
setParameterByClass(string $a_class, string $a_parameter, $a_value)
loadLanguageModule(string $a_module)
Load language module.
addSchedule(ilInfoScreenGUI $a_info, ilExAssignment $a_ass)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
const IL_CAL_UNIX
global $DIC
Definition: feed.php:28
GUI class for exercise assignments.
Provides fluid interface to RBAC services.
Definition: UIServices.php:23
Class ilObjExercise.
__construct(VocabulariesInterface $vocabularies)
getOverviewBody(ilExAssignment $a_ass)
Get assignment body for overview.
static getMimeType(string $a_file, bool $a_external=false)
get mime type for file
addFiles(ilInfoScreenGUI $a_info, ilExAssignment $a_ass)
static getInstanceByIds(int $a_ass_id, int $a_user_id=0)
addSection(string $a_title)
$url
Definition: ltiregstart.php:35
getOverviewHeader(ilExAssignment $a_ass)
Get assignment header for overview.
static getInstance()
addSubmission(ilInfoScreenGUI $a_info, ilExAssignment $a_ass)
getTimeString(int $a_deadline)
Get time string for deadline.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getIconForStatus(string $status, int $variant=ilLPStatusIcons::ICON_VARIANT_LONG)
Get the rendered icon for a status (failed, passed or not graded).
ILIAS MediaObjects MediaType MediaTypeManager $media_type
getSubmissionLink(string $a_cmd, array $a_params=null)