Completed
Push — master ( 7de195...5f1ca1 )
by Henry
08:39
created

modules/Gallery/Gallery.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
namespace Redaxscript\Modules\Gallery;
3
4
use Redaxscript\Filesystem;
5
use Redaxscript\Head;
6
use Redaxscript\Html;
7
use Redaxscript\Module;
8
use function array_key_exists;
9
use function array_reverse;
10
use function chmod;
11
use function file_exists;
12
use function getimagesize;
13
use function imagecopyresampled;
14
use function imagecreatefromgif;
15
use function imagecreatefromjpeg;
16
use function imagecreatefrompng;
17
use function imagecreatetruecolor;
18
use function imagedestroy;
19
use function imagejpeg;
20
use function is_array;
21
use function is_dir;
22
use function pathinfo;
23
use function round;
24
use function strtolower;
25
26
/**
27
 * responsive image gallery
28
 *
29
 * @since 3.0.0
30
 *
31
 * @package Redaxscript
32
 * @category Modules
33
 * @author Henry Ruhs
34
 */
35
36
class Gallery extends Module\Metadata
37
{
38
	/**
39
	 * array of the module
40
	 *
41
	 * @var array
42
	 */
43
44
	protected static $_moduleArray =
45
	[
46
		'name' => 'Gallery',
47
		'alias' => 'Gallery',
48
		'author' => 'Redaxmedia',
49
		'description' => 'Responsive image gallery',
50
		'version' => '4.5.0',
51
		'license' => 'Sponsor'
52
	];
53
54
	/**
55
	 * array of the option
56
	 *
57
	 * @var array
58
	 */
59
60
	protected $_optionArray =
61
	[
62
		'className' =>
63
		[
64
			'image' => 'rs-image-gallery',
65
			'list' => 'rs-js-gallery rs-list-gallery'
66
		],
67
		'allowedCommands' =>
68
		[
69
			'create',
70
			'remove'
71
		],
72
		'height' => 200,
73
		'quality' => 80,
74
		'thumbDirectory' => 'thumbs'
75
	];
76
77
	/**
78
	 * adminNotification
79
	 *
80
	 * @since 3.0.0
81
	 *
82
	 * @return array
83
	 */
84
85
	public function adminNotification() : array
86
	{
87
		return $this->getNotificationArray();
88
	}
89
90
	/**
91
	 * renderStart
92
	 *
93
	 * @since 3.0.0
94
	 */
95
96
	public function renderStart() : void
97
	{
98
		$this->_registry->set('noPageCache', true);
99
100
		/* link */
101
102
		$link = Head\Link::getInstance();
103
		$link
104
			->init()
105
			->appendFile(
106
			[
107
				'https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.min.css',
108
				'https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/default-skin/default-skin.min.css',
109
				'modules/Gallery/dist/styles/gallery.min.css'
110
			]);
111
112
		/* script */
113
114
		$script = Head\Script::getInstance();
115
		$script
116
			->init('foot')
117
			->appendFile(
118
			[
119
				'https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.min.js',
120
				'https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe-ui-default.min.js',
121
				'modules/Gallery/assets/scripts/init.js',
122
				'modules/Gallery/dist/scripts/gallery.min.js'
123
			]);
124
	}
125
126
	/**
127
	 * render
128
	 *
129
	 * @since 3.0.0
130
	 *
131
	 * @param string $directory
132
	 * @param array $optionArray
133
	 *
134
	 * @return string|null
135
	 */
136
137
	public function render(string $directory = null, array $optionArray = []) : ?string
138
	{
139
		$output = null;
140
		$outputItem = null;
141
142
		/* html element */
143
144
		$listElement = new Html\Element();
145
		$listElement->init('ul',
146
		[
147
			'class' => $this->_optionArray['className']['list']
148
		]);
149
150
		/* handle notification */
151
152
		if (!is_dir($directory))
153
		{
154
			$this->setNotification('error', $this->_language->get('directory_not_found') . $this->_language->get('colon') . ' ' . $directory . $this->_language->get('point'));
155
		}
156
157
		/* else collect item */
158
159
		else
160
		{
161
			/* remove as needed */
162
163
			if ($optionArray['command'] === 'remove')
164
			{
165
				$this->_removeThumb($directory);
166
			}
167
168
			/* create as needed */
169
170
			if ($optionArray['command'] === 'create' || !is_dir($directory . DIRECTORY_SEPARATOR . $this->_optionArray['thumbDirectory']))
171
			{
172
				$this->_createThumb($directory, $optionArray);
173
			}
174
			$outputItem .= $this->_renderItem($directory, $optionArray);
175
176
			/* collect list output */
177
178
			if ($outputItem)
179
			{
180
				$output = $listElement->html($outputItem);
181
			}
182
183
			/* include template */
184
185
			include_once('modules/Gallery/templates/gallery.phtml');
186
		}
187
		return $output;
188
	}
189
190
	/**
191
	 * renderItem
192
	 *
193
	 * @since 2.6.0
194
	 *
195
	 * @param string $directory
196
	 * @param array $optionArray
197
	 *
198
	 * @return string|null
199
	 */
200
201
	protected function _renderItem(string $directory = null, array $optionArray = []) : ?string
202
	{
203
		$outputItem = null;
204
		$itemCounter = 0;
205
206
		/* html element */
207
208
		$element = new Html\Element();
209
		$itemElement = $element->copy()->init('li');
210
		$linkElement = $element->copy()->init('a');
211
		$imageElement = $element
212
			->copy()
213
			->init('img',
214
			[
215
				'class' => $this->_optionArray['className']['image'],
216
				'loading' => 'lazy'
217
			]);
218
219
		/* gallery filesystem */
220
221
		$galleryFilesystem = new Filesystem\Filesystem();
222
		$galleryFilesystem->init($directory, false,
223
		[
224
			$this->_optionArray['thumbDirectory']
225
		]);
226
		$galleryFilesystemArray = $galleryFilesystem->getSortArray();
227
228
		/* adjust order */
229
230
		if ($optionArray['order'] === 'desc')
231
		{
232
			$galleryFilesystemArray = array_reverse($galleryFilesystemArray);
233
		}
234
235
		/* process filesystem */
236
237
		foreach ($galleryFilesystemArray as $value)
238
		{
239
			$imagePath = $directory . DIRECTORY_SEPARATOR . $value;
240
			$thumbPath = $directory . DIRECTORY_SEPARATOR . $this->_optionArray['thumbDirectory'] . DIRECTORY_SEPARATOR . $value;
241
			$imageSize = getimagesize($imagePath);
242
243
			/* collect item output */
244
245
			$outputItem .= file_exists($thumbPath) ? $itemElement
246
				->clear()
247
				->html(
248
					$linkElement
249
						->copy()
250
						->attr(
251
						[
252
							'href' => $imagePath,
253
							'data-index' => $itemCounter++,
254
							'data-height' => $imageSize[1],
255
							'data-width' => $imageSize[0]
256
						])
257
						->html(
258
							$imageElement
259
								->copy()
260
								->attr(
261
								[
262
									'src' => $thumbPath,
263
									'alt' => $value
264
								])
265
						)
266
				) : null;
267
		}
268
		return $outputItem;
269
	}
270
271
	/**
272
	 * removeThumb
273
	 *
274
	 * @since 3.0.0
275
	 *
276
	 * @param string $directory
277
	 */
278
279
	protected function _removeThumb(string $directory = null) : void
280
	{
281
		$galleryFilesystem = new Filesystem\Directory();
282
		$galleryFilesystem->init($directory, true);
283
		$galleryFilesystem->removeDirectory($this->_optionArray['thumbDirectory']);
284
	}
285
286
	/**
287
	 * createThumb
288
	 *
289
	 * @since 3.0.0
290
	 *
291
	 * @param string $directory
292
	 * @param array $optionArray
293
	 */
294
295
	protected function _createThumb(string $directory = null, array $optionArray = []) : void
296
	{
297
		/* gallery filesystem */
298
299
		$galleryFilesystem = new Filesystem\Directory();
300
		$galleryFilesystem->init($directory, false,
301
		[
302
			$this->_optionArray['thumbDirectory']
303
		]);
304
		$galleryFilesystem->createDirectory($this->_optionArray['thumbDirectory']);
305
		$galleryFilesystemArray = $galleryFilesystem->getSortArray();
306
307
		/* handle notification */
308
309
		if (!chmod($directory . DIRECTORY_SEPARATOR . $this->_optionArray['thumbDirectory'], 0777))
310
		{
311
			$this->setNotification('error', $this->_language->get('directory_permission_grant') . $this->_language->get('colon') . ' ' . $directory . DIRECTORY_SEPARATOR . $this->_optionArray['thumbDirectory'] . $this->_language->get('point'));
312
		}
313
314
		/* else process filesystem */
315
316
		else
317
		{
318
			foreach ($galleryFilesystemArray as $value)
319
			{
320
				$imagePath = $directory . DIRECTORY_SEPARATOR . $value;
321
				$imageExtension = strtolower(pathinfo($value, PATHINFO_EXTENSION));
322
				$thumbPath = $directory . DIRECTORY_SEPARATOR . $this->_optionArray['thumbDirectory'] . DIRECTORY_SEPARATOR . $value;
323
				$image = null;
324
325
				/* handle extension */
326
327
				if ($imageExtension === 'gif')
328
				{
329
					$image = imagecreatefromgif($imagePath);
330
				}
331
				if ($imageExtension === 'jpg')
332
				{
333
					$image = imagecreatefromjpeg($imagePath);
334
				}
335
				if ($imageExtension === 'png')
336
				{
337
					$image = imagecreatefrompng($imagePath);
338
				}
339
340
				/* source and dist */
341
342
				$sourceArray = $this->_calcSource($imagePath);
343
				$distArray = $this->_calcDist($sourceArray, $optionArray);
344
345
				/* create thumb files */
346
347
				$thumb = imagecreatetruecolor($distArray['width'], $distArray['height']);
348
				imagecopyresampled($thumb, $image, 0, 0, 0, 0, $distArray['width'], $distArray['height'], $sourceArray['width'], $sourceArray['height']);
349
				imagejpeg($thumb, $thumbPath, $distArray['quality']);
350
351
				/* destroy image */
352
353
				imagedestroy($thumb);
354
				imagedestroy($image);
355
			}
356
		}
357
	}
358
359
	/**
360
	 * calcSource
361
	 *
362
	 * @param string $imagePath
363
	 *
364
	 * @return array
365
	 */
366
367
	protected function _calcSource(string $imagePath = null) : array
368
	{
369
		$sourceArray['size'] = getimagesize($imagePath);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$sourceArray was never initialized. Although not strictly required by PHP, it is generally a good practice to add $sourceArray = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
370
		$sourceArray['height'] = $sourceArray['size'][1];
371
		$sourceArray['width'] = $sourceArray['size'][0];
372
		return $sourceArray;
373
	}
374
375
	/**
376
	 * calcDist
377
	 *
378
	 * @param array $sourceArray
379
	 * @param array $optionArray
380
	 *
381
	 * @return array
382
	 */
383
384
	protected function _calcDist(array $sourceArray = [], array $optionArray = []) : array
385
	{
386
		$distArray['height'] = is_array($optionArray) && array_key_exists('height', $optionArray) ? $optionArray['height'] : $this->_optionArray['height'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$distArray was never initialized. Although not strictly required by PHP, it is generally a good practice to add $distArray = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
387
		$distArray['quality'] = is_array($optionArray) && array_key_exists('quality', $optionArray) ? $optionArray['quality'] : $this->_optionArray['quality'];
388
389
		/* calculate */
390
391
		if ($distArray['height'])
392
		{
393
			$distArray['scaling'] = $distArray['height'] / $sourceArray['height'] * 100;
394
		}
395
		else
396
		{
397
			$distArray['height'] = round($distArray['scaling'] / 100 * $sourceArray['height']);
398
		}
399
		$distArray['width'] = round($distArray['scaling'] / 100 * $sourceArray['width']);
400
		return $distArray;
401
	}
402
}
403