diff --git a/.php_cs.dist b/.php_cs.dist index a73e16918c9f3..c0011033990d8 100644 --- a/.php_cs.dist +++ b/.php_cs.dist @@ -8,6 +8,8 @@ return PhpCsFixer\Config::create() ->setRules(array( '@Symfony' => true, '@Symfony:risky' => true, + '@PHPUnit48Migration:risky' => true, + 'php_unit_no_expectation_annotation' => false, // part of `PHPUnitXYMigration:risky` ruleset, to be enabled when PHPUnit 4.x support will be dropped, as we don't want to rewrite exceptions handling twice 'array_syntax' => array('syntax' => 'long'), 'protected_to_private' => false, )) @@ -30,16 +32,13 @@ return PhpCsFixer\Config::create() )) // file content autogenerated by `var_export` ->notPath('Symfony/Component/Translation/Tests/fixtures/resources.php') - // autogenerated xmls - ->notPath('Symfony/Component/Console/Tests/Fixtures/application_1.xml') - ->notPath('Symfony/Component/Console/Tests/Fixtures/application_2.xml') - // yml - ->notPath('Symfony/Component/Yaml/Tests/Fixtures/sfTests.yml') // test template ->notPath('Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Custom/_name_entry_label.html.php') // explicit heredoc test ->notPath('Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Resources/views/translation.html.php') - // purposefully invalid JSON - ->notPath('Symfony/Component/Asset/Tests/fixtures/manifest-invalid.json') + // explicit trigger_error tests + ->notPath('Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/default.phpt') + ->notPath('Symfony/Bridge/PhpUnit/Tests/DeprecationErrorHandler/weak.phpt') + ->notPath('Symfony/Component/Debug/Tests/DebugClassLoaderTest.php') ) ; diff --git a/CHANGELOG-4.0.md b/CHANGELOG-4.0.md index 7efe25d165fff..af2487c409bd7 100644 --- a/CHANGELOG-4.0.md +++ b/CHANGELOG-4.0.md @@ -7,6 +7,37 @@ in 4.0 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v4.0.0...v4.0.1 +* 4.0.3 (2018-01-05) + + * bug #25685 Use triggering file to determine weak vendors if when the test is run in a separate process (alexpott) + * bug #25671 Remove randomness from dumped containers (nicolas-grekas) + * bug #25532 [HttpKernel] Disable CSP header on exception pages (ostrolucky) + * bug #25678 [WebProfilerBundle] set the var in the right scope (Jochen Mandl) + * bug #25491 [Routing] Use the default host even if context is empty (sroze) + * bug #25672 [WebServerBundle] use interface_exists instead of class_exists (kbond) + * bug #25662 Dumper shouldn't use html format for phpdbg / cli-server (jhoff) + * bug #25529 [Validator] Fix access to root object when using composite constraint (ostrolucky) + * bug #25404 [Form] Remove group options without data on debug:form command (yceruto) + * bug #25430 Fixes for Oracle in PdoSessionHandler (elislenio) + * bug #25117 [FrameworkBundle] Make cache:clear "atomic" and consistent with cache:warmup (hkdobrev) + * bug #25583 [HttpKernel] Call Response->setPrivate() instead of sending raw header() when session is started (Toflar) + * bug #25601 [TwigBundle/Brige] catch missing requirements to throw meaningful exceptions (nicolas-grekas) + * bug #25547 [DX][DependencyInjection] Suggest to write an implementation if the interface cannot be autowired (sroze) + * bug #25599 Add application/ld+json format associated to json (vincentchalamon) + * bug #25623 [HttpFoundation] Fix false-positive ConflictingHeadersException (nicolas-grekas) + * bug #25624 [WebServerBundle] Fix escaping of php binary with arguments (nicolas-grekas) + * bug #25604 Add check for SecurityBundle in createAccessDeniedException (FGM) + * bug #25591 [HttpKernel] fix cleaning legacy containers (nicolas-grekas) + * bug #25526 [WebProfilerBundle] Fix panel break when stopwatch component is not installed. (umulmrum, javiereguiluz) + * bug #25606 Updating message to inform the user how to install the component (weaverryan) + * bug #25571 [SecurityBundle] allow auto_wire for SessionAuthenticationStrategy class (xavren) + * bug #25567 [Process] Fix setting empty env vars (nicolas-grekas) + * bug #25407 [Console] Commands with an alias should not be recognized as ambiguous (Simperfit) + * bug #25523 [WebServerBundle] fix a bug where require would not require the good file because of env (Simperfit) + * bug #25559 [Process] Dont use getenv(), it returns arrays and can introduce subtle breaks accros PHP versions (nicolas-grekas) + * bug #25552 [WebProfilerBundle] Let fetch() cast URL to string (ro0NL) + * bug #25521 [Console] fix a bug when you are passing a default value and passing -n would output the index (Simperfit) + * 4.0.2 (2017-12-15) * bug #25489 [FrameworkBundle] remove esi/ssi renderers if inactive (dmaicher) diff --git a/LICENSE b/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 0cee61b0cfcb1..ee9d187638fab 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -535,11 +535,11 @@ FrameworkBundle first argument. * `RouterDebugCommand::__construct()` now requires an instance of - `Symfony\Component\Routing\RouterInteface` as + `Symfony\Component\Routing\RouterInterface` as first argument. * `RouterMatchCommand::__construct()` now requires an instance of - `Symfony\Component\Routing\RouterInteface` as + `Symfony\Component\Routing\RouterInterface` as first argument. * `TranslationDebugCommand::__construct()` now requires an instance of @@ -627,7 +627,7 @@ HttpKernel # ... # explicit commands registration - AppBundle\Command: + AppBundle\Command\: resource: '../../src/AppBundle/Command/*' tags: ['console.command'] ``` diff --git a/src/Symfony/Bridge/Doctrine/LICENSE b/src/Symfony/Bridge/Doctrine/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Bridge/Doctrine/LICENSE +++ b/src/Symfony/Bridge/Doctrine/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php index fd09e82ded922..c019c31a9ac06 100644 --- a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php +++ b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php @@ -12,7 +12,6 @@ namespace Symfony\Bridge\Doctrine; use ProxyManager\Proxy\LazyLoadingInterface; -use Psr\Container\ContainerInterface; use Symfony\Component\DependencyInjection\Container; use Doctrine\Common\Persistence\AbstractManagerRegistry; @@ -24,7 +23,7 @@ abstract class ManagerRegistry extends AbstractManagerRegistry { /** - * @var ContainerInterface + * @var Container */ protected $container; @@ -58,7 +57,7 @@ function (&$wrappedInstance, LazyLoadingInterface $manager) use ($name) { $name = $this->aliases[$name]; } if (isset($this->fileMap[$name])) { - $wrappedInstance = $this->load($this->fileMap[$name], false); + $wrappedInstance = $this->load($this->fileMap[$name]); } else { $method = $this->methodMap[$name] ?? 'get'.strtr($name, $this->underscoreMap).'Service'; // BC with DI v3.4 $wrappedInstance = $this->{$method}(false); diff --git a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterMappingsPassTest.php b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterMappingsPassTest.php index ed76f8db68dfd..692ee89e4bede 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterMappingsPassTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterMappingsPassTest.php @@ -15,8 +15,7 @@ class RegisterMappingsPassTest extends TestCase */ public function testNoDriverParmeterException() { - $container = $this->createBuilder(array( - )); + $container = $this->createBuilder(); $this->process($container, array( 'manager.param.one', 'manager.param.two', diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/DoctrineChoiceLoaderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/DoctrineChoiceLoaderTest.php index 4999bda42ef57..b24a374fedf59 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/DoctrineChoiceLoaderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/DoctrineChoiceLoaderTest.php @@ -19,12 +19,18 @@ use Symfony\Bridge\Doctrine\Form\ChoiceList\EntityLoaderInterface; use Symfony\Bridge\Doctrine\Form\ChoiceList\IdReader; use Symfony\Component\Form\ChoiceList\ArrayChoiceList; +use Symfony\Component\Form\ChoiceList\Factory\ChoiceListFactoryInterface; /** * @author Bernhard Schussek */ class DoctrineChoiceLoaderTest extends TestCase { + /** + * @var ChoiceListFactoryInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $factory; + /** * @var ObjectManager|\PHPUnit_Framework_MockObject_MockObject */ diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php index c41629b4dea99..0213714397322 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php @@ -31,7 +31,6 @@ use Symfony\Component\Form\Forms; use Symfony\Component\Form\Tests\Extension\Core\Type\BaseTypeTest; use Symfony\Component\Form\Tests\Extension\Core\Type\FormTypeTest; -use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleAssociationToIntIdEntity; use Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdNoToStringEntity; @@ -1120,10 +1119,7 @@ public function testLoaderCaching() $repo = $this->em->getRepository(self::SINGLE_IDENT_CLASS); - $entityType = new EntityType( - $this->emRegistry, - PropertyAccess::createPropertyAccessor() - ); + $entityType = new EntityType($this->emRegistry); $entityTypeGuesser = new DoctrineOrmTypeGuesser($this->emRegistry); @@ -1183,10 +1179,7 @@ public function testLoaderCachingWithParameters() $repo = $this->em->getRepository(self::SINGLE_IDENT_CLASS); - $entityType = new EntityType( - $this->emRegistry, - PropertyAccess::createPropertyAccessor() - ); + $entityType = new EntityType($this->emRegistry); $entityTypeGuesser = new DoctrineOrmTypeGuesser($this->emRegistry); diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php index 2f86ac0dde632..fd6c23279c83d 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Bridge\Doctrine\PropertyInfo\Tests; +namespace Symfony\Bridge\Doctrine\Tests\PropertyInfo; use Doctrine\DBAL\Types\Type as DBALType; use Doctrine\ORM\EntityManager; diff --git a/src/Symfony/Bridge/Monolog/LICENSE b/src/Symfony/Bridge/Monolog/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Bridge/Monolog/LICENSE +++ b/src/Symfony/Bridge/Monolog/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php index a108126a2eed8..2f1bd008fa31b 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php @@ -107,7 +107,7 @@ public static function register($mode = 0) $trace = debug_backtrace(true); $group = 'other'; - + $isVendor = false; $isWeak = DeprecationErrorHandler::MODE_WEAK === $mode || (DeprecationErrorHandler::MODE_WEAK_VENDORS === $mode && $isVendor = $inVendors($file)); $i = count($trace); @@ -121,6 +121,11 @@ public static function register($mode = 0) $msg = $parsedMsg['deprecation']; $class = $parsedMsg['class']; $method = $parsedMsg['method']; + // If the deprecation has been triggered via + // \Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerTrait::endTest() + // then we need to use the serialized information to determine + // if the error has been triggered from vendor code. + $isWeak = DeprecationErrorHandler::MODE_WEAK === $mode || (DeprecationErrorHandler::MODE_WEAK_VENDORS === $mode && $isVendor = isset($parsedMsg['triggering_file']) && $inVendors($parsedMsg['triggering_file'])); } else { $class = isset($trace[$i]['object']) ? get_class($trace[$i]['object']) : $trace[$i]['class']; $method = $trace[$i]['function']; @@ -261,7 +266,7 @@ public static function collectDeprecations($outputFile) return $ErrorHandler::handleError($type, $msg, $file, $line, $context); } - $deprecations[] = array(error_reporting(), $msg); + $deprecations[] = array(error_reporting(), $msg, $file); }); register_shutdown_function(function () use ($outputFile, &$deprecations) { diff --git a/src/Symfony/Bridge/PhpUnit/LICENSE b/src/Symfony/Bridge/PhpUnit/LICENSE index 207646a052dcd..15fc1c88d330b 100644 --- a/src/Symfony/Bridge/PhpUnit/LICENSE +++ b/src/Symfony/Bridge/PhpUnit/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2014-2017 Fabien Potencier +Copyright (c) 2014-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php index cbc21b9e44005..7ded32a782464 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php @@ -263,10 +263,11 @@ public function endTest($test, $time) unlink($this->runsInSeparateProcess); putenv('SYMFONY_DEPRECATIONS_SERIALIZE'); foreach ($deprecations ? unserialize($deprecations) : array() as $deprecation) { + $error = serialize(array('deprecation' => $deprecation[1], 'class' => $className, 'method' => $test->getName(false), 'triggering_file' => isset($deprecation[2]) ? $deprecation[2] : null)); if ($deprecation[0]) { - trigger_error(serialize(array('deprecation' => $deprecation[1], 'class' => $className, 'method' => $test->getName(false))), E_USER_DEPRECATED); + trigger_error($error, E_USER_DEPRECATED); } else { - @trigger_error(serialize(array('deprecation' => $deprecation[1], 'class' => $className, 'method' => $test->getName(false))), E_USER_DEPRECATED); + @trigger_error($error, E_USER_DEPRECATED); } } $this->runsInSeparateProcess = false; diff --git a/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php b/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php index b07effe3d27dc..b408b74010bd9 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php @@ -12,10 +12,6 @@ public function test() $this->markTestSkipped('This test cannot be run on Windows.'); } - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('This test cannot be run on HHVM.'); - } - if (\PHP_VERSION_ID >= 70000) { $php = 'phpdbg -qrr'; } else { diff --git a/src/Symfony/Bridge/PhpUnit/composer.json b/src/Symfony/Bridge/PhpUnit/composer.json index cdaafa0610976..2b6d8dca2c6c3 100644 --- a/src/Symfony/Bridge/PhpUnit/composer.json +++ b/src/Symfony/Bridge/PhpUnit/composer.json @@ -41,6 +41,10 @@ "extra": { "branch-alias": { "dev-master": "4.0-dev" + }, + "thanks": { + "name": "phpunit/phpunit", + "url": "https://github.com/sebastianbergmann/phpunit" } } } diff --git a/src/Symfony/Bridge/ProxyManager/LICENSE b/src/Symfony/Bridge/ProxyManager/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Bridge/ProxyManager/LICENSE +++ b/src/Symfony/Bridge/ProxyManager/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Bridge/Twig/LICENSE b/src/Symfony/Bridge/Twig/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Bridge/Twig/LICENSE +++ b/src/Symfony/Bridge/Twig/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php index b20e0c3905a3a..88a39b1ea9604 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php @@ -88,18 +88,35 @@ public function getTransTests() array('{% trans into "fr"%}Hello{% endtrans %}', 'Hello'), // transchoice - array('{% transchoice count from "messages" %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtranschoice %}', - 'There is no apples', array('count' => 0)), - array('{% transchoice count %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtranschoice %}', - 'There is 5 apples', array('count' => 5)), - array('{% transchoice count %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples (%name%){% endtranschoice %}', - 'There is 5 apples (Symfony)', array('count' => 5, 'name' => 'Symfony')), - array('{% transchoice count with { \'%name%\': \'Symfony\' } %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples (%name%){% endtranschoice %}', - 'There is 5 apples (Symfony)', array('count' => 5)), - array('{% transchoice count into "fr"%}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtranschoice %}', - 'There is no apples', array('count' => 0)), - array('{% transchoice 5 into "fr"%}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtranschoice %}', - 'There is 5 apples'), + array( + '{% transchoice count from "messages" %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtranschoice %}', + 'There is no apples', + array('count' => 0), + ), + array( + '{% transchoice count %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtranschoice %}', + 'There is 5 apples', + array('count' => 5), + ), + array( + '{% transchoice count %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples (%name%){% endtranschoice %}', + 'There is 5 apples (Symfony)', + array('count' => 5, 'name' => 'Symfony'), + ), + array( + '{% transchoice count with { \'%name%\': \'Symfony\' } %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples (%name%){% endtranschoice %}', + 'There is 5 apples (Symfony)', + array('count' => 5), + ), + array( + '{% transchoice count into "fr"%}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtranschoice %}', + 'There is no apples', + array('count' => 0), + ), + array( + '{% transchoice 5 into "fr"%}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtranschoice %}', + 'There is 5 apples', + ), // trans filter array('{{ "Hello"|trans }}', 'Hello'), diff --git a/src/Symfony/Bridge/Twig/UndefinedCallableHandler.php b/src/Symfony/Bridge/Twig/UndefinedCallableHandler.php new file mode 100644 index 0000000000000..2a86b0d53679f --- /dev/null +++ b/src/Symfony/Bridge/Twig/UndefinedCallableHandler.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Twig; + +use Twig\Error\SyntaxError; + +/** + * @internal + */ +class UndefinedCallableHandler +{ + private static $filterComponents = array( + 'humanize' => 'form', + 'trans' => 'translation', + 'transchoice' => 'translation', + 'yaml_encode' => 'yaml', + 'yaml_dump' => 'yaml', + ); + + private static $functionComponents = array( + 'asset' => 'asset', + 'asset_version' => 'asset', + 'dump' => 'debug-bundle', + 'expression' => 'expression-language', + 'form_widget' => 'form', + 'form_errors' => 'form', + 'form_label' => 'form', + 'form_row' => 'form', + 'form_rest' => 'form', + 'form' => 'form', + 'form_start' => 'form', + 'form_end' => 'form', + 'csrf_token' => 'form', + 'logout_url' => 'security-http', + 'logout_path' => 'security-http', + 'is_granted' => 'security-core', + 'link' => 'web-link', + 'preload' => 'web-link', + 'dns_prefetch' => 'web-link', + 'preconnect' => 'web-link', + 'prefetch' => 'web-link', + 'prerender' => 'web-link', + 'workflow_can' => 'workflow', + 'workflow_transitions' => 'workflow', + 'workflow_has_marked_place' => 'workflow', + 'workflow_marked_places' => 'workflow', + ); + + public static function onUndefinedFilter($name) + { + if (!isset(self::$filterComponents[$name])) { + return false; + } + + // Twig will append the source context to the message, so that it will end up being like "[...] Unknown filter "%s" in foo.html.twig on line 123." + throw new SyntaxError(sprintf('Did you forget to run "composer require symfony/%s"? Unknown filter "%s".', $name, self::$filterComponents[$name])); + } + + public static function onUndefinedFunction($name) + { + if (!isset(self::$functionComponents[$name])) { + return false; + } + + throw new SyntaxError(sprintf('Did you forget to run "composer require symfony/%s"? Unknown function "%s".', $name, self::$functionComponents[$name])); + } +} diff --git a/src/Symfony/Bundle/DebugBundle/LICENSE b/src/Symfony/Bundle/DebugBundle/LICENSE index 207646a052dcd..15fc1c88d330b 100644 --- a/src/Symfony/Bundle/DebugBundle/LICENSE +++ b/src/Symfony/Bundle/DebugBundle/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2014-2017 Fabien Potencier +Copyright (c) 2014-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index a393db1acf850..e2d5d2be686a4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -67,10 +67,10 @@ CHANGELOG `Symfony\Component\EventDispatcher\EventDispatcherInterface` as first argument * `RouterDebugCommand::__construct()` now takes an instance of - `Symfony\Component\Routing\RouterInteface` as + `Symfony\Component\Routing\RouterInterface` as first argument * `RouterMatchCommand::__construct()` now takes an instance of - `Symfony\Component\Routing\RouterInteface` as + `Symfony\Component\Routing\RouterInterface` as first argument * `TranslationDebugCommand::__construct()` now takes an instance of `Symfony\Component\Translation\TranslatorInterface` as diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php index 6894604e6900f..a33b3f3d908dd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php @@ -73,6 +73,7 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { + $fs = $this->filesystem; $io = new SymfonyStyle($input, $output); $kernel = $this->getApplication()->getKernel(); @@ -80,25 +81,46 @@ protected function execute(InputInterface $input, OutputInterface $output) // the old cache dir name must not be longer than the real one to avoid exceeding // the maximum length of a directory or file path within it (esp. Windows MAX_PATH) $oldCacheDir = substr($realCacheDir, 0, -1).('~' === substr($realCacheDir, -1) ? '+' : '~'); + $fs->remove($oldCacheDir); if (!is_writable($realCacheDir)) { throw new \RuntimeException(sprintf('Unable to write in the "%s" directory', $realCacheDir)); } - if ($this->filesystem->exists($oldCacheDir)) { - $this->filesystem->remove($oldCacheDir); - } - $io->comment(sprintf('Clearing the cache for the %s environment with debug %s', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); $this->cacheClearer->clear($realCacheDir); // The current event dispatcher is stale, let's not use it anymore $this->getApplication()->setDispatcher(new EventDispatcher()); - if ($input->getOption('no-warmup')) { - $this->filesystem->rename($realCacheDir, $oldCacheDir); - } else { - $this->warmupCache($input, $output, $realCacheDir, $oldCacheDir); + $containerDir = new \ReflectionObject($kernel->getContainer()); + $containerDir = basename(dirname($containerDir->getFileName())); + + // the warmup cache dir name must have the same length as the real one + // to avoid the many problems in serialized resources files + $warmupDir = substr($realCacheDir, 0, -1).('_' === substr($realCacheDir, -1) ? '-' : '_'); + + if ($output->isVerbose() && $fs->exists($warmupDir)) { + $io->comment('Clearing outdated warmup directory...'); + } + $fs->remove($warmupDir); + $fs->mkdir($warmupDir); + + if (!$input->getOption('no-warmup')) { + if ($output->isVerbose()) { + $io->comment('Warming up cache...'); + } + $this->warmup($warmupDir, $realCacheDir, !$input->getOption('no-optional-warmers')); + } + + $containerDir = $fs->exists($warmupDir.'/'.$containerDir) ? false : $containerDir; + + $fs->rename($realCacheDir, $oldCacheDir); + $fs->rename($warmupDir, $realCacheDir); + + if ($containerDir) { + $fs->rename($oldCacheDir.'/'.$containerDir, $realCacheDir.'/'.$containerDir); + touch($realCacheDir.'/'.$containerDir.'.legacy'); } if ($output->isVerbose()) { @@ -106,7 +128,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } try { - $this->filesystem->remove($oldCacheDir); + $fs->remove($oldCacheDir); } catch (IOException $e) { $io->warning($e->getMessage()); } @@ -118,34 +140,6 @@ protected function execute(InputInterface $input, OutputInterface $output) $io->success(sprintf('Cache for the "%s" environment (debug=%s) was successfully cleared.', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); } - private function warmupCache(InputInterface $input, OutputInterface $output, string $realCacheDir, string $oldCacheDir) - { - $io = new SymfonyStyle($input, $output); - - // the warmup cache dir name must have the same length than the real one - // to avoid the many problems in serialized resources files - $realCacheDir = realpath($realCacheDir); - $warmupDir = substr($realCacheDir, 0, -1).('_' === substr($realCacheDir, -1) ? '-' : '_'); - - if ($this->filesystem->exists($warmupDir)) { - if ($output->isVerbose()) { - $io->comment('Clearing outdated warmup directory...'); - } - $this->filesystem->remove($warmupDir); - } - - if ($output->isVerbose()) { - $io->comment('Warming up cache...'); - } - $this->warmup($warmupDir, $realCacheDir, !$input->getOption('no-optional-warmers')); - - $this->filesystem->rename($realCacheDir, $oldCacheDir); - if ('\\' === DIRECTORY_SEPARATOR) { - sleep(1); // workaround for Windows PHP rename bug - } - $this->filesystem->rename($warmupDir, $realCacheDir); - } - private function warmup(string $warmupDir, string $realCacheDir, bool $enableOptionalWarmers = true) { // create a temporary kernel diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php index 96b4fa10fb22a..6fc94bc8a2a20 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php @@ -153,7 +153,7 @@ protected function file($file, string $fileName = null, string $disposition = Re protected function addFlash(string $type, string $message) { if (!$this->container->has('session')) { - throw new \LogicException('You can not use the addFlash method if sessions are disabled.'); + throw new \LogicException('You can not use the addFlash method if sessions are disabled. Enable them in "config/packages/framework.yaml".'); } $this->container->get('session')->getFlashBag()->add($type, $message); @@ -169,7 +169,7 @@ protected function addFlash(string $type, string $message) protected function isGranted($attributes, $subject = null): bool { if (!$this->container->has('security.authorization_checker')) { - throw new \LogicException('The SecurityBundle is not registered in your application.'); + throw new \LogicException('The SecurityBundle is not registered in your application. Try running "composer require symfony/security-bundle".'); } return $this->container->get('security.authorization_checker')->isGranted($attributes, $subject); @@ -206,7 +206,7 @@ protected function renderView(string $view, array $parameters = array()): string } if (!$this->container->has('twig')) { - throw new \LogicException('You can not use the "renderView" method if the Templating Component or the Twig Bundle are not available.'); + throw new \LogicException('You can not use the "renderView" method if the Templating Component or the Twig Bundle are not available. Try running "composer require symfony/twig-bundle".'); } return $this->container->get('twig')->render($view, $parameters); @@ -224,7 +224,7 @@ protected function render(string $view, array $parameters = array(), Response $r } elseif ($this->container->has('twig')) { $content = $this->container->get('twig')->render($view, $parameters); } else { - throw new \LogicException('You can not use the "render" method if the Templating Component or the Twig Bundle are not available.'); + throw new \LogicException('You can not use the "render" method if the Templating Component or the Twig Bundle are not available. Try running "composer require symfony/twig-bundle".'); } if (null === $response) { @@ -256,7 +256,7 @@ protected function stream(string $view, array $parameters = array(), StreamedRes $twig->display($view, $parameters); }; } else { - throw new \LogicException('You can not use the "stream" method if the Templating Component or the Twig Bundle are not available.'); + throw new \LogicException('You can not use the "stream" method if the Templating Component or the Twig Bundle are not available. Try running "composer require symfony/twig-bundle".'); } if (null === $response) { @@ -289,10 +289,16 @@ protected function createNotFoundException(string $message = 'Not Found', \Excep * * throw $this->createAccessDeniedException('Unable to access this page!'); * + * @throws \LogicException If the Security component is not available + * * @final since version 3.4 */ protected function createAccessDeniedException(string $message = 'Access Denied.', \Exception $previous = null): AccessDeniedException { + if (!class_exists(AccessDeniedException::class)) { + throw new \LogicException('You can not use the "createAccessDeniedException" method if the Security component is not available. Try running "composer require symfony/security-bundle".'); + } + return new AccessDeniedException($message, $previous); } @@ -326,7 +332,7 @@ protected function createFormBuilder($data = null, array $options = array()): Fo protected function getDoctrine(): ManagerRegistry { if (!$this->container->has('doctrine')) { - throw new \LogicException('The DoctrineBundle is not registered in your application.'); + throw new \LogicException('The DoctrineBundle is not registered in your application. Try running "composer require symfony/orm-pack".'); } return $this->container->get('doctrine'); @@ -346,7 +352,7 @@ protected function getDoctrine(): ManagerRegistry protected function getUser() { if (!$this->container->has('security.token_storage')) { - throw new \LogicException('The SecurityBundle is not registered in your application.'); + throw new \LogicException('The SecurityBundle is not registered in your application. Try running "composer require symfony/security-bundle".'); } if (null === $token = $this->container->get('security.token_storage')->getToken()) { @@ -372,7 +378,7 @@ protected function getUser() protected function isCsrfTokenValid(string $id, string $token): bool { if (!$this->container->has('security.csrf.token_manager')) { - throw new \LogicException('CSRF protection is not enabled in your application.'); + throw new \LogicException('CSRF protection is not enabled in your application. Enable it with the "csrf_protection" key in "config/packages/framework.yaml".'); } return $this->container->get('security.csrf.token_manager')->isTokenValid(new CsrfToken($id, $token)); diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index deec686a90b32..37ab6333d0671 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -36,6 +36,7 @@ use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\LogicException; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; +use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ServiceSubscriberInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -653,7 +654,7 @@ private function registerSessionConfiguration(array $config, ContainerBuilder $c // session storage $container->setAlias('session.storage', $config['storage_id'])->setPrivate(true); - $options = array(); + $options = array('cache_limiter' => '0'); foreach (array('name', 'cookie_lifetime', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'use_cookies', 'gc_maxlifetime', 'gc_probability', 'gc_divisor') as $key) { if (isset($config[$key])) { $options[$key] = $config[$key]; @@ -896,9 +897,6 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder if ($container->fileExists($dir = $bundle['path'].'/Resources/translations')) { $dirs[] = $dir; } - if ($container->fileExists($dir = $defaultDir.'/'.$name)) { - $dirs[] = $dir; - } if ($container->fileExists($dir = $rootDir.sprintf('/Resources/%s/translations', $name))) { $dirs[] = $dir; } @@ -1140,7 +1138,7 @@ private function registerSecurityCsrfConfiguration(array $config, ContainerBuild } if (!class_exists('Symfony\Component\Security\Csrf\CsrfToken')) { - throw new LogicException('CSRF support cannot be enabled as the Security CSRF component is not installed. Try running "composer require security-csrf".'); + throw new LogicException('CSRF support cannot be enabled as the Security CSRF component is not installed. Try running "composer require symfony/security-csrf".'); } if (!$this->sessionConfigEnabled) { @@ -1335,7 +1333,7 @@ private function registerLockConfiguration(array $config, ContainerBuilder $cont private function registerCacheConfiguration(array $config, ContainerBuilder $container) { - $version = substr(str_replace('/', '-', base64_encode(hash('sha256', uniqid(mt_rand(), true), true))), 0, 22); + $version = new Parameter('container.build_id'); $container->getDefinition('cache.adapter.apcu')->replaceArgument(2, $version); $container->getDefinition('cache.adapter.system')->replaceArgument(2, $version); $container->getDefinition('cache.adapter.filesystem')->replaceArgument(2, $config['directory']); diff --git a/src/Symfony/Bundle/FrameworkBundle/LICENSE b/src/Symfony/Bundle/FrameworkBundle/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/LICENSE +++ b/src/Symfony/Bundle/FrameworkBundle/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php index a3b9c573bc135..fa610e5c06ea2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php @@ -116,7 +116,7 @@ public function fileExcerpt($file, $line) { if (is_readable($file)) { if (extension_loaded('fileinfo')) { - $finfo = new \Finfo(); + $finfo = new \finfo(); // Check if the file is an application/octet-stream (eg. Phar file) because highlight_file cannot parse these files if ('application/octet-stream' === $finfo->file($file, FILEINFO_MIME_TYPE)) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index 1485e1b20d045..2f033cbd00492 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -141,13 +141,6 @@ public function testEsiDisabled() $container = $this->createContainerFromFile('esi_disabled'); $this->assertFalse($container->hasDefinition('fragment.renderer.esi'), 'The ESI fragment renderer is not registered'); - } - - public function testEsiInactive() - { - $container = $this->createContainerFromFile('default_config'); - - $this->assertFalse($container->hasDefinition('fragment.renderer.esi')); $this->assertFalse($container->hasDefinition('esi')); } @@ -164,6 +157,7 @@ public function testSsiDisabled() $container = $this->createContainerFromFile('ssi_disabled'); $this->assertFalse($container->hasDefinition('fragment.renderer.ssi'), 'The SSI fragment renderer is not registered'); + $this->assertFalse($container->hasDefinition('ssi')); } public function testEsiAndSsiWithoutFragments() @@ -175,14 +169,6 @@ public function testEsiAndSsiWithoutFragments() $this->assertTrue($container->hasDefinition('fragment.renderer.ssi'), 'The SSI fragment renderer is registered'); } - public function testSsiInactive() - { - $container = $this->createContainerFromFile('default_config'); - - $this->assertFalse($container->hasDefinition('fragment.renderer.ssi')); - $this->assertFalse($container->hasDefinition('ssi')); - } - public function testEnabledProfiler() { $container = $this->createContainerFromFile('profiler'); @@ -1037,6 +1023,9 @@ protected function createContainer(array $data = array()) 'kernel.name' => 'kernel', 'kernel.root_dir' => __DIR__, 'kernel.container_class' => 'testContainer', + 'container.build_hash' => 'Abc1234', + 'container.build_id' => hash('crc32', 'Abc123423456789'), + 'container.build_time' => 23456789, ), $data))); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php index 3aca2386771bf..14cb2adecfe55 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php +++ b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php @@ -47,6 +47,8 @@ class Translator extends BaseTranslator implements WarmableInterface private $resources = array(); /** + * Constructor. + * * Available options: * * * cache_dir: The cache directory (or null to disable caching) diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 054d05c40b2bd..b074883d56fa3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -19,7 +19,7 @@ "php": "^7.1.3", "ext-xml": "*", "symfony/cache": "~3.4|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", + "symfony/dependency-injection": "^3.4.3|^4.0.3", "symfony/config": "~3.4|~4.0", "symfony/event-dispatcher": "~3.4|~4.0", "symfony/http-foundation": "~3.4|~4.0", diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php index 23fd3e03a35b6..f758e212b3970 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php @@ -239,7 +239,7 @@ private function addFirewallsSection(ArrayNodeDefinition $rootNode, array $facto ->arrayNode('anonymous') ->canBeUnset() ->children() - ->scalarNode('secret')->defaultValue(uniqid('', true))->end() + ->scalarNode('secret')->defaultNull()->end() ->end() ->end() ->arrayNode('switch_user') diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/UserProvider/InMemoryFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/UserProvider/InMemoryFactory.php index f226b47cf5cc5..d79b96dadcced 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/UserProvider/InMemoryFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/UserProvider/InMemoryFactory.php @@ -14,6 +14,7 @@ use Symfony\Component\Config\Definition\Builder\NodeDefinition; use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\Reference; /** @@ -27,13 +28,14 @@ class InMemoryFactory implements UserProviderFactoryInterface public function create(ContainerBuilder $container, $id, $config) { $definition = $container->setDefinition($id, new ChildDefinition('security.user.provider.in_memory')); + $defaultPassword = new Parameter('container.build_id'); foreach ($config['users'] as $username => $user) { $userId = $id.'_'.$username; $container ->setDefinition($userId, new ChildDefinition('security.user.provider.in_memory.user')) - ->setArguments(array($username, (string) $user['password'], $user['roles'])) + ->setArguments(array($username, null !== $user['password'] ? (string) $user['password'] : $defaultPassword, $user['roles'])) ; $definition->addMethodCall('createUser', array(new Reference($userId))); @@ -55,7 +57,7 @@ public function addConfiguration(NodeDefinition $node) ->normalizeKeys(false) ->prototype('array') ->children() - ->scalarNode('password')->defaultValue(uniqid('', true))->end() + ->scalarNode('password')->defaultNull()->end() ->arrayNode('roles') ->beforeNormalization()->ifString()->then(function ($v) { return preg_split('/\s*,\s*/', $v); })->end() ->prototype('scalar')->end() diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 02d1eaeff574b..a144a9c39ef5f 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -22,6 +22,7 @@ use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\Config\FileLocator; use Symfony\Component\Security\Core\Authorization\ExpressionLanguage; @@ -425,6 +426,10 @@ private function createAuthenticationListeners($container, $id, $firewall, &$aut // Anonymous if (isset($firewall['anonymous'])) { + if (null === $firewall['anonymous']['secret']) { + $firewall['anonymous']['secret'] = new Parameter('container.build_hash'); + } + $listenerId = 'security.authentication.listener.anonymous.'.$id; $container ->setDefinition($listenerId, new ChildDefinition('security.authentication.listener.anonymous')) diff --git a/src/Symfony/Bundle/SecurityBundle/LICENSE b/src/Symfony/Bundle/SecurityBundle/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Bundle/SecurityBundle/LICENSE +++ b/src/Symfony/Bundle/SecurityBundle/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml index 4ebbbb85421df..6a4c109af4508 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml @@ -62,6 +62,7 @@ %security.authentication.session_strategy.strategy% + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Debug/TraceableFirewallListenerTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Debug/TraceableFirewallListenerTest.php index 3ddbb1fd4c438..287ba531f4031 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Debug/TraceableFirewallListenerTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Debug/TraceableFirewallListenerTest.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Bundle\SecurityBundle\Tests; +namespace Symfony\Bundle\SecurityBundle\Tests\Debug; use PHPUnit\Framework\TestCase; use Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener; diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index 816e3c4872c0d..cd10d1dfb628d 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -19,7 +19,7 @@ "php": "^7.1.3", "ext-xml": "*", "symfony/security": "~3.4|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", + "symfony/dependency-injection": "^3.4.3|^4.0.3", "symfony/http-kernel": "~3.4|~4.0" }, "require-dev": { diff --git a/src/Symfony/Bundle/TwigBundle/CHANGELOG.md b/src/Symfony/Bundle/TwigBundle/CHANGELOG.md index d71e970de0901..67cf39a41bcfb 100644 --- a/src/Symfony/Bundle/TwigBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/TwigBundle/CHANGELOG.md @@ -1,7 +1,7 @@ CHANGELOG ========= -4.4.0 +4.0.0 ----- * removed `ContainerAwareRuntimeLoader` diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configurator/EnvironmentConfigurator.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configurator/EnvironmentConfigurator.php index 7ea0dafe7cbf0..a1354622b6726 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configurator/EnvironmentConfigurator.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configurator/EnvironmentConfigurator.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\TwigBundle\DependencyInjection\Configurator; +use Symfony\Bridge\Twig\UndefinedCallableHandler; use Twig\Environment; // BC/FC with namespaced Twig @@ -49,5 +50,9 @@ public function configure(Environment $environment) } $environment->getExtension('Twig\Extension\CoreExtension')->setNumberFormat($this->decimals, $this->decimalPoint, $this->thousandsSeparator); + + // wrap UndefinedCallableHandler in closures for lazy-autoloading + $environment->registerUndefinedFilterCallback(function ($name) { return UndefinedCallableHandler::onUndefinedFilter($name); }); + $environment->registerUndefinedFunctionCallback(function ($name) { return UndefinedCallableHandler::onUndefinedFunction($name); }); } } diff --git a/src/Symfony/Bundle/TwigBundle/LICENSE b/src/Symfony/Bundle/TwigBundle/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Bundle/TwigBundle/LICENSE +++ b/src/Symfony/Bundle/TwigBundle/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Bundle/TwigBundle/Tests/Functional/CacheWarmingTest.php b/src/Symfony/Bundle/TwigBundle/Tests/Functional/CacheWarmingTest.php index a7a330859f688..a21c11adca16d 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/Functional/CacheWarmingTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/Functional/CacheWarmingTest.php @@ -9,12 +9,13 @@ * file that was distributed with this source code. */ -namespace Symfony\Bundle\TwigBundle\Tests; +namespace Symfony\Bundle\TwigBundle\Tests\Functional; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Filesystem\Filesystem; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; +use Symfony\Bundle\TwigBundle\Tests\TestCase; use Symfony\Bundle\TwigBundle\TwigBundle; class CacheWarmingTest extends TestCase diff --git a/src/Symfony/Bundle/TwigBundle/Tests/Functional/NoTemplatingEntryTest.php b/src/Symfony/Bundle/TwigBundle/Tests/Functional/NoTemplatingEntryTest.php index 3cf0268203050..952b5e6ae1937 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/Functional/NoTemplatingEntryTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/Functional/NoTemplatingEntryTest.php @@ -9,12 +9,13 @@ * file that was distributed with this source code. */ -namespace Symfony\Bundle\TwigBundle\Tests; +namespace Symfony\Bundle\TwigBundle\Tests\Functional; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Filesystem\Filesystem; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; +use Symfony\Bundle\TwigBundle\Tests\TestCase; use Symfony\Bundle\TwigBundle\TwigBundle; class NoTemplatingEntryTest extends TestCase diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index cf84f13a6f364..50ddf7e0c9ff5 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -18,7 +18,7 @@ "require": { "php": "^7.1.3", "symfony/config": "~3.4|~4.0", - "symfony/twig-bridge": "~3.4|~4.0", + "symfony/twig-bridge": "^3.4.3|^4.0.3", "symfony/http-foundation": "~3.4|~4.0", "symfony/http-kernel": "~3.4|~4.0", "twig/twig": "~1.34|~2.4" diff --git a/src/Symfony/Bundle/WebProfilerBundle/LICENSE b/src/Symfony/Bundle/WebProfilerBundle/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/LICENSE +++ b/src/Symfony/Bundle/WebProfilerBundle/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig index 4f20078e6a139..be77f891034c6 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig @@ -14,10 +14,13 @@ } %} {% endif %} + {% block toolbar %} - {% set total_time = collector.events|length ? '%.0f'|format(collector.duration) : 'n/a' %} + {% set has_time_events = collector.events|length > 0 %} + + {% set total_time = has_time_events ? '%.0f'|format(collector.duration) : 'n/a' %} {% set initialization_time = collector.events|length ? '%.0f'|format(collector.inittime) : 'n/a' %} - {% set status_color = collector.events|length and collector.duration > 1000 ? 'yellow' : '' %} + {% set status_color = has_time_events and collector.duration > 1000 ? 'yellow' : '' %} {% set icon %} {{ include('@WebProfiler/Icon/time.svg') }} @@ -47,6 +50,7 @@ {% endblock %} {% block panel %} + {% set has_time_events = collector.events|length > 0 %}

Performance metrics

@@ -75,10 +79,14 @@ Sub-Request{{ profile.children|length > 1 ? 's' }}
- {% set subrequests_time = 0 %} - {% for child in profile.children %} - {% set subrequests_time = subrequests_time + child.getcollector('time').events.__section__.duration %} - {% endfor %} + {% if has_time_events %} + {% set subrequests_time = 0 %} + {% for child in profile.children %} + {% set subrequests_time = subrequests_time + child.getcollector('time').events.__section__.duration %} + {% endfor %} + {% else %} + {% set subrequests_time = 'n/a' %} + {% endif %}
{{ subrequests_time }} ms diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig index e83e95ae134f6..aac9e3a0d4725 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig @@ -250,6 +250,8 @@ mode: arguments[0].mode, redirect: arguments[0].redirect }; + } else { + url = String(url); } if (!url.match(new RegExp({{ excluded_ajax_paths|json_encode|raw }}))) { var method = 'GET'; diff --git a/src/Symfony/Bundle/WebServerBundle/Command/ServerLogCommand.php b/src/Symfony/Bundle/WebServerBundle/Command/ServerLogCommand.php index 8b38748c3e1c8..6a31b596f67ae 100644 --- a/src/Symfony/Bundle/WebServerBundle/Command/ServerLogCommand.php +++ b/src/Symfony/Bundle/WebServerBundle/Command/ServerLogCommand.php @@ -39,7 +39,7 @@ public function isEnabled() } // based on a symfony/symfony package, it crashes due a missing FormatterInterface from monolog/monolog - if (!class_exists(FormatterInterface::class)) { + if (!interface_exists(FormatterInterface::class)) { return false; } diff --git a/src/Symfony/Bundle/WebServerBundle/LICENSE b/src/Symfony/Bundle/WebServerBundle/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Bundle/WebServerBundle/LICENSE +++ b/src/Symfony/Bundle/WebServerBundle/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Bundle/WebServerBundle/Resources/router.php b/src/Symfony/Bundle/WebServerBundle/Resources/router.php index 187be0b8366ac..a366b381aae47 100644 --- a/src/Symfony/Bundle/WebServerBundle/Resources/router.php +++ b/src/Symfony/Bundle/WebServerBundle/Resources/router.php @@ -30,7 +30,7 @@ return false; } -$script = getenv('APP_FRONT_CONTROLLER') ?: 'index.php'; +$script = isset($_ENV['APP_FRONT_CONTROLLER']) ? $_ENV['APP_FRONT_CONTROLLER'] : 'index.php'; $_SERVER = array_merge($_SERVER, $_ENV); $_SERVER['SCRIPT_FILENAME'] = $_SERVER['DOCUMENT_ROOT'].DIRECTORY_SEPARATOR.$script; diff --git a/src/Symfony/Bundle/WebServerBundle/WebServer.php b/src/Symfony/Bundle/WebServerBundle/WebServer.php index e3425ec8bb13a..beb5190b727aa 100644 --- a/src/Symfony/Bundle/WebServerBundle/WebServer.php +++ b/src/Symfony/Bundle/WebServerBundle/WebServer.php @@ -146,11 +146,11 @@ public function isRunning($pidFile = null) private function createServerProcess(WebServerConfig $config) { $finder = new PhpExecutableFinder(); - if (false === $binary = $finder->find()) { + if (false === $binary = $finder->find(false)) { throw new \RuntimeException('Unable to find the PHP binary.'); } - $process = new Process(array($binary, '-S', $config->getAddress(), $config->getRouter())); + $process = new Process(array_merge(array($binary), $finder->findArguments(), array('-dvariables_order=EGPCS', '-S', $config->getAddress(), $config->getRouter()))); $process->setWorkingDirectory($config->getDocumentRoot()); $process->setTimeout(null); diff --git a/src/Symfony/Bundle/WebServerBundle/WebServerConfig.php b/src/Symfony/Bundle/WebServerBundle/WebServerConfig.php index 6f39880083a3f..8a46208eadef2 100644 --- a/src/Symfony/Bundle/WebServerBundle/WebServerConfig.php +++ b/src/Symfony/Bundle/WebServerBundle/WebServerConfig.php @@ -32,7 +32,7 @@ public function __construct(string $documentRoot, string $env, string $address = throw new \InvalidArgumentException(sprintf('Unable to find the front controller under "%s" (none of these files exist: %s).', $documentRoot, implode(', ', $this->getFrontControllerFileNames($env)))); } - putenv('APP_FRONT_CONTROLLER='.$file); + $_ENV['APP_FRONT_CONTROLLER'] = $file; $this->documentRoot = $documentRoot; $this->env = $env; diff --git a/src/Symfony/Bundle/WebServerBundle/composer.json b/src/Symfony/Bundle/WebServerBundle/composer.json index 5de0d3a6a766a..ac474b471464e 100644 --- a/src/Symfony/Bundle/WebServerBundle/composer.json +++ b/src/Symfony/Bundle/WebServerBundle/composer.json @@ -21,7 +21,7 @@ "symfony/console": "~3.4|~4.0", "symfony/dependency-injection": "~3.4|~4.0", "symfony/http-kernel": "~3.4|~4.0", - "symfony/process": "~3.4|~4.0" + "symfony/process": "^3.4.2|^4.0.2" }, "autoload": { "psr-4": { "Symfony\\Bundle\\WebServerBundle\\": "" }, diff --git a/src/Symfony/Component/Asset/LICENSE b/src/Symfony/Component/Asset/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/Asset/LICENSE +++ b/src/Symfony/Component/Asset/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/BrowserKit/CHANGELOG.md b/src/Symfony/Component/BrowserKit/CHANGELOG.md index 47c847d0617e5..ceb1af7c2ad5a 100644 --- a/src/Symfony/Component/BrowserKit/CHANGELOG.md +++ b/src/Symfony/Component/BrowserKit/CHANGELOG.md @@ -22,7 +22,7 @@ CHANGELOG ----- * [BC BREAK] `Client::followRedirect()` won't redirect responses with - a non-3xx Status Code and `Location` header anymore, as per + a non-3xx Status Code and `Location` header anymore, as per http://tools.ietf.org/html/rfc2616#section-14.30 * added `Client::getInternalRequest()` and `Client::getInternalResponse()` to diff --git a/src/Symfony/Component/BrowserKit/LICENSE b/src/Symfony/Component/BrowserKit/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/BrowserKit/LICENSE +++ b/src/Symfony/Component/BrowserKit/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Cache/LICENSE b/src/Symfony/Component/Cache/LICENSE index ce39894f6a9a2..fcd3fa76970fa 100644 --- a/src/Symfony/Component/Cache/LICENSE +++ b/src/Symfony/Component/Cache/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2016-2017 Fabien Potencier +Copyright (c) 2016-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php index 82344fceaeba7..9b877efb080a9 100644 --- a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php +++ b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php @@ -71,7 +71,7 @@ private function init(\Memcached $client, $namespace, $defaultLifetime) * * @return \Memcached * - * @throws \ErrorEception When invalid options or servers are provided + * @throws \ErrorException When invalid options or servers are provided */ public static function createConnection($servers, array $options = array()) { diff --git a/src/Symfony/Component/Config/Definition/Builder/ExprBuilder.php b/src/Symfony/Component/Config/Definition/Builder/ExprBuilder.php index 3ea97802dcc58..64c0f5578ad41 100644 --- a/src/Symfony/Component/Config/Definition/Builder/ExprBuilder.php +++ b/src/Symfony/Component/Config/Definition/Builder/ExprBuilder.php @@ -186,7 +186,7 @@ public function thenEmptyArray() */ public function thenInvalid($message) { - $this->thenPart = function ($v) use ($message) {throw new \InvalidArgumentException(sprintf($message, json_encode($v))); }; + $this->thenPart = function ($v) use ($message) { throw new \InvalidArgumentException(sprintf($message, json_encode($v))); }; return $this; } diff --git a/src/Symfony/Component/Config/LICENSE b/src/Symfony/Component/Config/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/Config/LICENSE +++ b/src/Symfony/Component/Config/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Config/ResourceCheckerConfigCache.php b/src/Symfony/Component/Config/ResourceCheckerConfigCache.php index d22ec5f0f588a..ebacb7a4c0be9 100644 --- a/src/Symfony/Component/Config/ResourceCheckerConfigCache.php +++ b/src/Symfony/Component/Config/ResourceCheckerConfigCache.php @@ -158,7 +158,7 @@ private function safelyUnserialize($file) $meta = false; $signalingException = new \UnexpectedValueException(); $prevUnserializeHandler = ini_set('unserialize_callback_func', ''); - $prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context) use (&$prevErrorHandler, $signalingException) { + $prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = array()) use (&$prevErrorHandler, $signalingException) { if (E_WARNING === $type && 'Class __PHP_Incomplete_Class has no unserializer' === $msg) { throw $signalingException; } diff --git a/src/Symfony/Component/Config/Tests/Definition/Builder/TreeBuilderTest.php b/src/Symfony/Component/Config/Tests/Definition/Builder/TreeBuilderTest.php index 13304fae36e95..0a9312346e989 100644 --- a/src/Symfony/Component/Config/Tests/Definition/Builder/TreeBuilderTest.php +++ b/src/Symfony/Component/Config/Tests/Definition/Builder/TreeBuilderTest.php @@ -12,13 +12,9 @@ namespace Symfony\Component\Config\Tests\Definition\Builder; use PHPUnit\Framework\TestCase; -use Symfony\Component\Config\Tests\Definition\Builder\NodeBuilder as CustomNodeBuilder; +use Symfony\Component\Config\Tests\Fixtures\Builder\NodeBuilder as CustomNodeBuilder; use Symfony\Component\Config\Definition\Builder\TreeBuilder; -require __DIR__.'/../../Fixtures/Builder/NodeBuilder.php'; -require __DIR__.'/../../Fixtures/Builder/BarNodeDefinition.php'; -require __DIR__.'/../../Fixtures/Builder/VariableNodeDefinition.php'; - class TreeBuilderTest extends TestCase { public function testUsingACustomNodeBuilder() @@ -28,11 +24,11 @@ public function testUsingACustomNodeBuilder() $nodeBuilder = $root->children(); - $this->assertInstanceOf('Symfony\Component\Config\Tests\Definition\Builder\NodeBuilder', $nodeBuilder); + $this->assertInstanceOf('Symfony\Component\Config\Tests\Fixtures\Builder\NodeBuilder', $nodeBuilder); $nodeBuilder = $nodeBuilder->arrayNode('deeper')->children(); - $this->assertInstanceOf('Symfony\Component\Config\Tests\Definition\Builder\NodeBuilder', $nodeBuilder); + $this->assertInstanceOf('Symfony\Component\Config\Tests\Fixtures\Builder\NodeBuilder', $nodeBuilder); } public function testOverrideABuiltInNodeType() @@ -42,7 +38,7 @@ public function testOverrideABuiltInNodeType() $definition = $root->children()->variableNode('variable'); - $this->assertInstanceOf('Symfony\Component\Config\Tests\Definition\Builder\VariableNodeDefinition', $definition); + $this->assertInstanceOf('Symfony\Component\Config\Tests\Fixtures\Builder\VariableNodeDefinition', $definition); } public function testAddANodeType() @@ -52,7 +48,7 @@ public function testAddANodeType() $definition = $root->children()->barNode('variable'); - $this->assertInstanceOf('Symfony\Component\Config\Tests\Definition\Builder\BarNodeDefinition', $definition); + $this->assertInstanceOf('Symfony\Component\Config\Tests\Fixtures\Builder\BarNodeDefinition', $definition); } public function testCreateABuiltInNodeTypeWithACustomNodeBuilder() diff --git a/src/Symfony/Component/Config/Tests/Fixtures/Builder/BarNodeDefinition.php b/src/Symfony/Component/Config/Tests/Fixtures/Builder/BarNodeDefinition.php index 0d46f3d2c8c01..b9c62e53771c2 100644 --- a/src/Symfony/Component/Config/Tests/Fixtures/Builder/BarNodeDefinition.php +++ b/src/Symfony/Component/Config/Tests/Fixtures/Builder/BarNodeDefinition.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Config\Tests\Definition\Builder; +namespace Symfony\Component\Config\Tests\Fixtures\Builder; use Symfony\Component\Config\Definition\Builder\NodeDefinition; use Symfony\Component\Config\Tests\Fixtures\BarNode; diff --git a/src/Symfony/Component/Config/Tests/Fixtures/Builder/NodeBuilder.php b/src/Symfony/Component/Config/Tests/Fixtures/Builder/NodeBuilder.php index aa5986311ba62..22b8b32fb6de5 100644 --- a/src/Symfony/Component/Config/Tests/Fixtures/Builder/NodeBuilder.php +++ b/src/Symfony/Component/Config/Tests/Fixtures/Builder/NodeBuilder.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Config\Tests\Definition\Builder; +namespace Symfony\Component\Config\Tests\Fixtures\Builder; use Symfony\Component\Config\Definition\Builder\NodeBuilder as BaseNodeBuilder; diff --git a/src/Symfony/Component/Config/Tests/Fixtures/Builder/VariableNodeDefinition.php b/src/Symfony/Component/Config/Tests/Fixtures/Builder/VariableNodeDefinition.php index 1017880c11110..6126ed434f373 100644 --- a/src/Symfony/Component/Config/Tests/Fixtures/Builder/VariableNodeDefinition.php +++ b/src/Symfony/Component/Config/Tests/Fixtures/Builder/VariableNodeDefinition.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Config\Tests\Definition\Builder; +namespace Symfony\Component\Config\Tests\Fixtures\Builder; use Symfony\Component\Config\Definition\Builder\VariableNodeDefinition as BaseVariableNodeDefinition; diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 64d8fd6d19e4e..3c7c11f86d7f0 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -573,6 +573,7 @@ public function find($name) { $this->init(); + $aliases = array(); $allCommands = $this->commandLoader ? array_merge($this->commandLoader->getNames(), array_keys($this->commands)) : array_keys($this->commands); $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name); $commands = preg_grep('{^'.$expr.'}', $allCommands); @@ -605,14 +606,15 @@ public function find($name) // filter out aliases for commands which are already on the list if (count($commands) > 1) { $commandList = $this->commandLoader ? array_merge(array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands; - $commands = array_unique(array_filter($commands, function ($nameOrAlias) use ($commandList, $commands) { + $commands = array_unique(array_filter($commands, function ($nameOrAlias) use ($commandList, $commands, &$aliases) { $commandName = $commandList[$nameOrAlias] instanceof Command ? $commandList[$nameOrAlias]->getName() : $nameOrAlias; + $aliases[$nameOrAlias] = $commandName; return $commandName === $nameOrAlias || !in_array($commandName, $commands); })); } - $exact = in_array($name, $commands, true); + $exact = in_array($name, $commands, true) || isset($aliases[$name]); if (count($commands) > 1 && !$exact) { $usableWidth = $this->terminal->getWidth() - 10; $abbrevs = array_values($commands); diff --git a/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php b/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php index 18452d419fa44..bf14ba2d17582 100644 --- a/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php +++ b/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php @@ -41,14 +41,11 @@ public function process(ContainerBuilder $container) $lazyCommandMap = array(); $lazyCommandRefs = array(); $serviceIds = array(); - $lazyServiceIds = array(); foreach ($commandServices as $id => $tags) { $definition = $container->getDefinition($id); $class = $container->getParameterBag()->resolveValue($definition->getClass()); - $commandId = 'console.command.'.strtolower(str_replace('\\', '_', $class)); - if (isset($tags[0]['command'])) { $commandName = $tags[0]['command']; } else { @@ -62,20 +59,16 @@ public function process(ContainerBuilder $container) } if (null === $commandName) { - if (isset($serviceIds[$commandId]) || $container->hasAlias($commandId)) { - $commandId = $commandId.'_'.$id; - } if (!$definition->isPublic() || $definition->isPrivate()) { + $commandId = 'console.command.public_alias.'.$id; $container->setAlias($commandId, $id)->setPublic(true); $id = $commandId; } - $serviceIds[$commandId] = $id; + $serviceIds[] = $id; continue; } - $serviceIds[$commandId] = $id; - $lazyServiceIds[$id] = true; unset($tags[0]); $lazyCommandMap[$commandName] = $id; $lazyCommandRefs[$id] = new TypedReference($id, $class); @@ -101,6 +94,5 @@ public function process(ContainerBuilder $container) ->setArguments(array(ServiceLocatorTagPass::register($container, $lazyCommandRefs), $lazyCommandMap)); $container->setParameter('console.command.ids', $serviceIds); - $container->setParameter('console.lazy_command.ids', $lazyServiceIds); } } diff --git a/src/Symfony/Component/Console/Helper/QuestionHelper.php b/src/Symfony/Component/Console/Helper/QuestionHelper.php index 0bc1bb4ba92e9..dc088a0565ae8 100644 --- a/src/Symfony/Component/Console/Helper/QuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/QuestionHelper.php @@ -46,6 +46,12 @@ public function ask(InputInterface $input, OutputInterface $output, Question $qu } if (!$input->isInteractive()) { + if ($question instanceof ChoiceQuestion) { + $choices = $question->getChoices(); + + return $choices[$question->getDefault()]; + } + return $question->getDefault(); } diff --git a/src/Symfony/Component/Console/Input/InputInterface.php b/src/Symfony/Component/Console/Input/InputInterface.php index e2412d71f1714..b9e0651faf5db 100644 --- a/src/Symfony/Component/Console/Input/InputInterface.php +++ b/src/Symfony/Component/Console/Input/InputInterface.php @@ -24,7 +24,7 @@ interface InputInterface /** * Returns the first argument from the raw parameters (not parsed). * - * @return string The value of the first argument or null otherwise + * @return string|null The value of the first argument or null otherwise */ public function getFirstArgument(); diff --git a/src/Symfony/Component/Console/LICENSE b/src/Symfony/Component/Console/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/Console/LICENSE +++ b/src/Symfony/Component/Console/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 33fd93395c2e4..770564ed86e5e 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -56,6 +56,8 @@ public static function setUpBeforeClass() require_once self::$fixturesPath.'/BarBucCommand.php'; require_once self::$fixturesPath.'/FooSubnamespaced1Command.php'; require_once self::$fixturesPath.'/FooSubnamespaced2Command.php'; + require_once self::$fixturesPath.'/TestTiti.php'; + require_once self::$fixturesPath.'/TestToto.php'; } protected function normalizeLineBreaks($text) @@ -282,6 +284,14 @@ public function testFindAmbiguousNamespace() $application->findNamespace('f'); } + public function testFindNonAmbiguous() + { + $application = new Application(); + $application->add(new \TestTiti()); + $application->add(new \TestToto()); + $this->assertEquals('test-toto', $application->find('test')->getName()); + } + /** * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException * @expectedExceptionMessage There are no commands defined in the "bar" namespace. diff --git a/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php b/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php index 34f648610836a..2a0136d7974c7 100644 --- a/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php +++ b/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php @@ -31,28 +31,27 @@ public function testProcess($public) $container->addCompilerPass(new AddConsoleCommandPass()); $container->setParameter('my-command.class', 'Symfony\Component\Console\Tests\DependencyInjection\MyCommand'); + $id = 'my-command'; $definition = new Definition('%my-command.class%'); $definition->setPublic($public); $definition->addTag('console.command'); - $container->setDefinition('my-command', $definition); + $container->setDefinition($id, $definition); $container->compile(); - $alias = 'console.command.symfony_component_console_tests_dependencyinjection_mycommand'; + $alias = 'console.command.public_alias.my-command'; if ($public) { $this->assertFalse($container->hasAlias($alias)); - $id = 'my-command'; } else { - $id = $alias; // The alias is replaced by a Definition by the ReplaceAliasByActualDefinitionPass // in case the original service is private - $this->assertFalse($container->hasDefinition('my-command')); + $this->assertFalse($container->hasDefinition($id)); $this->assertTrue($container->hasDefinition($alias)); } $this->assertTrue($container->hasParameter('console.command.ids')); - $this->assertSame(array($alias => $id), $container->getParameter('console.command.ids')); + $this->assertSame(array($public ? $id : $alias), $container->getParameter('console.command.ids')); } public function testProcessRegistersLazyCommands() @@ -73,8 +72,7 @@ public function testProcessRegistersLazyCommands() $this->assertSame(ContainerCommandLoader::class, $commandLoader->getClass()); $this->assertSame(array('my:command' => 'my-command', 'my:alias' => 'my-command'), $commandLoader->getArgument(1)); $this->assertEquals(array(array('my-command' => new ServiceClosureArgument(new TypedReference('my-command', MyCommand::class)))), $commandLocator->getArguments()); - $this->assertSame(array('console.command.symfony_component_console_tests_dependencyinjection_mycommand' => 'my-command'), $container->getParameter('console.command.ids')); - $this->assertSame(array('my-command' => true), $container->getParameter('console.lazy_command.ids')); + $this->assertSame(array(), $container->getParameter('console.command.ids')); $this->assertSame(array(array('setName', array('my:command')), array('setAliases', array(array('my:alias')))), $command->getMethodCalls()); } @@ -96,8 +94,7 @@ public function testProcessFallsBackToDefaultName() $this->assertSame(ContainerCommandLoader::class, $commandLoader->getClass()); $this->assertSame(array('default' => 'with-default-name'), $commandLoader->getArgument(1)); $this->assertEquals(array(array('with-default-name' => new ServiceClosureArgument(new TypedReference('with-default-name', NamedCommand::class)))), $commandLocator->getArguments()); - $this->assertSame(array('console.command.symfony_component_console_tests_dependencyinjection_namedcommand' => 'with-default-name'), $container->getParameter('console.command.ids')); - $this->assertSame(array('with-default-name' => true), $container->getParameter('console.lazy_command.ids')); + $this->assertSame(array(), $container->getParameter('console.command.ids')); $container = new ContainerBuilder(); $container @@ -170,10 +167,9 @@ public function testProcessPrivateServicesWithSameCommand() (new AddConsoleCommandPass())->process($container); - $alias1 = 'console.command.symfony_component_console_tests_dependencyinjection_mycommand'; - $alias2 = $alias1.'_my-command2'; - $this->assertTrue($container->hasAlias($alias1)); - $this->assertTrue($container->hasAlias($alias2)); + $aliasPrefix = 'console.command.public_alias.'; + $this->assertTrue($container->hasAlias($aliasPrefix.'my-command1')); + $this->assertTrue($container->hasAlias($aliasPrefix.'my-command2')); } } diff --git a/src/Symfony/Component/Console/Tests/Fixtures/TestTiti.php b/src/Symfony/Component/Console/Tests/Fixtures/TestTiti.php new file mode 100644 index 0000000000000..72e29d2a0a2dc --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/TestTiti.php @@ -0,0 +1,21 @@ +setName('test-titi') + ->setDescription('The test:titi command') + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $output->write('test-titi'); + } +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/TestToto.php b/src/Symfony/Component/Console/Tests/Fixtures/TestToto.php new file mode 100644 index 0000000000000..f14805db68e6c --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/TestToto.php @@ -0,0 +1,22 @@ +setName('test-toto') + ->setDescription('The test-toto command') + ->setAliases(array('test')) + ; + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $output->write('test-toto'); + } +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth1.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth1.txt index ba622b6f0dc36..e7bd41347ba78 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth1.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth1.txt @@ -1,5 +1,5 @@ -In ApplicationTest.php line 715: +In ApplicationTest.php line 725: エラーメッセージ diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth1decorated.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth1decorated.txt index 258ebf83002b5..f87367888f8b7 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth1decorated.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth1decorated.txt @@ -1,5 +1,5 @@ -In ApplicationTest.php line 715: +In ApplicationTest.php line 725:    エラーメッセージ    diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth2.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth2.txt index 7e1c8ac44864c..481f0c534c33f 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth2.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth2.txt @@ -1,5 +1,5 @@ -In ApplicationTest.php line 729: +In ApplicationTest.php line 739: コマンドの実行中にエラーが 発生しました。 diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_escapeslines.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_escapeslines.txt index 537059fd8f0b1..fee2b98c68a61 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_escapeslines.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_escapeslines.txt @@ -1,5 +1,5 @@ -In ApplicationTest.php line 743: +In ApplicationTest.php line 753: dont break here < info>! diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_linebreaks.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_linebreaks.txt index 64bfe9a183c7a..48a7499a0b268 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_linebreaks.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_linebreaks.txt @@ -1,5 +1,5 @@ -In ApplicationTest.php line 760: +In ApplicationTest.php line 770: line 1 with extra spaces line 2 diff --git a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php index 4ba20fe7974b1..3b8c07d39379b 100644 --- a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php @@ -83,6 +83,10 @@ public function testAskChoice() $question->setMultiselect(true); $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream), $this->createOutputInterface(), $question)); + + $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, 0); + // We are supposed to get the default value since we are not in interactive mode + $this->assertEquals('Superman', $questionHelper->ask($this->createStreamableInputInterfaceMock($inputStream, true), $this->createOutputInterface(), $question)); } public function testAsk() diff --git a/src/Symfony/Component/CssSelector/LICENSE b/src/Symfony/Component/CssSelector/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/CssSelector/LICENSE +++ b/src/Symfony/Component/CssSelector/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Debug/DebugClassLoader.php b/src/Symfony/Component/Debug/DebugClassLoader.php index faae22c24dec3..0a13ac1e66b9e 100644 --- a/src/Symfony/Component/Debug/DebugClassLoader.php +++ b/src/Symfony/Component/Debug/DebugClassLoader.php @@ -28,6 +28,7 @@ class DebugClassLoader private $isFinder; private $loaded = array(); private static $caseCheck; + private static $checkedClasses = array(); private static $final = array(); private static $finalMethods = array(); private static $deprecated = array(); @@ -138,8 +139,14 @@ public function loadClass($class) try { if ($this->isFinder && !isset($this->loaded[$class])) { $this->loaded[$class] = true; - if ($file = $this->classLoader[0]->findFile($class)) { + if ($file = $this->classLoader[0]->findFile($class) ?: false) { + $wasCached = \function_exists('opcache_is_script_cached') && opcache_is_script_cached($file); + require $file; + + if ($wasCached) { + return; + } } } else { call_user_func($this->classLoader, $class); @@ -149,41 +156,58 @@ public function loadClass($class) error_reporting($e); } - $exists = class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false); + $this->checkClass($class, $file); + } - if ($class && '\\' === $class[0]) { + private function checkClass($class, $file = null) + { + $exists = null === $file || \class_exists($class, false) || \interface_exists($class, false) || \trait_exists($class, false); + + if (null !== $file && $class && '\\' === $class[0]) { $class = substr($class, 1); } if ($exists) { + if (isset(self::$checkedClasses[$class])) { + return; + } + self::$checkedClasses[$class] = true; + $refl = new \ReflectionClass($class); + if (null === $file && $refl->isInternal()) { + return; + } $name = $refl->getName(); - if ($name !== $class && 0 === strcasecmp($name, $class)) { + if ($name !== $class && 0 === \strcasecmp($name, $class)) { throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: "%s" vs "%s".', $class, $name)); } // Don't trigger deprecations for classes in the same vendor - if (2 > $len = 1 + (strpos($name, '\\') ?: strpos($name, '_'))) { + if (2 > $len = 1 + (\strpos($name, '\\') ?: \strpos($name, '_'))) { $len = 0; $ns = ''; } else { - $ns = substr($name, 0, $len); + $ns = \substr($name, 0, $len); } // Detect annotations on the class if (false !== $doc = $refl->getDocComment()) { foreach (array('final', 'deprecated', 'internal') as $annotation) { - if (false !== strpos($doc, '@'.$annotation) && preg_match('#\n \* @'.$annotation.'(?:( .+?)\.?)?\r?\n \*(?: @|/$)#s', $doc, $notice)) { + if (false !== \strpos($doc, $annotation) && preg_match('#\n \* @'.$annotation.'(?:( .+?)\.?)?\r?\n \*(?: @|/$)#s', $doc, $notice)) { self::${$annotation}[$name] = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : ''; } } } - $parentAndTraits = class_uses($name, false); - if ($parent = get_parent_class($class)) { + $parentAndTraits = \class_uses($name, false); + if ($parent = \get_parent_class($class)) { $parentAndTraits[] = $parent; + if (!isset(self::$checkedClasses[$parent])) { + $this->checkClass($parent); + } + if (isset(self::$final[$parent])) { @trigger_error(sprintf('The "%s" class is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $parent, self::$final[$parent], $name), E_USER_DEPRECATED); } @@ -191,13 +215,16 @@ public function loadClass($class) // Detect if the parent is annotated foreach ($parentAndTraits + $this->getOwnInterfaces($name, $parent) as $use) { - if (isset(self::$deprecated[$use]) && strncmp($ns, $use, $len)) { + if (!isset(self::$checkedClasses[$use])) { + $this->checkClass($use); + } + if (isset(self::$deprecated[$use]) && \strncmp($ns, $use, $len)) { $type = class_exists($name, false) ? 'class' : (interface_exists($name, false) ? 'interface' : 'trait'); $verb = class_exists($use, false) || interface_exists($name, false) ? 'extends' : (interface_exists($use, false) ? 'implements' : 'uses'); @trigger_error(sprintf('The "%s" %s %s "%s" that is deprecated%s.', $name, $type, $verb, $use, self::$deprecated[$use]), E_USER_DEPRECATED); } - if (isset(self::$internal[$use]) && strncmp($ns, $use, $len)) { + if (isset(self::$internal[$use]) && \strncmp($ns, $use, $len)) { @trigger_error(sprintf('The "%s" %s is considered internal%s. It may change without further notice. You should not use it from "%s".', $use, class_exists($use, false) ? 'class' : (interface_exists($use, false) ? 'interface' : 'trait'), self::$internal[$use], $name), E_USER_DEPRECATED); } } @@ -208,12 +235,12 @@ public function loadClass($class) foreach ($parentAndTraits as $use) { foreach (array('finalMethods', 'internalMethods') as $property) { if (isset(self::${$property}[$use])) { - self::${$property}[$name] = array_merge(self::${$property}[$name], self::${$property}[$use]); + self::${$property}[$name] = self::${$property}[$name] ? self::${$property}[$use] + self::${$property}[$name] : self::${$property}[$use]; } } } - $isClass = class_exists($name, false); + $isClass = \class_exists($name, false); foreach ($refl->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $method) { if ($method->class !== $name) { continue; @@ -232,7 +259,7 @@ public function loadClass($class) foreach ($parentAndTraits as $use) { if (isset(self::$internalMethods[$use][$method->name])) { list($declaringClass, $message) = self::$internalMethods[$use][$method->name]; - if (strncmp($ns, $declaringClass, $len)) { + if (\strncmp($ns, $declaringClass, $len)) { @trigger_error(sprintf('The "%s::%s()" method is considered internal%s. It may change without further notice. You should not extend it from "%s".', $declaringClass, $method->name, $message, $name), E_USER_DEPRECATED); } } @@ -244,7 +271,7 @@ public function loadClass($class) } foreach (array('final', 'internal') as $annotation) { - if (false !== strpos($doc, '@'.$annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$)#s', $doc, $notice)) { + if (false !== \strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$)#s', $doc, $notice)) { $message = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : ''; self::${$annotation.'Methods'}[$name][$method->name] = array($name, $message); } @@ -345,8 +372,6 @@ public function loadClass($class) throw new \RuntimeException(sprintf('Case mismatch between class and real file names: "%s" vs "%s" in "%s".', substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1))); } } - - return true; } } diff --git a/src/Symfony/Component/Debug/LICENSE b/src/Symfony/Component/Debug/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/Debug/LICENSE +++ b/src/Symfony/Component/Debug/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Debug/Tests/Exception/FlattenExceptionTest.php b/src/Symfony/Component/Debug/Tests/Exception/FlattenExceptionTest.php index d68f9a035e8f0..c4cf58315a4e3 100644 --- a/src/Symfony/Component/Debug/Tests/Exception/FlattenExceptionTest.php +++ b/src/Symfony/Component/Debug/Tests/Exception/FlattenExceptionTest.php @@ -258,6 +258,7 @@ function () {}, public function testRecursionInArguments() { + $a = null; $a = array('foo', array(2, &$a)); $exception = $this->createException($a); diff --git a/src/Symfony/Component/Debug/Tests/phpt/debug_class_loader.phpt b/src/Symfony/Component/Debug/Tests/phpt/debug_class_loader.phpt new file mode 100644 index 0000000000000..b9d3d7288714e --- /dev/null +++ b/src/Symfony/Component/Debug/Tests/phpt/debug_class_loader.phpt @@ -0,0 +1,26 @@ +--TEST-- +Test DebugClassLoader with previously loaded parents +--FILE-- + +--EXPECTF-- +The "Symfony\Component\Debug\Tests\Fixtures\FinalMethod::finalMethod()" method is considered final since version 3.3. It may change without further notice as of its next major version. You should not extend it from "Symfony\Component\Debug\Tests\Fixtures\ExtendedFinalMethod". diff --git a/src/Symfony/Component/Debug/Tests/phpt/exception_rethrown.phpt b/src/Symfony/Component/Debug/Tests/phpt/exception_rethrown.phpt index 877e208f406a7..9df0a65cf79f9 100644 --- a/src/Symfony/Component/Debug/Tests/phpt/exception_rethrown.phpt +++ b/src/Symfony/Component/Debug/Tests/phpt/exception_rethrown.phpt @@ -26,7 +26,6 @@ ErrorHandler::register()->setDefaultLogger(new TestLogger()); ini_set('display_errors', 1); throw new \Exception('foo'); - ?> --EXPECTF-- Uncaught Exception: foo diff --git a/src/Symfony/Component/Debug/Tests/phpt/fatal_with_nested_handlers.phpt b/src/Symfony/Component/Debug/Tests/phpt/fatal_with_nested_handlers.phpt index bd7b644dc3aa7..5c5245c069e63 100644 --- a/src/Symfony/Component/Debug/Tests/phpt/fatal_with_nested_handlers.phpt +++ b/src/Symfony/Component/Debug/Tests/phpt/fatal_with_nested_handlers.phpt @@ -24,7 +24,9 @@ var_dump(array( $eHandler[0]->setExceptionHandler('print_r'); if (true) { - class Broken implements \Serializable {}; + class Broken implements \Serializable + { + } } ?> diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index 19d55fbf8758b..cd6ad8721827e 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -329,6 +329,10 @@ private function createTypeNotFoundMessage(TypedReference $reference, $label) } else { $message = $this->container->has($type) ? 'this service is abstract' : 'no such service exists'; $message = sprintf('references %s "%s" but %s.%s', $r->isInterface() ? 'interface' : 'class', $type, $message, $this->createTypeAlternatives($reference)); + + if ($r->isInterface()) { + $message .= ' Did you create a class that implements this interface?'; + } } $message = sprintf('Cannot autowire service "%s": %s %s', $this->currentId, $label, $message); diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index ffa15161e5645..aecf7cb6f8a50 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -1190,6 +1190,8 @@ private function doResolveServices($value, array &$inlineServices = array()) $value = $this->doGet((string) $value, $value->getInvalidBehavior(), $inlineServices); } elseif ($value instanceof Definition) { $value = $this->createService($value, $inlineServices); + } elseif ($value instanceof Parameter) { + $value = $this->getParameter((string) $value); } elseif ($value instanceof Expression) { $value = $this->getExpressionLanguage()->evaluate($value, array('container' => $this)); } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 0edb71c6972f7..5a48950ad4168 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -218,6 +218,8 @@ public function dump(array $options = array()) array_pop($code); $code["Container{$hash}/{$options['class']}.php"] = substr_replace($files[$options['class'].'.php'], "namespace ? "\nnamespace {$this->namespace};\n" : ''; + $time = time(); + $id = hash('crc32', $hash.$time); $code[$options['class'].'.php'] = << '$hash', + 'container.build_id' => '$id', + 'container.build_time' => $time, +)); EOF; } else { @@ -543,7 +549,7 @@ private function isTrivialInstance(Definition $definition): bool } foreach ($definition->getArguments() as $arg) { - if (!$arg) { + if (!$arg || $arg instanceof Parameter) { continue; } if (is_array($arg) && 3 >= count($arg)) { @@ -551,7 +557,7 @@ private function isTrivialInstance(Definition $definition): bool if ($this->dumpValue($k) !== $this->dumpValue($k, false)) { return false; } - if (!$v) { + if (!$v || $v instanceof Parameter) { continue; } if ($v instanceof Reference && $this->container->has($id = (string) $v) && $this->container->findDefinition($id)->isSynthetic()) { @@ -837,10 +843,10 @@ private function addNewInstance(Definition $definition, $return, $instantiation, } if (0 === strpos($class, 'new ')) { - return $return.sprintf("(%s)->%s(%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? implode(', ', $arguments) : ''); + return $return.sprintf("(%s)->%s(%s);\n", $class, $callable[1], $arguments ? implode(', ', $arguments) : ''); } - return $return.sprintf("[%s, '%s'](%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? implode(', ', $arguments) : ''); + return $return.sprintf("[%s, '%s'](%s);\n", $class, $callable[1], $arguments ? implode(', ', $arguments) : ''); } return $return.sprintf("%s(%s);\n", $this->dumpLiteralClass($this->dumpValue($callable)), $arguments ? implode(', ', $arguments) : ''); @@ -898,6 +904,11 @@ public function __construct() EOF; } + if ($this->asFiles) { + $code = str_replace('$parameters', "\$buildParameters;\n private \$parameters", $code); + $code = str_replace('__construct()', '__construct(array $buildParameters = array())', $code); + $code .= " \$this->buildParameters = \$buildParameters;\n"; + } if ($this->container->getParameterBag()->all()) { $code .= " \$this->parameters = \$this->getDefaultParameters();\n\n"; @@ -1126,6 +1137,9 @@ private function addDefaultParametersMethod(): string public function getParameter($name) { $name = (string) $name; + if (isset($this->buildParameters[$name])) { + return $this->buildParameters[$name]; + } if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); @@ -1140,6 +1154,9 @@ public function getParameter($name) public function hasParameter($name) { $name = (string) $name; + if (isset($this->buildParameters[$name])) { + return true; + } return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -1156,6 +1173,9 @@ public function getParameterBag() foreach ($this->loadedDynamicParameters as $name => $loaded) { $parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); } + foreach ($this->buildParameters as $name => $value) { + $parameters[$name] = $value; + } $this->parameterBag = new FrozenParameterBag($parameters); } @@ -1163,6 +1183,9 @@ public function getParameterBag() } EOF; + if (!$this->asFiles) { + $code = preg_replace('/^.*buildParameters.*\n.*\n.*\n/m', '', $code); + } if ($dynamicPhp) { $loadedDynamicParameters = $this->exportParameters(array_combine(array_keys($dynamicPhp), array_fill(0, count($dynamicPhp), false)), '', 8); @@ -1483,16 +1506,21 @@ private function dumpValue($value, bool $interpolate = true): string throw new RuntimeException(sprintf('Cannot dump definition because of invalid factory method (%s)', $factory[1] ?: 'n/a')); } + $class = $this->dumpValue($factory[0]); if (is_string($factory[0])) { - return sprintf('%s::%s(%s)', $this->dumpLiteralClass($this->dumpValue($factory[0])), $factory[1], implode(', ', $arguments)); + return sprintf('%s::%s(%s)', $this->dumpLiteralClass($class), $factory[1], implode(', ', $arguments)); } if ($factory[0] instanceof Definition) { - return sprintf("[%s, '%s'](%s)", $this->dumpValue($factory[0]), $factory[1], implode(', ', $arguments)); + if (0 === strpos($class, 'new ')) { + return sprintf('(%s)->%s(%s)', $class, $factory[1], implode(', ', $arguments)); + } + + return sprintf("[%s, '%s'](%s)", $class, $factory[1], implode(', ', $arguments)); } if ($factory[0] instanceof Reference) { - return sprintf('%s->%s(%s)', $this->dumpValue($factory[0]), $factory[1], implode(', ', $arguments)); + return sprintf('%s->%s(%s)', $class, $factory[1], implode(', ', $arguments)); } } diff --git a/src/Symfony/Component/DependencyInjection/LICENSE b/src/Symfony/Component/DependencyInjection/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/DependencyInjection/LICENSE +++ b/src/Symfony/Component/DependencyInjection/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index 2e225aa05d627..7a0cccb9c9923 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -454,6 +454,9 @@ private function parseDefinition($id, $service, $file, array $defaults) $args = isset($call[1]) ? $this->resolveServices($call[1], $file) : array(); } + if (!is_array($args)) { + throw new InvalidArgumentException(sprintf('The second parameter for function call "%s" must be an array of its arguments for service "%s" in %s. Check your YAML syntax.', $method, $id, $file)); + } $definition->addMethodCall($method, $args); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index f06083756b209..fb07f47932265 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -595,6 +595,23 @@ public function testSetterInjectionCollisionThrowsException() $pass->process($container); } + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException + * @expectedExceptionMessage Cannot autowire service "my_service": argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\K::__construct()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\IInterface" but no such service exists. Did you create a class that implements this interface? + */ + public function testInterfaceWithNoImplementationSuggestToWriteOne() + { + $container = new ContainerBuilder(); + + $aDefinition = $container->register('my_service', K::class); + $aDefinition->setAutowired(true); + + (new AutowireRequiredMethodsPass())->process($container); + + $pass = new AutowirePass(); + $pass->process($container); + } + /** * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException * @expectedExceptionMessage Cannot autowire service "bar": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\Bar::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but no such service exists. You should maybe alias this class to the existing "foo" service. diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterEnvVarProcessorsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterEnvVarProcessorsPassTest.php index d807a6fa41ba9..cddb62dce9826 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterEnvVarProcessorsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterEnvVarProcessorsPassTest.php @@ -26,7 +26,7 @@ public function testSimpleProcessor() (new RegisterEnvVarProcessorsPass())->process($container); $this->assertTrue($container->has('container.env_var_processors_locator')); - $this->assertInstanceof(SimpleProcessor::class, $container->get('container.env_var_processors_locator')->get('foo')); + $this->assertInstanceOf(SimpleProcessor::class, $container->get('container.env_var_processors_locator')->get('foo')); $expected = array( 'foo' => array('string'), diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php index 1ca36e974fd80..21a2810578e97 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php @@ -32,7 +32,7 @@ public function testProcess() $parent = 'instanceof.'.parent::class.'.0.foo'; $def = $container->getDefinition('foo'); $this->assertEmpty($def->getInstanceofConditionals()); - $this->assertInstanceof(ChildDefinition::class, $def); + $this->assertInstanceOf(ChildDefinition::class, $def); $this->assertTrue($def->isAutowired()); $this->assertSame($parent, $def->getParent()); $this->assertSame(array('tag' => array(array()), 'baz' => array(array('attr' => 123))), $def->getTags()); diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php index 78fe2954af5fe..2ad4ac34fab04 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php @@ -412,6 +412,7 @@ class ProjectServiceContainer extends Container public $__foo_bar; public $__foo_baz; public $__internal; + protected $privates; protected $methodMap = array( 'bar' => 'getBarService', 'foo_bar' => 'getFooBarService', diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 38990201f4d69..2025cbe943764 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -18,7 +18,6 @@ use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Argument\RewindableGenerator; use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface; use Symfony\Component\DependencyInjection\Dumper\PhpDumper; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php index ae1e92eadbafd..04c17ee188fa7 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php @@ -90,6 +90,13 @@ public function __construct(I $i) } } +class K +{ + public function __construct(IInterface $i) + { + } +} + interface CollisionInterface { } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt index 6dc4792c32833..5a3b5c888fb37 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt @@ -307,6 +307,7 @@ use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; */ class ProjectServiceContainer extends Container { + private $buildParameters; private $parameters; private $targetDirs = array(); @@ -315,12 +316,13 @@ class ProjectServiceContainer extends Container */ protected $privates = array(); - public function __construct() + public function __construct(array $buildParameters = array()) { $dir = $this->targetDirs[0] = \dirname(__DIR__); for ($i = 1; $i <= 5; ++$i) { $this->targetDirs[$i] = $dir = \dirname($dir); } + $this->buildParameters = $buildParameters; $this->parameters = $this->getDefaultParameters(); $this->services = $this->privates = array(); @@ -415,6 +417,9 @@ class ProjectServiceContainer extends Container public function getParameter($name) { $name = (string) $name; + if (isset($this->buildParameters[$name])) { + return $this->buildParameters[$name]; + } if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); @@ -429,6 +434,9 @@ class ProjectServiceContainer extends Container public function hasParameter($name) { $name = (string) $name; + if (isset($this->buildParameters[$name])) { + return true; + } return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -445,6 +453,9 @@ class ProjectServiceContainer extends Container foreach ($this->loadedDynamicParameters as $name => $loaded) { $parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); } + foreach ($this->buildParameters as $name => $value) { + $parameters[$name] = $value; + } $this->parameterBag = new FrozenParameterBag($parameters); } @@ -499,6 +510,10 @@ if (!\class_exists(ProjectServiceContainer::class, false)) { \class_alias(\Container%s\ProjectServiceContainer::class, ProjectServiceContainer::class, false); } -return new \Container%s\ProjectServiceContainer(); +return new \Container%s\ProjectServiceContainer(array( + 'container.build_hash' => '%s', + 'container.build_id' => '%s', + 'container.build_time' => %d, +)); ) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php index f039d1ea0465c..4f41330edb390 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php @@ -79,7 +79,7 @@ protected function getTestServiceSubscriberService() */ protected function getFooServiceService() { - return $this->services['foo_service'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber([new \Symfony\Component\DependencyInjection\ServiceLocator(array('Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => function (): ?\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition { + return $this->services['foo_service'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber((new \Symfony\Component\DependencyInjection\ServiceLocator(array('Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => function (): ?\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition { return ($this->privates['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] ?? $this->privates['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition()); }, 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\TestServiceSubscriber' => function (): \Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber { return ($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] ?? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber()); @@ -87,6 +87,6 @@ protected function getFooServiceService() return ($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] ?? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber()); }, 'baz' => function (): ?\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition { return ($this->privates['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] ?? $this->privates['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition()); - })), 'withContext']('foo_service', $this)); + })))->withContext('foo_service', $this)); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php index d26331fba8d5c..fb80cd49360fe 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php @@ -448,9 +448,6 @@ public function testExtensionInPhar() if (extension_loaded('suhosin') && false === strpos(ini_get('suhosin.executor.include.whitelist'), 'phar')) { $this->markTestSkipped('To run this test, add "phar" to the "suhosin.executor.include.whitelist" settings in your php.ini file.'); } - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('HHVM makes this test conflict with those run in separate processes.'); - } require_once self::$fixturesPath.'/includes/ProjectWithXsdExtensionInPhar.phar'; diff --git a/src/Symfony/Component/DomCrawler/Crawler.php b/src/Symfony/Component/DomCrawler/Crawler.php index 0a26cd2641356..c71af316c02e1 100644 --- a/src/Symfony/Component/DomCrawler/Crawler.php +++ b/src/Symfony/Component/DomCrawler/Crawler.php @@ -691,8 +691,8 @@ public function filterXPath($xpath) */ public function filter($selector) { - if (!class_exists('Symfony\\Component\\CssSelector\\CssSelectorConverter')) { - throw new \RuntimeException('Unable to filter with a CSS selector as the Symfony CssSelector 2.8+ is not installed (you can use filterXPath instead).'); + if (!class_exists(CssSelectorConverter::class)) { + throw new \RuntimeException('To filter with a CSS selector, install the CssSelector component ("composer require symfony/css-selector"). Or use filterXpath instead.'); } $converter = new CssSelectorConverter($this->isHtml); diff --git a/src/Symfony/Component/DomCrawler/LICENSE b/src/Symfony/Component/DomCrawler/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/DomCrawler/LICENSE +++ b/src/Symfony/Component/DomCrawler/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Dotenv/LICENSE b/src/Symfony/Component/Dotenv/LICENSE index ce39894f6a9a2..fcd3fa76970fa 100644 --- a/src/Symfony/Component/Dotenv/LICENSE +++ b/src/Symfony/Component/Dotenv/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2016-2017 Fabien Potencier +Copyright (c) 2016-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/EventDispatcher/LICENSE b/src/Symfony/Component/EventDispatcher/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/EventDispatcher/LICENSE +++ b/src/Symfony/Component/EventDispatcher/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/ExpressionLanguage/LICENSE b/src/Symfony/Component/ExpressionLanguage/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/ExpressionLanguage/LICENSE +++ b/src/Symfony/Component/ExpressionLanguage/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Filesystem/LICENSE b/src/Symfony/Component/Filesystem/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/Filesystem/LICENSE +++ b/src/Symfony/Component/Filesystem/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php index 8d21ca3523222..def1e5fc09953 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php @@ -1519,7 +1519,7 @@ public function testAppendToFile() // skip mode check on Windows if ('\\' !== DIRECTORY_SEPARATOR) { - $this->assertFilePermissions(664, $filename, 'The written file should keep the same permissions as before.'); + $this->assertFilePermissions(664, $filename); umask($oldMask); } } diff --git a/src/Symfony/Component/Finder/LICENSE b/src/Symfony/Component/Finder/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/Finder/LICENSE +++ b/src/Symfony/Component/Finder/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Form/Console/Descriptor/Descriptor.php b/src/Symfony/Component/Form/Console/Descriptor/Descriptor.php index 6cccd8ead235f..fbdb19aff60f6 100644 --- a/src/Symfony/Component/Form/Console/Descriptor/Descriptor.php +++ b/src/Symfony/Component/Form/Console/Descriptor/Descriptor.php @@ -98,6 +98,8 @@ protected function collectOptions(ResolvedFormTypeInterface $type) } $this->overriddenOptions = array_filter($this->overriddenOptions); + $this->parentOptions = array_filter($this->parentOptions); + $this->extensionOptions = array_filter($this->extensionOptions); $this->requiredOptions = $optionsResolver->getRequiredOptions(); $this->parents = array_keys($this->parents); diff --git a/src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php b/src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php index 6e17e9b859e01..d899ffce4e2a1 100644 --- a/src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php @@ -126,30 +126,32 @@ protected function describeOption(OptionsResolver $optionsResolver, array $optio private function normalizeAndSortOptionsColumns(array $options) { - foreach ($options as $group => &$opts) { + foreach ($options as $group => $opts) { $sorted = false; foreach ($opts as $class => $opt) { + if (is_string($class)) { + unset($options[$group][$class]); + } + if (!is_array($opt) || 0 === count($opt)) { continue; } - unset($opts[$class]); - if (!$sorted) { - $opts = array(); + $options[$group] = array(); } else { - $opts[] = null; + $options[$group][] = null; } - $opts[] = sprintf('%s', (new \ReflectionClass($class))->getShortName()); - $opts[] = new TableSeparator(); + $options[$group][] = sprintf('%s', (new \ReflectionClass($class))->getShortName()); + $options[$group][] = new TableSeparator(); sort($opt); $sorted = true; - $opts = array_merge($opts, $opt); + $options[$group] = array_merge($options[$group], $opt); } if (!$sorted) { - sort($opts); + sort($options[$group]); } } diff --git a/src/Symfony/Component/Form/FormRegistry.php b/src/Symfony/Component/Form/FormRegistry.php index 7d08d690dffba..6be83ab95de60 100644 --- a/src/Symfony/Component/Form/FormRegistry.php +++ b/src/Symfony/Component/Form/FormRegistry.php @@ -82,11 +82,14 @@ public function getType($name) if (!$type) { // Support fully-qualified class names - if (class_exists($name) && in_array('Symfony\Component\Form\FormTypeInterface', class_implements($name))) { - $type = new $name(); - } else { - throw new InvalidArgumentException(sprintf('Could not load type "%s"', $name)); + if (!class_exists($name)) { + throw new InvalidArgumentException(sprintf('Could not load type "%s": class does not exist.', $name)); } + if (!is_subclass_of($name, 'Symfony\Component\Form\FormTypeInterface')) { + throw new InvalidArgumentException(sprintf('Could not load type "%s": class does not implement "Symfony\Component\Form\FormTypeInterface".', $name)); + } + + $type = new $name(); } $this->types[$name] = $this->resolveType($type); diff --git a/src/Symfony/Component/Form/LICENSE b/src/Symfony/Component/Form/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/Form/LICENSE +++ b/src/Symfony/Component/Form/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Form/Tests/Console/Descriptor/AbstractDescriptorTest.php b/src/Symfony/Component/Form/Tests/Console/Descriptor/AbstractDescriptorTest.php index 8849266527d81..c29e3fe2fc5e6 100644 --- a/src/Symfony/Component/Form/Tests/Console/Descriptor/AbstractDescriptorTest.php +++ b/src/Symfony/Component/Form/Tests/Console/Descriptor/AbstractDescriptorTest.php @@ -84,6 +84,7 @@ public function getDescribeResolvedFormTypeTestData() $parent = new ResolvedFormType(new FormType(), $typeExtensions); yield array(new ResolvedFormType(new ChoiceType(), array(), $parent), array('decorated' => false), 'resolved_form_type_1'); + yield array(new ResolvedFormType(new FormType()), array('decorated' => false), 'resolved_form_type_2'); } public function getDescribeOptionTestData() diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_2.json b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_2.json new file mode 100644 index 0000000000000..bdefb5c946626 --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_2.json @@ -0,0 +1,37 @@ +{ + "class": "Symfony\\Component\\Form\\Extension\\Core\\Type\\FormType", + "block_prefix": "form", + "options": { + "own": [ + "action", + "attr", + "auto_initialize", + "block_name", + "by_reference", + "compound", + "data", + "data_class", + "disabled", + "empty_data", + "error_bubbling", + "inherit_data", + "label", + "label_attr", + "label_format", + "mapped", + "method", + "post_max_size_message", + "property_path", + "required", + "translation_domain", + "trim", + "upload_max_size_message" + ], + "overridden": [], + "parent": [], + "extension": [], + "required": [] + }, + "parent_types": [], + "type_extensions": [] +} diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_2.txt b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_2.txt new file mode 100644 index 0000000000000..72b13dfef75aa --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_2.txt @@ -0,0 +1,32 @@ + +Symfony\Component\Form\Extension\Core\Type\FormType (Block prefix: "form") +========================================================================== + + ------------------------- + Options + ------------------------- + action + attr + auto_initialize + block_name + by_reference + compound + data + data_class + disabled + empty_data + error_bubbling + inherit_data + label + label_attr + label_format + mapped + method + post_max_size_message + property_path + required + translation_domain + trim + upload_max_size_message + ------------------------- + diff --git a/src/Symfony/Component/HttpFoundation/LICENSE b/src/Symfony/Component/HttpFoundation/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/HttpFoundation/LICENSE +++ b/src/Symfony/Component/HttpFoundation/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index b5b99452fd228..e40e7d8423c62 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -1852,6 +1852,7 @@ protected static function initializeFormats() 'js' => array('application/javascript', 'application/x-javascript', 'text/javascript'), 'css' => array('text/css'), 'json' => array('application/json', 'application/x-json'), + 'jsonld' => array('application/ld+json'), 'xml' => array('text/xml', 'application/xml', 'application/x-xml'), 'rdf' => array('application/rdf+xml'), 'atom' => array('application/atom+xml'), @@ -1927,13 +1928,13 @@ private function getTrustedValues($type, $ip = null) $clientValues = array(); $forwardedValues = array(); - if (self::$trustedHeaders[$type] && $this->headers->has(self::$trustedHeaders[$type])) { + if ((self::$trustedHeaderSet & $type) && $this->headers->has(self::$trustedHeaders[$type])) { foreach (explode(',', $this->headers->get(self::$trustedHeaders[$type])) as $v) { $clientValues[] = (self::HEADER_X_FORWARDED_PORT === $type ? '0.0.0.0:' : '').trim($v); } } - if (self::$trustedHeaders[self::HEADER_FORWARDED] && $this->headers->has(self::$trustedHeaders[self::HEADER_FORWARDED])) { + if ((self::$trustedHeaderSet & self::HEADER_FORWARDED) && $this->headers->has(self::$trustedHeaders[self::HEADER_FORWARDED])) { $forwardedValues = $this->headers->get(self::$trustedHeaders[self::HEADER_FORWARDED]); $forwardedValues = preg_match_all(sprintf('{(?:%s)=(?:"?\[?)([a-zA-Z0-9\.:_\-/]*+)}', self::$forwardedParams[$type]), $forwardedValues, $matches) ? $matches[1] : array(); } diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php index 2d600b66cd406..9f4ef7028edbe 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php @@ -34,6 +34,8 @@ class MemcachedSessionHandler extends AbstractSessionHandler private $prefix; /** + * Constructor. + * * List of available options: * * prefix: The prefix to use for the memcached keys in order to avoid collision * * expiretime: The time to live in seconds. diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php index 9ee3e1f0c9e77..edc0149f995a4 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php @@ -34,6 +34,8 @@ class MongoDbSessionHandler extends AbstractSessionHandler private $options; /** + * Constructor. + * * List of available options: * * database: The name of the database [required] * * collection: The name of the collection [required] diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php index 90c2307913a50..67b6cb268f0b2 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php @@ -332,13 +332,7 @@ protected function doWrite($sessionId, $data) return true; } - $updateStmt = $this->pdo->prepare( - "UPDATE $this->table SET $this->dataCol = :data, $this->lifetimeCol = :lifetime, $this->timeCol = :time WHERE $this->idCol = :id" - ); - $updateStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $updateStmt->bindParam(':data', $data, \PDO::PARAM_LOB); - $updateStmt->bindParam(':lifetime', $maxlifetime, \PDO::PARAM_INT); - $updateStmt->bindValue(':time', time(), \PDO::PARAM_INT); + $updateStmt = $this->getUpdateStatement($sessionId, $data, $maxlifetime); $updateStmt->execute(); // When MERGE is not supported, like in Postgres < 9.5, we have to use this approach that can result in @@ -348,13 +342,7 @@ protected function doWrite($sessionId, $data) // false positives due to longer gap locking. if (!$updateStmt->rowCount()) { try { - $insertStmt = $this->pdo->prepare( - "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time)" - ); - $insertStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $insertStmt->bindParam(':data', $data, \PDO::PARAM_LOB); - $insertStmt->bindParam(':lifetime', $maxlifetime, \PDO::PARAM_INT); - $insertStmt->bindValue(':time', time(), \PDO::PARAM_INT); + $insertStmt = $this->getInsertStatement($sessionId, $data, $maxlifetime); $insertStmt->execute(); } catch (\PDOException $e) { // Handle integrity violation SQLSTATE 23000 (or a subclass like 23505 in Postgres) for duplicate keys @@ -547,13 +535,7 @@ protected function doRead($sessionId) // Exclusive-reading of non-existent rows does not block, so we need to do an insert to block // until other connections to the session are committed. try { - $insertStmt = $this->pdo->prepare( - "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time)" - ); - $insertStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $insertStmt->bindValue(':data', '', \PDO::PARAM_LOB); - $insertStmt->bindValue(':lifetime', 0, \PDO::PARAM_INT); - $insertStmt->bindValue(':time', time(), \PDO::PARAM_INT); + $insertStmt = $this->getInsertStatement($sessionId, '', 0); $insertStmt->execute(); } catch (\PDOException $e) { // Catch duplicate key error because other connection created the session already. @@ -680,23 +662,82 @@ private function getSelectSql(): string return "SELECT $this->dataCol, $this->lifetimeCol, $this->timeCol FROM $this->table WHERE $this->idCol = :id"; } + /** + * Returns an insert statement supported by the database for writing session data. + * + * @param string $sessionId Session ID + * @param string $sessionData Encoded session data + * @param int $maxlifetime session.gc_maxlifetime + * + * @return \PDOStatement The insert statement + */ + private function getInsertStatement($sessionId, $sessionData, $maxlifetime) + { + switch ($this->driver) { + case 'oci': + $data = fopen('php://memory', 'r+'); + fwrite($data, $sessionData); + rewind($data); + $sql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, EMPTY_BLOB(), :lifetime, :time) RETURNING $this->dataCol into :data"; + break; + default: + $data = $sessionData; + $sql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time)"; + break; + } + + $stmt = $this->pdo->prepare($sql); + $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); + $stmt->bindParam(':data', $data, \PDO::PARAM_LOB); + $stmt->bindParam(':lifetime', $maxlifetime, \PDO::PARAM_INT); + $stmt->bindValue(':time', time(), \PDO::PARAM_INT); + + return $stmt; + } + + /** + * Returns an update statement supported by the database for writing session data. + * + * @param string $sessionId Session ID + * @param string $sessionData Encoded session data + * @param int $maxlifetime session.gc_maxlifetime + * + * @return \PDOStatement The update statement + */ + private function getUpdateStatement($sessionId, $sessionData, $maxlifetime) + { + switch ($this->driver) { + case 'oci': + $data = fopen('php://memory', 'r+'); + fwrite($data, $sessionData); + rewind($data); + $sql = "UPDATE $this->table SET $this->dataCol = EMPTY_BLOB(), $this->lifetimeCol = :lifetime, $this->timeCol = :time WHERE $this->idCol = :id RETURNING $this->dataCol into :data"; + break; + default: + $data = $sessionData; + $sql = "UPDATE $this->table SET $this->dataCol = :data, $this->lifetimeCol = :lifetime, $this->timeCol = :time WHERE $this->idCol = :id"; + break; + } + + $stmt = $this->pdo->prepare($sql); + $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); + $stmt->bindParam(':data', $data, \PDO::PARAM_LOB); + $stmt->bindParam(':lifetime', $maxlifetime, \PDO::PARAM_INT); + $stmt->bindValue(':time', time(), \PDO::PARAM_INT); + + return $stmt; + } + /** * Returns a merge/upsert (i.e. insert or update) statement when supported by the database for writing session data. */ private function getMergeStatement(string $sessionId, string $data, int$maxlifetime): ?\PDOStatement { - $mergeSql = null; switch (true) { case 'mysql' === $this->driver: $mergeSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time) ". "ON DUPLICATE KEY UPDATE $this->dataCol = VALUES($this->dataCol), $this->lifetimeCol = VALUES($this->lifetimeCol), $this->timeCol = VALUES($this->timeCol)"; break; - case 'oci' === $this->driver: - // DUAL is Oracle specific dummy table - $mergeSql = "MERGE INTO $this->table USING DUAL ON ($this->idCol = ?) ". - "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ". - "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?"; - break; case 'sqlsrv' === $this->driver && version_compare($this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), '10', '>='): // MERGE is only available since SQL Server 2008 and must be terminated by semicolon // It also requires HOLDLOCK according to http://weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx @@ -711,29 +752,30 @@ private function getMergeStatement(string $sessionId, string $data, int$maxlifet $mergeSql = "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (:id, :data, :lifetime, :time) ". "ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->lifetimeCol, $this->timeCol) = (EXCLUDED.$this->dataCol, EXCLUDED.$this->lifetimeCol, EXCLUDED.$this->timeCol)"; break; + default: + // MERGE is not supported with LOBs: http://www.oracle.com/technetwork/articles/fuecks-lobs-095315.html + return null; } - if (null !== $mergeSql) { - $mergeStmt = $this->pdo->prepare($mergeSql); - - if ('sqlsrv' === $this->driver || 'oci' === $this->driver) { - $mergeStmt->bindParam(1, $sessionId, \PDO::PARAM_STR); - $mergeStmt->bindParam(2, $sessionId, \PDO::PARAM_STR); - $mergeStmt->bindParam(3, $data, \PDO::PARAM_LOB); - $mergeStmt->bindParam(4, $maxlifetime, \PDO::PARAM_INT); - $mergeStmt->bindValue(5, time(), \PDO::PARAM_INT); - $mergeStmt->bindParam(6, $data, \PDO::PARAM_LOB); - $mergeStmt->bindParam(7, $maxlifetime, \PDO::PARAM_INT); - $mergeStmt->bindValue(8, time(), \PDO::PARAM_INT); - } else { - $mergeStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $mergeStmt->bindParam(':data', $data, \PDO::PARAM_LOB); - $mergeStmt->bindParam(':lifetime', $maxlifetime, \PDO::PARAM_INT); - $mergeStmt->bindValue(':time', time(), \PDO::PARAM_INT); - } - - return $mergeStmt; + $mergeStmt = $this->pdo->prepare($mergeSql); + + if ('sqlsrv' === $this->driver) { + $mergeStmt->bindParam(1, $sessionId, \PDO::PARAM_STR); + $mergeStmt->bindParam(2, $sessionId, \PDO::PARAM_STR); + $mergeStmt->bindParam(3, $data, \PDO::PARAM_LOB); + $mergeStmt->bindParam(4, $maxlifetime, \PDO::PARAM_INT); + $mergeStmt->bindValue(5, time(), \PDO::PARAM_INT); + $mergeStmt->bindParam(6, $data, \PDO::PARAM_LOB); + $mergeStmt->bindParam(7, $maxlifetime, \PDO::PARAM_INT); + $mergeStmt->bindValue(8, time(), \PDO::PARAM_INT); + } else { + $mergeStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); + $mergeStmt->bindParam(':data', $data, \PDO::PARAM_LOB); + $mergeStmt->bindParam(':lifetime', $maxlifetime, \PDO::PARAM_INT); + $mergeStmt->bindValue(':time', time(), \PDO::PARAM_INT); } + + return $mergeStmt; } /** diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index b9d7e313ec745..cceba302f2963 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -372,6 +372,7 @@ public function getFormatToMimeTypeMapProvider() array('js', array('application/javascript', 'application/x-javascript', 'text/javascript')), array('css', array('text/css')), array('json', array('application/json', 'application/x-json')), + array('jsonld', array('application/ld+json')), array('xml', array('text/xml', 'application/xml', 'application/x-xml')), array('rdf', array('application/rdf+xml')), array('atom', array('application/atom+xml')), @@ -968,6 +969,26 @@ public function testGetClientIpsWithConflictingHeaders($httpForwarded, $httpXFor $request->getClientIps(); } + /** + * @dataProvider getClientIpsWithConflictingHeadersProvider + */ + public function testGetClientIpsOnlyXHttpForwardedForTrusted($httpForwarded, $httpXForwardedFor) + { + $request = new Request(); + + $server = array( + 'REMOTE_ADDR' => '88.88.88.88', + 'HTTP_FORWARDED' => $httpForwarded, + 'HTTP_X_FORWARDED_FOR' => $httpXForwardedFor, + ); + + Request::setTrustedProxies(array('88.88.88.88'), Request::HEADER_X_FORWARDED_FOR); + + $request->initialize(array(), array(), array(), array(), array(), $server); + + $this->assertSame(array_reverse(explode(',', $httpXForwardedFor)), $request->getClientIps()); + } + public function getClientIpsWithConflictingHeadersProvider() { // $httpForwarded $httpXForwardedFor diff --git a/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php b/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php index e3318822bd4df..b35727962eacd 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php @@ -989,7 +989,7 @@ public function ianaCodesReasonPhrasesProvider() $ianaCodesReasonPhrases = array(); - $xpath = new \DomXPath($ianaHttpStatusCodes); + $xpath = new \DOMXPath($ianaHttpStatusCodes); $xpath->registerNamespace('ns', 'http://www.iana.org/assignments'); $records = $xpath->query('//ns:record'); diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/StrictSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/StrictSessionHandlerTest.php index 9d2c1949f3d72..8e978487632e1 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/StrictSessionHandlerTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/StrictSessionHandlerTest.php @@ -24,8 +24,8 @@ public function testOpen() ->with('path', 'name')->willReturn(true); $proxy = new StrictSessionHandler($handler); - $this->assertInstanceof('SessionUpdateTimestampHandlerInterface', $proxy); - $this->assertInstanceof(AbstractSessionHandler::class, $proxy); + $this->assertInstanceOf('SessionUpdateTimestampHandlerInterface', $proxy); + $this->assertInstanceOf(AbstractSessionHandler::class, $proxy); $this->assertTrue($proxy->open('path', 'name')); } diff --git a/src/Symfony/Component/HttpKernel/Client.php b/src/Symfony/Component/HttpKernel/Client.php index d682ff72fafb6..7979722d164f9 100644 --- a/src/Symfony/Component/HttpKernel/Client.php +++ b/src/Symfony/Component/HttpKernel/Client.php @@ -25,7 +25,7 @@ * * @author Fabien Potencier * - * @method Request|null getRequest() A Request instance + * @method Request|null getRequest() A Request instance * @method Response|null getResponse() A Response instance */ class Client extends BaseClient diff --git a/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php b/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php index cf3a2f0a530b8..937d1bd55eb27 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/ExceptionListener.php @@ -13,7 +13,9 @@ use Psr\Log\LoggerInterface; use Symfony\Component\Debug\Exception\FlattenException; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpKernel\KernelEvents; @@ -41,6 +43,7 @@ public function onKernelException(GetResponseForExceptionEvent $event) { $exception = $event->getException(); $request = $event->getRequest(); + $eventDispatcher = func_num_args() > 2 ? func_get_arg(2) : null; $this->logException($exception, sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', get_class($exception), $exception->getMessage(), $exception->getFile(), $exception->getLine())); @@ -67,6 +70,14 @@ public function onKernelException(GetResponseForExceptionEvent $event) } $event->setResponse($response); + + if ($eventDispatcher instanceof EventDispatcherInterface) { + $cspRemovalListener = function (FilterResponseEvent $event) use (&$cspRemovalListener, $eventDispatcher) { + $event->getResponse()->headers->remove('Content-Security-Policy'); + $eventDispatcher->removeListener(KernelEvents::RESPONSE, $cspRemovalListener); + }; + $eventDispatcher->addListener(KernelEvents::RESPONSE, $cspRemovalListener, -128); + } } public static function getSubscribedEvents() diff --git a/src/Symfony/Component/HttpKernel/EventListener/SaveSessionListener.php b/src/Symfony/Component/HttpKernel/EventListener/SaveSessionListener.php index 36809b59af914..1cee45e59a9d3 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/SaveSessionListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/SaveSessionListener.php @@ -53,6 +53,10 @@ public function onKernelResponse(FilterResponseEvent $event) $session = $event->getRequest()->getSession(); if ($session && $session->isStarted()) { $session->save(); + $event->getResponse() + ->setPrivate() + ->setMaxAge(0) + ->headers->addCacheControlDirective('must-revalidate'); } } diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 8a283df6eccda..4dd748c82ac0b 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -63,11 +63,11 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private $requestStackSize = 0; private $resetServices = false; - const VERSION = '4.0.2'; - const VERSION_ID = 40002; + const VERSION = '4.0.3'; + const VERSION_ID = 40003; const MAJOR_VERSION = 4; const MINOR_VERSION = 0; - const RELEASE_VERSION = 2; + const RELEASE_VERSION = 3; const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '07/2018'; @@ -532,7 +532,7 @@ protected function initializeContainer() $oldContainerDir = dirname($oldContainer->getFileName()); foreach (glob(dirname($oldContainerDir).'/*.legacy') as $legacyContainer) { if ($oldContainerDir.'.legacy' !== $legacyContainer && @unlink($legacyContainer)) { - (new Filesystem())->remove(substr($legacyContainer, 0, -16)); + (new Filesystem())->remove(substr($legacyContainer, 0, -7)); } } diff --git a/src/Symfony/Component/HttpKernel/LICENSE b/src/Symfony/Component/HttpKernel/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/HttpKernel/LICENSE +++ b/src/Symfony/Component/HttpKernel/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.php index a91157282b5f0..db34f9187bd1f 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/ExceptionListenerTest.php @@ -12,8 +12,11 @@ namespace Symfony\Component\HttpKernel\Tests\EventListener; use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\EventListener\ExceptionListener; +use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpFoundation\Request; @@ -122,6 +125,32 @@ public function testSubRequestFormat() $response = $event->getResponse(); $this->assertEquals('xml', $response->getContent()); } + + public function testCSPHeaderIsRemoved() + { + $dispatcher = new EventDispatcher(); + $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); + $kernel->expects($this->once())->method('handle')->will($this->returnCallback(function (Request $request) { + return new Response($request->getRequestFormat()); + })); + + $listener = new ExceptionListener('foo', $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock()); + + $dispatcher->addSubscriber($listener); + + $request = Request::create('/'); + $event = new GetResponseForExceptionEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, new \Exception('foo')); + $dispatcher->dispatch(KernelEvents::EXCEPTION, $event); + + $response = new Response('', 200, array('content-security-policy' => "style-src 'self'")); + $this->assertTrue($response->headers->has('content-security-policy')); + + $event = new FilterResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response); + $dispatcher->dispatch(KernelEvents::RESPONSE, $event); + + $this->assertFalse($response->headers->has('content-security-policy'), 'CSP header has been removed'); + $this->assertFalse($dispatcher->hasListeners(KernelEvents::RESPONSE), 'CSP removal listener has been removed'); + } } class TestLogger extends Logger implements DebugLoggerInterface diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/SaveSessionListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/SaveSessionListenerTest.php new file mode 100644 index 0000000000000..80200881c5a05 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/SaveSessionListenerTest.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\EventListener; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\Session\SessionInterface; +use Symfony\Component\HttpKernel\Event\FilterResponseEvent; +use Symfony\Component\HttpKernel\EventListener\SaveSessionListener; +use Symfony\Component\HttpKernel\HttpKernelInterface; + +class SaveSessionListenerTest extends TestCase +{ + public function testOnlyTriggeredOnMasterRequest() + { + $listener = new SaveSessionListener(); + $event = $this->getMockBuilder(FilterResponseEvent::class)->disableOriginalConstructor()->getMock(); + $event->expects($this->once())->method('isMasterRequest')->willReturn(false); + $event->expects($this->never())->method('getRequest'); + + // sub request + $listener->onKernelResponse($event); + } + + public function testSessionSavedAndResponsePrivate() + { + $listener = new SaveSessionListener(); + $kernel = $this->getMockBuilder(HttpKernelInterface::class)->disableOriginalConstructor()->getMock(); + + $session = $this->getMockBuilder(SessionInterface::class)->disableOriginalConstructor()->getMock(); + $session->expects($this->once())->method('isStarted')->willReturn(true); + $session->expects($this->once())->method('save'); + + $request = new Request(); + $request->setSession($session); + $response = new Response(); + $listener->onKernelResponse(new FilterResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response)); + + $this->assertTrue($response->headers->hasCacheControlDirective('private')); + $this->assertTrue($response->headers->hasCacheControlDirective('must-revalidate')); + $this->assertSame('0', $response->headers->getCacheControlDirective('max-age')); + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php index 8461a180c8c31..f1a44de87737d 100644 --- a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php @@ -64,6 +64,31 @@ public function testClone() $this->assertNull($clone->getContainer()); } + public function testInitializeContainerClearsOldContainers() + { + $fs = new Filesystem(); + $legacyContainerDir = __DIR__.'/Fixtures/cache/custom/ContainerA123456'; + $fs->mkdir($legacyContainerDir); + touch($legacyContainerDir.'.legacy'); + + $kernel = new CustomProjectDirKernel(); + $kernel->boot(); + + $containerDir = __DIR__.'/Fixtures/cache/custom/'.substr(get_class($kernel->getContainer()), 0, 16); + $this->assertTrue(unlink(__DIR__.'/Fixtures/cache/custom/FixturesCustomDebugProjectContainer.php.meta')); + $this->assertFileExists($containerDir); + $this->assertFileNotExists($containerDir.'.legacy'); + + $kernel = new CustomProjectDirKernel(function ($container) { $container->register('foo', 'stdClass')->setPublic(true); }); + $kernel->boot(); + + $this->assertFileExists($containerDir); + $this->assertFileExists($containerDir.'.legacy'); + + $this->assertFileNotExists($legacyContainerDir); + $this->assertFileNotExists($legacyContainerDir.'.legacy'); + } + public function testBootInitializesBundlesAndContainer() { $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer')); @@ -710,7 +735,7 @@ protected function getHttpKernel() class PassKernel extends CustomProjectDirKernel implements CompilerPassInterface { - public function __construct(\Closure $buildContainer = null) + public function __construct() { parent::__construct(); Kernel::__construct('pass', true); diff --git a/src/Symfony/Component/Inflector/LICENSE b/src/Symfony/Component/Inflector/LICENSE index ac30964e87ccb..fbcca13d6ae25 100644 --- a/src/Symfony/Component/Inflector/LICENSE +++ b/src/Symfony/Component/Inflector/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2012-2017 Fabien Potencier +Copyright (c) 2012-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Intl/Intl.php b/src/Symfony/Component/Intl/Intl.php index 3fc1974bfc775..3444c10f83435 100644 --- a/src/Symfony/Component/Intl/Intl.php +++ b/src/Symfony/Component/Intl/Intl.php @@ -234,7 +234,7 @@ public static function getIcuDataVersion() */ public static function getIcuStubVersion() { - return '60.1'; + return '60.2'; } /** diff --git a/src/Symfony/Component/Intl/LICENSE b/src/Symfony/Component/Intl/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/Intl/LICENSE +++ b/src/Symfony/Component/Intl/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Intl/Resources/bin/icu.ini b/src/Symfony/Component/Intl/Resources/bin/icu.ini index f06bc753355da..da25128e2868c 100644 --- a/src/Symfony/Component/Intl/Resources/bin/icu.ini +++ b/src/Symfony/Component/Intl/Resources/bin/icu.ini @@ -15,4 +15,4 @@ 57 = http://source.icu-project.org/repos/icu/icu/tags/release-57-1/source 58 = http://source.icu-project.org/repos/icu/tags/release-58-2/icu4c/source 59 = http://source.icu-project.org/repos/icu/tags/release-59-1/icu4c/source -60 = http://source.icu-project.org/repos/icu/tags/release-60-1/icu4c/source +60 = http://source.icu-project.org/repos/icu/tags/release-60-2/icu4c/source diff --git a/src/Symfony/Component/Intl/Resources/data/currencies/de.json b/src/Symfony/Component/Intl/Resources/data/currencies/de.json index 0a0796435719a..015dfbd13899d 100644 --- a/src/Symfony/Component/Intl/Resources/data/currencies/de.json +++ b/src/Symfony/Component/Intl/Resources/data/currencies/de.json @@ -1,5 +1,5 @@ { - "Version": "2.1.37.11", + "Version": "2.1.37.96", "Names": { "ADP": [ "ADP", diff --git a/src/Symfony/Component/Intl/Resources/data/currencies/ur.json b/src/Symfony/Component/Intl/Resources/data/currencies/ur.json index bbe4edc0ea763..0a5ca9e1d34cb 100644 --- a/src/Symfony/Component/Intl/Resources/data/currencies/ur.json +++ b/src/Symfony/Component/Intl/Resources/data/currencies/ur.json @@ -1,5 +1,5 @@ { - "Version": "2.1.37.28", + "Version": "2.1.37.69", "Names": { "AED": [ "AED", diff --git a/src/Symfony/Component/Intl/Resources/data/languages/de.json b/src/Symfony/Component/Intl/Resources/data/languages/de.json index f4a01cd421633..58e7a7c571a70 100644 --- a/src/Symfony/Component/Intl/Resources/data/languages/de.json +++ b/src/Symfony/Component/Intl/Resources/data/languages/de.json @@ -1,5 +1,5 @@ { - "Version": "2.1.37.11", + "Version": "2.1.37.96", "Names": { "aa": "Afar", "ab": "Abchasisch", diff --git a/src/Symfony/Component/Intl/Resources/data/languages/ur.json b/src/Symfony/Component/Intl/Resources/data/languages/ur.json index 33871c2dee4d2..e28f6175c9c33 100644 --- a/src/Symfony/Component/Intl/Resources/data/languages/ur.json +++ b/src/Symfony/Component/Intl/Resources/data/languages/ur.json @@ -1,5 +1,5 @@ { - "Version": "2.1.37.28", + "Version": "2.1.37.69", "Names": { "aa": "افار", "ab": "ابقازیان", diff --git a/src/Symfony/Component/Intl/Resources/data/regions/de.json b/src/Symfony/Component/Intl/Resources/data/regions/de.json index bd2259f58032e..1bc40b718aed4 100644 --- a/src/Symfony/Component/Intl/Resources/data/regions/de.json +++ b/src/Symfony/Component/Intl/Resources/data/regions/de.json @@ -1,5 +1,5 @@ { - "Version": "2.1.37.11", + "Version": "2.1.37.96", "Names": { "AC": "Ascension", "AD": "Andorra", diff --git a/src/Symfony/Component/Intl/Resources/data/regions/ur.json b/src/Symfony/Component/Intl/Resources/data/regions/ur.json index a28f28f770236..89fbae8bf9059 100644 --- a/src/Symfony/Component/Intl/Resources/data/regions/ur.json +++ b/src/Symfony/Component/Intl/Resources/data/regions/ur.json @@ -1,5 +1,5 @@ { - "Version": "2.1.37.28", + "Version": "2.1.37.69", "Names": { "AC": "اسینشن آئلینڈ", "AD": "انڈورا", diff --git a/src/Symfony/Component/Intl/Resources/data/scripts/de.json b/src/Symfony/Component/Intl/Resources/data/scripts/de.json index 07898c2c2e95a..735ee0fdcf61d 100644 --- a/src/Symfony/Component/Intl/Resources/data/scripts/de.json +++ b/src/Symfony/Component/Intl/Resources/data/scripts/de.json @@ -1,5 +1,5 @@ { - "Version": "2.1.37.11", + "Version": "2.1.37.96", "Names": { "Afak": "Afaka", "Aghb": "Kaukasisch-Albanisch", diff --git a/src/Symfony/Component/Intl/Resources/data/scripts/ur.json b/src/Symfony/Component/Intl/Resources/data/scripts/ur.json index bedfaaae754e6..7c26e92044e05 100644 --- a/src/Symfony/Component/Intl/Resources/data/scripts/ur.json +++ b/src/Symfony/Component/Intl/Resources/data/scripts/ur.json @@ -1,5 +1,5 @@ { - "Version": "2.1.37.28", + "Version": "2.1.37.69", "Names": { "Arab": "عربی", "Armn": "آرمینیائی", diff --git a/src/Symfony/Component/Intl/Resources/data/svn-info.txt b/src/Symfony/Component/Intl/Resources/data/svn-info.txt index c452480e2f9cc..1bfc195f5bda1 100644 --- a/src/Symfony/Component/Intl/Resources/data/svn-info.txt +++ b/src/Symfony/Component/Intl/Resources/data/svn-info.txt @@ -1,7 +1,7 @@ SVN information =============== -URL: http://source.icu-project.org/repos/icu/tags/release-60-1/icu4c/source -Revision: 40662 +URL: http://source.icu-project.org/repos/icu/tags/release-60-2/icu4c/source +Revision: 40727 Author: yoshito -Date: 2017-10-31T15:14:15.305164Z +Date: 2017-12-13T20:01:38.026283Z diff --git a/src/Symfony/Component/Intl/Resources/data/version.txt b/src/Symfony/Component/Intl/Resources/data/version.txt index c4601b28ee754..76887d82ad20d 100644 --- a/src/Symfony/Component/Intl/Resources/data/version.txt +++ b/src/Symfony/Component/Intl/Resources/data/version.txt @@ -1 +1 @@ -60.1 +60.2 diff --git a/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php b/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php index 18d2abba8f725..7a4f01b66ae5d 100644 --- a/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php +++ b/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php @@ -852,7 +852,9 @@ public function testParseWithNullPositionValue() $position = null; $formatter = $this->getDefaultDateFormatter('y'); $this->assertSame(0, $formatter->parse('1970', $position)); - $this->assertNull($position); + // Since $position is not supported by the Symfony implementation, the following won't work. + // The intl implementation works this way since 60.2. + // $this->assertSame(4, $position); } public function testSetPattern() diff --git a/src/Symfony/Component/Ldap/LICENSE b/src/Symfony/Component/Ldap/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/Ldap/LICENSE +++ b/src/Symfony/Component/Ldap/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Lock/LICENSE b/src/Symfony/Component/Lock/LICENSE index ce39894f6a9a2..fcd3fa76970fa 100644 --- a/src/Symfony/Component/Lock/LICENSE +++ b/src/Symfony/Component/Lock/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2016-2017 Fabien Potencier +Copyright (c) 2016-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/OptionsResolver/CHANGELOG.md b/src/Symfony/Component/OptionsResolver/CHANGELOG.md index c8f0244602195..6e9d49fb61d75 100644 --- a/src/Symfony/Component/OptionsResolver/CHANGELOG.md +++ b/src/Symfony/Component/OptionsResolver/CHANGELOG.md @@ -31,7 +31,7 @@ CHANGELOG * deprecated OptionsResolver::isKnown() in favor of isDefined() * [BC BREAK] OptionsResolver::isRequired() returns true now if a required option has a default value set - * [BC BREAK] merged Options into OptionsResolver and turned Options into an + * [BC BREAK] merged Options into OptionsResolver and turned Options into an interface * deprecated Options::overload() (now in OptionsResolver) * deprecated Options::set() (now in OptionsResolver) @@ -42,7 +42,7 @@ CHANGELOG lazy option/normalizer closures now * [BC BREAK] removed Traversable interface from Options since using within lazy option/normalizer closures resulted in exceptions - * [BC BREAK] removed Options::all() since using within lazy option/normalizer + * [BC BREAK] removed Options::all() since using within lazy option/normalizer closures resulted in exceptions * [BC BREAK] OptionDefinitionException now extends LogicException instead of RuntimeException diff --git a/src/Symfony/Component/OptionsResolver/LICENSE b/src/Symfony/Component/OptionsResolver/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/OptionsResolver/LICENSE +++ b/src/Symfony/Component/OptionsResolver/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Process/LICENSE b/src/Symfony/Component/Process/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/Process/LICENSE +++ b/src/Symfony/Component/Process/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index 56f1ee3fc2a3b..bf103c7cdb857 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -289,11 +289,16 @@ public function start(callable $callback = null, array $env = array()) $ptsWorkaround = fopen(__FILE__, 'r'); } + $envPairs = array(); + foreach ($env as $k => $v) { + $envPairs[] = $k.'='.$v; + } + if (!is_dir($this->cwd)) { throw new RuntimeException('The provided cwd does not exist.'); } - $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $env, $options); + $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $envPairs, $options); if (!is_resource($this->process)) { throw new RuntimeException('Unable to launch a new process.'); @@ -1536,7 +1541,13 @@ private function escapeArgument(string $argument): string private function getDefaultEnv() { - $env = getenv(); + $env = array(); + + foreach ($_SERVER as $k => $v) { + if (is_string($v) && false !== $v = getenv($k)) { + $env[$k] = $v; + } + } foreach ($_ENV as $k => $v) { if (is_string($v)) { diff --git a/src/Symfony/Component/Process/Tests/ProcessTest.php b/src/Symfony/Component/Process/Tests/ProcessTest.php index 1867e03c0936e..6b75b00a54937 100644 --- a/src/Symfony/Component/Process/Tests/ProcessTest.php +++ b/src/Symfony/Component/Process/Tests/ProcessTest.php @@ -1410,14 +1410,14 @@ public function testEnvBackupDoesNotDeleteExistingVars() public function testEnvIsInherited() { - $process = $this->getProcessForCode('echo serialize($_SERVER);', null, array('BAR' => 'BAZ')); + $process = $this->getProcessForCode('echo serialize($_SERVER);', null, array('BAR' => 'BAZ', 'EMPTY' => '')); putenv('FOO=BAR'); $_ENV['FOO'] = 'BAR'; $process->run(); - $expected = array('BAR' => 'BAZ', 'FOO' => 'BAR'); + $expected = array('BAR' => 'BAZ', 'EMPTY' => '', 'FOO' => 'BAR'); $env = array_intersect_key(unserialize($process->getOutput()), $expected); $this->assertEquals($expected, $env); diff --git a/src/Symfony/Component/PropertyAccess/LICENSE b/src/Symfony/Component/PropertyAccess/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/PropertyAccess/LICENSE +++ b/src/Symfony/Component/PropertyAccess/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/PropertyInfo/LICENSE b/src/Symfony/Component/PropertyInfo/LICENSE index 2ca4d6305bf2a..24fa32c2e9b27 100644 --- a/src/Symfony/Component/PropertyInfo/LICENSE +++ b/src/Symfony/Component/PropertyInfo/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-2017 Fabien Potencier +Copyright (c) 2015-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Routing/Generator/UrlGenerator.php b/src/Symfony/Component/Routing/Generator/UrlGenerator.php index 4d00f3a096e3b..02a59a9253976 100644 --- a/src/Symfony/Component/Routing/Generator/UrlGenerator.php +++ b/src/Symfony/Component/Routing/Generator/UrlGenerator.php @@ -181,57 +181,56 @@ protected function doGenerate($variables, $defaults, $requirements, $tokens, $pa } $schemeAuthority = ''; - if ($host = $this->context->getHost()) { - $scheme = $this->context->getScheme(); + $host = $this->context->getHost(); + $scheme = $this->context->getScheme(); - if ($requiredSchemes) { - if (!in_array($scheme, $requiredSchemes, true)) { - $referenceType = self::ABSOLUTE_URL; - $scheme = current($requiredSchemes); - } + if ($requiredSchemes) { + if (!in_array($scheme, $requiredSchemes, true)) { + $referenceType = self::ABSOLUTE_URL; + $scheme = current($requiredSchemes); } + } - if ($hostTokens) { - $routeHost = ''; - foreach ($hostTokens as $token) { - if ('variable' === $token[0]) { - if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#i'.(empty($token[4]) ? '' : 'u'), $mergedParams[$token[3]])) { - if ($this->strictRequirements) { - throw new InvalidParameterException(strtr($message, array('{parameter}' => $token[3], '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$token[3]]))); - } - - if ($this->logger) { - $this->logger->error($message, array('parameter' => $token[3], 'route' => $name, 'expected' => $token[2], 'given' => $mergedParams[$token[3]])); - } + if ($hostTokens) { + $routeHost = ''; + foreach ($hostTokens as $token) { + if ('variable' === $token[0]) { + if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#i'.(empty($token[4]) ? '' : 'u'), $mergedParams[$token[3]])) { + if ($this->strictRequirements) { + throw new InvalidParameterException(strtr($message, array('{parameter}' => $token[3], '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$token[3]]))); + } - return; + if ($this->logger) { + $this->logger->error($message, array('parameter' => $token[3], 'route' => $name, 'expected' => $token[2], 'given' => $mergedParams[$token[3]])); } - $routeHost = $token[1].$mergedParams[$token[3]].$routeHost; - } else { - $routeHost = $token[1].$routeHost; + return; } - } - if ($routeHost !== $host) { - $host = $routeHost; - if (self::ABSOLUTE_URL !== $referenceType) { - $referenceType = self::NETWORK_PATH; - } + $routeHost = $token[1].$mergedParams[$token[3]].$routeHost; + } else { + $routeHost = $token[1].$routeHost; } } - if (self::ABSOLUTE_URL === $referenceType || self::NETWORK_PATH === $referenceType) { - $port = ''; - if ('http' === $scheme && 80 != $this->context->getHttpPort()) { - $port = ':'.$this->context->getHttpPort(); - } elseif ('https' === $scheme && 443 != $this->context->getHttpsPort()) { - $port = ':'.$this->context->getHttpsPort(); + if ($routeHost !== $host) { + $host = $routeHost; + if (self::ABSOLUTE_URL !== $referenceType) { + $referenceType = self::NETWORK_PATH; } + } + } - $schemeAuthority = self::NETWORK_PATH === $referenceType ? '//' : "$scheme://"; - $schemeAuthority .= $host.$port; + if ((self::ABSOLUTE_URL === $referenceType || self::NETWORK_PATH === $referenceType) && !empty($host)) { + $port = ''; + if ('http' === $scheme && 80 != $this->context->getHttpPort()) { + $port = ':'.$this->context->getHttpPort(); + } elseif ('https' === $scheme && 443 != $this->context->getHttpsPort()) { + $port = ':'.$this->context->getHttpsPort(); } + + $schemeAuthority = self::NETWORK_PATH === $referenceType ? '//' : "$scheme://"; + $schemeAuthority .= $host.$port; } if (self::RELATIVE_PATH === $referenceType) { diff --git a/src/Symfony/Component/Routing/LICENSE b/src/Symfony/Component/Routing/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/Routing/LICENSE +++ b/src/Symfony/Component/Routing/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Routing/Route.php b/src/Symfony/Component/Routing/Route.php index 19594d057c988..29d352aebd17d 100644 --- a/src/Symfony/Component/Routing/Route.php +++ b/src/Symfony/Component/Routing/Route.php @@ -34,6 +34,8 @@ class Route implements \Serializable private $compiled; /** + * Constructor. + * * Available options: * * * compiler_class: A class name able to compile this route instance (RouteCompiler by default) diff --git a/src/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php b/src/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php index e334e437e1eed..68add771b7189 100644 --- a/src/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php +++ b/src/Symfony/Component/Routing/Tests/Generator/UrlGeneratorTest.php @@ -478,6 +478,38 @@ public function testHostIsCaseInsensitive() $this->assertSame('//EN.FooBar.com/app.php/', $generator->generate('test', array('locale' => 'EN'), UrlGeneratorInterface::NETWORK_PATH)); } + public function testDefaultHostIsUsedWhenContextHostIsEmpty() + { + $routes = $this->getRoutes('test', new Route('/route', array('domain' => 'my.fallback.host'), array('domain' => '.+'), array(), '{domain}', array('http'))); + + $generator = $this->getGenerator($routes); + $generator->getContext()->setHost(''); + + $this->assertSame('http://my.fallback.host/app.php/route', $generator->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_URL)); + } + + public function testDefaultHostIsUsedWhenContextHostIsEmptyAndSchemeIsNot() + { + $routes = $this->getRoutes('test', new Route('/route', array('domain' => 'my.fallback.host'), array('domain' => '.+'), array(), '{domain}', array('http', 'https'))); + + $generator = $this->getGenerator($routes); + $generator->getContext()->setHost(''); + $generator->getContext()->setScheme('https'); + + $this->assertSame('https://my.fallback.host/app.php/route', $generator->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_URL)); + } + + public function testAbsoluteUrlFallbackToRelativeIfHostIsEmptyAndSchemeIsNot() + { + $routes = $this->getRoutes('test', new Route('/route', array(), array(), array(), '', array('http', 'https'))); + + $generator = $this->getGenerator($routes); + $generator->getContext()->setHost(''); + $generator->getContext()->setScheme('https'); + + $this->assertSame('/app.php/route', $generator->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_URL)); + } + public function testGenerateNetworkPath() { $routes = $this->getRoutes('test', new Route('/{name}', array(), array(), array(), '{locale}.example.com', array('http'))); diff --git a/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php b/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php index 37ac752a6bf91..e4c18c47b144f 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php @@ -75,7 +75,7 @@ public function testRedirectPreservesUrlEncoding() ->setMethods(array('redirect')) ->setConstructorArgs(array(new RequestContext())) ->getMock(); - + $matcher->expects($this->once())->method('redirect')->with('/foo%3Abar/', 'foo')->willReturn(array()); $matcher->match('/foo%3Abar'); diff --git a/src/Symfony/Component/Security/Core/LICENSE b/src/Symfony/Component/Security/Core/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/Security/Core/LICENSE +++ b/src/Symfony/Component/Security/Core/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Security/Csrf/LICENSE b/src/Symfony/Component/Security/Csrf/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/Security/Csrf/LICENSE +++ b/src/Symfony/Component/Security/Csrf/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Security/Guard/LICENSE b/src/Symfony/Component/Security/Guard/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/Security/Guard/LICENSE +++ b/src/Symfony/Component/Security/Guard/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Security/Http/LICENSE b/src/Symfony/Component/Security/Http/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/Security/Http/LICENSE +++ b/src/Symfony/Component/Security/Http/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Security/LICENSE b/src/Symfony/Component/Security/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/Security/LICENSE +++ b/src/Symfony/Component/Security/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Serializer/LICENSE b/src/Symfony/Component/Serializer/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/Serializer/LICENSE +++ b/src/Symfony/Component/Serializer/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Serializer/Normalizer/CustomNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/CustomNormalizer.php index b56b10f2dcf70..6a15d8da90270 100644 --- a/src/Symfony/Component/Serializer/Normalizer/CustomNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/CustomNormalizer.php @@ -57,7 +57,7 @@ public function supportsNormalization($data, $format = null) } /** - * Checks if the given class implements the NormalizableInterface. + * Checks if the given class implements the DenormalizableInterface. * * @param mixed $data Data to denormalize from * @param string $type The class to which the data should be denormalized diff --git a/src/Symfony/Component/Stopwatch/LICENSE b/src/Symfony/Component/Stopwatch/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/Stopwatch/LICENSE +++ b/src/Symfony/Component/Stopwatch/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Templating/LICENSE b/src/Symfony/Component/Templating/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/Templating/LICENSE +++ b/src/Symfony/Component/Templating/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Translation/LICENSE b/src/Symfony/Component/Translation/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/Translation/LICENSE +++ b/src/Symfony/Component/Translation/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Validator/LICENSE b/src/Symfony/Component/Validator/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/Validator/LICENSE +++ b/src/Symfony/Component/Validator/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Validator/Tests/Validator/AbstractTest.php b/src/Symfony/Component/Validator/Tests/Validator/AbstractTest.php index 0480a5463283f..6587dae139550 100644 --- a/src/Symfony/Component/Validator/Tests/Validator/AbstractTest.php +++ b/src/Symfony/Component/Validator/Tests/Validator/AbstractTest.php @@ -13,6 +13,7 @@ use Symfony\Component\Validator\Constraints\Callback; use Symfony\Component\Validator\Constraints\Collection; +use Symfony\Component\Validator\Constraints\Expression; use Symfony\Component\Validator\Constraints\GroupSequence; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\NotNull; @@ -581,6 +582,7 @@ public function testAccessCurrentObject() $called = false; $entity = new Entity(); $entity->firstName = 'Bernhard'; + $entity->data = array('firstName' => 'Bernhard'); $callback = function ($value, ExecutionContextInterface $context) use ($entity, &$called) { $called = true; @@ -589,6 +591,7 @@ public function testAccessCurrentObject() $this->metadata->addConstraint(new Callback($callback)); $this->metadata->addPropertyConstraint('firstName', new Callback($callback)); + $this->metadata->addPropertyConstraint('data', new Collection(array('firstName' => new Expression('value == this.firstName')))); $this->validator->validate($entity); diff --git a/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php b/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php index ca3e57a75266b..d1166ad913d65 100644 --- a/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php +++ b/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php @@ -108,7 +108,7 @@ public function validate($value, $constraints = null, $groups = null) $this->validateGenericNode( $value, - null, + $previousObject, is_object($value) ? spl_object_hash($value) : null, $metadata, $this->defaultPropertyPath, diff --git a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php index c8e6929c6eb6e..cfe6d63c75920 100644 --- a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php @@ -208,7 +208,7 @@ public function setMinDepth($minDepth) */ public function cloneVar($var, $filter = 0) { - $this->prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context) { + $this->prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = array()) { if (E_RECOVERABLE_ERROR === $type || E_USER_ERROR === $type) { // Cloner never dies throw new \ErrorException($msg, 0, $type, $file, $line); diff --git a/src/Symfony/Component/VarDumper/LICENSE b/src/Symfony/Component/VarDumper/LICENSE index 207646a052dcd..15fc1c88d330b 100644 --- a/src/Symfony/Component/VarDumper/LICENSE +++ b/src/Symfony/Component/VarDumper/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2014-2017 Fabien Potencier +Copyright (c) 2014-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/VarDumper/VarDumper.php b/src/Symfony/Component/VarDumper/VarDumper.php index 8c610c5d33b86..9236a3d3d12da 100644 --- a/src/Symfony/Component/VarDumper/VarDumper.php +++ b/src/Symfony/Component/VarDumper/VarDumper.php @@ -29,7 +29,7 @@ public static function dump($var) { if (null === self::$handler) { $cloner = new VarCloner(); - $dumper = 'cli' === PHP_SAPI ? new CliDumper() : new HtmlDumper(); + $dumper = in_array(PHP_SAPI, array('cli', 'phpdbg')) ? new CliDumper() : new HtmlDumper(); self::$handler = function ($var) use ($cloner, $dumper) { $dumper->dump($cloner->cloneVar($var)); }; diff --git a/src/Symfony/Component/WebLink/LICENSE b/src/Symfony/Component/WebLink/LICENSE index 17d16a13367dd..21d7fb9e2f29b 100644 --- a/src/Symfony/Component/WebLink/LICENSE +++ b/src/Symfony/Component/WebLink/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2017 Fabien Potencier +Copyright (c) 2004-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Workflow/LICENSE b/src/Symfony/Component/Workflow/LICENSE index 207646a052dcd..15fc1c88d330b 100644 --- a/src/Symfony/Component/Workflow/LICENSE +++ b/src/Symfony/Component/Workflow/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2014-2017 Fabien Potencier +Copyright (c) 2014-2018 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/src/Symfony/Component/Workflow/Tests/DependencyInjection/ValidateWorkflowsPassTest.php b/src/Symfony/Component/Workflow/Tests/DependencyInjection/ValidateWorkflowsPassTest.php index 3b7ddf6d6d7ac..d728cc1195570 100644 --- a/src/Symfony/Component/Workflow/Tests/DependencyInjection/ValidateWorkflowsPassTest.php +++ b/src/Symfony/Component/Workflow/Tests/DependencyInjection/ValidateWorkflowsPassTest.php @@ -1,6 +1,6 @@