diff --git a/.travis.yml b/.travis.yml
index 11b1d0c0..fb92dd12 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -28,6 +28,7 @@ install:
if [[ "$SETUP" = "high" ]]; then
$COMPOSER_UP
elif [[ "$SETUP" = "lowest" ]]; then
+ composer self-update 1.6.5
$COMPOSER_UP --prefer-lowest --prefer-stable;
else
$COMPOSER_UP
diff --git a/src/Automatic/Automatic.php b/src/Automatic/Automatic.php
index 6e25908f..7a94d117 100644
--- a/src/Automatic/Automatic.php
+++ b/src/Automatic/Automatic.php
@@ -5,20 +5,24 @@
use Closure;
use Composer\Composer;
use Composer\Config;
+use Composer\Console\Application;
use Composer\DependencyResolver\Operation\InstallOperation;
use Composer\DependencyResolver\Operation\UninstallOperation;
use Composer\DependencyResolver\Operation\UpdateOperation;
use Composer\DependencyResolver\Pool;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\Factory;
+use Composer\Installer;
use Composer\Installer\InstallerEvent;
use Composer\Installer\InstallerEvents;
use Composer\Installer\PackageEvent;
use Composer\Installer\PackageEvents;
+use Composer\Installer\SuggestedPackagesReporter;
use Composer\IO\IOInterface;
+use Composer\IO\NullIO;
use Composer\Json\JsonFile;
+use Composer\Package\Comparer\Comparer;
use Composer\Package\Locker;
-use Composer\Plugin\CommandEvent;
use Composer\Plugin\PluginEvents;
use Composer\Plugin\PluginInterface;
use Composer\Plugin\PreFileDownloadEvent;
@@ -30,6 +34,7 @@
use Composer\Script\ScriptEvents;
use FilesystemIterator;
use Narrowspark\Automatic\Common\Contract\Exception\InvalidArgumentException;
+use Narrowspark\Automatic\Common\Contract\Exception\RuntimeException;
use Narrowspark\Automatic\Common\Contract\Package as PackageContract;
use Narrowspark\Automatic\Common\Contract\ScriptExtender as ScriptExtenderContract;
use Narrowspark\Automatic\Common\Traits\ExpandTargetDirTrait;
@@ -44,6 +49,7 @@
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use ReflectionClass;
+use Symfony\Component\Console\Input\ArgvInput;
class Automatic implements PluginInterface, EventSubscriberInterface
{
@@ -118,7 +124,6 @@ public static function getSubscribedEvents(): array
PackageEvents::POST_PACKAGE_UPDATE => 'record',
PackageEvents::POST_PACKAGE_UNINSTALL => 'record',
PluginEvents::PRE_FILE_DOWNLOAD => 'onFileDownload',
- PluginEvents::COMMAND => 'onCommand',
ScriptEvents::POST_INSTALL_CMD => 'onPostInstall',
ScriptEvents::POST_UPDATE_CMD => 'onPostUpdate',
ScriptEvents::POST_CREATE_PROJECT_CMD => [['onPostCreateProject', \PHP_INT_MAX]],
@@ -182,6 +187,54 @@ public function activate(Composer $composer, IOInterface $io): void
'This file locks the automatic information of your project to a known state',
'This file is @generated automatically',
]);
+
+ $backtrace = \debug_backtrace();
+
+ foreach ($backtrace as $trace) {
+ if (isset($trace['object']) && $trace['object'] instanceof Installer) {
+ /** @var \Composer\Installer $installer */
+ $installer = $trace['object'];
+ $installer->setSuggestedPackagesReporter(new SuggestedPackagesReporter(new NullIO()));
+
+ break;
+ }
+ }
+
+ foreach ($backtrace as $trace) {
+ if (! isset($trace['object']) || ! isset($trace['args'][0])) {
+ continue;
+ }
+
+ if (! $trace['object'] instanceof Application || ! $trace['args'][0] instanceof ArgvInput) {
+ continue;
+ }
+
+ /** @var \Symfony\Component\Console\Input\InputInterface $input */
+ $input = $trace['args'][0];
+ $app = $trace['object'];
+
+ try {
+ /** @var null|string $command */
+ $command = $input->getFirstArgument();
+ $command = $command ? $app->find($command)->getName() : null;
+ } catch (\InvalidArgumentException $e) {
+ $command = null;
+ }
+
+ if ($command === 'create-project') {
+ if (\version_compare(self::getComposerVersion(), '1.7.0', '>=')) {
+ $input->setOption('remove-vcs', true);
+ } else {
+ $input->setInteractive(false);
+ }
+ } elseif ($command === 'suggests') {
+ $input->setOption('by-package', true);
+ }
+
+ if ($input->hasOption('no-suggest')) {
+ $input->setOption('no-suggest', true);
+ }
+ }
}
/**
@@ -230,24 +283,6 @@ public function record(PackageEvent $event): void
}
}
- /**
- * Execute on composer command event.
- *
- * @param \Composer\Plugin\CommandEvent $event
- *
- * @return void
- */
- public function onCommand(CommandEvent $event): void
- {
- if ($event->getInput()->hasOption('no-suggest')) {
- $event->getInput()->setOption('no-suggest', true);
- }
-
- if ($event->getInput()->hasOption('remove-vcs')) {
- $event->getInput()->setOption('remove-vcs', true);
- }
- }
-
/**
* Execute on composer create project event.
*
@@ -338,7 +373,7 @@ public function onPostUpdate(Event $event, array $operations = []): void
foreach ((array) $lock->get(ConfiguratorInstaller::LOCK_KEY) as $packageName => $classList) {
foreach ($configuratorsClassmap[$packageName] as $path) {
- includeFile(\str_replace('%vendor_path%', $this->container->get('vendor-dir'), $path));
+ include \str_replace('%vendor_path%', $this->container->get('vendor-dir'), $path);
}
/** @var \Narrowspark\Automatic\Common\Configurator\AbstractConfigurator $class */
@@ -393,7 +428,8 @@ public function onPostUpdate(Event $event, array $operations = []): void
'',
'Some files may have been created or updated to configure your new packages.',
'The automatic.lock file has all information about the installed packages.',
- 'Please review, edit and commit them: these files are yours.'
+ 'Please review, edit and commit them: these files are yours.',
+ "\nTo show the package suggests run composer suggests."
);
}
@@ -804,9 +840,7 @@ private function getErrorMessage(IOInterface $io): ?string
return 'You must enable the openssl extension in your "php.ini" file.';
}
- \preg_match('/\d+.\d+.\d+/m', Composer::VERSION, $matches);
-
- if ($matches !== null && \version_compare($matches[0], '1.6.0') === -1) {
+ if (\version_compare(self::getComposerVersion(), '1.6.0', '<')) {
return \sprintf('Your version "%s" of Composer is too old; Please upgrade.', Composer::VERSION);
}
// @codeCoverageIgnoreEnd
@@ -818,16 +852,28 @@ private function getErrorMessage(IOInterface $io): ?string
return null;
}
-}
-/**
- * Scope isolated include.
- *
- * Prevents access to $this/self from included files.
- *
- * @param mixed $file
- */
-function includeFile($file)
-{
- include $file;
+ /**
+ * 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/tests/Automatic/AutomaticTest.php b/tests/Automatic/AutomaticTest.php
index 6215b22c..4f8abbf8 100644
--- a/tests/Automatic/AutomaticTest.php
+++ b/tests/Automatic/AutomaticTest.php
@@ -15,7 +15,6 @@
use Composer\IO\IOInterface;
use Composer\IO\NullIO;
use Composer\Package\Package;
-use Composer\Plugin\CommandEvent;
use Composer\Plugin\PreFileDownloadEvent;
use Composer\Repository\RepositoryManager;
use Composer\Repository\WritableRepositoryInterface;
@@ -80,7 +79,7 @@ protected function tearDown(): void
public function testGetSubscribedEvents(): void
{
- static::assertCount(14, Automatic::getSubscribedEvents());
+ static::assertCount(13, Automatic::getSubscribedEvents());
}
public function testActivate(): void
@@ -155,27 +154,6 @@ public function testActivateWithNoInteractive(): void
$this->automatic->activate($this->composerMock, $this->ioMock);
}
- public function testOnCommand(): void
- {
- $commandEventMock = $this->mock(CommandEvent::class);
- $commandEventMock->shouldReceive('getInput->hasOption')
- ->once()
- ->with('no-suggest')
- ->andReturn(true);
- $commandEventMock->shouldReceive('getInput->setOption')
- ->once()
- ->with('no-suggest', true);
- $commandEventMock->shouldReceive('getInput->hasOption')
- ->once()
- ->with('remove-vcs')
- ->andReturn(true);
- $commandEventMock->shouldReceive('getInput->setOption')
- ->once()
- ->with('remove-vcs', true);
-
- $this->automatic->onCommand($commandEventMock);
- }
-
public function testRecordWithUpdateRecord(): void
{
$packageEventMock = $this->mock(PackageEvent::class);