Skip to content

Commit f36c818

Browse files
authored
Add finders (#89)
1 parent 72182d9 commit f36c818

File tree

6 files changed

+201
-27
lines changed

6 files changed

+201
-27
lines changed

fixtures/set012/dir/file1.php

Whitespace-only changes.

fixtures/set012/dir/file2.php

Whitespace-only changes.

fixtures/set012/scoper.inc.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
use Symfony\Component\Finder\Finder;
4+
5+
return [
6+
'finders' => [
7+
(new Finder())
8+
->files()
9+
->in(__DIR__.DIRECTORY_SEPARATOR.'dir'),
10+
],
11+
];

src/Console/Command/AddPrefixCommand.php

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,10 +133,12 @@ protected function execute(InputInterface $input, OutputInterface $output)
133133
$input->getArgument(self::PATH_ARG)
134134
);
135135

136+
$paths = $this->retrievePaths($input, $config);
137+
136138
try {
137139
$this->handle->__invoke(
138140
$input->getOption(self::PREFIX_OPT),
139-
$input->getArgument(self::PATH_ARG),
141+
$paths,
140142
$input->getOption(self::OUTPUT_DIR_OPT),
141143
$config->getPatchers(),
142144
$config->getGlobalNamespaceWhitelisters(),
@@ -194,10 +196,6 @@ function (string $path) use ($cwd, $fileSystem) {
194196
$input->getArgument(self::PATH_ARG)
195197
);
196198

197-
if (0 === count($paths)) {
198-
$paths[] = $cwd;
199-
}
200-
201199
$input->setArgument(self::PATH_ARG, $paths);
202200
}
203201

@@ -305,6 +303,31 @@ private function retrieveConfig(InputInterface $input, OutputStyle $io): Configu
305303
return Configuration::load($configFile);
306304
}
307305

