57e0e71fee9204c576ee614bbaeba4e7a852d820
[moodle.git] / mod / assign / feedback / editpdf / 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 PDF feedback plugin
19  *
20  *
21  * @package   assignfeedback_editpdf
22  * @copyright 2012 Davo Smith
23  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
26 defined('MOODLE_INTERNAL') || die();
28 use \assignfeedback_editpdf\document_services;
29 use \assignfeedback_editpdf\page_editor;
31 /**
32  * library class for editpdf feedback plugin extending feedback plugin base class
33  *
34  * @package   assignfeedback_editpdf
35  * @copyright 2012 Davo Smith
36  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37  */
38 class assign_feedback_editpdf extends assign_feedback_plugin {
40     /** @var boolean|null $enabledcache Cached lookup of the is_enabled function */
41     private $enabledcache = null;
43     /**
44      * Get the name of the file feedback plugin
45      * @return string
46      */
47     public function get_name() {
48         return get_string('pluginname', 'assignfeedback_editpdf');
49     }
51     /**
52      * Create a widget for rendering the editor.
53      *
54      * @param int $userid
55      * @param stdClass $grade
56      * @param bool $readonly
57      * @return assignfeedback_editpdf_widget
58      */
59     public function get_widget($userid, $grade, $readonly) {
60         $attempt = -1;
61         if ($grade && $grade->attemptnumber) {
62             $attempt = $grade->attemptnumber;
63         } else {
64             $grade = $this->assignment->get_user_grade($userid, true);
65         }
67         $feedbackfile = document_services::get_feedback_document($this->assignment->get_instance()->id,
68                                                                  $userid,
69                                                                  $attempt);
71         $stampfiles = array();
72         $fs = get_file_storage();
73         $syscontext = context_system::instance();
75         // Copy any new stamps to this instance.
76         if ($files = $fs->get_area_files($syscontext->id,
77                                          'assignfeedback_editpdf',
78                                          'stamps',
79                                          0,
80                                          "filename",
81                                          false)) {
82             foreach ($files as $file) {
83                 $filename = $file->get_filename();
84                 if ($filename !== '.') {
86                     $existingfile = $fs->get_file($this->assignment->get_context()->id,
87                                                   'assignfeedback_editpdf',
88                                                   'stamps',
89                                                   $grade->id,
90                                                   '/',
91                                                   $file->get_filename());
92                     if (!$existingfile) {
93                         $newrecord = new stdClass();
94                         $newrecord->contextid = $this->assignment->get_context()->id;
95                         $newrecord->itemid = $grade->id;
96                         $fs->create_file_from_storedfile($newrecord, $file);
97                     }
98                 }
99             }
100         }
102         // Now get the full list of stamp files for this instance.
103         if ($files = $fs->get_area_files($this->assignment->get_context()->id,
104                                          'assignfeedback_editpdf',
105                                          'stamps',
106                                          $grade->id,
107                                          "filename",
108                                          false)) {
109             foreach ($files as $file) {
110                 $filename = $file->get_filename();
111                 if ($filename !== '.') {
112                     $url = moodle_url::make_pluginfile_url($this->assignment->get_context()->id,
113                                                    'assignfeedback_editpdf',
114                                                    'stamps',
115                                                    $grade->id,
116                                                    '/',
117                                                    $file->get_filename(),
118                                                    false);
119                     array_push($stampfiles, $url->out());
120                 }
121             }
122         }
124         $url = false;
125         $filename = '';
126         if ($feedbackfile) {
127             $url = moodle_url::make_pluginfile_url($this->assignment->get_context()->id,
128                                                    'assignfeedback_editpdf',
129                                                    document_services::FINAL_PDF_FILEAREA,
130                                                    $grade->id,
131                                                    '/',
132                                                    $feedbackfile->get_filename(),
133                                                    false);
134            $filename = $feedbackfile->get_filename();
135         }
137         // Retrieve total number of pages.
138         $pagetotal = document_services::page_number_for_attempt($this->assignment->get_instance()->id,
139                 $userid,
140                 $attempt,
141                 $readonly);
143         $widget = new assignfeedback_editpdf_widget($this->assignment->get_instance()->id,
144                                                     $userid,
145                                                     $attempt,
146                                                     $url,
147                                                     $filename,
148                                                     $stampfiles,
149                                                     $readonly,
150                                                     $pagetotal);
151         return $widget;
152     }
154     /**
155      * Get form elements for grading form
156      *
157      * @param stdClass $grade
158      * @param MoodleQuickForm $mform
159      * @param stdClass $data
160      * @param int $userid
161      * @return bool true if elements were added to the form
162      */
163     public function get_form_elements_for_user($grade, MoodleQuickForm $mform, stdClass $data, $userid) {
164         global $PAGE;
166         $attempt = -1;
167         if ($grade) {
168             $attempt = $grade->attemptnumber;
169         }
171         $files = document_services::list_compatible_submission_files_for_attempt($this->assignment, $userid, $attempt);
172         // Only show the editor if there was a compatible file submitted.
173         if (count($files)) {
175             $renderer = $PAGE->get_renderer('assignfeedback_editpdf');
177             $widget = $this->get_widget($userid, $grade, false);
179             $html = $renderer->render($widget);
180             $mform->addElement('static', 'editpdf', get_string('editpdf', 'assignfeedback_editpdf'), $html);
181             $mform->addHelpButton('editpdf', 'editpdf', 'assignfeedback_editpdf');
182             $mform->addElement('hidden', 'editpdf_source_userid', $userid);
183             $mform->setType('editpdf_source_userid', PARAM_INT);
184             $mform->setConstant('editpdf_source_userid', $userid);
185         }
186     }
188     /**
189      * Check to see if the grade feedback for the pdf has been modified.
190      *
191      * @param stdClass $grade Grade object.
192      * @param stdClass $data Data from the form submission (not used).
193      * @return boolean True if the pdf has been modified, else false.
194      */
195     public function is_feedback_modified(stdClass $grade, stdClass $data) {
196         global $USER;
197         $pagenumbercount = document_services::page_number_for_attempt($this->assignment, $grade->userid, $grade->attemptnumber);
198         for ($i = 0; $i < $pagenumbercount; $i++) {
199             // Select all annotations.
200             $draftannotations = page_editor::get_annotations($grade->id, $i, true);
201             $nondraftannotations = page_editor::get_annotations($grade->id, $i, false);
202             // Check to see if the count is the same.
203             if (count($draftannotations) != count($nondraftannotations)) {
204                 // The count is different so we have a modification.
205                 return true;
206             } else {
207                 // Have a closer look and see if the draft files match the non draft files.
208                 foreach ($nondraftannotations as $index => $ndannotation) {
209                     foreach ($ndannotation as $key => $value) {
210                         if ($key != 'id' && $value != $draftannotations[$index]->$key) {
211                             return true;
212                         }
213                     }
214                 }
215             }
216             // Select all comments.
217             $draftcomments = page_editor::get_comments($grade->id, $i, true);
218             $nondraftcomments = page_editor::get_comments($grade->id, $i, false);
219             if (count($draftcomments) != count($nondraftcomments)) {
220                 return true;
221             } else {
222                 // Go for a closer inspection.
223                 foreach ($nondraftcomments as $index => $ndcomment) {
224                     foreach ($ndcomment as $key => $value) {
225                         if ($key != 'id' && $value != $draftcomments[$index]->$key) {
226                             return true;
227                         }
228                     }
229                 }
230             }
231         }
232         return false;
233     }
235     /**
236      * Generate the pdf.
237      *
238      * @param stdClass $grade
239      * @param stdClass $data
240      * @return bool
241      */
242     public function save(stdClass $grade, stdClass $data) {
243         // Source user id is only added to the form if there was a pdf.
244         if (!empty($data->editpdf_source_userid)) {
245             $sourceuserid = $data->editpdf_source_userid;
246             // Copy drafts annotations and comments if current user is different to sourceuserid.
247             if ($sourceuserid != $grade->userid) {
248                 page_editor::copy_drafts_from_to($this->assignment, $grade, $sourceuserid);
249             }
250         }
251         if (page_editor::has_annotations_or_comments($grade->id, true)) {
252             document_services::generate_feedback_document($this->assignment, $grade->userid, $grade->attemptnumber);
253         }
255         return true;
256     }
258     /**
259      * Display the list of files in the feedback status table.
260      *
261      * @param stdClass $grade
262      * @param bool $showviewlink (Always set to false).
263      * @return string
264      */
265     public function view_summary(stdClass $grade, & $showviewlink) {
266         $showviewlink = false;
267         return $this->view($grade);
268     }
270     /**
271      * Display the list of files in the feedback status table.
272      *
273      * @param stdClass $grade
274      * @return string
275      */
276     public function view(stdClass $grade) {
277         global $PAGE;
278         $html = '';
279         // Show a link to download the pdf.
280         if (page_editor::has_annotations_or_comments($grade->id, false)) {
281             $html = $this->assignment->render_area_files('assignfeedback_editpdf',
282                                                          document_services::FINAL_PDF_FILEAREA,
283                                                          $grade->id);
285             // Also show the link to the read-only interface.
286             $renderer = $PAGE->get_renderer('assignfeedback_editpdf');
287             $widget = $this->get_widget($grade->userid, $grade, true);
289             $html .= $renderer->render($widget);
290         }
291         return $html;
292     }
294     /**
295      * Return true if there are no released comments/annotations.
296      *
297      * @param stdClass $grade
298      */
299     public function is_empty(stdClass $grade) {
300         global $DB;
302         $comments = $DB->count_records('assignfeedback_editpdf_cmnt', array('gradeid'=>$grade->id, 'draft'=>0));
303         $annotations = $DB->count_records('assignfeedback_editpdf_annot', array('gradeid'=>$grade->id, 'draft'=>0));
304         return $comments == 0 && $annotations == 0;
305     }
307     /**
308      * The assignment has been deleted - remove the plugin specific data
309      *
310      * @return bool
311      */
312     public function delete_instance() {
313         global $DB;
314         $grades = $DB->get_records('assign_grades', array('assignment'=>$this->assignment->get_instance()->id), '', 'id');
315         if ($grades) {
316             list($gradeids, $params) = $DB->get_in_or_equal(array_keys($grades), SQL_PARAMS_NAMED);
317             $DB->delete_records_select('assignfeedback_editpdf_annot', 'gradeid ' . $gradeids, $params);
318             $DB->delete_records_select('assignfeedback_editpdf_cmnt', 'gradeid ' . $gradeids, $params);
319         }
320         return true;
321     }
323     /**
324      * Automatically enable or disable editpdf feedback plugin based on
325      * whether the ghostscript path is set correctly.
326      *
327      * @return bool
328      */
329     public function is_enabled() {
330         if ($this->enabledcache === null) {
331             $testpath = assignfeedback_editpdf\pdf::test_gs_path(false);
332             $this->enabledcache = ($testpath->status == assignfeedback_editpdf\pdf::GSPATH_OK);
333         }
334         return $this->enabledcache;
335     }
336     /**
337      * Automatically hide the setting for the editpdf feedback plugin.
338      *
339      * @return bool false
340      */
341     public function is_configurable() {
342         return false;
343     }