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 private static ?string $dependency_problem = null; 28 29 private static function testDependencies() { 30 31 self::$image_support = false; 32 self::$pdf_support = false; 33 self::$no_ghostscript_support = false; 34 self::$no_imagick_pdf_readwrite = false; 35 self::$dependency_problem = null; 36 37 if (class_exists ("Imagick")) { 38 // determine file formats supported by ImageMagick 39 self::$formats = \Imagick::queryformats(); 40 41 if (count(self::$formats) > 0) { 42 self::$image_support = true; 43 if (in_array("PDF", self::$formats)) { 44 // Check if GhostScript will answer! 45 try { 46 // blank.pdf is an empty reference PDF file to test if GhostScript will react upon loading the file into ImageMagick 47 $im = new imagick(realpath("lib/plugins/mediathumbnails/blank.pdf")."[0]"); 48 $im->clear(); 49 $im->destroy(); 50 self::$pdf_support = true; 51 } catch (ImagickException $e) { 52 if (strpos($e,"PDFDelegateFailed") !== false) { 53 self::$no_ghostscript_support = true; 54 } 55 if (strpos($e,"security policy") !== false) { 56 self::$no_imagick_pdf_readwrite = true; 57 } 58 self::$pdf_support = false; 59 self::$dependency_problem = "Catched ImagickException: ".$e->getMessage(); 60 } 61 } else { 62 self::$dependency_problem = "Imagick reports it does not support PDF files."; 63 } 64 } else { 65 self::$dependency_problem = "Imagick reports it doesn't support any output formats."; 66 } 67 68 } else { 69 self::$dependency_problem = "Imagick class not found: ImageMagick PHP extension is not installed."; 70 } 71 } 72 public static function supportsPDF() { 73 if (self::$pdf_support === null) { 74 self::testDependencies(); 75 } 76 return self::$pdf_support; 77 } 78 public static function supportsImages() { 79 if (self::$image_support === null) { 80 self::testDependencies(); 81 } 82 return self::$image_support; 83 } 84 public static function ghostScriptFailed() { 85 if (self::$no_ghostscript_support === null) { 86 self::testDependencies(); 87 } 88 return self::$no_ghostscript_support; 89 } 90 public static function imagickPDFpolicyFailed() { 91 if (self::$no_imagick_pdf_readwrite === null) { 92 self::testDependencies(); 93 } 94 return self::$no_imagick_pdf_readwrite; 95 } 96 97 public function __construct(string $source_filepath, DokuWiki_Syntax_Plugin $plugin, bool $ismediapath = true) { 98 99 if ($ismediapath) { 100 $this->source_mediapath = $source_filepath; 101 $this->source_filepath = mediaFN($source_filepath); 102 } else { 103 $this->source_mediapath = false; 104 $this->source_filepath = $source_filepath; 105 } 106 107 $this->max_dimension = $plugin->getConf('thumb_max_dimension'); 108 109 // Now attach the correct thumb_engine for the file type of the source file 110 //TODO: check for extension "fileinfo", then check for MIME type: if (mime_content_type($filepath_local_file) == "application/pdf") { 111 $sourceFileSuffix = getFileSuffix($this->source_filepath); 112 if ($sourceFileSuffix == "pdf") { 113 // file suffix is pdf, so assume it's a PDF file 114 if (self::supportsPDF()) { 115 $this->thumb_engine = new thumb_pdf_engine($this); 116 } else { 117 118 $hint = self::$dependency_problem ? " Hint: '".self::$dependency_problem."'\n" : ""; 119 120 if (self::ghostScriptFailed()) { 121 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.\n".$hint."Please refer to the plugin documentation for a description of the dependencies. ".self::$dependency_problem); 122 } else if(self::imagickPDFpolicyFailed()) { 123 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.\n".$hint."Please refer to the plugin documentation for a description of the dependencies. ".self::$dependency_problem); 124 } else { 125 dbg("plugin mediathumbnails: PDF files are supported, but not on this system.\nMost likely, ImageMagick or its PHP extension imagick are not installed properly.\n".$hint."Please refer to the plugin documentation for a description of the dependencies."); 126 } 127 } 128 } else if (self::supportsImages() && in_array(strtoupper($sourceFileSuffix), self::$formats)) { 129 // file suffix is in support list of ImageMagick 130 $this->thumb_engine = new thumb_img_engine($this); 131 } else if (!self::supportsImages()) { 132 dbg("plugin mediathumbnails: Image files are supported, but not on this system.\nPlease refer to the plugin documentation for a description of the dependencies."); 133 } else { 134 // last resort: check if the source file is a ZIP file and look for thumbnails, therein 135 $this->thumb_engine = new thumb_zip_engine($this,$plugin->getConf('thumb_paths')); 136 } 137 } 138 139 public function getMaxDimension() { 140 return $this->max_dimension; 141 } 142 143 public function create() { 144 if (!$this->thumb_engine) { 145 return false; 146 } 147 148 return $this->thumb_engine->act(); 149 } 150 151 public function getSourceFilepath() { 152 return $this->source_filepath; 153 } 154 155 public function getSourceFileExists() { 156 return file_exists($this->source_filepath); 157 } 158 159 protected function getFilename() { 160 161 return basename($this->source_filepath) . ".thumb".$this->max_dimension.".".$this->thumb_engine->getFileSuffix(); 162 } 163 164 public function getFilepath() { 165 return dirname($this->source_filepath) . DIRECTORY_SEPARATOR . $this->getFilename(); 166 } 167 168 public function getMediapath() { 169 if ($this->source_mediapath !== false) { 170 return substr($this->source_mediapath,0,strrpos($this->source_mediapath,':')) . ":" . $this->getFilename(); 171 } else { 172 return false; 173 } 174 } 175 176 public function getTimestamp() { 177 return file_exists($this->getFilepath()) ? filemtime($this->getFilepath()) : false; 178 } 179}