Commit | Line | Data |
---|---|---|
5c386472 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 | * Library code for manipulating PDFs | |
19 | * | |
20 | * @package assignfeedback_editpdf | |
21 | * @copyright 2012 Davo Smith | |
22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
23 | */ | |
24 | ||
25 | namespace assignfeedback_editpdf; | |
26 | ||
27 | defined('MOODLE_INTERNAL') || die(); | |
28 | ||
29 | global $CFG; | |
30 | require_once($CFG->libdir.'/pdflib.php'); | |
31 | require_once($CFG->dirroot.'/mod/assign/feedback/editpdf/fpdi/fpdi.php'); | |
32 | ||
33 | /** | |
34 | * Library code for manipulating PDFs | |
35 | * | |
36 | * @package assignfeedback_editpdf | |
37 | * @copyright 2012 Davo Smith | |
38 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
39 | */ | |
40 | class pdf extends \FPDI { | |
41 | ||
42 | /** @var int the number of the current page in the PDF being processed */ | |
43 | protected $currentpage = 0; | |
44 | /** @var int the total number of pages in the PDF being processed */ | |
45 | protected $pagecount = 0; | |
46 | /** @var float used to scale the pixel position of annotations (in the database) to the position in the final PDF */ | |
47 | protected $scale = 0.0; | |
48 | /** @var string the path in which to store generated page images */ | |
49 | protected $imagefolder = null; | |
50 | /** @var string the path to the PDF currently being processed */ | |
51 | protected $filename = null; | |
52 | ||
53 | /** No errors */ | |
54 | const GSPATH_OK = 'ok'; | |
55 | /** Not set */ | |
56 | const GSPATH_EMPTY = 'empty'; | |
57 | /** Does not exist */ | |
58 | const GSPATH_DOESNOTEXIST = 'doesnotexist'; | |
59 | /** Is a dir */ | |
60 | const GSPATH_ISDIR = 'isdir'; | |
61 | /** Not executable */ | |
62 | const GSPATH_NOTEXECUTABLE = 'notexecutable'; | |
63 | /** Test file missing */ | |
64 | const GSPATH_NOTESTFILE = 'notestfile'; | |
65 | /** Any other error */ | |
66 | const GSPATH_ERROR = 'error'; | |
baf881b8 RT |
67 | /** Min. width an annotation should have */ |
68 | const MIN_ANNOTATION_WIDTH = 5; | |
69 | /** Min. height an annotation should have */ | |
70 | const MIN_ANNOTATION_HEIGHT = 5; | |
5c386472 DW |
71 | |
72 | /** | |
73 | * Combine the given PDF files into a single PDF. Optionally add a coversheet and coversheet fields. | |
74 | * @param string[] $pdflist the filenames of the files to combine | |
75 | * @param string $outfilename the filename to write to | |
76 | * @return int the number of pages in the combined PDF | |
77 | */ | |
78 | public function combine_pdfs($pdflist, $outfilename) { | |
79 | ||
4fe9950b | 80 | raise_memory_limit(MEMORY_EXTRA); |
ac2b4ffc | 81 | $olddebug = error_reporting(0); |
4fe9950b | 82 | |
5c386472 DW |
83 | $this->setPageUnit('pt'); |
84 | $this->setPrintHeader(false); | |
85 | $this->setPrintFooter(false); | |
86 | $this->scale = 72.0 / 100.0; | |
87 | $this->SetFont('helvetica', '', 16.0 * $this->scale); | |
88 | $this->SetTextColor(0, 0, 0); | |
89 | ||
90 | $totalpagecount = 0; | |
91 | ||
92 | foreach ($pdflist as $file) { | |
93 | $pagecount = $this->setSourceFile($file); | |
94 | $totalpagecount += $pagecount; | |
95 | for ($i = 1; $i<=$pagecount; $i++) { | |
96 | $this->create_page_from_source($i); | |
97 | } | |
98 | } | |
99 | ||
100 | $this->save_pdf($outfilename); | |
ac2b4ffc | 101 | error_reporting($olddebug); |
5c386472 DW |
102 | |
103 | return $totalpagecount; | |
104 | } | |
105 | ||
106 | /** | |
107 | * The number of the current page in the PDF being processed | |
108 | * @return int | |
109 | */ | |
110 | public function current_page() { | |
111 | return $this->currentpage; | |
112 | } | |
113 | ||
114 | /** | |
115 | * The total number of pages in the PDF being processed | |
116 | * @return int | |
117 | */ | |
118 | public function page_count() { | |
119 | return $this->pagecount; | |
120 | } | |
121 | ||
122 | /** | |
123 | * Load the specified PDF and set the initial output configuration | |
124 | * Used when processing comments and outputting a new PDF | |
125 | * @param string $filename the path to the PDF to load | |
126 | * @return int the number of pages in the PDF | |
127 | */ | |
128 | public function load_pdf($filename) { | |
4fe9950b | 129 | raise_memory_limit(MEMORY_EXTRA); |
ac2b4ffc | 130 | $olddebug = error_reporting(0); |
4fe9950b | 131 | |
5c386472 DW |
132 | $this->setPageUnit('pt'); |
133 | $this->scale = 72.0 / 100.0; | |
134 | $this->SetFont('helvetica', '', 16.0 * $this->scale); | |
135 | $this->SetFillColor(255, 255, 176); | |
136 | $this->SetDrawColor(0, 0, 0); | |
137 | $this->SetLineWidth(1.0 * $this->scale); | |
138 | $this->SetTextColor(0, 0, 0); | |
139 | $this->setPrintHeader(false); | |
140 | $this->setPrintFooter(false); | |
141 | $this->pagecount = $this->setSourceFile($filename); | |
142 | $this->filename = $filename; | |
4fe9950b | 143 | |
ac2b4ffc | 144 | error_reporting($olddebug); |
5c386472 DW |
145 | return $this->pagecount; |
146 | } | |
147 | ||
148 | /** | |
149 | * Sets the name of the PDF to process, but only loads the file if the | |
150 | * pagecount is zero (in order to count the number of pages) | |
151 | * Used when generating page images (but not a new PDF) | |
152 | * @param string $filename the path to the PDF to process | |
153 | * @param int $pagecount optional the number of pages in the PDF, if known | |
154 | * @return int the number of pages in the PDF | |
155 | */ | |
156 | public function set_pdf($filename, $pagecount = 0) { | |
157 | if ($pagecount == 0) { | |
158 | return $this->load_pdf($filename); | |
159 | } else { | |
160 | $this->filename = $filename; | |
161 | $this->pagecount = $pagecount; | |
162 | return $pagecount; | |
163 | } | |
164 | } | |
165 | ||
166 | /** | |
167 | * Copy the next page from the source file and set it as the current page | |
168 | * @return bool true if successful | |
169 | */ | |
170 | public function copy_page() { | |
171 | if (!$this->filename) { | |
172 | return false; | |
173 | } | |
174 | if ($this->currentpage>=$this->pagecount) { | |
175 | return false; | |
176 | } | |
177 | $this->currentpage++; | |
178 | $this->create_page_from_source($this->currentpage); | |
179 | return true; | |
180 | } | |
181 | ||
182 | /** | |
183 | * Create a page from a source PDF. | |
184 | * | |
185 | * @param int $pageno | |
186 | */ | |
187 | protected function create_page_from_source($pageno) { | |
188 | // Get the size (and deduce the orientation) of the next page. | |
189 | $template = $this->importPage($pageno); | |
190 | $size = $this->getTemplateSize($template); | |
191 | $orientation = 'P'; | |
192 | if ($size['w'] > $size['h']) { | |
193 | $orientation = 'L'; | |
194 | } | |
195 | // Create a page of the required size / orientation. | |
196 | $this->AddPage($orientation, array($size['w'], $size['h'])); | |
197 | // Prevent new page creation when comments are at the bottom of a page. | |
198 | $this->setPageOrientation($orientation, false, 0); | |
199 | // Fill in the page with the original contents from the student. | |
200 | $this->useTemplate($template); | |
201 | } | |
202 | ||
203 | /** | |
204 | * Copy all the remaining pages in the file | |
205 | */ | |
206 | public function copy_remaining_pages() { | |
207 | $morepages = true; | |
208 | while ($morepages) { | |
209 | $morepages = $this->copy_page(); | |
210 | } | |
211 | } | |
212 | ||
213 | /** | |
214 | * Add a comment to the current page | |
215 | * @param string $text the text of the comment | |
216 | * @param int $x the x-coordinate of the comment (in pixels) | |
217 | * @param int $y the y-coordinate of the comment (in pixels) | |
218 | * @param int $width the width of the comment (in pixels) | |
219 | * @param string $colour optional the background colour of the comment (red, yellow, green, blue, white, clear) | |
220 | * @return bool true if successful (always) | |
221 | */ | |
222 | public function add_comment($text, $x, $y, $width, $colour = 'yellow') { | |
223 | if (!$this->filename) { | |
224 | return false; | |
225 | } | |
1d38083c | 226 | $this->SetDrawColor(51, 51, 51); |
5c386472 DW |
227 | switch ($colour) { |
228 | case 'red': | |
1d38083c | 229 | $this->SetFillColor(249, 181, 179); |
5c386472 DW |
230 | break; |
231 | case 'green': | |
1d38083c | 232 | $this->SetFillColor(214, 234, 178); |
5c386472 DW |
233 | break; |
234 | case 'blue': | |
1d38083c | 235 | $this->SetFillColor(203, 217, 237); |
5c386472 DW |
236 | break; |
237 | case 'white': | |
238 | $this->SetFillColor(255, 255, 255); | |
239 | break; | |
240 | default: /* Yellow */ | |
1d38083c | 241 | $this->SetFillColor(255, 236, 174); |
5c386472 DW |
242 | break; |
243 | } | |
244 | ||
245 | $x *= $this->scale; | |
246 | $y *= $this->scale; | |
247 | $width *= $this->scale; | |
248 | $text = str_replace('<', '<', $text); | |
249 | $text = str_replace('>', '>', $text); | |
250 | // Draw the text with a border, but no background colour (using a background colour would cause the fill to | |
251 | // appear behind any existing content on the page, hence the extra filled rectangle drawn below). | |
252 | $this->MultiCell($width, 1.0, $text, 0, 'L', 0, 4, $x, $y); /* width, height, text, border, justify, fill, ln, x, y */ | |
253 | if ($colour != 'clear') { | |
254 | $newy = $this->GetY(); | |
255 | // Now we know the final size of the comment, draw a rectangle with the background colour. | |
256 | $this->Rect($x, $y, $width, $newy - $y, 'DF'); | |
257 | // Re-draw the text over the top of the background rectangle. | |
258 | $this->MultiCell($width, 1.0, $text, 0, 'L', 0, 4, $x, $y); /* width, height, text, border, justify, fill, ln, x, y */ | |
259 | } | |
260 | return true; | |
261 | } | |
262 | ||
263 | /** | |
264 | * Add an annotation to the current page | |
265 | * @param int $sx starting x-coordinate (in pixels) | |
266 | * @param int $sy starting y-coordinate (in pixels) | |
267 | * @param int $ex ending x-coordinate (in pixels) | |
268 | * @param int $ey ending y-coordinate (in pixels) | |
269 | * @param string $colour optional the colour of the annotation (red, yellow, green, blue, white, black) | |
270 | * @param string $type optional the type of annotation (line, oval, rectangle, highlight, pen, stamp) | |
271 | * @param int[]|string $path optional for 'pen' annotations this is an array of x and y coordinates for | |
272 | * the line, for 'stamp' annotations it is the name of the stamp file (without the path) | |
273 | * @param string $imagefolder - Folder containing stamp images. | |
274 | * @return bool true if successful (always) | |
275 | */ | |
276 | public function add_annotation($sx, $sy, $ex, $ey, $colour = 'yellow', $type = 'line', $path, $imagefolder) { | |
277 | global $CFG; | |
278 | if (!$this->filename) { | |
279 | return false; | |
280 | } | |
281 | switch ($colour) { | |
282 | case 'yellow': | |
1d38083c | 283 | $colourarray = array(255, 207, 53); |
5c386472 DW |
284 | break; |
285 | case 'green': | |
1d38083c | 286 | $colourarray = array(153, 202, 62); |
5c386472 DW |
287 | break; |
288 | case 'blue': | |
1d38083c | 289 | $colourarray = array(125, 159, 211); |
5c386472 DW |
290 | break; |
291 | case 'white': | |
292 | $colourarray = array(255, 255, 255); | |
293 | break; | |
294 | case 'black': | |
1d38083c | 295 | $colourarray = array(51, 51, 51); |
5c386472 DW |
296 | break; |
297 | default: /* Red */ | |
298 | $colour = 'red'; | |
1d38083c | 299 | $colourarray = array(239, 69, 64); |
5c386472 DW |
300 | break; |
301 | } | |
302 | $this->SetDrawColorArray($colourarray); | |
303 | ||
304 | $sx *= $this->scale; | |
305 | $sy *= $this->scale; | |
306 | $ex *= $this->scale; | |
307 | $ey *= $this->scale; | |
308 | ||
309 | $this->SetLineWidth(3.0 * $this->scale); | |
310 | switch ($type) { | |
311 | case 'oval': | |
312 | $rx = abs($sx - $ex) / 2; | |
313 | $ry = abs($sy - $ey) / 2; | |
314 | $sx = min($sx, $ex) + $rx; | |
315 | $sy = min($sy, $ey) + $ry; | |
baf881b8 RT |
316 | |
317 | // $rx and $ry should be >= min width and height | |
318 | if ($rx < self::MIN_ANNOTATION_WIDTH) { | |
319 | $rx = self::MIN_ANNOTATION_WIDTH; | |
320 | } | |
321 | if ($ry < self::MIN_ANNOTATION_HEIGHT) { | |
322 | $ry = self::MIN_ANNOTATION_HEIGHT; | |
323 | } | |
324 | ||
5c386472 DW |
325 | $this->Ellipse($sx, $sy, $rx, $ry); |
326 | break; | |
327 | case 'rectangle': | |
328 | $w = abs($sx - $ex); | |
329 | $h = abs($sy - $ey); | |
330 | $sx = min($sx, $ex); | |
331 | $sy = min($sy, $ey); | |
baf881b8 RT |
332 | |
333 | // Width or height should be >= min width and height | |
334 | if ($w < self::MIN_ANNOTATION_WIDTH) { | |
335 | $w = self::MIN_ANNOTATION_WIDTH; | |
336 | } | |
337 | if ($h < self::MIN_ANNOTATION_HEIGHT) { | |
338 | $h = self::MIN_ANNOTATION_HEIGHT; | |
339 | } | |
5c386472 DW |
340 | $this->Rect($sx, $sy, $w, $h); |
341 | break; | |
342 | case 'highlight': | |
343 | $w = abs($sx - $ex); | |
344 | $h = 8.0 * $this->scale; | |
345 | $sx = min($sx, $ex); | |
346 | $sy = min($sy, $ey) + ($h * 0.5); | |
347 | $this->SetAlpha(0.5, 'Normal', 0.5, 'Normal'); | |
348 | $this->SetLineWidth(8.0 * $this->scale); | |
baf881b8 RT |
349 | |
350 | // width should be >= min width | |
351 | if ($w < self::MIN_ANNOTATION_WIDTH) { | |
352 | $w = self::MIN_ANNOTATION_WIDTH; | |
353 | } | |
354 | ||
5c386472 DW |
355 | $this->Rect($sx, $sy, $w, $h); |
356 | $this->SetAlpha(1.0, 'Normal', 1.0, 'Normal'); | |
357 | break; | |
358 | case 'pen': | |
359 | if ($path) { | |
360 | $scalepath = array(); | |
361 | $points = preg_split('/[,:]/', $path); | |
362 | foreach ($points as $point) { | |
363 | $scalepath[] = intval($point) * $this->scale; | |
364 | } | |
baf881b8 RT |
365 | |
366 | if (!empty($scalepath)) { | |
367 | $this->PolyLine($scalepath, 'S'); | |
368 | } | |
5c386472 DW |
369 | } |
370 | break; | |
371 | case 'stamp': | |
372 | $imgfile = $imagefolder . '/' . clean_filename($path); | |
373 | $w = abs($sx - $ex); | |
374 | $h = abs($sy - $ey); | |
375 | $sx = min($sx, $ex); | |
376 | $sy = min($sy, $ey); | |
baf881b8 RT |
377 | |
378 | // Stamp is always more than 40px, so no need to check width/height. | |
5c386472 DW |
379 | $this->Image($imgfile, $sx, $sy, $w, $h); |
380 | break; | |
381 | default: // Line. | |
382 | $this->Line($sx, $sy, $ex, $ey); | |
383 | break; | |
384 | } | |
385 | $this->SetDrawColor(0, 0, 0); | |
386 | $this->SetLineWidth(1.0 * $this->scale); | |
387 | ||
388 | return true; | |
389 | } | |
390 | ||
391 | /** | |
392 | * Save the completed PDF to the given file | |
393 | * @param string $filename the filename for the PDF (including the full path) | |
394 | */ | |
395 | public function save_pdf($filename) { | |
ac2b4ffc | 396 | $olddebug = error_reporting(0); |
5c386472 | 397 | $this->Output($filename, 'F'); |
ac2b4ffc | 398 | error_reporting($olddebug); |
5c386472 DW |
399 | } |
400 | ||
401 | /** | |
402 | * Set the path to the folder in which to generate page image files | |
403 | * @param string $folder | |
404 | */ | |
405 | public function set_image_folder($folder) { | |
406 | $this->imagefolder = $folder; | |
407 | } | |
408 | ||
409 | /** | |
410 | * Generate an image of the specified page in the PDF | |
411 | * @param int $pageno the page to generate the image of | |
412 | * @throws moodle_exception | |
413 | * @throws coding_exception | |
414 | * @return string the filename of the generated image | |
415 | */ | |
416 | public function get_image($pageno) { | |
1bce3a70 RT |
417 | global $CFG; |
418 | ||
5c386472 DW |
419 | if (!$this->filename) { |
420 | throw new \coding_exception('Attempting to generate a page image without first setting the PDF filename'); | |
421 | } | |
422 | ||
423 | if (!$this->imagefolder) { | |
424 | throw new \coding_exception('Attempting to generate a page image without first specifying the image output folder'); | |
425 | } | |
426 | ||
427 | if (!is_dir($this->imagefolder)) { | |
428 | throw new \coding_exception('The specified image output folder is not a valid folder'); | |
429 | } | |
430 | ||
431 | $imagefile = $this->imagefolder.'/image_page' . $pageno . '.png'; | |
432 | $generate = true; | |
433 | if (file_exists($imagefile)) { | |
434 | if (filemtime($imagefile)>filemtime($this->filename)) { | |
435 | // Make sure the image is newer than the PDF file. | |
436 | $generate = false; | |
437 | } | |
438 | } | |
439 | ||
440 | if ($generate) { | |
441 | // Use ghostscript to generate an image of the specified page. | |
1bce3a70 | 442 | $gsexec = \escapeshellarg($CFG->pathtogs); |
1f738c8c DW |
443 | $imageres = \escapeshellarg(100); |
444 | $imagefilearg = \escapeshellarg($imagefile); | |
445 | $filename = \escapeshellarg($this->filename); | |
446 | $pagenoinc = \escapeshellarg($pageno + 1); | |
5c386472 | 447 | $command = "$gsexec -q -sDEVICE=png16m -dSAFER -dBATCH -dNOPAUSE -r$imageres -dFirstPage=$pagenoinc -dLastPage=$pagenoinc ". |
626d8335 | 448 | "-dDOINTERPOLATE -dGraphicsAlphaBits=4 -dTextAlphaBits=4 -sOutputFile=$imagefilearg $filename"; |
5c386472 | 449 | |
9092378d DP |
450 | $output = null; |
451 | $result = exec($command, $output); | |
5c386472 | 452 | if (!file_exists($imagefile)) { |
9092378d DP |
453 | $fullerror = '<pre>'.get_string('command', 'assignfeedback_editpdf')."\n"; |
454 | $fullerror .= $command . "\n\n"; | |
455 | $fullerror .= get_string('result', 'assignfeedback_editpdf')."\n"; | |
456 | $fullerror .= htmlspecialchars($result) . "\n\n"; | |
457 | $fullerror .= get_string('output', 'assignfeedback_editpdf')."\n"; | |
458 | $fullerror .= htmlspecialchars(implode("\n",$output)) . '</pre>'; | |
459 | throw new \moodle_exception('errorgenerateimage', 'assignfeedback_editpdf', '', $fullerror); | |
5c386472 DW |
460 | } |
461 | } | |
462 | ||
463 | return 'image_page'.$pageno.'.png'; | |
464 | } | |
465 | ||
466 | /** | |
467 | * Check to see if PDF is version 1.4 (or below); if not: use ghostscript to convert it | |
468 | * @param stored_file $file | |
469 | * @return string path to copy or converted pdf (false == fail) | |
470 | */ | |
471 | public static function ensure_pdf_compatible(\stored_file $file) { | |
1bce3a70 RT |
472 | global $CFG; |
473 | ||
5c386472 DW |
474 | $temparea = \make_temp_directory('assignfeedback_editpdf'); |
475 | $hash = $file->get_contenthash(); // Use the contenthash to make sure the temp files have unique names. | |
476 | $tempsrc = $temparea . "/src-$hash.pdf"; | |
477 | $tempdst = $temparea . "/dst-$hash.pdf"; | |
ac2b4ffc | 478 | $file->copy_content_to($tempsrc); // Copy the file. |
5c386472 | 479 | |
ac2b4ffc DW |
480 | $pdf = new pdf(); |
481 | $pagecount = 0; | |
482 | try { | |
483 | $pagecount = $pdf->load_pdf($tempsrc); | |
484 | } catch (\Exception $e) { | |
485 | // PDF was not valid - try running it through ghostscript to clean it up. | |
486 | $pagecount = 0; | |
487 | } | |
a916d557 | 488 | $pdf->Close(); // PDF loaded and never saved/outputted needs to be closed. |
ac2b4ffc DW |
489 | |
490 | if ($pagecount > 0) { | |
491 | // Page is valid and can be read by tcpdf. | |
492 | return $tempsrc; | |
5c386472 DW |
493 | } |
494 | ||
1bce3a70 | 495 | $gsexec = \escapeshellarg($CFG->pathtogs); |
1f738c8c DW |
496 | $tempdstarg = \escapeshellarg($tempdst); |
497 | $tempsrcarg = \escapeshellarg($tempsrc); | |
498 | $command = "$gsexec -q -sDEVICE=pdfwrite -dBATCH -dNOPAUSE -sOutputFile=$tempdstarg $tempsrcarg"; | |
5c386472 DW |
499 | exec($command); |
500 | @unlink($tempsrc); | |
501 | if (!file_exists($tempdst)) { | |
502 | // Something has gone wrong in the conversion. | |
503 | return false; | |
504 | } | |
505 | ||
ac2b4ffc DW |
506 | $pdf = new pdf(); |
507 | $pagecount = 0; | |
508 | try { | |
509 | $pagecount = $pdf->load_pdf($tempdst); | |
510 | } catch (\Exception $e) { | |
511 | // PDF was not valid - try running it through ghostscript to clean it up. | |
512 | $pagecount = 0; | |
513 | } | |
a916d557 EL |
514 | $pdf->Close(); // PDF loaded and never saved/outputted needs to be closed. |
515 | ||
ac2b4ffc DW |
516 | if ($pagecount <= 0) { |
517 | @unlink($tempdst); | |
518 | // Could not parse the converted pdf. | |
519 | return false; | |
520 | } | |
521 | ||
5c386472 DW |
522 | return $tempdst; |
523 | } | |
524 | ||
525 | /** | |
526 | * Test that the configured path to ghostscript is correct and working. | |
527 | * @param bool $generateimage - If true - a test image will be generated to verify the install. | |
528 | * @return bool | |
529 | */ | |
530 | public static function test_gs_path($generateimage = true) { | |
531 | global $CFG; | |
532 | ||
533 | $ret = (object)array( | |
534 | 'status' => self::GSPATH_OK, | |
535 | 'message' => null, | |
536 | ); | |
1bce3a70 | 537 | $gspath = $CFG->pathtogs; |
5c386472 DW |
538 | if (empty($gspath)) { |
539 | $ret->status = self::GSPATH_EMPTY; | |
540 | return $ret; | |
541 | } | |
542 | if (!file_exists($gspath)) { | |
543 | $ret->status = self::GSPATH_DOESNOTEXIST; | |
544 | return $ret; | |
545 | } | |
546 | if (is_dir($gspath)) { | |
547 | $ret->status = self::GSPATH_ISDIR; | |
548 | return $ret; | |
549 | } | |
550 | if (!is_executable($gspath)) { | |
551 | $ret->status = self::GSPATH_NOTEXECUTABLE; | |
552 | return $ret; | |
553 | } | |
554 | ||
9f7674bd | 555 | if (!$generateimage) { |
5c386472 DW |
556 | return $ret; |
557 | } | |
558 | ||
9f7674bd AO |
559 | $testfile = $CFG->dirroot.'/mod/assign/feedback/editpdf/tests/fixtures/testgs.pdf'; |
560 | if (!file_exists($testfile)) { | |
561 | $ret->status = self::GSPATH_NOTESTFILE; | |
5c386472 DW |
562 | return $ret; |
563 | } | |
564 | ||
565 | $testimagefolder = \make_temp_directory('assignfeedback_editpdf_test'); | |
566 | @unlink($testimagefolder.'/image_page0.png'); // Delete any previous test images. | |
567 | ||
568 | $pdf = new pdf(); | |
569 | $pdf->set_pdf($testfile); | |
570 | $pdf->set_image_folder($testimagefolder); | |
571 | try { | |
572 | $pdf->get_image(0); | |
573 | } catch (\moodle_exception $e) { | |
574 | $ret->status = self::GSPATH_ERROR; | |
575 | $ret->message = $e->getMessage(); | |
576 | } | |
a916d557 | 577 | $pdf->Close(); // PDF loaded and never saved/outputted needs to be closed. |
5c386472 DW |
578 | |
579 | return $ret; | |
580 | } | |
581 | ||
582 | /** | |
583 | * If the test image has been generated correctly - send it direct to the browser. | |
584 | */ | |
585 | public static function send_test_image() { | |
586 | global $CFG; | |
587 | header('Content-type: image/png'); | |
588 | require_once($CFG->libdir.'/filelib.php'); | |
589 | ||
590 | $testimagefolder = \make_temp_directory('assignfeedback_editpdf_test'); | |
591 | $testimage = $testimagefolder.'/image_page0.png'; | |
0c431257 | 592 | send_file($testimage, basename($testimage), 0); |
5c386472 DW |
593 | die(); |
594 | } | |
595 | ||
596 | } | |
597 |