From c0733c22cbd880e5ba47a658c5c2399a123fc58a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Paris?= Date: Sun, 11 Nov 2018 11:07:43 +0100 Subject: [PATCH 1/4] Add required key attribute I am getting warnings when running tests with recent phpunit versions: > - Element 'element': The attribute 'key' is required but missing. This requirement is far from being new, what is recent is phpunit validating its configuration file against the XSD schema. See https://github.com/sebastianbergmann/phpunit/commit/d4484be1a9c56c73353517510ce3b0690f6d738e --- phpunit.xml.dist | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index ada17c766a..d1244636bb 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -56,8 +56,8 @@ - Symfony\Component\Console - Symfony\Component\HttpFoundation + Symfony\Component\Console + Symfony\Component\HttpFoundation From 61e459234b9c418c650862c7a5918228847ae1b5 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sun, 11 Nov 2018 10:03:27 +0100 Subject: [PATCH 2/4] [Fwb][EventDispatcher][HttpKernel] Fix getClosureScopeClass usage to describe callables --- .../Console/Descriptor/JsonDescriptor.php | 7 +- .../Console/Descriptor/MarkdownDescriptor.php | 7 +- .../Console/Descriptor/TextDescriptor.php | 5 +- .../Console/Descriptor/XmlDescriptor.php | 7 +- .../Console/Descriptor/ObjectsProvider.php | 8 ++- .../Descriptor/callable_from_callable.json | 5 ++ .../Descriptor/callable_from_callable.md | 4 ++ .../Descriptor/callable_from_callable.txt | 1 + .../Descriptor/callable_from_callable.xml | 2 + .../EventDispatcher/Debug/WrappedListener.php | 6 +- .../Tests/Debug/WrappedListenerTest.php | 64 +++++++++++++++++++ .../DataCollector/RequestDataCollector.php | 4 +- .../VarDumper/Caster/ReflectionCaster.php | 8 +-- 13 files changed, 97 insertions(+), 31 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/callable_from_callable.json create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/callable_from_callable.md create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/callable_from_callable.txt create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/callable_from_callable.xml create mode 100644 src/Symfony/Component/EventDispatcher/Tests/Debug/WrappedListenerTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php index a8c279815b..05238f3724 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php @@ -374,10 +374,9 @@ class JsonDescriptor extends Descriptor } $data['name'] = $r->name; - $class = ($class = $r->getClosureThis()) ? \get_class($class) : null; - if ($scopeClass = $r->getClosureScopeClass() ?: $class) { - $data['class'] = $scopeClass; - if (!$class) { + if ($class = $r->getClosureScopeClass()) { + $data['class'] = $class->name; + if (!$r->getClosureThis()) { $data['static'] = true; } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php index 2e7d07272f..9249ca5baa 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php @@ -360,10 +360,9 @@ class MarkdownDescriptor extends Descriptor } $string .= "\n".sprintf('- Name: `%s`', $r->name); - $class = ($class = $r->getClosureThis()) ? \get_class($class) : null; - if ($scopeClass = $r->getClosureScopeClass() ?: $class) { - $string .= "\n".sprintf('- Class: `%s`', $class); - if (!$class) { + if ($class = $r->getClosureScopeClass()) { + $string .= "\n".sprintf('- Class: `%s`', $class->name); + if (!$r->getClosureThis()) { $string .= "\n- Static: yes"; } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php index b381c3a499..9846a9a90f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php @@ -474,10 +474,7 @@ class TextDescriptor extends Descriptor return 'Closure()'; } if ($class = $r->getClosureScopeClass()) { - return sprintf('%s::%s()', $class, $r->name); - } - if ($class = $r->getClosureThis()) { - return sprintf('%s::%s()', \get_class($class), $r->name); + return sprintf('%s::%s()', $class->name, $r->name); } return $r->name.'()'; diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php index ab74c1f6f2..b663e76221 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php @@ -586,10 +586,9 @@ class XmlDescriptor extends Descriptor } $callableXML->setAttribute('name', $r->name); - $class = ($class = $r->getClosureThis()) ? \get_class($class) : null; - if ($scopeClass = $r->getClosureScopeClass() ?: $class) { - $callableXML->setAttribute('class', $class); - if (!$class) { + if ($class = $r->getClosureScopeClass()) { + $callableXML->setAttribute('class', $class->name); + if (!$r->getClosureThis()) { $callableXML->setAttribute('static', 'true'); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php index 3025c6bb9e..b46e322353 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php @@ -155,7 +155,7 @@ class ObjectsProvider public static function getCallables() { - return array( + $callables = array( 'callable_1' => 'array_key_exists', 'callable_2' => array('Symfony\\Bundle\\FrameworkBundle\\Tests\\Console\\Descriptor\\CallableClass', 'staticMethod'), 'callable_3' => array(new CallableClass(), 'method'), @@ -164,6 +164,12 @@ class ObjectsProvider 'callable_6' => function () { return 'Closure'; }, 'callable_7' => new CallableClass(), ); + + if (\PHP_VERSION_ID >= 70100) { + $callables['callable_from_callable'] = \Closure::fromCallable(new CallableClass()); + } + + return $callables; } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/callable_from_callable.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/callable_from_callable.json new file mode 100644 index 0000000000..fc0b749d99 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/callable_from_callable.json @@ -0,0 +1,5 @@ +{ + "type": "closure", + "name": "__invoke", + "class": "Symfony\\Bundle\\FrameworkBundle\\Tests\\Console\\Descriptor\\CallableClass" +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/callable_from_callable.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/callable_from_callable.md new file mode 100644 index 0000000000..caf4193b4a --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/callable_from_callable.md @@ -0,0 +1,4 @@ + +- Type: `closure` +- Name: `__invoke` +- Class: `Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\CallableClass` diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/callable_from_callable.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/callable_from_callable.txt new file mode 100644 index 0000000000..78ef6a6527 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/callable_from_callable.txt @@ -0,0 +1 @@ +Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\CallableClass::__invoke() \ No newline at end of file diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/callable_from_callable.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/callable_from_callable.xml new file mode 100644 index 0000000000..1ad2ee8f47 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/callable_from_callable.xml @@ -0,0 +1,2 @@ + + diff --git a/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php b/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php index 9038ae7798..d49f69de72 100644 --- a/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php +++ b/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php @@ -46,10 +46,8 @@ class WrappedListener $r = new \ReflectionFunction($listener); if (false !== strpos($r->name, '{closure}')) { $this->pretty = $this->name = 'closure'; - } elseif ($this->name = $r->getClosureScopeClass()) { - $this->pretty = $this->name.'::'.$r->name; - } elseif ($class = $r->getClosureThis()) { - $this->name = \get_class($class); + } elseif ($class = $r->getClosureScopeClass()) { + $this->name = $class->name; $this->pretty = $this->name.'::'.$r->name; } else { $this->pretty = $this->name = $r->name; diff --git a/src/Symfony/Component/EventDispatcher/Tests/Debug/WrappedListenerTest.php b/src/Symfony/Component/EventDispatcher/Tests/Debug/WrappedListenerTest.php new file mode 100644 index 0000000000..f743f148d2 --- /dev/null +++ b/src/Symfony/Component/EventDispatcher/Tests/Debug/WrappedListenerTest.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher\Tests\Debug; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\Debug\WrappedListener; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Stopwatch\Stopwatch; + +class WrappedListenerTest extends TestCase +{ + /** + * @dataProvider provideListenersToDescribe + */ + public function testListenerDescription(callable $listener, $expected) + { + $wrappedListener = new WrappedListener($listener, null, $this->getMockBuilder(Stopwatch::class)->getMock(), $this->getMockBuilder(EventDispatcherInterface::class)->getMock()); + + $this->assertStringMatchesFormat($expected, $wrappedListener->getPretty()); + } + + public function provideListenersToDescribe() + { + $listeners = array( + array(new FooListener(), 'Symfony\Component\EventDispatcher\Tests\Debug\FooListener::__invoke'), + array(array(new FooListener(), 'listen'), 'Symfony\Component\EventDispatcher\Tests\Debug\FooListener::listen'), + array(array('Symfony\Component\EventDispatcher\Tests\Debug\FooListener', 'listenStatic'), 'Symfony\Component\EventDispatcher\Tests\Debug\FooListener::listenStatic'), + array('var_dump', 'var_dump'), + array(function () {}, 'closure'), + ); + + if (\PHP_VERSION_ID >= 70100) { + $listeners[] = array(\Closure::fromCallable(array(new FooListener(), 'listen')), 'Symfony\Component\EventDispatcher\Tests\Debug\FooListener::listen'); + $listeners[] = array(\Closure::fromCallable(array('Symfony\Component\EventDispatcher\Tests\Debug\FooListener', 'listenStatic')), 'Symfony\Component\EventDispatcher\Tests\Debug\FooListener::listenStatic'); + $listeners[] = array(\Closure::fromCallable(function () {}), 'closure'); + } + + return $listeners; + } +} + +class FooListener +{ + public function listen() + { + } + + public function __invoke() + { + } + + public static function listenStatic() + { + } +} diff --git a/src/Symfony/Component/HttpKernel/DataCollector/RequestDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/RequestDataCollector.php index 2501b93210..10492e4465 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/RequestDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/RequestDataCollector.php @@ -393,9 +393,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter $controller['method'] = $r->name; if ($class = $r->getClosureScopeClass()) { - $controller['class'] = $class; - } elseif ($class = $r->getClosureThis()) { - $controller['class'] = \get_class($class); + $controller['class'] = $class->name; } else { return $r->name; } diff --git a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php index a1f0a1a7eb..9bfef06983 100644 --- a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php @@ -40,13 +40,7 @@ class ReflectionCaster $a = static::castFunctionAbstract($c, $a, $stub, $isNested, $filter); if (false === strpos($c->name, '{closure}')) { - if (isset($a[$prefix.'class'])) { - $stub->class = $a[$prefix.'class']->value.'::'.$c->name; - } elseif (isset($a[$prefix.'this'])) { - $stub->class = $a[$prefix.'this']->class.'::'.$c->name; - } else { - $stub->class = $c->name; - } + $stub->class = isset($a[$prefix.'class']) ? $a[$prefix.'class']->value.'::'.$c->name : $c->name; unset($a[$prefix.'class']); } From 4dce4b7c306d8e0465f8cd23ee5c8695a9a9ea65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Paris?= Date: Sun, 11 Nov 2018 12:11:22 +0100 Subject: [PATCH 3/4] Bump phpunit XSD version to 5.2 Some attributes being used in the phpunit configuration files, namely failOnRisky and failOnWarning were introduced in phpunit 5.2.0. The Composer configuration shows that tests should run with old versions of phpunit, but phpunit only validates the configuration against the XSD since phpunit 7.2.0. These changes can be tested as follows: wget http://schema.phpunit.de/5.2/phpunit.xsd xargs xmllint --schema phpunit.xsd 1>/dev/null find src -name phpunit.xml.dist| xargs xmllint --schema phpunit.xsd 1>/dev/null See https://github.com/sebastianbergmann/phpunit/commit/7e06a82806be004cbfd30a02d92162e9ed4abc7c See https://github.com/symfony/symfony/blob/46e3745a03e199e64cc0fcf3284a96b5a25dcee9/composer.json#L98 --- phpunit.xml.dist | 2 +- src/Symfony/Bridge/Doctrine/phpunit.xml.dist | 2 +- src/Symfony/Bridge/Monolog/phpunit.xml.dist | 2 +- src/Symfony/Bridge/PhpUnit/phpunit.xml.dist | 2 +- src/Symfony/Bridge/ProxyManager/phpunit.xml.dist | 2 +- src/Symfony/Bridge/Twig/phpunit.xml.dist | 2 +- src/Symfony/Bundle/DebugBundle/phpunit.xml.dist | 2 +- src/Symfony/Bundle/FrameworkBundle/phpunit.xml.dist | 2 +- src/Symfony/Bundle/SecurityBundle/phpunit.xml.dist | 2 +- src/Symfony/Bundle/TwigBundle/phpunit.xml.dist | 2 +- src/Symfony/Bundle/WebProfilerBundle/phpunit.xml.dist | 2 +- src/Symfony/Component/Asset/phpunit.xml.dist | 2 +- src/Symfony/Component/BrowserKit/phpunit.xml.dist | 2 +- src/Symfony/Component/ClassLoader/phpunit.xml.dist | 2 +- src/Symfony/Component/Config/phpunit.xml.dist | 2 +- src/Symfony/Component/Console/phpunit.xml.dist | 2 +- src/Symfony/Component/CssSelector/phpunit.xml.dist | 2 +- src/Symfony/Component/Debug/phpunit.xml.dist | 2 +- src/Symfony/Component/DependencyInjection/phpunit.xml.dist | 2 +- src/Symfony/Component/DomCrawler/phpunit.xml.dist | 2 +- src/Symfony/Component/EventDispatcher/phpunit.xml.dist | 2 +- src/Symfony/Component/ExpressionLanguage/phpunit.xml.dist | 2 +- src/Symfony/Component/Filesystem/phpunit.xml.dist | 2 +- src/Symfony/Component/Finder/phpunit.xml.dist | 2 +- src/Symfony/Component/Form/phpunit.xml.dist | 2 +- src/Symfony/Component/HttpFoundation/phpunit.xml.dist | 2 +- src/Symfony/Component/HttpKernel/phpunit.xml.dist | 2 +- src/Symfony/Component/Intl/phpunit.xml.dist | 2 +- src/Symfony/Component/Ldap/phpunit.xml.dist | 2 +- src/Symfony/Component/Locale/phpunit.xml.dist | 2 +- src/Symfony/Component/OptionsResolver/phpunit.xml.dist | 2 +- src/Symfony/Component/Process/phpunit.xml.dist | 2 +- src/Symfony/Component/PropertyAccess/phpunit.xml.dist | 2 +- src/Symfony/Component/PropertyInfo/phpunit.xml.dist | 2 +- src/Symfony/Component/Routing/phpunit.xml.dist | 2 +- src/Symfony/Component/Security/Core/phpunit.xml.dist | 2 +- src/Symfony/Component/Security/Csrf/phpunit.xml.dist | 2 +- src/Symfony/Component/Security/Guard/phpunit.xml.dist | 2 +- src/Symfony/Component/Security/Http/phpunit.xml.dist | 2 +- src/Symfony/Component/Security/phpunit.xml.dist | 2 +- src/Symfony/Component/Serializer/phpunit.xml.dist | 2 +- src/Symfony/Component/Stopwatch/phpunit.xml.dist | 2 +- src/Symfony/Component/Templating/phpunit.xml.dist | 2 +- src/Symfony/Component/Translation/phpunit.xml.dist | 2 +- src/Symfony/Component/Validator/phpunit.xml.dist | 2 +- src/Symfony/Component/VarDumper/phpunit.xml.dist | 2 +- src/Symfony/Component/Yaml/phpunit.xml.dist | 2 +- 47 files changed, 47 insertions(+), 47 deletions(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index ada17c766a..f8d9c1fbbe 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,7 +1,7 @@ Date: Sun, 11 Nov 2018 15:04:13 +0100 Subject: [PATCH 4/4] [Form] Hardened test suite for empty data --- .../Tests/Form/Type/EntityTypeTest.php | 39 +++++++++++++++++++ .../Extension/Core/Type/BaseTypeTest.php | 22 +++++++++++ .../Extension/Core/Type/ButtonTypeTest.php | 12 ++++++ .../Extension/Core/Type/CheckboxTypeTest.php | 13 +++++++ .../Extension/Core/Type/ChoiceTypeTest.php | 9 +++-- .../Core/Type/CollectionTypeTest.php | 6 +++ .../Extension/Core/Type/CountryTypeTest.php | 5 +++ .../Extension/Core/Type/CurrencyTypeTest.php | 5 +++ .../Extension/Core/Type/DateTimeTypeTest.php | 16 ++++++++ .../Extension/Core/Type/DateTypeTest.php | 29 ++++++++++++++ .../Extension/Core/Type/FormTypeTest.php | 5 +++ .../Extension/Core/Type/IntegerTypeTest.php | 12 ++++++ .../Extension/Core/Type/LanguageTypeTest.php | 5 +++ .../Extension/Core/Type/LocaleTypeTest.php | 5 +++ .../Extension/Core/Type/MoneyTypeTest.php | 12 ++++++ .../Extension/Core/Type/NumberTypeTest.php | 12 ++++++ .../Extension/Core/Type/TimeTypeTest.php | 13 +++++++ .../Extension/Core/Type/TimezoneTypeTest.php | 12 ++++++ .../Tests/Extension/Core/Type/UrlTypeTest.php | 13 +++++++ 19 files changed, 241 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php index 3377549187..351ff941d5 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php @@ -1543,4 +1543,43 @@ class EntityTypeTest extends BaseTypeTest $this->assertEquals(array(), $form->getNormData()); $this->assertSame(array(), $form->getViewData(), 'View data is always an array'); } + + public function testSubmitNullUsesDefaultEmptyData($emptyData = 'empty', $expectedData = null) + { + $emptyData = '1'; + $entity1 = new SingleIntIdEntity(1, 'Foo'); + $this->persist(array($entity1)); + + $form = $this->factory->create(static::TESTED_TYPE, null, array( + 'em' => 'default', + 'class' => self::SINGLE_IDENT_CLASS, + 'empty_data' => $emptyData, + )); + $form->submit(null); + + $this->assertSame($emptyData, $form->getViewData()); + $this->assertSame($entity1, $form->getNormData()); + $this->assertSame($entity1, $form->getData()); + } + + public function testSubmitNullMultipleUsesDefaultEmptyData() + { + $emptyData = array('1'); + $entity1 = new SingleIntIdEntity(1, 'Foo'); + $this->persist(array($entity1)); + + $form = $this->factory->create(static::TESTED_TYPE, null, array( + 'em' => 'default', + 'class' => self::SINGLE_IDENT_CLASS, + 'multiple' => true, + 'empty_data' => $emptyData, + )); + $form->submit(null); + + $collection = new ArrayCollection(array($entity1)); + + $this->assertSame($emptyData, $form->getViewData()); + $this->assertEquals($collection, $form->getNormData()); + $this->assertEquals($collection, $form->getData()); + } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php index facab97309..da3f48b486 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/BaseTypeTest.php @@ -145,6 +145,28 @@ abstract class BaseTypeTest extends TypeTestCase $this->assertSame($view, $form->getViewData()); } + public function testSubmitNullUsesDefaultEmptyData($emptyData = 'empty', $expectedData = null) + { + $builder = $this->factory->createBuilder($this->getTestedType()); + + if ($builder->getCompound()) { + $emptyData = array(); + foreach ($builder as $field) { + // empty children should map null (model data) in the compound view data + $emptyData[$field->getName()] = null; + } + } else { + // simple fields share the view and the model format, unless they use a transformer + $expectedData = $emptyData; + } + + $form = $builder->setEmptyData($emptyData)->getForm()->submit(null); + + $this->assertSame($emptyData, $form->getViewData()); + $this->assertSame($expectedData, $form->getNormData()); + $this->assertSame($expectedData, $form->getData()); + } + protected function getTestedType() { return static::TESTED_TYPE; diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ButtonTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ButtonTypeTest.php index 9f105272fe..dbef3ff9ed 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ButtonTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ButtonTypeTest.php @@ -32,4 +32,16 @@ class ButtonTypeTest extends BaseTypeTest { $this->assertInstanceOf('Symfony\Component\Form\Button', $this->factory->create(static::TESTED_TYPE)); } + + /** + * @expectedException \Symfony\Component\Form\Exception\BadMethodCallException + * @expectedExceptionMessage Buttons do not support empty data. + * + * @param string $emptyData + * @param null $expectedData + */ + public function testSubmitNullUsesDefaultEmptyData($emptyData = 'empty', $expectedData = null) + { + parent::testSubmitNullUsesDefaultEmptyData($emptyData, $expectedData); + } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CheckboxTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CheckboxTypeTest.php index 95f4ad201e..38dbd67db8 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CheckboxTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CheckboxTypeTest.php @@ -187,4 +187,17 @@ class CheckboxTypeTest extends BaseTypeTest { parent::testSubmitNull(false, false, null); } + + public function testSubmitNullUsesDefaultEmptyData($emptyData = 'empty', $expectedData = true) + { + $form = $this->factory->create(static::TESTED_TYPE, null, array( + 'empty_data' => $emptyData, + )); + $form->submit(null); + + // view data is transformed to the string true value + $this->assertSame('1', $form->getViewData()); + $this->assertSame($expectedData, $form->getNormData()); + $this->assertSame($expectedData, $form->getData()); + } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php index 59dc05cb68..2ef745efa5 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -684,19 +684,20 @@ class ChoiceTypeTest extends BaseTypeTest $this->assertTrue($form->isSynchronized()); } - public function testSubmitSingleChoiceWithEmptyData() + public function testSubmitNullUsesDefaultEmptyData($emptyData = 'empty', $expectedData = null) { $form = $this->factory->create(static::TESTED_TYPE, null, array( 'multiple' => false, 'expanded' => false, - 'choices' => array('test'), + // empty data must match string choice value + 'choices' => array($emptyData), 'choices_as_values' => true, - 'empty_data' => 'test', + 'empty_data' => $emptyData, )); $form->submit(null); - $this->assertSame('test', $form->getData()); + $this->assertSame($emptyData, $form->getData()); } public function testSubmitSingleChoiceWithEmptyDataAndInitialData() diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php index 6fcc4dc6d3..bdeb4bd1a6 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php @@ -410,4 +410,10 @@ class CollectionTypeTest extends BaseTypeTest { parent::testSubmitNull(array(), array(), array()); } + + public function testSubmitNullUsesDefaultEmptyData($emptyData = array(), $expectedData = array()) + { + // resize form listener always set an empty array + parent::testSubmitNullUsesDefaultEmptyData($emptyData, $expectedData); + } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.php index 2db6daa258..e9cbc2afd2 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CountryTypeTest.php @@ -66,4 +66,9 @@ class CountryTypeTest extends BaseTypeTest { parent::testSubmitNull($expected, $norm, ''); } + + public function testSubmitNullUsesDefaultEmptyData($emptyData = 'FR', $expectedData = 'FR') + { + parent::testSubmitNullUsesDefaultEmptyData($emptyData, $expectedData); + } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CurrencyTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CurrencyTypeTest.php index 739cc408ba..ab2b389710 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CurrencyTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CurrencyTypeTest.php @@ -49,4 +49,9 @@ class CurrencyTypeTest extends BaseTypeTest { parent::testSubmitNull($expected, $norm, ''); } + + public function testSubmitNullUsesDefaultEmptyData($emptyData = 'EUR', $expectedData = 'EUR') + { + parent::testSubmitNullUsesDefaultEmptyData($emptyData, $expectedData); + } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php index 27c6581f0b..2531332f05 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTimeTypeTest.php @@ -615,4 +615,20 @@ class DateTimeTypeTest extends BaseTypeTest $this->assertNull($form->getNormData()); $this->assertSame('', $form->getViewData()); } + + public function testSubmitNullUsesDefaultEmptyData($emptyData = array(), $expectedData = null) + { + $form = $this->factory->create(static::TESTED_TYPE, null, array( + 'empty_data' => $emptyData, + )); + $form->submit(null); + + // view transformer writes back empty strings in the view data + $this->assertSame( + array('date' => array('year' => '', 'month' => '', 'day' => ''), 'time' => array('hour' => '', 'minute' => '')), + $form->getViewData() + ); + $this->assertSame($expectedData, $form->getNormData()); + $this->assertSame($expectedData, $form->getData()); + } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php index 1eb2e7887b..0f03b1851d 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/DateTypeTest.php @@ -1003,4 +1003,33 @@ class DateTypeTest extends BaseTypeTest $this->assertNull($form->getNormData()); $this->assertSame('', $form->getViewData()); } + + public function testSubmitNullUsesDefaultEmptyData($emptyData = array(), $expectedData = null) + { + $form = $this->factory->create(static::TESTED_TYPE, null, array( + 'empty_data' => $emptyData, + )); + $form->submit(null); + + // view transformer write back empty strings in the view data + $this->assertSame(array('year' => '', 'month' => '', 'day' => ''), $form->getViewData()); + $this->assertSame($expectedData, $form->getNormData()); + $this->assertSame($expectedData, $form->getData()); + } + + public function testSingleTextSubmitNullUsesDefaultEmptyData() + { + $emptyData = '2018-11-11'; + $form = $this->factory->create(static::TESTED_TYPE, null, array( + 'widget' => 'single_text', + 'empty_data' => $emptyData, + )); + $form->submit(null); + + $date = new \DateTime($emptyData); + + $this->assertSame($emptyData, $form->getViewData()); + $this->assertEquals($date, $form->getNormData()); + $this->assertEquals($date, $form->getData()); + } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php index 7d75dce26d..52722b0420 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php @@ -227,6 +227,11 @@ class FormTypeTest extends BaseTypeTest )); } + public function testSubmitNullUsesDefaultEmptyData($emptyData = array(), $expectedData = array()) + { + parent::testSubmitNullUsesDefaultEmptyData($emptyData, $expectedData); + } + public function testSubmitWithEmptyDataCreatesObjectIfClassAvailable() { $form = $this->factory->createBuilder(static::TESTED_TYPE, null, array( diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.php index 3059e79ce9..247f956a3b 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/IntegerTypeTest.php @@ -48,4 +48,16 @@ class IntegerTypeTest extends BaseTypeTest { parent::testSubmitNull($expected, $norm, ''); } + + public function testSubmitNullUsesDefaultEmptyData($emptyData = '10', $expectedData = 10) + { + $form = $this->factory->create(static::TESTED_TYPE, null, array( + 'empty_data' => $emptyData, + )); + $form->submit(null); + + $this->assertSame($emptyData, $form->getViewData()); + $this->assertSame($expectedData, $form->getNormData()); + $this->assertSame($expectedData, $form->getData()); + } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.php index beffecdd7e..d8127aa6d7 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/LanguageTypeTest.php @@ -59,4 +59,9 @@ class LanguageTypeTest extends BaseTypeTest { parent::testSubmitNull($expected, $norm, ''); } + + public function testSubmitNullUsesDefaultEmptyData($emptyData = 'en', $expectedData = 'en') + { + parent::testSubmitNullUsesDefaultEmptyData($emptyData, $expectedData); + } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/LocaleTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/LocaleTypeTest.php index 0439e7d2dd..ede22932f8 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/LocaleTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/LocaleTypeTest.php @@ -49,4 +49,9 @@ class LocaleTypeTest extends BaseTypeTest { parent::testSubmitNull($expected, $norm, ''); } + + public function testSubmitNullUsesDefaultEmptyData($emptyData = 'en', $expectedData = 'en') + { + parent::testSubmitNullUsesDefaultEmptyData($emptyData, $expectedData); + } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/MoneyTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/MoneyTypeTest.php index a865a93c9c..0b02fffddf 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/MoneyTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/MoneyTypeTest.php @@ -80,4 +80,16 @@ class MoneyTypeTest extends BaseTypeTest $this->assertSame('{{ widget }}', $view->vars['money_pattern']); } + + public function testSubmitNullUsesDefaultEmptyData($emptyData = '10.00', $expectedData = 10.0) + { + $form = $this->factory->create(static::TESTED_TYPE, null, array( + 'empty_data' => $emptyData, + )); + $form->submit(null); + + $this->assertSame($emptyData, $form->getViewData()); + $this->assertSame($expectedData, $form->getNormData()); + $this->assertSame($expectedData, $form->getData()); + } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/NumberTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/NumberTypeTest.php index 9d53297e8b..09c8f2dd28 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/NumberTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/NumberTypeTest.php @@ -73,4 +73,16 @@ class NumberTypeTest extends BaseTypeTest { parent::testSubmitNull($expected, $norm, ''); } + + public function testSubmitNullUsesDefaultEmptyData($emptyData = '10', $expectedData = 10.0) + { + $form = $this->factory->create(static::TESTED_TYPE, null, array( + 'empty_data' => $emptyData, + )); + $form->submit(null); + + $this->assertSame($emptyData, $form->getViewData()); + $this->assertSame($expectedData, $form->getNormData()); + $this->assertSame($expectedData, $form->getData()); + } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php index 611c6e42ac..98d4f902fa 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php @@ -797,4 +797,17 @@ class TimeTypeTest extends BaseTypeTest parent::testSubmitNull($expected, $norm, $view); } + + public function testSubmitNullUsesDefaultEmptyData($emptyData = array(), $expectedData = null) + { + $form = $this->factory->create(static::TESTED_TYPE, null, array( + 'empty_data' => $emptyData, + )); + $form->submit(null); + + // view transformer write back empty strings in the view data + $this->assertSame(array('hour' => '', 'minute' => ''), $form->getViewData()); + $this->assertSame($expectedData, $form->getNormData()); + $this->assertSame($expectedData, $form->getData()); + } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.php index 507b740505..b6b61cb171 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.php @@ -43,4 +43,16 @@ class TimezoneTypeTest extends BaseTypeTest { parent::testSubmitNull($expected, $norm, ''); } + + public function testSubmitNullUsesDefaultEmptyData($emptyData = 'Africa/Kinshasa', $expectedData = 'Africa/Kinshasa') + { + $form = $this->factory->create(static::TESTED_TYPE, null, array( + 'empty_data' => $emptyData, + )); + $form->submit(null); + + $this->assertSame($emptyData, $form->getViewData()); + $this->assertSame($expectedData, $form->getNormData()); + $this->assertSame($expectedData, $form->getData()); + } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/UrlTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/UrlTypeTest.php index a3336970dc..95be3775a4 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/UrlTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/UrlTypeTest.php @@ -100,4 +100,17 @@ class UrlTypeTest extends TextTypeTest $this->assertSame(array('domain.com', 'www.domain.com'), $form->getData()); } + + public function testSubmitNullUsesDefaultEmptyData($emptyData = 'empty', $expectedData = 'http://empty') + { + $form = $this->factory->create(static::TESTED_TYPE, null, array( + 'empty_data' => $emptyData, + )); + $form->submit(null); + + // listener normalizes data on submit + $this->assertSame($expectedData, $form->getViewData()); + $this->assertSame($expectedData, $form->getNormData()); + $this->assertSame($expectedData, $form->getData()); + } }