Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
95.12% |
39 / 41 |
|
71.43% |
5 / 7 |
CRAP | |
0.00% |
0 / 1 |
ImageLoader | |
95.12% |
39 / 41 |
|
71.43% |
5 / 7 |
19 | |
0.00% |
0 / 1 |
setThemeInfo | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getImage | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
getContentType | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
searchTheme | |
85.71% |
6 / 7 |
|
0.00% |
0 / 1 |
4.05 | |||
loadUnavailable | |
93.33% |
14 / 15 |
|
0.00% |
0 / 1 |
6.01 | |||
loadDefaultFailImage | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
2 | |||
getContentTypeFromExtension | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
2 |
1 | <?php |
2 | |
3 | /** |
4 | * Base class for loading images (shared by Cover\Loader and QRCode\Loader) |
5 | * |
6 | * PHP version 8 |
7 | * |
8 | * Copyright (C) Villanova University 2007. |
9 | * |
10 | * This program is free software; you can redistribute it and/or modify |
11 | * it under the terms of the GNU General Public License version 2, |
12 | * as published by the Free Software Foundation. |
13 | * |
14 | * This program is distributed in the hope that it will be useful, |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | * GNU General Public License for more details. |
18 | * |
19 | * You should have received a copy of the GNU General Public License |
20 | * along with this program; if not, write to the Free Software |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
22 | * |
23 | * @category VuFind |
24 | * @package Cover_Generator |
25 | * @author Andrew S. Nagy <vufind-tech@lists.sourceforge.net> |
26 | * @author Demian Katz <demian.katz@villanova.edu> |
27 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License |
28 | * @link https://vufind.org/wiki/configuration:external_content Wiki |
29 | */ |
30 | |
31 | namespace VuFind; |
32 | |
33 | use function array_key_exists; |
34 | |
35 | /** |
36 | * Base class for loading images (shared by Cover\Loader and QRCode\Loader) |
37 | * |
38 | * @category VuFind |
39 | * @package Cover_Generator |
40 | * @author Andrew S. Nagy <vufind-tech@lists.sourceforge.net> |
41 | * @author Demian Katz <demian.katz@villanova.edu> |
42 | * @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License |
43 | * @link https://vufind.org/wiki/configuration:external_content Wiki |
44 | */ |
45 | class ImageLoader implements \Laminas\Log\LoggerAwareInterface |
46 | { |
47 | use \VuFind\Log\LoggerAwareTrait; |
48 | |
49 | /** |
50 | * Property for storing raw image data; may be null if image is unavailable |
51 | * |
52 | * @var string |
53 | */ |
54 | protected $image = null; |
55 | |
56 | /** |
57 | * Content type of data in $image property |
58 | * |
59 | * @var string |
60 | */ |
61 | protected $contentType = null; |
62 | |
63 | /** |
64 | * Theme tools |
65 | * |
66 | * @var \VuFindTheme\ThemeInfo |
67 | */ |
68 | protected $themeTools = null; |
69 | |
70 | /** |
71 | * User-configured image to load from theme on error. |
72 | * |
73 | * @var string |
74 | */ |
75 | protected $configuredFailImage = null; |
76 | |
77 | /** |
78 | * Default image to load from theme if user-configured option fails. |
79 | * |
80 | * @var string |
81 | */ |
82 | protected $defaultFailImage = 'images/noCover2.gif'; |
83 | |
84 | /** |
85 | * Array containing map of allowed file extensions to mimetypes |
86 | * (to be extended) |
87 | * |
88 | * @var array |
89 | */ |
90 | protected $allowedFileExtensions = [ |
91 | 'gif' => 'image/gif', |
92 | 'jpeg' => 'image/jpeg', 'jpg' => 'image/jpeg', |
93 | 'png' => 'image/png', |
94 | 'tiff' => 'image/tiff', 'tif' => 'image/tiff', |
95 | ]; |
96 | |
97 | /** |
98 | * Setter for dependency |
99 | * |
100 | * @param \VuFindTheme\ThemeInfo $theme VuFind theme tools |
101 | * |
102 | * @return void |
103 | */ |
104 | public function setThemeInfo(\VuFindTheme\ThemeInfo $theme) |
105 | { |
106 | $this->themeTools = $theme; |
107 | } |
108 | |
109 | /** |
110 | * Get the image data (not meant to be called until after image is populated) |
111 | * |
112 | * @return string |
113 | */ |
114 | public function getImage() |
115 | { |
116 | // No image loaded? Use "unavailable" as default: |
117 | if (null === $this->image) { |
118 | $this->loadUnavailable(); |
119 | } |
120 | return $this->image; |
121 | } |
122 | |
123 | /** |
124 | * Get the content type of the current image (not meant to be called until after |
125 | * contentType is populated) |
126 | * |
127 | * @return string |
128 | */ |
129 | public function getContentType() |
130 | { |
131 | // No content type loaded? Use "unavailable" as default: |
132 | if (null === $this->contentType) { |
133 | $this->loadUnavailable(); |
134 | } |
135 | return $this->contentType; |
136 | } |
137 | |
138 | /** |
139 | * Find a file in the themes (return false if no file exists). |
140 | * |
141 | * @param string $path Relative path of file to find. |
142 | * @param array $formats Optional array of suffixes to add to $path while |
143 | * searching theme (used to check multiple extensions in each theme). |
144 | * |
145 | * @return string|bool |
146 | */ |
147 | protected function searchTheme($path, $formats = ['']) |
148 | { |
149 | // Check all supported image formats: |
150 | $filenames = []; |
151 | foreach ($formats as $format) { |
152 | $filenames[] = $path . $format; |
153 | } |
154 | if (null === $this->themeTools) { |
155 | throw new \Exception('\VuFindTheme\ThemeInfo object missing'); |
156 | } |
157 | $fileMatch = $this->themeTools->findContainingTheme($filenames, true); |
158 | return empty($fileMatch) ? false : $fileMatch; |
159 | } |
160 | |
161 | /** |
162 | * Load the user-specified "cover unavailable" graphic (or default if none |
163 | * specified). |
164 | * |
165 | * @return void |
166 | * @author Thomas Schwaerzler <vufind-tech@lists.sourceforge.net> |
167 | */ |
168 | public function loadUnavailable() |
169 | { |
170 | // No setting -- use default, and don't log anything: |
171 | if (empty($this->configuredFailImage)) { |
172 | $this->loadDefaultFailImage(); |
173 | return; |
174 | } |
175 | |
176 | // Setting found -- get "no cover" image from config.ini: |
177 | $noCoverImage = $this->searchTheme($this->configuredFailImage); |
178 | |
179 | // If file is blank/inaccessible, log error and display default: |
180 | if ( |
181 | empty($noCoverImage) || !file_exists($noCoverImage) |
182 | || !is_readable($noCoverImage) |
183 | ) { |
184 | $this->debug("Cannot access '{$this->configuredFailImage}'"); |
185 | $this->loadDefaultFailImage(); |
186 | return; |
187 | } |
188 | |
189 | try { |
190 | // Get mime type from file extension: |
191 | $this->contentType = $this->getContentTypeFromExtension($noCoverImage); |
192 | } catch (\Exception $e) { |
193 | // Log error and bail out if file lacks a known image extension: |
194 | $this->debug($e->getMessage()); |
195 | $this->loadDefaultFailImage(); |
196 | return; |
197 | } |
198 | |
199 | // Load the image data: |
200 | $this->image = file_get_contents($noCoverImage); |
201 | } |
202 | |
203 | /** |
204 | * Display the default "cover unavailable" graphic. |
205 | * |
206 | * @return void |
207 | */ |
208 | protected function loadDefaultFailImage() |
209 | { |
210 | $file = $this->searchTheme($this->defaultFailImage); |
211 | if (!file_exists($file)) { |
212 | throw new \Exception('Could not load default fail image.'); |
213 | } |
214 | $this->contentType = $this->getContentTypeFromExtension($file); |
215 | $this->image = file_get_contents($file); |
216 | } |
217 | |
218 | /** |
219 | * Get the content-type for a file based on extension. Throw an exception if |
220 | * an illegal extension is provided. |
221 | * |
222 | * @param string $filename Filename to analyze. |
223 | * |
224 | * @return string |
225 | * @throws \Exception |
226 | */ |
227 | protected function getContentTypeFromExtension($filename) |
228 | { |
229 | $parts = explode('.', $filename); |
230 | $fileExtension = strtolower(end($parts)); |
231 | if (!array_key_exists($fileExtension, $this->allowedFileExtensions)) { |
232 | throw new \Exception( |
233 | "Illegal file-extension '$fileExtension' for image '$filename'" |
234 | ); |
235 | } |
236 | |
237 | // Get mime type from file extension: |
238 | return $this->allowedFileExtensions[$fileExtension]; |
239 | } |
240 | } |