Merge branch 'MDL-37030-master' of git://github.com/damyon/moodle
[moodle.git] / mod / assign / assignmentplugin.php
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/>.
17 /**
18  * This file contains the functions for assign_plugin abstract class
19  *
20  *
21  * @package   mod_assign
22  * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
23  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
26 defined('MOODLE_INTERNAL') || die();
28 /**
29  * Abstract class for assign_plugin (submission/feedback).
30  *
31  * @package   mod_assign
32  * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
33  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
34  */
35 abstract class assign_plugin {
37     /** @var assign $assignment the assignment record that contains the global
38      *              settings for this assign instance
39      */
40     protected $assignment;
41     /** @var string $type assignment plugin type */
42     private $type = '';
43     /** @var string $error error message */
44     private $error = '';
47     /**
48      * Constructor for the abstract plugin type class
49      *
50      * @param assign $assignment
51      * @param string $type
52      */
53     public final function __construct(assign $assignment, $type) {
54         $this->assignment = $assignment;
55         $this->type = $type;
56     }
58     /**
59      * Is this the first plugin in the list?
60      *
61      * @return bool
62      */
63     public final function is_first() {
64         $order = get_config($this->get_subtype() . '_' . $this->get_type(), 'sortorder');
66         if ($order == 0) {
67             return true;
68         }
69         return false;
70     }
72     /**
73      * Is this the last plugin in the list?
74      *
75      * @return bool
76      */
77     public final function is_last() {
78         $lastindex = count(get_plugin_list($this->get_subtype()))-1;
79         $currentindex = get_config($this->get_subtype() . '_' . $this->get_type(), 'sortorder');
80         if ($lastindex == $currentindex) {
81             return true;
82         }
84         return false;
85     }
87     /**
88      * This function should be overridden to provide an array of elements that can be added to a moodle
89      * form for display in the settings page for the assignment.
90      * @param MoodleQuickForm $mform The form to add the elements to
91      * @return $array
92      */
93     public function get_settings(MoodleQuickForm $mform) {
94         return;
95     }
97     /**
98      * Allows the plugin to update the defaultvalues passed in to
99      * the settings form (needed to set up draft areas for editor
100      * and filemanager elements)
101      * @param array $defaultvalues
102      */
103     public function data_preprocessing(&$defaultvalues) {
104         return;
105     }
107     /**
108      * The assignment subtype is responsible for saving it's own settings as the database table for the
109      * standard type cannot be modified.
110      *
111      * @param stdClass $formdata - the data submitted from the form
112      * @return bool - on error the subtype should call set_error and return false.
113      */
114     public function save_settings(stdClass $formdata) {
115         return true;
116     }
118     /**
119      * Save the error message from the last error
120      *
121      * @param string $msg - the error description
122      */
123     protected final function set_error($msg) {
124         $this->error = $msg;
125     }
127     /**
128      * What was the last error?
129      *
130      * @return string
131      */
132     public final function get_error() {
133         return $this->error;
134     }
136     /**
137      * Should return the name of this plugin type.
138      *
139      * @return string - the name
140      */
141     public abstract function get_name();
143     /**
144      * Should return the subtype of this plugin.
145      *
146      * @return string - either 'assignsubmission' or 'feedback'
147      */
148     public abstract function get_subtype();
150     /**
151      * Should return the type of this plugin.
152      *
153      * @return string - the type
154      */
155     public final function get_type() {
156         return $this->type;
157     }
159     /**
160      * Get the installed version of this plugin
161      *
162      * @return string
163      */
164     public final function get_version() {
165         $version = get_config($this->get_subtype() . '_' . $this->get_type(), 'version');
166         if ($version) {
167             return $version;
168         } else {
169             return '';
170         }
171     }
173     /**
174      * Get the required moodle version for this plugin
175      *
176      * @return string
177      */
178     public final function get_requires() {
179         $requires = get_config($this->get_subtype() . '_' . $this->get_type(), 'requires');
180         if ($requires) {
181             return $requires;
182         } else {
183             return '';
184         }
185     }
187     /**
188      * Save any custom data for this form submission
189      *
190      * @param stdClass $submissionorgrade - assign_submission or assign_grade.
191      *              For submission plugins this is the submission data,
192      *              for feedback plugins it is the grade data
193      * @param stdClass $data - the data submitted from the form
194      * @return bool - on error the subtype should call set_error and return false.
195      */
196     public function save(stdClass $submissionorgrade, stdClass $data) {
197         return true;
198     }
200     /**
201      * Set this plugin to enabled
202      *
203      * @return bool
204      */
205     public final function enable() {
206         return $this->set_config('enabled', 1);
207     }
209     /**
210      * Set this plugin to disabled
211      *
212      * @return bool
213      */
214     public final function disable() {
215         return $this->set_config('enabled', 0);
216     }
218     /**
219      * Allows hiding this plugin from the submission/feedback screen if it is not enabled.
220      *
221      * @return bool - if false - this plugin will not accept submissions / feedback
222      */
223     public function is_enabled() {
224         return $this->get_config('enabled');
225     }
228     /**
229      * Get any additional fields for the submission/grading form for this assignment.
230      *
231      * @param mixed $submissionorgrade submission|grade - For submission plugins this is the submission data,
232      *                                                    for feedback plugins it is the grade data
233      * @param MoodleQuickForm $mform - This is the form
234      * @param stdClass $data - This is the form data that can be modified for example by a filemanager element
235      * @param int $userid - This is the userid for the current submission.
236      *                      This is passed separately as there may not yet be a submission or grade.
237      * @return boolean - true if we added anything to the form
238      */
239     public function get_form_elements_for_user($submissionorgrade, MoodleQuickForm $mform, stdClass $data, $userid) {
240         return $this->get_form_elements($submissionorgrade, $mform, $data);
241     }
243     /**
244      * Get any additional fields for the submission/grading form for this assignment.
245      * This function is retained for backwards compatibility - new plugins should override {@link get_form_elements_for_user()}.
246      *
247      * @param mixed $submissionorgrade submission|grade - For submission plugins this is the submission data,
248      *                                                    for feedback plugins it is the grade data
249      * @param MoodleQuickForm $mform - This is the form
250      * @param stdClass $data - This is the form data that can be modified for example by a filemanager element
251      * @return boolean - true if we added anything to the form
252      */
253     public function get_form_elements($submissionorgrade, MoodleQuickForm $mform, stdClass $data) {
254         return false;
255     }
257     /**
258      * Should not output anything - return the result as a string so it can be consumed by webservices.
259      *
260      * @param stdClass $submissionorgrade assign_submission or assign_grade
261      *                 For submission plugins this is the submission data,
262      *                 for feedback plugins it is the grade data
263      * @return string - return a string representation of the submission in full
264      */
265     public function view(stdClass $submissionorgrade) {
266         return '';
267     }
269     /**
270      * Get the numerical sort order for this plugin
271      *
272      * @return int
273      */
274     public final function get_sort_order() {
275         $order = get_config($this->get_subtype() . '_' . $this->get_type(), 'sortorder');
276         return $order?$order:0;
277     }
279     /**
280      * Is this plugin enaled?
281      *
282      * @return bool
283      */
284     public final function is_visible() {
285         $disabled = get_config($this->get_subtype() . '_' . $this->get_type(), 'disabled');
286         return !$disabled;
287     }
290     /**
291      * Has this plugin got a custom settings.php file?
292      *
293      * @return bool
294      */
295     public final function has_admin_settings() {
296         global $CFG;
298         $pluginroot = $CFG->dirroot . '/mod/assign/' . substr($this->get_subtype(), strlen('assign')) . '/' . $this->get_type();
299         $settingsfile = $pluginroot . '/settings.php';
300         return file_exists($settingsfile);
301     }
303     /**
304      * Set a configuration value for this plugin
305      *
306      * @param string $name The config key
307      * @param string $value The config value
308      * @return bool
309      */
310     public final function set_config($name, $value) {
311         global $DB;
313         $dbparams = array('assignment'=>$this->assignment->get_instance()->id,
314                           'subtype'=>$this->get_subtype(),
315                           'plugin'=>$this->get_type(),
316                           'name'=>$name);
317         $current = $DB->get_record('assign_plugin_config', $dbparams, '*', IGNORE_MISSING);
319         if ($current) {
320             $current->value = $value;
321             return $DB->update_record('assign_plugin_config', $current);
322         } else {
323             $setting = new stdClass();
324             $setting->assignment = $this->assignment->get_instance()->id;
325             $setting->subtype = $this->get_subtype();
326             $setting->plugin = $this->get_type();
327             $setting->name = $name;
328             $setting->value = $value;
330             return $DB->insert_record('assign_plugin_config', $setting) > 0;
331         }
332     }
334     /**
335      * Get a configuration value for this plugin
336      *
337      * @param mixed $setting The config key (string) or null
338      * @return mixed string | false
339      */
340     public final function get_config($setting = null) {
341         global $DB;
343         if ($setting) {
344             if (!$this->assignment->has_instance()) {
345                 return false;
346             }
347             $assignment = $this->assignment->get_instance();
348             if ($assignment) {
349                 $dbparams = array('assignment'=>$assignment->id,
350                                   'subtype'=>$this->get_subtype(),
351                                   'plugin'=>$this->get_type(),
352                                   'name'=>$setting);
353                 $result = $DB->get_record('assign_plugin_config', $dbparams, '*', IGNORE_MISSING);
354                 if ($result) {
355                     return $result->value;
356                 }
357             }
358             return false;
359         }
360         $dbparams = array('assignment'=>$this->assignment->get_instance()->id,
361                           'subtype'=>$this->get_subtype(),
362                            'plugin'=>$this->get_type());
363         $results = $DB->get_records('assign_plugin_config', $dbparams);
365         $config = new stdClass();
366         if (is_array($results)) {
367             foreach ($results as $setting) {
368                 $name = $setting->name;
369                 $config->$name = $setting->value;
370             }
371         }
372         return $config;
373     }
375     /**
376      * Should not output anything - return the result as a string so it can be consumed by webservices.
377      *
378      * @param stdClass $submissionorgrade assign_submission or assign_grade
379      *                 For submission plugins this is the submission data, for feedback plugins it is the grade data
380      * @param bool $showviewlink Modifed to return whether or not to show a link to the full submission/feedback
381      * @return string - return a string representation of the submission in full
382      */
383     public function view_summary(stdClass $submissionorgrade, & $showviewlink) {
384         return '';
385     }
387     /**
388      * Given a field name and value should update the text for this field in the plugins submission or grade
389      *
390      * @param string $name Name of the field.
391      * @param string $value Updated text
392      * @param int $submissionorgradeid The id of the submission or grade
393      * @return bool - true if the value was updated
394      */
395     public function set_editor_text($name, $value, $submissionorgradeid) {
396         return false;
397     }
399     /**
400      * Given a field name and value should update the format for this field in the plugins submission or grade
401      *
402      * @param string $name Name of the field.
403      * @param int $format Updated format.
404      * @param int $submissionorgradeid The id of the submission or grade.
405      * @return bool - true if the value was updated
406      */
407     public function set_editor_format($name, $format, $submissionorgradeid) {
408         return false;
409     }
411     /**
412      * Return a list of the fields that can be exported or imported via text.
413      *
414      * @return array - The list of field names (strings) and descriptions. ($name => $description)
415      */
416     public function get_editor_fields() {
417         return array();
418     }
420     /**
421      * Given a field name, should return the text of an editor field that is part of
422      * this plugin. This is used when exporting to portfolio.
423      *
424      * @param string $name Name of the field.
425      * @param int $submissionorgradeid The id of the submission or grade
426      * @return string - The text for the editor field
427      */
428     public function get_editor_text($name, $submissionorgradeid) {
429         return '';
430     }
432     /**
433      * Produce a list of files suitable for export that represent this feedback or submission
434      *
435      * @param stdClass $submissionorgrade assign_submission or assign_grade
436      *                 For submission plugins this is the submission data, for feedback plugins it is the grade data
437      * @param stdClass $user The user record for the current submission.
438      *                         Needed for url rewriting if this is a group submission.
439      * @return array - return an array of files indexed by filename
440      */
441     public function get_files(stdClass $submissionorgrade, stdClass $user) {
442         return array();
443     }
445     /**
446      * Given a field name, should return the format of an editor field that is part of
447      * this plugin. This is used when exporting to portfolio.
448      *
449      * @param string $name Name of the field.
450      * @param int $submissionid The id of the submission
451      * @return int - The format for the editor field
452      */
453     public function get_editor_format($name, $submissionid) {
454         return 0;
455     }
457     /**
458      * Return true if this plugin can upgrade an old Moodle 2.2 assignment of this type
459      * and version.
460      *
461      * @param string $type The old assignment subtype
462      * @param int $version The old assignment version
463      * @return bool True if upgrade is possible
464      */
465     public function can_upgrade($type, $version) {
466         return false;
467     }
469     /**
470      * Upgrade the settings from the old assignment to the new one
471      *
472      * @param context $oldcontext The context for the old assignment module
473      * @param stdClass $oldassignment The data record for the old assignment
474      * @param string $log Record upgrade messages in the log
475      * @return bool true or false - false will trigger a rollback
476      */
477     public function upgrade_settings(context $oldcontext, stdClass $oldassignment, & $log) {
478         $params = array('type'=>$this->type, 'subtype'=>$this->get_subtype());
479         $log .= ' ' . get_string('upgradenotimplemented', 'mod_assign', $params);
480         return false;
481     }
483     /**
484      * Upgrade the submission from the old assignment to the new one
485      *
486      * @param context $oldcontext The data record for the old context
487      * @param stdClass $oldassignment The data record for the old assignment
488      * @param stdClass $oldsubmissionorgrade The data record for the old submission
489      * @param stdClass $submissionorgrade assign_submission or assign_grade The new submission or grade
490      * @param string $log Record upgrade messages in the log
491      * @return boolean true or false - false will trigger a rollback
492      */
493     public function upgrade(context $oldcontext,
494                             stdClass $oldassignment,
495                             stdClass $oldsubmissionorgrade,
496                             stdClass $submissionorgrade,
497                             & $log) {
498         $params = array('type'=>$this->type, 'subtype'=>$this->get_subtype());
499         $log = $log . ' ' . get_string('upgradenotimplemented', 'mod_assign', $params);
500         return false;
501     }
503     /**
504      * Formatting for log info
505      *
506      * @param stdClass $submissionorgrade assign_submission or assign_grade The new submission or grade
507      * @return string
508      */
509     public function format_for_log(stdClass $submissionorgrade) {
510         // Format the info for each submission plugin add_to_log.
511         return '';
512     }
514     /**
515      * The assignment has been deleted - remove the plugin specific data
516      *
517      * @return bool
518      */
519     public function delete_instance() {
520         return true;
521     }
523     /**
524      * Run cron for this plugin
525      */
526     public static function cron() {
527     }
529     /**
530      * Is this assignment plugin empty? (ie no submission or feedback)
531      * @param stdClass $submissionorgrade assign_submission or assign_grade
532      * @return bool
533      */
534     public function is_empty(stdClass $submissionorgrade) {
535         return true;
536     }
538     /**
539      * Get file areas returns a list of areas this plugin stores files
540      * @return array - An array of fileareas (keys) and descriptions (values)
541      */
542     public function get_file_areas() {
543         return array();
544     }
547     /**
548      * Default implementation of file_get_info for plugins.
549      * This is used by the filebrowser to browse a plugins file areas.
550      *
551      * This implementation should work for most plugins but can be overridden if required.
552      * @param file_browser $browser
553      * @param string $filearea
554      * @param int $itemid
555      * @param string $filepath
556      * @param string $filename
557      * @return file_info_stored
558      */
559     public function get_file_info($browser, $filearea, $itemid, $filepath, $filename) {
560         global $CFG, $DB, $USER;
561         $urlbase = $CFG->wwwroot.'/pluginfile.php';
563         // Permission check on the itemid.
565         if ($this->get_subtype() == 'assignsubmission') {
566             if ($itemid) {
567                 $record = $DB->get_record('assign_submission', array('id'=>$itemid), 'userid', IGNORE_MISSING);
568                 if (!$record) {
569                     return null;
570                 }
571                 if (!$this->assignment->can_view_submission($record->userid)) {
572                     return null;
573                 }
574             }
575         } else {
576             // Not supported for feedback plugins.
577             return null;
578         }
580         $fs = get_file_storage();
581         $filepath = is_null($filepath) ? '/' : $filepath;
582         $filename = is_null($filename) ? '.' : $filename;
583         if (!($storedfile = $fs->get_file($this->assignment->get_context()->id,
584                                           $this->get_subtype() . '_' . $this->get_type(),
585                                           $filearea,
586                                           $itemid,
587                                           $filepath,
588                                           $filename))) {
589             return null;
590         }
591         return new file_info_stored($browser,
592                                     $this->assignment->get_context(),
593                                     $storedfile,
594                                     $urlbase,
595                                     $filearea,
596                                     $itemid,
597                                     true,
598                                     true,
599                                     false);
600     }
602     /**
603      * This allows a plugin to render a page in the context of the assignment
604      *
605      * If the plugin creates a link to the assignment view.php page with
606      * The following required parameters:
607      *      id=coursemoduleid
608      *      plugin=type
609      *      pluginsubtype=assignfeedback|assignsubmission
610      *      pluginaction=customaction
611      *
612      * Then this function will be called to display the page with the pluginaction passed as action
613      * @param string $action The plugin specified action
614      * @return string
615      */
616     public function view_page($action) {
617         return '';
618     }
620     /**
621      * If this plugin should not include a column in the grading table or a row on the summary page
622      * then return false
623      *
624      * @return bool
625      */
626     public function has_user_summary() {
627         return true;
628     }