MDL-63632 forum: Delete where not discussion author
[moodle.git] / mod / assign / feedback / comments / locallib.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 definition for the library class for comment feedback plugin
19  *
20  * @package   assignfeedback_comments
21  * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
22  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
25 defined('MOODLE_INTERNAL') || die();
27 /**
28  * Library class for comment feedback plugin extending feedback plugin base class.
29  *
30  * @package   assignfeedback_comments
31  * @copyright 2012 NetSpot {@link http://www.netspot.com.au}
32  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33  */
34 class assign_feedback_comments extends assign_feedback_plugin {
36     /**
37      * Get the name of the online comment feedback plugin.
38      * @return string
39      */
40     public function get_name() {
41         return get_string('pluginname', 'assignfeedback_comments');
42     }
44     /**
45      * Get the feedback comment from the database.
46      *
47      * @param int $gradeid
48      * @return stdClass|false The feedback comments for the given grade if it exists.
49      *                        False if it doesn't.
50      */
51     public function get_feedback_comments($gradeid) {
52         global $DB;
53         return $DB->get_record('assignfeedback_comments', array('grade'=>$gradeid));
54     }
56     /**
57      * Get quickgrading form elements as html.
58      *
59      * @param int $userid The user id in the table this quickgrading element relates to
60      * @param mixed $grade - The grade data - may be null if there are no grades for this user (yet)
61      * @return mixed - A html string containing the html form elements required for quickgrading
62      */
63     public function get_quickgrading_html($userid, $grade) {
64         $commenttext = '';
65         if ($grade) {
66             $feedbackcomments = $this->get_feedback_comments($grade->id);
67             if ($feedbackcomments) {
68                 $commenttext = $feedbackcomments->commenttext;
69             }
70         }
72         $pluginname = get_string('pluginname', 'assignfeedback_comments');
73         $labeloptions = array('for'=>'quickgrade_comments_' . $userid,
74                               'class'=>'accesshide');
75         $textareaoptions = array('name'=>'quickgrade_comments_' . $userid,
76                                  'id'=>'quickgrade_comments_' . $userid,
77                                  'class'=>'quickgrade');
78         return html_writer::tag('label', $pluginname, $labeloptions) .
79                html_writer::tag('textarea', $commenttext, $textareaoptions);
80     }
82     /**
83      * Has the plugin quickgrading form element been modified in the current form submission?
84      *
85      * @param int $userid The user id in the table this quickgrading element relates to
86      * @param stdClass $grade The grade
87      * @return boolean - true if the quickgrading form element has been modified
88      */
89     public function is_quickgrading_modified($userid, $grade) {
90         $commenttext = '';
91         if ($grade) {
92             $feedbackcomments = $this->get_feedback_comments($grade->id);
93             if ($feedbackcomments) {
94                 $commenttext = $feedbackcomments->commenttext;
95             }
96         }
97         // Note that this handles the difference between empty and not in the quickgrading
98         // form at all (hidden column).
99         $newvalue = optional_param('quickgrade_comments_' . $userid, false, PARAM_RAW);
100         return ($newvalue !== false) && ($newvalue != $commenttext);
101     }
103     /**
104      * Has the comment feedback been modified?
105      *
106      * @param stdClass $grade The grade object.
107      * @param stdClass $data Data from the form submission.
108      * @return boolean True if the comment feedback has been modified, else false.
109      */
110     public function is_feedback_modified(stdClass $grade, stdClass $data) {
111         $commenttext = '';
112         if ($grade) {
113             $feedbackcomments = $this->get_feedback_comments($grade->id);
114             if ($feedbackcomments) {
115                 $commenttext = $feedbackcomments->commenttext;
116             }
117         }
119         if ($commenttext == $data->assignfeedbackcomments_editor['text']) {
120             return false;
121         } else {
122             return true;
123         }
124     }
127     /**
128      * Override to indicate a plugin supports quickgrading.
129      *
130      * @return boolean - True if the plugin supports quickgrading
131      */
132     public function supports_quickgrading() {
133         return true;
134     }
136     /**
137      * Return a list of the text fields that can be imported/exported by this plugin.
138      *
139      * @return array An array of field names and descriptions. (name=>description, ...)
140      */
141     public function get_editor_fields() {
142         return array('comments' => get_string('pluginname', 'assignfeedback_comments'));
143     }
145     /**
146      * Get the saved text content from the editor.
147      *
148      * @param string $name
149      * @param int $gradeid
150      * @return string
151      */
152     public function get_editor_text($name, $gradeid) {
153         if ($name == 'comments') {
154             $feedbackcomments = $this->get_feedback_comments($gradeid);
155             if ($feedbackcomments) {
156                 return $feedbackcomments->commenttext;
157             }
158         }
160         return '';
161     }
163     /**
164      * Get the saved text content from the editor.
165      *
166      * @param string $name
167      * @param string $value
168      * @param int $gradeid
169      * @return string
170      */
171     public function set_editor_text($name, $value, $gradeid) {
172         global $DB;
174         if ($name == 'comments') {
175             $feedbackcomment = $this->get_feedback_comments($gradeid);
176             if ($feedbackcomment) {
177                 $feedbackcomment->commenttext = $value;
178                 return $DB->update_record('assignfeedback_comments', $feedbackcomment);
179             } else {
180                 $feedbackcomment = new stdClass();
181                 $feedbackcomment->commenttext = $value;
182                 $feedbackcomment->commentformat = FORMAT_HTML;
183                 $feedbackcomment->grade = $gradeid;
184                 $feedbackcomment->assignment = $this->assignment->get_instance()->id;
185                 return $DB->insert_record('assignfeedback_comments', $feedbackcomment) > 0;
186             }
187         }
189         return false;
190     }
192     /**
193      * Save quickgrading changes.
194      *
195      * @param int $userid The user id in the table this quickgrading element relates to
196      * @param stdClass $grade The grade
197      * @return boolean - true if the grade changes were saved correctly
198      */
199     public function save_quickgrading_changes($userid, $grade) {
200         global $DB;
201         $feedbackcomment = $this->get_feedback_comments($grade->id);
202         $quickgradecomments = optional_param('quickgrade_comments_' . $userid, null, PARAM_RAW);
203         if (!$quickgradecomments && $quickgradecomments !== '') {
204             return true;
205         }
206         if ($feedbackcomment) {
207             $feedbackcomment->commenttext = $quickgradecomments;
208             return $DB->update_record('assignfeedback_comments', $feedbackcomment);
209         } else {
210             $feedbackcomment = new stdClass();
211             $feedbackcomment->commenttext = $quickgradecomments;
212             $feedbackcomment->commentformat = FORMAT_HTML;
213             $feedbackcomment->grade = $grade->id;
214             $feedbackcomment->assignment = $this->assignment->get_instance()->id;
215             return $DB->insert_record('assignfeedback_comments', $feedbackcomment) > 0;
216         }
217     }
219     /**
220      * Save the settings for feedback comments plugin
221      *
222      * @param stdClass $data
223      * @return bool
224      */
225     public function save_settings(stdClass $data) {
226         $this->set_config('commentinline', !empty($data->assignfeedback_comments_commentinline));
227         return true;
228     }
230     /**
231      * Get the default setting for feedback comments plugin
232      *
233      * @param MoodleQuickForm $mform The form to add elements to
234      * @return void
235      */
236     public function get_settings(MoodleQuickForm $mform) {
237         $default = $this->get_config('commentinline');
238         if ($default === false) {
239             // Apply the admin default if we don't have a value yet.
240             $default = get_config('assignfeedback_comments', 'inline');
241         }
242         $mform->addElement('selectyesno',
243                            'assignfeedback_comments_commentinline',
244                            get_string('commentinline', 'assignfeedback_comments'));
245         $mform->addHelpButton('assignfeedback_comments_commentinline', 'commentinline', 'assignfeedback_comments');
246         $mform->setDefault('assignfeedback_comments_commentinline', $default);
247         // Disable comment online if comment feedback plugin is disabled.
248         $mform->disabledIf('assignfeedback_comments_commentinline', 'assignfeedback_comments_enabled', 'notchecked');
249    }
251     /**
252      * Convert the text from any submission plugin that has an editor field to
253      * a format suitable for inserting in the feedback text field.
254      *
255      * @param stdClass $submission
256      * @param stdClass $data - Form data to be filled with the converted submission text and format.
257      * @return boolean - True if feedback text was set.
258      */
259     protected function convert_submission_text_to_feedback($submission, $data) {
260         $format = false;
261         $text = '';
263         foreach ($this->assignment->get_submission_plugins() as $plugin) {
264             $fields = $plugin->get_editor_fields();
265             if ($plugin->is_enabled() && $plugin->is_visible() && !$plugin->is_empty($submission) && !empty($fields)) {
266                 foreach ($fields as $key => $description) {
267                     $rawtext = strip_pluginfile_content($plugin->get_editor_text($key, $submission->id));
269                     $newformat = $plugin->get_editor_format($key, $submission->id);
271                     if ($format !== false && $newformat != $format) {
272                         // There are 2 or more editor fields using different formats, set to plain as a fallback.
273                         $format = FORMAT_PLAIN;
274                     } else {
275                         $format = $newformat;
276                     }
277                     $text .= $rawtext;
278                 }
279             }
280         }
282         if ($format === false) {
283             $format = FORMAT_HTML;
284         }
285         $data->assignfeedbackcomments_editor['text'] = $text;
286         $data->assignfeedbackcomments_editor['format'] = $format;
288         return true;
289     }
291     /**
292      * Get form elements for the grading page
293      *
294      * @param stdClass|null $grade
295      * @param MoodleQuickForm $mform
296      * @param stdClass $data
297      * @return bool true if elements were added to the form
298      */
299     public function get_form_elements_for_user($grade, MoodleQuickForm $mform, stdClass $data, $userid) {
300         $commentinlinenabled = $this->get_config('commentinline');
301         $submission = $this->assignment->get_user_submission($userid, false);
302         $feedbackcomments = false;
304         if ($grade) {
305             $feedbackcomments = $this->get_feedback_comments($grade->id);
306         }
308         if ($feedbackcomments && !empty($feedbackcomments->commenttext)) {
309             $data->assignfeedbackcomments_editor['text'] = $feedbackcomments->commenttext;
310             $data->assignfeedbackcomments_editor['format'] = $feedbackcomments->commentformat;
311         } else {
312             // No feedback given yet - maybe we need to copy the text from the submission?
313             if (!empty($commentinlinenabled) && $submission) {
314                 $this->convert_submission_text_to_feedback($submission, $data);
315             }
316         }
318         $mform->addElement('editor', 'assignfeedbackcomments_editor', $this->get_name(), null, null);
320         return true;
321     }
323     /**
324      * Saving the comment content into database.
325      *
326      * @param stdClass $grade
327      * @param stdClass $data
328      * @return bool
329      */
330     public function save(stdClass $grade, stdClass $data) {
331         global $DB;
332         $feedbackcomment = $this->get_feedback_comments($grade->id);
333         if ($feedbackcomment) {
334             $feedbackcomment->commenttext = $data->assignfeedbackcomments_editor['text'];
335             $feedbackcomment->commentformat = $data->assignfeedbackcomments_editor['format'];
336             return $DB->update_record('assignfeedback_comments', $feedbackcomment);
337         } else {
338             $feedbackcomment = new stdClass();
339             $feedbackcomment->commenttext = $data->assignfeedbackcomments_editor['text'];
340             $feedbackcomment->commentformat = $data->assignfeedbackcomments_editor['format'];
341             $feedbackcomment->grade = $grade->id;
342             $feedbackcomment->assignment = $this->assignment->get_instance()->id;
343             return $DB->insert_record('assignfeedback_comments', $feedbackcomment) > 0;
344         }
345     }
347     /**
348      * Display the comment in the feedback table.
349      *
350      * @param stdClass $grade
351      * @param bool $showviewlink Set to true to show a link to view the full feedback
352      * @return string
353      */
354     public function view_summary(stdClass $grade, & $showviewlink) {
355         $feedbackcomments = $this->get_feedback_comments($grade->id);
356         if ($feedbackcomments) {
357             $text = format_text($feedbackcomments->commenttext,
358                                 $feedbackcomments->commentformat,
359                                 array('context' => $this->assignment->get_context()));
360             $short = shorten_text($text, 140);
362             // Show the view all link if the text has been shortened.
363             $showviewlink = $short != $text;
364             return $short;
365         }
366         return '';
367     }
369     /**
370      * Display the comment in the feedback table.
371      *
372      * @param stdClass $grade
373      * @return string
374      */
375     public function view(stdClass $grade) {
376         $feedbackcomments = $this->get_feedback_comments($grade->id);
377         if ($feedbackcomments) {
378             return format_text($feedbackcomments->commenttext,
379                                $feedbackcomments->commentformat,
380                                array('context' => $this->assignment->get_context()));
381         }
382         return '';
383     }
385     /**
386      * Return true if this plugin can upgrade an old Moodle 2.2 assignment of this type
387      * and version.
388      *
389      * @param string $type old assignment subtype
390      * @param int $version old assignment version
391      * @return bool True if upgrade is possible
392      */
393     public function can_upgrade($type, $version) {
395         if (($type == 'upload' || $type == 'uploadsingle' ||
396              $type == 'online' || $type == 'offline') && $version >= 2011112900) {
397             return true;
398         }
399         return false;
400     }
402     /**
403      * Upgrade the settings from the old assignment to the new plugin based one
404      *
405      * @param context $oldcontext - the context for the old assignment
406      * @param stdClass $oldassignment - the data for the old assignment
407      * @param string $log - can be appended to by the upgrade
408      * @return bool was it a success? (false will trigger a rollback)
409      */
410     public function upgrade_settings(context $oldcontext, stdClass $oldassignment, & $log) {
411         if ($oldassignment->assignmenttype == 'online') {
412             $this->set_config('commentinline', $oldassignment->var1);
413             return true;
414         }
415         return true;
416     }
418     /**
419      * Upgrade the feedback from the old assignment to the new one
420      *
421      * @param context $oldcontext - the database for the old assignment context
422      * @param stdClass $oldassignment The data record for the old assignment
423      * @param stdClass $oldsubmission The data record for the old submission
424      * @param stdClass $grade The data record for the new grade
425      * @param string $log Record upgrade messages in the log
426      * @return bool true or false - false will trigger a rollback
427      */
428     public function upgrade(context $oldcontext,
429                             stdClass $oldassignment,
430                             stdClass $oldsubmission,
431                             stdClass $grade,
432                             & $log) {
433         global $DB;
435         $feedbackcomments = new stdClass();
436         $feedbackcomments->commenttext = $oldsubmission->submissioncomment;
437         $feedbackcomments->commentformat = FORMAT_HTML;
439         $feedbackcomments->grade = $grade->id;
440         $feedbackcomments->assignment = $this->assignment->get_instance()->id;
441         if (!$DB->insert_record('assignfeedback_comments', $feedbackcomments) > 0) {
442             $log .= get_string('couldnotconvertgrade', 'mod_assign', $grade->userid);
443             return false;
444         }
446         return true;
447     }
449     /**
450      * If this plugin adds to the gradebook comments field, it must specify the format of the text
451      * of the comment
452      *
453      * Only one feedback plugin can push comments to the gradebook and that is chosen by the assignment
454      * settings page.
455      *
456      * @param stdClass $grade The grade
457      * @return int
458      */
459     public function format_for_gradebook(stdClass $grade) {
460         $feedbackcomments = $this->get_feedback_comments($grade->id);
461         if ($feedbackcomments) {
462             return $feedbackcomments->commentformat;
463         }
464         return FORMAT_MOODLE;
465     }
467     /**
468      * If this plugin adds to the gradebook comments field, it must format the text
469      * of the comment
470      *
471      * Only one feedback plugin can push comments to the gradebook and that is chosen by the assignment
472      * settings page.
473      *
474      * @param stdClass $grade The grade
475      * @return string
476      */
477     public function text_for_gradebook(stdClass $grade) {
478         $feedbackcomments = $this->get_feedback_comments($grade->id);
479         if ($feedbackcomments) {
480             return $feedbackcomments->commenttext;
481         }
482         return '';
483     }
485     /**
486      * The assignment has been deleted - cleanup
487      *
488      * @return bool
489      */
490     public function delete_instance() {
491         global $DB;
492         // Will throw exception on failure.
493         $DB->delete_records('assignfeedback_comments',
494                             array('assignment'=>$this->assignment->get_instance()->id));
495         return true;
496     }
498     /**
499      * Returns true if there are no feedback comments for the given grade.
500      *
501      * @param stdClass $grade
502      * @return bool
503      */
504     public function is_empty(stdClass $grade) {
505         return $this->view($grade) == '';
506     }
508     /**
509      * Return a description of external params suitable for uploading an feedback comment from a webservice.
510      *
511      * @return external_description|null
512      */
513     public function get_external_parameters() {
514         $editorparams = array('text' => new external_value(PARAM_RAW, 'The text for this feedback.'),
515                               'format' => new external_value(PARAM_INT, 'The format for this feedback'));
516         $editorstructure = new external_single_structure($editorparams, 'Editor structure', VALUE_OPTIONAL);
517         return array('assignfeedbackcomments_editor' => $editorstructure);
518     }
520     /**
521      * Return the plugin configs for external functions.
522      *
523      * @return array the list of settings
524      * @since Moodle 3.2
525      */
526     public function get_config_for_external() {
527         return (array) $this->get_config();
528     }