Completed
Push — master ( 0ea243...da58d4 )
by Henry
10:25 queued 33s
created

modules/DirectoryLister/DirectoryLister.php (1 issue)

call_checks.maybe_mismatching_type_passed_with_def

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);
0 ignored issues
show
It seems like $directoryQuery defined by $this->_request->getQuery('directory') on line 164 can also be of type array; however, Redaxscript\Filter\Path::sanitize() does only seem to accept null|string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
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'))
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