MDL-37337 Assignment: Restructure assignment settings screen to make it "wieldy"
[moodle.git] / mod / assign / submission / file / locallib.php
CommitLineData
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
27require_once($CFG->libdir.'/eventslib.php');
28
29defined('MOODLE_INTERNAL') || die();
e5403f8c
DW
30
31// File areas for file submission assignment.
8ab7bb9f
DW
32define('ASSIGNSUBMISSION_FILE_MAXFILES', 20);
33define('ASSIGNSUBMISSION_FILE_MAXSUMMARYFILES', 5);
34define('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 */
43class 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);
7e5be074
MN
161 $mform->addElement('filemanager', 'files_filemanager', html_writer::tag('span', $this->get_name(),
162 array('class' => 'accesshide')), null, $fileoptions);
163
bbd0e548
DW
164 return true;
165 }
166
167 /**
168 * Count the number of files
169 *
170 * @param int $submissionid
171 * @param string $area
172 * @return int
173 */
174 private function count_files($submissionid, $area) {
175
176 $fs = get_file_storage();
e5403f8c
DW
177 $files = $fs->get_area_files($this->assignment->get_context()->id,
178 'assignsubmission_file',
179 $area,
180 $submissionid,
181 'id',
182 false);
bbd0e548
DW
183
184 return count($files);
185 }
186
187 /**
e5403f8c
DW
188 * Save the files and trigger plagiarism plugin, if enabled,
189 * to scan the uploaded files via events trigger
bbd0e548
DW
190 *
191 * @param stdClass $submission
192 * @param stdClass $data
193 * @return bool
194 */
195 public function save(stdClass $submission, stdClass $data) {
196 global $USER, $DB;
197
198 $fileoptions = $this->get_file_options();
199
e5403f8c
DW
200 $data = file_postupdate_standard_filemanager($data,
201 'files',
202 $fileoptions,
203 $this->assignment->get_context(),
204 'assignsubmission_file',
205 ASSIGNSUBMISSION_FILE_FILEAREA,
206 $submission->id);
bbd0e548
DW
207
208 $filesubmission = $this->get_file_submission($submission->id);
209
e5403f8c 210 // Plagiarism code event trigger when files are uploaded.
bbd0e548
DW
211
212 $fs = get_file_storage();
e5403f8c
DW
213 $files = $fs->get_area_files($this->assignment->get_context()->id,
214 'assignsubmission_file',
215 ASSIGNSUBMISSION_FILE_FILEAREA,
216 $submission->id,
217 'id',
218 false);
219
8ab7bb9f 220 $count = $this->count_files($submission->id, ASSIGNSUBMISSION_FILE_FILEAREA);
e5403f8c
DW
221
222 // Send files to event system.
223 // This lets Moodle know that an assessable file was uploaded (eg for plagiarism detection).
bbd0e548
DW
224 $eventdata = new stdClass();
225 $eventdata->modulename = 'assign';
226 $eventdata->cmid = $this->assignment->get_course_module()->id;
227 $eventdata->itemid = $submission->id;
228 $eventdata->courseid = $this->assignment->get_course()->id;
229 $eventdata->userid = $USER->id;
230 if ($count > 1) {
e5403f8c 231 $eventdata->files = $files;
bbd0e548 232 }
e5403f8c 233 $eventdata->file = $files;
4447223b 234 $eventdata->pathnamehashes = array_keys($files);
bbd0e548
DW
235 events_trigger('assessable_file_uploaded', $eventdata);
236
bbd0e548 237 if ($filesubmission) {
e5403f8c
DW
238 $filesubmission->numfiles = $this->count_files($submission->id,
239 ASSIGNSUBMISSION_FILE_FILEAREA);
bbd0e548
DW
240 return $DB->update_record('assignsubmission_file', $filesubmission);
241 } else {
242 $filesubmission = new stdClass();
e5403f8c
DW
243 $filesubmission->numfiles = $this->count_files($submission->id,
244 ASSIGNSUBMISSION_FILE_FILEAREA);
bbd0e548
DW
245 $filesubmission->submission = $submission->id;
246 $filesubmission->assignment = $this->assignment->get_instance()->id;
247 return $DB->insert_record('assignsubmission_file', $filesubmission) > 0;
248 }
249 }
250
251 /**
252 * Produce a list of files suitable for export that represent this feedback or submission
253 *
254 * @param stdClass $submission The submission
255 * @return array - return an array of files indexed by filename
256 */
2406815b 257 public function get_files(stdClass $submission, stdClass $user) {
bbd0e548
DW
258 $result = array();
259 $fs = get_file_storage();
260
e5403f8c
DW
261 $files = $fs->get_area_files($this->assignment->get_context()->id,
262 'assignsubmission_file',
263 ASSIGNSUBMISSION_FILE_FILEAREA,
264 $submission->id,
265 'timemodified',
266 false);
bbd0e548
DW
267
268 foreach ($files as $file) {
269 $result[$file->get_filename()] = $file;
270 }
271 return $result;
272 }
273
274 /**
275 * Display the list of files in the submission status table
276 *
277 * @param stdClass $submission
278 * @param bool $showviewlink Set this to true if the list of files is long
279 * @return string
280 */
7ee1548a 281 public function view_summary(stdClass $submission, & $showviewlink) {
8ab7bb9f 282 $count = $this->count_files($submission->id, ASSIGNSUBMISSION_FILE_FILEAREA);
bbd0e548 283
e5403f8c 284 // Show we show a link to view all files for this plugin?
8ab7bb9f
DW
285 $showviewlink = $count > ASSIGNSUBMISSION_FILE_MAXSUMMARYFILES;
286 if ($count <= ASSIGNSUBMISSION_FILE_MAXSUMMARYFILES) {
e5403f8c
DW
287 return $this->assignment->render_area_files('assignsubmission_file',
288 ASSIGNSUBMISSION_FILE_FILEAREA,
289 $submission->id);
bbd0e548
DW
290 } else {
291 return get_string('countfiles', 'assignsubmission_file', $count);
292 }
293 }
294
295 /**
296 * No full submission view - the summary contains the list of files and that is the whole submission
297 *
298 * @param stdClass $submission
299 * @return string
300 */
301 public function view(stdClass $submission) {
e5403f8c
DW
302 return $this->assignment->render_area_files('assignsubmission_file',
303 ASSIGNSUBMISSION_FILE_FILEAREA,
304 $submission->id);
bbd0e548
DW
305 }
306
307
308
309 /**
310 * Return true if this plugin can upgrade an old Moodle 2.2 assignment of this type
311 * and version.
312 *
313 * @param string $type
314 * @param int $version
315 * @return bool True if upgrade is possible
316 */
317 public function can_upgrade($type, $version) {
318
319 $uploadsingletype ='uploadsingle';
320 $uploadtype ='upload';
321
322 if (($type == $uploadsingletype || $type == $uploadtype) && $version >= 2011112900) {
323 return true;
324 }
325 return false;
326 }
327
328
329 /**
330 * Upgrade the settings from the old assignment
331 * to the new plugin based one
332 *
333 * @param context $oldcontext - the old assignment context
334 * @param stdClass $oldassignment - the old assignment data record
335 * @param string $log record log events here
336 * @return bool Was it a success? (false will trigger rollback)
337 */
e5403f8c 338 public function upgrade_settings(context $oldcontext, stdClass $oldassignment, & $log) {
01d29b39
DW
339 global $DB;
340
bbd0e548
DW
341 if ($oldassignment->assignmenttype == 'uploadsingle') {
342 $this->set_config('maxfilesubmissions', 1);
343 $this->set_config('maxsubmissionsizebytes', $oldassignment->maxbytes);
344 return true;
01d29b39 345 } else if ($oldassignment->assignmenttype == 'upload') {
bbd0e548
DW
346 $this->set_config('maxfilesubmissions', $oldassignment->var1);
347 $this->set_config('maxsubmissionsizebytes', $oldassignment->maxbytes);
01d29b39
DW
348
349 // Advanced file upload uses a different setting to do the same thing.
350 $DB->set_field('assign',
351 'submissiondrafts',
352 $oldassignment->var4,
353 array('id'=>$this->assignment->get_instance()->id));
f531ca72
DW
354
355 // Convert advanced file upload "hide description before due date" setting.
356 $alwaysshow = 0;
357 if (!$oldassignment->var3) {
358 $alwaysshow = 1;
359 }
360 $DB->set_field('assign',
361 'alwaysshowdescription',
362 $alwaysshow,
363 array('id'=>$this->assignment->get_instance()->id));
bbd0e548
DW
364 return true;
365 }
bbd0e548
DW
366 }
367
368 /**
369 * Upgrade the submission from the old assignment to the new one
370 *
371 * @param context $oldcontext The context of the old assignment
372 * @param stdClass $oldassignment The data record for the old oldassignment
373 * @param stdClass $oldsubmission The data record for the old submission
374 * @param stdClass $submission The data record for the new submission
375 * @param string $log Record upgrade messages in the log
376 * @return bool true or false - false will trigger a rollback
377 */
e5403f8c
DW
378 public function upgrade(context $oldcontext,
379 stdClass $oldassignment,
380 stdClass $oldsubmission,
381 stdClass $submission,
382 & $log) {
bbd0e548
DW
383 global $DB;
384
385 $filesubmission = new stdClass();
386
387 $filesubmission->numfiles = $oldsubmission->numfiles;
388 $filesubmission->submission = $submission->id;
389 $filesubmission->assignment = $this->assignment->get_instance()->id;
390
391 if (!$DB->insert_record('assignsubmission_file', $filesubmission) > 0) {
392 $log .= get_string('couldnotconvertsubmission', 'mod_assign', $submission->userid);
393 return false;
394 }
395
e5403f8c 396 // Now copy the area files.
bbd0e548
DW
397 $this->assignment->copy_area_files_for_upgrade($oldcontext->id,
398 'mod_assignment',
399 'submission',
400 $oldsubmission->id,
bbd0e548
DW
401 $this->assignment->get_context()->id,
402 'assignsubmission_file',
8ab7bb9f 403 ASSIGNSUBMISSION_FILE_FILEAREA,
bbd0e548
DW
404 $submission->id);
405
bbd0e548
DW
406 return true;
407 }
408
409 /**
410 * The assignment has been deleted - cleanup
411 *
412 * @return bool
413 */
414 public function delete_instance() {
415 global $DB;
e5403f8c
DW
416 // Will throw exception on failure.
417 $DB->delete_records('assignsubmission_file',
418 array('assignment'=>$this->assignment->get_instance()->id));
bbd0e548
DW
419
420 return true;
421 }
422
423 /**
424 * Formatting for log info
425 *
426 * @param stdClass $submission The submission
bbd0e548
DW
427 * @return string
428 */
429 public function format_for_log(stdClass $submission) {
e5403f8c 430 // Format the info for each submission plugin (will be added to log).
8ab7bb9f 431 $filecount = $this->count_files($submission->id, ASSIGNSUBMISSION_FILE_FILEAREA);
bbd0e548 432
e5403f8c 433 return get_string('numfilesforlog', 'assignsubmission_file', $filecount);
bbd0e548
DW
434 }
435
436 /**
437 * Return true if there are no submission files
438 * @param stdClass $submission
439 */
440 public function is_empty(stdClass $submission) {
8ab7bb9f 441 return $this->count_files($submission->id, ASSIGNSUBMISSION_FILE_FILEAREA) == 0;
bbd0e548
DW
442 }
443
444 /**
445 * Get file areas returns a list of areas this plugin stores files
446 * @return array - An array of fileareas (keys) and descriptions (values)
447 */
448 public function get_file_areas() {
8ab7bb9f 449 return array(ASSIGNSUBMISSION_FILE_FILEAREA=>$this->get_name());
bbd0e548
DW
450 }
451
452}