1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
/* |
6
|
|
|
* This file is part of the humbug/php-scoper package. |
7
|
|
|
* |
8
|
|
|
* Copyright (c) 2017 Théo FIDRY <[email protected]>, |
9
|
|
|
* Pádraic Brady <[email protected]> |
10
|
|
|
* |
11
|
|
|
* For the full copyright and license information, please view the LICENSE |
12
|
|
|
* file that was distributed with this source code. |
13
|
|
|
*/ |
14
|
|
|
|
15
|
|
|
namespace Humbug\PhpScoper\Console; |
16
|
|
|
|
17
|
|
|
use InvalidArgumentException; |
18
|
|
|
use Symfony\Component\Finder\Finder; |
19
|
|
|
|
20
|
|
|
final class Configuration |
21
|
|
|
{ |
22
|
|
|
/** @internal */ |
23
|
|
|
const FINDER_KEYWORD = 'finders'; |
24
|
|
|
|
25
|
|
|
/** @internal */ |
26
|
|
|
const PATCHERS_KEYWORD = 'patchers'; |
27
|
|
|
|
28
|
|
|
/** @internal */ |
29
|
|
|
const WHITELIST_KEYWORD = 'whitelist'; |
30
|
|
|
|
31
|
|
|
/** @internal */ |
32
|
|
|
const GLOBAL_NAMESPACE_KEYWORD = 'global_namespace_whitelist'; |
33
|
|
|
|
34
|
|
|
/** @internal */ |
35
|
|
|
const KEYWORDS = [ |
36
|
|
|
self::FINDER_KEYWORD, |
37
|
|
|
self::PATCHERS_KEYWORD, |
38
|
|
|
self::WHITELIST_KEYWORD, |
39
|
|
|
self::GLOBAL_NAMESPACE_KEYWORD, |
40
|
|
|
]; |
41
|
|
|
|
42
|
|
|
private $path; |
43
|
|
|
private $patchers; |
44
|
|
|
private $finders; |
45
|
|
|
private $whitelist; |
46
|
|
|
private $globalNamespaceWhitelisters; |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* @param string|null $path Absolute path to the configuration file. |
50
|
|
|
* |
51
|
|
|
* @return self |
52
|
|
|
*/ |
53
|
|
|
public static function load(string $path = null): self |
54
|
|
|
{ |
55
|
|
|
if (null === $path) { |
56
|
|
|
return new self(null, [], [], [], []); |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
$config = include $path; |
60
|
|
|
|
61
|
|
|
if (false === is_array($config)) { |
62
|
|
|
throw new InvalidArgumentException( |
63
|
|
|
sprintf( |
64
|
|
|
'Expected configuration to be an array, found "%s" instead.', |
65
|
|
|
gettype($config) |
66
|
|
|
) |
67
|
|
|
); |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
self::validateConfigKeys($config); |
71
|
|
|
|
72
|
|
|
$finders = self::retrieveFinders($config); |
73
|
|
|
$patchers = self::retrievePatchers($config); |
74
|
|
|
$whitelist = self::retrieveWhitelist($config); |
75
|
|
|
$globalNamespace = self::retrieveGlobalNamespaceWhitelisters($config); |
76
|
|
|
|
77
|
|
|
return new self($path, $finders, $patchers, $whitelist, $globalNamespace); |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* @param string|null $path Absolute path to the configuration file loaded. |
82
|
|
|
* @param Finder[] $finders List of finders which will provide the files that will be scoped. |
83
|
|
|
* @param callable[] $patchers List of closures which can alter the content of the files being |
84
|
|
|
* scoped. |
85
|
|
|
* @param string[] $whitelist List of classes that will not be scoped. |
86
|
|
|
* @param callable[]|string[] $globalNamespace List of class names from the global namespace that should be scoped |
87
|
|
|
* or closures filtering if the class should be scoped or not. |
88
|
|
|
*/ |
89
|
|
|
private function __construct( |
90
|
|
|
string $path = null, |
91
|
|
|
array $finders, |
92
|
|
|
array $patchers, |
93
|
|
|
array $whitelist, |
94
|
|
|
array $globalNamespace |
95
|
|
|
) { |
96
|
|
|
$this->path = $path; |
97
|
|
|
$this->patchers = $patchers; |
98
|
|
|
$this->finders = $finders; |
99
|
|
|
$this->whitelist = $whitelist; |
100
|
|
|
$this->globalNamespaceWhitelisters = $globalNamespace; |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
public function getPath(): string |
104
|
|
|
{ |
105
|
|
|
return $this->path; |
106
|
|
|
} |
107
|
|
|
|
108
|
|
|
/** |
109
|
|
|
* @return Finder[] |
110
|
|
|
*/ |
111
|
|
|
public function getFinders(): array |
112
|
|
|
{ |
113
|
|
|
return $this->finders; |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
/** |
117
|
|
|
* @return callable[] |
118
|
|
|
*/ |
119
|
|
|
public function getPatchers(): array |
120
|
|
|
{ |
121
|
|
|
return $this->patchers; |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
public function getWhitelist(): array |
125
|
|
|
{ |
126
|
|
|
return $this->whitelist; |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
/** |
130
|
|
|
* @return callable[]|string[] |
131
|
|
|
*/ |
132
|
|
|
public function getGlobalNamespaceWhitelisters() |
133
|
|
|
{ |
134
|
|
|
return $this->globalNamespaceWhitelisters; |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
private static function validateConfigKeys(array $config) |
138
|
|
|
{ |
139
|
|
|
array_map( |
140
|
|
|
['self', 'validateConfigKey'], |
141
|
|
|
array_keys($config) |
142
|
|
|
); |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
private static function validateConfigKey(string $key) |
146
|
|
|
{ |
147
|
|
|
if (false === in_array($key, self::KEYWORDS)) { |
148
|
|
|
throw new InvalidArgumentException( |
149
|
|
|
sprintf( |
150
|
|
|
'Invalid configuration key value "%s" found.', |
151
|
|
|
$key |
152
|
|
|
) |
153
|
|
|
); |
154
|
|
|
} |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
private static function retrieveFinders(array $config): array |
158
|
|
|
{ |
159
|
|
|
if (false === array_key_exists(self::FINDER_KEYWORD, $config)) { |
160
|
|
|
return []; |
161
|
|
|
} |
162
|
|
|
|
163
|
|
|
$finders = $config[self::FINDER_KEYWORD]; |
164
|
|
|
|
165
|
|
|
if (false === is_array($finders)) { |
166
|
|
|
throw new InvalidArgumentException( |
167
|
|
|
sprintf( |
168
|
|
|
'Expected finders to be an array of "%s", found "%s" instead.', |
169
|
|
|
Finder::class, |
170
|
|
|
gettype($finders) |
171
|
|
|
) |
172
|
|
|
); |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
foreach ($finders as $index => $finder) { |
176
|
|
|
if ($finder instanceof Finder) { |
177
|
|
|
continue; |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
throw new InvalidArgumentException( |
181
|
|
|
sprintf( |
182
|
|
|
'Expected finders to be an array of "%s", the "%d" element is not.', |
183
|
|
|
Finder::class, |
184
|
|
|
$index |
185
|
|
|
) |
186
|
|
|
); |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
return $finders; |
190
|
|
|
} |
191
|
|
|
|
192
|
|
View Code Duplication |
private static function retrievePatchers(array $config): array |
|
|
|
|
193
|
|
|
{ |
194
|
|
|
if (false === array_key_exists(self::PATCHERS_KEYWORD, $config)) { |
195
|
|
|
return []; |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
$patchers = $config[self::PATCHERS_KEYWORD]; |
199
|
|
|
|
200
|
|
|
if (false === is_array($patchers)) { |
201
|
|
|
throw new InvalidArgumentException( |
202
|
|
|
sprintf( |
203
|
|
|
'Expected patchers to be an array of callables, found "%s" instead.', |
204
|
|
|
gettype($patchers) |
205
|
|
|
) |
206
|
|
|
); |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
foreach ($patchers as $index => $patcher) { |
210
|
|
|
if (is_callable($patcher)) { |
211
|
|
|
continue; |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
throw new InvalidArgumentException( |
215
|
|
|
sprintf( |
216
|
|
|
'Expected patchers to be an array of callables, the "%d" element is not.', |
217
|
|
|
$index |
218
|
|
|
) |
219
|
|
|
); |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
return $patchers; |
223
|
|
|
} |
224
|
|
|
|
225
|
|
View Code Duplication |
private static function retrieveWhitelist(array $config): array |
226
|
|
|
{ |
227
|
|
|
if (false === array_key_exists(self::WHITELIST_KEYWORD, $config)) { |
228
|
|
|
return []; |
229
|
|
|
} |
230
|
|
|
|
231
|
|
|
$whitelist = $config[self::WHITELIST_KEYWORD]; |
232
|
|
|
|
233
|
|
|
if (false === is_array($whitelist)) { |
234
|
|
|
throw new InvalidArgumentException( |
235
|
|
|
sprintf( |
236
|
|
|
'Expected whitelist to be an array of strings, found "%s" instead.', |
237
|
|
|
gettype($whitelist) |
238
|
|
|
) |
239
|
|
|
); |
240
|
|
|
} |
241
|
|
|
|
242
|
|
|
foreach ($whitelist as $index => $className) { |
243
|
|
|
if (is_string($className)) { |
244
|
|
|
continue; |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
throw new InvalidArgumentException( |
248
|
|
|
sprintf( |
249
|
|
|
'Expected whitelist to be an array of string, the "%d" element is not.', |
250
|
|
|
$index |
251
|
|
|
) |
252
|
|
|
); |
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
return $whitelist; |
256
|
|
|
} |
257
|
|
|
|
258
|
|
View Code Duplication |
private static function retrieveGlobalNamespaceWhitelisters(array $config): array |
259
|
|
|
{ |
260
|
|
|
if (false === array_key_exists(self::GLOBAL_NAMESPACE_KEYWORD, $config)) { |
261
|
|
|
return []; |
262
|
|
|
} |
263
|
|
|
|
264
|
|
|
$globalNamespace = $config[self::GLOBAL_NAMESPACE_KEYWORD]; |
265
|
|
|
|
266
|
|
|
if (false === is_array($globalNamespace)) { |
267
|
|
|
throw new InvalidArgumentException( |
268
|
|
|
sprintf( |
269
|
|
|
'Expected "global_namespace" to be an array, found "%s" instead.', |
270
|
|
|
gettype($globalNamespace) |
271
|
|
|
) |
272
|
|
|
); |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
foreach ($globalNamespace as $index => $className) { |
276
|
|
|
if (is_string($className) || is_callable($className)) { |
277
|
|
|
continue; |
278
|
|
|
} |
279
|
|
|
|
280
|
|
|
throw new InvalidArgumentException( |
281
|
|
|
sprintf( |
282
|
|
|
'Expected "global_namespace" to be an array of callables or strings, the "%d" element ' |
283
|
|
|
.'is not.', |
284
|
|
|
$index |
285
|
|
|
) |
286
|
|
|
); |
287
|
|
|
} |
288
|
|
|
|
289
|
|
|
return $globalNamespace; |
290
|
|
|
} |
291
|
|
|
} |
292
|
|
|
|
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.