From e1de7031af5bf77b8bd4f1fb4736de08e428e50a Mon Sep 17 00:00:00 2001 From: Alex Rock Ancelet Date: Mon, 16 Nov 2015 12:43:46 +0100 Subject: [PATCH 01/38] Try to fix #190 by fixing lowercase package name --- src/Symfony/Installer/NewCommand.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Installer/NewCommand.php b/src/Symfony/Installer/NewCommand.php index 6d380ea..83a33c2 100644 --- a/src/Symfony/Installer/NewCommand.php +++ b/src/Symfony/Installer/NewCommand.php @@ -397,8 +397,8 @@ private function fixComposerPackageName($name) { return strtolower( preg_replace( - array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), - array('\\1-\\2', '\\1-\\2'), + array('~[^\w.-]~iu', '~([A-Z]+)([A-Z][a-z])~u', '~([a-z\d])([A-Z])~u'), + array('', '\\1-\\2', '\\1-\\2'), strtr($name, '-', '.') ) ); From b6350e525d99ce839d79e3ded93ce0c7e6a2ef4b Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Sat, 25 Jun 2016 10:37:36 +0200 Subject: [PATCH 02/38] Bumped development version --- symfony | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/symfony b/symfony index 1f043d7..af704d7 100755 --- a/symfony +++ b/symfony @@ -18,7 +18,7 @@ require file_exists(__DIR__.'/vendor/autoload.php') ? __DIR__.'/vendor/autoload.php' : __DIR__.'/../../autoload.php'; -$appVersion = '1.5.3'; +$appVersion = '1.5.4-DEV'; // Windows uses Path instead of PATH if (!isset($_SERVER['PATH']) && isset($_SERVER['Path'])) { From 3258bf7bdaa9af3e8921ec6252c9b4c5e3b9530f Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Sat, 25 Jun 2016 19:28:08 +0200 Subject: [PATCH 03/38] Fixed some "undefined variables" error in checkInstallerVersion() --- src/Symfony/Installer/DownloadCommand.php | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Installer/DownloadCommand.php b/src/Symfony/Installer/DownloadCommand.php index 4112861..1715b27 100644 --- a/src/Symfony/Installer/DownloadCommand.php +++ b/src/Symfony/Installer/DownloadCommand.php @@ -62,6 +62,16 @@ abstract class DownloadCommand extends Command */ protected $version = 'latest'; + /** + * @var string The latest installer version + */ + private $latestInstallerVersion; + + /** + * @var string The version of the local installer being executed + */ + private $localInstallerVersion; + /** * @var string The path to the downloaded file */ @@ -95,6 +105,9 @@ protected function initialize(InputInterface $input, OutputInterface $output) $this->output = $output; $this->fs = new Filesystem(); + $this->latestInstallerVersion = $this->getUrlContents(Application::VERSIONS_URL); + $this->localInstallerVersion = $this->getApplication()->getVersion(); + $this->enableSignalHandler(); } @@ -558,7 +571,7 @@ protected function checkInstallerVersion() $this->output->writeln(sprintf( "\n WARNING Your Symfony Installer version (%s) is outdated.\n". ' Execute the command "%s selfupdate" to get the latest version (%s).', - $installedVersion, $_SERVER['PHP_SELF'], $latestVersion + $this->localInstallerVersion, $_SERVER['PHP_SELF'], $this->latestInstallerVersion )); } @@ -570,10 +583,7 @@ protected function checkInstallerVersion() */ protected function isInstallerUpdated() { - $installedVersion = $this->getApplication()->getVersion(); - $latestVersion = $this->getUrlContents(Application::VERSIONS_URL); - - return version_compare($installedVersion, $latestVersion, '>='); + return version_compare($this->localInstallerVersion, $this->latestInstallerVersion, '>='); } /** From 1e8ebb99917309d8eef7cd44e8340102c3e4c42d Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Sat, 25 Jun 2016 20:15:52 +0200 Subject: [PATCH 04/38] Prepare the 1.5.4 release --- symfony | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/symfony b/symfony index af704d7..0c6f8e9 100755 --- a/symfony +++ b/symfony @@ -18,7 +18,7 @@ require file_exists(__DIR__.'/vendor/autoload.php') ? __DIR__.'/vendor/autoload.php' : __DIR__.'/../../autoload.php'; -$appVersion = '1.5.4-DEV'; +$appVersion = '1.5.4'; // Windows uses Path instead of PATH if (!isset($_SERVER['PATH']) && isset($_SERVER['Path'])) { From ce0acc8bf847e1a335caae57d2cc530a5270e6b2 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Sat, 25 Jun 2016 20:17:37 +0200 Subject: [PATCH 05/38] Bumped development version --- symfony | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/symfony b/symfony index 0c6f8e9..8bb6309 100755 --- a/symfony +++ b/symfony @@ -18,7 +18,7 @@ require file_exists(__DIR__.'/vendor/autoload.php') ? __DIR__.'/vendor/autoload.php' : __DIR__.'/../../autoload.php'; -$appVersion = '1.5.4'; +$appVersion = '1.5.5-DEV'; // Windows uses Path instead of PATH if (!isset($_SERVER['PATH']) && isset($_SERVER['Path'])) { From e7b3fc3e8725dc0495f446e0f35f513f25448122 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Mon, 6 Jun 2016 15:14:04 +0200 Subject: [PATCH 06/38] Check that the system has the PHP version required by Symfony --- src/Symfony/Installer/NewCommand.php | 99 ++++++++----------- .../Installer/Tests/IntegrationTest.php | 26 ++++- 2 files changed, 68 insertions(+), 57 deletions(-) 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', ), ); } From 88d88d53e4f54e0ff8ef16f60c80c1b1d03f0252 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Sun, 10 Jul 2016 20:50:16 +0200 Subject: [PATCH 07/38] Released the 1.5.5 version --- symfony | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/symfony b/symfony index 8bb6309..878de56 100755 --- a/symfony +++ b/symfony @@ -18,7 +18,7 @@ require file_exists(__DIR__.'/vendor/autoload.php') ? __DIR__.'/vendor/autoload.php' : __DIR__.'/../../autoload.php'; -$appVersion = '1.5.5-DEV'; +$appVersion = '1.5.5'; // Windows uses Path instead of PATH if (!isset($_SERVER['PATH']) && isset($_SERVER['Path'])) { From d6f203fae79ef9b5dcb42a8ec5fa331207b61055 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Sun, 10 Jul 2016 20:55:26 +0200 Subject: [PATCH 08/38] Bumped development version --- symfony | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/symfony b/symfony index 878de56..201323d 100755 --- a/symfony +++ b/symfony @@ -18,7 +18,7 @@ require file_exists(__DIR__.'/vendor/autoload.php') ? __DIR__.'/vendor/autoload.php' : __DIR__.'/../../autoload.php'; -$appVersion = '1.5.5'; +$appVersion = '1.5.6-DEV'; // Windows uses Path instead of PATH if (!isset($_SERVER['PATH']) && isset($_SERVER['Path'])) { From 06406674091669093755e97b56aa49dd5b8a62a9 Mon Sep 17 00:00:00 2001 From: Fabrice Baumann Date: Fri, 15 Jul 2016 10:52:47 -0400 Subject: [PATCH 09/38] #266 Self update is not detecting the installed version --- src/Symfony/Installer/DownloadCommand.php | 4 ++-- src/Symfony/Installer/SelfUpdateCommand.php | 11 +---------- 2 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/Symfony/Installer/DownloadCommand.php b/src/Symfony/Installer/DownloadCommand.php index 1715b27..2ac118d 100644 --- a/src/Symfony/Installer/DownloadCommand.php +++ b/src/Symfony/Installer/DownloadCommand.php @@ -65,12 +65,12 @@ abstract class DownloadCommand extends Command /** * @var string The latest installer version */ - private $latestInstallerVersion; + protected $latestInstallerVersion; /** * @var string The version of the local installer being executed */ - private $localInstallerVersion; + protected $localInstallerVersion; /** * @var string The path to the downloaded file diff --git a/src/Symfony/Installer/SelfUpdateCommand.php b/src/Symfony/Installer/SelfUpdateCommand.php index a35c3f9..4e0dbc9 100644 --- a/src/Symfony/Installer/SelfUpdateCommand.php +++ b/src/Symfony/Installer/SelfUpdateCommand.php @@ -13,7 +13,6 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Filesystem\Exception\IOException; /** @@ -33,11 +32,6 @@ class SelfUpdateCommand extends DownloadCommand */ private $tempDir; - /** - * @var string The latest installer version - */ - private $latestInstallerVersion; - /** * @var string The URL where the latest installer version can be downloaded */ @@ -92,10 +86,7 @@ public function isEnabled() */ protected function initialize(InputInterface $input, OutputInterface $output) { - $this->fs = new Filesystem(); - $this->output = $output; - - $this->latestInstallerVersion = $this->getUrlContents(Application::VERSIONS_URL); + parent::initialize($input, $output); $this->remoteInstallerFile = 'http://symfony.com/installer'; $this->currentInstallerFile = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0]; $this->tempDir = sys_get_temp_dir(); From 8612bf80516c75e5890a1a1a8017935f2bc9af22 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 11 Jul 2016 09:32:48 +0200 Subject: [PATCH 10/38] update Guzzle dep to >= 5.3.1 --- composer.json | 2 +- composer.lock | 22 ++++++++-------------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/composer.json b/composer.json index fca1589..f2d3582 100644 --- a/composer.json +++ b/composer.json @@ -14,7 +14,7 @@ }, "require": { "php": ">=5.4.0", - "guzzlehttp/guzzle": "~5.0", + "guzzlehttp/guzzle": "^5.3.1", "symfony/console": "~2.6", "symfony/filesystem": "~2.5", "raulfraile/distill": "~0.9,!=0.9.3,!=0.9.4" diff --git a/composer.lock b/composer.lock index a669ed0..32c1a8a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,21 +4,21 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "cccc793e61a124372892d161b632d33d", - "content-hash": "b46d584a3de98e7413132f01256a1a5c", + "hash": "7587a63f96b596f379d4d830bee56119", + "content-hash": "3c97ce42899ed9440a9ef2cc5d78847f", "packages": [ { "name": "guzzlehttp/guzzle", - "version": "5.3.0", + "version": "5.3.1", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "f3c8c22471cb55475105c14769644a49c3262b93" + "reference": "70f1fa53b71c4647bf2762c09068a95f77e12fb8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f3c8c22471cb55475105c14769644a49c3262b93", - "reference": "f3c8c22471cb55475105c14769644a49c3262b93", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/70f1fa53b71c4647bf2762c09068a95f77e12fb8", + "reference": "70f1fa53b71c4647bf2762c09068a95f77e12fb8", "shasum": "" }, "require": { @@ -27,15 +27,9 @@ }, "require-dev": { "ext-curl": "*", - "phpunit/phpunit": "^4.0", - "psr/log": "^1.0" + "phpunit/phpunit": "^4.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "5.0-dev" - } - }, "autoload": { "psr-4": { "GuzzleHttp\\": "src/" @@ -63,7 +57,7 @@ "rest", "web service" ], - "time": "2015-05-20 03:47:55" + "time": "2016-07-15 19:28:39" }, { "name": "guzzlehttp/ringphp", From 205c2d97f6ff30fe96e83e94af2b170964ac41d9 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 19 Jul 2016 12:46:39 +0200 Subject: [PATCH 11/38] Prepare the 1.5.6 release --- symfony | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/symfony b/symfony index 201323d..55752d6 100755 --- a/symfony +++ b/symfony @@ -18,7 +18,7 @@ require file_exists(__DIR__.'/vendor/autoload.php') ? __DIR__.'/vendor/autoload.php' : __DIR__.'/../../autoload.php'; -$appVersion = '1.5.6-DEV'; +$appVersion = '1.5.6'; // Windows uses Path instead of PATH if (!isset($_SERVER['PATH']) && isset($_SERVER['Path'])) { From 7b09c9916fe125ccd50fd2d2ddfb98f8760379b1 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 19 Jul 2016 12:49:36 +0200 Subject: [PATCH 12/38] Bumped development version --- symfony | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/symfony b/symfony index 55752d6..14fd272 100755 --- a/symfony +++ b/symfony @@ -18,7 +18,7 @@ require file_exists(__DIR__.'/vendor/autoload.php') ? __DIR__.'/vendor/autoload.php' : __DIR__.'/../../autoload.php'; -$appVersion = '1.5.6'; +$appVersion = '1.5.7-DEV'; // Windows uses Path instead of PATH if (!isset($_SERVER['PATH']) && isset($_SERVER['Path'])) { From 0c711dab539bcaad7ac51effc74a0f716d8fe91f Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Fri, 22 Jul 2016 10:29:43 +0200 Subject: [PATCH 13/38] Added an option to force the installer update --- src/Symfony/Installer/SelfUpdateCommand.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Installer/SelfUpdateCommand.php b/src/Symfony/Installer/SelfUpdateCommand.php index 4e0dbc9..0b1810e 100644 --- a/src/Symfony/Installer/SelfUpdateCommand.php +++ b/src/Symfony/Installer/SelfUpdateCommand.php @@ -12,6 +12,7 @@ namespace Symfony\Installer; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Filesystem\Exception\IOException; @@ -66,6 +67,7 @@ protected function configure() $this ->setName('self-update') ->setAliases(array('selfupdate')) + ->addOption('force-update', 'f', InputOption::VALUE_NONE, 'It updates the installer to the latest available version without checking if it\'s older or newer than the locally installed version.') ->setDescription('Update the Symfony Installer to the latest version.') ->setHelp('The %command.name% command updates the installer to the latest available version.') ; @@ -100,14 +102,15 @@ protected function initialize(InputInterface $input, OutputInterface $output) */ protected function execute(InputInterface $input, OutputInterface $output) { - if ($this->isInstallerUpdated()) { + $forceUpdate = true === $input->getOption('force-update'); + if (!$forceUpdate && $this->isInstallerUpdated()) { $this->output->writeln(sprintf('// Symfony Installer is already updated to the latest version (%s).', $this->latestInstallerVersion)); return; - } else { - $this->output->writeln(sprintf('// updating Symfony Installer to %s version', $this->latestInstallerVersion)); } + $this->output->writeln(sprintf('// updating Symfony Installer to %s version', $this->latestInstallerVersion)); + try { $this ->downloadNewVersion() From 4f133718ab39f6d01b728c95d1cf27dbaaf4f19f Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Fri, 22 Jul 2016 15:31:22 +0200 Subject: [PATCH 14/38] Added a "troubleshooting" section in the README to solve common issues --- README.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/README.md b/README.md index a8506be..82d2257 100644 --- a/README.md +++ b/README.md @@ -129,3 +129,29 @@ c:\> php symfony self-update > installer tries to guess the best proxy settings from the `HTTP_PROXY` and > `http_proxy` environment variables. Make sure any of them is set before > executing the Symfony Installer. + +Troubleshooting +--------------- + +### SSL and certificates issues on Windows systems + +If you experience any error related with SSL or security certificates when using +the Symfony Installer on Windows systems: + +1) Check that the OpenSSL extension is enabled in your `php.ini` configuration: + +```ini +; make sure that the following line is uncommented +extension=php_openssl.dll +``` + +2) Check that the path to the file that contains the security certificates +exists and is defined in `php.ini`: + +```ini +openssl.cafile=C:/path/to/cacert.pem +``` + +If you can't locate the `cacert.pem` file anywhere on your system, you can +safely download it from the official website of the cURL project: +http://curl.haxx.se/ca/cacert.pem From 517498147d5479310d0cd107a294a2041184b81a Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Sun, 24 Jul 2016 17:11:26 +0200 Subject: [PATCH 15/38] Prepared the 1.5.7 release --- symfony | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/symfony b/symfony index 14fd272..eff25ab 100755 --- a/symfony +++ b/symfony @@ -18,7 +18,7 @@ require file_exists(__DIR__.'/vendor/autoload.php') ? __DIR__.'/vendor/autoload.php' : __DIR__.'/../../autoload.php'; -$appVersion = '1.5.7-DEV'; +$appVersion = '1.5.7'; // Windows uses Path instead of PATH if (!isset($_SERVER['PATH']) && isset($_SERVER['Path'])) { From db0fd8a642bd0fb95a35959b35a4b71f423defea Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Sun, 24 Jul 2016 17:13:10 +0200 Subject: [PATCH 16/38] Bumped development version --- symfony | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/symfony b/symfony index eff25ab..f16cbe5 100755 --- a/symfony +++ b/symfony @@ -18,7 +18,7 @@ require file_exists(__DIR__.'/vendor/autoload.php') ? __DIR__.'/vendor/autoload.php' : __DIR__.'/../../autoload.php'; -$appVersion = '1.5.7'; +$appVersion = '1.5.8-DEV'; // Windows uses Path instead of PATH if (!isset($_SERVER['PATH']) && isset($_SERVER['Path'])) { From 70b921a47372a5734d09adbbeacc5d74d77cda3d Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 26 Jul 2016 16:50:05 +0200 Subject: [PATCH 17/38] Released 1.5.8 version --- symfony | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/symfony b/symfony index f16cbe5..50e08f1 100755 --- a/symfony +++ b/symfony @@ -18,7 +18,7 @@ require file_exists(__DIR__.'/vendor/autoload.php') ? __DIR__.'/vendor/autoload.php' : __DIR__.'/../../autoload.php'; -$appVersion = '1.5.8-DEV'; +$appVersion = '1.5.8'; // Windows uses Path instead of PATH if (!isset($_SERVER['PATH']) && isset($_SERVER['Path'])) { From ff7e0c6234df6a29e2df57a9fe384472e67f7e0d Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 26 Jul 2016 16:54:04 +0200 Subject: [PATCH 18/38] Bumped development version --- symfony | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/symfony b/symfony index 50e08f1..2dcfded 100755 --- a/symfony +++ b/symfony @@ -18,7 +18,7 @@ require file_exists(__DIR__.'/vendor/autoload.php') ? __DIR__.'/vendor/autoload.php' : __DIR__.'/../../autoload.php'; -$appVersion = '1.5.8'; +$appVersion = '1.5.9-DEV'; // Windows uses Path instead of PATH if (!isset($_SERVER['PATH']) && isset($_SERVER['Path'])) { From e321bb6ce0b56584d9c90e7f104b03bd36bb9656 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 30 Aug 2016 12:03:35 +0200 Subject: [PATCH 19/38] Declare the Symfony Installer incompatible with 'suhosin' PHP extension --- symfony | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/symfony b/symfony index 2dcfded..77977bd 100755 --- a/symfony +++ b/symfony @@ -14,6 +14,17 @@ if (PHP_VERSION_ID < 50400) { exit(1); } +if (extension_loaded('suhosin')) { + file_put_contents('php://stderr', + "Symfony Installer is not compatible with the 'suhosin' PHP extension.\n". + "Disable that extension before running the installer.\n\n". + "Alternatively, install Symfony manually executing the following command:\n\n". + "composer create-project symfony/framework-standard-edition \n\n" + ); + + exit(1); +} + require file_exists(__DIR__.'/vendor/autoload.php') ? __DIR__.'/vendor/autoload.php' : __DIR__.'/../../autoload.php'; From ab6cce26df18a0ad96716ea19db49dc504b6e1c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1ty=C3=A1s=20Somfai?= Date: Fri, 2 Sep 2016 15:06:50 +0200 Subject: [PATCH 20/38] Fixed some issues for the self-update command: added coloring to the rollback message, set return code at general exception handling, fixed an undefined variable notice. --- src/Symfony/Installer/DownloadCommand.php | 1 + src/Symfony/Installer/SelfUpdateCommand.php | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Installer/DownloadCommand.php b/src/Symfony/Installer/DownloadCommand.php index 2ac118d..c3bf3d7 100644 --- a/src/Symfony/Installer/DownloadCommand.php +++ b/src/Symfony/Installer/DownloadCommand.php @@ -520,6 +520,7 @@ protected function getExecutedCommand() } $commandName = $this->getName(); + $commandArguments = ''; if ('new' === $commandName) { $commandArguments = sprintf('%s %s', $this->projectName, ('latest' !== $this->version) ? $this->version : ''); diff --git a/src/Symfony/Installer/SelfUpdateCommand.php b/src/Symfony/Installer/SelfUpdateCommand.php index 0b1810e..28b3890 100644 --- a/src/Symfony/Installer/SelfUpdateCommand.php +++ b/src/Symfony/Installer/SelfUpdateCommand.php @@ -136,6 +136,8 @@ protected function execute(InputInterface $input, OutputInterface $output) if ($this->output->isVeryVerbose()) { $this->output->writeln($e->getMessage()); } + + return 1; } } @@ -148,11 +150,11 @@ private function downloadNewVersion() { // check for permissions in local filesystem before start downloading files if (!is_writable($this->currentInstallerFile)) { - throw new \RuntimeException('Symfony Installer update failed: the "'.$this->currentInstallerFile.'" file could not be written'); + throw new IOException('Symfony Installer update failed: the "'.$this->currentInstallerFile.'" file could not be written'); } if (!is_writable($this->tempDir)) { - throw new \RuntimeException('Symfony Installer update failed: the "'.$this->tempDir.'" directory used to download files temporarily could not be written'); + throw new IOException('Symfony Installer update failed: the "'.$this->tempDir.'" directory used to download files temporarily could not be written'); } if (false === $newInstaller = $this->getUrlContents($this->remoteInstallerFile)) { @@ -225,7 +227,7 @@ private function rollback() { $this->output->writeln(array( '', - 'There was an error while updating the installer.', + 'There was an error while updating the installer.', 'The previous Symfony Installer version has been restored.', '', )); From 4773869486dbfd946b4d44e972f7d056b4fffbd5 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Fri, 30 Sep 2016 13:19:45 +0200 Subject: [PATCH 21/38] Finished this feature --- src/Symfony/Installer/NewCommand.php | 17 +++++++---- .../Installer/Tests/NewCommandTest.php | 30 +++++++++++++++++++ 2 files changed, 41 insertions(+), 6 deletions(-) create mode 100644 tests/Symfony/Installer/Tests/NewCommandTest.php diff --git a/src/Symfony/Installer/NewCommand.php b/src/Symfony/Installer/NewCommand.php index 83a33c2..54ecb19 100644 --- a/src/Symfony/Installer/NewCommand.php +++ b/src/Symfony/Installer/NewCommand.php @@ -395,13 +395,18 @@ protected function generateComposerProjectName() */ private function fixComposerPackageName($name) { - return strtolower( - preg_replace( - array('~[^\w.-]~iu', '~([A-Z]+)([A-Z][a-z])~u', '~([a-z\d])([A-Z])~u'), - array('', '\\1-\\2', '\\1-\\2'), - strtr($name, '-', '.') - ) + $name = str_replace( + ['à', 'á', 'â', 'ä', 'æ', 'ã', 'å', 'ā', 'é', 'è', 'ê', 'ë', 'ę', 'ė', 'ē', 'ī', 'į', 'í', 'ì', 'ï', 'î', 'ō', 'ø', 'œ', 'õ', 'ó', 'ò', 'ö', 'ô', 'ū', 'ú', 'ù', 'ü', 'û', 'ç', 'ć', 'č', 'ł', 'ñ', 'ń', 'ß', 'ś', 'š', 'ŵ', 'ŷ', 'ÿ', 'ź', 'ž', 'ż'], + ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'i', 'i', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'u', 'c', 'c', 'c', 'l', 'n', 'n', 's', 's', 's', 'w', 'y', 'y', 'z', 'z', 'z'], + $name ); + $name = strtr($name, '-', '.'); + + return strtolower(preg_replace( + ['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], + ['\\1-\\2', '\\1-\\2'], + $name + )); } protected function getDownloadedApplicationType() diff --git a/tests/Symfony/Installer/Tests/NewCommandTest.php b/tests/Symfony/Installer/Tests/NewCommandTest.php new file mode 100644 index 0000000..b124980 --- /dev/null +++ b/tests/Symfony/Installer/Tests/NewCommandTest.php @@ -0,0 +1,30 @@ +setAccessible(true); + + $fixedName = $method->invoke($command, $originalName); + $this->assertSame($expectedName, $fixedName); + } + + public function getProjectNames() + { + return [ + ['foobar', 'foobar'], + ['áèîøūñ', 'aeioun'], + ['çįßłŵž', 'cislwz'], + ]; + } +} \ No newline at end of file From 74d991b413657fc7641c7fe4dfa1d261af96be5c Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Fri, 30 Sep 2016 15:09:01 +0200 Subject: [PATCH 22/38] Clean the package names using the same regexp as Composer --- src/Symfony/Installer/NewCommand.php | 8 ++------ tests/Symfony/Installer/Tests/NewCommandTest.php | 8 +++++--- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Installer/NewCommand.php b/src/Symfony/Installer/NewCommand.php index 54ecb19..e261020 100644 --- a/src/Symfony/Installer/NewCommand.php +++ b/src/Symfony/Installer/NewCommand.php @@ -400,13 +400,9 @@ private function fixComposerPackageName($name) ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'i', 'i', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'u', 'c', 'c', 'c', 'l', 'n', 'n', 's', 's', 's', 'w', 'y', 'y', 'z', 'z', 'z'], $name ); - $name = strtr($name, '-', '.'); + $name = preg_replace('#[^A-Za-z0-9_./-]+#', '', $name); - return strtolower(preg_replace( - ['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], - ['\\1-\\2', '\\1-\\2'], - $name - )); + return strtolower($name); } protected function getDownloadedApplicationType() diff --git a/tests/Symfony/Installer/Tests/NewCommandTest.php b/tests/Symfony/Installer/Tests/NewCommandTest.php index b124980..5159f38 100644 --- a/tests/Symfony/Installer/Tests/NewCommandTest.php +++ b/tests/Symfony/Installer/Tests/NewCommandTest.php @@ -22,9 +22,11 @@ public function testFixComposerPackageName($originalName, $expectedName) public function getProjectNames() { return [ - ['foobar', 'foobar'], - ['áèîøūñ', 'aeioun'], - ['çįßłŵž', 'cislwz'], + ['foo/bar', 'foo/bar'], + ['áèî/øū', 'aei/ou'], + ['çñß/łŵž', 'cns/lwz'], + ['foo#bar\foo?bar=foo!bar{foo]bar', 'foobarfoobarfoobarfoobar'], + ['FOO/bar', 'foo/bar'], ]; } } \ No newline at end of file From 19b6799bc56e689cc14c4441cde3e1bd9449f6cc Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Fri, 30 Sep 2016 15:10:18 +0200 Subject: [PATCH 23/38] Missing EOL --- tests/Symfony/Installer/Tests/NewCommandTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Symfony/Installer/Tests/NewCommandTest.php b/tests/Symfony/Installer/Tests/NewCommandTest.php index 5159f38..6967299 100644 --- a/tests/Symfony/Installer/Tests/NewCommandTest.php +++ b/tests/Symfony/Installer/Tests/NewCommandTest.php @@ -29,4 +29,4 @@ public function getProjectNames() ['FOO/bar', 'foo/bar'], ]; } -} \ No newline at end of file +} From 9a4cb1b9e6aff6a43557e154da1cbd587839f35a Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Fri, 7 Oct 2016 15:23:51 +0200 Subject: [PATCH 24/38] Fixed tests for PHP 5.4 on Travis CI --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ed70733..c46fe05 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,7 @@ before_install: install: - composer install - - php box build + - ~/.phpenv/versions/5.6/bin/php box build script: - phpunit From c3f8200daa77b71f6c3fa0e9f0eebd900f8ed1e5 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Mon, 10 Oct 2016 08:51:31 +0200 Subject: [PATCH 25/38] Use Symfony's helper to format the memory values --- src/Symfony/Installer/DownloadCommand.php | 25 +++-------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/src/Symfony/Installer/DownloadCommand.php b/src/Symfony/Installer/DownloadCommand.php index c3bf3d7..f24c54a 100644 --- a/src/Symfony/Installer/DownloadCommand.php +++ b/src/Symfony/Installer/DownloadCommand.php @@ -21,6 +21,7 @@ use GuzzleHttp\Event\ProgressEvent; use GuzzleHttp\Utils; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Helper\Helper; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -146,10 +147,10 @@ protected function download() if (null === $progressBar) { ProgressBar::setPlaceholderFormatterDefinition('max', function (ProgressBar $bar) { - return $this->formatSize($bar->getMaxSteps()); + return Helper::formatMemory($bar->getMaxSteps()); }); ProgressBar::setPlaceholderFormatterDefinition('current', function (ProgressBar $bar) { - return str_pad($this->formatSize($bar->getProgress()), 11, ' ', STR_PAD_LEFT); + return str_pad(Helper::formatMemory($bar->getProgress()), 11, ' ', STR_PAD_LEFT); }); $progressBar = new ProgressBar($this->output, $downloadSize); @@ -449,26 +450,6 @@ protected function checkPermissions() return $this; } - /** - * Utility method to show the number of bytes in a readable format. - * - * @param int $bytes The number of bytes to format - * - * @return string The human readable string of bytes (e.g. 4.32MB) - */ - protected function formatSize($bytes) - { - $units = array('B', 'KB', 'MB', 'GB', 'TB'); - - $bytes = max($bytes, 0); - $pow = $bytes ? floor(log($bytes, 1024)) : 0; - $pow = min($pow, count($units) - 1); - - $bytes /= pow(1024, $pow); - - return number_format($bytes, 2).' '.$units[$pow]; - } - /** * Formats the error message contained in the given Requirement item * using the optional line length provided. From 28dafd2b228a153548211167eeac49cab5a341ae Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Sun, 9 Oct 2016 16:58:30 +0200 Subject: [PATCH 26/38] Introduce a ComposerManager class to simplify the commands --- src/Symfony/Installer/DemoCommand.php | 5 +- src/Symfony/Installer/DownloadCommand.php | 138 +------------ .../Installer/Manager/ComposerManager.php | 193 ++++++++++++++++++ src/Symfony/Installer/NewCommand.php | 74 ++----- .../ComposerManagerTest.php} | 14 +- 5 files changed, 227 insertions(+), 197 deletions(-) create mode 100644 src/Symfony/Installer/Manager/ComposerManager.php rename tests/Symfony/Installer/Tests/{NewCommandTest.php => Manager/ComposerManagerTest.php} (53%) diff --git a/src/Symfony/Installer/DemoCommand.php b/src/Symfony/Installer/DemoCommand.php index 8944c31..ed8fe87 100644 --- a/src/Symfony/Installer/DemoCommand.php +++ b/src/Symfony/Installer/DemoCommand.php @@ -15,6 +15,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Installer\Exception\AbortException; +use Symfony\Installer\Manager\ComposerManager; /** * This command creates a full-featured Symfony demo application. @@ -60,6 +61,8 @@ protected function initialize(InputInterface $input, OutputInterface $output) $this->projectDir = $this->fs->isAbsolutePath($directory) ? $directory : getcwd().DIRECTORY_SEPARATOR.$directory; $this->projectName = basename($directory); } + + $this->composerManager = new ComposerManager($this->projectDir); } /** @@ -75,7 +78,7 @@ protected function execute(InputInterface $input, OutputInterface $output) ->download() ->extract() ->cleanUp() - ->updateComposerJson() + ->updateComposerConfig() ->createGitIgnore() ->checkSymfonyRequirements() ->displayInstallationResult() diff --git a/src/Symfony/Installer/DownloadCommand.php b/src/Symfony/Installer/DownloadCommand.php index c3bf3d7..a88b07b 100644 --- a/src/Symfony/Installer/DownloadCommand.php +++ b/src/Symfony/Installer/DownloadCommand.php @@ -28,6 +28,7 @@ use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Intl\Exception\MethodArgumentValueNotImplementedException; use Symfony\Installer\Exception\AbortException; +use Symfony\Installer\Manager\ComposerManager; /** * Abstract command used by commands which download and extract compressed Symfony files. @@ -82,6 +83,9 @@ abstract class DownloadCommand extends Command */ protected $requirementsErrors = array(); + /** @var ComposerManager */ + protected $composerManager; + /** * Returns the type of the downloaded application in a human readable format. * It's mainly used to display readable error messages. @@ -363,23 +367,9 @@ private function getSymfonyRequirementsFilePath() * * @return $this */ - protected function updateComposerJson() + protected function updateComposerConfig() { - $composerConfig = $this->getProjectComposerConfig(); - - if (isset($composerConfig['config']['platform']['php'])) { - unset($composerConfig['config']['platform']['php']); - - if (empty($composerConfig['config']['platform'])) { - unset($composerConfig['config']['platform']); - } - - if (empty($composerConfig['config'])) { - unset($composerConfig['config']); - } - } - - $this->saveProjectComposerConfig($composerConfig); + $this->composerManager->initializeProjectConfig(); return $this; } @@ -418,17 +408,13 @@ protected function createGitIgnore() */ protected function getInstalledSymfonyVersion() { - $composer = json_decode(file_get_contents($this->projectDir.'/composer.lock'), true); + $symfonyVersion = $this->composerManager->getPackageVersion('symfony/symfony'); - foreach ($composer['packages'] as $package) { - if ('symfony/symfony' === $package['name']) { - if ('v' === substr($package['version'], 0, 1)) { - return substr($package['version'], 1); - }; + if (!empty($symfonyVersion) && 'v' === substr($symfonyVersion, 0, 1)) { + return substr($symfonyVersion, 1); + }; - return $package['version']; - } - } + return $symfonyVersion; } /** @@ -520,7 +506,6 @@ protected function getExecutedCommand() } $commandName = $this->getName(); - $commandArguments = ''; if ('new' === $commandName) { $commandArguments = sprintf('%s %s', $this->projectName, ('latest' !== $this->version) ? $this->version : ''); @@ -601,107 +586,6 @@ protected function getUrlContents($url) return $client->get($url)->getBody()->getContents(); } - /** - * It returns the project's Composer config as a PHP array. - * - * @return $this|array - */ - protected function getProjectComposerConfig() - { - $composerJsonFilepath = $this->projectDir.'/composer.json'; - - if (!is_writable($composerJsonFilepath)) { - if ($this->output->isVerbose()) { - $this->output->writeln(sprintf( - " [WARNING] Project's Composer config cannot be updated because\n". - " the %s file is not writable.\n", - $composerJsonFilepath - )); - } - - return $this; - } - - return json_decode(file_get_contents($composerJsonFilepath), true); - } - - /** - * It saves the given PHP array as the project's Composer config. In addition - * to JSON-serializing the contents, it synchronizes the composer.lock file to - * avoid out-of-sync Composer errors. - * - * @param array $config - */ - protected function saveProjectComposerConfig(array $config) - { - $composerJsonFilepath = $this->projectDir.'/composer.json'; - $this->fs->dumpFile($composerJsonFilepath, json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)."\n"); - - $this->syncComposerLockFile(); - } - - /** - * Updates the hash values stored in composer.lock to avoid out-of-sync - * problems when the composer.json file contents are changed. - */ - private function syncComposerLockFile() - { - $composerJsonFileContents = file_get_contents($this->projectDir.'/composer.json'); - $composerLockFileContents = json_decode(file_get_contents($this->projectDir.'/composer.lock'), true); - - if (array_key_exists('hash', $composerLockFileContents)) { - $composerLockFileContents['hash'] = md5($composerJsonFileContents); - } - - if (array_key_exists('content-hash', $composerLockFileContents)) { - $composerLockFileContents['content-hash'] = $this->getComposerContentHash($composerJsonFileContents); - } - - $this->fs->dumpFile($this->projectDir.'/composer.lock', json_encode($composerLockFileContents, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)."\n"); - } - - /** - * Returns the md5 hash of the sorted content of the composer file. - * - * @see https://github.com/composer/composer/blob/master/src/Composer/Package/Locker.php (getContentHash() method) - * - * @param string $composerJsonFileContents The contents of the composer.json file. - * - * @return string The hash of the composer file content. - */ - private function getComposerContentHash($composerJsonFileContents) - { - $composerConfig = json_decode($composerJsonFileContents, true); - - $relevantKeys = array( - 'name', - 'version', - 'require', - 'require-dev', - 'conflict', - 'replace', - 'provide', - 'minimum-stability', - 'prefer-stable', - 'repositories', - 'extra', - ); - - $relevantComposerConfig = array(); - - foreach (array_intersect($relevantKeys, array_keys($composerConfig)) as $key) { - $relevantComposerConfig[$key] = $composerConfig[$key]; - } - - if (isset($composerConfig['config']['platform'])) { - $relevantComposerConfig['config']['platform'] = $composerConfig['config']['platform']; - } - - ksort($relevantComposerConfig); - - return md5(json_encode($relevantComposerConfig)); - } - /** * Enables the signal handler. * diff --git a/src/Symfony/Installer/Manager/ComposerManager.php b/src/Symfony/Installer/Manager/ComposerManager.php new file mode 100644 index 0000000..e7c9266 --- /dev/null +++ b/src/Symfony/Installer/Manager/ComposerManager.php @@ -0,0 +1,193 @@ +projectDir = $projectDir; + $this->fs = new Filesystem(); + } + + public function initializeProjectConfig() + { + $composerConfig = $this->getProjectConfig(); + + if (isset($composerConfig['config']['platform']['php'])) { + unset($composerConfig['config']['platform']['php']); + + if (empty($composerConfig['config']['platform'])) { + unset($composerConfig['config']['platform']); + } + + if (empty($composerConfig['config'])) { + unset($composerConfig['config']); + } + } + + $this->saveProjectConfig($composerConfig); + } + + public function updateProjectConfig(array $newConfig) + { + $oldConfig = $this->getProjectConfig(); + $projectConfig = array_replace_recursive($oldConfig, $newConfig); + + // remove null values from project's config + $projectConfig = array_filter($projectConfig, function($value) { return !is_null($value); }); + + $this->saveProjectConfig($projectConfig); + } + + public function getPackageVersion($packageName) + { + $composerLockFileContents = json_decode(file_get_contents($this->projectDir.'/composer.lock'), true); + + foreach ($composerLockFileContents['packages'] as $packageConfig) { + if ($packageName === $packageConfig['name']) { + return $packageConfig['version']; + } + } + } + + /** + * Generates a good Composer project name based on the application name + * and on the user name. + * + * @param $projectName + * + * @return string The generated Composer package name + */ + public function createPackageName($projectName) + { + if (!empty($_SERVER['USERNAME'])) { + $packageName = $_SERVER['USERNAME'].'/'.$projectName; + } elseif (true === extension_loaded('posix') && $user = posix_getpwuid(posix_getuid())) { + $packageName = $user['name'].'/'.$projectName; + } elseif (get_current_user()) { + $packageName = get_current_user().'/'.$projectName; + } else { + // package names must be in the format foo/bar + $packageName = $projectName.'/'.$projectName; + } + + return $this->fixPackageName($packageName); + } + + /** + * It returns the project's Composer config as a PHP array. + * + * @return array + */ + private function getProjectConfig() + { + $composerJsonPath = $this->projectDir.'/composer.json'; + if (!is_writable($composerJsonPath)) { + return []; + } + + return json_decode(file_get_contents($composerJsonPath), true); + } + + /** + * It saves the given PHP array as the project's Composer config. In addition + * to JSON-serializing the contents, it synchronizes the composer.lock file to + * avoid out-of-sync Composer errors. + * + * @param array $config + */ + private function saveProjectConfig(array $config) + { + $composerJsonPath = $this->projectDir.'/composer.json'; + $this->fs->dumpFile($composerJsonPath, json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)."\n"); + + $this->syncComposerLockFile(); + } + + /** + * Updates the hash values stored in composer.lock to avoid out-of-sync + * problems when the composer.json file contents are changed. + */ + private function syncComposerLockFile() + { + $composerJsonFileContents = file_get_contents($this->projectDir.'/composer.json'); + $composerLockFileContents = json_decode(file_get_contents($this->projectDir.'/composer.lock'), true); + + if (array_key_exists('hash', $composerLockFileContents)) { + $composerLockFileContents['hash'] = md5($composerJsonFileContents); + } + + if (array_key_exists('content-hash', $composerLockFileContents)) { + $composerLockFileContents['content-hash'] = $this->getComposerContentHash($composerJsonFileContents); + } + + $this->fs->dumpFile($this->projectDir.'/composer.lock', json_encode($composerLockFileContents, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)."\n"); + } + + /** + * Returns the md5 hash of the sorted content of the composer file. + * + * @see https://github.com/composer/composer/blob/master/src/Composer/Package/Locker.php (getContentHash() method) + * + * @param string $composerJsonFileContents The contents of the composer.json file. + * + * @return string The hash of the composer file content. + */ + private function getComposerContentHash($composerJsonFileContents) + { + $composerConfig = json_decode($composerJsonFileContents, true); + + $relevantKeys = array( + 'name', + 'version', + 'require', + 'require-dev', + 'conflict', + 'replace', + 'provide', + 'minimum-stability', + 'prefer-stable', + 'repositories', + 'extra', + ); + + $relevantComposerConfig = array(); + + foreach (array_intersect($relevantKeys, array_keys($composerConfig)) as $key) { + $relevantComposerConfig[$key] = $composerConfig[$key]; + } + + if (isset($composerConfig['config']['platform'])) { + $relevantComposerConfig['config']['platform'] = $composerConfig['config']['platform']; + } + + ksort($relevantComposerConfig); + + return md5(json_encode($relevantComposerConfig)); + } + + /** + * Transforms a project name into a valid Composer package name. + * + * @param string $name The project name to transform + * + * @return string The valid Composer package name + */ + private function fixPackageName($name) + { + $name = str_replace( + ['à', 'á', 'â', 'ä', 'æ', 'ã', 'å', 'ā', 'é', 'è', 'ê', 'ë', 'ę', 'ė', 'ē', 'ī', 'į', 'í', 'ì', 'ï', 'î', 'ō', 'ø', 'œ', 'õ', 'ó', 'ò', 'ö', 'ô', 'ū', 'ú', 'ù', 'ü', 'û', 'ç', 'ć', 'č', 'ł', 'ñ', 'ń', 'ß', 'ś', 'š', 'ŵ', 'ŷ', 'ÿ', 'ź', 'ž', 'ż'], + ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'i', 'i', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'u', 'c', 'c', 'c', 'l', 'n', 'n', 's', 's', 's', 'w', 'y', 'y', 'z', 'z', 'z'], + $name + ); + $name = preg_replace('#[^A-Za-z0-9_./-]+#', '', $name); + + return strtolower($name); + } +} diff --git a/src/Symfony/Installer/NewCommand.php b/src/Symfony/Installer/NewCommand.php index e47a1c1..23e00cc 100644 --- a/src/Symfony/Installer/NewCommand.php +++ b/src/Symfony/Installer/NewCommand.php @@ -15,6 +15,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Installer\Exception\AbortException; +use Symfony\Installer\Manager\ComposerManager; /** * This command creates new Symfony projects for the given Symfony version. @@ -48,6 +49,8 @@ protected function initialize(InputInterface $input, OutputInterface $output) $this->version = trim($input->getArgument('version')); $this->projectDir = $this->fs->isAbsolutePath($directory) ? $directory : getcwd().DIRECTORY_SEPARATOR.$directory; $this->projectName = basename($directory); + + $this->composerManager = new ComposerManager($this->projectDir); } /** @@ -66,7 +69,7 @@ protected function execute(InputInterface $input, OutputInterface $output) ->cleanUp() ->dumpReadmeFile() ->updateParameters() - ->updateComposerJson() + ->updateComposerConfig() ->createGitIgnore() ->checkSymfonyRequirements() ->displayInstallationResult() @@ -322,72 +325,19 @@ protected function updateParameters() * * @return $this */ - protected function updateComposerJson() + protected function updateComposerConfig() { - parent::updateComposerJson(); - - $composerConfig = $this->getProjectComposerConfig(); - - $composerConfig['name'] = $this->generateComposerProjectName(); - $composerConfig['license'] = 'proprietary'; - - if (isset($composerConfig['description'])) { - unset($composerConfig['description']); - } - - if (isset($composerConfig['extra']['branch-alias'])) { - unset($composerConfig['extra']['branch-alias']); - } - - $this->saveProjectComposerConfig($composerConfig); + parent::updateComposerConfig(); + $this->composerManager->updateProjectConfig([ + 'name' => $this->composerManager->createPackageName($this->projectName), + 'license' => 'proprietary', + 'description' => null, + 'extra' => ['branch-alias' => null], + ]); return $this; } - /** - * Generates a good Composer project name based on the application name - * and on the user name. - * - * @return string The generated Composer project name - */ - protected function generateComposerProjectName() - { - $name = $this->projectName; - - if (!empty($_SERVER['USERNAME'])) { - $name = $_SERVER['USERNAME'].'/'.$name; - } elseif (true === extension_loaded('posix') && $user = posix_getpwuid(posix_getuid())) { - $name = $user['name'].'/'.$name; - } elseif (get_current_user()) { - $name = get_current_user().'/'.$name; - } else { - // package names must be in the format foo/bar - $name = $name.'/'.$name; - } - - return $this->fixComposerPackageName($name); - } - - /** - * Transforms uppercase strings into dash-separated strings - * (e.g. FooBar -> foo-bar) to comply with Composer rules for package names. - * - * @param string $name The project name to transform - * - * @return string The fixed Composer project name - */ - private function fixComposerPackageName($name) - { - $name = str_replace( - ['à', 'á', 'â', 'ä', 'æ', 'ã', 'å', 'ā', 'é', 'è', 'ê', 'ë', 'ę', 'ė', 'ē', 'ī', 'į', 'í', 'ì', 'ï', 'î', 'ō', 'ø', 'œ', 'õ', 'ó', 'ò', 'ö', 'ô', 'ū', 'ú', 'ù', 'ü', 'û', 'ç', 'ć', 'č', 'ł', 'ñ', 'ń', 'ß', 'ś', 'š', 'ŵ', 'ŷ', 'ÿ', 'ź', 'ž', 'ż'], - ['a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'e', 'e', 'e', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'i', 'i', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'u', 'u', 'u', 'u', 'u', 'c', 'c', 'c', 'l', 'n', 'n', 's', 's', 's', 'w', 'y', 'y', 'z', 'z', 'z'], - $name - ); - $name = preg_replace('#[^A-Za-z0-9_./-]+#', '', $name); - - return strtolower($name); - } - /** * {@inheritdoc} */ diff --git a/tests/Symfony/Installer/Tests/NewCommandTest.php b/tests/Symfony/Installer/Tests/Manager/ComposerManagerTest.php similarity index 53% rename from tests/Symfony/Installer/Tests/NewCommandTest.php rename to tests/Symfony/Installer/Tests/Manager/ComposerManagerTest.php index 6967299..6b8a14e 100644 --- a/tests/Symfony/Installer/Tests/NewCommandTest.php +++ b/tests/Symfony/Installer/Tests/Manager/ComposerManagerTest.php @@ -1,21 +1,21 @@ setAccessible(true); - $fixedName = $method->invoke($command, $originalName); + $fixedName = $method->invoke($composerManager, $originalName); $this->assertSame($expectedName, $fixedName); } From a455eeb779028c7883d0f454806cee4d0be7f652 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Mon, 10 Oct 2016 09:26:33 +0200 Subject: [PATCH 27/38] Use 'server:start' instead of 'server:run' when possible --- src/Symfony/Installer/DemoCommand.php | 6 ++++-- src/Symfony/Installer/NewCommand.php | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Installer/DemoCommand.php b/src/Symfony/Installer/DemoCommand.php index 8944c31..29db454 100644 --- a/src/Symfony/Installer/DemoCommand.php +++ b/src/Symfony/Installer/DemoCommand.php @@ -145,11 +145,13 @@ private function displayInstallationResult() )); } + $serverRunCommand = extension_loaded('pcntl') ? 'server:start' : 'server:run'; + $this->output->writeln(sprintf( " 1. Change your current directory to %s\n\n". - " 2. Execute the php bin/console server:run command to run the demo application.\n\n". + " 2. Execute the php bin/console %s command to run the demo application.\n\n". " 3. Browse to the http://localhost:8000 URL to see the demo application in action.\n\n", - $this->projectDir + $this->projectDir, $serverRunCommand )); return $this; diff --git a/src/Symfony/Installer/NewCommand.php b/src/Symfony/Installer/NewCommand.php index e47a1c1..9893d44 100644 --- a/src/Symfony/Installer/NewCommand.php +++ b/src/Symfony/Installer/NewCommand.php @@ -256,14 +256,15 @@ protected function displayInstallationResult() } $consoleDir = ($this->isSymfony3() ? 'bin' : 'app'); + $serverRunCommand = version_compare($this->version, '2.6.0', '>=') && extension_loaded('pcntl') ? 'server:start' : 'server:run'; $this->output->writeln(sprintf( " * Configure your application in app/config/parameters.yml file.\n\n". " * Run your application:\n". - " 1. Execute the php %s/console server:run command.\n". + " 1. Execute the php %s/console %s command.\n". " 2. Browse to the http://localhost:8000 URL.\n\n". " * Read the documentation at http://symfony.com/doc\n", - $consoleDir + $consoleDir, $serverRunCommand )); return $this; From e965861351b693b1459adb22049c4924cc825f4a Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 18 Oct 2016 16:24:08 +0200 Subject: [PATCH 28/38] Prepared the 1.5.9 release --- symfony | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/symfony b/symfony index 77977bd..b3fc5de 100755 --- a/symfony +++ b/symfony @@ -29,7 +29,7 @@ require file_exists(__DIR__.'/vendor/autoload.php') ? __DIR__.'/vendor/autoload.php' : __DIR__.'/../../autoload.php'; -$appVersion = '1.5.9-DEV'; +$appVersion = '1.5.9'; // Windows uses Path instead of PATH if (!isset($_SERVER['PATH']) && isset($_SERVER['Path'])) { From 436e8837fdd816e37f8e53afa8932c08ea36eff0 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 18 Oct 2016 16:39:48 +0200 Subject: [PATCH 29/38] Bumped development version --- symfony | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/symfony b/symfony index b3fc5de..1c4a17a 100755 --- a/symfony +++ b/symfony @@ -29,7 +29,7 @@ require file_exists(__DIR__.'/vendor/autoload.php') ? __DIR__.'/vendor/autoload.php' : __DIR__.'/../../autoload.php'; -$appVersion = '1.5.9'; +$appVersion = '1.5.10-DEV'; // Windows uses Path instead of PATH if (!isset($_SERVER['PATH']) && isset($_SERVER['Path'])) { From 2cfc573a35bd1eba33b80c44ab5a0c0ddf18cdfc Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Wed, 10 May 2017 10:14:47 +0200 Subject: [PATCH 30/38] Use https when refering to symfony.com --- composer.json | 2 +- src/Symfony/Installer/DemoCommand.php | 2 +- src/Symfony/Installer/NewCommand.php | 10 +++++----- src/Symfony/Installer/SelfUpdateCommand.php | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/composer.json b/composer.json index f2d3582..fc7cf5c 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,7 @@ "authors": [ { "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" + "homepage": "https://symfony.com/contributors" } ], "autoload": { diff --git a/src/Symfony/Installer/DemoCommand.php b/src/Symfony/Installer/DemoCommand.php index 3d1a2bf..ba72fbe 100644 --- a/src/Symfony/Installer/DemoCommand.php +++ b/src/Symfony/Installer/DemoCommand.php @@ -173,6 +173,6 @@ protected function getDownloadedApplicationType() */ protected function getRemoteFileUrl() { - return 'http://symfony.com/download?v=Symfony_Demo'; + return 'https://symfony.com/download?v=Symfony_Demo'; } } diff --git a/src/Symfony/Installer/NewCommand.php b/src/Symfony/Installer/NewCommand.php index 9c727d7..5f0bed5 100644 --- a/src/Symfony/Installer/NewCommand.php +++ b/src/Symfony/Installer/NewCommand.php @@ -97,7 +97,7 @@ protected function execute(InputInterface $input, OutputInterface $output) /** * Checks whether the given Symfony version is installable by the installer. * Due to the changes introduced in the Icu/Intl components - * (see http://symfony.com/blog/new-in-symfony-2-6-farewell-to-icu-component) + * (see https://symfony.com/blog/new-in-symfony-2-6-farewell-to-icu-component) * not all the previous Symfony versions are installable by the installer. * * The rules to decide if the version is installable are as follows: @@ -124,12 +124,12 @@ protected function checkSymfonyVersionIsInstallable() // 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(); + $symfonyVersions = $client->get('https://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' + 'https://symfony.com/versions.json' ); } @@ -266,7 +266,7 @@ protected function displayInstallationResult() " * Run your application:\n". " 1. Execute the php %s/console %s command.\n". " 2. Browse to the http://localhost:8000 URL.\n\n". - " * Read the documentation at http://symfony.com/doc\n", + " * Read the documentation at https://symfony.com/doc\n", $consoleDir, $serverRunCommand )); @@ -352,6 +352,6 @@ protected function getDownloadedApplicationType() */ protected function getRemoteFileUrl() { - return 'http://symfony.com/download?v=Symfony_Standard_Vendors_'.$this->version; + return 'https://symfony.com/download?v=Symfony_Standard_Vendors_'.$this->version; } } diff --git a/src/Symfony/Installer/SelfUpdateCommand.php b/src/Symfony/Installer/SelfUpdateCommand.php index 28b3890..2a93865 100644 --- a/src/Symfony/Installer/SelfUpdateCommand.php +++ b/src/Symfony/Installer/SelfUpdateCommand.php @@ -89,7 +89,7 @@ public function isEnabled() protected function initialize(InputInterface $input, OutputInterface $output) { parent::initialize($input, $output); - $this->remoteInstallerFile = 'http://symfony.com/installer'; + $this->remoteInstallerFile = 'https://symfony.com/installer'; $this->currentInstallerFile = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0]; $this->tempDir = sys_get_temp_dir(); $this->currentInstallerBackupFile = basename($this->currentInstallerFile, '.phar').'-backup.phar'; @@ -252,6 +252,6 @@ protected function getDownloadedApplicationType() */ protected function getRemoteFileUrl() { - return 'http://symfony.com/installer'; + return 'https://symfony.com/installer'; } } From 0272c23aa7bcbc6047f3c5646d2230e1039721bc Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Sun, 16 Jul 2017 11:43:39 +0200 Subject: [PATCH 31/38] Added a tip for people installing the Symfony Demo application --- .travis.yml | 6 +- composer.json | 3 +- composer.lock | 86 ++++++++++++++++--- src/Symfony/Installer/DownloadCommand.php | 14 +-- .../Installer/Tests/IntegrationTest.php | 40 ++++----- 5 files changed, 105 insertions(+), 44 deletions(-) diff --git a/.travis.yml b/.travis.yml index c46fe05..11424c2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,9 +12,7 @@ matrix: - php: 5.5 - php: 5.6 - php: 7.0 - - php: hhvm - allow_failures: - - php: hhvm + - php: 7.1 before_install: - composer self-update @@ -27,4 +25,4 @@ install: - ~/.phpenv/versions/5.6/bin/php box build script: - - phpunit + - ./vendor/bin/simple-phpunit diff --git a/composer.json b/composer.json index f2d3582..a14492d 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,8 @@ "raulfraile/distill": "~0.9,!=0.9.3,!=0.9.4" }, "require-dev": { - "symfony/process": "~2.5" + "symfony/process": "~2.5", + "symfony/phpunit-bridge": "^4.0" }, "extra": { "branch-alias": { diff --git a/composer.lock b/composer.lock index 32c1a8a..b82669d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "7587a63f96b596f379d4d830bee56119", - "content-hash": "3c97ce42899ed9440a9ef2cc5d78847f", + "content-hash": "8f72036c453520314de3967a312a6733", "packages": [ { "name": "guzzlehttp/guzzle", @@ -57,7 +56,7 @@ "rest", "web service" ], - "time": "2016-07-15 19:28:39" + "time": "2016-07-15T19:28:39+00:00" }, { "name": "guzzlehttp/ringphp", @@ -108,7 +107,7 @@ } ], "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.", - "time": "2015-05-20 03:37:09" + "time": "2015-05-20T03:37:09+00:00" }, { "name": "guzzlehttp/streams", @@ -158,7 +157,7 @@ "Guzzle", "stream" ], - "time": "2014-10-12 19:18:40" + "time": "2014-10-12T19:18:40+00:00" }, { "name": "pimple/pimple", @@ -204,7 +203,7 @@ "container", "dependency injection" ], - "time": "2015-09-11 15:10:35" + "time": "2015-09-11T15:10:35+00:00" }, { "name": "raulfraile/distill", @@ -273,7 +272,7 @@ "xz", "zip" ], - "time": "2015-10-17 06:41:00" + "time": "2015-10-17T06:41:00+00:00" }, { "name": "react/promise", @@ -317,7 +316,7 @@ } ], "description": "A lightweight implementation of CommonJS Promises/A for PHP", - "time": "2015-07-03 13:48:55" + "time": "2015-07-03T13:48:55+00:00" }, { "name": "symfony/console", @@ -374,7 +373,7 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2015-09-25 08:32:23" + "time": "2015-09-25T08:32:23+00:00" }, { "name": "symfony/filesystem", @@ -423,7 +422,7 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", - "time": "2015-09-09 17:42:36" + "time": "2015-09-09T17:42:36+00:00" }, { "name": "symfony/process", @@ -472,10 +471,73 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2015-09-19 19:59:23" + "time": "2015-09-19T19:59:23+00:00" + } + ], + "packages-dev": [ + { + "name": "symfony/phpunit-bridge", + "version": "v4.0.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/phpunit-bridge.git", + "reference": "61c84ebdce0d4c289413a222ee545f0114e60120" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/phpunit-bridge/zipball/61c84ebdce0d4c289413a222ee545f0114e60120", + "reference": "61c84ebdce0d4c289413a222ee545f0114e60120", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "conflict": { + "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" + }, + "suggest": { + "ext-zip": "Zip support is required when using bin/simple-phpunit", + "symfony/debug": "For tracking deprecated interfaces usages at runtime with DebugClassLoader" + }, + "bin": [ + "bin/simple-phpunit" + ], + "type": "symfony-bridge", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Bridge\\PhpUnit\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony PHPUnit Bridge", + "homepage": "https://symfony.com", + "time": "2017-12-14T19:48:22+00:00" } ], - "packages-dev": [], "aliases": [], "minimum-stability": "stable", "stability-flags": [], diff --git a/src/Symfony/Installer/DownloadCommand.php b/src/Symfony/Installer/DownloadCommand.php index 757d29f..b4634aa 100644 --- a/src/Symfony/Installer/DownloadCommand.php +++ b/src/Symfony/Installer/DownloadCommand.php @@ -134,7 +134,7 @@ protected function download() $symfonyArchiveFile = $distill ->getChooser() ->setStrategy(new MinimumSize()) - ->addFilesWithDifferentExtensions($this->getRemoteFileUrl(), ['tgz', 'zip']) + ->addFilesWithDifferentExtensions($this->getRemoteFileUrl(), array('tgz', 'zip')) ->getPreferredFile() ; @@ -184,7 +184,7 @@ protected function download() $request->getEmitter()->on('progress', $downloadCallback); $response = $client->send($request); } catch (ClientException $e) { - if ('new' === $this->getName() && ($e->getCode() === 403 || $e->getCode() === 404)) { + if ('new' === $this->getName() && (403 === $e->getCode() || 404 === $e->getCode())) { throw new \RuntimeException(sprintf( "The selected version (%s) cannot be installed because it does not exist.\n". "Execute the following command to install the latest stable Symfony release:\n". @@ -229,6 +229,10 @@ protected function checkProjectName() )); } + if ('demo' === $this->projectName && 'new' === $this->getName()) { + $this->output->writeln("\n TIP If you want to download the Symfony Demo app, execute 'symfony demo' instead of 'symfony new demo'"); + } + return $this; } @@ -413,7 +417,7 @@ protected function getInstalledSymfonyVersion() if (!empty($symfonyVersion) && 'v' === substr($symfonyVersion, 0, 1)) { return substr($symfonyVersion, 1); - }; + } return $symfonyVersion; } @@ -570,7 +574,7 @@ protected function getUrlContents($url) /** * Enables the signal handler. * - * @throws AbortException If the execution has been aborted with SIGINT signal. + * @throws AbortException if the execution has been aborted with SIGINT signal */ private function enableSignalHandler() { @@ -578,7 +582,7 @@ private function enableSignalHandler() return; } - declare(ticks = 1); + declare(ticks=1); pcntl_signal(SIGINT, function () { error_reporting(0); diff --git a/tests/Symfony/Installer/Tests/IntegrationTest.php b/tests/Symfony/Installer/Tests/IntegrationTest.php index 90a8d5a..963096f 100644 --- a/tests/Symfony/Installer/Tests/IntegrationTest.php +++ b/tests/Symfony/Installer/Tests/IntegrationTest.php @@ -52,11 +52,7 @@ public function testDemoApplicationInstallation() $this->assertContains('Downloading the Symfony Demo Application', $output); $this->assertContains('Symfony Demo Application was successfully installed.', $output); - $output = $this->runCommand('php bin/console --version', $projectDir); - $this->assertRegExp('/Symfony version 3\.\d+\.\d+(-DEV)? - app\/dev\/debug/', $output); - $composerConfig = json_decode(file_get_contents($projectDir.'/composer.json'), true); - $this->assertArrayNotHasKey('platform', $composerConfig['config'], 'The composer.json file does not define any platform configuration.'); } @@ -65,7 +61,7 @@ public function testDemoApplicationInstallation() */ public function testSymfonyInstallation($versionToInstall, $messageRegexp, $versionRegexp, $requiredPhpVersion) { - if (version_compare(phpversion(), $requiredPhpVersion, '<')) { + if (version_compare(PHP_VERSION, $requiredPhpVersion, '<')) { $this->markTestSkipped(sprintf('This test requires PHP %s or higher.', $requiredPhpVersion)); } @@ -76,14 +72,10 @@ public function testSymfonyInstallation($versionToInstall, $messageRegexp, $vers $this->assertContains('Downloading Symfony...', $output); $this->assertRegExp($messageRegexp, $output); - if ('3' === substr($versionToInstall, 0, 1) || '' === $versionToInstall) { - if (PHP_VERSION_ID < 50500) { - $this->markTestSkipped('Symfony 3 requires PHP 5.5.9 or higher.'); - } - - $output = $this->runCommand('php bin/console --version', $projectDir); - } else { + if (file_exists($projectDir.'/app/console')) { $output = $this->runCommand('php app/console --version', $projectDir); + } else { + $output = $this->runCommand('php bin/console --version', $projectDir); } $this->assertRegExp($versionRegexp, $output); @@ -122,6 +114,17 @@ public function testSymfonyInstallationInCurrentDirectory() $this->assertContains('Symfony version 2.7.5 - app/dev/debug', $output); } + public function testSymfonyDemoInstallationWithNewCommand() + { + if (PHP_VERSION_ID < 50500) { + $this->markTestSkipped('This test requires PHP 5.5 or higher.'); + } + + $output = $this->runCommand(sprintf('php %s/symfony.phar new demo 3.4', $this->rootDir)); + $this->assertContains("If you want to download the Symfony Demo app, execute 'symfony demo' instead of 'symfony new demo'", $output); + $this->fs->remove('demo'); + } + /** * Runs the given string as a command and returns the resulting output. * The CWD is set to the root project directory to simplify command paths. @@ -150,13 +153,6 @@ private function runCommand($command, $workingDirectory = null) public function provideSymfonyInstallationData() { return array( - array( - '', - '/.*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.*/', @@ -166,9 +162,9 @@ public function provideSymfonyInstallationData() array( 'lts', - '/.*Symfony 2\.8\.\d+ was successfully installed.*/', - '/Symfony version 2\.8\.\d+(-DEV)? - app\/dev\/debug/', - '5.3.9', + '/.*Symfony 3\.4\.\d+ was successfully installed.*/', + '/Symfony 3\.4\.\d+ \(kernel: app, env: dev, debug: true\)/', + '5.5.9', ), array( From ecb3967632e9a81851834551a42699e7a8e26db1 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 26 Dec 2017 12:14:22 +0100 Subject: [PATCH 32/38] Display a warning message when trying to install Symfony 4.x versions --- src/Symfony/Installer/NewCommand.php | 22 ++++++++++++++----- .../Installer/Tests/IntegrationTest.php | 13 +++++++++++ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Installer/NewCommand.php b/src/Symfony/Installer/NewCommand.php index 5f0bed5..b3bf403 100644 --- a/src/Symfony/Installer/NewCommand.php +++ b/src/Symfony/Installer/NewCommand.php @@ -139,7 +139,7 @@ protected function checkSymfonyVersionIsInstallable() 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 )); } @@ -173,11 +173,21 @@ protected function checkSymfonyVersionIsInstallable() } // 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', '<')) { + if (version_compare($this->version, '3.0.0', '>=') && version_compare(PHP_VERSION, '5.5.9', '<')) { throw new \RuntimeException(sprintf( "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() + $this->version, PHP_VERSION + )); + } + + // check that the Symfony version to be installed is not 4.x, which is incompatible with this installer + if (version_compare($this->version, '4.0.0', '>=')) { + throw new \RuntimeException(sprintf( + "The Symfony Installer is not compatible with Symfony 4.x or newer versions.\n". + "Run this other command to install Symfony using Composer instead:\n\n". + 'composer create-project symfony/skeleton %s', + $this->projectName )); } @@ -329,12 +339,12 @@ protected function updateParameters() protected function updateComposerConfig() { parent::updateComposerConfig(); - $this->composerManager->updateProjectConfig([ + $this->composerManager->updateProjectConfig(array( 'name' => $this->composerManager->createPackageName($this->projectName), 'license' => 'proprietary', 'description' => null, - 'extra' => ['branch-alias' => null], - ]); + 'extra' => array('branch-alias' => null), + )); return $this; } diff --git a/tests/Symfony/Installer/Tests/IntegrationTest.php b/tests/Symfony/Installer/Tests/IntegrationTest.php index 963096f..7ade375 100644 --- a/tests/Symfony/Installer/Tests/IntegrationTest.php +++ b/tests/Symfony/Installer/Tests/IntegrationTest.php @@ -101,6 +101,19 @@ public function testSymfonyRequiresNewerPhpVersion() $this->runCommand(sprintf('php %s/symfony.phar new my_test_project 3.0.0', $this->rootDir)); } + /** + * @expectedException \RuntimeException + * @expectedExceptionMessageRegExp /.+The Symfony Installer is not compatible with Symfony 4\.x or newer versions.*Run this other command to install Symfony using Composer instead:.*composer create-project symfony\/skeleton .+/s + */ + public function testUseComposerToInstallSymfony4() + { + if (PHP_VERSION_ID < 50500) { + $this->markTestSkipped('This test requires PHP 5.5 or newer.'); + } + + $this->runCommand(sprintf('php %s/symfony.phar new my_test_project', $this->rootDir)); + } + public function testSymfonyInstallationInCurrentDirectory() { $projectDir = sprintf('%s/my_test_project', sys_get_temp_dir()); From e3bf2ed78bbea1dce9f5454a136e5895b313d03a Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Wed, 27 Dec 2017 10:51:14 +0100 Subject: [PATCH 33/38] Prepare the 1.5.10 version release --- symfony | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/symfony b/symfony index 1c4a17a..3e179df 100755 --- a/symfony +++ b/symfony @@ -29,7 +29,7 @@ require file_exists(__DIR__.'/vendor/autoload.php') ? __DIR__.'/vendor/autoload.php' : __DIR__.'/../../autoload.php'; -$appVersion = '1.5.10-DEV'; +$appVersion = '1.5.10'; // Windows uses Path instead of PATH if (!isset($_SERVER['PATH']) && isset($_SERVER['Path'])) { From face333afef36267c587edf2e0075e0f5c7a746d Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Wed, 27 Dec 2017 10:53:04 +0100 Subject: [PATCH 34/38] Bumped development version --- symfony | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/symfony b/symfony index 3e179df..1f2e9a4 100755 --- a/symfony +++ b/symfony @@ -29,7 +29,7 @@ require file_exists(__DIR__.'/vendor/autoload.php') ? __DIR__.'/vendor/autoload.php' : __DIR__.'/../../autoload.php'; -$appVersion = '1.5.10'; +$appVersion = '1.5.11-DEV'; // Windows uses Path instead of PATH if (!isset($_SERVER['PATH']) && isset($_SERVER['Path'])) { From aa053a0672e720fdc298a22eaa2e48fe36f47c97 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Sun, 31 Dec 2017 13:39:12 +0100 Subject: [PATCH 35/38] Updated the README to no longer recommend using the Symfony Installer --- README.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 82d2257..aa9f633 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,21 @@ Symfony Installer ================= -**This is the official installer to start new projects based on the Symfony -full-stack framework.** +This is the official installer to start new projects based on the Symfony +full-stack framework. The installer is only compatible with Symfony 2 and 3. + +Creating Symfony 4 projects +--------------------------- + +**This installer is not compatible with Symfony 4** and newer versions. Instead, +use [Composer](https://getcomposer.org/) and create your Symfony 4 project as follows: + +```bash +$ composer create-project symfony/skeleton my_project_name +``` + +See the [Symfony Installation article](https://symfony.com/doc/current/setup.html) +on the official Symfony Documentation for more details. Installing the installer ------------------------ From 9de3bbeea60cc3aa0dc5b424daf2ff853260cf77 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Thu, 29 Mar 2018 15:52:03 +0200 Subject: [PATCH 36/38] Display a warning message when installing the Demo application --- src/Symfony/Installer/DemoCommand.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Symfony/Installer/DemoCommand.php b/src/Symfony/Installer/DemoCommand.php index ba72fbe..c941a78 100644 --- a/src/Symfony/Installer/DemoCommand.php +++ b/src/Symfony/Installer/DemoCommand.php @@ -157,6 +157,13 @@ private function displayInstallationResult() $this->projectDir, $serverRunCommand )); + $this->output->writeln( + " WARNING \n\n". + " This installer downloads the old Symfony Demo version based on Symfony 3.\n". + " If you prefer to install the new version based on Symfony 4 and Symfony Flex,\n". + " execute the following command:\n\n". + " composer create-project symfony/symfony-demo\n"); + return $this; } From bd73c8b50f471f4e219dacfc40e03a0aca442717 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Sun, 1 Apr 2018 13:14:00 +0200 Subject: [PATCH 37/38] Prepare the 1.5.11 release --- symfony | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/symfony b/symfony index 1f2e9a4..e1a476c 100755 --- a/symfony +++ b/symfony @@ -29,7 +29,7 @@ require file_exists(__DIR__.'/vendor/autoload.php') ? __DIR__.'/vendor/autoload.php' : __DIR__.'/../../autoload.php'; -$appVersion = '1.5.11-DEV'; +$appVersion = '1.5.11'; // Windows uses Path instead of PATH if (!isset($_SERVER['PATH']) && isset($_SERVER['Path'])) { From ac520353411281683ee5f27e23561bbcaa1ac048 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Sun, 1 Apr 2018 13:17:12 +0200 Subject: [PATCH 38/38] Bumped development version --- symfony | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/symfony b/symfony index e1a476c..b9f2d8d 100755 --- a/symfony +++ b/symfony @@ -29,7 +29,7 @@ require file_exists(__DIR__.'/vendor/autoload.php') ? __DIR__.'/vendor/autoload.php' : __DIR__.'/../../autoload.php'; -$appVersion = '1.5.11'; +$appVersion = '1.5.12-DEV'; // Windows uses Path instead of PATH if (!isset($_SERVER['PATH']) && isset($_SERVER['Path'])) {