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