Completed
Push — master ( da58d4...61a0f7 )
by Henry
06:34
created

modules/DirectoryLister/DirectoryLister.php (1 issue)

Check for mismatching type of a variable.

Bug Minor

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\DirectoryLister;
3
4
use Redaxscript\Dater;
5
use Redaxscript\Filesystem;
6
use Redaxscript\Filter;
7
use Redaxscript\Head;
8
use Redaxscript\Html;
9
use Redaxscript\Module;
10
use function array_key_exists;
11
use function ceil;
12
use function dirname;
13
use function explode;
14
use function filectime;
15
use function filesize;
16
use function http_build_query;
17
use function is_array;
18
use function is_dir;
19
use function is_file;
20
use function pathinfo;
21
use function str_replace;
22
23
/**
24
 * list the files of a directory
25
 *
26
 * @since 2.6.0
27
 *
28
 * @package Redaxscript
29
 * @category Modules
30
 * @author Henry Ruhs
31
 */
32
33
class DirectoryLister extends Module\Notification
34
{
35
	/**
36
	 * array of the module
37
	 *
38
	 * @var array
39
	 */
40
41
	protected static $_moduleArray =
42
	[
43
		'name' => 'Directory Lister',
44
		'alias' => 'DirectoryLister',
45
		'author' => 'Redaxmedia',
46
		'description' => 'List the files of a directory',
47
		'version' => '4.0.0'
48
	];
49
50
	/**
51
	 * array of the option
52
	 *
53
	 * @var array
54
	 */
55
56
	protected $_optionArray =
57
	[
58
		'className' =>
59
		[
60
			'list' => 'rs-list-directory-lister',
61
			'link' => 'rs-link-directory-lister',
62
			'textSize' => 'rs-text-directory-lister rs-is-size',
63
			'textDate' => 'rs-text-directory-lister rs-is-date',
64
			'types' =>
65
			[
66
				'directory' => 'rs-is-directory',
67
				'directoryParent' => 'rs-is-directory rs-is-parent',
68
				'file' => 'rs-is-file',
69
				'fileText' => 'rs-is-file rs-is-text',
70
				'fileImage' => 'rs-is-file rs-is-image',
71
				'fileMusic' => 'rs-is-file rs-is-music',
72
				'fileVideo' => 'rs-is-file rs-is-video',
73
				'fileArchive' => 'rs-is-file rs-is-archive'
74
			]
75
		],
76
		'size' =>
77
		[
78
			'unit' => 'kB',
79
			'divider' => 1024
80
		],
81
		'replaceKey' =>
82
		[
83
			'extension'	=> '{extension}'
84
		],
85
		'extension' =>
86
		[
87
			'doc' => 'fileText',
88
			'txt' => 'fileText',
89
			'gif' => 'fileImage',
90
			'jpg' => 'fileImage',
91
			'pdf' => 'fileImage',
92
			'png' => 'fileImage',
93
			'mp3' => 'fileMusic',
94
			'wav' => 'fileMusic',
95
			'avi' => 'fileVideo',
96
			'mov' => 'fileVideo',
97
			'mp4' => 'fileVideo',
98
			'tar' => 'fileArchive',
99
			'rar' => 'fileArchive',
100
			'zip' => 'fileArchive'
101
		]
102
	];
103
104
	/**
105
	 * renderStart
106
	 *
107
	 * @since 3.0.0
108
	 */
109
110
	public function renderStart() : void
111
	{
112
		$link = Head\Link::getInstance();
113
		$link
114
			->init()
115
			->appendFile('modules/DirectoryLister/dist/styles/directory-lister.min.css');
116
	}
117
118
	/**
119
	 * adminNotification
120
	 *
121
	 * @since 3.0.0
122
	 *
123
	 * @return array|null
124
	 */
125
126
	public function adminNotification() : ?array
127
	{
128
		return $this->getNotification();
129
	}
130
131
	/**
132
	 * render
133
	 *
134
	 * @since 2.6.0
135
	 *
136
	 * @param string $directory
137
	 * @param array $optionArray
138
	 *
139
	 * @return string|null
140
	 */
141
142
	public function render(string $directory = null, array $optionArray = []) : ?string
143
	{
144
		$output = null;
145
		$outputItem = null;
146
147
		/* html element */
148
149
		$listElement = new Html\Element();
150
		$listElement->init('ul',
151
		[
152
			'class' => $this->_optionArray['className']['list']
153
		]);
154
155
		/* handle option */
156
157
		if ($optionArray['hash'])
158
		{
159
			$optionArray['hash'] = '#' . $optionArray['hash'];
160
		}
161
162
		/* handle query */
163
164
		$directoryQuery = $this->_request->getQuery('directory');
165
		$directoryQueryArray = explode('/', $directoryQuery);
166
167
		/* parent directory */
168
169
		if ($directoryQueryArray[0] === $directory && $directory !== $directoryQuery)
170
		{
171
			$pathFilter = new Filter\Path();
172
			$rootDirectory = $directory;
173
			$directory = $pathFilter->sanitize($directoryQuery);
174
			$parentDirectory = $pathFilter->sanitize(dirname($directory));
175
			$outputItem .= $this->_renderParent($rootDirectory, $parentDirectory, $optionArray);
176
		}
177
178
		/* handle notification */
179
180
		if (!is_dir($directory))
181
		{
182
			$this->setNotification('error', $this->_language->get('directory_not_found') . $this->_language->get('colon') . ' ' . $directory . $this->_language->get('point'));
183
		}
184
185
		/* else collect item */
186
187
		else
188
		{
189
			$outputItem .= $this->_renderItem($directory, $optionArray);
190
191
			/* collect list output */
192
193
			if ($outputItem)
194
			{
195
				$output = $listElement->html($outputItem);
196
			}
197
		}
198
		return $output;
199
	}
200
201
	/**
202
	 * renderParent
203
	 *
204
	 * @param string $rootDirectory
205
	 * @param string $parentDirectory
206
	 * @param array $optionArray
207
	 *
208
	 * @return string|null
209
	 */
210
211
	protected function _renderParent(string $rootDirectory = null, string $parentDirectory = null, array $optionArray = []) : ?string
212
	{
213
		$queryString = $rootDirectory !== $parentDirectory ? '&' . http_build_query(
214
		[
215
			'directory' => $parentDirectory
216
		]) : null;
217
218
		/* html element */
219
220
		$element = new Html\Element();
221
		$itemElement = $element->copy()->init('li');
222
		$linkElement = $element
223
			->copy()
224
			->init('a',
225
			[
226
				'class' => $this->_optionArray['className']['link']
227
			]);
228
229
		/* collect item output */
230
231
		$outputItem = $itemElement
232
			->html(
233
				$linkElement
234
				->attr(
235
				[
236
					'href' => $this->_registry->get('parameterRoute') . $this->_registry->get('fullRoute') . $queryString . $optionArray['hash'],
237
					'title' => $this->_language->get('directory_parent', '_directory_lister')
238
				])
239
				->addClass($this->_optionArray['className']['types']['directoryParent'])
240
				->text($this->_language->get('directory_parent', '_directory_lister'))
0 ignored issues
show
It seems like $this->_language->get('d...', '_directory_lister') targeting Redaxscript\Language::get() can also be of type array; however, Redaxscript\Html\Element::text() does only seem to accept string|integer|null, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
241
			);
242
		return $outputItem;
243
	}
244
245
	/**
246
	 * renderItem
247
	 *
248
	 * @param string $directory
249
	 * @param array $optionArray
250
	 *
251
	 * @return string|null
252
	 */
253
254
	protected function _renderItem(string $directory = null, array $optionArray = []) : ?string
255
	{
256
		$outputItem = null;
257
		$dater = new Dater();
258
259
		/* html element */
260
261
		$element = new Html\Element();
262
		$itemElement = $element->copy()->init('li');
263
		$linkElement = $element
264
			->copy()
265
			->init('a',
266
			[
267
				'class' => $this->_optionArray['className']['link']
268
			]);
269
		$textSizeElement = $element
270
			->copy()
271
			->init('span',
272
			[
273
				'class' => $this->_optionArray['className']['textSize']
274
			]);
275
		$textDateElement = $element
276
			->copy()
277
			->init('span',
278
			[
279
				'class' => $this->_optionArray['className']['textDate']
280
			]);
281
282
		/* lister filesystem */
283
284
		$listerFilesystem = new Filesystem\Filesystem();
285
		$listerFilesystem->init($directory);
286
		$listerFilesystemArray = $listerFilesystem->getSortArray();
287
288
		/* process filesystem */
289
290
		foreach ($listerFilesystemArray as $value)
291
		{
292
			$path = $directory . DIRECTORY_SEPARATOR . $value;
293
			$fileExtension = pathinfo($path, PATHINFO_EXTENSION);
294
			$text = $this->_replace($value, $fileExtension, $optionArray['replace']);
295
			$isDir = is_dir($path);
296
			$isFile = is_file($path) && is_array($this->_optionArray['extension']) && array_key_exists($fileExtension, $this->_optionArray['extension']);
297
			$dater->init(filectime($path));
298
299
			/* handle directory */
300
301
			if ($isDir)
302
			{
303
				$itemElement
304
					->clear()
305
					->html(
306
						$linkElement
307
							->copy()
308
							->attr(
309
							[
310
								'href' => $this->_registry->get('parameterRoute') . $this->_registry->get('fullRoute') . '&' . http_build_query(
311
								[
312
									'directory' => $path . $optionArray['hash']
313
								]),
314
								'title' => $this->_language->get('directory', '_directory_lister')
315
							])
316
							->addClass($this->_optionArray['className']['types']['directory'])
317
							->text($text)
318
					)
319
					->append($textSizeElement);
320
			}
321
322
			/* else handle file */
323
324
			else if ($isFile)
325
			{
326
				$fileType = $this->_optionArray['extension'][$fileExtension];
327
				$textSize = ceil(filesize($path) / $this->_optionArray['size']['divider']);
328
				$itemElement
329
					->clear()
330
					->html(
331
						$linkElement
332
							->copy()
333
							->attr(
334
							[
335
								'href' => $this->_registry->get('root') . '/' . $path,
336
								'target' => '_blank',
337
								'title' => $this->_language->get('file', '_directory_lister')
338
							])
339
							->addClass($this->_optionArray['className']['types'][$fileType])
340
							->text($text)
341
					)
342
					->append(
343
						$textSizeElement
344
							->copy()
345
							->attr('data-unit', $this->_optionArray['size']['unit'])
346
							->text($textSize)
347
					);
348
			}
349
			if ($isDir || $isFile)
350
			{
351
				$outputItem .= $itemElement
352
					->append($textDateElement
353
						->copy()
354
						->text($dater->formatDate())
355
					);
356
			}
357
		}
358
		return $outputItem;
359
	}
360
361
	/**
362
	 * replace
363
	 *
364
	 * @param string $text
365
	 * @param string $fileExtension
366
	 * @param array|null $replaceArray
367
	 *
368
	 * @return string
369
	 */
370
371
	protected function _replace(string $text, string $fileExtension, ?array $replaceArray = []) : string
372
	{
373
		if (is_array($replaceArray))
374
		{
375
			foreach ($replaceArray as $replaceKey => $replaceValue)
376
			{
377
				if ($replaceKey === $this->_optionArray['replaceKey']['extension'])
378
				{
379
					$replaceKey = $fileExtension;
380
				}
381
				$text = str_replace($replaceKey, $replaceValue, $text);
382
			}
383
		}
384
		return $text;
385
	}
386
}
387