Commit | Line | Data |
---|---|---|
bbd0e548 DW |
1 | <?php |
2 | // This file is part of Moodle - http://moodle.org/ | |
3 | // | |
4 | // Moodle is free software: you can redistribute it and/or modify | |
5 | // it under the terms of the GNU General Public License as published by | |
6 | // the Free Software Foundation, either version 3 of the License, or | |
7 | // (at your option) any later version. | |
8 | // | |
9 | // Moodle is distributed in the hope that it will be useful, | |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | // GNU General Public License for more details. | |
13 | // | |
14 | // You should have received a copy of the GNU General Public License | |
15 | // along with Moodle. If not, see <http://www.gnu.org/licenses/>. | |
16 | ||
17 | /** | |
18 | * This file contains the definition for the library class for file submission plugin | |
19 | * | |
20 | * This class provides all the functionality for the new assign module. | |
21 | * | |
22 | * @package assignsubmission_file | |
23 | * @copyright 2012 NetSpot {@link http://www.netspot.com.au} | |
24 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
25 | */ | |
26 | ||
bbd0e548 DW |
27 | require_once($CFG->libdir.'/eventslib.php'); |
28 | ||
29 | defined('MOODLE_INTERNAL') || die(); | |
e5403f8c DW |
30 | |
31 | // File areas for file submission assignment. | |
8ab7bb9f DW |
32 | define('ASSIGNSUBMISSION_FILE_MAXFILES', 20); |
33 | define('ASSIGNSUBMISSION_FILE_MAXSUMMARYFILES', 5); | |
34 | define('ASSIGNSUBMISSION_FILE_FILEAREA', 'submission_files'); | |
bbd0e548 DW |
35 | |
36 | /** | |
e5403f8c | 37 | * Library class for file submission plugin extending submission plugin base class |
bbd0e548 DW |
38 | * |
39 | * @package assignsubmission_file | |
40 | * @copyright 2012 NetSpot {@link http://www.netspot.com.au} | |
41 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
42 | */ | |
43 | class assign_submission_file extends assign_submission_plugin { | |
44 | ||
45 | /** | |
46 | * Get the name of the file submission plugin | |
47 | * @return string | |
48 | */ | |
49 | public function get_name() { | |
50 | return get_string('file', 'assignsubmission_file'); | |
51 | } | |
52 | ||
53 | /** | |
54 | * Get file submission information from the database | |
55 | * | |
56 | * @param int $submissionid | |
57 | * @return mixed | |
58 | */ | |
59 | private function get_file_submission($submissionid) { | |
60 | global $DB; | |
61 | return $DB->get_record('assignsubmission_file', array('submission'=>$submissionid)); | |
62 | } | |
63 | ||
64 | /** | |
65 | * Get the default setting for file submission plugin | |
66 | * | |
67 | * @param MoodleQuickForm $mform The form to add elements to | |
68 | * @return void | |
69 | */ | |
70 | public function get_settings(MoodleQuickForm $mform) { | |
71 | global $CFG, $COURSE; | |
72 | ||
73 | $defaultmaxfilesubmissions = $this->get_config('maxfilesubmissions'); | |
74 | $defaultmaxsubmissionsizebytes = $this->get_config('maxsubmissionsizebytes'); | |
75 | ||
76 | $settings = array(); | |
77 | $options = array(); | |
e5403f8c | 78 | for ($i = 1; $i <= ASSIGNSUBMISSION_FILE_MAXFILES; $i++) { |
bbd0e548 DW |
79 | $options[$i] = $i; |
80 | } | |
81 | ||
e5403f8c DW |
82 | $name = get_string('maxfilessubmission', 'assignsubmission_file'); |
83 | $mform->addElement('select', 'assignsubmission_file_maxfiles', $name, $options); | |
84 | $mform->addHelpButton('assignsubmission_file_maxfiles', | |
85 | 'maxfilessubmission', | |
86 | 'assignsubmission_file'); | |
bbd0e548 DW |
87 | $mform->setDefault('assignsubmission_file_maxfiles', $defaultmaxfilesubmissions); |
88 | $mform->disabledIf('assignsubmission_file_maxfiles', 'assignsubmission_file_enabled', 'eq', 0); | |
89 | ||
e5403f8c DW |
90 | $choices = get_max_upload_sizes($CFG->maxbytes, |
91 | $COURSE->maxbytes, | |
92 | get_config('assignsubmission_file', 'maxbytes')); | |
6d976f3f CR |
93 | |
94 | // Remove the option for 0 bytes. | |
95 | unset($choices[0]); | |
e5403f8c | 96 | |
bbd0e548 | 97 | if ($COURSE->maxbytes == 0) { |
6d976f3f | 98 | $choices = array(0=>get_string('siteuploadlimit', 'assignsubmission_file')) + $choices; |
bbd0e548 | 99 | } else { |
6d976f3f | 100 | $choices = array(0=>get_string('courseuploadlimit') . ' (' . display_size($COURSE->maxbytes) . ')') + $choices; |
bbd0e548 DW |
101 | } |
102 | $settings[] = array('type' => 'select', | |
103 | 'name' => 'maxsubmissionsizebytes', | |
104 | 'description' => get_string('maximumsubmissionsize', 'assignsubmission_file'), | |
105 | 'options'=> $choices, | |
106 | 'default'=> $defaultmaxsubmissionsizebytes); | |
107 | ||
e5403f8c DW |
108 | $name = get_string('maximumsubmissionsize', 'assignsubmission_file'); |
109 | $mform->addElement('select', 'assignsubmission_file_maxsizebytes', $name, $choices); | |
110 | $mform->addHelpButton('assignsubmission_file_maxsizebytes', | |
111 | 'maximumsubmissionsize', | |
112 | 'assignsubmission_file'); | |
bbd0e548 | 113 | $mform->setDefault('assignsubmission_file_maxsizebytes', $defaultmaxsubmissionsizebytes); |
e5403f8c DW |
114 | $mform->disabledIf('assignsubmission_file_maxsizebytes', |
115 | 'assignsubmission_file_enabled', | |
116 | 'eq', 0); | |
bbd0e548 DW |
117 | } |
118 | ||
119 | /** | |
120 | * Save the settings for file submission plugin | |
121 | * | |
122 | * @param stdClass $data | |
123 | * @return bool | |
124 | */ | |
125 | public function save_settings(stdClass $data) { | |
126 | $this->set_config('maxfilesubmissions', $data->assignsubmission_file_maxfiles); | |
127 | $this->set_config('maxsubmissionsizebytes', $data->assignsubmission_file_maxsizebytes); | |
128 | return true; | |
129 | } | |
130 | ||
131 | /** | |
132 | * File format options | |
133 | * | |
134 | * @return array | |
135 | */ | |
136 | private function get_file_options() { | |
137 | $fileoptions = array('subdirs'=>1, | |
138 | 'maxbytes'=>$this->get_config('maxsubmissionsizebytes'), | |
139 | 'maxfiles'=>$this->get_config('maxfilesubmissions'), | |
140 | 'accepted_types'=>'*', | |
141 | 'return_types'=>FILE_INTERNAL); | |
142 | return $fileoptions; | |
143 | } | |
144 | ||
145 | /** | |
146 | * Add elements to submission form | |
147 | * | |
148 | * @param mixed $submission stdClass|null | |
149 | * @param MoodleQuickForm $mform | |
150 | * @param stdClass $data | |
151 | * @return bool | |
152 | */ | |
153 | public function get_form_elements($submission, MoodleQuickForm $mform, stdClass $data) { | |
154 | ||
155 | if ($this->get_config('maxfilesubmissions') <= 0) { | |
156 | return false; | |
157 | } | |
158 | ||
159 | $fileoptions = $this->get_file_options(); | |
160 | $submissionid = $submission ? $submission->id : 0; | |
161 | ||
e5403f8c DW |
162 | $data = file_prepare_standard_filemanager($data, |
163 | 'files', | |
164 | $fileoptions, | |
165 | $this->assignment->get_context(), | |
166 | 'assignsubmission_file', | |
167 | ASSIGNSUBMISSION_FILE_FILEAREA, | |
168 | $submissionid); | |
bbd0e548 DW |
169 | $mform->addElement('filemanager', 'files_filemanager', '', null, $fileoptions); |
170 | return true; | |
171 | } | |
172 | ||
173 | /** | |
174 | * Count the number of files | |
175 | * | |
176 | * @param int $submissionid | |
177 | * @param string $area | |
178 | * @return int | |
179 | */ | |
180 | private function count_files($submissionid, $area) { | |
181 | ||
182 | $fs = get_file_storage(); | |
e5403f8c DW |
183 | $files = $fs->get_area_files($this->assignment->get_context()->id, |
184 | 'assignsubmission_file', | |
185 | $area, | |
186 | $submissionid, | |
187 | 'id', | |
188 | false); | |
bbd0e548 DW |
189 | |
190 | return count($files); | |
191 | } | |
192 | ||
193 | /** | |
e5403f8c DW |
194 | * Save the files and trigger plagiarism plugin, if enabled, |
195 | * to scan the uploaded files via events trigger | |
bbd0e548 DW |
196 | * |
197 | * @param stdClass $submission | |
198 | * @param stdClass $data | |
199 | * @return bool | |
200 | */ | |
201 | public function save(stdClass $submission, stdClass $data) { | |
202 | global $USER, $DB; | |
203 | ||
204 | $fileoptions = $this->get_file_options(); | |
205 | ||
e5403f8c DW |
206 | $data = file_postupdate_standard_filemanager($data, |
207 | 'files', | |
208 | $fileoptions, | |
209 | $this->assignment->get_context(), | |
210 | 'assignsubmission_file', | |
211 | ASSIGNSUBMISSION_FILE_FILEAREA, | |
212 | $submission->id); | |
bbd0e548 DW |
213 | |
214 | $filesubmission = $this->get_file_submission($submission->id); | |
215 | ||
e5403f8c | 216 | // Plagiarism code event trigger when files are uploaded. |
bbd0e548 DW |
217 | |
218 | $fs = get_file_storage(); | |
e5403f8c DW |
219 | $files = $fs->get_area_files($this->assignment->get_context()->id, |
220 | 'assignsubmission_file', | |
221 | ASSIGNSUBMISSION_FILE_FILEAREA, | |
222 | $submission->id, | |
223 | 'id', | |
224 | false); | |
225 | ||
8ab7bb9f | 226 | $count = $this->count_files($submission->id, ASSIGNSUBMISSION_FILE_FILEAREA); |
e5403f8c DW |
227 | |
228 | // Send files to event system. | |
229 | // This lets Moodle know that an assessable file was uploaded (eg for plagiarism detection). | |
bbd0e548 DW |
230 | $eventdata = new stdClass(); |
231 | $eventdata->modulename = 'assign'; | |
232 | $eventdata->cmid = $this->assignment->get_course_module()->id; | |
233 | $eventdata->itemid = $submission->id; | |
234 | $eventdata->courseid = $this->assignment->get_course()->id; | |
235 | $eventdata->userid = $USER->id; | |
236 | if ($count > 1) { | |
e5403f8c | 237 | $eventdata->files = $files; |
bbd0e548 | 238 | } |
e5403f8c | 239 | $eventdata->file = $files; |
4447223b | 240 | $eventdata->pathnamehashes = array_keys($files); |
bbd0e548 DW |
241 | events_trigger('assessable_file_uploaded', $eventdata); |
242 | ||
bbd0e548 | 243 | if ($filesubmission) { |
e5403f8c DW |
244 | $filesubmission->numfiles = $this->count_files($submission->id, |
245 | ASSIGNSUBMISSION_FILE_FILEAREA); | |
bbd0e548 DW |
246 | return $DB->update_record('assignsubmission_file', $filesubmission); |
247 | } else { | |
248 | $filesubmission = new stdClass(); | |
e5403f8c DW |
249 | $filesubmission->numfiles = $this->count_files($submission->id, |
250 | ASSIGNSUBMISSION_FILE_FILEAREA); | |
bbd0e548 DW |
251 | $filesubmission->submission = $submission->id; |
252 | $filesubmission->assignment = $this->assignment->get_instance()->id; | |
253 | return $DB->insert_record('assignsubmission_file', $filesubmission) > 0; | |
254 | } | |
255 | } | |
256 | ||
257 | /** | |
258 | * Produce a list of files suitable for export that represent this feedback or submission | |
259 | * | |
260 | * @param stdClass $submission The submission | |
261 | * @return array - return an array of files indexed by filename | |
262 | */ | |
2406815b | 263 | public function get_files(stdClass $submission, stdClass $user) { |
bbd0e548 DW |
264 | $result = array(); |
265 | $fs = get_file_storage(); | |
266 | ||
e5403f8c DW |
267 | $files = $fs->get_area_files($this->assignment->get_context()->id, |
268 | 'assignsubmission_file', | |
269 | ASSIGNSUBMISSION_FILE_FILEAREA, | |
270 | $submission->id, | |
271 | 'timemodified', | |
272 | false); | |
bbd0e548 DW |
273 | |
274 | foreach ($files as $file) { | |
275 | $result[$file->get_filename()] = $file; | |
276 | } | |
277 | return $result; | |
278 | } | |
279 | ||
280 | /** | |
281 | * Display the list of files in the submission status table | |
282 | * | |
283 | * @param stdClass $submission | |
284 | * @param bool $showviewlink Set this to true if the list of files is long | |
285 | * @return string | |
286 | */ | |
7ee1548a | 287 | public function view_summary(stdClass $submission, & $showviewlink) { |
8ab7bb9f | 288 | $count = $this->count_files($submission->id, ASSIGNSUBMISSION_FILE_FILEAREA); |
bbd0e548 | 289 | |
e5403f8c | 290 | // Show we show a link to view all files for this plugin? |
8ab7bb9f DW |
291 | $showviewlink = $count > ASSIGNSUBMISSION_FILE_MAXSUMMARYFILES; |
292 | if ($count <= ASSIGNSUBMISSION_FILE_MAXSUMMARYFILES) { | |
e5403f8c DW |
293 | return $this->assignment->render_area_files('assignsubmission_file', |
294 | ASSIGNSUBMISSION_FILE_FILEAREA, | |
295 | $submission->id); | |
bbd0e548 DW |
296 | } else { |
297 | return get_string('countfiles', 'assignsubmission_file', $count); | |
298 | } | |
299 | } | |
300 | ||
301 | /** | |
302 | * No full submission view - the summary contains the list of files and that is the whole submission | |
303 | * | |
304 | * @param stdClass $submission | |
305 | * @return string | |
306 | */ | |
307 | public function view(stdClass $submission) { | |
e5403f8c DW |
308 | return $this->assignment->render_area_files('assignsubmission_file', |
309 | ASSIGNSUBMISSION_FILE_FILEAREA, | |
310 | $submission->id); | |
bbd0e548 DW |
311 | } |
312 | ||
313 | ||
314 | ||
315 | /** | |
316 | * Return true if this plugin can upgrade an old Moodle 2.2 assignment of this type | |
317 | * and version. | |
318 | * | |
319 | * @param string $type | |
320 | * @param int $version | |
321 | * @return bool True if upgrade is possible | |
322 | */ | |
323 | public function can_upgrade($type, $version) { | |
324 | ||
325 | $uploadsingletype ='uploadsingle'; | |
326 | $uploadtype ='upload'; | |
327 | ||
328 | if (($type == $uploadsingletype || $type == $uploadtype) && $version >= 2011112900) { | |
329 | return true; | |
330 | } | |
331 | return false; | |
332 | } | |
333 | ||
334 | ||
335 | /** | |
336 | * Upgrade the settings from the old assignment | |
337 | * to the new plugin based one | |
338 | * | |
339 | * @param context $oldcontext - the old assignment context | |
340 | * @param stdClass $oldassignment - the old assignment data record | |
341 | * @param string $log record log events here | |
342 | * @return bool Was it a success? (false will trigger rollback) | |
343 | */ | |
e5403f8c | 344 | public function upgrade_settings(context $oldcontext, stdClass $oldassignment, & $log) { |
01d29b39 DW |
345 | global $DB; |
346 | ||
bbd0e548 DW |
347 | if ($oldassignment->assignmenttype == 'uploadsingle') { |
348 | $this->set_config('maxfilesubmissions', 1); | |
349 | $this->set_config('maxsubmissionsizebytes', $oldassignment->maxbytes); | |
350 | return true; | |
01d29b39 | 351 | } else if ($oldassignment->assignmenttype == 'upload') { |
bbd0e548 DW |
352 | $this->set_config('maxfilesubmissions', $oldassignment->var1); |
353 | $this->set_config('maxsubmissionsizebytes', $oldassignment->maxbytes); | |
01d29b39 DW |
354 | |
355 | // Advanced file upload uses a different setting to do the same thing. | |
356 | $DB->set_field('assign', | |
357 | 'submissiondrafts', | |
358 | $oldassignment->var4, | |
359 | array('id'=>$this->assignment->get_instance()->id)); | |
f531ca72 DW |
360 | |
361 | // Convert advanced file upload "hide description before due date" setting. | |
362 | $alwaysshow = 0; | |
363 | if (!$oldassignment->var3) { | |
364 | $alwaysshow = 1; | |
365 | } | |
366 | $DB->set_field('assign', | |
367 | 'alwaysshowdescription', | |
368 | $alwaysshow, | |
369 | array('id'=>$this->assignment->get_instance()->id)); | |
bbd0e548 DW |
370 | return true; |
371 | } | |
bbd0e548 DW |
372 | } |
373 | ||
374 | /** | |
375 | * Upgrade the submission from the old assignment to the new one | |
376 | * | |
377 | * @param context $oldcontext The context of the old assignment | |
378 | * @param stdClass $oldassignment The data record for the old oldassignment | |
379 | * @param stdClass $oldsubmission The data record for the old submission | |
380 | * @param stdClass $submission The data record for the new submission | |
381 | * @param string $log Record upgrade messages in the log | |
382 | * @return bool true or false - false will trigger a rollback | |
383 | */ | |
e5403f8c DW |
384 | public function upgrade(context $oldcontext, |
385 | stdClass $oldassignment, | |
386 | stdClass $oldsubmission, | |
387 | stdClass $submission, | |
388 | & $log) { | |
bbd0e548 DW |
389 | global $DB; |
390 | ||
391 | $filesubmission = new stdClass(); | |
392 | ||
393 | $filesubmission->numfiles = $oldsubmission->numfiles; | |
394 | $filesubmission->submission = $submission->id; | |
395 | $filesubmission->assignment = $this->assignment->get_instance()->id; | |
396 | ||
397 | if (!$DB->insert_record('assignsubmission_file', $filesubmission) > 0) { | |
398 | $log .= get_string('couldnotconvertsubmission', 'mod_assign', $submission->userid); | |
399 | return false; | |
400 | } | |
401 | ||
e5403f8c | 402 | // Now copy the area files. |
bbd0e548 DW |
403 | $this->assignment->copy_area_files_for_upgrade($oldcontext->id, |
404 | 'mod_assignment', | |
405 | 'submission', | |
406 | $oldsubmission->id, | |
bbd0e548 DW |
407 | $this->assignment->get_context()->id, |
408 | 'assignsubmission_file', | |
8ab7bb9f | 409 | ASSIGNSUBMISSION_FILE_FILEAREA, |
bbd0e548 DW |
410 | $submission->id); |
411 | ||
bbd0e548 DW |
412 | return true; |
413 | } | |
414 | ||
415 | /** | |
416 | * The assignment has been deleted - cleanup | |
417 | * | |
418 | * @return bool | |
419 | */ | |
420 | public function delete_instance() { | |
421 | global $DB; | |
e5403f8c DW |
422 | // Will throw exception on failure. |
423 | $DB->delete_records('assignsubmission_file', | |
424 | array('assignment'=>$this->assignment->get_instance()->id)); | |
bbd0e548 DW |
425 | |
426 | return true; | |
427 | } | |
428 | ||
429 | /** | |
430 | * Formatting for log info | |
431 | * | |
432 | * @param stdClass $submission The submission | |
bbd0e548 DW |
433 | * @return string |
434 | */ | |
435 | public function format_for_log(stdClass $submission) { | |
e5403f8c | 436 | // Format the info for each submission plugin (will be added to log). |
8ab7bb9f | 437 | $filecount = $this->count_files($submission->id, ASSIGNSUBMISSION_FILE_FILEAREA); |
bbd0e548 | 438 | |
e5403f8c | 439 | return get_string('numfilesforlog', 'assignsubmission_file', $filecount); |
bbd0e548 DW |
440 | } |
441 | ||
442 | /** | |
443 | * Return true if there are no submission files | |
444 | * @param stdClass $submission | |
445 | */ | |
446 | public function is_empty(stdClass $submission) { | |
8ab7bb9f | 447 | return $this->count_files($submission->id, ASSIGNSUBMISSION_FILE_FILEAREA) == 0; |
bbd0e548 DW |
448 | } |
449 | ||
450 | /** | |
451 | * Get file areas returns a list of areas this plugin stores files | |
452 | * @return array - An array of fileareas (keys) and descriptions (values) | |
453 | */ | |
454 | public function get_file_areas() { | |
8ab7bb9f | 455 | return array(ASSIGNSUBMISSION_FILE_FILEAREA=>$this->get_name()); |
bbd0e548 DW |
456 | } |
457 | ||
458 | } |