Imgurl.php
Go to the documentation of this file.
1<?php
2
3namespace Depage\Graphics;
4
5/*
6 * @todo test to stay inside 3MP as maximum image size for safety reasons and
7 * to be able to support all iOS devices:
8 * http://www.williammalone.com/articles/html5-javascript-ios-maximum-image-size/
9 */
10
11class Imgurl
12{
13 protected $options = array();
14 protected $actions = array();
15 protected $notFound = false;
16 public $id = "";
17 public $rendered = false;
18 protected $invalidAction = false;
19 protected $cachePath = '';
20 /*
21 * action aliases
22 *
23 * Note that the order is important so shoter action names should
24 * come after larger ones
25 */
26 protected $aliases = array(
27 'quality' => "setQuality",
28 'q' => "setQuality",
29 'crop' => "addCrop",
30 'c' => "addCrop",
31 'resize' => "addResize",
32 'r' => "addResize",
33 'thumbfill' => "addThumbfill",
34 'tf' => "addThumbfill",
35 'thumb' => "addThumb",
36 't' => "addThumb",
37 'background' => "addBackground",
38 'bg' => "addBackground",
39 );
40
41 /*
42 * @param $options hold the same options as the graphics class
43 */
44 public function __construct($options = array())
45 {
46 $this->options = $options;
47 }
48
49 /*
50 * Analyzes the image url and set the path for srcImg and outImg
51 */
52 protected function analyze($url)
53 {
54 $this->invalidAction = false;
55 $this->notFound = false;
56 $this->rendered = false;
57 $this->id = "";
58 $this->actions = [];
59
60 if (isset($this->options['baseUrl']) && isset($this->options['cachePath'])) {
61 $baseUrl = rtrim($this->options['baseUrl'], '/');
62 $this->cachePath = $this->options['cachePath'];
63 $relativePath = $this->options['relPath'] ?? '';
64 } else if (defined('DEPAGE_PATH') && defined('DEPAGE_CACHE_PATH')) {
65 // we are using depage-framework so use constants for paths
66 $info = parse_url(DEPAGE_BASE);
67 $baseUrl = rtrim($info['path'], '/');
68 $relativePath = "";
69 $this->cachePath = \DEPAGE_CACHE_PATH . "graphics/";
70 } else {
71 // we using the library plainly -> get path through url
72 $scriptParts = explode("/", $_SERVER["SCRIPT_NAME"]);
73 $uriParts = explode("/", $_SERVER["REQUEST_URI"]);
74
75 if (strpos($_SERVER["SCRIPT_NAME"], "/lib/") !== false) {
76 for ($i = 0; $i < count($uriParts); $i++) {
77 // find common parts of url up to lib parameter
78 if ($uriParts[$i] == "lib") {
79 break;
80 }
81 }
82 } else {
83 for ($i = 0; $i < count($uriParts); $i++) {
84 // find common parts of url up to lib parameter
85 if ($scriptParts[$i] != $uriParts[$i]) {
86 break;
87 }
88 }
89 }
90 $baseUrl = implode("/", array_slice($uriParts, 0, $i));
91 if (isset($this->options['relPath'])) {
92 $relativePath = $this->options['relPath'];
93 } else {
94 $relativePath = str_repeat("../", count($scriptParts) - $i - 1);
95 }
96 $this->cachePath = $relativePath . "lib/cache/graphics/";
97 }
98 $baseUrlStatic = $baseUrl;
99 if (isset($this->options['baseUrlStatic'])) {
100 $baseUrlStatic = rtrim($this->options['baseUrlStatic'], '/');
101 }
102
103 // get image name
104 $imgUrl = $url;
105 if (strpos($url, $baseUrlStatic) === 0) {
106 $imgUrl = substr($url, strlen($baseUrlStatic) + 1);
107 } else if (strpos($url, $baseUrl) === 0) {
108 $imgUrl = substr($url, strlen($baseUrl) + 1);
109 }
110
111 // get action parameters
112 $success = preg_match("/(.*\.(jpg|jpeg|gif|png|webp|eps|tif|tiff|pdf|svg))\.([^\\\]*)\.(jpg|jpeg|gif|png|webp)/i", $imgUrl, $matches);
113
114 if (!$success) {
115 $this->invalidAction = true;
116
117 return;
118 }
119
120 $this->id = rawurldecode($matches[0]);
121 $this->srcImg = $relativePath . rawurldecode($matches[1]);
122 $this->outImg = $this->cachePath . rawurldecode($matches[0]);
123 $this->actions = $this->analyzeActions($matches[3]);
124 }
125 /*
126 * Analyzes actions and replaces shortcuts with real actions
127 */
128 protected function analyzeActions($actionString)
129 {
130 $actions = explode(".", $actionString);
131
132 foreach ($actions as &$action) {
133 $regex = implode("|", array_keys($this->aliases));
134 preg_match("/^($regex)/i", $action, $matches);
135
136 if (isset($matches[1]) && isset($this->aliases[$matches[1]])) {
137 $func = $this->aliases[$matches[1]];
138 $params = substr($action, strlen($matches[1]));
139 } else {
140 $func = "";
141 $params = "";
142 }
143
144 if (!empty($func)) {
145 $params = preg_split("/[-x,]+/", $params, null, PREG_SPLIT_NO_EMPTY);
146
147 if ($func == "addBackground") {
148 if (!in_array($params[0], array("transparent", "checkerboard"))) {
149 $params[0] = "#{$params[0]}";
150 }
151 } else {
152 foreach ($params as $i => &$p) {
153 $p = intval($p);
154 if ($p == 0 && $i < 2) {
155 $p = null;
156 }
157 }
158 }
159
160 $this->actions[] = array($func, $params);
161 } else {
162 $this->invalidAction = true;
163 }
164 }
165
166 return $this->actions;
167 }
168 public function render($url = null)
169 {
170 if (is_null($url)) {
171 $url = $_SERVER["REQUEST_URI"];
172 }
173 $this->analyze($url);
174
175 if ($this->invalidAction) {
176 return $this;
177 }
178 // make cache diretories
179 $outDir = dirname($this->outImg);
180 if (!is_dir($outDir)) {
181 mkdir($outDir, 0755, true);
182 }
183 if (file_exists($this->outImg) && filemtime($this->outImg) >= filemtime($this->srcImg)) {
184 // rendered image does exist already
185 return $this;
186 }
187
188 try {
189 $graphics = Graphics::factory($this->options);
190
191 // add actions to graphics class
192 foreach ($this->actions as $action) {
193 list($func, $params) = $action;
194 if (is_callable(array($graphics, $func))) {
195 call_user_func_array(array($graphics, $func), $params);
196 }
197 }
198
199 // render image out
200 $graphics->render($this->srcImg, $this->outImg);
201
202 $this->rendered = true;
203 } catch (Exceptions\FileNotFound $e) {
204 $this->notFound = true;
205 return $this;
206 } catch (Exceptions\Exception $e) {
207 $this->invalidAction = true;
208 }
209
210 return $this;
211 }
212
213 public function display()
214 {
215 $info = pathinfo($this->outImg);
216 $ext = strtolower($info['extension']);
217
218 if ($this->invalidAction) {
219 header("HTTP/1.1 500 Internal Server Error");
220 echo("invalid image action");
221 die();
222 }
223 if ($this->notFound) {
224 header("HTTP/1.1 404 Not Found");
225 echo("file not found");
226 die();
227 }
228
229 if ($ext == "jpg" || $ext == "jpeg") {
230 header("Content-type: image/jpeg");
231 } elseif ($ext == "png") {
232 header("Content-type: image/png");
233 } elseif ($ext == "gif") {
234 header("Content-type: image/gif");
235 } elseif ($ext == "webp") {
236 header("Content-type: image/webp");
237 }
238 readfile($this->outImg);
239
240 return $this;
241 }
242
243 public function getUrl($img)
244 {
245 $info = pathinfo($img);
246 $ext = $info['extension'];
247
248 if (count($this->actions) > 0) {
249 return $img . "." . implode(".", $this->actions) . "." . $ext;
250 } else {
251 return $img;
252 }
253 }
254
255 public function addBackground($background)
256 {
257 $this->actions[] = "bg{$background}";
258
259 return $this;
260 }
261 public function addCrop($width, $height, $x = 0, $y = 0)
262 {
263 $this->actions[] = "crop{$width}x{$height}-{$x}x{$y}";
264
265 return $this;
266 }
267 public function addResize($width, $height)
268 {
269 $this->actions[] = "r{$width}x{$height}";
270
271 return $this;
272 }
273 public function addThumb($width, $height)
274 {
275 $this->actions[] = "t{$width}x{$height}";
276
277 return $this;
278 }
279 public function addThumbfill($width, $height, $centerX = 50, $centerY = 50)
280 {
281 $action = "tf{$width}x{$height}";
282 if ($centerX != 50 || $centerY != 50) {
283 $action .= "-{$centerX}x{$centerY}";
284 }
285
286 $this->actions[] = $action;
287
288 return $this;
289 }
290 public function setQuality($quality)
291 {
292 $this->actions[] = "q{$quality}";
293
294 return $this;
295 }
296}
297/* vim:set ft=php sw=4 sts=4 fdm=marker et : */
static factory($options=array())
graphics object factory
Definition: Graphics.php:115
addThumbfill($width, $height, $centerX=50, $centerY=50)
Definition: Imgurl.php:279
addThumb($width, $height)
Definition: Imgurl.php:273
__construct($options=array())
Definition: Imgurl.php:44
addCrop($width, $height, $x=0, $y=0)
Definition: Imgurl.php:261
setQuality($quality)
Definition: Imgurl.php:290
analyzeActions($actionString)
Definition: Imgurl.php:128
render($url=null)
Definition: Imgurl.php:168
addBackground($background)
Definition: Imgurl.php:255
addResize($width, $height)
Definition: Imgurl.php:267