Skip to content

Commit 62af2e2

Browse files
authored
Move Configuration up (#183)
The Configuration class is not bound to the Console so this can be moved up by a namespace.
1 parent 61518eb commit 62af2e2

File tree

3 files changed

+351
-324
lines changed

3 files changed

+351
-324
lines changed

src/Configuration.php

Lines changed: 345 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,345 @@
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;
16+
17+
use Closure;
18+
use InvalidArgumentException;
19+
use Iterator;
20+
use RuntimeException;
21+
use SplFileInfo;
22+
use Symfony\Component\Finder\Finder;
23+
24+
/**
25+
* @final
26+
* TODO: make this class as final as soon as the underlying deprecated class is removed.
27+
*/
28+
class Configuration
29+
{
30+
private const FINDER_KEYWORD = 'finders';
31+
private const PATCHERS_KEYWORD = 'patchers';
32+
private const WHITELIST_KEYWORD = 'whitelist';
33+
private const GLOBAL_NAMESPACE_KEYWORD = 'global_namespace_whitelist';
34+
35+
private 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 $filesWithContents;
44+
private $patchers;
45+
private $whitelist;
46+
47+
/**
48+
* @param string|null $path Absolute path to the configuration file.
49+
* @param string[] $paths List of paths to append besides the one configured
50+
*
51+
* @return self
52+
*/
53+
public static function load(string $path = null, array $paths = []): self
54+
{
55+
if (null === $path) {
56+
$config = [];
57+
} else {
58+
$config = include $path;
59+
60+
if (false === is_array($config)) {
61+
throw new InvalidArgumentException(
62+
sprintf(
63+
'Expected configuration to be an array, found "%s" instead.',
64+
gettype($config)
65+
)
66+
);
67+
}
68+
}
69+
70+
self::validateConfigKeys($config);
71+
72+
$patchers = self::retrievePatchers($config);
73+
$whitelist = self::retrieveWhitelist($config);
74+
75+
$finders = self::retrieveFinders($config);
76+
$filesFromPaths = self::retrieveFilesFromPaths($paths);
77+
$filesWithContents = self::retrieveFilesWithContents(chain($filesFromPaths, ...$finders));
78+
79+
return new self($path, $filesWithContents, $patchers, $whitelist);
80+
}
81+
82+
/**
83+
* @param string|null $path Absolute path to the configuration file loaded.
84+
* @param [string, string][] $filesWithContents Array of tuple with the first argument being the file path and the second its contents
85+
* @param callable[] $patchers List of closures which can alter the content of the files being
86+
* scoped.
87+
* @param string[] $whitelist List of classes that will not be scoped.
88+
* @param Closure $globalNamespaceWhitelisters Closure taking a class name from the global namespace as an argument and
89+
* returning a boolean which if `true` means the class should be scoped
90+
* (i.e. is ignored) or scoped otherwise.
91+
*/
92+
private function __construct(
93+
?string $path,
94+
array $filesWithContents,
95+
array $patchers,
96+
array $whitelist
97+
) {
98+
$this->path = $path;
99+
$this->filesWithContents = $filesWithContents;
100+
$this->patchers = $patchers;
101+
$this->whitelist = $whitelist;
102+
}
103+
104+
public function withPaths(array $paths): self
105+
{
106+
$filesWithContents = self::retrieveFilesWithContents(
107+
chain(
108+
self::retrieveFilesFromPaths(
109+
array_unique($paths)
110+
)
111+
)
112+
);
113+
114+
return new self(
115+
$this->path,
116+
array_merge($this->filesWithContents, $filesWithContents),
117+
$this->patchers,
118+
$this->whitelist
119+
);
120+
}
121+
122+
public function getPath(): string
123+
{
124+
return $this->path;
125+
}
126+
127+
public function getFilesWithContents(): array
128+
{
129+
return $this->filesWithContents;
130+
}
131+
132+
/**
133+
* @return callable[]
134+
*/
135+
public function getPatchers(): array
136+
{
137+
return $this->patchers;
138+
}
139+
140+
public function getWhitelist(): array
141+
{
142+
return $this->whitelist;
143+
}
144+
145+
private static function validateConfigKeys(array $config): void
146+
{
147+
array_map(
148+
['self', 'validateConfigKey'],
149+
array_keys($config)
150+
);
151+
}
152+
153+
private static function validateConfigKey(string $key): void
154+
{
155+
if (false === in_array($key, self::KEYWORDS)) {
156+
throw new InvalidArgumentException(
157+
sprintf(
158+
'Invalid configuration key value "%s" found.',
159+
$key
160+
)
161+
);
162+
}
163+
}
164+
165+
private static function retrievePatchers(array $config): array
166+
{
167+
if (false === array_key_exists(self::PATCHERS_KEYWORD, $config)) {
168+
return [];
169+
}
170+
171+
$patchers = $config[self::PATCHERS_KEYWORD];
172+
173+
if (false === is_array($patchers)) {
174+
throw new InvalidArgumentException(
175+
sprintf(
176+
'Expected patchers to be an array of callables, found "%s" instead.',
177+
gettype($patchers)
178+
)
179+
);
180+
}
181+
182+
foreach ($patchers as $index => $patcher) {
183+
if (is_callable($patcher)) {
184+
continue;
185+
}
186+
187+
throw new InvalidArgumentException(
188+
sprintf(
189+
'Expected patchers to be an array of callables, the "%d" element is not.',
190+
$index
191+
)
192+
);
193+
}
194+
195+
return $patchers;
196+
}
197+
198+
private static function retrieveWhitelist(array $config): array
199+
{
200+
if (false === array_key_exists(self::WHITELIST_KEYWORD, $config)) {
201+
return [];
202+
}
203+
204+
$whitelist = $config[self::WHITELIST_KEYWORD];
205+
206+
if (false === is_array($whitelist)) {
207+
throw new InvalidArgumentException(
208+
sprintf(
209+
'Expected whitelist to be an array of strings, found "%s" instead.',
210+
gettype($whitelist)
211+
)
212+
);
213+
}
214+
215+
foreach ($whitelist as $index => $className) {
216+
if (is_string($className)) {
217+
continue;
218+
}
219+
220+
throw new InvalidArgumentException(
221+
sprintf(
222+
'Expected whitelist to be an array of string, the "%d" element is not.',
223+
$index
224+
)
225+
);
226+
}
227+
228+
return $whitelist;
229+
}
230+
231+
private static function retrieveFinders(array $config): array
232+
{
233+
if (false === array_key_exists(self::FINDER_KEYWORD, $config)) {
234+
return [];
235+
}
236+
237+
$finders = $config[self::FINDER_KEYWORD];
238+
239+
if (false === is_array($finders)) {
240+
throw new InvalidArgumentException(
241+
sprintf(
242+
'Expected finders to be an array of "%s", found "%s" instead.',
243+
Finder::class,
244+
gettype($finders)
245+
)
246+
);
247+
}
248+
249+
foreach ($finders as $index => $finder) {
250+
if ($finder instanceof Finder) {
251+
continue;
252+
}
253+
254+
throw new InvalidArgumentException(
255+
sprintf(
256+
'Expected finders to be an array of "%s", the "%d" element is not.',
257+
Finder::class,
258+
$index
259+
)
260+
);
261+
}
262+
263+
return $finders;
264+
}
265+
266+
/**
267+
* @param string[] $paths
268+
*
269+
* @return iterable
270+
*/
271+
private static function retrieveFilesFromPaths(array $paths): iterable
272+
{
273+
if ([] === $paths) {
274+
return [];
275+
}
276+
277+
$pathsToSearch = [];
278+
$filesToAppend = [];
279+
280+
foreach ($paths as $path) {
281+
if (false === file_exists($path)) {
282+
throw new RuntimeException(
283+
sprintf(
284+
'Could not find the file "%s".',
285+
$path
286+
)
287+
);
288+
}
289+
290+
if (is_dir($path)) {
291+
$pathsToSearch[] = $path;
292+
} else {
293+
$filesToAppend[] = $path;
294+
}
295+
}
296+
297+
$finder = new Finder();
298+
299+
$finder->files()
300+
->in($pathsToSearch)
301+
->append($filesToAppend)
302+
->sortByName()
303+
;
304+
305+
return $finder;
306+
}
307+
308+
/**
309+
* @param Iterator $files
310+
*
311+
* @return [string, string][] Array of tuple with the first argument being the file path and the second its contents
312+
*/
313+
private static function retrieveFilesWithContents(Iterator $files): array
314+
{
315+
return array_reduce(
316+
iterator_to_array($files),
317+
function (array $files, SplFileInfo $fileInfo): array {
318+
$file = $fileInfo->getRealPath();
319+
320+
if (false === $file) {
321+
throw new RuntimeException(
322+
sprintf(
323+
'Could not find the file "%s".',
324+
(string) $fileInfo
325+
)
326+
);
327+
}
328+
329+
if (false === is_readable($file)) {
330+
throw new RuntimeException(
331+
sprintf(
332+
'Could not read the file "%s".',
333+
$file
334+
)
335+
);
336+
}
337+
338+
$files[$fileInfo->getRealPath()] = [$fileInfo->getRealPath(), file_get_contents($file)];
339+
340+
return $files;
341+
},
342+
[]
343+
);
344+
}
345+
}

src/Console/Command/AddPrefixCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
namespace Humbug\PhpScoper\Console\Command;
1616

1717
use Humbug\PhpScoper\Autoload\ScoperAutoloadGenerator;
18-
use Humbug\PhpScoper\Console\Configuration;
18+
use Humbug\PhpScoper\Configuration;
1919
use Humbug\PhpScoper\Logger\ConsoleLogger;
2020
use Humbug\PhpScoper\Scoper;
2121
use Humbug\PhpScoper\Throwable\Exception\ParsingException;

0 commit comments

Comments
 (0)