diff --git a/.gitattributes b/.gitattributes index b0fe7d91..2c7947c4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,19 +1,25 @@ * text=auto *.php text eol=lf -tests/ export-ignore -build/ export-ignore -.github/ export-ignore +tests/ export-ignore +build/ export-ignore +.github/ export-ignore -.mergify.yml export-ignore -.php_cs export-ignore -.gitattributes export-ignore -.gitignore export-ignore -.travis.yml export-ignore -.editorconfig export-ignore -codecov.yml export-ignore -phpstan.neon export-ignore -phpunit.xml.dist export-ignore -infection.json.dist export-ignore -CONTRIBUTING.md export-ignore -README.md export-ignore +.changelog export-ignore +.editorconfig export-ignore +.gitattributes export-ignore +.gitignore export-ignore +.mergify.yml export-ignore +.nvmrc export-ignore +.php_cs export-ignore +.phpunit.xdebug.filter export-ignore +.textlintrc export-ignore +.travis.yml export-ignore +appveyor.yml export-ignore +CONTRIBUTING.md export-ignore +infection.json.dist export-ignore +package.json export-ignore +package-lock.json export-ignore +phpstan.neon export-ignore +phpunit.xml.dist export-ignore +psalm.xml export-ignore diff --git a/.github/workflows/coding-standard.yml b/.github/workflows/coding-standard.yml index 6f51014d..cd955d55 100644 --- a/.github/workflows/coding-standard.yml +++ b/.github/workflows/coding-standard.yml @@ -11,9 +11,10 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@master with: - php-version: 7.2 - - run: composer global require narrowspark/coding-standard:3.1.0 --no-interaction --prefer-dist --no-progress --profile --no-suggest --optimize-autoloader + php-version: 7.3 + extension-csv: mbstring, xml, ctype, iconv, zip, dom, fileinfo + - run: composer global require narrowspark/automatic-composer-prefetcher:dev-master narrowspark/coding-standard:3.2.0 --no-interaction --no-progress --profile --no-suggest --optimize-autoloader - name: 'lint php code' run: | cd $GITHUB_WORKSPACE - /home/runner/.composer/vendor/bin/php-cs-fixer fix -v --dry-run --stop-on-violation + /home/runner/.composer/vendor/bin/php-cs-fixer fix --config=$GITHUB_WORKSPACE/.php_cs -v --dry-run --stop-on-violation diff --git a/.github/workflows/mutation.yml b/.github/workflows/mutation.yml new file mode 100644 index 00000000..6d3323cd --- /dev/null +++ b/.github/workflows/mutation.yml @@ -0,0 +1,23 @@ +name: 'Mutation testing' + +on: + push: + paths: + - '**.php' + pull_request: + paths: + - '**.php' + +jobs: + php-cs-fixer: + name: 'Infection' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Setup PHP + uses: shivammathur/setup-php@master + with: + php-version: 7.2 + - run: composer install + - name: 'mutation tests' + run: ulimit -n 4096 && phpdbg -qrr ./vendor/bin/infection -vvv --min-msi=40 --min-covered-msi=60 diff --git a/.github/workflows/static-analyze-phpstan.yml b/.github/workflows/static-analyze.yml similarity index 74% rename from .github/workflows/static-analyze-phpstan.yml rename to .github/workflows/static-analyze.yml index 889f719d..ffa87272 100644 --- a/.github/workflows/static-analyze-phpstan.yml +++ b/.github/workflows/static-analyze.yml @@ -1,6 +1,12 @@ -name: 'Static analyzing with phpstan' +name: 'Static analyzing' -on: [push, pull_request] +on: + push: + paths: + - '**.php' + pull_request: + paths: + - '**.php' jobs: php-cs-fixer: diff --git a/.php_cs b/.php_cs index 39e5e5d9..3f98cb1e 100644 --- a/.php_cs +++ b/.php_cs @@ -19,6 +19,7 @@ $config = new Config($header, [ ], 'comment_to_phpdoc' => false, 'final_class' => false, + 'heredoc_indentation' => false, 'PhpCsFixerCustomFixers/no_commented_out_code' => false, ]); diff --git a/.travis.yml b/.travis.yml index b18bdd03..840da09a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -72,12 +72,6 @@ jobs: # script: # - composer psalm - - stage: Mutation - php: 7.2 - env: REMOVE_XDEBUG=true SETUP=high COMPOSER_VERSION=1.9.0 - script: - - ulimit -n 4096 && phpdbg -qrr ./vendor/bin/infection -vvv --min-msi=40 --min-covered-msi=60 - - stage: Coverage php: 7.2 env: REMOVE_XDEBUG=false SETUP=high COMPOSER_VERSION=1.9.0 diff --git a/build/update-mirror-classes.php b/build/update-mirror-classes.php index 46b707de..a5649913 100644 --- a/build/update-mirror-classes.php +++ b/build/update-mirror-classes.php @@ -18,36 +18,36 @@ $fs = new Filesystem(); -foreach (MirrorSettings::OUTPUT_LIST as $path => $namspace) { - $fs->remove($rootDir . \DIRECTORY_SEPARATOR . $path); -} - $comment = MirrorSettings::COMMENT_STRING; $regex = '/namespace ([a-zA-z]*)/s'; $aliasList = []; -foreach (MirrorSettings::MIRROR_LIST as $path => $settings) { - foreach (MirrorSettings::OUTPUT_LIST as $outputPath => $namespace) { +foreach (MirrorSettings::MIRROR_LIST as $list) { + $outputSettings = $list['output']; + + // remove output folder before creating new files. + $fs->remove($rootDir . \DIRECTORY_SEPARATOR . $outputSettings['path']); - $preparedOutputPath = \str_replace("/{$settings['path']}/", '/' . $outputPath.$settings['path'] . '/', $path); + foreach ($list['mirror_list'] as $path => $settings) { + $preparedOutputPath = \str_replace("/{$settings['path']}/", '/' . $outputSettings['path'].$settings['path'] . '/', $path); $fs->copy($path, $preparedOutputPath, true); $content = \file_get_contents($preparedOutputPath); $content = \str_replace(["\nclass", "\nabstract class", "\ninterface"], ["\n{$comment}\nclass", "\n{$comment}\nabstract class", "\n{$comment}\ninterface"], $content); - $mirrorContent = \str_replace($settings['namespace'], $namespace, $content); + $mirrorContent = \str_replace($settings['namespace'], $outputSettings['namespace'], $content); \preg_match($regex, $content, $matches, \PREG_OFFSET_CAPTURE, 0); \preg_match($regex, $mirrorContent, $mirrorMatches, \PREG_OFFSET_CAPTURE, 0); \preg_match('/(abstract class |final class |class |interface |trait )([A-z]*)/s', $content, $classMatches, \PREG_OFFSET_CAPTURE, 0); - if (! array_key_exists($outputPath, $aliasList)) { - $aliasList[$outputPath] = []; + if (! array_key_exists($outputSettings['path'], $aliasList)) { + $aliasList[$outputSettings['path']] = []; } - $aliasList[$outputPath][] = '\class_alias(' . $mirrorMatches[1][0] . '\\' . $classMatches[2][0] . '::class, ' . $matches[1][0] . '\\' . $classMatches[2][0] . '::class);' . "\n"; + $aliasList[$outputSettings['path']][] = 'class_alias(' . $mirrorMatches[1][0] . '\\' . $classMatches[2][0] . '::class, ' . $matches[1][0] . '\\' . $classMatches[2][0] . '::class);' . "\n"; $fs->dumpFile($preparedOutputPath, $mirrorContent); @@ -73,7 +73,7 @@ foreach ($aliasList as $output => $aliases) { $preparedOutputPath = 'src/'.rtrim($output, '/').'/alias.php'; - $fs->dumpFile($rootDir . DIRECTORY_SEPARATOR . $preparedOutputPath, "dumpFile($rootDir . DIRECTORY_SEPARATOR . $preparedOutputPath, "./vendor ./tests ./src/Prefetcher/Common/ + ./src/Security/Common/ ./src/Prefetcher/alias.php + ./src/Security/alias.php ./build/update-mirror-classes.php diff --git a/src/Automatic/AbstractConfigurator.php b/src/Automatic/AbstractConfigurator.php index 37334791..97c88df1 100644 --- a/src/Automatic/AbstractConfigurator.php +++ b/src/Automatic/AbstractConfigurator.php @@ -19,6 +19,9 @@ use Narrowspark\Automatic\Common\Contract\Exception\InvalidArgumentException; use Narrowspark\Automatic\Common\Contract\Package as PackageContract; use Narrowspark\Automatic\Contract\Configurator as MainConfiguratorContract; +use function array_keys; +use function is_subclass_of; +use function sprintf; abstract class AbstractConfigurator implements MainConfiguratorContract { @@ -78,11 +81,11 @@ public function getConfigurators(): array public function add(string $name, string $configurator): void { if ($this->has($name)) { - throw new InvalidArgumentException(\sprintf('Configurator with the name [%s] already exists.', $name)); + throw new InvalidArgumentException(sprintf('Configurator with the name [%s] already exists.', $name)); } - if (! \is_subclass_of($configurator, ConfiguratorContract::class)) { - throw new InvalidArgumentException(\sprintf('The class [%s] must implement the interface [\\%s].', $configurator, ConfiguratorContract::class)); + if (! is_subclass_of($configurator, ConfiguratorContract::class)) { + throw new InvalidArgumentException(sprintf('The class [%s] must implement the interface [\\%s].', $configurator, ConfiguratorContract::class)); } $this->configurators[$name] = $configurator; @@ -101,7 +104,7 @@ public function has(string $name): bool */ public function configure(PackageContract $package): void { - foreach (\array_keys($this->configurators) as $key) { + foreach (array_keys($this->configurators) as $key) { if ($package->hasConfig(ConfiguratorContract::TYPE, $key)) { $this->get($key)->configure($package); } @@ -113,7 +116,7 @@ public function configure(PackageContract $package): void */ public function unconfigure(PackageContract $package): void { - foreach (\array_keys($this->configurators) as $key) { + foreach (array_keys($this->configurators) as $key) { if ($package->hasConfig(ConfiguratorContract::TYPE, $key)) { $this->get($key)->unconfigure($package); } diff --git a/src/Automatic/Automatic.php b/src/Automatic/Automatic.php index cd89b75f..1c562a26 100644 --- a/src/Automatic/Automatic.php +++ b/src/Automatic/Automatic.php @@ -32,9 +32,10 @@ use Composer\Plugin\PluginInterface; use Composer\Script\Event; use Composer\Script\ScriptEvents as ComposerScriptEvents; +use Exception; use FilesystemIterator; +use InvalidArgumentException; use Narrowspark\Automatic\Common\Contract\Container as ContainerContract; -use Narrowspark\Automatic\Common\Contract\Exception\RuntimeException; use Narrowspark\Automatic\Common\Contract\Package as PackageContract; use Narrowspark\Automatic\Common\Traits\ExpandTargetDirTrait; use Narrowspark\Automatic\Common\Traits\GetGenericPropertyReaderTrait; @@ -48,9 +49,29 @@ use RecursiveDirectoryIterator; use RecursiveIteratorIterator; use ReflectionClass; +use ReflectionException; +use SplFileInfo; +use stdClass; use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Filesystem\Filesystem; +use const PHP_INT_MAX; +use function array_key_exists; +use function array_keys; +use function array_map; +use function array_merge; +use function array_unshift; +use function class_exists; +use function count; +use function debug_backtrace; +use function dirname; +use function file_get_contents; +use function in_array; +use function sprintf; +use function str_replace; +use function strlen; +use function substr; +use function version_compare; class Automatic implements EventSubscriberInterface, PluginInterface { @@ -145,7 +166,7 @@ public function getContainer(): ContainerContract */ public static function getAutomaticLockFile(): string { - return \str_replace('composer', self::COMPOSER_EXTRA_KEY, Util::getComposerLockFile()); + return str_replace('composer', self::COMPOSER_EXTRA_KEY, Util::getComposerLockFile()); } /** @@ -166,11 +187,11 @@ public static function getSubscribedEvents(): array PluginEvents::INIT => 'initAutoScripts', ComposerScriptEvents::POST_AUTOLOAD_DUMP => 'onPostAutoloadDump', ComposerScriptEvents::POST_INSTALL_CMD => 'onPostInstall', - ComposerScriptEvents::POST_UPDATE_CMD => [['onPostUpdate', \PHP_INT_MAX], ['onPostUpdatePostMessages', ~\PHP_INT_MAX + 1]], + ComposerScriptEvents::POST_UPDATE_CMD => [['onPostUpdate', PHP_INT_MAX], ['onPostUpdatePostMessages', ~PHP_INT_MAX + 1]], ComposerScriptEvents::POST_CREATE_PROJECT_CMD => [ - ['onPostCreateProject', \PHP_INT_MAX], - ['runSkeletonGenerator', \PHP_INT_MAX - 1], - ['initAutoScripts', \PHP_INT_MAX - 2], + ['onPostCreateProject', PHP_INT_MAX], + ['runSkeletonGenerator', PHP_INT_MAX - 1], + ['initAutoScripts', PHP_INT_MAX - 2], ], ]; } @@ -190,10 +211,10 @@ public function activate(Composer $composer, IOInterface $io): void // to avoid issues when Automatic is upgraded, we load all PHP classes now // that way, we are sure to use all classes from the same version. - foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator(\dirname(__DIR__, 1), FilesystemIterator::SKIP_DOTS)) as $file) { - /** @var \SplFileInfo $file */ - if (\substr($file->getFilename(), -4) === '.php') { - \class_exists(__NAMESPACE__ . \str_replace('/', '\\', \substr($file->getFilename(), \strlen(__DIR__), -4))); + foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator(dirname(__DIR__, 1), FilesystemIterator::SKIP_DOTS)) as $file) { + /** @var SplFileInfo $file */ + if (substr($file->getFilename(), -4) === '.php') { + class_exists(__NAMESPACE__ . str_replace('/', '\\', substr($file->getFilename(), strlen(__DIR__), -4))); } } @@ -214,7 +235,7 @@ public function activate(Composer $composer, IOInterface $io): void 'This file is @generated automatically', ]); - $this->extendComposer(\debug_backtrace()); + $this->extendComposer(debug_backtrace()); $this->container->set(InstallationManager::class, static function (ContainerContract $container) { return new InstallationManager( @@ -261,7 +282,7 @@ public function record(PackageEvent $event): void } if ($package->getName() === self::PACKAGE_NAME) { - \array_unshift($this->operations, $operation); + array_unshift($this->operations, $operation); return; } @@ -273,7 +294,7 @@ public function record(PackageEvent $event): void /** * Add auto-scripts to root composer.json. * - * @throws \Exception + * @throws Exception * * @return void */ @@ -288,31 +309,31 @@ public function initAutoScripts(): void $autoScript = '@' . ScriptEvents::AUTO_SCRIPTS; if (isset($scripts[ComposerScriptEvents::POST_INSTALL_CMD], $scripts[ComposerScriptEvents::POST_UPDATE_CMD]) - && \in_array($autoScript, $scripts[ComposerScriptEvents::POST_INSTALL_CMD], true) - && \in_array($autoScript, $scripts[ComposerScriptEvents::POST_UPDATE_CMD], true) + && in_array($autoScript, $scripts[ComposerScriptEvents::POST_INSTALL_CMD], true) + && in_array($autoScript, $scripts[ComposerScriptEvents::POST_UPDATE_CMD], true) ) { return; } [$json, $manipulator] = Util::getComposerJsonFileAndManipulator(); - if (\count($scripts) === 0) { + if (count($scripts) === 0) { $manipulator->addMainKey('scripts', []); } $manipulator->addSubNode( 'scripts', ComposerScriptEvents::POST_INSTALL_CMD, - \array_merge($scripts[ComposerScriptEvents::POST_INSTALL_CMD] ?? [], [$autoScript]) + array_merge($scripts[ComposerScriptEvents::POST_INSTALL_CMD] ?? [], [$autoScript]) ); $manipulator->addSubNode( 'scripts', ComposerScriptEvents::POST_UPDATE_CMD, - \array_merge($scripts[ComposerScriptEvents::POST_UPDATE_CMD] ?? [], [$autoScript]) + array_merge($scripts[ComposerScriptEvents::POST_UPDATE_CMD] ?? [], [$autoScript]) ); if (! isset($scripts[ScriptEvents::AUTO_SCRIPTS])) { - $manipulator->addSubNode('scripts', ScriptEvents::AUTO_SCRIPTS, new \stdClass()); + $manipulator->addSubNode('scripts', ScriptEvents::AUTO_SCRIPTS, new stdClass()); } $this->container->get(Filesystem::class)->dumpFile($json->getPath(), $manipulator->getContents()); @@ -325,7 +346,7 @@ public function initAutoScripts(): void * * @param \Composer\Script\Event $event * - * @throws \Exception + * @throws Exception */ public function onPostCreateProject(Event $event): void { @@ -358,7 +379,7 @@ public function onPostCreateProject(Event $event): void * * @param \Composer\Script\Event $event * - * @throws \Exception + * @throws Exception * * @return void */ @@ -424,7 +445,7 @@ public function onPreUninstall(PackageEvent $event): void * * @param \Composer\Installer\PackageEvent $event * - * @throws \Exception + * @throws Exception * * @return void */ @@ -440,7 +461,7 @@ public function onPostUninstall(PackageEvent $event): void if ($operation->getPackage()->getName() === self::PACKAGE_NAME) { $scripts = $this->container->get(Composer::class)->getPackage()->getScripts(); - if (\count($scripts) === 0) { + if (count($scripts) === 0) { return; } @@ -475,7 +496,7 @@ public function onPostUninstall(PackageEvent $event): void * * @param \Composer\Script\Event $event * - * @throws \ReflectionException + * @throws ReflectionException * * @return void */ @@ -494,14 +515,14 @@ public function onPostAutoloadDump(Event $event): void foreach ((array) $lock->get(ConfiguratorInstaller::LOCK_KEY) as $packageName => $classList) { foreach ($classMap[$packageName] as $class => $path) { - if (! \class_exists($class)) { - require_once \str_replace('%vendor_path%', $vendorDir, $path); + if (! class_exists($class)) { + require_once str_replace('%vendor_path%', $vendorDir, $path); } } /** @var \Narrowspark\Automatic\Common\Configurator\AbstractConfigurator $class */ foreach ($classList as $class) { - $reflectionClass = new \ReflectionClass($class); + $reflectionClass = new ReflectionClass($class); if ($reflectionClass->isInstantiable() && $reflectionClass->hasMethod('getName')) { $configurator->add($class::getName(), $reflectionClass->getName()); @@ -517,7 +538,7 @@ public function onPostAutoloadDump(Event $event): void * * @param \Composer\Script\Event $event * - * @throws \Exception + * @throws Exception * * @return void */ @@ -532,13 +553,13 @@ public function onPostInstall(Event $event): void * @param \Composer\Script\Event $event * @param array $operations * - * @throws \Exception + * @throws Exception * * @return void */ public function onPostUpdate(Event $event, array $operations = []): void { - if (\count($operations) !== 0) { + if (count($operations) !== 0) { $this->operations = $operations; } @@ -557,23 +578,23 @@ public function onPostUpdate(Event $event, array $operations = []): void } } - $count = \count($packages) + \count($this->uninstallOperations); + $count = count($packages) + count($this->uninstallOperations); - $io->writeError(\sprintf( + $io->writeError(sprintf( 'Automatic operations: %s package%s', $count, $count > 1 ? 's' : '' )); - if (\count($packages) !== 0) { + if (count($packages) !== 0) { $automaticOptions = $this->container->get('composer-extra')[self::COMPOSER_EXTRA_KEY]; $allowInstall = $automaticOptions['allow-auto-install'] ?? false; foreach ($packages as $package) { $prettyName = $package->getPrettyName(); - if (isset($automaticOptions['dont-discover']) && \array_key_exists($package->getName(), $automaticOptions['dont-discover'])) { - $io->write(\sprintf('Package "%s" was ignored.', $prettyName)); + if (isset($automaticOptions['dont-discover']) && array_key_exists($package->getName(), $automaticOptions['dont-discover'])) { + $io->write(sprintf('Package "%s" was ignored.', $prettyName)); return; } @@ -601,7 +622,7 @@ public function onPostUpdate(Event $event, array $operations = []): void } } - $io->writeError(\sprintf(' - Configuring %s', $package->getName())); + $io->writeError(sprintf(' - Configuring %s', $package->getName())); $install->transform($package); @@ -615,14 +636,14 @@ public function onPostUpdate(Event $event, array $operations = []): void } } - if (\count($this->uninstallOperations) !== 0) { + if (count($this->uninstallOperations) !== 0) { foreach ($this->uninstallOperations as $name) { - $io->writeError(\sprintf(' - Unconfiguring %s', $name)); + $io->writeError(sprintf(' - Unconfiguring %s', $name)); } } if ($count !== 0) { - \array_unshift( + array_unshift( $this->postMessages, '', 'Some files may have been created or updated to configure your new packages.', @@ -645,7 +666,7 @@ public function onPostUpdate(Event $event, array $operations = []): void * * @param \Composer\Script\Event $event * - * @throws \ReflectionException + * @throws ReflectionException * * @return void */ @@ -661,7 +682,7 @@ public function executeAutoScripts(Event $event): void return; } - if (\in_array(true, \array_map('\is_numeric', \array_keys($jsonContents['scripts'][ScriptEvents::AUTO_SCRIPTS])), true)) { + if (in_array(true, array_map('\is_numeric', array_keys($jsonContents['scripts'][ScriptEvents::AUTO_SCRIPTS])), true)) { return; } @@ -672,7 +693,7 @@ public function executeAutoScripts(Event $event): void foreach ((array) $this->container->get(Lock::class)->get(ScriptExecutor::TYPE) as $extenders) { foreach ($extenders as $class => $path) { - if (! \class_exists($class)) { + if (! class_exists($class)) { require_once $path; } @@ -714,14 +735,14 @@ private function isDevPackage($event, string $packageName): bool /** * Update composer.lock file with the composer.json change. * - * @throws \Exception + * @throws Exception * * @return void */ private function updateComposerLock(): void { $composerLockPath = Util::getComposerLockFile(); - $composerJson = \file_get_contents(Factory::getComposerFile()); + $composerJson = file_get_contents(Factory::getComposerFile()); $composer = $this->container->get(Composer::class); $lockFile = new JsonFile($composerLockPath, null, $this->container->get(IOInterface::class)); @@ -742,7 +763,7 @@ private function updateComposerLock(): void /** * Add extra option "allow-auto-install" to composer.json. * - * @throws \InvalidArgumentException + * @throws InvalidArgumentException * * @return void */ @@ -769,8 +790,8 @@ private function getErrorMessage(IOInterface $io): ?string return 'You must enable the openssl extension in your [php.ini] file'; } - if (\version_compare(self::getComposerVersion(), '1.7.0', '<')) { - return \sprintf('Your version "%s" of Composer is too old; Please upgrade', Composer::VERSION); + if (version_compare(Util::getComposerVersion(), '1.7.0', '<')) { + return sprintf('Your version "%s" of Composer is too old; Please upgrade', Composer::VERSION); } // @codeCoverageIgnoreEnd @@ -823,12 +844,12 @@ private function extendComposer($backtrace): void /** @var null|string $command */ $command = $input->getFirstArgument(); $command = $command !== null ? $app->find($command)->getName() : null; - } catch (\InvalidArgumentException $e) { + } catch (InvalidArgumentException $e) { $command = null; } if ($command === 'create-project') { - if (\version_compare(self::getComposerVersion(), '1.7.0', '>=')) { + if (version_compare(Util::getComposerVersion(), '1.7.0', '>=')) { $input->setOption('remove-vcs', true); } else { $input->setInteractive(false); @@ -844,28 +865,4 @@ private function extendComposer($backtrace): void break; } } - - /** - * Get the composer version. - * - * @throws \Narrowspark\Automatic\Common\Contract\Exception\RuntimeException - * - * @return string - */ - private static function getComposerVersion(): string - { - \preg_match('/\d+.\d+.\d+/m', Composer::VERSION, $matches); - - if ($matches !== null) { - return $matches[0]; - } - - \preg_match('/\d+.\d+.\d+/m', Composer::BRANCH_ALIAS_VERSION, $matches); - - if ($matches !== null) { - return $matches[0]; - } - - throw new RuntimeException('No composer version found.'); - } } diff --git a/src/Automatic/Configurator/ComposerAutoScriptsConfigurator.php b/src/Automatic/Configurator/ComposerAutoScriptsConfigurator.php index 56666627..37e24820 100644 --- a/src/Automatic/Configurator/ComposerAutoScriptsConfigurator.php +++ b/src/Automatic/Configurator/ComposerAutoScriptsConfigurator.php @@ -19,6 +19,8 @@ use Narrowspark\Automatic\Common\Contract\Configurator as ConfiguratorContract; use Narrowspark\Automatic\Common\Contract\Package as PackageContract; use Narrowspark\Automatic\Common\Util; +use function array_keys; +use function array_merge; final class ComposerAutoScriptsConfigurator extends AbstractConfigurator { @@ -61,7 +63,7 @@ public function configure(PackageContract $package): void { $autoScripts = $this->getComposerAutoScripts(); - $autoScripts = \array_merge($autoScripts, (array) $package->getConfig(ConfiguratorContract::TYPE, self::getName())); + $autoScripts = array_merge($autoScripts, (array) $package->getConfig(ConfiguratorContract::TYPE, self::getName())); $this->manipulateAndWrite($autoScripts); } @@ -73,7 +75,7 @@ public function unconfigure(PackageContract $package): void { $autoScripts = $this->getComposerAutoScripts(); - foreach (\array_keys((array) $package->getConfig(ConfiguratorContract::TYPE, self::getName())) as $cmd) { + foreach (array_keys((array) $package->getConfig(ConfiguratorContract::TYPE, self::getName())) as $cmd) { unset($autoScripts[$cmd]); } diff --git a/src/Automatic/Configurator/ComposerScriptsConfigurator.php b/src/Automatic/Configurator/ComposerScriptsConfigurator.php index ba43f75d..e8d4b5f5 100644 --- a/src/Automatic/Configurator/ComposerScriptsConfigurator.php +++ b/src/Automatic/Configurator/ComposerScriptsConfigurator.php @@ -24,6 +24,12 @@ use Narrowspark\Automatic\Common\Contract\Package as PackageContract; use Narrowspark\Automatic\Common\Util; use Narrowspark\Automatic\QuestionFactory; +use function array_flip; +use function array_keys; +use function array_merge; +use function count; +use function implode; +use function sprintf; final class ComposerScriptsConfigurator extends AbstractConfigurator { @@ -103,17 +109,17 @@ public function configure(PackageContract $package): void { $packageEvents = (array) $package->getConfig(ConfiguratorContract::TYPE, self::getName()); - if (\count($packageEvents) === 0) { + if (count($packageEvents) === 0) { return; } $composerContent = $this->json->read(); if (isset($composerContent['extra'][Automatic::COMPOSER_EXTRA_KEY][self::COMPOSER_EXTRA_KEY][self::BLACKLIST])) { - $blackList = \array_flip($composerContent['extra'][Automatic::COMPOSER_EXTRA_KEY][self::COMPOSER_EXTRA_KEY][self::BLACKLIST]); + $blackList = array_flip($composerContent['extra'][Automatic::COMPOSER_EXTRA_KEY][self::COMPOSER_EXTRA_KEY][self::BLACKLIST]); if (isset($blackList[$package->getName()])) { - $this->io->write(\sprintf('Composer scripts for [%s] skipped, because it was found in the [%s]', $package->getPrettyName(), self::BLACKLIST)); + $this->io->write(sprintf('Composer scripts for [%s] skipped, because it was found in the [%s]', $package->getPrettyName(), self::BLACKLIST)); return; } @@ -131,9 +137,9 @@ public function configure(PackageContract $package): void $allowed = false; - if (\count($allowedEvents) !== 0) { + if (count($allowedEvents) !== 0) { if (isset($composerContent['extra'][Automatic::COMPOSER_EXTRA_KEY][self::COMPOSER_EXTRA_KEY][self::WHITELIST])) { - $whiteList = \array_flip($composerContent['extra'][Automatic::COMPOSER_EXTRA_KEY][self::COMPOSER_EXTRA_KEY][self::WHITELIST]); + $whiteList = array_flip($composerContent['extra'][Automatic::COMPOSER_EXTRA_KEY][self::COMPOSER_EXTRA_KEY][self::WHITELIST]); if (isset($whiteList[$package->getName()])) { $allowed = true; @@ -145,10 +151,10 @@ public function configure(PackageContract $package): void } } - if (\count($packageEvents) !== 0) { - $this->io->write(\sprintf( + if (count($packageEvents) !== 0) { + $this->io->write(sprintf( ' Found not allowed composer events [%s] in [%s]' . "\n", - \implode(', ', \array_keys($packageEvents)), + implode(', ', array_keys($packageEvents)), $package->getName() )); } @@ -158,14 +164,14 @@ public function configure(PackageContract $package): void 'extra', Automatic::COMPOSER_EXTRA_KEY, [ - self::COMPOSER_EXTRA_KEY => \array_merge( + self::COMPOSER_EXTRA_KEY => array_merge( $composerContent['extra'][Automatic::COMPOSER_EXTRA_KEY][self::COMPOSER_EXTRA_KEY] ?? [], [self::WHITELIST => [$package->getName()]] ), ] ); - $this->manipulateAndWrite(\array_merge($this->getComposerScripts(), $allowedEvents)); + $this->manipulateAndWrite(array_merge($this->getComposerScripts(), $allowedEvents)); } } @@ -187,7 +193,7 @@ public function unconfigure(PackageContract $package): void $composerContent = $this->json->read(); if (isset($composerContent['extra'][Automatic::COMPOSER_EXTRA_KEY][self::COMPOSER_EXTRA_KEY][self::WHITELIST])) { - $whiteList = \array_flip($composerContent['extra'][Automatic::COMPOSER_EXTRA_KEY][self::COMPOSER_EXTRA_KEY][self::WHITELIST]); + $whiteList = array_flip($composerContent['extra'][Automatic::COMPOSER_EXTRA_KEY][self::COMPOSER_EXTRA_KEY][self::WHITELIST]); if (isset($whiteList[$package->getName()])) { unset($composerContent['extra'][Automatic::COMPOSER_EXTRA_KEY][self::COMPOSER_EXTRA_KEY][self::WHITELIST][$whiteList[$package->getName()]]); diff --git a/src/Automatic/Configurator/CopyFromPackageConfigurator.php b/src/Automatic/Configurator/CopyFromPackageConfigurator.php index e9d42bac..f5eeb8b1 100644 --- a/src/Automatic/Configurator/CopyFromPackageConfigurator.php +++ b/src/Automatic/Configurator/CopyFromPackageConfigurator.php @@ -17,6 +17,11 @@ use Narrowspark\Automatic\Common\Contract\Configurator as ConfiguratorContract; use Narrowspark\Automatic\Common\Contract\Package as PackageContract; use Symfony\Component\Filesystem\Exception\IOException; +use const DIRECTORY_SEPARATOR; +use function is_dir; +use function is_file; +use function sprintf; +use function str_replace; final class CopyFromPackageConfigurator extends AbstractConfigurator { @@ -38,13 +43,13 @@ public function configure(PackageContract $package): void foreach ((array) $package->getConfig(ConfiguratorContract::TYPE, self::getName()) as $from => $to) { $target = self::expandTargetDir($this->options, $to); $from = $this->path->concatenate([ - $this->composer->getConfig()->get('vendor-dir') . \DIRECTORY_SEPARATOR, - \str_replace('/', \DIRECTORY_SEPARATOR, $package->getPrettyName()) . \DIRECTORY_SEPARATOR, + $this->composer->getConfig()->get('vendor-dir') . DIRECTORY_SEPARATOR, + str_replace('/', DIRECTORY_SEPARATOR, $package->getPrettyName()) . DIRECTORY_SEPARATOR, $from, ]); - if (! \is_dir($from) && ! \is_file($from)) { - $this->write(\sprintf( + if (! is_dir($from) && ! is_file($from)) { + $this->write(sprintf( 'Failed to find the from folder or file path for "%s" in "%s" package', $from, $package->getName() @@ -57,7 +62,7 @@ public function configure(PackageContract $package): void /* @var string $functionName */ $functionName = 'copy'; - if (\is_dir($from)) { + if (is_dir($from)) { $functionName = 'mirror'; } @@ -66,9 +71,9 @@ public function configure(PackageContract $package): void $this->path->concatenate([$this->path->getWorkingDir(), $target]) ); - $this->write(\sprintf('Created "%s"', $this->path->relativize($target))); + $this->write(sprintf('Created "%s"', $this->path->relativize($target))); } catch (IOException $exception) { - $this->write(\sprintf( + $this->write(sprintf( 'Failed to create "%s"; Error message: %s', $this->path->relativize($target), $exception->getMessage() @@ -90,9 +95,9 @@ public function unconfigure(PackageContract $package): void try { $this->filesystem->remove($this->path->concatenate([$this->path->getWorkingDir(), $source])); - $this->write(\sprintf('Removed "%s"', $this->path->relativize($source))); + $this->write(sprintf('Removed "%s"', $this->path->relativize($source))); } catch (IOException $exception) { - $this->write(\sprintf( + $this->write(sprintf( 'Failed to remove "%s"; Error message: %s', $this->path->relativize($source), $exception->getMessage() diff --git a/src/Automatic/Configurator/EnvConfigurator.php b/src/Automatic/Configurator/EnvConfigurator.php index 577af98d..d91e28cf 100644 --- a/src/Automatic/Configurator/EnvConfigurator.php +++ b/src/Automatic/Configurator/EnvConfigurator.php @@ -17,6 +17,21 @@ use Narrowspark\Automatic\Common\Contract\Configurator as ConfiguratorContract; use Narrowspark\Automatic\Common\Contract\Package as PackageContract; use Narrowspark\Automatic\Configurator\Traits\AppendToFileTrait; +use const DIRECTORY_SEPARATOR; +use const FILTER_NULL_ON_FAILURE; +use const FILTER_VALIDATE_BOOLEAN; +use function file_get_contents; +use function filter_var; +use function is_file; +use function is_numeric; +use function is_string; +use function preg_replace; +use function sprintf; +use function str_replace; +use function strpbrk; +use function strpos; +use function substr; +use function var_export; final class EnvConfigurator extends AbstractConfigurator { @@ -37,42 +52,42 @@ public function configure(PackageContract $package): void { $this->write('Added environment variable defaults'); - $distenv = $this->path->getWorkingDir() . \DIRECTORY_SEPARATOR . '.env.dist'; + $distenv = $this->path->getWorkingDir() . DIRECTORY_SEPARATOR . '.env.dist'; - if (! \is_file($distenv) || $this->isFileMarked($package->getPrettyName(), $distenv)) { + if (! is_file($distenv) || $this->isFileMarked($package->getPrettyName(), $distenv)) { return; } $data = ''; foreach ((array) $package->getConfig(ConfiguratorContract::TYPE, self::getName()) as $key => $value) { - if (\strpos($key, '#') === 0 && \is_numeric(\substr($key, 1))) { + if (strpos($key, '#') === 0 && is_numeric(substr($key, 1))) { $data .= '# ' . $value . "\n"; continue; } - if (\is_string($value)) { + if (is_string($value)) { $value = self::expandTargetDir($this->options, $value); - } elseif (\filter_var($value, \FILTER_VALIDATE_BOOLEAN, \FILTER_NULL_ON_FAILURE) !== null) { - $value = \var_export($value, true); + } elseif (filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) !== null) { + $value = var_export($value, true); } - if (\strpbrk($value, " \t\n&!\"") !== false) { - $value = '"' . \str_replace(['\\', '"', "\t", "\n"], ['\\\\', '\\"', '\t', '\n'], $value) . '"'; + if (strpbrk($value, " \t\n&!\"") !== false) { + $value = '"' . str_replace(['\\', '"', "\t", "\n"], ['\\\\', '\\"', '\t', '\n'], $value) . '"'; } $data .= $key . '=' . $value . "\n"; } - if (! $this->filesystem->exists($this->path->getWorkingDir() . \DIRECTORY_SEPARATOR . '.env')) { - $this->filesystem->copy($distenv, $this->path->getWorkingDir() . \DIRECTORY_SEPARATOR . '.env'); + if (! $this->filesystem->exists($this->path->getWorkingDir() . DIRECTORY_SEPARATOR . '.env')) { + $this->filesystem->copy($distenv, $this->path->getWorkingDir() . DIRECTORY_SEPARATOR . '.env'); } $data = $this->markData($package->getPrettyName(), $data); $this->appendToFile($distenv, $data); - $this->appendToFile($this->path->getWorkingDir() . \DIRECTORY_SEPARATOR . '.env', $data); + $this->appendToFile($this->path->getWorkingDir() . DIRECTORY_SEPARATOR . '.env', $data); } /** @@ -83,7 +98,7 @@ public function unconfigure(PackageContract $package): void $this->write('Remove environment variables'); foreach (['.env', '.env.dist'] as $file) { - $env = $this->path->getWorkingDir() . \DIRECTORY_SEPARATOR . $file; + $env = $this->path->getWorkingDir() . DIRECTORY_SEPARATOR . $file; // @codeCoverageIgnoreStart if (! $this->filesystem->exists($env)) { @@ -91,10 +106,10 @@ public function unconfigure(PackageContract $package): void } // @codeCoverageIgnoreEnd $count = 0; - $contents = \preg_replace( - \sprintf('{###> %s ###.*###< %s ###%s+}s', $package->getPrettyName(), $package->getPrettyName(), "\n"), + $contents = preg_replace( + sprintf('{###> %s ###.*###< %s ###%s+}s', $package->getPrettyName(), $package->getPrettyName(), "\n"), '', - (string) \file_get_contents($env), + (string) file_get_contents($env), -1, $count ); @@ -105,7 +120,7 @@ public function unconfigure(PackageContract $package): void } // @codeCoverageIgnoreEnd - $this->write(\sprintf('Removing environment variables from %s', $file)); + $this->write(sprintf('Removing environment variables from %s', $file)); $this->filesystem->dumpFile($env, (string) $contents); } diff --git a/src/Automatic/Configurator/GitIgnoreConfigurator.php b/src/Automatic/Configurator/GitIgnoreConfigurator.php index cc692097..78dcb587 100644 --- a/src/Automatic/Configurator/GitIgnoreConfigurator.php +++ b/src/Automatic/Configurator/GitIgnoreConfigurator.php @@ -17,6 +17,11 @@ use Narrowspark\Automatic\Common\Contract\Configurator as ConfiguratorContract; use Narrowspark\Automatic\Common\Contract\Package as PackageContract; use Narrowspark\Automatic\Configurator\Traits\AppendToFileTrait; +use const DIRECTORY_SEPARATOR; +use function file_get_contents; +use function ltrim; +use function preg_replace; +use function sprintf; final class GitIgnoreConfigurator extends AbstractConfigurator { @@ -37,7 +42,7 @@ public function configure(PackageContract $package): void { $this->write('Added entries to .gitignore'); - $gitignore = $this->path->getWorkingDir() . \DIRECTORY_SEPARATOR . '.gitignore'; + $gitignore = $this->path->getWorkingDir() . DIRECTORY_SEPARATOR . '.gitignore'; if ($this->isFileMarked($package->getPrettyName(), $gitignore)) { return; @@ -50,7 +55,7 @@ public function configure(PackageContract $package): void $data .= $value . "\n"; } - $this->appendToFile($gitignore, "\n" . \ltrim($this->markData($package->getPrettyName(), $data), "\r\n")); + $this->appendToFile($gitignore, "\n" . ltrim($this->markData($package->getPrettyName(), $data), "\r\n")); } /** @@ -58,7 +63,7 @@ public function configure(PackageContract $package): void */ public function unconfigure(PackageContract $package): void { - $file = $this->path->getWorkingDir() . \DIRECTORY_SEPARATOR . '.gitignore'; + $file = $this->path->getWorkingDir() . DIRECTORY_SEPARATOR . '.gitignore'; // @codeCoverageIgnoreStart if (! $this->filesystem->exists($file)) { @@ -66,10 +71,10 @@ public function unconfigure(PackageContract $package): void } // @codeCoverageIgnoreEnd $count = 0; - $contents = \preg_replace( - \sprintf('{###> %s ###.*###< %s ###%s+}s', $package->getPrettyName(), $package->getPrettyName(), "\n"), + $contents = preg_replace( + sprintf('{###> %s ###.*###< %s ###%s+}s', $package->getPrettyName(), $package->getPrettyName(), "\n"), "\n", - (string) \file_get_contents($file), + (string) file_get_contents($file), -1, $count ); @@ -80,6 +85,6 @@ public function unconfigure(PackageContract $package): void $this->write('Removed entries in .gitignore'); - $this->filesystem->dumpFile($file, \ltrim((string) $contents, "\r\n")); + $this->filesystem->dumpFile($file, ltrim((string) $contents, "\r\n")); } } diff --git a/src/Automatic/Configurator/Traits/AppendToFileTrait.php b/src/Automatic/Configurator/Traits/AppendToFileTrait.php index 5db9b2aa..6d0b721c 100644 --- a/src/Automatic/Configurator/Traits/AppendToFileTrait.php +++ b/src/Automatic/Configurator/Traits/AppendToFileTrait.php @@ -15,6 +15,13 @@ use Symfony\Component\Filesystem\Exception\IOException; use Symfony\Component\Filesystem\Filesystem; +use const FILE_APPEND; +use function dirname; +use function file_put_contents; +use function is_dir; +use function is_writable; +use function method_exists; +use function sprintf; /** * @property Filesystem $filesystem @@ -35,24 +42,24 @@ trait AppendToFileTrait */ public function appendToFile(string $filename, string $content): void { - if (\method_exists($this->filesystem, 'appendToFile')) { + if (method_exists($this->filesystem, 'appendToFile')) { $this->filesystem->appendToFile($filename, $content); return; } // @codeCoverageIgnoreStart - $dir = \dirname($filename); + $dir = dirname($filename); - if (! \is_dir($dir)) { + if (! is_dir($dir)) { $this->filesystem->mkdir($dir); } - if (! \is_writable($dir)) { - throw new IOException(\sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir); + if (! is_writable($dir)) { + throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir); } - if (false === @\file_put_contents($filename, $content, \FILE_APPEND)) { - throw new IOException(\sprintf('Failed to write file "%s".', $filename), 0, null, $filename); + if (false === @file_put_contents($filename, $content, FILE_APPEND)) { + throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename); } // @codeCoverageIgnoreEnd } diff --git a/src/Automatic/Container.php b/src/Automatic/Container.php index c3e63cee..d44ac25c 100644 --- a/src/Automatic/Container.php +++ b/src/Automatic/Container.php @@ -31,6 +31,8 @@ use Narrowspark\Automatic\ScriptExtender\ScriptExtender; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Filesystem\Filesystem; +use function array_merge; +use function rtrim; /** * @internal @@ -60,10 +62,10 @@ public function __construct(Composer $composer, IOInterface $io) return $io; }, 'vendor-dir' => static function (ContainerContract $container) { - return \rtrim($container->get(Config::class)->get('vendor-dir'), '/'); + return rtrim($container->get(Config::class)->get('vendor-dir'), '/'); }, 'composer-extra' => static function (ContainerContract $container) { - return \array_merge( + return array_merge( [ Automatic::COMPOSER_EXTRA_KEY => [ 'allow-auto-install' => false, diff --git a/src/Automatic/Installer/AbstractInstaller.php b/src/Automatic/Installer/AbstractInstaller.php index a47883ae..8ecc3291 100644 --- a/src/Automatic/Installer/AbstractInstaller.php +++ b/src/Automatic/Installer/AbstractInstaller.php @@ -22,6 +22,10 @@ use Narrowspark\Automatic\Common\ClassFinder; use Narrowspark\Automatic\Common\Contract\Exception\UnexpectedValueException; use Narrowspark\Automatic\Lock; +use function array_map; +use function count; +use function sprintf; +use function str_replace; abstract class AbstractInstaller extends LibraryInstaller { @@ -76,8 +80,8 @@ public function install(InstalledRepositoryInterface $repo, PackageInterface $pa { $autoload = $package->getAutoload(); - if (\count($autoload['psr-4']) === 0) { - throw new UnexpectedValueException(\sprintf('Error while installing [%s], %s packages should have a namespace defined in their psr4 key to be usable.', $package->getPrettyName(), static::TYPE)); + if (count($autoload['psr-4']) === 0) { + throw new UnexpectedValueException(sprintf('Error while installing [%s], %s packages should have a namespace defined in their psr4 key to be usable.', $package->getPrettyName(), static::TYPE)); } parent::install($repo, $package); @@ -138,7 +142,7 @@ protected function findClasses(array $autoload, PackageInterface $package): ?arr $classes[] = $class; } - if (\count($classes) === 0) { + if (count($classes) === 0) { return null; } @@ -186,8 +190,8 @@ abstract protected function removeFromLock(PackageInterface $package, string $ke */ protected function addToClassMap(PackageInterface $package): void { - $classMap = \array_map(function (string $value) { - return \str_replace($this->vendorDir, '%vendor_path%', $value); + $classMap = array_map(function (string $value) { + return str_replace($this->vendorDir, '%vendor_path%', $value); }, $this->loader->getAll()); $this->lock->addSub(Automatic::LOCK_CLASSMAP, $package->getName(), $classMap); diff --git a/src/Automatic/Installer/InstallationManager.php b/src/Automatic/Installer/InstallationManager.php index fdb2da77..8493c68a 100644 --- a/src/Automatic/Installer/InstallationManager.php +++ b/src/Automatic/Installer/InstallationManager.php @@ -14,7 +14,16 @@ namespace Narrowspark\Automatic\Installer; use Composer\Factory; +use Exception; use Narrowspark\Automatic\Common\Installer\AbstractInstallationManager; +use function array_keys; +use function array_merge; +use function count; +use function in_array; +use function sprintf; +use function strpos; +use function strtolower; +use function trim; class InstallationManager extends AbstractInstallationManager { @@ -41,18 +50,18 @@ public function install(array $requires, array $devRequires = []): void $rootPackages = []; foreach ($this->getRootRequires() as $link) { - $rootPackages[\strtolower($link->getTarget())] = (string) $link->getConstraint(); + $rootPackages[strtolower($link->getTarget())] = (string) $link->getConstraint(); } $requiresToInstall = $this->preparePackagesToInstall($requires, $rootPackages); $devRequiresToInstall = $this->preparePackagesToInstall($devRequires, $rootPackages); - if ((\count($requiresToInstall) + \count($devRequiresToInstall)) !== 0) { + if ((count($requiresToInstall) + count($devRequiresToInstall)) !== 0) { $this->updateComposerJson($requiresToInstall, $devRequiresToInstall, self::ADD); $this->updateRootComposerJson($requiresToInstall, $devRequiresToInstall, self::ADD); - $this->whiteList = \array_keys(\array_merge($requiresToInstall, $devRequiresToInstall)); + $this->whiteList = array_keys(array_merge($requiresToInstall, $devRequiresToInstall)); } } @@ -64,7 +73,7 @@ public function install(array $requires, array $devRequires = []): void * * @throws \Narrowspark\Automatic\Common\Contract\Exception\RuntimeException * @throws \Narrowspark\Automatic\Common\Contract\Exception\InvalidArgumentException - * @throws \Exception + * @throws Exception * * @return void */ @@ -75,10 +84,10 @@ public function uninstall(array $requires, array $devRequires = []): void $this->updateComposerJson($requires, $devRequires, self::REMOVE); - $whiteList = \array_merge($requires, $devRequires); + $whiteList = array_merge($requires, $devRequires); foreach ($this->localRepository->getPackages() as $localPackage) { - $mixedRequires = \array_merge($localPackage->getRequires(), $localPackage->getDevRequires()); + $mixedRequires = array_merge($localPackage->getRequires(), $localPackage->getDevRequires()); foreach ($whiteList as $whitelistPackageName => $version) { if (isset($mixedRequires[$whitelistPackageName])) { @@ -93,7 +102,7 @@ public function uninstall(array $requires, array $devRequires = []): void } /** - * @throws \Exception + * @throws Exception * * @return int */ @@ -135,11 +144,11 @@ protected function preparePackagesToInstall(array $requires, array $rootPackages // Check if package is currently installed, if so, use installed constraint. if (isset($toInstall[$packageName])) { $version = $toInstall[$packageName]; - $constraint = \strpos($version, 'dev') === false ? '^' . $version : $version; + $constraint = strpos($version, 'dev') === false ? '^' . $version : $version; $toInstall[$packageName] = $constraint; - $this->io->write(\sprintf( + $this->io->write(sprintf( 'Added package %s to composer.json with constraint %s;' . ' to upgrade, run composer require %s:VERSION', $packageName, @@ -150,14 +159,14 @@ protected function preparePackagesToInstall(array $requires, array $rootPackages continue; } - if (\in_array($version, ['*', null, ''], true)) { + if (in_array($version, ['*', null, ''], true)) { $constraint = $this->io->askAndValidate( - \sprintf( + sprintf( 'Enter the version of %s to require (or leave blank to use the latest version): ', $packageName ), static function (string $input) { - return \trim($input) ?? false; + return trim($input) ?? false; } ); @@ -168,7 +177,7 @@ static function (string $input) { $constraint = $version; } - $this->io->writeError(\sprintf('Using version %s for %s', $constraint, $packageName)); + $this->io->writeError(sprintf('Using version %s for %s', $constraint, $packageName)); $toInstall[$packageName] = $constraint; } diff --git a/src/Automatic/Lock.php b/src/Automatic/Lock.php index 80a0d06e..9499829f 100644 --- a/src/Automatic/Lock.php +++ b/src/Automatic/Lock.php @@ -14,7 +14,12 @@ namespace Narrowspark\Automatic; use Composer\Json\JsonFile; +use Exception; use Narrowspark\Automatic\Common\Contract\Resettable as ResettableContract; +use function array_key_exists; +use function count; +use function is_array; +use function ksort; class Lock implements ResettableContract { @@ -56,14 +61,14 @@ public function __construct(string $lockFile) */ public function has(string $mainKey, ?string $name = null): bool { - $mainCheck = \array_key_exists($mainKey, $this->lock); + $mainCheck = array_key_exists($mainKey, $this->lock); if ($name === null) { return $mainCheck; } - if ($mainCheck === true && \is_array($this->lock[$mainKey])) { - return \array_key_exists($name, $this->lock[$mainKey]); + if ($mainCheck === true && is_array($this->lock[$mainKey])) { + return array_key_exists($name, $this->lock[$mainKey]); } return false; @@ -93,7 +98,7 @@ public function add(string $mainKey, $data): void */ public function addSub(string $mainKey, string $name, $data): void { - if (! \array_key_exists($mainKey, $this->lock)) { + if (! array_key_exists($mainKey, $this->lock)) { $this->lock[$mainKey] = []; } @@ -110,12 +115,12 @@ public function addSub(string $mainKey, string $name, $data): void */ public function get(string $mainKey, ?string $name = null) { - if (\array_key_exists($mainKey, $this->lock)) { + if (array_key_exists($mainKey, $this->lock)) { if ($name === null) { return $this->lock[$mainKey]; } - if (\is_array($this->lock[$mainKey]) && \array_key_exists($name, $this->lock[$mainKey])) { + if (is_array($this->lock[$mainKey]) && array_key_exists($name, $this->lock[$mainKey])) { return $this->lock[$mainKey][$name]; } } @@ -135,7 +140,7 @@ public function remove(string $mainKey, ?string $name = null): void unset($this->lock[$mainKey]); } - if (\array_key_exists($mainKey, $this->lock)) { + if (array_key_exists($mainKey, $this->lock)) { unset($this->lock[$mainKey][$name]); } } @@ -143,13 +148,13 @@ public function remove(string $mainKey, ?string $name = null): void /** * Write a lock file. * - * @throws \Exception + * @throws Exception * * @return void */ public function write(): void { - \ksort($this->lock); + ksort($this->lock); $this->json->write($this->lock); @@ -163,7 +168,7 @@ public function write(): void */ public function read(): array { - if (\count($this->lock) === 0) { + if (count($this->lock) === 0) { $this->lock = $this->json->read(); } diff --git a/src/Automatic/Operation/AbstractOperation.php b/src/Automatic/Operation/AbstractOperation.php index cd26cef5..eadb462e 100644 --- a/src/Automatic/Operation/AbstractOperation.php +++ b/src/Automatic/Operation/AbstractOperation.php @@ -21,7 +21,17 @@ use Narrowspark\Automatic\Contract\Operation as OperationContract; use Narrowspark\Automatic\Contract\PackageConfigurator as PackageConfiguratorContract; use Narrowspark\Automatic\Lock; +use ReflectionClass; +use ReflectionException; +use SplFileInfo; use Symfony\Component\Filesystem\Filesystem; +use const DIRECTORY_SEPARATOR; +use function array_keys; +use function count; +use function implode; +use function sprintf; +use function strpos; +use function strstr; abstract class AbstractOperation implements OperationContract { @@ -115,24 +125,24 @@ protected function showWarningOnRemainingConfigurators( PackageConfiguratorContract $packageConfigurator, ConfiguratorContract $configurator ): void { - $packageConfigurators = \array_keys((array) $package->getConfig(CommonConfiguratorContract::TYPE)); + $packageConfigurators = array_keys((array) $package->getConfig(CommonConfiguratorContract::TYPE)); - foreach (\array_keys($configurator->getConfigurators()) as $key => $value) { + foreach (array_keys($configurator->getConfigurators()) as $key => $value) { if (isset($packageConfigurators[$key])) { unset($packageConfigurators[$key]); } } - foreach (\array_keys($packageConfigurator->getConfigurators()) as $key => $value) { + foreach (array_keys($packageConfigurator->getConfigurators()) as $key => $value) { if (isset($packageConfigurators[$key])) { unset($packageConfigurators[$key]); } } - if (\count($packageConfigurators) !== 0) { - $this->io->writeError(\sprintf( + if (count($packageConfigurators) !== 0) { + $this->io->writeError(sprintf( 'Configurators [%s] did not run for package [%s]', - \implode(', ', $packageConfigurators), + implode(', ', $packageConfigurators), $package->getPrettyName() )); } @@ -143,7 +153,7 @@ protected function showWarningOnRemainingConfigurators( * * @param \Narrowspark\Automatic\Common\Contract\Package $package * - * @throws \ReflectionException + * @throws ReflectionException * * @return void */ @@ -152,7 +162,7 @@ protected function addPackageConfigurators(PackageContract $package): void if ($package->hasConfig(PackageConfiguratorContract::TYPE)) { /** @var \Narrowspark\Automatic\Common\Configurator\AbstractConfigurator $class */ foreach ((array) $package->getConfig(PackageConfiguratorContract::TYPE) as $class) { - $reflectionClass = new \ReflectionClass($class); + $reflectionClass = new ReflectionClass($class); if ($reflectionClass->isInstantiable() && $reflectionClass->hasMethod('getName')) { $this->packageConfigurator->add($class::getName(), $reflectionClass->getName()); @@ -172,10 +182,10 @@ protected function findClassesInAutomaticFolder(PackageContract $package, string $composerAutoload = $package->getAutoload(); $classes = []; - if (\count($composerAutoload) !== 0) { + if (count($composerAutoload) !== 0) { $classes = $this->classFinder->setComposerAutoload($name, $composerAutoload) - ->setFilter(static function (\SplFileInfo $fileInfo) use ($name) { - return \strpos((string) \strstr($fileInfo->getPathname(), $name), \DIRECTORY_SEPARATOR . 'Automatic' . \DIRECTORY_SEPARATOR) !== false; + ->setFilter(static function (SplFileInfo $fileInfo) use ($name) { + return strpos((string) strstr($fileInfo->getPathname(), $name), DIRECTORY_SEPARATOR . 'Automatic' . DIRECTORY_SEPARATOR) !== false; }) ->find() ->getAll(); diff --git a/src/Automatic/Operation/Install.php b/src/Automatic/Operation/Install.php index cb5b9d85..1e2a8f57 100644 --- a/src/Automatic/Operation/Install.php +++ b/src/Automatic/Operation/Install.php @@ -19,10 +19,20 @@ use Composer\IO\IOInterface; use Composer\Json\JsonFile; use Composer\Package\PackageInterface; +use Exception; use Narrowspark\Automatic\Automatic; use Narrowspark\Automatic\Common\Contract\Package as PackageContract; use Narrowspark\Automatic\Common\Package; use Narrowspark\Automatic\ScriptExecutor; +use const DIRECTORY_SEPARATOR; +use const SORT_STRING; +use function array_unshift; +use function class_exists; +use function count; +use function file_get_contents; +use function sort; +use function sprintf; +use function strpos; /** * @internal @@ -76,7 +86,7 @@ public function transform(PackageContract $package): void $classes = $this->findClassesInAutomaticFolder($package, $name); foreach ($classes as $class => $path) { - if (! \class_exists($class)) { + if (! class_exists($class)) { require_once $path; } } @@ -109,7 +119,7 @@ private function getPackageVersion(PackageInterface $package): string $version = $package->getPrettyVersion(); $extra = $package->getExtra(); - if (isset($extra['branch-alias']) && \strpos($version, 'dev-') === 0) { + if (isset($extra['branch-alias']) && strpos($version, 'dev-') === 0) { $branchAliases = $extra['branch-alias']; if ( @@ -129,7 +139,7 @@ private function getPackageVersion(PackageInterface $package): string * @param \Composer\Package\PackageInterface $composerPackage * @param string $automaticFile * - * @throws \Exception + * @throws Exception * * @return \Narrowspark\Automatic\Common\Contract\Package */ @@ -141,14 +151,14 @@ private function createAutomaticPackage(PackageInterface $composerPackage, strin foreach ($composerPackage->getRequires() as $link) { $target = $link->getTarget(); - if ($target === 'php' || \strpos($target, 'ext-') === 0) { + if ($target === 'php' || strpos($target, 'ext-') === 0) { continue; } $requires[] = $target; } - \sort($requires, \SORT_STRING); + sort($requires, SORT_STRING); $package->setRequires($requires); @@ -169,7 +179,7 @@ private function createAutomaticPackage(PackageInterface $composerPackage, strin $package->setAutoload($composerPackage->getAutoload()); if ($this->filesystem->exists($automaticFile)) { - $package->setConfig(JsonFile::parseJson((string) \file_get_contents($automaticFile))); + $package->setConfig(JsonFile::parseJson((string) file_get_contents($automaticFile))); } else { $package->setConfig($composerPackage->getExtra()['automatic']); } @@ -186,7 +196,7 @@ private function createAutomaticPackage(PackageInterface $composerPackage, strin */ private function getAutomaticFilePath(PackageInterface $composerPackage): string { - return $this->vendorDir . \DIRECTORY_SEPARATOR . $composerPackage->getName() . \DIRECTORY_SEPARATOR . 'automatic.json'; + return $this->vendorDir . DIRECTORY_SEPARATOR . $composerPackage->getName() . DIRECTORY_SEPARATOR . 'automatic.json'; } /** @@ -200,7 +210,7 @@ private function getAutomaticFilePath(PackageInterface $composerPackage): string */ private function addScriptExtenders(PackageContract $package, $classes, $name): void { - if ($package->hasConfig(ScriptExecutor::TYPE) && \count($classes) !== 0) { + if ($package->hasConfig(ScriptExecutor::TYPE) && count($classes) !== 0) { $extenders = []; $notFoundExtenders = []; @@ -212,12 +222,12 @@ private function addScriptExtenders(PackageContract $package, $classes, $name): } } - if (\count($notFoundExtenders) !== 0) { - $count = \count($notFoundExtenders); + if (count($notFoundExtenders) !== 0) { + $count = count($notFoundExtenders); - \array_unshift( + array_unshift( $notFoundExtenders, - \sprintf('%s script-extender%s not found in [%s]', $count, ($count <= 1 ? ' was' : 's were'), $name) + sprintf('%s script-extender%s not found in [%s]', $count, ($count <= 1 ? ' was' : 's were'), $name) ); $this->io->write($notFoundExtenders, true, IOInterface::VERBOSE); diff --git a/src/Automatic/Operation/Uninstall.php b/src/Automatic/Operation/Uninstall.php index a4bd7658..898ca156 100644 --- a/src/Automatic/Operation/Uninstall.php +++ b/src/Automatic/Operation/Uninstall.php @@ -19,6 +19,7 @@ use Narrowspark\Automatic\Common\Contract\Package as PackageContract; use Narrowspark\Automatic\Common\Package; use Narrowspark\Automatic\ScriptExecutor; +use function class_exists; /** * @internal @@ -56,7 +57,7 @@ public function transform(PackageContract $package): void $classes = $this->findClassesInAutomaticFolder($package, $name); foreach ($classes as $class => $path) { - if (! \class_exists($class)) { + if (! class_exists($class)) { require_once $path; } } diff --git a/src/Automatic/QuestionFactory.php b/src/Automatic/QuestionFactory.php index 1ac2507a..b91ad1bf 100644 --- a/src/Automatic/QuestionFactory.php +++ b/src/Automatic/QuestionFactory.php @@ -14,6 +14,10 @@ namespace Narrowspark\Automatic; use Narrowspark\Automatic\Common\Contract\Exception\InvalidArgumentException; +use function in_array; +use function sprintf; +use function str_replace; +use function strtolower; final class QuestionFactory { @@ -35,10 +39,10 @@ public static function getPackageQuestion(string $name, ?string $url): string $message .= ' (defaults to n): ' . "\n"; if ($url === null) { - return \sprintf($message, $name); + return sprintf($message, $name); } - return \sprintf(' Review the package from %s.' . "\n" . $message, \str_replace('.git', '', $url), $name); + return sprintf(' Review the package from %s.' . "\n" . $message, str_replace('.git', '', $url), $name); } /** @@ -53,7 +57,7 @@ public static function getPackageScriptsQuestion(string $name): string $message = ' Do you want to add this package [%s] composer scripts?' . "\n"; $message .= ' (defaults to no): ' . "\n"; - return \sprintf($message, $name); + return sprintf($message, $name); } /** @@ -71,9 +75,9 @@ public static function validatePackageQuestionAnswer(?string $value): string return 'n'; } - $value = \strtolower($value[0]); + $value = strtolower($value[0]); - if (! \in_array($value, ['y', 'n', 'a', 'p'], true)) { + if (! in_array($value, ['y', 'n', 'a', 'p'], true)) { throw new InvalidArgumentException('Invalid choice.'); } diff --git a/src/Automatic/ScriptExecutor.php b/src/Automatic/ScriptExecutor.php index dc748fd7..651b4340 100644 --- a/src/Automatic/ScriptExecutor.php +++ b/src/Automatic/ScriptExecutor.php @@ -22,6 +22,12 @@ use Narrowspark\Automatic\Common\Traits\ExpandTargetDirTrait; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\StreamOutput; +use function explode; +use function fopen; +use function fseek; +use function is_subclass_of; +use function sprintf; +use function stream_get_contents; final class ScriptExecutor { @@ -92,11 +98,11 @@ public function __construct(Composer $composer, IOInterface $io, ProcessExecutor public function add(string $name, string $extender): void { if (isset($this->extenders[$name])) { - throw new InvalidArgumentException(\sprintf('Script executor with the name [%s] already exists.', $name)); + throw new InvalidArgumentException(sprintf('Script executor with the name [%s] already exists.', $name)); } - if (! \is_subclass_of($extender, ScriptExtenderContract::class)) { - throw new InvalidArgumentException(\sprintf('The class [%s] must implement the interface [%s].', $extender, ScriptExtenderContract::class)); + if (! is_subclass_of($extender, ScriptExtenderContract::class)) { + throw new InvalidArgumentException(sprintf('The class [%s] must implement the interface [%s].', $extender, ScriptExtenderContract::class)); } $this->extenders[$name] = $extender; @@ -120,7 +126,7 @@ public function execute(string $type, string $cmd): void $isVerbose = $this->io->isVerbose(); $cmdOutput = new StreamOutput( - \fopen('php://temp', 'rwb'), + fopen('php://temp', 'rwb'), OutputInterface::VERBOSITY_VERBOSE, $this->io->isDecorated() ); @@ -131,7 +137,7 @@ public function execute(string $type, string $cmd): void }; // @codeCoverageIgnoreEnd - $this->io->writeError(\sprintf('Executing script [%s]', $parsedCmd), $isVerbose); + $this->io->writeError(sprintf('Executing script [%s]', $parsedCmd), $isVerbose); /** @var \Narrowspark\Automatic\Common\Contract\ScriptExtender $extender */ $extender = new $this->extenders[$type]($this->composer, $this->io, $this->options); @@ -139,7 +145,7 @@ public function execute(string $type, string $cmd): void $exitCode = $this->executor->execute($extender->expand($parsedCmd), $outputHandler); if ($isVerbose) { - $this->io->writeError(\sprintf('Executed script [%s] %s', $cmd, $exitCode === 0 ? '[OK]' : '[KO]')); + $this->io->writeError(sprintf('Executed script [%s] %s', $cmd, $exitCode === 0 ? '[OK]' : '[KO]')); } if ($exitCode !== 0) { @@ -147,11 +153,11 @@ public function execute(string $type, string $cmd): void $this->io->writeError('[KO]'); } - $this->io->writeError(\sprintf('Script [%s] returned with error code %s', $cmd, $exitCode)); + $this->io->writeError(sprintf('Script [%s] returned with error code %s', $cmd, $exitCode)); - \fseek($cmdOutput->getStream(), 0); + fseek($cmdOutput->getStream(), 0); - foreach (\explode("\n", (string) \stream_get_contents($cmdOutput->getStream())) as $line) { + foreach (explode("\n", (string) stream_get_contents($cmdOutput->getStream())) as $line) { $this->io->writeError('!! ' . $line); } diff --git a/src/Automatic/SkeletonGenerator.php b/src/Automatic/SkeletonGenerator.php index f5ad863b..c64fea9f 100644 --- a/src/Automatic/SkeletonGenerator.php +++ b/src/Automatic/SkeletonGenerator.php @@ -14,11 +14,16 @@ namespace Narrowspark\Automatic; use Composer\IO\IOInterface; +use Exception; use Narrowspark\Automatic\Common\Contract\Generator\DefaultGenerator as DefaultGeneratorContract; use Narrowspark\Automatic\Common\Package; use Narrowspark\Automatic\Installer\InstallationManager; use Narrowspark\Automatic\Installer\SkeletonInstaller; use Symfony\Component\Filesystem\Filesystem; +use function array_walk; +use function class_exists; +use function sprintf; +use function str_replace; final class SkeletonGenerator { @@ -83,7 +88,7 @@ public function __construct( /** * Generate the selected skeleton. * - * @throws \Exception + * @throws Exception * * @return void */ @@ -115,7 +120,7 @@ public function run(): void /** @var \Narrowspark\Automatic\Common\Generator\AbstractGenerator $generator */ $generator = $generators[$answer]; - $this->io->write(\sprintf('%sGenerating [%s] skeleton.%s', "\n", $generatorTypes[$answer], "\n")); + $this->io->write(sprintf('%sGenerating [%s] skeleton.%s', "\n", $generatorTypes[$answer], "\n")); $generator->generate(); @@ -136,7 +141,7 @@ public function run(): void /** * Removes all information about the skeleton package. * - * @throws \Exception + * @throws Exception * * @return void */ @@ -169,8 +174,8 @@ private function prepareGenerators(): array foreach ((array) $this->lock->get(SkeletonInstaller::LOCK_KEY) as $name => $generators) { foreach ((array) $this->lock->get(Automatic::LOCK_CLASSMAP, $name) as $class => $path) { - if (! \class_exists($class)) { - require_once \str_replace('%vendor_path%', $this->vendorPath, $path); + if (! class_exists($class)) { + require_once str_replace('%vendor_path%', $this->vendorPath, $path); } } @@ -179,7 +184,7 @@ private function prepareGenerators(): array $options = $this->options; - \array_walk($foundGenerators, static function (string &$class) use ($options): void { + array_walk($foundGenerators, static function (string &$class) use ($options): void { /** @var \Narrowspark\Automatic\Common\Generator\AbstractGenerator $class */ $class = new $class(new Filesystem(), $options); }); diff --git a/src/Common/AbstractContainer.php b/src/Common/AbstractContainer.php index 07146d0a..1a38f794 100644 --- a/src/Common/AbstractContainer.php +++ b/src/Common/AbstractContainer.php @@ -15,6 +15,8 @@ use Narrowspark\Automatic\Common\Contract\Container as ContainerContract; use Narrowspark\Automatic\Common\Contract\Exception\InvalidArgumentException; +use function array_key_exists; +use function sprintf; abstract class AbstractContainer implements ContainerContract { @@ -55,7 +57,7 @@ public function set(string $id, callable $callback): void */ public function has(string $id): bool { - return \array_key_exists($id, $this->data); + return array_key_exists($id, $this->data); } /** @@ -63,12 +65,12 @@ public function has(string $id): bool */ public function get(string $id) { - if (\array_key_exists($id, $this->objects)) { + if (array_key_exists($id, $this->objects)) { return $this->objects[$id]; } - if (! \array_key_exists($id, $this->data)) { - throw new InvalidArgumentException(\sprintf('Identifier [%s] is not defined.', $id)); + if (! array_key_exists($id, $this->data)) { + throw new InvalidArgumentException(sprintf('Identifier [%s] is not defined.', $id)); } return $this->objects[$id] = $this->data[$id]($this); diff --git a/src/Common/ClassFinder.php b/src/Common/ClassFinder.php index db80e7e3..48579f98 100644 --- a/src/Common/ClassFinder.php +++ b/src/Common/ClassFinder.php @@ -15,7 +15,29 @@ use Closure; use Narrowspark\Automatic\Common\Contract\Resettable as ResettableContract; +use SplFileInfo; use Symfony\Component\Finder\Finder; +use const DIRECTORY_SEPARATOR; +use const SORT_STRING; +use const T_ABSTRACT; +use const T_CLASS; +use const T_INTERFACE; +use const T_NAMESPACE; +use const T_NS_SEPARATOR; +use const T_STRING; +use const T_TRAIT; +use const T_WHITESPACE; +use function array_map; +use function array_merge; +use function array_unique; +use function count; +use function file_get_contents; +use function gc_mem_caches; +use function is_array; +use function ltrim; +use function rtrim; +use function token_get_all; +use function trim; final class ClassFinder implements ResettableContract { @@ -71,7 +93,7 @@ final class ClassFinder implements ResettableContract /** * A symfony finder filter. * - * @var \Closure + * @var Closure */ private $filter; @@ -139,8 +161,8 @@ public function getClasses(): array */ public function setExcludes(array $excludes): self { - $this->excludes = \array_map(static function (string $value) { - return \trim($value, '/'); + $this->excludes = array_map(static function (string $value) { + return trim($value, '/'); }, $excludes); return $this; @@ -149,7 +171,7 @@ public function setExcludes(array $excludes): self /** * Set a symfony finder filter. * - * @param \Closure $filter + * @param Closure $filter * * @return self */ @@ -243,13 +265,13 @@ public function addClassmap(string $packageName, array $paths): self */ public function find(): self { - $preparedPaths = \array_unique( - \array_merge( + $preparedPaths = array_unique( + array_merge( $this->getPreparedPaths($this->paths['psr0']), $this->getPreparedPaths($this->paths['psr4']), $this->getPreparedPaths($this->paths['classmap']) ), - \SORT_STRING + SORT_STRING ); $finder = Finder::create() @@ -263,58 +285,58 @@ public function find(): self $finder->filter($this->filter); } - /** @var \SplFileInfo $file */ + /** @var SplFileInfo $file */ foreach ($finder as $file) { $realPath = (string) $file->getRealPath(); $namespace = null; - $tokens = \token_get_all((string) \file_get_contents($realPath)); + $tokens = token_get_all((string) file_get_contents($realPath)); foreach ($tokens as $key => $token) { - if (\is_array($token)) { - if ($token[0] === \T_NAMESPACE) { + if (is_array($token)) { + if ($token[0] === T_NAMESPACE) { $namespace = self::getNamespace($key + 2, $tokens); - } elseif ($token[0] === \T_INTERFACE) { + } elseif ($token[0] === T_INTERFACE) { $name = self::getName($key + 2, $tokens); if ($name === null) { continue 2; } - $this->interfaces[\ltrim($namespace . '\\' . $name, '\\')] = $realPath; - } elseif ($token[0] === \T_TRAIT) { + $this->interfaces[ltrim($namespace . '\\' . $name, '\\')] = $realPath; + } elseif ($token[0] === T_TRAIT) { $name = self::getName($key + 2, $tokens); if ($name === null) { continue 2; } - $this->traits[\ltrim($namespace . '\\' . $name, '\\')] = $realPath; - } elseif ($token[0] === \T_ABSTRACT) { + $this->traits[ltrim($namespace . '\\' . $name, '\\')] = $realPath; + } elseif ($token[0] === T_ABSTRACT) { $name = self::getName($key + 4, $tokens); if ($name === null) { continue 2; } - $this->abstractClasses[\ltrim($namespace . '\\' . $name, '\\')] = $realPath; + $this->abstractClasses[ltrim($namespace . '\\' . $name, '\\')] = $realPath; continue 2; - } elseif ($token[0] === \T_CLASS) { + } elseif ($token[0] === T_CLASS) { $name = self::getName($key + 2, $tokens); if ($name === null) { continue 2; } - $this->classes[\ltrim($namespace . '\\' . $name, '\\')] = $realPath; + $this->classes[ltrim($namespace . '\\' . $name, '\\')] = $realPath; } } } unset($tokens); // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098 - \gc_mem_caches(); + gc_mem_caches(); } return $this; @@ -327,7 +349,7 @@ public function find(): self */ public function getAll(): array { - return \array_merge( + return array_merge( $this->interfaces, $this->traits, $this->abstractClasses, @@ -362,7 +384,7 @@ public function reset(): void private static function getNamespace(int $key, array $tokens): ?string { $namespace = null; - $tokenCount = \count($tokens); + $tokenCount = count($tokens); for ($i = $key; $i < $tokenCount; $i++) { if (self::isPartOfNamespace($tokens[$i])) { @@ -384,7 +406,7 @@ private static function getNamespace(int $key, array $tokens): ?string */ private static function isPartOfNamespace($token): bool { - return \is_array($token) && ($token[0] === \T_STRING || $token[0] === \T_NS_SEPARATOR); + return is_array($token) && ($token[0] === T_STRING || $token[0] === T_NS_SEPARATOR); } /** @@ -398,13 +420,13 @@ private static function isPartOfNamespace($token): bool private static function getName($key, array $tokens): ?string { $class = null; - $tokenCount = \count($tokens); + $tokenCount = count($tokens); for ($i = $key; $i < $tokenCount; $i++) { - if (\is_array($tokens[$i])) { - if ($tokens[$i][0] === \T_STRING) { + if (is_array($tokens[$i])) { + if ($tokens[$i][0] === T_STRING) { $class .= $tokens[$i][1]; - } elseif ($tokens[$i][0] === \T_WHITESPACE) { + } elseif ($tokens[$i][0] === T_WHITESPACE) { return $class; } } @@ -425,12 +447,12 @@ private function getPreparedPaths(array $paths): array $fullPaths = []; foreach ($paths as $name => $path) { - if (\is_array($path)) { + if (is_array($path)) { foreach ($path as $p) { - $fullPaths[] = \rtrim($this->vendorDir . \DIRECTORY_SEPARATOR . $name . \DIRECTORY_SEPARATOR . $p, '/'); + $fullPaths[] = rtrim($this->vendorDir . DIRECTORY_SEPARATOR . $name . DIRECTORY_SEPARATOR . $p, '/'); } } else { - $fullPaths[] = \rtrim($this->vendorDir . \DIRECTORY_SEPARATOR . $name . \DIRECTORY_SEPARATOR . $path, '/'); + $fullPaths[] = rtrim($this->vendorDir . DIRECTORY_SEPARATOR . $name . DIRECTORY_SEPARATOR . $path, '/'); } } diff --git a/src/Common/Configurator/AbstractConfigurator.php b/src/Common/Configurator/AbstractConfigurator.php index 2518bf47..ade2262a 100644 --- a/src/Common/Configurator/AbstractConfigurator.php +++ b/src/Common/Configurator/AbstractConfigurator.php @@ -19,6 +19,13 @@ use Narrowspark\Automatic\Common\Path; use Narrowspark\Automatic\Common\Traits\ExpandTargetDirTrait; use Symfony\Component\Filesystem\Filesystem; +use function file_get_contents; +use function is_array; +use function is_file; +use function rtrim; +use function sprintf; +use function strpos; +use function substr; abstract class AbstractConfigurator implements ConfiguratorContract { @@ -82,7 +89,7 @@ public function __construct(Composer $composer, IOInterface $io, array $options */ protected function write($messages): void { - if (! \is_array($messages)) { + if (! is_array($messages)) { $messages = [$messages]; } @@ -103,7 +110,7 @@ protected function write($messages): void */ protected function isFileMarked(string $packageName, string $file): bool { - return \is_file($file) && \strpos((string) \file_get_contents($file), \sprintf('###> %s ###', $packageName)) !== false; + return is_file($file) && strpos((string) file_get_contents($file), sprintf('###> %s ###', $packageName)) !== false; } /** @@ -117,7 +124,7 @@ protected function isFileMarked(string $packageName, string $file): bool */ protected function markData(string $packageName, string $data, int $spaceMultiplier = 0): string { - return \sprintf('###> %s ###' . "\n" . '%s' . "\n" . '###< %s ###' . "\n", $packageName, \rtrim($data, "\r\n"), $packageName); + return sprintf('###> %s ###' . "\n" . '%s' . "\n" . '###< %s ###' . "\n", $packageName, rtrim($data, "\r\n"), $packageName); } /** @@ -133,6 +140,6 @@ protected function markData(string $packageName, string $data, int $spaceMultipl */ protected function doInsertStringBeforePosition(string $string, string $insertStr, int $position): string { - return \substr($string, 0, $position) . $insertStr . \substr($string, $position); + return substr($string, 0, $position) . $insertStr . substr($string, $position); } } diff --git a/src/Common/Contract/Exception/Exception.php b/src/Common/Contract/Exception/Exception.php index 1f71fe61..94a25328 100644 --- a/src/Common/Contract/Exception/Exception.php +++ b/src/Common/Contract/Exception/Exception.php @@ -13,6 +13,8 @@ namespace Narrowspark\Automatic\Common\Contract\Exception; -interface Exception extends \Throwable +use Throwable; + +interface Exception extends Throwable { } diff --git a/src/Common/Installer/AbstractInstallationManager.php b/src/Common/Installer/AbstractInstallationManager.php index 5daaad03..484bb0a7 100644 --- a/src/Common/Installer/AbstractInstallationManager.php +++ b/src/Common/Installer/AbstractInstallationManager.php @@ -27,10 +27,14 @@ use Composer\Repository\CompositeRepository; use Composer\Repository\PlatformRepository; use Composer\Repository\RepositoryFactory; +use Exception; use Narrowspark\Automatic\Common\Contract\Exception\InvalidArgumentException; use Narrowspark\Automatic\Common\Traits\GetGenericPropertyReaderTrait; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Filesystem\Filesystem; +use function array_merge; +use function file_get_contents; +use function sprintf; abstract class AbstractInstallationManager { @@ -132,7 +136,7 @@ public function __construct(Composer $composer, IOInterface $io, InputInterface $this->io = $io; $this->input = $input; $this->jsonFile = new JsonFile(Factory::getComposerFile()); - $this->composerBackup = (string) \file_get_contents($this->jsonFile->getPath()); + $this->composerBackup = (string) file_get_contents($this->jsonFile->getPath()); $this->filesystem = new Filesystem(); $this->rootPackage = $this->composer->getPackage(); @@ -140,7 +144,7 @@ public function __construct(Composer $composer, IOInterface $io, InputInterface $pool = new Pool($this->stability); $pool->addRepository( - new CompositeRepository(\array_merge([new PlatformRepository()], RepositoryFactory::defaultRepos($io))) + new CompositeRepository(array_merge([new PlatformRepository()], RepositoryFactory::defaultRepos($io))) ); $this->versionSelector = new VersionSelector($pool); @@ -174,7 +178,7 @@ protected function findBestVersionForPackage(string $name): string $package = $this->versionSelector->findBestCandidate($name, null, null, 'stable'); if ($package === false) { - throw new InvalidArgumentException(\sprintf('Could not find package [%s] at any version for your minimum-stability [%s]. Check the package spelling or your minimum-stability.', $name, $this->stability)); + throw new InvalidArgumentException(sprintf('Could not find package [%s] at any version for your minimum-stability [%s]. Check the package spelling or your minimum-stability.', $name, $this->stability)); } return $this->versionSelector->findRecommendedRequireVersion($package); @@ -206,7 +210,7 @@ protected function updateRootComposerJson(array $requires, array $devRequires, i * @param array $devRequires * @param int $type * - * @throws \Exception happens in the JsonFile class + * @throws Exception happens in the JsonFile class * * @return void */ @@ -215,7 +219,7 @@ protected function updateComposerJson(array $requires, array $devRequires, int $ $this->io->writeError('Updating composer.json'); if ($type === self::ADD) { - $jsonManipulator = new JsonManipulator(\file_get_contents($this->jsonFile->getPath())); + $jsonManipulator = new JsonManipulator(file_get_contents($this->jsonFile->getPath())); $sortPackages = $this->composer->getConfig()->get('sort-packages') ?? false; foreach ($requires as $name => $version) { @@ -248,7 +252,7 @@ protected function updateComposerJson(array $requires, array $devRequires, int $ * @param \Composer\Package\RootPackageInterface $rootPackage * @param array $whitelistPackages * - * @throws \Exception + * @throws Exception * * @return int */ @@ -271,7 +275,7 @@ protected function runInstaller(RootPackageInterface $rootPackage, array $whitel */ protected function getRootRequires(): array { - return \array_merge($this->rootPackage->getRequires(), $this->rootPackage->getDevRequires()); + return array_merge($this->rootPackage->getRequires(), $this->rootPackage->getDevRequires()); } /** diff --git a/src/Common/Package.php b/src/Common/Package.php index bf9c89a2..638dd432 100644 --- a/src/Common/Package.php +++ b/src/Common/Package.php @@ -13,7 +13,13 @@ namespace Narrowspark\Automatic\Common; +use DateTime; +use DateTimeImmutable; +use Exception; use Narrowspark\Automatic\Common\Contract\Package as PackageContract; +use function array_key_exists; +use function is_array; +use function strtolower; final class Package implements PackageContract { @@ -107,14 +113,14 @@ final class Package implements PackageContract * @param string $name * @param null|string $prettyVersion * - * @throws \Exception + * @throws Exception */ public function __construct(string $name, ?string $prettyVersion) { $this->prettyName = $name; - $this->name = \strtolower($name); + $this->name = strtolower($name); $this->prettyVersion = $prettyVersion; - $this->created = (new \DateTimeImmutable())->format(\DateTime::RFC3339); + $this->created = (new DateTimeImmutable())->format(DateTime::RFC3339); } /** @@ -333,14 +339,14 @@ public function setConfig(array $configs): PackageContract */ public function hasConfig(string $mainKey, ?string $name = null): bool { - $mainCheck = \array_key_exists($mainKey, $this->configs); + $mainCheck = array_key_exists($mainKey, $this->configs); if ($name === null) { return $mainCheck; } - if ($mainCheck === true && \is_array($this->configs[$mainKey])) { - return \array_key_exists($name, $this->configs[$mainKey]); + if ($mainCheck === true && is_array($this->configs[$mainKey])) { + return array_key_exists($name, $this->configs[$mainKey]); } return false; @@ -351,12 +357,12 @@ public function hasConfig(string $mainKey, ?string $name = null): bool */ public function getConfig(string $mainKey, ?string $name = null) { - if (\array_key_exists($mainKey, $this->configs)) { + if (array_key_exists($mainKey, $this->configs)) { if ($name === null) { return $this->configs[$mainKey]; } - if (\is_array($this->configs[$mainKey]) && \array_key_exists($name, $this->configs[$mainKey])) { + if (is_array($this->configs[$mainKey]) && array_key_exists($name, $this->configs[$mainKey])) { return $this->configs[$mainKey][$name]; } } diff --git a/src/Common/Path.php b/src/Common/Path.php index a3427663..d16b4e74 100644 --- a/src/Common/Path.php +++ b/src/Common/Path.php @@ -13,6 +13,14 @@ namespace Narrowspark\Automatic\Common; +use const DIRECTORY_SEPARATOR; +use function array_reduce; +use function array_shift; +use function is_dir; +use function ltrim; +use function rtrim; +use function str_replace; + final class Path { /** @@ -49,9 +57,9 @@ public function getWorkingDir(): string */ public function relativize(string $absolutePath): string { - $relativePath = \str_replace($this->workingDirectory, '.', $absolutePath); + $relativePath = str_replace($this->workingDirectory, '.', $absolutePath); - return \is_dir($absolutePath) ? \rtrim($relativePath, \DIRECTORY_SEPARATOR) . \DIRECTORY_SEPARATOR : $relativePath; + return is_dir($absolutePath) ? rtrim($relativePath, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR : $relativePath; } /** @@ -61,10 +69,10 @@ public function relativize(string $absolutePath): string */ public function concatenate(array $parts): string { - $first = \array_shift($parts); + $first = array_shift($parts); - return \array_reduce($parts, static function (string $initial, string $next): string { - return \rtrim($initial, \DIRECTORY_SEPARATOR) . \DIRECTORY_SEPARATOR . \ltrim($next, \DIRECTORY_SEPARATOR); + return array_reduce($parts, static function (string $initial, string $next): string { + return rtrim($initial, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR . ltrim($next, DIRECTORY_SEPARATOR); }, $first); } } diff --git a/src/Common/ScriptExtender/PhpScriptExtender.php b/src/Common/ScriptExtender/PhpScriptExtender.php index d98bcf5a..4c4bd45c 100644 --- a/src/Common/ScriptExtender/PhpScriptExtender.php +++ b/src/Common/ScriptExtender/PhpScriptExtender.php @@ -16,6 +16,14 @@ use Composer\Util\ProcessExecutor; use Narrowspark\Automatic\Common\Contract\Exception\RuntimeException; use Symfony\Component\Process\PhpExecutableFinder; +use const PATH_SEPARATOR; +use function array_map; +use function array_shift; +use function explode; +use function getenv; +use function implode; +use function is_string; +use function php_ini_loaded_file; class PhpScriptExtender extends AbstractScriptExtender { @@ -40,18 +48,18 @@ public function expand(string $cmd): string // @codeCoverageIgnoreEnd $arguments = $phpFinder->findArguments(); - if (($env = \getenv('COMPOSER_ORIGINAL_INIS')) !== false) { - $paths = \explode(\PATH_SEPARATOR, (string) $env); - $ini = \array_shift($paths); + if (($env = getenv('COMPOSER_ORIGINAL_INIS')) !== false) { + $paths = explode(PATH_SEPARATOR, (string) $env); + $ini = array_shift($paths); } else { - $ini = \php_ini_loaded_file(); + $ini = php_ini_loaded_file(); } - if (\is_string($ini)) { + if (is_string($ini)) { $arguments[] = '--php-ini=' . $ini; } - $phpArgs = \implode(' ', \array_map([ProcessExecutor::class, 'escape'], $arguments)); + $phpArgs = implode(' ', array_map([ProcessExecutor::class, 'escape'], $arguments)); return ProcessExecutor::escape((string) $php) . ($phpArgs !== '' ? ' ' . $phpArgs : '') . ' ' . $cmd; } diff --git a/src/Common/Traits/ExpandTargetDirTrait.php b/src/Common/Traits/ExpandTargetDirTrait.php index 8c19b0e0..230f9966 100644 --- a/src/Common/Traits/ExpandTargetDirTrait.php +++ b/src/Common/Traits/ExpandTargetDirTrait.php @@ -13,6 +13,11 @@ namespace Narrowspark\Automatic\Common\Traits; +use function preg_match; +use function rtrim; +use function str_replace; +use function strtolower; + trait ExpandTargetDirTrait { /** @@ -23,18 +28,18 @@ trait ExpandTargetDirTrait */ public static function expandTargetDir(array $options, string $target): string { - $found = \preg_match('{%(.+?)%}', $target, $matches); + $found = preg_match('{%(.+?)%}', $target, $matches); if ($found !== 1) { return $target; } - $option = \str_replace('_', '-', \strtolower($matches[1])); + $option = str_replace('_', '-', strtolower($matches[1])); if (! isset($options[$option])) { return $matches[0]; } - return \str_replace($matches[0], \rtrim($options[$option], '/'), $target); + return str_replace($matches[0], rtrim($options[$option], '/'), $target); } } diff --git a/src/Common/Traits/GetGenericPropertyReaderTrait.php b/src/Common/Traits/GetGenericPropertyReaderTrait.php index ce723dea..66a3ccbf 100644 --- a/src/Common/Traits/GetGenericPropertyReaderTrait.php +++ b/src/Common/Traits/GetGenericPropertyReaderTrait.php @@ -20,7 +20,7 @@ trait GetGenericPropertyReaderTrait /** * Returns a callback that can read private variables from object. * - * @return \Closure + * @return Closure */ protected function getGenericPropertyReader(): Closure { diff --git a/src/Common/Traits/PhpFileMarkerTrait.php b/src/Common/Traits/PhpFileMarkerTrait.php index 30491448..92351b4f 100644 --- a/src/Common/Traits/PhpFileMarkerTrait.php +++ b/src/Common/Traits/PhpFileMarkerTrait.php @@ -13,6 +13,12 @@ namespace Narrowspark\Automatic\Common\Traits; +use function file_get_contents; +use function is_file; +use function sprintf; +use function str_repeat; +use function strpos; + trait PhpFileMarkerTrait { /** @@ -25,7 +31,7 @@ trait PhpFileMarkerTrait */ protected function isFileMarked(string $packageName, string $file): bool { - return \is_file($file) && \strpos(\file_get_contents($file), \sprintf('/** > %s **/', $packageName)) !== false; + return is_file($file) && strpos(file_get_contents($file), sprintf('/** > %s **/', $packageName)) !== false; } /** @@ -39,8 +45,8 @@ protected function isFileMarked(string $packageName, string $file): bool */ protected function markData(string $packageName, string $data, int $spaceMultiplier = 4): string { - $spaces = \str_repeat(' ', $spaceMultiplier); + $spaces = str_repeat(' ', $spaceMultiplier); - return \sprintf('%s/** > %s **/' . "\n" . '%s%s/** %s < **/' . "\n", $spaces, $packageName, $data, $spaces, $packageName); + return sprintf('%s/** > %s **/' . "\n" . '%s%s/** %s < **/' . "\n", $spaces, $packageName, $data, $spaces, $packageName); } } diff --git a/src/Common/Util.php b/src/Common/Util.php index c78ef3ae..212d851c 100644 --- a/src/Common/Util.php +++ b/src/Common/Util.php @@ -13,9 +13,15 @@ namespace Narrowspark\Automatic\Common; +use Composer\Composer; use Composer\Factory; use Composer\Json\JsonFile; use Composer\Json\JsonManipulator; +use InvalidArgumentException; +use Narrowspark\Automatic\Common\Contract\Exception\RuntimeException; +use function file_get_contents; +use function preg_match; +use function substr; final class Util { @@ -31,14 +37,14 @@ private function __construct() /** * Return the composer json file and json manipulator. * - * @throws \InvalidArgumentException + * @throws InvalidArgumentException * * @return array */ public static function getComposerJsonFileAndManipulator(): array { $json = new JsonFile(Factory::getComposerFile()); - $manipulator = new JsonManipulator(\file_get_contents($json->getPath())); + $manipulator = new JsonManipulator(file_get_contents($json->getPath())); return [$json, $manipulator]; } @@ -50,6 +56,30 @@ public static function getComposerJsonFileAndManipulator(): array */ public static function getComposerLockFile(): string { - return \substr(Factory::getComposerFile(), 0, -4) . 'lock'; + return substr(Factory::getComposerFile(), 0, -4) . 'lock'; + } + + /** + * Get the composer version. + * + * @throws \Narrowspark\Automatic\Common\Contract\Exception\RuntimeException + * + * @return string + */ + public static function getComposerVersion(): string + { + preg_match('/\d+.\d+.\d+/m', Composer::VERSION, $matches); + + if ($matches !== null) { + return $matches[0]; + } + + preg_match('/\d+.\d+.\d+/m', Composer::BRANCH_ALIAS_VERSION, $matches); + + if ($matches !== null) { + return $matches[0]; + } + + throw new RuntimeException('No composer version found.'); } } diff --git a/src/Prefetcher/Cache.php b/src/Prefetcher/Cache.php index 01636cd7..11dd8ba6 100644 --- a/src/Prefetcher/Cache.php +++ b/src/Prefetcher/Cache.php @@ -15,6 +15,10 @@ use Composer\Cache as BaseComposerCache; use Narrowspark\Automatic\Prefetcher\Contract\LegacyTagsManager as LegacyTagsManagerContract; +use function is_array; +use function is_string; +use function json_decode; +use function json_encode; /** * Ported from symfony flex, see original. @@ -53,8 +57,8 @@ public function read($file) { $content = parent::read($file); - if ($this->tagsManager !== null && \is_string($content) && $this->tagsManager->hasProvider($file) && \is_array($data = \json_decode($content, true))) { - $content = \json_encode($this->removeLegacyTags($data)); + if ($this->tagsManager !== null && is_string($content) && $this->tagsManager->hasProvider($file) && is_array($data = json_decode($content, true))) { + $content = json_encode($this->removeLegacyTags($data)); } return $content; diff --git a/src/Prefetcher/Common/AbstractContainer.php b/src/Prefetcher/Common/AbstractContainer.php index 51fdf046..808fa796 100644 --- a/src/Prefetcher/Common/AbstractContainer.php +++ b/src/Prefetcher/Common/AbstractContainer.php @@ -15,11 +15,14 @@ use Narrowspark\Automatic\Prefetcher\Common\Contract\Container as ContainerContract; use Narrowspark\Automatic\Prefetcher\Common\Contract\Exception\InvalidArgumentException; +use function array_key_exists; +use function sprintf; /** * This file is automatically generated, dont change this file, otherwise the changes are lost after the next mirror update. * * @codeCoverageIgnore + * * @internal */ abstract class AbstractContainer implements ContainerContract @@ -61,7 +64,7 @@ public function set(string $id, callable $callback): void */ public function has(string $id): bool { - return \array_key_exists($id, $this->data); + return array_key_exists($id, $this->data); } /** @@ -69,12 +72,12 @@ public function has(string $id): bool */ public function get(string $id) { - if (\array_key_exists($id, $this->objects)) { + if (array_key_exists($id, $this->objects)) { return $this->objects[$id]; } - if (! \array_key_exists($id, $this->data)) { - throw new InvalidArgumentException(\sprintf('Identifier [%s] is not defined.', $id)); + if (! array_key_exists($id, $this->data)) { + throw new InvalidArgumentException(sprintf('Identifier [%s] is not defined.', $id)); } return $this->objects[$id] = $this->data[$id]($this); diff --git a/src/Prefetcher/Common/Contract/Container.php b/src/Prefetcher/Common/Contract/Container.php index 9e420754..cc4af5a3 100644 --- a/src/Prefetcher/Common/Contract/Container.php +++ b/src/Prefetcher/Common/Contract/Container.php @@ -17,6 +17,7 @@ * This file is automatically generated, dont change this file, otherwise the changes are lost after the next mirror update. * * @codeCoverageIgnore + * * @internal */ interface Container diff --git a/src/Prefetcher/Common/Contract/Exception/Exception.php b/src/Prefetcher/Common/Contract/Exception/Exception.php index fdd653c1..1c15533a 100644 --- a/src/Prefetcher/Common/Contract/Exception/Exception.php +++ b/src/Prefetcher/Common/Contract/Exception/Exception.php @@ -13,12 +13,15 @@ namespace Narrowspark\Automatic\Prefetcher\Common\Contract\Exception; +use Throwable; + /** * This file is automatically generated, dont change this file, otherwise the changes are lost after the next mirror update. * * @codeCoverageIgnore + * * @internal */ -interface Exception extends \Throwable +interface Exception extends Throwable { } diff --git a/src/Prefetcher/Common/Contract/Resettable.php b/src/Prefetcher/Common/Contract/Resettable.php index d026bcd6..e84760f1 100644 --- a/src/Prefetcher/Common/Contract/Resettable.php +++ b/src/Prefetcher/Common/Contract/Resettable.php @@ -17,6 +17,7 @@ * This file is automatically generated, dont change this file, otherwise the changes are lost after the next mirror update. * * @codeCoverageIgnore + * * @internal */ interface Resettable diff --git a/src/Prefetcher/Common/Traits/GetGenericPropertyReaderTrait.php b/src/Prefetcher/Common/Traits/GetGenericPropertyReaderTrait.php index 27f19dbe..67c551b3 100644 --- a/src/Prefetcher/Common/Traits/GetGenericPropertyReaderTrait.php +++ b/src/Prefetcher/Common/Traits/GetGenericPropertyReaderTrait.php @@ -20,7 +20,7 @@ trait GetGenericPropertyReaderTrait /** * Returns a callback that can read private variables from object. * - * @return \Closure + * @return Closure */ protected function getGenericPropertyReader(): Closure { diff --git a/src/Prefetcher/Common/Util.php b/src/Prefetcher/Common/Util.php index 62408544..7850ec3b 100644 --- a/src/Prefetcher/Common/Util.php +++ b/src/Prefetcher/Common/Util.php @@ -13,9 +13,15 @@ namespace Narrowspark\Automatic\Prefetcher\Common; +use Composer\Composer; use Composer\Factory; use Composer\Json\JsonFile; use Composer\Json\JsonManipulator; +use InvalidArgumentException; +use Narrowspark\Automatic\Prefetcher\Common\Contract\Exception\RuntimeException; +use function file_get_contents; +use function preg_match; +use function substr; final class Util { @@ -31,14 +37,14 @@ private function __construct() /** * Return the composer json file and json manipulator. * - * @throws \InvalidArgumentException + * @throws InvalidArgumentException * * @return array */ public static function getComposerJsonFileAndManipulator(): array { $json = new JsonFile(Factory::getComposerFile()); - $manipulator = new JsonManipulator(\file_get_contents($json->getPath())); + $manipulator = new JsonManipulator(file_get_contents($json->getPath())); return [$json, $manipulator]; } @@ -50,6 +56,30 @@ public static function getComposerJsonFileAndManipulator(): array */ public static function getComposerLockFile(): string { - return \substr(Factory::getComposerFile(), 0, -4) . 'lock'; + return substr(Factory::getComposerFile(), 0, -4) . 'lock'; + } + + /** + * Get the composer version. + * + * @throws \Narrowspark\Automatic\Prefetcher\Common\Contract\Exception\RuntimeException + * + * @return string + */ + public static function getComposerVersion(): string + { + preg_match('/\d+.\d+.\d+/m', Composer::VERSION, $matches); + + if ($matches !== null) { + return $matches[0]; + } + + preg_match('/\d+.\d+.\d+/m', Composer::BRANCH_ALIAS_VERSION, $matches); + + if ($matches !== null) { + return $matches[0]; + } + + throw new RuntimeException('No composer version found.'); } } diff --git a/src/Prefetcher/Downloader/CurlDownloader.php b/src/Prefetcher/Downloader/CurlDownloader.php index 8ff92b3d..2c369455 100644 --- a/src/Prefetcher/Downloader/CurlDownloader.php +++ b/src/Prefetcher/Downloader/CurlDownloader.php @@ -15,6 +15,64 @@ use Composer\Downloader\TransportException; use Narrowspark\Automatic\Common\Contract\Exception\RuntimeException; +use const CURL_HTTP_VERSION_1_0; +use const CURL_HTTP_VERSION_2_0; +use const CURL_LOCK_DATA_COOKIE; +use const CURL_LOCK_DATA_DNS; +use const CURL_LOCK_DATA_SSL_SESSION; +use const CURL_VERSION_HTTP2; +use const CURLE_OK; +use const CURLINFO_HTTP_CODE; +use const CURLMOPT_MAX_HOST_CONNECTIONS; +use const CURLMOPT_PIPELINING; +use const CURLOPT_CAINFO; +use const CURLOPT_CAPATH; +use const CURLOPT_CUSTOMREQUEST; +use const CURLOPT_DNS_USE_GLOBAL_CACHE; +use const CURLOPT_FILE; +use const CURLOPT_FOLLOWLOCATION; +use const CURLOPT_HTTP_VERSION; +use const CURLOPT_HTTPHEADER; +use const CURLOPT_POSTFIELDS; +use const CURLOPT_SHARE; +use const CURLOPT_URL; +use const CURLOPT_WRITEHEADER; +use const CURLSHOPT_SHARE; +use const STREAM_NOTIFY_AUTH_RESULT; +use const STREAM_NOTIFY_FAILURE; +use const STREAM_NOTIFY_FILE_SIZE_IS; +use const STREAM_NOTIFY_PROGRESS; +use const STREAM_NOTIFY_RESOLVE; +use const STREAM_NOTIFY_SEVERITY_ERR; +use const STREAM_NOTIFY_SEVERITY_INFO; +use function array_diff; +use function array_diff_key; +use function curl_close; +use function curl_errno; +use function curl_error; +use function curl_getinfo; +use function curl_init; +use function curl_multi_add_handle; +use function curl_multi_exec; +use function curl_multi_info_read; +use function curl_multi_init; +use function curl_multi_remove_handle; +use function curl_multi_select; +use function curl_multi_setopt; +use function curl_setopt; +use function curl_share_init; +use function curl_share_setopt; +use function curl_version; +use function defined; +use function explode; +use function fclose; +use function fopen; +use function rename; +use function rewind; +use function rtrim; +use function stream_context_get_params; +use function stream_get_contents; +use function strpos; /** * Ported from symfony flex, see original. @@ -60,12 +118,12 @@ final class CurlDownloader */ private static $options = [ 'http' => [ - 'method' => \CURLOPT_CUSTOMREQUEST, - 'content' => \CURLOPT_POSTFIELDS, + 'method' => CURLOPT_CUSTOMREQUEST, + 'content' => CURLOPT_POSTFIELDS, ], 'ssl' => [ - 'cafile' => \CURLOPT_CAINFO, - 'capath' => \CURLOPT_CAPATH, + 'cafile' => CURLOPT_CAINFO, + 'capath' => CURLOPT_CAPATH, ], ]; @@ -88,7 +146,7 @@ final class CurlDownloader */ public function __construct() { - $multiCurl = \curl_multi_init(); + $multiCurl = curl_multi_init(); if ($multiCurl === false) { throw new RuntimeException('Initializing a new cURL multi handler failed.'); @@ -96,17 +154,17 @@ public function __construct() $this->multiHandle = $mh = $multiCurl; - \curl_multi_setopt($mh, \CURLMOPT_PIPELINING, /* CURLPIPE_MULTIPLEX */ 2); + curl_multi_setopt($mh, CURLMOPT_PIPELINING, /* CURLPIPE_MULTIPLEX */ 2); - if (\defined('CURLMOPT_MAX_HOST_CONNECTIONS')) { - \curl_multi_setopt($mh, \CURLMOPT_MAX_HOST_CONNECTIONS, 10); + if (defined('CURLMOPT_MAX_HOST_CONNECTIONS')) { + curl_multi_setopt($mh, CURLMOPT_MAX_HOST_CONNECTIONS, 10); } - $this->shareHandle = $sh = \curl_share_init(); + $this->shareHandle = $sh = curl_share_init(); - \curl_share_setopt($sh, \CURLSHOPT_SHARE, (string) \CURL_LOCK_DATA_COOKIE); - \curl_share_setopt($sh, \CURLSHOPT_SHARE, (string) \CURL_LOCK_DATA_DNS); - \curl_share_setopt($sh, \CURLSHOPT_SHARE, (string) \CURL_LOCK_DATA_SSL_SESSION); + curl_share_setopt($sh, CURLSHOPT_SHARE, (string) CURL_LOCK_DATA_COOKIE); + curl_share_setopt($sh, CURLSHOPT_SHARE, (string) CURL_LOCK_DATA_DNS); + curl_share_setopt($sh, CURLSHOPT_SHARE, (string) CURL_LOCK_DATA_SSL_SESSION); } /** @@ -123,47 +181,47 @@ public function __construct() */ public function get(string $originUrl, string $url, $context, ?string $file): array { - $params = \stream_context_get_params($context); - $ch = \curl_init(); - $hd = \fopen('php://temp/maxmemory:32768', 'w+b'); + $params = stream_context_get_params($context); + $ch = curl_init(); + $hd = fopen('php://temp/maxmemory:32768', 'w+b'); - if ($file !== null && ! $fd = @\fopen($file . '~', 'w+b')) { + if ($file !== null && ! $fd = @fopen($file . '~', 'w+b')) { $file = null; } if ($file === null) { - $fd = @\fopen('php://temp/maxmemory:524288', 'w+b'); + $fd = @fopen('php://temp/maxmemory:524288', 'w+b'); } - $headers = \array_diff($params['options']['http']['header'], ['Connection: close']); + $headers = array_diff($params['options']['http']['header'], ['Connection: close']); if (! isset($params['options']['http']['protocol_version'])) { - \curl_setopt($ch, \CURLOPT_HTTP_VERSION, \CURL_HTTP_VERSION_1_0); + curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); } else { $headers[] = 'Connection: keep-alive'; - if (\strpos($url, 'https://') === 0 && \defined('CURL_VERSION_HTTP2') && \defined('CURL_HTTP_VERSION_2_0') && (\CURL_VERSION_HTTP2 & \curl_version()['features'])) { - \curl_setopt($ch, \CURLOPT_HTTP_VERSION, \CURL_HTTP_VERSION_2_0); + if (strpos($url, 'https://') === 0 && defined('CURL_VERSION_HTTP2') && defined('CURL_HTTP_VERSION_2_0') && (CURL_VERSION_HTTP2 & curl_version()['features'])) { + curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0); } } - \curl_setopt($ch, \CURLOPT_URL, $url); - \curl_setopt($ch, \CURLOPT_HTTPHEADER, $headers); - \curl_setopt($ch, \CURLOPT_FOLLOWLOCATION, true); - \curl_setopt($ch, \CURLOPT_DNS_USE_GLOBAL_CACHE, false); - \curl_setopt($ch, \CURLOPT_WRITEHEADER, $hd); - \curl_setopt($ch, \CURLOPT_FILE, $fd); - \curl_setopt($ch, \CURLOPT_SHARE, $this->shareHandle); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($ch, CURLOPT_DNS_USE_GLOBAL_CACHE, false); + curl_setopt($ch, CURLOPT_WRITEHEADER, $hd); + curl_setopt($ch, CURLOPT_FILE, $fd); + curl_setopt($ch, CURLOPT_SHARE, $this->shareHandle); foreach (self::$options as $type => $options) { foreach ($options as $name => $curlopt) { if (isset($params['options'][$type][$name])) { - \curl_setopt($ch, $curlopt, $params['options'][$type][$name]); + curl_setopt($ch, $curlopt, $params['options'][$type][$name]); } } } - $progress = \array_diff_key(\curl_getinfo($ch), self::$timeInfo); + $progress = array_diff_key(curl_getinfo($ch), self::$timeInfo); $this->jobs[(int) $ch] = [ 'progress' => $progress, @@ -173,39 +231,39 @@ public function get(string $originUrl, string $url, $context, ?string $file): ar 'fd' => $fd, ]; - \curl_multi_add_handle($this->multiHandle, $ch); + curl_multi_add_handle($this->multiHandle, $ch); - $params['notification'](\STREAM_NOTIFY_RESOLVE, \STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, 0, false); + $params['notification'](STREAM_NOTIFY_RESOLVE, STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, 0, false); $active = true; try { while ($active && isset($this->jobs[(int) $ch])) { - \curl_multi_exec($this->multiHandle, $active); - \curl_multi_select($this->multiHandle); + curl_multi_exec($this->multiHandle, $active); + curl_multi_select($this->multiHandle); - while ($progress = \curl_multi_info_read($this->multiHandle)) { + while ($progress = curl_multi_info_read($this->multiHandle)) { if (! isset($this->jobs[$i = (int) $h = $progress['handle']])) { continue; } - $progress = \array_diff_key(\curl_getinfo($h), self::$timeInfo); + $progress = array_diff_key(curl_getinfo($h), self::$timeInfo); $job = $this->jobs[$i]; unset($this->jobs[$i]); - \curl_multi_remove_handle($this->multiHandle, $h); + curl_multi_remove_handle($this->multiHandle, $h); try { $this->onProgress($h, $job['callback'], $progress, $job['progress']); - if (\curl_error($h) !== '') { - throw new TransportException(\curl_error($h)); + if (curl_error($h) !== '') { + throw new TransportException(curl_error($h)); } - if ($job['file'] && \curl_errno($h) === \CURLE_OK && ! isset($this->exceptions[$i])) { - \fclose($job['fd']); - \rename($job['file'] . '~', $job['file']); + if ($job['file'] && curl_errno($h) === CURLE_OK && ! isset($this->exceptions[$i])) { + fclose($job['fd']); + rename($job['file'] . '~', $job['file']); } } catch (TransportException $e) { $this->exceptions[$i] = $e; @@ -218,7 +276,7 @@ public function get(string $originUrl, string $url, $context, ?string $file): ar } $h = $this->jobs[$i]['ch']; - $progress = \array_diff_key(\curl_getinfo($h), self::$timeInfo); + $progress = array_diff_key(curl_getinfo($h), self::$timeInfo); if ($this->jobs[$i]['progress'] !== $progress) { $previousProgress = $this->jobs[$i]['progress']; @@ -229,7 +287,7 @@ public function get(string $originUrl, string $url, $context, ?string $file): ar } catch (TransportException $e) { unset($this->jobs[$i]); - \curl_multi_remove_handle($this->multiHandle, $h); + curl_multi_remove_handle($this->multiHandle, $h); $this->exceptions[$i] = $e; } @@ -237,8 +295,8 @@ public function get(string $originUrl, string $url, $context, ?string $file): ar } } - if (\curl_error($ch) !== '' || \curl_errno($ch) !== \CURLE_OK) { - $this->exceptions[(int) $ch] = new TransportException(\curl_error($ch), \curl_getinfo($ch, \CURLINFO_HTTP_CODE) ?: 0); + if (curl_error($ch) !== '' || curl_errno($ch) !== CURLE_OK) { + $this->exceptions[(int) $ch] = new TransportException(curl_error($ch), curl_getinfo($ch, CURLINFO_HTTP_CODE) ?: 0); } if (isset($this->exceptions[(int) $ch])) { @@ -246,23 +304,23 @@ public function get(string $originUrl, string $url, $context, ?string $file): ar } } finally { if ($file && ! isset($this->exceptions[(int) $ch])) { - $fd = \fopen($file, 'rb'); + $fd = fopen($file, 'rb'); } unset($this->jobs[(int) $ch], $this->exceptions[(int) $ch]); - \curl_multi_remove_handle($this->multiHandle, $ch); - \curl_close($ch); - \rewind($hd); + curl_multi_remove_handle($this->multiHandle, $ch); + curl_close($ch); + rewind($hd); - $headers = \explode("\r\n", \rtrim(\stream_get_contents($hd))); + $headers = explode("\r\n", rtrim(stream_get_contents($hd))); - \fclose($hd); - \rewind($fd); + fclose($hd); + rewind($fd); - $contents = \stream_get_contents($fd); + $contents = stream_get_contents($fd); - \fclose($fd); + fclose($fd); } return [$headers, $contents]; @@ -283,16 +341,16 @@ private function onProgress($ch, callable $notify, array $progress, array $previ } if (! ($previousProgress['http_code'] && $progress['http_code'] && $progress['http_code'] < 200) || $progress['http_code'] <= 400) { - $code = 403 === $progress['http_code'] ? \STREAM_NOTIFY_AUTH_RESULT : \STREAM_NOTIFY_FAILURE; - $notify($code, \STREAM_NOTIFY_SEVERITY_ERR, \curl_error($ch), $progress['http_code'], 0, 0, false); + $code = 403 === $progress['http_code'] ? STREAM_NOTIFY_AUTH_RESULT : STREAM_NOTIFY_FAILURE; + $notify($code, STREAM_NOTIFY_SEVERITY_ERR, curl_error($ch), $progress['http_code'], 0, 0, false); } if ($previousProgress['download_content_length'] < $progress['download_content_length']) { - $notify(\STREAM_NOTIFY_FILE_SIZE_IS, \STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, (int) $progress['download_content_length'], false); + $notify(STREAM_NOTIFY_FILE_SIZE_IS, STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, (int) $progress['download_content_length'], false); } if ($previousProgress['size_download'] < $progress['size_download']) { - $notify(\STREAM_NOTIFY_PROGRESS, \STREAM_NOTIFY_SEVERITY_INFO, '', 0, (int) $progress['size_download'], (int) $progress['download_content_length'], false); + $notify(STREAM_NOTIFY_PROGRESS, STREAM_NOTIFY_SEVERITY_INFO, '', 0, (int) $progress['size_download'], (int) $progress['download_content_length'], false); } } } diff --git a/src/Prefetcher/Downloader/ParallelDownloader.php b/src/Prefetcher/Downloader/ParallelDownloader.php index d61c9dfc..481a4012 100644 --- a/src/Prefetcher/Downloader/ParallelDownloader.php +++ b/src/Prefetcher/Downloader/ParallelDownloader.php @@ -17,6 +17,23 @@ use Composer\Downloader\TransportException; use Composer\IO\IOInterface; use Composer\Util\RemoteFilesystem; +use Exception; +use Throwable; +use const DIRECTORY_SEPARATOR; +use const PHP_OS; +use const STREAM_NOTIFY_FILE_SIZE_IS; +use const STREAM_NOTIFY_PROGRESS; +use const STREAM_NOTIFY_SEVERITY_ERR; +use function array_replace_recursive; +use function array_shift; +use function count; +use function extension_loaded; +use function func_num_args; +use function method_exists; +use function microtime; +use function preg_match; +use function sprintf; +use function stripos; /** * Ported from symfony flex, see original. @@ -117,10 +134,10 @@ public function __construct(IOInterface $io, Config $config, array $options = [] { $this->io = $io; - if (! \method_exists(parent::class, 'getRemoteContents')) { + if (! method_exists(parent::class, 'getRemoteContents')) { $this->io->writeError('Composer >=1.7 not found, downloads will happen in sequence', true, IOInterface::DEBUG); // @codeCoverageIgnoreStart - } elseif (! \extension_loaded('curl')) { + } elseif (! extension_loaded('curl')) { $this->io->writeError('ext-curl not found, downloads will happen in sequence', true, IOInterface::DEBUG); } else { $this->downloader = new CurlDownloader(); @@ -168,7 +185,7 @@ public function download(array &$nextArgs, callable $nextCallback, bool $quiet = $this->quiet = $quiet; $this->progress = $progress; - $this->downloadCount = \count($nextArgs); + $this->downloadCount = count($nextArgs); $this->nextCallback = $nextCallback; $this->sharedState = (object) [ 'bytesMaxCount' => 0, @@ -178,23 +195,23 @@ public function download(array &$nextArgs, callable $nextCallback, bool $quiet = 'nestingLevel' => 0, 'maxNestingReached' => false, 'lastProgress' => 0, - 'lastUpdate' => \microtime(true), + 'lastUpdate' => microtime(true), ]; if (! $this->quiet) { - if ($this->downloader === null && \method_exists(RemoteFilesystem::class, 'getRemoteContents')) { + if ($this->downloader === null && method_exists(RemoteFilesystem::class, 'getRemoteContents')) { $this->io->writeError('Enable the "cURL" PHP extension for faster downloads'); } $note = ''; if ($this->io->isDecorated()) { - $note = \DIRECTORY_SEPARATOR === '\\' ? '' : (false !== \stripos(\PHP_OS, 'darwin') ? '🎵' : '🎶'); - $note .= $this->downloader !== null ? (\DIRECTORY_SEPARATOR !== '\\' ? ' 💨' : '') : ''; + $note = DIRECTORY_SEPARATOR === '\\' ? '' : (false !== stripos(PHP_OS, 'darwin') ? '🎵' : '🎶'); + $note .= $this->downloader !== null ? (DIRECTORY_SEPARATOR !== '\\' ? ' 💨' : '') : ''; } $this->io->writeError(''); - $this->io->writeError(\sprintf('Prefetching %d packages %s', $this->downloadCount, $note)); + $this->io->writeError(sprintf('Prefetching %d packages %s', $this->downloadCount, $note)); $this->io->writeError(' - Downloading', false); if ($this->progress === true) { @@ -226,7 +243,7 @@ public function download(array &$nextArgs, callable $nextCallback, bool $quiet = */ public function getOptions(): array { - $options = \array_replace_recursive(parent::getOptions(), $this->nextOptions); + $options = array_replace_recursive(parent::getOptions(), $this->nextOptions); $this->nextOptions = []; return $options; @@ -241,7 +258,7 @@ public function getOptions(): array * @param bool $progress Display the progression * @param array $options Additional context options * - * @throws \Exception + * @throws Exception * * @return bool|string */ @@ -252,7 +269,7 @@ public function copy( $progress = true, $options = [] ) { - $options = \array_replace_recursive($this->nextOptions, $options); + $options = array_replace_recursive($this->nextOptions, $options); $this->nextOptions = []; $rfs = clone $this; $rfs->fileName = $fileName; @@ -288,7 +305,7 @@ public function callbackGet( $bytesMax, $nativeDownload = true ): void { - if (! $nativeDownload && \STREAM_NOTIFY_SEVERITY_ERR === $severity) { + if (! $nativeDownload && STREAM_NOTIFY_SEVERITY_ERR === $severity) { throw new TransportException($message, $messageCode); } @@ -298,12 +315,12 @@ public function callbackGet( return; } - if (\STREAM_NOTIFY_FILE_SIZE_IS === $notificationCode) { + if (STREAM_NOTIFY_FILE_SIZE_IS === $notificationCode) { $state->bytesMaxCount++; $state->bytesMax += $bytesMax; } - if (! $bytesMax || \STREAM_NOTIFY_PROGRESS !== $notificationCode) { + if (! $bytesMax || STREAM_NOTIFY_PROGRESS !== $notificationCode) { if ($state->nextArgs && ! $nativeDownload) { $this->getNext(); } @@ -323,12 +340,12 @@ public function callbackGet( } if ($state->nextArgs !== null && ! $this->quiet && $this->progress && 1 <= $progress - $state->lastProgress) { - $progressTime = \microtime(true); + $progressTime = microtime(true); if (5 <= $progress - $state->lastProgress || 1 <= $progressTime - $state->lastUpdate) { $state->lastProgress = $progress; - $this->io->overwriteError(\sprintf(' (%d%%)', $progress), false); - $state->lastUpdate = \microtime(true); + $this->io->overwriteError(sprintf(' (%d%%)', $progress), false); + $state->lastUpdate = microtime(true); } } @@ -346,12 +363,12 @@ public function callbackGet( /** * {@inheritdoc} */ - protected function getRemoteContents($originUrl, $fileUrl, $context, array &$responseHeaders = null) + protected function getRemoteContents($originUrl, $fileUrl, $context, ?array &$responseHeaders = null) { if (isset(self::$cache[$fileUrl])) { $result = self::$cache[$fileUrl]; - if (3 < \func_num_args()) { + if (3 < func_num_args()) { [$responseHeaders, $result] = $result; } @@ -361,7 +378,7 @@ protected function getRemoteContents($originUrl, $fileUrl, $context, array &$res if (self::$cacheNext) { self::$cacheNext = false; - if (3 < \func_num_args()) { + if (3 < func_num_args()) { $result = $this->getRemoteContents($originUrl, $fileUrl, $context, $responseHeaders); self::$cache[$fileUrl] = [$responseHeaders, $result]; @@ -374,14 +391,14 @@ protected function getRemoteContents($originUrl, $fileUrl, $context, array &$res return $result; } - if ($this->downloader === null || \preg_match('/^https?:/', $originUrl) !== 1) { + if ($this->downloader === null || preg_match('/^https?:/', $originUrl) !== 1) { return parent::getRemoteContents($originUrl, $fileUrl, $context, $responseHeaders); } try { $result = $this->downloader->get($originUrl, $fileUrl, $context, $this->fileName); - if (3 < \func_num_args()) { + if (3 < func_num_args()) { [$responseHeaders, $result] = $result; } @@ -390,7 +407,7 @@ protected function getRemoteContents($originUrl, $fileUrl, $context, array &$res $this->io->writeError('Retrying download: ' . $exception->getMessage(), true, IOInterface::DEBUG); return parent::getRemoteContents($originUrl, $fileUrl, $context, $responseHeaders); - } catch (\Throwable $e) { + } catch (Throwable $e) { $responseHeaders = []; throw $e; @@ -414,7 +431,7 @@ private function getNext(): void $state->maxNestingReached = false; if ($this->nextCallback !== null) { - ($this->nextCallback)(...\array_shift($state->nextArgs)); + ($this->nextCallback)(...array_shift($state->nextArgs)); } } catch (TransportException $exception) { $this->io->writeError('Skipping download: ' . $exception->getMessage(), true, IOInterface::DEBUG); diff --git a/src/Prefetcher/LegacyTagsManager.php b/src/Prefetcher/LegacyTagsManager.php index 83a6b672..394dd0db 100644 --- a/src/Prefetcher/LegacyTagsManager.php +++ b/src/Prefetcher/LegacyTagsManager.php @@ -17,6 +17,12 @@ use Composer\Semver\Constraint\Constraint; use Composer\Semver\VersionParser; use Narrowspark\Automatic\Prefetcher\Contract\LegacyTagsManager as LegacyTagsManagerContract; +use function array_filter; +use function array_intersect_key; +use function count; +use function explode; +use function sprintf; +use function strpos; final class LegacyTagsManager implements LegacyTagsManagerContract { @@ -72,9 +78,9 @@ public function addConstraint(string $name, string $require): void public function hasProvider(string $file): bool { foreach ($this->legacyTags as $name => $constraint) { - [$namespace,] = \explode('/', $name, 2); + [$namespace,] = explode('/', $name, 2); - if (\strpos($file, \sprintf('provider-%s$', $namespace)) !== false) { + if (strpos($file, sprintf('provider-%s$', $namespace)) !== false) { return true; } } @@ -122,7 +128,7 @@ public function removeLegacyTags(array $data): array } else { if (! isset(self::$packageCache[$name])) { $this->io->writeError( - \sprintf('Restricting packages listed in [%s] to [%s]', $name, (string) $legacy['version']) + sprintf('Restricting packages listed in [%s] to [%s]', $name, (string) $legacy['version']) ); self::$packageCache[$name] = true; } @@ -132,7 +138,7 @@ public function removeLegacyTags(array $data): array } } - if (\count(\array_filter($packages)) === 0) { + if (count(array_filter($packages)) === 0) { return $data; } @@ -152,7 +158,7 @@ public function removeLegacyTags(array $data): array $devMaster = $versions['dev-master']; } - $versions = \array_intersect_key($versions, $data['packages'][$parentName]); + $versions = array_intersect_key($versions, $data['packages'][$parentName]); if ($devMaster !== null && null !== $devMasterAlias = $versions['dev-master']['extra']['branch-alias']['dev-master'] ?? null) { /** @var \Composer\Semver\Constraint\Constraint $legacyConstrain */ @@ -163,7 +169,7 @@ public function removeLegacyTags(array $data): array } } - if (\count($versions) !== 0) { + if (count($versions) !== 0) { $data['packages'][$name] = $versions; } } diff --git a/src/Prefetcher/Plugin.php b/src/Prefetcher/Plugin.php index d1941104..f005a4ab 100644 --- a/src/Prefetcher/Plugin.php +++ b/src/Prefetcher/Plugin.php @@ -32,14 +32,33 @@ use Composer\Repository\RepositoryInterface; use Composer\Repository\RepositoryManager; use FilesystemIterator; +use InvalidArgumentException; use Narrowspark\Automatic\Common\AbstractContainer; use Narrowspark\Automatic\Common\Contract\Container as ContainerContract; -use Narrowspark\Automatic\Common\Contract\Exception\RuntimeException; +use Narrowspark\Automatic\Common\Util; use Narrowspark\Automatic\Prefetcher\Contract\LegacyTagsManager as LegacyTagsManagerContract; use Narrowspark\Automatic\Prefetcher\Downloader\ParallelDownloader; use RecursiveDirectoryIterator; use RecursiveIteratorIterator; +use ReflectionMethod; +use SplFileInfo; use Symfony\Component\Console\Input\ArgvInput; +use const DIRECTORY_SEPARATOR; +use const PHP_INT_MAX; +use function array_merge; +use function class_exists; +use function debug_backtrace; +use function dirname; +use function explode; +use function getenv; +use function is_int; +use function method_exists; +use function sprintf; +use function str_replace; +use function strlen; +use function strpos; +use function substr; +use function version_compare; class Plugin implements EventSubscriberInterface, PluginInterface { @@ -89,16 +108,16 @@ public function activate(Composer $composer, IOInterface $io): void return; } - if (! \class_exists(AbstractContainer::class)) { - require __DIR__ . \DIRECTORY_SEPARATOR . 'alias.php'; + if (! class_exists(AbstractContainer::class)) { + require __DIR__ . DIRECTORY_SEPARATOR . 'alias.php'; } // to avoid issues when Automatic Prefetcher is upgraded, we load all PHP classes now // that way, we are sure to use all classes from the same version. - foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator(\dirname(__DIR__, 1), FilesystemIterator::SKIP_DOTS)) as $file) { - /** @var \SplFileInfo $file */ - if (\substr($file->getFilename(), -4) === '.php') { - \class_exists(__NAMESPACE__ . \str_replace('/', '\\', \substr($file->getFilename(), \strlen(__DIR__), -4))); + foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator(dirname(__DIR__, 1), FilesystemIterator::SKIP_DOTS)) as $file) { + /** @var SplFileInfo $file */ + if (substr($file->getFilename(), -4) === '.php') { + class_exists(__NAMESPACE__ . str_replace('/', '\\', substr($file->getFilename(), strlen(__DIR__), -4))); } } @@ -118,7 +137,7 @@ public function activate(Composer $composer, IOInterface $io): void $this->container->get(Prefetcher::class)->populateRepoCacheDir(); - $this->extendComposer(\debug_backtrace(), $tagsManager); + $this->extendComposer(debug_backtrace(), $tagsManager); } /** @@ -131,10 +150,10 @@ public static function getSubscribedEvents(): array } return [ - InstallerEvents::PRE_DEPENDENCIES_SOLVING => [['onPreDependenciesSolving', \PHP_INT_MAX]], - InstallerEvents::POST_DEPENDENCIES_SOLVING => [['populateFilesCacheDir', \PHP_INT_MAX]], - PackageEvents::PRE_PACKAGE_INSTALL => [['populateFilesCacheDir', ~\PHP_INT_MAX]], - PackageEvents::PRE_PACKAGE_UPDATE => [['populateFilesCacheDir', ~\PHP_INT_MAX]], + InstallerEvents::PRE_DEPENDENCIES_SOLVING => [['onPreDependenciesSolving', PHP_INT_MAX]], + InstallerEvents::POST_DEPENDENCIES_SOLVING => [['populateFilesCacheDir', PHP_INT_MAX]], + PackageEvents::PRE_PACKAGE_INSTALL => [['populateFilesCacheDir', ~PHP_INT_MAX]], + PackageEvents::PRE_PACKAGE_UPDATE => [['populateFilesCacheDir', ~PHP_INT_MAX]], PluginEvents::PRE_FILE_DOWNLOAD => 'onFileDownload', ]; } @@ -151,7 +170,7 @@ public function onPreDependenciesSolving(InstallerEvent $event): void $listed = []; $packages = []; $pool = $event->getPool(); - $pool = \Closure::bind(function () { + $pool = Closure::bind(function () { foreach ($this->providerRepos as $k => $repo) { $this->providerRepos[$k] = new class($repo) extends BaseComposerRepository { /** @@ -176,7 +195,7 @@ public function whatProvides(Pool $pool, $name, $bypassFilters = false) { $packages = []; - if (! \method_exists($this->repo, 'whatProvides')) { + if (! method_exists($this->repo, 'whatProvides')) { return $packages; } @@ -193,7 +212,7 @@ public function whatProvides(Pool $pool, $name, $bypassFilters = false) }, clone $pool, $pool)(); foreach ($event->getRequest()->getJobs() as $job) { - if ($job['cmd'] !== 'install' || \strpos($job['packageName'], '/') === false) { + if ($job['cmd'] !== 'install' || strpos($job['packageName'], '/') === false) { continue; } @@ -201,16 +220,16 @@ public function whatProvides(Pool $pool, $name, $bypassFilters = false) $packages[] = [$job['packageName'], $job['constraint']]; } - $loadExtraRepos = ! (new \ReflectionMethod(Pool::class, 'match'))->isPublic(); // Detect Composer < 1.7.3 + $loadExtraRepos = ! (new ReflectionMethod(Pool::class, 'match'))->isPublic(); // Detect Composer < 1.7.3 $this->container->get(ParallelDownloader::class)->download($packages, static function (string $packageName, $constraint) use (&$listed, &$packages, $pool, $loadExtraRepos): void { /** @var \Composer\Package\PackageInterface $package */ foreach ($pool->whatProvides($packageName, $constraint, true) as $package) { - $links = $loadExtraRepos ? \array_merge($package->getRequires(), $package->getConflicts(), $package->getReplaces()) : $package->getRequires(); + $links = $loadExtraRepos ? array_merge($package->getRequires(), $package->getConflicts(), $package->getReplaces()) : $package->getRequires(); /** @var \Composer\Package\Link $link */ foreach ($links as $link) { - if (isset($listed[$link->getTarget()]) || \strpos($link->getTarget(), '/') === false) { + if (isset($listed[$link->getTarget()]) || strpos($link->getTarget(), '/') === false) { continue; } @@ -232,7 +251,10 @@ public function whatProvides(Pool $pool, $name, $bypassFilters = false) */ public function populateFilesCacheDir($event): void { - $this->container->get(Prefetcher::class)->fetchAllFromOperations($event); + /** @var \Narrowspark\Automatic\Prefetcher\Prefetcher $prefetcher */ + $prefetcher = $this->container->get(Prefetcher::class); + + $prefetcher->fetchAllFromOperations($event); } /** @@ -266,13 +288,13 @@ private function configureLegacyTagsManager( LegacyTagsManagerContract $tagsManager, array $extra ): void { - $envRequire = \getenv('AUTOMATIC_PREFETCHER_REQUIRE'); + $envRequire = getenv('AUTOMATIC_PREFETCHER_REQUIRE'); if ($envRequire !== false) { $requires = []; - foreach (\explode(',', $envRequire) as $packageString) { - [$packageName, $version] = \explode(':', $packageString, 2); + foreach (explode(',', $envRequire) as $packageString) { + [$packageName, $version] = explode(':', $packageString, 2); $requires[$packageName] = $version; } @@ -295,14 +317,14 @@ private function configureLegacyTagsManager( private function addLegacyTags(IOInterface $io, array $requires, LegacyTagsManagerContract $tagsManager): void { foreach ($requires as $name => $version) { - if (\is_int($name)) { - $io->writeError(\sprintf('Constrain [%s] skipped, because package name is a number [%s]', $version, $name)); + if (is_int($name)) { + $io->writeError(sprintf('Constrain [%s] skipped, because package name is a number [%s]', $version, $name)); continue; } - if (\strpos($name, '/') === false) { - $io->writeError(\sprintf('Constrain [%s] skipped, package name [%s] without a slash is not supported', $version, $name)); + if (strpos($name, '/') === false) { + $io->writeError(sprintf('Constrain [%s] skipped, package name [%s] without a slash is not supported', $version, $name)); continue; } @@ -367,8 +389,8 @@ private function getErrorMessage(): ?string return 'You must enable the openssl extension in your [php.ini] file'; } - if (\version_compare(self::getComposerVersion(), '1.7.0', '<')) { - return \sprintf('Your version "%s" of Composer is too old; Please upgrade', Composer::VERSION); + if (version_compare(Util::getComposerVersion(), '1.7.0', '<')) { + return sprintf('Your version "%s" of Composer is too old; Please upgrade', Composer::VERSION); } // @codeCoverageIgnoreEnd @@ -402,7 +424,7 @@ private function extendComposer($backtrace, LegacyTagsManagerContract $tagsManag /** @var null|string $command */ $command = $input->getFirstArgument(); $command = $command !== null ? $app->find($command)->getName() : null; - } catch (\InvalidArgumentException $e) { + } catch (InvalidArgumentException $e) { $command = null; } @@ -422,28 +444,4 @@ private function extendComposer($backtrace, LegacyTagsManagerContract $tagsManag break; } } - - /** - * Get the composer version. - * - * @throws \Narrowspark\Automatic\Common\Contract\Exception\RuntimeException - * - * @return string - */ - private static function getComposerVersion(): string - { - \preg_match('/\d+.\d+.\d+/m', Composer::VERSION, $matches); - - if ($matches !== null) { - return $matches[0]; - } - - \preg_match('/\d+.\d+.\d+/m', Composer::BRANCH_ALIAS_VERSION, $matches); - - if ($matches !== null) { - return $matches[0]; - } - - throw new RuntimeException('No composer version found.'); - } } diff --git a/src/Prefetcher/Prefetcher.php b/src/Prefetcher/Prefetcher.php index 67ca1cb9..53dd6748 100644 --- a/src/Prefetcher/Prefetcher.php +++ b/src/Prefetcher/Prefetcher.php @@ -25,6 +25,21 @@ use Narrowspark\Automatic\Common\Util; use Narrowspark\Automatic\Prefetcher\Downloader\ParallelDownloader; use Symfony\Component\Console\Input\InputInterface; +use const DIRECTORY_SEPARATOR; +use const PHP_URL_HOST; +use function count; +use function current; +use function dirname; +use function file_exists; +use function get_class; +use function is_dir; +use function method_exists; +use function mkdir; +use function parse_url; +use function preg_match; +use function rtrim; +use function sprintf; +use function strpos; class Prefetcher { @@ -116,7 +131,7 @@ public function __construct(Composer $composer, IOInterface $io, InputInterface $this->config = $composer->getConfig(); $this->fileDownloader = $composer->getDownloadManager()->getDownloader('file'); $this->rfs = $rfs; - $this->cacheFilesDir = \rtrim($this->config->get('cache-files-dir'), '\/'); + $this->cacheFilesDir = rtrim($this->config->get('cache-files-dir'), '\/'); } /** @@ -131,8 +146,8 @@ public function populateRepoCacheDir(): void if ($pluginManager instanceof PluginManager) { foreach ($pluginManager->getPlugins() as $plugin) { - if (\strpos(\get_class($plugin), PrestissimoPlugin::class) === 0) { - if (\method_exists($this->rfs, 'getRemoteContents')) { + if (strpos(get_class($plugin), PrestissimoPlugin::class) === 0) { + if (method_exists($this->rfs, 'getRemoteContents')) { $plugin->disable(); } else { $this->cacheDirPopulated = true; @@ -155,7 +170,7 @@ public function prefetchComposerRepositories(): void if ($this->populateRepoCacheDir === true && isset(self::$repoReadingCommands[$command]) - && ($command !== 'install' || (\file_exists(Factory::getComposerFile()) && ! \file_exists(Util::getComposerLockFile()))) + && ($command !== 'install' || (file_exists(Factory::getComposerFile()) && ! file_exists(Util::getComposerLockFile()))) ) { $repos = []; @@ -165,7 +180,7 @@ public function prefetchComposerRepositories(): void } /** @see https://github.com/composer/composer/blob/master/src/Composer/Repository/ComposerRepository.php#L74 */ - if (! \preg_match('#^http(s\??)?://#', $repo['url'])) { + if (! preg_match('#^http(s\??)?://#', $repo['url'])) { continue; } @@ -212,30 +227,30 @@ public function fetchAllFromOperations($event): void $url = self::getUrlFromPackage($package); - if ($url === null || ! $originUrl = \parse_url($url, \PHP_URL_HOST)) { + if ($url === null || ! $originUrl = parse_url($url, PHP_URL_HOST)) { continue; } - $destination = $this->cacheFilesDir . \DIRECTORY_SEPARATOR . $this->getCacheKey($package, $url); + $destination = $this->cacheFilesDir . DIRECTORY_SEPARATOR . $this->getCacheKey($package, $url); - if (\file_exists($destination)) { + if (file_exists($destination)) { continue; } - if (! @\mkdir($concurrentDirectory = \dirname($destination), 0775, true) && ! \is_dir($concurrentDirectory)) { + if (! @mkdir($concurrentDirectory = dirname($destination), 0775, true) && ! is_dir($concurrentDirectory)) { continue; } - if (\preg_match('#^https://github\.com/#', $package->getSourceUrl()) - && \preg_match('#^https://api\.github\.com/repos(/[^/]++/[^/]++/)zipball(.++)$#', $url, $matches) + if (preg_match('#^https://github\.com/#', $package->getSourceUrl()) + && preg_match('#^https://api\.github\.com/repos(/[^/]++/[^/]++/)zipball(.++)$#', $url, $matches) ) { - $url = \sprintf('https://codeload.github.com%slegacy.zip%s', $matches[1], $matches[2]); + $url = sprintf('https://codeload.github.com%slegacy.zip%s', $matches[1], $matches[2]); } $downloads[] = [$originUrl, $url, [], $destination, false]; } - if (\count($downloads) > 1) { + if (count($downloads) > 1) { $progress = true; if ($this->input->hasParameterOption('--no-progress', true)) { @@ -262,10 +277,10 @@ private static function getUrlFromPackage(PackageInterface $package): ?string } if ($package->getDistMirrors()) { - $fileUrl = \current($package->getDistUrls()); + $fileUrl = current($package->getDistUrls()); } - if (! \preg_match('/^https?:/', $fileUrl)) { + if (! preg_match('/^https?:/', $fileUrl)) { return null; } @@ -300,12 +315,10 @@ function (PackageInterface $package, $processedUrl) { */ private function getDryRun(): bool { - $dryRun = false; - if ($this->input->hasParameterOption('--dry-run')) { - $dryRun = true; + return true; } - return $dryRun; + return false; } } diff --git a/src/Prefetcher/TruncatedComposerRepository.php b/src/Prefetcher/TruncatedComposerRepository.php index 55a81a87..0a22b34d 100644 --- a/src/Prefetcher/TruncatedComposerRepository.php +++ b/src/Prefetcher/TruncatedComposerRepository.php @@ -19,6 +19,8 @@ use Composer\Repository\ComposerRepository as BaseComposerRepository; use Composer\Util\RemoteFilesystem; use Narrowspark\Automatic\Prefetcher\Contract\LegacyTagsManager as LegacyTagsManagerContract; +use function is_array; +use function preg_replace; /** * Ported from symfony flex, see original. @@ -36,14 +38,14 @@ public function __construct( array $repoConfig, IOInterface $io, Config $config, - EventDispatcher $eventDispatcher = null, - RemoteFilesystem $rfs = null + ?EventDispatcher $eventDispatcher = null, + ?RemoteFilesystem $rfs = null ) { parent::__construct($repoConfig, $io, $config, $eventDispatcher, $rfs); $this->cache = new Cache( $io, - $config->get('cache-repo-dir') . '/' . \preg_replace('{[^a-z0-9.]}i', '-', $this->url), + $config->get('cache-repo-dir') . '/' . preg_replace('{[^a-z0-9.]}i', '-', $this->url), 'a-z0-9.$' ); } @@ -67,6 +69,6 @@ protected function fetchFile($filename, $cacheKey = null, $sha256 = null, $store { $data = parent::fetchFile($filename, $cacheKey, $sha256, $storeLastModifiedTime); - return \is_array($data) ? $this->cache->removeLegacyTags($data) : $data; + return is_array($data) ? $this->cache->removeLegacyTags($data) : $data; } } diff --git a/src/Prefetcher/alias.php b/src/Prefetcher/alias.php index 7953b991..987c56f3 100644 --- a/src/Prefetcher/alias.php +++ b/src/Prefetcher/alias.php @@ -11,11 +11,13 @@ * with this source code in the file LICENSE. */ -\class_alias(Narrowspark\Automatic\Prefetcher\Common\Contract\Exception\Exception::class, Narrowspark\Automatic\Common\Contract\Exception\Exception::class); -\class_alias(Narrowspark\Automatic\Prefetcher\Common\Contract\Exception\InvalidArgumentException::class, Narrowspark\Automatic\Common\Contract\Exception\InvalidArgumentException::class); -\class_alias(Narrowspark\Automatic\Prefetcher\Common\Contract\Container::class, Narrowspark\Automatic\Common\Contract\Container::class); -\class_alias(Narrowspark\Automatic\Prefetcher\Common\AbstractContainer::class, Narrowspark\Automatic\Common\AbstractContainer::class); -\class_alias(Narrowspark\Automatic\Prefetcher\Common\Contract\Resettable::class, Narrowspark\Automatic\Common\Contract\Resettable::class); -\class_alias(Narrowspark\Automatic\Prefetcher\Common\Traits\GetGenericPropertyReaderTrait::class, Narrowspark\Automatic\Common\Traits\GetGenericPropertyReaderTrait::class); -\class_alias(Narrowspark\Automatic\Prefetcher\Common\Contract\Exception\RuntimeException::class, Narrowspark\Automatic\Common\Contract\Exception\RuntimeException::class); -\class_alias(Narrowspark\Automatic\Prefetcher\Common\Util::class, Narrowspark\Automatic\Common\Util::class); +use function class_alias; + +class_alias(Narrowspark\Automatic\Prefetcher\Common\Contract\Exception\Exception::class, Narrowspark\Automatic\Common\Contract\Exception\Exception::class); +class_alias(Narrowspark\Automatic\Prefetcher\Common\Contract\Exception\InvalidArgumentException::class, Narrowspark\Automatic\Common\Contract\Exception\InvalidArgumentException::class); +class_alias(Narrowspark\Automatic\Prefetcher\Common\Contract\Container::class, Narrowspark\Automatic\Common\Contract\Container::class); +class_alias(Narrowspark\Automatic\Prefetcher\Common\AbstractContainer::class, Narrowspark\Automatic\Common\AbstractContainer::class); +class_alias(Narrowspark\Automatic\Prefetcher\Common\Contract\Resettable::class, Narrowspark\Automatic\Common\Contract\Resettable::class); +class_alias(Narrowspark\Automatic\Prefetcher\Common\Traits\GetGenericPropertyReaderTrait::class, Narrowspark\Automatic\Common\Traits\GetGenericPropertyReaderTrait::class); +class_alias(Narrowspark\Automatic\Prefetcher\Common\Contract\Exception\RuntimeException::class, Narrowspark\Automatic\Common\Contract\Exception\RuntimeException::class); +class_alias(Narrowspark\Automatic\Prefetcher\Common\Util::class, Narrowspark\Automatic\Common\Util::class); diff --git a/src/Security/Audit.php b/src/Security/Audit.php index f8b58518..db4c3511 100644 --- a/src/Security/Audit.php +++ b/src/Security/Audit.php @@ -21,6 +21,15 @@ use Narrowspark\Automatic\Security\Contract\Downloader as DownloaderContract; use Narrowspark\Automatic\Security\Contract\Exception\RuntimeException; use Symfony\Component\Filesystem\Filesystem; +use const DIRECTORY_SEPARATOR; +use function file_get_contents; +use function is_array; +use function json_decode; +use function ksort; +use function sprintf; +use function strlen; +use function strpos; +use function substr; final class Audit { @@ -68,6 +77,13 @@ final class Audit */ private $sha; + /** + * Check if composer is in dev mode. + * + * @var bool + */ + private $devMode = true; + /** * Create a new Audit instance. * @@ -84,6 +100,16 @@ public function __construct(string $composerVendorPath, DownloaderContract $down $this->sha = $sha; } + /** + * Set the composer dev mode. + * + * @param bool $bool + */ + public function setDevMode($bool): void + { + $this->devMode = $bool; + } + /** * Checks a package on name and version. * @@ -103,7 +129,7 @@ public function checkPackage(string $name, string $version, array $securityAdvis [$messages, $vulnerabilities] = $this->checkPackageAgainstSecurityAdvisories($securityAdvisories, $package); - \ksort($vulnerabilities); + ksort($vulnerabilities); return [$vulnerabilities, $messages]; } @@ -127,8 +153,13 @@ public function checkLock(string $lock): array /** @var \Composer\Package\Package[] $packages */ $packages = []; + $keys = ['packages']; - foreach (['packages', 'packages-dev'] as $key) { + if ($this->devMode) { + $keys[] = 'packages-dev'; + } + + foreach ($keys as $key) { $data = $lockContents[$key]; foreach ($data as $pkgData) { @@ -148,7 +179,7 @@ public function checkLock(string $lock): array [$messages, $vulnerabilities] = $this->checkPackageAgainstSecurityAdvisories($securityAdvisories, $package, $messages, $vulnerabilities); } - \ksort($vulnerabilities); + ksort($vulnerabilities); return [$vulnerabilities, $messages]; } @@ -162,7 +193,7 @@ public function checkLock(string $lock): array */ public function getSecurityAdvisories(?IOInterface $io = null): array { - $narrowsparkAutomaticPath = $this->composerVendorPath . \DIRECTORY_SEPARATOR . 'narrowspark' . \DIRECTORY_SEPARATOR . 'automatic' . \DIRECTORY_SEPARATOR; + $narrowsparkAutomaticPath = $this->composerVendorPath . DIRECTORY_SEPARATOR . 'narrowspark' . DIRECTORY_SEPARATOR . 'automatic' . DIRECTORY_SEPARATOR; if (! $this->filesystem->exists($narrowsparkAutomaticPath)) { $this->filesystem->mkdir($narrowsparkAutomaticPath); @@ -172,10 +203,10 @@ public function getSecurityAdvisories(?IOInterface $io = null): array $securityAdvisoriesPath = $narrowsparkAutomaticPath . self::SECURITY_ADVISORIES; if ($this->filesystem->exists($securityAdvisoriesShaPath)) { - $oldSha = \file_get_contents($securityAdvisoriesShaPath); + $oldSha = file_get_contents($securityAdvisoriesShaPath); if ($oldSha === $this->sha) { - return \json_decode((string) \file_get_contents($securityAdvisoriesPath), true); + return json_decode((string) file_get_contents($securityAdvisoriesPath), true); } } @@ -188,7 +219,7 @@ public function getSecurityAdvisories(?IOInterface $io = null): array $this->filesystem->dumpFile($securityAdvisoriesShaPath, $this->sha); $this->filesystem->dumpFile($securityAdvisoriesPath, $securityAdvisories); - return \json_decode($securityAdvisories, true); + return json_decode($securityAdvisories, true); } /** @@ -198,11 +229,11 @@ public function getSecurityAdvisories(?IOInterface $io = null): array */ private function getLockContents(string $lock): array { - $contents = \json_decode((string) \file_get_contents($lock), true); + $contents = json_decode((string) file_get_contents($lock), true); $packages = ['packages' => [], 'packages-dev' => []]; foreach (['packages', 'packages-dev'] as $key) { - if (! \is_array($contents[$key])) { + if (! is_array($contents[$key])) { continue; } @@ -212,7 +243,7 @@ private function getLockContents(string $lock): array 'version' => $package['version'], ]; - if (isset($package['time']) && false !== \strpos($package['version'], 'dev')) { + if (isset($package['time']) && false !== strpos($package['version'], 'dev')) { $data['time'] = $package['time']; } @@ -242,7 +273,7 @@ private function checkPackageAgainstSecurityAdvisories( $name = $package->getName(); foreach ($securityAdvisories[$name] as $key => $advisoryData) { - if (! \is_array($advisoryData['branches'])) { + if (! is_array($advisoryData['branches'])) { $messages[$name][] = '"branches" is expected to be an array.'; continue; @@ -250,9 +281,9 @@ private function checkPackageAgainstSecurityAdvisories( foreach ($advisoryData['branches'] as $n => $branch) { if (! isset($branch['versions'])) { - $messages[$n][] = \sprintf('Key [versions] is not set for branch [%s].', $key); - } elseif (! \is_array($branch['versions'])) { - $messages[$n][] = \sprintf('Key [versions] is expected to be an array for branch [%s].', $key); + $messages[$n][] = sprintf('Key [versions] is not set for branch [%s].', $key); + } elseif (! is_array($branch['versions'])) { + $messages[$n][] = sprintf('Key [versions] is expected to be an array for branch [%s].', $key); } else { $constraints = []; @@ -260,7 +291,7 @@ private function checkPackageAgainstSecurityAdvisories( $op = null; foreach (Constraint::getSupportedOperators() as $operators) { - if (\strpos($version, $operators) === 0) { + if (strpos($version, $operators) === 0) { $op = $operators; break; @@ -268,19 +299,19 @@ private function checkPackageAgainstSecurityAdvisories( } if (null === $op) { - $messages[$n][] = \sprintf('Version [%s] does not contain a supported operator.', $version); + $messages[$n][] = sprintf('Version [%s] does not contain a supported operator.', $version); continue; } - $constraints[] = new Constraint($op, \substr($version, \strlen($op))); + $constraints[] = new Constraint($op, substr($version, strlen($op))); } $affectedConstraint = new MultiConstraint($constraints); $affectedPackage = $affectedConstraint->matches(new Constraint('==', $package->getVersion())); if ($affectedPackage) { - $composerPackage = \substr($advisoryData['reference'], 11); + $composerPackage = substr($advisoryData['reference'], 11); $vulnerabilities[$composerPackage] = $vulnerabilities[$composerPackage] ?? [ 'version' => $package->getPrettyVersion(), diff --git a/src/Security/Command/AuditCommand.php b/src/Security/Command/AuditCommand.php index 5c5bb745..c46d5a01 100644 --- a/src/Security/Command/AuditCommand.php +++ b/src/Security/Command/AuditCommand.php @@ -16,6 +16,7 @@ use Composer\Command\BaseCommand; use Composer\Factory; use Composer\IO\NullIO; +use Narrowspark\Automatic\Common\Util; use Narrowspark\Automatic\Security\Audit; use Narrowspark\Automatic\Security\Command\Formatter\JsonFormatter; use Narrowspark\Automatic\Security\Command\Formatter\SimpleFormatter; @@ -23,12 +24,16 @@ use Narrowspark\Automatic\Security\Contract\Exception\RuntimeException; use Narrowspark\Automatic\Security\Downloader\ComposerDownloader; use Narrowspark\Automatic\Security\Downloader\CurlDownloader; -use Narrowspark\Automatic\Security\Util; use Symfony\Component\Console\Helper\HelperSet; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; +use function count; +use function extension_loaded; +use function method_exists; +use function rtrim; +use function sprintf; final class AuditCommand extends BaseCommand { @@ -61,7 +66,7 @@ protected function configure(): void */ protected function execute(InputInterface $input, OutputInterface $output): int { - if (\extension_loaded('curl')) { + if (extension_loaded('curl')) { $downloader = new CurlDownloader(); } else { $downloader = new ComposerDownloader(); @@ -87,7 +92,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } $config = Factory::createConfig(new NullIO()); - $audit = new Audit(\rtrim($config->get('vendor-dir'), '/'), $downloader, $sha); + $audit = new Audit(rtrim($config->get('vendor-dir'), '/'), $downloader, $sha); /** @var null|string $composerFile */ $composerFile = $input->getOption('composer-lock'); @@ -121,13 +126,13 @@ protected function execute(InputInterface $input, OutputInterface $output): int $message = 'This checker can only detect vulnerabilities that are referenced in the SensioLabs security advisories database.'; - if (\method_exists($output, 'comment')) { + if (method_exists($output, 'comment')) { $output->comment($message); } else { - $output->writeln(\sprintf('%s', $message)); + $output->writeln(sprintf('%s', $message)); } - if (\count($messages) !== 0) { + if (count($messages) !== 0) { $output->note('Please report this found messages to https://github.com/narrowspark/security-advisories.'); foreach ($messages as $key => $msg) { @@ -135,9 +140,9 @@ protected function execute(InputInterface $input, OutputInterface $output): int } } - $count = \count($vulnerabilities); + $count = count($vulnerabilities); - if (\count($vulnerabilities) !== 0) { + if (count($vulnerabilities) !== 0) { switch ($input->getOption('format')) { case 'json': $formatter = new JsonFormatter(); @@ -154,7 +159,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $formatter->displayResults($output, $vulnerabilities); - $output->writeln('[!] ' . \sprintf('%s vulnerabilit%s found - ', $count, $count === 1 ? 'y' : 'ies') + $output->writeln('[!] ' . sprintf('%s vulnerabilit%s found - ', $count, $count === 1 ? 'y' : 'ies') . 'We recommend you to check the related security advisories and upgrade these dependencies.'); return $errorExitCode; diff --git a/src/Security/Command/Formatter/JsonFormatter.php b/src/Security/Command/Formatter/JsonFormatter.php index 3173ea6f..40824335 100644 --- a/src/Security/Command/Formatter/JsonFormatter.php +++ b/src/Security/Command/Formatter/JsonFormatter.php @@ -15,6 +15,8 @@ use Narrowspark\Automatic\Security\Contract\Command\Formatter as FormatterContract; use Symfony\Component\Console\Style\SymfonyStyle; +use const JSON_PRETTY_PRINT; +use function json_encode; final class JsonFormatter implements FormatterContract { @@ -23,6 +25,6 @@ final class JsonFormatter implements FormatterContract */ public function displayResults(SymfonyStyle $output, array $vulnerabilities): void { - $output->writeln((string) \json_encode($vulnerabilities, \JSON_PRETTY_PRINT)); + $output->writeln((string) json_encode($vulnerabilities, JSON_PRETTY_PRINT)); } } diff --git a/src/Security/Command/Formatter/SimpleFormatter.php b/src/Security/Command/Formatter/SimpleFormatter.php index 6801f9bc..b33d6379 100644 --- a/src/Security/Command/Formatter/SimpleFormatter.php +++ b/src/Security/Command/Formatter/SimpleFormatter.php @@ -15,6 +15,9 @@ use Narrowspark\Automatic\Security\Contract\Command\Formatter as FormatterContract; use Symfony\Component\Console\Style\SymfonyStyle; +use function count; +use function str_repeat; +use function strlen; final class SimpleFormatter implements FormatterContract { @@ -23,10 +26,10 @@ final class SimpleFormatter implements FormatterContract */ public function displayResults(SymfonyStyle $output, array $vulnerabilities): void { - if (\count($vulnerabilities) !== 0) { + if (count($vulnerabilities) !== 0) { foreach ($vulnerabilities as $dependency => $issues) { $dependencyFullName = $dependency . ' (' . $issues['version'] . ')'; - $output->writeln('' . $dependencyFullName . "\n" . \str_repeat('-', \strlen($dependencyFullName)) . '' . "\n"); + $output->writeln('' . $dependencyFullName . "\n" . str_repeat('-', strlen($dependencyFullName)) . '' . "\n"); foreach ($issues['advisories'] as $issue => $details) { $output->write(' * '); diff --git a/src/Security/Command/Formatter/TextFormatter.php b/src/Security/Command/Formatter/TextFormatter.php index c1cf7a23..61f17e62 100644 --- a/src/Security/Command/Formatter/TextFormatter.php +++ b/src/Security/Command/Formatter/TextFormatter.php @@ -15,6 +15,9 @@ use Narrowspark\Automatic\Security\Contract\Command\Formatter as FormatterContract; use Symfony\Component\Console\Style\SymfonyStyle; +use function array_map; +use function count; +use function sprintf; final class TextFormatter implements FormatterContract { @@ -23,12 +26,12 @@ final class TextFormatter implements FormatterContract */ public function displayResults(SymfonyStyle $output, array $vulnerabilities): void { - if (\count($vulnerabilities) !== 0) { + if (count($vulnerabilities) !== 0) { foreach ($vulnerabilities as $dependency => $issues) { - $output->section(\sprintf('%s (%s)', $dependency, $issues['version'])); + $output->section(sprintf('%s (%s)', $dependency, $issues['version'])); - $details = \array_map(static function (array $value) { - return \sprintf('%s: %s' . "\n" . ' %s', $value['cve'] ?: '(no CVE ID)', $value['title'], $value['link']); + $details = array_map(static function (array $value) { + return sprintf('%s: %s' . "\n" . ' %s', $value['cve'] ?: '(no CVE ID)', $value['title'], $value['link']); }, $issues['advisories']); $output->listing($details); diff --git a/src/Security/Common/AbstractContainer.php b/src/Security/Common/AbstractContainer.php new file mode 100644 index 00000000..32dd13b2 --- /dev/null +++ b/src/Security/Common/AbstractContainer.php @@ -0,0 +1,93 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Narrowspark\Automatic\Security\Common; + +use Narrowspark\Automatic\Security\Common\Contract\Container as ContainerContract; +use Narrowspark\Automatic\Security\Common\Contract\Exception\InvalidArgumentException; +use function array_key_exists; +use function sprintf; + +/** + * This file is automatically generated, dont change this file, otherwise the changes are lost after the next mirror update. + * + * @codeCoverageIgnore + * + * @internal + */ +abstract class AbstractContainer implements ContainerContract +{ + /** + * The array of closures defining each entry of the container. + * + * @var array + */ + protected $data = []; + + /** + * The array of entries once they have been instantiated. + * + * @var array + */ + protected $objects = []; + + /** + * Instantiate the container. + * + * @param array $data + */ + public function __construct(array $data) + { + $this->data = $data; + } + + /** + * {@inheritdoc} + */ + public function set(string $id, callable $callback): void + { + $this->data[$id] = $callback; + } + + /** + * {@inheritdoc} + */ + public function has(string $id): bool + { + return array_key_exists($id, $this->data); + } + + /** + * {@inheritdoc} + */ + public function get(string $id) + { + if (array_key_exists($id, $this->objects)) { + return $this->objects[$id]; + } + + if (! array_key_exists($id, $this->data)) { + throw new InvalidArgumentException(sprintf('Identifier [%s] is not defined.', $id)); + } + + return $this->objects[$id] = $this->data[$id]($this); + } + + /** + * {@inheritdoc} + */ + public function getAll(): array + { + return $this->data; + } +} diff --git a/src/Security/Common/Contract/Container.php b/src/Security/Common/Contract/Container.php new file mode 100644 index 00000000..a4c6dfea --- /dev/null +++ b/src/Security/Common/Contract/Container.php @@ -0,0 +1,65 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Narrowspark\Automatic\Security\Common\Contract; + +/** + * This file is automatically generated, dont change this file, otherwise the changes are lost after the next mirror update. + * + * @codeCoverageIgnore + * + * @internal + */ +interface Container +{ + /** + * Finds an entry of the container by its identifier and returns it. + * + * @param string $id identifier of the entry to look for + * + * @throws \Narrowspark\Automatic\Security\Common\Contract\Exception\InvalidArgumentException if no entry is found + * + * @return mixed + */ + public function get(string $id); + + /** + * Set a new entry to the container. + * + * @param string $id + * @param callable $callback + * + * @return void + */ + public function set(string $id, callable $callback): void; + + /** + * Returns true if the container can return an entry for the given identifier. + * Returns false otherwise. + * + * `has($id)` returning true does not mean that `get($id)` will not throw an exception. + * It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`. + * + * @param string $id identifier of the entry to look for + * + * @return bool + */ + public function has(string $id): bool; + + /** + * Returns all container entries. + * + * @return array + */ + public function getAll(): array; +} diff --git a/src/Security/Common/Contract/Exception/Exception.php b/src/Security/Common/Contract/Exception/Exception.php new file mode 100644 index 00000000..01f08bee --- /dev/null +++ b/src/Security/Common/Contract/Exception/Exception.php @@ -0,0 +1,27 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Narrowspark\Automatic\Security\Common\Contract\Exception; + +use Throwable; + +/** + * This file is automatically generated, dont change this file, otherwise the changes are lost after the next mirror update. + * + * @codeCoverageIgnore + * + * @internal + */ +interface Exception extends Throwable +{ +} diff --git a/src/Security/Common/Contract/Exception/InvalidArgumentException.php b/src/Security/Common/Contract/Exception/InvalidArgumentException.php new file mode 100644 index 00000000..fa34fa0e --- /dev/null +++ b/src/Security/Common/Contract/Exception/InvalidArgumentException.php @@ -0,0 +1,20 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Narrowspark\Automatic\Security\Common\Contract\Exception; + +use InvalidArgumentException as BaseInvalidArgumentException; + +final class InvalidArgumentException extends BaseInvalidArgumentException implements Exception +{ +} diff --git a/src/Security/Common/Contract/Exception/RuntimeException.php b/src/Security/Common/Contract/Exception/RuntimeException.php new file mode 100644 index 00000000..896637ad --- /dev/null +++ b/src/Security/Common/Contract/Exception/RuntimeException.php @@ -0,0 +1,20 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Narrowspark\Automatic\Security\Common\Contract\Exception; + +use RuntimeException as BaseRuntimeException; + +final class RuntimeException extends BaseRuntimeException implements Exception +{ +} diff --git a/src/Security/Common/Contract/Resettable.php b/src/Security/Common/Contract/Resettable.php new file mode 100644 index 00000000..a520d347 --- /dev/null +++ b/src/Security/Common/Contract/Resettable.php @@ -0,0 +1,36 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Narrowspark\Automatic\Security\Common\Contract; + +/** + * This file is automatically generated, dont change this file, otherwise the changes are lost after the next mirror update. + * + * @codeCoverageIgnore + * + * @internal + */ +interface Resettable +{ + /** + * Provides a way to reset an object to its initial state. + * + * When calling the "reset()" method on an object, it should be put back to its + * initial state. This usually means clearing any internal buffers and forwarding + * the call to internal dependencies. All properties of the object should be put + * back to the same state it had when it was first ready to use. + * + * @return void + */ + public function reset(): void; +} diff --git a/src/Security/Common/Traits/GetGenericPropertyReaderTrait.php b/src/Security/Common/Traits/GetGenericPropertyReaderTrait.php new file mode 100644 index 00000000..db675daa --- /dev/null +++ b/src/Security/Common/Traits/GetGenericPropertyReaderTrait.php @@ -0,0 +1,37 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Narrowspark\Automatic\Security\Common\Traits; + +use Closure; + +trait GetGenericPropertyReaderTrait +{ + /** + * Returns a callback that can read private variables from object. + * + * @return Closure + */ + protected function getGenericPropertyReader(): Closure + { + $reader = function &(object $object, string $property) { + $value = &Closure::bind(function &() use ($property) { + return $this->{$property}; + }, $object, $object)->__invoke(); + + return $value; + }; + + return $reader; + } +} diff --git a/src/Security/Common/Util.php b/src/Security/Common/Util.php new file mode 100644 index 00000000..187aa6af --- /dev/null +++ b/src/Security/Common/Util.php @@ -0,0 +1,85 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Narrowspark\Automatic\Security\Common; + +use Composer\Composer; +use Composer\Factory; +use Composer\Json\JsonFile; +use Composer\Json\JsonManipulator; +use InvalidArgumentException; +use Narrowspark\Automatic\Security\Common\Contract\Exception\RuntimeException; +use function file_get_contents; +use function preg_match; +use function substr; + +final class Util +{ + /** + * Private constructor; non-instantiable. + * + * @codeCoverageIgnore + */ + private function __construct() + { + } + + /** + * Return the composer json file and json manipulator. + * + * @throws InvalidArgumentException + * + * @return array + */ + public static function getComposerJsonFileAndManipulator(): array + { + $json = new JsonFile(Factory::getComposerFile()); + $manipulator = new JsonManipulator(file_get_contents($json->getPath())); + + return [$json, $manipulator]; + } + + /** + * Get the composer.lock file path. + * + * @return string + */ + public static function getComposerLockFile(): string + { + return substr(Factory::getComposerFile(), 0, -4) . 'lock'; + } + + /** + * Get the composer version. + * + * @throws \Narrowspark\Automatic\Security\Common\Contract\Exception\RuntimeException + * + * @return string + */ + public static function getComposerVersion(): string + { + preg_match('/\d+.\d+.\d+/m', Composer::VERSION, $matches); + + if ($matches !== null) { + return $matches[0]; + } + + preg_match('/\d+.\d+.\d+/m', Composer::BRANCH_ALIAS_VERSION, $matches); + + if ($matches !== null) { + return $matches[0]; + } + + throw new RuntimeException('No composer version found.'); + } +} diff --git a/src/Security/Container.php b/src/Security/Container.php new file mode 100644 index 00000000..3c875eb8 --- /dev/null +++ b/src/Security/Container.php @@ -0,0 +1,84 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace Narrowspark\Automatic\Security; + +use Composer\Composer; +use Composer\Config; +use Composer\Factory; +use Composer\IO\IOInterface; +use Composer\Util\RemoteFilesystem; +use Narrowspark\Automatic\Common\AbstractContainer; +use Narrowspark\Automatic\Common\Contract\Container as ContainerContract; +use Narrowspark\Automatic\Common\Traits\GetGenericPropertyReaderTrait; +use Narrowspark\Automatic\Security\Contract\Downloader as DownloaderContract; +use Narrowspark\Automatic\Security\Downloader\ComposerDownloader; +use Narrowspark\Automatic\Security\Downloader\CurlDownloader; +use Symfony\Component\Console\Input\InputInterface; +use function extension_loaded; + +/** + * @internal + */ +final class Container extends AbstractContainer +{ + use GetGenericPropertyReaderTrait; + + /** + * Instantiate the container. + * + * @param \Composer\Composer $composer + * @param \Composer\IO\IOInterface $io + */ + public function __construct(Composer $composer, IOInterface $io) + { + $genericPropertyReader = $this->getGenericPropertyReader(); + + parent::__construct([ + Composer::class => static function () use ($composer) { + return $composer; + }, + Config::class => static function (ContainerContract $container) { + return $container->get(Composer::class)->getConfig(); + }, + IOInterface::class => static function () use ($io) { + return $io; + }, + InputInterface::class => static function (ContainerContract $container) use ($genericPropertyReader) { + return $genericPropertyReader($container->get(IOInterface::class), 'input'); + }, + RemoteFilesystem::class => static function (ContainerContract $container) { + return Factory::createRemoteFilesystem( + $container->get(IOInterface::class), + $container->get(Config::class) + ); + }, + 'composer-extra' => static function (ContainerContract $container) { + return $container->get(Composer::class)->getPackage()->getExtra(); + }, + DownloaderContract::class => static function () { + if (extension_loaded('curl')) { + return new CurlDownloader(); + } + + return new ComposerDownloader(); + }, + 'security_advisories' => static function (ContainerContract $container) { + /** @var Audit $audit */ + $audit = $container->get(Audit::class); + + return $audit->getSecurityAdvisories($container->get(IOInterface::class)); + }, + ]); + } +} diff --git a/src/Security/Contract/Exception/Exception.php b/src/Security/Contract/Exception/Exception.php index eb100731..4323fad6 100644 --- a/src/Security/Contract/Exception/Exception.php +++ b/src/Security/Contract/Exception/Exception.php @@ -13,6 +13,8 @@ namespace Narrowspark\Automatic\Security\Contract\Exception; -interface Exception extends \Throwable +use Throwable; + +interface Exception extends Throwable { } diff --git a/src/Security/Downloader/AbstractDownloader.php b/src/Security/Downloader/AbstractDownloader.php index fb3215df..76105cee 100644 --- a/src/Security/Downloader/AbstractDownloader.php +++ b/src/Security/Downloader/AbstractDownloader.php @@ -16,6 +16,13 @@ use Narrowspark\Automatic\Security\Contract\Downloader as DownloaderContract; use Narrowspark\Automatic\Security\Contract\Exception\RuntimeException; use Narrowspark\Automatic\Security\Plugin; +use const PHP_MAJOR_VERSION; +use const PHP_MINOR_VERSION; +use const PHP_RELEASE_VERSION; +use function function_exists; +use function getenv; +use function php_uname; +use function sprintf; abstract class AbstractDownloader implements DownloaderContract { @@ -39,13 +46,13 @@ public function setTimeout(int $timeout): void */ protected function getUserAgent(): string { - return \sprintf( + return sprintf( 'Narrowspark-Security-Audit/%s (%s; %s; %s%s)', Plugin::VERSION, - \function_exists('php_uname') ? \php_uname('s') : 'Unknown', - \function_exists('php_uname') ? \php_uname('r') : 'Unknown', - 'PHP ' . \PHP_MAJOR_VERSION . '.' . \PHP_MINOR_VERSION . '.' . \PHP_RELEASE_VERSION, - \getenv('CI') !== false ? '; CI' : '' + function_exists('php_uname') ? php_uname('s') : 'Unknown', + function_exists('php_uname') ? php_uname('r') : 'Unknown', + 'PHP ' . PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION, + getenv('CI') !== false ? '; CI' : '' ); } @@ -66,7 +73,7 @@ protected function checkStatus(int $statusCode, string $body): void } if ($statusCode !== 200) { - throw new RuntimeException(\sprintf('The web service failed for an unknown reason (HTTP %s).', $statusCode), $statusCode); + throw new RuntimeException(sprintf('The web service failed for an unknown reason (HTTP %s).', $statusCode), $statusCode); } } } diff --git a/src/Security/Downloader/ComposerDownloader.php b/src/Security/Downloader/ComposerDownloader.php index 12590a66..ad6fb389 100644 --- a/src/Security/Downloader/ComposerDownloader.php +++ b/src/Security/Downloader/ComposerDownloader.php @@ -17,6 +17,14 @@ use Composer\Util\StreamContextFactory; use Narrowspark\Automatic\Security\Contract\Exception\RuntimeException; use Symfony\Component\Filesystem\Filesystem; +use function error_get_last; +use function error_reporting; +use function file_get_contents; +use function is_dir; +use function is_link; +use function preg_match; +use function sprintf; +use function trim; final class ComposerDownloader extends AbstractDownloader { @@ -43,31 +51,31 @@ public function download(string $url): string $caPathOrFile = CaBundle::getSystemCaRootBundlePath(); $filesystem = new Filesystem(); - if (\is_dir($caPathOrFile) || (\is_link($caPathOrFile) && \is_dir((string) $filesystem->readlink($caPathOrFile)))) { + if (is_dir($caPathOrFile) || (is_link($caPathOrFile) && is_dir((string) $filesystem->readlink($caPathOrFile)))) { $opts['ssl']['capath'] = $caPathOrFile; } else { $opts['ssl']['cafile'] = $caPathOrFile; } $context = StreamContextFactory::getContext($url, $opts); - $level = \error_reporting(0); - $body = \file_get_contents($url, false, $context); + $level = error_reporting(0); + $body = file_get_contents($url, false, $context); - \error_reporting($level); + error_reporting($level); if ($body === false) { - $error = \error_get_last(); + $error = error_get_last(); - throw new RuntimeException(\sprintf('An error occurred: %s.', $error['message'])); + throw new RuntimeException(sprintf('An error occurred: %s.', $error['message'])); } // status code - if ((bool) \preg_match('{HTTP/\d\.\d (\d+) }i', $http_response_header[0], $match) === false) { + if ((bool) preg_match('{HTTP/\d\.\d (\d+) }i', $http_response_header[0], $match) === false) { throw new RuntimeException('An unknown error occurred.'); } $this->checkStatus((int) $match[1], $body); - return \trim($body); + return trim($body); } } diff --git a/src/Security/Downloader/CurlDownloader.php b/src/Security/Downloader/CurlDownloader.php index 187901a8..aaae08bc 100644 --- a/src/Security/Downloader/CurlDownloader.php +++ b/src/Security/Downloader/CurlDownloader.php @@ -16,6 +16,35 @@ use Composer\CaBundle\CaBundle; use Narrowspark\Automatic\Security\Contract\Exception\RuntimeException; use Symfony\Component\Filesystem\Filesystem; +use const CURLINFO_HEADER_SIZE; +use const CURLINFO_HTTP_CODE; +use const CURLOPT_CAINFO; +use const CURLOPT_CAPATH; +use const CURLOPT_CONNECTTIMEOUT; +use const CURLOPT_FAILONERROR; +use const CURLOPT_FOLLOWLOCATION; +use const CURLOPT_HEADER; +use const CURLOPT_HTTPHEADER; +use const CURLOPT_MAXREDIRS; +use const CURLOPT_RETURNTRANSFER; +use const CURLOPT_SSL_VERIFYHOST; +use const CURLOPT_SSL_VERIFYPEER; +use const CURLOPT_TIMEOUT; +use const CURLOPT_URL; +use const CURLOPT_USERAGENT; +use function curl_close; +use function curl_error; +use function curl_exec; +use function curl_getinfo; +use function curl_init; +use function curl_setopt; +use function ini_get; +use function is_dir; +use function is_link; +use function is_string; +use function sprintf; +use function substr; +use function trim; final class CurlDownloader extends AbstractDownloader { @@ -24,47 +53,47 @@ final class CurlDownloader extends AbstractDownloader */ public function download(string $url): string { - $curl = \curl_init(); - - \curl_setopt($curl, \CURLOPT_RETURNTRANSFER, true); - \curl_setopt($curl, \CURLOPT_HEADER, true); - \curl_setopt($curl, \CURLOPT_URL, $url); - \curl_setopt($curl, \CURLOPT_HTTPHEADER, ['Accept: application/text']); - \curl_setopt($curl, \CURLOPT_CONNECTTIMEOUT, $this->timeout); - \curl_setopt($curl, \CURLOPT_TIMEOUT, 10); - \curl_setopt($curl, \CURLOPT_FOLLOWLOCATION, \is_string(\ini_get('open_basedir')) ? 0 : 1); - \curl_setopt($curl, \CURLOPT_MAXREDIRS, 3); - \curl_setopt($curl, \CURLOPT_FAILONERROR, false); - \curl_setopt($curl, \CURLOPT_SSL_VERIFYPEER, 1); - \curl_setopt($curl, \CURLOPT_SSL_VERIFYHOST, 2); - \curl_setopt($curl, \CURLOPT_USERAGENT, $this->getUserAgent()); + $curl = curl_init(); + + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + curl_setopt($curl, CURLOPT_HEADER, true); + curl_setopt($curl, CURLOPT_URL, $url); + curl_setopt($curl, CURLOPT_HTTPHEADER, ['Accept: application/text']); + curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, $this->timeout); + curl_setopt($curl, CURLOPT_TIMEOUT, 10); + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, is_string(ini_get('open_basedir')) ? 0 : 1); + curl_setopt($curl, CURLOPT_MAXREDIRS, 3); + curl_setopt($curl, CURLOPT_FAILONERROR, false); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 1); + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2); + curl_setopt($curl, CURLOPT_USERAGENT, $this->getUserAgent()); $caPathOrFile = CaBundle::getSystemCaRootBundlePath(); $filesystem = new Filesystem(); - if (\is_dir($caPathOrFile) || (\is_link($caPathOrFile) && \is_dir((string) $filesystem->readlink($caPathOrFile)))) { - \curl_setopt($curl, \CURLOPT_CAPATH, $caPathOrFile); + if (is_dir($caPathOrFile) || (is_link($caPathOrFile) && is_dir((string) $filesystem->readlink($caPathOrFile)))) { + curl_setopt($curl, CURLOPT_CAPATH, $caPathOrFile); } else { - \curl_setopt($curl, \CURLOPT_CAINFO, $caPathOrFile); + curl_setopt($curl, CURLOPT_CAINFO, $caPathOrFile); } - $response = \curl_exec($curl); + $response = curl_exec($curl); if ($response === false) { - $error = \curl_error($curl); + $error = curl_error($curl); - \curl_close($curl); + curl_close($curl); - throw new RuntimeException(\sprintf('An error occurred: %s.', $error)); + throw new RuntimeException(sprintf('An error occurred: %s.', $error)); } - $body = \substr((string) $response, \curl_getinfo($curl, \CURLINFO_HEADER_SIZE)); - $statusCode = (int) \curl_getinfo($curl, \CURLINFO_HTTP_CODE); + $body = substr((string) $response, curl_getinfo($curl, CURLINFO_HEADER_SIZE)); + $statusCode = (int) curl_getinfo($curl, CURLINFO_HTTP_CODE); - \curl_close($curl); + curl_close($curl); $this->checkStatus($statusCode, $body); - return \trim($body); + return trim($body); } } diff --git a/src/Security/Plugin.php b/src/Security/Plugin.php index 6c6cba30..b3ea4748 100644 --- a/src/Security/Plugin.php +++ b/src/Security/Plugin.php @@ -14,6 +14,7 @@ namespace Narrowspark\Automatic\Security; use Composer\Composer; +use Composer\Config; use Composer\DependencyResolver\Operation\UninstallOperation; use Composer\DependencyResolver\Operation\UpdateOperation; use Composer\EventDispatcher\EventSubscriberInterface; @@ -26,14 +27,30 @@ use Composer\Script\Event; use Composer\Script\ScriptEvents as ComposerScriptEvents; use FilesystemIterator; -use Narrowspark\Automatic\Security\Contract\Downloader; +use Narrowspark\Automatic\Common\AbstractContainer; +use Narrowspark\Automatic\Common\Contract\Container as ContainerContract; +use Narrowspark\Automatic\Common\Util; +use Narrowspark\Automatic\Security\Contract\Downloader as DownloaderContract; use Narrowspark\Automatic\Security\Contract\Exception\RuntimeException; -use Narrowspark\Automatic\Security\Downloader\ComposerDownloader; -use Narrowspark\Automatic\Security\Downloader\CurlDownloader; use RecursiveDirectoryIterator; use RecursiveIteratorIterator; - -final class Plugin implements Capable, EventSubscriberInterface, PluginInterface +use SplFileInfo; +use Symfony\Component\Console\Input\InputInterface; +use const DIRECTORY_SEPARATOR; +use const PHP_INT_MAX; +use function array_filter; +use function array_key_exists; +use function class_exists; +use function count; +use function preg_match; +use function rtrim; +use function sprintf; +use function str_replace; +use function strlen; +use function substr; +use function version_compare; + +class Plugin implements Capable, EventSubscriberInterface, PluginInterface { /** @var string */ public const VERSION = '0.12.0'; @@ -44,13 +61,6 @@ final class Plugin implements Capable, EventSubscriberInterface, PluginInterface /** @var string */ public const PACKAGE_NAME = 'narrowspark/automatic-security-audit'; - /** - * The SecurityAdvisories database. - * - * @var array - */ - private $securityAdvisories = []; - /** * Found package vulnerabilities. * @@ -59,39 +69,42 @@ final class Plugin implements Capable, EventSubscriberInterface, PluginInterface private $foundVulnerabilities = []; /** - * The composer instance. + * Check if the the plugin is activated. * - * @var \Composer\Composer + * @var bool */ - private $composer; + private static $activated = true; /** - * The composer io implementation. + * Sha of the security security-advisories.json. * - * @var \Composer\IO\IOInterface + * @var string */ - private $io; + private $securitySha; /** - * A Audit instance. + * A Container instance. * - * @var \Narrowspark\Automatic\Security\Audit + * @var \Narrowspark\Automatic\Common\Contract\Container */ - private $audit; + protected $container; /** - * Check if the the plugin is activated. + * Check if the package should run in uninstall mode. * * @var bool */ - private static $activated = true; + private $uninstallMode = false; /** - * Sha of the security security-advisories.json. + * Get the Container instance. * - * @var string + * @return \Narrowspark\Automatic\Common\Contract\Container */ - private $securitySha; + public function getContainer(): ContainerContract + { + return $this->container; + } /** * {@inheritdoc} @@ -103,10 +116,10 @@ public static function getSubscribedEvents(): array } return [ - PackageEvents::POST_PACKAGE_INSTALL => [['auditPackage', ~\PHP_INT_MAX]], - PackageEvents::POST_PACKAGE_UPDATE => [['auditPackage', ~\PHP_INT_MAX]], - ComposerScriptEvents::POST_INSTALL_CMD => [['auditComposerLock', \PHP_INT_MAX]], - ComposerScriptEvents::POST_UPDATE_CMD => [['auditComposerLock', \PHP_INT_MAX], ['onPostUpdatePostMessages', ~\PHP_INT_MAX]], + PackageEvents::POST_PACKAGE_INSTALL => [['auditPackage', ~PHP_INT_MAX]], + PackageEvents::POST_PACKAGE_UPDATE => [['auditPackage', ~PHP_INT_MAX]], + ComposerScriptEvents::POST_INSTALL_CMD => [['auditComposerLock', PHP_INT_MAX]], + ComposerScriptEvents::POST_UPDATE_CMD => [['auditComposerLock', PHP_INT_MAX], ['onPostUpdatePostMessages', ~PHP_INT_MAX]], ]; } @@ -115,15 +128,25 @@ public static function getSubscribedEvents(): array */ public function activate(Composer $composer, IOInterface $io): void { - if (\extension_loaded('curl')) { - $downloader = new CurlDownloader(); - } else { - $downloader = new ComposerDownloader(); + // to avoid issues when Automatic is upgraded, we load all PHP classes now + // that way, we are sure to use all files from the same version. + foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator(__DIR__, FilesystemIterator::SKIP_DOTS)) as $file) { + /** @var SplFileInfo $file */ + if (substr($file->getFilename(), -4) === '.php') { + class_exists(__NAMESPACE__ . str_replace('/', '\\', substr($file->getFilename(), strlen(__DIR__), -4))); + } } - $extra = $composer->getPackage()->getExtra(); + if (! class_exists(AbstractContainer::class)) { + require __DIR__ . DIRECTORY_SEPARATOR . 'alias.php'; + } - if (isset($extra[self::COMPOSER_EXTRA_KEY]['timeout'])) { + $this->container = new Container($composer, $io); + + $extra = $this->container->get('composer-extra'); + $downloader = $this->container->get(DownloaderContract::class); + + if (array_key_exists(self::COMPOSER_EXTRA_KEY, $extra) && array_key_exists('timeout', $extra[self::COMPOSER_EXTRA_KEY])) { $downloader->setTimeout($extra[self::COMPOSER_EXTRA_KEY]['timeout']); } @@ -132,26 +155,24 @@ public function activate(Composer $composer, IOInterface $io): void $io->writeError('Narrowspark Automatic Security Audit has been disabled. ' . $errorMessage . ''); - $downloader = $extra = null; + $extra = null; return; } - // to avoid issues when Automatic is upgraded, we load all PHP classes now - // that way, we are sure to use all files from the same version. - foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator(__DIR__, FilesystemIterator::SKIP_DOTS)) as $file) { - /** @var \SplFileInfo $file */ - if (\substr($file->getFilename(), -4) === '.php') { - \class_exists(__NAMESPACE__ . \str_replace('/', '\\', \substr($file->getFilename(), \strlen(__DIR__), -4))); - } - } + $this->container->set(Audit::class, function (ContainerContract $container) { + $audit = new Audit(rtrim($container->get(Config::class)->get('vendor-dir'), '/'), $container->get(DownloaderContract::class), $this->securitySha); - $this->composer = $composer; - $this->io = $io; + $name = 'no-dev'; + $input = $container->get(InputInterface::class); - $this->audit = new Audit(\rtrim($composer->getConfig()->get('vendor-dir'), '/'), $downloader, $this->securitySha); + $audit->setDevMode($input->hasOption($name) ? ! (bool) $input->getOption($name) : true); - $this->securityAdvisories = $this->audit->getSecurityAdvisories($io); + return $audit; + }); + + // Downloading needed security advisories database. + $this->container->get('security_advisories'); } /** @@ -173,12 +194,17 @@ public function getCapabilities(): array */ public function onPostUpdatePostMessages(Event $event): void { - $count = \count(\array_filter($this->foundVulnerabilities)); + if ($this->uninstallMode) { + return; + } + + $count = count(array_filter($this->foundVulnerabilities)); + $io = $this->container->get(IOInterface::class); if ($count !== 0) { - $this->io->write('[!] Audit Security Report: ' . \sprintf('%s vulnerabilit%s found - run "composer audit" for more information', $count, $count === 1 ? 'y' : 'ies')); + $io->write('[!] Audit Security Report: ' . sprintf('%s vulnerabilit%s found - run "composer audit" for more information', $count, $count === 1 ? 'y' : 'ies')); } else { - $this->io->write('[+] Audit Security Report: No known vulnerabilities found'); + $io->write('[+] Audit Security Report: No known vulnerabilities found'); } } @@ -194,6 +220,10 @@ public function auditPackage(PackageEvent $event): void $operation = $event->getOperation(); if ($operation instanceof UninstallOperation) { + if ($operation->getPackage()->getPrettyName() === self::PACKAGE_NAME) { + $this->uninstallMode = true; + } + return; } @@ -203,13 +233,13 @@ public function auditPackage(PackageEvent $event): void $composerPackage = $operation->getPackage(); } - $data = $this->audit->checkPackage( + $data = $this->container->get(Audit::class)->checkPackage( $composerPackage->getName(), $composerPackage->getVersion(), - $this->securityAdvisories + $this->container->get('security_advisories') ); - if (\count($data) === 0) { + if (count($data) === 0) { return; } @@ -225,13 +255,13 @@ public function auditPackage(PackageEvent $event): void */ public function auditComposerLock(Event $event): void { - if (\count($this->foundVulnerabilities) !== 0) { + if ($this->uninstallMode || count($this->foundVulnerabilities) !== 0) { return; } - $data = $this->audit->checkLock(Util::getComposerLockFile()); + $data = $this->container->get(Audit::class)->checkLock(Util::getComposerLockFile()); - if (\count($data) === 0) { + if (count($data) === 0) { return; } @@ -241,16 +271,16 @@ public function auditComposerLock(Event $event): void /** * Check if automatic can be activated. * - * @param \Composer\IO\IOInterface $io - * @param Downloader $downloader + * @param \Composer\IO\IOInterface $io + * @param \Narrowspark\Automatic\Security\Contract\Downloader $downloader * * @return null|string */ - private function getErrorMessage(IOInterface $io, Downloader $downloader): ?string + private function getErrorMessage(IOInterface $io, DownloaderContract $downloader): ?string { // @codeCoverageIgnoreStart - if (\version_compare(self::getComposerVersion(), '1.7.0', '<')) { - return \sprintf('Your version "%s" of Composer is too old; Please upgrade', Composer::VERSION); + if (version_compare(self::getComposerVersion(), '1.7.0', '<')) { + return sprintf('Your version "%s" of Composer is too old; Please upgrade', Composer::VERSION); } // @codeCoverageIgnoreEnd @@ -274,13 +304,13 @@ private function getErrorMessage(IOInterface $io, Downloader $downloader): ?stri */ private static function getComposerVersion(): string { - \preg_match('/\d+.\d+.\d+/m', Composer::VERSION, $matches); + preg_match('/\d+.\d+.\d+/m', Composer::VERSION, $matches); if ($matches !== null) { return $matches[0]; } - \preg_match('/\d+.\d+.\d+/m', Composer::BRANCH_ALIAS_VERSION, $matches); + preg_match('/\d+.\d+.\d+/m', Composer::BRANCH_ALIAS_VERSION, $matches); if ($matches !== null) { return $matches[0]; diff --git a/src/Security/Util.php b/src/Security/Util.php deleted file mode 100644 index 52cec267..00000000 --- a/src/Security/Util.php +++ /dev/null @@ -1,38 +0,0 @@ - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Narrowspark\Automatic\Security; - -use Composer\Factory; - -final class Util -{ - /** - * Private constructor; non-instantiable. - * - * @codeCoverageIgnore - */ - private function __construct() - { - } - - /** - * Get the composer.lock file path. - * - * @return string - */ - public static function getComposerLockFile(): string - { - return \substr(Factory::getComposerFile(), 0, -4) . 'lock'; - } -} diff --git a/src/Security/alias.php b/src/Security/alias.php new file mode 100644 index 00000000..81c47227 --- /dev/null +++ b/src/Security/alias.php @@ -0,0 +1,23 @@ + + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +use function class_alias; + +class_alias(Narrowspark\Automatic\Security\Common\Contract\Exception\Exception::class, Narrowspark\Automatic\Common\Contract\Exception\Exception::class); +class_alias(Narrowspark\Automatic\Security\Common\Contract\Exception\InvalidArgumentException::class, Narrowspark\Automatic\Common\Contract\Exception\InvalidArgumentException::class); +class_alias(Narrowspark\Automatic\Security\Common\Contract\Container::class, Narrowspark\Automatic\Common\Contract\Container::class); +class_alias(Narrowspark\Automatic\Security\Common\AbstractContainer::class, Narrowspark\Automatic\Common\AbstractContainer::class); +class_alias(Narrowspark\Automatic\Security\Common\Contract\Resettable::class, Narrowspark\Automatic\Common\Contract\Resettable::class); +class_alias(Narrowspark\Automatic\Security\Common\Traits\GetGenericPropertyReaderTrait::class, Narrowspark\Automatic\Common\Traits\GetGenericPropertyReaderTrait::class); +class_alias(Narrowspark\Automatic\Security\Common\Contract\Exception\RuntimeException::class, Narrowspark\Automatic\Common\Contract\Exception\RuntimeException::class); +class_alias(Narrowspark\Automatic\Security\Common\Util::class, Narrowspark\Automatic\Common\Util::class); diff --git a/tests/Automatic/AbstractConfiguratorTest.php b/tests/Automatic/AbstractConfiguratorTest.php index fad2ce89..c769b62a 100644 --- a/tests/Automatic/AbstractConfiguratorTest.php +++ b/tests/Automatic/AbstractConfiguratorTest.php @@ -18,6 +18,7 @@ use Narrowspark\Automatic\Common\Contract\Exception\InvalidArgumentException; use Narrowspark\Automatic\Test\Fixture\MockConfigurator; use Narrowspark\TestingHelper\Phpunit\MockeryTestCase; +use stdClass; /** * @internal @@ -70,7 +71,7 @@ public function testAddWithoutConfiguratorContractClass(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('The class [stdClass] must implement the interface [\\Narrowspark\\Automatic\\Common\\Contract\\Configurator].'); - $this->configurator->add('test', \stdClass::class); + $this->configurator->add('test', stdClass::class); } public function testClear(): void diff --git a/tests/Automatic/AutomaticTest.php b/tests/Automatic/AutomaticTest.php index a3b1991b..9ba28fe3 100644 --- a/tests/Automatic/AutomaticTest.php +++ b/tests/Automatic/AutomaticTest.php @@ -31,6 +31,7 @@ use Composer\Script\ScriptEvents as ComposerScriptEvents; use Composer\Util\ProcessExecutor; use Composer\Util\RemoteFilesystem; +use Mockery; use Narrowspark\Automatic\Automatic; use Narrowspark\Automatic\Common\Contract\Container as ContainerContract; use Narrowspark\Automatic\Contract\Configurator as ConfiguratorContract; @@ -47,6 +48,21 @@ use Nyholm\NSA; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Filesystem\Filesystem; +use const DIRECTORY_SEPARATOR; +use function array_map; +use function dirname; +use function file_get_contents; +use function file_put_contents; +use function glob; +use function is_dir; +use function json_decode; +use function json_encode; +use function mb_substr; +use function method_exists; +use function mkdir; +use function putenv; +use function rmdir; +use function unlink; /** * @internal @@ -69,8 +85,8 @@ protected function setUp(): void $this->composerCachePath = __DIR__ . '/AutomaticTest'; - @\mkdir($this->composerCachePath); - \putenv('COMPOSER_CACHE_DIR=' . $this->composerCachePath); + @mkdir($this->composerCachePath); + putenv('COMPOSER_CACHE_DIR=' . $this->composerCachePath); $this->arrangeComposerClasses(); @@ -91,17 +107,17 @@ protected function tearDown(): void FunctionMock::$isOpensslActive = true; - \putenv('COMPOSER_CACHE_DIR='); - \putenv('COMPOSER_CACHE_DIR'); + putenv('COMPOSER_CACHE_DIR='); + putenv('COMPOSER_CACHE_DIR'); - $narrowsparkPath = __DIR__ . \DIRECTORY_SEPARATOR . 'narrowspark'; + $narrowsparkPath = __DIR__ . DIRECTORY_SEPARATOR . 'narrowspark'; $this->delete($this->composerCachePath); $this->delete($narrowsparkPath); - @\unlink($this->composerCachePath . \DIRECTORY_SEPARATOR . '.htaccess'); - @\rmdir($this->composerCachePath); - @\rmdir($narrowsparkPath); + @unlink($this->composerCachePath . DIRECTORY_SEPARATOR . '.htaccess'); + @rmdir($this->composerCachePath); + @rmdir($narrowsparkPath); } public function testGetSubscribedEvents(): void @@ -140,10 +156,10 @@ public function testActivate(): void $installationManager = $this->mock(InstallationManager::class); $installationManager->shouldReceive('addInstaller') ->once() - ->with(\Mockery::type(ConfiguratorInstaller::class)); + ->with(Mockery::type(ConfiguratorInstaller::class)); $installationManager->shouldReceive('addInstaller') ->once() - ->with(\Mockery::type(SkeletonInstaller::class)); + ->with(Mockery::type(SkeletonInstaller::class)); $this->composerMock->shouldReceive('getInstallationManager') ->once() @@ -158,7 +174,7 @@ public function testActivate(): void ->times(2) ->andReturn($downloadManagerMock); - if (! \method_exists(RemoteFilesystem::class, 'getRemoteContents')) { + if (! method_exists(RemoteFilesystem::class, 'getRemoteContents')) { $this->ioMock->shouldReceive('writeError') ->once() ->with('Composer >=1.7 not found, downloads will happen in sequence', true, IOInterface::DEBUG); @@ -236,7 +252,7 @@ public function testRecordWithUpdateRecord(): void public function testRecordWithInstallRecord(): void { - \putenv('COMPOSER_VENDOR_DIR=' . __DIR__); + putenv('COMPOSER_VENDOR_DIR=' . __DIR__); $automatic = new Automatic(); @@ -294,13 +310,13 @@ public function isInteractive(): bool $automatic->record($packageEventMock); - \putenv('COMPOSER_VENDOR_DIR='); - \putenv('COMPOSER_VENDOR_DIR'); + putenv('COMPOSER_VENDOR_DIR='); + putenv('COMPOSER_VENDOR_DIR'); } public function testRecordWithInstallRecordAndLock(): void { - \putenv('COMPOSER_VENDOR_DIR=' . __DIR__); + putenv('COMPOSER_VENDOR_DIR=' . __DIR__); $packageEventMock = $this->mock(PackageEvent::class); @@ -334,13 +350,13 @@ public function testRecordWithInstallRecordAndLock(): void $this->plugin->setContainer($containerMock); $this->plugin->record($packageEventMock); - \putenv('COMPOSER_VENDOR_DIR='); - \putenv('COMPOSER_VENDOR_DIR'); + putenv('COMPOSER_VENDOR_DIR='); + putenv('COMPOSER_VENDOR_DIR'); } public function testRecordWithInstallRecordAndAutomaticPackage(): void { - \putenv('COMPOSER_VENDOR_DIR=' . __DIR__); + putenv('COMPOSER_VENDOR_DIR=' . __DIR__); $automatic = new Automatic(); @@ -418,13 +434,13 @@ public function isInteractive(): bool $automatic->record($packageEventMock); $automatic->record($automaticPackageEventMock); - \putenv('COMPOSER_VENDOR_DIR='); - \putenv('COMPOSER_VENDOR_DIR'); + putenv('COMPOSER_VENDOR_DIR='); + putenv('COMPOSER_VENDOR_DIR'); } public function testExecuteAutoScripts(): void { - \putenv('COMPOSER=' . __DIR__ . '/Fixture/composer.json'); + putenv('COMPOSER=' . __DIR__ . '/Fixture/composer.json'); $eventMock = $this->mock(Event::class); $eventMock->shouldReceive('stopPropagation') @@ -440,7 +456,7 @@ public function testExecuteAutoScripts(): void $lockMock->shouldReceive('get') ->once() ->with(ScriptExecutor::TYPE) - ->andReturn(['test/test' => [ScriptExtender::class => \dirname(__DIR__, 2) . '/Automatic/ScriptExtender.php']]); + ->andReturn(['test/test' => [ScriptExtender::class => dirname(__DIR__, 2) . '/Automatic/ScriptExtender.php']]); $containerMock = $this->mock(ContainerContract::class); $containerMock->shouldReceive('get') @@ -455,13 +471,13 @@ public function testExecuteAutoScripts(): void $this->plugin->setContainer($containerMock); $this->plugin->executeAutoScripts($eventMock); - \putenv('COMPOSER='); - \putenv('COMPOSER'); + putenv('COMPOSER='); + putenv('COMPOSER'); } public function testExecuteAutoScriptsWithNumericArray(): void { - \putenv('COMPOSER=' . __DIR__ . '/Fixture/composer-with-numeric-scripts.json'); + putenv('COMPOSER=' . __DIR__ . '/Fixture/composer-with-numeric-scripts.json'); $eventMock = $this->mock(Event::class); $eventMock->shouldReceive('stopPropagation') @@ -478,13 +494,13 @@ public function testExecuteAutoScriptsWithNumericArray(): void $this->plugin->setContainer($containerMock); $this->plugin->executeAutoScripts($eventMock); - \putenv('COMPOSER='); - \putenv('COMPOSER'); + putenv('COMPOSER='); + putenv('COMPOSER'); } public function testExecuteAutoScriptsWithoutScripts(): void { - \putenv('COMPOSER=' . __DIR__ . '/Fixture/composer-empty-scripts.json'); + putenv('COMPOSER=' . __DIR__ . '/Fixture/composer-empty-scripts.json'); $eventMock = $this->mock(Event::class); $eventMock->shouldReceive('stopPropagation') @@ -503,8 +519,8 @@ public function testExecuteAutoScriptsWithoutScripts(): void $this->plugin->setContainer($containerMock); $this->plugin->executeAutoScripts($eventMock); - \putenv('COMPOSER='); - \putenv('COMPOSER'); + putenv('COMPOSER='); + putenv('COMPOSER'); } public function testGetAutomaticLockFile(): void @@ -522,8 +538,8 @@ public function testOnPostUninstall(): void ->once() ->andReturn(true); - $filePath = __DIR__ . \DIRECTORY_SEPARATOR . 'composer_uninstall.json'; - $lockfilePath = \mb_substr($filePath, 0, -4) . 'lock'; + $filePath = __DIR__ . DIRECTORY_SEPARATOR . 'composer_uninstall.json'; + $lockfilePath = mb_substr($filePath, 0, -4) . 'lock'; $scripts = [ ComposerScriptEvents::POST_INSTALL_CMD => [ @@ -535,12 +551,12 @@ public function testOnPostUninstall(): void 'test' => 'this should stay', ]; - \file_put_contents($filePath, \json_encode([ + file_put_contents($filePath, json_encode([ 'scripts' => $scripts, ])); - \file_put_contents($lockfilePath, \json_encode([])); + file_put_contents($lockfilePath, json_encode([])); - \putenv('COMPOSER=' . $filePath); + putenv('COMPOSER=' . $filePath); $this->composerMock->shouldReceive('getPackage->getScripts') ->once() @@ -578,17 +594,17 @@ public function testOnPostUninstall(): void $this->plugin->setContainer($containerMock); $this->plugin->onPostUninstall($event); - $jsonData = \json_decode(\file_get_contents($filePath), true); + $jsonData = json_decode(file_get_contents($filePath), true); self::assertArrayHasKey('test', $jsonData['scripts']); self::assertCount(0, $jsonData['scripts'][ComposerScriptEvents::POST_INSTALL_CMD]); self::assertCount(0, $jsonData['scripts'][ComposerScriptEvents::POST_INSTALL_CMD]); - \putenv('COMPOSER='); - \putenv('COMPOSER'); + putenv('COMPOSER='); + putenv('COMPOSER'); - @\unlink($filePath); - @\unlink($lockfilePath); + @unlink($filePath); + @unlink($lockfilePath); } public function testOnPostUninstallWithWithoutDev(): void @@ -625,13 +641,13 @@ public function testOnPostUpdatePostMessages(): void public function testInitAutoScripts(): void { - $composerJsonPath = __DIR__ . \DIRECTORY_SEPARATOR . 'Fixture' . \DIRECTORY_SEPARATOR . 'testInitAutoScripts.json'; - $composerLockPath = \mb_substr($composerJsonPath, 0, -4) . 'lock'; + $composerJsonPath = __DIR__ . DIRECTORY_SEPARATOR . 'Fixture' . DIRECTORY_SEPARATOR . 'testInitAutoScripts.json'; + $composerLockPath = mb_substr($composerJsonPath, 0, -4) . 'lock'; - \file_put_contents($composerJsonPath, \json_encode(['test' => []])); - \file_put_contents($composerLockPath, \json_encode(['packages' => []])); + file_put_contents($composerJsonPath, json_encode(['test' => []])); + file_put_contents($composerLockPath, json_encode(['packages' => []])); - \putenv('COMPOSER=' . $composerJsonPath); + putenv('COMPOSER=' . $composerJsonPath); $packageMock = $this->mock(PackageInterface::class); $packageMock->shouldReceive('getScripts') @@ -652,7 +668,7 @@ public function testInitAutoScripts(): void $this->plugin->initAutoScripts(); - $jsonContent = \json_decode(\file_get_contents($composerJsonPath), true); + $jsonContent = json_decode(file_get_contents($composerJsonPath), true); self::assertTrue(isset($jsonContent['scripts'])); self::assertTrue(isset($jsonContent['scripts']['post-install-cmd'])); @@ -660,15 +676,15 @@ public function testInitAutoScripts(): void self::assertSame('@' . ScriptEvents::AUTO_SCRIPTS, $jsonContent['scripts']['post-install-cmd'][0]); self::assertSame('@' . ScriptEvents::AUTO_SCRIPTS, $jsonContent['scripts']['post-update-cmd'][0]); - $lockContent = \json_decode(\file_get_contents($composerLockPath), true); + $lockContent = json_decode(file_get_contents($composerLockPath), true); self::assertIsString($lockContent['content-hash']); - \putenv('COMPOSER='); - \putenv('COMPOSER'); + putenv('COMPOSER='); + putenv('COMPOSER'); - @\unlink($composerJsonPath); - @\unlink($composerLockPath); + @unlink($composerJsonPath); + @unlink($composerLockPath); } public function testInitAutoScriptsWithAutoScriptInComposerJson(): void @@ -700,18 +716,18 @@ public function testInitAutoScriptsWithAutoScriptInComposerJson(): void public function testOnPostCreateProject(): void { - $composerJsonPath = __DIR__ . \DIRECTORY_SEPARATOR . 'Fixture' . \DIRECTORY_SEPARATOR . 'testOnPostCreateProject.json'; - $composerLockPath = \mb_substr($composerJsonPath, 0, -4) . 'lock'; + $composerJsonPath = __DIR__ . DIRECTORY_SEPARATOR . 'Fixture' . DIRECTORY_SEPARATOR . 'testOnPostCreateProject.json'; + $composerLockPath = mb_substr($composerJsonPath, 0, -4) . 'lock'; - \file_put_contents($composerJsonPath, \json_encode([ + file_put_contents($composerJsonPath, json_encode([ 'name' => 'narrowspark/narrowspark', 'type' => 'project', 'description' => 'A skeleton to start a new Narrowspark project.', 'license' => 'MIT', ])); - \file_put_contents($composerLockPath, \json_encode(['packages' => []])); + file_put_contents($composerLockPath, json_encode(['packages' => []])); - \putenv('COMPOSER=' . $composerJsonPath); + putenv('COMPOSER=' . $composerJsonPath); $containerMock = $this->arrangeUpdateComposerLock(); $containerMock->shouldReceive('get') @@ -727,7 +743,7 @@ public function testOnPostCreateProject(): void $this->plugin->onPostCreateProject($this->mock(Event::class)); - $jsonContent = \json_decode(\file_get_contents($composerJsonPath), true); + $jsonContent = json_decode(file_get_contents($composerJsonPath), true); self::assertFalse(isset($jsonContent['name'])); self::assertFalse(isset($jsonContent['description'])); @@ -737,15 +753,15 @@ public function testOnPostCreateProject(): void self::assertTrue(isset($jsonContent['extra']['test'])); self::assertSame('foo', $jsonContent['extra']['test']); - $lockContent = \json_decode(\file_get_contents($composerLockPath), true); + $lockContent = json_decode(file_get_contents($composerLockPath), true); self::assertIsString($lockContent['content-hash']); - \putenv('COMPOSER='); - \putenv('COMPOSER'); + putenv('COMPOSER='); + putenv('COMPOSER'); - @\unlink($composerJsonPath); - @\unlink($composerLockPath); + @unlink($composerJsonPath); + @unlink($composerLockPath); } public function testRunSkeletonGeneratorWithoutInstaller(): void @@ -810,7 +826,7 @@ public function testOnPostAutoloadDump(): void $containerMock->shouldReceive('get') ->once() ->with('vendor-dir') - ->andReturn(__DIR__ . \DIRECTORY_SEPARATOR . 'Fixture' . \DIRECTORY_SEPARATOR . 'Configurator'); + ->andReturn(__DIR__ . DIRECTORY_SEPARATOR . 'Fixture' . DIRECTORY_SEPARATOR . 'Configurator'); $this->plugin->setContainer($containerMock); $this->plugin->onPostAutoloadDump($this->mock(Event::class)); @@ -857,7 +873,7 @@ public function testOnPostAutoloadDumpWithReset(): void $containerMock->shouldReceive('get') ->twice() ->with('vendor-dir') - ->andReturn(__DIR__ . \DIRECTORY_SEPARATOR . 'Fixture' . \DIRECTORY_SEPARATOR . 'Configurator'); + ->andReturn(__DIR__ . DIRECTORY_SEPARATOR . 'Fixture' . DIRECTORY_SEPARATOR . 'Configurator'); $event = $this->mock(Event::class); @@ -898,9 +914,9 @@ private function arrangeAutomaticConfig(): void } /** - * @return \Mockery\MockInterface + * @return \Composer\Repository\RepositoryManager|\Mockery\MockInterface */ - private function arrangeLocalRepository(): \Mockery\MockInterface + private function arrangeLocalRepository() { $localRepositoryMock = $this->mock(WritableRepositoryInterface::class); @@ -941,14 +957,14 @@ private function arrangeUpdateComposerLock() private function delete(string $path): void { - \array_map(function ($value): void { - if (\is_dir($value)) { + array_map(function ($value): void { + if (is_dir($value)) { $this->delete($value); - @\rmdir($value); + @rmdir($value); } else { - @\unlink($value); + @unlink($value); } - }, \glob($path . \DIRECTORY_SEPARATOR . '*')); + }, glob($path . DIRECTORY_SEPARATOR . '*')); } } diff --git a/tests/Automatic/Configurator/ComposerAutoScriptsConfiguratorTest.php b/tests/Automatic/Configurator/ComposerAutoScriptsConfiguratorTest.php index 66e8b731..f44f7420 100644 --- a/tests/Automatic/Configurator/ComposerAutoScriptsConfiguratorTest.php +++ b/tests/Automatic/Configurator/ComposerAutoScriptsConfiguratorTest.php @@ -23,6 +23,7 @@ use Narrowspark\Automatic\Configurator\ComposerAutoScriptsConfigurator; use Narrowspark\Automatic\Test\Fixture\ComposerJsonFactory; use Narrowspark\TestingHelper\Phpunit\MockeryTestCase; +use function unlink; /** * @internal @@ -110,7 +111,7 @@ public function testConfigure(): void $this->configurator->configure($packageMock); - \unlink($composerJsonPath); + unlink($composerJsonPath); } public function testUnconfigure(): void @@ -142,7 +143,7 @@ public function testUnconfigure(): void $this->configurator->unconfigure($packageMock); - \unlink($composerJsonPath); + unlink($composerJsonPath); } /** diff --git a/tests/Automatic/Configurator/ComposerScriptsConfiguratorTest.php b/tests/Automatic/Configurator/ComposerScriptsConfiguratorTest.php index 9a8e41fe..2e6a13ef 100644 --- a/tests/Automatic/Configurator/ComposerScriptsConfiguratorTest.php +++ b/tests/Automatic/Configurator/ComposerScriptsConfiguratorTest.php @@ -25,6 +25,10 @@ use Narrowspark\Automatic\QuestionFactory; use Narrowspark\Automatic\Test\Fixture\ComposerJsonFactory; use Narrowspark\TestingHelper\Phpunit\MockeryTestCase; +use function file_put_contents; +use function json_encode; +use function sprintf; +use function unlink; /** * @internal @@ -97,7 +101,7 @@ public function testConfigure(): void ->andReturn($composerRootJsonData); $composerJsonPath = __DIR__ . '/composer.json'; - \file_put_contents($composerJsonPath, \json_encode(['extra' => []])); + file_put_contents($composerJsonPath, json_encode(['extra' => []])); $this->jsonMock->shouldReceive('getPath') ->once() @@ -125,7 +129,7 @@ public function testConfigure(): void $this->configurator->configure($package); - \unlink($composerJsonPath); + unlink($composerJsonPath); } public function testConfigureWithUpdate(): void @@ -149,7 +153,7 @@ public function testConfigureWithUpdate(): void $composerJsonPath = __DIR__ . '/composer.json'; - \file_put_contents($composerJsonPath, \json_encode(['extra' => []])); + file_put_contents($composerJsonPath, json_encode(['extra' => []])); $this->jsonMock->shouldReceive('getPath') ->once() @@ -175,7 +179,7 @@ public function testConfigureWithUpdate(): void $this->configurator->configure($package); - \unlink($composerJsonPath); + unlink($composerJsonPath); } public function testConfigureWithBlacklist(): void @@ -222,7 +226,7 @@ public function testConfigureNotAllowedScripts(): void ->andReturn($composerRootJsonData); $composerJsonPath = __DIR__ . '/composer.json'; - \file_put_contents($composerJsonPath, \json_encode(['extra' => []])); + file_put_contents($composerJsonPath, json_encode(['extra' => []])); $this->jsonMock->shouldReceive('getPath') ->once() @@ -250,7 +254,7 @@ public function testConfigureNotAllowedScripts(): void $this->ioMock->shouldReceive('write') ->once() - ->with(\sprintf( + ->with(sprintf( ' Found not allowed composer events [notallowed] in [%s]' . "\n", $package->getName() )) @@ -258,7 +262,7 @@ public function testConfigureNotAllowedScripts(): void $this->configurator->configure($package); - \unlink($composerJsonPath); + unlink($composerJsonPath); } public function testConfigureWithoutScripts(): void @@ -310,7 +314,7 @@ public function testUnconfigure(): void $this->configurator->unconfigure($package); - \unlink($composerJsonPath); + unlink($composerJsonPath); } /** diff --git a/tests/Automatic/Configurator/CopyFromPackageConfiguratorTest.php b/tests/Automatic/Configurator/CopyFromPackageConfiguratorTest.php index 0d02aabf..3322a4f6 100644 --- a/tests/Automatic/Configurator/CopyFromPackageConfiguratorTest.php +++ b/tests/Automatic/Configurator/CopyFromPackageConfiguratorTest.php @@ -13,14 +13,21 @@ namespace Narrowspark\Automatic\Test\Configurator; +use Closure; use Composer\Composer; use Composer\IO\IOInterface; +use Exception; use Narrowspark\Automatic\Common\Contract\Configurator as ConfiguratorContract; use Narrowspark\Automatic\Common\Package; use Narrowspark\Automatic\Configurator\CopyFromPackageConfigurator; use Narrowspark\TestingHelper\Phpunit\MockeryTestCase; use Symfony\Component\Filesystem\Exception\IOException; use Symfony\Component\Filesystem\Filesystem; +use const DIRECTORY_SEPARATOR; +use function get_class; +use function rmdir; +use function sys_get_temp_dir; +use function unlink; /** * @internal @@ -71,16 +78,16 @@ public function testCopyFileFromPackage(): void $this->configurator->configure($package); - $filePath = \sys_get_temp_dir() . \DIRECTORY_SEPARATOR . '' . $toFileName; + $filePath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . '' . $toFileName; self::assertFileExists($filePath); - \unlink($filePath); + unlink($filePath); } public function testCopyDirWithFileFromPackage(): void { - $toAndFromFileName = \DIRECTORY_SEPARATOR . 'css' . \DIRECTORY_SEPARATOR . 'style.css'; + $toAndFromFileName = DIRECTORY_SEPARATOR . 'css' . DIRECTORY_SEPARATOR . 'style.css'; $package = $this->arrangePackageWithConfig($toAndFromFileName, $toAndFromFileName); @@ -89,23 +96,23 @@ public function testCopyDirWithFileFromPackage(): void ->with([' - Copying files'], true, IOInterface::VERBOSE); $this->ioMock->shouldReceive('writeError') ->once() - ->with([' - Created "' . \DIRECTORY_SEPARATOR . 'css' . \DIRECTORY_SEPARATOR . 'style.css"'], true, IOInterface::VERBOSE); + ->with([' - Created "' . DIRECTORY_SEPARATOR . 'css' . DIRECTORY_SEPARATOR . 'style.css"'], true, IOInterface::VERBOSE); $this->configurator->configure($package); - $dirPath = \sys_get_temp_dir() . \DIRECTORY_SEPARATOR . 'css'; - $filePath = $dirPath . \DIRECTORY_SEPARATOR . 'style.css'; + $dirPath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'css'; + $filePath = $dirPath . DIRECTORY_SEPARATOR . 'style.css'; self::assertDirectoryExists($dirPath); self::assertFileExists($filePath); - \unlink($filePath); - \rmdir($dirPath); + unlink($filePath); + rmdir($dirPath); } public function testCopyDirFromPackage(): void { - $toAndFromFileName = \DIRECTORY_SEPARATOR . 'css'; + $toAndFromFileName = DIRECTORY_SEPARATOR . 'css'; $package = $this->arrangePackageWithConfig($toAndFromFileName, $toAndFromFileName); @@ -114,18 +121,18 @@ public function testCopyDirFromPackage(): void ->with([' - Copying files'], true, IOInterface::VERBOSE); $this->ioMock->shouldReceive('writeError') ->once() - ->with([' - Created "' . \DIRECTORY_SEPARATOR . 'css"'], true, IOInterface::VERBOSE); + ->with([' - Created "' . DIRECTORY_SEPARATOR . 'css"'], true, IOInterface::VERBOSE); $this->configurator->configure($package); - $dirPath = \sys_get_temp_dir() . \DIRECTORY_SEPARATOR . 'css'; - $filePath = $dirPath . \DIRECTORY_SEPARATOR . 'style.css'; + $dirPath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'css'; + $filePath = $dirPath . DIRECTORY_SEPARATOR . 'style.css'; self::assertDirectoryExists($dirPath); self::assertFileExists($filePath); - \unlink($filePath); - \rmdir($dirPath); + unlink($filePath); + rmdir($dirPath); } public function testTryCopyFileThatIsNotFoundFromPackage(): void @@ -139,11 +146,11 @@ public function testTryCopyFileThatIsNotFoundFromPackage(): void ->with([' - Copying files'], true, IOInterface::VERBOSE); $this->ioMock->shouldReceive('writeError') ->once() - ->with([' - Failed to find the from folder or file path for "' . __DIR__ . \DIRECTORY_SEPARATOR . 'Stub' . \DIRECTORY_SEPARATOR . 'stub' . \DIRECTORY_SEPARATOR . 'notfound.txt" in "' . $package->getName() . '" package'], true, IOInterface::VERBOSE); + ->with([' - Failed to find the from folder or file path for "' . __DIR__ . DIRECTORY_SEPARATOR . 'Stub' . DIRECTORY_SEPARATOR . 'stub' . DIRECTORY_SEPARATOR . 'notfound.txt" in "' . $package->getName() . '" package'], true, IOInterface::VERBOSE); $this->configurator->configure($package); - $filePath = \sys_get_temp_dir() . \DIRECTORY_SEPARATOR . '' . $toFileName; + $filePath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . '' . $toFileName; self::assertFileNotExists($filePath); } @@ -175,7 +182,7 @@ public function testUnconfigureAFileFromPackage(): void public function testUnconfigureADirWithFileFromPackage(): void { - $toAndFromFileName = \DIRECTORY_SEPARATOR . 'css' . \DIRECTORY_SEPARATOR . 'style.css'; + $toAndFromFileName = DIRECTORY_SEPARATOR . 'css' . DIRECTORY_SEPARATOR . 'style.css'; $package = $this->arrangePackageWithConfig($toAndFromFileName, $toAndFromFileName); @@ -184,7 +191,7 @@ public function testUnconfigureADirWithFileFromPackage(): void ->with([' - Copying files'], true, IOInterface::VERBOSE); $this->ioMock->shouldReceive('writeError') ->once() - ->with([' - Created "' . \DIRECTORY_SEPARATOR . 'css' . \DIRECTORY_SEPARATOR . 'style.css"'], true, IOInterface::VERBOSE); + ->with([' - Created "' . DIRECTORY_SEPARATOR . 'css' . DIRECTORY_SEPARATOR . 'style.css"'], true, IOInterface::VERBOSE); $this->configurator->configure($package); @@ -193,20 +200,20 @@ public function testUnconfigureADirWithFileFromPackage(): void ->with([' - Removing files'], true, IOInterface::VERBOSE); $this->ioMock->shouldReceive('writeError') ->once() - ->with([' - Removed "' . \DIRECTORY_SEPARATOR . 'css' . \DIRECTORY_SEPARATOR . 'style.css"'], true, IOInterface::VERBOSE); + ->with([' - Removed "' . DIRECTORY_SEPARATOR . 'css' . DIRECTORY_SEPARATOR . 'style.css"'], true, IOInterface::VERBOSE); $this->configurator->unconfigure($package); - $dirPath = \sys_get_temp_dir() . \DIRECTORY_SEPARATOR . 'css'; + $dirPath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'css'; self::assertDirectoryExists($dirPath); - \rmdir($dirPath); + rmdir($dirPath); } public function testUnconfigureWithAIOException(): void { - $toAndFromFileName = \DIRECTORY_SEPARATOR . 'css' . \DIRECTORY_SEPARATOR . 'style.css'; + $toAndFromFileName = DIRECTORY_SEPARATOR . 'css' . DIRECTORY_SEPARATOR . 'style.css'; $package = $this->arrangePackageWithConfig($toAndFromFileName, $toAndFromFileName); @@ -215,7 +222,7 @@ public function testUnconfigureWithAIOException(): void ->with([' - Copying files'], true, IOInterface::VERBOSE); $this->ioMock->shouldReceive('writeError') ->once() - ->with([' - Created "' . \DIRECTORY_SEPARATOR . 'css' . \DIRECTORY_SEPARATOR . 'style.css"'], true, IOInterface::VERBOSE); + ->with([' - Created "' . DIRECTORY_SEPARATOR . 'css' . DIRECTORY_SEPARATOR . 'style.css"'], true, IOInterface::VERBOSE); $this->configurator->configure($package); @@ -232,40 +239,40 @@ public function testUnconfigureWithAIOException(): void ->with([' - Removing files'], true, IOInterface::VERBOSE); $this->ioMock->shouldReceive('writeError') ->once() - ->with([' - Failed to remove "' . \DIRECTORY_SEPARATOR . 'css' . \DIRECTORY_SEPARATOR . 'style.css"; Error message: '], true, IOInterface::VERBOSE); + ->with([' - Failed to remove "' . DIRECTORY_SEPARATOR . 'css' . DIRECTORY_SEPARATOR . 'style.css"; Error message: '], true, IOInterface::VERBOSE); $this->configurator->unconfigure($package); - $dirPath = \sys_get_temp_dir() . \DIRECTORY_SEPARATOR . 'css'; + $dirPath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'css'; - \unlink($dirPath . \DIRECTORY_SEPARATOR . 'style.css'); + unlink($dirPath . DIRECTORY_SEPARATOR . 'style.css'); self::assertDirectoryExists($dirPath); - \rmdir($dirPath); + rmdir($dirPath); } public function testCopyFileFromPackageWithConfig(): void { $toFileName = 'copy_of_copy.txt'; - $package = $this->arrangePackageWithConfig('copy.txt', '%SELF_DIR%' . \DIRECTORY_SEPARATOR . $toFileName); + $package = $this->arrangePackageWithConfig('copy.txt', '%SELF_DIR%' . DIRECTORY_SEPARATOR . $toFileName); $this->ioMock->shouldReceive('writeError') ->once() ->with([' - Copying files'], true, IOInterface::VERBOSE); $this->ioMock->shouldReceive('writeError') ->once() - ->with([' - Created "test' . \DIRECTORY_SEPARATOR . 'copy_of_copy.txt"'], true, IOInterface::VERBOSE); + ->with([' - Created "test' . DIRECTORY_SEPARATOR . 'copy_of_copy.txt"'], true, IOInterface::VERBOSE); $this->configurator->configure($package); - $filePath = \sys_get_temp_dir() . \DIRECTORY_SEPARATOR . 'test' . \DIRECTORY_SEPARATOR . $toFileName; + $filePath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR . $toFileName; self::assertFileExists($filePath); - \unlink($filePath); - \rmdir(\sys_get_temp_dir() . \DIRECTORY_SEPARATOR . 'test' . \DIRECTORY_SEPARATOR); + unlink($filePath); + rmdir(sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'test' . DIRECTORY_SEPARATOR); } /** @@ -282,7 +289,7 @@ protected function assertPreConditions(): void * @param string $from * @param string $to * - * @throws \Exception + * @throws Exception * * @return Package */ @@ -305,6 +312,6 @@ private function setPrivate($obj, $attribute): callable $this->{$attribute} = $value; }; - return \Closure::bind($setter, $obj, \get_class($obj)); + return Closure::bind($setter, $obj, get_class($obj)); } } diff --git a/tests/Automatic/Configurator/EnvConfiguratorTest.php b/tests/Automatic/Configurator/EnvConfiguratorTest.php index 99dff0e7..880787a3 100644 --- a/tests/Automatic/Configurator/EnvConfiguratorTest.php +++ b/tests/Automatic/Configurator/EnvConfiguratorTest.php @@ -19,6 +19,8 @@ use Narrowspark\Automatic\Common\Package; use Narrowspark\Automatic\Configurator\EnvConfigurator; use Narrowspark\TestingHelper\Phpunit\MockeryTestCase; +use function touch; +use function unlink; /** * @internal @@ -57,7 +59,7 @@ protected function setUp(): void $this->envPath = __DIR__ . '/.env'; $this->envDistPath = $this->envPath . '.dist'; - \touch($this->envDistPath); + touch($this->envDistPath); } /** @@ -67,8 +69,8 @@ protected function tearDown(): void { parent::tearDown(); - @\unlink($this->envDistPath); - @\unlink($this->envPath); + @unlink($this->envDistPath); + @unlink($this->envPath); } public function testGetName(): void diff --git a/tests/Automatic/Configurator/GitignoreConfiguratorTest.php b/tests/Automatic/Configurator/GitignoreConfiguratorTest.php index c57e1e01..11608a18 100644 --- a/tests/Automatic/Configurator/GitignoreConfiguratorTest.php +++ b/tests/Automatic/Configurator/GitignoreConfiguratorTest.php @@ -15,10 +15,14 @@ use Composer\Composer; use Composer\IO\NullIO; +use Exception; use Narrowspark\Automatic\Common\Contract\Configurator as ConfiguratorContract; use Narrowspark\Automatic\Common\Package; use Narrowspark\Automatic\Configurator\GitIgnoreConfigurator; use PHPUnit\Framework\TestCase; +use function sys_get_temp_dir; +use function touch; +use function unlink; /** * @internal @@ -51,9 +55,9 @@ protected function setUp(): void $this->configurator = new GitIgnoreConfigurator($this->composer, $this->nullIo, ['public-dir' => 'public']); - $this->gitignorePath = \sys_get_temp_dir() . '/.gitignore'; + $this->gitignorePath = sys_get_temp_dir() . '/.gitignore'; - \touch($this->gitignorePath); + touch($this->gitignorePath); } /** @@ -63,7 +67,7 @@ protected function tearDown(): void { parent::tearDown(); - @\unlink($this->gitignorePath); + @unlink($this->gitignorePath); } public function testGetName(): void @@ -143,7 +147,7 @@ public function testUnconfigureWithNotFoundPackage(): void * @param string $name * @param array $config * - * @throws \Exception + * @throws Exception * * @return Package */ diff --git a/tests/Automatic/ConfiguratorTest.php b/tests/Automatic/ConfiguratorTest.php index 233296f0..23fa192e 100644 --- a/tests/Automatic/ConfiguratorTest.php +++ b/tests/Automatic/ConfiguratorTest.php @@ -17,6 +17,8 @@ use Narrowspark\Automatic\Common\Contract\Configurator as ConfiguratorContract; use Narrowspark\Automatic\Common\Package; use Narrowspark\Automatic\Configurator; +use function sys_get_temp_dir; +use function unlink; /** * @internal @@ -39,7 +41,7 @@ protected function setUp(): void parent::setUp(); $this->copyFileName = 'copy_of_copy.txt'; - $this->copyPath = \sys_get_temp_dir() . '/' . $this->copyFileName; + $this->copyPath = sys_get_temp_dir() . '/' . $this->copyFileName; } public function testConfigureWithCopy(): void @@ -60,7 +62,7 @@ public function testConfigureWithCopy(): void self::assertFileExists($this->copyPath); - \unlink($this->copyPath); + unlink($this->copyPath); } public function testGetConfigurators(): void diff --git a/tests/Automatic/ContainerTest.php b/tests/Automatic/ContainerTest.php index 269bbd1c..3fb57f30 100644 --- a/tests/Automatic/ContainerTest.php +++ b/tests/Automatic/ContainerTest.php @@ -19,6 +19,7 @@ use Composer\IO\BufferIO; use Composer\IO\IOInterface; use Composer\Package\RootPackageInterface; +use Mockery; use Narrowspark\Automatic\Automatic; use Narrowspark\Automatic\Common\ClassFinder; use Narrowspark\Automatic\Configurator; @@ -35,6 +36,8 @@ use Narrowspark\TestingHelper\Phpunit\MockeryTestCase; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Filesystem\Filesystem; +use function is_array; +use function is_string; /** * @internal @@ -54,7 +57,7 @@ public static function setUpBeforeClass(): void parent::setUpBeforeClass(); $composer = new Composer(); - $configMock = \Mockery::mock(Config::class); + $configMock = Mockery::mock(Config::class); $configMock->shouldReceive('get') ->with('vendor-dir') ->andReturn('/vendor'); @@ -73,13 +76,13 @@ public static function setUpBeforeClass(): void $composer->setConfig($configMock); - $package = \Mockery::mock(RootPackageInterface::class); + $package = Mockery::mock(RootPackageInterface::class); $package->shouldReceive('getExtra') ->andReturn([]); $composer->setPackage($package); - $downloadManager = \Mockery::mock(DownloadManager::class); + $downloadManager = Mockery::mock(DownloadManager::class); $downloadManager->shouldReceive('getDownloader') ->with('file'); @@ -100,7 +103,7 @@ public function testContainerInstances(string $key, $expected): void { $value = self::$staticContainer->get($key); - if (\is_string($value) || \is_array($value)) { + if (is_string($value) || is_array($value)) { self::assertSame($expected, $value); } else { self::assertInstanceOf($expected, $value); @@ -142,6 +145,6 @@ public function provideContainerInstancesCases(): iterable public function testGetAll(): void { - self::assertCount(16, static::$staticContainer->getAll()); + self::assertCount(16, self::$staticContainer->getAll()); } } diff --git a/tests/Automatic/Fixture/ComposerJsonFactory.php b/tests/Automatic/Fixture/ComposerJsonFactory.php index 9315f765..62e80280 100644 --- a/tests/Automatic/Fixture/ComposerJsonFactory.php +++ b/tests/Automatic/Fixture/ComposerJsonFactory.php @@ -13,6 +13,14 @@ namespace Narrowspark\Automatic\Test\Fixture; +use const JSON_PRETTY_PRINT; +use const JSON_UNESCAPED_SLASHES; +use const JSON_UNESCAPED_UNICODE; +use function count; +use function file_get_contents; +use function json_decode; +use function json_encode; + final class ComposerJsonFactory { /** @@ -44,7 +52,7 @@ public static function createComposerJson( 'extra' => $extra, ]; - if (\count($devRequire) !== 0) { + if (count($devRequire) !== 0) { $composerJsonContent['require-dev'] = $devRequire; } @@ -132,7 +140,7 @@ public static function createComposerScriptJson(string $name, array $script = [] */ public static function jsonFileToArray(string $jsonFilePath): array { - return \json_decode(\file_get_contents($jsonFilePath), true); + return json_decode(file_get_contents($jsonFilePath), true); } /** @@ -142,7 +150,7 @@ public static function jsonFileToArray(string $jsonFilePath): array */ public static function jsonToArray(string $jsonContent): array { - return \json_decode($jsonContent, true); + return json_decode($jsonContent, true); } /** @@ -152,6 +160,6 @@ public static function jsonToArray(string $jsonContent): array */ public static function arrayToJson(array $jsonData): string { - return \json_encode($jsonData, \JSON_UNESCAPED_SLASHES | \JSON_PRETTY_PRINT | \JSON_UNESCAPED_UNICODE); + return json_encode($jsonData, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); } } diff --git a/tests/Automatic/Installer/AbstractInstallerTest.php b/tests/Automatic/Installer/AbstractInstallerTest.php index 50604052..cee2cbf2 100644 --- a/tests/Automatic/Installer/AbstractInstallerTest.php +++ b/tests/Automatic/Installer/AbstractInstallerTest.php @@ -16,12 +16,14 @@ use Composer\Downloader\DownloadManager; use Composer\Package\PackageInterface; use Composer\Repository\InstalledRepositoryInterface; +use Mockery; use Narrowspark\Automatic\Automatic; use Narrowspark\Automatic\Common\ClassFinder; use Narrowspark\Automatic\Common\Contract\Exception\UnexpectedValueException; use Narrowspark\Automatic\Lock; use Narrowspark\Automatic\Test\Traits\ArrangeComposerClasses; use Narrowspark\TestingHelper\Phpunit\MockeryTestCase; +use function trim; /** * @internal @@ -129,7 +131,7 @@ public function testInstall(): void ->andReturn($name); $this->packageMock->shouldReceive('getName') ->times(3) - ->andReturn(\trim($name, '/')); + ->andReturn(trim($name, '/')); $this->packageMock->shouldReceive('getTargetDir') ->andReturn(null); @@ -144,9 +146,9 @@ public function testInstall(): void $this->downloadManagerMock->shouldReceive('download'); $this->lockMock->shouldReceive('addSub') - ->with($this->installerClass::LOCK_KEY, $name, \Mockery::type('array')); + ->with($this->installerClass::LOCK_KEY, $name, Mockery::type('array')); $this->lockMock->shouldReceive('addSub') - ->with(Automatic::LOCK_CLASSMAP, $name, \Mockery::type('array')); + ->with(Automatic::LOCK_CLASSMAP, $name, Mockery::type('array')); $this->configuratorInstaller->install($this->repositoryMock, $this->packageMock); } @@ -165,12 +167,12 @@ public function testUpdate(): void $this->packageMock->shouldReceive('getPrettyName') ->andReturn($name); $this->packageMock->shouldReceive('getName') - ->andReturn(\trim($name, '/')); + ->andReturn(trim($name, '/')); $this->targetPackageMock->shouldReceive('getPrettyName') ->andReturn($name); $this->targetPackageMock->shouldReceive('getName') - ->andReturn(\trim($name, '/')); + ->andReturn(trim($name, '/')); $this->targetPackageMock->shouldReceive('getTargetDir') ->andReturn(''); $this->targetPackageMock->shouldReceive('getBinaries') @@ -184,9 +186,9 @@ public function testUpdate(): void ->andReturn(['psr-4' => ['Test\\' => '']]); $this->lockMock->shouldReceive('addSub') - ->with($this->installerClass::LOCK_KEY, $name, \Mockery::type('array')); + ->with($this->installerClass::LOCK_KEY, $name, Mockery::type('array')); $this->lockMock->shouldReceive('addSub') - ->with(Automatic::LOCK_CLASSMAP, $name, \Mockery::type('array')); + ->with(Automatic::LOCK_CLASSMAP, $name, Mockery::type('array')); $this->configuratorInstaller->update($this->repositoryMock, $this->packageMock, $this->targetPackageMock); } @@ -206,7 +208,7 @@ public function testInstallWithNotFoundClasses(): void $this->packageMock->shouldReceive('getBinaries') ->andReturn([]); $this->packageMock->shouldReceive('getName') - ->andReturn(\trim($name, '/')); + ->andReturn(trim($name, '/')); $this->repositoryMock->shouldReceive('hasPackage') ->twice() diff --git a/tests/Automatic/Installer/InstallationManagerTest.php b/tests/Automatic/Installer/InstallationManagerTest.php index 58037dc9..1f3f6891 100644 --- a/tests/Automatic/Installer/InstallationManagerTest.php +++ b/tests/Automatic/Installer/InstallationManagerTest.php @@ -18,11 +18,25 @@ use Composer\Package\RootPackageInterface; use Composer\Repository\RepositoryInterface; use Composer\Repository\RepositoryManager; +use Mockery; use Narrowspark\Automatic\Common\Contract\Package as PackageContract; use Narrowspark\Automatic\Installer\InstallationManager; use Narrowspark\Automatic\Test\Traits\ArrangeComposerClasses; use Narrowspark\TestingHelper\Phpunit\MockeryTestCase; use PHPUnit\Framework\Assert; +use const DIRECTORY_SEPARATOR; +use function array_keys; +use function array_map; +use function dirname; +use function file_put_contents; +use function glob; +use function is_dir; +use function json_encode; +use function mkdir; +use function putenv; +use function rmdir; +use function sprintf; +use function unlink; /** * @internal @@ -48,8 +62,8 @@ protected function setUp(): void $this->composerCachePath = __DIR__ . '/AutomaticTest'; - @\mkdir($this->composerCachePath); - \putenv('COMPOSER_CACHE_DIR=' . $this->composerCachePath); + @mkdir($this->composerCachePath); + putenv('COMPOSER_CACHE_DIR=' . $this->composerCachePath); $this->arrangeComposerClasses(); @@ -83,17 +97,17 @@ protected function tearDown(): void { parent::tearDown(); - \putenv('COMPOSER_CACHE_DIR='); - \putenv('COMPOSER_CACHE_DIR'); + putenv('COMPOSER_CACHE_DIR='); + putenv('COMPOSER_CACHE_DIR'); - $narrowsparkPath = __DIR__ . \DIRECTORY_SEPARATOR . 'narrowspark'; + $narrowsparkPath = __DIR__ . DIRECTORY_SEPARATOR . 'narrowspark'; $this->delete($this->composerCachePath); $this->delete($narrowsparkPath); - @\unlink($this->composerCachePath . \DIRECTORY_SEPARATOR . '.htaccess'); - @\rmdir($this->composerCachePath); - @\rmdir($narrowsparkPath); + @unlink($this->composerCachePath . DIRECTORY_SEPARATOR . '.htaccess'); + @rmdir($this->composerCachePath); + @rmdir($narrowsparkPath); } public function testInstallWithoutRequireAndRequireDev(): void @@ -118,16 +132,16 @@ public function testInstallWithoutRequireAndRequireDev(): void public function testInstallWithRequireAndNoPackageVersion(): void { $path = __DIR__ . '/Fixture/composer.json'; - $dirPath = \dirname($path); + $dirPath = dirname($path); - @\mkdir($dirPath); - @\file_put_contents($path, \json_encode(['require' => [], 'require-dev' => []])); - \putenv('COMPOSER=' . $path); + @mkdir($dirPath); + @file_put_contents($path, json_encode(['require' => [], 'require-dev' => []])); + putenv('COMPOSER=' . $path); $this->ioMock->shouldReceive('writeError') ->with('Downloading https://repo.packagist.org/packages.json', true, IOInterface::DEBUG); $this->ioMock->shouldReceive('writeError') - ->with(\Mockery::type('string'), true, IOInterface::DEBUG); + ->with(Mockery::type('string'), true, IOInterface::DEBUG); $this->ioMock->shouldReceive('writeError') ->with('Updating composer.json'); $this->ioMock->shouldReceive('writeError') @@ -169,8 +183,8 @@ public function testInstallWithRequireAndNoPackageVersion(): void $this->ioMock->shouldReceive('askAndValidate') ->once() ->with( - \sprintf('Enter the version of %s to require (or leave blank to use the latest version): ', $name), - \Mockery::type('closure') + sprintf('Enter the version of %s to require (or leave blank to use the latest version): ', $name), + Mockery::type('closure') ) ->andReturnFalse(); @@ -184,7 +198,7 @@ public function testInstallWithRequireAndNoPackageVersion(): void $this->rootPackageMock->shouldReceive('setRequires') ->once() ->withArgs(static function ($value) use ($name) { - $keys = \array_keys($value); + $keys = array_keys($value); Assert::assertSame($name, $keys[1]); Assert::assertInstanceOf(Link::class, $value[$name]); @@ -201,25 +215,25 @@ public function testInstallWithRequireAndNoPackageVersion(): void $manager->install([$packageMock]); $this->delete($dirPath); - \rmdir($dirPath); + rmdir($dirPath); - \putenv('COMPOSER='); - \putenv('COMPOSER'); + putenv('COMPOSER='); + putenv('COMPOSER'); } public function testInstallWithRequireAndPackageVersion(): void { $path = __DIR__ . '/Fixture/composer.json'; - $dirPath = \dirname($path); + $dirPath = dirname($path); - @\mkdir($dirPath); - @\file_put_contents($path, \json_encode(['require' => [], 'require-dev' => []])); - \putenv('COMPOSER=' . $path); + @mkdir($dirPath); + @file_put_contents($path, json_encode(['require' => [], 'require-dev' => []])); + putenv('COMPOSER=' . $path); $this->ioMock->shouldReceive('writeError') ->with('Downloading https://repo.packagist.org/packages.json', true, IOInterface::DEBUG); $this->ioMock->shouldReceive('writeError') - ->with(\Mockery::type('string'), true, IOInterface::DEBUG); + ->with(Mockery::type('string'), true, IOInterface::DEBUG); $this->ioMock->shouldReceive('writeError') ->with('Updating composer.json'); $this->ioMock->shouldReceive('writeError') @@ -253,13 +267,13 @@ public function testInstallWithRequireAndPackageVersion(): void $this->ioMock->shouldReceive('askAndValidate') ->never() ->with( - \sprintf('Enter the version of %s to require (or leave blank to use the latest version): ', $name), - \Mockery::type('closure') + sprintf('Enter the version of %s to require (or leave blank to use the latest version): ', $name), + Mockery::type('closure') ); $this->ioMock->shouldReceive('writeError') ->once() - ->with(\sprintf('Using version %s for %s', $constraint, $name)); + ->with(sprintf('Using version %s for %s', $constraint, $name)); $this->configMock->shouldReceive('get') ->with('sort-packages') @@ -271,7 +285,7 @@ public function testInstallWithRequireAndPackageVersion(): void $this->rootPackageMock->shouldReceive('setRequires') ->once() ->withArgs(static function ($value) use ($name) { - $keys = \array_keys($value); + $keys = array_keys($value); Assert::assertSame($name, $keys[1]); Assert::assertInstanceOf(Link::class, $value[$name]); @@ -288,20 +302,20 @@ public function testInstallWithRequireAndPackageVersion(): void $manager->install([$packageMock]); $this->delete($dirPath); - \rmdir($dirPath); + rmdir($dirPath); - \putenv('COMPOSER='); - \putenv('COMPOSER'); + putenv('COMPOSER='); + putenv('COMPOSER'); } public function testUninstallWithoutRequireAndRequireDev(): void { $path = __DIR__ . '/Fixture/composer.json'; - $dirPath = \dirname($path); + $dirPath = dirname($path); - @\mkdir($dirPath); - @\file_put_contents($path, \json_encode(['require' => [], 'require-dev' => []])); - \putenv('COMPOSER=' . $path); + @mkdir($dirPath); + @file_put_contents($path, json_encode(['require' => [], 'require-dev' => []])); + putenv('COMPOSER=' . $path); $this->ioMock->shouldReceive('writeError') ->atLeast() @@ -328,10 +342,10 @@ public function testUninstallWithoutRequireAndRequireDev(): void $manager->uninstall([]); $this->delete($dirPath); - \rmdir($dirPath); + rmdir($dirPath); - \putenv('COMPOSER='); - \putenv('COMPOSER'); + putenv('COMPOSER='); + putenv('COMPOSER'); } /** @@ -344,14 +358,14 @@ protected function allowMockingNonExistentMethods($allow = false): void private function delete(string $path): void { - \array_map(function ($value): void { - if (\is_dir($value)) { + array_map(function ($value): void { + if (is_dir($value)) { $this->delete($value); - @\rmdir($value); + @rmdir($value); } else { - @\unlink($value); + @unlink($value); } - }, \glob($path . \DIRECTORY_SEPARATOR . '*')); + }, glob($path . DIRECTORY_SEPARATOR . '*')); } } diff --git a/tests/Automatic/LockTest.php b/tests/Automatic/LockTest.php index c906480e..85c859b2 100644 --- a/tests/Automatic/LockTest.php +++ b/tests/Automatic/LockTest.php @@ -15,6 +15,7 @@ use Narrowspark\Automatic\Lock; use PHPUnit\Framework\TestCase; +use function unlink; /** * @internal @@ -30,7 +31,7 @@ public static function tearDownAfterClass(): void { parent::tearDownAfterClass(); - @\unlink(__DIR__ . '/test.lock'); + @unlink(__DIR__ . '/test.lock'); } /** diff --git a/tests/Automatic/Operation/InstallTest.php b/tests/Automatic/Operation/InstallTest.php index 4a1644f1..9ee49315 100644 --- a/tests/Automatic/Operation/InstallTest.php +++ b/tests/Automatic/Operation/InstallTest.php @@ -28,6 +28,8 @@ use Narrowspark\Automatic\Test\Fixture\Test\TransformWithScriptsExecutor\Automatic\TestExecutor; use Narrowspark\Automatic\Test\Operation\Traits\ArrangeOperationsClasses; use Narrowspark\TestingHelper\Phpunit\MockeryTestCase; +use const DIRECTORY_SEPARATOR; +use function str_replace; /** * @internal @@ -286,7 +288,7 @@ public function testTransformWithScriptsExecutor(): void ScriptExecutor::TYPE, $name, [ - TestExecutor::class => $this->fixturePath . \DIRECTORY_SEPARATOR . \str_replace('/', \DIRECTORY_SEPARATOR, $packageName) . \DIRECTORY_SEPARATOR . 'Automatic' . \DIRECTORY_SEPARATOR . 'TestExecutor.php', + TestExecutor::class => $this->fixturePath . DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $packageName) . DIRECTORY_SEPARATOR . 'Automatic' . DIRECTORY_SEPARATOR . 'TestExecutor.php', ] ); $this->lockMock->shouldReceive('addSub') diff --git a/tests/Automatic/Operation/Traits/ArrangeOperationsClasses.php b/tests/Automatic/Operation/Traits/ArrangeOperationsClasses.php index a3570b43..63319028 100644 --- a/tests/Automatic/Operation/Traits/ArrangeOperationsClasses.php +++ b/tests/Automatic/Operation/Traits/ArrangeOperationsClasses.php @@ -19,6 +19,8 @@ use Narrowspark\Automatic\Configurator; use Narrowspark\Automatic\Lock; use Narrowspark\Automatic\PackageConfigurator; +use const DIRECTORY_SEPARATOR; +use function dirname; trait ArrangeOperationsClasses { @@ -45,7 +47,7 @@ trait ArrangeOperationsClasses protected function arrangeOperationsClasses(): void { - $this->fixturePath = \dirname(__DIR__, 2) . \DIRECTORY_SEPARATOR . 'Fixture'; + $this->fixturePath = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'Fixture'; $this->lockMock = $this->mock(Lock::class); $this->ioMock = $this->mock(IOInterface::class); diff --git a/tests/Automatic/PackageConfiguratorTest.php b/tests/Automatic/PackageConfiguratorTest.php index 824b1101..21a1533e 100644 --- a/tests/Automatic/PackageConfiguratorTest.php +++ b/tests/Automatic/PackageConfiguratorTest.php @@ -14,6 +14,7 @@ namespace Narrowspark\Automatic\Test; use Composer\IO\IOInterface; +use Exception; use Narrowspark\Automatic\Common\Contract\Configurator as ConfiguratorContract; use Narrowspark\Automatic\Common\Package; use Narrowspark\Automatic\PackageConfigurator; @@ -90,7 +91,7 @@ protected function getConfiguratorClass(): string * @param string $name * @param array $config * - * @throws \Exception + * @throws Exception * * @return Package */ diff --git a/tests/Automatic/ScriptExecutorTest.php b/tests/Automatic/ScriptExecutorTest.php index 7426ae2b..7d8d89b0 100644 --- a/tests/Automatic/ScriptExecutorTest.php +++ b/tests/Automatic/ScriptExecutorTest.php @@ -13,14 +13,17 @@ namespace Narrowspark\Automatic\Test; +use Closure; use Composer\Composer; use Composer\EventDispatcher\ScriptExecutionException; use Composer\IO\IOInterface; use Composer\Util\ProcessExecutor; +use Mockery; use Narrowspark\Automatic\Common\Contract\Exception\InvalidArgumentException; use Narrowspark\Automatic\ScriptExecutor; use Narrowspark\Automatic\ScriptExtender\ScriptExtender; use Narrowspark\TestingHelper\Phpunit\MockeryTestCase; +use stdClass; /** * @internal @@ -60,7 +63,7 @@ public function testAddedExtenderThrowException(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('The class [stdClass] must implement the interface [Narrowspark\Automatic\Common\Contract\ScriptExtender].'); - $this->scriptExecutor->add(ScriptExtender::getType(), \stdClass::class); + $this->scriptExecutor->add(ScriptExtender::getType(), stdClass::class); } public function testAddedExtenderThrowExceptionOnExistendExtender(): void @@ -88,7 +91,7 @@ public function testExecute(): void $this->processExecutorMock->shouldReceive('execute') ->once() - ->with('php -v', \Mockery::type(\Closure::class)) + ->with('php -v', Mockery::type(Closure::class)) ->andReturn(0); $this->ioMock->shouldReceive('writeError') ->once() @@ -115,7 +118,7 @@ public function testExecuteWithCmdError(): void $this->processExecutorMock->shouldReceive('execute') ->once() - ->with('php -v', \Mockery::type(\Closure::class)) + ->with('php -v', Mockery::type(Closure::class)) ->andReturn(1); $this->ioMock->shouldReceive('writeError') ->once() @@ -146,7 +149,7 @@ public function testExecuteWithoutVerbose(): void $this->processExecutorMock->shouldReceive('execute') ->once() - ->with('php -v', \Mockery::type(\Closure::class)) + ->with('php -v', Mockery::type(Closure::class)) ->andReturn(0); $this->ioMock->shouldReceive('writeError') @@ -174,7 +177,7 @@ public function testExecuteWithoutVerboseAndCmdError(): void $this->processExecutorMock->shouldReceive('execute') ->once() - ->with('php -v', \Mockery::type(\Closure::class)) + ->with('php -v', Mockery::type(Closure::class)) ->andReturn(1); $this->ioMock->shouldReceive('writeError') diff --git a/tests/Automatic/SkeletonGeneratorTest.php b/tests/Automatic/SkeletonGeneratorTest.php index c73ffe1c..b07d5d3f 100644 --- a/tests/Automatic/SkeletonGeneratorTest.php +++ b/tests/Automatic/SkeletonGeneratorTest.php @@ -14,6 +14,7 @@ namespace Narrowspark\Automatic\Test; use Composer\IO\IOInterface; +use Mockery; use Narrowspark\Automatic\Automatic; use Narrowspark\Automatic\Common\Package; use Narrowspark\Automatic\Installer\InstallationManager; @@ -24,6 +25,8 @@ use Narrowspark\Automatic\Test\Fixture\FrameworkDefaultFixtureGenerator; use Narrowspark\TestingHelper\Phpunit\MockeryTestCase; use PHPUnit\Framework\Assert; +use function file_exists; +use function unlink; /** * @internal @@ -73,8 +76,8 @@ protected function tearDown(): void $path = __DIR__ . '/Fixture/test.php'; - if (\file_exists($path)) { - @\unlink($path); + if (file_exists($path)) { + @unlink($path); } } @@ -141,7 +144,7 @@ public function testRemove(): void $this->installationManagerMock->shouldReceive('uninstall') ->once() - ->with(\Mockery::type('array'), []); + ->with(Mockery::type('array'), []); $this->lockMock->shouldReceive('read') ->once(); diff --git a/tests/Common/ClassFinderTest.php b/tests/Common/ClassFinderTest.php index 4af87513..e9a6510d 100644 --- a/tests/Common/ClassFinderTest.php +++ b/tests/Common/ClassFinderTest.php @@ -13,6 +13,7 @@ namespace Narrowspark\Automatic\Test\Common; +use Closure; use Narrowspark\Automatic\Common\ClassFinder; use Narrowspark\Automatic\Common\Traits\GetGenericPropertyReaderTrait; use Narrowspark\Automatic\Test\Common\Fixture\Finder\AbstractClass; @@ -23,6 +24,10 @@ use Narrowspark\Automatic\Test\Common\Fixture\Finder\Nested\DummyClassNested; use Narrowspark\Automatic\Test\Common\Fixture\Finder\StaticFunctionAndClasses; use PHPUnit\Framework\TestCase; +use function mkdir; +use function rmdir; +use function touch; +use function unlink; /** * @internal @@ -75,8 +80,8 @@ public function testWithEmptyFolder(): void $dir = __DIR__ . '/Fixture/empty'; $filePath = $dir . '/empty.php'; - @\mkdir($dir); - @\touch($filePath); + @mkdir($dir); + @touch($filePath); $this->loader ->addPsr0('/Fixture/empty', ['']) @@ -87,8 +92,8 @@ public function testWithEmptyFolder(): void self::assertSame([], $this->loader->getAbstractClasses()); self::assertSame([], $this->loader->getInterfaces()); - @\unlink($filePath); - @\rmdir($dir); + @unlink($filePath); + @rmdir($dir); } public function testSetComposerAutoload(): void @@ -130,7 +135,7 @@ public function testSetFilter(): void return false; }); - self::assertInstanceOf(\Closure::class, $genericPropertyReader($this->loader, 'filter')); + self::assertInstanceOf(Closure::class, $genericPropertyReader($this->loader, 'filter')); $this->loader ->addPsr4('Fixture/Finder', ['']) diff --git a/tests/Common/ContainerTest.php b/tests/Common/ContainerTest.php index f940e3d9..96c4f44b 100644 --- a/tests/Common/ContainerTest.php +++ b/tests/Common/ContainerTest.php @@ -14,9 +14,12 @@ namespace Narrowspark\Automatic\Test\Common; use Composer\Composer; +use Mockery; use Narrowspark\Automatic\Common\AbstractContainer; use Narrowspark\Automatic\Common\Contract\Exception\InvalidArgumentException; use Narrowspark\TestingHelper\Phpunit\MockeryTestCase; +use function is_array; +use function is_string; /** * @internal @@ -36,7 +39,7 @@ public static function setUpBeforeClass(): void parent::setUpBeforeClass(); self::$staticContainer = new DummyContainer([ Composer::class => static function (AbstractContainer $container) { - return \Mockery::mock(Composer::class); + return Mockery::mock(Composer::class); }, 'vendor-dir' => static function () { return '/vendor'; @@ -56,7 +59,7 @@ public function testContainerInstances(string $key, $expected): void { $value = self::$staticContainer->get($key); - if (\is_string($value) || \is_array($value)) { + if (is_string($value) || is_array($value)) { self::assertSame($expected, $value); } else { self::assertInstanceOf($expected, $value); @@ -78,23 +81,23 @@ public function testGetThrowException(): void $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('Identifier [test] is not defined.'); - static::$staticContainer->get('test'); + self::$staticContainer->get('test'); } public function testGetCache(): void { - self::assertSame('/vendor', static::$staticContainer->get('vendor-dir')); + self::assertSame('/vendor', self::$staticContainer->get('vendor-dir')); - static::$staticContainer->set('vendor-dir', static function () { + self::$staticContainer->set('vendor-dir', static function () { return 'test'; }); - self::assertSame('/vendor', static::$staticContainer->get('vendor-dir')); + self::assertSame('/vendor', self::$staticContainer->get('vendor-dir')); } public function testGetAll(): void { - self::assertCount(2, static::$staticContainer->getAll()); + self::assertCount(2, self::$staticContainer->getAll()); } } diff --git a/tests/Common/PackageTest.php b/tests/Common/PackageTest.php index 898f53ff..ac00c21e 100644 --- a/tests/Common/PackageTest.php +++ b/tests/Common/PackageTest.php @@ -13,6 +13,8 @@ namespace Narrowspark\Automatic\Test\Common; +use DateTime; +use DateTimeImmutable; use Narrowspark\Automatic\Common\Contract\Package as ContractPackage; use Narrowspark\Automatic\Common\Package; use PHPUnit\Framework\TestCase; @@ -143,7 +145,7 @@ public function testSetAndGetParentName(): void public function testSetAndGetTime(): void { - $time = (new \DateTimeImmutable())->format(\DateTime::RFC3339); + $time = (new DateTimeImmutable())->format(DateTime::RFC3339); $this->package->setTime($time); diff --git a/tests/Common/PathTest.php b/tests/Common/PathTest.php index 28597e35..1a790416 100644 --- a/tests/Common/PathTest.php +++ b/tests/Common/PathTest.php @@ -15,6 +15,7 @@ use Narrowspark\Automatic\Common\Path; use PHPUnit\Framework\TestCase; +use const DIRECTORY_SEPARATOR; /** * @internal @@ -44,7 +45,7 @@ public function testGetWorkingDir(): void public function testRelativize(): void { self::assertSame( - '.' . \DIRECTORY_SEPARATOR, + '.' . DIRECTORY_SEPARATOR, $this->path->relativize(__DIR__) ); } @@ -52,8 +53,8 @@ public function testRelativize(): void public function testConcatenateOnWindows(): void { self::assertEquals( - 'c:' . \DIRECTORY_SEPARATOR . 'my-project' . \DIRECTORY_SEPARATOR . 'src' . \DIRECTORY_SEPARATOR . 'kernel.php', - $this->path->concatenate(['c:' . \DIRECTORY_SEPARATOR . 'my-project', 'src' . \DIRECTORY_SEPARATOR, 'kernel.php']) + 'c:' . DIRECTORY_SEPARATOR . 'my-project' . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'kernel.php', + $this->path->concatenate(['c:' . DIRECTORY_SEPARATOR . 'my-project', 'src' . DIRECTORY_SEPARATOR, 'kernel.php']) ); } @@ -77,11 +78,11 @@ public function testConcatenate(string $part1, string $part2, string $expectedPa public function provideConcatenateCases(): iterable { return [ - [__DIR__, 'foo' . \DIRECTORY_SEPARATOR . 'bar.txt', __DIR__ . \DIRECTORY_SEPARATOR . 'foo' . \DIRECTORY_SEPARATOR . 'bar.txt'], - [__DIR__, \DIRECTORY_SEPARATOR . 'foo' . \DIRECTORY_SEPARATOR . 'bar.txt', __DIR__ . \DIRECTORY_SEPARATOR . 'foo' . \DIRECTORY_SEPARATOR . 'bar.txt'], - ['', 'foo' . \DIRECTORY_SEPARATOR . 'bar.txt', \DIRECTORY_SEPARATOR . 'foo' . \DIRECTORY_SEPARATOR . 'bar.txt'], - ['', \DIRECTORY_SEPARATOR . 'foo' . \DIRECTORY_SEPARATOR . 'bar.txt', \DIRECTORY_SEPARATOR . 'foo' . \DIRECTORY_SEPARATOR . 'bar.txt'], - ['.', 'foo' . \DIRECTORY_SEPARATOR . 'bar.txt', '.' . \DIRECTORY_SEPARATOR . 'foo' . \DIRECTORY_SEPARATOR . 'bar.txt'], + [__DIR__, 'foo' . DIRECTORY_SEPARATOR . 'bar.txt', __DIR__ . DIRECTORY_SEPARATOR . 'foo' . DIRECTORY_SEPARATOR . 'bar.txt'], + [__DIR__, DIRECTORY_SEPARATOR . 'foo' . DIRECTORY_SEPARATOR . 'bar.txt', __DIR__ . DIRECTORY_SEPARATOR . 'foo' . DIRECTORY_SEPARATOR . 'bar.txt'], + ['', 'foo' . DIRECTORY_SEPARATOR . 'bar.txt', DIRECTORY_SEPARATOR . 'foo' . DIRECTORY_SEPARATOR . 'bar.txt'], + ['', DIRECTORY_SEPARATOR . 'foo' . DIRECTORY_SEPARATOR . 'bar.txt', DIRECTORY_SEPARATOR . 'foo' . DIRECTORY_SEPARATOR . 'bar.txt'], + ['.', 'foo' . DIRECTORY_SEPARATOR . 'bar.txt', '.' . DIRECTORY_SEPARATOR . 'foo' . DIRECTORY_SEPARATOR . 'bar.txt'], ]; } } diff --git a/tests/Common/ScriptExtender/PhpScriptExtenderTest.php b/tests/Common/ScriptExtender/PhpScriptExtenderTest.php index 6ea62c26..d3b4f759 100644 --- a/tests/Common/ScriptExtender/PhpScriptExtenderTest.php +++ b/tests/Common/ScriptExtender/PhpScriptExtenderTest.php @@ -17,6 +17,8 @@ use Composer\IO\NullIO; use Narrowspark\Automatic\Common\ScriptExtender\PhpScriptExtender; use PHPUnit\Framework\TestCase; +use ReflectionClass; +use function putenv; /** * @internal @@ -40,7 +42,7 @@ protected function setUp(): void public function testClassIsNotFinal(): void { - $reflection = new \ReflectionClass(PhpScriptExtender::class); + $reflection = new ReflectionClass(PhpScriptExtender::class); self::assertFalse($reflection->isFinal()); } @@ -62,8 +64,8 @@ public function testExpand(): void public function testExpandWithIniLoad(): void { // clear the composer env - \putenv('COMPOSER_ORIGINAL_INIS='); - \putenv('COMPOSER_ORIGINAL_INIS'); + putenv('COMPOSER_ORIGINAL_INIS='); + putenv('COMPOSER_ORIGINAL_INIS'); $output = $this->extender->expand('echo "hallo";'); diff --git a/tests/Common/Traits/PhpFileMarkerTraitTest.php b/tests/Common/Traits/PhpFileMarkerTraitTest.php index 1e828cf2..442e729b 100644 --- a/tests/Common/Traits/PhpFileMarkerTraitTest.php +++ b/tests/Common/Traits/PhpFileMarkerTraitTest.php @@ -15,6 +15,10 @@ use Narrowspark\Automatic\Common\Traits\PhpFileMarkerTrait; use PHPUnit\Framework\TestCase; +use function file_put_contents; +use function sys_get_temp_dir; +use function tempnam; +use function unlink; /** * @internal @@ -32,19 +36,19 @@ protected function setUp(): void { parent::setUp(); - $this->path = \tempnam(\sys_get_temp_dir(), 'diac'); + $this->path = tempnam(sys_get_temp_dir(), 'diac'); } protected function tearDown(): void { parent::tearDown(); - @\unlink($this->path); + @unlink($this->path); } public function testIsFileMarked(): void { - \file_put_contents($this->path, ' marked **/ \'test\' /** < marked **/' . "\n" . '];' . "\n"); + file_put_contents($this->path, ' marked **/ \'test\' /** < marked **/' . "\n" . '];' . "\n"); self::assertFalse($this->isFileMarked('test', $this->path)); self::assertTrue($this->isFileMarked('marked', $this->path)); @@ -52,7 +56,7 @@ public function testIsFileMarked(): void public function testMarkData(): void { - \file_put_contents($this->path, $this->markData('test', '$arr = [];', 4)); + file_put_contents($this->path, $this->markData('test', '$arr = [];', 4)); self::assertTrue($this->isFileMarked('test', $this->path)); } diff --git a/tests/Internal/MirrorClassTest.php b/tests/Internal/MirrorClassTest.php index 53d39e61..47e5792a 100644 --- a/tests/Internal/MirrorClassTest.php +++ b/tests/Internal/MirrorClassTest.php @@ -14,6 +14,10 @@ namespace Narrowspark\Automatic\Test\Internal; use PHPUnit\Framework\TestCase; +use const DIRECTORY_SEPARATOR; +use function dirname; +use function file_get_contents; +use function str_replace; /** * @internal @@ -24,21 +28,22 @@ final class MirrorClassTest extends TestCase { public function testMirrorFiles(): void { - $rootPath = \dirname(__DIR__, 2) . \DIRECTORY_SEPARATOR; + $rootPath = dirname(__DIR__, 2) . DIRECTORY_SEPARATOR; + $comment = MirrorSettings::COMMENT_STRING; - foreach (MirrorSettings::MIRROR_LIST as $path => $settings) { - foreach (MirrorSettings::OUTPUT_LIST as $outputPath => $namespace) { - $comment = MirrorSettings::COMMENT_STRING; + foreach (MirrorSettings::MIRROR_LIST as $list) { + $outputSettings = $list['output']; - $content = \file_get_contents($rootPath . $path); - $content = \str_replace(["\nclass", "\nabstract class", "\ninterface"], ["\n{$comment}\nclass", "\n{$comment}\nabstract class", "\n{$comment}\ninterface"], $content); - $content = \str_replace($settings['namespace'], $namespace, $content); + foreach ($list['mirror_list'] as $path => $settings) { + $content = file_get_contents($rootPath . $path); + $content = str_replace(["\nclass", "\nabstract class", "\ninterface"], ["\n{$comment}\nclass", "\n{$comment}\nabstract class", "\n{$comment}\ninterface"], $content); + $content = str_replace($settings['namespace'], $outputSettings['namespace'], $content); - $outputPath = $outputPath . $settings['path']; + $outputPath = $outputSettings['path'] . $settings['path']; - $mirrorPath = \str_replace("/{$settings['path']}/", "/{$outputPath}/", $rootPath . $path); + $mirrorPath = str_replace("/{$settings['path']}/", "/{$outputPath}/", $rootPath . $path); - self::assertSame($content, \file_get_contents($mirrorPath), $mirrorPath); + self::assertSame($content, file_get_contents($mirrorPath), $mirrorPath); } } } diff --git a/tests/Internal/MirrorSettings.php b/tests/Internal/MirrorSettings.php index 34158c2b..44b23b80 100644 --- a/tests/Internal/MirrorSettings.php +++ b/tests/Internal/MirrorSettings.php @@ -13,40 +13,47 @@ namespace Narrowspark\Automatic\Test\Internal; +use const DIRECTORY_SEPARATOR; + final class MirrorSettings { + public const COMMON_OPTIONS = [ + 'path' => 'Common', + 'namespace' => 'Automatic\\Common', + ]; + public const MIRROR_LIST = [ - 'src/Common/Contract/Exception/Exception.php' => [ - 'path' => 'Common', - 'namespace' => 'Automatic\\Common', - ], - 'src/Common/Contract/Exception/InvalidArgumentException.php' => [ - 'path' => 'Common', - 'namespace' => 'Automatic\\Common', - ], - 'src/Common/Contract/Container.php' => [ - 'path' => 'Common', - 'namespace' => 'Automatic\\Common', - ], - 'src/Common/AbstractContainer.php' => [ - 'path' => 'Common', - 'namespace' => 'Automatic\\Common', + [ + 'output' => [ + 'path' => 'Prefetcher' . DIRECTORY_SEPARATOR, + 'namespace' => 'Automatic\\Prefetcher\\Common', + ], + 'mirror_list' => [ + 'src/Common/Contract/Exception/Exception.php' => self::COMMON_OPTIONS, + 'src/Common/Contract/Exception/InvalidArgumentException.php' => self::COMMON_OPTIONS, + 'src/Common/Contract/Container.php' => self::COMMON_OPTIONS, + 'src/Common/AbstractContainer.php' => self::COMMON_OPTIONS, + 'src/Common/Contract/Resettable.php' => self::COMMON_OPTIONS, + 'src/Common/Traits/GetGenericPropertyReaderTrait.php' => self::COMMON_OPTIONS, + 'src/Common/Contract/Exception/RuntimeException.php' => self::COMMON_OPTIONS, + 'src/Common/Util.php' => self::COMMON_OPTIONS, + ], ], - 'src/Common/Contract/Resettable.php' => [ - 'path' => 'Common', - 'namespace' => 'Automatic\\Common', - ], - 'src/Common/Traits/GetGenericPropertyReaderTrait.php' => [ - 'path' => 'Common', - 'namespace' => 'Automatic\\Common', - ], - 'src/Common/Contract/Exception/RuntimeException.php' => [ - 'path' => 'Common', - 'namespace' => 'Automatic\\Common', - ], - 'src/Common/Util.php' => [ - 'path' => 'Common', - 'namespace' => 'Automatic\\Common', + [ + 'output' => [ + 'path' => 'Security' . DIRECTORY_SEPARATOR, + 'namespace' => 'Automatic\\Security\\Common', + ], + 'mirror_list' => [ + 'src/Common/Contract/Exception/Exception.php' => self::COMMON_OPTIONS, + 'src/Common/Contract/Exception/InvalidArgumentException.php' => self::COMMON_OPTIONS, + 'src/Common/Contract/Container.php' => self::COMMON_OPTIONS, + 'src/Common/AbstractContainer.php' => self::COMMON_OPTIONS, + 'src/Common/Contract/Resettable.php' => self::COMMON_OPTIONS, + 'src/Common/Traits/GetGenericPropertyReaderTrait.php' => self::COMMON_OPTIONS, + 'src/Common/Contract/Exception/RuntimeException.php' => self::COMMON_OPTIONS, + 'src/Common/Util.php' => self::COMMON_OPTIONS, + ], ], ]; @@ -55,11 +62,8 @@ final class MirrorSettings * This file is automatically generated, dont change this file, otherwise the changes are lost after the next mirror update. * * @codeCoverageIgnore + * * @internal */ STRING; - - public const OUTPUT_LIST = [ - 'Prefetcher' . \DIRECTORY_SEPARATOR => 'Automatic\\Prefetcher\\Common', - ]; } diff --git a/tests/Prefetcher/ContainerTest.php b/tests/Prefetcher/ContainerTest.php index 0a2ec282..5b60ae21 100644 --- a/tests/Prefetcher/ContainerTest.php +++ b/tests/Prefetcher/ContainerTest.php @@ -20,6 +20,7 @@ use Composer\IO\IOInterface; use Composer\Package\RootPackageInterface; use Composer\Util\RemoteFilesystem; +use Mockery; use Narrowspark\Automatic\Prefetcher\Container; use Narrowspark\Automatic\Prefetcher\Contract\LegacyTagsManager as LegacyTagsManagerContract; use Narrowspark\Automatic\Prefetcher\Downloader\ParallelDownloader; @@ -27,6 +28,8 @@ use Narrowspark\Automatic\Prefetcher\Prefetcher; use Narrowspark\TestingHelper\Phpunit\MockeryTestCase; use Symfony\Component\Console\Input\InputInterface; +use function is_array; +use function is_string; /** * @internal @@ -48,7 +51,7 @@ public static function setUpBeforeClass(): void parent::setUpBeforeClass(); $composer = new Composer(); - $configMock = \Mockery::mock(Config::class); + $configMock = Mockery::mock(Config::class); $configMock->shouldReceive('get') ->with('vendor-dir') ->andReturn('/vendor'); @@ -67,13 +70,13 @@ public static function setUpBeforeClass(): void $composer->setConfig($configMock); - $package = \Mockery::mock(RootPackageInterface::class); + $package = Mockery::mock(RootPackageInterface::class); $package->shouldReceive('getExtra') ->andReturn([]); $composer->setPackage($package); - $downloadManager = \Mockery::mock(DownloadManager::class); + $downloadManager = Mockery::mock(DownloadManager::class); $downloadManager->shouldReceive('getDownloader') ->with('file'); @@ -94,7 +97,7 @@ public function testContainerInstances(string $key, $expected): void { $value = self::$staticContainer->get($key); - if (\is_string($value) || \is_array($value)) { + if (is_string($value) || is_array($value)) { self::assertSame($expected, $value); } else { self::assertInstanceOf($expected, $value); @@ -121,6 +124,6 @@ public function provideContainerInstancesCases(): iterable public function testGetAll(): void { - self::assertCount(9, static::$staticContainer->getAll()); + self::assertCount(9, self::$staticContainer->getAll()); } } diff --git a/tests/Prefetcher/Downloader/ParallelDownloaderTest.php b/tests/Prefetcher/Downloader/ParallelDownloaderTest.php index 37609cef..aecc7884 100644 --- a/tests/Prefetcher/Downloader/ParallelDownloaderTest.php +++ b/tests/Prefetcher/Downloader/ParallelDownloaderTest.php @@ -18,6 +18,7 @@ use Narrowspark\Automatic\Prefetcher\Downloader\ParallelDownloader; use Narrowspark\Automatic\Test\Traits\ArrangeComposerClasses; use Narrowspark\TestingHelper\Phpunit\MockeryTestCase; +use function method_exists; /** * @internal @@ -40,7 +41,7 @@ protected function setUp(): void $this->arrangeComposerClasses(); - if (! \method_exists(RemoteFilesystem::class, 'getRemoteContents')) { + if (! method_exists(RemoteFilesystem::class, 'getRemoteContents')) { $this->ioMock->shouldReceive('writeError') ->once() ->with('Composer >=1.7 not found, downloads will happen in sequence', true, IOInterface::DEBUG); diff --git a/tests/Prefetcher/LegacyTagsManagerTest.php b/tests/Prefetcher/LegacyTagsManagerTest.php index 0fc3c8cd..2cf54880 100644 --- a/tests/Prefetcher/LegacyTagsManagerTest.php +++ b/tests/Prefetcher/LegacyTagsManagerTest.php @@ -14,8 +14,13 @@ namespace Narrowspark\Automatic\Test\Prefetcher; use Composer\IO\IOInterface; +use Generator; use Narrowspark\Automatic\Prefetcher\LegacyTagsManager; use Narrowspark\TestingHelper\Phpunit\MockeryTestCase; +use const DIRECTORY_SEPARATOR; +use function file_get_contents; +use function json_decode; +use function sprintf; /** * @internal @@ -40,7 +45,7 @@ protected function setUp(): void { parent::setUp(); - $pPath = __DIR__ . \DIRECTORY_SEPARATOR . 'Fixture' . \DIRECTORY_SEPARATOR . 'Packagist' . \DIRECTORY_SEPARATOR; + $pPath = __DIR__ . DIRECTORY_SEPARATOR . 'Fixture' . DIRECTORY_SEPARATOR . 'Packagist' . DIRECTORY_SEPARATOR; $this->downloadFileList = [ 'cakephp$cakephp' => $pPath . 'provider-cakephp$cakephp.json', @@ -94,10 +99,10 @@ public function testRemoveLegacyTagsWithSymfony(): void { $this->tagsManger->addConstraint('symfony/symfony', '>=3.4'); - $originalData = \json_decode(\file_get_contents($this->downloadFileList['symfony$symfony']), true); + $originalData = json_decode(file_get_contents($this->downloadFileList['symfony$symfony']), true); $this->ioMock->shouldReceive('writeError') - ->with(\sprintf('Restricting packages listed in [%s] to [%s]', 'symfony/symfony', '>=3.4')); + ->with(sprintf('Restricting packages listed in [%s] to [%s]', 'symfony/symfony', '>=3.4')); $data = $this->tagsManger->removeLegacyTags($originalData); @@ -106,19 +111,19 @@ public function testRemoveLegacyTagsWithSymfony(): void public function testRemoveLegacyTagsSkipIfNoProviderFound(): void { - $originalData = \json_decode(\file_get_contents($this->downloadFileList['codeigniter$framework']), true); + $originalData = json_decode(file_get_contents($this->downloadFileList['codeigniter$framework']), true); self::assertSame($originalData, $this->tagsManger->removeLegacyTags($originalData)); } public function testRemoveLegacyTagsWithCakePHP(): void { - $originalData = \json_decode(\file_get_contents($this->downloadFileList['cakephp$cakephp']), true); + $originalData = json_decode(file_get_contents($this->downloadFileList['cakephp$cakephp']), true); $this->tagsManger->addConstraint('cakephp/cakephp', '>=3.5'); $this->ioMock->shouldReceive('writeError') - ->with(\sprintf('Restricting packages listed in [%s] to [%s]', 'cakephp/cakephp', '>=3.5')); + ->with(sprintf('Restricting packages listed in [%s] to [%s]', 'cakephp/cakephp', '>=3.5')); $data = $this->tagsManger->removeLegacyTags($originalData); @@ -144,7 +149,7 @@ public function testRemoveLegacyTags(array $expected, array $packages, string $s } /** - * @return \Generator + * @return Generator */ public function provideRemoveLegacyTagsCases(): iterable { diff --git a/tests/Prefetcher/PluginTest.php b/tests/Prefetcher/PluginTest.php index 320e9a00..59f9995b 100644 --- a/tests/Prefetcher/PluginTest.php +++ b/tests/Prefetcher/PluginTest.php @@ -16,6 +16,7 @@ use Composer\Installer\InstallerEvent; use Composer\Plugin\PreFileDownloadEvent; use Composer\Util\RemoteFilesystem; +use Mockery; use Narrowspark\Automatic\Common\Contract\Container as ContainerContract; use Narrowspark\Automatic\Prefetcher\Downloader\ParallelDownloader; use Narrowspark\Automatic\Prefetcher\FunctionMock; @@ -111,7 +112,7 @@ public function testOnFileDownload(): void $event->shouldReceive('setRemoteFilesystem') ->once() - ->with(\Mockery::type(ParallelDownloader::class)); + ->with(Mockery::type(ParallelDownloader::class)); $containerMock = $this->mock(ContainerContract::class); $containerMock->shouldReceive('get') diff --git a/tests/Security/AuditTest.php b/tests/Security/AuditTest.php index a68b7b00..4127e13f 100644 --- a/tests/Security/AuditTest.php +++ b/tests/Security/AuditTest.php @@ -17,6 +17,14 @@ use Narrowspark\Automatic\Security\Contract\Exception\RuntimeException; use Narrowspark\Automatic\Security\Downloader\ComposerDownloader; use PHPUnit\Framework\TestCase; +use const DIRECTORY_SEPARATOR; +use function array_map; +use function array_merge; +use function count; +use function glob; +use function is_dir; +use function rmdir; +use function unlink; /** * @internal @@ -53,14 +61,14 @@ protected function tearDown(): void parent::tearDown(); $this->delete($this->path); - @\rmdir($this->path); + @rmdir($this->path); } public function testCheckPackageWithSymfony(): void { [$vulnerabilities, $messages] = $this->audit->checkPackage('symfony/symfony', 'v2.5.2', $this->audit->getSecurityAdvisories()); - $this->assertSymfonySecurity(\count($vulnerabilities), $vulnerabilities); + $this->assertSymfonySecurity(count($vulnerabilities), $vulnerabilities); self::assertCount(0, $messages); } @@ -68,28 +76,40 @@ public function testCheckPackageWithSymfonyAndCache(): void { [$vulnerabilities, $messages] = $this->audit->checkPackage('symfony/symfony', 'v2.5.2', $this->audit->getSecurityAdvisories()); - $this->assertSymfonySecurity(\count($vulnerabilities), $vulnerabilities); + $this->assertSymfonySecurity(count($vulnerabilities), $vulnerabilities); self::assertCount(0, $messages); [$vulnerabilities, $messages] = $this->audit->checkPackage('symfony/symfony', 'v2.5.2', $this->audit->getSecurityAdvisories()); - $this->assertSymfonySecurity(\count($vulnerabilities), $vulnerabilities); + $this->assertSymfonySecurity(count($vulnerabilities), $vulnerabilities); } public function testCheckLockWithSymfony252(): void { [$vulnerabilities, $messages] = $this->audit->checkLock( - __DIR__ . \DIRECTORY_SEPARATOR . 'Fixture' . \DIRECTORY_SEPARATOR . 'symfony_2.5.2_composer.lock' + __DIR__ . DIRECTORY_SEPARATOR . 'Fixture' . DIRECTORY_SEPARATOR . 'symfony_2.5.2_composer.lock' ); - $this->assertSymfonySecurity(\count($vulnerabilities), $vulnerabilities); + $this->assertSymfonySecurity(count($vulnerabilities), $vulnerabilities); + self::assertCount(0, $messages); + } + + public function testCheckLockWithSymfony252OnDevPackageWithNoDevMode(): void + { + $this->audit->setDevMode(false); + + [$vulnerabilities, $messages] = $this->audit->checkLock( + __DIR__ . DIRECTORY_SEPARATOR . 'Fixture' . DIRECTORY_SEPARATOR . 'symfony_2.5.2_dev_packages_composer.lock' + ); + + self::assertCount(0, $vulnerabilities); self::assertCount(0, $messages); } public function testCheckLockWithComposer171(): void { [$vulnerabilities, $messages] = $this->audit->checkLock( - __DIR__ . \DIRECTORY_SEPARATOR . 'Fixture' . \DIRECTORY_SEPARATOR . 'composer_1.7.1_composer.lock' + __DIR__ . DIRECTORY_SEPARATOR . 'Fixture' . DIRECTORY_SEPARATOR . 'composer_1.7.1_composer.lock' ); self::assertCount(0, $vulnerabilities); @@ -118,7 +138,7 @@ public function testCheckPackageWithCustomPackage(): void private function assertSymfonySecurity(int $vulnerabilitiesCount, array $vulnerabilities): void { self::assertEquals( - \array_merge([ + array_merge([ 'symfony/symfony' => [ 'version' => 'v2.5.2', 'advisories' => [ @@ -295,14 +315,14 @@ private function assertSymfonySecurity(int $vulnerabilitiesCount, array $vulnera private function delete(string $path): void { - \array_map(function ($value): void { - if (\is_dir($value)) { + array_map(function ($value): void { + if (is_dir($value)) { $this->delete($value); - @\rmdir($value); + @rmdir($value); } else { - @\unlink($value); + @unlink($value); } - }, \glob($path . \DIRECTORY_SEPARATOR . '*')); + }, glob($path . DIRECTORY_SEPARATOR . '*')); } } diff --git a/tests/Security/Command/AuditCommandTest.php b/tests/Security/Command/AuditCommandTest.php index c96489f8..d2130dee 100644 --- a/tests/Security/Command/AuditCommandTest.php +++ b/tests/Security/Command/AuditCommandTest.php @@ -19,6 +19,14 @@ use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Tester\CommandTester; +use const DIRECTORY_SEPARATOR; +use function dirname; +use function putenv; +use function strrpos; +use function strstr; +use function substr; +use function trim; +use function version_compare; /** * @internal @@ -45,7 +53,7 @@ protected function setUp(): void $this->application = new Application(); - $consoleVersion = \version_compare(Versions::getVersion('symfony/console'), '3.0.0', '<'); + $consoleVersion = version_compare(Versions::getVersion('symfony/console'), '3.0.0', '<'); $this->greenString = $consoleVersion ? '' : '[+]'; $this->redString = $consoleVersion ? '' : '[!]'; @@ -53,24 +61,24 @@ protected function setUp(): void public function testAuditCommand(): void { - \putenv('COMPOSER=' . \dirname(__DIR__, 1) . \DIRECTORY_SEPARATOR . 'Fixture' . \DIRECTORY_SEPARATOR . 'composer_1.7.1_composer.lock'); + putenv('COMPOSER=' . dirname(__DIR__, 1) . DIRECTORY_SEPARATOR . 'Fixture' . DIRECTORY_SEPARATOR . 'composer_1.7.1_composer.lock'); $commandTester = $this->executeCommand(new AuditCommand()); - self::assertStringContainsString($this->greenString . ' No known vulnerabilities found', \trim($commandTester->getDisplay(true))); + self::assertStringContainsString($this->greenString . ' No known vulnerabilities found', trim($commandTester->getDisplay(true))); - \putenv('COMPOSER='); - \putenv('COMPOSER'); + putenv('COMPOSER='); + putenv('COMPOSER'); } public function testAuditCommandWithComposerLockOption(): void { $commandTester = $this->executeCommand( new AuditCommand(), - ['--composer-lock' => \dirname(__DIR__, 1) . \DIRECTORY_SEPARATOR . 'Fixture' . \DIRECTORY_SEPARATOR . 'composer_1.7.1_composer.lock'] + ['--composer-lock' => dirname(__DIR__, 1) . DIRECTORY_SEPARATOR . 'Fixture' . DIRECTORY_SEPARATOR . 'composer_1.7.1_composer.lock'] ); - $output = \trim($commandTester->getDisplay(true)); + $output = trim($commandTester->getDisplay(true)); self::assertStringContainsString('=== Audit Security Report ===', $output); self::assertStringContainsString('This checker can only detect vulnerabilities that are referenced', $output); @@ -84,20 +92,20 @@ public function testAuditCommandWithEmptyComposerLockPath(): void ['--composer-lock' => 'composer_1.7.1_composer.lock'] ); - $output = \trim($commandTester->getDisplay(true)); + $output = trim($commandTester->getDisplay(true)); - self::assertStringContainsString(\trim('=== Audit Security Report ==='), $output); - self::assertStringContainsString(\trim('Lock file does not exist.'), $output); + self::assertStringContainsString(trim('=== Audit Security Report ==='), $output); + self::assertStringContainsString(trim('Lock file does not exist.'), $output); } public function testAuditCommandWithError(): void { $commandTester = $this->executeCommand( new AuditCommand(), - ['--composer-lock' => \dirname(__DIR__, 1) . \DIRECTORY_SEPARATOR . 'Fixture' . \DIRECTORY_SEPARATOR . 'symfony_2.5.2_composer.lock'] + ['--composer-lock' => dirname(__DIR__, 1) . DIRECTORY_SEPARATOR . 'Fixture' . DIRECTORY_SEPARATOR . 'symfony_2.5.2_composer.lock'] ); - $output = \trim($commandTester->getDisplay(true)); + $output = trim($commandTester->getDisplay(true)); self::assertStringContainsString('=== Audit Security Report ===', $output); self::assertStringContainsString('This checker can only detect vulnerabilities that are referenced', $output); @@ -111,12 +119,12 @@ public function testAuditCommandWithErrorAndZeroExitCode(): void $commandTester = $this->executeCommand( new AuditCommand(), [ - '--composer-lock' => \dirname(__DIR__, 1) . \DIRECTORY_SEPARATOR . 'Fixture' . \DIRECTORY_SEPARATOR . 'symfony_2.5.2_composer.lock', + '--composer-lock' => dirname(__DIR__, 1) . DIRECTORY_SEPARATOR . 'Fixture' . DIRECTORY_SEPARATOR . 'symfony_2.5.2_composer.lock', '--disable-exit' => null, ] ); - $output = \trim($commandTester->getDisplay(true)); + $output = trim($commandTester->getDisplay(true)); self::assertStringContainsString('=== Audit Security Report ===', $output); self::assertStringContainsString('This checker can only detect vulnerabilities that are referenced', $output); @@ -130,12 +138,12 @@ public function testAuditCommandWithErrorZeroExitCodeAndOneVulnerability(): void $commandTester = $this->executeCommand( new AuditCommand(), [ - '--composer-lock' => \dirname(__DIR__, 1) . \DIRECTORY_SEPARATOR . 'Fixture' . \DIRECTORY_SEPARATOR . 'pygmentize_1.1_composer.lock', + '--composer-lock' => dirname(__DIR__, 1) . DIRECTORY_SEPARATOR . 'Fixture' . DIRECTORY_SEPARATOR . 'pygmentize_1.1_composer.lock', '--disable-exit' => null, ] ); - $output = \trim($commandTester->getDisplay(true)); + $output = trim($commandTester->getDisplay(true)); self::assertStringContainsString('=== Audit Security Report ===', $output); self::assertStringContainsString('This checker can only detect vulnerabilities that are referenced', $output); @@ -149,15 +157,15 @@ public function testAuditCommandWithErrorAndJsonFormat(): void $commandTester = $this->executeCommand( new AuditCommand(), [ - '--composer-lock' => \dirname(__DIR__, 1) . \DIRECTORY_SEPARATOR . 'Fixture' . \DIRECTORY_SEPARATOR . 'symfony_2.5.2_composer.lock', + '--composer-lock' => dirname(__DIR__, 1) . DIRECTORY_SEPARATOR . 'Fixture' . DIRECTORY_SEPARATOR . 'symfony_2.5.2_composer.lock', '--format' => 'json', '--timeout' => '20', ] ); - $output = \trim($commandTester->getDisplay(true)); + $output = trim($commandTester->getDisplay(true)); - self::assertJson(\strstr(\substr($output, 0, \strrpos($output, '}') + 1), '{')); + self::assertJson(strstr(substr($output, 0, strrpos($output, '}') + 1), '{')); self::assertStringContainsString('=== Audit Security Report ===', $output); self::assertStringContainsString('This checker can only detect vulnerabilities that are referenced', $output); self::assertStringContainsString($this->redString . ' 2 vulnerabilities found - We recommend you to check the related security advisories and upgrade these dependencies.', $output); @@ -168,15 +176,15 @@ public function testAuditCommandWithErrorAndSimpleFormat(): void $commandTester = $this->executeCommand( new AuditCommand(), [ - '--composer-lock' => \dirname(__DIR__, 1) . \DIRECTORY_SEPARATOR . 'Fixture' . \DIRECTORY_SEPARATOR . 'symfony_2.5.2_composer.lock', + '--composer-lock' => dirname(__DIR__, 1) . DIRECTORY_SEPARATOR . 'Fixture' . DIRECTORY_SEPARATOR . 'symfony_2.5.2_composer.lock', '--format' => 'simple', ] ); - $output = \trim($commandTester->getDisplay(true)); + $output = trim($commandTester->getDisplay(true)); self::assertStringContainsString('=== Audit Security Report ===', $output); - self::assertStringContainsString(\trim('symfony/symfony (v2.5.2) + self::assertStringContainsString(trim('symfony/symfony (v2.5.2) ------------------------ '), $output); self::assertStringContainsString('This checker can only detect vulnerabilities that are referenced', $output); diff --git a/tests/Security/Fixture/symfony_2.5.2_dev_packages_composer.lock b/tests/Security/Fixture/symfony_2.5.2_dev_packages_composer.lock new file mode 100644 index 00000000..b2c41fc2 --- /dev/null +++ b/tests/Security/Fixture/symfony_2.5.2_dev_packages_composer.lock @@ -0,0 +1,992 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "f4984f8e9643d2860a86d45a862b64a4", + "packages": [], + "packages-dev": [ + { + "name": "doctrine/annotations", + "version": "v1.6.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", + "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", + "shasum": "" + }, + "require": { + "doctrine/lexer": "1.*", + "php": "^7.1" + }, + "require-dev": { + "doctrine/cache": "1.*", + "phpunit/phpunit": "^6.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.6.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Docblock Annotations Parser", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "annotations", + "docblock", + "parser" + ], + "time": "2017-12-06T07:11:42+00:00" + }, + { + "name": "doctrine/cache", + "version": "v1.8.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/cache.git", + "reference": "d768d58baee9a4862ca783840eca1b9add7a7f57" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/cache/zipball/d768d58baee9a4862ca783840eca1b9add7a7f57", + "reference": "d768d58baee9a4862ca783840eca1b9add7a7f57", + "shasum": "" + }, + "require": { + "php": "~7.1" + }, + "conflict": { + "doctrine/common": ">2.2,<2.4" + }, + "require-dev": { + "alcaeus/mongo-php-adapter": "^1.1", + "doctrine/coding-standard": "^4.0", + "mongodb/mongodb": "^1.1", + "phpunit/phpunit": "^7.0", + "predis/predis": "~1.0" + }, + "suggest": { + "alcaeus/mongo-php-adapter": "Required to use legacy MongoDB driver" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.8.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Caching library offering an object-oriented API for many cache backends", + "homepage": "https://www.doctrine-project.org", + "keywords": [ + "cache", + "caching" + ], + "time": "2018-08-21T18:01:43+00:00" + }, + { + "name": "doctrine/collections", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/collections.git", + "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/collections/zipball/a01ee38fcd999f34d9bfbcee59dbda5105449cbf", + "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "~0.1@dev", + "phpunit/phpunit": "^5.7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\Common\\Collections\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Collections Abstraction library", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "array", + "collections", + "iterator" + ], + "time": "2017-07-22T10:37:32+00:00" + }, + { + "name": "doctrine/common", + "version": "v2.9.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/common.git", + "reference": "a210246d286c77d2b89040f8691ba7b3a713d2c1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/common/zipball/a210246d286c77d2b89040f8691ba7b3a713d2c1", + "reference": "a210246d286c77d2b89040f8691ba7b3a713d2c1", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "doctrine/cache": "^1.0", + "doctrine/collections": "^1.0", + "doctrine/event-manager": "^1.0", + "doctrine/inflector": "^1.0", + "doctrine/lexer": "^1.0", + "doctrine/persistence": "^1.0", + "doctrine/reflection": "^1.0", + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^1.0", + "phpunit/phpunit": "^6.3", + "squizlabs/php_codesniffer": "^3.0", + "symfony/phpunit-bridge": "^4.0.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.9.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Common Library for Doctrine projects", + "homepage": "https://www.doctrine-project.org", + "keywords": [ + "annotations", + "collections", + "eventmanager", + "persistence", + "spl" + ], + "time": "2018-07-12T21:16:12+00:00" + }, + { + "name": "doctrine/event-manager", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/event-manager.git", + "reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/a520bc093a0170feeb6b14e9d83f3a14452e64b3", + "reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "conflict": { + "doctrine/common": "<2.9@dev" + }, + "require-dev": { + "doctrine/coding-standard": "^4.0", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Doctrine Event Manager component", + "homepage": "https://www.doctrine-project.org/projects/event-manager.html", + "keywords": [ + "event", + "eventdispatcher", + "eventmanager" + ], + "time": "2018-06-11T11:59:03+00:00" + }, + { + "name": "doctrine/inflector", + "version": "v1.3.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/inflector.git", + "reference": "5527a48b7313d15261292c149e55e26eae771b0a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/inflector/zipball/5527a48b7313d15261292c149e55e26eae771b0a", + "reference": "5527a48b7313d15261292c149e55e26eae771b0a", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "require-dev": { + "phpunit/phpunit": "^6.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\Inflector\\": "lib/Doctrine/Common/Inflector" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Common String Manipulations with regard to casing and singular/plural rules.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "inflection", + "pluralize", + "singularize", + "string" + ], + "time": "2018-01-09T20:05:19+00:00" + }, + { + "name": "doctrine/lexer", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", + "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-0": { + "Doctrine\\Common\\Lexer\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "http://www.doctrine-project.org", + "keywords": [ + "lexer", + "parser" + ], + "time": "2014-09-09T13:34:57+00:00" + }, + { + "name": "doctrine/persistence", + "version": "v1.0.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/persistence.git", + "reference": "af1ec238659a83e320f03e0e454e200f689b4b97" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/persistence/zipball/af1ec238659a83e320f03e0e454e200f689b4b97", + "reference": "af1ec238659a83e320f03e0e454e200f689b4b97", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "doctrine/cache": "^1.0", + "doctrine/collections": "^1.0", + "doctrine/event-manager": "^1.0", + "doctrine/reflection": "^1.0", + "php": "^7.1" + }, + "conflict": { + "doctrine/common": "<2.9@dev" + }, + "require-dev": { + "doctrine/coding-standard": "^4.0", + "phpstan/phpstan": "^0.8", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Doctrine Persistence abstractions.", + "homepage": "https://doctrine-project.org/projects/persistence.html", + "keywords": [ + "persistence" + ], + "time": "2018-07-12T12:37:50+00:00" + }, + { + "name": "doctrine/reflection", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/reflection.git", + "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/reflection/zipball/02538d3f95e88eb397a5f86274deb2c6175c2ab6", + "reference": "02538d3f95e88eb397a5f86274deb2c6175c2ab6", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.0", + "ext-tokenizer": "*", + "php": "^7.1" + }, + "require-dev": { + "doctrine/coding-standard": "^4.0", + "doctrine/common": "^2.8", + "phpstan/phpstan": "^0.9.2", + "phpstan/phpstan-phpunit": "^0.9.4", + "phpunit/phpunit": "^7.0", + "squizlabs/php_codesniffer": "^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Doctrine Reflection component", + "homepage": "https://www.doctrine-project.org/projects/reflection.html", + "keywords": [ + "reflection" + ], + "time": "2018-06-14T14:45:07+00:00" + }, + { + "name": "psr/log", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2016-10-10T12:19:37+00:00" + }, + { + "name": "symfony/icu", + "version": "v1.0.1", + "target-dir": "Symfony/Component/Icu", + "source": { + "type": "git", + "url": "https://github.com/symfony/icu.git", + "reference": "fdba214b1e087c149843bde976263c53ac10c975" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/icu/zipball/fdba214b1e087c149843bde976263c53ac10c975", + "reference": "fdba214b1e087c149843bde976263c53ac10c975", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/intl": "~2.3" + }, + "type": "library", + "autoload": { + "psr-0": { + "Symfony\\Component\\Icu\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Contains an excerpt of the ICU data and classes to load it.", + "homepage": "http://symfony.com", + "keywords": [ + "icu", + "intl" + ], + "abandoned": "symfony/intl", + "time": "2013-10-04T09:12:07+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.9.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "e3d826245268269cd66f8326bd8bc066687b4a19" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e3d826245268269cd66f8326bd8bc066687b4a19", + "reference": "e3d826245268269cd66f8326bd8bc066687b4a19", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.9-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + }, + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2018-08-06T14:22:27+00:00" + }, + { + "name": "symfony/symfony", + "version": "v2.5.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/symfony.git", + "reference": "e66ee967571b89234c90946fe0d50dad195ad29c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/symfony/zipball/e66ee967571b89234c90946fe0d50dad195ad29c", + "reference": "e66ee967571b89234c90946fe0d50dad195ad29c", + "shasum": "" + }, + "require": { + "doctrine/common": "~2.2", + "php": ">=5.3.3", + "psr/log": "~1.0", + "symfony/icu": "~1.0", + "twig/twig": "~1.12" + }, + "replace": { + "symfony/browser-kit": "self.version", + "symfony/class-loader": "self.version", + "symfony/config": "self.version", + "symfony/console": "self.version", + "symfony/css-selector": "self.version", + "symfony/debug": "self.version", + "symfony/dependency-injection": "self.version", + "symfony/doctrine-bridge": "self.version", + "symfony/dom-crawler": "self.version", + "symfony/event-dispatcher": "self.version", + "symfony/expression-language": "self.version", + "symfony/filesystem": "self.version", + "symfony/finder": "self.version", + "symfony/form": "self.version", + "symfony/framework-bundle": "self.version", + "symfony/http-foundation": "self.version", + "symfony/http-kernel": "self.version", + "symfony/intl": "self.version", + "symfony/locale": "self.version", + "symfony/monolog-bridge": "self.version", + "symfony/options-resolver": "self.version", + "symfony/process": "self.version", + "symfony/propel1-bridge": "self.version", + "symfony/property-access": "self.version", + "symfony/proxy-manager-bridge": "self.version", + "symfony/routing": "self.version", + "symfony/security": "self.version", + "symfony/security-acl": "self.version", + "symfony/security-bundle": "self.version", + "symfony/security-core": "self.version", + "symfony/security-csrf": "self.version", + "symfony/security-http": "self.version", + "symfony/serializer": "self.version", + "symfony/stopwatch": "self.version", + "symfony/swiftmailer-bridge": "self.version", + "symfony/templating": "self.version", + "symfony/translation": "self.version", + "symfony/twig-bridge": "self.version", + "symfony/twig-bundle": "self.version", + "symfony/validator": "self.version", + "symfony/web-profiler-bundle": "self.version", + "symfony/yaml": "self.version" + }, + "require-dev": { + "doctrine/data-fixtures": "1.0.*", + "doctrine/dbal": "~2.2", + "doctrine/orm": "~2.2,>=2.2.3", + "egulias/email-validator": "1.1.0", + "ircmaxell/password-compat": "1.0.*", + "monolog/monolog": "~1.3", + "ocramius/proxy-manager": ">=0.3.1,<0.6-dev", + "propel/propel1": "1.6.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev" + } + }, + "autoload": { + "psr-0": { + "Symfony\\": "src/" + }, + "classmap": [ + "src/Symfony/Component/HttpFoundation/Resources/stubs", + "src/Symfony/Component/Intl/Resources/stubs" + ], + "files": [ + "src/Symfony/Component/Intl/Resources/stubs/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Symfony Community", + "homepage": "http://symfony.com/contributors" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "The Symfony PHP framework", + "homepage": "http://symfony.com", + "keywords": [ + "framework" + ], + "time": "2014-07-15T15:39:46+00:00" + }, + { + "name": "twig/twig", + "version": "v1.35.4", + "source": { + "type": "git", + "url": "https://github.com/twigphp/Twig.git", + "reference": "7e081e98378a1e78c29cc9eba4aefa5d78a05d2a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/7e081e98378a1e78c29cc9eba4aefa5d78a05d2a", + "reference": "7e081e98378a1e78c29cc9eba4aefa5d78a05d2a", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/polyfill-ctype": "^1.8" + }, + "require-dev": { + "psr/container": "^1.0", + "symfony/debug": "^2.7", + "symfony/phpunit-bridge": "^3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.35-dev" + } + }, + "autoload": { + "psr-0": { + "Twig_": "lib/" + }, + "psr-4": { + "Twig\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + }, + { + "name": "Twig Team", + "homepage": "https://twig.symfony.com/contributors", + "role": "Contributors" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "https://twig.symfony.com", + "keywords": [ + "templating" + ], + "time": "2018-07-13T07:12:17+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} diff --git a/tests/Security/PluginTest.php b/tests/Security/PluginTest.php index 52a28f09..2bfac9a1 100644 --- a/tests/Security/PluginTest.php +++ b/tests/Security/PluginTest.php @@ -21,6 +21,7 @@ use Composer\Package\PackageInterface; use Composer\Plugin\Capability\CommandProvider as CommandProviderContract; use Composer\Script\Event; +use Narrowspark\Automatic\Common\Contract\Container as ContainerContract; use Narrowspark\Automatic\Security\Audit; use Narrowspark\Automatic\Security\CommandProvider; use Narrowspark\Automatic\Security\Downloader\ComposerDownloader; @@ -28,7 +29,10 @@ use Narrowspark\Automatic\Test\Traits\ArrangeComposerClasses; use Narrowspark\TestingHelper\Phpunit\MockeryTestCase; use Nyholm\NSA; +use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Filesystem\Filesystem; +use const DIRECTORY_SEPARATOR; +use function putenv; /** * @internal @@ -52,8 +56,13 @@ protected function setUp(): void { $this->arrangeComposerClasses(); - $this->securityPlugin = new Plugin(); - $this->tmpFolder = __DIR__ . \DIRECTORY_SEPARATOR . 'tmp'; + $this->securityPlugin = new class() extends Plugin { + public function setContainer($container): void + { + $this->container = $container; + } + }; + $this->tmpFolder = __DIR__ . DIRECTORY_SEPARATOR . 'tmp'; } /** @@ -63,7 +72,7 @@ protected function tearDown(): void { parent::tearDown(); - (new Filesystem())->remove([$this->tmpFolder, __DIR__ . \DIRECTORY_SEPARATOR . 'narrowspark']); + (new Filesystem())->remove([$this->tmpFolder, __DIR__ . DIRECTORY_SEPARATOR . 'narrowspark']); } public function testActivate(): void @@ -72,6 +81,18 @@ public function testActivate(): void ->once() ->andReturn([Plugin::COMPOSER_EXTRA_KEY => ['timeout' => 20]]); + $name = 'no-dev'; + + $inputMock = $this->mock(InputInterface::class); + $inputMock->shouldReceive('hasOption') + ->with($name) + ->andReturn(true); + $inputMock->shouldReceive('getOption') + ->with($name) + ->andReturn(true); + + $this->ioMock->input = $inputMock; + $this->configMock->shouldReceive('get') ->once() ->with('vendor-dir') @@ -113,7 +134,12 @@ public function testOnPostUpdatePostMessages(): void ->once() ->with('[+] Audit Security Report: No known vulnerabilities found'); - NSA::setProperty($this->securityPlugin, 'io', $this->ioMock); + $containerMock = $this->mock(ContainerContract::class); + $containerMock->shouldReceive('get') + ->with(IOInterface::class) + ->andReturn($this->ioMock); + + $this->securityPlugin->setContainer($containerMock); $this->securityPlugin->onPostUpdatePostMessages($eventMock); } @@ -128,7 +154,13 @@ public function testOnPostUpdatePostMessagesWithVulnerability(): void ->once() ->with('[!] Audit Security Report: 1 vulnerability found - run "composer audit" for more information'); - NSA::setProperty($this->securityPlugin, 'io', $this->ioMock); + + $containerMock = $this->mock(ContainerContract::class); + $containerMock->shouldReceive('get') + ->with(IOInterface::class) + ->andReturn($this->ioMock); + + $this->securityPlugin->setContainer($containerMock); $this->securityPlugin->onPostUpdatePostMessages($eventMock); } @@ -154,11 +186,17 @@ public function testAuditPackage(): void ->andReturn($operationMock); $downloader = new ComposerDownloader(); - $audit = new Audit($this->tmpFolder, $downloader, $downloader->download(Audit::SECURITY_ADVISORIES_BASE_URL . Audit::SECURITY_ADVISORIES_SHA)); - NSA::setProperty($this->securityPlugin, 'audit', $audit); - NSA::setProperty($this->securityPlugin, 'securityAdvisories', $audit->getSecurityAdvisories()); + $containerMock = $this->mock(ContainerContract::class); + $containerMock->shouldReceive('get') + ->with(Audit::class) + ->andReturn($audit); + $containerMock->shouldReceive('get') + ->with('security_advisories') + ->andReturn($audit->getSecurityAdvisories()); + + $this->securityPlugin->setContainer($containerMock); $this->securityPlugin->auditPackage($eventMock); @@ -168,6 +206,9 @@ public function testAuditPackage(): void public function testAuditPackageWithUninstall(): void { $operationMock = $this->mock(UninstallOperation::class); + $operationMock->shouldReceive('getPackage->getPrettyName') + ->once() + ->andReturn(Plugin::PACKAGE_NAME); $eventMock = $this->mock(PackageEvent::class); $eventMock->shouldReceive('getOperation') @@ -203,8 +244,15 @@ public function testAuditPackageWithUpdate(): void $audit = new Audit($this->tmpFolder, $downloader, $downloader->download(Audit::SECURITY_ADVISORIES_BASE_URL . Audit::SECURITY_ADVISORIES_SHA)); - NSA::setProperty($this->securityPlugin, 'audit', $audit); - NSA::setProperty($this->securityPlugin, 'securityAdvisories', $audit->getSecurityAdvisories()); + $containerMock = $this->mock(ContainerContract::class); + $containerMock->shouldReceive('get') + ->with(Audit::class) + ->andReturn($audit); + $containerMock->shouldReceive('get') + ->with('security_advisories') + ->andReturn($audit->getSecurityAdvisories()); + + $this->securityPlugin->setContainer($containerMock); $this->securityPlugin->auditPackage($eventMock); @@ -213,20 +261,23 @@ public function testAuditPackageWithUpdate(): void public function testAuditComposerLock(): void { - \putenv('COMPOSER=' . __DIR__ . \DIRECTORY_SEPARATOR . 'Fixture' . \DIRECTORY_SEPARATOR . 'symfony_2.5.2_composer.json'); + putenv('COMPOSER=' . __DIR__ . DIRECTORY_SEPARATOR . 'Fixture' . DIRECTORY_SEPARATOR . 'symfony_2.5.2_composer.json'); $downloader = new ComposerDownloader(); - $audit = new Audit($this->tmpFolder, $downloader, $downloader->download(Audit::SECURITY_ADVISORIES_BASE_URL . Audit::SECURITY_ADVISORIES_SHA)); + $containerMock = $this->mock(ContainerContract::class); + $containerMock->shouldReceive('get') + ->with(Audit::class) + ->andReturn(new Audit($this->tmpFolder, $downloader, $downloader->download(Audit::SECURITY_ADVISORIES_BASE_URL . Audit::SECURITY_ADVISORIES_SHA))); - NSA::setProperty($this->securityPlugin, 'audit', $audit); + $this->securityPlugin->setContainer($containerMock); $this->securityPlugin->auditComposerLock($this->mock(Event::class)); self::assertCount(2, NSA::getProperty($this->securityPlugin, 'foundVulnerabilities')); - \putenv('COMPOSER='); - \putenv('COMPOSER'); + putenv('COMPOSER='); + putenv('COMPOSER'); } /** diff --git a/tests/Security/UtilTest.php b/tests/Security/UtilTest.php deleted file mode 100644 index 043813e9..00000000 --- a/tests/Security/UtilTest.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Narrowspark\Automatic\Security\Test; - -use Narrowspark\Automatic\Security\Util; -use PHPUnit\Framework\TestCase; - -/** - * @internal - * - * @small - */ -final class UtilTest extends TestCase -{ - public function testGetComposerLockFile(): void - { - self::assertSame('./composer.lock', Util::getComposerLockFile()); - } -}