872b7283d54405bd544ce41246eb9b1ad31d741a
[moodle.git] / mod / assign / renderer.php
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/>.
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  */
25 defined('MOODLE_INTERNAL') || die();
27 require_once($CFG->dirroot . '/mod/assign/locallib.php');
29 use \mod_assign\output\grading_app;
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  */
38 class mod_assign_renderer extends plugin_renderer_base {
40     /**
41      * Rendering assignment files
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     }
53     /**
54      * Rendering assignment files
55      *
56      * @param assign_files $tree
57      * @return string
58      */
59     public function render_assign_files(assign_files $tree) {
60         $this->htmlid = html_writer::random_id('assign_files_tree');
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>';
66         if ($tree->portfolioform) {
67             $html .= $tree->portfolioform;
68         }
69         return $html;
70     }
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     }
89     /**
90      * Render a grading message notification
91      * @param assign_gradingmessage $result The result to render
92      * @return string
93      */
94     public function render_assign_gradingmessage(assign_gradingmessage $result) {
95         $urlparams = array('id' => $result->coursemoduleid, 'action'=>'grading');
96         if (!empty($result->page)) {
97             $urlparams['page'] = $result->page;
98         }
99         $url = new moodle_url('/mod/assign/view.php', $urlparams);
100         $classes = $result->gradingerror ? 'notifyproblem' : 'notifysuccess';
102         $o = '';
103         $o .= $this->output->heading($result->heading, 4);
104         $o .= $this->output->notification($result->message, $classes);
105         $o .= $this->output->continue_button($url);
106         return $o;
107     }
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 = '';
116         if ($form->jsinitfunction) {
117             $this->page->requires->js_init_call($form->jsinitfunction, array());
118         }
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     }
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 = '';
133         $supendedclass = '';
134         $suspendedicon = '';
136         if (!$summary->user) {
137             return;
138         }
140         if ($summary->suspendeduser) {
141             $supendedclass = ' usersuspended';
142             $suspendedstring = get_string('userenrolmentsuspended', 'grades');
143             $suspendedicon = ' ' . $this->pix_icon('i/enrolmentsuspended', $suspendedstring);
144         }
145         $o .= $this->output->container_start('usersummary');
146         $o .= $this->output->box_start('boxaligncenter usersummarysection'.$supendedclass);
147         if ($summary->blindmarking) {
148             $o .= get_string('hiddenuser', 'assign') . $summary->uniqueidforuser.$suspendedicon;
149         } else {
150             $o .= $this->output->user_picture($summary->user);
151             $o .= $this->output->spacer(array('width'=>30));
152             $urlparams = array('id' => $summary->user->id, 'course'=>$summary->courseid);
153             $url = new moodle_url('/user/view.php', $urlparams);
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             }
162             $fullname .= $suspendedicon;
163             $o .= $this->output->action_link($url, $fullname);
164         }
165         $o .= $this->output->box_end();
166         $o .= $this->output->container_end();
168         return $o;
169     }
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 = '';
180         $o .= $this->output->container_start('submitforgrading');
181         $o .= $this->output->heading(get_string('confirmsubmissionheading', 'assign'), 3);
183         $cancelurl = new moodle_url('/mod/assign/view.php', array('id' => $page->coursemoduleid));
184         if (count($page->notifications)) {
185             // At least one of the submission plugins is not ready for submission.
187             $o .= $this->output->heading(get_string('submissionnotready', 'assign'), 4);
189             foreach ($page->notifications as $notification) {
190                 $o .= $this->output->notification($notification);
191             }
193             $o .= $this->output->continue_button($cancelurl);
194         } else {
195             // All submission plugins ready - show the confirmation form.
196             $o .= $this->moodleform($page->confirmform);
197         }
198         $o .= $this->output->container_end();
200         return $o;
201     }
203     /**
204      * Page is done - render the footer.
205      *
206      * @return void
207      */
208     public function render_footer() {
209         return $this->output->footer();
210     }
212     /**
213      * Render the header.
214      *
215      * @param assign_header $header
216      * @return string
217      */
218     public function render_assign_header(assign_header $header) {
219         $o = '';
221         if ($header->subpage) {
222             $this->page->navbar->add($header->subpage);
223         }
225         $this->page->set_title(get_string('pluginname', 'assign'));
226         $this->page->set_heading($this->page->course->fullname);
228         $o .= $this->output->header();
229         $heading = format_string($header->assign->name, false, array('context' => $header->context));
230         $o .= $this->output->heading($heading);
231         if ($header->preface) {
232             $o .= $header->preface;
233         }
235         if ($header->showintro) {
236             $o .= $this->output->box_start('generalbox boxaligncenter', 'intro');
237             $o .= format_module_intro('assign', $header->assign, $header->coursemoduleid);
238             $o .= $header->postfix;
239             $o .= $this->output->box_end();
240         }
242         return $o;
243     }
245     /**
246      * Render the header for an individual plugin.
247      *
248      * @param assign_plugin_header $header
249      * @return string
250      */
251     public function render_assign_plugin_header(assign_plugin_header $header) {
252         $o = $header->plugin->view_header();
253         return $o;
254     }
256     /**
257      * Render a table containing the current status of the grading process.
258      *
259      * @param assign_grading_summary $summary
260      * @return string
261      */
262     public function render_assign_grading_summary(assign_grading_summary $summary) {
263         // Create a table for the data.
264         $o = '';
265         $o .= $this->output->container_start('gradingsummary');
266         $o .= $this->output->heading(get_string('gradingsummary', 'assign'), 3);
267         $o .= $this->output->box_start('boxaligncenter gradingsummarytable');
268         $t = new html_table();
270         // Status.
271         if ($summary->teamsubmission) {
272             if ($summary->warnofungroupedusers) {
273                 $o .= $this->output->notification(get_string('ungroupedusers', 'assign'));
274             }
276             $this->add_table_row_tuple($t, get_string('numberofteams', 'assign'),
277                                        $summary->participantcount);
278         } else {
279             $this->add_table_row_tuple($t, get_string('numberofparticipants', 'assign'),
280                                        $summary->participantcount);
281         }
283         // Drafts count and dont show drafts count when using offline assignment.
284         if ($summary->submissiondraftsenabled && $summary->submissionsenabled) {
285             $this->add_table_row_tuple($t, get_string('numberofdraftsubmissions', 'assign'),
286                                        $summary->submissiondraftscount);
287         }
289         // Submitted for grading.
290         if ($summary->submissionsenabled) {
291             $this->add_table_row_tuple($t, get_string('numberofsubmittedassignments', 'assign'),
292                                        $summary->submissionssubmittedcount);
293             if (!$summary->teamsubmission) {
294                 $this->add_table_row_tuple($t, get_string('numberofsubmissionsneedgrading', 'assign'),
295                                            $summary->submissionsneedgradingcount);
296             }
297         }
299         $time = time();
300         if ($summary->duedate) {
301             // Due date.
302             $duedate = $summary->duedate;
303             $this->add_table_row_tuple($t, get_string('duedate', 'assign'),
304                                        userdate($duedate));
306             // Time remaining.
307             $due = '';
308             if ($duedate - $time <= 0) {
309                 $due = get_string('assignmentisdue', 'assign');
310             } else {
311                 $due = format_time($duedate - $time);
312             }
313             $this->add_table_row_tuple($t, get_string('timeremaining', 'assign'), $due);
315             if ($duedate < $time) {
316                 $cutoffdate = $summary->cutoffdate;
317                 if ($cutoffdate) {
318                     if ($cutoffdate > $time) {
319                         $late = get_string('latesubmissionsaccepted', 'assign', userdate($summary->cutoffdate));
320                     } else {
321                         $late = get_string('nomoresubmissionsaccepted', 'assign');
322                     }
323                     $this->add_table_row_tuple($t, get_string('latesubmissions', 'assign'), $late);
324                 }
325             }
327         }
329         // All done - write the table.
330         $o .= html_writer::table($t);
331         $o .= $this->output->box_end();
333         // Link to the grading page.
334         $o .= '<center>';
335         $o .= $this->output->container_start('submissionlinks');
336         $urlparams = array('id' => $summary->coursemoduleid, 'action' => 'grading');
337         $url = new moodle_url('/mod/assign/view.php', $urlparams);
338         $o .= '<a href="' . $url . '" class="btn btn-secondary">' . get_string('viewgrading', 'mod_assign') . '</a> ';
339         if ($summary->cangrade) {
340             $urlparams = array('id' => $summary->coursemoduleid, 'action' => 'grader');
341             $url = new moodle_url('/mod/assign/view.php', $urlparams);
342             $o .= '<a href="' . $url . '" class="btn btn-primary">' . get_string('grade') . '</a>';
343         }
344         $o .= $this->output->container_end();
346         // Close the container and insert a spacer.
347         $o .= $this->output->container_end();
348         $o .= '</center>';
350         return $o;
351     }
353     /**
354      * Render a table containing all the current grades and feedback.
355      *
356      * @param assign_feedback_status $status
357      * @return string
358      */
359     public function render_assign_feedback_status(assign_feedback_status $status) {
360         global $DB, $CFG;
361         $o = '';
363         $o .= $this->output->container_start('feedback');
364         $o .= $this->output->heading(get_string('feedback', 'assign'), 3);
365         $o .= $this->output->box_start('boxaligncenter feedbacktable');
366         $t = new html_table();
368         // Grade.
369         if (isset($status->gradefordisplay)) {
370             $row = new html_table_row();
371             $cell1 = new html_table_cell(get_string('grade'));
372             $cell2 = new html_table_cell($status->gradefordisplay);
373             $row->cells = array($cell1, $cell2);
374             $t->data[] = $row;
376             // Grade date.
377             $row = new html_table_row();
378             $cell1 = new html_table_cell(get_string('gradedon', 'assign'));
379             $cell2 = new html_table_cell(userdate($status->gradeddate));
380             $row->cells = array($cell1, $cell2);
381             $t->data[] = $row;
382         }
384         if ($status->grader) {
385             // Grader.
386             $row = new html_table_row();
387             $cell1 = new html_table_cell(get_string('gradedby', 'assign'));
388             $userdescription = $this->output->user_picture($status->grader) .
389                                $this->output->spacer(array('width'=>30)) .
390                                fullname($status->grader, $status->canviewfullnames);
391             $cell2 = new html_table_cell($userdescription);
392             $row->cells = array($cell1, $cell2);
393             $t->data[] = $row;
394         }
396         foreach ($status->feedbackplugins as $plugin) {
397             if ($plugin->is_enabled() &&
398                     $plugin->is_visible() &&
399                     $plugin->has_user_summary() &&
400                     !empty($status->grade) &&
401                     !$plugin->is_empty($status->grade)) {
403                 $row = new html_table_row();
404                 $cell1 = new html_table_cell($plugin->get_name());
405                 $displaymode = assign_feedback_plugin_feedback::SUMMARY;
406                 $pluginfeedback = new assign_feedback_plugin_feedback($plugin,
407                                                                       $status->grade,
408                                                                       $displaymode,
409                                                                       $status->coursemoduleid,
410                                                                       $status->returnaction,
411                                                                       $status->returnparams);
412                 $cell2 = new html_table_cell($this->render($pluginfeedback));
413                 $row->cells = array($cell1, $cell2);
414                 $t->data[] = $row;
415             }
416         }
418         $o .= html_writer::table($t);
419         $o .= $this->output->box_end();
421         $o .= $this->output->container_end();
422         return $o;
423     }
425     /**
426      * Render a compact view of the current status of the submission.
427      *
428      * @param assign_submission_status_compact $status
429      * @return string
430      */
431     public function render_assign_submission_status_compact(assign_submission_status_compact $status) {
432         $o = '';
433         $o .= $this->output->container_start('submissionstatustable');
434         $o .= $this->output->heading(get_string('submission', 'assign'), 3);
435         $time = time();
437         if ($status->teamsubmissionenabled) {
438             $group = $status->submissiongroup;
439             if ($group) {
440                 $team = format_string($group->name, false, $status->context);
441             } else if ($status->preventsubmissionnotingroup) {
442                 if (count($status->usergroups) == 0) {
443                     $team = '<span class="alert alert-error">' . get_string('noteam', 'assign') . '</span>';
444                 } else if (count($status->usergroups) > 1) {
445                     $team = '<span class="alert alert-error">' . get_string('multipleteams', 'assign') . '</span>';
446                 }
447             } else {
448                 $team = get_string('defaultteam', 'assign');
449             }
450             $o .= $this->output->container(get_string('teamname', 'assign', $team), 'teamname');
451         }
453         if (!$status->teamsubmissionenabled) {
454             if ($status->submission && $status->submission->status != ASSIGN_SUBMISSION_STATUS_NEW) {
455                 $statusstr = get_string('submissionstatus_' . $status->submission->status, 'assign');
456                 $o .= $this->output->container($statusstr, 'submissionstatus' . $status->submission->status);
457             } else {
458                 if (!$status->submissionsenabled) {
459                     $o .= $this->output->container(get_string('noonlinesubmissions', 'assign'), 'submissionstatus');
460                 } else {
461                     $o .= $this->output->container(get_string('noattempt', 'assign'), 'submissionstatus');
462                 }
463             }
464         } else {
465             $group = $status->submissiongroup;
466             if (!$group && $status->preventsubmissionnotingroup) {
467                 $o .= $this->output->container(get_string('nosubmission', 'assign'), 'submissionstatus');
468             } else if ($status->teamsubmission && $status->teamsubmission->status != ASSIGN_SUBMISSION_STATUS_NEW) {
469                 $teamstatus = $status->teamsubmission->status;
470                 $submissionsummary = get_string('submissionstatus_' . $teamstatus, 'assign');
471                 $groupid = 0;
472                 if ($status->submissiongroup) {
473                     $groupid = $status->submissiongroup->id;
474                 }
476                 $members = $status->submissiongroupmemberswhoneedtosubmit;
477                 $userslist = array();
478                 foreach ($members as $member) {
479                     $urlparams = array('id' => $member->id, 'course' => $status->courseid);
480                     $url = new moodle_url('/user/view.php', $urlparams);
481                     if ($status->view == assign_submission_status::GRADER_VIEW && $status->blindmarking) {
482                         $userslist[] = $member->alias;
483                     } else {
484                         $fullname = fullname($member, $status->canviewfullnames);
485                         $userslist[] = $this->output->action_link($url, $fullname);
486                     }
487                 }
488                 if (count($userslist) > 0) {
489                     $userstr = join(', ', $userslist);
490                     $formatteduserstr = get_string('userswhoneedtosubmit', 'assign', $userstr);
491                     $submissionsummary .= $this->output->container($formatteduserstr);
492                 }
493                 $o .= $this->output->container($submissionsummary, 'submissionstatus' . $status->teamsubmission->status);
494             } else {
495                 if (!$status->submissionsenabled) {
496                     $o .= $this->output->container(get_string('noonlinesubmissions', 'assign'), 'submissionstatus');
497                 } else {
498                     $o .= $this->output->container(get_string('nosubmission', 'assign'), 'submissionstatus');
499                 }
500             }
501         }
503         // Is locked?
504         if ($status->locked) {
505             $o .= $this->output->container(get_string('submissionslocked', 'assign'), 'submissionlocked');
506         }
508         // Grading status.
509         $statusstr = '';
510         $classname = 'gradingstatus';
511         if ($status->gradingstatus == ASSIGN_GRADING_STATUS_GRADED ||
512             $status->gradingstatus == ASSIGN_GRADING_STATUS_NOT_GRADED) {
513             $statusstr = get_string($status->gradingstatus, 'assign');
514         } else {
515             $gradingstatus = 'markingworkflowstate' . $status->gradingstatus;
516             $statusstr = get_string($gradingstatus, 'assign');
517         }
518         if ($status->gradingstatus == ASSIGN_GRADING_STATUS_GRADED ||
519             $status->gradingstatus == ASSIGN_MARKING_WORKFLOW_STATE_RELEASED) {
520             $classname = 'submissiongraded';
521         } else {
522             $classname = 'submissionnotgraded';
523         }
524         $o .= $this->output->container($statusstr, $classname);
526         $submission = $status->teamsubmission ? $status->teamsubmission : $status->submission;
527         $duedate = $status->duedate;
528         if ($duedate > 0) {
530             if ($status->extensionduedate) {
531                 // Extension date.
532                 $duedate = $status->extensionduedate;
533             }
535             // Time remaining.
536             $classname = 'timeremaining';
537             if ($duedate - $time <= 0) {
538                 if (!$submission ||
539                         $submission->status != ASSIGN_SUBMISSION_STATUS_SUBMITTED) {
540                     if ($status->submissionsenabled) {
541                         $remaining = get_string('overdue', 'assign', format_time($time - $duedate));
542                         $classname = 'overdue';
543                     } else {
544                         $remaining = get_string('duedatereached', 'assign');
545                     }
546                 } else {
547                     if ($submission->timemodified > $duedate) {
548                         $remaining = get_string('submittedlate',
549                                               'assign',
550                                               format_time($submission->timemodified - $duedate));
551                         $classname = 'latesubmission';
552                     } else {
553                         $remaining = get_string('submittedearly',
554                                                'assign',
555                                                format_time($submission->timemodified - $duedate));
556                         $classname = 'earlysubmission';
557                     }
558                 }
559             } else {
560                 $remaining = get_string('paramtimeremaining', 'assign', format_time($duedate - $time));
561             }
562             $o .= $this->output->container($remaining, $classname);
563         }
565         // Show graders whether this submission is editable by students.
566         if ($status->view == assign_submission_status::GRADER_VIEW) {
567             if ($status->canedit) {
568                 $o .= $this->output->container(get_string('submissioneditable', 'assign'), 'submissioneditable');
569             } else {
570                 $o .= $this->output->container(get_string('submissionnoteditable', 'assign'), 'submissionnoteditable');
571             }
572         }
574         // Grading criteria preview.
575         if (!empty($status->gradingcontrollerpreview)) {
576             $o .= $this->output->container($status->gradingcontrollerpreview, 'gradingmethodpreview');
577         }
579         if ($submission) {
581             if (!$status->teamsubmission || $status->submissiongroup != false || !$status->preventsubmissionnotingroup) {
582                 foreach ($status->submissionplugins as $plugin) {
583                     $pluginshowsummary = !$plugin->is_empty($submission) || !$plugin->allow_submissions();
584                     if ($plugin->is_enabled() &&
585                         $plugin->is_visible() &&
586                         $plugin->has_user_summary() &&
587                         $pluginshowsummary
588                     ) {
590                         $displaymode = assign_submission_plugin_submission::SUMMARY;
591                         $pluginsubmission = new assign_submission_plugin_submission($plugin,
592                             $submission,
593                             $displaymode,
594                             $status->coursemoduleid,
595                             $status->returnaction,
596                             $status->returnparams);
597                         $plugincomponent = $plugin->get_subtype() . '_' . $plugin->get_type();
598                         $o .= $this->output->container($this->render($pluginsubmission), 'assignsubmission ' . $plugincomponent);
599                     }
600                 }
601             }
602         }
604         $o .= $this->output->container_end();
605         return $o;
606     }
608     /**
609      * Render a table containing the current status of the submission.
610      *
611      * @param assign_submission_status $status
612      * @return string
613      */
614     public function render_assign_submission_status(assign_submission_status $status) {
615         $o = '';
616         $o .= $this->output->container_start('submissionstatustable');
617         $o .= $this->output->heading(get_string('submissionstatusheading', 'assign'), 3);
618         $time = time();
620         if ($status->allowsubmissionsfromdate &&
621                 $time <= $status->allowsubmissionsfromdate) {
622             $o .= $this->output->box_start('generalbox boxaligncenter submissionsalloweddates');
623             if ($status->alwaysshowdescription) {
624                 $date = userdate($status->allowsubmissionsfromdate);
625                 $o .= get_string('allowsubmissionsfromdatesummary', 'assign', $date);
626             } else {
627                 $date = userdate($status->allowsubmissionsfromdate);
628                 $o .= get_string('allowsubmissionsanddescriptionfromdatesummary', 'assign', $date);
629             }
630             $o .= $this->output->box_end();
631         }
632         $o .= $this->output->box_start('boxaligncenter submissionsummarytable');
634         $t = new html_table();
636         $warningmsg = '';
637         if ($status->teamsubmissionenabled) {
638             $row = new html_table_row();
639             $cell1 = new html_table_cell(get_string('submissionteam', 'assign'));
640             $group = $status->submissiongroup;
641             if ($group) {
642                 $cell2 = new html_table_cell(format_string($group->name, false, $status->context));
643             } else if ($status->preventsubmissionnotingroup) {
644                 if (count($status->usergroups) == 0) {
645                     $notification = new \core\output\notification(get_string('noteam', 'assign'), 'error');
646                     $notification->set_show_closebutton(false);
647                     $cell2 = new html_table_cell(
648                         $this->output->render($notification)
649                     );
650                     $warningmsg = $this->output->notification(get_string('noteam_desc', 'assign'), 'error');
651                 } else if (count($status->usergroups) > 1) {
652                     $notification = new \core\output\notification(get_string('multipleteams', 'assign'), 'error');
653                     $notification->set_show_closebutton(false);
654                     $cell2 = new html_table_cell(
655                         $this->output->render($notification)
656                     );
657                     $warningmsg = $this->output->notification(get_string('multipleteams_desc', 'assign'), 'error');
658                 }
659             } else {
660                 $cell2 = new html_table_cell(get_string('defaultteam', 'assign'));
661             }
662             $row->cells = array($cell1, $cell2);
663             $t->data[] = $row;
664         }
666         if ($status->attemptreopenmethod != ASSIGN_ATTEMPT_REOPEN_METHOD_NONE) {
667             $currentattempt = 1;
668             if (!$status->teamsubmissionenabled) {
669                 if ($status->submission) {
670                     $currentattempt = $status->submission->attemptnumber + 1;
671                 }
672             } else {
673                 if ($status->teamsubmission) {
674                     $currentattempt = $status->teamsubmission->attemptnumber + 1;
675                 }
676             }
678             $row = new html_table_row();
679             $cell1 = new html_table_cell(get_string('attemptnumber', 'assign'));
680             $maxattempts = $status->maxattempts;
681             if ($maxattempts == ASSIGN_UNLIMITED_ATTEMPTS) {
682                 $message = get_string('currentattempt', 'assign', $currentattempt);
683             } else {
684                 $message = get_string('currentattemptof', 'assign', array('attemptnumber'=>$currentattempt,
685                                                                           'maxattempts'=>$maxattempts));
686             }
687             $cell2 = new html_table_cell($message);
688             $row->cells = array($cell1, $cell2);
689             $t->data[] = $row;
690         }
692         $row = new html_table_row();
693         $cell1 = new html_table_cell(get_string('submissionstatus', 'assign'));
694         if (!$status->teamsubmissionenabled) {
695             if ($status->submission && $status->submission->status != ASSIGN_SUBMISSION_STATUS_NEW) {
696                 $statusstr = get_string('submissionstatus_' . $status->submission->status, 'assign');
697                 $cell2 = new html_table_cell($statusstr);
698                 $cell2->attributes = array('class'=>'submissionstatus' . $status->submission->status);
699             } else {
700                 if (!$status->submissionsenabled) {
701                     $cell2 = new html_table_cell(get_string('noonlinesubmissions', 'assign'));
702                 } else {
703                     $cell2 = new html_table_cell(get_string('noattempt', 'assign'));
704                 }
705             }
706             $row->cells = array($cell1, $cell2);
707             $t->data[] = $row;
708         } else {
709             $row = new html_table_row();
710             $cell1 = new html_table_cell(get_string('submissionstatus', 'assign'));
711             $group = $status->submissiongroup;
712             if (!$group && $status->preventsubmissionnotingroup) {
713                 $cell2 = new html_table_cell(get_string('nosubmission', 'assign'));
714             } else if ($status->teamsubmission && $status->teamsubmission->status != ASSIGN_SUBMISSION_STATUS_NEW) {
715                 $teamstatus = $status->teamsubmission->status;
716                 $submissionsummary = get_string('submissionstatus_' . $teamstatus, 'assign');
717                 $groupid = 0;
718                 if ($status->submissiongroup) {
719                     $groupid = $status->submissiongroup->id;
720                 }
722                 $members = $status->submissiongroupmemberswhoneedtosubmit;
723                 $userslist = array();
724                 foreach ($members as $member) {
725                     $urlparams = array('id' => $member->id, 'course'=>$status->courseid);
726                     $url = new moodle_url('/user/view.php', $urlparams);
727                     if ($status->view == assign_submission_status::GRADER_VIEW && $status->blindmarking) {
728                         $userslist[] = $member->alias;
729                     } else {
730                         $fullname = fullname($member, $status->canviewfullnames);
731                         $userslist[] = $this->output->action_link($url, $fullname);
732                     }
733                 }
734                 if (count($userslist) > 0) {
735                     $userstr = join(', ', $userslist);
736                     $formatteduserstr = get_string('userswhoneedtosubmit', 'assign', $userstr);
737                     $submissionsummary .= $this->output->container($formatteduserstr);
738                 }
740                 $cell2 = new html_table_cell($submissionsummary);
741                 $cell2->attributes = array('class'=>'submissionstatus' . $status->teamsubmission->status);
742             } else {
743                 $cell2 = new html_table_cell(get_string('nosubmission', 'assign'));
744                 if (!$status->submissionsenabled) {
745                     $cell2 = new html_table_cell(get_string('noonlinesubmissions', 'assign'));
746                 } else {
747                     $cell2 = new html_table_cell(get_string('nosubmission', 'assign'));
748                 }
749             }
750             $row->cells = array($cell1, $cell2);
751             $t->data[] = $row;
752         }
754         // Is locked?
755         if ($status->locked) {
756             $row = new html_table_row();
757             $cell1 = new html_table_cell();
758             $cell2 = new html_table_cell(get_string('submissionslocked', 'assign'));
759             $cell2->attributes = array('class'=>'submissionlocked');
760             $row->cells = array($cell1, $cell2);
761             $t->data[] = $row;
762         }
764         // Grading status.
765         $row = new html_table_row();
766         $cell1 = new html_table_cell(get_string('gradingstatus', 'assign'));
768         if ($status->gradingstatus == ASSIGN_GRADING_STATUS_GRADED ||
769             $status->gradingstatus == ASSIGN_GRADING_STATUS_NOT_GRADED) {
770             $cell2 = new html_table_cell(get_string($status->gradingstatus, 'assign'));
771         } else {
772             $gradingstatus = 'markingworkflowstate' . $status->gradingstatus;
773             $cell2 = new html_table_cell(get_string($gradingstatus, 'assign'));
774         }
775         if ($status->gradingstatus == ASSIGN_GRADING_STATUS_GRADED ||
776             $status->gradingstatus == ASSIGN_MARKING_WORKFLOW_STATE_RELEASED) {
777             $cell2->attributes = array('class' => 'submissiongraded');
778         } else {
779             $cell2->attributes = array('class' => 'submissionnotgraded');
780         }
781         $row->cells = array($cell1, $cell2);
782         $t->data[] = $row;
784         $submission = $status->teamsubmission ? $status->teamsubmission : $status->submission;
785         $duedate = $status->duedate;
786         if ($duedate > 0) {
787             // Due date.
788             $row = new html_table_row();
789             $cell1 = new html_table_cell(get_string('duedate', 'assign'));
790             $cell2 = new html_table_cell(userdate($duedate));
791             $row->cells = array($cell1, $cell2);
792             $t->data[] = $row;
794             if ($status->view == assign_submission_status::GRADER_VIEW) {
795                 if ($status->cutoffdate) {
796                     // Cut off date.
797                     $row = new html_table_row();
798                     $cell1 = new html_table_cell(get_string('cutoffdate', 'assign'));
799                     $cell2 = new html_table_cell(userdate($status->cutoffdate));
800                     $row->cells = array($cell1, $cell2);
801                     $t->data[] = $row;
802                 }
803             }
805             if ($status->extensionduedate) {
806                 // Extension date.
807                 $row = new html_table_row();
808                 $cell1 = new html_table_cell(get_string('extensionduedate', 'assign'));
809                 $cell2 = new html_table_cell(userdate($status->extensionduedate));
810                 $row->cells = array($cell1, $cell2);
811                 $t->data[] = $row;
812                 $duedate = $status->extensionduedate;
813             }
815             // Time remaining.
816             $row = new html_table_row();
817             $cell1 = new html_table_cell(get_string('timeremaining', 'assign'));
818             if ($duedate - $time <= 0) {
819                 if (!$submission ||
820                         $submission->status != ASSIGN_SUBMISSION_STATUS_SUBMITTED) {
821                     if ($status->submissionsenabled) {
822                         $overduestr = get_string('overdue', 'assign', format_time($time - $duedate));
823                         $cell2 = new html_table_cell($overduestr);
824                         $cell2->attributes = array('class'=>'overdue');
825                     } else {
826                         $cell2 = new html_table_cell(get_string('duedatereached', 'assign'));
827                     }
828                 } else {
829                     if ($submission->timemodified > $duedate) {
830                         $latestr = get_string('submittedlate',
831                                               'assign',
832                                               format_time($submission->timemodified - $duedate));
833                         $cell2 = new html_table_cell($latestr);
834                         $cell2->attributes = array('class'=>'latesubmission');
835                     } else {
836                         $earlystr = get_string('submittedearly',
837                                                'assign',
838                                                format_time($submission->timemodified - $duedate));
839                         $cell2 = new html_table_cell($earlystr);
840                         $cell2->attributes = array('class'=>'earlysubmission');
841                     }
842                 }
843             } else {
844                 $cell2 = new html_table_cell(format_time($duedate - $time));
845             }
846             $row->cells = array($cell1, $cell2);
847             $t->data[] = $row;
848         }
850         // Show graders whether this submission is editable by students.
851         if ($status->view == assign_submission_status::GRADER_VIEW) {
852             $row = new html_table_row();
853             $cell1 = new html_table_cell(get_string('editingstatus', 'assign'));
854             if ($status->canedit) {
855                 $cell2 = new html_table_cell(get_string('submissioneditable', 'assign'));
856                 $cell2->attributes = array('class'=>'submissioneditable');
857             } else {
858                 $cell2 = new html_table_cell(get_string('submissionnoteditable', 'assign'));
859                 $cell2->attributes = array('class'=>'submissionnoteditable');
860             }
861             $row->cells = array($cell1, $cell2);
862             $t->data[] = $row;
863         }
865         // Grading criteria preview.
866         if (!empty($status->gradingcontrollerpreview)) {
867             $row = new html_table_row();
868             $cell1 = new html_table_cell(get_string('gradingmethodpreview', 'assign'));
869             $cell2 = new html_table_cell($status->gradingcontrollerpreview);
870             $row->cells = array($cell1, $cell2);
871             $t->data[] = $row;
872         }
874         // Last modified.
875         if ($submission) {
876             $row = new html_table_row();
877             $cell1 = new html_table_cell(get_string('timemodified', 'assign'));
879             if ($submission->status != ASSIGN_SUBMISSION_STATUS_NEW) {
880                 $cell2 = new html_table_cell(userdate($submission->timemodified));
881             } else {
882                 $cell2 = new html_table_cell('-');
883             }
885             $row->cells = array($cell1, $cell2);
886             $t->data[] = $row;
888             if (!$status->teamsubmission || $status->submissiongroup != false || !$status->preventsubmissionnotingroup) {
889                 foreach ($status->submissionplugins as $plugin) {
890                     $pluginshowsummary = !$plugin->is_empty($submission) || !$plugin->allow_submissions();
891                     if ($plugin->is_enabled() &&
892                         $plugin->is_visible() &&
893                         $plugin->has_user_summary() &&
894                         $pluginshowsummary
895                     ) {
897                         $row = new html_table_row();
898                         $cell1 = new html_table_cell($plugin->get_name());
899                         $displaymode = assign_submission_plugin_submission::SUMMARY;
900                         $pluginsubmission = new assign_submission_plugin_submission($plugin,
901                             $submission,
902                             $displaymode,
903                             $status->coursemoduleid,
904                             $status->returnaction,
905                             $status->returnparams);
906                         $cell2 = new html_table_cell($this->render($pluginsubmission));
907                         $row->cells = array($cell1, $cell2);
908                         $t->data[] = $row;
909                     }
910                 }
911             }
912         }
914         $o .= $warningmsg;
915         $o .= html_writer::table($t);
916         $o .= $this->output->box_end();
918         // Links.
919         if ($status->view == assign_submission_status::STUDENT_VIEW) {
920             if ($status->canedit) {
921                 if (!$submission || $submission->status == ASSIGN_SUBMISSION_STATUS_NEW) {
922                     $o .= $this->output->box_start('generalbox submissionaction');
923                     $urlparams = array('id' => $status->coursemoduleid, 'action' => 'editsubmission');
924                     $o .= $this->output->single_button(new moodle_url('/mod/assign/view.php', $urlparams),
925                                                        get_string('addsubmission', 'assign'), 'get');
926                     $o .= $this->output->box_start('boxaligncenter submithelp');
927                     $o .= get_string('addsubmission_help', 'assign');
928                     $o .= $this->output->box_end();
929                     $o .= $this->output->box_end();
930                 } else if ($submission->status == ASSIGN_SUBMISSION_STATUS_REOPENED) {
931                     $o .= $this->output->box_start('generalbox submissionaction');
932                     $urlparams = array('id' => $status->coursemoduleid,
933                                        'action' => 'editprevioussubmission',
934                                        'sesskey'=>sesskey());
935                     $o .= $this->output->single_button(new moodle_url('/mod/assign/view.php', $urlparams),
936                                                        get_string('addnewattemptfromprevious', 'assign'), 'get');
937                     $o .= $this->output->box_start('boxaligncenter submithelp');
938                     $o .= get_string('addnewattemptfromprevious_help', 'assign');
939                     $o .= $this->output->box_end();
940                     $o .= $this->output->box_end();
941                     $o .= $this->output->box_start('generalbox submissionaction');
942                     $urlparams = array('id' => $status->coursemoduleid, 'action' => 'editsubmission');
943                     $o .= $this->output->single_button(new moodle_url('/mod/assign/view.php', $urlparams),
944                                                        get_string('addnewattempt', 'assign'), 'get');
945                     $o .= $this->output->box_start('boxaligncenter submithelp');
946                     $o .= get_string('addnewattempt_help', 'assign');
947                     $o .= $this->output->box_end();
948                     $o .= $this->output->box_end();
949                 } else {
950                     $o .= $this->output->box_start('generalbox submissionaction');
951                     $urlparams = array('id' => $status->coursemoduleid, 'action' => 'editsubmission');
952                     $o .= $this->output->single_button(new moodle_url('/mod/assign/view.php', $urlparams),
953                                                        get_string('editsubmission', 'assign'), 'get');
954                     $o .= $this->output->box_start('boxaligncenter submithelp');
955                     $o .= get_string('editsubmission_help', 'assign');
956                     $o .= $this->output->box_end();
957                     $o .= $this->output->box_end();
958                 }
959             }
961             if ($status->cansubmit) {
962                 $urlparams = array('id' => $status->coursemoduleid, 'action'=>'submit');
963                 $o .= $this->output->box_start('generalbox submissionaction');
964                 $o .= $this->output->single_button(new moodle_url('/mod/assign/view.php', $urlparams),
965                                                    get_string('submitassignment', 'assign'), 'get');
966                 $o .= $this->output->box_start('boxaligncenter submithelp');
967                 $o .= get_string('submitassignment_help', 'assign');
968                 $o .= $this->output->box_end();
969                 $o .= $this->output->box_end();
970             }
971         }
973         $o .= $this->output->container_end();
974         return $o;
975     }
977     /**
978      * Output the attempt history chooser for this assignment
979      *
980      * @param assign_attempt_history_chooser $history
981      * @return string
982      */
983     public function render_assign_attempt_history_chooser(assign_attempt_history_chooser $history) {
984         $o = '';
986         $context = $history->export_for_template($this);
987         $o .= $this->render_from_template('mod_assign/attempt_history_chooser', $context);
989         return $o;
990     }
992     /**
993      * Output the attempt history for this assignment
994      *
995      * @param assign_attempt_history $history
996      * @return string
997      */
998     public function render_assign_attempt_history(assign_attempt_history $history) {
999         $o = '';
1001         $submittedstr = get_string('submitted', 'assign');
1002         $gradestr = get_string('grade');
1003         $gradedonstr = get_string('gradedon', 'assign');
1004         $gradedbystr = get_string('gradedby', 'assign');
1006         // Don't show the last one because it is the current submission.
1007         array_pop($history->submissions);
1009         // Show newest to oldest.
1010         $history->submissions = array_reverse($history->submissions);
1012         if (empty($history->submissions)) {
1013             return '';
1014         }
1016         $containerid = 'attempthistory' . uniqid();
1017         $o .= $this->output->heading(get_string('attempthistory', 'assign'), 3);
1018         $o .= $this->box_start('attempthistory', $containerid);
1020         foreach ($history->submissions as $i => $submission) {
1021             $grade = null;
1022             foreach ($history->grades as $onegrade) {
1023                 if ($onegrade->attemptnumber == $submission->attemptnumber) {
1024                     $grade = $onegrade;
1025                     break;
1026                 }
1027             }
1029             $editbtn = '';
1031             if ($submission) {
1032                 $submissionsummary = userdate($submission->timemodified);
1033             } else {
1034                 $submissionsummary = get_string('nosubmission', 'assign');
1035             }
1037             $attemptsummaryparams = array('attemptnumber'=>$submission->attemptnumber+1,
1038                                           'submissionsummary'=>$submissionsummary);
1039             $o .= $this->heading(get_string('attemptheading', 'assign', $attemptsummaryparams), 4);
1041             $t = new html_table();
1043             if ($submission) {
1044                 $cell1 = new html_table_cell(get_string('submissionstatus', 'assign'));
1045                 $cell2 = new html_table_cell(get_string('submissionstatus_' . $submission->status, 'assign'));
1046                 $t->data[] = new html_table_row(array($cell1, $cell2));
1048                 foreach ($history->submissionplugins as $plugin) {
1049                     $pluginshowsummary = !$plugin->is_empty($submission) || !$plugin->allow_submissions();
1050                     if ($plugin->is_enabled() &&
1051                             $plugin->is_visible() &&
1052                             $plugin->has_user_summary() &&
1053                             $pluginshowsummary) {
1055                         $cell1 = new html_table_cell($plugin->get_name());
1056                         $pluginsubmission = new assign_submission_plugin_submission($plugin,
1057                                                                                     $submission,
1058                                                                                     assign_submission_plugin_submission::SUMMARY,
1059                                                                                     $history->coursemoduleid,
1060                                                                                     $history->returnaction,
1061                                                                                     $history->returnparams);
1062                         $cell2 = new html_table_cell($this->render($pluginsubmission));
1064                         $t->data[] = new html_table_row(array($cell1, $cell2));
1065                     }
1066                 }
1067             }
1069             if ($grade) {
1070                 // Heading 'feedback'.
1071                 $title = get_string('feedback', 'assign', $i);
1072                 $title .= $this->output->spacer(array('width'=>10));
1073                 if ($history->cangrade) {
1074                     // Edit previous feedback.
1075                     $returnparams = http_build_query($history->returnparams);
1076                     $urlparams = array('id' => $history->coursemoduleid,
1077                                    'rownum'=>$history->rownum,
1078                                    'useridlistid'=>$history->useridlistid,
1079                                    'attemptnumber'=>$grade->attemptnumber,
1080                                    'action'=>'grade',
1081                                    'returnaction'=>$history->returnaction,
1082                                    'returnparams'=>$returnparams);
1083                     $url = new moodle_url('/mod/assign/view.php', $urlparams);
1084                     $icon = new pix_icon('gradefeedback',
1085                                             get_string('editattemptfeedback', 'assign', $grade->attemptnumber+1),
1086                                             'mod_assign');
1087                     $title .= $this->output->action_icon($url, $icon);
1088                 }
1089                 $cell = new html_table_cell($title);
1090                 $cell->attributes['class'] = 'feedbacktitle';
1091                 $cell->colspan = 2;
1092                 $t->data[] = new html_table_row(array($cell));
1094                 // Grade.
1095                 $cell1 = new html_table_cell($gradestr);
1096                 $cell2 = $grade->gradefordisplay;
1097                 $t->data[] = new html_table_row(array($cell1, $cell2));
1099                 // Graded on.
1100                 $cell1 = new html_table_cell($gradedonstr);
1101                 $cell2 = new html_table_cell(userdate($grade->timemodified));
1102                 $t->data[] = new html_table_row(array($cell1, $cell2));
1104                 // Graded by.
1105                 $cell1 = new html_table_cell($gradedbystr);
1106                 $cell2 = new html_table_cell($this->output->user_picture($grade->grader) .
1107                                              $this->output->spacer(array('width'=>30)) . fullname($grade->grader));
1108                 $t->data[] = new html_table_row(array($cell1, $cell2));
1110                 // Feedback from plugins.
1111                 foreach ($history->feedbackplugins as $plugin) {
1112                     if ($plugin->is_enabled() &&
1113                         $plugin->is_visible() &&
1114                         $plugin->has_user_summary() &&
1115                         !$plugin->is_empty($grade)) {
1117                         $cell1 = new html_table_cell($plugin->get_name());
1118                         $pluginfeedback = new assign_feedback_plugin_feedback(
1119                             $plugin, $grade, assign_feedback_plugin_feedback::SUMMARY, $history->coursemoduleid,
1120                             $history->returnaction, $history->returnparams
1121                         );
1122                         $cell2 = new html_table_cell($this->render($pluginfeedback));
1123                         $t->data[] = new html_table_row(array($cell1, $cell2));
1124                     }
1126                 }
1128             }
1130             $o .= html_writer::table($t);
1131         }
1132         $o .= $this->box_end();
1133         $jsparams = array($containerid);
1135         $this->page->requires->yui_module('moodle-mod_assign-history', 'Y.one("#' . $containerid . '").history');
1137         return $o;
1138     }
1140     /**
1141      * Render a submission plugin submission
1142      *
1143      * @param assign_submission_plugin_submission $submissionplugin
1144      * @return string
1145      */
1146     public function render_assign_submission_plugin_submission(assign_submission_plugin_submission $submissionplugin) {
1147         $o = '';
1149         if ($submissionplugin->view == assign_submission_plugin_submission::SUMMARY) {
1150             $showviewlink = false;
1151             $summary = $submissionplugin->plugin->view_summary($submissionplugin->submission,
1152                                                                $showviewlink);
1154             $classsuffix = $submissionplugin->plugin->get_subtype() .
1155                            '_' .
1156                            $submissionplugin->plugin->get_type() .
1157                            '_' .
1158                            $submissionplugin->submission->id;
1160             $o .= $this->output->box_start('boxaligncenter plugincontentsummary summary_' . $classsuffix);
1162             $link = '';
1163             if ($showviewlink) {
1164                 $previewstr = get_string('viewsubmission', 'assign');
1165                 $icon = $this->output->pix_icon('t/preview', $previewstr);
1167                 $expandstr = get_string('viewfull', 'assign');
1168                 $options = array('class'=>'expandsummaryicon expand_' . $classsuffix);
1169                 $o .= $this->output->pix_icon('t/switch_plus', $expandstr, null, $options);
1171                 $jsparams = array($submissionplugin->plugin->get_subtype(),
1172                                   $submissionplugin->plugin->get_type(),
1173                                   $submissionplugin->submission->id);
1175                 $this->page->requires->js_init_call('M.mod_assign.init_plugin_summary', $jsparams);
1177                 $action = 'viewplugin' . $submissionplugin->plugin->get_subtype();
1178                 $returnparams = http_build_query($submissionplugin->returnparams);
1179                 $link .= '<noscript>';
1180                 $urlparams = array('id' => $submissionplugin->coursemoduleid,
1181                                    'sid'=>$submissionplugin->submission->id,
1182                                    'plugin'=>$submissionplugin->plugin->get_type(),
1183                                    'action'=>$action,
1184                                    'returnaction'=>$submissionplugin->returnaction,
1185                                    'returnparams'=>$returnparams);
1186                 $url = new moodle_url('/mod/assign/view.php', $urlparams);
1187                 $link .= $this->output->action_link($url, $icon);
1188                 $link .= '</noscript>';
1190                 $link .= $this->output->spacer(array('width'=>15));
1191             }
1193             $o .= $link . $summary;
1194             $o .= $this->output->box_end();
1195             if ($showviewlink) {
1196                 $o .= $this->output->box_start('boxaligncenter hidefull full_' . $classsuffix);
1197                 $classes = 'expandsummaryicon contract_' . $classsuffix;
1198                 $o .= $this->output->pix_icon('t/switch_minus',
1199                                               get_string('viewsummary', 'assign'),
1200                                               null,
1201                                               array('class'=>$classes));
1202                 $o .= $submissionplugin->plugin->view($submissionplugin->submission);
1203                 $o .= $this->output->box_end();
1204             }
1205         } else if ($submissionplugin->view == assign_submission_plugin_submission::FULL) {
1206             $o .= $this->output->box_start('boxaligncenter submissionfull');
1207             $o .= $submissionplugin->plugin->view($submissionplugin->submission);
1208             $o .= $this->output->box_end();
1209         }
1211         return $o;
1212     }
1214     /**
1215      * Render the grading table.
1216      *
1217      * @param assign_grading_table $table
1218      * @return string
1219      */
1220     public function render_assign_grading_table(assign_grading_table $table) {
1221         $o = '';
1222         $o .= $this->output->box_start('boxaligncenter gradingtable');
1224         $this->page->requires->js_init_call('M.mod_assign.init_grading_table', array());
1225         $this->page->requires->string_for_js('nousersselected', 'assign');
1226         $this->page->requires->string_for_js('batchoperationconfirmgrantextension', 'assign');
1227         $this->page->requires->string_for_js('batchoperationconfirmlock', 'assign');
1228         $this->page->requires->string_for_js('batchoperationconfirmreverttodraft', 'assign');
1229         $this->page->requires->string_for_js('batchoperationconfirmunlock', 'assign');
1230         $this->page->requires->string_for_js('batchoperationconfirmaddattempt', 'assign');
1231         $this->page->requires->string_for_js('batchoperationconfirmdownloadselected', 'assign');
1232         $this->page->requires->string_for_js('batchoperationconfirmsetmarkingworkflowstate', 'assign');
1233         $this->page->requires->string_for_js('batchoperationconfirmsetmarkingallocation', 'assign');
1234         $this->page->requires->string_for_js('editaction', 'assign');
1235         foreach ($table->plugingradingbatchoperations as $plugin => $operations) {
1236             foreach ($operations as $operation => $description) {
1237                 $this->page->requires->string_for_js('batchoperationconfirm' . $operation,
1238                                                      'assignfeedback_' . $plugin);
1239             }
1240         }
1241         $o .= $this->flexible_table($table, $table->get_rows_per_page(), true);
1242         $o .= $this->output->box_end();
1244         return $o;
1245     }
1247     /**
1248      * Render a feedback plugin feedback
1249      *
1250      * @param assign_feedback_plugin_feedback $feedbackplugin
1251      * @return string
1252      */
1253     public function render_assign_feedback_plugin_feedback(assign_feedback_plugin_feedback $feedbackplugin) {
1254         $o = '';
1256         if ($feedbackplugin->view == assign_feedback_plugin_feedback::SUMMARY) {
1257             $showviewlink = false;
1258             $summary = $feedbackplugin->plugin->view_summary($feedbackplugin->grade, $showviewlink);
1260             $classsuffix = $feedbackplugin->plugin->get_subtype() .
1261                            '_' .
1262                            $feedbackplugin->plugin->get_type() .
1263                            '_' .
1264                            $feedbackplugin->grade->id;
1265             $o .= $this->output->box_start('boxaligncenter plugincontentsummary summary_' . $classsuffix);
1267             $link = '';
1268             if ($showviewlink) {
1269                 $previewstr = get_string('viewfeedback', 'assign');
1270                 $icon = $this->output->pix_icon('t/preview', $previewstr);
1272                 $expandstr = get_string('viewfull', 'assign');
1273                 $options = array('class'=>'expandsummaryicon expand_' . $classsuffix);
1274                 $o .= $this->output->pix_icon('t/switch_plus', $expandstr, null, $options);
1276                 $jsparams = array($feedbackplugin->plugin->get_subtype(),
1277                                   $feedbackplugin->plugin->get_type(),
1278                                   $feedbackplugin->grade->id);
1279                 $this->page->requires->js_init_call('M.mod_assign.init_plugin_summary', $jsparams);
1281                 $urlparams = array('id' => $feedbackplugin->coursemoduleid,
1282                                    'gid'=>$feedbackplugin->grade->id,
1283                                    'plugin'=>$feedbackplugin->plugin->get_type(),
1284                                    'action'=>'viewplugin' . $feedbackplugin->plugin->get_subtype(),
1285                                    'returnaction'=>$feedbackplugin->returnaction,
1286                                    'returnparams'=>http_build_query($feedbackplugin->returnparams));
1287                 $url = new moodle_url('/mod/assign/view.php', $urlparams);
1288                 $link .= '<noscript>';
1289                 $link .= $this->output->action_link($url, $icon);
1290                 $link .= '</noscript>';
1292                 $link .= $this->output->spacer(array('width'=>15));
1293             }
1295             $o .= $link . $summary;
1296             $o .= $this->output->box_end();
1297             if ($showviewlink) {
1298                 $o .= $this->output->box_start('boxaligncenter hidefull full_' . $classsuffix);
1299                 $classes = 'expandsummaryicon contract_' . $classsuffix;
1300                 $o .= $this->output->pix_icon('t/switch_minus',
1301                                               get_string('viewsummary', 'assign'),
1302                                               null,
1303                                               array('class'=>$classes));
1304                 $o .= $feedbackplugin->plugin->view($feedbackplugin->grade);
1305                 $o .= $this->output->box_end();
1306             }
1307         } else if ($feedbackplugin->view == assign_feedback_plugin_feedback::FULL) {
1308             $o .= $this->output->box_start('boxaligncenter feedbackfull');
1309             $o .= $feedbackplugin->plugin->view($feedbackplugin->grade);
1310             $o .= $this->output->box_end();
1311         }
1313         return $o;
1314     }
1316     /**
1317      * Render a course index summary
1318      *
1319      * @param assign_course_index_summary $indexsummary
1320      * @return string
1321      */
1322     public function render_assign_course_index_summary(assign_course_index_summary $indexsummary) {
1323         $o = '';
1325         $strplural = get_string('modulenameplural', 'assign');
1326         $strsectionname  = $indexsummary->courseformatname;
1327         $strduedate = get_string('duedate', 'assign');
1328         $strsubmission = get_string('submission', 'assign');
1329         $strgrade = get_string('grade');
1331         $table = new html_table();
1332         if ($indexsummary->usesections) {
1333             $table->head  = array ($strsectionname, $strplural, $strduedate, $strsubmission, $strgrade);
1334             $table->align = array ('left', 'left', 'center', 'right', 'right');
1335         } else {
1336             $table->head  = array ($strplural, $strduedate, $strsubmission, $strgrade);
1337             $table->align = array ('left', 'left', 'center', 'right');
1338         }
1339         $table->data = array();
1341         $currentsection = '';
1342         foreach ($indexsummary->assignments as $info) {
1343             $params = array('id' => $info['cmid']);
1344             $link = html_writer::link(new moodle_url('/mod/assign/view.php', $params),
1345                                       $info['cmname']);
1346             $due = $info['timedue'] ? userdate($info['timedue']) : '-';
1348             $printsection = '';
1349             if ($indexsummary->usesections) {
1350                 if ($info['sectionname'] !== $currentsection) {
1351                     if ($info['sectionname']) {
1352                         $printsection = $info['sectionname'];
1353                     }
1354                     if ($currentsection !== '') {
1355                         $table->data[] = 'hr';
1356                     }
1357                     $currentsection = $info['sectionname'];
1358                 }
1359             }
1361             if ($indexsummary->usesections) {
1362                 $row = array($printsection, $link, $due, $info['submissioninfo'], $info['gradeinfo']);
1363             } else {
1364                 $row = array($link, $due, $info['submissioninfo'], $info['gradeinfo']);
1365             }
1366             $table->data[] = $row;
1367         }
1369         $o .= html_writer::table($table);
1371         return $o;
1372     }
1376     /**
1377      * Internal function - creates htmls structure suitable for YUI tree.
1378      *
1379      * @param assign_files $tree
1380      * @param array $dir
1381      * @return string
1382      */
1383     protected function htmllize_tree(assign_files $tree, $dir) {
1384         global $CFG;
1385         $yuiconfig = array();
1386         $yuiconfig['type'] = 'html';
1388         if (empty($dir['subdirs']) and empty($dir['files'])) {
1389             return '';
1390         }
1392         $result = '<ul>';
1393         foreach ($dir['subdirs'] as $subdir) {
1394             $image = $this->output->pix_icon(file_folder_icon(),
1395                                              $subdir['dirname'],
1396                                              'moodle',
1397                                              array('class'=>'icon'));
1398             $result .= '<li yuiConfig=\'' . json_encode($yuiconfig) . '\'>' .
1399                        '<div>' . $image . ' ' . s($subdir['dirname']) . '</div> ' .
1400                        $this->htmllize_tree($tree, $subdir) .
1401                        '</li>';
1402         }
1404         foreach ($dir['files'] as $file) {
1405             $filename = $file->get_filename();
1406             if ($CFG->enableplagiarism) {
1407                 require_once($CFG->libdir.'/plagiarismlib.php');
1408                 $plagiarismlinks = plagiarism_get_links(array('userid'=>$file->get_userid(),
1409                                                              'file'=>$file,
1410                                                              'cmid'=>$tree->cm->id,
1411                                                              'course'=>$tree->course));
1412             } else {
1413                 $plagiarismlinks = '';
1414             }
1415             $image = $this->output->pix_icon(file_file_icon($file),
1416                                              $filename,
1417                                              'moodle',
1418                                              array('class'=>'icon'));
1419             $result .= '<li yuiConfig=\'' . json_encode($yuiconfig) . '\'>' .
1420                        '<div>' . $image . ' ' .
1421                                  $file->fileurl . ' ' .
1422                                  $plagiarismlinks . ' ' .
1423                                  $file->portfoliobutton . '</div>' .
1424                        '</li>';
1425         }
1427         $result .= '</ul>';
1429         return $result;
1430     }
1432     /**
1433      * Helper method dealing with the fact we can not just fetch the output of flexible_table
1434      *
1435      * @param flexible_table $table The table to render
1436      * @param int $rowsperpage How many assignments to render in a page
1437      * @param bool $displaylinks - Whether to render links in the table
1438      *                             (e.g. downloads would not enable this)
1439      * @return string HTML
1440      */
1441     protected function flexible_table(flexible_table $table, $rowsperpage, $displaylinks) {
1443         $o = '';
1444         ob_start();
1445         $table->out($rowsperpage, $displaylinks);
1446         $o = ob_get_contents();
1447         ob_end_clean();
1449         return $o;
1450     }
1452     /**
1453      * Helper method dealing with the fact we can not just fetch the output of moodleforms
1454      *
1455      * @param moodleform $mform
1456      * @return string HTML
1457      */
1458     protected function moodleform(moodleform $mform) {
1460         $o = '';
1461         ob_start();
1462         $mform->display();
1463         $o = ob_get_contents();
1464         ob_end_clean();
1466         return $o;
1467     }
1469     /**
1470      * Defer to template..
1471      *
1472      * @param grading_app $app - All the data to render the grading app.
1473      */
1474     public function render_grading_app(grading_app $app) {
1475         $context = $app->export_for_template($this);
1476         return $this->render_from_template('mod_assign/grading_app', $context);
1477     }