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