MDL-66147 mod_assign: submissions overview page shows time interval
[moodle.git] / mod / assign / renderer.php
CommitLineData
bbd0e548
DW
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * This file contains a renderer for the assignment class
19 *
20 * @package mod_assign
21 * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25defined('MOODLE_INTERNAL') || die();
26
bbd0e548
DW
27require_once($CFG->dirroot . '/mod/assign/locallib.php');
28
bb690849
DW
29use \mod_assign\output\grading_app;
30
bbd0e548
DW
31/**
32 * A custom renderer class that extends the plugin_renderer_base and is used by the assign module.
33 *
34 * @package mod_assign
35 * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37 */
38class mod_assign_renderer extends plugin_renderer_base {
39
40 /**
e5403f8c 41 * Rendering assignment files
bbd0e548
DW
42 *
43 * @param context $context
44 * @param int $userid
45 * @param string $filearea
46 * @param string $component
47 * @return string
48 */
49 public function assign_files(context $context, $userid, $filearea, $component) {
50 return $this->render(new assign_files($context, $userid, $filearea, $component));
51 }
52
53 /**
e5403f8c 54 * Rendering assignment files
bbd0e548
DW
55 *
56 * @param assign_files $tree
57 * @return string
58 */
59 public function render_assign_files(assign_files $tree) {
9a046c06 60 $this->htmlid = html_writer::random_id('assign_files_tree');
bbd0e548
DW
61 $this->page->requires->js_init_call('M.mod_assign.init_tree', array(true, $this->htmlid));
62 $html = '<div id="'.$this->htmlid.'">';
63 $html .= $this->htmllize_tree($tree, $tree->dir);
64 $html .= '</div>';
65
66 if ($tree->portfolioform) {
67 $html .= $tree->portfolioform;
68 }
69 return $html;
70 }
71
72 /**
73 * Utility function to add a row of data to a table with 2 columns. Modified
74 * the table param and does not return a value
75 *
76 * @param html_table $table The table to append the row of data to
77 * @param string $first The first column text
78 * @param string $second The second column text
79 * @return void
80 */
81 private function add_table_row_tuple(html_table $table, $first, $second) {
82 $row = new html_table_row();
83 $cell1 = new html_table_cell($first);
84 $cell2 = new html_table_cell($second);
85 $row->cells = array($cell1, $cell2);
86 $table->data[] = $row;
87 }
88
bf78ebd6 89 /**
df211804
DW
90 * Render a grading message notification
91 * @param assign_gradingmessage $result The result to render
bf78ebd6
DW
92 * @return string
93 */
df211804 94 public function render_assign_gradingmessage(assign_gradingmessage $result) {
e5403f8c 95 $urlparams = array('id' => $result->coursemoduleid, 'action'=>'grading');
cfdd3e5c
GF
96 if (!empty($result->page)) {
97 $urlparams['page'] = $result->page;
98 }
e5403f8c 99 $url = new moodle_url('/mod/assign/view.php', $urlparams);
153510ea 100 $classes = $result->gradingerror ? 'notifyproblem' : 'notifysuccess';
2a4fbc32 101
bf78ebd6 102 $o = '';
df211804 103 $o .= $this->output->heading($result->heading, 4);
153510ea 104 $o .= $this->output->notification($result->message, $classes);
2a4fbc32 105 $o .= $this->output->continue_button($url);
bf78ebd6
DW
106 return $o;
107 }
108
bbd0e548
DW
109 /**
110 * Render the generic form
111 * @param assign_form $form The form to render
112 * @return string
113 */
114 public function render_assign_form(assign_form $form) {
115 $o = '';
bf78ebd6
DW
116 if ($form->jsinitfunction) {
117 $this->page->requires->js_init_call($form->jsinitfunction, array());
118 }
bbd0e548
DW
119 $o .= $this->output->box_start('boxaligncenter ' . $form->classname);
120 $o .= $this->moodleform($form->form);
121 $o .= $this->output->box_end();
122 return $o;
123 }
124
125 /**
126 * Render the user summary
127 *
128 * @param assign_user_summary $summary The user summary to render
129 * @return string
130 */
131 public function render_assign_user_summary(assign_user_summary $summary) {
132 $o = '';
a69944eb
RT
133 $supendedclass = '';
134 $suspendedicon = '';
bbd0e548
DW
135
136 if (!$summary->user) {
137 return;
138 }
a69944eb
RT
139
140 if ($summary->suspendeduser) {
141 $supendedclass = ' usersuspended';
142 $suspendedstring = get_string('userenrolmentsuspended', 'grades');
663640f5 143 $suspendedicon = ' ' . $this->pix_icon('i/enrolmentsuspended', $suspendedstring);
a69944eb 144 }
bbd0e548 145 $o .= $this->output->container_start('usersummary');
a69944eb 146 $o .= $this->output->box_start('boxaligncenter usersummarysection'.$supendedclass);
b473171a 147 if ($summary->blindmarking) {
a69944eb 148 $o .= get_string('hiddenuser', 'assign') . $summary->uniqueidforuser.$suspendedicon;
b473171a
DW
149 } else {
150 $o .= $this->output->user_picture($summary->user);
151 $o .= $this->output->spacer(array('width'=>30));
e5403f8c
DW
152 $urlparams = array('id' => $summary->user->id, 'course'=>$summary->courseid);
153 $url = new moodle_url('/user/view.php', $urlparams);
d08e6c31
DW
154 $fullname = fullname($summary->user, $summary->viewfullnames);
155 $extrainfo = array();
156 foreach ($summary->extrauserfields as $extrafield) {
157 $extrainfo[] = $summary->user->$extrafield;
158 }
159 if (count($extrainfo)) {
160 $fullname .= ' (' . implode(', ', $extrainfo) . ')';
161 }
a69944eb 162 $fullname .= $suspendedicon;
d08e6c31 163 $o .= $this->output->action_link($url, $fullname);
b473171a 164 }
bbd0e548
DW
165 $o .= $this->output->box_end();
166 $o .= $this->output->container_end();
167
168 return $o;
169 }
170
171 /**
172 * Render the submit for grading page
173 *
174 * @param assign_submit_for_grading_page $page
175 * @return string
176 */
177 public function render_assign_submit_for_grading_page($page) {
178 $o = '';
179
180 $o .= $this->output->container_start('submitforgrading');
5687cd04 181 $o .= $this->output->heading(get_string('confirmsubmissionheading', 'assign'), 3);
bbd0e548
DW
182
183 $cancelurl = new moodle_url('/mod/assign/view.php', array('id' => $page->coursemoduleid));
184 if (count($page->notifications)) {
e5403f8c 185 // At least one of the submission plugins is not ready for submission.
bbd0e548
DW
186
187 $o .= $this->output->heading(get_string('submissionnotready', 'assign'), 4);
188
189 foreach ($page->notifications as $notification) {
190 $o .= $this->output->notification($notification);
191 }
192
193 $o .= $this->output->continue_button($cancelurl);
194 } else {
e5403f8c 195 // All submission plugins ready - show the confirmation form.
94f26900 196 $o .= $this->moodleform($page->confirmform);
bbd0e548
DW
197 }
198 $o .= $this->output->container_end();
199
bbd0e548
DW
200 return $o;
201 }
202
203 /**
e5403f8c 204 * Page is done - render the footer.
bbd0e548
DW
205 *
206 * @return void
207 */
208 public function render_footer() {
209 return $this->output->footer();
210 }
211
212 /**
e5403f8c 213 * Render the header.
bbd0e548
DW
214 *
215 * @param assign_header $header
216 * @return string
217 */
218 public function render_assign_header(assign_header $header) {
219 $o = '';
220
221 if ($header->subpage) {
222 $this->page->navbar->add($header->subpage);
ff9a0f82
DW
223 $args = ['contextname' => $header->context->get_context_name(false, true), 'subpage' => $header->subpage];
224 $title = get_string('subpagetitle', 'assign', $args);
225 } else {
226 $title = $header->context->get_context_name(false, true);
bbd0e548 227 }
ff9a0f82
DW
228 $courseshortname = $header->context->get_course_context()->get_context_name(false, true);
229 $title = $courseshortname . ': ' . $title;
230 $heading = format_string($header->assign->name, false, array('context' => $header->context));
bbd0e548 231
ff9a0f82 232 $this->page->set_title($title);
bea4ed1b 233 $this->page->set_heading($this->page->course->fullname);
bbd0e548
DW
234
235 $o .= $this->output->header();
bea4ed1b 236 $o .= $this->output->heading($heading);
a1e54f4d
DW
237 if ($header->preface) {
238 $o .= $header->preface;
239 }
bbd0e548
DW
240
241 if ($header->showintro) {
242 $o .= $this->output->box_start('generalbox boxaligncenter', 'intro');
243 $o .= format_module_intro('assign', $header->assign, $header->coursemoduleid);
7faf78cb 244 $o .= $header->postfix;
bbd0e548
DW
245 $o .= $this->output->box_end();
246 }
247
248 return $o;
249 }
250
af904bd7
HB
251 /**
252 * Render the header for an individual plugin.
253 *
254 * @param assign_plugin_header $header
255 * @return string
256 */
257 public function render_assign_plugin_header(assign_plugin_header $header) {
258 $o = $header->plugin->view_header();
259 return $o;
260 }
261
bbd0e548 262 /**
e5403f8c 263 * Render a table containing the current status of the grading process.
bbd0e548
DW
264 *
265 * @param assign_grading_summary $summary
266 * @return string
267 */
268 public function render_assign_grading_summary(assign_grading_summary $summary) {
e5403f8c 269 // Create a table for the data.
bbd0e548
DW
270 $o = '';
271 $o .= $this->output->container_start('gradingsummary');
272 $o .= $this->output->heading(get_string('gradingsummary', 'assign'), 3);
273 $o .= $this->output->box_start('boxaligncenter gradingsummarytable');
274 $t = new html_table();
275
a8f7818b
ZT
276 // Visibility Status.
277 $this->add_table_row_tuple($t, get_string('hiddenfromstudents'),
278 (!$summary->isvisible) ? get_string('yes') : get_string('no'));
279
e5403f8c 280 // Status.
12a1a0da 281 if ($summary->teamsubmission) {
74ddcaaa 282 if ($summary->warnofungroupedusers === assign_grading_summary::WARN_GROUPS_REQUIRED) {
e528997a 283 $o .= $this->output->notification(get_string('ungroupedusers', 'assign'));
74ddcaaa
DS
284 } else if ($summary->warnofungroupedusers === assign_grading_summary::WARN_GROUPS_OPTIONAL) {
285 $o .= $this->output->notification(get_string('ungroupedusersoptional', 'assign'));
e528997a
AH
286 }
287
12a1a0da
DW
288 $this->add_table_row_tuple($t, get_string('numberofteams', 'assign'),
289 $summary->participantcount);
290 } else {
291 $this->add_table_row_tuple($t, get_string('numberofparticipants', 'assign'),
292 $summary->participantcount);
293 }
bbd0e548 294
bf57184c
RW
295 // Drafts count and dont show drafts count when using offline assignment.
296 if ($summary->submissiondraftsenabled && $summary->submissionsenabled) {
bbd0e548
DW
297 $this->add_table_row_tuple($t, get_string('numberofdraftsubmissions', 'assign'),
298 $summary->submissiondraftscount);
e5403f8c 299 }
bbd0e548 300
e5403f8c 301 // Submitted for grading.
bbd0e548
DW
302 if ($summary->submissionsenabled) {
303 $this->add_table_row_tuple($t, get_string('numberofsubmittedassignments', 'assign'),
304 $summary->submissionssubmittedcount);
8f7e1c05
DW
305 if (!$summary->teamsubmission) {
306 $this->add_table_row_tuple($t, get_string('numberofsubmissionsneedgrading', 'assign'),
307 $summary->submissionsneedgradingcount);
308 }
bbd0e548
DW
309 }
310
311 $time = time();
312 if ($summary->duedate) {
e5403f8c 313 // Due date.
bbd0e548 314 $duedate = $summary->duedate;
9e719b81
JD
315 if ($summary->courserelativedatesmode) {
316 // Returns a formatted string, in the format '10d 10h 45m'.
317 $diffstr = get_time_interval_string($duedate, $summary->coursestartdate);
318 if ($duedate >= $summary->coursestartdate) {
319 $userduedate = get_string('relativedatessubmissionduedateafter', 'mod_assign', ['datediffstr' => $diffstr]);
320 } else {
321 $userduedate = get_string('relativedatessubmissionduedatebefore', 'mod_assign', ['datediffstr' => $diffstr]);
322 }
323 } else {
324 $userduedate = userdate($duedate);
325 }
bbd0e548 326 $this->add_table_row_tuple($t, get_string('duedate', 'assign'),
9e719b81 327 $userduedate);
bbd0e548 328
e5403f8c 329 // Time remaining.
9e719b81
JD
330 if ($summary->courserelativedatesmode) {
331 $due = get_string('relativedatessubmissiontimeleft', 'mod_assign');
bbd0e548 332 } else {
9e719b81
JD
333 $due = '';
334 if ($duedate - $time <= 0) {
335 $due = get_string('assignmentisdue', 'assign');
336 } else {
337 $due = format_time($duedate - $time);
338 }
bbd0e548
DW
339 }
340 $this->add_table_row_tuple($t, get_string('timeremaining', 'assign'), $due);
9e795179
DW
341
342 if ($duedate < $time) {
343 $cutoffdate = $summary->cutoffdate;
344 if ($cutoffdate) {
345 if ($cutoffdate > $time) {
b351e446 346 $late = get_string('latesubmissionsaccepted', 'assign', userdate($summary->cutoffdate));
9e795179
DW
347 } else {
348 $late = get_string('nomoresubmissionsaccepted', 'assign');
349 }
350 $this->add_table_row_tuple($t, get_string('latesubmissions', 'assign'), $late);
351 }
352 }
353
bbd0e548
DW
354 }
355
e5403f8c 356 // All done - write the table.
bbd0e548
DW
357 $o .= html_writer::table($t);
358 $o .= $this->output->box_end();
359
e5403f8c 360 // Link to the grading page.
bb690849 361 $o .= '<center>';
2664105c 362 $o .= $this->output->container_start('submissionlinks');
6853cd5e 363 $urlparams = array('id' => $summary->coursemoduleid, 'action' => 'grading');
e5403f8c 364 $url = new moodle_url('/mod/assign/view.php', $urlparams);
15fbd905 365 $o .= '<a href="' . $url . '" class="btn btn-secondary">' . get_string('viewgrading', 'mod_assign') . '</a> ';
bf0a1542
DW
366 if ($summary->cangrade) {
367 $urlparams = array('id' => $summary->coursemoduleid, 'action' => 'grader');
368 $url = new moodle_url('/mod/assign/view.php', $urlparams);
369 $o .= '<a href="' . $url . '" class="btn btn-primary">' . get_string('grade') . '</a>';
370 }
d9a88f42 371 $o .= $this->output->container_end();
bbd0e548 372
e5403f8c 373 // Close the container and insert a spacer.
bbd0e548 374 $o .= $this->output->container_end();
bb690849 375 $o .= '</center>';
bbd0e548
DW
376
377 return $o;
378 }
379
380 /**
e5403f8c 381 * Render a table containing all the current grades and feedback.
bbd0e548
DW
382 *
383 * @param assign_feedback_status $status
384 * @return string
385 */
386 public function render_assign_feedback_status(assign_feedback_status $status) {
387 global $DB, $CFG;
388 $o = '';
389
390 $o .= $this->output->container_start('feedback');
391 $o .= $this->output->heading(get_string('feedback', 'assign'), 3);
392 $o .= $this->output->box_start('boxaligncenter feedbacktable');
393 $t = new html_table();
394
e5403f8c 395 // Grade.
46692c3a
DW
396 if (isset($status->gradefordisplay)) {
397 $row = new html_table_row();
398 $cell1 = new html_table_cell(get_string('grade'));
399 $cell2 = new html_table_cell($status->gradefordisplay);
400 $row->cells = array($cell1, $cell2);
401 $t->data[] = $row;
bbd0e548 402
46692c3a
DW
403 // Grade date.
404 $row = new html_table_row();
405 $cell1 = new html_table_cell(get_string('gradedon', 'assign'));
406 $cell2 = new html_table_cell(userdate($status->gradeddate));
407 $row->cells = array($cell1, $cell2);
408 $t->data[] = $row;
409 }
bbd0e548
DW
410
411 if ($status->grader) {
e5403f8c 412 // Grader.
bbd0e548
DW
413 $row = new html_table_row();
414 $cell1 = new html_table_cell(get_string('gradedby', 'assign'));
e5403f8c
DW
415 $userdescription = $this->output->user_picture($status->grader) .
416 $this->output->spacer(array('width'=>30)) .
05fdbe37 417 fullname($status->grader, $status->canviewfullnames);
e5403f8c 418 $cell2 = new html_table_cell($userdescription);
bbd0e548
DW
419 $row->cells = array($cell1, $cell2);
420 $t->data[] = $row;
421 }
422
423 foreach ($status->feedbackplugins as $plugin) {
df47b77f
DW
424 if ($plugin->is_enabled() &&
425 $plugin->is_visible() &&
426 $plugin->has_user_summary() &&
427 !empty($status->grade) &&
428 !$plugin->is_empty($status->grade)) {
429
bbd0e548
DW
430 $row = new html_table_row();
431 $cell1 = new html_table_cell($plugin->get_name());
e5403f8c
DW
432 $displaymode = assign_feedback_plugin_feedback::SUMMARY;
433 $pluginfeedback = new assign_feedback_plugin_feedback($plugin,
434 $status->grade,
435 $displaymode,
436 $status->coursemoduleid,
437 $status->returnaction,
438 $status->returnparams);
bbd0e548
DW
439 $cell2 = new html_table_cell($this->render($pluginfeedback));
440 $row->cells = array($cell1, $cell2);
441 $t->data[] = $row;
442 }
443 }
444
bbd0e548
DW
445 $o .= html_writer::table($t);
446 $o .= $this->output->box_end();
447
448 $o .= $this->output->container_end();
449 return $o;
450 }
451
bb690849
DW
452 /**
453 * Render a compact view of the current status of the submission.
454 *
455 * @param assign_submission_status_compact $status
456 * @return string
457 */
458 public function render_assign_submission_status_compact(assign_submission_status_compact $status) {
459 $o = '';
460 $o .= $this->output->container_start('submissionstatustable');
461 $o .= $this->output->heading(get_string('submission', 'assign'), 3);
462 $time = time();
463
464 if ($status->teamsubmissionenabled) {
465 $group = $status->submissiongroup;
466 if ($group) {
467 $team = format_string($group->name, false, $status->context);
468 } else if ($status->preventsubmissionnotingroup) {
469 if (count($status->usergroups) == 0) {
470 $team = '<span class="alert alert-error">' . get_string('noteam', 'assign') . '</span>';
471 } else if (count($status->usergroups) > 1) {
472 $team = '<span class="alert alert-error">' . get_string('multipleteams', 'assign') . '</span>';
473 }
474 } else {
475 $team = get_string('defaultteam', 'assign');
476 }
477 $o .= $this->output->container(get_string('teamname', 'assign', $team), 'teamname');
478 }
479
480 if (!$status->teamsubmissionenabled) {
481 if ($status->submission && $status->submission->status != ASSIGN_SUBMISSION_STATUS_NEW) {
482 $statusstr = get_string('submissionstatus_' . $status->submission->status, 'assign');
483 $o .= $this->output->container($statusstr, 'submissionstatus' . $status->submission->status);
484 } else {
485 if (!$status->submissionsenabled) {
486 $o .= $this->output->container(get_string('noonlinesubmissions', 'assign'), 'submissionstatus');
487 } else {
488 $o .= $this->output->container(get_string('noattempt', 'assign'), 'submissionstatus');
489 }
490 }
491 } else {
492 $group = $status->submissiongroup;
493 if (!$group && $status->preventsubmissionnotingroup) {
494 $o .= $this->output->container(get_string('nosubmission', 'assign'), 'submissionstatus');
495 } else if ($status->teamsubmission && $status->teamsubmission->status != ASSIGN_SUBMISSION_STATUS_NEW) {
496 $teamstatus = $status->teamsubmission->status;
497 $submissionsummary = get_string('submissionstatus_' . $teamstatus, 'assign');
498 $groupid = 0;
499 if ($status->submissiongroup) {
500 $groupid = $status->submissiongroup->id;
501 }
502
503 $members = $status->submissiongroupmemberswhoneedtosubmit;
504 $userslist = array();
505 foreach ($members as $member) {
6853cd5e 506 $urlparams = array('id' => $member->id, 'course' => $status->courseid);
bb690849
DW
507 $url = new moodle_url('/user/view.php', $urlparams);
508 if ($status->view == assign_submission_status::GRADER_VIEW && $status->blindmarking) {
509 $userslist[] = $member->alias;
510 } else {
511 $fullname = fullname($member, $status->canviewfullnames);
512 $userslist[] = $this->output->action_link($url, $fullname);
513 }
514 }
515 if (count($userslist) > 0) {
516 $userstr = join(', ', $userslist);
517 $formatteduserstr = get_string('userswhoneedtosubmit', 'assign', $userstr);
518 $submissionsummary .= $this->output->container($formatteduserstr);
519 }
520 $o .= $this->output->container($submissionsummary, 'submissionstatus' . $status->teamsubmission->status);
521 } else {
522 if (!$status->submissionsenabled) {
523 $o .= $this->output->container(get_string('noonlinesubmissions', 'assign'), 'submissionstatus');
524 } else {
525 $o .= $this->output->container(get_string('nosubmission', 'assign'), 'submissionstatus');
526 }
527 }
528 }
529
530 // Is locked?
531 if ($status->locked) {
532 $o .= $this->output->container(get_string('submissionslocked', 'assign'), 'submissionlocked');
533 }
534
535 // Grading status.
536 $statusstr = '';
537 $classname = 'gradingstatus';
538 if ($status->gradingstatus == ASSIGN_GRADING_STATUS_GRADED ||
539 $status->gradingstatus == ASSIGN_GRADING_STATUS_NOT_GRADED) {
540 $statusstr = get_string($status->gradingstatus, 'assign');
541 } else {
542 $gradingstatus = 'markingworkflowstate' . $status->gradingstatus;
543 $statusstr = get_string($gradingstatus, 'assign');
544 }
545 if ($status->gradingstatus == ASSIGN_GRADING_STATUS_GRADED ||
546 $status->gradingstatus == ASSIGN_MARKING_WORKFLOW_STATE_RELEASED) {
547 $classname = 'submissiongraded';
548 } else {
549 $classname = 'submissionnotgraded';
550 }
551 $o .= $this->output->container($statusstr, $classname);
552
553 $submission = $status->teamsubmission ? $status->teamsubmission : $status->submission;
554 $duedate = $status->duedate;
555 if ($duedate > 0) {
556
557 if ($status->extensionduedate) {
558 // Extension date.
559 $duedate = $status->extensionduedate;
560 }
561
562 // Time remaining.
563 $classname = 'timeremaining';
564 if ($duedate - $time <= 0) {
565 if (!$submission ||
566 $submission->status != ASSIGN_SUBMISSION_STATUS_SUBMITTED) {
567 if ($status->submissionsenabled) {
568 $remaining = get_string('overdue', 'assign', format_time($time - $duedate));
569 $classname = 'overdue';
570 } else {
571 $remaining = get_string('duedatereached', 'assign');
572 }
573 } else {
574 if ($submission->timemodified > $duedate) {
575 $remaining = get_string('submittedlate',
576 'assign',
577 format_time($submission->timemodified - $duedate));
578 $classname = 'latesubmission';
579 } else {
580 $remaining = get_string('submittedearly',
581 'assign',
582 format_time($submission->timemodified - $duedate));
583 $classname = 'earlysubmission';
584 }
585 }
586 } else {
587 $remaining = get_string('paramtimeremaining', 'assign', format_time($duedate - $time));
588 }
589 $o .= $this->output->container($remaining, $classname);
590 }
591
592 // Show graders whether this submission is editable by students.
593 if ($status->view == assign_submission_status::GRADER_VIEW) {
594 if ($status->canedit) {
595 $o .= $this->output->container(get_string('submissioneditable', 'assign'), 'submissioneditable');
596 } else {
597 $o .= $this->output->container(get_string('submissionnoteditable', 'assign'), 'submissionnoteditable');
598 }
599 }
600
601 // Grading criteria preview.
602 if (!empty($status->gradingcontrollerpreview)) {
603 $o .= $this->output->container($status->gradingcontrollerpreview, 'gradingmethodpreview');
604 }
605
606 if ($submission) {
607
608 if (!$status->teamsubmission || $status->submissiongroup != false || !$status->preventsubmissionnotingroup) {
609 foreach ($status->submissionplugins as $plugin) {
610 $pluginshowsummary = !$plugin->is_empty($submission) || !$plugin->allow_submissions();
611 if ($plugin->is_enabled() &&
612 $plugin->is_visible() &&
613 $plugin->has_user_summary() &&
614 $pluginshowsummary
615 ) {
616
617 $displaymode = assign_submission_plugin_submission::SUMMARY;
618 $pluginsubmission = new assign_submission_plugin_submission($plugin,
619 $submission,
620 $displaymode,
621 $status->coursemoduleid,
622 $status->returnaction,
623 $status->returnparams);
624 $plugincomponent = $plugin->get_subtype() . '_' . $plugin->get_type();
625 $o .= $this->output->container($this->render($pluginsubmission), 'assignsubmission ' . $plugincomponent);
626 }
627 }
628 }
629 }
630
631 $o .= $this->output->container_end();
632 return $o;
633 }
634
bbd0e548 635 /**
e5403f8c 636 * Render a table containing the current status of the submission.
bbd0e548
DW
637 *
638 * @param assign_submission_status $status
639 * @return string
640 */
641 public function render_assign_submission_status(assign_submission_status $status) {
642 $o = '';
643 $o .= $this->output->container_start('submissionstatustable');
644 $o .= $this->output->heading(get_string('submissionstatusheading', 'assign'), 3);
645 $time = time();
646
647 if ($status->allowsubmissionsfromdate &&
648 $time <= $status->allowsubmissionsfromdate) {
649 $o .= $this->output->box_start('generalbox boxaligncenter submissionsalloweddates');
650 if ($status->alwaysshowdescription) {
e5403f8c
DW
651 $date = userdate($status->allowsubmissionsfromdate);
652 $o .= get_string('allowsubmissionsfromdatesummary', 'assign', $date);
bbd0e548 653 } else {
e5403f8c
DW
654 $date = userdate($status->allowsubmissionsfromdate);
655 $o .= get_string('allowsubmissionsanddescriptionfromdatesummary', 'assign', $date);
bbd0e548
DW
656 }
657 $o .= $this->output->box_end();
658 }
659 $o .= $this->output->box_start('boxaligncenter submissionsummarytable');
660
661 $t = new html_table();
662
e7f3fd59 663 $warningmsg = '';
12a1a0da
DW
664 if ($status->teamsubmissionenabled) {
665 $row = new html_table_row();
666 $cell1 = new html_table_cell(get_string('submissionteam', 'assign'));
667 $group = $status->submissiongroup;
668 if ($group) {
669 $cell2 = new html_table_cell(format_string($group->name, false, $status->context));
e528997a 670 } else if ($status->preventsubmissionnotingroup) {
ee5d4eef 671 if (count($status->usergroups) == 0) {
255d3aaa
DS
672 $notification = new \core\output\notification(get_string('noteam', 'assign'), 'error');
673 $notification->set_show_closebutton(false);
08a54173 674 $cell2 = new html_table_cell(
255d3aaa 675 $this->output->render($notification)
08a54173 676 );
e7f3fd59 677 $warningmsg = $this->output->notification(get_string('noteam_desc', 'assign'), 'error');
ee5d4eef 678 } else if (count($status->usergroups) > 1) {
255d3aaa
DS
679 $notification = new \core\output\notification(get_string('multipleteams', 'assign'), 'error');
680 $notification->set_show_closebutton(false);
08a54173 681 $cell2 = new html_table_cell(
255d3aaa 682 $this->output->render($notification)
08a54173 683 );
e7f3fd59 684 $warningmsg = $this->output->notification(get_string('multipleteams_desc', 'assign'), 'error');
ee5d4eef 685 }
12a1a0da
DW
686 } else {
687 $cell2 = new html_table_cell(get_string('defaultteam', 'assign'));
688 }
689 $row->cells = array($cell1, $cell2);
690 $t->data[] = $row;
691 }
692
df211804
DW
693 if ($status->attemptreopenmethod != ASSIGN_ATTEMPT_REOPEN_METHOD_NONE) {
694 $currentattempt = 1;
695 if (!$status->teamsubmissionenabled) {
696 if ($status->submission) {
697 $currentattempt = $status->submission->attemptnumber + 1;
698 }
699 } else {
700 if ($status->teamsubmission) {
701 $currentattempt = $status->teamsubmission->attemptnumber + 1;
702 }
703 }
704
705 $row = new html_table_row();
706 $cell1 = new html_table_cell(get_string('attemptnumber', 'assign'));
707 $maxattempts = $status->maxattempts;
708 if ($maxattempts == ASSIGN_UNLIMITED_ATTEMPTS) {
709 $message = get_string('currentattempt', 'assign', $currentattempt);
710 } else {
711 $message = get_string('currentattemptof', 'assign', array('attemptnumber'=>$currentattempt,
712 'maxattempts'=>$maxattempts));
713 }
714 $cell2 = new html_table_cell($message);
715 $row->cells = array($cell1, $cell2);
716 $t->data[] = $row;
717 }
718
bbd0e548
DW
719 $row = new html_table_row();
720 $cell1 = new html_table_cell(get_string('submissionstatus', 'assign'));
12a1a0da 721 if (!$status->teamsubmissionenabled) {
9e3eee67 722 if ($status->submission && $status->submission->status != ASSIGN_SUBMISSION_STATUS_NEW) {
e5403f8c
DW
723 $statusstr = get_string('submissionstatus_' . $status->submission->status, 'assign');
724 $cell2 = new html_table_cell($statusstr);
12a1a0da
DW
725 $cell2->attributes = array('class'=>'submissionstatus' . $status->submission->status);
726 } else {
727 if (!$status->submissionsenabled) {
728 $cell2 = new html_table_cell(get_string('noonlinesubmissions', 'assign'));
729 } else {
df211804 730 $cell2 = new html_table_cell(get_string('noattempt', 'assign'));
12a1a0da
DW
731 }
732 }
733 $row->cells = array($cell1, $cell2);
734 $t->data[] = $row;
bbd0e548 735 } else {
12a1a0da
DW
736 $row = new html_table_row();
737 $cell1 = new html_table_cell(get_string('submissionstatus', 'assign'));
e528997a
AH
738 $group = $status->submissiongroup;
739 if (!$group && $status->preventsubmissionnotingroup) {
740 $cell2 = new html_table_cell(get_string('nosubmission', 'assign'));
741 } else if ($status->teamsubmission && $status->teamsubmission->status != ASSIGN_SUBMISSION_STATUS_NEW) {
e5403f8c
DW
742 $teamstatus = $status->teamsubmission->status;
743 $submissionsummary = get_string('submissionstatus_' . $teamstatus, 'assign');
12a1a0da
DW
744 $groupid = 0;
745 if ($status->submissiongroup) {
746 $groupid = $status->submissiongroup->id;
747 }
748
749 $members = $status->submissiongroupmemberswhoneedtosubmit;
750 $userslist = array();
751 foreach ($members as $member) {
e5403f8c
DW
752 $urlparams = array('id' => $member->id, 'course'=>$status->courseid);
753 $url = new moodle_url('/user/view.php', $urlparams);
88cfe469
DW
754 if ($status->view == assign_submission_status::GRADER_VIEW && $status->blindmarking) {
755 $userslist[] = $member->alias;
756 } else {
e5403f8c
DW
757 $fullname = fullname($member, $status->canviewfullnames);
758 $userslist[] = $this->output->action_link($url, $fullname);
88cfe469 759 }
12a1a0da
DW
760 }
761 if (count($userslist) > 0) {
762 $userstr = join(', ', $userslist);
e5403f8c
DW
763 $formatteduserstr = get_string('userswhoneedtosubmit', 'assign', $userstr);
764 $submissionsummary .= $this->output->container($formatteduserstr);
12a1a0da
DW
765 }
766
767 $cell2 = new html_table_cell($submissionsummary);
768 $cell2->attributes = array('class'=>'submissionstatus' . $status->teamsubmission->status);
bbd0e548
DW
769 } else {
770 $cell2 = new html_table_cell(get_string('nosubmission', 'assign'));
12a1a0da
DW
771 if (!$status->submissionsenabled) {
772 $cell2 = new html_table_cell(get_string('noonlinesubmissions', 'assign'));
773 } else {
774 $cell2 = new html_table_cell(get_string('nosubmission', 'assign'));
775 }
bbd0e548 776 }
12a1a0da
DW
777 $row->cells = array($cell1, $cell2);
778 $t->data[] = $row;
bbd0e548 779 }
bbd0e548 780
e5403f8c 781 // Is locked?
bbd0e548
DW
782 if ($status->locked) {
783 $row = new html_table_row();
784 $cell1 = new html_table_cell();
785 $cell2 = new html_table_cell(get_string('submissionslocked', 'assign'));
786 $cell2->attributes = array('class'=>'submissionlocked');
787 $row->cells = array($cell1, $cell2);
788 $t->data[] = $row;
789 }
790
e5403f8c 791 // Grading status.
bbd0e548
DW
792 $row = new html_table_row();
793 $cell1 = new html_table_cell(get_string('gradingstatus', 'assign'));
794
bd3ee807
MN
795 if ($status->gradingstatus == ASSIGN_GRADING_STATUS_GRADED ||
796 $status->gradingstatus == ASSIGN_GRADING_STATUS_NOT_GRADED) {
797 $cell2 = new html_table_cell(get_string($status->gradingstatus, 'assign'));
bbd0e548 798 } else {
bd3ee807
MN
799 $gradingstatus = 'markingworkflowstate' . $status->gradingstatus;
800 $cell2 = new html_table_cell(get_string($gradingstatus, 'assign'));
801 }
802 if ($status->gradingstatus == ASSIGN_GRADING_STATUS_GRADED ||
803 $status->gradingstatus == ASSIGN_MARKING_WORKFLOW_STATE_RELEASED) {
804 $cell2->attributes = array('class' => 'submissiongraded');
805 } else {
806 $cell2->attributes = array('class' => 'submissionnotgraded');
bbd0e548
DW
807 }
808 $row->cells = array($cell1, $cell2);
809 $t->data[] = $row;
810
79397b56 811 $submission = $status->teamsubmission ? $status->teamsubmission : $status->submission;
bbd0e548 812 $duedate = $status->duedate;
9e795179 813 if ($duedate > 0) {
e5403f8c 814 // Due date.
bbd0e548
DW
815 $row = new html_table_row();
816 $cell1 = new html_table_cell(get_string('duedate', 'assign'));
817 $cell2 = new html_table_cell(userdate($duedate));
818 $row->cells = array($cell1, $cell2);
819 $t->data[] = $row;
820
9e795179
DW
821 if ($status->view == assign_submission_status::GRADER_VIEW) {
822 if ($status->cutoffdate) {
e5403f8c 823 // Cut off date.
9e795179
DW
824 $row = new html_table_row();
825 $cell1 = new html_table_cell(get_string('cutoffdate', 'assign'));
826 $cell2 = new html_table_cell(userdate($status->cutoffdate));
827 $row->cells = array($cell1, $cell2);
828 $t->data[] = $row;
829 }
830 }
831
832 if ($status->extensionduedate) {
e5403f8c 833 // Extension date.
9e795179
DW
834 $row = new html_table_row();
835 $cell1 = new html_table_cell(get_string('extensionduedate', 'assign'));
836 $cell2 = new html_table_cell(userdate($status->extensionduedate));
837 $row->cells = array($cell1, $cell2);
838 $t->data[] = $row;
839 $duedate = $status->extensionduedate;
840 }
841
842 // Time remaining.
bbd0e548
DW
843 $row = new html_table_row();
844 $cell1 = new html_table_cell(get_string('timeremaining', 'assign'));
845 if ($duedate - $time <= 0) {
79397b56
DB
846 if (!$submission ||
847 $submission->status != ASSIGN_SUBMISSION_STATUS_SUBMITTED) {
bbd0e548 848 if ($status->submissionsenabled) {
e5403f8c
DW
849 $overduestr = get_string('overdue', 'assign', format_time($time - $duedate));
850 $cell2 = new html_table_cell($overduestr);
bbd0e548
DW
851 $cell2->attributes = array('class'=>'overdue');
852 } else {
853 $cell2 = new html_table_cell(get_string('duedatereached', 'assign'));
854 }
855 } else {
79397b56 856 if ($submission->timemodified > $duedate) {
e5403f8c
DW
857 $latestr = get_string('submittedlate',
858 'assign',
79397b56 859 format_time($submission->timemodified - $duedate));
e5403f8c 860 $cell2 = new html_table_cell($latestr);
bbd0e548
DW
861 $cell2->attributes = array('class'=>'latesubmission');
862 } else {
e5403f8c
DW
863 $earlystr = get_string('submittedearly',
864 'assign',
79397b56 865 format_time($submission->timemodified - $duedate));
e5403f8c 866 $cell2 = new html_table_cell($earlystr);
bbd0e548
DW
867 $cell2->attributes = array('class'=>'earlysubmission');
868 }
869 }
870 } else {
871 $cell2 = new html_table_cell(format_time($duedate - $time));
872 }
873 $row->cells = array($cell1, $cell2);
874 $t->data[] = $row;
875 }
876
9e795179
DW
877 // Show graders whether this submission is editable by students.
878 if ($status->view == assign_submission_status::GRADER_VIEW) {
879 $row = new html_table_row();
848ade1d 880 $cell1 = new html_table_cell(get_string('editingstatus', 'assign'));
9e795179
DW
881 if ($status->canedit) {
882 $cell2 = new html_table_cell(get_string('submissioneditable', 'assign'));
883 $cell2->attributes = array('class'=>'submissioneditable');
884 } else {
885 $cell2 = new html_table_cell(get_string('submissionnoteditable', 'assign'));
886 $cell2->attributes = array('class'=>'submissionnoteditable');
887 }
6c712479
DW
888 $row->cells = array($cell1, $cell2);
889 $t->data[] = $row;
ec32d068
RW
890 }
891
892 // Grading criteria preview.
893 if (!empty($status->gradingcontrollerpreview)) {
894 $row = new html_table_row();
895 $cell1 = new html_table_cell(get_string('gradingmethodpreview', 'assign'));
896 $cell2 = new html_table_cell($status->gradingcontrollerpreview);
9e795179
DW
897 $row->cells = array($cell1, $cell2);
898 $t->data[] = $row;
899 }
900
901 // Last modified.
12a1a0da 902 if ($submission) {
bbd0e548
DW
903 $row = new html_table_row();
904 $cell1 = new html_table_cell(get_string('timemodified', 'assign'));
232b26f0
CS
905
906 if ($submission->status != ASSIGN_SUBMISSION_STATUS_NEW) {
907 $cell2 = new html_table_cell(userdate($submission->timemodified));
908 } else {
909 $cell2 = new html_table_cell('-');
910 }
911
bbd0e548
DW
912 $row->cells = array($cell1, $cell2);
913 $t->data[] = $row;
914
e528997a
AH
915 if (!$status->teamsubmission || $status->submissiongroup != false || !$status->preventsubmissionnotingroup) {
916 foreach ($status->submissionplugins as $plugin) {
917 $pluginshowsummary = !$plugin->is_empty($submission) || !$plugin->allow_submissions();
918 if ($plugin->is_enabled() &&
919 $plugin->is_visible() &&
920 $plugin->has_user_summary() &&
921 $pluginshowsummary
922 ) {
923
924 $row = new html_table_row();
925 $cell1 = new html_table_cell($plugin->get_name());
926 $displaymode = assign_submission_plugin_submission::SUMMARY;
927 $pluginsubmission = new assign_submission_plugin_submission($plugin,
928 $submission,
929 $displaymode,
930 $status->coursemoduleid,
931 $status->returnaction,
932 $status->returnparams);
933 $cell2 = new html_table_cell($this->render($pluginsubmission));
934 $row->cells = array($cell1, $cell2);
935 $t->data[] = $row;
936 }
bbd0e548
DW
937 }
938 }
939 }
940
e7f3fd59 941 $o .= $warningmsg;
bbd0e548
DW
942 $o .= html_writer::table($t);
943 $o .= $this->output->box_end();
944
9e795179
DW
945 // Links.
946 if ($status->view == assign_submission_status::STUDENT_VIEW) {
947 if ($status->canedit) {
9e3eee67 948 if (!$submission || $submission->status == ASSIGN_SUBMISSION_STATUS_NEW) {
df211804 949 $o .= $this->output->box_start('generalbox submissionaction');
9e795179
DW
950 $urlparams = array('id' => $status->coursemoduleid, 'action' => 'editsubmission');
951 $o .= $this->output->single_button(new moodle_url('/mod/assign/view.php', $urlparams),
952 get_string('addsubmission', 'assign'), 'get');
df211804 953 $o .= $this->output->box_start('boxaligncenter submithelp');
464ddd07 954 $o .= get_string('addsubmission_help', 'assign');
df211804
DW
955 $o .= $this->output->box_end();
956 $o .= $this->output->box_end();
957 } else if ($submission->status == ASSIGN_SUBMISSION_STATUS_REOPENED) {
958 $o .= $this->output->box_start('generalbox submissionaction');
e9fe65d5
DW
959 $urlparams = array('id' => $status->coursemoduleid,
960 'action' => 'editprevioussubmission',
961 'sesskey'=>sesskey());
df211804
DW
962 $o .= $this->output->single_button(new moodle_url('/mod/assign/view.php', $urlparams),
963 get_string('addnewattemptfromprevious', 'assign'), 'get');
964 $o .= $this->output->box_start('boxaligncenter submithelp');
965 $o .= get_string('addnewattemptfromprevious_help', 'assign');
966 $o .= $this->output->box_end();
967 $o .= $this->output->box_end();
968 $o .= $this->output->box_start('generalbox submissionaction');
969 $urlparams = array('id' => $status->coursemoduleid, 'action' => 'editsubmission');
970 $o .= $this->output->single_button(new moodle_url('/mod/assign/view.php', $urlparams),
971 get_string('addnewattempt', 'assign'), 'get');
972 $o .= $this->output->box_start('boxaligncenter submithelp');
973 $o .= get_string('addnewattempt_help', 'assign');
974 $o .= $this->output->box_end();
975 $o .= $this->output->box_end();
9e795179 976 } else {
df211804 977 $o .= $this->output->box_start('generalbox submissionaction');
9e795179
DW
978 $urlparams = array('id' => $status->coursemoduleid, 'action' => 'editsubmission');
979 $o .= $this->output->single_button(new moodle_url('/mod/assign/view.php', $urlparams),
980 get_string('editsubmission', 'assign'), 'get');
37fc47f1
DW
981 $urlparams = array('id' => $status->coursemoduleid, 'action' => 'removesubmissionconfirm');
982 $o .= $this->output->single_button(new moodle_url('/mod/assign/view.php', $urlparams),
983 get_string('removesubmission', 'assign'), 'get');
df211804
DW
984 $o .= $this->output->box_start('boxaligncenter submithelp');
985 $o .= get_string('editsubmission_help', 'assign');
986 $o .= $this->output->box_end();
987 $o .= $this->output->box_end();
9e795179 988 }
caff10a0 989 }
bbd0e548 990
9e795179
DW
991 if ($status->cansubmit) {
992 $urlparams = array('id' => $status->coursemoduleid, 'action'=>'submit');
df211804 993 $o .= $this->output->box_start('generalbox submissionaction');
9e795179
DW
994 $o .= $this->output->single_button(new moodle_url('/mod/assign/view.php', $urlparams),
995 get_string('submitassignment', 'assign'), 'get');
996 $o .= $this->output->box_start('boxaligncenter submithelp');
997 $o .= get_string('submitassignment_help', 'assign');
998 $o .= $this->output->box_end();
df211804 999 $o .= $this->output->box_end();
9e795179 1000 }
bbd0e548
DW
1001 }
1002
1003 $o .= $this->output->container_end();
1004 return $o;
1005 }
1006
bb690849
DW
1007 /**
1008 * Output the attempt history chooser for this assignment
1009 *
1010 * @param assign_attempt_history_chooser $history
1011 * @return string
1012 */
1013 public function render_assign_attempt_history_chooser(assign_attempt_history_chooser $history) {
1014 $o = '';
1015
1016 $context = $history->export_for_template($this);
1017 $o .= $this->render_from_template('mod_assign/attempt_history_chooser', $context);
1018
1019 return $o;
1020 }
1021
df211804
DW
1022 /**
1023 * Output the attempt history for this assignment
1024 *
1025 * @param assign_attempt_history $history
1026 * @return string
1027 */
1028 public function render_assign_attempt_history(assign_attempt_history $history) {
1029 $o = '';
1030
1031 $submittedstr = get_string('submitted', 'assign');
1032 $gradestr = get_string('grade');
1033 $gradedonstr = get_string('gradedon', 'assign');
1034 $gradedbystr = get_string('gradedby', 'assign');
1035
1036 // Don't show the last one because it is the current submission.
1037 array_pop($history->submissions);
1038
1039 // Show newest to oldest.
1040 $history->submissions = array_reverse($history->submissions);
1041
1042 if (empty($history->submissions)) {
1043 return '';
1044 }
1045
1046 $containerid = 'attempthistory' . uniqid();
bb690849 1047 $o .= $this->output->heading(get_string('attempthistory', 'assign'), 3);
df211804
DW
1048 $o .= $this->box_start('attempthistory', $containerid);
1049
1050 foreach ($history->submissions as $i => $submission) {
1051 $grade = null;
1052 foreach ($history->grades as $onegrade) {
1053 if ($onegrade->attemptnumber == $submission->attemptnumber) {
e6a93dc2
DM
1054 if ($onegrade->grade != ASSIGN_GRADE_NOT_SET) {
1055 $grade = $onegrade;
1056 }
df211804
DW
1057 break;
1058 }
1059 }
1060
1061 $editbtn = '';
1062
1063 if ($submission) {
1064 $submissionsummary = userdate($submission->timemodified);
1065 } else {
1066 $submissionsummary = get_string('nosubmission', 'assign');
1067 }
1068
1069 $attemptsummaryparams = array('attemptnumber'=>$submission->attemptnumber+1,
1070 'submissionsummary'=>$submissionsummary);
1071 $o .= $this->heading(get_string('attemptheading', 'assign', $attemptsummaryparams), 4);
1072
1073 $t = new html_table();
1074
1075 if ($submission) {
1076 $cell1 = new html_table_cell(get_string('submissionstatus', 'assign'));
1077 $cell2 = new html_table_cell(get_string('submissionstatus_' . $submission->status, 'assign'));
1078 $t->data[] = new html_table_row(array($cell1, $cell2));
1079
1080 foreach ($history->submissionplugins as $plugin) {
1081 $pluginshowsummary = !$plugin->is_empty($submission) || !$plugin->allow_submissions();
1082 if ($plugin->is_enabled() &&
1083 $plugin->is_visible() &&
1084 $plugin->has_user_summary() &&
1085 $pluginshowsummary) {
1086
1087 $cell1 = new html_table_cell($plugin->get_name());
1088 $pluginsubmission = new assign_submission_plugin_submission($plugin,
1089 $submission,
1090 assign_submission_plugin_submission::SUMMARY,
1091 $history->coursemoduleid,
1092 $history->returnaction,
1093 $history->returnparams);
1094 $cell2 = new html_table_cell($this->render($pluginsubmission));
1095
1096 $t->data[] = new html_table_row(array($cell1, $cell2));
1097 }
1098 }
1099 }
1100
1101 if ($grade) {
1102 // Heading 'feedback'.
1103 $title = get_string('feedback', 'assign', $i);
1104 $title .= $this->output->spacer(array('width'=>10));
1105 if ($history->cangrade) {
1106 // Edit previous feedback.
1107 $returnparams = http_build_query($history->returnparams);
1108 $urlparams = array('id' => $history->coursemoduleid,
99758819
DW
1109 'rownum'=>$history->rownum,
1110 'useridlistid'=>$history->useridlistid,
df211804
DW
1111 'attemptnumber'=>$grade->attemptnumber,
1112 'action'=>'grade',
df211804
DW
1113 'returnaction'=>$history->returnaction,
1114 'returnparams'=>$returnparams);
1115 $url = new moodle_url('/mod/assign/view.php', $urlparams);
1116 $icon = new pix_icon('gradefeedback',
1117 get_string('editattemptfeedback', 'assign', $grade->attemptnumber+1),
1118 'mod_assign');
1119 $title .= $this->output->action_icon($url, $icon);
1120 }
1121 $cell = new html_table_cell($title);
1122 $cell->attributes['class'] = 'feedbacktitle';
1123 $cell->colspan = 2;
1124 $t->data[] = new html_table_row(array($cell));
1125
1126 // Grade.
1127 $cell1 = new html_table_cell($gradestr);
1128 $cell2 = $grade->gradefordisplay;
1129 $t->data[] = new html_table_row(array($cell1, $cell2));
1130
1131 // Graded on.
1132 $cell1 = new html_table_cell($gradedonstr);
1133 $cell2 = new html_table_cell(userdate($grade->timemodified));
1134 $t->data[] = new html_table_row(array($cell1, $cell2));
1135
13543706
DW
1136 // Graded by set to a real user. Not set can be empty or -1.
1137 if (!empty($grade->grader) && is_object($grade->grader)) {
1138 $cell1 = new html_table_cell($gradedbystr);
1139 $cell2 = new html_table_cell($this->output->user_picture($grade->grader) .
1140 $this->output->spacer(array('width' => 30)) . fullname($grade->grader));
1141 $t->data[] = new html_table_row(array($cell1, $cell2));
1142 }
df211804
DW
1143
1144 // Feedback from plugins.
1145 foreach ($history->feedbackplugins as $plugin) {
1146 if ($plugin->is_enabled() &&
1147 $plugin->is_visible() &&
1148 $plugin->has_user_summary() &&
1149 !$plugin->is_empty($grade)) {
1150
1151 $cell1 = new html_table_cell($plugin->get_name());
1152 $pluginfeedback = new assign_feedback_plugin_feedback(
1153 $plugin, $grade, assign_feedback_plugin_feedback::SUMMARY, $history->coursemoduleid,
1154 $history->returnaction, $history->returnparams
1155 );
1156 $cell2 = new html_table_cell($this->render($pluginfeedback));
1157 $t->data[] = new html_table_row(array($cell1, $cell2));
1158 }
1159
1160 }
1161
1162 }
1163
1164 $o .= html_writer::table($t);
1165 }
1166 $o .= $this->box_end();
1167 $jsparams = array($containerid);
1168
1169 $this->page->requires->yui_module('moodle-mod_assign-history', 'Y.one("#' . $containerid . '").history');
1170
1171 return $o;
1172 }
1173
bbd0e548 1174 /**
e5403f8c 1175 * Render a submission plugin submission
bbd0e548
DW
1176 *
1177 * @param assign_submission_plugin_submission $submissionplugin
1178 * @return string
1179 */
1180 public function render_assign_submission_plugin_submission(assign_submission_plugin_submission $submissionplugin) {
1181 $o = '';
1182
1183 if ($submissionplugin->view == assign_submission_plugin_submission::SUMMARY) {
bbd0e548 1184 $showviewlink = false;
e5403f8c
DW
1185 $summary = $submissionplugin->plugin->view_summary($submissionplugin->submission,
1186 $showviewlink);
1187
1188 $classsuffix = $submissionplugin->plugin->get_subtype() .
1189 '_' .
1190 $submissionplugin->plugin->get_type() .
1191 '_' .
1192 $submissionplugin->submission->id;
66d3fe37 1193
66d3fe37
DW
1194 $o .= $this->output->box_start('boxaligncenter plugincontentsummary summary_' . $classsuffix);
1195
1196 $link = '';
bbd0e548 1197 if ($showviewlink) {
66d3fe37
DW
1198 $previewstr = get_string('viewsubmission', 'assign');
1199 $icon = $this->output->pix_icon('t/preview', $previewstr);
1200
1201 $expandstr = get_string('viewfull', 'assign');
e5403f8c
DW
1202 $options = array('class'=>'expandsummaryicon expand_' . $classsuffix);
1203 $o .= $this->output->pix_icon('t/switch_plus', $expandstr, null, $options);
66d3fe37
DW
1204
1205 $jsparams = array($submissionplugin->plugin->get_subtype(),
1206 $submissionplugin->plugin->get_type(),
1207 $submissionplugin->submission->id);
e5403f8c 1208
66d3fe37
DW
1209 $this->page->requires->js_init_call('M.mod_assign.init_plugin_summary', $jsparams);
1210
e5403f8c
DW
1211 $action = 'viewplugin' . $submissionplugin->plugin->get_subtype();
1212 $returnparams = http_build_query($submissionplugin->returnparams);
66d3fe37 1213 $link .= '<noscript>';
e5403f8c
DW
1214 $urlparams = array('id' => $submissionplugin->coursemoduleid,
1215 'sid'=>$submissionplugin->submission->id,
1216 'plugin'=>$submissionplugin->plugin->get_type(),
1217 'action'=>$action,
1218 'returnaction'=>$submissionplugin->returnaction,
1219 'returnparams'=>$returnparams);
1220 $url = new moodle_url('/mod/assign/view.php', $urlparams);
1221 $link .= $this->output->action_link($url, $icon);
66d3fe37 1222 $link .= '</noscript>';
bbd0e548
DW
1223
1224 $link .= $this->output->spacer(array('width'=>15));
1225 }
1226
1227 $o .= $link . $summary;
66d3fe37
DW
1228 $o .= $this->output->box_end();
1229 if ($showviewlink) {
1230 $o .= $this->output->box_start('boxaligncenter hidefull full_' . $classsuffix);
1231 $classes = 'expandsummaryicon contract_' . $classsuffix;
1232 $o .= $this->output->pix_icon('t/switch_minus',
1233 get_string('viewsummary', 'assign'),
1234 null,
1235 array('class'=>$classes));
1236 $o .= $submissionplugin->plugin->view($submissionplugin->submission);
1237 $o .= $this->output->box_end();
1238 }
bbd0e548
DW
1239 } else if ($submissionplugin->view == assign_submission_plugin_submission::FULL) {
1240 $o .= $this->output->box_start('boxaligncenter submissionfull');
1241 $o .= $submissionplugin->plugin->view($submissionplugin->submission);
1242 $o .= $this->output->box_end();
1243 }
1244
1245 return $o;
1246 }
1247
1248 /**
e5403f8c 1249 * Render the grading table.
bbd0e548
DW
1250 *
1251 * @param assign_grading_table $table
1252 * @return string
1253 */
1254 public function render_assign_grading_table(assign_grading_table $table) {
1255 $o = '';
1256 $o .= $this->output->box_start('boxaligncenter gradingtable');
df47b77f 1257
bbd0e548
DW
1258 $this->page->requires->js_init_call('M.mod_assign.init_grading_table', array());
1259 $this->page->requires->string_for_js('nousersselected', 'assign');
9e795179 1260 $this->page->requires->string_for_js('batchoperationconfirmgrantextension', 'assign');
bbd0e548 1261 $this->page->requires->string_for_js('batchoperationconfirmlock', 'assign');
37fc47f1 1262 $this->page->requires->string_for_js('batchoperationconfirmremovesubmission', 'assign');
bbd0e548 1263 $this->page->requires->string_for_js('batchoperationconfirmreverttodraft', 'assign');
9e795179 1264 $this->page->requires->string_for_js('batchoperationconfirmunlock', 'assign');
df211804 1265 $this->page->requires->string_for_js('batchoperationconfirmaddattempt', 'assign');
d0d8a2da 1266 $this->page->requires->string_for_js('batchoperationconfirmdownloadselected', 'assign');
f8d107b3
DM
1267 $this->page->requires->string_for_js('batchoperationconfirmsetmarkingworkflowstate', 'assign');
1268 $this->page->requires->string_for_js('batchoperationconfirmsetmarkingallocation', 'assign');
bbd0e548 1269 $this->page->requires->string_for_js('editaction', 'assign');
df47b77f
DW
1270 foreach ($table->plugingradingbatchoperations as $plugin => $operations) {
1271 foreach ($operations as $operation => $description) {
e5403f8c
DW
1272 $this->page->requires->string_for_js('batchoperationconfirm' . $operation,
1273 'assignfeedback_' . $plugin);
df47b77f
DW
1274 }
1275 }
bbd0e548
DW
1276 $o .= $this->flexible_table($table, $table->get_rows_per_page(), true);
1277 $o .= $this->output->box_end();
1278
1279 return $o;
e5403f8c 1280 }
bbd0e548
DW
1281
1282 /**
1283 * Render a feedback plugin feedback
1284 *
1285 * @param assign_feedback_plugin_feedback $feedbackplugin
1286 * @return string
1287 */
1288 public function render_assign_feedback_plugin_feedback(assign_feedback_plugin_feedback $feedbackplugin) {
1289 $o = '';
1290
1291 if ($feedbackplugin->view == assign_feedback_plugin_feedback::SUMMARY) {
bbd0e548
DW
1292 $showviewlink = false;
1293 $summary = $feedbackplugin->plugin->view_summary($feedbackplugin->grade, $showviewlink);
66d3fe37 1294
e5403f8c
DW
1295 $classsuffix = $feedbackplugin->plugin->get_subtype() .
1296 '_' .
1297 $feedbackplugin->plugin->get_type() .
1298 '_' .
1299 $feedbackplugin->grade->id;
66d3fe37
DW
1300 $o .= $this->output->box_start('boxaligncenter plugincontentsummary summary_' . $classsuffix);
1301
1302 $link = '';
bbd0e548 1303 if ($showviewlink) {
66d3fe37
DW
1304 $previewstr = get_string('viewfeedback', 'assign');
1305 $icon = $this->output->pix_icon('t/preview', $previewstr);
1306
1307 $expandstr = get_string('viewfull', 'assign');
e5403f8c
DW
1308 $options = array('class'=>'expandsummaryicon expand_' . $classsuffix);
1309 $o .= $this->output->pix_icon('t/switch_plus', $expandstr, null, $options);
66d3fe37
DW
1310
1311 $jsparams = array($feedbackplugin->plugin->get_subtype(),
1312 $feedbackplugin->plugin->get_type(),
1313 $feedbackplugin->grade->id);
1314 $this->page->requires->js_init_call('M.mod_assign.init_plugin_summary', $jsparams);
1315
e5403f8c
DW
1316 $urlparams = array('id' => $feedbackplugin->coursemoduleid,
1317 'gid'=>$feedbackplugin->grade->id,
1318 'plugin'=>$feedbackplugin->plugin->get_type(),
1319 'action'=>'viewplugin' . $feedbackplugin->plugin->get_subtype(),
1320 'returnaction'=>$feedbackplugin->returnaction,
1321 'returnparams'=>http_build_query($feedbackplugin->returnparams));
1322 $url = new moodle_url('/mod/assign/view.php', $urlparams);
66d3fe37 1323 $link .= '<noscript>';
e5403f8c 1324 $link .= $this->output->action_link($url, $icon);
66d3fe37
DW
1325 $link .= '</noscript>';
1326
bbd0e548
DW
1327 $link .= $this->output->spacer(array('width'=>15));
1328 }
1329
1330 $o .= $link . $summary;
66d3fe37
DW
1331 $o .= $this->output->box_end();
1332 if ($showviewlink) {
1333 $o .= $this->output->box_start('boxaligncenter hidefull full_' . $classsuffix);
1334 $classes = 'expandsummaryicon contract_' . $classsuffix;
1335 $o .= $this->output->pix_icon('t/switch_minus',
1336 get_string('viewsummary', 'assign'),
1337 null,
1338 array('class'=>$classes));
1339 $o .= $feedbackplugin->plugin->view($feedbackplugin->grade);
1340 $o .= $this->output->box_end();
1341 }
bbd0e548
DW
1342 } else if ($feedbackplugin->view == assign_feedback_plugin_feedback::FULL) {
1343 $o .= $this->output->box_start('boxaligncenter feedbackfull');
1344 $o .= $feedbackplugin->plugin->view($feedbackplugin->grade);
1345 $o .= $this->output->box_end();
1346 }
1347
1348 return $o;
1349 }
1350
64220210
DW
1351 /**
1352 * Render a course index summary
1353 *
1354 * @param assign_course_index_summary $indexsummary
1355 * @return string
1356 */
1357 public function render_assign_course_index_summary(assign_course_index_summary $indexsummary) {
1358 $o = '';
1359
1360 $strplural = get_string('modulenameplural', 'assign');
1361 $strsectionname = $indexsummary->courseformatname;
1362 $strduedate = get_string('duedate', 'assign');
1363 $strsubmission = get_string('submission', 'assign');
1364 $strgrade = get_string('grade');
1365
1366 $table = new html_table();
1367 if ($indexsummary->usesections) {
1368 $table->head = array ($strsectionname, $strplural, $strduedate, $strsubmission, $strgrade);
1369 $table->align = array ('left', 'left', 'center', 'right', 'right');
1370 } else {
1371 $table->head = array ($strplural, $strduedate, $strsubmission, $strgrade);
1372 $table->align = array ('left', 'left', 'center', 'right');
1373 }
1374 $table->data = array();
1375
1376 $currentsection = '';
1377 foreach ($indexsummary->assignments as $info) {
1378 $params = array('id' => $info['cmid']);
1379 $link = html_writer::link(new moodle_url('/mod/assign/view.php', $params),
1380 $info['cmname']);
1381 $due = $info['timedue'] ? userdate($info['timedue']) : '-';
1382
1383 $printsection = '';
1384 if ($indexsummary->usesections) {
1385 if ($info['sectionname'] !== $currentsection) {
1386 if ($info['sectionname']) {
1387 $printsection = $info['sectionname'];
1388 }
1389 if ($currentsection !== '') {
1390 $table->data[] = 'hr';
1391 }
1392 $currentsection = $info['sectionname'];
1393 }
1394 }
1395
1396 if ($indexsummary->usesections) {
1397 $row = array($printsection, $link, $due, $info['submissioninfo'], $info['gradeinfo']);
1398 } else {
1399 $row = array($link, $due, $info['submissioninfo'], $info['gradeinfo']);
1400 }
1401 $table->data[] = $row;
1402 }
1403
1404 $o .= html_writer::table($table);
1405
1406 return $o;
1407 }
1408
bbd0e548
DW
1409
1410
1411 /**
1412 * Internal function - creates htmls structure suitable for YUI tree.
1413 *
1414 * @param assign_files $tree
1415 * @param array $dir
1416 * @return string
1417 */
1418 protected function htmllize_tree(assign_files $tree, $dir) {
1419 global $CFG;
1420 $yuiconfig = array();
1421 $yuiconfig['type'] = 'html';
1422
1423 if (empty($dir['subdirs']) and empty($dir['files'])) {
1424 return '';
1425 }
1426
1427 $result = '<ul>';
1428 foreach ($dir['subdirs'] as $subdir) {
e5403f8c
DW
1429 $image = $this->output->pix_icon(file_folder_icon(),
1430 $subdir['dirname'],
1431 'moodle',
1432 array('class'=>'icon'));
1433 $result .= '<li yuiConfig=\'' . json_encode($yuiconfig) . '\'>' .
1434 '<div>' . $image . ' ' . s($subdir['dirname']) . '</div> ' .
1435 $this->htmllize_tree($tree, $subdir) .
1436 '</li>';
bbd0e548
DW
1437 }
1438
1439 foreach ($dir['files'] as $file) {
1440 $filename = $file->get_filename();
bbd0e548
DW
1441 if ($CFG->enableplagiarism) {
1442 require_once($CFG->libdir.'/plagiarismlib.php');
e5403f8c
DW
1443 $plagiarismlinks = plagiarism_get_links(array('userid'=>$file->get_userid(),
1444 'file'=>$file,
1445 'cmid'=>$tree->cm->id,
1446 'course'=>$tree->course));
bbd0e548 1447 } else {
e5403f8c 1448 $plagiarismlinks = '';
bbd0e548 1449 }
e5403f8c
DW
1450 $image = $this->output->pix_icon(file_file_icon($file),
1451 $filename,
1452 'moodle',
1453 array('class'=>'icon'));
1454 $result .= '<li yuiConfig=\'' . json_encode($yuiconfig) . '\'>' .
403f5536
OI
1455 '<div>' .
1456 '<div class="fileuploadsubmission">' . $image . ' ' .
1457 $file->fileurl . ' ' .
1458 $plagiarismlinks . ' ' .
1459 $file->portfoliobutton . ' ' .
1460 '</div>' .
1461 '<div class="fileuploadsubmissiontime">' . $file->timemodified . '</div>' .
1462 '</div>' .
1463 '</li>';
bbd0e548
DW
1464 }
1465
1466 $result .= '</ul>';
1467
1468 return $result;
1469 }
1470
1471 /**
1472 * Helper method dealing with the fact we can not just fetch the output of flexible_table
1473 *
1474 * @param flexible_table $table The table to render
1475 * @param int $rowsperpage How many assignments to render in a page
e5403f8c
DW
1476 * @param bool $displaylinks - Whether to render links in the table
1477 * (e.g. downloads would not enable this)
bbd0e548
DW
1478 * @return string HTML
1479 */
1480 protected function flexible_table(flexible_table $table, $rowsperpage, $displaylinks) {
1481
1482 $o = '';
1483 ob_start();
1484 $table->out($rowsperpage, $displaylinks);
1485 $o = ob_get_contents();
1486 ob_end_clean();
1487
1488 return $o;
1489 }
1490
1491 /**
1492 * Helper method dealing with the fact we can not just fetch the output of moodleforms
1493 *
1494 * @param moodleform $mform
1495 * @return string HTML
1496 */
1497 protected function moodleform(moodleform $mform) {
1498
1499 $o = '';
1500 ob_start();
1501 $mform->display();
1502 $o = ob_get_contents();
1503 ob_end_clean();
1504
1505 return $o;
1506 }
1507
bb690849
DW
1508 /**
1509 * Defer to template..
1510 *
6853cd5e 1511 * @param grading_app $app - All the data to render the grading app.
bb690849
DW
1512 */
1513 public function render_grading_app(grading_app $app) {
1514 $context = $app->export_for_template($this);
1515 return $this->render_from_template('mod_assign/grading_app', $context);
1516 }
bbd0e548
DW
1517}
1518