Completed
Push — master ( 29f0c5...0d72ed )
by Henry
09:47
created

modules/Gallery/Gallery.php (2 issues)

lazy-initialization of arrays.

Coding Style Comprehensibility Informational

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