1<?php
2/**
3 * DokuWiki Plugin mediathumbnails (thumbnail class)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Thomas Schäfer <thomas.schaefer@itschert.net>
7 */
8
9require('thumb_engines.php');
10
11function getFileSuffix(string $file) {
12	return substr(strrchr($file,'.'),1);
13}
14
15class thumbnail {
16
17	private $source_filepath;
18	private $source_mediapath;
19	private ?thumb_engine $thumb_engine = null;
20	private int $max_dimension;
21
22	private static $formats;
23	private static ?bool $pdf_support = null;
24	private static ?bool $image_support = null;
25	private static ?bool $no_ghostscript_support = null;
26	private static ?bool $no_imagick_pdf_readwrite = null;
27
28	private static function testDependencies() {
29
30		self::$image_support = false;
31		self::$pdf_support = false;
32		self::$no_ghostscript_support = false;
33		self::$no_imagick_pdf_readwrite = false;
34
35		if (class_exists ("Imagick")) {
36			// determine file formats supported by ImageMagick
37			self::$formats = \Imagick::queryformats();
38
39			if (count(self::$formats) > 0) {
40				self::$image_support = true;
41				if (in_array("PDF", self::$formats)) {
42					// Check if GhostScript will answer!
43					try {
44						// blank.pdf is an empty reference PDF file to test if GhostScript will react upon loading the file into ImageMagick
45						$im = new imagick(realpath("lib/plugins/mediathumbnails/blank.pdf")."[0]");
46						$im->clear();
47						$im->destroy();
48						self::$pdf_support = true;
49					} catch (ImagickException $e) {
50						if (strpos($e,"PDFDelegateFailed") !== false) {
51							self::$no_ghostscript_support = true;
52						}
53						if (strpos($e,"security policy") !== false) {
54							self::$no_imagick_pdf_readwrite = true;
55						}
56						self::$pdf_support = false;
57					}
58
59				}
60			}
61
62		}
63	}
64	public static function supportsPDF() {
65		if (self::$pdf_support === null) {
66			self::testDependencies();
67		}
68		return self::$pdf_support;
69	}
70	public static function supportsImages() {
71		if (self::$image_support === null) {
72			self::testDependencies();
73		}
74		return self::$image_support;
75	}
76	public static function ghostScriptFailed() {
77		if (self::$no_ghostscript_support === null) {
78			self::testDependencies();
79		}
80		return self::$no_ghostscript_support;
81	}
82	public static function imagickPDFpolicyFailed() {
83		if (self::$no_imagick_pdf_readwrite === null) {
84			self::testDependencies();
85		}
86		return self::$no_imagick_pdf_readwrite;
87	}
88
89	public function __construct(string $source_filepath, DokuWiki_Syntax_Plugin $plugin, bool $ismediapath = true) {
90
91		if ($ismediapath) {
92			$this->source_mediapath = $source_filepath;
93			$this->source_filepath = mediaFN($source_filepath);
94		} else {
95			$this->source_mediapath = false;
96			$this->source_filepath = $source_filepath;
97		}
98
99		$this->max_dimension = $plugin->getConf('thumb_max_dimension');
100
101		// Now attach the correct thumb_engine for the file type of the source file
102		//TODO: check for extension "fileinfo", then check for MIME type: if (mime_content_type($filepath_local_file) == "application/pdf") {
103		$sourceFileSuffix = getFileSuffix($this->source_filepath);
104		if ($sourceFileSuffix == "pdf") {
105			// file suffix is pdf, so assume it's a PDF file
106			if (self::supportsPDF()) {
107				$this->thumb_engine = new thumb_pdf_engine($this);
108			} else {
109				if (self::ghostScriptFailed()) {
110					dbg("plugin mediathumbnails: PDF files are supported, but not on this system.\nMost likely, ImageMagick and its PHP extension imagick are installed properly, but GhostScript is not.\nPlease refer to the plugin documentation for a description of the dependencies.");
111				} else if(self::imagickPDFpolicyFailed()) {
112					dbg("plugin mediathumbnails: PDF files are supported, but not on this system.\nMost likely, ImageMagick is configured so that PDF conversion is not allowed due to security policies.\nPlease refer to the plugin documentation for a description of the dependencies.");
113				} else {
114					dbg("plugin mediathumbnails: PDF files are supported, but not on this system.\nMost likely, ImageMagick or its PHP extension imagick are not installed properly.\nPlease refer to the plugin documentation for a description of the dependencies.");
115				}
116			}
117		} else if (self::supportsImages() && in_array(strtoupper($sourceFileSuffix), self::$formats)) {
118			// file suffix is in support list of ImageMagick
119			$this->thumb_engine = new thumb_img_engine($this);
120		} else if (!self::supportsImages()) {
121			dbg("plugin mediathumbnails: Image files are supported, but not on this system.\nPlease refer to the plugin documentation for a description of the dependencies.");
122		} else {
123			// last resort: check if the source file is a ZIP file and look for thumbnails, therein
124			$this->thumb_engine = new thumb_zip_engine($this,$plugin->getConf('thumb_paths'));
125		}
126	}
127
128	public function getMaxDimension() {
129		return $this->max_dimension;
130	}
131
132	public function create() {
133		if (!$this->thumb_engine) {
134			return false;
135		}
136
137		return $this->thumb_engine->act();
138	}
139
140	public function getSourceFilepath() {
141		return $this->source_filepath;
142	}
143
144	protected function getFilename() {
145
146		return basename($this->source_filepath) . ".thumb".$this->max_dimension.".".$this->thumb_engine->getFileSuffix();
147	}
148
149	public function getFilepath() {
150		return dirname($this->source_filepath) . DIRECTORY_SEPARATOR . $this->getFilename();
151	}
152
153	public function getMediapath() {
154		if ($this->source_mediapath !== false) {
155			return substr($this->source_mediapath,0,strrpos($this->source_mediapath,':')) . ":" . $this->getFilename();
156		} else {
157			return false;
158		}
159	}
160
161	public function getTimestamp() {
162		return file_exists($this->getFilepath()) ? filemtime($this->getFilepath()) : false;
163	}
164}