Skip to content

Commit

Permalink
Rework config and command (humbug#144)
Browse files Browse the repository at this point in the history
Reworked the configuration to make it easier to re-use: the command now
provides the globalNamespaceWhitelister ready for use as well as the
list of files with their contents.

As the handler has a lot of IO-bound dependencies, it is actually very
hard to re-use so it makes more sense to integrate it back to the
command.

This paves the way for box-project/box#31.
  • Loading branch information
theofidry authored Feb 2, 2018
1 parent 32a9034 commit cb82944
Show file tree
Hide file tree
Showing 10 changed files with 948 additions and 1,189 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ fixtures/set011/composer.lock: fixtures/set011/composer.json
fixtures/set015/composer.lock: fixtures/set015/composer.json
@echo fixtures/set005/composer.lock is not up to date.

bin/php-scoper.phar:
bin/php-scoper.phar: bin/php-scoper src vendor vendor-bin/box/vendor scoper.inc.php box.json
$(MAKE) build

box.json:
Expand Down
117 changes: 117 additions & 0 deletions fixtures/set015/composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

168 changes: 137 additions & 31 deletions src/Console/Command/AddPrefixCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@

namespace Humbug\PhpScoper\Console\Command;

use Closure;
use Humbug\PhpScoper\Autoload\ScoperAutoloadGenerator;
use Humbug\PhpScoper\Console\Configuration;
use Humbug\PhpScoper\Handler\HandleAddPrefix;
use Humbug\PhpScoper\Logger\ConsoleLogger;
use Humbug\PhpScoper\Scoper;
use Humbug\PhpScoper\Throwable\Exception\ParsingException;
use Symfony\Component\Console\Exception\RuntimeException;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
Expand All @@ -27,6 +30,7 @@
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Filesystem\Filesystem;
use Throwable;
use function Humbug\PhpScoper\get_common_path;

final class AddPrefixCommand extends BaseCommand
{
Expand All @@ -40,17 +44,17 @@ final class AddPrefixCommand extends BaseCommand
private const NO_CONFIG_OPT = 'no-config';

private $fileSystem;
private $handle;
private $scoper;

/**
* @inheritdoc
*/
public function __construct(Filesystem $fileSystem, HandleAddPrefix $handle)
public function __construct(Filesystem $fileSystem, Scoper $scoper)
{
parent::__construct();

$this->fileSystem = $fileSystem;
$this->handle = $handle;
$this->scoper = $scoper;
}

/**
Expand Down Expand Up @@ -126,6 +130,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$this->validateOutputDir($input, $io);

$config = $this->retrieveConfig($input, $output, $io);
$output = $input->getOption(self::OUTPUT_DIR_OPT);

$logger = new ConsoleLogger(
$this->getApplication(),
Expand All @@ -137,20 +142,20 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$input->getArgument(self::PATH_ARG)
);

$paths = $this->retrievePaths($input, $config);

try {
$this->handle->__invoke(
$this->scopeFiles(
$input->getOption(self::PREFIX_OPT),
$paths,
$input->getOption(self::OUTPUT_DIR_OPT),
$config->getFilesWithContents(),
$output,
$config->getPatchers(),
$config->getWhitelist(),
$config->getGlobalNamespaceWhitelisters(),
$config->getGlobalNamespaceWhitelister(),
$input->getOption(self::STOP_ON_FAILURE_OPT),
$logger
);
} catch (Throwable $throwable) {
$this->fileSystem->remove($output);

$logger->outputScopingEndWithFailure();

throw $throwable;
Expand All @@ -161,6 +166,116 @@ protected function execute(InputInterface $input, OutputInterface $output): int
return 0;
}

private function scopeFiles(
string $prefix,
array $filesWithContents,
string $output,
array $patchers,
array $whitelist,
Closure $globalNamespaceWhitelister,
bool $stopOnFailure,
ConsoleLogger $logger
): void {
// Creates output directory if does not already exist
$this->fileSystem->mkdir($output);

$logger->outputFileCount(count($filesWithContents));

$vendorDirs = [];
$commonPath = get_common_path(array_keys($filesWithContents));

foreach ($filesWithContents as $fileWithContents) {
[$inputFilePath, $inputContents] = $fileWithContents;

$outputFilePath = $output.str_replace($commonPath, '', $inputFilePath);

if (preg_match('~((?:.*)\/vendor)\/.*~', $outputFilePath, $matches)) {
$vendorDirs[$matches[1]] = true;
}

$this->scopeFile(
$inputFilePath,
$inputContents,
$outputFilePath,
$prefix,
$patchers,
$whitelist,
$globalNamespaceWhitelister,
$stopOnFailure,
$logger
);
}

$vendorDirs = array_keys($vendorDirs);

usort(
$vendorDirs,
function ($a, $b) {
return strlen($b) <=> strlen($a);
}
);

$vendorDir = (0 === count($vendorDirs)) ? null : $vendorDirs[0];

if (null !== $vendorDir) {
$autoload = (new ScoperAutoloadGenerator($whitelist))->dump($prefix);

$this->fileSystem->dumpFile($vendorDir.'/scoper-autoload.php', $autoload);
}
}

/**
* @param string $inputFilePath
* @param string $outputFilePath
* @param string $inputContents
* @param string $prefix
* @param callable[] $patchers
* @param string[] $whitelist
* @param callable $globalWhitelister
* @param bool $stopOnFailure
* @param ConsoleLogger $logger
*/
private function scopeFile(
string $inputFilePath,
string $inputContents,
string $outputFilePath,
string $prefix,
array $patchers,
array $whitelist,
callable $globalWhitelister,
bool $stopOnFailure,
ConsoleLogger $logger
): void {
// TODO: use $inputContents instead of doing file_get_contents in the Scopers

try {
$scoppedContent = $this->scoper->scope($inputFilePath, $prefix, $patchers, $whitelist, $globalWhitelister);
} catch (Throwable $error) {
$exception = new ParsingException(
sprintf(
'Could not parse the file "%s".',
$inputFilePath
),
0,
$error
);

if ($stopOnFailure) {
throw $exception;
}

$logger->outputWarnOfFailure($inputFilePath, $exception);

$scoppedContent = file_get_contents($inputFilePath);
}

$this->fileSystem->dumpFile($outputFilePath, $scoppedContent);

if (false === isset($exception)) {
$logger->outputSuccess($inputFilePath);
}
}

private function validatePrefix(InputInterface $input): void
{
$prefix = $input->getOption(self::PREFIX_OPT);
Expand Down Expand Up @@ -276,7 +391,9 @@ private function retrieveConfig(InputInterface $input, OutputInterface $output,
OutputStyle::VERBOSITY_DEBUG
);

return Configuration::load(null);
$config = Configuration::load();

return $this->retrievePaths($input, $config);
}

$configFile = $input->getOption(self::CONFIG_FILE_OPT);
Expand Down Expand Up @@ -309,7 +426,7 @@ private function retrieveConfig(InputInterface $input, OutputInterface $output,
if (false === file_exists($configFile)) {
throw new RuntimeException(
sprintf(
'Could not find the file "<comment>%s</comment>".',
'Could not find the configuration file "<comment>%s</comment>".',
$configFile
)
);
Expand All @@ -323,32 +440,21 @@ private function retrieveConfig(InputInterface $input, OutputInterface $output,
OutputStyle::VERBOSITY_DEBUG
);

return Configuration::load($configFile);
$config = Configuration::load($configFile);

return $this->retrievePaths($input, $config);
}

/**
* @param InputInterface $input
* @param Configuration $configuration
*
* @return string[] List of absolute paths
*/
private function retrievePaths(InputInterface $input, Configuration $configuration): array
private function retrievePaths(InputInterface $input, Configuration $config): Configuration
{
// Checks if there is any path included and if note use the current working directory as the include path
$paths = $input->getArgument(self::PATH_ARG);

$finders = $configuration->getFinders();

foreach ($finders as $finder) {
foreach ($finder as $file) {
$paths[] = $file->getRealPath();
}
}

if (0 === count($paths)) {
return [getcwd()];
if (0 === count($paths) && 0 === count($config->getFilesWithContents())) {
$paths = [getcwd()];
}

return array_unique($paths);
return $config->withPaths($paths);
}

private function makeAbsolutePath(string $path): string
Expand Down
Loading

0 comments on commit cb82944

Please sign in to comment.