Skip to content

Commit 079c5bc

Browse files
authored
Add an init command (#114)
Add an init command to generate a configuration file listing all the configuration keys with their documentations. While running the add-prefix command — provided the `--no-config` option is not used, and no config file is found, the user will be prompted a messager asking whether or not he wishes to generate the init command. For now the init command provides a limited interactive experience as little configuration is convenient to configure from the command line in an easy way. We are also not entirely sure of how those configuration will evolve before reaching a stable version.
1 parent e93a4a0 commit 079c5bc

File tree

15 files changed

+432
-94
lines changed

15 files changed

+432
-94
lines changed

Makefile

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,36 +58,43 @@ tc: vendor/bin/phpunit
5858
phpdbg -qrr -d zend.enable_gc=0 $(PHPUNIT) --coverage-html=dist/coverage --coverage-text
5959

6060
e2e: ## Run end-to-end tests
61-
e2e: e2e_004 e2e_005 e2e_011
61+
e2e: e2e_004 e2e_005 e2e_011 e2e_013
6262

63-
e2e_004: ## Run end-to-end tests for the fixture set 004
63+
e2e_004: ## Run end-to-end tests for the fixture set 004: source code case
6464
e2e_004: bin/php-scoper.phar
65-
php -d zend.enable_gc=0 $(PHPSCOPER) add-prefix --working-dir=fixtures/set004 --output-dir=../../build/set004 --force
65+
php -d zend.enable_gc=0 $(PHPSCOPER) add-prefix --working-dir=fixtures/set004 --output-dir=../../build/set004 --force --no-config --no-interaction
6666
composer --working-dir=build/set004 dump-autoload
6767
php -d zend.enable_gc=0 -d phar.readonly=0 $(BOX) build -c build/set004/box.json.dist
6868

6969
php build/set004/bin/greet.phar > build/set004/output
7070
diff fixtures/set004/expected-output build/set004/output
7171

72-
e2e_005: ## Run end-to-end tests for the fixture set 005
72+
e2e_005: ## Run end-to-end tests for the fixture set 005: third-party code case
7373
e2e_005: bin/php-scoper.phar fixtures/set005/vendor
74-
php -d zend.enable_gc=0 $(PHPSCOPER) add-prefix --working-dir=fixtures/set005 --output-dir=../../build/set005 --force
74+
php -d zend.enable_gc=0 $(PHPSCOPER) add-prefix --working-dir=fixtures/set005 --output-dir=../../build/set005 --force --no-config --no-interaction
7575
composer --working-dir=build/set005 dump-autoload
7676
php -d zend.enable_gc=0 -d phar.readonly=0 $(BOX) build -c build/set005/box.json.dist
7777

7878
php build/set005/bin/greet.phar > build/set005/output
7979
diff fixtures/set005/expected-output build/set005/output
8080

81-
e2e_011: ## Run end-to-end tests for the fixture set 011
81+
e2e_011: ## Run end-to-end tests for the fixture set 011: whitelist case
8282
e2e_011: bin/php-scoper.phar fixtures/set011/vendor
83-
php -d zend.enable_gc=0 $(PHPSCOPER) add-prefix --working-dir=fixtures/set011 --output-dir=../../build/set011 --force
83+
php -d zend.enable_gc=0 $(PHPSCOPER) add-prefix --working-dir=fixtures/set011 --output-dir=../../build/set011 --force --no-interaction
8484
cp -R fixtures/set011/tests build/set011/
8585
composer --working-dir=build/set011 dump-autoload
8686
php -d zend.enable_gc=0 -d phar.readonly=0 $(BOX) build -c build/set011/box.json.dist
8787

8888
php build/set011/bin/greet.phar > build/set011/output
8989
diff fixtures/set011/expected-output build/set011/output
9090

91+
e2e_013: # Run end-to-end tests for the fixture set 013: the init command
92+
e2e_013: bin/php-scoper.phar
93+
rm -rf build/set013
94+
cp -R fixtures/set013 build/set013
95+
$(PHPSCOPER) init --working-dir=build/set013 --no-interaction
96+
diff src/scoper.inc.php.tpl build/set013/scoper.inc.php
97+
9198
tb: ## Run Blackfire profiling
9299
tb: vendor
93100
rm -rf build

README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ potentially very difficult to debug due to dissimilar or unsupported package ver
4444
## Installation
4545

4646

47-
### PHAR (preferred)
47+
### PHAR (preferred) [NOT SUPPORTED YET]
4848

4949
The preferred method of installation is to use the PHP-Scoper PHAR, which can
5050
be downloaded from the most recent [Github Release](releases). Subsequent updates
@@ -103,8 +103,9 @@ PHP-Scoper's makefile.
103103

104104
## Configuration
105105

106-
By default, PHP-Scoper will look for the file `scoper.inc.php` in the current
107-
working directory:
106+
If you need more granular configuration, you can create a `scoper.inc.php` by
107+
running the command `php-scoper init`. A different file/location can be passed
108+
with a `--config` option.
108109

109110
```php
110111
<?php declare(strict_types=1);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?php
2+
3+
return [];
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?php
2+
3+
return [];

fixtures/set013/.gitkeep

Whitespace-only changes.

fixtures/set013/scoper.inc.php

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,79 @@
11
<?php
22

3+
declare(strict_types=1);
4+
5+
use Isolated\Symfony\Component\Finder\Finder;
6+
37
return [
8+
'global_namespace_whitelist' => [
9+
'AppKernel',
10+
function (string $className): bool {
11+
return 'PHPUnit' === substr($className, 0, 6);
12+
},
13+
],
14+
15+
// By default when running php-scoper add-prefix, it will prefix all relevant code found in the current working
16+
// directory. You can however define which files should be scoped by defining a collection of Finders in the
17+
// following configuration key.
18+
//
19+
// For more see: https://github.com/humbug/php-scoper#finders-and-paths
20+
'finders' => [
21+
Finder::create()->files()->in('src'),
22+
Finder::create()
23+
->files()
24+
->ignoreVCS(true)
25+
->notName('/LICENSE|.*\\.md|.*\\.dist|Makefile|composer\\.json|composer\\.lock/')
26+
->exclude([
27+
'doc',
28+
'test',
29+
'test_old',
30+
'tests',
31+
'Tests',
32+
'vendor-bin',
33+
])
34+
->in('vendor'),
35+
Finder::create()->append([
36+
'composer.json',
37+
]),
38+
],
39+
40+
// When scoping PHP files, there will be scenarios where some of the code being scoped indirectly references the
41+
// original namespace. These will include, for example, strings or string manipulations. PHP-Scoper has limited
42+
// support for prefixing such strings. To circumvent that, you can define patchers to manipulate the file to your
43+
// heart contents.
44+
//
45+
// For more see: https://github.com/humbug/php-scoper#patchers
46+
'patchers' => [
47+
function (string $filePath, string $prefix, string $content): string {
48+
// Change the content here.
49+
50+
return $content;
51+
},
52+
],
53+
54+
// By default, PHP-Scoper only prefixes code where the namespace is non-global. In other words, non-namespaced
55+
// code is not prefixed. This leaves the majority of classes, functions and constants in PHP - and most extensions,
56+
// untouched.
57+
//
58+
// This is not necessarily a desirable outcome for vendor dependencies which are also not namespaced. To ensure
59+
// they are isolated, you can configure the following which can be a list of strings or callables taking a string
60+
// (the class name) as an argument and return a boolean (true meaning the class is going to prefixed).
61+
//
62+
// For more, see https://github.com/humbug/php-scoper#global-namespace-whitelisting
63+
'global_namespace_whitelist' => [
64+
'AppKernel',
65+
],
66+
67+
// PHP-Scoper's goal is to make sure that all code for a project lies in a distinct PHP namespace. However, you
68+
// may want to share a common API between the bundled code of your PHAR and the consumer code. For example if
69+
// you have a PHPUnit PHAR with isolated code, you still want the PHAR to be able to understand the
70+
// PHPUnit\Framework\TestCase class.
71+
//
72+
// A way to achieve this is by specifying a list of classes to not prefix with the following configuration key. Note
73+
// that this does not work with functions or constants neither with classes belonging to the global namespace.
74+
//
75+
// Fore more see https://github.com/humbug/php-scoper#whitelist
476
'whitelist' => [
5-
'Acme\Foo',
77+
'PHPUnit\Framework\TestCase',
678
],
779
];

scoper.inc.php

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,6 @@
1515
use Isolated\Symfony\Component\Finder\Finder;
1616

1717
return [
18-
'global_namespace_whitelist' => [
19-
'AppKernel',
20-
function (string $className): bool {
21-
return 'PHPUnit' === substr($className, 0, 6);
22-
},
23-
],
2418
'finders' => [
2519
Finder::create()->files()->in('src'),
2620
Finder::create()

src/Console/Command/AddPrefixCommand.php

Lines changed: 13 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,18 @@
1717
use Humbug\PhpScoper\Console\Configuration;
1818
use Humbug\PhpScoper\Handler\HandleAddPrefix;
1919
use Humbug\PhpScoper\Logger\ConsoleLogger;
20-
use InvalidArgumentException;
21-
use Symfony\Component\Console\Command\Command;
2220
use Symfony\Component\Console\Exception\RuntimeException;
2321
use Symfony\Component\Console\Input\InputArgument;
2422
use Symfony\Component\Console\Input\InputInterface;
2523
use Symfony\Component\Console\Input\InputOption;
24+
use Symfony\Component\Console\Input\StringInput;
2625
use Symfony\Component\Console\Output\OutputInterface;
2726
use Symfony\Component\Console\Style\OutputStyle;
2827
use Symfony\Component\Console\Style\SymfonyStyle;
2928
use Symfony\Component\Filesystem\Filesystem;
3029
use Throwable;
3130

32-
final class AddPrefixCommand extends Command
31+
final class AddPrefixCommand extends BaseCommand
3332
{
3433
private const PATH_ARG = 'paths';
3534
private const PREFIX_OPT = 'prefix';
@@ -39,7 +38,6 @@ final class AddPrefixCommand extends Command
3938
private const CONFIG_FILE_OPT = 'config';
4039
private const CONFIG_FILE_DEFAULT = 'scoper.inc.php';
4140
private const NO_CONFIG_OPT = 'no-config';
42-
private const WORKING_DIR_OPT = 'working-dir';
4341

4442
private $fileSystem;
4543
private $handle;
@@ -60,6 +58,8 @@ public function __construct(Filesystem $fileSystem, HandleAddPrefix $handle)
6058
*/
6159
protected function configure(): void
6260
{
61+
parent::configure();
62+
6363
$this
6464
->setName('add-prefix')
6565
->setDescription('Goes through all the PHP files found in the given paths to apply the given prefix to namespaces & FQNs.')
@@ -113,13 +113,6 @@ protected function configure(): void
113113
),
114114
null
115115
)
116-
->addOption(
117-
self::WORKING_DIR_OPT,
118-
'd',
119-
InputOption::VALUE_REQUIRED,
120-
'If specified, use the given directory as working directory.',
121-
null
122-
)
123116
;
124117
}
125118

@@ -137,7 +130,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
137130
$this->validatePaths($input);
138131
$this->validateOutputDir($input, $io);
139132

140-
$config = $this->retrieveConfig($input, $io);
133+
$config = $this->retrieveConfig($input, $output, $io);
141134

142135
$logger = new ConsoleLogger(
143136
$this->getApplication(),
@@ -173,32 +166,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int
173166
return 0;
174167
}
175168

176-
private function changeWorkingDirectory(InputInterface $input): void
177-
{
178-
$workingDir = $input->getOption(self::WORKING_DIR_OPT);
179-
180-
if (null !== $workingDir) {
181-
if (false === file_exists($workingDir)) {
182-
throw new InvalidArgumentException(
183-
sprintf(
184-
'Could not change the working directory to "%s": directory does not exists.',
185-
$workingDir
186-
)
187-
);
188-
}
189-
190-
if (false === chdir($workingDir)) {
191-
throw new RuntimeException(
192-
sprintf(
193-
'Failed to change the working directory to "%s" from "%s".',
194-
$workingDir,
195-
getcwd()
196-
)
197-
);
198-
}
199-
}
200-
}
201-
202169
private function validatePrefix(InputInterface $input): void
203170
{
204171
$prefix = $input->getOption(self::PREFIX_OPT);
@@ -306,7 +273,7 @@ private function validateOutputDir(InputInterface $input, OutputStyle $io): void
306273
}
307274
}
308275

309-
private function retrieveConfig(InputInterface $input, OutputStyle $io): Configuration
276+
private function retrieveConfig(InputInterface $input, OutputInterface $output, OutputStyle $io): Configuration
310277
{
311278
if ($input->getOption(self::NO_CONFIG_OPT)) {
312279
$io->writeln(
@@ -323,6 +290,13 @@ private function retrieveConfig(InputInterface $input, OutputStyle $io): Configu
323290
$configFile = $this->makeAbsolutePath(self::CONFIG_FILE_DEFAULT);
324291

325292
if (false === file_exists($configFile)) {
293+
$initCommand = $this->getApplication()->find('init');
294+
295+
$initInput = new StringInput('');
296+
$initInput->setInteractive($input->isInteractive());
297+
298+
$initCommand->run($initInput, $output);
299+
326300
$io->writeln(
327301
sprintf(
328302
'Config file "<comment>%s</comment>" not found. Skipping.',
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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\Command;
16+
17+
use InvalidArgumentException;
18+
use Symfony\Component\Console\Command\Command;
19+
use Symfony\Component\Console\Exception\RuntimeException;
20+
use Symfony\Component\Console\Input\InputInterface;
21+
use Symfony\Component\Console\Input\InputOption;
22+
23+
abstract class BaseCommand extends Command
24+
{
25+
private const WORKING_DIR_OPT = 'working-dir';
26+
27+
/**
28+
* @inheritdoc
29+
*/
30+
protected function configure(): void
31+
{
32+
$this->addOption(
33+
self::WORKING_DIR_OPT,
34+
'd',
35+
InputOption::VALUE_REQUIRED,
36+
'If specified, use the given directory as working directory.',
37+
null
38+
);
39+
}
40+
41+
final public function changeWorkingDirectory(InputInterface $input): void
42+
{
43+
$workingDir = $input->getOption(self::WORKING_DIR_OPT);
44+
45+
if (null === $workingDir) {
46+
return;
47+
}
48+
49+
if (false === file_exists($workingDir)) {
50+
throw new InvalidArgumentException(
51+
sprintf(
52+
'Could not change the working directory to "%s": directory does not exists.',
53+
$workingDir
54+
)
55+
);
56+
}
57+
58+
if (false === chdir($workingDir)) {
59+
throw new RuntimeException(
60+
sprintf(
61+
'Failed to change the working directory to "%s" from "%s".',
62+
$workingDir,
63+
getcwd()
64+
)
65+
);
66+
}
67+
}
68+
}

0 commit comments

Comments
 (0)