@@ -168,6 +168,9 @@ public function __construct($cfgName, $evaluation, $approveCfgAbsence = false, $
168168 */
169169class RequirementCollection implements IteratorAggregate
170170{
171+ /**
172+ * @var Requirement[]
173+ */
171174 private $ requirements = array ();
172175
173176 /**
@@ -265,7 +268,7 @@ public function addCollection(RequirementCollection $collection)
265268 /**
266269 * Returns both requirements and recommendations.
267270 *
268- * @return array Array of Requirement instances
271+ * @return Requirement[]
269272 */
270273 public function all ()
271274 {
@@ -275,7 +278,7 @@ public function all()
275278 /**
276279 * Returns all mandatory requirements.
277280 *
278- * @return array Array of Requirement instances
281+ * @return Requirement[]
279282 */
280283 public function getRequirements ()
281284 {
@@ -292,7 +295,7 @@ public function getRequirements()
292295 /**
293296 * Returns the mandatory requirements that were not met.
294297 *
295- * @return array Array of Requirement instances
298+ * @return Requirement[]
296299 */
297300 public function getFailedRequirements ()
298301 {
@@ -309,7 +312,7 @@ public function getFailedRequirements()
309312 /**
310313 * Returns all optional recommendations.
311314 *
312- * @return array Array of Requirement instances
315+ * @return Requirement[]
313316 */
314317 public function getRecommendations ()
315318 {
@@ -326,7 +329,7 @@ public function getRecommendations()
326329 /**
327330 * Returns the recommendations that were not met.
328331 *
329- * @return array Array of Requirement instances
332+ * @return Requirement[]
330333 */
331334 public function getFailedRecommendations ()
332335 {
@@ -376,7 +379,8 @@ public function getPhpIniConfigPath()
376379 */
377380class SymfonyRequirements extends RequirementCollection
378381{
379- const REQUIRED_PHP_VERSION = '5.3.3 ' ;
382+ const LEGACY_REQUIRED_PHP_VERSION = '5.3.3 ' ;
383+ const REQUIRED_PHP_VERSION = '5.5.9 ' ;
380384
381385 /**
382386 * Constructor that initializes the requirements.
@@ -386,16 +390,26 @@ public function __construct()
386390 /* mandatory requirements follow */
387391
388392 $ installedPhpVersion = phpversion ();
393+ $ requiredPhpVersion = $ this ->getPhpRequiredVersion ();
389394
390- $ this ->addRequirement (
391- version_compare ($ installedPhpVersion , self ::REQUIRED_PHP_VERSION , '>= ' ),
392- sprintf ('PHP version must be at least %s (%s installed) ' , self ::REQUIRED_PHP_VERSION , $ installedPhpVersion ),
393- sprintf ('You are running PHP version "<strong>%s</strong>", but Symfony needs at least PHP "<strong>%s</strong>" to run.
394- Before using Symfony, upgrade your PHP installation, preferably to the latest version. ' ,
395- $ installedPhpVersion , self ::REQUIRED_PHP_VERSION ),
396- sprintf ('Install PHP %s or newer (installed version is %s) ' , self ::REQUIRED_PHP_VERSION , $ installedPhpVersion )
395+ $ this ->addRecommendation (
396+ $ requiredPhpVersion ,
397+ 'Vendors should be installed in order to check all requirements. ' ,
398+ 'Run the <code>composer install</code> command. ' ,
399+ 'Run the "composer install" command. '
397400 );
398401
402+ if (false !== $ requiredPhpVersion ) {
403+ $ this ->addRequirement (
404+ version_compare ($ installedPhpVersion , $ requiredPhpVersion , '>= ' ),
405+ sprintf ('PHP version must be at least %s (%s installed) ' , $ requiredPhpVersion , $ installedPhpVersion ),
406+ sprintf ('You are running PHP version "<strong>%s</strong>", but Symfony needs at least PHP "<strong>%s</strong>" to run.
407+ Before using Symfony, upgrade your PHP installation, preferably to the latest version. ' ,
408+ $ installedPhpVersion , $ requiredPhpVersion ),
409+ sprintf ('Install PHP %s or newer (installed version is %s) ' , $ requiredPhpVersion , $ installedPhpVersion )
410+ );
411+ }
412+
399413 $ this ->addRequirement (
400414 version_compare ($ installedPhpVersion , '5.3.16 ' , '!= ' ),
401415 'PHP version must not be 5.3.16 as Symfony won \'t work properly with it ' ,
@@ -431,7 +445,7 @@ public function __construct()
431445 'Set the "<strong>date.timezone</strong>" setting in php.ini<a href="#phpini">*</a> (like Europe/Paris). '
432446 );
433447
434- if (version_compare ($ installedPhpVersion , self :: REQUIRED_PHP_VERSION , '>= ' )) {
448+ if (false !== $ requiredPhpVersion && version_compare ($ installedPhpVersion , $ requiredPhpVersion , '>= ' )) {
435449 $ timezones = array ();
436450 foreach (DateTimeZone::listAbbreviations () as $ abbreviations ) {
437451 foreach ($ abbreviations as $ abbreviation ) {
@@ -446,6 +460,12 @@ public function __construct()
446460 );
447461 }
448462
463+ $ this ->addRequirement (
464+ function_exists ('iconv ' ),
465+ 'iconv() must be available ' ,
466+ 'Install and enable the <strong>iconv</strong> extension. '
467+ );
468+
449469 $ this ->addRequirement (
450470 function_exists ('json_encode ' ),
451471 'json_encode() must be available ' ,
@@ -546,10 +566,10 @@ function_exists('simplexml_import_dom'),
546566 require_once __DIR__ .'/../vendor/autoload.php ' ;
547567
548568 try {
549- $ r = new \ ReflectionClass ('Sensio\Bundle\DistributionBundle\SensioDistributionBundle ' );
569+ $ r = new ReflectionClass ('Sensio\Bundle\DistributionBundle\SensioDistributionBundle ' );
550570
551571 $ contents = file_get_contents (dirname ($ r ->getFileName ()).'/Resources/skeleton/app/SymfonyRequirements.php ' );
552- } catch (\ ReflectionException $ e ) {
572+ } catch (ReflectionException $ e ) {
553573 $ contents = '' ;
554574 }
555575 $ this ->addRecommendation (
@@ -702,9 +722,9 @@ function_exists('posix_isatty'),
702722
703723 if (strtoupper (substr (PHP_OS , 0 , 3 )) === 'WIN ' ) {
704724 $ this ->addRecommendation (
705- $ this ->getRealpathCacheSize () > 1000 ,
706- 'realpath_cache_size should be above 1024 in php.ini ' ,
707- 'Set "<strong>realpath_cache_size</strong>" to e.g. "<strong>1024 </strong>" in php.ini<a href="#phpini">*</a> to improve performance on windows . '
725+ $ this ->getRealpathCacheSize () >= 5 * 1024 * 1024 ,
726+ 'realpath_cache_size should be at least 5M in php.ini ' ,
727+ 'Setting "<strong>realpath_cache_size</strong>" to e.g. "<strong>5242880 </strong>" or "<strong>5M</strong>" in php.ini<a href="#phpini">*</a> may improve performance on Windows significantly in some cases . '
708728 );
709729 }
710730
@@ -743,7 +763,11 @@ protected function getRealpathCacheSize()
743763 {
744764 $ size = ini_get ('realpath_cache_size ' );
745765 $ size = trim ($ size );
746- $ unit = strtolower (substr ($ size , -1 , 1 ));
766+ $ unit = '' ;
767+ if (!ctype_digit ($ size )) {
768+ $ unit = strtolower (substr ($ size , -1 , 1 ));
769+ $ size = (int ) substr ($ size , 0 , -1 );
770+ }
747771 switch ($ unit ) {
748772 case 'g ' :
749773 return $ size * 1024 * 1024 * 1024 ;
@@ -755,4 +779,28 @@ protected function getRealpathCacheSize()
755779 return (int ) $ size ;
756780 }
757781 }
782+
783+ /**
784+ * Defines PHP required version from Symfony version.
785+ *
786+ * @return string|false The PHP required version or false if it could not be guessed
787+ */
788+ protected function getPhpRequiredVersion ()
789+ {
790+ if (!file_exists ($ path = __DIR__ .'/../composer.lock ' )) {
791+ return false ;
792+ }
793+
794+ $ composerLock = json_decode (file_get_contents ($ path ), true );
795+ foreach ($ composerLock ['packages ' ] as $ package ) {
796+ $ name = $ package ['name ' ];
797+ if ('symfony/symfony ' !== $ name && 'symfony/http-kernel ' !== $ name ) {
798+ continue ;
799+ }
800+
801+ return (int ) $ package ['version ' ][1 ] > 2 ? self ::REQUIRED_PHP_VERSION : self ::LEGACY_REQUIRED_PHP_VERSION ;
802+ }
803+
804+ return false ;
805+ }
758806}
0 commit comments