Completed
Push — master ( 29f0c5...0d72ed )
by Henry
09:47
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
 * javascript powered 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' => 'JavaScript powered gallery',
50
		'version' => '4.0.0'
51
	];
52
53
	/**
54
	 * array of the option
55
	 *
56
	 * @var array
57
	 */
58
59
	protected $_optionArray =
60
	[
61
		'className' =>
62
		[
63
			'image' => 'rs-image-gallery',
64
			'list' => 'rs-js-gallery rs-list-gallery'
65
		],
66
		'allowedCommands' =>
67
		[
68
			'create',
69
			'remove'
70
		],
71
		'height' => 200,
72
		'quality' => 80,
73
		'thumbDirectory' => 'thumbs'
74
	];
75
76
	/**
77
	 * adminNotification
78
	 *
79
	 * @since 3.0.0
80
	 *
81
	 * @return array
82
	 */
83
84
	public function adminNotification() : array
85
	{
86
		return $this->getNotificationArray();
87
	}
88
89
	/**
90
	 * renderStart
91
	 *
92
	 * @since 3.0.0
93
	 */
94
95
	public function renderStart() : void
96
	{
97
		$this->_registry->set('noPageCache', true);
98
99
		/* link */
100
101
		$link = Head\Link::getInstance();
102
		$link
103
			->init()
104
			->appendFile(
105
			[
106
				'https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.min.css',
107
				'https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/default-skin/default-skin.min.css',
108
				'modules/Gallery/dist/styles/gallery.min.css'
109
			]);
110
111
		/* script */
112
113
		$script = Head\Script::getInstance();
114
		$script
115
			->init('foot')
116
			->appendFile(
117
			[
118
				'https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe.js',
119
				'https://cdnjs.cloudflare.com/ajax/libs/photoswipe/4.1.3/photoswipe-ui-default.min.js',
120
				'modules/Gallery/assets/scripts/init.js',
121
				'modules/Gallery/dist/scripts/gallery.min.js'
122
			]);
123
	}
124
125
	/**
126
	 * render
127
	 *
128
	 * @since 3.0.0
129
	 *
130
	 * @param string $directory
131
	 * @param array $optionArray
132
	 *
133
	 * @return string|null
134
	 */
135
136
	public function render(string $directory = null, array $optionArray = []) : ?string
137
	{
138
		$output = null;
139
		$outputItem = null;
140
141
		/* html element */
142
143
		$listElement = new Html\Element();
144
		$listElement->init('ul',
145
		[
146
			'class' => $this->_optionArray['className']['list']
147
		]);
148
149
		/* handle notification */
150
151
		if (!is_dir($directory))
152
		{
153
			$this->setNotification('error', $this->_language->get('directory_not_found') . $this->_language->get('colon') . ' ' . $directory . $this->_language->get('point'));
154
		}
155
156
		/* else collect item */
157
158
		else
159
		{
160
			/* remove as needed */
161
162
			if ($optionArray['command'] === 'remove')
163
			{
164
				$this->_removeThumb($directory);
165
			}
166
167
			/* create as needed */
168
169
			if ($optionArray['command'] === 'create' || !is_dir($directory . DIRECTORY_SEPARATOR . $this->_optionArray['thumbDirectory']))
170
			{
171
				$this->_createThumb($directory, $optionArray);
172
			}
173
			$outputItem .= $this->_renderItem($directory, $optionArray);
174
175
			/* collect list output */
176
177
			if ($outputItem)
178
			{
179
				$output = $listElement->html($outputItem);
180
			}
181
182
			/* include template */
183
184
			include_once('modules/Gallery/templates/gallery.phtml');
185
		}
186
		return $output;
187
	}
188
189
	/**
190
	 * renderItem
191
	 *
192
	 * @since 2.6.0
193
	 *
194
	 * @param string $directory
195
	 * @param array $optionArray
196
	 *
197
	 * @return string|null
198
	 */
199
200
	protected function _renderItem(string $directory = null, array $optionArray = []) : ?string
201
	{
202
		$outputItem = null;
203
		$itemCounter = 0;
204
205
		/* html element */
206
207
		$element = new Html\Element();
208
		$itemElement = $element->copy()->init('li');
209
		$linkElement = $element->copy()->init('a');
210
		$imageElement = $element
211
			->copy()
212
			->init('img',
213
			[
214
				'class' => $this->_optionArray['className']['image'],
215
				'loading' => 'lazy'
216
			]);
217
218
		/* gallery filesystem */
219
220
		$galleryFilesystem = new Filesystem\Filesystem();
221
		$galleryFilesystem->init($directory, false,
222
		[
223
			$this->_optionArray['thumbDirectory']
224
		]);
225
		$galleryFilesystemArray = $galleryFilesystem->getSortArray();
226
227
		/* adjust order */
228
229
		if ($optionArray['order'] === 'desc')
230
		{
231
			$galleryFilesystemArray = array_reverse($galleryFilesystemArray);
232
		}
233
234
		/* process filesystem */
235
236
		foreach ($galleryFilesystemArray as $value)
237
		{
238
			$imagePath = $directory . DIRECTORY_SEPARATOR . $value;
239
			$thumbPath = $directory . DIRECTORY_SEPARATOR . $this->_optionArray['thumbDirectory'] . DIRECTORY_SEPARATOR . $value;
240
			$imageSize = getimagesize($imagePath);
241
242
			/* collect item output */
243
244
			$outputItem .= file_exists($thumbPath) ? $itemElement
245
				->clear()
246
				->html(
247
					$linkElement
248
						->copy()
249
						->attr(
250
						[
251
							'href' => $imagePath,
252
							'data-index' => $itemCounter++,
253
							'data-height' => $imageSize[1],
254
							'data-width' => $imageSize[0]
255
						])
256
						->html(
257
							$imageElement
258
								->copy()
259
								->attr(
260
								[
261
									'src' => $thumbPath,
262
									'alt' => $value
263
								])
264
						)
265
				) : null;
266
		}
267
		return $outputItem;
268
	}
