PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/mod/assign/renderer.php

http://github.com/moodle/moodle
PHP | 1503 lines | 1103 code | 180 blank | 220 comment | 239 complexity | 11af46013a51ad4a448170aaaca0b393 MD5 | raw file
Possible License(s): MIT, AGPL-3.0, MPL-2.0-no-copyleft-exception, LGPL-3.0, GPL-3.0, Apache-2.0, LGPL-2.1, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  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. * This file contains a renderer for the assignment class
  18. *
  19. * @package mod_assign
  20. * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
  21. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  22. */
  23. defined('MOODLE_INTERNAL') || die();
  24. require_once($CFG->dirroot . '/mod/assign/locallib.php');
  25. use \mod_assign\output\grading_app;
  26. /**
  27. * A custom renderer class that extends the plugin_renderer_base and is used by the assign module.
  28. *
  29. * @package mod_assign
  30. * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
  31. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  32. */
  33. class mod_assign_renderer extends plugin_renderer_base {
  34. /**
  35. * Rendering assignment files
  36. *
  37. * @param context $context
  38. * @param int $userid
  39. * @param string $filearea
  40. * @param string $component
  41. * @return string
  42. */
  43. public function assign_files(context $context, $userid, $filearea, $component) {
  44. return $this->render(new assign_files($context, $userid, $filearea, $component));
  45. }
  46. /**
  47. * Rendering assignment files
  48. *
  49. * @param assign_files $tree
  50. * @return string
  51. */
  52. public function render_assign_files(assign_files $tree) {
  53. $this->htmlid = html_writer::random_id('assign_files_tree');
  54. $this->page->requires->js_init_call('M.mod_assign.init_tree', array(true, $this->htmlid));
  55. $html = '<div id="'.$this->htmlid.'">';
  56. $html .= $this->htmllize_tree($tree, $tree->dir);
  57. $html .= '</div>';
  58. if ($tree->portfolioform) {
  59. $html .= $tree->portfolioform;
  60. }
  61. return $html;
  62. }
  63. /**
  64. * Utility function to add a row of data to a table with 2 columns where the first column is the table's header.
  65. * Modified the table param and does not return a value.
  66. *
  67. * @param html_table $table The table to append the row of data to
  68. * @param string $first The first column text
  69. * @param string $second The second column text
  70. * @param array $firstattributes The first column attributes (optional)
  71. * @param array $secondattributes The second column attributes (optional)
  72. * @return void
  73. */
  74. private function add_table_row_tuple(html_table $table, $first, $second, $firstattributes = [],
  75. $secondattributes = []) {
  76. $row = new html_table_row();
  77. $cell1 = new html_table_cell($first);
  78. $cell1->header = true;
  79. if (!empty($firstattributes)) {
  80. $cell1->attributes = $firstattributes;
  81. }
  82. $cell2 = new html_table_cell($second);
  83. if (!empty($secondattributes)) {
  84. $cell2->attributes = $secondattributes;
  85. }
  86. $row->cells = array($cell1, $cell2);
  87. $table->data[] = $row;
  88. }
  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';
  101. $o = '';
  102. $o .= $this->output->heading($result->heading, 4);
  103. $o .= $this->output->notification($result->message, $classes);
  104. $o .= $this->output->continue_button($url);
  105. return $o;
  106. }
  107. /**
  108. * Render the generic form
  109. * @param assign_form $form The form to render
  110. * @return string
  111. */
  112. public function render_assign_form(assign_form $form) {
  113. $o = '';
  114. if ($form->jsinitfunction) {
  115. $this->page->requires->js_init_call($form->jsinitfunction, array());
  116. }
  117. $o .= $this->output->box_start('boxaligncenter ' . $form->classname);
  118. $o .= $this->moodleform($form->form);
  119. $o .= $this->output->box_end();
  120. return $o;
  121. }
  122. /**
  123. * Render the user summary
  124. *
  125. * @param assign_user_summary $summary The user summary to render
  126. * @return string
  127. */
  128. public function render_assign_user_summary(assign_user_summary $summary) {
  129. $o = '';
  130. $supendedclass = '';
  131. $suspendedicon = '';
  132. if (!$summary->user) {
  133. return;
  134. }
  135. if ($summary->suspendeduser) {
  136. $supendedclass = ' usersuspended';
  137. $suspendedstring = get_string('userenrolmentsuspended', 'grades');
  138. $suspendedicon = ' ' . $this->pix_icon('i/enrolmentsuspended', $suspendedstring);
  139. }
  140. $o .= $this->output->container_start('usersummary');
  141. $o .= $this->output->box_start('boxaligncenter usersummarysection'.$supendedclass);
  142. if ($summary->blindmarking) {
  143. $o .= get_string('hiddenuser', 'assign') . $summary->uniqueidforuser.$suspendedicon;
  144. } else {
  145. $o .= $this->output->user_picture($summary->user);
  146. $o .= $this->output->spacer(array('width'=>30));
  147. $urlparams = array('id' => $summary->user->id, 'course'=>$summary->courseid);
  148. $url = new moodle_url('/user/view.php', $urlparams);
  149. $fullname = fullname($summary->user, $summary->viewfullnames);
  150. $extrainfo = array();
  151. foreach ($summary->extrauserfields as $extrafield) {
  152. $extrainfo[] = $summary->user->$extrafield;
  153. }
  154. if (count($extrainfo)) {
  155. $fullname .= ' (' . implode(', ', $extrainfo) . ')';
  156. }
  157. $fullname .= $suspendedicon;
  158. $o .= $this->output->action_link($url, $fullname);
  159. }
  160. $o .= $this->output->box_end();
  161. $o .= $this->output->container_end();
  162. return $o;
  163. }
  164. /**
  165. * Render the submit for grading page
  166. *
  167. * @param assign_submit_for_grading_page $page
  168. * @return string
  169. */
  170. public function render_assign_submit_for_grading_page($page) {
  171. $o = '';
  172. $o .= $this->output->container_start('submitforgrading');
  173. $o .= $this->output->heading(get_string('confirmsubmissionheading', 'assign'), 3);
  174. $cancelurl = new moodle_url('/mod/assign/view.php', array('id' => $page->coursemoduleid));
  175. if (count($page->notifications)) {
  176. // At least one of the submission plugins is not ready for submission.
  177. $o .= $this->output->heading(get_string('submissionnotready', 'assign'), 4);
  178. foreach ($page->notifications as $notification) {
  179. $o .= $this->output->notification($notification);
  180. }
  181. $o .= $this->output->continue_button($cancelurl);
  182. } else {
  183. // All submission plugins ready - show the confirmation form.
  184. $o .= $this->moodleform($page->confirmform);
  185. }
  186. $o .= $this->output->container_end();
  187. return $o;
  188. }
  189. /**
  190. * Page is done - render the footer.
  191. *
  192. * @return void
  193. */
  194. public function render_footer() {
  195. return $this->output->footer();
  196. }
  197. /**
  198. * Render the header.
  199. *
  200. * @param assign_header $header
  201. * @return string
  202. */
  203. public function render_assign_header(assign_header $header) {
  204. $o = '';
  205. if ($header->subpage) {
  206. $this->page->navbar->add($header->subpage);
  207. $args = ['contextname' => $header->context->get_context_name(false, true), 'subpage' => $header->subpage];
  208. $title = get_string('subpagetitle', 'assign', $args);
  209. } else {
  210. $title = $header->context->get_context_name(false, true);
  211. }
  212. $courseshortname = $header->context->get_course_context()->get_context_name(false, true);
  213. $title = $courseshortname . ': ' . $title;
  214. $heading = format_string($header->assign->name, false, array('context' => $header->context));
  215. $this->page->set_title($title);
  216. $this->page->set_heading($this->page->course->fullname);
  217. $o .= $this->output->header();
  218. $o .= $this->output->heading($heading);
  219. if ($header->preface) {
  220. $o .= $header->preface;
  221. }
  222. if ($header->showintro) {
  223. $o .= $this->output->box_start('generalbox boxaligncenter', 'intro');
  224. $o .= format_module_intro('assign', $header->assign, $header->coursemoduleid);
  225. $o .= $header->postfix;
  226. $o .= $this->output->box_end();
  227. }
  228. return $o;
  229. }
  230. /**
  231. * Render the header for an individual plugin.
  232. *
  233. * @param assign_plugin_header $header
  234. * @return string
  235. */
  236. public function render_assign_plugin_header(assign_plugin_header $header) {
  237. $o = $header->plugin->view_header();
  238. return $o;
  239. }
  240. /**
  241. * Render a table containing the current status of the grading process.
  242. *
  243. * @param assign_grading_summary $summary
  244. * @return string
  245. */
  246. public function render_assign_grading_summary(assign_grading_summary $summary) {
  247. // Create a table for the data.
  248. $o = '';
  249. $o .= $this->output->container_start('gradingsummary');
  250. $o .= $this->output->heading(get_string('gradingsummary', 'assign'), 3);
  251. $o .= $this->output->box_start('boxaligncenter gradingsummarytable');
  252. $t = new html_table();
  253. // Visibility Status.
  254. $cell1content = get_string('hiddenfromstudents');
  255. $cell2content = (!$summary->isvisible) ? get_string('yes') : get_string('no');
  256. $this->add_table_row_tuple($t, $cell1content, $cell2content);
  257. // Status.
  258. if ($summary->teamsubmission) {
  259. if ($summary->warnofungroupedusers === assign_grading_summary::WARN_GROUPS_REQUIRED) {
  260. $o .= $this->output->notification(get_string('ungroupedusers', 'assign'));
  261. } else if ($summary->warnofungroupedusers === assign_grading_summary::WARN_GROUPS_OPTIONAL) {
  262. $o .= $this->output->notification(get_string('ungroupedusersoptional', 'assign'));
  263. }
  264. $cell1content = get_string('numberofteams', 'assign');
  265. } else {
  266. $cell1content = get_string('numberofparticipants', 'assign');
  267. }
  268. $cell2content = $summary->participantcount;
  269. $this->add_table_row_tuple($t, $cell1content, $cell2content);
  270. // Drafts count and dont show drafts count when using offline assignment.
  271. if ($summary->submissiondraftsenabled && $summary->submissionsenabled) {
  272. $cell1content = get_string('numberofdraftsubmissions', 'assign');
  273. $cell2content = $summary->submissiondraftscount;
  274. $this->add_table_row_tuple($t, $cell1content, $cell2content);
  275. }
  276. // Submitted for grading.
  277. if ($summary->submissionsenabled) {
  278. $cell1content = get_string('numberofsubmittedassignments', 'assign');
  279. $cell2content = $summary->submissionssubmittedcount;
  280. $this->add_table_row_tuple($t, $cell1content, $cell2content);
  281. if (!$summary->teamsubmission) {
  282. $cell1content = get_string('numberofsubmissionsneedgrading', 'assign');
  283. $cell2content = $summary->submissionsneedgradingcount;
  284. $this->add_table_row_tuple($t, $cell1content, $cell2content);
  285. }
  286. }
  287. $time = time();
  288. if ($summary->duedate) {
  289. // Due date.
  290. $cell1content = get_string('duedate', 'assign');
  291. $duedate = $summary->duedate;
  292. if ($summary->courserelativedatesmode) {
  293. // Returns a formatted string, in the format '10d 10h 45m'.
  294. $diffstr = get_time_interval_string($duedate, $summary->coursestartdate);
  295. if ($duedate >= $summary->coursestartdate) {
  296. $cell2content = get_string('relativedatessubmissionduedateafter', 'mod_assign',
  297. ['datediffstr' => $diffstr]);
  298. } else {
  299. $cell2content = get_string('relativedatessubmissionduedatebefore', 'mod_assign',
  300. ['datediffstr' => $diffstr]);
  301. }
  302. } else {
  303. $cell2content = userdate($duedate);
  304. }
  305. $this->add_table_row_tuple($t, $cell1content, $cell2content);
  306. // Time remaining.
  307. $cell1content = get_string('timeremaining', 'assign');
  308. if ($summary->courserelativedatesmode) {
  309. $cell2content = get_string('relativedatessubmissiontimeleft', 'mod_assign');
  310. } else {
  311. if ($duedate - $time <= 0) {
  312. $cell2content = get_string('assignmentisdue', 'assign');
  313. } else {
  314. $cell2content = format_time($duedate - $time);
  315. }
  316. }
  317. $this->add_table_row_tuple($t, $cell1content, $cell2content);
  318. if ($duedate < $time) {
  319. $cell1content = get_string('latesubmissions', 'assign');
  320. $cutoffdate = $summary->cutoffdate;
  321. if ($cutoffdate) {
  322. if ($cutoffdate > $time) {
  323. $cell2content = get_string('latesubmissionsaccepted', 'assign', userdate($summary->cutoffdate));
  324. } else {
  325. $cell2content = get_string('nomoresubmissionsaccepted', 'assign');
  326. }
  327. $this->add_table_row_tuple($t, $cell1content, $cell2content);
  328. }
  329. }
  330. }
  331. // All done - write the table.
  332. $o .= html_writer::table($t);
  333. $o .= $this->output->box_end();
  334. // Link to the grading page.
  335. $o .= html_writer::start_tag('center');
  336. $o .= $this->output->container_start('submissionlinks');
  337. $urlparams = array('id' => $summary->coursemoduleid, 'action' => 'grading');
  338. $url = new moodle_url('/mod/assign/view.php', $urlparams);
  339. $o .= html_writer::link($url, get_string('viewgrading', 'mod_assign'),
  340. ['class' => 'btn btn-secondary']);
  341. if ($summary->cangrade) {
  342. $urlparams = array('id' => $summary->coursemoduleid, 'action' => 'grader');
  343. $url = new moodle_url('/mod/assign/view.php', $urlparams);
  344. $o .= html_writer::link($url, get_string('grade'),
  345. ['class' => 'btn btn-primary ml-1']);
  346. }
  347. $o .= $this->output->container_end();
  348. // Close the container and insert a spacer.
  349. $o .= $this->output->container_end();
  350. $o .= html_writer::end_tag('center');
  351. return $o;
  352. }
  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. $o = '';
  361. $o .= $this->output->container_start('feedback');
  362. $o .= $this->output->heading(get_string('feedback', 'assign'), 3);
  363. $o .= $this->output->box_start('boxaligncenter feedbacktable');
  364. $t = new html_table();
  365. // Grade.
  366. if (isset($status->gradefordisplay)) {
  367. $cell1content = get_string('grade');
  368. $cell2content = $status->gradefordisplay;
  369. $this->add_table_row_tuple($t, $cell1content, $cell2content);
  370. // Grade date.
  371. $cell1content = get_string('gradedon', 'assign');
  372. $cell2content = userdate($status->gradeddate);
  373. $this->add_table_row_tuple($t, $cell1content, $cell2content);
  374. }
  375. if ($status->grader) {
  376. // Grader.
  377. $cell1content = get_string('gradedby', 'assign');
  378. $cell2content = $this->output->user_picture($status->grader) .
  379. $this->output->spacer(array('width' => 30)) .
  380. fullname($status->grader, $status->canviewfullnames);
  381. $this->add_table_row_tuple($t, $cell1content, $cell2content);
  382. }
  383. foreach ($status->feedbackplugins as $plugin) {
  384. if ($plugin->is_enabled() &&
  385. $plugin->is_visible() &&
  386. $plugin->has_user_summary() &&
  387. !empty($status->grade) &&
  388. !$plugin->is_empty($status->grade)) {
  389. $displaymode = assign_feedback_plugin_feedback::SUMMARY;
  390. $pluginfeedback = new assign_feedback_plugin_feedback($plugin,
  391. $status->grade,
  392. $displaymode,
  393. $status->coursemoduleid,
  394. $status->returnaction,
  395. $status->returnparams);
  396. $cell1content = $plugin->get_name();
  397. $cell2content = $this->render($pluginfeedback);
  398. $this->add_table_row_tuple($t, $cell1content, $cell2content);
  399. }
  400. }
  401. $o .= html_writer::table($t);
  402. $o .= $this->output->box_end();
  403. $o .= $this->output->container_end();
  404. return $o;
  405. }
  406. /**
  407. * Render a compact view of the current status of the submission.
  408. *
  409. * @param assign_submission_status_compact $status
  410. * @return string
  411. */
  412. public function render_assign_submission_status_compact(assign_submission_status_compact $status) {
  413. $o = '';
  414. $o .= $this->output->container_start('submissionstatustable');
  415. $o .= $this->output->heading(get_string('submission', 'assign'), 3);
  416. $time = time();
  417. if ($status->teamsubmissionenabled) {
  418. $group = $status->submissiongroup;
  419. if ($group) {
  420. $team = format_string($group->name, false, $status->context);
  421. } else if ($status->preventsubmissionnotingroup) {
  422. if (count($status->usergroups) == 0) {
  423. $team = '<span class="alert alert-error">' . get_string('noteam', 'assign') . '</span>';
  424. } else if (count($status->usergroups) > 1) {
  425. $team = '<span class="alert alert-error">' . get_string('multipleteams', 'assign') . '</span>';
  426. }
  427. } else {
  428. $team = get_string('defaultteam', 'assign');
  429. }
  430. $o .= $this->output->container(get_string('teamname', 'assign', $team), 'teamname');
  431. }
  432. if (!$status->teamsubmissionenabled) {
  433. if ($status->submission && $status->submission->status != ASSIGN_SUBMISSION_STATUS_NEW) {
  434. $statusstr = get_string('submissionstatus_' . $status->submission->status, 'assign');
  435. $o .= $this->output->container($statusstr, 'submissionstatus' . $status->submission->status);
  436. } else {
  437. if (!$status->submissionsenabled) {
  438. $o .= $this->output->container(get_string('noonlinesubmissions', 'assign'), 'submissionstatus');
  439. } else {
  440. $o .= $this->output->container(get_string('noattempt', 'assign'), 'submissionstatus');
  441. }
  442. }
  443. } else {
  444. $group = $status->submissiongroup;
  445. if (!$group && $status->preventsubmissionnotingroup) {
  446. $o .= $this->output->container(get_string('nosubmission', 'assign'), 'submissionstatus');
  447. } else if ($status->teamsubmission && $status->teamsubmission->status != ASSIGN_SUBMISSION_STATUS_NEW) {
  448. $teamstatus = $status->teamsubmission->status;
  449. $submissionsummary = get_string('submissionstatus_' . $teamstatus, 'assign');
  450. $groupid = 0;
  451. if ($status->submissiongroup) {
  452. $groupid = $status->submissiongroup->id;
  453. }
  454. $members = $status->submissiongroupmemberswhoneedtosubmit;
  455. $userslist = array();
  456. foreach ($members as $member) {
  457. $urlparams = array('id' => $member->id, 'course' => $status->courseid);
  458. $url = new moodle_url('/user/view.php', $urlparams);
  459. if ($status->view == assign_submission_status::GRADER_VIEW && $status->blindmarking) {
  460. $userslist[] = $member->alias;
  461. } else {
  462. $fullname = fullname($member, $status->canviewfullnames);
  463. $userslist[] = $this->output->action_link($url, $fullname);
  464. }
  465. }
  466. if (count($userslist) > 0) {
  467. $userstr = join(', ', $userslist);
  468. $formatteduserstr = get_string('userswhoneedtosubmit', 'assign', $userstr);
  469. $submissionsummary .= $this->output->container($formatteduserstr);
  470. }
  471. $o .= $this->output->container($submissionsummary, 'submissionstatus' . $status->teamsubmission->status);
  472. } else {
  473. if (!$status->submissionsenabled) {
  474. $o .= $this->output->container(get_string('noonlinesubmissions', 'assign'), 'submissionstatus');
  475. } else {
  476. $o .= $this->output->container(get_string('nosubmission', 'assign'), 'submissionstatus');
  477. }
  478. }
  479. }
  480. // Is locked?
  481. if ($status->locked) {
  482. $o .= $this->output->container(get_string('submissionslocked', 'assign'), 'submissionlocked');
  483. }
  484. // Grading status.
  485. $statusstr = '';
  486. $classname = 'gradingstatus';
  487. if ($status->gradingstatus == ASSIGN_GRADING_STATUS_GRADED ||
  488. $status->gradingstatus == ASSIGN_GRADING_STATUS_NOT_GRADED) {
  489. $statusstr = get_string($status->gradingstatus, 'assign');
  490. } else {
  491. $gradingstatus = 'markingworkflowstate' . $status->gradingstatus;
  492. $statusstr = get_string($gradingstatus, 'assign');
  493. }
  494. if ($status->gradingstatus == ASSIGN_GRADING_STATUS_GRADED ||
  495. $status->gradingstatus == ASSIGN_MARKING_WORKFLOW_STATE_RELEASED) {
  496. $classname = 'submissiongraded';
  497. } else {
  498. $classname = 'submissionnotgraded';
  499. }
  500. $o .= $this->output->container($statusstr, $classname);
  501. $submission = $status->teamsubmission ? $status->teamsubmission : $status->submission;
  502. $duedate = $status->duedate;
  503. if ($duedate > 0) {
  504. if ($status->extensionduedate) {
  505. // Extension date.
  506. $duedate = $status->extensionduedate;
  507. }
  508. // Time remaining.
  509. $classname = 'timeremaining';
  510. if ($duedate - $time <= 0) {
  511. if (!$submission ||
  512. $submission->status != ASSIGN_SUBMISSION_STATUS_SUBMITTED) {
  513. if ($status->submissionsenabled) {
  514. $remaining = get_string('overdue', 'assign', format_time($time - $duedate));
  515. $classname = 'overdue';
  516. } else {
  517. $remaining = get_string('duedatereached', 'assign');
  518. }
  519. } else {
  520. if ($submission->timemodified > $duedate) {
  521. $remaining = get_string('submittedlate',
  522. 'assign',
  523. format_time($submission->timemodified - $duedate));
  524. $classname = 'latesubmission';
  525. } else {
  526. $remaining = get_string('submittedearly',
  527. 'assign',
  528. format_time($submission->timemodified - $duedate));
  529. $classname = 'earlysubmission';
  530. }
  531. }
  532. } else {
  533. $remaining = get_string('paramtimeremaining', 'assign', format_time($duedate - $time));
  534. }
  535. $o .= $this->output->container($remaining, $classname);
  536. }
  537. // Show graders whether this submission is editable by students.
  538. if ($status->view == assign_submission_status::GRADER_VIEW) {
  539. if ($status->canedit) {
  540. $o .= $this->output->container(get_string('submissioneditable', 'assign'), 'submissioneditable');
  541. } else {
  542. $o .= $this->output->container(get_string('submissionnoteditable', 'assign'), 'submissionnoteditable');
  543. }
  544. }
  545. // Grading criteria preview.
  546. if (!empty($status->gradingcontrollerpreview)) {
  547. $o .= $this->output->container($status->gradingcontrollerpreview, 'gradingmethodpreview');
  548. }
  549. if ($submission) {
  550. if (!$status->teamsubmission || $status->submissiongroup != false || !$status->preventsubmissionnotingroup) {
  551. foreach ($status->submissionplugins as $plugin) {
  552. $pluginshowsummary = !$plugin->is_empty($submission) || !$plugin->allow_submissions();
  553. if ($plugin->is_enabled() &&
  554. $plugin->is_visible() &&
  555. $plugin->has_user_summary() &&
  556. $pluginshowsummary
  557. ) {
  558. $displaymode = assign_submission_plugin_submission::SUMMARY;
  559. $pluginsubmission = new assign_submission_plugin_submission($plugin,
  560. $submission,
  561. $displaymode,
  562. $status->coursemoduleid,
  563. $status->returnaction,
  564. $status->returnparams);
  565. $plugincomponent = $plugin->get_subtype() . '_' . $plugin->get_type();
  566. $o .= $this->output->container($this->render($pluginsubmission), 'assignsubmission ' . $plugincomponent);
  567. }
  568. }
  569. }
  570. }
  571. $o .= $this->output->container_end();
  572. return $o;
  573. }
  574. /**
  575. * Render a table containing the current status of the submission.
  576. *
  577. * @param assign_submission_status $status
  578. * @return string
  579. */
  580. public function render_assign_submission_status(assign_submission_status $status) {
  581. $o = '';
  582. $o .= $this->output->container_start('submissionstatustable');
  583. $o .= $this->output->heading(get_string('submissionstatusheading', 'assign'), 3);
  584. $time = time();
  585. if ($status->allowsubmissionsfromdate &&
  586. $time <= $status->allowsubmissionsfromdate) {
  587. $o .= $this->output->box_start('generalbox boxaligncenter submissionsalloweddates');
  588. if ($status->alwaysshowdescription) {
  589. $date = userdate($status->allowsubmissionsfromdate);
  590. $o .= get_string('allowsubmissionsfromdatesummary', 'assign', $date);
  591. } else {
  592. $date = userdate($status->allowsubmissionsfromdate);
  593. $o .= get_string('allowsubmissionsanddescriptionfromdatesummary', 'assign', $date);
  594. }
  595. $o .= $this->output->box_end();
  596. }
  597. $o .= $this->output->box_start('boxaligncenter submissionsummarytable');
  598. $t = new html_table();
  599. $warningmsg = '';
  600. if ($status->teamsubmissionenabled) {
  601. $cell1content = get_string('submissionteam', 'assign');
  602. $group = $status->submissiongroup;
  603. if ($group) {
  604. $cell2content = format_string($group->name, false, $status->context);
  605. } else if ($status->preventsubmissionnotingroup) {
  606. if (count($status->usergroups) == 0) {
  607. $notification = new \core\output\notification(get_string('noteam', 'assign'), 'error');
  608. $notification->set_show_closebutton(false);
  609. $warningmsg = $this->output->notification(get_string('noteam_desc', 'assign'), 'error');
  610. } else if (count($status->usergroups) > 1) {
  611. $notification = new \core\output\notification(get_string('multipleteams', 'assign'), 'error');
  612. $notification->set_show_closebutton(false);
  613. $warningmsg = $this->output->notification(get_string('multipleteams_desc', 'assign'), 'error');
  614. }
  615. $cell2content = $this->output->render($notification);
  616. } else {
  617. $cell2content = get_string('defaultteam', 'assign');
  618. }
  619. $this->add_table_row_tuple($t, $cell1content, $cell2content);
  620. }
  621. if ($status->attemptreopenmethod != ASSIGN_ATTEMPT_REOPEN_METHOD_NONE) {
  622. $currentattempt = 1;
  623. if (!$status->teamsubmissionenabled) {
  624. if ($status->submission) {
  625. $currentattempt = $status->submission->attemptnumber + 1;
  626. }
  627. } else {
  628. if ($status->teamsubmission) {
  629. $currentattempt = $status->teamsubmission->attemptnumber + 1;
  630. }
  631. }
  632. $cell1content = get_string('attemptnumber', 'assign');
  633. $maxattempts = $status->maxattempts;
  634. if ($maxattempts == ASSIGN_UNLIMITED_ATTEMPTS) {
  635. $cell2content = get_string('currentattempt', 'assign', $currentattempt);
  636. } else {
  637. $cell2content = get_string('currentattemptof', 'assign',
  638. array('attemptnumber' => $currentattempt, 'maxattempts' => $maxattempts));
  639. }
  640. $this->add_table_row_tuple($t, $cell1content, $cell2content);
  641. }
  642. $cell1content = get_string('submissionstatus', 'assign');
  643. $cell2attributes = [];
  644. if (!$status->teamsubmissionenabled) {
  645. if ($status->submission && $status->submission->status != ASSIGN_SUBMISSION_STATUS_NEW) {
  646. $cell2content = get_string('submissionstatus_' . $status->submission->status, 'assign');
  647. $cell2attributes = array('class' => 'submissionstatus' . $status->submission->status);
  648. } else {
  649. if (!$status->submissionsenabled) {
  650. $cell2content = get_string('noonlinesubmissions', 'assign');
  651. } else {
  652. $cell2content = get_string('noattempt', 'assign');
  653. }
  654. }
  655. } else {
  656. $group = $status->submissiongroup;
  657. if (!$group && $status->preventsubmissionnotingroup) {
  658. $cell2content = get_string('nosubmission', 'assign');
  659. } else if ($status->teamsubmission && $status->teamsubmission->status != ASSIGN_SUBMISSION_STATUS_NEW) {
  660. $teamstatus = $status->teamsubmission->status;
  661. $cell2content = get_string('submissionstatus_' . $teamstatus, 'assign');
  662. $members = $status->submissiongroupmemberswhoneedtosubmit;
  663. $userslist = array();
  664. foreach ($members as $member) {
  665. $urlparams = array('id' => $member->id, 'course'=>$status->courseid);
  666. $url = new moodle_url('/user/view.php', $urlparams);
  667. if ($status->view == assign_submission_status::GRADER_VIEW && $status->blindmarking) {
  668. $userslist[] = $member->alias;
  669. } else {
  670. $fullname = fullname($member, $status->canviewfullnames);
  671. $userslist[] = $this->output->action_link($url, $fullname);
  672. }
  673. }
  674. if (count($userslist) > 0) {
  675. $userstr = join(', ', $userslist);
  676. $formatteduserstr = get_string('userswhoneedtosubmit', 'assign', $userstr);
  677. $cell2content .= $this->output->container($formatteduserstr);
  678. }
  679. $cell2attributes = array('class' => 'submissionstatus' . $status->teamsubmission->status);
  680. } else {
  681. if (!$status->submissionsenabled) {
  682. $cell2content = get_string('noonlinesubmissions', 'assign');
  683. } else {
  684. $cell2content = get_string('nosubmission', 'assign');
  685. }
  686. }
  687. }
  688. $this->add_table_row_tuple($t, $cell1content, $cell2content, [], $cell2attributes);
  689. // Is locked?
  690. if ($status->locked) {
  691. $cell1content = '';
  692. $cell2content = get_string('submissionslocked', 'assign');
  693. $cell2attributes = array('class' => 'submissionlocked');
  694. $this->add_table_row_tuple($t, $cell1content, $cell2content, [], $cell2attributes);
  695. }
  696. // Grading status.
  697. $cell1content = get_string('gradingstatus', 'assign');
  698. if ($status->gradingstatus == ASSIGN_GRADING_STATUS_GRADED ||
  699. $status->gradingstatus == ASSIGN_GRADING_STATUS_NOT_GRADED) {
  700. $cell2content = get_string($status->gradingstatus, 'assign');
  701. } else {
  702. $gradingstatus = 'markingworkflowstate' . $status->gradingstatus;
  703. $cell2content = get_string($gradingstatus, 'assign');
  704. }
  705. if ($status->gradingstatus == ASSIGN_GRADING_STATUS_GRADED ||
  706. $status->gradingstatus == ASSIGN_MARKING_WORKFLOW_STATE_RELEASED) {
  707. $cell2attributes = array('class' => 'submissiongraded');
  708. } else {
  709. $cell2attributes = array('class' => 'submissionnotgraded');
  710. }
  711. $this->add_table_row_tuple($t, $cell1content, $cell2content, [], $cell2attributes);
  712. $submission = $status->teamsubmission ? $status->teamsubmission : $status->submission;
  713. $duedate = $status->duedate;
  714. if ($duedate > 0) {
  715. // Due date.
  716. $cell1content = get_string('duedate', 'assign');
  717. $cell2content = userdate($duedate);
  718. $this->add_table_row_tuple($t, $cell1content, $cell2content);
  719. if ($status->view == assign_submission_status::GRADER_VIEW) {
  720. if ($status->cutoffdate) {
  721. // Cut off date.
  722. $cell1content = get_string('cutoffdate', 'assign');
  723. $cell2content = userdate($status->cutoffdate);
  724. $this->add_table_row_tuple($t, $cell1content, $cell2content);
  725. }
  726. }
  727. if ($status->extensionduedate) {
  728. // Extension date.
  729. $cell1content = get_string('extensionduedate', 'assign');
  730. $cell2content = userdate($status->extensionduedate);
  731. $this->add_table_row_tuple($t, $cell1content, $cell2content);
  732. $duedate = $status->extensionduedate;
  733. }
  734. // Time remaining.
  735. $cell1content = get_string('timeremaining', 'assign');
  736. $cell2attributes = [];
  737. if ($duedate - $time <= 0) {
  738. if (!$submission ||
  739. $submission->status != ASSIGN_SUBMISSION_STATUS_SUBMITTED) {
  740. if ($status->submissionsenabled) {
  741. $cell2content = get_string('overdue', 'assign', format_time($time - $duedate));
  742. $cell2attributes = array('class' => 'overdue');
  743. } else {
  744. $cell2content = get_string('duedatereached', 'assign');
  745. }
  746. } else {
  747. if ($submission->timemodified > $duedate) {
  748. $cell2content = get_string('submittedlate',
  749. 'assign',
  750. format_time($submission->timemodified - $duedate));
  751. $cell2attributes = array('class' => 'latesubmission');
  752. } else {
  753. $cell2content = get_string('submittedearly',
  754. 'assign',
  755. format_time($submission->timemodified - $duedate));
  756. $cell2attributes = array('class' => 'earlysubmission');
  757. }
  758. }
  759. } else {
  760. $cell2content = format_time($duedate - $time);
  761. }
  762. $this->add_table_row_tuple($t, $cell1content, $cell2content, [], $cell2attributes);
  763. }
  764. // Show graders whether this submission is editable by students.
  765. if ($status->view == assign_submission_status::GRADER_VIEW) {
  766. $cell1content = get_string('editingstatus', 'assign');
  767. if ($status->canedit) {
  768. $cell2content = get_string('submissioneditable', 'assign');
  769. $cell2attributes = array('class' => 'submissioneditable');
  770. } else {
  771. $cell2content = get_string('submissionnoteditable', 'assign');
  772. $cell2attributes = array('class' => 'submissionnoteditable');
  773. }
  774. $this->add_table_row_tuple($t, $cell1content, $cell2content, [], $cell2attributes);
  775. }
  776. // Grading criteria preview.
  777. if (!empty($status->gradingcontrollerpreview)) {
  778. $cell1content = get_string('gradingmethodpreview', 'assign');
  779. $cell2content = $status->gradingcontrollerpreview;
  780. $this->add_table_row_tuple($t, $cell1content, $cell2content, [], $cell2attributes);
  781. }
  782. // Last modified.
  783. if ($submission) {
  784. $cell1content = get_string('timemodified', 'assign');
  785. if ($submission->status != ASSIGN_SUBMISSION_STATUS_NEW) {
  786. $cell2content = userdate($submission->timemodified);
  787. } else {
  788. $cell2content = "-";
  789. }
  790. $this->add_table_row_tuple($t, $cell1content, $cell2content);
  791. if (!$status->teamsubmission || $status->submissiongroup != false || !$status->preventsubmissionnotingroup) {
  792. foreach ($status->submissionplugins as $plugin) {
  793. $pluginshowsummary = !$plugin->is_empty($submission) || !$plugin->allow_submissions();
  794. if ($plugin->is_enabled() &&
  795. $plugin->is_visible() &&
  796. $plugin->has_user_summary() &&
  797. $pluginshowsummary
  798. ) {
  799. $cell1content = $plugin->get_name();
  800. $displaymode = assign_submission_plugin_submission::SUMMARY;
  801. $pluginsubmission = new assign_submission_plugin_submission($plugin,
  802. $submission,
  803. $displaymode,
  804. $status->coursemoduleid,
  805. $status->returnaction,
  806. $status->returnparams);
  807. $cell2content = $this->render($pluginsubmission);
  808. $this->add_table_row_tuple($t, $cell1content, $cell2content);
  809. }
  810. }
  811. }
  812. }
  813. $o .= $warningmsg;
  814. $o .= html_writer::table($t);
  815. $o .= $this->output->box_end();
  816. // Links.
  817. if ($status->view == assign_submission_status::STUDENT_VIEW) {
  818. if ($status->canedit) {
  819. if (!$submission || $submission->status == ASSIGN_SUBMISSION_STATUS_NEW) {
  820. $o .= $this->output->box_start('generalbox submissionaction');
  821. $urlparams = array('id' => $status->coursemoduleid, 'action' => 'editsubmission');
  822. $o .= $this->output->single_button(new moodle_url('/mod/assign/view.php', $urlparams),
  823. get_string('addsubmission', 'assign'), 'get');
  824. $o .= $this->output->box_start('boxaligncenter submithelp');
  825. $o .= get_string('addsubmission_help', 'assign');
  826. $o .= $this->output->box_end();
  827. $o .= $this->output->box_end();
  828. } else if ($submission->status == ASSIGN_SUBMISSION_STATUS_REOPENED) {
  829. $o .= $this->output->box_start('generalbox submissionaction');
  830. $urlparams = array('id' => $status->coursemoduleid,
  831. 'action' => 'editprevioussubmission',
  832. 'sesskey'=>sesskey());
  833. $o .= $this->output->single_button(new moodle_url('/mod/assign/view.php', $urlparams),
  834. get_string('addnewattemptfromprevious', 'assign'), 'get');
  835. $o .= $this->output->box_start('boxaligncenter submithelp');
  836. $o .= get_string('addnewattemptfromprevious_help', 'assign');
  837. $o .= $this->output->box_end();
  838. $o .= $this->output->box_end();
  839. $o .= $this->output->box_start('generalbox submissionaction');
  840. $urlparams = array('id' => $status->coursemoduleid, 'action' => 'editsubmission');
  841. $o .= $this->output->single_button(new moodle_url('/mod/assign/view.php', $urlparams),
  842. get_string('addnewattempt', 'assign'), 'get');
  843. $o .= $this->output->box_start('boxaligncenter submithelp');
  844. $o .= get_string('addnewattempt_help', 'assign');
  845. $o .= $this->output->box_end();
  846. $o .= $this->output->box_end();
  847. } else {
  848. $o .= $this->output->box_start('generalbox submissionaction');
  849. $urlparams = array('id' => $status->coursemoduleid, 'action' => 'editsubmission');
  850. $o .= $this->output->single_button(new moodle_url('/mod/assign/view.php', $urlparams),
  851. get_string('editsubmission', 'assign'), 'get');
  852. $urlparams = array('id' => $status->coursemoduleid, 'action' => 'removesubmissionconfirm');
  853. $o .= $this->output->single_button(new moodle_url('/mod/assign/view.php', $urlparams),
  854. get_string('removesubmission', 'assign'), 'get');
  855. $o .= $this->output->box_start('boxaligncenter submithelp');
  856. $o .= get_string('editsubmission_help', 'assign');
  857. $o .= $this->output->box_end();
  858. $o .= $this->output->box_end();
  859. }
  860. }
  861. if ($status->cansubmit) {
  862. $urlparams = array('id' => $status->coursemoduleid, 'action'=>'submit');
  863. $o .= $this->output->box_start('generalbox submissionaction');
  864. $o .= $this->output->single_button(new moodle_url('/mod/assign/view.php', $urlparams),
  865. get_string('submitassignment', 'assign'), 'get');
  866. $o .= $this->output->box_start('boxaligncenter submithelp');
  867. $o .= get_string('submitassignment_help', 'assign');
  868. $o .= $this->output->box_end();
  869. $o .= $this->output->box_end();
  870. }
  871. }
  872. $o .= $this->output->container_end();
  873. return $o;
  874. }
  875. /**
  876. * Output the attempt history chooser for this assignment
  877. *
  878. * @param assign_attempt_history_chooser $history
  879. * @return string
  880. */
  881. public function render_assign_attempt_history_chooser(assign_attempt_history_chooser $history) {
  882. $o = '';
  883. $context = $history->export_for_template($this);
  884. $o .= $this->render_from_template('mod_assign/attempt_history_chooser', $context);
  885. return $o;
  886. }
  887. /**
  888. * Output the attempt history for this assignment
  889. *
  890. * @param assign_attempt_history $history
  891. * @return string
  892. */
  893. public function render_assign_attempt_history(assign_attempt_history $history) {
  894. $o = '';
  895. // Don't show the last one because it is the current submission.
  896. array_pop($history->submissions);
  897. // Show newest to oldest.
  898. $history->submissions = array_reverse($history->submissions);
  899. if (empty($history->submissions)) {
  900. return '';
  901. }
  902. $containerid = 'attempthistory' . uniqid();
  903. $o .= $this->output->heading(get_string('attempthistory', 'assign'), 3);
  904. $o .= $this->box_start('attempthistory', $containerid);
  905. foreach ($history->submissions as $i => $submission) {
  906. $grade = null;
  907. foreach ($history->grades as $onegrade) {
  908. if ($onegrade->attemptnumber == $submission->attemptnumber) {
  909. if ($onegrade->grade != ASSIGN_GRADE_NOT_SET) {
  910. $grade = $onegrade;
  911. }
  912. break;
  913. }
  914. }
  915. if ($submission) {
  916. $submissionsummary = userdate($submission->timemodified);
  917. } else {
  918. $submissionsummary = get_string('nosubmission', 'assign');
  919. }
  920. $attemptsummaryparams = array('attemptnumber'=>$submission->attemptnumber+1,
  921. 'submissionsummary'=>$submissionsummary);
  922. $o .= $this->heading(get_string('attemptheading', 'assign', $attemptsummaryparams), 4);
  923. $t = new html_table();
  924. if ($submission) {
  925. $cell1content = get_string('submissionstatus', 'assign');
  926. $cell2content = get_string('submissionstatus_' . $submission->status, 'assign');
  927. $this->add_table_row_tuple($t, $cell1content, $cell2content);
  928. foreach ($history->submissionplugins as $plugin) {
  929. $pluginshowsummary = !$plugin->is_empty($submission) || !$plugin->allow_submissions();
  930. if ($plugin->is_enabled() &&
  931. $plugin->is_visible() &&
  932. $plugin->has_user_summary() &&
  933. $pluginshowsummary) {
  934. $cell1content = $plugin->get_name();
  935. $pluginsubmission = new assign_submission_plugin_submission($plugin,
  936. $submission,
  937. assign_submission_plugin_submission::SUMMARY,
  938. $history->coursemoduleid,
  939. $history->returnaction,
  940. $history->returnparams);
  941. $cell2content = $this->render($pluginsubmission);
  942. $this->add_table_row_tuple($t, $cell1content, $cell2content);
  943. }
  944. }
  945. }
  946. if ($grade) {
  947. // Heading 'feedback'.
  948. $title = get_string('feedback', 'assign', $i);
  949. $title .= $this->output->spacer(array('width'=>10));
  950. if ($history->cangrade) {
  951. // Edit previous feedback.
  952. $returnparams = http_build_query($history->returnparams);
  953. $urlparams = array('id' => $history->coursemoduleid,
  954. 'rownum'=>$history->rownum,
  955. 'useridlistid'=>$history->useridlistid,
  956. 'attemptnumber'=>$grade->attemptnumber,
  957. 'action'=>'grade',
  958. 'returnaction'=>$history->returnaction,
  959. 'returnparams'=>$returnparams);
  960. $url = new moodle_url('/mod/assign/view.php', $urlparams);
  961. $icon = new pix_icon('gradefeedback',
  962. get_string('editattemptfeedback', 'assign', $grade->attemptnumber+1),
  963. 'mod_assign');
  964. $title .= $this->output->action_icon($url, $icon);
  965. }
  966. $cell = new html_table_cell($title);
  967. $cell->attributes['class'] = 'feedbacktitle';
  968. $cell->colspan = 2;
  969. $t->data[] = new html_table_row(array($cell));
  970. // Grade.
  971. $cell1content = get_string('grade');
  972. $cell2content = $grade->gradefordisplay;
  973. $this->add_table_row_tuple($t, $cell1content, $cell2content);
  974. // Graded on.
  975. $cell1content = get_string('gradedon', 'assign');
  976. $cell2content = userdate($grade->timemodified);
  977. $this->add_table_row_tuple($t, $cell1content, $cell2content);

Large files files are truncated, but you can click here to view the full file