diff --git a/composer.json b/composer.json index 1fcc351..8706c82 100644 --- a/composer.json +++ b/composer.json @@ -11,10 +11,7 @@ ], "require": { "php": "^7.2.9", - "ext-zip": "*", - "guzzlehttp/guzzle": "^6.0|^7.0", "symfony/console": "^4.0|^5.0", - "symfony/filesystem": "^4.0|^5.0", "symfony/process": "^4.2|^5.0" }, "require-dev": { diff --git a/src/NewCommand.php b/src/NewCommand.php index cf7f54b..efc09a9 100644 --- a/src/NewCommand.php +++ b/src/NewCommand.php @@ -2,17 +2,13 @@ namespace Laravel\Installer\Console; -use GuzzleHttp\Client; use RuntimeException; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Filesystem\Exception\IOExceptionInterface; -use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Process\Process; -use ZipArchive; class NewCommand extends Command { @@ -28,7 +24,6 @@ protected function configure() ->setDescription('Create a new Laravel application') ->addArgument('name', InputArgument::OPTIONAL) ->addOption('dev', null, InputOption::VALUE_NONE, 'Installs the latest "development" release') - ->addOption('auth', null, InputOption::VALUE_NONE, 'Installs the Laravel authentication scaffolding') ->addOption('force', 'f', InputOption::VALUE_NONE, 'Forces install even if the directory already exists'); } @@ -45,61 +40,28 @@ protected function execute(InputInterface $input, OutputInterface $output) throw new RuntimeException('The Laravel installer requires PHP 7.3.0 or greater. Please use "composer create-project laravel/laravel" instead.'); } - if (! extension_loaded('zip')) { - throw new RuntimeException('The Zip PHP extension is not installed. Please install it and try again.'); - } - $name = $input->getArgument('name'); - $directory = $name && $name !== '.' ? getcwd().'/'.$name : getcwd(); + $directory = $name && $name !== '.' ? getcwd().'/'.$name : '.'; + + $version = $this->getVersion($input); if (! $input->getOption('force')) { $this->verifyApplicationDoesntExist($directory); } - $output->writeln('Crafting application...'); - - $this->download($zipFile = $this->makeFilename(), $this->getVersion($input)) - ->extract($zipFile, $directory) - ->prepareWritableDirectories($directory, $output) - ->cleanUp($zipFile); - $composer = $this->findComposer(); $commands = [ - $composer.' install --no-scripts', - $composer.' run-script post-root-package-install', - $composer.' run-script post-create-project-cmd', - $composer.' run-script post-autoload-dump', + $composer." create-project laravel/laravel $directory $version --remove-vcs --prefer-dist", + "chmod 644 $directory/artisan", ]; - if ($input->getOption('no-ansi')) { - $commands = array_map(function ($value) { - return $value.' --no-ansi'; - }, $commands); + if ($directory != '.') { + array_unshift($commands, "rm -rf $directory"); } - if ($input->getOption('quiet')) { - $commands = array_map(function ($value) { - return $value.' --quiet'; - }, $commands); - } - - $process = Process::fromShellCommandline(implode(' && ', $commands), $directory, null, null, null); - - if ('\\' !== DIRECTORY_SEPARATOR && file_exists('/dev/tty') && is_readable('/dev/tty')) { - try { - $process->setTty(true); - } catch (RuntimeException $e) { - $output->writeln('Warning: '.$e->getMessage()); - } - } - - $process->run(function ($type, $line) use ($output) { - $output->write($line); - }); - - if ($process->isSuccessful()) { + if ($this->runCommands($commands, $input, $output)->isSuccessful()) { $output->writeln('Application ready! Build something amazing.'); } @@ -120,135 +82,72 @@ protected function verifyApplicationDoesntExist($directory) } /** - * Generate a random temporary filename. + * Get the version that should be downloaded. * + * @param \Symfony\Component\Console\Input\InputInterface $input * @return string */ - protected function makeFilename() - { - return getcwd().'/laravel_'.md5(time().uniqid()).'.zip'; - } - - /** - * Download the temporary Zip to the given file. - * - * @param string $zipFile - * @param string $version - * @return $this - */ - protected function download($zipFile, $version = 'master') - { - switch ($version) { - case 'develop': - $filename = 'latest-develop.zip'; - break; - case 'auth': - $filename = 'latest-auth.zip'; - break; - case 'master': - $filename = 'latest.zip'; - break; - } - - $response = (new Client)->get('http://cabinet.laravel.com/'.$filename); - - file_put_contents($zipFile, $response->getBody()); - - return $this; - } - - /** - * Extract the Zip file into the given directory. - * - * @param string $zipFile - * @param string $directory - * @return $this - */ - protected function extract($zipFile, $directory) + protected function getVersion(InputInterface $input) { - $archive = new ZipArchive; - - $response = $archive->open($zipFile, ZipArchive::CHECKCONS); - - if ($response === ZipArchive::ER_NOZIP) { - throw new RuntimeException('The zip file could not download. Verify that you are able to access: http://cabinet.laravel.com/latest.zip'); + if ($input->getOption('dev')) { + return 'dev-master'; } - $archive->extractTo($directory); - - $archive->close(); - - return $this; + return ''; } /** - * Clean-up the Zip file. - * - * @param string $zipFile - * @return $this - */ - protected function cleanUp($zipFile) - { - @chmod($zipFile, 0777); - - @unlink($zipFile); - - return $this; - } - - /** - * Make sure the storage and bootstrap cache directories are writable. + * Get the composer command for the environment. * - * @param string $appDirectory - * @param \Symfony\Component\Console\Output\OutputInterface $output - * @return $this + * @return string */ - protected function prepareWritableDirectories($appDirectory, OutputInterface $output) + protected function findComposer() { - $filesystem = new Filesystem; + $composerPath = getcwd().'/composer.phar'; - try { - $filesystem->chmod($appDirectory.DIRECTORY_SEPARATOR.'bootstrap/cache', 0755, 0000, true); - $filesystem->chmod($appDirectory.DIRECTORY_SEPARATOR.'storage', 0755, 0000, true); - } catch (IOExceptionInterface $e) { - $output->writeln('You should verify that the "storage" and "bootstrap/cache" directories are writable.'); + if (file_exists($composerPath)) { + return '"'.PHP_BINARY.'" '.$composerPath; } - return $this; + return 'composer'; } /** - * Get the version that should be downloaded. + * Run the given commands. * + * @param array $commands * @param \Symfony\Component\Console\Input\InputInterface $input - * @return string + * @param \Symfony\Component\Console\Output\OutputInterface $output + * @return Process */ - protected function getVersion(InputInterface $input) + protected function runCommands($commands, InputInterface $input, OutputInterface $output) { - if ($input->getOption('dev')) { - return 'develop'; + if ($input->getOption('no-ansi')) { + $commands = array_map(function ($value) { + return $value.' --no-ansi'; + }, $commands); } - if ($input->getOption('auth')) { - return 'auth'; + if ($input->getOption('quiet')) { + $commands = array_map(function ($value) { + return $value.' --quiet'; + }, $commands); } - return 'master'; - } - - /** - * Get the composer command for the environment. - * - * @return string - */ - protected function findComposer() - { - $composerPath = getcwd().'/composer.phar'; + $process = Process::fromShellCommandline(implode(' && ', $commands), null, null, null, null); - if (file_exists($composerPath)) { - return '"'.PHP_BINARY.'" '.$composerPath; + if ('\\' !== DIRECTORY_SEPARATOR && file_exists('/dev/tty') && is_readable('/dev/tty')) { + try { + $process->setTty(true); + } catch (RuntimeException $e) { + $output->writeln('Warning: '.$e->getMessage()); + } } - return 'composer'; + $process->run(function ($type, $line) use ($output) { + $output->write($line); + }); + + return $process; } } diff --git a/tests/NewCommandTest.php b/tests/NewCommandTest.php index a1404b7..0163bc4 100644 --- a/tests/NewCommandTest.php +++ b/tests/NewCommandTest.php @@ -6,7 +6,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Application; use Symfony\Component\Console\Tester\CommandTester; -use Symfony\Component\Filesystem\Filesystem; class NewCommandTest extends TestCase { @@ -15,20 +14,17 @@ public function test_it_can_scaffold_a_new_laravel_app() $scaffoldDirectoryName = 'tests-output/my-app'; $scaffoldDirectory = __DIR__.'/../'.$scaffoldDirectoryName; - if (file_exists($scaffoldDirectory)) { - (new Filesystem)->remove($scaffoldDirectory); - } + exec("rm -rf $scaffoldDirectory"); $app = new Application('Laravel Installer'); $app->add(new NewCommand); $tester = new CommandTester($app->find('new')); - $statusCode = $tester->execute(['name' => $scaffoldDirectoryName, '--auth' => null]); + $statusCode = $tester->execute(['name' => $scaffoldDirectoryName]); $this->assertEquals($statusCode, 0); $this->assertDirectoryExists($scaffoldDirectory.'/vendor'); $this->assertFileExists($scaffoldDirectory.'/.env'); - $this->assertFileExists($scaffoldDirectory.'/resources/views/auth/login.blade.php'); } }