1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Helper; |
4
|
|
|
|
5
|
|
|
/** |
6
|
|
|
* Helper for common file system functions. |
7
|
|
|
*/ |
8
|
|
|
final class FileSystem |
9
|
|
|
{ |
10
|
|
|
/** |
11
|
|
|
* @param string $userProvidedPath |
12
|
|
|
* @return string|null |
13
|
|
|
*/ |
14
|
|
|
public static function getRealPathToReadableAndWritableFile($userProvidedPath) |
15
|
|
|
{ |
16
|
|
|
$realPath = realpath(dirname($userProvidedPath)) . '/' . basename($userProvidedPath); |
17
|
|
|
return is_file($realPath) && is_readable($realPath) && is_writable($realPath) ? $realPath : null; |
18
|
|
|
} |
19
|
|
|
|
20
|
|
|
/** |
21
|
|
|
* @param string $path |
22
|
|
|
* @return string[] |
23
|
|
|
*/ |
24
|
|
|
public static function readFileIntoArray($path) |
25
|
|
|
{ |
26
|
|
|
$array = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); |
27
|
|
|
if ($array === false) { |
28
|
|
|
throw new \RuntimeException($path . ' could not be read.'); |
29
|
|
|
} |
30
|
|
|
|
31
|
|
|
return $array; |
32
|
|
|
} |
33
|
|
|
|
34
|
|
|
/** |
35
|
|
|
* @param string[] $lines |
36
|
|
|
* @param string $path |
37
|
|
|
*/ |
38
|
|
|
public static function writeArrayToFile(array $lines, $path) |
39
|
|
|
{ |
40
|
|
|
$handle = fopen($path, 'wb'); |
41
|
|
|
fwrite($handle, implode(PHP_EOL, $lines)); |
42
|
|
|
fclose($handle); |
43
|
|
|
} |
44
|
|
|
|
45
|
|
|
/** |
46
|
|
|
* @param string|null $userProvidedPathToBlacklist |
47
|
|
|
* @return string[] |
48
|
|
|
*/ |
49
|
|
|
public static function getBlacklistingRegExps($userProvidedPathToBlacklist = null) |
50
|
|
|
{ |
51
|
|
|
if ($userProvidedPathToBlacklist === null) { |
52
|
|
|
return []; |
53
|
|
|
} |
54
|
|
|
|
55
|
|
|
if (!is_file($userProvidedPathToBlacklist) || !is_readable($userProvidedPathToBlacklist)) { |
56
|
|
|
throw new \InvalidArgumentException($userProvidedPathToBlacklist . ' is no readable file'); |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
return FileSystem::readFileIntoArray($userProvidedPathToBlacklist); |
60
|
|
|
} |
61
|
|
|
|
62
|
|
|
/** |
63
|
|
|
* @param \SplFileInfo[] $foundFilesInfos |
64
|
|
|
* @param string[] $blacklistRegExps |
65
|
|
|
* @return string[] |
66
|
|
|
*/ |
67
|
|
|
public static function filterFilesIn(array $foundFilesInfos, array $blacklistRegExps) |
68
|
|
|
{ |
69
|
|
|
$filteredFiles = []; |
70
|
|
|
|
71
|
|
|
/** @var \Iterator $foundFilesInfos */ |
72
|
|
View Code Duplication |
foreach ($foundFilesInfos as $foundFileInfo) { |
|
|
|
|
73
|
|
|
/** @var $foundFileInfo \SplFileInfo */ |
74
|
|
|
foreach ($blacklistRegExps as $blacklistRegExp) { |
75
|
|
|
if (preg_match($blacklistRegExp, $foundFileInfo->getRealPath()) === 1) { |
76
|
|
|
continue 2; |
77
|
|
|
} |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
$filteredFiles[] = $foundFileInfo->getRealPath(); |
81
|
|
|
} |
82
|
|
|
|
83
|
|
|
return $filteredFiles; |
84
|
|
|
} |
85
|
|
|
|
86
|
|
|
/** |
87
|
|
|
* @param string|null $userProvidedPathToOutput |
88
|
|
|
* @param string $pathToUsedFiles |
89
|
|
|
* @return string |
90
|
|
|
*/ |
91
|
|
|
public static function getPathToOutput($userProvidedPathToOutput = null, $pathToUsedFiles) |
92
|
|
|
{ |
93
|
|
|
$pathToOutput = ($userProvidedPathToOutput !== null) |
94
|
|
|
? realpath(dirname($userProvidedPathToOutput)) . '/' . basename($userProvidedPathToOutput) |
95
|
|
|
: realpath(dirname($pathToUsedFiles)) . '/potentially-unused-files.txt'; |
96
|
|
|
|
97
|
|
|
if (is_file($pathToOutput) && !is_writable($pathToOutput)) { |
98
|
|
|
throw new \InvalidArgumentException('Output file ' . $pathToOutput . ' is not writable'); |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
if (!is_writable(dirname($pathToOutput))) { |
102
|
|
|
throw new \InvalidArgumentException('Output path ' . dirname($pathToOutput) . ' is not writable'); |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
return $pathToOutput; |
106
|
|
|
} |
107
|
|
|
} |
108
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.