269
270
	/**
271
	 * removeThumb
272
	 *
273
	 * @since 3.0.0
274
	 *
275
	 * @param string $directory
276
	 */
277
278
	protected function _removeThumb(string $directory = null) : void
279
	{
280
		$galleryFilesystem = new Filesystem\Directory();
281
		$galleryFilesystem->init($directory, true);
282
		$galleryFilesystem->removeDirectory($this->_optionArray['thumbDirectory']);
283
	}
284
285
	/**
286
	 * createThumb
287
	 *
288
	 * @since 3.0.0
289
	 *
290
	 * @param string $directory
291
	 * @param array $optionArray
292
	 */
293
294
	protected function _createThumb(string $directory = null, array $optionArray = []) : void
295
	{
296
		/* gallery filesystem */
297
298
		$galleryFilesystem = new Filesystem\Directory();
299
		$galleryFilesystem->init($directory, false,
300
		[
301
			$this->_optionArray['thumbDirectory']
302
		]);
303
		$galleryFilesystem->createDirectory($this->_optionArray['thumbDirectory']);
304
		$galleryFilesystemArray = $galleryFilesystem->getSortArray();
305
306
		/* handle notification */
307
308
		if (!chmod($directory . DIRECTORY_SEPARATOR . $this->_optionArray['thumbDirectory'], 0777))
309
		{
310
			$this->setNotification('error', $this->_language->get('directory_permission_grant') . $this->_language->get('colon') . ' ' . $directory . DIRECTORY_SEPARATOR . $this->_optionArray['thumbDirectory'] . $this->_language->get('point'));
311
		}
312
313
		/* else process filesystem */
314
315
		else
316
		{
317
			foreach ($galleryFilesystemArray as $value)
318
			{
319
				$imagePath = $directory . DIRECTORY_SEPARATOR . $value;
320
				$imageExtension = strtolower(pathinfo($value, PATHINFO_EXTENSION));
321
				$thumbPath = $directory . DIRECTORY_SEPARATOR . $this->_optionArray['thumbDirectory'] . DIRECTORY_SEPARATOR . $value;
322
				$image = null;
323
324
				/* handle extension */
325
326
				if ($imageExtension === 'gif')
327
				{
328
					$image = imagecreatefromgif($imagePath);
329
				}
330
				if ($imageExtension === 'jpg')
331
				{
332
					$image = imagecreatefromjpeg($imagePath);
333
				}
334
				if ($imageExtension === 'png')
335
				{
336
					$image = imagecreatefrompng($imagePath);
337
				}
338
339
				/* source and dist */
340
341
				$sourceArray = $this->_calcSource($imagePath);
342
				$distArray = $this->_calcDist($sourceArray, $optionArray);
343
344
				/* create thumb files */
345
346
				$thumb = imagecreatetruecolor($distArray['width'], $distArray['height']);
347
				imagecopyresampled($thumb, $image, 0, 0, 0, 0, $distArray['width'], $distArray['height'], $sourceArray['width'], $sourceArray['height']);
348
				imagejpeg($thumb, $thumbPath, $distArray['quality']);
349
350
				/* destroy image */
351
352
				imagedestroy($thumb);
353
				imagedestroy($image);
354
			}
355
		}
356
	}
357
358
	/**
359
	 * calcSource
360
	 *
361
	 * @param string $imagePath
362
	 *
363
	 * @return array
364
	 */
365
366
	protected function _calcSource(string $imagePath = null) : array
367
	{
368
		$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...
369
		$sourceArray['height'] = $sourceArray['size'][1];
370
		$sourceArray['width'] = $sourceArray['size'][0];
371
		return $sourceArray;
372
	}
373
374
	/**
375
	 * calcDist
376
	 *
377
	 * @param array $sourceArray
378
	 * @param array $optionArray
379
	 *
380
	 * @return array
381
	 */
382
383
	protected function _calcDist(array $sourceArray = [], array $optionArray = []) : array
384
	{
385
		$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...
386
		$distArray['quality'] = is_array($optionArray) && array_key_exists('quality', $optionArray) ? $optionArray['quality'] : $this->_optionArray['quality'];
387
388
		/* calculate */
389
390
		if ($distArray['height'])
391
		{
392
			$distArray['scaling'] = $distArray['height'] / $sourceArray['height'] * 100;
393
		}
394
		else
395
		{
396
			$distArray['height'] = round($distArray['scaling'] / 100 * $sourceArray['height']);
397
		}
398
		$distArray['width'] = round($distArray['scaling'] / 100 * $sourceArray['width']);
399
		return $distArray;
400
	}
401
}
402