diff --git a/src/Symfony/Installer/NewCommand.php b/src/Symfony/Installer/NewCommand.php index 048c4aa..f6df447 100644 --- a/src/Symfony/Installer/NewCommand.php +++ b/src/Symfony/Installer/NewCommand.php @@ -110,89 +110,76 @@ protected function execute(InputInterface $input, OutputInterface $output) */ protected function checkSymfonyVersionIsInstallable() { - // 'latest' is a special version name that refers to the latest stable version - // 'lts' is a special version name that refers to the current long term support version - if (in_array($this->version, array('latest', 'lts'))) { - return $this; + // validate the given version syntax + if (!preg_match('/^latest|lts|[2-9]\.\d(?:\.\d{1,2})?(?:-(?:dev|BETA\d*|RC\d*))?$/i', $this->version)) { + throw new \RuntimeException(sprintf( + "The Symfony version can be a branch number (e.g. 2.8), a full version\n". + "number (e.g. 3.1.4), a special word ('latest' or 'lts') and a unstable\n". + "version number (e.g. 3.2.0-rc1) but '%s' was given.", $this->version + )); } - // validate semver syntax - if (!preg_match('/^[23]\.\d(?:\.\d{1,2})?(?:-(?:dev|BETA\d*|RC\d*))?$/i', $this->version)) { - throw new \RuntimeException('The Symfony version must be 2.N, 2.N.M, 3.N or 3.N.M (where N and M are positive integers). The special "-dev", "-BETA" and "-RC" versions are also supported.'); + // Get the full list of Symfony versions to check if it's installable + $client = $this->getGuzzleClient(); + $symfonyVersions = $client->get('http://symfony.com/versions.json')->json(); + if (empty($symfonyVersions)) { + throw new \RuntimeException( + "There was a problem while downloading the list of Symfony versions from\n". + "symfony.com. Check that you are online and the following URL is accessible:\n\n". + 'http://symfony.com/versions.json' + ); } - if (preg_match('/^[23]\.\d$/', $this->version)) { - // Check if we have a minor version in order to retrieve the last patch from symfony.com - - $client = $this->getGuzzleClient(); - $versionsList = $client->get('http://symfony.com/versions.json')->json(); - - if ($versionsList && isset($versionsList[$this->version])) { - // Get the latest patch of the minor version the user asked - $this->version = $versionsList[$this->version]; - } elseif ($versionsList && !isset($versionsList[$this->version])) { + // if a branch number is used, transform it into a real version number + if (preg_match('/^[2-9]\.\d$/', $this->version)) { + if (!isset($symfonyVersions[$this->version])) { throw new \RuntimeException(sprintf( "The selected branch (%s) does not exist, or is not maintained.\n". "To solve this issue, install Symfony with the latest stable release:\n\n". - '%s %s %s', - $this->version, - $_SERVER['PHP_SELF'], - $this->getName(), - $this->projectDir + '%s %s %s', $this->version, $_SERVER['PHP_SELF'], $this->getName(), $this->projectDir )); } + + $this->version = $symfonyVersions[$this->version]; } - // 2.0, 2.1, 2.2 and 2.4 cannot be installed because they are unmaintained - if (preg_match('/^2\.[0124]\.\d{1,2}$/', $this->version)) { - throw new \RuntimeException(sprintf( - "The selected version (%s) cannot be installed because it belongs\n". - "to an unmaintained Symfony branch which is not compatible with this installer.\n". - "To solve this issue install Symfony manually executing the following command:\n\n". - 'composer create-project symfony/framework-standard-edition %s %s', - $this->version, $this->projectDir, $this->version - )); + // if a special version name is used, transform it into a real version number + if (in_array($this->version, array('latest', 'lts'))) { + $this->version = $symfonyVersions[$this->version]; } - // 2.3 can be installed starting from version 2.3.21 (inclusive) - if (preg_match('/^2\.3\.\d{1,2}$/', $this->version) && version_compare($this->version, '2.3.21', '<')) { - throw new \RuntimeException(sprintf( - "The selected version (%s) cannot be installed because this installer\n". - "is compatible with Symfony 2.3 versions starting from 2.3.21.\n". - "To solve this issue install Symfony manually executing the following command:\n\n". - 'composer create-project symfony/framework-standard-edition %s %s', - $this->version, $this->projectDir, $this->version - )); + // versions are case-sensitive in the download server (3.1.0-rc1 must be 3.1.0-RC1) + if ($isUnstableVersion = preg_match('/^.*\-(BETA|RC)\d*$/i', $this->version)) { + $this->version = strtoupper($this->version); } - // 2.5 can be installed starting from version 2.5.6 (inclusive) - if (preg_match('/^2\.5\.\d{1,2}$/', $this->version) && version_compare($this->version, '2.5.6', '<')) { + $isNonInstallable = in_array($this->version, $symfonyVersions['non_installable']); + $isInstallable = in_array($this->version, $symfonyVersions['installable']); + + // installable and non-installable versions are explicitly declared in the + // list of versions; there is an edge-case: unstable versions are not listed + // and they are generally installable (e.g. 3.1.0-RC1) + if ($isNonInstallable || (!$isInstallable && !$isUnstableVersion)) { throw new \RuntimeException(sprintf( - "The selected version (%s) cannot be installed because this installer\n". - "is compatible with Symfony 2.5 versions starting from 2.5.6.\n". + "The selected version (%s) cannot be installed because it is not compatible\n". + "with this installer or because it hasn't been published as a package yet.\n". "To solve this issue install Symfony manually executing the following command:\n\n". 'composer create-project symfony/framework-standard-edition %s %s', $this->version, $this->projectDir, $this->version )); } - // "-dev" versions are not supported because Symfony doesn't provide packages for them - if (preg_match('/^.*\-dev$/i', $this->version)) { + // check that the system has the PHP version required by the Symfony version to be installed + if (version_compare($this->version, '3.0.0', '>=') && version_compare(phpversion(), '5.5.9', '<')) { throw new \RuntimeException(sprintf( - "The selected version (%s) cannot be installed because it hasn't\n". - "been published as a package yet. Read the following article for\n". - "an alternative installation method:\n\n". - "> How to Install or Upgrade to the Latest, Unreleased Symfony Version\n". - '> http://symfony.com/doc/current/cookbook/install/unstable_versions.html', - $this->version + "The selected version (%s) cannot be installed because it requires\n". + "PHP 5.5.9 or higher and your system has PHP %s installed.\n", + $this->version, phpversion() )); } - // warn the user when downloading an unstable version - if (preg_match('/^.*\-(BETA|RC)\d*$/i', $this->version)) { + if ($isUnstableVersion) { $this->output->writeln("\n WARNING You are downloading an unstable Symfony version."); - // versions provided by the download server are case sensitive - $this->version = strtoupper($this->version); } return $this; diff --git a/tests/Symfony/Installer/Tests/IntegrationTest.php b/tests/Symfony/Installer/Tests/IntegrationTest.php index 27f4160..90a8d5a 100644 --- a/tests/Symfony/Installer/Tests/IntegrationTest.php +++ b/tests/Symfony/Installer/Tests/IntegrationTest.php @@ -63,8 +63,12 @@ public function testDemoApplicationInstallation() /** * @dataProvider provideSymfonyInstallationData */ - public function testSymfonyInstallation($versionToInstall, $messageRegexp, $versionRegexp) + public function testSymfonyInstallation($versionToInstall, $messageRegexp, $versionRegexp, $requiredPhpVersion) { + if (version_compare(phpversion(), $requiredPhpVersion, '<')) { + $this->markTestSkipped(sprintf('This test requires PHP %s or higher.', $requiredPhpVersion)); + } + $projectDir = sprintf('%s/my_test_project', sys_get_temp_dir()); $this->fs->remove($projectDir); @@ -92,6 +96,19 @@ public function testSymfonyInstallation($versionToInstall, $messageRegexp, $vers ); } + /** + * @expectedException \RuntimeException + * @expectedExceptionMessageRegExp /.+The selected version \(3.0.0\) cannot be installed because it requires.+PHP 5.5.9 or higher and your system has PHP 5.4.* installed.+/s + */ + public function testSymfonyRequiresNewerPhpVersion() + { + if (PHP_VERSION_ID >= 50500) { + $this->markTestSkipped('This test requires PHP 5.4 or lower.'); + } + + $this->runCommand(sprintf('php %s/symfony.phar new my_test_project 3.0.0', $this->rootDir)); + } + public function testSymfonyInstallationInCurrentDirectory() { $projectDir = sprintf('%s/my_test_project', sys_get_temp_dir()); @@ -137,42 +154,49 @@ public function provideSymfonyInstallationData() '', '/.*Symfony 3\.1\.\d+ was successfully installed.*/', '/Symfony version 3\.1\.\d+(-DEV)? - app\/dev\/debug/', + '5.5.9', ), array( '3.0', '/.*Symfony 3\.0\.\d+ was successfully installed.*/', '/Symfony version 3\.0\.\d+(-DEV)? - app\/dev\/debug/', + '5.5.9', ), array( 'lts', '/.*Symfony 2\.8\.\d+ was successfully installed.*/', '/Symfony version 2\.8\.\d+(-DEV)? - app\/dev\/debug/', + '5.3.9', ), array( '2.3', '/.*Symfony 2\.3\.\d+ was successfully installed.*/', '/Symfony version 2\.3\.\d+ - app\/dev\/debug/', + '5.3.9', ), array( '2.5.6', '/.*Symfony 2\.5\.6 was successfully installed.*/', '/Symfony version 2\.5\.6 - app\/dev\/debug/', + '5.3.9', ), array( '2.7.0-BETA1', '/.*Symfony 2\.7\.0\-BETA1 was successfully installed.*/', '/Symfony version 2\.7\.0\-BETA1 - app\/dev\/debug/', + '5.3.9', ), array( '3.0.0-BETA1', '/.*Symfony dev\-master was successfully installed.*/', '/Symfony version 3\.0\.0\-BETA1 - app\/dev\/debug/', + '5.5.9', ), ); }