306+
/**
307+
* @param InputInterface $input
308+
* @param Configuration $configuration
309+
*
310+
* @return string[] List of absolute paths
311+
*/
312+
private function retrievePaths(InputInterface $input, Configuration $configuration): array
313+
{
314+
$paths = $input->getArgument(self::PATH_ARG);
315+
316+
$finders = $configuration->getFinders();
317+
318+
foreach ($finders as $finder) {
319+
foreach ($finder as $file) {
320+
$paths[] = $file->getRealPath();
321+
}
322+
}
323+
324+
if (0 === count($paths)) {
325+
return [getcwd()];
326+
}
327+
328+
return $paths;
329+
}
330+
308331
private function makeAbsolutePath(string $path): string
309332
{
310333
if (false === $this->fileSystem->isAbsolutePath($path)) {

src/Console/Configuration.php

Lines changed: 112 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,44 @@
1515
namespace Humbug\PhpScoper\Console;
1616

1717
use InvalidArgumentException;
18+
use Symfony\Component\Finder\Finder;
1819

1920
final class Configuration
2021
{
22+
/** @internal */
23+
const FINDER_KEYWORD = 'finders';
24+
25+
/** @internal */
26+
const PATCHERS_KEYWORD = 'patchers';
27+
28+
/** @internal */
29+
const GLOBAL_NAMESPACE_KEYWORD = 'global_namespace_whitelist';
30+
31+
/** @internal */
32+
const KEYWORDS = [
33+
self::FINDER_KEYWORD,
34+
self::PATCHERS_KEYWORD,
35+
self::GLOBAL_NAMESPACE_KEYWORD,
36+
];
37+
2138
private $path;
2239
private $patchers;
40+
private $finders;
2341
private $globalNamespaceWhitelisters;
2442

2543
/**
2644
* @param string|null $path Absolute path to the configuration file loaded
45+
* @param Finder[] $finders
2746
* @param callable[] $patchers List of closures which can alter the content of the files being
2847
* scoped
2948
* @param callable[]|string[] $globalNamespace List of class names from the global namespace that should be scoped
3049
* or closures filtering if the class should be scoped or not
3150
*/
32-
private function __construct(string $path = null, array $patchers, array $globalNamespace)
51+
private function __construct(string $path = null, array $finders, array $patchers, array $globalNamespace)
3352
{
3453
$this->path = $path;
3554
$this->patchers = $patchers;
55+
$this->finders = $finders;
3656
$this->globalNamespaceWhitelisters = $globalNamespace;
3757
}
3858

@@ -44,7 +64,7 @@ private function __construct(string $path = null, array $patchers, array $global
4464
public static function load(string $path = null): self
4565
{
4666
if (null === $path) {
47-
return new self(null, [], []);
67+
return new self(null, [], [], []);
4868
}
4969

5070
$config = include $path;
@@ -58,17 +78,28 @@ public static function load(string $path = null): self
5878
);
5979
}
6080

81+
self::validateConfigKeys($config);
82+
83+
$finders = self::retrieveFinders($config);
6184
$patchers = self::retrievePatchers($config);
6285
$globalNamespace = self::retrieveGlobalNamespaceWhitelisters($config);
6386

64-
return new self($path, $patchers, $globalNamespace);
87+
return new self($path, $finders, $patchers, $globalNamespace);
6588
}
6689

6790
public function getPath(): string
6891
{
6992
return $this->path;
7093
}
7194

95+
/**
96+
* @return Finder[]
97+
*/
98+
public function getFinders(): array
99+
{
100+
return $this->finders;
101+
}
102+
72103
/**
73104
* @return callable[]
74105
*/
@@ -85,13 +116,68 @@ public function getGlobalNamespaceWhitelisters()
85116
return $this->globalNamespaceWhitelisters;
86117
}
87118

119+
private static function validateConfigKeys(array $config)
120+
{
121+
array_map(
122+
['self', 'validateConfigKey'],
123+
array_keys($config)
124+
);
125+
}
126+
127+
private static function validateConfigKey(string $key)
128+
{
129+
if (false === in_array($key, self::KEYWORDS)) {
130+
throw new InvalidArgumentException(
131+
sprintf(
132+
'Invalid configuration key value "%s" found.',
133+
$key
134+
)
135+
);
136+
}
137+
}
138+
139+
private static function retrieveFinders(array $config): array
140+
{
141+
if (false === array_key_exists(self::FINDER_KEYWORD, $config)) {
142+
return [];
143+
}
144+
145+
$finders = $config[self::FINDER_KEYWORD];
146+
147+
if (false === is_array($finders)) {
148+
throw new InvalidArgumentException(
149+
sprintf(
150+
'Expected finders to be an array of "%s", found "%s" instead.',
151+
Finder::class,
152+
gettype($finders)
153+
)
154+
);
155+
}
156+
157+
foreach ($finders as $index => $finder) {
158+
if ($finder instanceof Finder) {
159+
continue;
160+
}
161+
162+
throw new InvalidArgumentException(
163+
sprintf(
164+
'Expected finders to be an array of "%s", the "%d" element is not.',
165+
Finder::class,
166+
$index
167+
)
168+
);
169+
}
170+
171+
return $finders;
172+
}
173+
88174
private static function retrievePatchers(array $config): array
89175
{
90-
if (false === array_key_exists('patchers', $config)) {
176+
if (false === array_key_exists(self::PATCHERS_KEYWORD, $config)) {
91177
return [];
92178
}
93179

94-
$patchers = $config['patchers'];
180+
$patchers = $config[self::PATCHERS_KEYWORD];
95181

96182
if (false === is_array($patchers)) {
97183
throw new InvalidArgumentException(
@@ -103,26 +189,28 @@ private static function retrievePatchers(array $config): array
103189
}
104190

105191
foreach ($patchers as $index => $patcher) {
106-
if (false === is_callable($patcher)) {
107-
throw new InvalidArgumentException(
108-
sprintf(
109-
'Expected patchers to be an array of callables, the "%d" element is not.',
110-
$index
111-
)
112-
);
192+
if (is_callable($patcher)) {
193+
continue;
113194
}
195+
196+
throw new InvalidArgumentException(
197+
sprintf(
198+
'Expected patchers to be an array of callables, the "%d" element is not.',
199+
$index
200+
)
201+
);
114202
}
115203

116204
return $patchers;
117205
}
118206

119207
private static function retrieveGlobalNamespaceWhitelisters(array $config): array
120208
{
121-
if (false === array_key_exists('global_namespace_whitelist', $config)) {
209+
if (false === array_key_exists(self::GLOBAL_NAMESPACE_KEYWORD, $config)) {
122210
return [];
123211
}
124212

125-
$globalNamespace = $config['global_namespace_whitelist'];
213+
$globalNamespace = $config[self::GLOBAL_NAMESPACE_KEYWORD];
126214

127215
if (false === is_array($globalNamespace)) {
128216
throw new InvalidArgumentException(
@@ -134,15 +222,17 @@ private static function retrieveGlobalNamespaceWhitelisters(array $config): arra
134222
}
135223

136224
foreach ($globalNamespace as $index => $className) {
137-
if (false === is_string($className) && false === is_callable($className)) {
138-
throw new InvalidArgumentException(
139-
sprintf(
140-
'Expected "global_namespace" to be an array of callables or strings, the "%d" element '
141-
.'is not.',
142-
$index
143-
)
144-
);
225+
if (is_string($className) || is_callable($className)) {
226+
continue;
145227
}
228+
229+
throw new InvalidArgumentException(
230+
sprintf(
231+
'Expected "global_namespace" to be an array of callables or strings, the "%d" element '
232+
.'is not.',
233+
$index
234+
)
235+
);
146236
}
147237

148238
return $globalNamespace;

tests/Console/Command/AddPrefixCommandTest.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,56 @@ public function test_scope_the_given_paths()
200200
$this->handleProphecy->__invoke(Argument::cetera())->shouldHaveBeenCalledTimes(1);
201201
}
202202

203+
public function test_scope_the_given_paths_and_the_ones_found_by_the_finder()
204+
{
205+
chdir($rootPath = escape_path(self::FIXTURE_PATH.'/set012'));
206+
207+
$input = [
208+
'add-prefix',
209+
'--prefix' => 'MyPrefix',
210+
'paths' => [
211+
escape_path('/path/to/dir1'),
212+
escape_path('/path/to/dir2'),
213+
escape_path('/path/to/file'),
214+
],
215+
'--output-dir' => $this->tmp,
216+
'--no-interaction',
217+
];
218+
219+
$this->fileSystemProphecy->isAbsolutePath('scoper.inc.php')->willReturn(false);
220+
$this->fileSystemProphecy->isAbsolutePath(Argument::cetera())->willReturn(true);
221+
$this->fileSystemProphecy->exists(Argument::cetera())->willReturn(false);
222+
223+
$this->handleProphecy
224+
->__invoke(
225+
'MyPrefix',
226+
[
227+
escape_path('/path/to/dir1'),
228+
escape_path('/path/to/dir2'),
229+
escape_path('/path/to/file'),
230+
realpath(escape_path($rootPath.'/dir/file1.php')),
231+
realpath(escape_path($rootPath.'/dir/file2.php')),
232+
],
233+
$this->tmp,
234+
Argument::type('array'),
235+
Argument::type('array'),
236+
false,
237+
Argument::type(ConsoleLogger::class)
238+
)
239+
->shouldBeCalled()
240+
;
241+
242+
$this->appTester->run($input);
243+
244+
$this->assertSame(0, $this->appTester->getStatusCode());
245+
246+
$this->fileSystemProphecy->isAbsolutePath('scoper.inc.php')->shouldHaveBeenCalledTimes(1);
247+
$this->fileSystemProphecy->isAbsolutePath(Argument::cetera())->shouldHaveBeenCalledTimes(5);
248+
$this->fileSystemProphecy->exists(Argument::cetera())->shouldHaveBeenCalledTimes(1);
249+
250+
$this->handleProphecy->__invoke(Argument::cetera())->shouldHaveBeenCalledTimes(1);
251+
}
252+
203253
public function test_applies_a_random_prefix_when_none_given()
204254
{
205255
$input = [

0 commit comments

Comments
 (0)