From 1bea774f4de173de64f63d0d64d83473c706a989 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 12 Aug 2017 22:32:56 +0200 Subject: [PATCH 1/7] [VarDumper] play nice with open_basedir when looking for composer.json --- src/Symfony/Component/VarDumper/Caster/LinkStub.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/VarDumper/Caster/LinkStub.php b/src/Symfony/Component/VarDumper/Caster/LinkStub.php index 1a9aa419d1..eb9bc85c91 100644 --- a/src/Symfony/Component/VarDumper/Caster/LinkStub.php +++ b/src/Symfony/Component/VarDumper/Caster/LinkStub.php @@ -89,7 +89,11 @@ class LinkStub extends ConstStub } $parent = $dir; - while (!file_exists($parent.'/composer.json')) { + while (!@file_exists($parent.'/composer.json')) { + if (!@file_exists($parent)) { + // open_basedir restriction in effect + break; + } if ($parent === dirname($parent)) { return self::$composerRoots[$dir] = false; } From 1a5fd79c21cf43274e517884fdb5b187038bff64 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Tue, 15 Aug 2017 15:11:19 +0200 Subject: [PATCH 2/7] Allow phpdocumentor/reflection-docblock 4. --- composer.json | 2 +- src/Symfony/Bundle/FrameworkBundle/composer.json | 2 +- src/Symfony/Component/PropertyInfo/composer.json | 2 +- src/Symfony/Component/Serializer/composer.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 00faa0845d..ff894a349e 100644 --- a/composer.json +++ b/composer.json @@ -98,7 +98,7 @@ "symfony/phpunit-bridge": "~3.2", "symfony/polyfill-apcu": "~1.1", "symfony/security-acl": "~2.8|~3.0", - "phpdocumentor/reflection-docblock": "^3.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0", "sensio/framework-extra-bundle": "^3.0.2" }, "conflict": { diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index c605471911..f542a5a2a8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -55,7 +55,7 @@ "symfony/property-info": "~3.3", "symfony/web-link": "~3.3", "doctrine/annotations": "~1.0", - "phpdocumentor/reflection-docblock": "^3.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0", "twig/twig": "~1.34|~2.4", "sensio/framework-extra-bundle": "^3.0.2" }, diff --git a/src/Symfony/Component/PropertyInfo/composer.json b/src/Symfony/Component/PropertyInfo/composer.json index 13aebfbf0e..d068a5ff6a 100644 --- a/src/Symfony/Component/PropertyInfo/composer.json +++ b/src/Symfony/Component/PropertyInfo/composer.json @@ -30,7 +30,7 @@ "symfony/serializer": "~2.8|~3.0", "symfony/cache": "~3.1", "symfony/dependency-injection": "~3.3", - "phpdocumentor/reflection-docblock": "^3.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0", "doctrine/annotations": "~1.0" }, "conflict": { diff --git a/src/Symfony/Component/Serializer/composer.json b/src/Symfony/Component/Serializer/composer.json index cd9fd88371..e4ee63a730 100644 --- a/src/Symfony/Component/Serializer/composer.json +++ b/src/Symfony/Component/Serializer/composer.json @@ -28,7 +28,7 @@ "doctrine/annotations": "~1.0", "symfony/dependency-injection": "~3.2", "doctrine/cache": "~1.0", - "phpdocumentor/reflection-docblock": "~3.0" + "phpdocumentor/reflection-docblock": "^3.0|^4.0" }, "conflict": { "symfony/dependency-injection": "<3.2", From 2e4e6ad62662e309605d930aa58978b1f88a6fe6 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 12 Aug 2017 11:24:07 +0200 Subject: [PATCH 3/7] [HttpKernel] Remove old container files --- src/Symfony/Component/HttpKernel/Kernel.php | 18 ++++++++- .../Component/HttpKernel/Tests/KernelTest.php | 40 +++++++++++++++++-- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index a6c31e8a3f..8c70005d28 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -584,6 +584,11 @@ abstract class Kernel implements KernelInterface, TerminableInterface file_put_contents($this->getCacheDir().'/'.$class.'Compiler.log', null !== $container ? implode("\n", $container->getCompiler()->getLog()) : ''); } } + + if ($oldContainer = file_exists($cache->getPath()) ? @include $cache->getPath() : false) { + $oldContainer = new \ReflectionClass($oldContainer); + } + $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass()); $fresh = false; @@ -592,7 +597,15 @@ abstract class Kernel implements KernelInterface, TerminableInterface $this->container = require $cache->getPath(); $this->container->set('kernel', $this); - if (!$fresh && $this->container->has('cache_warmer')) { + if ($fresh) { + return; + } + + if ($oldContainer && get_class($this->container) !== $oldContainer->name) { + (new Filesystem())->remove(dirname($oldContainer->getFileName())); + } + + if ($this->container->has('cache_warmer')) { $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir')); } } @@ -773,6 +786,9 @@ abstract class Kernel implements KernelInterface, TerminableInterface @chmod($dir.$file, 0666 & ~umask()); } + // track changes made to the container directory + $container->fileExists(dirname($dir.$file)); + $cache->write($rootCode, $container->getResources()); } diff --git a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php index 052e5766d6..4392e30e65 100644 --- a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php @@ -771,13 +771,38 @@ EOF; public function testProjectDirExtension() { - $kernel = new CustomProjectDirKernel('test', true); + $kernel = new CustomProjectDirKernel(); $kernel->boot(); $this->assertSame('foo', $kernel->getProjectDir()); $this->assertSame('foo', $kernel->getContainer()->getParameter('kernel.project_dir')); } + public function testKernelReset() + { + (new Filesystem())->remove(__DIR__.'/Fixtures/cache'); + + $kernel = new CustomProjectDirKernel(); + $kernel->boot(); + + $containerClass = get_class($kernel->getContainer()); + $containerFile = (new \ReflectionClass($kernel->getContainer()))->getFileName(); + unlink(__DIR__.'/Fixtures/cache/custom/FixturesCustomDebugProjectContainer.php.meta'); + + $kernel = new CustomProjectDirKernel(); + $kernel->boot(); + + $this->assertSame($containerClass, get_class($kernel->getContainer())); + $this->assertFileExists($containerFile); + unlink(__DIR__.'/Fixtures/cache/custom/FixturesCustomDebugProjectContainer.php.meta'); + + $kernel = new CustomProjectDirKernel(function ($container) { $container->register('foo', 'stdClass'); }); + $kernel->boot(); + + $this->assertTrue(get_class($kernel->getContainer()) !== $containerClass); + $this->assertFileNotExists($containerFile); + } + /** * Returns a mock for the BundleInterface. * @@ -878,12 +903,14 @@ class TestKernel implements HttpKernelInterface class CustomProjectDirKernel extends Kernel { private $baseDir; + private $buildContainer; - public function __construct() + public function __construct(\Closure $buildContainer = null) { - parent::__construct('test', false); + parent::__construct('custom', true); $this->baseDir = 'foo'; + $this->buildContainer = $buildContainer; } public function registerBundles() @@ -904,4 +931,11 @@ class CustomProjectDirKernel extends Kernel { return __DIR__.'/Fixtures'; } + + protected function build(ContainerBuilder $container) + { + if ($build = $this->buildContainer) { + $build($container); + } + } } From adff65a60246817685de0c1a68998364c9d6ffcf Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 16 Aug 2017 10:13:36 +0200 Subject: [PATCH 4/7] [DI] Fix reading env vars from fastcgi params --- .../Compiler/ServiceLocatorTagPass.php | 7 ++--- .../DependencyInjection/Container.php | 5 +++- .../DependencyInjection/ContainerBuilder.php | 15 ++++++----- .../EnvPlaceholderParameterBag.php | 26 +++++++++++++++++++ .../Tests/ContainerBuilderTest.php | 24 +++++++++++------ 5 files changed, 57 insertions(+), 20 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ServiceLocatorTagPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ServiceLocatorTagPass.php index bf9f83bbe8..59c5e39022 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ServiceLocatorTagPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ServiceLocatorTagPass.php @@ -54,20 +54,17 @@ final class ServiceLocatorTagPass extends AbstractRecursivePass $value->setArguments($arguments); - if ($public = $value->isPublic()) { - $value->setPublic(false); - } $id = 'service_locator.'.md5(serialize($value)); if ($isRoot) { if ($id !== $this->currentId) { - $this->container->setAlias($id, new Alias($this->currentId, $public)); + $this->container->setAlias($id, new Alias($this->currentId, false)); } return $value; } - $this->container->setDefinition($id, $value); + $this->container->setDefinition($id, $value->setPublic(false)); return new Reference($id); } diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index 3b0a82d80e..81241e3415 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -429,7 +429,7 @@ class Container implements ResettableContainerInterface * * @param string $name The name of the environment variable * - * @return scalar The value to use for the provided environment variable name + * @return mixed The value to use for the provided environment variable name * * @throws EnvNotFoundException When the environment variable is not found and has no default value */ @@ -438,6 +438,9 @@ class Container implements ResettableContainerInterface if (isset($this->envCache[$name]) || array_key_exists($name, $this->envCache)) { return $this->envCache[$name]; } + if (0 !== strpos($name, 'HTTP_') && isset($_SERVER[$name])) { + return $this->envCache[$name] = $_SERVER[$name]; + } if (isset($_ENV[$name])) { return $this->envCache[$name] = $_ENV[$name]; } diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 555c3b0973..4f86cd0468 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -729,9 +729,10 @@ class ContainerBuilder extends Container implements TaggedContainerInterface $bag = $this->getParameterBag(); if ($resolveEnvPlaceholders && $bag instanceof EnvPlaceholderParameterBag) { - $this->parameterBag = new ParameterBag($this->resolveEnvPlaceholders($bag->all(), true)); + $bag->resolveEnvReferences(); + $this->parameterBag = new ParameterBag($bag->all()); $this->envPlaceholders = $bag->getEnvPlaceholders(); - $this->parameterBag = $bag = new ParameterBag($this->resolveEnvPlaceholders($this->parameterBag->all())); + $this->parameterBag = $bag = new ParameterBag($this->resolveEnvPlaceholders($bag->all(), true)); } $compiler->compile($this); @@ -746,7 +747,9 @@ class ContainerBuilder extends Container implements TaggedContainerInterface parent::compile(); - $this->envPlaceholders = $bag instanceof EnvPlaceholderParameterBag ? $bag->getEnvPlaceholders() : array(); + if ($bag instanceof EnvPlaceholderParameterBag) { + $this->envPlaceholders = $bag->getEnvPlaceholders(); + } } /** @@ -1311,10 +1314,10 @@ class ContainerBuilder extends Container implements TaggedContainerInterface foreach ($envPlaceholders as $env => $placeholders) { foreach ($placeholders as $placeholder) { if (false !== stripos($value, $placeholder)) { - if (true === $format) { - $resolved = $bag->escapeValue($this->getEnv($env)); - } else { + if (true !== $format) { $resolved = sprintf($format, $env); + } elseif ($placeholder === $resolved = $bag->escapeValue($this->getEnv($env))) { + $resolved = $bag->all()[strtolower("env($env)")]; } $value = str_ireplace($placeholder, $resolved, $value); $usedEnvs[$env] = $env; diff --git a/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php b/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php index d20e53531a..34f79477fa 100644 --- a/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php +++ b/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php @@ -20,6 +20,7 @@ use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; class EnvPlaceholderParameterBag extends ParameterBag { private $envPlaceholders = array(); + private $resolveEnvReferences = false; /** * {@inheritdoc} @@ -101,4 +102,29 @@ class EnvPlaceholderParameterBag extends ParameterBag } } } + + /** + * Replaces "%env(FOO)%" references by their placeholder, keeping regular "%parameters%" references as is. + */ + public function resolveEnvReferences() + { + $this->resolveEnvReferences = true; + try { + $this->resolve(); + } finally { + $this->resolveEnvReferences = false; + } + } + + /** + * {@inheritdoc} + */ + public function resolveString($value, array $resolving = array()) + { + if ($this->resolveEnvReferences) { + return preg_replace_callback('/%%|%(env\([^%\s]+\))%/', function ($match) { return isset($match[1]) ? $this->get($match[1]) : '%%'; }, $value); + } + + return parent::resolveString($value, $resolving); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 51397309b7..7ab2e7c6f6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -603,29 +603,37 @@ class ContainerBuilderTest extends TestCase public function testResolveEnvValues() { $_ENV['DUMMY_ENV_VAR'] = 'du%%y'; + $_SERVER['DUMMY_SERVER_VAR'] = 'ABC'; + $_SERVER['HTTP_DUMMY_VAR'] = 'DEF'; $container = new ContainerBuilder(); - $container->setParameter('bar', '%% %env(DUMMY_ENV_VAR)%'); + $container->setParameter('bar', '%% %env(DUMMY_ENV_VAR)% %env(DUMMY_SERVER_VAR)% %env(HTTP_DUMMY_VAR)%'); + $container->setParameter('env(HTTP_DUMMY_VAR)', '123'); - $this->assertSame('%% du%%%%y', $container->resolveEnvPlaceholders('%bar%', true)); + $this->assertSame('%% du%%%%y ABC 123', $container->resolveEnvPlaceholders('%bar%', true)); - unset($_ENV['DUMMY_ENV_VAR']); + unset($_ENV['DUMMY_ENV_VAR'], $_SERVER['DUMMY_SERVER_VAR'], $_SERVER['HTTP_DUMMY_VAR']); } public function testCompileWithResolveEnv() { - $_ENV['DUMMY_ENV_VAR'] = 'du%%y'; + putenv('DUMMY_ENV_VAR=du%%y'); + $_SERVER['DUMMY_SERVER_VAR'] = 'ABC'; + $_SERVER['HTTP_DUMMY_VAR'] = 'DEF'; $container = new ContainerBuilder(); $container->setParameter('env(FOO)', 'Foo'); - $container->setParameter('bar', '%% %env(DUMMY_ENV_VAR)%'); + $container->setParameter('bar', '%% %env(DUMMY_ENV_VAR)% %env(DUMMY_SERVER_VAR)% %env(HTTP_DUMMY_VAR)%'); $container->setParameter('foo', '%env(FOO)%'); + $container->setParameter('baz', '%foo%'); + $container->setParameter('env(HTTP_DUMMY_VAR)', '123'); $container->compile(true); - $this->assertSame('% du%%y', $container->getParameter('bar')); - $this->assertSame('Foo', $container->getParameter('foo')); + $this->assertSame('% du%%y ABC 123', $container->getParameter('bar')); + $this->assertSame('Foo', $container->getParameter('baz')); - unset($_ENV['DUMMY_ENV_VAR']); + unset($_SERVER['DUMMY_SERVER_VAR'], $_SERVER['HTTP_DUMMY_VAR']); + putenv('DUMMY_ENV_VAR'); } /** From 046f8c101bdca3b6fc9a1559935e219815d80c77 Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Sat, 5 Aug 2017 01:29:29 +0200 Subject: [PATCH 5/7] [VarDumper] Fix interval caster with PT3600S-like spec --- .../Component/VarDumper/Caster/DateCaster.php | 13 ++++++++----- .../VarDumper/Tests/Caster/DateCasterTest.php | 8 ++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Caster/DateCaster.php b/src/Symfony/Component/VarDumper/Caster/DateCaster.php index 5a59ca48e1..68290930bf 100644 --- a/src/Symfony/Component/VarDumper/Caster/DateCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/DateCaster.php @@ -52,11 +52,14 @@ class DateCaster private static function formatInterval(\DateInterval $i) { - $format = '%R ' - .($i->y ? '%yy ' : '') - .($i->m ? '%mm ' : '') - .($i->d ? '%dd ' : '') - ; + $format = '%R '; + + if ($i->y === 0 && $i->m === 0 && ($i->h >= 24 || $i->i >= 60 || $i->s >= 60)) { + $i = date_diff($d = new \DateTime(), date_add(clone $d, $i)); // recalculate carry over points + $format .= 0 < $i->days ? '%ad ' : ''; + } else { + $format .= ($i->y ? '%yy ' : '').($i->m ? '%mm ' : '').($i->d ? '%dd ' : ''); + } if (\PHP_VERSION_ID >= 70100 && isset($i->f)) { $format .= $i->h || $i->i || $i->s || $i->f ? '%H:%I:%S.%F' : ''; diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php index d470bbc191..3f325f5d6e 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php @@ -173,6 +173,10 @@ EODUMP; array('P5M', 0, '+ 5m', null), array('P6Y', 0, '+ 6y', null), array('P1Y2M3DT4H5M6S', 0, '+ 1y 2m 3d 04:05:06'.$ms, null), + array('PT1M60S', 0, '+ 00:02:00'.$ms, null), + array('PT1H60M', 0, '+ 02:00:00'.$ms, null), + array('P1DT24H', 0, '+ 2d', null), + array('P1M32D', 0, '+ 1m 32d', null), array('PT0S', 1, '0s', '0s'), array('PT1S', 1, '- 00:00:01'.$ms, '-1s'), @@ -182,6 +186,10 @@ EODUMP; array('P5M', 1, '- 5m', null), array('P6Y', 1, '- 6y', null), array('P1Y2M3DT4H5M6S', 1, '- 1y 2m 3d 04:05:06'.$ms, null), + array('PT1M60S', 1, '- 00:02:00'.$ms, null), + array('PT1H60M', 1, '- 02:00:00'.$ms, null), + array('P1DT24H', 1, '- 2d', null), + array('P1M32D', 1, '- 1m 32d', null), ); } From 06bbee862f91cd2e6862132cab148b809a5e46d4 Mon Sep 17 00:00:00 2001 From: Oleg Voronkovich Date: Sun, 18 Jun 2017 20:41:58 +0300 Subject: [PATCH 6/7] [Routing] Use "controller" keyword for configuring routes controllers --- src/Symfony/Component/Routing/CHANGELOG.md | 1 + .../Routing/Loader/XmlFileLoader.php | 10 +++ .../Routing/Loader/YamlFileLoader.php | 13 +++- .../Loader/schema/routing/routing-1.0.xsd | 2 + .../controller/import__controller.xml | 10 +++ .../controller/import__controller.yml | 4 + .../Fixtures/controller/import_controller.xml | 8 ++ .../Fixtures/controller/import_controller.yml | 3 + .../controller/import_override_defaults.xml | 10 +++ .../controller/import_override_defaults.yml | 5 ++ .../Fixtures/controller/override_defaults.xml | 10 +++ .../Fixtures/controller/override_defaults.yml | 5 ++ .../Tests/Fixtures/controller/routing.xml | 14 ++++ .../Tests/Fixtures/controller/routing.yml | 11 +++ .../Tests/Loader/XmlFileLoaderTest.php | 74 +++++++++++++++++++ .../Tests/Loader/YamlFileLoaderTest.php | 74 +++++++++++++++++++ 16 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/controller/import__controller.xml create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/controller/import__controller.yml create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/controller/import_controller.xml create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/controller/import_controller.yml create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/controller/import_override_defaults.xml create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/controller/import_override_defaults.yml create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/controller/override_defaults.xml create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/controller/override_defaults.yml create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/controller/routing.xml create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/controller/routing.yml diff --git a/src/Symfony/Component/Routing/CHANGELOG.md b/src/Symfony/Component/Routing/CHANGELOG.md index b79318e29a..33faeb73aa 100644 --- a/src/Symfony/Component/Routing/CHANGELOG.md +++ b/src/Symfony/Component/Routing/CHANGELOG.md @@ -6,6 +6,7 @@ CHANGELOG * Added support for prioritized routing loaders. * Add matched and default parameters to redirect responses + * Added support for a `controller` keyword for configuring route controllers in YAML and XML configurations. 3.3.0 ----- diff --git a/src/Symfony/Component/Routing/Loader/XmlFileLoader.php b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php index 8a6e8ce359..6a3322bb8c 100644 --- a/src/Symfony/Component/Routing/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php @@ -229,6 +229,16 @@ class XmlFileLoader extends FileLoader } } + if ($controller = $node->getAttribute('controller')) { + if (isset($defaults['_controller'])) { + $name = $node->hasAttribute('id') ? sprintf('"%s"', $node->getAttribute('id')) : sprintf('the "%s" tag', $node->tagName); + + throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "controller" attribute and the defaults key "_controller" for %s.', $path, $name)); + } + + $defaults['_controller'] = $controller; + } + return array($defaults, $requirements, $options, $condition); } diff --git a/src/Symfony/Component/Routing/Loader/YamlFileLoader.php b/src/Symfony/Component/Routing/Loader/YamlFileLoader.php index 31314011b9..5a08751321 100644 --- a/src/Symfony/Component/Routing/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/YamlFileLoader.php @@ -27,7 +27,7 @@ use Symfony\Component\Config\Loader\FileLoader; class YamlFileLoader extends FileLoader { private static $availableKeys = array( - 'resource', 'type', 'prefix', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', 'condition', + 'resource', 'type', 'prefix', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', 'condition', 'controller', ); private $yamlParser; @@ -115,6 +115,10 @@ class YamlFileLoader extends FileLoader $methods = isset($config['methods']) ? $config['methods'] : array(); $condition = isset($config['condition']) ? $config['condition'] : null; + if (isset($config['controller'])) { + $defaults['_controller'] = $config['controller']; + } + $route = new Route($config['path'], $defaults, $requirements, $options, $host, $schemes, $methods, $condition); $collection->add($name, $route); @@ -140,6 +144,10 @@ class YamlFileLoader extends FileLoader $schemes = isset($config['schemes']) ? $config['schemes'] : null; $methods = isset($config['methods']) ? $config['methods'] : null; + if (isset($config['controller'])) { + $defaults['_controller'] = $config['controller']; + } + $this->setCurrentDir(dirname($path)); $subCollection = $this->import($config['resource'], $type, false, $file); @@ -203,5 +211,8 @@ class YamlFileLoader extends FileLoader $name, $path )); } + if (isset($config['controller']) && isset($config['defaults']['_controller'])) { + throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "controller" key and the defaults key "_controller" for "%s".', $path, $name)); + } } } diff --git a/src/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd b/src/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd index 92d4ae2078..a97111aaa5 100644 --- a/src/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd +++ b/src/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd @@ -41,6 +41,7 @@ + @@ -52,6 +53,7 @@ + diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/controller/import__controller.xml b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import__controller.xml new file mode 100644 index 0000000000..bbe727d41b --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import__controller.xml @@ -0,0 +1,10 @@ + + + + + FrameworkBundle:Template:template + + diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/controller/import__controller.yml b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import__controller.yml new file mode 100644 index 0000000000..4240b74dc6 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import__controller.yml @@ -0,0 +1,4 @@ +_static: + resource: routing.yml + defaults: + _controller: FrameworkBundle:Template:template diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_controller.xml b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_controller.xml new file mode 100644 index 0000000000..378b9ca18f --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_controller.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_controller.yml b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_controller.yml new file mode 100644 index 0000000000..1a71c62b27 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_controller.yml @@ -0,0 +1,3 @@ +_static: + resource: routing.yml + controller: FrameworkBundle:Template:template diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_override_defaults.xml b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_override_defaults.xml new file mode 100644 index 0000000000..e3c755a40a --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_override_defaults.xml @@ -0,0 +1,10 @@ + + + + + AppBundle:Blog:index + + diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_override_defaults.yml b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_override_defaults.yml new file mode 100644 index 0000000000..db1ab3cbed --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_override_defaults.yml @@ -0,0 +1,5 @@ +_static: + resource: routing.yml + controller: FrameworkBundle:Template:template + defaults: + _controller: AppBundle:Homepage:show diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/controller/override_defaults.xml b/src/Symfony/Component/Routing/Tests/Fixtures/controller/override_defaults.xml new file mode 100644 index 0000000000..f47c57b308 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/controller/override_defaults.xml @@ -0,0 +1,10 @@ + + + + + AppBundle:Blog:index + + diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/controller/override_defaults.yml b/src/Symfony/Component/Routing/Tests/Fixtures/controller/override_defaults.yml new file mode 100644 index 0000000000..00a2c0e976 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/controller/override_defaults.yml @@ -0,0 +1,5 @@ +app_blog: + path: /blog + controller: AppBundle:Homepage:show + defaults: + _controller: AppBundle:Blog:index diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/controller/routing.xml b/src/Symfony/Component/Routing/Tests/Fixtures/controller/routing.xml new file mode 100644 index 0000000000..6420138a65 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/controller/routing.xml @@ -0,0 +1,14 @@ + + + + + + + AppBundle:Blog:list + + + + diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/controller/routing.yml b/src/Symfony/Component/Routing/Tests/Fixtures/controller/routing.yml new file mode 100644 index 0000000000..cb71ec3b75 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/controller/routing.yml @@ -0,0 +1,11 @@ +app_homepage: + path: / + controller: AppBundle:Homepage:show + +app_blog: + path: /blog + defaults: + _controller: AppBundle:Blog:list + +app_logout: + path: /logout diff --git a/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php index d24ec79a79..221434b006 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php @@ -287,4 +287,78 @@ class XmlFileLoaderTest extends TestCase $route->getDefault('map') ); } + + public function testLoadRouteWithControllerAttribute() + { + $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $routeCollection = $loader->load('routing.xml'); + + $route = $routeCollection->get('app_homepage'); + + $this->assertSame('AppBundle:Homepage:show', $route->getDefault('_controller')); + } + + public function testLoadRouteWithoutControllerAttribute() + { + $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $routeCollection = $loader->load('routing.xml'); + + $route = $routeCollection->get('app_logout'); + + $this->assertNull($route->getDefault('_controller')); + } + + public function testLoadRouteWithControllerSetInDefaults() + { + $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $routeCollection = $loader->load('routing.xml'); + + $route = $routeCollection->get('app_blog'); + + $this->assertSame('AppBundle:Blog:list', $route->getDefault('_controller')); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessageRegExp /The routing file "[^"]*" must not specify both the "controller" attribute and the defaults key "_controller" for "app_blog"/ + */ + public function testOverrideControllerInDefaults() + { + $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $loader->load('override_defaults.xml'); + } + + /** + * @dataProvider provideFilesImportingRoutesWithControllers + */ + public function testImportRouteWithController($file) + { + $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $routeCollection = $loader->load($file); + + $route = $routeCollection->get('app_homepage'); + $this->assertSame('FrameworkBundle:Template:template', $route->getDefault('_controller')); + + $route = $routeCollection->get('app_blog'); + $this->assertSame('FrameworkBundle:Template:template', $route->getDefault('_controller')); + + $route = $routeCollection->get('app_logout'); + $this->assertSame('FrameworkBundle:Template:template', $route->getDefault('_controller')); + } + + public function provideFilesImportingRoutesWithControllers() + { + yield array('import_controller.xml'); + yield array('import__controller.xml'); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessageRegExp /The routing file "[^"]*" must not specify both the "controller" attribute and the defaults key "_controller" for the "import" tag/ + */ + public function testImportWithOverriddenController() + { + $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $loader->load('import_override_defaults.xml'); + } } diff --git a/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php index 8342c266df..1f7fd43897 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php @@ -108,4 +108,78 @@ class YamlFileLoaderTest extends TestCase $this->assertSame('context.getMethod() == "POST"', $route->getCondition()); } } + + public function testLoadRouteWithControllerAttribute() + { + $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $routeCollection = $loader->load('routing.yml'); + + $route = $routeCollection->get('app_homepage'); + + $this->assertSame('AppBundle:Homepage:show', $route->getDefault('_controller')); + } + + public function testLoadRouteWithoutControllerAttribute() + { + $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $routeCollection = $loader->load('routing.yml'); + + $route = $routeCollection->get('app_logout'); + + $this->assertNull($route->getDefault('_controller')); + } + + public function testLoadRouteWithControllerSetInDefaults() + { + $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $routeCollection = $loader->load('routing.yml'); + + $route = $routeCollection->get('app_blog'); + + $this->assertSame('AppBundle:Blog:list', $route->getDefault('_controller')); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessageRegExp /The routing file "[^"]*" must not specify both the "controller" key and the defaults key "_controller" for "app_blog"/ + */ + public function testOverrideControllerInDefaults() + { + $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $loader->load('override_defaults.yml'); + } + + /** + * @dataProvider provideFilesImportingRoutesWithControllers + */ + public function testImportRouteWithController($file) + { + $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $routeCollection = $loader->load($file); + + $route = $routeCollection->get('app_homepage'); + $this->assertSame('FrameworkBundle:Template:template', $route->getDefault('_controller')); + + $route = $routeCollection->get('app_blog'); + $this->assertSame('FrameworkBundle:Template:template', $route->getDefault('_controller')); + + $route = $routeCollection->get('app_logout'); + $this->assertSame('FrameworkBundle:Template:template', $route->getDefault('_controller')); + } + + public function provideFilesImportingRoutesWithControllers() + { + yield array('import_controller.yml'); + yield array('import__controller.yml'); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessageRegExp /The routing file "[^"]*" must not specify both the "controller" key and the defaults key "_controller" for "_static"/ + */ + public function testImportWithOverriddenController() + { + $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $loader->load('import_override_defaults.yml'); + } } From 773f166d5e78b5aaa012580f17a62fb1104407e9 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 17 Aug 2017 15:29:00 +0200 Subject: [PATCH 7/7] [VarDumper] Fix tests with phpredis 3.1.3 --- .../Component/VarDumper/Tests/Caster/RedisCasterTest.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/RedisCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/RedisCasterTest.php index af038192f5..80acdb6679 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/RedisCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/RedisCasterTest.php @@ -61,8 +61,7 @@ Redis { EODUMP; } else { $xCast = <<<'EODUMP' -Redis { - +"socket": Redis Socket Buffer resource +Redis {%A isConnected: true host: "127.0.0.1" port: 6379