Assignment MDL-7206 - download all submissions as a zip - finally pushing this into...
[moodle.git] / mod / assignment / type / uploadsingle / assignment.class.php
1 <?php
3 /**
4  * Extend the base assignment class for assignments where you upload a single file
5  *
6  */
7 class assignment_uploadsingle extends assignment_base {
10     function print_student_answer($userid, $return=false){
11         global $CFG, $USER, $OUTPUT;
13         $fs = get_file_storage();
14         $browser = get_file_browser();
16         $output = '';
18         if ($files = $fs->get_area_files($this->context->id, 'assignment_submission', $userid, "timemodified", false)) {
20             foreach ($files as $file) {
21                 $filename = $file->get_filename();
22                 $found = true;
23                 $mimetype = $file->get_mimetype();
24                 $path = file_encode_url($CFG->wwwroot.'/pluginfile.php', '/'.$this->context->id.'/assignment_submission/'.$userid.'/'.$filename);
25                 $output .= '<a href="'.$path.'" ><img class="icon" src="'.$OUTPUT->pix_url(file_mimetype_icon($mimetype)).'" alt="'.$mimetype.'" />'.s($filename).'</a><br />';
26             }
27         }
29         $output = '<div class="files">'.$output.'</div>';
30         return $output;
31     }
33     function assignment_uploadsingle($cmid='staticonly', $assignment=NULL, $cm=NULL, $course=NULL) {
34         parent::assignment_base($cmid, $assignment, $cm, $course);
35         $this->type = 'uploadsingle';
36     }
38     function view() {
40         global $USER, $OUTPUT;
42         $context = get_context_instance(CONTEXT_MODULE,$this->cm->id);
43         require_capability('mod/assignment:view', $context);
45         add_to_log($this->course->id, "assignment", "view", "view.php?id={$this->cm->id}", $this->assignment->id, $this->cm->id);
47         $this->view_header();
49         $this->view_intro();
51         $this->view_dates();
53         $filecount = $this->count_user_files($USER->id);
55         if ($submission = $this->get_submission()) {
56             if ($submission->timemarked) {
57                 $this->view_feedback();
58             }
59             if ($filecount) {
60                 echo $OUTPUT->box($this->print_user_files($USER->id, true), 'generalbox boxaligncenter');
61             }
62         }
64         if (has_capability('mod/assignment:submit', $context)  && $this->isopen() && (!$filecount || $this->assignment->resubmit || !$submission->timemarked)) {
65             $this->view_upload_form();
66         }
68         $this->view_footer();
69     }
72     function view_upload_form() {
73         $mform = new mod_assignment_upload_file_form('upload.php', $this);
74         $mform->display();
75     }
78     function upload() {
79         global $CFG, $USER, $DB, $OUTPUT;
81         require_capability('mod/assignment:submit', get_context_instance(CONTEXT_MODULE, $this->cm->id));
83         $this->view_header(get_string('upload'));
85         $filecount = $this->count_user_files($USER->id);
86         $submission = $this->get_submission($USER->id);
87         if ($this->isopen() && (!$filecount || $this->assignment->resubmit || !$submission->timemarked)) {
88             if ($submission = $this->get_submission($USER->id)) {
89                 //TODO: change later to ">= 0", to prevent resubmission when graded 0
90                 if (($submission->grade > 0) and !$this->assignment->resubmit) {
91                     echo $OUTPUT->notification(get_string('alreadygraded', 'assignment'));
92                 }
93             }
95             $mform = new mod_assignment_upload_file_form('upload.php', $this);
96             if ($mform->get_data()) {
97                 $fs = get_file_storage();
98                 $filename = $mform->get_new_filename('newfile');
99                 if ($filename !== false) {
100                     $fs->delete_area_files($this->context->id, 'assignment_submission', $USER->id);
101                     if ($file = $mform->save_stored_file('newfile', $this->context->id, 'assignment_submission', $USER->id, '/', $filename, false, $USER->id)) {
102                         $submission = $this->get_submission($USER->id, true); //create new submission if needed
103                         $submission->timemodified = time();
104                         $submission->numfiles     = 1;
105                         if ($DB->update_record('assignment_submissions', $submission)) {
106                             add_to_log($this->course->id, 'assignment', 'upload',
107                                     'view.php?a='.$this->assignment->id, $this->assignment->id, $this->cm->id);
108                             $this->update_grade($submission);
109                             $this->email_teachers($submission);
110                             echo $OUTPUT->heading(get_string('uploadedfile'));
111                             //trigger event with information about this file.
112                             $eventdata = new object();
113                             $eventdata->component  = 'mod/assignment';
114                             $eventdata->course     = $this->course;
115                             $eventdata->assignment = $this->assignment;
116                             $eventdata->cm         = $this->cm;
117                             $eventdata->user       = $USER;
118                             $eventdata->file       = $file;
119                             events_trigger('assignment_file_sent', $eventdata);
121                             redirect('view.php?id='.$this->cm->id);
122                         } else {
123                             echo $OUTPUT->notification(get_string("uploadnotregistered", "assignment", $newfile_name) );
124                             $file->delete();
125                         }
126                     }
127                 }
128             } else {
129                 echo $OUTPUT->notification(get_string("uploaderror", "assignment")); //submitting not allowed!
130             }
131         }
133         echo $OUTPUT->continue_button('view.php?id='.$this->cm->id);
135         $this->view_footer();
136     }
138     function setup_elements(&$mform) {
139         global $CFG, $COURSE;
141         $ynoptions = array( 0 => get_string('no'), 1 => get_string('yes'));
143         $mform->addElement('select', 'resubmit', get_string("allowresubmit", "assignment"), $ynoptions);
144         $mform->setHelpButton('resubmit', array('resubmit', get_string('allowresubmit', 'assignment'), 'assignment'));
145         $mform->setDefault('resubmit', 0);
147         $mform->addElement('select', 'emailteachers', get_string("emailteachers", "assignment"), $ynoptions);
148         $mform->setHelpButton('emailteachers', array('emailteachers', get_string('emailteachers', 'assignment'), 'assignment'));
149         $mform->setDefault('emailteachers', 0);
151         $choices = get_max_upload_sizes($CFG->maxbytes, $COURSE->maxbytes);
152         $choices[0] = get_string('courseuploadlimit') . ' ('.display_size($COURSE->maxbytes).')';
153         $mform->addElement('select', 'maxbytes', get_string('maximumsize', 'assignment'), $choices);
154         $mform->setDefault('maxbytes', $CFG->assignment_maxbytes);
156     }
158     function portfolio_exportable() {
159         return true;
160     }
162     function send_file($filearea, $args) {
163         global $CFG, $DB, $USER;
164         require_once($CFG->libdir.'/filelib.php');
166         require_login($this->course, false, $this->cm);
168         $userid = (int)array_shift($args);
169         $relativepath = '/'.implode('/', $args);
170         $fullpath = $this->context->id.$filearea.$userid.$relativepath;
172         $fs = get_file_storage();
174         if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
175             return false;
176         }
178         if ($filearea === 'assignment_submission') {
179             if ($USER->id != $userid and !has_capability('mod/assignment:grade', $this->context)) {
180                 return false;
181             }
183         } else {
184             return false;
185         }
187         send_stored_file($file, 0, 0, true); // download MUST be forced - security!
188     }
190     function extend_settings_navigation($node) {
191         global $CFG, $USER, $OUTPUT;
193         // get users submission if there is one
194         $submission = $this->get_submission();
195         if (has_capability('mod/assignment:submit', get_context_instance(CONTEXT_MODULE, $this->cm->id))) {
196             $editable = $this->isopen() && (!$submission || $this->assignment->resubmit || !$submission->timemarked);
197         } else {
198             $editable = false;
199         }
201         // If the user has submitted something add a bit more stuff
202         if ($submission) {
203             // Add a view link to the settings nav
204             $link = new moodle_url('/mod/assignment/view.php', array('id'=>$this->cm->id));
205             $node->add(get_string('viewmysubmission', 'assignment'), $link, navigation_node::TYPE_SETTING);
206             if (!empty($submission->timemodified)) {
207                 $submissionnode = $node->add(get_string('submitted', 'assignment') . ' ' . userdate($submission->timemodified));
208                 $submissionnode->text = preg_replace('#([^,])\s#', '$1&nbsp;', $submissionnode->text);
209                 $submissionnode->add_class('note');
210                 if ($submission->timemodified <= $this->assignment->timedue || empty($this->assignment->timedue)) {
211                     $submissionnode->add_class('early');
212                 } else {
213                     $submissionnode->add_class('late');
214                 }
215             }
216         }
218         // Check if the user has uploaded any files, if so we can add some more stuff to the settings nav
219         if ($submission && has_capability('mod/assignment:submit', $this->context) && $this->count_user_files($USER->id)) {
220             $fs = get_file_storage();
221             if ($files = $fs->get_area_files($this->context->id, 'assignment_submission', $USER->id, "timemodified", false)) {
222                 $filenode = $node->add(get_string('submission', 'assignment'));
223                 foreach ($files as $file) {
224                     $filename = $file->get_filename();
225                     $mimetype = $file->get_mimetype();
226                     $link = file_encode_url($CFG->wwwroot.'/pluginfile.php', '/'.$this->context->id.'/assignment_submission/'.$USER->id.'/'.$filename);
227                     $filenode->add($filename, $link, navigation_node::TYPE_SETTING, null, null, new pix_icon(file_mimetype_icon($mimetype), ''));
228                 }
229             }
230         }
231     }
233     /**
234      * creates a zip of all assignment submissions and sends a zip to the browser
235      */
236     function download_submissions() {
237         global $CFG,$DB;
238         require_once($CFG->libdir.'/filelib.php');
240         $submissions = $this->get_submissions('','');
241         if (empty($submissions)) {
242             error("there are no submissions to download");
243         }
244         $filesforzipping = array();
245         $filenewname = clean_filename($this->assignment->name); //create prefix of individual files
246         $tempdir = assignment_create_temp_dir($CFG->dataroot."/temp/", "assignment".$this->assignment->id); //location for temp files.
247         $fs = get_file_storage();
249         $groupmode = groupmode($this->course,$this->cm);
250         $groupid = 0;   // All users
251         $groupname = '';
252         if($groupmode) {
253             $group = get_current_group($this->course->id, true);
254             $groupid = $group->id;
255             $groupname = $group->name.'-';
256         }
257         $filename = str_replace(' ', '_', clean_filename($this->course->shortname.'-'.$this->assignment->name.'-'.$groupname.$this->assignment->id.".zip")); //name of new zip file.
258         foreach ($submissions as $submission) {
259             $a_userid = $submission->userid; //get userid
260             if ((groups_is_member($groupid,$a_userid)or !$groupmode or !$groupid)) {
261                 $a_assignid = $submission->assignment; //get name of this assignment for use in the file names.
262                 $a_user = $DB->get_record("user", array("id"=>$a_userid),'id,username,firstname,lastname'); //get user firstname/lastname
263                 
264                 $files = $fs->get_area_files($this->context->id, 'assignment_submission', $a_userid, "timemodified", false);
265                 foreach ($files as $file) {
266                     //get files new name.
267                     $fileforzipname =  $a_user->username . "_" . $filenewname . "_" . $file->get_filename();
268                     //get files old name
269                     if (!$file->copy_content_to($tempdir . $fileforzipname)) {
270                         error ("failed to copy file<br>" .$tempdir. $fileforzipname);
271                     }
272                     //save file name to array for zipping.
273                     $filesforzipping[$fileforzipname] = $tempdir.$fileforzipname;
274                 }
275             }
276         } // End of foreach
277         if ($zipfile = assignment_pack_files($filesforzipping)) {
278             remove_dir($tempdir); //remove old tempdir with individual files.
279             send_temp_file($zipfile, $filename); //send file and delete after sending.
280         }
281     }