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 | 87 | $mform->setDefault('assignsubmission_file_maxfiles', $defaultmaxfilesubmissions); |
b0da618b | 88 | $mform->disabledIf('assignsubmission_file_maxfiles', 'assignsubmission_file_enabled', 'notchecked'); |
bbd0e548 | 89 | |
e5403f8c DW |
90 | $choices = get_max_upload_sizes($CFG->maxbytes, |
91 | $COURSE->maxbytes, | |
92 | get_config('assignsubmission_file', 'maxbytes')); | |
6d976f3f | 93 | |
bbd0e548 DW |
94 | $settings[] = array('type' => 'select', |
95 | 'name' => 'maxsubmissionsizebytes', | |
96 | 'description' => get_string('maximumsubmissionsize', 'assignsubmission_file'), | |
97 | 'options'=> $choices, | |
98 | 'default'=> $defaultmaxsubmissionsizebytes); | |
99 | ||
e5403f8c DW |
100 | $name = get_string('maximumsubmissionsize', 'assignsubmission_file'); |
101 | $mform->addElement('select', 'assignsubmission_file_maxsizebytes', $name, $choices); | |
102 | $mform->addHelpButton('assignsubmission_file_maxsizebytes', | |
103 | 'maximumsubmissionsize', | |
104 | 'assignsubmission_file'); | |
bbd0e548 | 105 | $mform->setDefault('assignsubmission_file_maxsizebytes', $defaultmaxsubmissionsizebytes); |
e5403f8c DW |
106 | $mform->disabledIf('assignsubmission_file_maxsizebytes', |
107 | 'assignsubmission_file_enabled', | |
b0da618b | 108 | 'notchecked'); |
bbd0e548 DW |
109 | } |
110 | ||
111 | /** | |
112 | * Save the settings for file submission plugin | |
113 | * | |
114 | * @param stdClass $data | |
115 | * @return bool | |
116 | */ | |
117 | public function save_settings(stdClass $data) { | |
118 | $this->set_config('maxfilesubmissions', $data->assignsubmission_file_maxfiles); | |
119 | $this->set_config('maxsubmissionsizebytes', $data->assignsubmission_file_maxsizebytes); | |
120 | return true; | |
121 | } | |
122 | ||
123 | /** | |
124 | * File format options | |
125 | * | |
126 | * @return array | |
127 | */ | |
128 | private function get_file_options() { | |
129 | $fileoptions = array('subdirs'=>1, | |
130 | 'maxbytes'=>$this->get_config('maxsubmissionsizebytes'), | |
131 | 'maxfiles'=>$this->get_config('maxfilesubmissions'), | |
132 | 'accepted_types'=>'*', | |
133 | 'return_types'=>FILE_INTERNAL); | |
134 | return $fileoptions; | |
135 | } | |
136 | ||
137 | /** | |
138 | * Add elements to submission form | |
139 | * | |
140 | * @param mixed $submission stdClass|null | |
141 | * @param MoodleQuickForm $mform | |
142 | * @param stdClass $data | |
143 | * @return bool | |
144 | */ | |
145 | public function get_form_elements($submission, MoodleQuickForm $mform, stdClass $data) { | |
146 | ||
147 | if ($this->get_config('maxfilesubmissions') <= 0) { | |
148 | return false; | |
149 | } | |
150 | ||
151 | $fileoptions = $this->get_file_options(); | |
152 | $submissionid = $submission ? $submission->id : 0; | |
153 | ||
e5403f8c DW |
154 | $data = file_prepare_standard_filemanager($data, |
155 | 'files', | |
156 | $fileoptions, | |
157 | $this->assignment->get_context(), | |
158 | 'assignsubmission_file', | |
159 | ASSIGNSUBMISSION_FILE_FILEAREA, | |
160 | $submissionid); | |
3a5c3b3c | 161 | $mform->addElement('filemanager', 'files_filemanager', $this->get_name(), null, $fileoptions); |
7e5be074 | 162 | |
bbd0e548 DW |
163 | return true; |
164 | } | |
165 | ||
166 | /** | |
167 | * Count the number of files | |
168 | * | |
169 | * @param int $submissionid | |
170 | * @param string $area | |
171 | * @return int | |
172 | */ | |
173 | private function count_files($submissionid, $area) { | |
174 | ||
175 | $fs = get_file_storage(); | |
e5403f8c DW |
176 | $files = $fs->get_area_files($this->assignment->get_context()->id, |
177 | 'assignsubmission_file', | |
178 | $area, | |
179 | $submissionid, | |
180 | 'id', | |
181 | false); | |
bbd0e548 DW |
182 | |
183 | return count($files); | |
184 | } | |
185 | ||
186 | /** | |
e5403f8c DW |
187 | * Save the files and trigger plagiarism plugin, if enabled, |
188 | * to scan the uploaded files via events trigger | |
bbd0e548 DW |
189 | * |
190 | * @param stdClass $submission | |
191 | * @param stdClass $data | |
192 | * @return bool | |
193 | */ | |
194 | public function save(stdClass $submission, stdClass $data) { | |
195 | global $USER, $DB; | |
196 | ||
197 | $fileoptions = $this->get_file_options(); | |
198 | ||
e5403f8c DW |
199 | $data = file_postupdate_standard_filemanager($data, |
200 | 'files', | |
201 | $fileoptions, | |
202 | $this->assignment->get_context(), | |
203 | 'assignsubmission_file', | |
204 | ASSIGNSUBMISSION_FILE_FILEAREA, | |
205 | $submission->id); | |
bbd0e548 DW |
206 | |
207 | $filesubmission = $this->get_file_submission($submission->id); | |
208 | ||
e5403f8c | 209 | // Plagiarism code event trigger when files are uploaded. |
bbd0e548 DW |
210 | |
211 | $fs = get_file_storage(); | |
e5403f8c DW |
212 | $files = $fs->get_area_files($this->assignment->get_context()->id, |
213 | 'assignsubmission_file', | |
214 | ASSIGNSUBMISSION_FILE_FILEAREA, | |
215 | $submission->id, | |
216 | 'id', | |
217 | false); | |
218 | ||
8ab7bb9f | 219 | $count = $this->count_files($submission->id, ASSIGNSUBMISSION_FILE_FILEAREA); |
e5403f8c | 220 | |
e3d2d064 FM |
221 | $params = array( |
222 | 'context' => context_module::instance($this->assignment->get_course_module()->id), | |
223 | 'objectid' => $submission->id, | |
224 | 'other' => array( | |
225 | 'content' => '', | |
226 | 'pathnamehashes' => array_keys($files) | |
227 | ) | |
228 | ); | |
229 | $event = \assignsubmission_file\event\assessable_uploaded::create($params); | |
230 | $event->set_legacy_files($files); | |
231 | $event->trigger(); | |
bbd0e548 | 232 | |
bbd0e548 | 233 | if ($filesubmission) { |
e5403f8c DW |
234 | $filesubmission->numfiles = $this->count_files($submission->id, |
235 | ASSIGNSUBMISSION_FILE_FILEAREA); | |
bbd0e548 DW |
236 | return $DB->update_record('assignsubmission_file', $filesubmission); |
237 | } else { | |
238 | $filesubmission = new stdClass(); | |
e5403f8c DW |
239 | $filesubmission->numfiles = $this->count_files($submission->id, |
240 | ASSIGNSUBMISSION_FILE_FILEAREA); | |
bbd0e548 DW |
241 | $filesubmission->submission = $submission->id; |
242 | $filesubmission->assignment = $this->assignment->get_instance()->id; | |
243 | return $DB->insert_record('assignsubmission_file', $filesubmission) > 0; | |
244 | } | |
245 | } | |
246 | ||
247 | /** | |
248 | * Produce a list of files suitable for export that represent this feedback or submission | |
249 | * | |
250 | * @param stdClass $submission The submission | |
1561a37c | 251 | * @param stdClass $user The user record - unused |
bbd0e548 DW |
252 | * @return array - return an array of files indexed by filename |
253 | */ | |
2406815b | 254 | public function get_files(stdClass $submission, stdClass $user) { |
bbd0e548 DW |
255 | $result = array(); |
256 | $fs = get_file_storage(); | |
257 | ||
e5403f8c DW |
258 | $files = $fs->get_area_files($this->assignment->get_context()->id, |
259 | 'assignsubmission_file', | |
260 | ASSIGNSUBMISSION_FILE_FILEAREA, | |
261 | $submission->id, | |
262 | 'timemodified', | |
263 | false); | |
bbd0e548 DW |
264 | |
265 | foreach ($files as $file) { | |
266 | $result[$file->get_filename()] = $file; | |
267 | } | |
268 | return $result; | |
269 | } | |
270 | ||
271 | /** | |
272 | * Display the list of files in the submission status table | |
273 | * | |
274 | * @param stdClass $submission | |
275 | * @param bool $showviewlink Set this to true if the list of files is long | |
276 | * @return string | |
277 | */ | |
7ee1548a | 278 | public function view_summary(stdClass $submission, & $showviewlink) { |
8ab7bb9f | 279 | $count = $this->count_files($submission->id, ASSIGNSUBMISSION_FILE_FILEAREA); |
bbd0e548 | 280 | |
e5403f8c | 281 | // Show we show a link to view all files for this plugin? |
8ab7bb9f DW |
282 | $showviewlink = $count > ASSIGNSUBMISSION_FILE_MAXSUMMARYFILES; |
283 | if ($count <= ASSIGNSUBMISSION_FILE_MAXSUMMARYFILES) { | |
e5403f8c DW |
284 | return $this->assignment->render_area_files('assignsubmission_file', |
285 | ASSIGNSUBMISSION_FILE_FILEAREA, | |
286 | $submission->id); | |
bbd0e548 DW |
287 | } else { |
288 | return get_string('countfiles', 'assignsubmission_file', $count); | |
289 | } | |
290 | } | |
291 | ||
292 | /** | |
293 | * No full submission view - the summary contains the list of files and that is the whole submission | |
294 | * | |
295 | * @param stdClass $submission | |
296 | * @return string | |
297 | */ | |
298 | public function view(stdClass $submission) { | |
e5403f8c DW |
299 | return $this->assignment->render_area_files('assignsubmission_file', |
300 | ASSIGNSUBMISSION_FILE_FILEAREA, | |
301 | $submission->id); | |
bbd0e548 DW |
302 | } |
303 | ||
304 | ||
305 | ||
306 | /** | |
307 | * Return true if this plugin can upgrade an old Moodle 2.2 assignment of this type | |
308 | * and version. | |
309 | * | |
310 | * @param string $type | |
311 | * @param int $version | |
312 | * @return bool True if upgrade is possible | |
313 | */ | |
314 | public function can_upgrade($type, $version) { | |
315 | ||
316 | $uploadsingletype ='uploadsingle'; | |
317 | $uploadtype ='upload'; | |
318 | ||
319 | if (($type == $uploadsingletype || $type == $uploadtype) && $version >= 2011112900) { | |
320 | return true; | |
321 | } | |
322 | return false; | |
323 | } | |
324 | ||
325 | ||
326 | /** | |
327 | * Upgrade the settings from the old assignment | |
328 | * to the new plugin based one | |
329 | * | |
330 | * @param context $oldcontext - the old assignment context | |
331 | * @param stdClass $oldassignment - the old assignment data record | |
332 | * @param string $log record log events here | |
333 | * @return bool Was it a success? (false will trigger rollback) | |
334 | */ | |
e5403f8c | 335 | public function upgrade_settings(context $oldcontext, stdClass $oldassignment, & $log) { |
01d29b39 DW |
336 | global $DB; |
337 | ||
bbd0e548 DW |
338 | if ($oldassignment->assignmenttype == 'uploadsingle') { |
339 | $this->set_config('maxfilesubmissions', 1); | |
340 | $this->set_config('maxsubmissionsizebytes', $oldassignment->maxbytes); | |
341 | return true; | |
01d29b39 | 342 | } else if ($oldassignment->assignmenttype == 'upload') { |
bbd0e548 DW |
343 | $this->set_config('maxfilesubmissions', $oldassignment->var1); |
344 | $this->set_config('maxsubmissionsizebytes', $oldassignment->maxbytes); | |
01d29b39 DW |
345 | |
346 | // Advanced file upload uses a different setting to do the same thing. | |
347 | $DB->set_field('assign', | |
348 | 'submissiondrafts', | |
349 | $oldassignment->var4, | |
350 | array('id'=>$this->assignment->get_instance()->id)); | |
f531ca72 DW |
351 | |
352 | // Convert advanced file upload "hide description before due date" setting. | |
353 | $alwaysshow = 0; | |
354 | if (!$oldassignment->var3) { | |
355 | $alwaysshow = 1; | |
356 | } | |
357 | $DB->set_field('assign', | |
358 | 'alwaysshowdescription', | |
359 | $alwaysshow, | |
360 | array('id'=>$this->assignment->get_instance()->id)); | |
bbd0e548 DW |
361 | return true; |
362 | } | |
bbd0e548 DW |
363 | } |
364 | ||
365 | /** | |
366 | * Upgrade the submission from the old assignment to the new one | |
367 | * | |
368 | * @param context $oldcontext The context of the old assignment | |
369 | * @param stdClass $oldassignment The data record for the old oldassignment | |
370 | * @param stdClass $oldsubmission The data record for the old submission | |
371 | * @param stdClass $submission The data record for the new submission | |
372 | * @param string $log Record upgrade messages in the log | |
373 | * @return bool true or false - false will trigger a rollback | |
374 | */ | |
e5403f8c DW |
375 | public function upgrade(context $oldcontext, |
376 | stdClass $oldassignment, | |
377 | stdClass $oldsubmission, | |
378 | stdClass $submission, | |
379 | & $log) { | |
bbd0e548 DW |
380 | global $DB; |
381 | ||
382 | $filesubmission = new stdClass(); | |
383 | ||
384 | $filesubmission->numfiles = $oldsubmission->numfiles; | |
385 | $filesubmission->submission = $submission->id; | |
386 | $filesubmission->assignment = $this->assignment->get_instance()->id; | |
387 | ||
388 | if (!$DB->insert_record('assignsubmission_file', $filesubmission) > 0) { | |
389 | $log .= get_string('couldnotconvertsubmission', 'mod_assign', $submission->userid); | |
390 | return false; | |
391 | } | |
392 | ||
e5403f8c | 393 | // Now copy the area files. |
bbd0e548 DW |
394 | $this->assignment->copy_area_files_for_upgrade($oldcontext->id, |
395 | 'mod_assignment', | |
396 | 'submission', | |
397 | $oldsubmission->id, | |
bbd0e548 DW |
398 | $this->assignment->get_context()->id, |
399 | 'assignsubmission_file', | |
8ab7bb9f | 400 | ASSIGNSUBMISSION_FILE_FILEAREA, |
bbd0e548 DW |
401 | $submission->id); |
402 | ||
bbd0e548 DW |
403 | return true; |
404 | } | |
405 | ||
406 | /** | |
407 | * The assignment has been deleted - cleanup | |
408 | * | |
409 | * @return bool | |
410 | */ | |
411 | public function delete_instance() { | |
412 | global $DB; | |
e5403f8c DW |
413 | // Will throw exception on failure. |
414 | $DB->delete_records('assignsubmission_file', | |
415 | array('assignment'=>$this->assignment->get_instance()->id)); | |
bbd0e548 DW |
416 | |
417 | return true; | |
418 | } | |
419 | ||
420 | /** | |
421 | * Formatting for log info | |
422 | * | |
423 | * @param stdClass $submission The submission | |
bbd0e548 DW |
424 | * @return string |
425 | */ | |
426 | public function format_for_log(stdClass $submission) { | |
e5403f8c | 427 | // Format the info for each submission plugin (will be added to log). |
8ab7bb9f | 428 | $filecount = $this->count_files($submission->id, ASSIGNSUBMISSION_FILE_FILEAREA); |
bbd0e548 | 429 | |
e5403f8c | 430 | return get_string('numfilesforlog', 'assignsubmission_file', $filecount); |
bbd0e548 DW |
431 | } |
432 | ||
433 | /** | |
434 | * Return true if there are no submission files | |
435 | * @param stdClass $submission | |
436 | */ | |
437 | public function is_empty(stdClass $submission) { | |
8ab7bb9f | 438 | return $this->count_files($submission->id, ASSIGNSUBMISSION_FILE_FILEAREA) == 0; |
bbd0e548 DW |
439 | } |
440 | ||
441 | /** | |
442 | * Get file areas returns a list of areas this plugin stores files | |
443 | * @return array - An array of fileareas (keys) and descriptions (values) | |
444 | */ | |
445 | public function get_file_areas() { | |
8ab7bb9f | 446 | return array(ASSIGNSUBMISSION_FILE_FILEAREA=>$this->get_name()); |
bbd0e548 DW |
447 | } |
448 | ||
df211804 DW |
449 | /** |
450 | * Copy the student's submission from a previous submission. Used when a student opts to base their resubmission | |
451 | * on the last submission. | |
452 | * @param stdClass $sourcesubmission | |
453 | * @param stdClass $destsubmission | |
454 | */ | |
455 | public function copy_submission(stdClass $sourcesubmission, stdClass $destsubmission) { | |
456 | global $DB; | |
457 | ||
458 | // Copy the files across. | |
459 | $contextid = $this->assignment->get_context()->id; | |
460 | $fs = get_file_storage(); | |
461 | $files = $fs->get_area_files($contextid, | |
462 | 'assignsubmission_file', | |
463 | ASSIGNSUBMISSION_FILE_FILEAREA, | |
464 | $sourcesubmission->id, | |
465 | 'id', | |
466 | false); | |
467 | foreach ($files as $file) { | |
468 | $fieldupdates = array('itemid' => $destsubmission->id); | |
469 | $fs->create_file_from_storedfile($fieldupdates, $file); | |
470 | } | |
471 | ||
472 | // Copy the assignsubmission_file record. | |
473 | if ($filesubmission = $this->get_file_submission($sourcesubmission->id)) { | |
474 | unset($filesubmission->id); | |
475 | $filesubmission->submission = $destsubmission->id; | |
476 | $DB->insert_record('assignsubmission_file', $filesubmission); | |
477 | } | |
478 | return true; | |
479 | } | |
05a6445a DW |
480 | |
481 | /** | |
482 | * Return a description of external params suitable for uploading a file submission from a webservice. | |
483 | * | |
484 | * @return external_description|null | |
485 | */ | |
486 | public function get_external_parameters() { | |
539af602 DW |
487 | return array( |
488 | 'files_filemanager' => new external_value( | |
489 | PARAM_INT, | |
490 | 'The id of a draft area containing files for this submission.' | |
491 | ) | |
492 | ); | |
05a6445a | 493 | } |
bbd0e548 | 494 | } |