diff --git a/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php b/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php index 7469183e75..81cef949c7 100644 --- a/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php @@ -40,11 +40,25 @@ class RoutingExtension extends \Twig_Extension ); } + /** + * @param string $name + * @param array $parameters + * @param bool $relative + * + * @return string + */ public function getPath($name, $parameters = array(), $relative = false) { return $this->generator->generate($name, $parameters, $relative ? UrlGeneratorInterface::RELATIVE_PATH : UrlGeneratorInterface::ABSOLUTE_PATH); } + /** + * @param string $name + * @param array $parameters + * @param bool $schemeRelative + * + * @return string + */ public function getUrl($name, $parameters = array(), $schemeRelative = false) { return $this->generator->generate($name, $parameters, $schemeRelative ? UrlGeneratorInterface::NETWORK_PATH : UrlGeneratorInterface::ABSOLUTE_URL); diff --git a/src/Symfony/Component/Console/Helper/QuestionHelper.php b/src/Symfony/Component/Console/Helper/QuestionHelper.php index 4b4e1a63f9..8998f7b0f3 100644 --- a/src/Symfony/Component/Console/Helper/QuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/QuestionHelper.php @@ -38,7 +38,7 @@ class QuestionHelper extends Helper * @param OutputInterface $output An OutputInterface instance * @param Question $question The question to ask * - * @return string The user answer + * @return mixed The user answer * * @throws RuntimeException If there is no data to read in the input stream */ @@ -384,7 +384,7 @@ class QuestionHelper extends Helper * @param OutputInterface $output An Output instance * @param Question $question A Question instance * - * @return string The validated response + * @return mixed The validated response * * @throws \Exception In case the max number of attempts has been reached and no valid response has been given */ diff --git a/src/Symfony/Component/Console/Helper/Table.php b/src/Symfony/Component/Console/Helper/Table.php index dd775f6957..cf2d0a622c 100644 --- a/src/Symfony/Component/Console/Helper/Table.php +++ b/src/Symfony/Component/Console/Helper/Table.php @@ -440,6 +440,9 @@ class Table foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) { $value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : ''; $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, array('colspan' => $cell->getColspan())); + if ($nbLines === $unmergedRowKey - $line) { + break; + } } } } diff --git a/src/Symfony/Component/Console/Tests/Helper/TableTest.php b/src/Symfony/Component/Console/Tests/Helper/TableTest.php index 6f32048c19..2680f2c201 100644 --- a/src/Symfony/Component/Console/Tests/Helper/TableTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/TableTest.php @@ -298,10 +298,10 @@ TABLE array( array( new TableCell('9971-5-0210-0', array('rowspan' => 3)), - 'Divine Comedy', + new TableCell('Divine Comedy', array('rowspan' => 2)), 'Dante Alighieri', ), - array('A Tale of Two Cities', 'Charles Dickens'), + array(), array("The Lord of \nthe Rings", "J. R. \nR. Tolkien"), new TableSeparator(), array('80-902734-1-6', new TableCell("And Then \nThere \nWere None", array('rowspan' => 3)), 'Agatha Christie'), @@ -309,18 +309,18 @@ TABLE ), 'default', <<<'TABLE' -+---------------+----------------------+-----------------+ -| ISBN | Title | Author | -+---------------+----------------------+-----------------+ -| 9971-5-0210-0 | Divine Comedy | Dante Alighieri | -| | A Tale of Two Cities | Charles Dickens | -| | The Lord of | J. R. | -| | the Rings | R. Tolkien | -+---------------+----------------------+-----------------+ -| 80-902734-1-6 | And Then | Agatha Christie | -| 80-902734-1-7 | There | Test | -| | Were None | | -+---------------+----------------------+-----------------+ ++---------------+---------------+-----------------+ +| ISBN | Title | Author | ++---------------+---------------+-----------------+ +| 9971-5-0210-0 | Divine Comedy | Dante Alighieri | +| | | | +| | The Lord of | J. R. | +| | the Rings | R. Tolkien | ++---------------+---------------+-----------------+ +| 80-902734-1-6 | And Then | Agatha Christie | +| 80-902734-1-7 | There | Test | +| | Were None | | ++---------------+---------------+-----------------+ TABLE ), diff --git a/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php b/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php index f9e6024164..9434ac70b5 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php @@ -12,6 +12,7 @@ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; /** @@ -47,6 +48,9 @@ class MergeExtensionConfigurationPass implements CompilerPassInterface $tmpContainer = new ContainerBuilder($container->getParameterBag()); $tmpContainer->setResourceTracking($container->isTrackingResources()); $tmpContainer->addObjectResource($extension); + if ($extension instanceof ConfigurationExtensionInterface && null !== $configuration = $extension->getConfiguration($config, $tmpContainer)) { + $tmpContainer->addObjectResource($configuration); + } foreach ($exprLangProviders as $provider) { $tmpContainer->addExpressionLanguageProvider($provider); diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index cc6e0e71b3..6863485169 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -64,6 +64,7 @@ class PassConfig new RemoveUnusedDefinitionsPass(), )), new CheckExceptionOnInvalidReferenceBehaviorPass(), + new CheckCircularReferencesPass(), ); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php index c4479403aa..c4eee4033e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/IntegrationTest.php @@ -113,4 +113,30 @@ class IntegrationTest extends \PHPUnit_Framework_TestCase $this->assertFalse($container->hasDefinition('b')); $this->assertFalse($container->hasDefinition('c'), 'Service C was not inlined.'); } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException + */ + public function testCircularReferencesCausedByMethodCallsAreDetectedDuringCompilation() + { + $container = new ContainerBuilder(); + $container->setResourceTracking(false); + + $container + ->register('foobar', '\stdClass') + ->addArgument(new Reference('foo')) + ; + + $container + ->register('foo', '\stdClass') + ->addArgument(new Reference('bar')) + ; + + $container + ->register('foo', '\stdClass') + ->addMethodCall('addFoobar', array(new Reference('foobar'))) + ; + + $container->compile(); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php index 8d957d47b5..6ba0b2f481 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php @@ -11,6 +11,9 @@ namespace Symfony\Component\DependencyInjection\Tests\Compiler; +use Symfony\Component\Config\Definition\Builder\TreeBuilder; +use Symfony\Component\Config\Definition\ConfigurationInterface; +use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\DependencyInjection\Compiler\MergeExtensionConfigurationPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; @@ -48,4 +51,32 @@ class MergeExtensionConfigurationPassTest extends \PHPUnit_Framework_TestCase $this->assertEquals(array($provider), $tmpProviders); } + + public function testExtensionConfigurationIsTrackedByDefault() + { + $extension = $this->getMockBuilder('Symfony\\Component\\DependencyInjection\\Extension\\Extension')->getMock(); + $extension->expects($this->once()) + ->method('getConfiguration') + ->will($this->returnValue(new FooConfiguration())); + $extension->expects($this->any()) + ->method('getAlias') + ->will($this->returnValue('foo')); + + $container = new ContainerBuilder(new ParameterBag()); + $container->registerExtension($extension); + $container->prependExtensionConfig('foo', array('bar' => true)); + + $pass = new MergeExtensionConfigurationPass(); + $pass->process($container); + + $this->assertContains(new FileResource(__FILE__), $container->getResources(), '', false, false); + } +} + +class FooConfiguration implements ConfigurationInterface +{ + public function getConfigTreeBuilder() + { + return new TreeBuilder(); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php index 89475f1fd0..68731d732a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php @@ -63,7 +63,6 @@ $container ; $container ->register('baz', 'Baz') - ->addMethodCall('setFoo', array(new Reference('foo_with_inline'))) ; $container ->register('request', 'Request') diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot index f6536980aa..97771dee56 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot @@ -37,6 +37,5 @@ digraph sc { node_method_call1 -> node_foobaz [label="setBar()" style="dashed"]; node_foo_with_inline -> node_inlined [label="setBar()" style="dashed"]; node_inlined -> node_baz [label="setBaz()" style="dashed"]; - node_baz -> node_foo_with_inline [label="setFoo()" style="dashed"]; node_configurator_service -> node_baz [label="setFoo()" style="dashed"]; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php index aa3c5832dc..3ada9ad23c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php @@ -81,11 +81,7 @@ class ProjectServiceContainer extends Container */ protected function getBazService() { - $this->services['baz'] = $instance = new \Baz(); - - $instance->setFoo($this->get('foo_with_inline')); - - return $instance; + return $this->services['baz'] = new \Baz(); } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index 817bdaaaac..1ff11eaaa7 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -100,11 +100,7 @@ class ProjectServiceContainer extends Container */ protected function getBazService() { - $this->services['baz'] = $instance = new \Baz(); - - $instance->setFoo($this->get('foo_with_inline')); - - return $instance; + return $this->services['baz'] = new \Baz(); } /** @@ -245,12 +241,11 @@ class ProjectServiceContainer extends Container protected function getFooWithInlineService() { $a = new \Bar(); - - $this->services['foo_with_inline'] = $instance = new \Foo(); - $a->pub = 'pub'; $a->setBaz($this->get('baz')); + $this->services['foo_with_inline'] = $instance = new \Foo(); + $instance->setBar($a); return $instance; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml index 72224fe56f..79825ff716 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml @@ -70,11 +70,7 @@ - - - - - + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml index 1afd15c530..4dfe70c161 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml @@ -52,8 +52,6 @@ services: baz: class: Baz - calls: - - [setFoo, ['@foo_with_inline']] request: class: Request diff --git a/src/Symfony/Component/Process/ExecutableFinder.php b/src/Symfony/Component/Process/ExecutableFinder.php index 824457ce2a..d8e689622a 100644 --- a/src/Symfony/Component/Process/ExecutableFinder.php +++ b/src/Symfony/Component/Process/ExecutableFinder.php @@ -75,7 +75,7 @@ class ExecutableFinder $suffixes = array(''); if ('\\' === DIRECTORY_SEPARATOR) { $pathExt = getenv('PATHEXT'); - $suffixes = $pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes; + $suffixes = array_merge($suffixes, $pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes); } foreach ($suffixes as $suffix) { foreach ($dirs as $dir) { diff --git a/src/Symfony/Component/Serializer/NameConverter/CamelCaseToSnakeCaseNameConverter.php b/src/Symfony/Component/Serializer/NameConverter/CamelCaseToSnakeCaseNameConverter.php index d3daf12e46..861c37b349 100644 --- a/src/Symfony/Component/Serializer/NameConverter/CamelCaseToSnakeCaseNameConverter.php +++ b/src/Symfony/Component/Serializer/NameConverter/CamelCaseToSnakeCaseNameConverter.php @@ -44,14 +44,15 @@ class CamelCaseToSnakeCaseNameConverter implements NameConverterInterface public function normalize($propertyName) { if (null === $this->attributes || in_array($propertyName, $this->attributes)) { + $lcPropertyName = lcfirst($propertyName); $snakeCasedName = ''; - $len = strlen($propertyName); + $len = strlen($lcPropertyName); for ($i = 0; $i < $len; ++$i) { - if (ctype_upper($propertyName[$i])) { - $snakeCasedName .= '_'.strtolower($propertyName[$i]); + if (ctype_upper($lcPropertyName[$i])) { + $snakeCasedName .= '_'.strtolower($lcPropertyName[$i]); } else { - $snakeCasedName .= strtolower($propertyName[$i]); + $snakeCasedName .= strtolower($lcPropertyName[$i]); } } diff --git a/src/Symfony/Component/Serializer/Tests/NameConverter/CamelCaseToSnakeCaseNameConverterTest.php b/src/Symfony/Component/Serializer/Tests/NameConverter/CamelCaseToSnakeCaseNameConverterTest.php index 2d57017340..2d7131f237 100644 --- a/src/Symfony/Component/Serializer/Tests/NameConverter/CamelCaseToSnakeCaseNameConverterTest.php +++ b/src/Symfony/Component/Serializer/Tests/NameConverter/CamelCaseToSnakeCaseNameConverterTest.php @@ -27,27 +27,30 @@ class CamelCaseToSnakeCaseNameConverterTest extends \PHPUnit_Framework_TestCase /** * @dataProvider attributeProvider */ - public function testNormalize($underscored, $lowerCamelCased) + public function testNormalize($underscored, $camelCased, $useLowerCamelCase) { - $nameConverter = new CamelCaseToSnakeCaseNameConverter(); - $this->assertEquals($nameConverter->normalize($lowerCamelCased), $underscored); + $nameConverter = new CamelCaseToSnakeCaseNameConverter(null, $useLowerCamelCase); + $this->assertEquals($nameConverter->normalize($camelCased), $underscored); } /** * @dataProvider attributeProvider */ - public function testDenormalize($underscored, $lowerCamelCased) + public function testDenormalize($underscored, $camelCased, $useLowerCamelCase) { - $nameConverter = new CamelCaseToSnakeCaseNameConverter(); - $this->assertEquals($nameConverter->denormalize($underscored), $lowerCamelCased); + $nameConverter = new CamelCaseToSnakeCaseNameConverter(null, $useLowerCamelCase); + $this->assertEquals($nameConverter->denormalize($underscored), $camelCased); } public function attributeProvider() { return array( - array('coop_tilleuls', 'coopTilleuls'), - array('_kevin_dunglas', '_kevinDunglas'), - array('this_is_a_test', 'thisIsATest'), + array('coop_tilleuls', 'coopTilleuls', true), + array('_kevin_dunglas', '_kevinDunglas', true), + array('this_is_a_test', 'thisIsATest', true), + array('coop_tilleuls', 'CoopTilleuls', false), + array('_kevin_dunglas', '_kevinDunglas', false), + array('this_is_a_test', 'ThisIsATest', false), ); } }