MDL-31987 Assignment module: Assignment count submissions correctly.
[moodle.git] / mod / assignment / type / upload / assignment.class.php
CommitLineData
e7521559 1<?php
ce2a1c4d
DC
2
3// This file is part of Moodle - http://moodle.org/
4//
5// Moodle is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// Moodle is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17
18/**
19 * Assignment upload type implementation
20 *
21 * @package mod-assignment
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25require_once(dirname(__FILE__).'/upload_form.php');
67a87e7d 26require_once($CFG->libdir . '/portfoliolib.php');
27require_once($CFG->dirroot . '/mod/assignment/lib.php');
fcdcc372 28
39bc9fbb 29define('ASSIGNMENT_STATUS_SUBMITTED', 'submitted'); // student thinks it is finished
30define('ASSIGNMENT_STATUS_CLOSED', 'closed'); // teacher prevents more submissions
55b4d096 31
fcdcc372 32/**
55b4d096 33 * Extend the base assignment class for assignments where you upload a single file
fcdcc372 34 *
35 */
36class assignment_upload extends assignment_base {
fcdcc372 37
7bddd4b7 38 function assignment_upload($cmid='staticonly', $assignment=NULL, $cm=NULL, $course=NULL) {
39 parent::assignment_base($cmid, $assignment, $cm, $course);
0b5a80a1 40 $this->type = 'upload';
fcdcc372 41 }
42
fcdcc372 43 function view() {
867aeead 44 global $USER, $OUTPUT;
fcdcc372 45
55b4d096 46 require_capability('mod/assignment:view', $this->context);
da69510f 47 $cansubmit = has_capability('mod/assignment:submit', $this->context);
fcdcc372 48
55b4d096 49 add_to_log($this->course->id, 'assignment', 'view', "view.php?id={$this->cm->id}", $this->assignment->id, $this->cm->id);
50
51 $this->view_header();
29889a2a 52
53 if ($this->assignment->timeavailable > time()
8c408f8e 54 and !has_capability('mod/assignment:grade', $this->context) // grading user can see it anytime
55 and $this->assignment->var3) { // force hiding before available date
3a003ead 56 echo $OUTPUT->box_start('generalbox boxaligncenter', 'intro');
29889a2a 57 print_string('notavailableyet', 'assignment');
3a003ead 58 echo $OUTPUT->box_end();
29889a2a 59 } else {
60 $this->view_intro();
61 }
62
55b4d096 63 $this->view_dates();
fcdcc372 64
c7bb34b6 65 if (is_enrolled($this->context, $USER)) {
64f93798
PS
66 if ($submission = $this->get_submission($USER->id)) {
67 $filecount = $this->count_user_files($submission->id);
68 } else {
69 $filecount = 0;
70 }
da69510f
DM
71 if ($cansubmit or !empty($filecount)) { //if a user has submitted files using a previous role we should still show the files
72 $this->view_feedback();
6fc73d59 73
da69510f
DM
74 if (!$this->drafts_tracked() or !$this->isopen() or $this->is_finalized($submission)) {
75 echo $OUTPUT->heading(get_string('submission', 'assignment'), 3);
76 } else {
77 echo $OUTPUT->heading(get_string('submissiondraft', 'assignment'), 3);
78 }
fcdcc372 79
da69510f
DM
80 if ($filecount and $submission) {
81 echo $OUTPUT->box($this->print_user_files($USER->id, true), 'generalbox boxaligncenter', 'userfiles');
55b4d096 82 } else {
da69510f
DM
83 if (!$this->isopen() or $this->is_finalized($submission)) {
84 echo $OUTPUT->box(get_string('nofiles', 'assignment'), 'generalbox boxaligncenter nofiles', 'userfiles');
85 } else {
86 echo $OUTPUT->box(get_string('nofilesyet', 'assignment'), 'generalbox boxaligncenter nofiles', 'userfiles');
87 }
55b4d096 88 }
6fc73d59 89
c7bb34b6 90 $this->view_upload_form();
55b4d096 91
da69510f
DM
92 if ($this->notes_allowed()) {
93 echo $OUTPUT->heading(get_string('notes', 'assignment'), 3);
94 $this->view_notes();
95 }
55b4d096 96
da69510f
DM
97 $this->view_final_submission();
98 }
8ba4cbd2 99 }
100 $this->view_footer();
fcdcc372 101 }
102
fcdcc372 103
55b4d096 104 function view_feedback($submission=NULL) {
d021e5b4 105 global $USER, $CFG, $DB, $OUTPUT, $PAGE;
12dce253 106 require_once($CFG->libdir.'/gradelib.php');
d021e5b4 107 require_once("$CFG->dirroot/grade/grading/lib.php");
8ba4cbd2 108
55b4d096 109 if (!$submission) { /// Get submission for this assignment
d021e5b4
MG
110 $userid = $USER->id;
111 $submission = $this->get_submission($userid);
112 } else {
113 $userid = $submission->userid;
55b4d096 114 }
8ba4cbd2 115
d021e5b4
MG
116 // Check the user can submit
117 $canviewfeedback = ($userid == $USER->id && has_capability('mod/assignment:submit', $this->context, $USER->id, false));
118 // If not then check if the user still has the view cap and has a previous submission
119 $canviewfeedback = $canviewfeedback || (!empty($submission) && $submission->userid == $USER->id && has_capability('mod/assignment:view', $this->context));
120 // Or if user can grade (is a teacher or admin)
121 $canviewfeedback = $canviewfeedback || has_capability('mod/assignment:grade', $this->context);
122
123 if (!$canviewfeedback) {
124 // can not view or submit assignments -> no feedback
125 return;
126 }
fcdcc372 127
d021e5b4 128 $grading_info = grade_get_grades($this->course->id, 'mod', 'assignment', $this->assignment->id, $userid);
12dce253 129 $item = $grading_info->items[0];
d021e5b4 130 $grade = $item->grades[$userid];
12dce253 131
132 if ($grade->hidden or $grade->grade === false) { // hidden or error
133 return;
134 }
135
db354342 136 if ($grade->grade === null and empty($grade->str_feedback)) { // No grade to show yet
d021e5b4 137 if ($this->count_responsefiles($userid)) { // but possibly response files are present
db354342 138 echo $OUTPUT->heading(get_string('responsefiles', 'assignment'), 3);
d021e5b4 139 $responsefiles = $this->print_responsefiles($userid, true);
db354342
HB
140 echo $OUTPUT->box($responsefiles, 'generalbox boxaligncenter');
141 }
12dce253 142 return;
143 }
144
145 $graded_date = $grade->dategraded;
146 $graded_by = $grade->usermodified;
147
55b4d096 148 /// We need the teacher info
74d7d735 149 if (!$teacher = $DB->get_record('user', array('id'=>$graded_by))) {
a939f681 150 print_error('cannotfindteacher');
55b4d096 151 }
fcdcc372 152
55b4d096 153 /// Print the feedback
867aeead 154 echo $OUTPUT->heading(get_string('submissionfeedback', 'assignment'), 3);
8ba4cbd2 155
55b4d096 156 echo '<table cellspacing="0" class="feedback">';
fcdcc372 157
55b4d096 158 echo '<tr>';
159 echo '<td class="left picture">';
812dbaf7 160 echo $OUTPUT->user_picture($teacher);
55b4d096 161 echo '</td>';
162 echo '<td class="topic">';
163 echo '<div class="from">';
164 echo '<div class="fullname">'.fullname($teacher).'</div>';
12dce253 165 echo '<div class="time">'.userdate($graded_date).'</div>';
55b4d096 166 echo '</div>';
167 echo '</td>';
168 echo '</tr>';
fcdcc372 169
55b4d096 170 echo '<tr>';
171 echo '<td class="left side">&nbsp;</td>';
172 echo '<td class="content">';
d021e5b4
MG
173 $gradestr = '<div class="grade">'. get_string("grade").': '.$grade->str_long_grade. '</div>';
174 if (!empty($submission) && $controller = get_grading_manager($this->context, 'mod_assignment', 'submission')->get_active_controller()) {
175 $controller->set_grade_range(make_grades_menu($this->assignment->grade));
176 echo $controller->render_grade($PAGE, $submission->id, $item, $gradestr, has_capability('mod/assignment:grade', $this->context));
177 } else {
178 echo $gradestr;
55b4d096 179 }
d021e5b4 180 echo '<div class="clearer"></div>';
8ba4cbd2 181
55b4d096 182 echo '<div class="comment">';
12dce253 183 echo $grade->str_feedback;
55b4d096 184 echo '</div>';
185 echo '</tr>';
8ba4cbd2 186
55b4d096 187 echo '<tr>';
188 echo '<td class="left side">&nbsp;</td>';
189 echo '<td class="content">';
d021e5b4 190 echo $this->print_responsefiles($userid, true);
55b4d096 191 echo '</tr>';
8ba4cbd2 192
55b4d096 193 echo '</table>';
fcdcc372 194 }
195
fcdcc372 196
55b4d096 197 function view_upload_form() {
ce2a1c4d 198 global $CFG, $USER, $OUTPUT;
fcdcc372 199
8ba4cbd2 200 $submission = $this->get_submission($USER->id);
fcdcc372 201
55b4d096 202 if ($this->is_finalized($submission)) {
203 // no uploading
204 return;
205 }
8ba4cbd2 206
55b4d096 207 if ($this->can_upload_file($submission)) {
ce2a1c4d
DC
208 $fs = get_file_storage();
209 // edit files in another page
b001cbbf 210 if ($submission) {
ce2a1c4d
DC
211 if ($files = $fs->get_area_files($this->context->id, 'mod_assignment', 'submission', $submission->id, "timemodified", false)) {
212 $str = get_string('editthesefiles', 'assignment');
213 } else {
214 $str = get_string('uploadfiles', 'assignment');
215 }
216 } else {
217 $str = get_string('uploadfiles', 'assignment');
218 }
b001cbbf 219 echo $OUTPUT->single_button(new moodle_url('/mod/assignment/type/upload/upload.php', array('contextid'=>$this->context->id, 'userid'=>$USER->id)), $str, 'get');
fcdcc372 220 }
55b4d096 221 }
8ba4cbd2 222
55b4d096 223 function view_notes() {
3a003ead 224 global $USER, $OUTPUT;
55b4d096 225
226 if ($submission = $this->get_submission($USER->id)
227 and !empty($submission->data1)) {
367a75fa 228 echo $OUTPUT->box(format_text($submission->data1, FORMAT_HTML, array('overflowdiv'=>true)), 'generalbox boxaligncenter boxwidthwide');
55b4d096 229 } else {
3a003ead 230 echo $OUTPUT->box(get_string('notesempty', 'assignment'), 'generalbox boxaligncenter');
55b4d096 231 }
232 if ($this->can_update_notes($submission)) {
233 $options = array ('id'=>$this->cm->id, 'action'=>'editnotes');
d9cb14b8 234 echo '<div style="text-align:center">';
5c2ed7e2 235 echo $OUTPUT->single_button(new moodle_url('upload.php', $options), get_string('edit'));
d9cb14b8 236 echo '</div>';
55b4d096 237 }
fcdcc372 238 }
239
55b4d096 240 function view_final_submission() {
867aeead 241 global $CFG, $USER, $OUTPUT;
fcdcc372 242
8ba4cbd2 243 $submission = $this->get_submission($USER->id);
fcdcc372 244
39bc9fbb 245 if ($this->isopen() and $this->can_finalize($submission)) {
55b4d096 246 //print final submit button
867aeead 247 echo $OUTPUT->heading(get_string('submitformarking','assignment'), 3);
d9cb14b8 248 echo '<div style="text-align:center">';
55b4d096 249 echo '<form method="post" action="upload.php">';
d9cb14b8 250 echo '<fieldset class="invisiblefieldset">';
55b4d096 251 echo '<input type="hidden" name="id" value="'.$this->cm->id.'" />';
a19dffc0 252 echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
55b4d096 253 echo '<input type="hidden" name="action" value="finalize" />';
254 echo '<input type="submit" name="formarking" value="'.get_string('sendformarking', 'assignment').'" />';
d9cb14b8 255 echo '</fieldset>';
55b4d096 256 echo '</form>';
d9cb14b8 257 echo '</div>';
39bc9fbb 258 } else if (!$this->isopen()) {
867aeead 259 echo $OUTPUT->heading(get_string('nomoresubmissions','assignment'), 3);
39bc9fbb 260
42f50aec 261 } else if ($this->drafts_tracked() and $state = $this->is_finalized($submission)) {
39bc9fbb 262 if ($state == ASSIGNMENT_STATUS_SUBMITTED) {
867aeead 263 echo $OUTPUT->heading(get_string('submitedformarking','assignment'), 3);
39bc9fbb 264 } else {
867aeead 265 echo $OUTPUT->heading(get_string('nomoresubmissions','assignment'), 3);
39bc9fbb 266 }
55b4d096 267 } else {
268 //no submission yet
269 }
270 }
39bc9fbb 271
272
273 /**
dc6cb74e 274 * Return true if var3 == hide description till available day
39bc9fbb 275 *
dc6cb74e 276 *@return boolean
39bc9fbb 277 */
dc6cb74e 278 function description_is_hidden() {
279 return ($this->assignment->var3 && (time() <= $this->assignment->timeavailable));
280 }
fcdcc372 281
55b4d096 282 function print_student_answer($userid, $return=false){
ce2a1c4d 283 global $CFG, $OUTPUT, $PAGE;
fcdcc372 284
55b4d096 285 $submission = $this->get_submission($userid);
8ba4cbd2 286
55b4d096 287 $output = '';
8ba4cbd2 288
172dd12c 289 if ($this->drafts_tracked() and $this->isopen() and !$this->is_finalized($submission)) {
290 $output .= '<strong>'.get_string('draft', 'assignment').':</strong> ';
291 }
55b4d096 292
172dd12c 293 if ($this->notes_allowed() and !empty($submission->data1)) {
3ea5951e 294 $link = new moodle_url("/mod/assignment/type/upload/notes.php", array('id'=>$this->cm->id, 'userid'=>$userid));
9bf16314
PS
295 $action = new popup_action('click', $link, 'notes', array('height' => 500, 'width' => 780));
296 $output .= $OUTPUT->action_link($link, get_string('notes', 'assignment'), $action, array('title'=>get_string('notes', 'assignment')));
e7521559 297
172dd12c 298 $output .= '&nbsp;';
299 }
55b4d096 300
e525b6f1 301
ce2a1c4d
DC
302 $renderer = $PAGE->get_renderer('mod_assignment');
303 $output = $OUTPUT->box_start('files').$output;
304 $output .= $renderer->assignment_files($this->context, $submission->id);
305 $output .= $OUTPUT->box_end();
8ba4cbd2 306
55b4d096 307 return $output;
fcdcc372 308 }
309
fcdcc372 310
55b4d096 311 /**
312 * Produces a list of links to the files uploaded by a user
313 *
314 * @param $userid int optional id of the user. If 0 then $USER->id is used.
315 * @param $return boolean optional defaults to false. If true the list is returned rather than printed
316 * @return string optional
317 */
318 function print_user_files($userid=0, $return=false) {
ce2a1c4d 319 global $CFG, $USER, $OUTPUT, $PAGE;
55b4d096 320
321 $mode = optional_param('mode', '', PARAM_ALPHA);
322 $offset = optional_param('offset', 0, PARAM_INT);
fcdcc372 323
55b4d096 324 if (!$userid) {
325 if (!isloggedin()) {
326 return '';
8ba4cbd2 327 }
55b4d096 328 $userid = $USER->id;
8ba4cbd2 329 }
330
e525b6f1 331 $output = $OUTPUT->box_start('files');
8ba4cbd2 332
39bc9fbb 333 $submission = $this->get_submission($userid);
8ba4cbd2 334
ce2a1c4d
DC
335 // only during grading
336 if ($this->drafts_tracked() and $this->isopen() and !$this->is_finalized($submission) and !empty($mode)) {
39bc9fbb 337 $output .= '<strong>'.get_string('draft', 'assignment').':</strong><br />';
338 }
fcdcc372 339
39bc9fbb 340 if ($this->notes_allowed() and !empty($submission->data1) and !empty($mode)) { // only during grading
fcdcc372 341
39bc9fbb 342 $npurl = $CFG->wwwroot."/mod/assignment/type/upload/notes.php?id={$this->cm->id}&amp;userid=$userid&amp;offset=$offset&amp;mode=single";
343 $output .= '<a href="'.$npurl.'">'.get_string('notes', 'assignment').'</a><br />';
fcdcc372 344
39bc9fbb 345 }
8ba4cbd2 346
03076be4 347 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
39bc9fbb 348 if ($this->can_unfinalize($submission)) {
2ea89456 349 //$options = array ('id'=>$this->cm->id, 'userid'=>$userid, 'action'=>'unfinalize', 'mode'=>$mode, 'offset'=>$offset);
350 $output .= '<br /><input type="submit" name="unfinalize" value="'.get_string('unfinalize', 'assignment').'" />';
c663653f 351 $output .= $OUTPUT->help_icon('unfinalize', 'assignment');
2ea89456 352
39bc9fbb 353 } else if ($this->can_finalize($submission)) {
2ea89456 354 //$options = array ('id'=>$this->cm->id, 'userid'=>$userid, 'action'=>'finalizeclose', 'mode'=>$mode, 'offset'=>$offset);
355 $output .= '<br /><input type="submit" name="finalize" value="'.get_string('finalize', 'assignment').'" />';
55b4d096 356 }
55b4d096 357 }
8ba4cbd2 358
2ea89456 359 if ($submission) {
360 $renderer = $PAGE->get_renderer('mod_assignment');
361 $output .= $renderer->assignment_files($this->context, $submission->id);
362 }
ce2a1c4d 363 $output .= $OUTPUT->box_end();
39bc9fbb 364
55b4d096 365 if ($return) {
366 return $output;
367 }
368 echo $output;
369 }
8ba4cbd2 370
2ea89456 371 function submissions($mode) {
372 // redirects out of form to process (un)finalizing.
373 $unfinalize = optional_param('unfinalize', FALSE, PARAM_TEXT);
374 $finalize = optional_param('finalize', FALSE, PARAM_TEXT);
375 if ($unfinalize) {
376 $this->unfinalize('single');
377 } else if ($finalize) {
378 $this->finalize('single');
379 }
2d274675
AB
380 if ($unfinalize || $finalize) {
381 $mode = 'singlenosave';
382 }
2ea89456 383 parent::submissions($mode);
384 }
385
e7755fc6 386 function process_feedback($formdata=null) {
291ee134
AB
387 if (!$feedback = data_submitted() or !confirm_sesskey()) { // No incoming data?
388 return false;
389 }
390 $userid = required_param('userid', PARAM_INT);
391 $offset = required_param('offset', PARAM_INT);
392 $mform = $this->display_submission($offset, $userid, false);
393 parent::process_feedback($mform);
394 }
395
8caba229
GGC
396 /**
397 * Counts all complete (real) assignment submissions by enrolled students. This overrides assignment_base::count_real_submissions().
45353da4
RW
398 * This is necessary for tracked advanced file uploads where we need to check that the data2 field is equal to ASSIGNMENT_STATUS_SUBMITTED
399 * to determine if a submission is complete.
8caba229
GGC
400 *
401 * @param int $groupid (optional) If nonzero then count is restricted to this group
402 * @return int The number of submissions
403 */
404 function count_real_submissions($groupid=0) {
8caba229
GGC
405 global $DB;
406
407 // Grab the context assocated with our course module
408 $context = get_context_instance(CONTEXT_MODULE, $this->cm->id);
409
410 // Get ids of users enrolled in the given course.
411 list($enroledsql, $params) = get_enrolled_sql($context, 'mod/assignment:view', $groupid);
412 $params['assignmentid'] = $this->cm->instance;
413
45353da4
RW
414 $query = '';
415 if ($this->drafts_tracked() and $this->isopen()) {
416 $query = ' AND ' . $DB->sql_compare_text('s.data2') . " = '" . ASSIGNMENT_STATUS_SUBMITTED . "'";
417 } else {
418 // Count on submissions with files actually uploaded
419 $query = " AND s.numfiles > 0";
420 }
8caba229
GGC
421 return $DB->count_records_sql("SELECT COUNT('x')
422 FROM {assignment_submissions} s
423 LEFT JOIN {assignment} a ON a.id = s.assignment
424 INNER JOIN ($enroledsql) u ON u.id = s.userid
45353da4
RW
425 WHERE s.assignment = :assignmentid" .
426 $query, $params);
8caba229
GGC
427 }
428
55b4d096 429 function print_responsefiles($userid, $return=false) {
ce2a1c4d 430 global $CFG, $USER, $OUTPUT, $PAGE;
8ba4cbd2 431
55b4d096 432 $mode = optional_param('mode', '', PARAM_ALPHA);
433 $offset = optional_param('offset', 0, PARAM_INT);
8ba4cbd2 434
e525b6f1 435 $output = $OUTPUT->box_start('responsefiles');
fcdcc372 436
55b4d096 437 $candelete = $this->can_manage_responsefiles();
438 $strdelete = get_string('delete');
fcdcc372 439
172dd12c 440 $fs = get_file_storage();
441 $browser = get_file_browser();
fcdcc372 442
64f93798 443 if ($submission = $this->get_submission($userid)) {
ce2a1c4d 444 $renderer = $PAGE->get_renderer('mod_assignment');
be534597 445 $output .= $renderer->assignment_files($this->context, $submission->id, 'response');
8ba4cbd2 446 }
2ea89456 447 $output .= $OUTPUT->box_end();
fcdcc372 448
55b4d096 449 if ($return) {
450 return $output;
8ba4cbd2 451 }
55b4d096 452 echo $output;
453 }
fcdcc372 454
ce2a1c4d
DC
455 /**
456 * Upload files
457 * upload_file function requires moodle form instance and file manager options
458 * @param object $mform
459 * @param array $options
460 */
461 function upload($mform = null, $filemanager_options = null) {
55b4d096 462 $action = required_param('action', PARAM_ALPHA);
55b4d096 463 switch ($action) {
464 case 'finalize':
465 $this->finalize();
466 break;
39bc9fbb 467 case 'finalizeclose':
03076be4 468 $this->finalizeclose();
39bc9fbb 469 break;
55b4d096 470 case 'unfinalize':
471 $this->unfinalize();
472 break;
473 case 'uploadresponse':
6ad4b78f 474 $this->upload_responsefile($mform, $filemanager_options);
55b4d096 475 break;
476 case 'uploadfile':
ce2a1c4d 477 $this->upload_file($mform, $filemanager_options);
55b4d096 478 case 'savenotes':
479 case 'editnotes':
480 $this->upload_notes();
481 default:
a939f681 482 print_error('unknowuploadaction', '', '', $action);
8ba4cbd2 483 }
55b4d096 484 }
fcdcc372 485
55b4d096 486 function upload_notes() {
c561f44c 487 global $CFG, $USER, $OUTPUT, $DB;
fcdcc372 488
55b4d096 489 $action = required_param('action', PARAM_ALPHA);
fcdcc372 490
ce2a1c4d 491 $returnurl = new moodle_url('/mod/assignment/view.php', array('id'=>$this->cm->id));
fcdcc372 492
1d284fbd 493 $mform = new mod_assignment_upload_notes_form();
6117edc7 494
39790bd8 495 $defaults = new stdClass();
6117edc7 496 $defaults->id = $this->cm->id;
497
e38204d1 498 if ($submission = $this->get_submission($USER->id)) {
cc27235e 499 $defaults->text = clean_text($submission->data1);
e38204d1 500 } else {
6117edc7 501 $defaults->text = '';
e38204d1 502 }
503
beac4717 504 $mform->set_data($defaults);
6117edc7 505
5571b5f4 506 if ($mform->is_cancelled()) {
ce2a1c4d
DC
507 $returnurl = new moodle_url('/mod/assignment/view.php', array('id'=>$this->cm->id));
508 redirect($returnurl);
5571b5f4 509 }
510
e38204d1 511 if (!$this->can_update_notes($submission)) {
512 $this->view_header(get_string('upload'));
3a003ead 513 echo $OUTPUT->notification(get_string('uploaderror', 'assignment'));
514 echo $OUTPUT->continue_button($returnurl);
e38204d1 515 $this->view_footer();
516 die;
517 }
518
294ce987 519 if ($data = $mform->get_data() and $action == 'savenotes') {
55b4d096 520 $submission = $this->get_submission($USER->id, true); // get or create submission
39790bd8 521 $updated = new stdClass();
55b4d096 522 $updated->id = $submission->id;
523 $updated->timemodified = time();
6117edc7 524 $updated->data1 = $data->text;
fcdcc372 525
dd88de0e
PS
526 $DB->update_record('assignment_submissions', $updated);
527 add_to_log($this->course->id, 'assignment', 'upload', 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id);
528 redirect($returnurl);
529 $submission = $this->get_submission($USER->id);
530 $this->update_grade($submission);
55b4d096 531 }
fcdcc372 532
55b4d096 533 /// show notes edit form
55b4d096 534 $this->view_header(get_string('notes', 'assignment'));
6117edc7 535
867aeead 536 echo $OUTPUT->heading(get_string('notes', 'assignment'));
6fc73d59 537
6117edc7 538 $mform->display();
8ba4cbd2 539
55b4d096 540 $this->view_footer();
541 die;
fcdcc372 542 }
543
6ad4b78f 544 function upload_responsefile($mform, $options) {
83a7f058 545 global $CFG, $USER, $OUTPUT, $PAGE;
8ba4cbd2 546
55b4d096 547 $userid = required_param('userid', PARAM_INT);
548 $mode = required_param('mode', PARAM_ALPHA);
549 $offset = required_param('offset', PARAM_INT);
fcdcc372 550
e1d4da05 551 $returnurl = new moodle_url("submissions.php", array('id'=>$this->cm->id,'userid'=>$userid,'mode'=>$mode,'offset'=>$offset)); //not xhtml, just url.
6ad4b78f 552
553 if ($formdata = $mform->get_data() and $this->can_manage_responsefiles()) {
172dd12c 554 $fs = get_file_storage();
6ad4b78f 555 $submission = $this->get_submission($userid, true, true);
556 if ($formdata = file_postupdate_standard_filemanager($formdata, 'files', $options, $this->context, 'mod_assignment', 'response', $submission->id)) {
557 $returnurl = new moodle_url("/mod/assignment/submissions.php", array('id'=>$this->cm->id,'userid'=>$formdata->userid,'mode'=>$formdata->mode,'offset'=>$formdata->offset));
558 redirect($returnurl->out(false));
38ac07d2 559 }
fcdcc372 560 }
83a7f058 561 $PAGE->set_title(get_string('upload'));
562 echo $OUTPUT->header();
3a003ead 563 echo $OUTPUT->notification(get_string('uploaderror', 'assignment'));
be534597 564 echo $OUTPUT->continue_button($returnurl->out(true));
256d2850 565 echo $OUTPUT->footer();
172dd12c 566 die;
fcdcc372 567 }
568
ce2a1c4d 569 function upload_file($mform, $options) {
3a003ead 570 global $CFG, $USER, $DB, $OUTPUT;
8ba4cbd2 571
ce2a1c4d 572 $returnurl = new moodle_url('/mod/assignment/view.php', array('id'=>$this->cm->id));
55b4d096 573 $submission = $this->get_submission($USER->id);
8ba4cbd2 574
55b4d096 575 if (!$this->can_upload_file($submission)) {
576 $this->view_header(get_string('upload'));
3a003ead 577 echo $OUTPUT->notification(get_string('uploaderror', 'assignment'));
578 echo $OUTPUT->continue_button($returnurl);
55b4d096 579 $this->view_footer();
580 die;
581 }
8ba4cbd2 582
ce2a1c4d 583 if ($formdata = $mform->get_data()) {
172dd12c 584 $fs = get_file_storage();
ce2a1c4d
DC
585 $submission = $this->get_submission($USER->id, true); //create new submission if needed
586 $fs->delete_area_files($this->context->id, 'mod_assignment', 'submission', $submission->id);
587 $formdata = file_postupdate_standard_filemanager($formdata, 'files', $options, $this->context, 'mod_assignment', 'submission', $submission->id);
39790bd8 588 $updates = new stdClass();
ce2a1c4d 589 $updates->id = $submission->id;
45353da4 590 $updates->numfiles = count($fs->get_area_files($this->context->id, 'mod_assignment', 'submission', $submission->id, 'sortorder', false));
ce2a1c4d 591 $updates->timemodified = time();
dd88de0e
PS
592 $DB->update_record('assignment_submissions', $updates);
593 add_to_log($this->course->id, 'assignment', 'upload',
594 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id);
595 $this->update_grade($submission);
596 if (!$this->drafts_tracked()) {
597 $this->email_teachers($submission);
598 }
ce2a1c4d 599
dd88de0e
PS
600 // send files to event system
601 $files = $fs->get_area_files($this->context->id, 'mod_assignment', 'submission', $submission->id);
602 // Let Moodle know that assessable files were uploaded (eg for plagiarism detection)
39790bd8 603 $eventdata = new stdClass();
dd88de0e
PS
604 $eventdata->modulename = 'assignment';
605 $eventdata->cmid = $this->cm->id;
606 $eventdata->itemid = $submission->id;
607 $eventdata->courseid = $this->course->id;
608 $eventdata->userid = $USER->id;
609 if ($files) {
4447223b 610 $eventdata->files = $files; // This is depreceated - please use pathnamehashes instead!
fcdcc372 611 }
4447223b 612 $eventdata->pathnamehashes = array_keys($files);
dd88de0e 613 events_trigger('assessable_file_uploaded', $eventdata);
ce2a1c4d
DC
614 $returnurl = new moodle_url('/mod/assignment/view.php', array('id'=>$this->cm->id));
615 redirect($returnurl);
fcdcc372 616 }
172dd12c 617
55b4d096 618 $this->view_header(get_string('upload'));
3a003ead 619 echo $OUTPUT->notification(get_string('uploaderror', 'assignment'));
620 echo $OUTPUT->continue_button($returnurl);
55b4d096 621 $this->view_footer();
622 die;
fcdcc372 623 }
624
b861b609 625 function send_file($filearea, $args, $forcedownload, array $options=array()) {
172dd12c 626 global $CFG, $DB, $USER;
627 require_once($CFG->libdir.'/filelib.php');
628
629 require_login($this->course, false, $this->cm);
630
64f93798
PS
631 if ($filearea === 'submission') {
632 $submissionid = (int)array_shift($args);
172dd12c 633
64f93798
PS
634 if (!$submission = $DB->get_record('assignment_submissions', array('assignment'=>$this->assignment->id, 'id'=>$submissionid))) {
635 return false;
636 }
172dd12c 637
64f93798
PS
638 if ($USER->id != $submission->userid and !has_capability('mod/assignment:grade', $this->context)) {
639 return false;
640 }
641
642 $relativepath = implode('/', $args);
643 $fullpath = "/{$this->context->id}/mod_assignment/submission/$submission->id/$relativepath";
172dd12c 644
64f93798
PS
645 $fs = get_file_storage();
646 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
172dd12c 647 return false;
648 }
261cbbac
DM
649
650 send_stored_file($file, 0, 0, true, $options); // download MUST be forced - security!
64f93798
PS
651
652 } else if ($filearea === 'response') {
653 $submissionid = (int)array_shift($args);
172dd12c 654
64f93798 655 if (!$submission = $DB->get_record('assignment_submissions', array('assignment'=>$this->assignment->id, 'id'=>$submissionid))) {
172dd12c 656 return false;
657 }
658
64f93798
PS
659 if ($USER->id != $submission->userid and !has_capability('mod/assignment:grade', $this->context)) {
660 return false;
661 }
662
663 $relativepath = implode('/', $args);
664 $fullpath = "/{$this->context->id}/mod_assignment/response/$submission->id/$relativepath";
665
666 $fs = get_file_storage();
667 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
668 return false;
669 }
261cbbac 670 send_stored_file($file, 0, 0, true, $options);
172dd12c 671 }
672
64f93798 673 return false;
172dd12c 674 }
675
2ea89456 676 function finalize($forcemode=null) {
867aeead 677 global $USER, $DB, $OUTPUT;
2ea89456 678 $userid = optional_param('userid', $USER->id, PARAM_INT);
679 $offset = optional_param('offset', 0, PARAM_INT);
03076be4 680 $confirm = optional_param('confirm', 0, PARAM_BOOL);
ce2a1c4d 681 $returnurl = new moodle_url('/mod/assignment/view.php', array('id'=>$this->cm->id));
2ea89456 682 $submission = $this->get_submission($userid);
55b4d096 683
2ea89456 684 if ($forcemode!=null) {
685 $returnurl = new moodle_url('/mod/assignment/submissions.php',
686 array('id'=>$this->cm->id,
687 'userid'=>$userid,
688 'mode'=>$forcemode,
689 'offset'=>$offset
690 ));
55b4d096 691 }
692
2ea89456 693 if (!$this->can_finalize($submission)) {
694 redirect($returnurl->out(false)); // probably already graded, redirect to assignment page, the reason should be obvious
695 }
55b4d096 696
2ea89456 697 if ($forcemode==null) {
698 if (!data_submitted() or !$confirm or !confirm_sesskey()) {
699 $optionsno = array('id'=>$this->cm->id);
700 $optionsyes = array ('id'=>$this->cm->id, 'confirm'=>1, 'action'=>'finalize', 'sesskey'=>sesskey());
701 $this->view_header(get_string('submitformarking', 'assignment'));
702 echo $OUTPUT->heading(get_string('submitformarking', 'assignment'));
703 echo $OUTPUT->confirm(get_string('onceassignmentsent', 'assignment'), new moodle_url('upload.php', $optionsyes),new moodle_url( 'view.php', $optionsno));
704 $this->view_footer();
705 die;
706 }
03076be4 707 }
39790bd8 708 $updated = new stdClass();
03076be4 709 $updated->id = $submission->id;
710 $updated->data2 = ASSIGNMENT_STATUS_SUBMITTED;
711 $updated->timemodified = time();
712
dd88de0e
PS
713 $DB->update_record('assignment_submissions', $updated);
714 add_to_log($this->course->id, 'assignment', 'upload', //TODO: add finalize action to log
715 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id);
716 $submission = $this->get_submission($userid);
717 $this->update_grade($submission);
718 $this->email_teachers($submission);
dcffbe54
MD
719
720 // Trigger assessable_files_done event to show files are complete
39790bd8 721 $eventdata = new stdClass();
dcffbe54
MD
722 $eventdata->modulename = 'assignment';
723 $eventdata->cmid = $this->cm->id;
724 $eventdata->itemid = $submission->id;
725 $eventdata->courseid = $this->course->id;
2ea89456 726 $eventdata->userid = $userid;
dcffbe54 727 events_trigger('assessable_files_done', $eventdata);
1c5517a5 728
2d274675
AB
729 if ($forcemode==null) {
730 redirect($returnurl->out(false));
731 }
03076be4 732 }
39bc9fbb 733
03076be4 734 function finalizeclose() {
74d7d735 735 global $DB;
736
03076be4 737 $userid = optional_param('userid', 0, PARAM_INT);
738 $mode = required_param('mode', PARAM_ALPHA);
739 $offset = required_param('offset', PARAM_INT);
ce2a1c4d 740 $returnurl = new moodle_url('/mod/assignment/submissions.php', array('id'=>$this->cm->id, 'userid'=>$userid, 'mode'=>$mode, 'offset'=>$offset, 'forcerefresh'=>1));
03076be4 741
12dce253 742 // create but do not add student submission date
03076be4 743 $submission = $this->get_submission($userid, true, true);
744
a19dffc0 745 if (!data_submitted() or !$this->can_finalize($submission) or !confirm_sesskey()) {
03076be4 746 redirect($returnurl); // probably closed already
747 }
748
39790bd8 749 $updated = new stdClass();
03076be4 750 $updated->id = $submission->id;
751 $updated->data2 = ASSIGNMENT_STATUS_CLOSED;
752
dd88de0e
PS
753 $DB->update_record('assignment_submissions', $updated);
754 add_to_log($this->course->id, 'assignment', 'upload', //TODO: add finalize action to log
755 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id);
756 $submission = $this->get_submission($userid, false, true);
757 $this->update_grade($submission);
55b4d096 758 redirect($returnurl);
759 }
fcdcc372 760
2ea89456 761 function unfinalize($forcemode=null) {
74d7d735 762 global $DB;
8ba4cbd2 763
55b4d096 764 $userid = required_param('userid', PARAM_INT);
765 $mode = required_param('mode', PARAM_ALPHA);
766 $offset = required_param('offset', PARAM_INT);
fcdcc372 767
2ea89456 768 if ($forcemode!=null) {
769 $mode=$forcemode;
770 }
f1af9d35 771 $returnurl = new moodle_url('/mod/assignment/submissions.php', array('id'=>$this->cm->id, 'userid'=>$userid, 'mode'=>$mode, 'offset'=>$offset, 'forcerefresh'=>1) );
74d7d735 772 if (data_submitted()
55b4d096 773 and $submission = $this->get_submission($userid)
a19dffc0
PS
774 and $this->can_unfinalize($submission)
775 and confirm_sesskey()) {
fcdcc372 776
39790bd8 777 $updated = new stdClass();
55b4d096 778 $updated->id = $submission->id;
779 $updated->data2 = '';
dd88de0e
PS
780 $DB->update_record('assignment_submissions', $updated);
781 //TODO: add unfinalize action to log
e4784b61 782 add_to_log($this->course->id, 'assignment', 'view submission', 'submissions.php?id='.$this->cm->id.'&userid='.$userid.'&mode='.$mode.'&offset='.$offset, $this->assignment->id, $this->cm->id);
dd88de0e
PS
783 $submission = $this->get_submission($userid);
784 $this->update_grade($submission);
fcdcc372 785 }
2d274675
AB
786
787 if ($forcemode==null) {
788 redirect($returnurl);
789 }
55b4d096 790 }
fcdcc372 791
fcdcc372 792
55b4d096 793 function delete() {
794 $action = optional_param('action', '', PARAM_ALPHA);
fcdcc372 795
55b4d096 796 switch ($action) {
797 case 'response':
798 $this->delete_responsefile();
799 break;
800 default:
801 $this->delete_file();
fcdcc372 802 }
55b4d096 803 die;
804 }
fcdcc372 805
fcdcc372 806
55b4d096 807 function delete_responsefile() {
83a7f058 808 global $CFG, $OUTPUT,$PAGE;
8ba4cbd2 809
55b4d096 810 $file = required_param('file', PARAM_FILE);
811 $userid = required_param('userid', PARAM_INT);
812 $mode = required_param('mode', PARAM_ALPHA);
813 $offset = required_param('offset', PARAM_INT);
814 $confirm = optional_param('confirm', 0, PARAM_BOOL);
fcdcc372 815
ce2a1c4d 816 $returnurl = new moodle_url('/mod/assignment/submissions.php', array('id'=>$this->cm->id, 'userid'=>$userid, 'mode'=>$mode, 'offset'=>$offset));
fcdcc372 817
55b4d096 818 if (!$this->can_manage_responsefiles()) {
819 redirect($returnurl);
820 }
fcdcc372 821
55b4d096 822 $urlreturn = 'submissions.php';
823 $optionsreturn = array('id'=>$this->cm->id, 'offset'=>$offset, 'mode'=>$mode, 'userid'=>$userid);
fcdcc372 824
a19dffc0
PS
825 if (!data_submitted() or !$confirm or !confirm_sesskey()) {
826 $optionsyes = array ('id'=>$this->cm->id, 'file'=>$file, 'userid'=>$userid, 'confirm'=>1, 'action'=>'response', 'mode'=>$mode, 'offset'=>$offset, 'sesskey'=>sesskey());
83a7f058 827 $PAGE->set_title(get_string('delete'));
828 echo $OUTPUT->header();
867aeead 829 echo $OUTPUT->heading(get_string('delete'));
75d47fa9 830 echo $OUTPUT->confirm(get_string('confirmdeletefile', 'assignment', $file), new moodle_url('delete.php', $optionsyes), new moodle_url($urlreturn, $optionsreturn));
256d2850 831 echo $OUTPUT->footer();
55b4d096 832 die;
833 }
fcdcc372 834
64f93798
PS
835 if ($submission = $this->get_submission($userid)) {
836 $fs = get_file_storage();
837 if ($file = $fs->get_file($this->context->id, 'mod_assignment', 'response', $submission->id, '/', $file)) {
838 $file->delete();
55b4d096 839 }
840 }
64f93798 841 redirect($returnurl);
55b4d096 842 }
fcdcc372 843
fcdcc372 844
55b4d096 845 function delete_file() {
55c7042d 846 global $CFG, $DB, $OUTPUT, $PAGE;
fcdcc372 847
55b4d096 848 $file = required_param('file', PARAM_FILE);
849 $userid = required_param('userid', PARAM_INT);
850 $confirm = optional_param('confirm', 0, PARAM_BOOL);
851 $mode = optional_param('mode', '', PARAM_ALPHA);
852 $offset = optional_param('offset', 0, PARAM_INT);
fcdcc372 853
cdbea7ee 854 require_login($this->course, false, $this->cm);
fcdcc372 855
55b4d096 856 if (empty($mode)) {
857 $urlreturn = 'view.php';
858 $optionsreturn = array('id'=>$this->cm->id);
ce2a1c4d 859 $returnurl = new moodle_url('/mod/assignment/view.php', array('id'=>$this->cm->id));
8ba4cbd2 860 } else {
55b4d096 861 $urlreturn = 'submissions.php';
862 $optionsreturn = array('id'=>$this->cm->id, 'offset'=>$offset, 'mode'=>$mode, 'userid'=>$userid);
ce2a1c4d 863 $returnurl = new moodle_url('/mod/assignment/submissions.php', array('id'=>$this->cm->id, 'offset'=>$offset, 'userid'=>$userid));
fcdcc372 864 }
865
55b4d096 866 if (!$submission = $this->get_submission($userid) // incorrect submission
867 or !$this->can_delete_files($submission)) { // can not delete
868 $this->view_header(get_string('delete'));
3a003ead 869 echo $OUTPUT->notification(get_string('cannotdeletefiles', 'assignment'));
870 echo $OUTPUT->continue_button($returnurl);
55b4d096 871 $this->view_footer();
872 die;
fcdcc372 873 }
874
a19dffc0 875 if (!data_submitted() or !$confirm or !confirm_sesskey()) {
64f93798 876 $optionsyes = array ('id'=>$this->cm->id, 'file'=>$file, 'userid'=>$userid, 'confirm'=>1, 'sesskey'=>sesskey(), 'mode'=>$mode, 'offset'=>$offset, 'sesskey'=>sesskey());
55b4d096 877 if (empty($mode)) {
878 $this->view_header(get_string('delete'));
879 } else {
55c7042d 880 $PAGE->set_title(get_string('delete'));
881 echo $OUTPUT->header();
fcdcc372 882 }
867aeead 883 echo $OUTPUT->heading(get_string('delete'));
75d47fa9 884 echo $OUTPUT->confirm(get_string('confirmdeletefile', 'assignment', $file), new moodle_url('delete.php', $optionsyes), new moodle_url($urlreturn, $optionsreturn));
55b4d096 885 if (empty($mode)) {
886 $this->view_footer();
887 } else {
256d2850 888 echo $OUTPUT->footer();
fcdcc372 889 }
55b4d096 890 die;
fcdcc372 891 }
892
172dd12c 893 $fs = get_file_storage();
64f93798
PS
894 if ($file = $fs->get_file($this->context->id, 'mod_assignment', 'submission', $submission->id, '/', $file)) {
895 $file->delete();
896 $submission->timemodified = time();
897 $DB->update_record('assignment_submissions', $submission);
898 add_to_log($this->course->id, 'assignment', 'upload', //TODO: add delete action to log
899 'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id);
900 $this->update_grade($submission);
8ba4cbd2 901 }
64f93798 902 redirect($returnurl);
55b4d096 903 }
8ba4cbd2 904
8ba4cbd2 905
55b4d096 906 function can_upload_file($submission) {
907 global $USER;
fcdcc372 908
64f93798 909 if (is_enrolled($this->context, $USER, 'mod/assignment:submit')
55b4d096 910 and $this->isopen() // assignment not closed yet
694b7aef 911 and (empty($submission) or ($submission->userid == $USER->id)) // his/her own submission
83774723 912 and !$this->is_finalized($submission)) { // no uploading after final submission
55b4d096 913 return true;
914 } else {
915 return false;
8ba4cbd2 916 }
55b4d096 917 }
fcdcc372 918
55b4d096 919 function can_manage_responsefiles() {
920 if (has_capability('mod/assignment:grade', $this->context)) {
921 return true;
922 } else {
923 return false;
924 }
925 }
fcdcc372 926
55b4d096 927 function can_delete_files($submission) {
928 global $USER;
fcdcc372 929
55b4d096 930 if (has_capability('mod/assignment:grade', $this->context)) {
931 return true;
fcdcc372 932 }
933
64f93798 934 if (is_enrolled($this->context, $USER, 'mod/assignment:submit')
55b4d096 935 and $this->isopen() // assignment not closed yet
55b4d096 936 and $this->assignment->resubmit // deleting allowed
937 and $USER->id == $submission->userid // his/her own submission
938 and !$this->is_finalized($submission)) { // no deleting after final submission
939 return true;
940 } else {
941 return false;
fcdcc372 942 }
55b4d096 943 }
fcdcc372 944
42f50aec 945 function drafts_tracked() {
946 return !empty($this->assignment->var4);
947 }
948
39bc9fbb 949 /**
950 * Returns submission status
951 * @param object $submission - may be empty
952 * @return string submission state - empty, ASSIGNMENT_STATUS_SUBMITTED or ASSIGNMENT_STATUS_CLOSED
953 */
55b4d096 954 function is_finalized($submission) {
42f50aec 955 if (!$this->drafts_tracked()) {
956 return '';
957
958 } else if (empty($submission)) {
39bc9fbb 959 return '';
960
961 } else if ($submission->data2 == ASSIGNMENT_STATUS_SUBMITTED or $submission->data2 == ASSIGNMENT_STATUS_CLOSED) {
962 return $submission->data2;
963
55b4d096 964 } else {
39bc9fbb 965 return '';
fcdcc372 966 }
55b4d096 967 }
fcdcc372 968
55b4d096 969 function can_unfinalize($submission) {
2388e7ca
GS
970 if(is_bool($submission)) {
971 return false;
972 }
973
42f50aec 974 if (!$this->drafts_tracked()) {
975 return false;
976 }
2388e7ca 977
55b4d096 978 if (has_capability('mod/assignment:grade', $this->context)
ad1e3409 979 and $this->isopen()
980 and $this->is_finalized($submission)) {
55b4d096 981 return true;
fcdcc372 982 } else {
55b4d096 983 return false;
fcdcc372 984 }
fcdcc372 985 }
986
55b4d096 987 function can_finalize($submission) {
988 global $USER;
2388e7ca
GS
989
990 if(is_bool($submission)) {
991 return false;
992 }
993
42f50aec 994 if (!$this->drafts_tracked()) {
995 return false;
996 }
8ba4cbd2 997
4454447d
PS
998 if ($this->is_finalized($submission)) {
999 return false;
1000 }
ad1e3409 1001
1002 if (has_capability('mod/assignment:grade', $this->context)) {
1003 return true;
1004
64f93798 1005 } else if (is_enrolled($this->context, $USER, 'mod/assignment:submit')
55b4d096 1006 and $this->isopen() // assignment not closed yet
1007 and !empty($submission) // submission must exist
55b4d096 1008 and $submission->userid == $USER->id // his/her own submission
87f702a0 1009 and ($this->count_user_files($submission->id)
ad1e3409 1010 or ($this->notes_allowed() and !empty($submission->data1)))) { // something must be submitted
8ba4cbd2 1011
55b4d096 1012 return true;
8ba4cbd2 1013 } else {
55b4d096 1014 return false;
8ba4cbd2 1015 }
55b4d096 1016 }
8ba4cbd2 1017
55b4d096 1018 function can_update_notes($submission) {
1019 global $USER;
8ba4cbd2 1020
64f93798 1021 if (is_enrolled($this->context, $USER, 'mod/assignment:submit')
ad1e3409 1022 and $this->notes_allowed() // notesd must be allowed
55b4d096 1023 and $this->isopen() // assignment not closed yet
55b4d096 1024 and (empty($submission) or $USER->id == $submission->userid) // his/her own submission
1025 and !$this->is_finalized($submission)) { // no updateingafter final submission
1026 return true;
8ba4cbd2 1027 } else {
55b4d096 1028 return false;
8ba4cbd2 1029 }
8ba4cbd2 1030 }
1031
55b4d096 1032 function notes_allowed() {
1033 return (boolean)$this->assignment->var2;
1034 }
8ba4cbd2 1035
55b4d096 1036 function count_responsefiles($userid) {
64f93798
PS
1037 if ($submission = $this->get_submission($userid)) {
1038 $fs = get_file_storage();
1039 $files = $fs->get_area_files($this->context->id, 'mod_assignment', 'response', $submission->id, "id", false);
1040 return count($files);
1041 } else {
1042 return 0;
1043 }
38ac07d2 1044 }
8ba4cbd2 1045
436cfa9f 1046 function setup_elements(&$mform) {
675be221 1047 global $CFG, $COURSE;
436cfa9f 1048
1049 $ynoptions = array( 0 => get_string('no'), 1 => get_string('yes'));
1050
1051 $choices = get_max_upload_sizes($CFG->maxbytes, $COURSE->maxbytes);
436cfa9f 1052 $choices[0] = get_string('courseuploadlimit') . ' ('.display_size($COURSE->maxbytes).')';
1053 $mform->addElement('select', 'maxbytes', get_string('maximumsize', 'assignment'), $choices);
1054 $mform->setDefault('maxbytes', $CFG->assignment_maxbytes);
1055
e66841b9
DM
1056 $mform->addElement('select', 'resubmit', get_string('allowdeleting', 'assignment'), $ynoptions);
1057 $mform->addHelpButton('resubmit', 'allowdeleting', 'assignment');
436cfa9f 1058 $mform->setDefault('resubmit', 1);
1059
1060 $options = array();
1061 for($i = 1; $i <= 20; $i++) {
1062 $options[$i] = $i;
1063 }
e66841b9
DM
1064 $mform->addElement('select', 'var1', get_string('allowmaxfiles', 'assignment'), $options);
1065 $mform->addHelpButton('var1', 'allowmaxfiles', 'assignment');
436cfa9f 1066 $mform->setDefault('var1', 3);
1067
e66841b9
DM
1068 $mform->addElement('select', 'var2', get_string('allownotes', 'assignment'), $ynoptions);
1069 $mform->addHelpButton('var2', 'allownotes', 'assignment');
436cfa9f 1070 $mform->setDefault('var2', 0);
1071
e66841b9
DM
1072 $mform->addElement('select', 'var3', get_string('hideintro', 'assignment'), $ynoptions);
1073 $mform->addHelpButton('var3', 'hideintro', 'assignment');
436cfa9f 1074 $mform->setDefault('var3', 0);
1075
e66841b9
DM
1076 $mform->addElement('select', 'emailteachers', get_string('emailteachers', 'assignment'), $ynoptions);
1077 $mform->addHelpButton('emailteachers', 'emailteachers', 'assignment');
436cfa9f 1078 $mform->setDefault('emailteachers', 0);
1079
e66841b9
DM
1080 $mform->addElement('select', 'var4', get_string('trackdrafts', 'assignment'), $ynoptions);
1081 $mform->addHelpButton('var4', 'trackdrafts', 'assignment');
26087ac5 1082 $mform->setDefault('var4', 1);
436cfa9f 1083
bce59524
DM
1084 $course_context = get_context_instance(CONTEXT_COURSE, $COURSE->id);
1085 plagiarism_get_form_elements_module($mform, $course_context);
436cfa9f 1086 }
1087
67a87e7d 1088 function portfolio_exportable() {
1089 return true;
1090 }
1091
47c96a77 1092 function extend_settings_navigation($node) {
1093 global $CFG, $USER, $OUTPUT;
1094
1095 // get users submission if there is one
1096 $submission = $this->get_submission();
64f93798 1097 if (is_enrolled($this->context, $USER, 'mod/assignment:submit')) {
47c96a77 1098 $editable = $this->isopen() && (!$submission || $this->assignment->resubmit || !$submission->timemarked);
1099 } else {
1100 $editable = false;
1101 }
1102
d6d8c494 1103 // If the user has submitted something add some related links and data
229278a7 1104 if (isset($submission->data2) AND $submission->data2 == 'submitted') {
47c96a77 1105 // Add a view link to the settings nav
a6855934 1106 $link = new moodle_url('/mod/assignment/view.php', array('id'=>$this->cm->id));
47c96a77 1107 $node->add(get_string('viewmysubmission', 'assignment'), $link, navigation_node::TYPE_SETTING);
1108 if (!empty($submission->timemodified)) {
3406acde
SH
1109 $submittednode = $node->add(get_string('submitted', 'assignment') . ' ' . userdate($submission->timemodified));
1110 $submittednode->text = preg_replace('#([^,])\s#', '$1&nbsp;', $submittednode->text);
1111 $submittednode->add_class('note');
47c96a77 1112 if ($submission->timemodified <= $this->assignment->timedue || empty($this->assignment->timedue)) {
3406acde 1113 $submittednode->add_class('early');
47c96a77 1114 } else {
3406acde 1115 $submittednode->add_class('late');
47c96a77 1116 }
1117 }
1118 }
1119
1120 // Check if the user has uploaded any files, if so we can add some more stuff to the settings nav
87f702a0 1121 if ($submission && is_enrolled($this->context, $USER, 'mod/assignment:submit') && $this->count_user_files($submission->id)) {
47c96a77 1122 $fs = get_file_storage();
64f93798 1123 if ($files = $fs->get_area_files($this->context->id, 'mod_assignment', 'submission', $submission->id, "timemodified", false)) {
47c96a77 1124 if (!$this->drafts_tracked() or !$this->isopen() or $this->is_finalized($submission)) {
3406acde 1125 $filenode = $node->add(get_string('submission', 'assignment'));
47c96a77 1126 } else {
3406acde 1127 $filenode = $node->add(get_string('submissiondraft', 'assignment'));
47c96a77 1128 }
1129 foreach ($files as $file) {
1130 $filename = $file->get_filename();
1131 $mimetype = $file->get_mimetype();
64f93798 1132 $link = file_encode_url($CFG->wwwroot.'/pluginfile.php', '/'.$this->context->id.'/mod_assignment/submission/'.$submission->id.'/'.$filename);
559276b1 1133 $filenode->add($filename, $link, navigation_node::TYPE_SETTING, null, null, new pix_icon(file_file_icon($file),''));
47c96a77 1134 }
1135 }
1136 }
1137
1138 // Show a notes link if they are enabled
1139 if ($this->notes_allowed()) {
a6855934 1140 $link = new moodle_url('/mod/assignment/upload.php', array('id'=>$this->cm->id, 'action'=>'editnotes', 'sesskey'=>sesskey()));
47c96a77 1141 $node->add(get_string('notes', 'assignment'), $link);
1142 }
1143 }
b37ce778
DM
1144
1145 /**
1146 * creates a zip of all assignment submissions and sends a zip to the browser
1147 */
1148 public function download_submissions() {
1149 global $CFG,$DB;
1150 require_once($CFG->libdir.'/filelib.php');
b37ce778
DM
1151 $submissions = $this->get_submissions('','');
1152 if (empty($submissions)) {
14f001a9 1153 print_error('errornosubmissions', 'assignment');
b37ce778
DM
1154 }
1155 $filesforzipping = array();
b37ce778
DM
1156 $fs = get_file_storage();
1157
a211a40c 1158 $groupmode = groups_get_activity_groupmode($this->cm);
b37ce778
DM
1159 $groupid = 0; // All users
1160 $groupname = '';
14f001a9 1161 if ($groupmode) {
a211a40c
DM
1162 $groupid = groups_get_activity_group($this->cm, true);
1163 $groupname = groups_get_group_name($groupid).'-';
b37ce778
DM
1164 }
1165 $filename = str_replace(' ', '_', clean_filename($this->course->shortname.'-'.$this->assignment->name.'-'.$groupname.$this->assignment->id.".zip")); //name of new zip file.
1166 foreach ($submissions as $submission) {
1167 $a_userid = $submission->userid; //get userid
1168 if ((groups_is_member($groupid,$a_userid)or !$groupmode or !$groupid)) {
1169 $a_assignid = $submission->assignment; //get name of this assignment for use in the file names.
1170 $a_user = $DB->get_record("user", array("id"=>$a_userid),'id,username,firstname,lastname'); //get user firstname/lastname
64f93798
PS
1171
1172 $files = $fs->get_area_files($this->context->id, 'mod_assignment', 'submission', $submission->id, "timemodified", false);
b37ce778
DM
1173 foreach ($files as $file) {
1174 //get files new name.
902eca42
DM
1175 $fileext = strstr($file->get_filename(), '.');
1176 $fileoriginal = str_replace($fileext, '', $file->get_filename());
1177 $fileforzipname = clean_filename(fullname($a_user) . "_" . $fileoriginal."_".$a_userid.$fileext);
b37ce778 1178 //save file name to array for zipping.
6db11242 1179 $filesforzipping[$fileforzipname] = $file;
b37ce778
DM
1180 }
1181 }
1182 } // end of foreach loop
1183 if ($zipfile = assignment_pack_files($filesforzipping)) {
b37ce778
DM
1184 send_temp_file($zipfile, $filename); //send file and delete after sending.
1185 }
1186 }
ad2d5eba
GGC
1187
1188 /**
1189 * Check the given submission is complete. Preliminary rows are often created in the assignment_submissions
1190 * table before a submission actually takes place. This function checks to see if the given submission has actually
1191 * been submitted.
1192 *
1193 * @param stdClass $submission The submission we want to check for completion
1194 * @return bool Indicates if the submission was found to be complete
1195 */
1196 public function is_submitted_with_required_data($submission) {
1197 return ($submission->timemodified AND $submission->data2);
1198 }
6117edc7 1199}
1200
f07b9627 1201class mod_assignment_upload_notes_form extends moodleform {
c561f44c
SH
1202
1203 function get_data() {
1204 $data = parent::get_data();
1205 if ($data) {
1206 $data->format = $data->text['format'];
1207 $data->text = $data->text['text'];
1208 }
1209 return $data;
1210 }
1211
1212 function set_data($data) {
1213 if (!isset($data->format)) {
1214 $data->format = FORMAT_HTML;
1215 }
1216 if (isset($data->text)) {
1217 $data->text = array('text'=>$data->text, 'format'=>$data->format);
1218 }
1219 parent::set_data($data);
1220 }
1221
6117edc7 1222 function definition() {
172dd12c 1223 $mform = $this->_form;
6117edc7 1224
1225 // visible elements
c561f44c 1226 $mform->addElement('editor', 'text', get_string('notes', 'assignment'), null, null);
6117edc7 1227 $mform->setType('text', PARAM_RAW); // to be cleaned before display
55b4d096 1228
6117edc7 1229 // hidden params
1230 $mform->addElement('hidden', 'id', 0);
1231 $mform->setType('id', PARAM_INT);
1232 $mform->addElement('hidden', 'action', 'savenotes');
172dd12c 1233 $mform->setType('action', PARAM_ALPHA);
6117edc7 1234
1235 // buttons
a23f0aaf 1236 $this->add_action_buttons();
6117edc7 1237 }
fcdcc372 1238}
8ba4cbd2 1239
172dd12c 1240class mod_assignment_upload_response_form extends moodleform {
1241 function definition() {
1242 $mform = $this->_form;
1243 $instance = $this->_customdata;
1244
1245 // visible elements
6ad4b78f 1246 $mform->addElement('filemanager', 'files_filemanager', get_string('uploadafile'), null, $instance->options);
172dd12c 1247
1248 // hidden params
1249 $mform->addElement('hidden', 'id', $instance->cm->id);
1250 $mform->setType('id', PARAM_INT);
6ad4b78f 1251 $mform->addElement('hidden', 'contextid', $instance->contextid);
1252 $mform->setType('contextid', PARAM_INT);
172dd12c 1253 $mform->addElement('hidden', 'action', 'uploadresponse');
1254 $mform->setType('action', PARAM_ALPHA);
6ad4b78f 1255 $mform->addElement('hidden', 'mode', $instance->mode);
172dd12c 1256 $mform->setType('mode', PARAM_ALPHA);
6ad4b78f 1257 $mform->addElement('hidden', 'offset', $instance->offset);
172dd12c 1258 $mform->setType('offset', PARAM_INT);
6ad4b78f 1259 $mform->addElement('hidden', 'forcerefresh' , $instance->forcerefresh);
172dd12c 1260 $mform->setType('forcerefresh', PARAM_INT);
6ad4b78f 1261 $mform->addElement('hidden', 'userid', $instance->userid);
172dd12c 1262 $mform->setType('userid', PARAM_INT);
1263
1264 // buttons
1265 $this->add_action_buttons(false, get_string('uploadthisfile'));
1266 }
1267}
1268
67a87e7d 1269
1270
e7521559 1271