From 2b2f0df27e0180b14efc65c7ff2dface448cd1f0 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 25 Sep 2014 09:50:05 +0200 Subject: [PATCH 1/4] Fix expression language in the container when using the "container" variable --- .../DependencyInjection/Dumper/PhpDumper.php | 2 +- .../Tests/Fixtures/containers/container9.php | 2 +- .../Tests/Fixtures/php/services9.php | 2 +- .../Tests/Fixtures/php/services9_compiled.php | 2 +- .../Tests/Fixtures/xml/services6.xml | 2 +- .../Tests/Fixtures/xml/services9.xml | 2 +- .../Tests/Fixtures/yaml/services6.yml | 2 +- .../Tests/Fixtures/yaml/services9.yml | 2 +- .../Tests/Loader/XmlFileLoaderTest.php | 2 +- .../Tests/Loader/YamlFileLoaderTest.php | 2 +- .../Component/ExpressionLanguage/Parser.php | 18 +++++++++++++++++- .../ExpressionLanguage/Tests/ParserTest.php | 6 ++++++ 12 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 01f0266c45..ed85efa4e0 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -1212,7 +1212,7 @@ EOF; return $this->getServiceCall((string) $value, $value); } elseif ($value instanceof Expression) { - return $this->getExpressionLanguage()->compile((string) $value, array('container')); + return $this->getExpressionLanguage()->compile((string) $value, array('this' => 'container')); } elseif ($value instanceof Parameter) { return $this->dumpParameter($value); } elseif (true === $interpolate && is_string($value)) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php index 19882c0211..582c631fa7 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php @@ -52,7 +52,7 @@ $container-> addMethodCall('setBar', array(new Reference('foo2', ContainerInterface::NULL_ON_INVALID_REFERENCE)))-> addMethodCall('setBar', array(new Reference('foo3', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)))-> addMethodCall('setBar', array(new Reference('foobaz', ContainerInterface::IGNORE_ON_INVALID_REFERENCE)))-> - addMethodCall('setBar', array(new Expression('service("foo").foo() ~ parameter("foo")'))) + addMethodCall('setBar', array(new Expression('service("foo").foo() ~ (container.hasparameter("foo") ? parameter("foo") : "default")'))) ; $container-> register('factory_service', 'Bar')-> diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php index 84036928bf..b225259ff6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php @@ -197,7 +197,7 @@ class ProjectServiceContainer extends Container if ($this->has('foobaz')) { $instance->setBar($this->get('foobaz', ContainerInterface::NULL_ON_INVALID_REFERENCE)); } - $instance->setBar(($this->get("foo")->foo() . $this->getParameter("foo"))); + $instance->setBar(($this->get("foo")->foo() . (($this->hasparameter("foo")) ? ($this->getParameter("foo")) : ("default")))); return $instance; } 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 0dd611e90c..1bb87851fc 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -202,7 +202,7 @@ class ProjectServiceContainer extends Container $instance->setBar($this->get('foo')); $instance->setBar(NULL); - $instance->setBar(($this->get("foo")->foo() . $this->getParameter("foo"))); + $instance->setBar(($this->get("foo")->foo() . (($this->hasparameter("foo")) ? ($this->getParameter("foo")) : ("default")))); return $instance; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml index ffc038234f..eb47fe71a1 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml @@ -33,7 +33,7 @@ - service("foo").foo() ~ parameter("foo") + service("foo").foo() ~ (container.hasparameter("foo") ? parameter("foo") : "default") diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml index 294ad5c589..95b6e7d686 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml @@ -54,7 +54,7 @@ - service("foo").foo() ~ parameter("foo") + service("foo").foo() ~ (container.hasparameter("foo") ? parameter("foo") : "default") diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml index d3c793f2e3..38fdef814c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml @@ -15,7 +15,7 @@ services: calls: - [ setBar, [] ] - [ setBar ] - - [ setBar, ['@=service("foo").foo() ~ parameter("foo")'] ] + - [ setBar, ['@=service("foo").foo() ~ (container.hasparameter("foo") ? parameter("foo") : "default")'] ] method_call2: class: FooClass calls: diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml index 6de64ee463..6529192cd6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml @@ -38,7 +38,7 @@ services: - [setBar, ['@?foo2']] - [setBar, ['@?foo3']] - [setBar, ['@?foobaz']] - - [setBar, ['@=service("foo").foo() ~ parameter("foo")']] + - [setBar, ['@=service("foo").foo() ~ (container.hasparameter("foo") ? parameter("foo") : "default")']] factory_service: class: Bar diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php index 95ad9aa742..986e0aa0d1 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php @@ -210,7 +210,7 @@ class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase $this->assertEquals('sc_configure', $services['configurator1']->getConfigurator(), '->load() parses the configurator tag'); $this->assertEquals(array(new Reference('baz', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, false), 'configure'), $services['configurator2']->getConfigurator(), '->load() parses the configurator tag'); $this->assertEquals(array('BazClass', 'configureStatic'), $services['configurator3']->getConfigurator(), '->load() parses the configurator tag'); - $this->assertEquals(array(array('setBar', array()), array('setBar', array(new Expression('service("foo").foo() ~ parameter("foo")')))), $services['method_call1']->getMethodCalls(), '->load() parses the method_call tag'); + $this->assertEquals(array(array('setBar', array()), array('setBar', array(new Expression('service("foo").foo() ~ (container.hasparameter("foo") ? parameter("foo") : "default")')))), $services['method_call1']->getMethodCalls(), '->load() parses the method_call tag'); $this->assertEquals(array(array('setBar', array('foo', new Reference('foo'), array(true, false)))), $services['method_call2']->getMethodCalls(), '->load() parses the method_call tag'); $this->assertNull($services['factory_service']->getClass()); $this->assertEquals('getInstance', $services['factory_service']->getFactoryMethod()); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php index 83a7ea4f66..1958d11e86 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php @@ -138,7 +138,7 @@ class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase $this->assertEquals('sc_configure', $services['configurator1']->getConfigurator(), '->load() parses the configurator tag'); $this->assertEquals(array(new Reference('baz'), 'configure'), $services['configurator2']->getConfigurator(), '->load() parses the configurator tag'); $this->assertEquals(array('BazClass', 'configureStatic'), $services['configurator3']->getConfigurator(), '->load() parses the configurator tag'); - $this->assertEquals(array(array('setBar', array()), array('setBar', array()), array('setBar', array(new Expression('service("foo").foo() ~ parameter("foo")')))), $services['method_call1']->getMethodCalls(), '->load() parses the method_call tag'); + $this->assertEquals(array(array('setBar', array()), array('setBar', array()), array('setBar', array(new Expression('service("foo").foo() ~ (container.hasparameter("foo") ? parameter("foo") : "default")')))), $services['method_call1']->getMethodCalls(), '->load() parses the method_call tag'); $this->assertEquals(array(array('setBar', array('foo', new Reference('foo'), array(true, false)))), $services['method_call2']->getMethodCalls(), '->load() parses the method_call tag'); $this->assertEquals('baz_factory', $services['factory_service']->getFactoryService()); diff --git a/src/Symfony/Component/ExpressionLanguage/Parser.php b/src/Symfony/Component/ExpressionLanguage/Parser.php index db4b5858b1..1c385aceec 100644 --- a/src/Symfony/Component/ExpressionLanguage/Parser.php +++ b/src/Symfony/Component/ExpressionLanguage/Parser.php @@ -75,6 +75,16 @@ class Parser /** * Converts a token stream to a node tree. * + * The valid names is an array where the values + * are the names that the user can use in an expression. + * + * If the variable name in the compiled PHP code must be + * different, define it as the key. + * + * For instance, ['this' => 'container'] means that the + * variable 'container' can be used in the expression + * but the compiled code will use 'this'. + * * @param TokenStream $stream A token stream instance * @param array $names An array of valid names * @@ -194,7 +204,13 @@ class Parser throw new SyntaxError(sprintf('Variable "%s" is not valid', $token->value), $token->cursor); } - $node = new Node\NameNode($token->value); + // is the name used in the compiled code different + // from the name used in the expression? + if (is_int($name = array_search($token->value, $this->names))) { + $name = $token->value; + } + + $node = new Node\NameNode($name); } } break; diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php index 4cbab6591f..58229857fc 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php @@ -148,6 +148,12 @@ class ParserTest extends \PHPUnit_Framework_TestCase 'foo.bar().foo().baz[3]', array('foo'), ), + + array( + new Node\NameNode('foo'), + 'bar', + array('foo' => 'bar'), + ), ); } From ea4ae7401191ce896b833ddf80dad35790f5b1e5 Mon Sep 17 00:00:00 2001 From: Eric GELOEN Date: Wed, 6 Nov 2013 01:36:01 +0100 Subject: [PATCH 2/4] [Form][DateTime] Propagate invalid_message & invalid_message parameters to date & time sub widgets --- .../Component/Form/Extension/Core/Type/DateTimeType.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php b/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php index a612b6fc9c..e8c4e748de 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/DateTimeType.php @@ -117,6 +117,8 @@ class DateTimeType extends AbstractType 'empty_value', 'required', 'translation_domain', + 'invalid_message', + 'invalid_message_parameters', ))); $timeOptions = array_intersect_key($options, array_flip(array( @@ -128,6 +130,8 @@ class DateTimeType extends AbstractType 'empty_value', 'required', 'translation_domain', + 'invalid_message', + 'invalid_message_parameters', ))); if (null !== $options['date_widget']) { From 10f9135f636213bc1f0e532c1fab1d95c5843b24 Mon Sep 17 00:00:00 2001 From: Alex Bakhturin Date: Wed, 24 Sep 2014 16:34:46 -0700 Subject: [PATCH 3/4] [Finder] [Iterator] Make the tests less fragile --- .../Tests/Iterator/IteratorTestCase.php | 25 ++++++ .../Tests/Iterator/RealIteratorTestCase.php | 6 +- .../Tests/Iterator/SortableIteratorTest.php | 82 +++++++++++-------- 3 files changed, 78 insertions(+), 35 deletions(-) diff --git a/src/Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.php b/src/Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.php index 504cfb01b1..5f74f38095 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/IteratorTestCase.php @@ -34,6 +34,31 @@ abstract class IteratorTestCase extends \PHPUnit_Framework_TestCase $this->assertEquals($expected, array_values($values)); } + /** + * Same as assertOrderedIterator, but checks the order of groups of + * array elements. + * + * @param array $expected - an array of arrays. For any two subarrays + * $a and $b such that $a goes before $b in $expected, the method + * asserts that any element of $a goes before any element of $b + * in the sequence generated by $iterator + * @param \Traversable $iterator + */ + protected function assertOrderedIteratorForGroups($expected, \Traversable $iterator) + { + $values = array_values(array_map(function (\SplFileInfo $fileinfo) { return $fileinfo->getPathname(); }, iterator_to_array($iterator))); + + foreach ($expected as $subarray) { + $temp = array(); + while (count($values) && count($temp) < count($subarray)) { + array_push($temp, array_shift($values)); + } + sort($temp); + sort($subarray); + $this->assertEquals($subarray, $temp); + } + } + /** * Same as IteratorTestCase::assertIterator with foreach usage * diff --git a/src/Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.php b/src/Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.php index 8aa5c89d82..2a7383dc0a 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/RealIteratorTestCase.php @@ -80,7 +80,11 @@ abstract class RealIteratorTestCase extends IteratorTestCase if (is_array($files)) { $f = array(); foreach ($files as $file) { - $f[] = self::$tmpDir.DIRECTORY_SEPARATOR.str_replace('/', DIRECTORY_SEPARATOR, $file); + if (is_array($file)) { + $f[] = self::toAbsolute($file); + } else { + $f[] = self::$tmpDir.DIRECTORY_SEPARATOR.str_replace('/', DIRECTORY_SEPARATOR, $file); + } } return $f; diff --git a/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php index f4def17a18..e2f433f8e7 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php @@ -54,7 +54,13 @@ class SortableIteratorTest extends RealIteratorTestCase $iterator = new SortableIterator($inner, $mode); - $this->assertOrderedIterator($expected, $iterator); + if ($mode === SortableIterator::SORT_BY_ACCESSED_TIME + || $mode === SortableIterator::SORT_BY_CHANGED_TIME + || $mode === SortableIterator::SORT_BY_MODIFIED_TIME) { + $this->assertOrderedIteratorForGroups($expected, $iterator); + } else { + $this->assertOrderedIterator($expected, $iterator); + } } public function getAcceptData() @@ -102,45 +108,53 @@ class SortableIteratorTest extends RealIteratorTestCase ); $sortByAccessedTime = array( - 'foo/bar.tmp', - 'test.php', - 'toto', - 'foo bar', - 'foo', - 'test.py', - '.foo', - '.foo/.bar', - '.foo/bar', - '.git', - '.bar', + // For these two files the access time was set to 2005-10-15 + array('foo/bar.tmp', 'test.php'), + // These files were created more or less at the same time + array( + '.git', + '.foo', + '.foo/.bar', + '.foo/bar', + 'test.py', + 'foo', + 'toto', + 'foo bar', + ), + // This file was accessed after sleeping for 1 sec + array('.bar'), ); $sortByChangedTime = array( - 'foo', - 'foo/bar.tmp', - 'toto', - '.git', - '.bar', - '.foo', - 'foo bar', - '.foo/.bar', - '.foo/bar', - 'test.php', - 'test.py', + array( + '.git', + '.foo', + '.foo/.bar', + '.foo/bar', + '.bar', + 'foo', + 'foo/bar.tmp', + 'toto', + 'foo bar', + ), + array('test.php'), + array('test.py'), ); $sortByModifiedTime = array( - 'foo/bar.tmp', - 'foo', - 'toto', - '.git', - '.bar', - '.foo', - 'foo bar', - '.foo/.bar', - '.foo/bar', - 'test.php', - 'test.py', + array( + '.git', + '.foo', + '.foo/.bar', + '.foo/bar', + '.bar', + 'foo', + 'foo/bar.tmp', + 'toto', + 'foo bar', + ), + array('test.php'), + array('test.py'), ); return array( From f1ae970a4e3c861819a1a0621b3cc299f2ea2dc6 Mon Sep 17 00:00:00 2001 From: Alex Bakhturin Date: Fri, 26 Sep 2014 10:04:52 -0700 Subject: [PATCH 4/4] Make Doctrine's dependency injection test less fragile. [Doctrine][DependencyInjection] The test checks that a few items are ordered according to the value of their 'priority' attribute. However, a few of the items have the same value of this attribute. RegisterEventListenersAndSubscribersPass doesn't use a stable sorting, yet the test asserts that items that are 'equal' shall go in the original order. Modified so that the order of the original items is not checked. --- .../RegisterEventListenersAndSubscribersPassTest.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.php b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.php index 24fbcdc9a6..ae8a76750f 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/DependencyInjection/CompilerPass/RegisterEventListenersAndSubscribersPassTest.php @@ -139,7 +139,11 @@ class RegisterEventListenersAndSubscribersPassTest extends \PHPUnit_Framework_Te ; $this->process($container); - $this->assertEquals(array('c', 'd', 'e', 'b', 'a'), $this->getServiceOrder($container, 'addEventSubscriber')); + $serviceOrder = $this->getServiceOrder($container, 'addEventSubscriber'); + $unordered = array_splice($serviceOrder, 0, 3); + sort($unordered); + $this->assertEquals(array('c', 'd', 'e'), $unordered); + $this->assertEquals(array('b', 'a'), $serviceOrder); } private function process(ContainerBuilder $container)