diff --git a/composer.json b/composer.json index b08ff80..4849d52 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,8 @@ "require": { "php": ">=5.4.5", "composer-plugin-api": "^1.0.0", - "composer/semver": "^1.4" + "composer/semver": "^1.4", + "guzzlehttp/guzzle": "^6.2.1" }, "autoload": { "psr-4": { diff --git a/src/DrupalScaffoldCommand.php b/src/DrupalScaffoldCommand.php index 485a2f5..1734fac 100644 --- a/src/DrupalScaffoldCommand.php +++ b/src/DrupalScaffoldCommand.php @@ -27,6 +27,9 @@ protected function configure() { * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { + $vendorDir = $this->getComposer()->getConfig()->get('vendor-dir'); + require $vendorDir . '/autoload.php'; + $handler = new Handler($this->getComposer(), $this->getIO()); $handler->downloadScaffold(); // Generate the autoload.php file after generating the scaffold files. diff --git a/src/GuzzleFileFetcher.php b/src/GuzzleFileFetcher.php new file mode 100644 index 0000000..e71d68a --- /dev/null +++ b/src/GuzzleFileFetcher.php @@ -0,0 +1,68 @@ +config = $config; + } + + /** + * {@inheritdoc} + */ + public function fetch($version, $destination, $override) { + $client = new Client(); + $requests = []; + $metadata = []; + + foreach ($this->filenames as $sourceFilename => $filename) { + $target = "$destination/$filename"; + if ($override || !file_exists($target)) { + $url = $this->getUri($sourceFilename, $version); + $this->fs->ensureDirectoryExists($destination . '/' . dirname($filename)); + $requests[] = new Request('GET', $url); + $metadata[] = [ + 'url' => $url, + 'target' => $target, + 'filename' => $filename, + ]; + } + } + + $pool = new Pool($client, $requests, [ + 'concurrency' => 5, + 'fulfilled' => function ($response, $index) use ($metadata) { + $this->io->writeError(" - {$metadata[$index]['filename']} ({$metadata[$index]['url']}): ", TRUE); + file_put_contents($metadata[$index]['target'], (string) $response->getBody()); + }, + 'rejected' => function ($reason, $index) { + throw $reason; + }, + ]); + + $promise = $pool->promise(); + $promise->wait(); + } +} diff --git a/src/Handler.php b/src/Handler.php index 1bdefe0..dcf9bd9 100644 --- a/src/Handler.php +++ b/src/Handler.php @@ -14,6 +14,7 @@ use Composer\Semver\Semver; use Composer\Util\Filesystem; use Composer\Util\RemoteFilesystem; +use GuzzleHttp\ClientInterface; use Symfony\Component\Filesystem\Filesystem as SymfonyFilesystem; /** @@ -69,6 +70,7 @@ protected function manualLoad() { 'CommandProvider', 'DrupalScaffoldCommand', 'FileFetcher', + 'GuzzleFileFetcher', 'PrestissimoFileFetcher', ]; @@ -157,8 +159,9 @@ public function downloadScaffold() { $version = $this->getDrupalCoreVersion($drupalCorePackage); $remoteFs = new RemoteFilesystem($this->io); + $fetcherClass = $this->getFetcherClass(); - $fetcher = new PrestissimoFileFetcher($remoteFs, $options['source'], $this->io, $this->progress, $this->composer->getConfig()); + $fetcher = new $fetcherClass($remoteFs, $options['source'], $this->io, $this->progress, $this->composer->getConfig()); $fetcher->setFilenames(array_combine($files, $files)); $fetcher->fetch($version, $webroot, TRUE); @@ -408,4 +411,11 @@ protected function getInitialDefault() { return []; } + protected function getFetcherClass() { + if (interface_exists("\\GuzzleHttp\\ClientInterface") && Semver::satisfies(ClientInterface::VERSION, '^6')) { + return GuzzleFileFetcher::class; + } + return FileFetcher::class; + } + } diff --git a/src/Plugin.php b/src/Plugin.php index 7833903..28e8a7e 100644 --- a/src/Plugin.php +++ b/src/Plugin.php @@ -51,7 +51,7 @@ public static function getSubscribedEvents() { return array( PackageEvents::POST_PACKAGE_INSTALL => 'postPackage', PackageEvents::POST_PACKAGE_UPDATE => 'postPackage', - ScriptEvents::POST_UPDATE_CMD => 'postCmd', + ScriptEvents::POST_AUTOLOAD_DUMP => 'postCmd', PluginEvents::COMMAND => 'cmdBegins', ); } diff --git a/src/PrestissimoFileFetcher.php b/src/PrestissimoFileFetcher.php index a1f8e70..2d088bc 100644 --- a/src/PrestissimoFileFetcher.php +++ b/src/PrestissimoFileFetcher.php @@ -11,68 +11,9 @@ /** * Extends the default FileFetcher and uses hirak/prestissimo for parallel * downloads. + * + * @deprecated Use the GuzzleFileFetcher instead. */ class PrestissimoFileFetcher extends FileFetcher { - /** - * @var \Composer\Config - */ - protected $config; - - /** - * Constructs this PrestissimoFileFetcher object. - */ - public function __construct(RemoteFilesystem $remoteFilesystem, $source, IOInterface $io, $progress = TRUE, Config $config) { - parent::__construct($remoteFilesystem, $source, $io, $progress); - $this->config = $config; - } - - /** - * {@inheritdoc} - */ - public function fetch($version, $destination, $override) { - if (class_exists(CurlMulti::class)) { - $this->fetchWithPrestissimo($version, $destination, $override); - return; - } - parent::fetch($version, $destination, $override); - } - - /** - * Fetch files in parallel. - */ - protected function fetchWithPrestissimo($version, $destination, $override) { - $requests = []; - - foreach ($this->filenames as $sourceFilename => $filename) { - $target = "$destination/$filename"; - if ($override || !file_exists($target)) { - $url = $this->getUri($sourceFilename, $version); - $this->fs->ensureDirectoryExists($destination . '/' . dirname($filename)); - $requests[] = new CopyRequest($url, $target, FALSE, $this->io, $this->config); - } - } - - $successCnt = $failureCnt = 0; - $totalCnt = count($requests); - if ($totalCnt == 0) { - return; - } - - $multi = new CurlMulti(); - $multi->setRequests($requests); - do { - $multi->setupEventLoop(); - $multi->wait(); - $result = $multi->getFinishedResults(); - $successCnt += $result['successCnt']; - $failureCnt += $result['failureCnt']; - if ($this->progress) { - foreach ($result['urls'] as $url) { - $this->io->writeError(" - Downloading $successCnt/$totalCnt: $url", TRUE); - } - } - } while ($multi->remain()); - } - }