PageRenderTime 70ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/mod/assignment/type/upload/assignment.class.php

https://bitbucket.org/systime/screening2
PHP | 1083 lines | 828 code | 215 blank | 40 comment | 139 complexity | 5bdc7ba25eb5520a4e8021837198eea1 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, GPL-3.0, BSD-3-Clause, LGPL-2.0
  1. <?php // $Id: assignment.class.php,v 1.32.2.19 2010/11/09 02:39:18 aparup Exp $
  2. require_once($CFG->libdir.'/formslib.php');
  3. define('ASSIGNMENT_STATUS_SUBMITTED', 'submitted'); // student thinks it is finished
  4. define('ASSIGNMENT_STATUS_CLOSED', 'closed'); // teacher prevents more submissions
  5. /**
  6. * Extend the base assignment class for assignments where you upload a single file
  7. *
  8. */
  9. class assignment_upload extends assignment_base {
  10. function assignment_upload($cmid='staticonly', $assignment=NULL, $cm=NULL, $course=NULL) {
  11. parent::assignment_base($cmid, $assignment, $cm, $course);
  12. $this->type = 'upload';
  13. }
  14. function view() {
  15. global $USER;
  16. require_capability('mod/assignment:view', $this->context);
  17. add_to_log($this->course->id, 'assignment', 'view', "view.php?id={$this->cm->id}", $this->assignment->id, $this->cm->id);
  18. $this->view_header();
  19. if ($this->assignment->timeavailable > time()
  20. and !has_capability('mod/assignment:grade', $this->context) // grading user can see it anytime
  21. and $this->assignment->var3) { // force hiding before available date
  22. print_simple_box_start('center', '', '', 0, 'generalbox', 'intro');
  23. print_string('notavailableyet', 'assignment');
  24. print_simple_box_end();
  25. } else {
  26. $this->view_intro();
  27. }
  28. $this->view_dates();
  29. $filecount = $this->count_user_files($USER->id);
  30. $submission = $this->get_submission($USER->id);
  31. $this->view_feedback();
  32. if (!$this->drafts_tracked() or !$this->isopen() or $this->is_finalized($submission)) {
  33. print_heading(get_string('submission', 'assignment'), '', 3);
  34. } else {
  35. print_heading(get_string('submissiondraft', 'assignment'), '', 3);
  36. }
  37. if ($filecount and $submission) {
  38. print_simple_box($this->print_user_files($USER->id, true), 'center');
  39. } else {
  40. if (!$this->isopen() or $this->is_finalized($submission)) {
  41. print_simple_box(get_string('nofiles', 'assignment'), 'center');
  42. } else {
  43. print_simple_box(get_string('nofilesyet', 'assignment'), 'center');
  44. }
  45. }
  46. if (has_capability('mod/assignment:submit', $this->context)) {
  47. $this->view_upload_form();
  48. }
  49. if ($this->notes_allowed()) {
  50. print_heading(get_string('notes', 'assignment'), '', 3);
  51. $this->view_notes();
  52. }
  53. $this->view_final_submission();
  54. $this->view_footer();
  55. }
  56. function view_feedback($submission=NULL) {
  57. global $USER, $CFG;
  58. require_once($CFG->libdir.'/gradelib.php');
  59. if (!$submission) { /// Get submission for this assignment
  60. $submission = $this->get_submission($USER->id);
  61. }
  62. if (empty($submission->timemarked)) { /// Nothing to show, so print nothing
  63. if ($this->count_responsefiles($USER->id)) {
  64. print_heading(get_string('responsefiles', 'assignment', $this->course->teacher), '', 3);
  65. $responsefiles = $this->print_responsefiles($USER->id, true);
  66. print_simple_box($responsefiles, 'center');
  67. }
  68. return;
  69. }
  70. $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, $USER->id);
  71. $item = $grading_info->items[0];
  72. $grade = $item->grades[$USER->id];
  73. if ($grade->hidden or $grade->grade === false) { // hidden or error
  74. return;
  75. }
  76. if ($grade->grade === null and empty($grade->str_feedback)) { /// Nothing to show yet
  77. return;
  78. }
  79. $graded_date = $grade->dategraded;
  80. $graded_by = $grade->usermodified;
  81. /// We need the teacher info
  82. if (!$teacher = get_record('user', 'id', $graded_by)) {
  83. error('Could not find the teacher');
  84. }
  85. /// Print the feedback
  86. print_heading(get_string('submissionfeedback', 'assignment'), '', 3);
  87. echo '<table cellspacing="0" class="feedback">';
  88. echo '<tr>';
  89. echo '<td class="left picture">';
  90. print_user_picture($teacher, $this->course->id, $teacher->picture);
  91. echo '</td>';
  92. echo '<td class="topic">';
  93. echo '<div class="from">';
  94. echo '<div class="fullname">'.fullname($teacher).'</div>';
  95. echo '<div class="time">'.userdate($graded_date).'</div>';
  96. echo '</div>';
  97. echo '</td>';
  98. echo '</tr>';
  99. echo '<tr>';
  100. echo '<td class="left side">&nbsp;</td>';
  101. echo '<td class="content">';
  102. if ($this->assignment->grade) {
  103. echo '<div class="grade">';
  104. echo get_string("grade").': '.$grade->str_long_grade;
  105. echo '</div>';
  106. echo '<div class="clearer"></div>';
  107. }
  108. echo '<div class="comment">';
  109. echo $grade->str_feedback;
  110. echo '</div>';
  111. echo '</tr>';
  112. echo '<tr>';
  113. echo '<td class="left side">&nbsp;</td>';
  114. echo '<td class="content">';
  115. echo $this->print_responsefiles($USER->id, true);
  116. echo '</tr>';
  117. echo '</table>';
  118. }
  119. function view_upload_form() {
  120. global $CFG, $USER;
  121. $submission = $this->get_submission($USER->id);
  122. $struploadafile = get_string('uploadafile');
  123. $maxbytes = $this->assignment->maxbytes == 0 ? $this->course->maxbytes : $this->assignment->maxbytes;
  124. $strmaxsize = get_string('maxsize', '', display_size($maxbytes));
  125. if ($this->is_finalized($submission)) {
  126. // no uploading
  127. return;
  128. }
  129. if ($this->can_upload_file($submission)) {
  130. echo '<div style="text-align:center">';
  131. echo '<form enctype="multipart/form-data" method="post" action="upload.php">';
  132. echo '<fieldset class="invisiblefieldset">';
  133. echo "<p>$struploadafile ($strmaxsize)</p>";
  134. echo '<input type="hidden" name="id" value="'.$this->cm->id.'" />';
  135. echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
  136. echo '<input type="hidden" name="action" value="uploadfile" />';
  137. require_once($CFG->libdir.'/uploadlib.php');
  138. upload_print_form_fragment(1,array('newfile'),null,false,null,0,$this->assignment->maxbytes,false);
  139. echo '<input type="submit" name="save" value="'.get_string('uploadthisfile').'" />';
  140. echo '</fieldset>';
  141. echo '</form>';
  142. echo '</div>';
  143. echo '<br />';
  144. }
  145. }
  146. function view_notes() {
  147. global $USER;
  148. if ($submission = $this->get_submission($USER->id)
  149. and !empty($submission->data1)) {
  150. print_simple_box(format_text($submission->data1, FORMAT_HTML), 'center', '630px');
  151. } else {
  152. print_simple_box(get_string('notesempty', 'assignment'), 'center');
  153. }
  154. if ($this->can_update_notes($submission)) {
  155. $options = array ('id'=>$this->cm->id, 'action'=>'editnotes');
  156. echo '<div style="text-align:center">';
  157. print_single_button('upload.php', $options, get_string('edit'), 'post', '_self', false);
  158. echo '</div>';
  159. }
  160. }
  161. function view_final_submission() {
  162. global $CFG, $USER;
  163. $submission = $this->get_submission($USER->id);
  164. if ($this->isopen() and $this->can_finalize($submission)) {
  165. //print final submit button
  166. print_heading(get_string('submitformarking','assignment'), '', 3);
  167. echo '<div style="text-align:center">';
  168. echo '<form method="post" action="upload.php">';
  169. echo '<fieldset class="invisiblefieldset">';
  170. echo '<input type="hidden" name="id" value="'.$this->cm->id.'" />';
  171. echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
  172. echo '<input type="hidden" name="action" value="finalize" />';
  173. echo '<input type="submit" name="formarking" value="'.get_string('sendformarking', 'assignment').'" />';
  174. echo '</fieldset>';
  175. echo '</form>';
  176. echo '</div>';
  177. } else if (!$this->isopen()) {
  178. print_heading(get_string('nomoresubmissions','assignment'), '', 3);
  179. } else if ($this->drafts_tracked() and $state = $this->is_finalized($submission)) {
  180. if ($state == ASSIGNMENT_STATUS_SUBMITTED) {
  181. print_heading(get_string('submitedformarking','assignment'), '', 3);
  182. } else {
  183. print_heading(get_string('nomoresubmissions','assignment'), '', 3);
  184. }
  185. } else {
  186. //no submission yet
  187. }
  188. }
  189. /**
  190. * Return true if var3 == hide description till available day
  191. *
  192. *@return boolean
  193. */
  194. function description_is_hidden() {
  195. return ($this->assignment->var3 && (time() <= $this->assignment->timeavailable));
  196. }
  197. function custom_feedbackform($submission, $return=false) {
  198. global $CFG;
  199. $mode = optional_param('mode', '', PARAM_ALPHA);
  200. $offset = optional_param('offset', 0, PARAM_INT);
  201. $forcerefresh = optional_param('forcerefresh', 0, PARAM_BOOL);
  202. $output = get_string('responsefiles', 'assignment').': ';
  203. $output .= '<form enctype="multipart/form-data" method="post" '.
  204. "action=\"$CFG->wwwroot/mod/assignment/upload.php\">";
  205. $output .= '<div>';
  206. $output .= '<input type="hidden" name="id" value="'.$this->cm->id.'" />';
  207. $output .= '<input type="hidden" name="action" value="uploadresponse" />';
  208. $output .= '<input type="hidden" name="mode" value="'.$mode.'" />';
  209. $output .= '<input type="hidden" name="offset" value="'.$offset.'" />';
  210. $output .= '<input type="hidden" name="userid" value="'.$submission->userid.'" />';
  211. $output .= '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
  212. require_once($CFG->libdir.'/uploadlib.php');
  213. $output .= upload_print_form_fragment(1,array('newfile'),null,false,null,0,0,true);
  214. $output .= '<input type="submit" name="save" value="'.get_string('uploadthisfile').'" />';
  215. $output .= '</div>';
  216. $output .= '</form>';
  217. if ($forcerefresh) {
  218. $output .= $this->update_main_listing($submission);
  219. }
  220. $responsefiles = $this->print_responsefiles($submission->userid, true);
  221. if (!empty($responsefiles)) {
  222. $output .= $responsefiles;
  223. }
  224. if ($return) {
  225. return $output;
  226. }
  227. echo $output;
  228. return;
  229. }
  230. function print_student_answer($userid, $return=false){
  231. global $CFG;
  232. $filearea = $this->file_area_name($userid);
  233. $submission = $this->get_submission($userid);
  234. $output = '';
  235. if ($basedir = $this->file_area($userid)) {
  236. if ($this->drafts_tracked() and $this->isopen() and !$this->is_finalized($submission)) {
  237. $output .= '<strong>'.get_string('draft', 'assignment').':</strong> ';
  238. }
  239. if ($this->notes_allowed() and !empty($submission->data1)) {
  240. $output .= link_to_popup_window ('/mod/assignment/type/upload/notes.php?id='.$this->cm->id.'&amp;userid='.$userid,
  241. 'notes'.$userid, get_string('notes', 'assignment'), 500, 780, get_string('notes', 'assignment'), 'none', true, 'notesbutton'.$userid);
  242. $output .= '&nbsp;';
  243. }
  244. if ($files = get_directory_list($basedir, 'responses')) {
  245. require_once($CFG->libdir.'/filelib.php');
  246. foreach ($files as $key => $file) {
  247. $icon = mimeinfo('icon', $file);
  248. $ffurl = get_file_url("$filearea/$file");
  249. $output .= '<a href="'.$ffurl.'" ><img class="icon" src="'.$CFG->pixpath.'/f/'.$icon.'" alt="'.$icon.'" />'.$file.'</a>&nbsp;';
  250. }
  251. }
  252. }
  253. $output = '<div class="files">'.$output.'</div>';
  254. $output .= '<br />';
  255. return $output;
  256. }
  257. /**
  258. * Produces a list of links to the files uploaded by a user
  259. *
  260. * @param $userid int optional id of the user. If 0 then $USER->id is used.
  261. * @param $return boolean optional defaults to false. If true the list is returned rather than printed
  262. * @return string optional
  263. */
  264. function print_user_files($userid=0, $return=false) {
  265. global $CFG, $USER;
  266. $mode = optional_param('mode', '', PARAM_ALPHA);
  267. $offset = optional_param('offset', 0, PARAM_INT);
  268. if (!$userid) {
  269. if (!isloggedin()) {
  270. return '';
  271. }
  272. $userid = $USER->id;
  273. }
  274. $filearea = $this->file_area_name($userid);
  275. $output = '';
  276. $submission = $this->get_submission($userid);
  277. $candelete = $this->can_delete_files($submission);
  278. $strdelete = get_string('delete');
  279. if ($this->drafts_tracked() and $this->isopen() and !$this->is_finalized($submission) and !empty($mode)) { // only during grading
  280. $output .= '<strong>'.get_string('draft', 'assignment').':</strong><br />';
  281. }
  282. if ($this->notes_allowed() and !empty($submission->data1) and !empty($mode)) { // only during grading
  283. $npurl = $CFG->wwwroot."/mod/assignment/type/upload/notes.php?id={$this->cm->id}&amp;userid=$userid&amp;offset=$offset&amp;mode=single";
  284. $output .= '<a href="'.$npurl.'">'.get_string('notes', 'assignment').'</a><br />';
  285. }
  286. if ($basedir = $this->file_area($userid)) {
  287. if ($files = get_directory_list($basedir, 'responses')) {
  288. require_once($CFG->libdir.'/filelib.php');
  289. foreach ($files as $key => $file) {
  290. $icon = mimeinfo('icon', $file);
  291. $ffurl = get_file_url("$filearea/$file");
  292. $output .= '<a href="'.$ffurl.'" ><img src="'.$CFG->pixpath.'/f/'.$icon.'" class="icon" alt="'.$icon.'" />'.$file.'</a>';
  293. if ($candelete) {
  294. $delurl = "$CFG->wwwroot/mod/assignment/delete.php?id={$this->cm->id}&amp;file=$file&amp;userid={$submission->userid}&amp;mode=$mode&amp;offset=$offset";
  295. $output .= '<a href="'.$delurl.'">&nbsp;'
  296. .'<img title="'.$strdelete.'" src="'.$CFG->pixpath.'/t/delete.gif" class="iconsmall" alt="" /></a> ';
  297. }
  298. $output .= '<br />';
  299. }
  300. }
  301. }
  302. if ($this->drafts_tracked() and $this->isopen() and has_capability('mod/assignment:grade', $this->context) and $mode != '') { // we do not want it on view.php page
  303. if ($this->can_unfinalize($submission)) {
  304. $options = array ('id'=>$this->cm->id, 'userid'=>$userid, 'action'=>'unfinalize', 'mode'=>$mode, 'offset'=>$offset, 'sesskey'=>sesskey());
  305. $output .= print_single_button('upload.php', $options, get_string('unfinalize', 'assignment'), 'post', '_self', true);
  306. } else if ($this->can_finalize($submission)) {
  307. $options = array ('id'=>$this->cm->id, 'userid'=>$userid, 'action'=>'finalizeclose', 'mode'=>$mode, 'offset'=>$offset, 'sesskey'=>sesskey());
  308. $output .= print_single_button('upload.php', $options, get_string('finalize', 'assignment'), 'post', '_self', true);
  309. }
  310. }
  311. $output = '<div class="files">'.$output.'</div>';
  312. if ($return) {
  313. return $output;
  314. }
  315. echo $output;
  316. }
  317. function print_responsefiles($userid, $return=false) {
  318. global $CFG, $USER;
  319. $mode = optional_param('mode', '', PARAM_ALPHA);
  320. $offset = optional_param('offset', 0, PARAM_INT);
  321. $filearea = $this->file_area_name($userid).'/responses';
  322. $output = '';
  323. $candelete = $this->can_manage_responsefiles();
  324. $strdelete = get_string('delete');
  325. if ($basedir = $this->file_area($userid)) {
  326. $basedir .= '/responses';
  327. if ($files = get_directory_list($basedir)) {
  328. require_once($CFG->libdir.'/filelib.php');
  329. foreach ($files as $key => $file) {
  330. $icon = mimeinfo('icon', $file);
  331. $ffurl = get_file_url("$filearea/$file");
  332. $output .= '<a href="'.$ffurl.'" ><img src="'.$CFG->pixpath.'/f/'.$icon.'" alt="'.$icon.'" />'.$file.'</a>';
  333. if ($candelete) {
  334. $delurl = "$CFG->wwwroot/mod/assignment/delete.php?id={$this->cm->id}&amp;file=$file&amp;userid=$userid&amp;mode=$mode&amp;offset=$offset&amp;action=response";
  335. $output .= '<a href="'.$delurl.'">&nbsp;'
  336. .'<img title="'.$strdelete.'" src="'.$CFG->pixpath.'/t/delete.gif" class="iconsmall" alt=""/></a> ';
  337. }
  338. $output .= '&nbsp;';
  339. }
  340. }
  341. $output = '<div class="responsefiles">'.$output.'</div>';
  342. }
  343. if ($return) {
  344. return $output;
  345. }
  346. echo $output;
  347. }
  348. function upload() {
  349. $action = required_param('action', PARAM_ALPHA);
  350. switch ($action) {
  351. case 'finalize':
  352. $this->finalize();
  353. break;
  354. case 'finalizeclose':
  355. $this->finalizeclose();
  356. break;
  357. case 'unfinalize':
  358. $this->unfinalize();
  359. break;
  360. case 'uploadresponse':
  361. $this->upload_responsefile();
  362. break;
  363. case 'uploadfile':
  364. $this->upload_file();
  365. case 'savenotes':
  366. case 'editnotes':
  367. $this->upload_notes();
  368. default:
  369. error('Error: Unknow upload action ('.$action.').');
  370. }
  371. }
  372. function upload_notes() {
  373. global $CFG, $USER;
  374. $action = required_param('action', PARAM_ALPHA);
  375. $returnurl = 'view.php?id='.$this->cm->id;
  376. $mform = new mod_assignment_upload_notes_form();
  377. $defaults = new object();
  378. $defaults->id = $this->cm->id;
  379. if ($submission = $this->get_submission($USER->id)) {
  380. $defaults->text = clean_text($submission->data1);
  381. } else {
  382. $defaults->text = '';
  383. }
  384. $mform->set_data($defaults);
  385. if ($mform->is_cancelled()) {
  386. redirect('view.php?id='.$this->cm->id);
  387. }
  388. if (!$this->can_update_notes($submission)) {
  389. $this->view_header(get_string('upload'));
  390. notify(get_string('uploaderror', 'assignment'));
  391. print_continue($returnurl);
  392. $this->view_footer();
  393. die;
  394. }
  395. if ($data = $mform->get_data() and $action == 'savenotes') {
  396. $submission = $this->get_submission($USER->id, true); // get or create submission
  397. $updated = new object();
  398. $updated->id = $submission->id;
  399. $updated->timemodified = time();
  400. $updated->data1 = $data->text;
  401. if (update_record('assignment_submissions', $updated)) {
  402. add_to_log($this->course->id, 'assignment', 'upload', 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id);
  403. redirect($returnurl);
  404. $submission = $this->get_submission($USER->id);
  405. $this->update_grade($submission);
  406. } else {
  407. $this->view_header(get_string('notes', 'assignment'));
  408. notify(get_string('notesupdateerror', 'assignment'));
  409. print_continue($returnurl);
  410. $this->view_footer();
  411. die;
  412. }
  413. }
  414. /// show notes edit form
  415. $this->view_header(get_string('notes', 'assignment'));
  416. print_heading(get_string('notes', 'assignment'), '');
  417. $mform->display();
  418. $this->view_footer();
  419. die;
  420. }
  421. function upload_responsefile() {
  422. global $CFG;
  423. $userid = required_param('userid', PARAM_INT);
  424. $mode = required_param('mode', PARAM_ALPHA);
  425. $offset = required_param('offset', PARAM_INT);
  426. $returnurl = "submissions.php?id={$this->cm->id}&amp;userid=$userid&amp;mode=$mode&amp;offset=$offset";
  427. if (data_submitted('nomatch') and $this->can_manage_responsefiles() and confirm_sesskey()) {
  428. $dir = $this->file_area_name($userid).'/responses';
  429. check_dir_exists($CFG->dataroot.'/'.$dir, true, true);
  430. require_once($CFG->dirroot.'/lib/uploadlib.php');
  431. $um = new upload_manager('newfile',false,true,$this->course,false,0,true);
  432. if (!$um->process_file_uploads($dir)) {
  433. print_header(get_string('upload'));
  434. notify(get_string('uploaderror', 'assignment'));
  435. echo $um->get_errors();
  436. print_continue($returnurl);
  437. print_footer('none');
  438. die;
  439. }
  440. }
  441. redirect($returnurl);
  442. }
  443. function upload_file() {
  444. global $CFG, $USER;
  445. $mode = optional_param('mode', '', PARAM_ALPHA);
  446. $offset = optional_param('offset', 0, PARAM_INT);
  447. $returnurl = 'view.php?id='.$this->cm->id;
  448. $filecount = $this->count_user_files($USER->id);
  449. $submission = $this->get_submission($USER->id);
  450. if (!$this->can_upload_file($submission)) {
  451. $this->view_header(get_string('upload'));
  452. notify(get_string('uploaderror', 'assignment'));
  453. print_continue($returnurl);
  454. $this->view_footer();
  455. die;
  456. }
  457. $dir = $this->file_area_name($USER->id);
  458. check_dir_exists($CFG->dataroot.'/'.$dir, true, true); // better to create now so that student submissions do not block it later
  459. require_once($CFG->dirroot.'/lib/uploadlib.php');
  460. $um = new upload_manager('newfile',false,true,$this->course,false,$this->assignment->maxbytes,true);
  461. if ($um->process_file_uploads($dir) and confirm_sesskey()) {
  462. $submission = $this->get_submission($USER->id, true); //create new submission if needed
  463. $updated = new object();
  464. $updated->id = $submission->id;
  465. $updated->timemodified = time();
  466. if (update_record('assignment_submissions', $updated)) {
  467. add_to_log($this->course->id, 'assignment', 'upload',
  468. 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id);
  469. $submission = $this->get_submission($USER->id);
  470. $this->update_grade($submission);
  471. if (!$this->drafts_tracked()) {
  472. $this->email_teachers($submission);
  473. }
  474. } else {
  475. $new_filename = $um->get_new_filename();
  476. $this->view_header(get_string('upload'));
  477. notify(get_string('uploadnotregistered', 'assignment', $new_filename));
  478. print_continue($returnurl);
  479. $this->view_footer();
  480. die;
  481. }
  482. redirect('view.php?id='.$this->cm->id);
  483. }
  484. $this->view_header(get_string('upload'));
  485. notify(get_string('uploaderror', 'assignment'));
  486. echo $um->get_errors();
  487. print_continue($returnurl);
  488. $this->view_footer();
  489. die;
  490. }
  491. function finalize() {
  492. global $USER;
  493. $confirm = optional_param('confirm', 0, PARAM_BOOL);
  494. $returnurl = 'view.php?id='.$this->cm->id;
  495. $submission = $this->get_submission($USER->id);
  496. if (!$this->can_finalize($submission)) {
  497. redirect($returnurl); // probably already graded, redirect to assignment page, the reason should be obvious
  498. }
  499. if (!data_submitted() or !$confirm or !confirm_sesskey()) {
  500. $optionsno = array('id'=>$this->cm->id);
  501. $optionsyes = array ('id'=>$this->cm->id, 'confirm'=>1, 'action'=>'finalize', 'sesskey'=>sesskey());
  502. $this->view_header(get_string('submitformarking', 'assignment'));
  503. print_heading(get_string('submitformarking', 'assignment'));
  504. notice_yesno(get_string('onceassignmentsent', 'assignment'), 'upload.php', 'view.php', $optionsyes, $optionsno, 'post', 'get');
  505. $this->view_footer();
  506. die;
  507. }
  508. $updated = new object();
  509. $updated->id = $submission->id;
  510. $updated->data2 = ASSIGNMENT_STATUS_SUBMITTED;
  511. $updated->timemodified = time();
  512. if (update_record('assignment_submissions', $updated)) {
  513. add_to_log($this->course->id, 'assignment', 'upload', //TODO: add finalize action to log
  514. 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id);
  515. $submission = $this->get_submission($USER->id);
  516. $this->update_grade($submission);
  517. $this->email_teachers($submission);
  518. } else {
  519. $this->view_header(get_string('submitformarking', 'assignment'));
  520. notify(get_string('finalizeerror', 'assignment'));
  521. print_continue($returnurl);
  522. $this->view_footer();
  523. die;
  524. }
  525. redirect($returnurl);
  526. }
  527. function finalizeclose() {
  528. $userid = optional_param('userid', 0, PARAM_INT);
  529. $mode = required_param('mode', PARAM_ALPHA);
  530. $offset = required_param('offset', PARAM_INT);
  531. $returnurl = "submissions.php?id={$this->cm->id}&amp;userid=$userid&amp;mode=$mode&amp;offset=$offset&amp;forcerefresh=1";
  532. // create but do not add student submission date
  533. $submission = $this->get_submission($userid, true, true);
  534. if (!data_submitted() or !$this->can_finalize($submission) or !confirm_sesskey()) {
  535. redirect($returnurl); // probably closed already
  536. }
  537. $updated = new object();
  538. $updated->id = $submission->id;
  539. $updated->data2 = ASSIGNMENT_STATUS_CLOSED;
  540. if (update_record('assignment_submissions', $updated)) {
  541. add_to_log($this->course->id, 'assignment', 'upload', //TODO: add finalize action to log
  542. 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id);
  543. $submission = $this->get_submission($userid, false, true);
  544. $this->update_grade($submission);
  545. }
  546. redirect($returnurl);
  547. }
  548. function unfinalize() {
  549. $userid = required_param('userid', PARAM_INT);
  550. $mode = required_param('mode', PARAM_ALPHA);
  551. $offset = required_param('offset', PARAM_INT);
  552. $returnurl = "submissions.php?id={$this->cm->id}&amp;userid=$userid&amp;mode=$mode&amp;offset=$offset&amp;forcerefresh=1";
  553. if (data_submitted('nomatch')
  554. and $submission = $this->get_submission($userid)
  555. and $this->can_unfinalize($submission)
  556. and confirm_sesskey()) {
  557. $updated = new object();
  558. $updated->id = $submission->id;
  559. $updated->data2 = '';
  560. if (update_record('assignment_submissions', $updated)) {
  561. //TODO: add unfinalize action to log
  562. add_to_log($this->course->id, 'assignment', 'view submission', 'submissions.php?id='.$this->assignment->id, $this->assignment->id, $this->cm->id);
  563. $submission = $this->get_submission($userid);
  564. $this->update_grade($submission);
  565. } else {
  566. $this->view_header(get_string('submitformarking', 'assignment'));
  567. notify(get_string('unfinalizeerror', 'assignment'));
  568. print_continue($returnurl);
  569. $this->view_footer();
  570. die;
  571. }
  572. }
  573. redirect($returnurl);
  574. }
  575. function delete() {
  576. $action = optional_param('action', '', PARAM_ALPHA);
  577. switch ($action) {
  578. case 'response':
  579. $this->delete_responsefile();
  580. break;
  581. default:
  582. $this->delete_file();
  583. }
  584. die;
  585. }
  586. function delete_responsefile() {
  587. global $CFG;
  588. $file = required_param('file', PARAM_FILE);
  589. $userid = required_param('userid', PARAM_INT);
  590. $mode = required_param('mode', PARAM_ALPHA);
  591. $offset = required_param('offset', PARAM_INT);
  592. $confirm = optional_param('confirm', 0, PARAM_BOOL);
  593. $returnurl = "submissions.php?id={$this->cm->id}&amp;userid=$userid&amp;mode=$mode&amp;offset=$offset";
  594. if (!$this->can_manage_responsefiles()) {
  595. redirect($returnurl);
  596. }
  597. $urlreturn = 'submissions.php';
  598. $optionsreturn = array('id'=>$this->cm->id, 'offset'=>$offset, 'mode'=>$mode, 'userid'=>$userid);
  599. if (!data_submitted('nomatch') or !$confirm or !confirm_sesskey()) {
  600. $optionsyes = array ('id'=>$this->cm->id, 'file'=>$file, 'userid'=>$userid, 'confirm'=>1, 'action'=>'response', 'mode'=>$mode, 'offset'=>$offset, 'sesskey'=>sesskey());
  601. print_header(get_string('delete'));
  602. print_heading(get_string('delete'));
  603. notice_yesno(get_string('confirmdeletefile', 'assignment', $file), 'delete.php', $urlreturn, $optionsyes, $optionsreturn, 'post', 'get');
  604. print_footer('none');
  605. die;
  606. }
  607. $dir = $this->file_area_name($userid).'/responses';
  608. $filepath = $CFG->dataroot.'/'.$dir.'/'.$file;
  609. if (file_exists($filepath)) {
  610. if (@unlink($filepath)) {
  611. redirect($returnurl);
  612. }
  613. }
  614. // print delete error
  615. print_header(get_string('delete'));
  616. notify(get_string('deletefilefailed', 'assignment'));
  617. print_continue($returnurl);
  618. print_footer('none');
  619. die;
  620. }
  621. function delete_file() {
  622. global $CFG;
  623. $file = required_param('file', PARAM_FILE);
  624. $userid = required_param('userid', PARAM_INT);
  625. $confirm = optional_param('confirm', 0, PARAM_BOOL);
  626. $mode = optional_param('mode', '', PARAM_ALPHA);
  627. $offset = optional_param('offset', 0, PARAM_INT);
  628. require_login($this->course->id, false, $this->cm);
  629. if (empty($mode)) {
  630. $urlreturn = 'view.php';
  631. $optionsreturn = array('id'=>$this->cm->id);
  632. $returnurl = 'view.php?id='.$this->cm->id;
  633. } else {
  634. $urlreturn = 'submissions.php';
  635. $optionsreturn = array('id'=>$this->cm->id, 'offset'=>$offset, 'mode'=>$mode, 'userid'=>$userid);
  636. $returnurl = "submissions.php?id={$this->cm->id}&amp;offset=$offset&amp;mode=$mode&amp;userid=$userid";
  637. }
  638. if (!$submission = $this->get_submission($userid) // incorrect submission
  639. or !$this->can_delete_files($submission)) { // can not delete
  640. $this->view_header(get_string('delete'));
  641. notify(get_string('cannotdeletefiles', 'assignment'));
  642. print_continue($returnurl);
  643. $this->view_footer();
  644. die;
  645. }
  646. $dir = $this->file_area_name($userid);
  647. if (!data_submitted('nomatch') or !$confirm or !confirm_sesskey()) {
  648. $optionsyes = array ('id'=>$this->cm->id, 'file'=>$file, 'userid'=>$userid, 'confirm'=>1, 'sesskey'=>sesskey(), 'mode'=>$mode, 'offset'=>$offset, 'sesskey'=>sesskey());
  649. if (empty($mode)) {
  650. $this->view_header(get_string('delete'));
  651. } else {
  652. print_header(get_string('delete'));
  653. }
  654. print_heading(get_string('delete'));
  655. notice_yesno(get_string('confirmdeletefile', 'assignment', $file), 'delete.php', $urlreturn, $optionsyes, $optionsreturn, 'post', 'get');
  656. if (empty($mode)) {
  657. $this->view_footer();
  658. } else {
  659. print_footer('none');
  660. }
  661. die;
  662. }
  663. $filepath = $CFG->dataroot.'/'.$dir.'/'.$file;
  664. if (file_exists($filepath)) {
  665. if (@unlink($filepath)) {
  666. $updated = new object();
  667. $updated->id = $submission->id;
  668. $updated->timemodified = time();
  669. if (update_record('assignment_submissions', $updated)) {
  670. add_to_log($this->course->id, 'assignment', 'upload', //TODO: add delete action to log
  671. 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id);
  672. $submission = $this->get_submission($userid);
  673. $this->update_grade($submission);
  674. }
  675. redirect($returnurl);
  676. }
  677. }
  678. // print delete error
  679. if (empty($mode)) {
  680. $this->view_header(get_string('delete'));
  681. } else {
  682. print_header(get_string('delete'));
  683. }
  684. notify(get_string('deletefilefailed', 'assignment'));
  685. print_continue($returnurl);
  686. if (empty($mode)) {
  687. $this->view_footer();
  688. } else {
  689. print_footer('none');
  690. }
  691. die;
  692. }
  693. function can_upload_file($submission) {
  694. global $USER;
  695. if (has_capability('mod/assignment:submit', $this->context) // can submit
  696. and $this->isopen() // assignment not closed yet
  697. and (empty($submission) or $submission->userid == $USER->id) // his/her own submission
  698. and $this->count_user_files($USER->id) < $this->assignment->var1 // file limit not reached
  699. and !$this->is_finalized($submission)) { // no uploading after final submission
  700. return true;
  701. } else {
  702. return false;
  703. }
  704. }
  705. function can_manage_responsefiles() {
  706. if (has_capability('mod/assignment:grade', $this->context)) {
  707. return true;
  708. } else {
  709. return false;
  710. }
  711. }
  712. function can_delete_files($submission) {
  713. global $USER;
  714. if (has_capability('mod/assignment:grade', $this->context)) {
  715. return true;
  716. }
  717. if (has_capability('mod/assignment:submit', $this->context)
  718. and $this->isopen() // assignment not closed yet
  719. and $this->assignment->resubmit // deleting allowed
  720. and $USER->id == $submission->userid // his/her own submission
  721. and !$this->is_finalized($submission)) { // no deleting after final submission
  722. return true;
  723. } else {
  724. return false;
  725. }
  726. }
  727. function drafts_tracked() {
  728. return !empty($this->assignment->var4);
  729. }
  730. /**
  731. * Returns submission status
  732. * @param object $submission - may be empty
  733. * @return string submission state - empty, ASSIGNMENT_STATUS_SUBMITTED or ASSIGNMENT_STATUS_CLOSED
  734. */
  735. function is_finalized($submission) {
  736. if (!$this->drafts_tracked()) {
  737. return '';
  738. } else if (empty($submission)) {
  739. return '';
  740. } else if ($submission->data2 == ASSIGNMENT_STATUS_SUBMITTED or $submission->data2 == ASSIGNMENT_STATUS_CLOSED) {
  741. return $submission->data2;
  742. } else {
  743. return '';
  744. }
  745. }
  746. function can_unfinalize($submission) {
  747. if (!$this->drafts_tracked()) {
  748. return false;
  749. }
  750. if (has_capability('mod/assignment:grade', $this->context)
  751. and $this->isopen()
  752. and $this->is_finalized($submission)) {
  753. return true;
  754. } else {
  755. return false;
  756. }
  757. }
  758. function can_finalize($submission) {
  759. global $USER;
  760. if (!$this->drafts_tracked()) {
  761. return false;
  762. }
  763. if ($this->is_finalized($submission)) {
  764. return false;
  765. }
  766. if (has_capability('mod/assignment:grade', $this->context)) {
  767. return true;
  768. } else if (has_capability('mod/assignment:submit', $this->context) // can submit
  769. and $this->isopen() // assignment not closed yet
  770. and !empty($submission) // submission must exist
  771. and $submission->userid == $USER->id // his/her own submission
  772. and ($this->count_user_files($USER->id)
  773. or ($this->notes_allowed() and !empty($submission->data1)))) { // something must be submitted
  774. return true;
  775. } else {
  776. return false;
  777. }
  778. }
  779. function can_update_notes($submission) {
  780. global $USER;
  781. if (has_capability('mod/assignment:submit', $this->context)
  782. and $this->notes_allowed() // notesd must be allowed
  783. and $this->isopen() // assignment not closed yet
  784. and (empty($submission) or $USER->id == $submission->userid) // his/her own submission
  785. and !$this->is_finalized($submission)) { // no updateingafter final submission
  786. return true;
  787. } else {
  788. return false;
  789. }
  790. }
  791. function notes_allowed() {
  792. return (boolean)$this->assignment->var2;
  793. }
  794. /**
  795. * Count the files uploaded by a given user
  796. *
  797. * @param $userid int The user id
  798. * @return int
  799. */
  800. function count_user_files($userid) {
  801. global $CFG;
  802. $filearea = $this->file_area_name($userid);
  803. if ( is_dir($CFG->dataroot.'/'.$filearea) && $basedir = $this->file_area($userid)) {
  804. if ($files = get_directory_list($basedir, 'responses')) {
  805. return count($files);
  806. }
  807. }
  808. return 0;
  809. }
  810. function count_responsefiles($userid) {
  811. global $CFG;
  812. $filearea = $this->file_area_name($userid).'/responses';
  813. if ( is_dir($CFG->dataroot.'/'.$filearea) && $basedir = $this->file_area($userid)) {
  814. $basedir .= '/responses';
  815. if ($files = get_directory_list($basedir)) {
  816. return count($files);
  817. }
  818. }
  819. return 0;
  820. }
  821. function setup_elements(&$mform) {
  822. global $CFG, $COURSE;
  823. $ynoptions = array( 0 => get_string('no'), 1 => get_string('yes'));
  824. $choices = get_max_upload_sizes($CFG->maxbytes, $COURSE->maxbytes);
  825. $choices[0] = get_string('courseuploadlimit') . ' ('.display_size($COURSE->maxbytes).')';
  826. $mform->addElement('select', 'maxbytes', get_string('maximumsize', 'assignment'), $choices);
  827. $mform->setDefault('maxbytes', $CFG->assignment_maxbytes);
  828. $mform->addElement('select', 'resubmit', get_string("allowdeleting", "assignment"), $ynoptions);
  829. $mform->setHelpButton('resubmit', array('allowdeleting', get_string('allowdeleting', 'assignment'), 'assignment'));
  830. $mform->setDefault('resubmit', 1);
  831. $options = array();
  832. for($i = 1; $i <= 20; $i++) {
  833. $options[$i] = $i;
  834. }
  835. $mform->addElement('select', 'var1', get_string("allowmaxfiles", "assignment"), $options);
  836. $mform->setHelpButton('var1', array('allowmaxfiles', get_string('allowmaxfiles', 'assignment'), 'assignment'));
  837. $mform->setDefault('var1', 3);
  838. $mform->addElement('select', 'var2', get_string("allownotes", "assignment"), $ynoptions);
  839. $mform->setHelpButton('var2', array('allownotes', get_string('allownotes', 'assignment'), 'assignment'));
  840. $mform->setDefault('var2', 0);
  841. $mform->addElement('select', 'var3', get_string("hideintro", "assignment"), $ynoptions);
  842. $mform->setHelpButton('var3', array('hideintro', get_string('hideintro', 'assignment'), 'assignment'));
  843. $mform->setDefault('var3', 0);
  844. $mform->addElement('select', 'emailteachers', get_string("emailteachers", "assignment"), $ynoptions);
  845. $mform->setHelpButton('emailteachers', array('emailteachers', get_string('emailteachers', 'assignment'), 'assignment'));
  846. $mform->setDefault('emailteachers', 0);
  847. $mform->addElement('select', 'var4', get_string("trackdrafts", "assignment"), $ynoptions);
  848. $mform->setHelpButton('var4', array('trackdrafts', get_string('trackdrafts', 'assignment'), 'assignment'));
  849. $mform->setDefault('var4', 1);
  850. }
  851. }
  852. class mod_assignment_upload_notes_form extends moodleform {
  853. function definition() {
  854. $mform =& $this->_form;
  855. // visible elements
  856. $mform->addElement('htmleditor', 'text', get_string('notes', 'assignment'), array('cols'=>85, 'rows'=>30));
  857. $mform->setType('text', PARAM_RAW); // to be cleaned before display
  858. $mform->setHelpButton('text', array('reading', 'writing'), false, 'editorhelpbutton');
  859. // hidden params
  860. $mform->addElement('hidden', 'id', 0);
  861. $mform->setType('id', PARAM_INT);
  862. $mform->addElement('hidden', 'action', 'savenotes');
  863. $mform->setType('id', PARAM_ALPHA);
  864. // buttons
  865. $this->add_action_buttons();
  866. }
  867. }
  868. ?>