1<?php
2/**
3 * DokuWiki Plugin mediathumbnails (thumb_engine class and subclasses)
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
9abstract class thumb_engine {
10
11	private ?thumbnail $thumbnail = null;
12
13	public function __construct(thumbnail $thumbnail) {
14		$this->thumbnail = $thumbnail;
15	}
16
17	protected function getSourceFilepath() {
18		return $this->thumbnail->getSourceFilepath();
19	}
20
21	protected function getTargetFilepath() {
22		return $this->thumbnail->getFilepath();
23	}
24
25	protected function getTargetMaxDimension() {
26		return $this->thumbnail->getMaxDimension();
27	}
28
29	public function act() {
30		if ($this->act_internal()) {
31			// Set timestamp to the source file's timestamp (this is used to check in later passes if the file already exists in the correct version).
32			if (filemtime($this->getSourceFilepath()) !== filemtime($this->getTargetFilepath())) {
33				touch($this->getTargetFilepath(), filemtime($this->getSourceFilepath()));
34			}
35			return true;
36		}
37		return false;
38	}
39
40	// Checks if a thumbnail file for the current file version has already been created
41	protected function thumb_needs_update() {
42		return !file_exists($this->getTargetFilepath()) || filemtime($this->getTargetFilepath()) !== filemtime($this->getSourceFilepath());
43	}
44
45	public abstract function act_internal();
46
47	public abstract function getFileSuffix();
48}
49
50class thumb_pdf_engine extends thumb_engine {
51
52	public function getFileSuffix() {
53		return "jpg";
54	}
55
56	public function act_internal() {
57		if ($this->thumb_needs_update()) {
58			$im = new imagick($this->getSourceFilepath()."[0]");
59			$im->setImageColorspace(255);
60			$im->setResolution(300, 300);
61			$im->setCompressionQuality(95);
62			$im->setImageFormat('jpeg');
63			//$im->resizeImage($this->getTargetMaxDimension(),0,imagick::FILTER_LANCZOS,0.9);
64			//$im->thumbnailImage($this->getTargetMaxDimension(),$this->getTargetMaxDimension(),true,false);
65			$im->writeImage($this->getTargetFilepath());
66			$im->clear();
67			$im->destroy();
68
69			// unfortunately, resizeImage or thumbnailImage leads to a black thumbnail in my setup, so I reopen the file and resize it now.
70			$im = new imagick($this->getTargetFilepath());
71			$im->thumbnailImage($this->getTargetMaxDimension(),$this->getTargetMaxDimension(),true,false);
72			$im->writeImage($this->getTargetFilepath());
73			$im->clear();
74			$im->destroy();
75
76			return true;
77		} else {
78			return true;
79		}
80	}
81}
82
83class thumb_img_engine extends thumb_engine {
84
85	public function getFileSuffix() {
86		return getFileSuffix($this->getSourceFilepath());
87	}
88
89	public function act_internal() {
90		if ($this->thumb_needs_update()) {
91			$im = new imagick( $this->getSourceFilepath() );
92			$im->thumbnailImage($this->getTargetMaxDimension(),$this->getTargetMaxDimension(),true,false);
93			$im->writeImage($this->getTargetFilepath());
94			$im->clear();
95			$im->destroy();
96
97			return true;
98		} else {
99			return true;
100		}
101	}
102}
103
104class thumb_zip_engine extends thumb_engine {
105
106	private array $thumb_paths;
107	private $file_suffix = "";
108
109	public function __construct(thumbnail $thumbnail, array $thumb_paths) {
110		parent::__construct($thumbnail);
111		$this->thumb_paths = $thumb_paths;
112	}
113
114	public function getFileSuffix() {
115		return $this->file_suffix;
116	}
117
118	public function act_internal() {
119
120		$zip = new ZipArchive;
121		if ($zip->open($this->getSourceFilepath()) !== true) {
122			// file is no zip or cannot be opened
123			return false;
124		}
125
126		// The media file exists and acts as a zip file!
127
128		// Check all possible paths (configured in configuration key 'thumb_paths') if there is a file available
129		foreach($this->thumb_paths as $thumbnail_path) {
130			$this->file_suffix = substr(strrchr($thumbnail_path,'.'),1);
131
132			if ($zip->locateName($thumbnail_path) !== false) {
133
134				if (!$this->thumb_needs_update()) {
135					return true;
136				}
137
138				// Get the thumbnail file!
139				$fp = $zip->getStream($thumbnail_path);
140				if(!$fp) {
141					return false;
142				}
143
144				$thumbnaildata = '';
145				while (!feof($fp)) {
146					$thumbnaildata .= fread($fp, 8192);
147				}
148
149				fclose($fp);
150
151				// Write thumbnail file to media folder
152				file_put_contents($this->getTargetFilepath(), $thumbnaildata);
153
154				return true;
155			}
156		}
157
158		return true;
159	}
160}