From 7d1cfb785974efa7641fe62096ce5f63344739f6 Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Sat, 18 Aug 2012 14:43:48 +0300 Subject: [PATCH 001/447] [Form] Remove unneeded FormUtil constants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They are part of the public API (as const are always public) but cannot be used at all from outside the class as the $pluralMap is private. The meaning of the indices is already documented in the array. --- Util/FormUtil.php | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/Util/FormUtil.php b/Util/FormUtil.php index 614361c49b..b4048f76a6 100644 --- a/Util/FormUtil.php +++ b/Util/FormUtil.php @@ -16,16 +16,6 @@ */ abstract class FormUtil { - const PLURAL_SUFFIX = 0; - - const PLURAL_SUFFIX_LENGTH = 1; - - const PLURAL_SUFFIX_AFTER_VOCAL = 2; - - const PLURAL_SUFFIX_AFTER_CONS = 3; - - const SINGULAR_SUFFIX = 4; - /** * Map english plural to singular suffixes * @@ -128,8 +118,8 @@ public static function singularify($plural) // in the plural table to compare them with the characters of the actual // given plural suffix for ($i = 0, $numPlurals = count(self::$pluralMap); $i < $numPlurals; ++$i) { - $suffix = self::$pluralMap[$i][self::PLURAL_SUFFIX]; - $suffixLength = self::$pluralMap[$i][self::PLURAL_SUFFIX_LENGTH]; + $suffix = self::$pluralMap[$i][0]; + $suffixLength = self::$pluralMap[$i][1]; $j = 0; // Compare characters in the plural table and of the suffix of the @@ -145,17 +135,19 @@ public static function singularify($plural) if ($j < $pluralLength) { $nextIsVocal = false !== strpos('aeiou', $lowerPluralRev[$j]); - if (!self::$pluralMap[$i][self::PLURAL_SUFFIX_AFTER_VOCAL] && $nextIsVocal) { + if (!self::$pluralMap[$i][2] && $nextIsVocal) { + // suffix may not succeed a vocal but next char is one break; } - if (!self::$pluralMap[$i][self::PLURAL_SUFFIX_AFTER_CONS] && !$nextIsVocal) { + if (!self::$pluralMap[$i][3] && !$nextIsVocal) { + // suffix may not succeed a consonant but next char is one break; } } $newBase = substr($plural, 0, $pluralLength - $suffixLength); - $newSuffix = self::$pluralMap[$i][self::SINGULAR_SUFFIX]; + $newSuffix = self::$pluralMap[$i][4]; // Check whether the first character in the plural suffix // is uppercased. If yes, uppercase the first character in From 37b79c73d1454bb58e6156b2b28ed5bd82ec1128 Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Sat, 18 Aug 2012 17:12:41 +0200 Subject: [PATCH 002/447] micro-optim: replace for with foreach --- Util/FormUtil.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Util/FormUtil.php b/Util/FormUtil.php index b4048f76a6..5e8d461698 100644 --- a/Util/FormUtil.php +++ b/Util/FormUtil.php @@ -113,13 +113,13 @@ public static function singularify($plural) $lowerPluralRev = strtolower($pluralRev); $pluralLength = strlen($lowerPluralRev); - // The outer loop $i iterates over the entries of the plural table + // The outer loop iterates over the entries of the plural table // The inner loop $j iterates over the characters of the plural suffix // in the plural table to compare them with the characters of the actual // given plural suffix - for ($i = 0, $numPlurals = count(self::$pluralMap); $i < $numPlurals; ++$i) { - $suffix = self::$pluralMap[$i][0]; - $suffixLength = self::$pluralMap[$i][1]; + foreach (self::$pluralMap as $map) { + $suffix = $map[0]; + $suffixLength = $map[1]; $j = 0; // Compare characters in the plural table and of the suffix of the @@ -135,19 +135,19 @@ public static function singularify($plural) if ($j < $pluralLength) { $nextIsVocal = false !== strpos('aeiou', $lowerPluralRev[$j]); - if (!self::$pluralMap[$i][2] && $nextIsVocal) { + if (!$map[2] && $nextIsVocal) { // suffix may not succeed a vocal but next char is one break; } - if (!self::$pluralMap[$i][3] && !$nextIsVocal) { + if (!$map[3] && !$nextIsVocal) { // suffix may not succeed a consonant but next char is one break; } } $newBase = substr($plural, 0, $pluralLength - $suffixLength); - $newSuffix = self::$pluralMap[$i][4]; + $newSuffix = $map[4]; // Check whether the first character in the plural suffix // is uppercased. If yes, uppercase the first character in From a900ffb6edb898399fe174c561d043868bd65cb8 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 10 Sep 2012 12:59:37 +0200 Subject: [PATCH 003/447] replaced self.version/2.1.* by 2.2.* in composer.json files --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index bd5d58393b..e861e3b1d2 100644 --- a/composer.json +++ b/composer.json @@ -26,8 +26,8 @@ "symfony/http-foundation": "2.2.*" }, "suggest": { - "symfony/validator": "2.1.*", - "symfony/http-foundation": "2.1.*" + "symfony/validator": "2.2.*", + "symfony/http-foundation": "2.2.*" }, "autoload": { "psr-0": { "Symfony\\Component\\Form": "" } From ce260e5800e345ddd6975f38053a5dd10e6d290b Mon Sep 17 00:00:00 2001 From: Filippo Tessarotto Date: Fri, 28 Sep 2012 09:34:16 +0200 Subject: [PATCH 004/447] Optimize autoload prefix in composer.json By having more specific autoload prefixes it is possible to reduce the number of stat calls made. Also it prevents conflicts with similar namespaces. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index e861e3b1d2..1e69cb140d 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ "symfony/http-foundation": "2.2.*" }, "autoload": { - "psr-0": { "Symfony\\Component\\Form": "" } + "psr-0": { "Symfony\\Component\\Form\\": "" } }, "target-dir": "Symfony/Component/Form", "minimum-stability": "dev", From 4b1fa4c6066ecf7a34322d8e0179f6ec2b0875a9 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 11 Oct 2012 08:28:46 +0200 Subject: [PATCH 005/447] [Form] Removed unused method ChoiceView::isSelected() --- Extension/Core/View/ChoiceView.php | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/Extension/Core/View/ChoiceView.php b/Extension/Core/View/ChoiceView.php index 5b348eae2a..97cdd214c2 100644 --- a/Extension/Core/View/ChoiceView.php +++ b/Extension/Core/View/ChoiceView.php @@ -52,20 +52,4 @@ public function __construct($data, $value, $label) $this->value = $value; $this->label = $label; } - - /** - * Returns whether this choice is selected for the given value. - * - * @param string|array $value The selected choice value. - * - * @return Boolean Whether the choice is selected. - */ - public function isSelected($value) - { - if (is_array($value)) { - return false !== array_search($this->value, $value, true); - } - - return $this->value === $value; - } } From e17080a64a2daafc3e178f5fca8b19d0783461c2 Mon Sep 17 00:00:00 2001 From: Danny Berger Date: Sat, 13 Oct 2012 08:51:08 -0600 Subject: [PATCH 006/447] Fix a few namespaces to match file system. --- Tests/FormRegistryTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Tests/FormRegistryTest.php b/Tests/FormRegistryTest.php index f2d4009048..645a73d9df 100644 --- a/Tests/FormRegistryTest.php +++ b/Tests/FormRegistryTest.php @@ -9,8 +9,10 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Form; +namespace Symfony\Component\Form\Tests; +use Symfony\Component\Form\FormRegistry; +use Symfony\Component\Form\FormTypeGuesserChain; use Symfony\Component\Form\Tests\Fixtures\TestExtension; use Symfony\Component\Form\Tests\Fixtures\FooSubTypeWithParentInstance; use Symfony\Component\Form\Tests\Fixtures\FooSubType; From cfc69ef804a06e71a0c5d689643e99fa44fc4073 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A1=D0=B0=D1=88=D0=B0=20=D0=A1=D1=82=D0=B0=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D0=BA=D0=BE=D0=B2=D0=B8=D1=9B?= Date: Sun, 21 Oct 2012 15:41:00 +0300 Subject: [PATCH 007/447] Changed getPattern visibility It should be possible to override this method. --- Extension/Core/Type/MoneyType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/Core/Type/MoneyType.php b/Extension/Core/Type/MoneyType.php index dfbbae20a8..e9b5faabde 100644 --- a/Extension/Core/Type/MoneyType.php +++ b/Extension/Core/Type/MoneyType.php @@ -81,7 +81,7 @@ public function getName() * The pattern contains the placeholder "{{ widget }}" where the HTML tag should * be inserted */ - private static function getPattern($currency) + protected static function getPattern($currency) { if (!$currency) { return '{{ widget }}'; From 37b8145a7df0c47775f1a40c621c7d8198733366 Mon Sep 17 00:00:00 2001 From: Sasa Stamenkovic Date: Mon, 22 Oct 2012 22:46:47 +0200 Subject: [PATCH 008/447] Changed MoneyType::$patterns visibility. --- Extension/Core/Type/MoneyType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/Core/Type/MoneyType.php b/Extension/Core/Type/MoneyType.php index e9b5faabde..433e8dddfe 100644 --- a/Extension/Core/Type/MoneyType.php +++ b/Extension/Core/Type/MoneyType.php @@ -20,7 +20,7 @@ class MoneyType extends AbstractType { - private static $patterns = array(); + protected static $patterns = array(); /** * {@inheritdoc} From f7174cee590c115e3b60d9dd9deda49a759aa1b7 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 25 Oct 2012 15:42:46 +0200 Subject: [PATCH 009/447] [Form] tweaked previous merge --- .../Core/EventListener/TrimListenerTest.php | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Tests/Extension/Core/EventListener/TrimListenerTest.php b/Tests/Extension/Core/EventListener/TrimListenerTest.php index df8f327001..a5771119fb 100644 --- a/Tests/Extension/Core/EventListener/TrimListenerTest.php +++ b/Tests/Extension/Core/EventListener/TrimListenerTest.php @@ -50,13 +50,13 @@ public function testTrimSkipNonStrings() /** * @dataProvider codePointProvider */ - public function testTrimUtf8($description, $chars) + public function testTrimUtf8($chars) { if (!function_exists('mb_check_encoding')) { $this->markTestSkipped('The "mb_check_encoding" function is not available'); } - $data = mb_convert_encoding(pack('H*', implode('', (array)$chars)), 'UTF-8', 'UCS-2BE'); + $data = mb_convert_encoding(pack('H*', implode('', $chars)), 'UTF-8', 'UCS-2BE'); $data = $data."ab\ncd".$data; $form = $this->getMock('Symfony\Component\Form\Tests\FormInterface'); @@ -65,17 +65,15 @@ public function testTrimUtf8($description, $chars) $filter = new TrimListener(); $filter->preBind($event); - $this->assertSame("ab\ncd", $event->getData(), 'TrimListener should trim character(s): '.$description.': '.implode(', ', $chars)); + $this->assertSame("ab\ncd", $event->getData(), 'TrimListener should trim character(s): '.implode(', ', $chars)); } public function codePointProvider() { return array( - array('General category: Separator', - array('0020', '00A0', '1680', '180E', '2000', '2001', '2002', '2003', '2004', '2005', - '2006', '2007', '2008', '2009', '200A', '2028', '2029', '202F', '205F', '3000')), - array('General category: Other, control', array('0009', '000A', '000B', '000C', '000D', '0085')), -// array('General category: Other, format. ZERO WIDTH SPACE', '200B') + 'General category: Separator' => array(array('0020', '00A0', '1680', '180E', '2000', '2001', '2002', '2003', '2004', '2005', '2006', '2007', '2008', '2009', '200A', '2028', '2029', '202F', '205F', '3000')), + 'General category: Other, control' => array(array('0009', '000A', '000B', '000C', '000D', '0085')), + //'General category: Other, format. ZERO WIDTH SPACE' => array(array('200B')), ); } } From 165bef39400708e1eaefd6c89143477d05fcc968 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 25 Oct 2012 15:43:31 +0200 Subject: [PATCH 010/447] [Form] updated CHANGELOG --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8c4589db2..bdbb2b3546 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +2.2.0 +----- + + * TrimListener now removes unicode whitespaces + 2.1.0 ----- From 044dfdfd88da0c5e4be75411adfed48b1fbccc5c Mon Sep 17 00:00:00 2001 From: Pascal Borreli Date: Sun, 28 Oct 2012 23:25:34 +0000 Subject: [PATCH 011/447] Fixed typos --- Tests/Extension/Core/Type/CollectionTypeTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Extension/Core/Type/CollectionTypeTest.php b/Tests/Extension/Core/Type/CollectionTypeTest.php index aa79fa060e..15896dae22 100644 --- a/Tests/Extension/Core/Type/CollectionTypeTest.php +++ b/Tests/Extension/Core/Type/CollectionTypeTest.php @@ -141,7 +141,7 @@ public function testPrototypeMultipartPropagation() $this->assertTrue($form->createView()->vars['multipart']); } - public function testGetDataDoesNotContainsProtypeNameBeforeDataAreSet() + public function testGetDataDoesNotContainsPrototypeNameBeforeDataAreSet() { $form = $this->factory->create('collection', array(), array( 'type' => 'file', From 6487a3d6527d8c29d401c8d3d17f806184ed875f Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 8 Nov 2012 17:14:44 +0100 Subject: [PATCH 012/447] [Form] Fixed NumberToLocalizedStringTransformer to throw an exception if numbers contain illegal characters --- .../NumberToLocalizedStringTransformer.php | 23 ++++++++-- ...NumberToLocalizedStringTransformerTest.php | 46 +++++++++++++++---- 2 files changed, 58 insertions(+), 11 deletions(-) diff --git a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php index 48c96274d3..d1421a6389 100644 --- a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php @@ -107,18 +107,35 @@ public function reverseTransform($value) throw new TransformationFailedException('"NaN" is not a valid number'); } + $position = 0; $formatter = $this->getNumberFormatter(); - $value = $formatter->parse($value); + $result = $formatter->parse($value, \NumberFormatter::TYPE_DOUBLE, $position); if (intl_is_failure($formatter->getErrorCode())) { throw new TransformationFailedException($formatter->getErrorMessage()); } - if ($value >= INF || $value <= -INF) { + if ($result >= INF || $result <= -INF) { throw new TransformationFailedException('I don\'t have a clear idea what infinity looks like'); } - return $value; + // After parsing, position holds the index of the character where the + // parsing stopped + if ($position < strlen($value)) { + // Check if there are unrecognized characters at the end of the + // number + $remainder = substr($value, $position); + + // Remove all whitespace characters + if ('' !== preg_replace('/[\s\xc2\xa0]*/', '', $remainder)) { + throw new TransformationFailedException( + sprintf('The number contains unrecognized characters: "%s"', + $remainder + )); + } + } + + return $result; } /** diff --git a/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php index e17466f568..6add79469c 100644 --- a/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php @@ -93,7 +93,7 @@ public function testReverseTransformWithGrouping() } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testTransformExpectsNumeric() { @@ -103,7 +103,7 @@ public function testTransformExpectsNumeric() } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testReverseTransformExpectsString() { @@ -113,7 +113,7 @@ public function testReverseTransformExpectsString() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformExpectsValidNumber() { @@ -123,7 +123,7 @@ public function testReverseTransformExpectsValidNumber() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException * @link https://github.com/symfony/symfony/issues/3161 */ public function testReverseTransformDisallowsNaN() @@ -134,7 +134,7 @@ public function testReverseTransformDisallowsNaN() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsNaN2() { @@ -144,7 +144,7 @@ public function testReverseTransformDisallowsNaN2() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsInfinity() { @@ -154,7 +154,7 @@ public function testReverseTransformDisallowsInfinity() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsInfinity2() { @@ -164,7 +164,7 @@ public function testReverseTransformDisallowsInfinity2() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsNegativeInfinity() { @@ -172,4 +172,34 @@ public function testReverseTransformDisallowsNegativeInfinity() $transformer->reverseTransform('-∞'); } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformDisallowsLeadingExtraCharacters() + { + $transformer = new NumberToLocalizedStringTransformer(); + + $transformer->reverseTransform('foo123'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformDisallowsCenteredExtraCharacters() + { + $transformer = new NumberToLocalizedStringTransformer(); + + $transformer->reverseTransform('12foo3'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformDisallowsTrailingExtraCharacters() + { + $transformer = new NumberToLocalizedStringTransformer(); + + $transformer->reverseTransform('123foo'); + } } From 2c064565f1186db9e5d812b5700c83c17dbc0d2f Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 9 Nov 2012 10:18:50 +0100 Subject: [PATCH 013/447] made usage of Composer autoloader for subtree-split unit tests --- .gitignore | 2 ++ README.md | 9 +++------ Tests/bootstrap.php | 22 ---------------------- phpunit.xml.dist | 2 +- 4 files changed, 6 insertions(+), 29 deletions(-) delete mode 100644 Tests/bootstrap.php diff --git a/.gitignore b/.gitignore index d1502b087b..44de97a36a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ vendor/ composer.lock +phpunit.xml + diff --git a/README.md b/README.md index f6ddf031aa..c336935dd8 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,6 @@ Resources You can run the unit tests with the following command: - phpunit - -If you also want to run the unit tests that depend on other Symfony -Components, install dev dependencies before running PHPUnit: - - php composer.phar install --dev + $ cd path/to/Symfony/Component/Form/ + $ composer.phar install --dev + $ phpunit diff --git a/Tests/bootstrap.php b/Tests/bootstrap.php deleted file mode 100644 index 902cefce5c..0000000000 --- a/Tests/bootstrap.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -spl_autoload_register(function ($class) { - if (0 === strpos(ltrim($class, '/'), 'Symfony\Component\Form')) { - if (file_exists($file = __DIR__.'/../'.substr(str_replace('\\', '/', $class), strlen('Symfony\Component\Form')).'.php')) { - require_once $file; - } - } -}); - -if (file_exists($loader = __DIR__.'/../vendor/autoload.php')) { - require_once $loader; -} diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 0fd49c27e4..d0d261f194 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -9,7 +9,7 @@ processIsolation="false" stopOnFailure="false" syntaxCheck="false" - bootstrap="Tests/bootstrap.php" + bootstrap="vendor/autoload.php" > From 1932c9836b028e10cf9f908ac9460b380c7cab17 Mon Sep 17 00:00:00 2001 From: Sam Williams Date: Wed, 7 Nov 2012 08:40:27 +1100 Subject: [PATCH 014/447] setData method also accepts objects. Doc should reflect this. --- FormInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FormInterface.php b/FormInterface.php index 682c6a727f..9051aba51e 100644 --- a/FormInterface.php +++ b/FormInterface.php @@ -98,7 +98,7 @@ public function getErrors(); /** * Updates the form with default data. * - * @param array $modelData The data formatted as expected for the underlying object + * @param mixed $modelData The data formatted as expected for the underlying object * * @return FormInterface The form instance * From 64815641300239511293201d2f242e8ea09f0ad2 Mon Sep 17 00:00:00 2001 From: Roman Marintsenko Date: Wed, 31 Oct 2012 12:04:56 +0200 Subject: [PATCH 015/447] Make non-instantiable utils classes consistent with each other --- Util/FormUtil.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Util/FormUtil.php b/Util/FormUtil.php index 5e8d461698..5aea15a51a 100644 --- a/Util/FormUtil.php +++ b/Util/FormUtil.php @@ -14,7 +14,7 @@ /** * @author Bernhard Schussek */ -abstract class FormUtil +class FormUtil { /** * Map english plural to singular suffixes @@ -97,6 +97,11 @@ abstract class FormUtil array('xuae', 4, false, true, 'eau'), ); + /** + * This class should not be instantiated + */ + private function __construct() {} + /** * Returns the singular form of a word * From 1f9ab68283f05f7c8a051af614869d3956eb9b8e Mon Sep 17 00:00:00 2001 From: Eric GELOEN Date: Tue, 13 Nov 2012 19:41:37 +0100 Subject: [PATCH 016/447] [Form] Update password type trimming to false --- Extension/Core/Type/PasswordType.php | 1 + Tests/Extension/Core/Type/PasswordTypeTest.php | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/Extension/Core/Type/PasswordType.php b/Extension/Core/Type/PasswordType.php index 14ece2ac50..d76281e567 100644 --- a/Extension/Core/Type/PasswordType.php +++ b/Extension/Core/Type/PasswordType.php @@ -35,6 +35,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'always_empty' => true, + 'trim' => false, )); } diff --git a/Tests/Extension/Core/Type/PasswordTypeTest.php b/Tests/Extension/Core/Type/PasswordTypeTest.php index 96f1410968..fdfd0083eb 100644 --- a/Tests/Extension/Core/Type/PasswordTypeTest.php +++ b/Tests/Extension/Core/Type/PasswordTypeTest.php @@ -39,4 +39,13 @@ public function testNotEmptyIfBoundAndNotAlwaysEmpty() $this->assertSame('pAs5w0rd', $view->vars['value']); } + + public function testNotTrimmed() + { + $form = $this->factory->create('password', null); + $form->bind(' pAs5w0rd '); + $data = $form->getData(); + + $this->assertSame(' pAs5w0rd ', $data); + } } From adbf326b4a893c0b9a79aa00cb742d0d536b1778 Mon Sep 17 00:00:00 2001 From: Thomas Lallement Date: Thu, 1 Nov 2012 16:08:59 +0100 Subject: [PATCH 017/447] CS Fixes - Replaced "array of type" by "Type[]" in PHPDoc block --- AbstractExtension.php | 8 ++++---- AbstractType.php | 4 ++-- Form.php | 14 +++++++------- FormBuilder.php | 2 +- FormConfigInterface.php | 4 ++-- FormExtensionInterface.php | 2 +- FormInterface.php | 4 ++-- FormRegistry.php | 5 +++-- ResolvedFormTypeInterface.php | 2 +- 9 files changed, 23 insertions(+), 22 deletions(-) diff --git a/AbstractExtension.php b/AbstractExtension.php index ea2e95924c..190a5ab8a6 100644 --- a/AbstractExtension.php +++ b/AbstractExtension.php @@ -21,13 +21,13 @@ abstract class AbstractExtension implements FormExtensionInterface { /** * The types provided by this extension - * @var array An array of FormTypeInterface + * @var FormTypeInterface[] An array of FormTypeInterface */ private $types; /** * The type extensions provided by this extension - * @var array An array of FormTypeExtensionInterface + * @var FormTypeExtensionInterface[] An array of FormTypeExtensionInterface */ private $typeExtensions; @@ -112,7 +112,7 @@ public function getTypeGuesser() /** * Registers the types. * - * @return array An array of FormTypeInterface instances + * @return FormTypeInterface[] An array of FormTypeInterface instances */ protected function loadTypes() { @@ -122,7 +122,7 @@ protected function loadTypes() /** * Registers the type extensions. * - * @return array An array of FormTypeExtensionInterface instances + * @return FormTypeExtensionInterface[] An array of FormTypeExtensionInterface instances */ protected function loadTypeExtensions() { diff --git a/AbstractType.php b/AbstractType.php index 67919632c2..479ceac511 100644 --- a/AbstractType.php +++ b/AbstractType.php @@ -96,7 +96,7 @@ public function getParent() /** * Sets the extensions for this type. * - * @param array $extensions An array of FormTypeExtensionInterface + * @param FormTypeExtensionInterface[] $extensions An array of FormTypeExtensionInterface * * @throws Exception\UnexpectedTypeException if any extension does not implement FormTypeExtensionInterface * @@ -110,7 +110,7 @@ public function setExtensions(array $extensions) /** * Returns the extensions associated with this type. * - * @return array An array of FormTypeExtensionInterface + * @return FormTypeExtensionInterface[] An array of FormTypeExtensionInterface * * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use * {@link ResolvedFormTypeInterface::getTypeExtensions()} instead. diff --git a/Form.php b/Form.php index ec3d5393a8..6fbb1d5beb 100644 --- a/Form.php +++ b/Form.php @@ -70,13 +70,13 @@ class Form implements \IteratorAggregate, FormInterface /** * The children of this form - * @var array An array of FormInterface instances + * @var FormInterface[] An array of FormInterface instances */ private $children = array(); /** * The errors of this form - * @var array An array of FormError instances + * @var FormError[] An array of FormError instances */ private $errors = array(); @@ -203,7 +203,7 @@ public function getPropertyPath() /** * Returns the types used by this form. * - * @return array An array of FormTypeInterface + * @return FormTypeInterface[] An array of FormTypeInterface * * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use * {@link getConfig()} and {@link FormConfigInterface::getType()} instead. @@ -761,9 +761,9 @@ public function getErrorsAsString($level = 0) } /** - * Returns the DataTransformers. + * Returns the model transformers of the form. * - * @return array An array of DataTransformerInterface + * @return DataTransformerInterface[] An array of DataTransformerInterface * * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use * {@link getConfig()} and {@link FormConfigInterface::getModelTransformers()} instead. @@ -774,9 +774,9 @@ public function getNormTransformers() } /** - * Returns the DataTransformers. + * Returns the view transformers of the form. * - * @return array An array of DataTransformerInterface + * @return DataTransformerInterface[] An array of DataTransformerInterface * * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use * {@link getConfig()} and {@link FormConfigInterface::getViewTransformers()} instead. diff --git a/FormBuilder.php b/FormBuilder.php index 9d23ff565f..1f8d713ddb 100644 --- a/FormBuilder.php +++ b/FormBuilder.php @@ -288,7 +288,7 @@ public function getIterator() /** * Returns the types used by this builder. * - * @return array An array of FormTypeInterface + * @return FormTypeInterface[] An array of FormTypeInterface * * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use * {@link FormConfigInterface::getType()} instead. diff --git a/FormConfigInterface.php b/FormConfigInterface.php index 364d6a60b0..5710f6e2ad 100644 --- a/FormConfigInterface.php +++ b/FormConfigInterface.php @@ -86,14 +86,14 @@ public function getType(); /** * Returns the view transformers of the form. * - * @return array An array of {@link DataTransformerInterface} instances. + * @return DataTransformerInterface[] An array of {@link DataTransformerInterface} instances. */ public function getViewTransformers(); /** * Returns the model transformers of the form. * - * @return array An array of {@link DataTransformerInterface} instances. + * @return DataTransformerInterface[] An array of {@link DataTransformerInterface} instances. */ public function getModelTransformers(); diff --git a/FormExtensionInterface.php b/FormExtensionInterface.php index 5347c451d2..dc3ca46570 100644 --- a/FormExtensionInterface.php +++ b/FormExtensionInterface.php @@ -41,7 +41,7 @@ public function hasType($name); * * @param string $name The name of the type * - * @return array An array of extensions as FormTypeExtensionInterface instances + * @return FormTypeExtensionInterface[] An array of extensions as FormTypeExtensionInterface instances */ public function getTypeExtensions($name); diff --git a/FormInterface.php b/FormInterface.php index 682c6a727f..fea607de1b 100644 --- a/FormInterface.php +++ b/FormInterface.php @@ -84,14 +84,14 @@ public function remove($name); /** * Returns all children in this group. * - * @return array An array of FormInterface instances + * @return FormInterface[] An array of FormInterface instances */ public function all(); /** * Returns all errors. * - * @return array An array of FormError instances that occurred during binding + * @return FormError[] An array of FormError instances that occurred during binding */ public function getErrors(); diff --git a/FormRegistry.php b/FormRegistry.php index a4146dbff3..d7180f93a5 100644 --- a/FormRegistry.php +++ b/FormRegistry.php @@ -23,7 +23,8 @@ class FormRegistry implements FormRegistryInterface { /** * Extensions - * @var array An array of FormExtensionInterface + * + * @var FormExtensionInterface[] An array of FormExtensionInterface */ private $extensions = array(); @@ -45,7 +46,7 @@ class FormRegistry implements FormRegistryInterface /** * Constructor. * - * @param array $extensions An array of FormExtensionInterface + * @param FormExtensionInterface[] $extensions An array of FormExtensionInterface * @param ResolvedFormTypeFactoryInterface $resolvedTypeFactory The factory for resolved form types. * * @throws UnexpectedTypeException if any extension does not implement FormExtensionInterface diff --git a/ResolvedFormTypeInterface.php b/ResolvedFormTypeInterface.php index c6333d543f..611bd3a25f 100644 --- a/ResolvedFormTypeInterface.php +++ b/ResolvedFormTypeInterface.php @@ -42,7 +42,7 @@ public function getInnerType(); /** * Returns the extensions of the wrapped form type. * - * @return array An array of {@link FormTypeExtensionInterface} instances. + * @return FormTypeExtensionInterface[] An array of {@link FormTypeExtensionInterface} instances. */ public function getTypeExtensions(); From 1c2347ffbed0ffed37b865be34053792f4801def Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 22 Nov 2012 16:42:25 +0100 Subject: [PATCH 018/447] [Form] Adapted FormValidator to latest changes in the Validator --- .../Validator/Constraints/FormValidator.php | 10 +- .../Constraints/FormValidatorTest.php | 280 +++++++++--------- 2 files changed, 136 insertions(+), 154 deletions(-) diff --git a/Extension/Validator/Constraints/FormValidator.php b/Extension/Validator/Constraints/FormValidator.php index 65e54f6feb..167fcd95e9 100644 --- a/Extension/Validator/Constraints/FormValidator.php +++ b/Extension/Validator/Constraints/FormValidator.php @@ -51,18 +51,12 @@ public function validate($form, Constraint $constraint) if ($form->isSynchronized()) { // Validate the form data only if transformation succeeded - $path = $this->context->getPropertyPath(); - $graphWalker = $this->context->getGraphWalker(); $groups = self::getValidationGroups($form); - if (!empty($path)) { - $path .= '.'; - } - // Validate the data against its own constraints if (self::allowDataWalking($form)) { foreach ($groups as $group) { - $graphWalker->walkReference($form->getData(), $group, $path . 'data', true); + $this->context->validate($form->getData(), 'data', $group, true); } } @@ -72,7 +66,7 @@ public function validate($form, Constraint $constraint) foreach ($constraints as $constraint) { foreach ($groups as $group) { if (in_array($group, $constraint->groups)) { - $graphWalker->walkConstraint($constraint, $form->getData(), $group, $path . 'data'); + $this->context->validateValue($form->getData(), $constraint, 'data', $group); // Prevent duplicate validation continue 2; diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index b79fd5d41b..f47618fb28 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -22,8 +22,6 @@ use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\NotBlank; -use Symfony\Component\Validator\GlobalExecutionContext; -use Symfony\Component\Validator\ExecutionContext; /** * @author Bernhard Schussek @@ -67,20 +65,19 @@ protected function setUp() public function testValidate() { - $context = $this->getExecutionContext(); - $graphWalker = $context->getGraphWalker(); + $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => array('group1', 'group2')); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); - $graphWalker->expects($this->at(0)) - ->method('walkReference') - ->with($object, 'group1', 'data', true); - $graphWalker->expects($this->at(1)) - ->method('walkReference') - ->with($object, 'group2', 'data', true); + $context->expects($this->at(0)) + ->method('validate') + ->with($object, 'data', 'group1', true); + $context->expects($this->at(1)) + ->method('validate') + ->with($object, 'data', 'group2', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); @@ -88,8 +85,7 @@ public function testValidate() public function testValidateConstraints() { - $context = $this->getExecutionContext(); - $graphWalker = $context->getGraphWalker(); + $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $constraint1 = new NotNull(array('groups' => array('group1', 'group2'))); $constraint2 = new NotBlank(array('groups' => 'group2')); @@ -103,20 +99,20 @@ public function testValidateConstraints() ->getForm(); // First default constraints - $graphWalker->expects($this->at(0)) - ->method('walkReference') - ->with($object, 'group1', 'data', true); - $graphWalker->expects($this->at(1)) - ->method('walkReference') - ->with($object, 'group2', 'data', true); + $context->expects($this->at(0)) + ->method('validate') + ->with($object, 'data', 'group1', true); + $context->expects($this->at(1)) + ->method('validate') + ->with($object, 'data', 'group2', true); // Then custom constraints - $graphWalker->expects($this->at(2)) - ->method('walkConstraint') - ->with($constraint1, $object, 'group1', 'data'); - $graphWalker->expects($this->at(3)) - ->method('walkConstraint') - ->with($constraint2, $object, 'group2', 'data'); + $context->expects($this->at(2)) + ->method('validateValue') + ->with($object, $constraint1, 'data', 'group1'); + $context->expects($this->at(3)) + ->method('validateValue') + ->with($object, $constraint2, 'data', 'group2'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); @@ -124,8 +120,7 @@ public function testValidateConstraints() public function testDontValidateIfParentWithoutCascadeValidation() { - $context = $this->getExecutionContext(); - $graphWalker = $context->getGraphWalker(); + $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parent = $this->getBuilder('parent', null, array('cascade_validation' => false)) @@ -138,8 +133,8 @@ public function testDontValidateIfParentWithoutCascadeValidation() $form->setData($object); - $graphWalker->expects($this->never()) - ->method('walkReference'); + $context->expects($this->never()) + ->method('validate'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); @@ -147,8 +142,7 @@ public function testDontValidateIfParentWithoutCascadeValidation() public function testValidateConstraintsEvenIfNoCascadeValidation() { - $context = $this->getExecutionContext(); - $graphWalker = $context->getGraphWalker(); + $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $constraint1 = new NotNull(array('groups' => array('group1', 'group2'))); $constraint2 = new NotBlank(array('groups' => 'group2')); @@ -166,12 +160,12 @@ public function testValidateConstraintsEvenIfNoCascadeValidation() ->getForm(); $parent->add($form); - $graphWalker->expects($this->at(0)) - ->method('walkConstraint') - ->with($constraint1, $object, 'group1', 'data'); - $graphWalker->expects($this->at(1)) - ->method('walkConstraint') - ->with($constraint2, $object, 'group2', 'data'); + $context->expects($this->at(0)) + ->method('validateValue') + ->with($object, $constraint1, 'data', 'group1'); + $context->expects($this->at(1)) + ->method('validateValue') + ->with($object, $constraint2, 'data', 'group2'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); @@ -179,8 +173,7 @@ public function testValidateConstraintsEvenIfNoCascadeValidation() public function testDontValidateIfNotSynchronized() { - $context = $this->getExecutionContext(); - $graphWalker = $context->getGraphWalker(); + $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $form = $this->getBuilder('name', '\stdClass', array( @@ -200,30 +193,26 @@ function () { throw new TransformationFailedException(); } // Launch transformer $form->bind('foo'); - $graphWalker->expects($this->never()) - ->method('walkReference'); + $context->expects($this->never()) + ->method('validate'); + + $context->expects($this->once()) + ->method('addViolation') + ->with( + 'invalid_message_key', + array('{{ value }}' => 'foo', '{{ foo }}' => 'bar'), + 'foo' + ); + $context->expects($this->never()) + ->method('addViolationAt'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); - - $expectedViolation = new ConstraintViolation( - 'invalid_message_key', - array('{{ value }}' => 'foo', '{{ foo }}' => 'bar'), - 'Root', - null, - 'foo', - null, - Form::ERR_INVALID - ); - - $this->assertCount(1, $context->getViolations()); - $this->assertEquals($expectedViolation, $context->getViolations()->get(0)); } public function testDontValidateConstraintsIfNotSynchronized() { - $context = $this->getExecutionContext(); - $graphWalker = $context->getGraphWalker(); + $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $constraint1 = $this->getMock('Symfony\Component\Validator\Constraint'); $constraint2 = $this->getMock('Symfony\Component\Validator\Constraint'); @@ -243,8 +232,8 @@ function () { throw new TransformationFailedException(); } // Launch transformer $form->bind(array()); - $graphWalker->expects($this->never()) - ->method('walkReference'); + $context->expects($this->never()) + ->method('validate'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); @@ -253,7 +242,7 @@ function () { throw new TransformationFailedException(); } // https://github.com/symfony/symfony/issues/4359 public function testDontMarkInvalidIfAnyChildIsNotSynchronized() { - $context = $this->getExecutionContext(); + $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $failingTransformer = new CallbackTransformer( @@ -275,28 +264,30 @@ function () { throw new TransformationFailedException(); } // Launch transformer $form->bind(array('child' => 'foo')); + $context->expects($this->never()) + ->method('addViolation'); + $context->expects($this->never()) + ->method('addViolationAt'); + $this->validator->initialize($context); $this->validator->validate($form, new Form()); - - $this->assertCount(0, $context->getViolations()); } public function testHandleCallbackValidationGroups() { - $context = $this->getExecutionContext(); - $graphWalker = $context->getGraphWalker(); + $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => array($this, 'getValidationGroups')); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); - $graphWalker->expects($this->at(0)) - ->method('walkReference') - ->with($object, 'group1', 'data', true); - $graphWalker->expects($this->at(1)) - ->method('walkReference') - ->with($object, 'group2', 'data', true); + $context->expects($this->at(0)) + ->method('validate') + ->with($object, 'data', 'group1', true); + $context->expects($this->at(1)) + ->method('validate') + ->with($object, 'data', 'group2', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); @@ -304,8 +295,7 @@ public function testHandleCallbackValidationGroups() public function testHandleClosureValidationGroups() { - $context = $this->getExecutionContext(); - $graphWalker = $context->getGraphWalker(); + $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => function(FormInterface $form){ return array('group1', 'group2'); @@ -314,12 +304,12 @@ public function testHandleClosureValidationGroups() ->setData($object) ->getForm(); - $graphWalker->expects($this->at(0)) - ->method('walkReference') - ->with($object, 'group1', 'data', true); - $graphWalker->expects($this->at(1)) - ->method('walkReference') - ->with($object, 'group2', 'data', true); + $context->expects($this->at(0)) + ->method('validate') + ->with($object, 'data', 'group1', true); + $context->expects($this->at(1)) + ->method('validate') + ->with($object, 'data', 'group2', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); @@ -327,8 +317,7 @@ public function testHandleClosureValidationGroups() public function testUseInheritedValidationGroup() { - $context = $this->getExecutionContext('foo.bar'); - $graphWalker = $context->getGraphWalker(); + $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parentOptions = array( @@ -344,9 +333,9 @@ public function testUseInheritedValidationGroup() $form->setData($object); - $graphWalker->expects($this->once()) - ->method('walkReference') - ->with($object, 'group', 'foo.bar.data', true); + $context->expects($this->once()) + ->method('validate') + ->with($object, 'data', 'group', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); @@ -354,8 +343,7 @@ public function testUseInheritedValidationGroup() public function testUseInheritedCallbackValidationGroup() { - $context = $this->getExecutionContext('foo.bar'); - $graphWalker = $context->getGraphWalker(); + $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parentOptions = array( @@ -371,12 +359,12 @@ public function testUseInheritedCallbackValidationGroup() $form->setData($object); - $graphWalker->expects($this->at(0)) - ->method('walkReference') - ->with($object, 'group1', 'foo.bar.data', true); - $graphWalker->expects($this->at(1)) - ->method('walkReference') - ->with($object, 'group2', 'foo.bar.data', true); + $context->expects($this->at(0)) + ->method('validate') + ->with($object, 'data', 'group1', true); + $context->expects($this->at(1)) + ->method('validate') + ->with($object, 'data', 'group2', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); @@ -384,8 +372,7 @@ public function testUseInheritedCallbackValidationGroup() public function testUseInheritedClosureValidationGroup() { - $context = $this->getExecutionContext('foo.bar'); - $graphWalker = $context->getGraphWalker(); + $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parentOptions = array( @@ -403,12 +390,12 @@ public function testUseInheritedClosureValidationGroup() $form->setData($object); - $graphWalker->expects($this->at(0)) - ->method('walkReference') - ->with($object, 'group1', 'foo.bar.data', true); - $graphWalker->expects($this->at(1)) - ->method('walkReference') - ->with($object, 'group2', 'foo.bar.data', true); + $context->expects($this->at(0)) + ->method('validate') + ->with($object, 'data', 'group1', true); + $context->expects($this->at(1)) + ->method('validate') + ->with($object, 'data', 'group2', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); @@ -416,16 +403,15 @@ public function testUseInheritedClosureValidationGroup() public function testAppendPropertyPath() { - $context = $this->getExecutionContext('foo.bar'); - $graphWalker = $context->getGraphWalker(); + $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $form = $this->getBuilder('name', '\stdClass') ->setData($object) ->getForm(); - $graphWalker->expects($this->once()) - ->method('walkReference') - ->with($object, 'Default', 'foo.bar.data', true); + $context->expects($this->once()) + ->method('validate') + ->with($object, 'data', 'Default', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); @@ -433,15 +419,14 @@ public function testAppendPropertyPath() public function testDontWalkScalars() { - $context = $this->getExecutionContext(); - $graphWalker = $context->getGraphWalker(); + $context = $this->getMockExecutionContext(); $form = $this->getBuilder() ->setData('scalar') ->getForm(); - $graphWalker->expects($this->never()) - ->method('walkReference'); + $context->expects($this->never()) + ->method('validate'); $this->validator->initialize($context); $this->validator->validate($form, new Form()); @@ -449,7 +434,7 @@ public function testDontWalkScalars() public function testViolationIfExtraData() { - $context = $this->getExecutionContext(); + $context = $this->getMockExecutionContext(); $form = $this->getBuilder('parent', null, array('extra_fields_message' => 'Extra!')) ->setCompound(true) @@ -459,17 +444,24 @@ public function testViolationIfExtraData() $form->bind(array('foo' => 'bar')); + $context->expects($this->once()) + ->method('addViolation') + ->with( + 'Extra!', + array('{{ extra_fields }}' => 'foo'), + array('foo' => 'bar') + ); + $context->expects($this->never()) + ->method('addViolationAt'); + $this->validator->initialize($context); $this->validator->validate($form, new Form()); - - $this->assertCount(1, $context->getViolations()); - $this->assertEquals('Extra!', $context->getViolations()->get(0)->getMessage()); } /** * @dataProvider getPostMaxSizeFixtures */ - public function testPostMaxSizeViolation($contentLength, $iniMax, $nbViolation, $msg) + public function testPostMaxSizeViolation($contentLength, $iniMax, $nbViolation, array $params = array()) { $this->serverParams->expects($this->once()) ->method('getContentLength') @@ -478,30 +470,39 @@ public function testPostMaxSizeViolation($contentLength, $iniMax, $nbViolation, ->method('getNormalizedIniPostMaxSize') ->will($this->returnValue($iniMax)); - $context = $this->getExecutionContext(); + $context = $this->getMockExecutionContext(); $options = array('post_max_size_message' => 'Max {{ max }}!'); $form = $this->getBuilder('name', null, $options)->getForm(); + for ($i = 0; $i < $nbViolation; ++$i) { + if (0 === $i && count($params) > 0) { + $context->expects($this->at($i)) + ->method('addViolation') + ->with($options['post_max_size_message'], $params); + } else { + $context->expects($this->at($i)) + ->method('addViolation'); + } + } + + $context->expects($this->never()) + ->method('addViolationAt'); + $this->validator->initialize($context); $this->validator->validate($form, new Form()); - - $this->assertCount($nbViolation, $context->getViolations()); - if (null !== $msg) { - $this->assertEquals($msg, $context->getViolations()->get(0)->getMessage()); - } } public function getPostMaxSizeFixtures() { return array( - array(pow(1024, 3) + 1, '1G', 1, 'Max 1G!'), - array(pow(1024, 3), '1G', 0, null), - array(pow(1024, 2) + 1, '1M', 1, 'Max 1M!'), - array(pow(1024, 2), '1M', 0, null), - array(1024 + 1, '1K', 1, 'Max 1K!'), - array(1024, '1K', 0, null), - array(null, '1K', 0, null), - array(1024, '', 0, null), + array(pow(1024, 3) + 1, '1G', 1, array('{{ max }}' => '1G')), + array(pow(1024, 3), '1G', 0), + array(pow(1024, 2) + 1, '1M', 1, array('{{ max }}' => '1M')), + array(pow(1024, 2), '1M', 0), + array(1024 + 1, '1K', 1, array('{{ max }}' => '1K')), + array(1024, '1K', 0), + array(null, '1K', 0), + array(1024, '', 0), ); } @@ -513,7 +514,7 @@ public function testNoViolationIfNotRoot() $this->serverParams->expects($this->never()) ->method('getNormalizedIniPostMaxSize'); - $context = $this->getExecutionContext(); + $context = $this->getMockExecutionContext(); $parent = $this->getBuilder() ->setCompound(true) ->setDataMapper($this->getDataMapper()) @@ -521,10 +522,13 @@ public function testNoViolationIfNotRoot() $form = $this->getForm(); $parent->add($form); + $context->expects($this->never()) + ->method('addViolation'); + $context->expects($this->never()) + ->method('addViolationAt'); + $this->validator->initialize($context); $this->validator->validate($form, new Form()); - - $this->assertCount(0, $context->getViolations()); } /** @@ -537,25 +541,9 @@ public function getValidationGroups(FormInterface $form) return array('group1', 'group2'); } - private function getMockGraphWalker() + private function getMockExecutionContext() { - return $this->getMockBuilder('Symfony\Component\Validator\GraphWalker') - ->disableOriginalConstructor() - ->getMock(); - } - - private function getMockMetadataFactory() - { - return $this->getMock('Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface'); - } - - private function getExecutionContext($propertyPath = null) - { - $graphWalker = $this->getMockGraphWalker(); - $metadataFactory = $this->getMockMetadataFactory(); - $globalContext = new GlobalExecutionContext('Root', $graphWalker, $metadataFactory); - - return new ExecutionContext($globalContext, null, $propertyPath, null, null, null); + return $this->getMock('Symfony\Component\Validator\ExecutionContextInterface'); } /** From 56b9acd1c611630a3eb9563141c5e7d73823d5ac Mon Sep 17 00:00:00 2001 From: Joseph Bielawski Date: Tue, 11 Dec 2012 09:37:25 +0100 Subject: [PATCH 019/447] [Form] Add tests to prove that label is not rendered when is marked as false --- Tests/AbstractDivLayoutTest.php | 17 +++++++++++++++++ Tests/AbstractTableLayoutTest.php | 19 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/Tests/AbstractDivLayoutTest.php b/Tests/AbstractDivLayoutTest.php index 576d7890da..ac9b18b065 100644 --- a/Tests/AbstractDivLayoutTest.php +++ b/Tests/AbstractDivLayoutTest.php @@ -526,6 +526,23 @@ public function testLabelHasNoId() ); } + public function testLabelIsNotRenderedWhenSetToFalse() + { + $form = $this->factory->createNamed('name', 'text', null, array( + 'label' => false + )); + $html = $this->renderRow($form->createView()); + + $this->assertMatchesXpath($html, +'/div + [ + ./input[@id="name"] + ] + [count(//label)=0] +' + ); + } + /** * @dataProvider themeBlockInheritanceProvider */ diff --git a/Tests/AbstractTableLayoutTest.php b/Tests/AbstractTableLayoutTest.php index c21c712c5c..efa957fb0b 100644 --- a/Tests/AbstractTableLayoutTest.php +++ b/Tests/AbstractTableLayoutTest.php @@ -39,6 +39,25 @@ public function testRow() ); } + public function testLabelIsNotRenderedWhenSetToFalse() + { + $form = $this->factory->createNamed('name', 'text', null, array( + 'label' => false + )); + $html = $this->renderRow($form->createView()); + + $this->assertMatchesXpath($html, +'/tr + [ + ./td + [count(//label)=0] + /following-sibling::td + [./input[@id="name"]] + ] +' + ); + } + public function testRepeatedRow() { $form = $this->factory->createNamed('name', 'repeated'); From ff8d8a4ee15bd34eb425b4f516c8076f64020295 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 11 Dec 2012 11:49:22 +0100 Subject: [PATCH 020/447] fixed CS --- Tests/Extension/Core/Type/FormTypeTest.php | 2 ++ Tests/Extension/Validator/Constraints/FormValidatorTest.php | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/Extension/Core/Type/FormTypeTest.php b/Tests/Extension/Core/Type/FormTypeTest.php index 6fbddeb6a4..1a8e4ad07b 100644 --- a/Tests/Extension/Core/Type/FormTypeTest.php +++ b/Tests/Extension/Core/Type/FormTypeTest.php @@ -482,6 +482,7 @@ public function testSubformCallsSettersIfReferenceIsScalar() $builder->get('referenceCopy')->addViewTransformer(new CallbackTransformer( function () {}, function ($value) { // reverseTransform + return 'foobar'; } )); @@ -507,6 +508,7 @@ public function testSubformAlwaysInsertsIntoArrays() $builder->get('referenceCopy')->addViewTransformer(new CallbackTransformer( function () {}, function ($value) use ($ref2) { // reverseTransform + return $ref2; } )); diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index f47618fb28..a3d9f26d98 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -12,13 +12,11 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\Constraints; use Symfony\Component\Form\FormBuilder; -use Symfony\Component\Validator\ConstraintViolation; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\CallbackTransformer; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\Extension\Validator\Constraints\Form; use Symfony\Component\Form\Extension\Validator\Constraints\FormValidator; -use Symfony\Component\Form\Util\PropertyPath; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\NotBlank; From e7cfe77ca44180e17869d7b5ec433da8cf6f1e90 Mon Sep 17 00:00:00 2001 From: Colin Frei Date: Wed, 12 Dec 2012 17:43:13 +0100 Subject: [PATCH 021/447] [Form] Trigger errors for deprecated methods in Form Component --- AbstractType.php | 8 ++++++ AbstractTypeExtension.php | 4 +++ CallbackValidator.php | 4 +++ Event/DataEvent.php | 2 ++ Extension/Core/Type/FieldType.php | 5 ++++ Extension/Validator/ValidatorTypeGuesser.php | 1 + Form.php | 24 +++++++++++++++++ FormBuilder.php | 2 ++ FormConfigBuilder.php | 20 +++++++++++++++ FormFactory.php | 6 +++++ FormRegistry.php | 2 ++ FormTypeGuesserChain.php | 2 ++ FormView.php | 27 ++++++++++++++++++++ 13 files changed, 107 insertions(+) diff --git a/AbstractType.php b/AbstractType.php index 479ceac511..ec45e824e0 100644 --- a/AbstractType.php +++ b/AbstractType.php @@ -67,6 +67,8 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) */ public function getDefaultOptions(array $options) { + trigger_error('getDefaultOptions() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED); + return array(); } @@ -82,6 +84,8 @@ public function getDefaultOptions(array $options) */ public function getAllowedOptionValues(array $options) { + trigger_error('getAllowedOptionValues() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED); + return array(); } @@ -104,6 +108,8 @@ public function getParent() */ public function setExtensions(array $extensions) { + trigger_error('setExtensions() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); + $this->extensions = $extensions; } @@ -117,6 +123,8 @@ public function setExtensions(array $extensions) */ public function getExtensions() { + trigger_error('getExtensions() is deprecated since version 2.1 and will be removed in 2.3. Use ResolvedFormTypeInterface::getTypeExtensions instead.', E_USER_DEPRECATED); + return $this->extensions; } } diff --git a/AbstractTypeExtension.php b/AbstractTypeExtension.php index 080b546b2d..c5dcfb94eb 100644 --- a/AbstractTypeExtension.php +++ b/AbstractTypeExtension.php @@ -58,6 +58,8 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) */ public function getDefaultOptions() { + trigger_error('getDefaultOptions() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED); + return array(); } @@ -71,6 +73,8 @@ public function getDefaultOptions() */ public function getAllowedOptionValues() { + trigger_error('getAllowedOptionValues() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED); + return array(); } } diff --git a/CallbackValidator.php b/CallbackValidator.php index 6d677c11f0..0e7c8012eb 100644 --- a/CallbackValidator.php +++ b/CallbackValidator.php @@ -27,6 +27,8 @@ class CallbackValidator implements FormValidatorInterface */ public function __construct($callback) { + trigger_error('CallbackValidator is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); + $this->callback = $callback; } @@ -35,6 +37,8 @@ public function __construct($callback) */ public function validate(FormInterface $form) { + trigger_error('validate() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); + return call_user_func($this->callback, $form); } } diff --git a/Event/DataEvent.php b/Event/DataEvent.php index 1091b5ccf2..cc7c3b2e7e 100644 --- a/Event/DataEvent.php +++ b/Event/DataEvent.php @@ -33,6 +33,8 @@ class DataEvent extends Event */ public function __construct(FormInterface $form, $data) { + trigger_error('DataEvent is deprecated since version 2.1 and will be removed in 2.3. Code against \Symfony\Component\Form\FormEvent instead.', E_USER_DEPRECATED); + $this->form = $form; $this->data = $data; } diff --git a/Extension/Core/Type/FieldType.php b/Extension/Core/Type/FieldType.php index dbafde1f65..e5da968ca1 100644 --- a/Extension/Core/Type/FieldType.php +++ b/Extension/Core/Type/FieldType.php @@ -22,6 +22,11 @@ */ class FieldType extends AbstractType { + function __construct() + { + trigger_error('FieldType is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); + } + /** * {@inheritdoc} */ diff --git a/Extension/Validator/ValidatorTypeGuesser.php b/Extension/Validator/ValidatorTypeGuesser.php index 6aa2da1122..ad89971ce3 100755 --- a/Extension/Validator/ValidatorTypeGuesser.php +++ b/Extension/Validator/ValidatorTypeGuesser.php @@ -70,6 +70,7 @@ public function guessMaxLength($class, $property) */ public function guessMinLength($class, $property) { + trigger_error('guessMinLength() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); } /** diff --git a/Form.php b/Form.php index 6fbb1d5beb..ed6cea4e00 100644 --- a/Form.php +++ b/Form.php @@ -210,6 +210,8 @@ public function getPropertyPath() */ public function getTypes() { + trigger_error('getTypes() is deprecated since version 2.1 and will be removed in 2.3. Use getConfig() and FormConfigInterface::getType() instead.', E_USER_DEPRECATED); + $types = array(); for ($type = $this->config->getType(); null !== $type; $type = $type->getParent()) { @@ -279,6 +281,8 @@ public function getParent() */ public function hasParent() { + trigger_error('hasParent() is deprecated since version 2.1 and will be removed in 2.3. Use getParent() or inverse isRoot() instead.', E_USER_DEPRECATED); + return null !== $this->parent; } @@ -310,6 +314,8 @@ public function isRoot() */ public function hasAttribute($name) { + trigger_error('hasAttribute() is deprecated since version 2.1 and will be removed in 2.3. Use getConfig() and FormConfigInterface::hasAttribute() instead.', E_USER_DEPRECATED); + return $this->config->hasAttribute($name); } @@ -325,6 +331,8 @@ public function hasAttribute($name) */ public function getAttribute($name) { + trigger_error('getAttribute() is deprecated since version 2.1 and will be removed in 2.3. Use getConfig() and FormConfigInterface::getAttribute() instead.', E_USER_DEPRECATED); + return $this->config->getAttribute($name); } @@ -470,6 +478,8 @@ public function getViewData() */ public function getClientData() { + trigger_error('getClientData() is deprecated since version 2.1 and will be removed in 2.3. Use getViewData() instead.', E_USER_DEPRECATED); + return $this->getViewData(); } @@ -627,6 +637,8 @@ public function bind($submittedData) */ public function bindRequest(Request $request) { + trigger_error('bindRequest() is deprecated since version 2.1 and will be removed in 2.3. Use FormConfigInterface::bind() instead.', E_USER_DEPRECATED); + return $this->bind($request); } @@ -654,6 +666,8 @@ public function addError(FormError $error) */ public function getErrorBubbling() { + trigger_error('getErrorBubbling() is deprecated since version 2.1 and will be removed in 2.3. Use getConfig() and FormConfigInterface::getErrorBubbling() instead.', E_USER_DEPRECATED); + return $this->config->getErrorBubbling(); } @@ -721,6 +735,8 @@ public function isValid() */ public function hasErrors() { + trigger_error('hasErrors() is deprecated since version 2.1 and will be removed in 2.3. Count getErrors() instead.', E_USER_DEPRECATED); + return count($this->errors) > 0; } @@ -770,6 +786,8 @@ public function getErrorsAsString($level = 0) */ public function getNormTransformers() { + trigger_error('getNormTransformers() is deprecated since version 2.1 and will be removed in 2.3. Use getConfig() and FormConfigInterface::getModelTransformers() instead.', E_USER_DEPRECATED); + return $this->config->getModelTransformers(); } @@ -783,6 +801,8 @@ public function getNormTransformers() */ public function getClientTransformers() { + trigger_error('getClientTransformers() is deprecated since version 2.1 and will be removed in 2.3. Use getConfig() and FormConfigInterface::getViewTransformers() instead.', E_USER_DEPRECATED); + return $this->config->getViewTransformers(); } @@ -804,6 +824,8 @@ public function all() */ public function getChildren() { + trigger_error('getChilren() is deprecated since version 2.1 and will be removed in 2.3. Use all() instead.', E_USER_DEPRECATED); + return $this->all(); } @@ -817,6 +839,8 @@ public function getChildren() */ public function hasChildren() { + trigger_error('hasChildren() is deprecated since version 2.1 and will be removed in 2.3. Use count() instead.', E_USER_DEPRECATED); + return count($this->children) > 0; } diff --git a/FormBuilder.php b/FormBuilder.php index 1f8d713ddb..86e5587eff 100644 --- a/FormBuilder.php +++ b/FormBuilder.php @@ -295,6 +295,8 @@ public function getIterator() */ public function getTypes() { + trigger_error('getTypes() is deprecated since version 2.1 and will be removed in 2.3. Use getConfig() and FormConfigInterface::getType() instead.', E_USER_DEPRECATED); + $types = array(); for ($type = $this->getType(); null !== $type; $type = $type->getParent()) { diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index 9a21df4642..529fb89179 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -196,6 +196,8 @@ public function addEventSubscriber(EventSubscriberInterface $subscriber) */ public function addValidator(FormValidatorInterface $validator) { + trigger_error('addValidator() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); + if ($this->locked) { throw new FormException('The config builder cannot be modified anymore.'); } @@ -251,6 +253,8 @@ public function resetViewTransformers() */ public function appendClientTransformer(DataTransformerInterface $viewTransformer) { + trigger_error('appendClientTransformer() is deprecated since version 2.1 and will be removed in 2.3. Use addViewTransformer() instead.', E_USER_DEPRECATED); + if ($this->locked) { throw new FormException('The config builder cannot be modified anymore.'); } @@ -271,6 +275,8 @@ public function appendClientTransformer(DataTransformerInterface $viewTransforme */ public function prependClientTransformer(DataTransformerInterface $viewTransformer) { + trigger_error('prependClientTransformer() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); + if ($this->locked) { throw new FormException('The config builder cannot be modified anymore.'); } @@ -290,6 +296,8 @@ public function prependClientTransformer(DataTransformerInterface $viewTransform */ public function resetClientTransformers() { + trigger_error('resetClientTransformers() is deprecated since version 2.1 and will be removed in 2.3. Use resetViewTransformers() instead.', E_USER_DEPRECATED); + if ($this->locked) { throw new FormException('The config builder cannot be modified anymore.'); } @@ -342,6 +350,8 @@ public function resetModelTransformers() */ public function appendNormTransformer(DataTransformerInterface $modelTransformer) { + trigger_error('appendNormTransformer() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); + if ($this->locked) { throw new FormException('The config builder cannot be modified anymore.'); } @@ -363,6 +373,8 @@ public function appendNormTransformer(DataTransformerInterface $modelTransformer */ public function prependNormTransformer(DataTransformerInterface $modelTransformer) { + trigger_error('prependNormTransformer() is deprecated since version 2.1 and will be removed in 2.3. Use addModelTransformer() instead.', E_USER_DEPRECATED); + if ($this->locked) { throw new FormException('The config builder cannot be modified anymore.'); } @@ -382,6 +394,8 @@ public function prependNormTransformer(DataTransformerInterface $modelTransforme */ public function resetNormTransformers() { + trigger_error('resetNormTransformers() is deprecated since version 2.1 and will be removed in 2.3. Use resetModelTransformers() instead.', E_USER_DEPRECATED); + if ($this->locked) { throw new FormException('The config builder cannot be modified anymore.'); } @@ -471,6 +485,8 @@ public function getViewTransformers() */ public function getClientTransformers() { + trigger_error('getClientTransformers() is deprecated since version 2.1 and will be removed in 2.3. Use getViewTransformers() instead.', E_USER_DEPRECATED); + return $this->getViewTransformers(); } @@ -492,6 +508,8 @@ public function getModelTransformers() */ public function getNormTransformers() { + trigger_error('getNormTransformers() is deprecated since version 2.1 and will be removed in 2.3. Use getModelTransformers() instead.', E_USER_DEPRECATED); + return $this->getModelTransformers(); } @@ -508,6 +526,8 @@ public function getDataMapper() */ public function getValidators() { + trigger_error('getValidators() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); + return $this->validators; } diff --git a/FormFactory.php b/FormFactory.php index 2d06e59be4..ce60e7d42f 100644 --- a/FormFactory.php +++ b/FormFactory.php @@ -146,6 +146,8 @@ public function createBuilderForProperty($class, $property, $data = null, array */ public function hasType($name) { + trigger_error('hasType() is deprecated since version 2.1 and will be removed in 2.3. Use FormRegistryInterface::hasType() instead.', E_USER_DEPRECATED); + return $this->registry->hasType($name); } @@ -160,6 +162,8 @@ public function hasType($name) */ public function addType(FormTypeInterface $type) { + trigger_error('addType() is deprecated since version 2.1 and will be removed in 2.3. Use form extensions or type registration in the Dependency Injection Container instead.', E_USER_DEPRECATED); + $parentType = $type->getParent(); $this->registry->addType($this->resolvedTypeFactory->createResolvedType( @@ -185,6 +189,8 @@ public function addType(FormTypeInterface $type) */ public function getType($name) { + trigger_error('getType() is deprecated since version 2.1 and will be removed in 2.3. Use FormRegistryInterface::getType() instead.', E_USER_DEPRECATED); + return $this->registry->getType($name)->getInnerType(); } diff --git a/FormRegistry.php b/FormRegistry.php index 73de7875f6..24df9a8053 100644 --- a/FormRegistry.php +++ b/FormRegistry.php @@ -68,6 +68,8 @@ public function __construct(array $extensions, ResolvedFormTypeFactoryInterface */ public function addType(ResolvedFormTypeInterface $type) { + trigger_error('addType() is deprecated since version 2.1 and will be removed in 2.3. Use form extensions or type registration in the Dependency Injection Container instead.', E_USER_DEPRECATED); + $this->types[$type->getName()] = $type; } diff --git a/FormTypeGuesserChain.php b/FormTypeGuesserChain.php index 608709de87..5890e5b246 100644 --- a/FormTypeGuesserChain.php +++ b/FormTypeGuesserChain.php @@ -75,6 +75,8 @@ public function guessMaxLength($class, $property) */ public function guessMinLength($class, $property) { + trigger_error('guessMinLength() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); + return $this->guess(function ($guesser) use ($class, $property) { return $guesser->guessMinLength($class, $property); }); diff --git a/FormView.php b/FormView.php index 84eb19843c..b230d9c063 100644 --- a/FormView.php +++ b/FormView.php @@ -64,6 +64,7 @@ public function __construct(FormView $parent = null) */ public function getName() { + trigger_error('getName() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'vars\' instead which contains an entry named "name".', E_USER_DEPRECATED); return $this->vars['name']; } @@ -78,6 +79,8 @@ public function getName() */ public function set($name, $value) { + trigger_error('set() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'vars\' instead.', E_USER_DEPRECATED); + $this->vars[$name] = $value; return $this; @@ -93,6 +96,8 @@ public function set($name, $value) */ public function has($name) { + trigger_error('has() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'vars\' instead.', E_USER_DEPRECATED); + return array_key_exists($name, $this->vars); } @@ -107,6 +112,8 @@ public function has($name) */ public function get($name, $default = null) { + trigger_error('get() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'vars\' instead.', E_USER_DEPRECATED); + if (false === $this->has($name)) { return $default; } @@ -122,6 +129,8 @@ public function get($name, $default = null) */ public function all() { + trigger_error('all() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'vars\' instead.', E_USER_DEPRECATED); + return $this->vars; } @@ -135,6 +144,8 @@ public function all() */ public function getVars() { + trigger_error('getVars() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'vars\' instead.', E_USER_DEPRECATED); + return $this->vars; } @@ -152,6 +163,8 @@ public function getVars() */ public function setAttribute($name, $value) { + trigger_error('setAttribute() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'vars\' instead which contains an entry named "attr".', E_USER_DEPRECATED); + $this->vars['attr'][$name] = $value; return $this; @@ -207,6 +220,8 @@ public function setRendered() */ public function setParent(FormView $parent = null) { + trigger_error('setParent() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'parent\' instead.', E_USER_DEPRECATED); + $this->parent = $parent; return $this; @@ -222,6 +237,8 @@ public function setParent(FormView $parent = null) */ public function getParent() { + trigger_error('getParent() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'parent\' instead.', E_USER_DEPRECATED); + return $this->parent; } @@ -235,6 +252,8 @@ public function getParent() */ public function hasParent() { + trigger_error('hasParent() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'parent\' instead.', E_USER_DEPRECATED); + return null !== $this->parent; } @@ -250,6 +269,8 @@ public function hasParent() */ public function setChildren(array $children) { + trigger_error('setChildren() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'children\' instead.', E_USER_DEPRECATED); + $this->children = $children; return $this; @@ -265,6 +286,8 @@ public function setChildren(array $children) */ public function getChildren() { + trigger_error('getChildren() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'children\' instead.', E_USER_DEPRECATED); + return $this->children; } @@ -280,6 +303,8 @@ public function getChildren() */ public function getChild($name) { + trigger_error('getChild() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'children\' instead.', E_USER_DEPRECATED); + return $this->children[$name]; } @@ -293,6 +318,8 @@ public function getChild($name) */ public function hasChildren() { + trigger_error('hasChildren() is deprecated since version 2.1 and will be removed in 2.3. Use count() instead.', E_USER_DEPRECATED); + return count($this->children) > 0; } From 7242ede2d13593fce1adf1707acad73c21202131 Mon Sep 17 00:00:00 2001 From: Colin Frei Date: Fri, 14 Dec 2012 07:29:01 +0100 Subject: [PATCH 022/447] [Form] replace bindRequest() with bind(), as bindRequest is deprecated --- Tests/CompoundFormTest.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index 32349ba54e..eb026d6b52 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -364,7 +364,7 @@ public function testBindPostOrPutRequest($method) $form->add($this->getBuilder('name')->getForm()); $form->add($this->getBuilder('image')->getForm()); - $form->bindRequest($request); + $form->bind($request); $file = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK); @@ -413,7 +413,7 @@ public function testBindPostOrPutRequestWithEmptyRootFormName($method) $form->add($this->getBuilder('name')->getForm()); $form->add($this->getBuilder('image')->getForm()); - $form->bindRequest($request); + $form->bind($request); $file = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK); @@ -454,7 +454,7 @@ public function testBindPostOrPutRequestWithSingleChildForm($method) ->addEventSubscriber(new BindRequestListener()) ->getForm(); - $form->bindRequest($request); + $form->bind($request); $file = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK); @@ -487,7 +487,7 @@ public function testBindPostOrPutRequestWithSingleChildFormUploadedFile($method) ->addEventSubscriber(new BindRequestListener()) ->getForm(); - $form->bindRequest($request); + $form->bind($request); $this->assertEquals('Bernhard', $form->getData()); @@ -519,7 +519,7 @@ public function testBindGetRequest() $form->add($this->getBuilder('firstName')->getForm()); $form->add($this->getBuilder('lastName')->getForm()); - $form->bindRequest($request); + $form->bind($request); $this->assertEquals('Bernhard', $form['firstName']->getData()); $this->assertEquals('Schussek', $form['lastName']->getData()); @@ -549,7 +549,7 @@ public function testBindGetRequestWithEmptyRootFormName() $form->add($this->getBuilder('firstName')->getForm()); $form->add($this->getBuilder('lastName')->getForm()); - $form->bindRequest($request); + $form->bind($request); $this->assertEquals('Bernhard', $form['firstName']->getData()); $this->assertEquals('Schussek', $form['lastName']->getData()); From e83632359d58ce736e34fe2e1c19606a7ac1d330 Mon Sep 17 00:00:00 2001 From: Colin Frei Date: Fri, 14 Dec 2012 07:31:09 +0100 Subject: [PATCH 023/447] [Form] catch deprecated errors in tests --- Tests/CompoundFormTest.php | 6 ++++ Tests/DeprecationErrorHandler.php | 36 +++++++++++++++++++ .../FixRadioInputListenerTest.php | 8 ++--- .../FixUrlProtocolListenerTest.php | 8 ++--- .../MergeCollectionListenerTest.php | 20 +++++------ .../EventListener/ResizeFormListenerTest.php | 30 ++++++++-------- .../Core/EventListener/TrimListenerTest.php | 8 ++--- Tests/Extension/Core/Type/TypeTestCase.php | 8 +++++ .../CsrfValidationListenerTest.php | 4 +-- .../EventListener/BindRequestListenerTest.php | 18 +++++----- .../EventListener/ValidationListenerTest.php | 8 ++--- Tests/FormFactoryTest.php | 6 ++++ Tests/FormRegistryTest.php | 4 +++ Tests/SimpleFormTest.php | 3 +- 14 files changed, 114 insertions(+), 53 deletions(-) create mode 100644 Tests/DeprecationErrorHandler.php diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index eb026d6b52..05483f6496 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -118,12 +118,16 @@ public function testHasChildren() { $this->form->add($this->getBuilder()->getForm()); + set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handle')); $this->assertTrue($this->form->hasChildren()); + restore_error_handler(); } public function testHasNoChildren() { + set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handle')); $this->assertFalse($this->form->hasChildren()); + restore_error_handler(); } public function testAdd() @@ -151,7 +155,9 @@ public function testRemove() $this->form->remove('foo'); $this->assertNull($child->getParent()); + set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handle')); $this->assertFalse($this->form->hasChildren()); + restore_error_handler(); } /** diff --git a/Tests/DeprecationErrorHandler.php b/Tests/DeprecationErrorHandler.php new file mode 100644 index 0000000000..0a4c970e85 --- /dev/null +++ b/Tests/DeprecationErrorHandler.php @@ -0,0 +1,36 @@ +getMock('Symfony\Component\Form\Tests\FormInterface'); - $event = new FormEvent($form, $data); + $event = DeprecationErrorHandler::getFormEvent($form, $data); $this->listener->preBind($event); @@ -53,7 +53,7 @@ public function testFixZero() { $data = '0'; $form = $this->getMock('Symfony\Component\Form\Tests\FormInterface'); - $event = new FormEvent($form, $data); + $event = DeprecationErrorHandler::getFormEvent($form, $data); $this->listener->preBind($event); @@ -64,7 +64,7 @@ public function testIgnoreEmptyString() { $data = ''; $form = $this->getMock('Symfony\Component\Form\Tests\FormInterface'); - $event = new FormEvent($form, $data); + $event = DeprecationErrorHandler::getFormEvent($form, $data); $this->listener->preBind($event); diff --git a/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php b/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php index ab0bdf3a44..d8f68cb7da 100644 --- a/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php +++ b/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; -use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Core\EventListener\FixUrlProtocolListener; +use Symfony\Component\Form\Tests\DeprecationErrorHandler; class FixUrlProtocolListenerTest extends \PHPUnit_Framework_TestCase { @@ -27,7 +27,7 @@ public function testFixHttpUrl() { $data = "www.symfony.com"; $form = $this->getMock('Symfony\Component\Form\Tests\FormInterface'); - $event = new FormEvent($form, $data); + $event = DeprecationErrorHandler::getFormEvent($form, $data); $filter = new FixUrlProtocolListener('http'); $filter->onBind($event); @@ -39,7 +39,7 @@ public function testSkipKnownUrl() { $data = "http://www.symfony.com"; $form = $this->getMock('Symfony\Component\Form\Tests\FormInterface'); - $event = new FormEvent($form, $data); + $event = DeprecationErrorHandler::getFormEvent($form, $data); $filter = new FixUrlProtocolListener('http'); $filter->onBind($event); @@ -51,7 +51,7 @@ public function testSkipOtherProtocol() { $data = "ftp://www.symfony.com"; $form = $this->getMock('Symfony\Component\Form\Tests\FormInterface'); - $event = new FormEvent($form, $data); + $event = DeprecationErrorHandler::getFormEvent($form, $data); $filter = new FixUrlProtocolListener('http'); $filter->onBind($event); diff --git a/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php b/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php index 78a0c01fac..75ae84a6b7 100644 --- a/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php +++ b/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; -use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Core\EventListener\MergeCollectionListener; +use Symfony\Component\Form\Tests\DeprecationErrorHandler; abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase { @@ -84,7 +84,7 @@ public function testAddExtraEntriesIfAllowAdd($allowDelete) $this->form->setData($originalData); - $event = new FormEvent($this->form, $newData); + $event = DeprecationErrorHandler::getFormEvent($this->form, $newData); $listener->onBind($event); // The original object was modified @@ -108,7 +108,7 @@ public function testAddExtraEntriesIfAllowAddDontOverwriteExistingIndices($allow $this->form->setData($originalData); - $event = new FormEvent($this->form, $newData); + $event = DeprecationErrorHandler::getFormEvent($this->form, $newData); $listener->onBind($event); // The original object was modified @@ -133,7 +133,7 @@ public function testDoNothingIfNotAllowAdd($allowDelete) $this->form->setData($originalData); - $event = new FormEvent($this->form, $newData); + $event = DeprecationErrorHandler::getFormEvent($this->form, $newData); $listener->onBind($event); // We still have the original object @@ -157,7 +157,7 @@ public function testRemoveMissingEntriesIfAllowDelete($allowAdd) $this->form->setData($originalData); - $event = new FormEvent($this->form, $newData); + $event = DeprecationErrorHandler::getFormEvent($this->form, $newData); $listener->onBind($event); // The original object was modified @@ -182,7 +182,7 @@ public function testDoNothingIfNotAllowDelete($allowAdd) $this->form->setData($originalData); - $event = new FormEvent($this->form, $newData); + $event = DeprecationErrorHandler::getFormEvent($this->form, $newData); $listener->onBind($event); // We still have the original object @@ -201,7 +201,7 @@ public function testDoNothingIfNotAllowDelete($allowAdd) public function testRequireArrayOrTraversable($allowAdd, $allowDelete) { $newData = 'no array or traversable'; - $event = new FormEvent($this->form, $newData); + $event = DeprecationErrorHandler::getFormEvent($this->form, $newData); $listener = new MergeCollectionListener($allowAdd, $allowDelete); $listener->onBind($event); } @@ -215,7 +215,7 @@ public function testDealWithNullData() $this->form->setData($originalData); - $event = new FormEvent($this->form, $newData); + $event = DeprecationErrorHandler::getFormEvent($this->form, $newData); $listener->onBind($event); $this->assertSame($originalData, $event->getData()); @@ -233,7 +233,7 @@ public function testDealWithNullOriginalDataIfAllowAdd($allowDelete) $this->form->setData($originalData); - $event = new FormEvent($this->form, $newData); + $event = DeprecationErrorHandler::getFormEvent($this->form, $newData); $listener->onBind($event); $this->assertSame($newData, $event->getData()); @@ -251,7 +251,7 @@ public function testDontDealWithNullOriginalDataIfNotAllowAdd($allowDelete) $this->form->setData($originalData); - $event = new FormEvent($this->form, $newData); + $event = DeprecationErrorHandler::getFormEvent($this->form, $newData); $listener->onBind($event); $this->assertNull($event->getData()); diff --git a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php index ba83360e09..e271ad020a 100644 --- a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php +++ b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php @@ -11,9 +11,9 @@ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; -use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener; use Symfony\Component\Form\FormBuilder; +use Symfony\Component\Form\Tests\DeprecationErrorHandler; class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase { @@ -80,7 +80,7 @@ public function testPreSetDataResizesForm() ->will($this->returnValue($this->getForm('2'))); $data = array(1 => 'string', 2 => 'string'); - $event = new FormEvent($this->form, $data); + $event = DeprecationErrorHandler::getFormEvent($this->form, $data); $listener = new ResizeFormListener($this->factory, 'text', array('max_length' => '10'), false, false); $listener->preSetData($event); @@ -95,7 +95,7 @@ public function testPreSetDataResizesForm() public function testPreSetDataRequiresArrayOrTraversable() { $data = 'no array or traversable'; - $event = new FormEvent($this->form, $data); + $event = DeprecationErrorHandler::getFormEvent($this->form, $data); $listener = new ResizeFormListener($this->factory, 'text', array(), false, false); $listener->preSetData($event); } @@ -105,7 +105,7 @@ public function testPreSetDataDealsWithNullData() $this->factory->expects($this->never())->method('createNamed'); $data = null; - $event = new FormEvent($this->form, $data); + $event = DeprecationErrorHandler::getFormEvent($this->form, $data); $listener = new ResizeFormListener($this->factory, 'text', array(), false, false); $listener->preSetData($event); } @@ -120,7 +120,7 @@ public function testPreBindResizesUpIfAllowAdd() ->will($this->returnValue($this->getForm('1'))); $data = array(0 => 'string', 1 => 'string'); - $event = new FormEvent($this->form, $data); + $event = DeprecationErrorHandler::getFormEvent($this->form, $data); $listener = new ResizeFormListener($this->factory, 'text', array('max_length' => 10), true, false); $listener->preBind($event); @@ -134,7 +134,7 @@ public function testPreBindResizesDownIfAllowDelete() $this->form->add($this->getForm('1')); $data = array(0 => 'string'); - $event = new FormEvent($this->form, $data); + $event = DeprecationErrorHandler::getFormEvent($this->form, $data); $listener = new ResizeFormListener($this->factory, 'text', array(), false, true); $listener->preBind($event); @@ -148,7 +148,7 @@ public function testPreBindRemovesZeroKeys() $this->form->add($this->getForm('0')); $data = array(); - $event = new FormEvent($this->form, $data); + $event = DeprecationErrorHandler::getFormEvent($this->form, $data); $listener = new ResizeFormListener($this->factory, 'text', array(), false, true); $listener->preBind($event); @@ -161,7 +161,7 @@ public function testPreBindDoesNothingIfNotAllowAddNorAllowDelete() $this->form->add($this->getForm('1')); $data = array(0 => 'string', 2 => 'string'); - $event = new FormEvent($this->form, $data); + $event = DeprecationErrorHandler::getFormEvent($this->form, $data); $listener = new ResizeFormListener($this->factory, 'text', array(), false, false); $listener->preBind($event); @@ -176,7 +176,7 @@ public function testPreBindDoesNothingIfNotAllowAddNorAllowDelete() public function testPreBindRequiresArrayOrTraversable() { $data = 'no array or traversable'; - $event = new FormEvent($this->form, $data); + $event = DeprecationErrorHandler::getFormEvent($this->form, $data); $listener = new ResizeFormListener($this->factory, 'text', array(), false, false); $listener->preBind($event); } @@ -186,7 +186,7 @@ public function testPreBindDealsWithNullData() $this->form->add($this->getForm('1')); $data = null; - $event = new FormEvent($this->form, $data); + $event = DeprecationErrorHandler::getFormEvent($this->form, $data); $listener = new ResizeFormListener($this->factory, 'text', array(), false, true); $listener->preBind($event); @@ -199,7 +199,7 @@ public function testPreBindDealsWithEmptyData() $this->form->add($this->getForm('1')); $data = ''; - $event = new FormEvent($this->form, $data); + $event = DeprecationErrorHandler::getFormEvent($this->form, $data); $listener = new ResizeFormListener($this->factory, 'text', array(), false, true); $listener->preBind($event); @@ -211,7 +211,7 @@ public function testOnBindNormDataRemovesEntriesMissingInTheFormIfAllowDelete() $this->form->add($this->getForm('1')); $data = array(0 => 'first', 1 => 'second', 2 => 'third'); - $event = new FormEvent($this->form, $data); + $event = DeprecationErrorHandler::getFormEvent($this->form, $data); $listener = new ResizeFormListener($this->factory, 'text', array(), false, true); $listener->onBind($event); @@ -223,7 +223,7 @@ public function testOnBindNormDataDoesNothingIfNotAllowDelete() $this->form->add($this->getForm('1')); $data = array(0 => 'first', 1 => 'second', 2 => 'third'); - $event = new FormEvent($this->form, $data); + $event = DeprecationErrorHandler::getFormEvent($this->form, $data); $listener = new ResizeFormListener($this->factory, 'text', array(), false, false); $listener->onBind($event); @@ -236,7 +236,7 @@ public function testOnBindNormDataDoesNothingIfNotAllowDelete() public function testOnBindNormDataRequiresArrayOrTraversable() { $data = 'no array or traversable'; - $event = new FormEvent($this->form, $data); + $event = DeprecationErrorHandler::getFormEvent($this->form, $data); $listener = new ResizeFormListener($this->factory, 'text', array(), false, false); $listener->onBind($event); } @@ -246,7 +246,7 @@ public function testOnBindNormDataDealsWithNullData() $this->form->add($this->getForm('1')); $data = null; - $event = new FormEvent($this->form, $data); + $event = DeprecationErrorHandler::getFormEvent($this->form, $data); $listener = new ResizeFormListener($this->factory, 'text', array(), false, true); $listener->onBind($event); diff --git a/Tests/Extension/Core/EventListener/TrimListenerTest.php b/Tests/Extension/Core/EventListener/TrimListenerTest.php index a5771119fb..eb46f18e27 100644 --- a/Tests/Extension/Core/EventListener/TrimListenerTest.php +++ b/Tests/Extension/Core/EventListener/TrimListenerTest.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; -use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Core\EventListener\TrimListener; +use Symfony\Component\Form\Tests\DeprecationErrorHandler; class TrimListenerTest extends \PHPUnit_Framework_TestCase { @@ -27,7 +27,7 @@ public function testTrim() { $data = " Foo! "; $form = $this->getMock('Symfony\Component\Form\Tests\FormInterface'); - $event = new FormEvent($form, $data); + $event = DeprecationErrorHandler::getFormEvent($form, $data); $filter = new TrimListener(); $filter->preBind($event); @@ -39,7 +39,7 @@ public function testTrimSkipNonStrings() { $data = 1234; $form = $this->getMock('Symfony\Component\Form\Tests\FormInterface'); - $event = new FormEvent($form, $data); + $event = DeprecationErrorHandler::getFormEvent($form, $data); $filter = new TrimListener(); $filter->preBind($event); @@ -60,7 +60,7 @@ public function testTrimUtf8($chars) $data = $data."ab\ncd".$data; $form = $this->getMock('Symfony\Component\Form\Tests\FormInterface'); - $event = new FormEvent($form, $data); + $event = DeprecationErrorHandler::getFormEvent($form, $data); $filter = new TrimListener(); $filter->preBind($event); diff --git a/Tests/Extension/Core/Type/TypeTestCase.php b/Tests/Extension/Core/Type/TypeTestCase.php index 9101e45308..ca84b5dc22 100644 --- a/Tests/Extension/Core/Type/TypeTestCase.php +++ b/Tests/Extension/Core/Type/TypeTestCase.php @@ -33,6 +33,14 @@ protected function setUp() $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->builder = new FormBuilder(null, null, $this->dispatcher, $this->factory); + + set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handle')); + + } + + protected function tearDown() + { + restore_error_handler(); } public static function assertDateTimeEquals(\DateTime $expected, \DateTime $actual) diff --git a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php index 65d649ab86..236b7c6462 100644 --- a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php +++ b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php @@ -11,9 +11,9 @@ namespace Symfony\Component\Form\Tests\Extension\Csrf\EventListener; -use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener; +use Symfony\Component\Form\Tests\DeprecationErrorHandler; class CsrfValidationListenerTest extends \PHPUnit_Framework_TestCase { @@ -67,7 +67,7 @@ protected function getMockForm() public function testStringFormData() { $data = "XP4HUzmHPi"; - $event = new FormEvent($this->form, $data); + $event = DeprecationErrorHandler::getFormEvent($this->form, $data); $validation = new CsrfValidationListener('csrf', $this->csrfProvider, 'unknown'); $validation->preBind($event); diff --git a/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php b/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php index bfb9afa0a7..197eb18252 100644 --- a/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php +++ b/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php @@ -14,9 +14,9 @@ use Symfony\Component\Form\Extension\HttpFoundation\EventListener\BindRequestListener; use Symfony\Component\Form\Form; use Symfony\Component\Form\FormConfigBuilder; -use Symfony\Component\Form\FormEvent; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\File\UploadedFile; +use Symfony\Component\Form\Tests\DeprecationErrorHandler; /** * @author Bernhard Schussek @@ -98,7 +98,7 @@ public function testBindRequest($method) $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('author', null, $dispatcher); $form = new Form($config); - $event = new FormEvent($form, $request); + $event = DeprecationErrorHandler::getFormEvent($form, $request); $listener = new BindRequestListener(); $listener->preBind($event); @@ -125,7 +125,7 @@ public function testBindRequestWithEmptyName($method) $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('', null, $dispatcher); $form = new Form($config); - $event = new FormEvent($form, $request); + $event = DeprecationErrorHandler::getFormEvent($form, $request); $listener = new BindRequestListener(); $listener->preBind($event); @@ -154,7 +154,7 @@ public function testBindEmptyRequestToCompoundForm($method) $config->setCompound(true); $config->setDataMapper($this->getMock('Symfony\Component\Form\DataMapperInterface')); $form = new Form($config); - $event = new FormEvent($form, $request); + $event = DeprecationErrorHandler::getFormEvent($form, $request); $listener = new BindRequestListener(); $listener->preBind($event); @@ -180,7 +180,7 @@ public function testBindEmptyRequestToSimpleForm($method) $config = new FormConfigBuilder('author', null, $dispatcher); $config->setCompound(false); $form = new Form($config); - $event = new FormEvent($form, $request); + $event = DeprecationErrorHandler::getFormEvent($form, $request); $listener = new BindRequestListener(); $listener->preBind($event); @@ -203,7 +203,7 @@ public function testBindGetRequest() $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('author', null, $dispatcher); $form = new Form($config); - $event = new FormEvent($form, $request); + $event = DeprecationErrorHandler::getFormEvent($form, $request); $listener = new BindRequestListener(); $listener->preBind($event); @@ -227,7 +227,7 @@ public function testBindGetRequestWithEmptyName() $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('', null, $dispatcher); $form = new Form($config); - $event = new FormEvent($form, $request); + $event = DeprecationErrorHandler::getFormEvent($form, $request); $listener = new BindRequestListener(); $listener->preBind($event); @@ -253,7 +253,7 @@ public function testBindEmptyGetRequestToCompoundForm() $config->setCompound(true); $config->setDataMapper($this->getMock('Symfony\Component\Form\DataMapperInterface')); $form = new Form($config); - $event = new FormEvent($form, $request); + $event = DeprecationErrorHandler::getFormEvent($form, $request); $listener = new BindRequestListener(); $listener->preBind($event); @@ -275,7 +275,7 @@ public function testBindEmptyGetRequestToSimpleForm() $config = new FormConfigBuilder('author', null, $dispatcher); $config->setCompound(false); $form = new Form($config); - $event = new FormEvent($form, $request); + $event = DeprecationErrorHandler::getFormEvent($form, $request); $listener = new BindRequestListener(); $listener->preBind($event); diff --git a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php index 69dd6fa9b2..956c841726 100644 --- a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php +++ b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\EventListener; -use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormError; @@ -19,6 +18,7 @@ use Symfony\Component\Form\Extension\Validator\Constraints\Form; use Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener; use Symfony\Component\Validator\ConstraintViolation; +use Symfony\Component\Form\Tests\DeprecationErrorHandler; class ValidationListenerTest extends \PHPUnit_Framework_TestCase { @@ -111,7 +111,7 @@ public function testMapViolation() ->method('mapViolation') ->with($violation, $form, false); - $this->listener->validateForm(new FormEvent($form, null)); + $this->listener->validateForm(DeprecationErrorHandler::getFormEvent($form, null)); } public function testMapViolationAllowsNonSyncIfInvalid() @@ -128,7 +128,7 @@ public function testMapViolationAllowsNonSyncIfInvalid() // pass true now ->with($violation, $form, true); - $this->listener->validateForm(new FormEvent($form, null)); + $this->listener->validateForm(DeprecationErrorHandler::getFormEvent($form, null)); } public function testValidateIgnoresNonRoot() @@ -144,6 +144,6 @@ public function testValidateIgnoresNonRoot() $this->violationMapper->expects($this->never()) ->method('mapViolation'); - $this->listener->validateForm(new FormEvent($form, null)); + $this->listener->validateForm(DeprecationErrorHandler::getFormEvent($form, null)); } } diff --git a/Tests/FormFactoryTest.php b/Tests/FormFactoryTest.php index 105e6b6663..fd20435310 100644 --- a/Tests/FormFactoryTest.php +++ b/Tests/FormFactoryTest.php @@ -85,7 +85,9 @@ public function testAddType() ->method('addType') ->with($resolvedType); + set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handle')); $this->factory->addType($type); + restore_error_handler(); } public function testHasType() @@ -95,7 +97,9 @@ public function testHasType() ->with('name') ->will($this->returnValue('RESULT')); + set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handle')); $this->assertSame('RESULT', $this->factory->hasType('name')); + restore_error_handler(); } public function testGetType() @@ -112,7 +116,9 @@ public function testGetType() ->with('name') ->will($this->returnValue($resolvedType)); + set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handle')); $this->assertEquals($type, $this->factory->getType('name')); + restore_error_handler(); } public function testCreateNamedBuilderWithTypeName() diff --git a/Tests/FormRegistryTest.php b/Tests/FormRegistryTest.php index a11a82a56d..e0d9aa7dee 100644 --- a/Tests/FormRegistryTest.php +++ b/Tests/FormRegistryTest.php @@ -76,7 +76,9 @@ public function testGetTypeReturnsAddedType() ->method('getName') ->will($this->returnValue('foo')); + set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handle')); $this->registry->addType($resolvedType); + restore_error_handler(); $this->assertSame($resolvedType, $this->registry->getType('foo')); } @@ -223,7 +225,9 @@ public function testHasTypeAfterAdding() $this->assertFalse($this->registry->hasType('foo')); + set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handle')); $this->registry->addType($resolvedType); + restore_error_handler(); $this->assertTrue($this->registry->hasType('foo')); } diff --git a/Tests/SimpleFormTest.php b/Tests/SimpleFormTest.php index 3a590b7509..0346740bf5 100644 --- a/Tests/SimpleFormTest.php +++ b/Tests/SimpleFormTest.php @@ -16,7 +16,6 @@ use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\Util\PropertyPath; use Symfony\Component\Form\FormConfigBuilder; -use Symfony\Component\Form\FormView; use Symfony\Component\Form\FormError; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\EventDispatcher\EventDispatcher; @@ -579,9 +578,11 @@ public function testBindValidatesAfterTransformation() { $test = $this; $validator = $this->getFormValidator(); + set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handle')); $form = $this->getBuilder() ->addValidator($validator) ->getForm(); + restore_error_handler(); $validator->expects($this->once()) ->method('validate') From 909553a7ff84b5786e1246724481b6a045af0d8d Mon Sep 17 00:00:00 2001 From: Colin Frei Date: Fri, 14 Dec 2012 07:33:36 +0100 Subject: [PATCH 024/447] [Form] handle BC use of deprecated stuff in non-test-methods. --- Form.php | 8 ++++++++ FormFactory.php | 2 ++ FormRegistry.php | 2 ++ 3 files changed, 12 insertions(+) diff --git a/Form.php b/Form.php index ed6cea4e00..4d363b3e3b 100644 --- a/Form.php +++ b/Form.php @@ -366,7 +366,9 @@ public function setData($modelData) // Hook to change content of the data if ($dispatcher->hasListeners(FormEvents::PRE_SET_DATA) || $dispatcher->hasListeners(FormEvents::SET_DATA)) { + set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handleBC')); $event = new FormEvent($this, $modelData); + restore_error_handler(); $dispatcher->dispatch(FormEvents::PRE_SET_DATA, $event); // BC until 2.3 $dispatcher->dispatch(FormEvents::SET_DATA, $event); @@ -529,7 +531,9 @@ public function bind($submittedData) // Hook to change content of the data bound by the browser if ($dispatcher->hasListeners(FormEvents::PRE_BIND) || $dispatcher->hasListeners(FormEvents::BIND_CLIENT_DATA)) { + set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handleBC')); $event = new FormEvent($this, $submittedData); + restore_error_handler(); $dispatcher->dispatch(FormEvents::PRE_BIND, $event); // BC until 2.3 $dispatcher->dispatch(FormEvents::BIND_CLIENT_DATA, $event); @@ -589,7 +593,9 @@ public function bind($submittedData) // Hook to change content of the data into the normalized // representation if ($dispatcher->hasListeners(FormEvents::BIND) || $dispatcher->hasListeners(FormEvents::BIND_NORM_DATA)) { + set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handleBC')); $event = new FormEvent($this, $normData); + restore_error_handler(); $dispatcher->dispatch(FormEvents::BIND, $event); // BC until 2.3 $dispatcher->dispatch(FormEvents::BIND_NORM_DATA, $event); @@ -613,9 +619,11 @@ public function bind($submittedData) $dispatcher->dispatch(FormEvents::POST_BIND, $event); } + set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handleBC')); foreach ($this->config->getValidators() as $validator) { $validator->validate($this); } + restore_error_handler(); return $this; } diff --git a/FormFactory.php b/FormFactory.php index ce60e7d42f..a5d8053724 100644 --- a/FormFactory.php +++ b/FormFactory.php @@ -99,7 +99,9 @@ public function createBuilderForProperty($class, $property, $data = null, array $typeGuess = $guesser->guessType($class, $property); $maxLengthGuess = $guesser->guessMaxLength($class, $property); // Keep $minLengthGuess for BC until Symfony 2.3 + set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handleBC')); $minLengthGuess = $guesser->guessMinLength($class, $property); + restore_error_handler(); $requiredGuess = $guesser->guessRequired($class, $property); $patternGuess = $guesser->guessPattern($class, $property); diff --git a/FormRegistry.php b/FormRegistry.php index 24df9a8053..39a3f6befe 100644 --- a/FormRegistry.php +++ b/FormRegistry.php @@ -131,11 +131,13 @@ private function resolveAndAddType(FormTypeInterface $type) ); } + set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handleBC')); $this->addType($this->resolvedTypeFactory->createResolvedType( $type, $typeExtensions, $parentType ? $this->getType($parentType) : null )); + restore_error_handler(); } /** From 727997d373859ddb71129cce5eca1112534d9ad4 Mon Sep 17 00:00:00 2001 From: rubenrua Date: Fri, 14 Dec 2012 19:44:04 +0100 Subject: [PATCH 025/447] Added Galician translation --- Resources/translations/validators.gl.xlf | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 Resources/translations/validators.gl.xlf diff --git a/Resources/translations/validators.gl.xlf b/Resources/translations/validators.gl.xlf new file mode 100644 index 0000000000..db23fe2be6 --- /dev/null +++ b/Resources/translations/validators.gl.xlf @@ -0,0 +1,19 @@ + + + + + + This form should not contain extra fields. + Este formulario non debería conter campos adicionais. + + + The uploaded file was too large. Please try to upload a smaller file. + O arquivo subido é demasiado grande. Por favor, suba un arquivo máis pequeno. + + + The CSRF token is invalid. Please try to resubmit the form. + O token CSRF non é válido. Por favor, probe a enviar novamente o formulario + + + + From 4d082c5510aa52f67be2b3b62c8fd0c94226e047 Mon Sep 17 00:00:00 2001 From: Pascal Borreli Date: Fri, 14 Dec 2012 22:07:21 +0000 Subject: [PATCH 026/447] [Form] Fixed duplicate case expression --- Extension/Validator/ValidatorTypeGuesser.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Extension/Validator/ValidatorTypeGuesser.php b/Extension/Validator/ValidatorTypeGuesser.php index 6aa2da1122..8c4cac9796 100755 --- a/Extension/Validator/ValidatorTypeGuesser.php +++ b/Extension/Validator/ValidatorTypeGuesser.php @@ -165,12 +165,6 @@ public function guessTypeForConstraint(Constraint $constraint) case 'Symfony\Component\Validator\Constraints\MaxCount': return new TypeGuess('collection', array(), Guess::LOW_CONFIDENCE); - case 'Symfony\Component\Validator\Constraints\Time': - return new TypeGuess('time', array('input'=>'string'), Guess::HIGH_CONFIDENCE); - - case 'Symfony\Component\Validator\Constraints\Url': - return new TypeGuess('url', array(), Guess::HIGH_CONFIDENCE); - case 'Symfony\Component\Validator\Constraints\True': case 'Symfony\Component\Validator\Constraints\False': return new TypeGuess('checkbox', array(), Guess::MEDIUM_CONFIDENCE); From 85bb1161bc3662be8df6ce807b84bb0e14d1eedd Mon Sep 17 00:00:00 2001 From: Colin Frei Date: Fri, 14 Dec 2012 23:16:06 +0100 Subject: [PATCH 027/447] [Form] [FrameworkBundle] catch deprecation errors in tests --- Tests/AbstractLayoutTest.php | 2 ++ Tests/Extension/Core/Type/TypeTestCase.php | 8 -------- Tests/FormIntegrationTestCase.php | 7 +++++++ 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index 527d73a7f5..2388ba6b67 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -45,6 +45,8 @@ protected function tearDown() { $this->csrfProvider = null; $this->factory = null; + + parent::tearDown(); } protected function assertXpathNodeValue(\DomElement $element, $expression, $nodeValue) diff --git a/Tests/Extension/Core/Type/TypeTestCase.php b/Tests/Extension/Core/Type/TypeTestCase.php index ca84b5dc22..9101e45308 100644 --- a/Tests/Extension/Core/Type/TypeTestCase.php +++ b/Tests/Extension/Core/Type/TypeTestCase.php @@ -33,14 +33,6 @@ protected function setUp() $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->builder = new FormBuilder(null, null, $this->dispatcher, $this->factory); - - set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handle')); - - } - - protected function tearDown() - { - restore_error_handler(); } public static function assertDateTimeEquals(\DateTime $expected, \DateTime $actual) diff --git a/Tests/FormIntegrationTestCase.php b/Tests/FormIntegrationTestCase.php index 536ff4c824..428265a18c 100644 --- a/Tests/FormIntegrationTestCase.php +++ b/Tests/FormIntegrationTestCase.php @@ -32,6 +32,13 @@ protected function setUp() $this->factory = Forms::createFormFactoryBuilder() ->addExtensions($this->getExtensions()) ->getFormFactory(); + + set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handle')); + } + + protected function tearDown() + { + restore_error_handler(); } protected function getExtensions() From 3aab0520934b97253a8297aa56501c975d9a1f27 Mon Sep 17 00:00:00 2001 From: Colin Frei Date: Fri, 14 Dec 2012 23:16:49 +0100 Subject: [PATCH 028/447] [Form] Catch deprecation errors that are caused by BC code --- AbstractType.php | 2 ++ AbstractTypeExtension.php | 2 ++ 2 files changed, 4 insertions(+) diff --git a/AbstractType.php b/AbstractType.php index ec45e824e0..11fec087df 100644 --- a/AbstractType.php +++ b/AbstractType.php @@ -51,8 +51,10 @@ public function finishView(FormView $view, FormInterface $form, array $options) */ public function setDefaultOptions(OptionsResolverInterface $resolver) { + set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handleBC')); $resolver->setDefaults($this->getDefaultOptions(array())); $resolver->addAllowedValues($this->getAllowedOptionValues(array())); + restore_error_handler(); } /** diff --git a/AbstractTypeExtension.php b/AbstractTypeExtension.php index c5dcfb94eb..629fb5527c 100644 --- a/AbstractTypeExtension.php +++ b/AbstractTypeExtension.php @@ -44,8 +44,10 @@ public function finishView(FormView $view, FormInterface $form, array $options) */ public function setDefaultOptions(OptionsResolverInterface $resolver) { + set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handleBC')); $resolver->setDefaults($this->getDefaultOptions()); $resolver->addAllowedValues($this->getAllowedOptionValues()); + restore_error_handler(); } /** From 134dbd7df87fb0061759d937d23e4b04832621f2 Mon Sep 17 00:00:00 2001 From: Colin Frei Date: Fri, 14 Dec 2012 23:17:14 +0100 Subject: [PATCH 029/447] [Form] Fix two cases where deprecated methods were being used --- Form.php | 2 +- Util/VirtualFormAwareIterator.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Form.php b/Form.php index 4d363b3e3b..5514fead5e 100644 --- a/Form.php +++ b/Form.php @@ -655,7 +655,7 @@ public function bindRequest(Request $request) */ public function addError(FormError $error) { - if ($this->parent && $this->getErrorBubbling()) { + if ($this->parent && $this->config->getErrorBubbling()) { $this->parent->addError($error); } else { $this->errors[] = $error; diff --git a/Util/VirtualFormAwareIterator.php b/Util/VirtualFormAwareIterator.php index b73654c1e2..c1322bb35d 100644 --- a/Util/VirtualFormAwareIterator.php +++ b/Util/VirtualFormAwareIterator.php @@ -23,7 +23,7 @@ class VirtualFormAwareIterator extends \ArrayIterator implements \RecursiveItera { public function getChildren() { - return new self($this->current()->getChildren()); + return new self($this->current()->all()); } public function hasChildren() From 06aa864eab7600b5d993eb7184bb73b74c519516 Mon Sep 17 00:00:00 2001 From: Tom Van Looy Date: Sat, 15 Dec 2012 21:50:02 +0100 Subject: [PATCH 030/447] Fix #6374 move FormBuilderInterface from Tests to Test --- {Tests => Test}/FormBuilderInterface.php | 2 +- Tests/FormFactoryTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename {Tests => Test}/FormBuilderInterface.php (89%) diff --git a/Tests/FormBuilderInterface.php b/Test/FormBuilderInterface.php similarity index 89% rename from Tests/FormBuilderInterface.php rename to Test/FormBuilderInterface.php index 76d1d62ea8..711cecd0b8 100644 --- a/Tests/FormBuilderInterface.php +++ b/Test/FormBuilderInterface.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Form\Tests; +namespace Symfony\Component\Form\Test; interface FormBuilderInterface extends \Iterator, \Symfony\Component\Form\FormBuilderInterface { diff --git a/Tests/FormFactoryTest.php b/Tests/FormFactoryTest.php index fd20435310..b6c1f5a7e3 100644 --- a/Tests/FormFactoryTest.php +++ b/Tests/FormFactoryTest.php @@ -638,6 +638,6 @@ private function getMockType() private function getMockFormBuilder() { - return $this->getMock('Symfony\Component\Form\Tests\FormBuilderInterface'); + return $this->getMock('Symfony\Component\Form\Test\FormBuilderInterface'); } } From b1cc7e269ce823513fa1c31ba59b676399000e12 Mon Sep 17 00:00:00 2001 From: Colin Frei Date: Sun, 16 Dec 2012 09:38:51 +0100 Subject: [PATCH 031/447] Move DeprecationErrorHandler to Test folder so it's not removed when building the zip file --- AbstractType.php | 2 +- AbstractTypeExtension.php | 2 +- Form.php | 8 ++++---- FormFactory.php | 2 +- FormRegistry.php | 2 +- {Tests => Test}/DeprecationErrorHandler.php | 4 ++-- Tests/CompoundFormTest.php | 6 +++--- .../Core/EventListener/FixRadioInputListenerTest.php | 2 +- .../Core/EventListener/FixUrlProtocolListenerTest.php | 2 +- .../Core/EventListener/MergeCollectionListenerTest.php | 2 +- .../Core/EventListener/ResizeFormListenerTest.php | 2 +- Tests/Extension/Core/EventListener/TrimListenerTest.php | 2 +- .../Csrf/EventListener/CsrfValidationListenerTest.php | 2 +- .../EventListener/BindRequestListenerTest.php | 2 +- .../Validator/EventListener/ValidationListenerTest.php | 2 +- Tests/FormFactoryTest.php | 6 +++--- Tests/FormIntegrationTestCase.php | 2 +- Tests/FormRegistryTest.php | 4 ++-- Tests/SimpleFormTest.php | 2 +- 19 files changed, 28 insertions(+), 28 deletions(-) rename {Tests => Test}/DeprecationErrorHandler.php (85%) diff --git a/AbstractType.php b/AbstractType.php index 11fec087df..00d374b7f7 100644 --- a/AbstractType.php +++ b/AbstractType.php @@ -51,7 +51,7 @@ public function finishView(FormView $view, FormInterface $form, array $options) */ public function setDefaultOptions(OptionsResolverInterface $resolver) { - set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handleBC')); + set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC')); $resolver->setDefaults($this->getDefaultOptions(array())); $resolver->addAllowedValues($this->getAllowedOptionValues(array())); restore_error_handler(); diff --git a/AbstractTypeExtension.php b/AbstractTypeExtension.php index 629fb5527c..38f4a8f1b6 100644 --- a/AbstractTypeExtension.php +++ b/AbstractTypeExtension.php @@ -44,7 +44,7 @@ public function finishView(FormView $view, FormInterface $form, array $options) */ public function setDefaultOptions(OptionsResolverInterface $resolver) { - set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handleBC')); + set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC')); $resolver->setDefaults($this->getDefaultOptions()); $resolver->addAllowedValues($this->getAllowedOptionValues()); restore_error_handler(); diff --git a/Form.php b/Form.php index 307db6798f..add1c6b8d3 100644 --- a/Form.php +++ b/Form.php @@ -366,7 +366,7 @@ public function setData($modelData) // Hook to change content of the data if ($dispatcher->hasListeners(FormEvents::PRE_SET_DATA) || $dispatcher->hasListeners(FormEvents::SET_DATA)) { - set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handleBC')); + set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC')); $event = new FormEvent($this, $modelData); restore_error_handler(); $dispatcher->dispatch(FormEvents::PRE_SET_DATA, $event); @@ -531,7 +531,7 @@ public function bind($submittedData) // Hook to change content of the data bound by the browser if ($dispatcher->hasListeners(FormEvents::PRE_BIND) || $dispatcher->hasListeners(FormEvents::BIND_CLIENT_DATA)) { - set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handleBC')); + set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC')); $event = new FormEvent($this, $submittedData); restore_error_handler(); $dispatcher->dispatch(FormEvents::PRE_BIND, $event); @@ -593,7 +593,7 @@ public function bind($submittedData) // Hook to change content of the data into the normalized // representation if ($dispatcher->hasListeners(FormEvents::BIND) || $dispatcher->hasListeners(FormEvents::BIND_NORM_DATA)) { - set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handleBC')); + set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC')); $event = new FormEvent($this, $normData); restore_error_handler(); $dispatcher->dispatch(FormEvents::BIND, $event); @@ -619,7 +619,7 @@ public function bind($submittedData) $dispatcher->dispatch(FormEvents::POST_BIND, $event); } - set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handleBC')); + set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC')); foreach ($this->config->getValidators() as $validator) { $validator->validate($this); } diff --git a/FormFactory.php b/FormFactory.php index a5d8053724..cf6c6c748f 100644 --- a/FormFactory.php +++ b/FormFactory.php @@ -99,7 +99,7 @@ public function createBuilderForProperty($class, $property, $data = null, array $typeGuess = $guesser->guessType($class, $property); $maxLengthGuess = $guesser->guessMaxLength($class, $property); // Keep $minLengthGuess for BC until Symfony 2.3 - set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handleBC')); + set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC')); $minLengthGuess = $guesser->guessMinLength($class, $property); restore_error_handler(); $requiredGuess = $guesser->guessRequired($class, $property); diff --git a/FormRegistry.php b/FormRegistry.php index 39a3f6befe..c45233c7aa 100644 --- a/FormRegistry.php +++ b/FormRegistry.php @@ -131,7 +131,7 @@ private function resolveAndAddType(FormTypeInterface $type) ); } - set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handleBC')); + set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC')); $this->addType($this->resolvedTypeFactory->createResolvedType( $type, $typeExtensions, diff --git a/Tests/DeprecationErrorHandler.php b/Test/DeprecationErrorHandler.php similarity index 85% rename from Tests/DeprecationErrorHandler.php rename to Test/DeprecationErrorHandler.php index 0a4c970e85..8c6dd90831 100644 --- a/Tests/DeprecationErrorHandler.php +++ b/Test/DeprecationErrorHandler.php @@ -1,6 +1,6 @@ form->add($this->getBuilder()->getForm()); - set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handle')); + set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); $this->assertTrue($this->form->hasChildren()); restore_error_handler(); } public function testHasNoChildren() { - set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handle')); + set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); $this->assertFalse($this->form->hasChildren()); restore_error_handler(); } @@ -155,7 +155,7 @@ public function testRemove() $this->form->remove('foo'); $this->assertNull($child->getParent()); - set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handle')); + set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); $this->assertFalse($this->form->hasChildren()); restore_error_handler(); } diff --git a/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php b/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php index aa404eb7b3..84af19cd4d 100644 --- a/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php +++ b/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php @@ -13,7 +13,7 @@ use Symfony\Component\Form\Extension\Core\EventListener\FixRadioInputListener; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; -use Symfony\Component\Form\Tests\DeprecationErrorHandler; +use Symfony\Component\Form\Test\DeprecationErrorHandler; class FixRadioInputListenerTest extends \PHPUnit_Framework_TestCase { diff --git a/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php b/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php index d8f68cb7da..14f75a28ba 100644 --- a/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php +++ b/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; use Symfony\Component\Form\Extension\Core\EventListener\FixUrlProtocolListener; -use Symfony\Component\Form\Tests\DeprecationErrorHandler; +use Symfony\Component\Form\Test\DeprecationErrorHandler; class FixUrlProtocolListenerTest extends \PHPUnit_Framework_TestCase { diff --git a/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php b/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php index 75ae84a6b7..11dfc43d73 100644 --- a/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php +++ b/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; use Symfony\Component\Form\Extension\Core\EventListener\MergeCollectionListener; -use Symfony\Component\Form\Tests\DeprecationErrorHandler; +use Symfony\Component\Form\Test\DeprecationErrorHandler; abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase { diff --git a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php index e271ad020a..c3cec1f1bc 100644 --- a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php +++ b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php @@ -13,7 +13,7 @@ use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener; use Symfony\Component\Form\FormBuilder; -use Symfony\Component\Form\Tests\DeprecationErrorHandler; +use Symfony\Component\Form\Test\DeprecationErrorHandler; class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase { diff --git a/Tests/Extension/Core/EventListener/TrimListenerTest.php b/Tests/Extension/Core/EventListener/TrimListenerTest.php index eb46f18e27..0acb8e4751 100644 --- a/Tests/Extension/Core/EventListener/TrimListenerTest.php +++ b/Tests/Extension/Core/EventListener/TrimListenerTest.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; use Symfony\Component\Form\Extension\Core\EventListener\TrimListener; -use Symfony\Component\Form\Tests\DeprecationErrorHandler; +use Symfony\Component\Form\Test\DeprecationErrorHandler; class TrimListenerTest extends \PHPUnit_Framework_TestCase { diff --git a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php index 236b7c6462..a93b3d2963 100644 --- a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php +++ b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php @@ -13,7 +13,7 @@ use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener; -use Symfony\Component\Form\Tests\DeprecationErrorHandler; +use Symfony\Component\Form\Test\DeprecationErrorHandler; class CsrfValidationListenerTest extends \PHPUnit_Framework_TestCase { diff --git a/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php b/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php index 197eb18252..94ae47a3c4 100644 --- a/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php +++ b/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php @@ -16,7 +16,7 @@ use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\File\UploadedFile; -use Symfony\Component\Form\Tests\DeprecationErrorHandler; +use Symfony\Component\Form\Test\DeprecationErrorHandler; /** * @author Bernhard Schussek diff --git a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php index 956c841726..323a3fbd80 100644 --- a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php +++ b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php @@ -18,7 +18,7 @@ use Symfony\Component\Form\Extension\Validator\Constraints\Form; use Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener; use Symfony\Component\Validator\ConstraintViolation; -use Symfony\Component\Form\Tests\DeprecationErrorHandler; +use Symfony\Component\Form\Test\DeprecationErrorHandler; class ValidationListenerTest extends \PHPUnit_Framework_TestCase { diff --git a/Tests/FormFactoryTest.php b/Tests/FormFactoryTest.php index b6c1f5a7e3..aa43310850 100644 --- a/Tests/FormFactoryTest.php +++ b/Tests/FormFactoryTest.php @@ -85,7 +85,7 @@ public function testAddType() ->method('addType') ->with($resolvedType); - set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handle')); + set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); $this->factory->addType($type); restore_error_handler(); } @@ -97,7 +97,7 @@ public function testHasType() ->with('name') ->will($this->returnValue('RESULT')); - set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handle')); + set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); $this->assertSame('RESULT', $this->factory->hasType('name')); restore_error_handler(); } @@ -116,7 +116,7 @@ public function testGetType() ->with('name') ->will($this->returnValue($resolvedType)); - set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handle')); + set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); $this->assertEquals($type, $this->factory->getType('name')); restore_error_handler(); } diff --git a/Tests/FormIntegrationTestCase.php b/Tests/FormIntegrationTestCase.php index 428265a18c..fad0616280 100644 --- a/Tests/FormIntegrationTestCase.php +++ b/Tests/FormIntegrationTestCase.php @@ -33,7 +33,7 @@ protected function setUp() ->addExtensions($this->getExtensions()) ->getFormFactory(); - set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handle')); + set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); } protected function tearDown() diff --git a/Tests/FormRegistryTest.php b/Tests/FormRegistryTest.php index e0d9aa7dee..43232938c6 100644 --- a/Tests/FormRegistryTest.php +++ b/Tests/FormRegistryTest.php @@ -76,7 +76,7 @@ public function testGetTypeReturnsAddedType() ->method('getName') ->will($this->returnValue('foo')); - set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handle')); + set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); $this->registry->addType($resolvedType); restore_error_handler(); @@ -225,7 +225,7 @@ public function testHasTypeAfterAdding() $this->assertFalse($this->registry->hasType('foo')); - set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handle')); + set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); $this->registry->addType($resolvedType); restore_error_handler(); diff --git a/Tests/SimpleFormTest.php b/Tests/SimpleFormTest.php index 0df934b135..f971a20991 100644 --- a/Tests/SimpleFormTest.php +++ b/Tests/SimpleFormTest.php @@ -644,7 +644,7 @@ public function testBindValidatesAfterTransformation() { $test = $this; $validator = $this->getFormValidator(); - set_error_handler(array('Symfony\Component\Form\Tests\DeprecationErrorHandler', 'handle')); + set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); $form = $this->getBuilder() ->addValidator($validator) ->getForm(); From 67143bb0d0a1671ab017ebe3f8522f79e0724af5 Mon Sep 17 00:00:00 2001 From: Pascal Helfenstein Date: Sun, 16 Dec 2012 14:02:47 +0100 Subject: [PATCH 032/447] [Form] empty_value should not be selectable in choice field if the field is required --- Tests/AbstractLayoutTest.php | 40 ++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index 5a457d1345..a7ff80e9de 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -524,7 +524,7 @@ public function testSingleChoiceWithNonRequiredEmptyValue() [@name="name"] [not(@required)] [ - ./option[@value=""][not(@selected)][.="[trans]Select&Anything&Not&Me[/trans]"] + ./option[@value=""][not(@selected)][@disabled][.="[trans]Select&Anything&Not&Me[/trans]"] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] @@ -548,7 +548,7 @@ public function testSingleChoiceRequiredWithEmptyValue() [@name="name"] [@required="required"] [ - ./option[@value=""][.="[trans]Test&Me[/trans]"] + ./option[@value=""][not(@selected)][@disabled][.="[trans]Test&Me[/trans]"] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] @@ -571,7 +571,7 @@ public function testSingleChoiceRequiredWithEmptyValueViaView() [@name="name"] [@required="required"] [ - ./option[@value=""][.="[trans][/trans]"] + ./option[@value=""][not(@selected)][@disabled][.="[trans][/trans]"] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] @@ -790,7 +790,7 @@ public function testCountryWithEmptyValue() $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] - [./option[@value=""][not(@selected)][.="[trans]Select&Country[/trans]"]] + [./option[@value=""][not(@selected)][@disabled][.="[trans]Select&Country[/trans]"]] [./option[@value="AT"][@selected="selected"][.="[trans]Austria[/trans]"]] [count(./option)>201] ' @@ -852,13 +852,13 @@ public function testDateTimeWithEmptyValueGlobal() [ ./select [@id="name_date_month"] - [./option[@value=""][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][@selected][@disabled][.="[trans]Change&Me[/trans]"]] /following-sibling::select [@id="name_date_day"] - [./option[@value=""][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][@selected][@disabled][.="[trans]Change&Me[/trans]"]] /following-sibling::select [@id="name_date_year"] - [./option[@value=""][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][@selected][@disabled][.="[trans]Change&Me[/trans]"]] ] /following-sibling::div [@id="name_time"] @@ -907,10 +907,10 @@ public function testDateTimeWithEmptyValueOnTime() [ ./select [@id="name_time_hour"] - [./option[@value=""][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][not(@selected)][@disabled][.="[trans]Change&Me[/trans]"]] /following-sibling::select [@id="name_time_minute"] - [./option[@value=""][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][not(@selected)][@disabled][.="[trans]Change&Me[/trans]"]] ] ] [count(.//select)=5] @@ -1063,13 +1063,13 @@ public function testDateChoiceWithEmptyValueGlobal() [ ./select [@id="name_month"] - [./option[@value=""][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][@selected][@disabled][.="[trans]Change&Me[/trans]"]] /following-sibling::select [@id="name_day"] - [./option[@value=""][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][@selected][@disabled][.="[trans]Change&Me[/trans]"]] /following-sibling::select [@id="name_year"] - [./option[@value=""][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][@selected][@disabled][.="[trans]Change&Me[/trans]"]] ] [count(./select)=3] ' @@ -1096,7 +1096,7 @@ public function testDateChoiceWithEmptyValueOnYear() [./option[@value="1"]] /following-sibling::select [@id="name_year"] - [./option[@value=""][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][@selected][@disabled][.="[trans]Change&Me[/trans]"]] ] [count(./select)=3] ' @@ -1195,15 +1195,15 @@ public function testBirthDayWithEmptyValue() [ ./select [@id="name_month"] - [./option[@value=""][.="[trans][/trans]"]] + [./option[@value=""][not(@selected)][@disabled][.="[trans][/trans]"]] [./option[@value="1"][@selected="selected"]] /following-sibling::select [@id="name_day"] - [./option[@value=""][.="[trans][/trans]"]] + [./option[@value=""][not(@selected)][@disabled][.="[trans][/trans]"]] [./option[@value="1"][@selected="selected"]] /following-sibling::select [@id="name_year"] - [./option[@value=""][.="[trans][/trans]"]] + [./option[@value=""][not(@selected)][@disabled][.="[trans][/trans]"]] [./option[@value="1950"][@selected="selected"]] ] [count(./select)=3] @@ -1635,11 +1635,11 @@ public function testTimeWithEmptyValueGlobal() [ ./select [@id="name_hour"] - [./option[@value=""][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][@selected][@disabled][.="[trans]Change&Me[/trans]"]] [count(./option)>24] /following-sibling::select [@id="name_minute"] - [./option[@value=""][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][@selected][@disabled][.="[trans]Change&Me[/trans]"]] [count(./option)>60] ] [count(./select)=2] @@ -1660,7 +1660,7 @@ public function testTimeWithEmptyValueOnYear() [ ./select [@id="name_hour"] - [./option[@value=""][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][@selected][@disabled][.="[trans]Change&Me[/trans]"]] [count(./option)>24] /following-sibling::select [@id="name_minute"] @@ -1710,7 +1710,7 @@ public function testTimezoneWithEmptyValue() $this->assertWidgetMatchesXpath($form->createView(), array(), '/select - [./option[@value=""][.="[trans]Select&Timezone[/trans]"]] + [./option[@value=""][@selected][@disabled][.="[trans]Select&Timezone[/trans]"]] [count(./optgroup)>10] [count(.//option)>201] ' From 54c10093a914b15ab2d0ac75394c2e0a3f26b7b7 Mon Sep 17 00:00:00 2001 From: Tom Van Looy Date: Mon, 17 Dec 2012 09:01:30 +0100 Subject: [PATCH 033/447] Move FormInterface too --- {Tests => Test}/FormInterface.php | 2 +- Tests/AbstractFormTest.php | 2 +- .../Core/EventListener/FixRadioInputListenerTest.php | 6 +++--- .../Core/EventListener/FixUrlProtocolListenerTest.php | 6 +++--- .../Core/EventListener/MergeCollectionListenerTest.php | 2 +- .../Extension/Core/EventListener/ResizeFormListenerTest.php | 2 +- Tests/Extension/Core/EventListener/TrimListenerTest.php | 6 +++--- .../Csrf/EventListener/CsrfValidationListenerTest.php | 2 +- .../Validator/EventListener/ValidationListenerTest.php | 2 +- Tests/SimpleFormTest.php | 2 +- 10 files changed, 16 insertions(+), 16 deletions(-) rename {Tests => Test}/FormInterface.php (89%) diff --git a/Tests/FormInterface.php b/Test/FormInterface.php similarity index 89% rename from Tests/FormInterface.php rename to Test/FormInterface.php index 5c27c6ead4..22a83fd76f 100644 --- a/Tests/FormInterface.php +++ b/Test/FormInterface.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Form\Tests; +namespace Symfony\Component\Form\Test; interface FormInterface extends \Iterator, \Symfony\Component\Form\FormInterface { diff --git a/Tests/AbstractFormTest.php b/Tests/AbstractFormTest.php index 4581ad9d72..5e13863aa9 100644 --- a/Tests/AbstractFormTest.php +++ b/Tests/AbstractFormTest.php @@ -76,7 +76,7 @@ protected function getBuilder($name = 'name', EventDispatcherInterface $dispatch */ protected function getMockForm($name = 'name') { - $form = $this->getMock('Symfony\Component\Form\Tests\FormInterface'); + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $form->expects($this->any()) ->method('getName') diff --git a/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php b/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php index 84af19cd4d..5a7f5e7d17 100644 --- a/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php +++ b/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php @@ -41,7 +41,7 @@ protected function tearDown() public function testFixRadio() { $data = '1'; - $form = $this->getMock('Symfony\Component\Form\Tests\FormInterface'); + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = DeprecationErrorHandler::getFormEvent($form, $data); $this->listener->preBind($event); @@ -52,7 +52,7 @@ public function testFixRadio() public function testFixZero() { $data = '0'; - $form = $this->getMock('Symfony\Component\Form\Tests\FormInterface'); + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = DeprecationErrorHandler::getFormEvent($form, $data); $this->listener->preBind($event); @@ -63,7 +63,7 @@ public function testFixZero() public function testIgnoreEmptyString() { $data = ''; - $form = $this->getMock('Symfony\Component\Form\Tests\FormInterface'); + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = DeprecationErrorHandler::getFormEvent($form, $data); $this->listener->preBind($event); diff --git a/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php b/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php index 14f75a28ba..70db9b421e 100644 --- a/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php +++ b/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php @@ -26,7 +26,7 @@ protected function setUp() public function testFixHttpUrl() { $data = "www.symfony.com"; - $form = $this->getMock('Symfony\Component\Form\Tests\FormInterface'); + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = DeprecationErrorHandler::getFormEvent($form, $data); $filter = new FixUrlProtocolListener('http'); @@ -38,7 +38,7 @@ public function testFixHttpUrl() public function testSkipKnownUrl() { $data = "http://www.symfony.com"; - $form = $this->getMock('Symfony\Component\Form\Tests\FormInterface'); + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = DeprecationErrorHandler::getFormEvent($form, $data); $filter = new FixUrlProtocolListener('http'); @@ -50,7 +50,7 @@ public function testSkipKnownUrl() public function testSkipOtherProtocol() { $data = "ftp://www.symfony.com"; - $form = $this->getMock('Symfony\Component\Form\Tests\FormInterface'); + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = DeprecationErrorHandler::getFormEvent($form, $data); $filter = new FixUrlProtocolListener('http'); diff --git a/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php b/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php index 11dfc43d73..8e0ccad7b1 100644 --- a/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php +++ b/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php @@ -49,7 +49,7 @@ protected function getForm($name = 'name', $propertyPath = null) protected function getMockForm() { - return $this->getMock('Symfony\Component\Form\Tests\FormInterface'); + return $this->getMock('Symfony\Component\Form\Test\FormInterface'); } public function getBooleanMatrix1() diff --git a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php index c3cec1f1bc..ad1e6a577d 100644 --- a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php +++ b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php @@ -62,7 +62,7 @@ private function getDataMapper() protected function getMockForm() { - return $this->getMock('Symfony\Component\Form\Tests\FormInterface'); + return $this->getMock('Symfony\Component\Form\Test\FormInterface'); } public function testPreSetDataResizesForm() diff --git a/Tests/Extension/Core/EventListener/TrimListenerTest.php b/Tests/Extension/Core/EventListener/TrimListenerTest.php index 0acb8e4751..49419065d2 100644 --- a/Tests/Extension/Core/EventListener/TrimListenerTest.php +++ b/Tests/Extension/Core/EventListener/TrimListenerTest.php @@ -26,7 +26,7 @@ protected function setUp() public function testTrim() { $data = " Foo! "; - $form = $this->getMock('Symfony\Component\Form\Tests\FormInterface'); + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = DeprecationErrorHandler::getFormEvent($form, $data); $filter = new TrimListener(); @@ -38,7 +38,7 @@ public function testTrim() public function testTrimSkipNonStrings() { $data = 1234; - $form = $this->getMock('Symfony\Component\Form\Tests\FormInterface'); + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = DeprecationErrorHandler::getFormEvent($form, $data); $filter = new TrimListener(); @@ -59,7 +59,7 @@ public function testTrimUtf8($chars) $data = mb_convert_encoding(pack('H*', implode('', $chars)), 'UTF-8', 'UCS-2BE'); $data = $data."ab\ncd".$data; - $form = $this->getMock('Symfony\Component\Form\Tests\FormInterface'); + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = DeprecationErrorHandler::getFormEvent($form, $data); $filter = new TrimListener(); diff --git a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php index a93b3d2963..49c40d3b05 100644 --- a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php +++ b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php @@ -60,7 +60,7 @@ protected function getDataMapper() protected function getMockForm() { - return $this->getMock('Symfony\Component\Form\Tests\FormInterface'); + return $this->getMock('Symfony\Component\Form\Test\FormInterface'); } // https://github.com/symfony/symfony/pull/5838 diff --git a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php index 323a3fbd80..7e358910e2 100644 --- a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php +++ b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php @@ -94,7 +94,7 @@ private function getForm($name = 'name', $propertyPath = null, $dataClass = null private function getMockForm() { - return $this->getMock('Symfony\Component\Form\Tests\FormInterface'); + return $this->getMock('Symfony\Component\Form\Test\FormInterface'); } // More specific mapping tests can be found in ViolationMapperTest diff --git a/Tests/SimpleFormTest.php b/Tests/SimpleFormTest.php index f971a20991..6d13d4a568 100644 --- a/Tests/SimpleFormTest.php +++ b/Tests/SimpleFormTest.php @@ -686,7 +686,7 @@ public function testCreateViewWithParent() { $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); $view = $this->getMock('Symfony\Component\Form\FormView'); - $parentForm = $this->getMock('Symfony\Component\Form\Tests\FormInterface'); + $parentForm = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $parentView = $this->getMock('Symfony\Component\Form\FormView'); $form = $this->getBuilder()->setType($type)->getForm(); $form->setParent($parentForm); From 3eaf047c58a65a432a6fbd70fb1bd8760aad918e Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 14 Dec 2012 16:05:05 +0100 Subject: [PATCH 034/447] [Form] Added an alternative signature Form::add($name, $type, $options) --- CHANGELOG.md | 2 + .../Core/EventListener/ResizeFormListener.php | 17 ++--- Extension/Core/Type/CollectionType.php | 1 - Form.php | 19 +++++- FormBuilder.php | 21 +----- FormBuilderInterface.php | 23 +++++-- FormConfigBuilder.php | 27 ++++++++ FormConfigBuilderInterface.php | 7 ++ FormConfigInterface.php | 7 ++ FormInterface.php | 11 ++-- Tests/CompoundFormTest.php | 65 ++++++++++++++++++- .../EventListener/ResizeFormListenerTest.php | 34 +++++----- 12 files changed, 171 insertions(+), 63 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bdbb2b3546..3f26b8169c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ CHANGELOG ----- * TrimListener now removes unicode whitespaces + * deprecated getParent(), setParent() and hasParent() in FormBuilderInterface + * FormInterface::add() now accepts a FormInterface instance OR a field's name, type and options 2.1.0 ----- diff --git a/Extension/Core/EventListener/ResizeFormListener.php b/Extension/Core/EventListener/ResizeFormListener.php index 7c34a99161..a3719f56f4 100644 --- a/Extension/Core/EventListener/ResizeFormListener.php +++ b/Extension/Core/EventListener/ResizeFormListener.php @@ -13,7 +13,6 @@ use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; -use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -24,11 +23,6 @@ */ class ResizeFormListener implements EventSubscriberInterface { - /** - * @var FormFactoryInterface - */ - protected $factory; - /** * @var string */ @@ -51,9 +45,8 @@ class ResizeFormListener implements EventSubscriberInterface */ protected $allowDelete; - public function __construct(FormFactoryInterface $factory, $type, array $options = array(), $allowAdd = false, $allowDelete = false) + public function __construct($type, array $options = array(), $allowAdd = false, $allowDelete = false) { - $this->factory = $factory; $this->type = $type; $this->allowAdd = $allowAdd; $this->allowDelete = $allowDelete; @@ -90,9 +83,9 @@ public function preSetData(FormEvent $event) // Then add all rows again in the correct order foreach ($data as $name => $value) { - $form->add($this->factory->createNamed($name, $this->type, null, array_replace(array( + $form->add((string) $name, $this->type, array_replace(array( 'property_path' => '['.$name.']', - ), $this->options))); + ), $this->options)); } } @@ -122,9 +115,9 @@ public function preBind(FormEvent $event) if ($this->allowAdd) { foreach ($data as $name => $value) { if (!$form->has($name)) { - $form->add($this->factory->createNamed($name, $this->type, null, array_replace(array( + $form->add((string) $name, $this->type, array_replace(array( 'property_path' => '['.$name.']', - ), $this->options))); + ), $this->options)); } } } diff --git a/Extension/Core/Type/CollectionType.php b/Extension/Core/Type/CollectionType.php index 353a89bc4b..3ff36b9727 100644 --- a/Extension/Core/Type/CollectionType.php +++ b/Extension/Core/Type/CollectionType.php @@ -34,7 +34,6 @@ public function buildForm(FormBuilderInterface $builder, array $options) } $resizeListener = new ResizeFormListener( - $builder->getFormFactory(), $options['type'], $options['options'], $options['allow_add'], diff --git a/Form.php b/Form.php index 307db6798f..af01ebc06d 100644 --- a/Form.php +++ b/Form.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\FormException; +use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Exception\AlreadyBoundException; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Util\FormUtil; @@ -859,7 +860,7 @@ public function hasChildren() /** * {@inheritdoc} */ - public function add(FormInterface $child) + public function add($child, $type = null, array $options = array()) { if ($this->bound) { throw new AlreadyBoundException('You cannot add children to a bound form'); @@ -888,6 +889,22 @@ public function add(FormInterface $child) $viewData = $this->getViewData(); } + if (!$child instanceof FormInterface) { + if (!is_string($child)) { + throw new UnexpectedTypeException($child, 'string or Symfony\Component\Form\FormInterface'); + } + + if (null !== $type && !is_string($type) && !$type instanceof FormTypeInterface) { + throw new UnexpectedTypeException($type, 'string or Symfony\Component\Form\FormTypeInterface'); + } + + if (null === $type) { + $child = $this->config->getFormFactory()->createForProperty($this->config->getDataClass(), $child, null, $options); + } else { + $child = $this->config->getFormFactory()->createNamed($child, $type, null, $options); + } + } + $this->children[$child->getName()] = $child; $child->setParent($this); diff --git a/FormBuilder.php b/FormBuilder.php index 86e5587eff..e49bf6250d 100644 --- a/FormBuilder.php +++ b/FormBuilder.php @@ -22,13 +22,6 @@ */ class FormBuilder extends FormConfigBuilder implements \IteratorAggregate, FormBuilderInterface { - /** - * The form factory. - * - * @var FormFactoryInterface - */ - private $factory; - /** * The children of the form builder. * @@ -63,15 +56,7 @@ public function __construct($name, $dataClass, EventDispatcherInterface $dispatc { parent::__construct($name, $dataClass, $dispatcher, $options); - $this->factory = $factory; - } - - /** - * {@inheritdoc} - */ - public function getFormFactory() - { - return $this->factory; + $this->setFormFactory($factory); } /** @@ -125,10 +110,10 @@ public function create($name, $type = null, array $options = array()) } if (null !== $type) { - return $this->factory->createNamedBuilder($name, $type, null, $options, $this); + return $this->getFormFactory()->createNamedBuilder($name, $type, null, $options, $this); } - return $this->factory->createBuilderForProperty($this->getDataClass(), $name, null, $options, $this); + return $this->getFormFactory()->createBuilderForProperty($this->getDataClass(), $name, null, $options, $this); } /** diff --git a/FormBuilderInterface.php b/FormBuilderInterface.php index 034a65a5a2..d2a29fc821 100644 --- a/FormBuilderInterface.php +++ b/FormBuilderInterface.php @@ -52,6 +52,7 @@ public function create($name, $type = null, array $options = array()); * @throws Exception\FormException if the given child does not exist */ public function get($name); + /** * Removes the field with the given name. * @@ -77,13 +78,6 @@ public function has($name); */ public function all(); - /** - * Returns the associated form factory. - * - * @return FormFactoryInterface The factory - */ - public function getFormFactory(); - /** * Creates the form. * @@ -97,6 +91,11 @@ public function getForm(); * @param FormBuilderInterface $parent The parent builder * * @return FormBuilderInterface The builder object. + * + * @deprecated Deprecated since version 2.2, to be removed in 2.3. You + * should not rely on the parent of a builder, because it is + * likely that the parent is only set after turning the builder + * into a form. */ public function setParent(FormBuilderInterface $parent = null); @@ -104,6 +103,11 @@ public function setParent(FormBuilderInterface $parent = null); * Returns the parent builder. * * @return FormBuilderInterface The parent builder + * + * @deprecated Deprecated since version 2.2, to be removed in 2.3. You + * should not rely on the parent of a builder, because it is + * likely that the parent is only set after turning the builder + * into a form. */ public function getParent(); @@ -111,6 +115,11 @@ public function getParent(); * Returns whether the builder has a parent. * * @return Boolean + * + * @deprecated Deprecated since version 2.2, to be removed in 2.3. You + * should not rely on the parent of a builder, because it is + * likely that the parent is only set after turning the builder + * into a form. */ public function hasParent(); } diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index 529fb89179..51077298a6 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -131,6 +131,11 @@ class FormConfigBuilder implements FormConfigBuilderInterface */ private $dataLocked; + /** + * @var FormFactoryInterface + */ + private $formFactory; + /** * @var array */ @@ -611,6 +616,14 @@ public function getDataLocked() return $this->dataLocked; } + /** + * {@inheritdoc} + */ + public function getFormFactory() + { + return $this->formFactory; + } + /** * {@inheritdoc} */ @@ -849,6 +862,20 @@ public function setDataLocked($locked) return $this; } + /** + * {@inheritdoc} + */ + public function setFormFactory(FormFactoryInterface $formFactory) + { + if ($this->locked) { + throw new FormException('The config builder cannot be modified anymore.'); + } + + $this->formFactory = $formFactory; + + return $this; + } + /** * {@inheritdoc} */ diff --git a/FormConfigBuilderInterface.php b/FormConfigBuilderInterface.php index 35eff8790b..496fc38c66 100644 --- a/FormConfigBuilderInterface.php +++ b/FormConfigBuilderInterface.php @@ -241,6 +241,13 @@ public function setData($data); */ public function setDataLocked($locked); + /** + * Sets the form factory used for creating new forms. + * + * @param FormFactoryInterface $formFactory The form factory. + */ + public function setFormFactory(FormFactoryInterface $formFactory); + /** * Builds and returns the form configuration. * diff --git a/FormConfigInterface.php b/FormConfigInterface.php index 5710f6e2ad..b5d914f6d3 100644 --- a/FormConfigInterface.php +++ b/FormConfigInterface.php @@ -192,6 +192,13 @@ public function getDataClass(); */ public function getDataLocked(); + /** + * Returns the form factory used for creating new forms. + * + * @return FormFactoryInterface The form factory. + */ + public function getFormFactory(); + /** * Returns all options passed during the construction of the form. * diff --git a/FormInterface.php b/FormInterface.php index 63ac2e2eb0..b42e42dab9 100644 --- a/FormInterface.php +++ b/FormInterface.php @@ -41,14 +41,17 @@ public function getParent(); /** * Adds a child to the form. * - * @param FormInterface $child The FormInterface to add as a child + * @param FormInterface|string $child The FormInterface instance or the name of the child. + * @param string|null $type The child's type, if a name was passed. + * @param array $options The child's options, if a name was passed. * * @return FormInterface The form instance * - * @throws Exception\AlreadyBoundException If the form has already been bound. - * @throws Exception\FormException When trying to add a child to a non-compound form. + * @throws Exception\AlreadyBoundException If the form has already been bound. + * @throws Exception\FormException When trying to add a child to a non-compound form. + * @throws Exception\UnexpectedTypeException If $child or $type has an unexpected type. */ - public function add(FormInterface $child); + public function add($child, $type = null, array $options = array()); /** * Returns the child with the given name. diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index 05483f6496..f40fa2b6d7 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -33,7 +33,7 @@ public function testValidIfAllChildrenAreValid() $this->assertTrue($this->form->isValid()); } - public function testInvalidIfChildrenIsInvalid() + public function testInvalidIfChildIsInvalid() { $this->form->add($this->getValidForm('firstName')); $this->form->add($this->getInvalidForm('lastName')); @@ -135,12 +135,71 @@ public function testAdd() $child = $this->getBuilder('foo')->getForm(); $this->form->add($child); + $this->assertTrue($this->form->has('foo')); + $this->assertSame($this->form, $child->getParent()); + $this->assertSame(array('foo' => $child), $this->form->all()); + } + + public function testAddUsingNameAndType() + { + $child = $this->getBuilder('foo')->getForm(); + + $this->factory->expects($this->once()) + ->method('createNamed') + ->with('foo', 'text', null, array('bar' => 'baz')) + ->will($this->returnValue($child)); + + $this->form->add('foo', 'text', array('bar' => 'baz')); + + $this->assertTrue($this->form->has('foo')); + $this->assertSame($this->form, $child->getParent()); + $this->assertSame(array('foo' => $child), $this->form->all()); + } + + public function testAddUsingNameButNoType() + { + $this->form = $this->getBuilder('name', null, '\stdClass') + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + + $child = $this->getBuilder('foo')->getForm(); + + $this->factory->expects($this->once()) + ->method('createForProperty') + ->with('\stdClass', 'foo') + ->will($this->returnValue($child)); + + $this->form->add('foo'); + + $this->assertTrue($this->form->has('foo')); + $this->assertSame($this->form, $child->getParent()); + $this->assertSame(array('foo' => $child), $this->form->all()); + } + + public function testAddUsingNameButNoTypeAndOptions() + { + $this->form = $this->getBuilder('name', null, '\stdClass') + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + + $child = $this->getBuilder('foo')->getForm(); + + $this->factory->expects($this->once()) + ->method('createForProperty') + ->with('\stdClass', 'foo', null, array('bar' => 'baz')) + ->will($this->returnValue($child)); + + $this->form->add('foo', null, array('bar' => 'baz')); + + $this->assertTrue($this->form->has('foo')); $this->assertSame($this->form, $child->getParent()); $this->assertSame(array('foo' => $child), $this->form->all()); } /** - * @expectedException Symfony\Component\Form\Exception\AlreadyBoundException + * @expectedException \Symfony\Component\Form\Exception\AlreadyBoundException */ public function testAddThrowsExceptionIfAlreadyBound() { @@ -161,7 +220,7 @@ public function testRemove() } /** - * @expectedException Symfony\Component\Form\Exception\AlreadyBoundException + * @expectedException \Symfony\Component\Form\Exception\AlreadyBoundException */ public function testRemoveThrowsExceptionIfAlreadyBound() { diff --git a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php index e271ad020a..201882e888 100644 --- a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php +++ b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php @@ -81,7 +81,7 @@ public function testPreSetDataResizesForm() $data = array(1 => 'string', 2 => 'string'); $event = DeprecationErrorHandler::getFormEvent($this->form, $data); - $listener = new ResizeFormListener($this->factory, 'text', array('max_length' => '10'), false, false); + $listener = new ResizeFormListener('text', array('max_length' => '10'), false, false); $listener->preSetData($event); $this->assertFalse($this->form->has('0')); @@ -90,13 +90,13 @@ public function testPreSetDataResizesForm() } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testPreSetDataRequiresArrayOrTraversable() { $data = 'no array or traversable'; $event = DeprecationErrorHandler::getFormEvent($this->form, $data); - $listener = new ResizeFormListener($this->factory, 'text', array(), false, false); + $listener = new ResizeFormListener('text', array(), false, false); $listener->preSetData($event); } @@ -106,7 +106,7 @@ public function testPreSetDataDealsWithNullData() $data = null; $event = DeprecationErrorHandler::getFormEvent($this->form, $data); - $listener = new ResizeFormListener($this->factory, 'text', array(), false, false); + $listener = new ResizeFormListener('text', array(), false, false); $listener->preSetData($event); } @@ -121,7 +121,7 @@ public function testPreBindResizesUpIfAllowAdd() $data = array(0 => 'string', 1 => 'string'); $event = DeprecationErrorHandler::getFormEvent($this->form, $data); - $listener = new ResizeFormListener($this->factory, 'text', array('max_length' => 10), true, false); + $listener = new ResizeFormListener('text', array('max_length' => 10), true, false); $listener->preBind($event); $this->assertTrue($this->form->has('0')); @@ -135,7 +135,7 @@ public function testPreBindResizesDownIfAllowDelete() $data = array(0 => 'string'); $event = DeprecationErrorHandler::getFormEvent($this->form, $data); - $listener = new ResizeFormListener($this->factory, 'text', array(), false, true); + $listener = new ResizeFormListener('text', array(), false, true); $listener->preBind($event); $this->assertTrue($this->form->has('0')); @@ -149,7 +149,7 @@ public function testPreBindRemovesZeroKeys() $data = array(); $event = DeprecationErrorHandler::getFormEvent($this->form, $data); - $listener = new ResizeFormListener($this->factory, 'text', array(), false, true); + $listener = new ResizeFormListener('text', array(), false, true); $listener->preBind($event); $this->assertFalse($this->form->has('0')); @@ -162,7 +162,7 @@ public function testPreBindDoesNothingIfNotAllowAddNorAllowDelete() $data = array(0 => 'string', 2 => 'string'); $event = DeprecationErrorHandler::getFormEvent($this->form, $data); - $listener = new ResizeFormListener($this->factory, 'text', array(), false, false); + $listener = new ResizeFormListener('text', array(), false, false); $listener->preBind($event); $this->assertTrue($this->form->has('0')); @@ -171,13 +171,13 @@ public function testPreBindDoesNothingIfNotAllowAddNorAllowDelete() } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testPreBindRequiresArrayOrTraversable() { $data = 'no array or traversable'; $event = DeprecationErrorHandler::getFormEvent($this->form, $data); - $listener = new ResizeFormListener($this->factory, 'text', array(), false, false); + $listener = new ResizeFormListener('text', array(), false, false); $listener->preBind($event); } @@ -187,7 +187,7 @@ public function testPreBindDealsWithNullData() $data = null; $event = DeprecationErrorHandler::getFormEvent($this->form, $data); - $listener = new ResizeFormListener($this->factory, 'text', array(), false, true); + $listener = new ResizeFormListener('text', array(), false, true); $listener->preBind($event); $this->assertFalse($this->form->has('1')); @@ -200,7 +200,7 @@ public function testPreBindDealsWithEmptyData() $data = ''; $event = DeprecationErrorHandler::getFormEvent($this->form, $data); - $listener = new ResizeFormListener($this->factory, 'text', array(), false, true); + $listener = new ResizeFormListener('text', array(), false, true); $listener->preBind($event); $this->assertFalse($this->form->has('1')); @@ -212,7 +212,7 @@ public function testOnBindNormDataRemovesEntriesMissingInTheFormIfAllowDelete() $data = array(0 => 'first', 1 => 'second', 2 => 'third'); $event = DeprecationErrorHandler::getFormEvent($this->form, $data); - $listener = new ResizeFormListener($this->factory, 'text', array(), false, true); + $listener = new ResizeFormListener('text', array(), false, true); $listener->onBind($event); $this->assertEquals(array(1 => 'second'), $event->getData()); @@ -224,20 +224,20 @@ public function testOnBindNormDataDoesNothingIfNotAllowDelete() $data = array(0 => 'first', 1 => 'second', 2 => 'third'); $event = DeprecationErrorHandler::getFormEvent($this->form, $data); - $listener = new ResizeFormListener($this->factory, 'text', array(), false, false); + $listener = new ResizeFormListener('text', array(), false, false); $listener->onBind($event); $this->assertEquals($data, $event->getData()); } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testOnBindNormDataRequiresArrayOrTraversable() { $data = 'no array or traversable'; $event = DeprecationErrorHandler::getFormEvent($this->form, $data); - $listener = new ResizeFormListener($this->factory, 'text', array(), false, false); + $listener = new ResizeFormListener('text', array(), false, false); $listener->onBind($event); } @@ -247,7 +247,7 @@ public function testOnBindNormDataDealsWithNullData() $data = null; $event = DeprecationErrorHandler::getFormEvent($this->form, $data); - $listener = new ResizeFormListener($this->factory, 'text', array(), false, true); + $listener = new ResizeFormListener('text', array(), false, true); $listener->onBind($event); $this->assertEquals(array(), $event->getData()); From 3dc7204b3604d72dcdd2c5c854dd0b195612a476 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 14 Dec 2012 19:27:28 +0100 Subject: [PATCH 035/447] [Form] Improved Form::add() and FormBuilder::add() to accept integers as field names --- .../Core/EventListener/ResizeFormListener.php | 4 ++-- Extension/Core/Type/ChoiceType.php | 2 +- Form.php | 4 ++-- FormBuilder.php | 4 ++-- FormBuilderInterface.php | 6 +++--- FormConfigBuilder.php | 16 +++++++--------- FormFactoryInterface.php | 4 ++-- FormInterface.php | 6 +++--- Tests/CompoundFormTest.php | 17 +++++++++++++++++ Tests/FormBuilderTest.php | 11 +++++++++-- Tests/FormConfigTest.php | 19 +++++++++++++++++-- 11 files changed, 65 insertions(+), 28 deletions(-) diff --git a/Extension/Core/EventListener/ResizeFormListener.php b/Extension/Core/EventListener/ResizeFormListener.php index a3719f56f4..12d1cba505 100644 --- a/Extension/Core/EventListener/ResizeFormListener.php +++ b/Extension/Core/EventListener/ResizeFormListener.php @@ -83,7 +83,7 @@ public function preSetData(FormEvent $event) // Then add all rows again in the correct order foreach ($data as $name => $value) { - $form->add((string) $name, $this->type, array_replace(array( + $form->add($name, $this->type, array_replace(array( 'property_path' => '['.$name.']', ), $this->options)); } @@ -115,7 +115,7 @@ public function preBind(FormEvent $event) if ($this->allowAdd) { foreach ($data as $name => $value) { if (!$form->has($name)) { - $form->add((string) $name, $this->type, array_replace(array( + $form->add($name, $this->type, array_replace(array( 'property_path' => '['.$name.']', ), $this->options)); } diff --git a/Extension/Core/Type/ChoiceType.php b/Extension/Core/Type/ChoiceType.php index 356cc2322c..a33a01b9cb 100644 --- a/Extension/Core/Type/ChoiceType.php +++ b/Extension/Core/Type/ChoiceType.php @@ -256,7 +256,7 @@ private function addSubForms(FormBuilderInterface $builder, array $choiceViews, $choiceType = 'radio'; } - $builder->add((string) $i, $choiceType, $choiceOpts); + $builder->add($i, $choiceType, $choiceOpts); } } } diff --git a/Form.php b/Form.php index af01ebc06d..b1895aa588 100644 --- a/Form.php +++ b/Form.php @@ -890,8 +890,8 @@ public function add($child, $type = null, array $options = array()) } if (!$child instanceof FormInterface) { - if (!is_string($child)) { - throw new UnexpectedTypeException($child, 'string or Symfony\Component\Form\FormInterface'); + if (!is_string($child) && !is_int($child)) { + throw new UnexpectedTypeException($child, 'string, integer or Symfony\Component\Form\FormInterface'); } if (null !== $type && !is_string($type) && !$type instanceof FormTypeInterface) { diff --git a/FormBuilder.php b/FormBuilder.php index e49bf6250d..da193be94c 100644 --- a/FormBuilder.php +++ b/FormBuilder.php @@ -78,8 +78,8 @@ public function add($child, $type = null, array $options = array()) return $this; } - if (!is_string($child)) { - throw new UnexpectedTypeException($child, 'string or Symfony\Component\Form\FormBuilder'); + if (!is_string($child) && !is_int($child)) { + throw new UnexpectedTypeException($child, 'string, integer or Symfony\Component\Form\FormBuilder'); } if (null !== $type && !is_string($type) && !$type instanceof FormTypeInterface) { diff --git a/FormBuilderInterface.php b/FormBuilderInterface.php index d2a29fc821..002bd43fc3 100644 --- a/FormBuilderInterface.php +++ b/FormBuilderInterface.php @@ -23,9 +23,9 @@ interface FormBuilderInterface extends \Traversable, \Countable, FormConfigBuild * If you add a nested group, this group should also be represented in the * object hierarchy. * - * @param string|FormBuilderInterface $child - * @param string|FormTypeInterface $type - * @param array $options + * @param string|integer|FormBuilderInterface $child + * @param string|FormTypeInterface $type + * @param array $options * * @return FormBuilderInterface The builder object. */ diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index 51077298a6..a3f16ba720 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -144,7 +144,7 @@ class FormConfigBuilder implements FormConfigBuilderInterface /** * Creates an empty form configuration. * - * @param string $name The form name + * @param string|integer $name The form name * @param string $dataClass The class of the form's data * @param EventDispatcherInterface $dispatcher The event dispatcher * @param array $options The form options @@ -154,15 +154,13 @@ class FormConfigBuilder implements FormConfigBuilderInterface */ public function __construct($name, $dataClass, EventDispatcherInterface $dispatcher, array $options = array()) { - $name = (string) $name; - self::validateName($name); if (null !== $dataClass && !class_exists($dataClass)) { throw new \InvalidArgumentException(sprintf('The data class "%s" is not a valid class.', $dataClass)); } - $this->name = $name; + $this->name = (string) $name; $this->dataClass = $dataClass; $this->dispatcher = $dispatcher; $this->options = $options; @@ -895,15 +893,15 @@ public function getFormConfig() /** * Validates whether the given variable is a valid form name. * - * @param string $name The tested form name. + * @param string|integer $name The tested form name. * - * @throws UnexpectedTypeException If the name is not a string. + * @throws UnexpectedTypeException If the name is not a string or an integer. * @throws \InvalidArgumentException If the name contains invalid characters. */ public static function validateName($name) { - if (!is_string($name)) { - throw new UnexpectedTypeException($name, 'string'); + if (null !== $name && !is_string($name) && !is_int($name)) { + throw new UnexpectedTypeException($name, 'string, integer or null'); } if (!self::isValidName($name)) { @@ -930,6 +928,6 @@ public static function validateName($name) */ public static function isValidName($name) { - return '' === $name || preg_match('/^[a-zA-Z0-9_][a-zA-Z0-9_\-:]*$/D', $name); + return '' === $name || null === $name || preg_match('/^[a-zA-Z0-9_][a-zA-Z0-9_\-:]*$/D', $name); } } diff --git a/FormFactoryInterface.php b/FormFactoryInterface.php index fc90068479..98c53d9b53 100644 --- a/FormFactoryInterface.php +++ b/FormFactoryInterface.php @@ -37,7 +37,7 @@ public function create($type = 'form', $data = null, array $options = array(), F * * @see createNamedBuilder() * - * @param string $name The name of the form + * @param string|integer $name The name of the form * @param string|FormTypeInterface $type The type of the form * @param mixed $data The initial data * @param array $options The options @@ -83,7 +83,7 @@ public function createBuilder($type = 'form', $data = null, array $options = arr /** * Returns a form builder. * - * @param string $name The name of the form + * @param string|integer $name The name of the form * @param string|FormTypeInterface $type The type of the form * @param mixed $data The initial data * @param array $options The options diff --git a/FormInterface.php b/FormInterface.php index b42e42dab9..d217a07dd1 100644 --- a/FormInterface.php +++ b/FormInterface.php @@ -41,9 +41,9 @@ public function getParent(); /** * Adds a child to the form. * - * @param FormInterface|string $child The FormInterface instance or the name of the child. - * @param string|null $type The child's type, if a name was passed. - * @param array $options The child's options, if a name was passed. + * @param FormInterface|string|integer $child The FormInterface instance or the name of the child. + * @param string|null $type The child's type, if a name was passed. + * @param array $options The child's options, if a name was passed. * * @return FormInterface The form instance * diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index f40fa2b6d7..4e4a48e1fc 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -156,6 +156,23 @@ public function testAddUsingNameAndType() $this->assertSame(array('foo' => $child), $this->form->all()); } + public function testAddUsingIntegerNameAndType() + { + $child = $this->getBuilder(0)->getForm(); + + $this->factory->expects($this->once()) + ->method('createNamed') + ->with('0', 'text', null, array('bar' => 'baz')) + ->will($this->returnValue($child)); + + // in order to make casting unnecessary + $this->form->add(0, 'text', array('bar' => 'baz')); + + $this->assertTrue($this->form->has(0)); + $this->assertSame($this->form, $child->getParent()); + $this->assertSame(array(0 => $child), $this->form->all()); + } + public function testAddUsingNameButNoType() { $this->form = $this->getBuilder('name', null, '\stdClass') diff --git a/Tests/FormBuilderTest.php b/Tests/FormBuilderTest.php index 42d4317459..4ccb4ae76e 100644 --- a/Tests/FormBuilderTest.php +++ b/Tests/FormBuilderTest.php @@ -50,10 +50,10 @@ public function testNoSetName() $this->assertFalse(method_exists($this->builder, 'setName')); } - public function testAddNameNoString() + public function testAddNameNoStringAndNoInteger() { $this->setExpectedException('Symfony\Component\Form\Exception\UnexpectedTypeException'); - $this->builder->add(1234); + $this->builder->add(true); } public function testAddTypeNoString() @@ -82,6 +82,13 @@ public function testAdd() $this->assertTrue($this->builder->has('foo')); } + public function testAddIntegerName() + { + $this->assertFalse($this->builder->has(0)); + $this->builder->add(0, 'text'); + $this->assertTrue($this->builder->has(0)); + } + public function testAll() { $this->factory->expects($this->once()) diff --git a/Tests/FormConfigTest.php b/Tests/FormConfigTest.php index e11561a47f..a7626f86a6 100644 --- a/Tests/FormConfigTest.php +++ b/Tests/FormConfigTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Form\Tests; +use Symfony\Component\Form\Exception\UnexpectedTypeException; + /** * @author Bernhard Schussek */ @@ -21,8 +23,6 @@ class FormConfigTest extends \PHPUnit_Framework_TestCase public function getHtml4Ids() { return array( - array('a0', true), - array('a9', true), array('z0', true), array('A0', true), array('A9', true), @@ -53,6 +53,16 @@ public function getHtml4Ids() // For root forms, leading underscores will be stripped from the // "id" attribute to produce valid HTML4. array('_', true), + // Integers are allowed + array(0, true), + array(123, true), + // NULL is allowed + array(null, true), + // Other types are not + array(1.23, false), + array(5., false), + array(true, false), + array(new \stdClass(), false), ); } @@ -68,6 +78,11 @@ public function testNameAcceptsOnlyNamesValidAsIdsInHtml4($name, $accepted) if (!$accepted) { $this->fail(sprintf('The value "%s" should not be accepted', $name)); } + } catch (UnexpectedTypeException $e) { + // if the value was not accepted, but should be, rethrow exception + if ($accepted) { + throw $e; + } } catch (\InvalidArgumentException $e) { // if the value was not accepted, but should be, rethrow exception if ($accepted) { From 29e6bc4656888615b329868279c1b25a1caac34e Mon Sep 17 00:00:00 2001 From: Florin Patan Date: Sun, 16 Dec 2012 14:02:54 +0200 Subject: [PATCH 036/447] Fixed most of the docblocks/unused namespaces --- .../Core/DataTransformer/DataTransformerChain.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Extension/Core/DataTransformer/DataTransformerChain.php b/Extension/Core/DataTransformer/DataTransformerChain.php index 7d434434b9..e653de9e8f 100644 --- a/Extension/Core/DataTransformer/DataTransformerChain.php +++ b/Extension/Core/DataTransformer/DataTransformerChain.php @@ -12,6 +12,8 @@ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; +use Symfony\Component\Form\Exception\TransformationFailedException; +use Symfony\Component\Form\Exception\UnexpectedTypeException; /** * Passes a value through multiple value transformers @@ -48,8 +50,8 @@ public function __construct(array $transformers) * * @return mixed The transformed value * - * @throws Symfony\Component\Form\Exception\TransformationFailedException - * @throws Symfony\Component\Form\Exception\UnexpectedTypeException + * @throws TransformationFailedException + * @throws UnexpectedTypeException */ public function transform($value) { @@ -73,8 +75,8 @@ public function transform($value) * * @return mixed The reverse-transformed value * - * @throws Symfony\Component\Form\Exception\TransformationFailedException - * @throws Symfony\Component\Form\Exception\UnexpectedTypeException + * @throws TransformationFailedException + * @throws UnexpectedTypeException */ public function reverseTransform($value) { From 32be91f39fd87a53077dad9920fb187ff075a5ee Mon Sep 17 00:00:00 2001 From: Drak Date: Wed, 19 Dec 2012 13:30:34 +0000 Subject: [PATCH 037/447] [Form] Prevent trigger of E_USER_DEPRECATED for new API --- Event/DataEvent.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Event/DataEvent.php b/Event/DataEvent.php index cc7c3b2e7e..7739688823 100644 --- a/Event/DataEvent.php +++ b/Event/DataEvent.php @@ -13,6 +13,7 @@ use Symfony\Component\EventDispatcher\Event; use Symfony\Component\Form\FormInterface; +use Symfony\Component\Form\FormEvent; /** * @author Bernhard Schussek @@ -33,7 +34,9 @@ class DataEvent extends Event */ public function __construct(FormInterface $form, $data) { - trigger_error('DataEvent is deprecated since version 2.1 and will be removed in 2.3. Code against \Symfony\Component\Form\FormEvent instead.', E_USER_DEPRECATED); + if (!$this instanceof FormEvent) { + trigger_error(sprintf('%s is deprecated since version 2.1 and will be removed in 2.3. Code against \Symfony\Component\Form\FormEvent instead.', get_class($this)), E_USER_DEPRECATED); + } $this->form = $form; $this->data = $data; From fdf101c8f8150de90b193f446fa39f644f0d1b3c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 20 Dec 2012 08:41:17 +0100 Subject: [PATCH 038/447] fixed CS --- Extension/Core/Type/FieldType.php | 2 +- FormView.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Extension/Core/Type/FieldType.php b/Extension/Core/Type/FieldType.php index e5da968ca1..6a479623f5 100644 --- a/Extension/Core/Type/FieldType.php +++ b/Extension/Core/Type/FieldType.php @@ -22,7 +22,7 @@ */ class FieldType extends AbstractType { - function __construct() + public function __construct() { trigger_error('FieldType is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); } diff --git a/FormView.php b/FormView.php index b230d9c063..d4a3f93d82 100644 --- a/FormView.php +++ b/FormView.php @@ -65,6 +65,7 @@ public function __construct(FormView $parent = null) public function getName() { trigger_error('getName() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'vars\' instead which contains an entry named "name".', E_USER_DEPRECATED); + return $this->vars['name']; } From 560cf4cf386137be922ee5d2e59423a88736cd96 Mon Sep 17 00:00:00 2001 From: Joseph Bielawski Date: Thu, 20 Dec 2012 10:02:06 +0100 Subject: [PATCH 039/447] Update src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php Fix `preg_match` to work with older PCRE. --- .../DateTimeToStringTransformer.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Extension/Core/DataTransformer/DateTimeToStringTransformer.php b/Extension/Core/DataTransformer/DateTimeToStringTransformer.php index f7c4eb4798..6ae4ab48cf 100644 --- a/Extension/Core/DataTransformer/DateTimeToStringTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToStringTransformer.php @@ -160,14 +160,14 @@ public function reverseTransform($value) // Check which of the date parts are present in the pattern preg_match( '/(' . - '(?[djDl])|' . - '(?[FMmn])|' . - '(?[Yy])|' . - '(?[ghGH])|' . - '(?i)|' . - '(?s)|' . - '(?z)|' . - '(?U)|' . + '(?P[djDl])|' . + '(?P[FMmn])|' . + '(?P[Yy])|' . + '(?P[ghGH])|' . + '(?Pi)|' . + '(?Ps)|' . + '(?Pz)|' . + '(?PU)|' . '[^djDlFMmnYyghGHiszU]' . ')*/', $this->parseFormat, From a12178cbd809869ba3baa29de92f0928b4dfc5c0 Mon Sep 17 00:00:00 2001 From: Eric GELOEN Date: Mon, 9 Apr 2012 17:25:41 +0200 Subject: [PATCH 040/447] [Form] Add options with_minutes to DateTimeType & TimeType --- Extension/Core/Type/DateTimeType.php | 11 ++- Extension/Core/Type/TimeType.php | 49 ++++++++---- .../Extension/Core/Type/DateTimeTypeTest.php | 29 +++++++ Tests/Extension/Core/Type/TimeTypeTest.php | 77 +++++++++++++++++++ 4 files changed, 151 insertions(+), 15 deletions(-) diff --git a/Extension/Core/Type/DateTimeType.php b/Extension/Core/Type/DateTimeType.php index 8151c3e7fb..1ffc0a155f 100644 --- a/Extension/Core/Type/DateTimeType.php +++ b/Extension/Core/Type/DateTimeType.php @@ -69,9 +69,14 @@ class DateTimeType extends AbstractType */ public function buildForm(FormBuilderInterface $builder, array $options) { - $parts = array('year', 'month', 'day', 'hour', 'minute'); + $parts = array('year', 'month', 'day', 'hour'); $dateParts = array('year', 'month', 'day'); - $timeParts = array('hour', 'minute'); + $timeParts = array('hour'); + + if ($options['with_minutes']) { + $parts[] = 'minute'; + $timeParts[] = 'minute'; + } if ($options['with_seconds']) { $parts[] = 'second'; @@ -118,6 +123,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'hours', 'minutes', 'seconds', + 'with_minutes', 'with_seconds', 'empty_value', 'required', @@ -223,6 +229,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'widget' => null, 'date_widget' => $dateWidget, 'time_widget' => $timeWidget, + 'with_minutes' => true, 'with_seconds' => false, // Don't modify \DateTime classes by reference, we treat // them like immutable value objects diff --git a/Extension/Core/Type/TimeType.php b/Extension/Core/Type/TimeType.php index 8973948a2f..bc661f66b9 100644 --- a/Extension/Core/Type/TimeType.php +++ b/Extension/Core/Type/TimeType.php @@ -15,6 +15,7 @@ use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\ReversedTransformer; +use Symfony\Component\Form\Exception\InvalidConfigurationException; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToTimestampTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToArrayTransformer; @@ -29,10 +30,20 @@ class TimeType extends AbstractType */ public function buildForm(FormBuilderInterface $builder, array $options) { - $parts = array('hour', 'minute'); - $format = 'H:i'; + $parts = array('hour'); + $format = 'H'; + + if ($options['with_seconds'] && !$options['with_minutes']) { + throw new InvalidConfigurationException('You can not disable minutes if you have enabled seconds.'); + } + + if ($options['with_minutes']) { + $format .= ':i'; + $parts[] = 'minute'; + } + if ($options['with_seconds']) { - $format = 'H:i:s'; + $format .= ':s'; $parts[] = 'second'; } @@ -49,15 +60,19 @@ public function buildForm(FormBuilderInterface $builder, array $options) foreach ($options['hours'] as $hour) { $hours[$hour] = str_pad($hour, 2, '0', STR_PAD_LEFT); } - foreach ($options['minutes'] as $minute) { - $minutes[$minute] = str_pad($minute, 2, '0', STR_PAD_LEFT); - } // Only pass a subset of the options to children $hourOptions['choices'] = $hours; $hourOptions['empty_value'] = $options['empty_value']['hour']; - $minuteOptions['choices'] = $minutes; - $minuteOptions['empty_value'] = $options['empty_value']['minute']; + + if ($options['with_minutes']) { + foreach ($options['minutes'] as $minute) { + $minutes[$minute] = str_pad($minute, 2, '0', STR_PAD_LEFT); + } + + $minuteOptions['choices'] = $minutes; + $minuteOptions['empty_value'] = $options['empty_value']['minute']; + } if ($options['with_seconds']) { $seconds = array(); @@ -72,17 +87,23 @@ public function buildForm(FormBuilderInterface $builder, array $options) // Append generic carry-along options foreach (array('required', 'translation_domain') as $passOpt) { - $hourOptions[$passOpt] = $minuteOptions[$passOpt] = $options[$passOpt]; + $hourOptions[$passOpt] = $options[$passOpt]; + + if ($options['with_minutes']) { + $minuteOptions[$passOpt] = $options[$passOpt]; + } + if ($options['with_seconds']) { $secondOptions[$passOpt] = $options[$passOpt]; } } } - $builder - ->add('hour', $options['widget'], $hourOptions) - ->add('minute', $options['widget'], $minuteOptions) - ; + $builder->add('hour', $options['widget'], $hourOptions); + + if ($options['with_minutes']) { + $builder->add('minute', $options['widget'], $minuteOptions); + } if ($options['with_seconds']) { $builder->add('second', $options['widget'], $secondOptions); @@ -113,6 +134,7 @@ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars = array_replace($view->vars, array( 'widget' => $options['widget'], + 'with_minutes' => $options['with_minutes'], 'with_seconds' => $options['with_seconds'], )); @@ -167,6 +189,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'seconds' => range(0, 59), 'widget' => 'choice', 'input' => 'datetime', + 'with_minutes' => true, 'with_seconds' => false, 'model_timezone' => $modelTimezone, 'view_timezone' => $viewTimezone, diff --git a/Tests/Extension/Core/Type/DateTimeTypeTest.php b/Tests/Extension/Core/Type/DateTimeTypeTest.php index e394315f3e..1db1850d85 100644 --- a/Tests/Extension/Core/Type/DateTimeTypeTest.php +++ b/Tests/Extension/Core/Type/DateTimeTypeTest.php @@ -94,6 +94,35 @@ public function testSubmit_timestamp() $this->assertEquals($dateTime->format('U'), $form->getData()); } + public function testSubmit_withoutMinutes() + { + $form = $this->factory->create('datetime', null, array( + 'data_timezone' => 'UTC', + 'user_timezone' => 'UTC', + 'date_widget' => 'choice', + 'time_widget' => 'choice', + 'input' => 'datetime', + 'with_minutes' => false, + )); + + $form->setData(new \DateTime('2010-06-02 03:04:05 UTC')); + + $input = array( + 'date' => array( + 'day' => '2', + 'month' => '6', + 'year' => '2010', + ), + 'time' => array( + 'hour' => '3', + ), + ); + + $form->bind($input); + + $this->assertDateTimeEquals(new \DateTime('2010-06-02 03:00:00 UTC'), $form->getData()); + } + public function testSubmit_withSeconds() { $form = $this->factory->create('datetime', null, array( diff --git a/Tests/Extension/Core/Type/TimeTypeTest.php b/Tests/Extension/Core/Type/TimeTypeTest.php index 1f51a9dc35..9b5f9ef714 100644 --- a/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/Tests/Extension/Core/Type/TimeTypeTest.php @@ -111,6 +111,22 @@ public function testSubmit_datetimeSingleText() $this->assertEquals('03:04', $form->getViewData()); } + public function testSubmit_datetimeSingleTextWithoutMinutes() + { + $form = $this->factory->create('time', null, array( + 'data_timezone' => 'UTC', + 'user_timezone' => 'UTC', + 'input' => 'datetime', + 'widget' => 'single_text', + 'with_minutes' => false, + )); + + $form->bind('03'); + + $this->assertEquals(new \DateTime('1970-01-01 03:00:00 UTC'), $form->getData()); + $this->assertEquals('03', $form->getViewData()); + } + public function testSubmit_arraySingleText() { $form = $this->factory->create('time', null, array( @@ -131,6 +147,26 @@ public function testSubmit_arraySingleText() $this->assertEquals('03:04', $form->getViewData()); } + public function testSubmit_arraySingleTextWithoutMinutes() + { + $form = $this->factory->create('time', null, array( + 'data_timezone' => 'UTC', + 'user_timezone' => 'UTC', + 'input' => 'array', + 'widget' => 'single_text', + 'with_minutes' => false, + )); + + $data = array( + 'hour' => '3', + ); + + $form->bind('03'); + + $this->assertEquals($data, $form->getData()); + $this->assertEquals('03', $form->getViewData()); + } + public function testSubmit_arraySingleTextWithSeconds() { $form = $this->factory->create('time', null, array( @@ -168,6 +204,36 @@ public function testSubmit_stringSingleText() $this->assertEquals('03:04', $form->getViewData()); } + public function testSubmit_stringSingleTextWithoutMinutes() + { + $form = $this->factory->create('time', null, array( + 'data_timezone' => 'UTC', + 'user_timezone' => 'UTC', + 'input' => 'string', + 'widget' => 'single_text', + 'with_minutes' => false, + )); + + $form->bind('03'); + + $this->assertEquals('03:00:00', $form->getData()); + $this->assertEquals('03', $form->getViewData()); + } + + public function testSetData_withoutMinutes() + { + $form = $this->factory->create('time', null, array( + 'data_timezone' => 'UTC', + 'user_timezone' => 'UTC', + 'input' => 'datetime', + 'with_minutes' => false, + )); + + $form->setData(new \DateTime('03:04:05 UTC')); + + $this->assertEquals(array('hour' => 3), $form->getClientData()); + } + public function testSetData_withSeconds() { $form = $this->factory->create('time', null, array( @@ -561,4 +627,15 @@ public function testSecondErrorsBubbleUp($widget) $this->assertSame(array(), $form['second']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } + + /** + * @expectedException Symfony\Component\Form\Exception\InvalidConfigurationException + */ + public function testInitializeWithSecondsAndWithoutMinutes() + { + $this->factory->create('time', null, array( + 'with_minutes' => false, + 'with_seconds' => true, + )); + } } From f10ca486e5a5e0e80a771ae4f2421449e3f4dc4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Pluchino?= Date: Fri, 28 Dec 2012 16:54:59 +0100 Subject: [PATCH 041/447] [Form] Fix deprecated call method --- Extension/Validator/ValidatorTypeGuesser.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Extension/Validator/ValidatorTypeGuesser.php b/Extension/Validator/ValidatorTypeGuesser.php index 8b64fef965..a9f40808db 100755 --- a/Extension/Validator/ValidatorTypeGuesser.php +++ b/Extension/Validator/ValidatorTypeGuesser.php @@ -15,14 +15,14 @@ use Symfony\Component\Form\Guess\Guess; use Symfony\Component\Form\Guess\TypeGuess; use Symfony\Component\Form\Guess\ValueGuess; -use Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface; +use Symfony\Component\Validator\MetadataFactoryInterface; use Symfony\Component\Validator\Constraint; class ValidatorTypeGuesser implements FormTypeGuesserInterface { private $metadataFactory; - public function __construct(ClassMetadataFactoryInterface $metadataFactory) + public function __construct(MetadataFactoryInterface $metadataFactory) { $this->metadataFactory = $metadataFactory; } @@ -269,7 +269,7 @@ public function guessPatternForConstraint(Constraint $constraint) protected function guess($class, $property, \Closure $closure, $defaultValue = null) { $guesses = array(); - $classMetadata = $this->metadataFactory->getClassMetadata($class); + $classMetadata = $this->metadataFactory->getMetadataFor($class); if ($classMetadata->hasMemberMetadatas($property)) { $memberMetadatas = $classMetadata->getMemberMetadatas($property); @@ -291,4 +291,4 @@ protected function guess($class, $property, \Closure $closure, $defaultValue = n return Guess::getBestGuess($guesses); } -} +} \ No newline at end of file From b18eb856262c4565ceec148b0e64cd80ea3c8f14 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 4 Jan 2013 17:58:00 +0100 Subject: [PATCH 042/447] updated license year --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index cdffe7aebc..88a57f8d8d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2012 Fabien Potencier +Copyright (c) 2004-2013 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From b8f655ea1209c882d92e9ab8db4af3d4ab46c290 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 6 Dec 2012 19:58:12 +0100 Subject: [PATCH 043/447] [Form] Removed separator characters between choice or text fields in DateType --- CHANGELOG.md | 2 ++ Extension/Core/Type/DateType.php | 7 ++++- Tests/Extension/Core/Type/DateTypeTest.php | 31 +++++++++++++++------- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f26b8169c..9e63fc3705 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ CHANGELOG * TrimListener now removes unicode whitespaces * deprecated getParent(), setParent() and hasParent() in FormBuilderInterface * FormInterface::add() now accepts a FormInterface instance OR a field's name, type and options + * removed special characters between the choice or text fields of DateType unless + the option "format" is set to a custom value 2.1.0 ----- diff --git a/Extension/Core/Type/DateType.php b/Extension/Core/Type/DateType.php index 1e44296d40..ec7d055869 100644 --- a/Extension/Core/Type/DateType.php +++ b/Extension/Core/Type/DateType.php @@ -137,13 +137,18 @@ public function finishView(FormView $view, FormInterface $form, array $options) if ($form->getConfig()->hasAttribute('formatter')) { $pattern = $form->getConfig()->getAttribute('formatter')->getPattern(); + // remove special characters unless the format was explicitly specified + if (!is_string($options['format'])) { + $pattern = preg_replace('/[^yMd]+/', '', $pattern); + } + // set right order with respect to locale (e.g.: de_DE=dd.MM.yy; en_US=M/d/yy) // lookup various formats at http://userguide.icu-project.org/formatparse/datetime if (preg_match('/^([yMd]+).+([yMd]+).+([yMd]+)$/', $pattern)) { $pattern = preg_replace(array('/y+/', '/M+/', '/d+/'), array('{{ year }}', '{{ month }}', '{{ day }}'), $pattern); } else { // default fallback - $pattern = '{{ year }}-{{ month }}-{{ day }}'; + $pattern = '{{ year }}{{ month }}{{ day }}'; } $view->vars['date_pattern'] = $pattern; diff --git a/Tests/Extension/Core/Type/DateTypeTest.php b/Tests/Extension/Core/Type/DateTypeTest.php index fdff501668..3ccd49fd7b 100644 --- a/Tests/Extension/Core/Type/DateTypeTest.php +++ b/Tests/Extension/Core/Type/DateTypeTest.php @@ -24,21 +24,21 @@ protected function setUp() } /** - * @expectedException Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testInvalidWidgetOption() { - $form = $this->factory->create('date', null, array( + $this->factory->create('date', null, array( 'widget' => 'fake_widget', )); } /** - * @expectedException Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testInvalidInputOption() { - $form = $this->factory->create('date', null, array( + $this->factory->create('date', null, array( 'input' => 'fake_input', )); } @@ -271,7 +271,7 @@ public function testSubmitFromInputRawDifferentPattern() * This test is to check that the strings '0', '1', '2', '3' are no accepted * as valid IntlDateFormatter constants for FULL, LONG, MEDIUM or SHORT respectively. * - * @expectedException Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testThrowExceptionIfFormatIsNoPattern() { @@ -283,7 +283,7 @@ public function testThrowExceptionIfFormatIsNoPattern() } /** - * @expectedException Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testThrowExceptionIfFormatDoesNotContainYearMonthAndDay() { @@ -294,7 +294,7 @@ public function testThrowExceptionIfFormatDoesNotContainYearMonthAndDay() } /** - * @expectedException Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testThrowExceptionIfFormatIsNoConstant() { @@ -304,7 +304,7 @@ public function testThrowExceptionIfFormatIsNoConstant() } /** - * @expectedException Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testThrowExceptionIfFormatIsInvalid() { @@ -510,7 +510,7 @@ public function testPassDatePatternToView() $form = $this->factory->create('date'); $view = $form->createView(); - $this->assertSame('{{ day }}.{{ month }}.{{ year }}', $view->vars['date_pattern']); + $this->assertSame('{{ day }}{{ month }}{{ year }}', $view->vars['date_pattern']); } public function testPassDatePatternToViewDifferentFormat() @@ -521,10 +521,21 @@ public function testPassDatePatternToViewDifferentFormat() $view = $form->createView(); - $this->assertSame('{{ day }}. {{ month }} {{ year }}', $view->vars['date_pattern']); + $this->assertSame('{{ day }}{{ month }}{{ year }}', $view->vars['date_pattern']); } public function testPassDatePatternToViewDifferentPattern() + { + $form = $this->factory->create('date', null, array( + 'format' => 'MMyyyydd' + )); + + $view = $form->createView(); + + $this->assertSame('{{ month }}{{ year }}{{ day }}', $view->vars['date_pattern']); + } + + public function testPassDatePatternToViewDifferentPatternWithSeparators() { $form = $this->factory->create('date', null, array( 'format' => 'MM*yyyy*dd' From 499b2367b2577c5cdf30941ead677fe7cc89ded8 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Sat, 5 Jan 2013 18:52:40 +0100 Subject: [PATCH 044/447] Fixed @expectedException definitions to reference absolute exception paths --- .../Core/ChoiceList/LazyChoiceListTest.php | 2 +- .../Core/ChoiceList/ObjectChoiceListTest.php | 2 +- .../ArrayToPartsTransformerTest.php | 6 +-- .../ChoiceToValueTransformerTest.php | 2 +- .../ChoicesToValuesTransformerTest.php | 4 +- .../DateTimeToArrayTransformerTest.php | 38 +++++++++---------- .../DateTimeToRfc3339TransformerTest.php | 6 +-- ...ntegerToLocalizedStringTransformerTest.php | 12 +++--- .../ValueToDuplicatesTransformerTest.php | 6 +-- .../MergeCollectionListenerTest.php | 2 +- Tests/Extension/Core/Type/ChoiceTypeTest.php | 4 +- Tests/Extension/Core/Type/DateTypeTest.php | 12 +++--- Tests/Extension/Core/Type/FormTypeTest.php | 2 +- Tests/Extension/Core/Type/TimeTypeTest.php | 2 +- Tests/FormRegistryTest.php | 6 +-- Tests/Util/PropertyPathCollectionTest.php | 8 ++-- Tests/Util/PropertyPathTest.php | 38 +++++++++---------- 17 files changed, 76 insertions(+), 76 deletions(-) diff --git a/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php b/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php index 628ac60ad8..1a7ded0501 100644 --- a/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php @@ -82,7 +82,7 @@ public function testGetValuesForChoices() } /** - * @expectedException Symfony\Component\Form\Exception\FormException + * @expectedException \Symfony\Component\Form\Exception\FormException */ public function testLoadChoiceListShouldReturnChoiceList() { diff --git a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php index 12f22d2d1f..771a37e119 100644 --- a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php @@ -193,7 +193,7 @@ public function testInitArrayUsesToString() } /** - * @expectedException Symfony\Component\Form\Exception\FormException + * @expectedException \Symfony\Component\Form\Exception\FormException */ public function testInitArrayThrowsExceptionIfToStringNotFound() { diff --git a/Tests/Extension/Core/DataTransformer/ArrayToPartsTransformerTest.php b/Tests/Extension/Core/DataTransformer/ArrayToPartsTransformerTest.php index 0ac8f44bae..f576b64df1 100644 --- a/Tests/Extension/Core/DataTransformer/ArrayToPartsTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/ArrayToPartsTransformerTest.php @@ -68,7 +68,7 @@ public function testTransform_empty() } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testTransformRequiresArray() { @@ -123,7 +123,7 @@ public function testReverseTransform_completelyNull() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransform_partiallyNull() { @@ -140,7 +140,7 @@ public function testReverseTransform_partiallyNull() } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testReverseTransformRequiresArray() { diff --git a/Tests/Extension/Core/DataTransformer/ChoiceToValueTransformerTest.php b/Tests/Extension/Core/DataTransformer/ChoiceToValueTransformerTest.php index 844e1ff356..ec551e1cd1 100644 --- a/Tests/Extension/Core/DataTransformer/ChoiceToValueTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/ChoiceToValueTransformerTest.php @@ -67,7 +67,7 @@ public function testReverseTransform($in, $out) } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testReverseTransformExpectsScalar() { diff --git a/Tests/Extension/Core/DataTransformer/ChoicesToValuesTransformerTest.php b/Tests/Extension/Core/DataTransformer/ChoicesToValuesTransformerTest.php index 215b89baad..0abbd7b7eb 100644 --- a/Tests/Extension/Core/DataTransformer/ChoicesToValuesTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/ChoicesToValuesTransformerTest.php @@ -45,7 +45,7 @@ public function testTransformNull() } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testTransformExpectsArray() { @@ -67,7 +67,7 @@ public function testReverseTransformNull() } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testReverseTransformExpectsArray() { diff --git a/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.php b/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.php index 82234d28ba..4f2e29b8c7 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.php @@ -117,7 +117,7 @@ public function testTransform_differentTimezones() } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testTransformRequiresDateTime() { @@ -191,7 +191,7 @@ public function testReverseTransform_completelyEmpty_subsetOfFields() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransform_partiallyEmpty_year() { @@ -206,7 +206,7 @@ public function testReverseTransform_partiallyEmpty_year() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransform_partiallyEmpty_month() { @@ -221,7 +221,7 @@ public function testReverseTransform_partiallyEmpty_month() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransform_partiallyEmpty_day() { @@ -236,7 +236,7 @@ public function testReverseTransform_partiallyEmpty_day() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransform_partiallyEmpty_hour() { @@ -251,7 +251,7 @@ public function testReverseTransform_partiallyEmpty_hour() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransform_partiallyEmpty_minute() { @@ -266,7 +266,7 @@ public function testReverseTransform_partiallyEmpty_minute() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransform_partiallyEmpty_second() { @@ -326,7 +326,7 @@ public function testReverseTransformToDifferentTimezone() } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testReverseTransformRequiresArray() { @@ -335,7 +335,7 @@ public function testReverseTransformRequiresArray() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithNegativeYear() { @@ -351,7 +351,7 @@ public function testReverseTransformWithNegativeYear() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithNegativeMonth() { @@ -367,7 +367,7 @@ public function testReverseTransformWithNegativeMonth() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithNegativeDay() { @@ -383,7 +383,7 @@ public function testReverseTransformWithNegativeDay() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithNegativeHour() { @@ -399,7 +399,7 @@ public function testReverseTransformWithNegativeHour() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithNegativeMinute() { @@ -415,7 +415,7 @@ public function testReverseTransformWithNegativeMinute() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithNegativeSecond() { @@ -431,7 +431,7 @@ public function testReverseTransformWithNegativeSecond() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithInvalidMonth() { @@ -447,7 +447,7 @@ public function testReverseTransformWithInvalidMonth() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithInvalidDay() { @@ -463,7 +463,7 @@ public function testReverseTransformWithInvalidDay() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithStringDay() { @@ -479,7 +479,7 @@ public function testReverseTransformWithStringDay() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithStringMonth() { @@ -495,7 +495,7 @@ public function testReverseTransformWithStringMonth() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithStringYear() { diff --git a/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php b/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php index 40195cb517..75dc226f85 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php @@ -79,7 +79,7 @@ public function testTransform($fromTz, $toTz, $from, $to) } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testTransformRequiresValidDateTime() { @@ -102,7 +102,7 @@ public function testReverseTransform($toTz, $fromTz, $to, $from) } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testReverseTransformRequiresString() { @@ -111,7 +111,7 @@ public function testReverseTransformRequiresString() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformWithNonExistingDate() { diff --git a/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php index a33f24003c..a469d8c024 100644 --- a/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php @@ -50,7 +50,7 @@ public function testReverseTransformWithGrouping() } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testReverseTransformExpectsString() { @@ -60,7 +60,7 @@ public function testReverseTransformExpectsString() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformExpectsValidNumber() { @@ -70,7 +70,7 @@ public function testReverseTransformExpectsValidNumber() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsNaN() { @@ -80,7 +80,7 @@ public function testReverseTransformDisallowsNaN() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsNaN2() { @@ -90,7 +90,7 @@ public function testReverseTransformDisallowsNaN2() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsInfinity() { @@ -100,7 +100,7 @@ public function testReverseTransformDisallowsInfinity() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransformDisallowsNegativeInfinity() { diff --git a/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php b/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php index 520a4dc5f2..20b9353911 100644 --- a/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php @@ -83,7 +83,7 @@ public function testReverseTransform_completelyNull() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransform_partiallyNull() { @@ -97,7 +97,7 @@ public function testReverseTransform_partiallyNull() } /** - * @expectedException Symfony\Component\Form\Exception\TransformationFailedException + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ public function testReverseTransform_differences() { @@ -111,7 +111,7 @@ public function testReverseTransform_differences() } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testReverseTransformRequiresArray() { diff --git a/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php b/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php index 8e0ccad7b1..bf83e057e9 100644 --- a/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php +++ b/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php @@ -196,7 +196,7 @@ public function testDoNothingIfNotAllowDelete($allowAdd) /** * @dataProvider getBooleanMatrix2 - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testRequireArrayOrTraversable($allowAdd, $allowDelete) { diff --git a/Tests/Extension/Core/Type/ChoiceTypeTest.php b/Tests/Extension/Core/Type/ChoiceTypeTest.php index a302e2a9ac..98016e3ad4 100644 --- a/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -79,7 +79,7 @@ public function testChoicesOptionExpectsArray() } /** - * @expectedException Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testChoiceListOptionExpectsChoiceListInterface() { @@ -89,7 +89,7 @@ public function testChoiceListOptionExpectsChoiceListInterface() } /** - * expectedException Symfony\Component\Form\Exception\FormException + * expectedException \Symfony\Component\Form\Exception\FormException */ public function testEitherChoiceListOrChoicesMustBeSet() { diff --git a/Tests/Extension/Core/Type/DateTypeTest.php b/Tests/Extension/Core/Type/DateTypeTest.php index fdff501668..cc0e9bf50d 100644 --- a/Tests/Extension/Core/Type/DateTypeTest.php +++ b/Tests/Extension/Core/Type/DateTypeTest.php @@ -24,7 +24,7 @@ protected function setUp() } /** - * @expectedException Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testInvalidWidgetOption() { @@ -34,7 +34,7 @@ public function testInvalidWidgetOption() } /** - * @expectedException Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testInvalidInputOption() { @@ -271,7 +271,7 @@ public function testSubmitFromInputRawDifferentPattern() * This test is to check that the strings '0', '1', '2', '3' are no accepted * as valid IntlDateFormatter constants for FULL, LONG, MEDIUM or SHORT respectively. * - * @expectedException Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testThrowExceptionIfFormatIsNoPattern() { @@ -283,7 +283,7 @@ public function testThrowExceptionIfFormatIsNoPattern() } /** - * @expectedException Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testThrowExceptionIfFormatDoesNotContainYearMonthAndDay() { @@ -294,7 +294,7 @@ public function testThrowExceptionIfFormatDoesNotContainYearMonthAndDay() } /** - * @expectedException Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testThrowExceptionIfFormatIsNoConstant() { @@ -304,7 +304,7 @@ public function testThrowExceptionIfFormatIsNoConstant() } /** - * @expectedException Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testThrowExceptionIfFormatIsInvalid() { diff --git a/Tests/Extension/Core/Type/FormTypeTest.php b/Tests/Extension/Core/Type/FormTypeTest.php index 1a8e4ad07b..65c7b68693 100644 --- a/Tests/Extension/Core/Type/FormTypeTest.php +++ b/Tests/Extension/Core/Type/FormTypeTest.php @@ -391,7 +391,7 @@ public function testSetDataThroughParamsWithZero($data, $dataAsString) } /** - * @expectedException Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ public function testAttributesException() { diff --git a/Tests/Extension/Core/Type/TimeTypeTest.php b/Tests/Extension/Core/Type/TimeTypeTest.php index 9b5f9ef714..908a41de5f 100644 --- a/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/Tests/Extension/Core/Type/TimeTypeTest.php @@ -629,7 +629,7 @@ public function testSecondErrorsBubbleUp($widget) } /** - * @expectedException Symfony\Component\Form\Exception\InvalidConfigurationException + * @expectedException \Symfony\Component\Form\Exception\InvalidConfigurationException */ public function testInitializeWithSecondsAndWithoutMinutes() { diff --git a/Tests/FormRegistryTest.php b/Tests/FormRegistryTest.php index 43232938c6..d6add6fdb0 100644 --- a/Tests/FormRegistryTest.php +++ b/Tests/FormRegistryTest.php @@ -188,7 +188,7 @@ public function testGetTypeConnectsParentIfGetParentReturnsInstance() } /** - * @expectedException Symfony\Component\Form\Exception\FormException + * @expectedException \Symfony\Component\Form\Exception\FormException */ public function testGetTypeThrowsExceptionIfParentNotFound() { @@ -200,7 +200,7 @@ public function testGetTypeThrowsExceptionIfParentNotFound() } /** - * @expectedException Symfony\Component\Form\Exception\FormException + * @expectedException \Symfony\Component\Form\Exception\FormException */ public function testGetTypeThrowsExceptionIfTypeNotFound() { @@ -208,7 +208,7 @@ public function testGetTypeThrowsExceptionIfTypeNotFound() } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testGetTypeThrowsExceptionIfNoString() { diff --git a/Tests/Util/PropertyPathCollectionTest.php b/Tests/Util/PropertyPathCollectionTest.php index e183ab72da..21e9d04847 100644 --- a/Tests/Util/PropertyPathCollectionTest.php +++ b/Tests/Util/PropertyPathCollectionTest.php @@ -124,7 +124,7 @@ public function testGetValueReadsNestedArrayAccess() } /** - * @expectedException Symfony\Component\Form\Exception\InvalidPropertyException + * @expectedException \Symfony\Component\Form\Exception\InvalidPropertyException */ public function testGetValueThrowsExceptionIfArrayAccessExpected() { @@ -154,7 +154,7 @@ public function testSetValueUpdatesNestedArrayAccess() } /** - * @expectedException Symfony\Component\Form\Exception\InvalidPropertyException + * @expectedException \Symfony\Component\Form\Exception\InvalidPropertyException */ public function testSetValueThrowsExceptionIfArrayAccessExpected() { @@ -240,7 +240,7 @@ public function testSetValueCallsCustomAdderAndRemover() } /** - * @expectedException Symfony\Component\Form\Exception\InvalidPropertyException + * @expectedException \Symfony\Component\Form\Exception\InvalidPropertyException */ public function testMapFormToDataFailsIfOnlyAdderFound() { @@ -258,7 +258,7 @@ public function testMapFormToDataFailsIfOnlyAdderFound() } /** - * @expectedException Symfony\Component\Form\Exception\InvalidPropertyException + * @expectedException \Symfony\Component\Form\Exception\InvalidPropertyException */ public function testMapFormToDataFailsIfOnlyRemoverFound() { diff --git a/Tests/Util/PropertyPathTest.php b/Tests/Util/PropertyPathTest.php index 7642def026..e9be1445e6 100644 --- a/Tests/Util/PropertyPathTest.php +++ b/Tests/Util/PropertyPathTest.php @@ -27,7 +27,7 @@ public function testGetValueReadsArray() } /** - * @expectedException Symfony\Component\Form\Exception\InvalidPropertyException + * @expectedException \Symfony\Component\Form\Exception\InvalidPropertyException */ public function testGetValueThrowsExceptionIfIndexNotationExpected() { @@ -126,7 +126,7 @@ public function testGetValueReadsPropertyWithCustomPropertyPath() } /** - * @expectedException Symfony\Component\Form\Exception\PropertyAccessDeniedException + * @expectedException \Symfony\Component\Form\Exception\PropertyAccessDeniedException */ public function testGetValueThrowsExceptionIfPropertyIsNotPublic() { @@ -156,7 +156,7 @@ public function testGetValueCamelizesGetterNames() } /** - * @expectedException Symfony\Component\Form\Exception\PropertyAccessDeniedException + * @expectedException \Symfony\Component\Form\Exception\PropertyAccessDeniedException */ public function testGetValueThrowsExceptionIfGetterIsNotPublic() { @@ -208,7 +208,7 @@ public function testGetValueReadsMagicGetThatReturnsConstant() } /** - * @expectedException Symfony\Component\Form\Exception\PropertyAccessDeniedException + * @expectedException \Symfony\Component\Form\Exception\PropertyAccessDeniedException */ public function testGetValueThrowsExceptionIfIsserIsNotPublic() { @@ -218,7 +218,7 @@ public function testGetValueThrowsExceptionIfIsserIsNotPublic() } /** - * @expectedException Symfony\Component\Form\Exception\InvalidPropertyException + * @expectedException \Symfony\Component\Form\Exception\InvalidPropertyException */ public function testGetValueThrowsExceptionIfPropertyDoesNotExist() { @@ -228,7 +228,7 @@ public function testGetValueThrowsExceptionIfPropertyDoesNotExist() } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testGetValueThrowsExceptionIfNotObjectOrArray() { @@ -238,7 +238,7 @@ public function testGetValueThrowsExceptionIfNotObjectOrArray() } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testGetValueThrowsExceptionIfNull() { @@ -248,7 +248,7 @@ public function testGetValueThrowsExceptionIfNull() } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testGetValueThrowsExceptionIfEmpty() { @@ -268,7 +268,7 @@ public function testSetValueUpdatesArrays() } /** - * @expectedException Symfony\Component\Form\Exception\InvalidPropertyException + * @expectedException \Symfony\Component\Form\Exception\InvalidPropertyException */ public function testSetValueThrowsExceptionIfIndexNotationExpected() { @@ -341,7 +341,7 @@ public function testSetValueCamelizesSetterNames() } /** - * @expectedException Symfony\Component\Form\Exception\PropertyAccessDeniedException + * @expectedException \Symfony\Component\Form\Exception\PropertyAccessDeniedException */ public function testSetValueThrowsExceptionIfGetterIsNotPublic() { @@ -351,7 +351,7 @@ public function testSetValueThrowsExceptionIfGetterIsNotPublic() } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testSetValueThrowsExceptionIfNotObjectOrArray() { @@ -362,7 +362,7 @@ public function testSetValueThrowsExceptionIfNotObjectOrArray() } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testSetValueThrowsExceptionIfNull() { @@ -373,7 +373,7 @@ public function testSetValueThrowsExceptionIfNull() } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testSetValueThrowsExceptionIfEmpty() { @@ -391,7 +391,7 @@ public function testToString() } /** - * @expectedException Symfony\Component\Form\Exception\InvalidPropertyPathException + * @expectedException \Symfony\Component\Form\Exception\InvalidPropertyPathException */ public function testInvalidPropertyPath_noDotBeforeProperty() { @@ -399,7 +399,7 @@ public function testInvalidPropertyPath_noDotBeforeProperty() } /** - * @expectedException Symfony\Component\Form\Exception\InvalidPropertyPathException + * @expectedException \Symfony\Component\Form\Exception\InvalidPropertyPathException */ public function testInvalidPropertyPath_dotAtTheBeginning() { @@ -407,7 +407,7 @@ public function testInvalidPropertyPath_dotAtTheBeginning() } /** - * @expectedException Symfony\Component\Form\Exception\InvalidPropertyPathException + * @expectedException \Symfony\Component\Form\Exception\InvalidPropertyPathException */ public function testInvalidPropertyPath_unexpectedCharacters() { @@ -415,7 +415,7 @@ public function testInvalidPropertyPath_unexpectedCharacters() } /** - * @expectedException Symfony\Component\Form\Exception\InvalidPropertyPathException + * @expectedException \Symfony\Component\Form\Exception\InvalidPropertyPathException */ public function testInvalidPropertyPath_empty() { @@ -423,7 +423,7 @@ public function testInvalidPropertyPath_empty() } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testInvalidPropertyPath_null() { @@ -431,7 +431,7 @@ public function testInvalidPropertyPath_null() } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testInvalidPropertyPath_false() { From 0d63cf5ab2796c8dc73d1d89499eb1b34a640989 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Sat, 5 Jan 2013 18:31:34 +0100 Subject: [PATCH 045/447] [Form] Introduced base ExceptionInterface --- AbstractExtension.php | 4 +- CHANGELOG.md | 1 + Exception/AlreadyBoundException.php | 2 +- Exception/CreationException.php | 2 +- Exception/ErrorMappingException.php | 2 +- Exception/Exception.php | 26 +++++++ Exception/ExceptionInterface.php | 21 ++++++ Exception/FormException.php | 10 ++- Exception/InvalidConfigurationException.php | 2 +- Exception/InvalidPropertyException.php | 2 +- Exception/InvalidPropertyPathException.php | 2 +- Exception/NotInitializedException.php | 2 +- Exception/NotValidException.php | 2 +- Exception/PropertyAccessDeniedException.php | 2 +- Exception/StringCastException.php | 2 +- Exception/TransformationFailedException.php | 4 +- Exception/TypeDefinitionException.php | 2 +- Exception/TypeLoaderException.php | 2 +- Exception/UnexpectedTypeException.php | 2 +- Extension/Core/ChoiceList/LazyChoiceList.php | 4 +- Extension/Core/Type/ChoiceType.php | 4 +- Extension/Core/Type/FormType.php | 4 +- .../EventListener/BindRequestListener.php | 4 +- Form.php | 14 ++-- FormBuilder.php | 12 ++-- FormConfigBuilder.php | 72 +++++++++---------- FormRegistry.php | 7 +- FormRenderer.php | 8 +-- PreloadedExtension.php | 4 +- ResolvedFormType.php | 4 +- .../Core/ChoiceList/LazyChoiceListTest.php | 2 +- .../Core/ChoiceList/ObjectChoiceListTest.php | 2 +- Tests/Extension/Core/Type/ChoiceTypeTest.php | 2 +- Tests/FormBuilderTest.php | 2 +- Tests/FormRegistryTest.php | 4 +- Tests/SimpleFormTest.php | 8 +-- Tests/Util/PropertyPathCollectionTest.php | 2 +- 37 files changed, 154 insertions(+), 97 deletions(-) create mode 100644 Exception/Exception.php create mode 100644 Exception/ExceptionInterface.php diff --git a/AbstractExtension.php b/AbstractExtension.php index 190a5ab8a6..daa57e768f 100644 --- a/AbstractExtension.php +++ b/AbstractExtension.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form; -use Symfony\Component\Form\Exception\FormException; +use Symfony\Component\Form\Exception\Exception; use Symfony\Component\Form\Exception\UnexpectedTypeException; /** @@ -53,7 +53,7 @@ public function getType($name) } if (!isset($this->types[$name])) { - throw new FormException(sprintf('The type "%s" can not be loaded by this extension', $name)); + throw new Exception(sprintf('The type "%s" can not be loaded by this extension', $name)); } return $this->types[$name]; diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e63fc3705..d0d298f9df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ CHANGELOG * FormInterface::add() now accepts a FormInterface instance OR a field's name, type and options * removed special characters between the choice or text fields of DateType unless the option "format" is set to a custom value + * deprecated FormException and introduced ExceptionInterface instead 2.1.0 ----- diff --git a/Exception/AlreadyBoundException.php b/Exception/AlreadyBoundException.php index c08d8cf732..9679725e9f 100644 --- a/Exception/AlreadyBoundException.php +++ b/Exception/AlreadyBoundException.php @@ -11,6 +11,6 @@ namespace Symfony\Component\Form\Exception; -class AlreadyBoundException extends FormException +class AlreadyBoundException extends Exception { } diff --git a/Exception/CreationException.php b/Exception/CreationException.php index 91caa0fd59..e6c4b4e173 100644 --- a/Exception/CreationException.php +++ b/Exception/CreationException.php @@ -16,6 +16,6 @@ * * @author Bernhard Schussek */ -class CreationException extends FormException +class CreationException extends Exception { } diff --git a/Exception/ErrorMappingException.php b/Exception/ErrorMappingException.php index 2283b0f775..adbb2deb51 100644 --- a/Exception/ErrorMappingException.php +++ b/Exception/ErrorMappingException.php @@ -11,6 +11,6 @@ namespace Symfony\Component\Form\Exception; -class ErrorMappingException extends FormException +class ErrorMappingException extends Exception { } diff --git a/Exception/Exception.php b/Exception/Exception.php new file mode 100644 index 0000000000..b882d70396 --- /dev/null +++ b/Exception/Exception.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Exception; + +/** + * Base exception class. + * + * @author Bernhard Schussek + * + * @deprecated This class is a replacement for when class FormException was + * used previously. It should not be used and will be removed. + * Occurrences of this class should be replaced by more specialized + * exception classes, preferably derived from SPL exceptions. + */ +class Exception extends \Exception implements ExceptionInterface +{ +} diff --git a/Exception/ExceptionInterface.php b/Exception/ExceptionInterface.php new file mode 100644 index 0000000000..975bdb89ad --- /dev/null +++ b/Exception/ExceptionInterface.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Exception; + +/** + * Base ExceptionInterface for the Form component. + * + * @author Bernhard Schussek + */ +interface ExceptionInterface extends FormException +{ +} diff --git a/Exception/FormException.php b/Exception/FormException.php index 5dd0884d8b..dbc6d06499 100644 --- a/Exception/FormException.php +++ b/Exception/FormException.php @@ -11,6 +11,14 @@ namespace Symfony\Component\Form\Exception; -class FormException extends \Exception +/** + * Alias of {@link ExceptionInterface}. + * + * @author Bernhard Schussek + * + * @deprecated This interface was deprecated and will be removed in Symfony 2.3. + * You should code against {@link ExceptionInterface} instead. + */ +interface FormException { } diff --git a/Exception/InvalidConfigurationException.php b/Exception/InvalidConfigurationException.php index 9804f4b433..08c7b72815 100644 --- a/Exception/InvalidConfigurationException.php +++ b/Exception/InvalidConfigurationException.php @@ -11,6 +11,6 @@ namespace Symfony\Component\Form\Exception; -class InvalidConfigurationException extends FormException +class InvalidConfigurationException extends Exception { } diff --git a/Exception/InvalidPropertyException.php b/Exception/InvalidPropertyException.php index 4d9eee5599..48185d55fd 100644 --- a/Exception/InvalidPropertyException.php +++ b/Exception/InvalidPropertyException.php @@ -11,6 +11,6 @@ namespace Symfony\Component\Form\Exception; -class InvalidPropertyException extends FormException +class InvalidPropertyException extends Exception { } diff --git a/Exception/InvalidPropertyPathException.php b/Exception/InvalidPropertyPathException.php index e2a6a84183..c8bd3ad71b 100644 --- a/Exception/InvalidPropertyPathException.php +++ b/Exception/InvalidPropertyPathException.php @@ -11,6 +11,6 @@ namespace Symfony\Component\Form\Exception; -class InvalidPropertyPathException extends FormException +class InvalidPropertyPathException extends Exception { } diff --git a/Exception/NotInitializedException.php b/Exception/NotInitializedException.php index 62fea232c1..2c416ede3f 100644 --- a/Exception/NotInitializedException.php +++ b/Exception/NotInitializedException.php @@ -11,6 +11,6 @@ namespace Symfony\Component\Form\Exception; -class NotInitializedException extends FormException +class NotInitializedException extends Exception { } diff --git a/Exception/NotValidException.php b/Exception/NotValidException.php index 2b3cc00854..42c5f4ffbd 100644 --- a/Exception/NotValidException.php +++ b/Exception/NotValidException.php @@ -11,6 +11,6 @@ namespace Symfony\Component\Form\Exception; -class NotValidException extends FormException +class NotValidException extends Exception { } diff --git a/Exception/PropertyAccessDeniedException.php b/Exception/PropertyAccessDeniedException.php index a89e9583be..4905da9ea2 100644 --- a/Exception/PropertyAccessDeniedException.php +++ b/Exception/PropertyAccessDeniedException.php @@ -11,6 +11,6 @@ namespace Symfony\Component\Form\Exception; -class PropertyAccessDeniedException extends FormException +class PropertyAccessDeniedException extends Exception { } diff --git a/Exception/StringCastException.php b/Exception/StringCastException.php index ff882ae8f6..d4bdf0a7fe 100644 --- a/Exception/StringCastException.php +++ b/Exception/StringCastException.php @@ -11,6 +11,6 @@ namespace Symfony\Component\Form\Exception; -class StringCastException extends FormException +class StringCastException extends Exception { } diff --git a/Exception/TransformationFailedException.php b/Exception/TransformationFailedException.php index 73e0b7b2ee..2bbefbabc8 100644 --- a/Exception/TransformationFailedException.php +++ b/Exception/TransformationFailedException.php @@ -14,8 +14,8 @@ /** * Indicates a value transformation error. * - * @author Bernhard Schussek + * @author Bernhard Schussek */ -class TransformationFailedException extends \RuntimeException +class TransformationFailedException extends \RuntimeException implements ExceptionInterface { } diff --git a/Exception/TypeDefinitionException.php b/Exception/TypeDefinitionException.php index ece48004c7..0567350502 100644 --- a/Exception/TypeDefinitionException.php +++ b/Exception/TypeDefinitionException.php @@ -16,6 +16,6 @@ * * @author Bernhard Schussek */ -class TypeDefinitionException extends FormException +class TypeDefinitionException extends Exception { } diff --git a/Exception/TypeLoaderException.php b/Exception/TypeLoaderException.php index 0c70bb2eb2..a257b504fa 100644 --- a/Exception/TypeLoaderException.php +++ b/Exception/TypeLoaderException.php @@ -11,6 +11,6 @@ namespace Symfony\Component\Form\Exception; -class TypeLoaderException extends FormException +class TypeLoaderException extends Exception { } diff --git a/Exception/UnexpectedTypeException.php b/Exception/UnexpectedTypeException.php index ef898fd349..77cabb7d7b 100644 --- a/Exception/UnexpectedTypeException.php +++ b/Exception/UnexpectedTypeException.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form\Exception; -class UnexpectedTypeException extends FormException +class UnexpectedTypeException extends Exception { public function __construct($value, $expectedType) { diff --git a/Extension/Core/ChoiceList/LazyChoiceList.php b/Extension/Core/ChoiceList/LazyChoiceList.php index d5f5cfd555..e690266fbc 100644 --- a/Extension/Core/ChoiceList/LazyChoiceList.php +++ b/Extension/Core/ChoiceList/LazyChoiceList.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form\Extension\Core\ChoiceList; -use Symfony\Component\Form\Exception\FormException; +use Symfony\Component\Form\Exception\Exception; /** * A choice list that is loaded lazily @@ -141,7 +141,7 @@ private function load() $choiceList = $this->loadChoiceList(); if (!$choiceList instanceof ChoiceListInterface) { - throw new FormException('loadChoiceList() should return a ChoiceListInterface instance. Got ' . gettype($choiceList)); + throw new Exception('loadChoiceList() should return a ChoiceListInterface instance. Got ' . gettype($choiceList)); } $this->choiceList = $choiceList; diff --git a/Extension/Core/Type/ChoiceType.php b/Extension/Core/Type/ChoiceType.php index a33a01b9cb..28327b6291 100644 --- a/Extension/Core/Type/ChoiceType.php +++ b/Extension/Core/Type/ChoiceType.php @@ -15,7 +15,7 @@ use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; -use Symfony\Component\Form\Exception\FormException; +use Symfony\Component\Form\Exception\Exception; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; use Symfony\Component\Form\Extension\Core\EventListener\FixRadioInputListener; use Symfony\Component\Form\Extension\Core\EventListener\FixCheckboxInputListener; @@ -41,7 +41,7 @@ class ChoiceType extends AbstractType public function buildForm(FormBuilderInterface $builder, array $options) { if (!$options['choice_list'] && !is_array($options['choices']) && !$options['choices'] instanceof \Traversable) { - throw new FormException('Either the option "choices" or "choice_list" must be set.'); + throw new Exception('Either the option "choices" or "choice_list" must be set.'); } if ($options['expanded']) { diff --git a/Extension/Core/Type/FormType.php b/Extension/Core/Type/FormType.php index 902a1750f5..0b9c38df90 100644 --- a/Extension/Core/Type/FormType.php +++ b/Extension/Core/Type/FormType.php @@ -17,7 +17,7 @@ use Symfony\Component\Form\FormView; use Symfony\Component\Form\Extension\Core\EventListener\TrimListener; use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; -use Symfony\Component\Form\Exception\FormException; +use Symfony\Component\Form\Exception\Exception; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; @@ -61,7 +61,7 @@ public function buildView(FormView $view, FormInterface $form, array $options) if ($view->parent) { if ('' === $name) { - throw new FormException('Form node with empty name can be used only as root form node.'); + throw new Exception('Form node with empty name can be used only as root form node.'); } if ('' !== ($parentFullName = $view->parent->vars['full_name'])) { diff --git a/Extension/HttpFoundation/EventListener/BindRequestListener.php b/Extension/HttpFoundation/EventListener/BindRequestListener.php index 1c019fc976..b4d0ed7b13 100644 --- a/Extension/HttpFoundation/EventListener/BindRequestListener.php +++ b/Extension/HttpFoundation/EventListener/BindRequestListener.php @@ -13,7 +13,7 @@ use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; -use Symfony\Component\Form\Exception\FormException; +use Symfony\Component\Form\Exception\Exception; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; @@ -74,7 +74,7 @@ public function preBind(FormEvent $event) break; default: - throw new FormException(sprintf( + throw new Exception(sprintf( 'The request method "%s" is not supported', $request->getMethod() )); diff --git a/Form.php b/Form.php index f43192f698..ad44f15d35 100644 --- a/Form.php +++ b/Form.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form; -use Symfony\Component\Form\Exception\FormException; +use Symfony\Component\Form\Exception\Exception; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Exception\AlreadyBoundException; use Symfony\Component\Form\Exception\TransformationFailedException; @@ -152,7 +152,7 @@ public function __construct(FormConfigInterface $config) // `setData` and `add` will not lead to the correct population of // the child forms. if ($config->getCompound() && !$config->getDataMapper()) { - throw new FormException('Compound forms need a data mapper'); + throw new Exception('Compound forms need a data mapper'); } $this->config = $config; @@ -256,7 +256,7 @@ public function setParent(FormInterface $parent = null) } if (null !== $parent && '' === $this->config->getName()) { - throw new FormException('A form with an empty name cannot have a parent form.'); + throw new Exception('A form with an empty name cannot have a parent form.'); } $this->parent = $parent; @@ -359,7 +359,7 @@ public function setData($modelData) } if ($this->lockSetData) { - throw new FormException('A cycle was detected. Listeners to the PRE_SET_DATA event must not call setData(). You should call setData() on the FormEvent object instead.'); + throw new Exception('A cycle was detected. Listeners to the PRE_SET_DATA event must not call setData(). You should call setData() on the FormEvent object instead.'); } $this->lockSetData = true; @@ -394,7 +394,7 @@ public function setData($modelData) if (null === $dataClass && is_object($viewData) && !$viewData instanceof \ArrayAccess) { $expectedType = 'scalar, array or an instance of \ArrayAccess'; - throw new FormException( + throw new Exception( 'The form\'s view data is expected to be of type ' . $expectedType . ', ' . 'but is ' . $actualType . '. You ' . 'can avoid this error by setting the "data_class" option to ' . @@ -404,7 +404,7 @@ public function setData($modelData) } if (null !== $dataClass && !$viewData instanceof $dataClass) { - throw new FormException( + throw new Exception( 'The form\'s view data is expected to be an instance of class ' . $dataClass . ', but is '. $actualType . '. You can avoid this error ' . 'by setting the "data_class" option to null or by adding a view ' . @@ -867,7 +867,7 @@ public function add($child, $type = null, array $options = array()) } if (!$this->config->getCompound()) { - throw new FormException('You cannot add children to a simple form. Maybe you should set the option "compound" to true?'); + throw new Exception('You cannot add children to a simple form. Maybe you should set the option "compound" to true?'); } // Obtain the view data diff --git a/FormBuilder.php b/FormBuilder.php index da193be94c..428044e21a 100644 --- a/FormBuilder.php +++ b/FormBuilder.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form; -use Symfony\Component\Form\Exception\FormException; +use Symfony\Component\Form\Exception\Exception; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -65,7 +65,7 @@ public function __construct($name, $dataClass, EventDispatcherInterface $dispatc public function add($child, $type = null, array $options = array()) { if ($this->locked) { - throw new FormException('The form builder cannot be modified anymore.'); + throw new Exception('The form builder cannot be modified anymore.'); } if ($child instanceof self) { @@ -102,7 +102,7 @@ public function add($child, $type = null, array $options = array()) public function create($name, $type = null, array $options = array()) { if ($this->locked) { - throw new FormException('The form builder cannot be modified anymore.'); + throw new Exception('The form builder cannot be modified anymore.'); } if (null === $type && null === $this->getDataClass()) { @@ -129,7 +129,7 @@ public function get($name) return $this->children[$name]; } - throw new FormException(sprintf('The child with the name "%s" does not exist.', $name)); + throw new Exception(sprintf('The child with the name "%s" does not exist.', $name)); } /** @@ -138,7 +138,7 @@ public function get($name) public function remove($name) { if ($this->locked) { - throw new FormException('The form builder cannot be modified anymore.'); + throw new Exception('The form builder cannot be modified anymore.'); } unset($this->unresolvedChildren[$name]); @@ -217,7 +217,7 @@ public function getParent() public function setParent(FormBuilderInterface $parent = null) { if ($this->locked) { - throw new FormException('The form builder cannot be modified anymore.'); + throw new Exception('The form builder cannot be modified anymore.'); } $this->parent = $parent; diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index a3f16ba720..942e3346f4 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form; -use Symfony\Component\Form\Exception\FormException; +use Symfony\Component\Form\Exception\Exception; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Util\PropertyPath; use Symfony\Component\Form\Util\PropertyPathInterface; @@ -172,7 +172,7 @@ public function __construct($name, $dataClass, EventDispatcherInterface $dispatc public function addEventListener($eventName, $listener, $priority = 0) { if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } $this->dispatcher->addListener($eventName, $listener, $priority); @@ -186,7 +186,7 @@ public function addEventListener($eventName, $listener, $priority = 0) public function addEventSubscriber(EventSubscriberInterface $subscriber) { if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } $this->dispatcher->addSubscriber($subscriber); @@ -202,7 +202,7 @@ public function addValidator(FormValidatorInterface $validator) trigger_error('addValidator() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } $this->validators[] = $validator; @@ -216,7 +216,7 @@ public function addValidator(FormValidatorInterface $validator) public function addViewTransformer(DataTransformerInterface $viewTransformer, $forcePrepend = false) { if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } if ($forcePrepend) { @@ -234,7 +234,7 @@ public function addViewTransformer(DataTransformerInterface $viewTransformer, $f public function resetViewTransformers() { if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } $this->viewTransformers = array(); @@ -249,7 +249,7 @@ public function resetViewTransformers() * * @return FormConfigBuilder The configuration object. * - * @throws FormException if the form configuration is locked + * @throws Exception if the form configuration is locked * * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use * {@link addViewTransformer()} instead. @@ -259,7 +259,7 @@ public function appendClientTransformer(DataTransformerInterface $viewTransforme trigger_error('appendClientTransformer() is deprecated since version 2.1 and will be removed in 2.3. Use addViewTransformer() instead.', E_USER_DEPRECATED); if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } return $this->addViewTransformer($viewTransformer); @@ -272,7 +272,7 @@ public function appendClientTransformer(DataTransformerInterface $viewTransforme * * @return FormConfigBuilder The configuration object. * - * @throws FormException if the form configuration is locked + * @throws Exception if the form configuration is locked * * @deprecated Deprecated since version 2.1, to be removed in 2.3. */ @@ -281,7 +281,7 @@ public function prependClientTransformer(DataTransformerInterface $viewTransform trigger_error('prependClientTransformer() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } return $this->addViewTransformer($viewTransformer, true); @@ -292,7 +292,7 @@ public function prependClientTransformer(DataTransformerInterface $viewTransform * * @return FormConfigBuilder The configuration object. * - * @throws FormException if the form configuration is locked + * @throws Exception if the form configuration is locked * * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use * {@link resetViewTransformers()} instead. @@ -302,7 +302,7 @@ public function resetClientTransformers() trigger_error('resetClientTransformers() is deprecated since version 2.1 and will be removed in 2.3. Use resetViewTransformers() instead.', E_USER_DEPRECATED); if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } return $this->resetViewTransformers(); @@ -314,7 +314,7 @@ public function resetClientTransformers() public function addModelTransformer(DataTransformerInterface $modelTransformer, $forceAppend = false) { if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } if ($forceAppend) { @@ -332,7 +332,7 @@ public function addModelTransformer(DataTransformerInterface $modelTransformer, public function resetModelTransformers() { if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } $this->modelTransformers = array(); @@ -347,7 +347,7 @@ public function resetModelTransformers() * * @return FormConfigBuilder The configuration object. * - * @throws FormException if the form configuration is locked + * @throws Exception if the form configuration is locked * * @deprecated Deprecated since version 2.1, to be removed in 2.3. */ @@ -356,7 +356,7 @@ public function appendNormTransformer(DataTransformerInterface $modelTransformer trigger_error('appendNormTransformer() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } return $this->addModelTransformer($modelTransformer, true); @@ -369,7 +369,7 @@ public function appendNormTransformer(DataTransformerInterface $modelTransformer * * @return FormConfigBuilder The configuration object. * - * @throws FormException if the form configuration is locked + * @throws Exception if the form configuration is locked * * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use * {@link addModelTransformer()} instead. @@ -379,7 +379,7 @@ public function prependNormTransformer(DataTransformerInterface $modelTransforme trigger_error('prependNormTransformer() is deprecated since version 2.1 and will be removed in 2.3. Use addModelTransformer() instead.', E_USER_DEPRECATED); if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } return $this->addModelTransformer($modelTransformer); @@ -390,7 +390,7 @@ public function prependNormTransformer(DataTransformerInterface $modelTransforme * * @return FormConfigBuilder The configuration object. * - * @throws FormException if the form configuration is locked + * @throws Exception if the form configuration is locked * * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use * {@link resetModelTransformers()} instead. @@ -400,7 +400,7 @@ public function resetNormTransformers() trigger_error('resetNormTransformers() is deprecated since version 2.1 and will be removed in 2.3. Use resetModelTransformers() instead.', E_USER_DEPRECATED); if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } return $this->resetModelTransformers(); @@ -652,7 +652,7 @@ public function getOption($name, $default = null) public function setAttribute($name, $value) { if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } $this->attributes[$name] = $value; @@ -666,7 +666,7 @@ public function setAttribute($name, $value) public function setAttributes(array $attributes) { if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } $this->attributes = $attributes; @@ -680,7 +680,7 @@ public function setAttributes(array $attributes) public function setDataMapper(DataMapperInterface $dataMapper = null) { if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } $this->dataMapper = $dataMapper; @@ -694,7 +694,7 @@ public function setDataMapper(DataMapperInterface $dataMapper = null) public function setDisabled($disabled) { if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } $this->disabled = (Boolean) $disabled; @@ -708,7 +708,7 @@ public function setDisabled($disabled) public function setEmptyData($emptyData) { if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } $this->emptyData = $emptyData; @@ -722,7 +722,7 @@ public function setEmptyData($emptyData) public function setErrorBubbling($errorBubbling) { if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } $this->errorBubbling = null === $errorBubbling ? null : (Boolean) $errorBubbling; @@ -736,7 +736,7 @@ public function setErrorBubbling($errorBubbling) public function setRequired($required) { if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } $this->required = (Boolean) $required; @@ -750,7 +750,7 @@ public function setRequired($required) public function setPropertyPath($propertyPath) { if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } if (null !== $propertyPath && !$propertyPath instanceof PropertyPathInterface) { @@ -768,7 +768,7 @@ public function setPropertyPath($propertyPath) public function setMapped($mapped) { if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } $this->mapped = $mapped; @@ -782,7 +782,7 @@ public function setMapped($mapped) public function setByReference($byReference) { if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } $this->byReference = $byReference; @@ -796,7 +796,7 @@ public function setByReference($byReference) public function setVirtual($virtual) { if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } $this->virtual = $virtual; @@ -810,7 +810,7 @@ public function setVirtual($virtual) public function setCompound($compound) { if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } $this->compound = $compound; @@ -824,7 +824,7 @@ public function setCompound($compound) public function setType(ResolvedFormTypeInterface $type) { if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } $this->type = $type; @@ -838,7 +838,7 @@ public function setType(ResolvedFormTypeInterface $type) public function setData($data) { if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } $this->data = $data; @@ -852,7 +852,7 @@ public function setData($data) public function setDataLocked($locked) { if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } $this->dataLocked = $locked; @@ -866,7 +866,7 @@ public function setDataLocked($locked) public function setFormFactory(FormFactoryInterface $formFactory) { if ($this->locked) { - throw new FormException('The config builder cannot be modified anymore.'); + throw new Exception('The config builder cannot be modified anymore.'); } $this->formFactory = $formFactory; diff --git a/FormRegistry.php b/FormRegistry.php index c45233c7aa..53f6d906de 100644 --- a/FormRegistry.php +++ b/FormRegistry.php @@ -11,8 +11,9 @@ namespace Symfony\Component\Form; +use Symfony\Component\Form\Exception\ExceptionInterface; use Symfony\Component\Form\Exception\UnexpectedTypeException; -use Symfony\Component\Form\Exception\FormException; +use Symfony\Component\Form\Exception\Exception; /** * The central registry of the Form component. @@ -95,7 +96,7 @@ public function getType($name) } if (!$type) { - throw new FormException(sprintf('Could not load type "%s"', $name)); + throw new Exception(sprintf('Could not load type "%s"', $name)); } $this->resolveAndAddType($type); @@ -151,7 +152,7 @@ public function hasType($name) try { $this->getType($name); - } catch (FormException $e) { + } catch (ExceptionInterface $e) { return false; } diff --git a/FormRenderer.php b/FormRenderer.php index 5ace682561..b2394742f5 100644 --- a/FormRenderer.php +++ b/FormRenderer.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form; -use Symfony\Component\Form\Exception\FormException; +use Symfony\Component\Form\Exception\Exception; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; /** @@ -88,7 +88,7 @@ public function renderCsrfToken($intention) public function renderBlock(FormView $view, $blockName, array $variables = array()) { if (0 == count($this->variableStack)) { - throw new FormException('This method should only be called while rendering a form element.'); + throw new Exception('This method should only be called while rendering a form element.'); } $viewCacheKey = $view->vars[self::CACHE_KEY_VAR]; @@ -97,7 +97,7 @@ public function renderBlock(FormView $view, $blockName, array $variables = array $resource = $this->engine->getResourceForBlockName($view, $blockName); if (!$resource) { - throw new FormException(sprintf('No block "%s" found while rendering the form.', $blockName)); + throw new Exception(sprintf('No block "%s" found while rendering the form.', $blockName)); } // Merge the passed with the existing attributes @@ -217,7 +217,7 @@ public function searchAndRenderBlock(FormView $view, $blockNameSuffix, array $va // Escape if no resource exists for this block if (!$resource) { - throw new FormException(sprintf( + throw new Exception(sprintf( 'Unable to render the form as none of the following blocks exist: "%s".', implode('", "', array_reverse($blockNameHierarchy)) )); diff --git a/PreloadedExtension.php b/PreloadedExtension.php index 9219d8f22d..eac7b0582d 100644 --- a/PreloadedExtension.php +++ b/PreloadedExtension.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form; -use Symfony\Component\Form\Exception\FormException; +use Symfony\Component\Form\Exception\Exception; /** * A form extension with preloaded types, type exceptions and type guessers. @@ -55,7 +55,7 @@ public function __construct(array $types, array $typeExtensions, FormTypeGuesser public function getType($name) { if (!isset($this->types[$name])) { - throw new FormException(sprintf('The type "%s" can not be loaded by this extension', $name)); + throw new Exception(sprintf('The type "%s" can not be loaded by this extension', $name)); } return $this->types[$name]; diff --git a/ResolvedFormType.php b/ResolvedFormType.php index 04dc865a5e..d889d0df5a 100644 --- a/ResolvedFormType.php +++ b/ResolvedFormType.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form; -use Symfony\Component\Form\Exception\FormException; +use Symfony\Component\Form\Exception\Exception; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -46,7 +46,7 @@ class ResolvedFormType implements ResolvedFormTypeInterface public function __construct(FormTypeInterface $innerType, array $typeExtensions = array(), ResolvedFormTypeInterface $parent = null) { if (!preg_match('/^[a-z0-9_]*$/i', $innerType->getName())) { - throw new FormException(sprintf( + throw new Exception(sprintf( 'The "%s" form type name ("%s") is not valid. Names must only contain letters, numbers, and "_".', get_class($innerType), $innerType->getName() diff --git a/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php b/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php index 1a7ded0501..6a6a48c7d6 100644 --- a/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php @@ -82,7 +82,7 @@ public function testGetValuesForChoices() } /** - * @expectedException \Symfony\Component\Form\Exception\FormException + * @expectedException \Symfony\Component\Form\Exception\Exception */ public function testLoadChoiceListShouldReturnChoiceList() { diff --git a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php index 771a37e119..ff449610a5 100644 --- a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php @@ -193,7 +193,7 @@ public function testInitArrayUsesToString() } /** - * @expectedException \Symfony\Component\Form\Exception\FormException + * @expectedException \Symfony\Component\Form\Exception\Exception */ public function testInitArrayThrowsExceptionIfToStringNotFound() { diff --git a/Tests/Extension/Core/Type/ChoiceTypeTest.php b/Tests/Extension/Core/Type/ChoiceTypeTest.php index 98016e3ad4..61ce5e7c58 100644 --- a/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -89,7 +89,7 @@ public function testChoiceListOptionExpectsChoiceListInterface() } /** - * expectedException \Symfony\Component\Form\Exception\FormException + * expectedException \Symfony\Component\Form\Exception\Exception */ public function testEitherChoiceListOrChoicesMustBeSet() { diff --git a/Tests/FormBuilderTest.php b/Tests/FormBuilderTest.php index 4ccb4ae76e..96e1d63c7c 100644 --- a/Tests/FormBuilderTest.php +++ b/Tests/FormBuilderTest.php @@ -162,7 +162,7 @@ public function testCreateNoTypeNo() public function testGetUnknown() { - $this->setExpectedException('Symfony\Component\Form\Exception\FormException', 'The child with the name "foo" does not exist.'); + $this->setExpectedException('Symfony\Component\Form\Exception\Exception', 'The child with the name "foo" does not exist.'); $this->builder->get('foo'); } diff --git a/Tests/FormRegistryTest.php b/Tests/FormRegistryTest.php index d6add6fdb0..50aec90d4f 100644 --- a/Tests/FormRegistryTest.php +++ b/Tests/FormRegistryTest.php @@ -188,7 +188,7 @@ public function testGetTypeConnectsParentIfGetParentReturnsInstance() } /** - * @expectedException \Symfony\Component\Form\Exception\FormException + * @expectedException \Symfony\Component\Form\Exception\Exception */ public function testGetTypeThrowsExceptionIfParentNotFound() { @@ -200,7 +200,7 @@ public function testGetTypeThrowsExceptionIfParentNotFound() } /** - * @expectedException \Symfony\Component\Form\Exception\FormException + * @expectedException \Symfony\Component\Form\Exception\Exception */ public function testGetTypeThrowsExceptionIfTypeNotFound() { diff --git a/Tests/SimpleFormTest.php b/Tests/SimpleFormTest.php index 6d13d4a568..0d72df3acb 100644 --- a/Tests/SimpleFormTest.php +++ b/Tests/SimpleFormTest.php @@ -741,7 +741,7 @@ public function testSetNullParentWorksWithEmptyName() } /** - * @expectedException \Symfony\Component\Form\Exception\FormException + * @expectedException \Symfony\Component\Form\Exception\Exception * @expectedExceptionMessage A form with an empty name cannot have a parent form. */ public function testFormCannotHaveEmptyNameNotInRootLevel() @@ -787,7 +787,7 @@ public function testGetPropertyPathDefaultsToIndexedNameIfParentDataClassIsNull( } /** - * @expectedException \Symfony\Component\Form\Exception\FormException + * @expectedException \Symfony\Component\Form\Exception\Exception */ public function testViewDataMustNotBeObjectIfDataClassIsNull() { @@ -817,7 +817,7 @@ public function testViewDataMayBeArrayAccessIfDataClassIsNull() } /** - * @expectedException \Symfony\Component\Form\Exception\FormException + * @expectedException \Symfony\Component\Form\Exception\Exception */ public function testViewDataMustBeObjectIfDataClassIsSet() { @@ -832,7 +832,7 @@ public function testViewDataMustBeObjectIfDataClassIsSet() } /** - * @expectedException \Symfony\Component\Form\Exception\FormException + * @expectedException \Symfony\Component\Form\Exception\Exception */ public function testSetDataCannotInvokeItself() { diff --git a/Tests/Util/PropertyPathCollectionTest.php b/Tests/Util/PropertyPathCollectionTest.php index 21e9d04847..2f7589663e 100644 --- a/Tests/Util/PropertyPathCollectionTest.php +++ b/Tests/Util/PropertyPathCollectionTest.php @@ -285,7 +285,7 @@ public function testNoAdderAndRemoverThrowsSensibleError($car, $path, $message) try { $path->setValue($car, $axes); $this->fail('An expected exception was not thrown!'); - } catch (\Symfony\Component\Form\Exception\FormException $e) { + } catch (\Symfony\Component\Form\Exception\Exception $e) { $this->assertEquals($message, $e->getMessage()); } } From 21541cbfdf63642b74d550efa1a0a4d5719c0b6a Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Sat, 5 Jan 2013 18:40:19 +0100 Subject: [PATCH 046/447] [Form] Protected methods in FormConfigBuilder and FormBuilder from being called when it is turned into a FormConfigInterface instance --- CHANGELOG.md | 2 + Exception/BadMethodCallException.php | 21 ++++++ FormBuilder.php | 104 ++++++++++++++++++--------- FormConfigBuilder.php | 75 ++++++++++--------- 4 files changed, 135 insertions(+), 67 deletions(-) create mode 100644 Exception/BadMethodCallException.php diff --git a/CHANGELOG.md b/CHANGELOG.md index d0d298f9df..c229302a5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ CHANGELOG * removed special characters between the choice or text fields of DateType unless the option "format" is set to a custom value * deprecated FormException and introduced ExceptionInterface instead + * [BC BREAK] FormException is now an interface + * protected FormBuilder methods from being called when it is turned into a FormConfigInterface with getFormConfig() 2.1.0 ----- diff --git a/Exception/BadMethodCallException.php b/Exception/BadMethodCallException.php new file mode 100644 index 0000000000..27649dd022 --- /dev/null +++ b/Exception/BadMethodCallException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Exception; + +/** + * Base BadMethodCallException for the Form component. + * + * @author Bernhard Schussek + */ +class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface +{ +} diff --git a/FormBuilder.php b/FormBuilder.php index 428044e21a..0cec9b9426 100644 --- a/FormBuilder.php +++ b/FormBuilder.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form; +use Symfony\Component\Form\Exception\BadMethodCallException; use Symfony\Component\Form\Exception\Exception; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -65,7 +66,7 @@ public function __construct($name, $dataClass, EventDispatcherInterface $dispatc public function add($child, $type = null, array $options = array()) { if ($this->locked) { - throw new Exception('The form builder cannot be modified anymore.'); + throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if ($child instanceof self) { @@ -102,7 +103,7 @@ public function add($child, $type = null, array $options = array()) public function create($name, $type = null, array $options = array()) { if ($this->locked) { - throw new Exception('The form builder cannot be modified anymore.'); + throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if (null === $type && null === $this->getDataClass()) { @@ -121,6 +122,10 @@ public function create($name, $type = null, array $options = array()) */ public function get($name) { + if ($this->locked) { + throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); + } + if (isset($this->unresolvedChildren[$name])) { return $this->resolveChild($name); } @@ -138,7 +143,7 @@ public function get($name) public function remove($name) { if ($this->locked) { - throw new Exception('The form builder cannot be modified anymore.'); + throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } unset($this->unresolvedChildren[$name]); @@ -158,6 +163,10 @@ public function remove($name) */ public function has($name) { + if ($this->locked) { + throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); + } + if (isset($this->unresolvedChildren[$name])) { return true; } @@ -174,6 +183,10 @@ public function has($name) */ public function all() { + if ($this->locked) { + throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); + } + $this->resolveChildren(); return $this->children; @@ -184,6 +197,10 @@ public function all() */ public function count() { + if ($this->locked) { + throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); + } + return count($this->children); } @@ -192,6 +209,10 @@ public function count() */ public function getForm() { + if ($this->locked) { + throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); + } + $this->resolveChildren(); $form = new Form($this->getFormConfig()); @@ -208,6 +229,10 @@ public function getForm() */ public function getParent() { + if ($this->locked) { + throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); + } + return $this->parent; } @@ -217,7 +242,7 @@ public function getParent() public function setParent(FormBuilderInterface $parent = null) { if ($this->locked) { - throw new Exception('The form builder cannot be modified anymore.'); + throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->parent = $parent; @@ -230,36 +255,11 @@ public function setParent(FormBuilderInterface $parent = null) */ public function hasParent() { - return null !== $this->parent; - } - - /** - * Converts an unresolved child into a {@link FormBuilder} instance. - * - * @param string $name The name of the unresolved child. - * - * @return FormBuilder The created instance. - */ - private function resolveChild($name) - { - $info = $this->unresolvedChildren[$name]; - $child = $this->create($name, $info['type'], $info['options']); - $this->children[$name] = $child; - unset($this->unresolvedChildren[$name]); - - return $child; - } - - /** - * Converts all unresolved children into {@link FormBuilder} instances. - */ - private function resolveChildren() - { - foreach ($this->unresolvedChildren as $name => $info) { - $this->children[$name] = $this->create($name, $info['type'], $info['options']); + if ($this->locked) { + throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } - $this->unresolvedChildren = array(); + return null !== $this->parent; } /** @@ -267,6 +267,10 @@ private function resolveChildren() */ public function getIterator() { + if ($this->locked) { + throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); + } + return new \ArrayIterator($this->children); } @@ -277,9 +281,16 @@ public function getIterator() * * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use * {@link FormConfigInterface::getType()} instead. + * + * @throws BadMethodCallException If the builder was turned into a {@link FormConfigInterface} + * via {@link getFormConfig()}. */ public function getTypes() { + if ($this->locked) { + throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); + } + trigger_error('getTypes() is deprecated since version 2.1 and will be removed in 2.3. Use getConfig() and FormConfigInterface::getType() instead.', E_USER_DEPRECATED); $types = array(); @@ -290,4 +301,33 @@ public function getTypes() return $types; } + + /** + * Converts an unresolved child into a {@link FormBuilder} instance. + * + * @param string $name The name of the unresolved child. + * + * @return FormBuilder The created instance. + */ + private function resolveChild($name) + { + $info = $this->unresolvedChildren[$name]; + $child = $this->create($name, $info['type'], $info['options']); + $this->children[$name] = $child; + unset($this->unresolvedChildren[$name]); + + return $child; + } + + /** + * Converts all unresolved children into {@link FormBuilder} instances. + */ + private function resolveChildren() + { + foreach ($this->unresolvedChildren as $name => $info) { + $this->children[$name] = $this->create($name, $info['type'], $info['options']); + } + + $this->unresolvedChildren = array(); + } } diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index 942e3346f4..1b428194f8 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form; +use Symfony\Component\Form\Exception\BadMethodCallException; use Symfony\Component\Form\Exception\Exception; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Util\PropertyPath; @@ -172,7 +173,7 @@ public function __construct($name, $dataClass, EventDispatcherInterface $dispatc public function addEventListener($eventName, $listener, $priority = 0) { if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->dispatcher->addListener($eventName, $listener, $priority); @@ -186,7 +187,7 @@ public function addEventListener($eventName, $listener, $priority = 0) public function addEventSubscriber(EventSubscriberInterface $subscriber) { if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->dispatcher->addSubscriber($subscriber); @@ -202,7 +203,7 @@ public function addValidator(FormValidatorInterface $validator) trigger_error('addValidator() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->validators[] = $validator; @@ -216,7 +217,7 @@ public function addValidator(FormValidatorInterface $validator) public function addViewTransformer(DataTransformerInterface $viewTransformer, $forcePrepend = false) { if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if ($forcePrepend) { @@ -234,7 +235,7 @@ public function addViewTransformer(DataTransformerInterface $viewTransformer, $f public function resetViewTransformers() { if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->viewTransformers = array(); @@ -249,7 +250,7 @@ public function resetViewTransformers() * * @return FormConfigBuilder The configuration object. * - * @throws Exception if the form configuration is locked + * @throws BadMethodCallException if the form configuration is locked * * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use * {@link addViewTransformer()} instead. @@ -259,7 +260,7 @@ public function appendClientTransformer(DataTransformerInterface $viewTransforme trigger_error('appendClientTransformer() is deprecated since version 2.1 and will be removed in 2.3. Use addViewTransformer() instead.', E_USER_DEPRECATED); if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } return $this->addViewTransformer($viewTransformer); @@ -272,7 +273,7 @@ public function appendClientTransformer(DataTransformerInterface $viewTransforme * * @return FormConfigBuilder The configuration object. * - * @throws Exception if the form configuration is locked + * @throws BadMethodCallException if the form configuration is locked * * @deprecated Deprecated since version 2.1, to be removed in 2.3. */ @@ -281,7 +282,7 @@ public function prependClientTransformer(DataTransformerInterface $viewTransform trigger_error('prependClientTransformer() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } return $this->addViewTransformer($viewTransformer, true); @@ -292,7 +293,7 @@ public function prependClientTransformer(DataTransformerInterface $viewTransform * * @return FormConfigBuilder The configuration object. * - * @throws Exception if the form configuration is locked + * @throws BadMethodCallException if the form configuration is locked * * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use * {@link resetViewTransformers()} instead. @@ -302,7 +303,7 @@ public function resetClientTransformers() trigger_error('resetClientTransformers() is deprecated since version 2.1 and will be removed in 2.3. Use resetViewTransformers() instead.', E_USER_DEPRECATED); if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } return $this->resetViewTransformers(); @@ -314,7 +315,7 @@ public function resetClientTransformers() public function addModelTransformer(DataTransformerInterface $modelTransformer, $forceAppend = false) { if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if ($forceAppend) { @@ -332,7 +333,7 @@ public function addModelTransformer(DataTransformerInterface $modelTransformer, public function resetModelTransformers() { if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->modelTransformers = array(); @@ -347,7 +348,7 @@ public function resetModelTransformers() * * @return FormConfigBuilder The configuration object. * - * @throws Exception if the form configuration is locked + * @throws BadMethodCallException if the form configuration is locked * * @deprecated Deprecated since version 2.1, to be removed in 2.3. */ @@ -356,7 +357,7 @@ public function appendNormTransformer(DataTransformerInterface $modelTransformer trigger_error('appendNormTransformer() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } return $this->addModelTransformer($modelTransformer, true); @@ -369,7 +370,7 @@ public function appendNormTransformer(DataTransformerInterface $modelTransformer * * @return FormConfigBuilder The configuration object. * - * @throws Exception if the form configuration is locked + * @throws BadMethodCallException if the form configuration is locked * * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use * {@link addModelTransformer()} instead. @@ -379,7 +380,7 @@ public function prependNormTransformer(DataTransformerInterface $modelTransforme trigger_error('prependNormTransformer() is deprecated since version 2.1 and will be removed in 2.3. Use addModelTransformer() instead.', E_USER_DEPRECATED); if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } return $this->addModelTransformer($modelTransformer); @@ -390,7 +391,7 @@ public function prependNormTransformer(DataTransformerInterface $modelTransforme * * @return FormConfigBuilder The configuration object. * - * @throws Exception if the form configuration is locked + * @throws BadMethodCallException if the form configuration is locked * * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use * {@link resetModelTransformers()} instead. @@ -400,7 +401,7 @@ public function resetNormTransformers() trigger_error('resetNormTransformers() is deprecated since version 2.1 and will be removed in 2.3. Use resetModelTransformers() instead.', E_USER_DEPRECATED); if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } return $this->resetModelTransformers(); @@ -652,7 +653,7 @@ public function getOption($name, $default = null) public function setAttribute($name, $value) { if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->attributes[$name] = $value; @@ -666,7 +667,7 @@ public function setAttribute($name, $value) public function setAttributes(array $attributes) { if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->attributes = $attributes; @@ -680,7 +681,7 @@ public function setAttributes(array $attributes) public function setDataMapper(DataMapperInterface $dataMapper = null) { if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->dataMapper = $dataMapper; @@ -694,7 +695,7 @@ public function setDataMapper(DataMapperInterface $dataMapper = null) public function setDisabled($disabled) { if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->disabled = (Boolean) $disabled; @@ -708,7 +709,7 @@ public function setDisabled($disabled) public function setEmptyData($emptyData) { if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->emptyData = $emptyData; @@ -722,7 +723,7 @@ public function setEmptyData($emptyData) public function setErrorBubbling($errorBubbling) { if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->errorBubbling = null === $errorBubbling ? null : (Boolean) $errorBubbling; @@ -736,7 +737,7 @@ public function setErrorBubbling($errorBubbling) public function setRequired($required) { if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->required = (Boolean) $required; @@ -750,7 +751,7 @@ public function setRequired($required) public function setPropertyPath($propertyPath) { if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } if (null !== $propertyPath && !$propertyPath instanceof PropertyPathInterface) { @@ -768,7 +769,7 @@ public function setPropertyPath($propertyPath) public function setMapped($mapped) { if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->mapped = $mapped; @@ -782,7 +783,7 @@ public function setMapped($mapped) public function setByReference($byReference) { if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->byReference = $byReference; @@ -796,7 +797,7 @@ public function setByReference($byReference) public function setVirtual($virtual) { if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->virtual = $virtual; @@ -810,7 +811,7 @@ public function setVirtual($virtual) public function setCompound($compound) { if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->compound = $compound; @@ -824,7 +825,7 @@ public function setCompound($compound) public function setType(ResolvedFormTypeInterface $type) { if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->type = $type; @@ -838,7 +839,7 @@ public function setType(ResolvedFormTypeInterface $type) public function setData($data) { if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->data = $data; @@ -852,7 +853,7 @@ public function setData($data) public function setDataLocked($locked) { if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->dataLocked = $locked; @@ -866,7 +867,7 @@ public function setDataLocked($locked) public function setFormFactory(FormFactoryInterface $formFactory) { if ($this->locked) { - throw new Exception('The config builder cannot be modified anymore.'); + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } $this->formFactory = $formFactory; @@ -879,6 +880,10 @@ public function setFormFactory(FormFactoryInterface $formFactory) */ public function getFormConfig() { + if ($this->locked) { + throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); + } + // This method should be idempotent, so clone the builder $config = clone $this; $config->locked = true; From eaf459a256947ec165b352fef3883db6850d022f Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Tue, 27 Nov 2012 23:17:30 +0100 Subject: [PATCH 047/447] [Form] Adapted Form component to translator integration in the validator --- .../ViolationMapper/ViolationMapper.php | 1 + FormError.php | 18 +++++++++++++----- Tests/AbstractDivLayoutTest.php | 6 +++--- Tests/AbstractLayoutTest.php | 8 ++++---- Tests/AbstractTableLayoutTest.php | 6 +++--- .../EventListener/ValidationListenerTest.php | 10 ++++------ .../ViolationMapper/ViolationMapperTest.php | 10 ++++++++-- 7 files changed, 36 insertions(+), 23 deletions(-) diff --git a/Extension/Validator/ViolationMapper/ViolationMapper.php b/Extension/Validator/ViolationMapper/ViolationMapper.php index 9ac6bb69b3..cece98804e 100644 --- a/Extension/Validator/ViolationMapper/ViolationMapper.php +++ b/Extension/Validator/ViolationMapper/ViolationMapper.php @@ -123,6 +123,7 @@ public function mapViolation(ConstraintViolation $violation, FormInterface $form // Only add the error if the form is synchronized if ($this->acceptsErrors($scope)) { $scope->addError(new FormError( + $violation->getMessage(), $violation->getMessageTemplate(), $violation->getMessageParameters(), $violation->getMessagePluralization() diff --git a/FormError.php b/FormError.php index b336a40388..343165ca46 100644 --- a/FormError.php +++ b/FormError.php @@ -18,6 +18,11 @@ */ class FormError { + /** + * @var string + */ + private $message; + /** * The template for the error message * @var string @@ -41,16 +46,19 @@ class FormError * * Any array key in $messageParameters will be used as a placeholder in * $messageTemplate. - * @see \Symfony\Component\Translation\Translator * - * @param string $messageTemplate The template for the error message + * @param string $message The translated error message + * @param string|null $messageTemplate The template for the error message * @param array $messageParameters The parameters that should be * substituted in the message template. * @param integer|null $messagePluralization The value for error message pluralization + * + * @see \Symfony\Component\Translation\Translator */ - public function __construct($messageTemplate, array $messageParameters = array(), $messagePluralization = null) + public function __construct($message, $messageTemplate = null, array $messageParameters = array(), $messagePluralization = null) { - $this->messageTemplate = $messageTemplate; + $this->message = $message; + $this->messageTemplate = $messageTemplate ?: $message; $this->messageParameters = $messageParameters; $this->messagePluralization = $messagePluralization; } @@ -62,7 +70,7 @@ public function __construct($messageTemplate, array $messageParameters = array() */ public function getMessage() { - return strtr($this->messageTemplate, $this->messageParameters); + return $this->message; } /** diff --git a/Tests/AbstractDivLayoutTest.php b/Tests/AbstractDivLayoutTest.php index ac9b18b065..7fd743006e 100644 --- a/Tests/AbstractDivLayoutTest.php +++ b/Tests/AbstractDivLayoutTest.php @@ -19,7 +19,7 @@ abstract class AbstractDivLayoutTest extends AbstractLayoutTest public function testRow() { $form = $this->factory->createNamed('name', 'text'); - $form->addError(new FormError('Error!')); + $form->addError(new FormError('[trans]Error![/trans]')); $view = $form->createView(); $html = $this->renderRow($view); @@ -58,7 +58,7 @@ public function testRowOverrideVariables() public function testRepeatedRow() { $form = $this->factory->createNamed('name', 'repeated'); - $form->addError(new FormError('Error!')); + $form->addError(new FormError('[trans]Error![/trans]')); $view = $form->createView(); $html = $this->renderRow($view); @@ -398,7 +398,7 @@ public function testNestedFormError() ) ->getForm(); - $form->get('child')->addError(new FormError('Error!')); + $form->get('child')->addError(new FormError('[trans]Error![/trans]')); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index a7ff80e9de..e2801c2d8e 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -283,8 +283,8 @@ public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly public function testErrors() { $form = $this->factory->createNamed('name', 'text'); - $form->addError(new FormError('Error 1')); - $form->addError(new FormError('Error 2')); + $form->addError(new FormError('[trans]Error 1[/trans]')); + $form->addError(new FormError('[trans]Error 2[/trans]')); $view = $form->createView(); $html = $this->renderErrors($view); @@ -1151,7 +1151,7 @@ public function testDateErrorBubbling() { $child = $this->factory->createNamed('date', 'date'); $form = $this->factory->createNamed('form', 'form')->add($child); - $child->addError(new FormError('Error!')); + $child->addError(new FormError('[trans]Error![/trans]')); $view = $form->createView(); $this->assertEmpty($this->renderErrors($view)); @@ -1676,7 +1676,7 @@ public function testTimeErrorBubbling() { $child = $this->factory->createNamed('time', 'time'); $form = $this->factory->createNamed('form', 'form')->add($child); - $child->addError(new FormError('Error!')); + $child->addError(new FormError('[trans]Error![/trans]')); $view = $form->createView(); $this->assertEmpty($this->renderErrors($view)); diff --git a/Tests/AbstractTableLayoutTest.php b/Tests/AbstractTableLayoutTest.php index efa957fb0b..e0f62c4ab1 100644 --- a/Tests/AbstractTableLayoutTest.php +++ b/Tests/AbstractTableLayoutTest.php @@ -18,7 +18,7 @@ abstract class AbstractTableLayoutTest extends AbstractLayoutTest public function testRow() { $form = $this->factory->createNamed('name', 'text'); - $form->addError(new FormError('Error!')); + $form->addError(new FormError('[trans]Error![/trans]')); $view = $form->createView(); $html = $this->renderRow($view); @@ -91,7 +91,7 @@ public function testRepeatedRow() public function testRepeatedRowWithErrors() { $form = $this->factory->createNamed('name', 'repeated'); - $form->addError(new FormError('Error!')); + $form->addError(new FormError('[trans]Error![/trans]')); $view = $form->createView(); $html = $this->renderRow($view); @@ -250,7 +250,7 @@ public function testNestedFormError() ) ->getForm(); - $form->get('child')->addError(new FormError('Error!')); + $form->get('child')->addError(new FormError('[trans]Error![/trans]')); $this->assertWidgetMatchesXpath($form->createView(), array(), '/table diff --git a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php index 7e358910e2..d9555e13e1 100644 --- a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php +++ b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php @@ -49,6 +49,8 @@ class ValidationListenerTest extends \PHPUnit_Framework_TestCase private $message; + private $messageTemplate; + private $params; protected function setUp() @@ -63,17 +65,13 @@ protected function setUp() $this->violationMapper = $this->getMock('Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapperInterface'); $this->listener = new ValidationListener($this->validator, $this->violationMapper); $this->message = 'Message'; + $this->messageTemplate = 'Message template'; $this->params = array('foo' => 'bar'); } private function getConstraintViolation($code = null) { - return new ConstraintViolation($this->message, $this->params, null, 'prop.path', null, null, $code); - } - - private function getFormError() - { - return new FormError($this->message, $this->params); + return new ConstraintViolation($this->message, $this->messageTemplate, $this->params, null, 'prop.path', null, null, $code); } private function getBuilder($name = 'name', $propertyPath = null, $dataClass = null) diff --git a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php index e192f07108..2f41a99101 100644 --- a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php +++ b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php @@ -48,6 +48,11 @@ class ViolationMapperTest extends \PHPUnit_Framework_TestCase */ private $message; + /** + * @var string + */ + private $messageTemplate; + /** * @var array */ @@ -62,6 +67,7 @@ protected function setUp() $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->mapper = new ViolationMapper(); $this->message = 'Message'; + $this->messageTemplate = 'Message template'; $this->params = array('foo' => 'bar'); } @@ -101,7 +107,7 @@ private function getDataMapper() */ protected function getConstraintViolation($propertyPath) { - return new ConstraintViolation($this->message, $this->params, null, $propertyPath, null); + return new ConstraintViolation($this->message, $this->messageTemplate, $this->params, null, $propertyPath, null); } /** @@ -109,7 +115,7 @@ protected function getConstraintViolation($propertyPath) */ protected function getFormError() { - return new FormError($this->message, $this->params); + return new FormError($this->message, $this->messageTemplate, $this->params); } public function testMapToVirtualFormIfDataDoesNotMatch() From 4be01612c7b04bcbe027502b390d302ba7841ba3 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Wed, 28 Nov 2012 14:07:07 +0100 Subject: [PATCH 048/447] [Form][Validator] Added BC breaks in unstable code to the CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c229302a5e..d8e309637f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ CHANGELOG * deprecated FormException and introduced ExceptionInterface instead * [BC BREAK] FormException is now an interface * protected FormBuilder methods from being called when it is turned into a FormConfigInterface with getFormConfig() + * [BC BREAK] inserted argument `$message` in the constructor of `FormError` 2.1.0 ----- From 29ad3e95bd801ae8e55f4d4dfc73a7e1e871543f Mon Sep 17 00:00:00 2001 From: Pascal Borreli Date: Tue, 8 Jan 2013 18:19:54 +0000 Subject: [PATCH 049/447] Fixed typos --- Form.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Form.php b/Form.php index ad44f15d35..eb93637877 100644 --- a/Form.php +++ b/Form.php @@ -542,7 +542,7 @@ public function bind($submittedData) } // Check whether the form is compound. - // This check is preferrable over checking the number of children, + // This check is preferable over checking the number of children, // since forms without children may also be compound. // (think of empty collection forms) if ($this->config->getCompound()) { @@ -837,7 +837,7 @@ public function all() */ public function getChildren() { - trigger_error('getChilren() is deprecated since version 2.1 and will be removed in 2.3. Use all() instead.', E_USER_DEPRECATED); + trigger_error('getChildren() is deprecated since version 2.1 and will be removed in 2.3. Use all() instead.', E_USER_DEPRECATED); return $this->all(); } From 1a7ac1de74f5bb99c586f4f05f2344a6caaf4e58 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Wed, 9 Jan 2013 10:35:45 +0100 Subject: [PATCH 050/447] [Form] Fixed regression introduced when merging 2.1 into master --- FormBuilder.php | 1 - Tests/FormBuilderTest.php | 3 --- 2 files changed, 4 deletions(-) diff --git a/FormBuilder.php b/FormBuilder.php index 9d11b5f750..0dfd8d0962 100644 --- a/FormBuilder.php +++ b/FormBuilder.php @@ -211,7 +211,6 @@ public function getFormConfig() { $config = parent::getFormConfig(); - $config->factory = null; $config->parent = null; $config->children = array(); $config->unresolvedChildren = array(); diff --git a/Tests/FormBuilderTest.php b/Tests/FormBuilderTest.php index 6836ea140d..14c8746f8b 100644 --- a/Tests/FormBuilderTest.php +++ b/Tests/FormBuilderTest.php @@ -247,17 +247,14 @@ public function testGetFormConfigErasesReferences() $config = $builder->getFormConfig(); $reflClass = new \ReflectionClass($config); - $factory = $reflClass->getProperty('factory'); $parent = $reflClass->getProperty('parent'); $children = $reflClass->getProperty('children'); $unresolvedChildren = $reflClass->getProperty('unresolvedChildren'); - $factory->setAccessible(true); $parent->setAccessible(true); $children->setAccessible(true); $unresolvedChildren->setAccessible(true); - $this->assertNull($factory->getValue($config)); $this->assertNull($parent->getValue($config)); $this->assertEmpty($children->getValue($config)); $this->assertEmpty($unresolvedChildren->getValue($config)); From 891d9e5ec2801d87c611b2a2243a7f0c4a2af053 Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Thu, 10 Jan 2013 02:11:10 +0100 Subject: [PATCH 051/447] Enhanced the triggering of E_USER_DEPRECATED errors - Removed useless error handlers around FormEvent as the triggering has been fixed in it. - Enhanced the triggering of deprecation errors for places where the BC method provide some user logic needing to be converted to a new way. - Enhanced the deprecation messages to mention the replacement whenever possible. --- AbstractType.php | 22 +++++++++----- AbstractTypeExtension.php | 22 +++++++++----- CallbackValidator.php | 2 +- Form.php | 23 +++++++++----- FormBuilder.php | 4 +-- Test/DeprecationErrorHandler.php | 12 -------- Tests/CompoundFormTest.php | 4 +-- .../FixRadioInputListenerTest.php | 8 ++--- .../FixUrlProtocolListenerTest.php | 8 ++--- .../MergeCollectionListenerTest.php | 20 ++++++------- .../EventListener/ResizeFormListenerTest.php | 30 +++++++++---------- .../Core/EventListener/TrimListenerTest.php | 8 ++--- .../CsrfValidationListenerTest.php | 4 +-- .../EventListener/BindRequestListenerTest.php | 18 +++++------ .../EventListener/ValidationListenerTest.php | 10 +++---- Tests/SimpleFormTest.php | 3 +- 16 files changed, 101 insertions(+), 97 deletions(-) diff --git a/AbstractType.php b/AbstractType.php index 00d374b7f7..8769415ea6 100644 --- a/AbstractType.php +++ b/AbstractType.php @@ -51,10 +51,20 @@ public function finishView(FormView $view, FormInterface $form, array $options) */ public function setDefaultOptions(OptionsResolverInterface $resolver) { - set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC')); - $resolver->setDefaults($this->getDefaultOptions(array())); - $resolver->addAllowedValues($this->getAllowedOptionValues(array())); - restore_error_handler(); + $defaults = $this->getDefaultOptions(array()); + $allowedTypes = $this->getAllowedOptionValues(array()); + + if (!empty($defaults)) { + trigger_error('getDefaultOptions() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED); + + $resolver->setDefaults($defaults); + } + + if (!empty($allowedTypes)) { + trigger_error('getAllowedOptionValues() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED); + + $resolver->addAllowedValues($allowedTypes); + } } /** @@ -69,8 +79,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) */ public function getDefaultOptions(array $options) { - trigger_error('getDefaultOptions() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED); - return array(); } @@ -86,8 +94,6 @@ public function getDefaultOptions(array $options) */ public function getAllowedOptionValues(array $options) { - trigger_error('getAllowedOptionValues() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED); - return array(); } diff --git a/AbstractTypeExtension.php b/AbstractTypeExtension.php index 38f4a8f1b6..3e51ed442b 100644 --- a/AbstractTypeExtension.php +++ b/AbstractTypeExtension.php @@ -44,10 +44,20 @@ public function finishView(FormView $view, FormInterface $form, array $options) */ public function setDefaultOptions(OptionsResolverInterface $resolver) { - set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC')); - $resolver->setDefaults($this->getDefaultOptions()); - $resolver->addAllowedValues($this->getAllowedOptionValues()); - restore_error_handler(); + $defaults = $this->getDefaultOptions(array()); + $allowedTypes = $this->getAllowedOptionValues(array()); + + if (!empty($defaults)) { + trigger_error('getDefaultOptions() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED); + + $resolver->setDefaults($defaults); + } + + if (!empty($allowedTypes)) { + trigger_error('getAllowedOptionValues() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED); + + $resolver->addAllowedValues($allowedTypes); + } } /** @@ -60,8 +70,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) */ public function getDefaultOptions() { - trigger_error('getDefaultOptions() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED); - return array(); } @@ -75,8 +83,6 @@ public function getDefaultOptions() */ public function getAllowedOptionValues() { - trigger_error('getAllowedOptionValues() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED); - return array(); } } diff --git a/CallbackValidator.php b/CallbackValidator.php index 0e7c8012eb..f769cc7cbd 100644 --- a/CallbackValidator.php +++ b/CallbackValidator.php @@ -27,7 +27,7 @@ class CallbackValidator implements FormValidatorInterface */ public function __construct($callback) { - trigger_error('CallbackValidator is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); + trigger_error('CallbackValidator is deprecated since version 2.1 and will be removed in 2.3. Use the FormEvents::POST_BIND event instead.', E_USER_DEPRECATED); $this->callback = $callback; } diff --git a/Form.php b/Form.php index eb93637877..eb729ebc1f 100644 --- a/Form.php +++ b/Form.php @@ -367,11 +367,12 @@ public function setData($modelData) // Hook to change content of the data if ($dispatcher->hasListeners(FormEvents::PRE_SET_DATA) || $dispatcher->hasListeners(FormEvents::SET_DATA)) { - set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC')); $event = new FormEvent($this, $modelData); - restore_error_handler(); $dispatcher->dispatch(FormEvents::PRE_SET_DATA, $event); // BC until 2.3 + if ($dispatcher->hasListeners(FormEvents::SET_DATA)) { + trigger_error('The FormEvents::SET_DATA event is deprecated since 2.1 and will be removed in 2.3. Use the FormEvents::PRE_SET_DATA event instead.', E_USER_DEPRECATED); + } $dispatcher->dispatch(FormEvents::SET_DATA, $event); $modelData = $event->getData(); } @@ -532,11 +533,12 @@ public function bind($submittedData) // Hook to change content of the data bound by the browser if ($dispatcher->hasListeners(FormEvents::PRE_BIND) || $dispatcher->hasListeners(FormEvents::BIND_CLIENT_DATA)) { - set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC')); $event = new FormEvent($this, $submittedData); - restore_error_handler(); $dispatcher->dispatch(FormEvents::PRE_BIND, $event); // BC until 2.3 + if ($dispatcher->hasListeners(FormEvents::BIND_CLIENT_DATA)) { + trigger_error('The FormEvents::BIND_CLIENT_DATA event is deprecated since 2.1 and will be removed in 2.3. Use the FormEvents::PRE_BIND event instead.', E_USER_DEPRECATED); + } $dispatcher->dispatch(FormEvents::BIND_CLIENT_DATA, $event); $submittedData = $event->getData(); } @@ -594,11 +596,12 @@ public function bind($submittedData) // Hook to change content of the data into the normalized // representation if ($dispatcher->hasListeners(FormEvents::BIND) || $dispatcher->hasListeners(FormEvents::BIND_NORM_DATA)) { - set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC')); $event = new FormEvent($this, $normData); - restore_error_handler(); $dispatcher->dispatch(FormEvents::BIND, $event); // BC until 2.3 + if ($dispatcher->hasListeners(FormEvents::BIND_NORM_DATA)) { + trigger_error('The FormEvents::BIND_NORM_DATA event is deprecated since 2.1 and will be removed in 2.3. Use the FormEvents::BIND event instead.', E_USER_DEPRECATED); + } $dispatcher->dispatch(FormEvents::BIND_NORM_DATA, $event); $normData = $event->getData(); } @@ -621,10 +624,14 @@ public function bind($submittedData) } set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC')); - foreach ($this->config->getValidators() as $validator) { + $validators = $this->config->getValidators(); + restore_error_handler(); + + foreach ($validators as $validator) { + trigger_error(sprintf('FormConfigInterface::getValidators() is deprecated since 2.1 and will be removed in 2.3. Convert your %s class to a listener on the FormEvents::POST_BIND event.', get_class($validator)), E_USER_DEPRECATED); + $validator->validate($this); } - restore_error_handler(); return $this; } diff --git a/FormBuilder.php b/FormBuilder.php index 0dfd8d0962..a47d969e05 100644 --- a/FormBuilder.php +++ b/FormBuilder.php @@ -301,12 +301,12 @@ public function getIterator() */ public function getTypes() { + trigger_error('getTypes() is deprecated since version 2.1 and will be removed in 2.3. Use getConfig() and FormConfigInterface::getType() instead.', E_USER_DEPRECATED); + if ($this->locked) { throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } - trigger_error('getTypes() is deprecated since version 2.1 and will be removed in 2.3. Use getConfig() and FormConfigInterface::getType() instead.', E_USER_DEPRECATED); - $types = array(); for ($type = $this->getType(); null !== $type; $type = $type->getParent()) { diff --git a/Test/DeprecationErrorHandler.php b/Test/DeprecationErrorHandler.php index 8c6dd90831..21b3a6e6b0 100644 --- a/Test/DeprecationErrorHandler.php +++ b/Test/DeprecationErrorHandler.php @@ -2,9 +2,6 @@ namespace Symfony\Component\Form\Test; -use Symfony\Component\Form\FormInterface as NonTestFormInterface; -use Symfony\Component\Form\FormEvent; - class DeprecationErrorHandler { public static function handle($errorNumber, $message, $file, $line, $context) @@ -24,13 +21,4 @@ public static function handleBC($errorNumber, $message, $file, $line, $context) return false; } - - public static function getFormEvent(NonTestFormInterface $form, $data) - { - set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); - $event = new FormEvent($form, $data); - restore_error_handler(); - - return $event; - } } diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index 9f1ce08d9e..ca97c8ec2a 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -231,9 +231,7 @@ public function testRemove() $this->form->remove('foo'); $this->assertNull($child->getParent()); - set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); - $this->assertFalse($this->form->hasChildren()); - restore_error_handler(); + $this->assertCount(0, $this->form); } /** diff --git a/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php b/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php index 5a7f5e7d17..35bc7323dd 100644 --- a/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php +++ b/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php @@ -11,9 +11,9 @@ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; +use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Core\EventListener\FixRadioInputListener; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; -use Symfony\Component\Form\Test\DeprecationErrorHandler; class FixRadioInputListenerTest extends \PHPUnit_Framework_TestCase { @@ -42,7 +42,7 @@ public function testFixRadio() { $data = '1'; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); - $event = DeprecationErrorHandler::getFormEvent($form, $data); + $event = new FormEvent($form, $data); $this->listener->preBind($event); @@ -53,7 +53,7 @@ public function testFixZero() { $data = '0'; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); - $event = DeprecationErrorHandler::getFormEvent($form, $data); + $event = new FormEvent($form, $data); $this->listener->preBind($event); @@ -64,7 +64,7 @@ public function testIgnoreEmptyString() { $data = ''; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); - $event = DeprecationErrorHandler::getFormEvent($form, $data); + $event = new FormEvent($form, $data); $this->listener->preBind($event); diff --git a/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php b/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php index 70db9b421e..2517f40b04 100644 --- a/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php +++ b/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; +use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Core\EventListener\FixUrlProtocolListener; -use Symfony\Component\Form\Test\DeprecationErrorHandler; class FixUrlProtocolListenerTest extends \PHPUnit_Framework_TestCase { @@ -27,7 +27,7 @@ public function testFixHttpUrl() { $data = "www.symfony.com"; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); - $event = DeprecationErrorHandler::getFormEvent($form, $data); + $event = new FormEvent($form, $data); $filter = new FixUrlProtocolListener('http'); $filter->onBind($event); @@ -39,7 +39,7 @@ public function testSkipKnownUrl() { $data = "http://www.symfony.com"; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); - $event = DeprecationErrorHandler::getFormEvent($form, $data); + $event = new FormEvent($form, $data); $filter = new FixUrlProtocolListener('http'); $filter->onBind($event); @@ -51,7 +51,7 @@ public function testSkipOtherProtocol() { $data = "ftp://www.symfony.com"; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); - $event = DeprecationErrorHandler::getFormEvent($form, $data); + $event = new FormEvent($form, $data); $filter = new FixUrlProtocolListener('http'); $filter->onBind($event); diff --git a/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php b/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php index bf83e057e9..b6ca56e7a4 100644 --- a/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php +++ b/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; +use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Core\EventListener\MergeCollectionListener; -use Symfony\Component\Form\Test\DeprecationErrorHandler; abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase { @@ -84,7 +84,7 @@ public function testAddExtraEntriesIfAllowAdd($allowDelete) $this->form->setData($originalData); - $event = DeprecationErrorHandler::getFormEvent($this->form, $newData); + $event = new FormEvent($this->form, $newData); $listener->onBind($event); // The original object was modified @@ -108,7 +108,7 @@ public function testAddExtraEntriesIfAllowAddDontOverwriteExistingIndices($allow $this->form->setData($originalData); - $event = DeprecationErrorHandler::getFormEvent($this->form, $newData); + $event = new FormEvent($this->form, $newData); $listener->onBind($event); // The original object was modified @@ -133,7 +133,7 @@ public function testDoNothingIfNotAllowAdd($allowDelete) $this->form->setData($originalData); - $event = DeprecationErrorHandler::getFormEvent($this->form, $newData); + $event = new FormEvent($this->form, $newData); $listener->onBind($event); // We still have the original object @@ -157,7 +157,7 @@ public function testRemoveMissingEntriesIfAllowDelete($allowAdd) $this->form->setData($originalData); - $event = DeprecationErrorHandler::getFormEvent($this->form, $newData); + $event = new FormEvent($this->form, $newData); $listener->onBind($event); // The original object was modified @@ -182,7 +182,7 @@ public function testDoNothingIfNotAllowDelete($allowAdd) $this->form->setData($originalData); - $event = DeprecationErrorHandler::getFormEvent($this->form, $newData); + $event = new FormEvent($this->form, $newData); $listener->onBind($event); // We still have the original object @@ -201,7 +201,7 @@ public function testDoNothingIfNotAllowDelete($allowAdd) public function testRequireArrayOrTraversable($allowAdd, $allowDelete) { $newData = 'no array or traversable'; - $event = DeprecationErrorHandler::getFormEvent($this->form, $newData); + $event = new FormEvent($this->form, $newData); $listener = new MergeCollectionListener($allowAdd, $allowDelete); $listener->onBind($event); } @@ -215,7 +215,7 @@ public function testDealWithNullData() $this->form->setData($originalData); - $event = DeprecationErrorHandler::getFormEvent($this->form, $newData); + $event = new FormEvent($this->form, $newData); $listener->onBind($event); $this->assertSame($originalData, $event->getData()); @@ -233,7 +233,7 @@ public function testDealWithNullOriginalDataIfAllowAdd($allowDelete) $this->form->setData($originalData); - $event = DeprecationErrorHandler::getFormEvent($this->form, $newData); + $event = new FormEvent($this->form, $newData); $listener->onBind($event); $this->assertSame($newData, $event->getData()); @@ -251,7 +251,7 @@ public function testDontDealWithNullOriginalDataIfNotAllowAdd($allowDelete) $this->form->setData($originalData); - $event = DeprecationErrorHandler::getFormEvent($this->form, $newData); + $event = new FormEvent($this->form, $newData); $listener->onBind($event); $this->assertNull($event->getData()); diff --git a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php index 459b1d7f24..5dfcc3d789 100644 --- a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php +++ b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php @@ -13,7 +13,7 @@ use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener; use Symfony\Component\Form\FormBuilder; -use Symfony\Component\Form\Test\DeprecationErrorHandler; +use Symfony\Component\Form\FormEvent; class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase { @@ -80,7 +80,7 @@ public function testPreSetDataResizesForm() ->will($this->returnValue($this->getForm('2'))); $data = array(1 => 'string', 2 => 'string'); - $event = DeprecationErrorHandler::getFormEvent($this->form, $data); + $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array('max_length' => '10'), false, false); $listener->preSetData($event); @@ -95,7 +95,7 @@ public function testPreSetDataResizesForm() public function testPreSetDataRequiresArrayOrTraversable() { $data = 'no array or traversable'; - $event = DeprecationErrorHandler::getFormEvent($this->form, $data); + $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, false); $listener->preSetData($event); } @@ -105,7 +105,7 @@ public function testPreSetDataDealsWithNullData() $this->factory->expects($this->never())->method('createNamed'); $data = null; - $event = DeprecationErrorHandler::getFormEvent($this->form, $data); + $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, false); $listener->preSetData($event); } @@ -120,7 +120,7 @@ public function testPreBindResizesUpIfAllowAdd() ->will($this->returnValue($this->getForm('1'))); $data = array(0 => 'string', 1 => 'string'); - $event = DeprecationErrorHandler::getFormEvent($this->form, $data); + $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array('max_length' => 10), true, false); $listener->preBind($event); @@ -134,7 +134,7 @@ public function testPreBindResizesDownIfAllowDelete() $this->form->add($this->getForm('1')); $data = array(0 => 'string'); - $event = DeprecationErrorHandler::getFormEvent($this->form, $data); + $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); $listener->preBind($event); @@ -148,7 +148,7 @@ public function testPreBindRemovesZeroKeys() $this->form->add($this->getForm('0')); $data = array(); - $event = DeprecationErrorHandler::getFormEvent($this->form, $data); + $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); $listener->preBind($event); @@ -161,7 +161,7 @@ public function testPreBindDoesNothingIfNotAllowAddNorAllowDelete() $this->form->add($this->getForm('1')); $data = array(0 => 'string', 2 => 'string'); - $event = DeprecationErrorHandler::getFormEvent($this->form, $data); + $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, false); $listener->preBind($event); @@ -176,7 +176,7 @@ public function testPreBindDoesNothingIfNotAllowAddNorAllowDelete() public function testPreBindRequiresArrayOrTraversable() { $data = 'no array or traversable'; - $event = DeprecationErrorHandler::getFormEvent($this->form, $data); + $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, false); $listener->preBind($event); } @@ -186,7 +186,7 @@ public function testPreBindDealsWithNullData() $this->form->add($this->getForm('1')); $data = null; - $event = DeprecationErrorHandler::getFormEvent($this->form, $data); + $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); $listener->preBind($event); @@ -199,7 +199,7 @@ public function testPreBindDealsWithEmptyData() $this->form->add($this->getForm('1')); $data = ''; - $event = DeprecationErrorHandler::getFormEvent($this->form, $data); + $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); $listener->preBind($event); @@ -211,7 +211,7 @@ public function testOnBindNormDataRemovesEntriesMissingInTheFormIfAllowDelete() $this->form->add($this->getForm('1')); $data = array(0 => 'first', 1 => 'second', 2 => 'third'); - $event = DeprecationErrorHandler::getFormEvent($this->form, $data); + $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); $listener->onBind($event); @@ -223,7 +223,7 @@ public function testOnBindNormDataDoesNothingIfNotAllowDelete() $this->form->add($this->getForm('1')); $data = array(0 => 'first', 1 => 'second', 2 => 'third'); - $event = DeprecationErrorHandler::getFormEvent($this->form, $data); + $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, false); $listener->onBind($event); @@ -236,7 +236,7 @@ public function testOnBindNormDataDoesNothingIfNotAllowDelete() public function testOnBindNormDataRequiresArrayOrTraversable() { $data = 'no array or traversable'; - $event = DeprecationErrorHandler::getFormEvent($this->form, $data); + $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, false); $listener->onBind($event); } @@ -246,7 +246,7 @@ public function testOnBindNormDataDealsWithNullData() $this->form->add($this->getForm('1')); $data = null; - $event = DeprecationErrorHandler::getFormEvent($this->form, $data); + $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); $listener->onBind($event); diff --git a/Tests/Extension/Core/EventListener/TrimListenerTest.php b/Tests/Extension/Core/EventListener/TrimListenerTest.php index 49419065d2..9e5d20db71 100644 --- a/Tests/Extension/Core/EventListener/TrimListenerTest.php +++ b/Tests/Extension/Core/EventListener/TrimListenerTest.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; +use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Core\EventListener\TrimListener; -use Symfony\Component\Form\Test\DeprecationErrorHandler; class TrimListenerTest extends \PHPUnit_Framework_TestCase { @@ -27,7 +27,7 @@ public function testTrim() { $data = " Foo! "; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); - $event = DeprecationErrorHandler::getFormEvent($form, $data); + $event = new FormEvent($form, $data); $filter = new TrimListener(); $filter->preBind($event); @@ -39,7 +39,7 @@ public function testTrimSkipNonStrings() { $data = 1234; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); - $event = DeprecationErrorHandler::getFormEvent($form, $data); + $event = new FormEvent($form, $data); $filter = new TrimListener(); $filter->preBind($event); @@ -60,7 +60,7 @@ public function testTrimUtf8($chars) $data = $data."ab\ncd".$data; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); - $event = DeprecationErrorHandler::getFormEvent($form, $data); + $event = new FormEvent($form, $data); $filter = new TrimListener(); $filter->preBind($event); diff --git a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php index 49c40d3b05..136ddbc1e0 100644 --- a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php +++ b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php @@ -12,8 +12,8 @@ namespace Symfony\Component\Form\Tests\Extension\Csrf\EventListener; use Symfony\Component\Form\FormBuilder; +use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener; -use Symfony\Component\Form\Test\DeprecationErrorHandler; class CsrfValidationListenerTest extends \PHPUnit_Framework_TestCase { @@ -67,7 +67,7 @@ protected function getMockForm() public function testStringFormData() { $data = "XP4HUzmHPi"; - $event = DeprecationErrorHandler::getFormEvent($this->form, $data); + $event = new FormEvent($this->form, $data); $validation = new CsrfValidationListener('csrf', $this->csrfProvider, 'unknown'); $validation->preBind($event); diff --git a/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php b/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php index 94ae47a3c4..bfb9afa0a7 100644 --- a/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php +++ b/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php @@ -14,9 +14,9 @@ use Symfony\Component\Form\Extension\HttpFoundation\EventListener\BindRequestListener; use Symfony\Component\Form\Form; use Symfony\Component\Form\FormConfigBuilder; +use Symfony\Component\Form\FormEvent; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\File\UploadedFile; -use Symfony\Component\Form\Test\DeprecationErrorHandler; /** * @author Bernhard Schussek @@ -98,7 +98,7 @@ public function testBindRequest($method) $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('author', null, $dispatcher); $form = new Form($config); - $event = DeprecationErrorHandler::getFormEvent($form, $request); + $event = new FormEvent($form, $request); $listener = new BindRequestListener(); $listener->preBind($event); @@ -125,7 +125,7 @@ public function testBindRequestWithEmptyName($method) $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('', null, $dispatcher); $form = new Form($config); - $event = DeprecationErrorHandler::getFormEvent($form, $request); + $event = new FormEvent($form, $request); $listener = new BindRequestListener(); $listener->preBind($event); @@ -154,7 +154,7 @@ public function testBindEmptyRequestToCompoundForm($method) $config->setCompound(true); $config->setDataMapper($this->getMock('Symfony\Component\Form\DataMapperInterface')); $form = new Form($config); - $event = DeprecationErrorHandler::getFormEvent($form, $request); + $event = new FormEvent($form, $request); $listener = new BindRequestListener(); $listener->preBind($event); @@ -180,7 +180,7 @@ public function testBindEmptyRequestToSimpleForm($method) $config = new FormConfigBuilder('author', null, $dispatcher); $config->setCompound(false); $form = new Form($config); - $event = DeprecationErrorHandler::getFormEvent($form, $request); + $event = new FormEvent($form, $request); $listener = new BindRequestListener(); $listener->preBind($event); @@ -203,7 +203,7 @@ public function testBindGetRequest() $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('author', null, $dispatcher); $form = new Form($config); - $event = DeprecationErrorHandler::getFormEvent($form, $request); + $event = new FormEvent($form, $request); $listener = new BindRequestListener(); $listener->preBind($event); @@ -227,7 +227,7 @@ public function testBindGetRequestWithEmptyName() $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $config = new FormConfigBuilder('', null, $dispatcher); $form = new Form($config); - $event = DeprecationErrorHandler::getFormEvent($form, $request); + $event = new FormEvent($form, $request); $listener = new BindRequestListener(); $listener->preBind($event); @@ -253,7 +253,7 @@ public function testBindEmptyGetRequestToCompoundForm() $config->setCompound(true); $config->setDataMapper($this->getMock('Symfony\Component\Form\DataMapperInterface')); $form = new Form($config); - $event = DeprecationErrorHandler::getFormEvent($form, $request); + $event = new FormEvent($form, $request); $listener = new BindRequestListener(); $listener->preBind($event); @@ -275,7 +275,7 @@ public function testBindEmptyGetRequestToSimpleForm() $config = new FormConfigBuilder('author', null, $dispatcher); $config->setCompound(false); $form = new Form($config); - $event = DeprecationErrorHandler::getFormEvent($form, $request); + $event = new FormEvent($form, $request); $listener = new BindRequestListener(); $listener->preBind($event); diff --git a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php index d9555e13e1..9c2ca410dd 100644 --- a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php +++ b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php @@ -11,14 +11,12 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\EventListener; -use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormBuilder; -use Symfony\Component\Form\FormError; +use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Util\PropertyPath; use Symfony\Component\Form\Extension\Validator\Constraints\Form; use Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener; use Symfony\Component\Validator\ConstraintViolation; -use Symfony\Component\Form\Test\DeprecationErrorHandler; class ValidationListenerTest extends \PHPUnit_Framework_TestCase { @@ -109,7 +107,7 @@ public function testMapViolation() ->method('mapViolation') ->with($violation, $form, false); - $this->listener->validateForm(DeprecationErrorHandler::getFormEvent($form, null)); + $this->listener->validateForm(new FormEvent($form, null)); } public function testMapViolationAllowsNonSyncIfInvalid() @@ -126,7 +124,7 @@ public function testMapViolationAllowsNonSyncIfInvalid() // pass true now ->with($violation, $form, true); - $this->listener->validateForm(DeprecationErrorHandler::getFormEvent($form, null)); + $this->listener->validateForm(new FormEvent($form, null)); } public function testValidateIgnoresNonRoot() @@ -142,6 +140,6 @@ public function testValidateIgnoresNonRoot() $this->violationMapper->expects($this->never()) ->method('mapViolation'); - $this->listener->validateForm(DeprecationErrorHandler::getFormEvent($form, null)); + $this->listener->validateForm(new FormEvent($form, null)); } } diff --git a/Tests/SimpleFormTest.php b/Tests/SimpleFormTest.php index 0d72df3acb..d0fe3347bd 100644 --- a/Tests/SimpleFormTest.php +++ b/Tests/SimpleFormTest.php @@ -648,7 +648,6 @@ public function testBindValidatesAfterTransformation() $form = $this->getBuilder() ->addValidator($validator) ->getForm(); - restore_error_handler(); $validator->expects($this->once()) ->method('validate') @@ -658,6 +657,8 @@ public function testBindValidatesAfterTransformation() })); $form->bind('foobar'); + + restore_error_handler(); } public function testBindResetsErrors() From f8a190659e7d473c98398da6d40abdae18689b32 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Mon, 7 Jan 2013 09:19:31 +0100 Subject: [PATCH 052/447] [PropertyAccess] Extracted PropertyAccess component out of Form --- CHANGELOG.md | 9 + Exception/InvalidPropertyException.php | 16 - Exception/InvalidPropertyPathException.php | 16 - Exception/PropertyAccessDeniedException.php | 16 - .../Core/ChoiceList/ObjectChoiceList.php | 61 +- Extension/Core/CoreExtension.php | 3 +- .../Core/DataMapper/PropertyPathMapper.php | 28 +- Extension/Core/Type/FormType.php | 14 +- .../ViolationMapper/RelativePath.php | 2 +- .../ViolationMapper/ViolationMapper.php | 8 +- .../ViolationMapper/ViolationPath.php | 4 +- .../ViolationMapper/ViolationPathIterator.php | 2 +- Form.php | 2 +- FormConfigBuilder.php | 4 +- FormConfigBuilderInterface.php | 24 +- FormConfigInterface.php | 2 +- FormInterface.php | 2 +- .../Core/ChoiceList/ObjectChoiceListTest.php | 3 + .../DataMapper/PropertyPathMapperTest.php | 66 +- Tests/Extension/Core/Type/ChoiceTypeTest.php | 2 - Tests/Extension/Core/Type/FormTypeTest.php | 2 +- .../EventListener/ValidationListenerTest.php | 2 +- .../ViolationMapper/ViolationMapperTest.php | 2 +- Tests/Fixtures/Magician.php | 27 - Tests/SimpleFormTest.php | 2 +- Tests/Util/FormUtilTest.php | 135 ---- Tests/Util/PropertyPathArrayObjectTest.php | 20 - Tests/Util/PropertyPathArrayTest.php | 20 - Tests/Util/PropertyPathBuilderTest.php | 251 -------- Tests/Util/PropertyPathCollectionTest.php | 341 ---------- .../PropertyPathCustomArrayObjectTest.php | 22 - Tests/Util/PropertyPathTest.php | 557 ---------------- Util/FormUtil.php | 166 +---- Util/PropertyPath.php | 608 +----------------- Util/PropertyPathBuilder.php | 284 +------- Util/PropertyPathInterface.php | 75 +-- Util/PropertyPathIterator.php | 41 +- Util/PropertyPathIteratorInterface.php | 25 +- composer.json | 3 +- 39 files changed, 222 insertions(+), 2645 deletions(-) delete mode 100644 Exception/InvalidPropertyException.php delete mode 100644 Exception/InvalidPropertyPathException.php delete mode 100644 Exception/PropertyAccessDeniedException.php delete mode 100644 Tests/Fixtures/Magician.php delete mode 100644 Tests/Util/FormUtilTest.php delete mode 100644 Tests/Util/PropertyPathArrayObjectTest.php delete mode 100644 Tests/Util/PropertyPathArrayTest.php delete mode 100644 Tests/Util/PropertyPathBuilderTest.php delete mode 100644 Tests/Util/PropertyPathCollectionTest.php delete mode 100644 Tests/Util/PropertyPathCustomArrayObjectTest.php delete mode 100644 Tests/Util/PropertyPathTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index d8e309637f..67f8e3c18e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,15 @@ CHANGELOG * [BC BREAK] FormException is now an interface * protected FormBuilder methods from being called when it is turned into a FormConfigInterface with getFormConfig() * [BC BREAK] inserted argument `$message` in the constructor of `FormError` + * the PropertyPath class and related classes were moved to a dedicated + PropertyAccess component. During the move, InvalidPropertyException was + renamed to NoSuchPropertyException. FormUtil was split: FormUtil::singularify() + can now be found in Symfony\Component\PropertyAccess\StringUtil. The methods + getValue() and setValue() from PropertyPath were extracted into a new class + PropertyAccessor. + * added an optional PropertyAccessorInterface parameter to FormType, + ObjectChoiceList and PropertyPathMapper + * [BC BREAK] PropertyPathMapper and FormType now have a constructor 2.1.0 ----- diff --git a/Exception/InvalidPropertyException.php b/Exception/InvalidPropertyException.php deleted file mode 100644 index 48185d55fd..0000000000 --- a/Exception/InvalidPropertyException.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Exception; - -class InvalidPropertyException extends Exception -{ -} diff --git a/Exception/InvalidPropertyPathException.php b/Exception/InvalidPropertyPathException.php deleted file mode 100644 index c8bd3ad71b..0000000000 --- a/Exception/InvalidPropertyPathException.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Exception; - -class InvalidPropertyPathException extends Exception -{ -} diff --git a/Exception/PropertyAccessDeniedException.php b/Exception/PropertyAccessDeniedException.php deleted file mode 100644 index 4905da9ea2..0000000000 --- a/Exception/PropertyAccessDeniedException.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Exception; - -class PropertyAccessDeniedException extends Exception -{ -} diff --git a/Extension/Core/ChoiceList/ObjectChoiceList.php b/Extension/Core/ChoiceList/ObjectChoiceList.php index eeb6b646c3..04be48ace4 100644 --- a/Extension/Core/ChoiceList/ObjectChoiceList.php +++ b/Extension/Core/ChoiceList/ObjectChoiceList.php @@ -11,9 +11,11 @@ namespace Symfony\Component\Form\Extension\Core\ChoiceList; -use Symfony\Component\Form\Util\PropertyPath; use Symfony\Component\Form\Exception\StringCastException; -use Symfony\Component\Form\Exception\InvalidPropertyException; +use Symfony\Component\PropertyAccess\PropertyPath; +use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException; +use Symfony\Component\PropertyAccess\PropertyAccess; +use Symfony\Component\PropertyAccess\PropertyAccessorInterface; /** * A choice list for object choices. @@ -32,6 +34,11 @@ */ class ObjectChoiceList extends ChoiceList { + /** + * @var PropertyAccessorInterface + */ + private $propertyAccessor; + /** * The property path used to obtain the choice label. * @@ -56,28 +63,30 @@ class ObjectChoiceList extends ChoiceList /** * Creates a new object choice list. * - * @param array|\Traversable $choices The array of choices. Choices may also be given - * as hierarchy of unlimited depth by creating nested - * arrays. The title of the sub-hierarchy can be - * stored in the array key pointing to the nested - * array. The topmost level of the hierarchy may also - * be a \Traversable. - * @param string $labelPath A property path pointing to the property used - * for the choice labels. The value is obtained - * by calling the getter on the object. If the - * path is NULL, the object's __toString() method - * is used instead. - * @param array $preferredChoices A flat array of choices that should be - * presented to the user with priority. - * @param string $groupPath A property path pointing to the property used - * to group the choices. Only allowed if - * the choices are given as flat array. - * @param string $valuePath A property path pointing to the property used - * for the choice values. If not given, integers - * are generated instead. + * @param array|\Traversable $choices The array of choices. Choices may also be given + * as hierarchy of unlimited depth by creating nested + * arrays. The title of the sub-hierarchy can be + * stored in the array key pointing to the nested + * array. The topmost level of the hierarchy may also + * be a \Traversable. + * @param string $labelPath A property path pointing to the property used + * for the choice labels. The value is obtained + * by calling the getter on the object. If the + * path is NULL, the object's __toString() method + * is used instead. + * @param array $preferredChoices A flat array of choices that should be + * presented to the user with priority. + * @param string $groupPath A property path pointing to the property used + * to group the choices. Only allowed if + * the choices are given as flat array. + * @param string $valuePath A property path pointing to the property used + * for the choice values. If not given, integers + * are generated instead. + * @param PropertyAccessorInterface $propertyAccessor The reflection graph for reading property paths. */ - public function __construct($choices, $labelPath = null, array $preferredChoices = array(), $groupPath = null, $valuePath = null) + public function __construct($choices, $labelPath = null, array $preferredChoices = array(), $groupPath = null, $valuePath = null, PropertyAccessorInterface $propertyAccessor = null) { + $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::getPropertyAccessor(); $this->labelPath = null !== $labelPath ? new PropertyPath($labelPath) : null; $this->groupPath = null !== $groupPath ? new PropertyPath($groupPath) : null; $this->valuePath = null !== $valuePath ? new PropertyPath($valuePath) : null; @@ -108,8 +117,8 @@ protected function initialize($choices, array $labels, array $preferredChoices) } try { - $group = $this->groupPath->getValue($choice); - } catch (InvalidPropertyException $e) { + $group = $this->propertyAccessor->getValue($choice, $this->groupPath); + } catch (NoSuchPropertyException $e) { // Don't group items whose group property does not exist // see https://github.com/symfony/symfony/commit/d9b7abb7c7a0f28e0ce970afc5e305dce5dccddf $group = null; @@ -150,7 +159,7 @@ protected function initialize($choices, array $labels, array $preferredChoices) protected function createValue($choice) { if ($this->valuePath) { - return (string) $this->valuePath->getValue($choice); + return (string) $this->propertyAccessor->getValue($choice, $this->valuePath); } return parent::createValue($choice); @@ -163,7 +172,7 @@ private function extractLabels($choices, array &$labels) $labels[$i] = array(); $this->extractLabels($choice, $labels[$i]); } elseif ($this->labelPath) { - $labels[$i] = $this->labelPath->getValue($choice); + $labels[$i] = $this->propertyAccessor->getValue($choice, $this->labelPath); } elseif (method_exists($choice, '__toString')) { $labels[$i] = (string) $choice; } else { diff --git a/Extension/Core/CoreExtension.php b/Extension/Core/CoreExtension.php index f0f0d181da..ab6529d6dc 100644 --- a/Extension/Core/CoreExtension.php +++ b/Extension/Core/CoreExtension.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Extension\Core; use Symfony\Component\Form\AbstractExtension; +use Symfony\Component\PropertyAccess\PropertyAccess; /** * Represents the main form extension, which loads the core functionality. @@ -24,7 +25,7 @@ protected function loadTypes() { return array( new Type\FieldType(), - new Type\FormType(), + new Type\FormType(PropertyAccess::getPropertyAccessor()), new Type\BirthdayType(), new Type\CheckboxType(), new Type\ChoiceType(), diff --git a/Extension/Core/DataMapper/PropertyPathMapper.php b/Extension/Core/DataMapper/PropertyPathMapper.php index ce850eaac7..f691ecca21 100644 --- a/Extension/Core/DataMapper/PropertyPathMapper.php +++ b/Extension/Core/DataMapper/PropertyPathMapper.php @@ -14,9 +14,31 @@ use Symfony\Component\Form\DataMapperInterface; use Symfony\Component\Form\Util\VirtualFormAwareIterator; use Symfony\Component\Form\Exception\UnexpectedTypeException; +use Symfony\Component\PropertyAccess\PropertyAccess; +use Symfony\Component\PropertyAccess\PropertyAccessorInterface; +/** + * A data mapper using property paths to read/write data. + * + * @author Bernhard Schussek + */ class PropertyPathMapper implements DataMapperInterface { + /** + * @var PropertyAccessorInterface + */ + private $propertyAccessor; + + /** + * Creates a new property path mapper. + * + * @param PropertyAccessorInterface $propertyAccessor + */ + public function __construct(PropertyAccessorInterface $propertyAccessor = null) + { + $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::getPropertyAccessor(); + } + /** * {@inheritdoc} */ @@ -39,7 +61,7 @@ public function mapDataToForms($data, array $forms) $config = $form->getConfig(); if (null !== $propertyPath && $config->getMapped()) { - $form->setData($propertyPath->getValue($data)); + $form->setData($this->propertyAccessor->getValue($data, $propertyPath)); } } } @@ -70,8 +92,8 @@ public function mapFormsToData(array $forms, &$data) if (null !== $propertyPath && $config->getMapped() && $form->isSynchronized() && !$form->isDisabled()) { // If the data is identical to the value in $data, we are // dealing with a reference - if (!is_object($data) || !$config->getByReference() || $form->getData() !== $propertyPath->getValue($data)) { - $propertyPath->setValue($data, $form->getData()); + if (!is_object($data) || !$config->getByReference() || $form->getData() !== $this->propertyAccessor->getValue($data, $propertyPath)) { + $this->propertyAccessor->setValue($data, $propertyPath, $form->getData()); } } } diff --git a/Extension/Core/Type/FormType.php b/Extension/Core/Type/FormType.php index 0b9c38df90..44b60aaf86 100644 --- a/Extension/Core/Type/FormType.php +++ b/Extension/Core/Type/FormType.php @@ -20,9 +20,21 @@ use Symfony\Component\Form\Exception\Exception; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; +use Symfony\Component\PropertyAccess\PropertyAccess; +use Symfony\Component\PropertyAccess\PropertyAccessorInterface; class FormType extends AbstractType { + /** + * @var PropertyAccessorInterface + */ + private $propertyAccessor; + + public function __construct(PropertyAccessorInterface $propertyAccessor = null) + { + $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::getPropertyAccessor(); + } + /** * {@inheritdoc} */ @@ -41,7 +53,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) ->setCompound($options['compound']) ->setData(isset($options['data']) ? $options['data'] : null) ->setDataLocked(isset($options['data'])) - ->setDataMapper($options['compound'] ? new PropertyPathMapper() : null) + ->setDataMapper($options['compound'] ? new PropertyPathMapper($this->propertyAccessor) : null) ; if ($options['trim']) { diff --git a/Extension/Validator/ViolationMapper/RelativePath.php b/Extension/Validator/ViolationMapper/RelativePath.php index 8f487bcc15..ef5c9fad05 100644 --- a/Extension/Validator/ViolationMapper/RelativePath.php +++ b/Extension/Validator/ViolationMapper/RelativePath.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\Util\PropertyPath; +use Symfony\Component\PropertyAccess\PropertyPath; /** * @author Bernhard Schussek diff --git a/Extension/Validator/ViolationMapper/ViolationMapper.php b/Extension/Validator/ViolationMapper/ViolationMapper.php index cece98804e..61d08c3e5d 100644 --- a/Extension/Validator/ViolationMapper/ViolationMapper.php +++ b/Extension/Validator/ViolationMapper/ViolationMapper.php @@ -13,9 +13,9 @@ use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\Util\VirtualFormAwareIterator; -use Symfony\Component\Form\Util\PropertyPathIterator; -use Symfony\Component\Form\Util\PropertyPathBuilder; -use Symfony\Component\Form\Util\PropertyPathIteratorInterface; +use Symfony\Component\PropertyAccess\PropertyPathIterator; +use Symfony\Component\PropertyAccess\PropertyPathBuilder; +use Symfony\Component\PropertyAccess\PropertyPathIteratorInterface; use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationPathIterator; use Symfony\Component\Form\FormError; use Symfony\Component\Validator\ConstraintViolation; @@ -265,7 +265,7 @@ private function reconstructPath(ViolationPath $violationPath, FormInterface $or $propertyPathBuilder->remove(0, $i + 1); $i = 0; } else { - /* @var \Symfony\Component\Form\Util\PropertyPathInterface $propertyPath */ + /* @var \Symfony\Component\PropertyAccess\PropertyPathInterface $propertyPath */ $propertyPath = $scope->getPropertyPath(); if (null === $propertyPath) { diff --git a/Extension/Validator/ViolationMapper/ViolationPath.php b/Extension/Validator/ViolationMapper/ViolationPath.php index 65cbda6b18..9c99e8618f 100644 --- a/Extension/Validator/ViolationMapper/ViolationPath.php +++ b/Extension/Validator/ViolationMapper/ViolationPath.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; -use Symfony\Component\Form\Util\PropertyPath; -use Symfony\Component\Form\Util\PropertyPathInterface; +use Symfony\Component\PropertyAccess\PropertyPath; +use Symfony\Component\PropertyAccess\PropertyPathInterface; /** * @author Bernhard Schussek diff --git a/Extension/Validator/ViolationMapper/ViolationPathIterator.php b/Extension/Validator/ViolationMapper/ViolationPathIterator.php index 531da861eb..50baa4533e 100644 --- a/Extension/Validator/ViolationMapper/ViolationPathIterator.php +++ b/Extension/Validator/ViolationMapper/ViolationPathIterator.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; -use Symfony\Component\Form\Util\PropertyPathIterator; +use Symfony\Component\PropertyAccess\PropertyPathIterator; /** * @author Bernhard Schussek diff --git a/Form.php b/Form.php index eb93637877..7a49822425 100644 --- a/Form.php +++ b/Form.php @@ -16,8 +16,8 @@ use Symfony\Component\Form\Exception\AlreadyBoundException; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Util\FormUtil; -use Symfony\Component\Form\Util\PropertyPath; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\PropertyAccess\PropertyPath; /** * Form represents a form. diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index 1b428194f8..5d1f3a2331 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -14,8 +14,8 @@ use Symfony\Component\Form\Exception\BadMethodCallException; use Symfony\Component\Form\Exception\Exception; use Symfony\Component\Form\Exception\UnexpectedTypeException; -use Symfony\Component\Form\Util\PropertyPath; -use Symfony\Component\Form\Util\PropertyPathInterface; +use Symfony\Component\PropertyAccess\PropertyPath; +use Symfony\Component\PropertyAccess\PropertyPathInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\ImmutableEventDispatcher; diff --git a/FormConfigBuilderInterface.php b/FormConfigBuilderInterface.php index 496fc38c66..c63f0e8aaa 100644 --- a/FormConfigBuilderInterface.php +++ b/FormConfigBuilderInterface.php @@ -117,7 +117,7 @@ public function setAttributes(array $attributes); /** * Sets the data mapper used by the form. * - * @param DataMapperInterface $dataMapper + * @param DataMapperInterface $dataMapper * * @return self The configuration object. */ @@ -126,7 +126,7 @@ public function setDataMapper(DataMapperInterface $dataMapper = null); /** * Set whether the form is disabled. * - * @param Boolean $disabled Whether the form is disabled + * @param Boolean $disabled Whether the form is disabled * * @return self The configuration object. */ @@ -135,7 +135,7 @@ public function setDisabled($disabled); /** * Sets the data used for the client data when no value is bound. * - * @param mixed $emptyData The empty data. + * @param mixed $emptyData The empty data. * * @return self The configuration object. */ @@ -144,7 +144,7 @@ public function setEmptyData($emptyData); /** * Sets whether errors bubble up to the parent. * - * @param Boolean $errorBubbling + * @param Boolean $errorBubbling * * @return self The configuration object. */ @@ -162,9 +162,9 @@ public function setRequired($required); /** * Sets the property path that the form should be mapped to. * - * @param null|string|PropertyPathInterface $propertyPath The property path or null if the path - * should be set automatically based on - * the form's name. + * @param null|string|\Symfony\Component\PropertyAccess\PropertyPathInterface $propertyPath + * The property path or null if the path should be set + * automatically based on the form's name. * * @return self The configuration object. */ @@ -174,7 +174,7 @@ public function setPropertyPath($propertyPath); * Sets whether the form should be mapped to an element of its * parent's data. * - * @param Boolean $mapped Whether the form should be mapped. + * @param Boolean $mapped Whether the form should be mapped. * * @return self The configuration object. */ @@ -183,7 +183,7 @@ public function setMapped($mapped); /** * Sets whether the form's data should be modified by reference. * - * @param Boolean $byReference Whether the data should be + * @param Boolean $byReference Whether the data should be * modified by reference. * * @return self The configuration object. @@ -193,7 +193,7 @@ public function setByReference($byReference); /** * Sets whether the form should be virtual. * - * @param Boolean $virtual Whether the form should be virtual. + * @param Boolean $virtual Whether the form should be virtual. * * @return self The configuration object. */ @@ -202,7 +202,7 @@ public function setVirtual($virtual); /** * Sets whether the form should be compound. * - * @param Boolean $compound Whether the form should be compound. + * @param Boolean $compound Whether the form should be compound. * * @return self The configuration object. * @@ -235,7 +235,7 @@ public function setData($data); * this configuration. The data can only be modified then by * binding the form. * - * @param Boolean $locked Whether to lock the default data. + * @param Boolean $locked Whether to lock the default data. * * @return self The configuration object. */ diff --git a/FormConfigInterface.php b/FormConfigInterface.php index b5d914f6d3..0a27c2a7fb 100644 --- a/FormConfigInterface.php +++ b/FormConfigInterface.php @@ -35,7 +35,7 @@ public function getName(); /** * Returns the property path that the form should be mapped to. * - * @return null|Util\PropertyPathInterface The property path. + * @return null|\Symfony\Component\PropertyAccess\PropertyPathInterface The property path. */ public function getPropertyPath(); diff --git a/FormInterface.php b/FormInterface.php index d217a07dd1..94f6b3e29d 100644 --- a/FormInterface.php +++ b/FormInterface.php @@ -166,7 +166,7 @@ public function getName(); /** * Returns the property path that the form is mapped to. * - * @return Util\PropertyPathInterface The property path. + * @return \Symfony\Component\PropertyAccess\PropertyPathInterface The property path. */ public function getPropertyPath(); diff --git a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php index ff449610a5..b7487377e6 100644 --- a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php @@ -39,6 +39,9 @@ class ObjectChoiceListTest extends \PHPUnit_Framework_TestCase private $obj4; + /** + * @var ObjectChoiceList + */ private $list; protected function setUp() diff --git a/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php b/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php index 05d2fe1577..8af2fd5f07 100644 --- a/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php +++ b/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php @@ -11,10 +11,8 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataMapper; -use Symfony\Component\Form\Form; use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\Form\FormConfigInterface; -use Symfony\Component\Form\Util\PropertyPath; use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase @@ -29,14 +27,24 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase */ private $dispatcher; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $propertyAccessor; + protected function setUp() { if (!class_exists('Symfony\Component\EventDispatcher\Event')) { $this->markTestSkipped('The "EventDispatcher" component is not available'); } + if (!class_exists('Symfony\Component\PropertyAccess\PropertyAccess')) { + $this->markTestSkipped('The "PropertyAccess" component is not available'); + } + $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); - $this->mapper = new PropertyPathMapper(); + $this->propertyAccessor = $this->getMock('Symfony\Component\PropertyAccess\PropertyAccessorInterface'); + $this->mapper = new PropertyPathMapper($this->propertyAccessor); } /** @@ -45,7 +53,7 @@ protected function setUp() */ private function getPropertyPath($path) { - return $this->getMockBuilder('Symfony\Component\Form\Util\PropertyPath') + return $this->getMockBuilder('Symfony\Component\PropertyAccess\PropertyPath') ->setConstructorArgs(array($path)) ->setMethods(array('getValue', 'setValue')) ->getMock(); @@ -84,9 +92,9 @@ public function testMapDataToFormsPassesObjectRefIfByReference() $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); - $propertyPath->expects($this->once()) + $this->propertyAccessor->expects($this->once()) ->method('getValue') - ->with($car) + ->with($car, $propertyPath) ->will($this->returnValue($engine)); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); @@ -107,9 +115,9 @@ public function testMapDataToFormsPassesObjectCloneIfNotByReference() $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); - $propertyPath->expects($this->once()) + $this->propertyAccessor->expects($this->once()) ->method('getValue') - ->with($car) + ->with($car, $propertyPath) ->will($this->returnValue($engine)); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); @@ -143,7 +151,7 @@ public function testMapDataToFormsIgnoresUnmapped() $car = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); - $propertyPath->expects($this->never()) + $this->propertyAccessor->expects($this->never()) ->method('getValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); @@ -161,7 +169,7 @@ public function testMapDataToFormsIgnoresEmptyData() { $propertyPath = $this->getPropertyPath('engine'); - $propertyPath->expects($this->never()) + $this->propertyAccessor->expects($this->never()) ->method('getValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); @@ -180,9 +188,9 @@ public function testMapDataToFormsSkipsVirtualForms() $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); - $propertyPath->expects($this->once()) + $this->propertyAccessor->expects($this->once()) ->method('getValue') - ->with($car) + ->with($car, $propertyPath) ->will($this->returnValue($engine)); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); @@ -211,9 +219,9 @@ public function testMapFormsToDataWritesBackIfNotByReference() $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); - $propertyPath->expects($this->once()) + $this->propertyAccessor->expects($this->once()) ->method('setValue') - ->with($car, $engine); + ->with($car, $propertyPath, $engine); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(false); @@ -230,9 +238,9 @@ public function testMapFormsToDataWritesBackIfByReferenceButNoReference() $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); - $propertyPath->expects($this->once()) + $this->propertyAccessor->expects($this->once()) ->method('setValue') - ->with($car, $engine); + ->with($car, $propertyPath, $engine); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); @@ -250,12 +258,12 @@ public function testMapFormsToDataWritesBackIfByReferenceAndReference() $propertyPath = $this->getPropertyPath('engine'); // $car already contains the reference of $engine - $propertyPath->expects($this->once()) + $this->propertyAccessor->expects($this->once()) ->method('getValue') - ->with($car) + ->with($car, $propertyPath) ->will($this->returnValue($engine)); - $propertyPath->expects($this->never()) + $this->propertyAccessor->expects($this->never()) ->method('setValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); @@ -273,7 +281,7 @@ public function testMapFormsToDataIgnoresUnmapped() $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); - $propertyPath->expects($this->never()) + $this->propertyAccessor->expects($this->never()) ->method('setValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); @@ -291,7 +299,7 @@ public function testMapFormsToDataIgnoresEmptyData() $car = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); - $propertyPath->expects($this->never()) + $this->propertyAccessor->expects($this->never()) ->method('setValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); @@ -309,7 +317,7 @@ public function testMapFormsToDataIgnoresUnsynchronized() $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); - $propertyPath->expects($this->never()) + $this->propertyAccessor->expects($this->never()) ->method('setValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); @@ -327,7 +335,7 @@ public function testMapFormsToDataIgnoresDisabled() $engine = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); - $propertyPath->expects($this->never()) + $this->propertyAccessor->expects($this->never()) ->method('setValue'); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); @@ -347,14 +355,14 @@ public function testMapFormsToDataSkipsVirtualForms() $parentPath = $this->getPropertyPath('name'); $childPath = $this->getPropertyPath('engine'); - $parentPath->expects($this->never()) - ->method('getValue'); - $parentPath->expects($this->never()) - ->method('setValue'); + // getValue() and setValue() must never be invoked for $parentPath - $childPath->expects($this->once()) + $this->propertyAccessor->expects($this->once()) + ->method('getValue') + ->with($car, $childPath); + $this->propertyAccessor->expects($this->once()) ->method('setValue') - ->with($car, $engine); + ->with($car, $childPath, $engine); $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setPropertyPath($parentPath); diff --git a/Tests/Extension/Core/Type/ChoiceTypeTest.php b/Tests/Extension/Core/Type/ChoiceTypeTest.php index 61ce5e7c58..3b32ab38e8 100644 --- a/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; -use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList; - use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList; use Symfony\Component\Form\Extension\Core\View\ChoiceView; diff --git a/Tests/Extension/Core/Type/FormTypeTest.php b/Tests/Extension/Core/Type/FormTypeTest.php index 65c7b68693..fae4ae3e5b 100644 --- a/Tests/Extension/Core/Type/FormTypeTest.php +++ b/Tests/Extension/Core/Type/FormTypeTest.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; -use Symfony\Component\Form\Util\PropertyPath; +use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\Form\Form; use Symfony\Component\Form\CallbackTransformer; use Symfony\Component\Form\Tests\Fixtures\Author; diff --git a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php index d9555e13e1..77420ebb9f 100644 --- a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php +++ b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php @@ -14,7 +14,7 @@ use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormError; -use Symfony\Component\Form\Util\PropertyPath; +use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\Form\Extension\Validator\Constraints\Form; use Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener; use Symfony\Component\Validator\ConstraintViolation; diff --git a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php index 2f41a99101..ac529b213f 100644 --- a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php +++ b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php @@ -17,7 +17,7 @@ use Symfony\Component\Form\Form; use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\Form\FormError; -use Symfony\Component\Form\Util\PropertyPath; +use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\Validator\ConstraintViolation; /** diff --git a/Tests/Fixtures/Magician.php b/Tests/Fixtures/Magician.php deleted file mode 100644 index cd66f29d07..0000000000 --- a/Tests/Fixtures/Magician.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Tests\Fixtures; - -class Magician -{ - private $foobar; - - public function __set($property, $value) - { - $this->$property = $value; - } - - public function __get($property) - { - return isset($this->$property) ? $this->$property : null; - } -} diff --git a/Tests/SimpleFormTest.php b/Tests/SimpleFormTest.php index 0d72df3acb..102c973fd4 100644 --- a/Tests/SimpleFormTest.php +++ b/Tests/SimpleFormTest.php @@ -14,7 +14,7 @@ use Symfony\Component\Form\Form; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormEvents; -use Symfony\Component\Form\Util\PropertyPath; +use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\Form\FormError; use Symfony\Component\Form\Exception\TransformationFailedException; diff --git a/Tests/Util/FormUtilTest.php b/Tests/Util/FormUtilTest.php deleted file mode 100644 index c70c0d6fcc..0000000000 --- a/Tests/Util/FormUtilTest.php +++ /dev/null @@ -1,135 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Tests\Util; - -use Symfony\Component\Form\Util\FormUtil; - -class FormUtilTest extends \PHPUnit_Framework_TestCase -{ - public function singularifyProvider() - { - // see http://english-zone.com/spelling/plurals.html - // see http://www.scribd.com/doc/3271143/List-of-100-Irregular-Plural-Nouns-in-English - return array( - array('tags', 'tag'), - array('alumni', 'alumnus'), - array('funguses', array('fungus', 'funguse', 'fungusis')), - array('fungi', 'fungus'), - array('axes', array('ax', 'axe', 'axis')), - array('appendices', array('appendex', 'appendix', 'appendice')), - array('indices', array('index', 'indix', 'indice')), - array('prices', array('prex', 'prix', 'price')), - array('indexes', 'index'), - array('children', 'child'), - array('men', 'man'), - array('women', 'woman'), - array('oxen', 'ox'), - array('bacteria', array('bacterion', 'bacterium')), - array('criteria', array('criterion', 'criterium')), - array('feet', 'foot'), - array('nebulae', 'nebula'), - array('babies', 'baby'), - array('hooves', 'hoof'), - array('chateaux', 'chateau'), - array('echoes', array('echo', 'echoe')), - array('analyses', array('analys', 'analyse', 'analysis')), - array('theses', array('thes', 'these', 'thesis')), - array('foci', 'focus'), - array('focuses', array('focus', 'focuse', 'focusis')), - array('oases', array('oas', 'oase', 'oasis')), - array('matrices', array('matrex', 'matrix', 'matrice')), - array('matrixes', 'matrix'), - array('bureaus', 'bureau'), - array('bureaux', 'bureau'), - array('beaux', 'beau'), - array('data', array('daton', 'datum')), - array('phenomena', array('phenomenon', 'phenomenum')), - array('strata', array('straton', 'stratum')), - array('geese', 'goose'), - array('teeth', 'tooth'), - array('antennae', 'antenna'), - array('antennas', 'antenna'), - array('houses', array('hous', 'house', 'housis')), - array('arches', array('arch', 'arche')), - array('atlases', array('atlas', 'atlase', 'atlasis')), - array('batches', array('batch', 'batche')), - array('bushes', array('bush', 'bushe')), - array('buses', array('bus', 'buse', 'busis')), - array('calves', 'calf'), - array('circuses', array('circus', 'circuse', 'circusis')), - array('crises', array('cris', 'crise', 'crisis')), - array('dwarves', 'dwarf'), - array('elves', 'elf'), - array('emphases', array('emphas', 'emphase', 'emphasis')), - array('faxes', 'fax'), - array('halves', 'half'), - array('heroes', array('hero', 'heroe')), - array('hoaxes', 'hoax'), - array('irises', array('iris', 'irise', 'irisis')), - array('kisses', array('kiss', 'kisse', 'kissis')), - array('knives', 'knife'), - array('lives', 'life'), - array('lice', 'louse'), - array('mice', 'mouse'), - array('neuroses', array('neuros', 'neurose', 'neurosis')), - array('plateaux', 'plateau'), - array('poppies', 'poppy'), - array('quizzes', 'quiz'), - array('scarves', 'scarf'), - array('spies', 'spy'), - array('stories', 'story'), - array('syllabi', 'syllabus'), - array('thieves', 'thief'), - array('waltzes', array('waltz', 'waltze')), - array('wharves', 'wharf'), - array('wives', 'wife'), - array('ions', 'ion'), - array('bases', array('bas', 'base', 'basis')), - array('cars', 'car'), - array('cassettes', array('cassett', 'cassette')), - array('lamps', 'lamp'), - array('hats', 'hat'), - array('cups', 'cup'), - array('boxes', 'box'), - array('sandwiches', array('sandwich', 'sandwiche')), - array('suitcases', array('suitcas', 'suitcase', 'suitcasis')), - array('roses', array('ros', 'rose', 'rosis')), - array('garages', array('garag', 'garage')), - array('shoes', array('sho', 'shoe')), - array('days', 'day'), - array('boys', 'boy'), - array('roofs', 'roof'), - array('cliffs', 'cliff'), - array('sheriffs', 'sheriff'), - array('discos', 'disco'), - array('pianos', 'piano'), - array('photos', 'photo'), - array('trees', array('tre', 'tree')), - array('bees', array('be', 'bee')), - array('cheeses', array('chees', 'cheese', 'cheesis')), - array('radii', 'radius'), - - // test casing: if the first letter was uppercase, it should remain so - array('Men', 'Man'), - array('GrandChildren', 'GrandChild'), - array('SubTrees', array('SubTre', 'SubTree')), - ); - } - - /** - * @dataProvider singularifyProvider - */ - public function testSingularify($plural, $singular) - { - $this->assertEquals($singular, FormUtil::singularify($plural)); - } -} diff --git a/Tests/Util/PropertyPathArrayObjectTest.php b/Tests/Util/PropertyPathArrayObjectTest.php deleted file mode 100644 index 96ddc6d6f0..0000000000 --- a/Tests/Util/PropertyPathArrayObjectTest.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Tests\Util; - -class PropertyPathArrayObjectTest extends PropertyPathCollectionTest -{ - protected function getCollection(array $array) - { - return new \ArrayObject($array); - } -} diff --git a/Tests/Util/PropertyPathArrayTest.php b/Tests/Util/PropertyPathArrayTest.php deleted file mode 100644 index ce726c80f8..0000000000 --- a/Tests/Util/PropertyPathArrayTest.php +++ /dev/null @@ -1,20 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Tests\Util; - -class PropertyPathArrayTest extends PropertyPathCollectionTest -{ - protected function getCollection(array $array) - { - return $array; - } -} diff --git a/Tests/Util/PropertyPathBuilderTest.php b/Tests/Util/PropertyPathBuilderTest.php deleted file mode 100644 index 6649bdcdc9..0000000000 --- a/Tests/Util/PropertyPathBuilderTest.php +++ /dev/null @@ -1,251 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Tests\Util; - -use Symfony\Component\Form\Util\PropertyPath; -use Symfony\Component\Form\Util\PropertyPathBuilder; - -/** - * @author Bernhard Schussek - */ -class PropertyPathBuilderTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var string - */ - const PREFIX = 'old1[old2].old3[old4][old5].old6'; - - /** - * @var PropertyPathBuilder - */ - private $builder; - - protected function setUp() - { - $this->builder = new PropertyPathBuilder(new PropertyPath(self::PREFIX)); - } - - public function testCreateEmpty() - { - $builder = new PropertyPathBuilder(); - - $this->assertNull($builder->getPropertyPath()); - } - - public function testCreateCopyPath() - { - $this->assertEquals(new PropertyPath(self::PREFIX), $this->builder->getPropertyPath()); - } - - public function testAppendIndex() - { - $this->builder->appendIndex('new1'); - - $path = new PropertyPath(self::PREFIX . '[new1]'); - - $this->assertEquals($path, $this->builder->getPropertyPath()); - } - - public function testAppendProperty() - { - $this->builder->appendProperty('new1'); - - $path = new PropertyPath(self::PREFIX . '.new1'); - - $this->assertEquals($path, $this->builder->getPropertyPath()); - } - - public function testAppend() - { - $this->builder->append(new PropertyPath('new1[new2]')); - - $path = new PropertyPath(self::PREFIX . '.new1[new2]'); - - $this->assertEquals($path, $this->builder->getPropertyPath()); - } - - public function testAppendWithOffset() - { - $this->builder->append(new PropertyPath('new1[new2].new3'), 1); - - $path = new PropertyPath(self::PREFIX . '[new2].new3'); - - $this->assertEquals($path, $this->builder->getPropertyPath()); - } - - public function testAppendWithOffsetAndLength() - { - $this->builder->append(new PropertyPath('new1[new2].new3'), 1, 1); - - $path = new PropertyPath(self::PREFIX . '[new2]'); - - $this->assertEquals($path, $this->builder->getPropertyPath()); - } - - public function testReplaceByIndex() - { - $this->builder->replaceByIndex(1, 'new1'); - - $path = new PropertyPath('old1[new1].old3[old4][old5].old6'); - - $this->assertEquals($path, $this->builder->getPropertyPath()); - } - - public function testReplaceByIndexWithoutName() - { - $this->builder->replaceByIndex(0); - - $path = new PropertyPath('[old1][old2].old3[old4][old5].old6'); - - $this->assertEquals($path, $this->builder->getPropertyPath()); - } - - /** - * @expectedException \OutOfBoundsException - */ - public function testReplaceByIndexDoesNotAllowInvalidOffsets() - { - $this->builder->replaceByIndex(6, 'new1'); - } - - /** - * @expectedException \OutOfBoundsException - */ - public function testReplaceByIndexDoesNotAllowNegativeOffsets() - { - $this->builder->replaceByIndex(-1, 'new1'); - } - - public function testReplaceByProperty() - { - $this->builder->replaceByProperty(1, 'new1'); - - $path = new PropertyPath('old1.new1.old3[old4][old5].old6'); - - $this->assertEquals($path, $this->builder->getPropertyPath()); - } - - public function testReplaceByPropertyWithoutName() - { - $this->builder->replaceByProperty(1); - - $path = new PropertyPath('old1.old2.old3[old4][old5].old6'); - - $this->assertEquals($path, $this->builder->getPropertyPath()); - } - - /** - * @expectedException \OutOfBoundsException - */ - public function testReplaceByPropertyDoesNotAllowInvalidOffsets() - { - $this->builder->replaceByProperty(6, 'new1'); - } - - /** - * @expectedException \OutOfBoundsException - */ - public function testReplaceByPropertyDoesNotAllowNegativeOffsets() - { - $this->builder->replaceByProperty(-1, 'new1'); - } - - public function testReplace() - { - $this->builder->replace(1, 1, new PropertyPath('new1[new2].new3')); - - $path = new PropertyPath('old1.new1[new2].new3.old3[old4][old5].old6'); - - $this->assertEquals($path, $this->builder->getPropertyPath()); - } - - /** - * @expectedException \OutOfBoundsException - */ - public function testReplaceDoesNotAllowInvalidOffsets() - { - $this->builder->replace(6, 1, new PropertyPath('new1[new2].new3')); - } - - /** - * @expectedException \OutOfBoundsException - */ - public function testReplaceDoesNotAllowNegativeOffsets() - { - $this->builder->replace(-1, 1, new PropertyPath('new1[new2].new3')); - } - - public function testReplaceWithLengthGreaterOne() - { - $this->builder->replace(0, 2, new PropertyPath('new1[new2].new3')); - - $path = new PropertyPath('new1[new2].new3.old3[old4][old5].old6'); - - $this->assertEquals($path, $this->builder->getPropertyPath()); - } - - public function testReplaceSubstring() - { - $this->builder->replace(1, 1, new PropertyPath('new1[new2].new3.new4[new5]'), 1, 3); - - $path = new PropertyPath('old1[new2].new3.new4.old3[old4][old5].old6'); - - $this->assertEquals($path, $this->builder->getPropertyPath()); - } - - public function testReplaceSubstringWithLengthGreaterOne() - { - $this->builder->replace(1, 2, new PropertyPath('new1[new2].new3.new4[new5]'), 1, 3); - - $path = new PropertyPath('old1[new2].new3.new4[old4][old5].old6'); - - $this->assertEquals($path, $this->builder->getPropertyPath()); - } - - // https://github.com/symfony/symfony/issues/5605 - public function testReplaceWithLongerPath() - { - // error occurs when path contains at least two more elements - // than the builder - $path = new PropertyPath('new1.new2.new3'); - - $builder = new PropertyPathBuilder(new PropertyPath('old1')); - $builder->replace(0, 1, $path); - - $this->assertEquals($path, $builder->getPropertyPath()); - } - - public function testRemove() - { - $this->builder->remove(3); - - $path = new PropertyPath('old1[old2].old3[old5].old6'); - - $this->assertEquals($path, $this->builder->getPropertyPath()); - } - - /** - * @expectedException \OutOfBoundsException - */ - public function testRemoveDoesNotAllowInvalidOffsets() - { - $this->builder->remove(6); - } - - /** - * @expectedException \OutOfBoundsException - */ - public function testRemoveDoesNotAllowNegativeOffsets() - { - $this->builder->remove(-1); - } -} diff --git a/Tests/Util/PropertyPathCollectionTest.php b/Tests/Util/PropertyPathCollectionTest.php deleted file mode 100644 index 2f7589663e..0000000000 --- a/Tests/Util/PropertyPathCollectionTest.php +++ /dev/null @@ -1,341 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Tests\Util; - -use Symfony\Component\Form\Util\PropertyPath; -use Symfony\Component\Form\Util\FormUtil; - -class PropertyPathCollectionTest_Car -{ - private $axes; - - public function __construct($axes = null) - { - $this->axes = $axes; - } - - // In the test, use a name that FormUtil can't uniquely singularify - public function addAxis($axis) - { - $this->axes[] = $axis; - } - - public function removeAxis($axis) - { - foreach ($this->axes as $key => $value) { - if ($value === $axis) { - unset($this->axes[$key]); - - return; - } - } - } - - public function getAxes() - { - return $this->axes; - } -} - -class PropertyPathCollectionTest_CarCustomSingular -{ - public function addFoo($axis) {} - - public function removeFoo($axis) {} - - public function getAxes() {} -} - -class PropertyPathCollectionTest_Engine -{ -} - -class PropertyPathCollectionTest_CarOnlyAdder -{ - public function addAxis($axis) {} - - public function getAxes() {} -} - -class PropertyPathCollectionTest_CarOnlyRemover -{ - public function removeAxis($axis) {} - - public function getAxes() {} -} - -class PropertyPathCollectionTest_CarNoAdderAndRemover -{ - public function getAxes() {} -} - -class PropertyPathCollectionTest_CarNoAdderAndRemoverWithProperty -{ - protected $axes = array(); - - public function getAxes() {} -} - -class PropertyPathCollectionTest_CompositeCar -{ - public function getStructure() {} - - public function setStructure($structure) {} -} - -class PropertyPathCollectionTest_CarStructure -{ - public function addAxis($axis) {} - - public function removeAxis($axis) {} - - public function getAxes() {} -} - -abstract class PropertyPathCollectionTest extends \PHPUnit_Framework_TestCase -{ - abstract protected function getCollection(array $array); - - public function testGetValueReadsArrayAccess() - { - $object = $this->getCollection(array('firstName' => 'Bernhard')); - - $path = new PropertyPath('[firstName]'); - - $this->assertEquals('Bernhard', $path->getValue($object)); - } - - public function testGetValueReadsNestedArrayAccess() - { - $object = $this->getCollection(array('person' => array('firstName' => 'Bernhard'))); - - $path = new PropertyPath('[person][firstName]'); - - $this->assertEquals('Bernhard', $path->getValue($object)); - } - - /** - * @expectedException \Symfony\Component\Form\Exception\InvalidPropertyException - */ - public function testGetValueThrowsExceptionIfArrayAccessExpected() - { - $path = new PropertyPath('[firstName]'); - - $path->getValue(new \stdClass()); - } - - public function testSetValueUpdatesArrayAccess() - { - $object = $this->getCollection(array()); - - $path = new PropertyPath('[firstName]'); - $path->setValue($object, 'Bernhard'); - - $this->assertEquals('Bernhard', $object['firstName']); - } - - public function testSetValueUpdatesNestedArrayAccess() - { - $object = $this->getCollection(array()); - - $path = new PropertyPath('[person][firstName]'); - $path->setValue($object, 'Bernhard'); - - $this->assertEquals('Bernhard', $object['person']['firstName']); - } - - /** - * @expectedException \Symfony\Component\Form\Exception\InvalidPropertyException - */ - public function testSetValueThrowsExceptionIfArrayAccessExpected() - { - $path = new PropertyPath('[firstName]'); - - $path->setValue(new \stdClass(), 'Bernhard'); - } - - public function testSetValueCallsAdderAndRemoverForCollections() - { - $axesBefore = $this->getCollection(array(1 => 'second', 3 => 'fourth', 4 => 'fifth')); - $axesMerged = $this->getCollection(array(1 => 'first', 2 => 'second', 3 => 'third')); - $axesAfter = $this->getCollection(array(1 => 'second', 5 => 'first', 6 => 'third')); - $axesMergedCopy = is_object($axesMerged) ? clone $axesMerged : $axesMerged; - - // Don't use a mock in order to test whether the collections are - // modified while iterating them - $car = new PropertyPathCollectionTest_Car($axesBefore); - - $path = new PropertyPath('axes'); - - $path->setValue($car, $axesMerged); - - $this->assertEquals($axesAfter, $car->getAxes()); - - // The passed collection was not modified - $this->assertEquals($axesMergedCopy, $axesMerged); - } - - public function testSetValueCallsAdderAndRemoverForNestedCollections() - { - $car = $this->getMock(__CLASS__ . '_CompositeCar'); - $structure = $this->getMock(__CLASS__ . '_CarStructure'); - $axesBefore = $this->getCollection(array(1 => 'second', 3 => 'fourth')); - $axesAfter = $this->getCollection(array(0 => 'first', 1 => 'second', 2 => 'third')); - - $path = new PropertyPath('structure.axes'); - - $car->expects($this->any()) - ->method('getStructure') - ->will($this->returnValue($structure)); - - $structure->expects($this->at(0)) - ->method('getAxes') - ->will($this->returnValue($axesBefore)); - $structure->expects($this->at(1)) - ->method('removeAxis') - ->with('fourth'); - $structure->expects($this->at(2)) - ->method('addAxis') - ->with('first'); - $structure->expects($this->at(3)) - ->method('addAxis') - ->with('third'); - - $path->setValue($car, $axesAfter); - } - - public function testSetValueCallsCustomAdderAndRemover() - { - $this->markTestSkipped('This feature is temporarily disabled as of 2.1'); - - $car = $this->getMock(__CLASS__ . '_CarCustomSingular'); - $axesBefore = $this->getCollection(array(1 => 'second', 3 => 'fourth')); - $axesAfter = $this->getCollection(array(0 => 'first', 1 => 'second', 2 => 'third')); - - $path = new PropertyPath('axes|foo'); - - $car->expects($this->at(0)) - ->method('getAxes') - ->will($this->returnValue($axesBefore)); - $car->expects($this->at(1)) - ->method('removeFoo') - ->with('fourth'); - $car->expects($this->at(2)) - ->method('addFoo') - ->with('first'); - $car->expects($this->at(3)) - ->method('addFoo') - ->with('third'); - - $path->setValue($car, $axesAfter); - } - - /** - * @expectedException \Symfony\Component\Form\Exception\InvalidPropertyException - */ - public function testMapFormToDataFailsIfOnlyAdderFound() - { - $car = $this->getMock(__CLASS__ . '_CarOnlyAdder'); - $axesBefore = $this->getCollection(array(1 => 'second', 3 => 'fourth')); - $axesAfter = $this->getCollection(array(0 => 'first', 1 => 'second', 2 => 'third')); - - $path = new PropertyPath('axes'); - - $car->expects($this->any()) - ->method('getAxes') - ->will($this->returnValue($axesBefore)); - - $path->setValue($car, $axesAfter); - } - - /** - * @expectedException \Symfony\Component\Form\Exception\InvalidPropertyException - */ - public function testMapFormToDataFailsIfOnlyRemoverFound() - { - $car = $this->getMock(__CLASS__ . '_CarOnlyRemover'); - $axesBefore = $this->getCollection(array(1 => 'second', 3 => 'fourth')); - $axesAfter = $this->getCollection(array(0 => 'first', 1 => 'second', 2 => 'third')); - - $path = new PropertyPath('axes'); - - $car->expects($this->any()) - ->method('getAxes') - ->will($this->returnValue($axesBefore)); - - $path->setValue($car, $axesAfter); - } - - /** - * @dataProvider noAdderRemoverData - */ - public function testNoAdderAndRemoverThrowsSensibleError($car, $path, $message) - { - $axes = $this->getCollection(array(0 => 'first', 1 => 'second', 2 => 'third')); - - try { - $path->setValue($car, $axes); - $this->fail('An expected exception was not thrown!'); - } catch (\Symfony\Component\Form\Exception\Exception $e) { - $this->assertEquals($message, $e->getMessage()); - } - } - - public function noAdderRemoverData() - { - $data = array(); - - $car = $this->getMock(__CLASS__ . '_CarNoAdderAndRemover'); - $propertyPath = new PropertyPath('axes'); - $expectedMessage = sprintf( - 'Neither element "axes" nor method "setAxes()" exists in class ' - .'"%s", nor could adders and removers be found based on the ' - .'guessed singulars: %s' -// . '(provide a singular by suffixing the ' -// .'property path with "|{singular}" to override the guesser)' - , - get_class($car), - implode(', ', (array) $singulars = FormUtil::singularify('Axes')) - ); - $data[] = array($car, $propertyPath, $expectedMessage); - - /* - Temporarily disabled in 2.1 - - $propertyPath = new PropertyPath('axes|boo'); - $expectedMessage = sprintf( - 'Neither element "axes" nor method "setAxes()" exists in class ' - .'"%s", nor could adders and removers be found based on the ' - .'passed singular: %s', - get_class($car), - 'boo' - ); - $data[] = array($car, $propertyPath, $expectedMessage); - */ - - $car = $this->getMock(__CLASS__ . '_CarNoAdderAndRemoverWithProperty'); - $propertyPath = new PropertyPath('axes'); - $expectedMessage = sprintf( - 'Property "axes" is not public in class "%s", nor could adders and ' - .'removers be found based on the guessed singulars: %s' -// .' (provide a singular by suffixing the property path with ' -// .'"|{singular}" to override the guesser)' - . '. Maybe you should ' - .'create the method "setAxes()"?', - get_class($car), - implode(', ', (array) $singulars = FormUtil::singularify('Axes')) - ); - $data[] = array($car, $propertyPath, $expectedMessage); - - return $data; - } -} diff --git a/Tests/Util/PropertyPathCustomArrayObjectTest.php b/Tests/Util/PropertyPathCustomArrayObjectTest.php deleted file mode 100644 index a8c6476372..0000000000 --- a/Tests/Util/PropertyPathCustomArrayObjectTest.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Tests\Util; - -use Symfony\Component\Form\Tests\Fixtures\CustomArrayObject; - -class PropertyPathCustomArrayObjectTest extends PropertyPathCollectionTest -{ - protected function getCollection(array $array) - { - return new CustomArrayObject($array); - } -} diff --git a/Tests/Util/PropertyPathTest.php b/Tests/Util/PropertyPathTest.php deleted file mode 100644 index e9be1445e6..0000000000 --- a/Tests/Util/PropertyPathTest.php +++ /dev/null @@ -1,557 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Tests\Util; - -use Symfony\Component\Form\Util\PropertyPath; -use Symfony\Component\Form\Tests\Fixtures\Author; -use Symfony\Component\Form\Tests\Fixtures\Magician; - -class PropertyPathTest extends \PHPUnit_Framework_TestCase -{ - public function testGetValueReadsArray() - { - $array = array('firstName' => 'Bernhard'); - - $path = new PropertyPath('[firstName]'); - - $this->assertEquals('Bernhard', $path->getValue($array)); - } - - /** - * @expectedException \Symfony\Component\Form\Exception\InvalidPropertyException - */ - public function testGetValueThrowsExceptionIfIndexNotationExpected() - { - $array = array('firstName' => 'Bernhard'); - - $path = new PropertyPath('firstName'); - - $path->getValue($array); - } - - public function testGetValueReadsZeroIndex() - { - $array = array('Bernhard'); - - $path = new PropertyPath('[0]'); - - $this->assertEquals('Bernhard', $path->getValue($array)); - } - - public function testGetValueReadsIndexWithSpecialChars() - { - $array = array('%!@$§.' => 'Bernhard'); - - $path = new PropertyPath('[%!@$§.]'); - - $this->assertEquals('Bernhard', $path->getValue($array)); - } - - public function testGetValueReadsNestedIndexWithSpecialChars() - { - $array = array('root' => array('%!@$§.' => 'Bernhard')); - - $path = new PropertyPath('[root][%!@$§.]'); - - $this->assertEquals('Bernhard', $path->getValue($array)); - } - - public function testGetValueReadsArrayWithCustomPropertyPath() - { - $array = array('child' => array('index' => array('firstName' => 'Bernhard'))); - - $path = new PropertyPath('[child][index][firstName]'); - - $this->assertEquals('Bernhard', $path->getValue($array)); - } - - public function testGetValueReadsArrayWithMissingIndexForCustomPropertyPath() - { - $array = array('child' => array('index' => array())); - - $path = new PropertyPath('[child][index][firstName]'); - - $this->assertNull($path->getValue($array)); - } - - public function testGetValueReadsProperty() - { - $object = new Author(); - $object->firstName = 'Bernhard'; - - $path = new PropertyPath('firstName'); - - $this->assertEquals('Bernhard', $path->getValue($object)); - } - - public function testGetValueIgnoresSingular() - { - $this->markTestSkipped('This feature is temporarily disabled as of 2.1'); - - $object = (object) array('children' => 'Many'); - - $path = new PropertyPath('children|child'); - - $this->assertEquals('Many', $path->getValue($object)); - } - - public function testGetValueReadsPropertyWithSpecialCharsExceptDot() - { - $array = (object) array('%!@$§' => 'Bernhard'); - - $path = new PropertyPath('%!@$§'); - - $this->assertEquals('Bernhard', $path->getValue($array)); - } - - public function testGetValueReadsPropertyWithCustomPropertyPath() - { - $object = new Author(); - $object->child = array(); - $object->child['index'] = new Author(); - $object->child['index']->firstName = 'Bernhard'; - - $path = new PropertyPath('child[index].firstName'); - - $this->assertEquals('Bernhard', $path->getValue($object)); - } - - /** - * @expectedException \Symfony\Component\Form\Exception\PropertyAccessDeniedException - */ - public function testGetValueThrowsExceptionIfPropertyIsNotPublic() - { - $path = new PropertyPath('privateProperty'); - - $path->getValue(new Author()); - } - - public function testGetValueReadsGetters() - { - $path = new PropertyPath('lastName'); - - $object = new Author(); - $object->setLastName('Schussek'); - - $this->assertEquals('Schussek', $path->getValue($object)); - } - - public function testGetValueCamelizesGetterNames() - { - $path = new PropertyPath('last_name'); - - $object = new Author(); - $object->setLastName('Schussek'); - - $this->assertEquals('Schussek', $path->getValue($object)); - } - - /** - * @expectedException \Symfony\Component\Form\Exception\PropertyAccessDeniedException - */ - public function testGetValueThrowsExceptionIfGetterIsNotPublic() - { - $path = new PropertyPath('privateGetter'); - - $path->getValue(new Author()); - } - - public function testGetValueReadsIssers() - { - $path = new PropertyPath('australian'); - - $object = new Author(); - $object->setAustralian(false); - - $this->assertFalse($path->getValue($object)); - } - - public function testGetValueReadHassers() - { - $path = new PropertyPath('read_permissions'); - - $object = new Author(); - $object->setReadPermissions(true); - - $this->assertTrue($path->getValue($object)); - } - - public function testGetValueReadsMagicGet() - { - $path = new PropertyPath('magicProperty'); - - $object = new Magician(); - $object->__set('magicProperty', 'foobar'); - - $this->assertSame('foobar', $path->getValue($object)); - } - - /* - * https://github.com/symfony/symfony/pull/4450 - */ - public function testGetValueReadsMagicGetThatReturnsConstant() - { - $path = new PropertyPath('magicProperty'); - - $object = new Magician(); - - $this->assertNull($path->getValue($object)); - } - - /** - * @expectedException \Symfony\Component\Form\Exception\PropertyAccessDeniedException - */ - public function testGetValueThrowsExceptionIfIsserIsNotPublic() - { - $path = new PropertyPath('privateIsser'); - - $path->getValue(new Author()); - } - - /** - * @expectedException \Symfony\Component\Form\Exception\InvalidPropertyException - */ - public function testGetValueThrowsExceptionIfPropertyDoesNotExist() - { - $path = new PropertyPath('foobar'); - - $path->getValue(new Author()); - } - - /** - * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException - */ - public function testGetValueThrowsExceptionIfNotObjectOrArray() - { - $path = new PropertyPath('foobar'); - - $path->getValue('baz'); - } - - /** - * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException - */ - public function testGetValueThrowsExceptionIfNull() - { - $path = new PropertyPath('foobar'); - - $path->getValue(null); - } - - /** - * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException - */ - public function testGetValueThrowsExceptionIfEmpty() - { - $path = new PropertyPath('foobar'); - - $path->getValue(''); - } - - public function testSetValueUpdatesArrays() - { - $array = array(); - - $path = new PropertyPath('[firstName]'); - $path->setValue($array, 'Bernhard'); - - $this->assertEquals(array('firstName' => 'Bernhard'), $array); - } - - /** - * @expectedException \Symfony\Component\Form\Exception\InvalidPropertyException - */ - public function testSetValueThrowsExceptionIfIndexNotationExpected() - { - $array = array(); - - $path = new PropertyPath('firstName'); - $path->setValue($array, 'Bernhard'); - } - - public function testSetValueUpdatesArraysWithCustomPropertyPath() - { - $array = array(); - - $path = new PropertyPath('[child][index][firstName]'); - $path->setValue($array, 'Bernhard'); - - $this->assertEquals(array('child' => array('index' => array('firstName' => 'Bernhard'))), $array); - } - - public function testSetValueUpdatesProperties() - { - $object = new Author(); - - $path = new PropertyPath('firstName'); - $path->setValue($object, 'Bernhard'); - - $this->assertEquals('Bernhard', $object->firstName); - } - - public function testSetValueUpdatesPropertiesWithCustomPropertyPath() - { - $object = new Author(); - $object->child = array(); - $object->child['index'] = new Author(); - - $path = new PropertyPath('child[index].firstName'); - $path->setValue($object, 'Bernhard'); - - $this->assertEquals('Bernhard', $object->child['index']->firstName); - } - - public function testSetValueUpdateMagicSet() - { - $object = new Magician(); - - $path = new PropertyPath('magicProperty'); - $path->setValue($object, 'foobar'); - - $this->assertEquals('foobar', $object->__get('magicProperty')); - } - - public function testSetValueUpdatesSetters() - { - $object = new Author(); - - $path = new PropertyPath('lastName'); - $path->setValue($object, 'Schussek'); - - $this->assertEquals('Schussek', $object->getLastName()); - } - - public function testSetValueCamelizesSetterNames() - { - $object = new Author(); - - $path = new PropertyPath('last_name'); - $path->setValue($object, 'Schussek'); - - $this->assertEquals('Schussek', $object->getLastName()); - } - - /** - * @expectedException \Symfony\Component\Form\Exception\PropertyAccessDeniedException - */ - public function testSetValueThrowsExceptionIfGetterIsNotPublic() - { - $path = new PropertyPath('privateSetter'); - - $path->setValue(new Author(), 'foobar'); - } - - /** - * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException - */ - public function testSetValueThrowsExceptionIfNotObjectOrArray() - { - $path = new PropertyPath('foobar'); - $value = 'baz'; - - $path->setValue($value, 'bam'); - } - - /** - * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException - */ - public function testSetValueThrowsExceptionIfNull() - { - $path = new PropertyPath('foobar'); - $value = null; - - $path->setValue($value, 'bam'); - } - - /** - * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException - */ - public function testSetValueThrowsExceptionIfEmpty() - { - $path = new PropertyPath('foobar'); - $value = ''; - - $path->setValue($value, 'bam'); - } - - public function testToString() - { - $path = new PropertyPath('reference.traversable[index].property'); - - $this->assertEquals('reference.traversable[index].property', $path->__toString()); - } - - /** - * @expectedException \Symfony\Component\Form\Exception\InvalidPropertyPathException - */ - public function testInvalidPropertyPath_noDotBeforeProperty() - { - new PropertyPath('[index]property'); - } - - /** - * @expectedException \Symfony\Component\Form\Exception\InvalidPropertyPathException - */ - public function testInvalidPropertyPath_dotAtTheBeginning() - { - new PropertyPath('.property'); - } - - /** - * @expectedException \Symfony\Component\Form\Exception\InvalidPropertyPathException - */ - public function testInvalidPropertyPath_unexpectedCharacters() - { - new PropertyPath('property.$form'); - } - - /** - * @expectedException \Symfony\Component\Form\Exception\InvalidPropertyPathException - */ - public function testInvalidPropertyPath_empty() - { - new PropertyPath(''); - } - - /** - * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException - */ - public function testInvalidPropertyPath_null() - { - new PropertyPath(null); - } - - /** - * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException - */ - public function testInvalidPropertyPath_false() - { - new PropertyPath(false); - } - - public function testValidPropertyPath_zero() - { - new PropertyPath('0'); - } - - public function testGetParent_dot() - { - $propertyPath = new PropertyPath('grandpa.parent.child'); - - $this->assertEquals(new PropertyPath('grandpa.parent'), $propertyPath->getParent()); - } - - public function testGetParent_index() - { - $propertyPath = new PropertyPath('grandpa.parent[child]'); - - $this->assertEquals(new PropertyPath('grandpa.parent'), $propertyPath->getParent()); - } - - public function testGetParent_noParent() - { - $propertyPath = new PropertyPath('path'); - - $this->assertNull($propertyPath->getParent()); - } - - public function testCopyConstructor() - { - $propertyPath = new PropertyPath('grandpa.parent[child]'); - $copy = new PropertyPath($propertyPath); - - $this->assertEquals($propertyPath, $copy); - } - - public function testGetElement() - { - $propertyPath = new PropertyPath('grandpa.parent[child]'); - - $this->assertEquals('child', $propertyPath->getElement(2)); - } - - /** - * @expectedException \OutOfBoundsException - */ - public function testGetElementDoesNotAcceptInvalidIndices() - { - $propertyPath = new PropertyPath('grandpa.parent[child]'); - - $propertyPath->getElement(3); - } - - /** - * @expectedException \OutOfBoundsException - */ - public function testGetElementDoesNotAcceptNegativeIndices() - { - $propertyPath = new PropertyPath('grandpa.parent[child]'); - - $propertyPath->getElement(-1); - } - - public function testIsProperty() - { - $propertyPath = new PropertyPath('grandpa.parent[child]'); - - $this->assertTrue($propertyPath->isProperty(1)); - $this->assertFalse($propertyPath->isProperty(2)); - } - - /** - * @expectedException \OutOfBoundsException - */ - public function testIsPropertyDoesNotAcceptInvalidIndices() - { - $propertyPath = new PropertyPath('grandpa.parent[child]'); - - $propertyPath->isProperty(3); - } - - /** - * @expectedException \OutOfBoundsException - */ - public function testIsPropertyDoesNotAcceptNegativeIndices() - { - $propertyPath = new PropertyPath('grandpa.parent[child]'); - - $propertyPath->isProperty(-1); - } - - public function testIsIndex() - { - $propertyPath = new PropertyPath('grandpa.parent[child]'); - - $this->assertFalse($propertyPath->isIndex(1)); - $this->assertTrue($propertyPath->isIndex(2)); - } - - /** - * @expectedException \OutOfBoundsException - */ - public function testIsIndexDoesNotAcceptInvalidIndices() - { - $propertyPath = new PropertyPath('grandpa.parent[child]'); - - $propertyPath->isIndex(3); - } - - /** - * @expectedException \OutOfBoundsException - */ - public function testIsIndexDoesNotAcceptNegativeIndices() - { - $propertyPath = new PropertyPath('grandpa.parent[child]'); - - $propertyPath->isIndex(-1); - } -} diff --git a/Util/FormUtil.php b/Util/FormUtil.php index 797028bd19..481f6a5080 100644 --- a/Util/FormUtil.php +++ b/Util/FormUtil.php @@ -11,181 +11,29 @@ namespace Symfony\Component\Form\Util; +use Symfony\Component\PropertyAccess\StringUtil; + /** * @author Bernhard Schussek */ class FormUtil { - /** - * Map english plural to singular suffixes - * - * @var array - * - * @see http://english-zone.com/spelling/plurals.html - * @see http://www.scribd.com/doc/3271143/List-of-100-Irregular-Plural-Nouns-in-English - */ - private static $pluralMap = array( - // First entry: plural suffix, reversed - // Second entry: length of plural suffix - // Third entry: Whether the suffix may succeed a vocal - // Fourth entry: Whether the suffix may succeed a consonant - // Fifth entry: singular suffix, normal - - // bacteria (bacterium), criteria (criterion), phenomena (phenomenon) - array('a', 1, true, true, array('on', 'um')), - - // nebulae (nebula) - array('ea', 2, true, true, 'a'), - - // mice (mouse), lice (louse) - array('eci', 3, false, true, 'ouse'), - - // geese (goose) - array('esee', 4, false, true, 'oose'), - - // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius) - array('i', 1, true, true, 'us'), - - // men (man), women (woman) - array('nem', 3, true, true, 'man'), - - // children (child) - array('nerdlihc', 8, true, true, 'child'), - - // oxen (ox) - array('nexo', 4, false, false, 'ox'), - - // indices (index), appendices (appendix), prices (price) - array('seci', 4, false, true, array('ex', 'ix', 'ice')), - - // babies (baby) - array('sei', 3, false, true, 'y'), - - // analyses (analysis), ellipses (ellipsis), funguses (fungus), - // neuroses (neurosis), theses (thesis), emphases (emphasis), - // oases (oasis), crises (crisis), houses (house), bases (base), - // atlases (atlas), kisses (kiss) - array('ses', 3, true, true, array('s', 'se', 'sis')), - - // lives (life), wives (wife) - array('sevi', 4, false, true, 'ife'), - - // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf) - array('sev', 3, true, true, 'f'), - - // axes (axis), axes (ax), axes (axe) - array('sexa', 4, false, false, array('ax', 'axe', 'axis')), - - // indexes (index), matrixes (matrix) - array('sex', 3, true, false, 'x'), - - // quizzes (quiz) - array('sezz', 4, true, false, 'z'), - - // bureaus (bureau) - array('suae', 4, false, true, 'eau'), - - // roses (rose), garages (garage), cassettes (cassette), - // waltzes (waltz), heroes (hero), bushes (bush), arches (arch), - // shoes (shoe) - array('se', 2, true, true, array('', 'e')), - - // tags (tag) - array('s', 1, true, true, ''), - - // chateaux (chateau) - array('xuae', 4, false, true, 'eau'), - ); - /** * This class should not be instantiated */ private function __construct() {} /** - * Returns the singular form of a word - * - * If the method can't determine the form with certainty, an array of the - * possible singulars is returned. + * Alias for {@link StringUtil::singularify()} * - * @param string $plural A word in plural form - * @return string|array The singular form or an array of possible singular - * forms + * @deprecated Deprecated since version 2.2, to be removed in 2.3. Use + * {@link StringUtil::singularify()} instead. */ public static function singularify($plural) { - $pluralRev = strrev($plural); - $lowerPluralRev = strtolower($pluralRev); - $pluralLength = strlen($lowerPluralRev); - - // The outer loop iterates over the entries of the plural table - // The inner loop $j iterates over the characters of the plural suffix - // in the plural table to compare them with the characters of the actual - // given plural suffix - foreach (self::$pluralMap as $map) { - $suffix = $map[0]; - $suffixLength = $map[1]; - $j = 0; - - // Compare characters in the plural table and of the suffix of the - // given plural one by one - while ($suffix[$j] === $lowerPluralRev[$j]) { - // Let $j point to the next character - ++$j; - - // Successfully compared the last character - // Add an entry with the singular suffix to the singular array - if ($j === $suffixLength) { - // Is there any character preceding the suffix in the plural string? - if ($j < $pluralLength) { - $nextIsVocal = false !== strpos('aeiou', $lowerPluralRev[$j]); - - if (!$map[2] && $nextIsVocal) { - // suffix may not succeed a vocal but next char is one - break; - } - - if (!$map[3] && !$nextIsVocal) { - // suffix may not succeed a consonant but next char is one - break; - } - } - - $newBase = substr($plural, 0, $pluralLength - $suffixLength); - $newSuffix = $map[4]; - - // Check whether the first character in the plural suffix - // is uppercased. If yes, uppercase the first character in - // the singular suffix too - $firstUpper = ctype_upper($pluralRev[$j - 1]); - - if (is_array($newSuffix)) { - $singulars = array(); - - foreach ($newSuffix as $newSuffixEntry) { - $singulars[] = $newBase . ($firstUpper ? ucfirst($newSuffixEntry) : $newSuffixEntry); - } - - return $singulars; - } - - return $newBase . ($firstUpper ? ucFirst($newSuffix) : $newSuffix); - } - - // Suffix is longer than word - if ($j === $pluralLength) { - break; - } - } - } - - // Convert teeth to tooth, feet to foot - if (false !== ($pos = strpos($plural, 'ee'))) { - return substr_replace($plural, 'oo', $pos, 2); - } + trigger_error('\Symfony\Component\Form\Util\FormUtil::singularify() is deprecated since version 2.2 and will be removed in 2.3. Use \Symfony\Component\PropertyAccess\StringUtil::singularify() in the PropertyAccess component instead.', E_USER_DEPRECATED); - // Assume that plural and singular is identical - return $plural; + return StringUtil::singularify($plural); } /** diff --git a/Util/PropertyPath.php b/Util/PropertyPath.php index a5cf13befe..445fae81d5 100644 --- a/Util/PropertyPath.php +++ b/Util/PropertyPath.php @@ -11,619 +11,47 @@ namespace Symfony\Component\Form\Util; -use Traversable; -use ReflectionClass; -use Symfony\Component\Form\Exception\InvalidPropertyPathException; -use Symfony\Component\Form\Exception\InvalidPropertyException; -use Symfony\Component\Form\Exception\PropertyAccessDeniedException; -use Symfony\Component\Form\Exception\UnexpectedTypeException; +use Symfony\Component\PropertyAccess\PropertyPath as BasePropertyPath; +use Symfony\Component\PropertyAccess\PropertyAccess; /** - * Allows easy traversing of a property path + * Alias for {@link \Symfony\Component\PropertyAccess\PropertyPath}. * * @author Bernhard Schussek + * + * @deprecated deprecated since version 2.2, to be removed in 2.3. Use + * {@link \Symfony\Component\PropertyAccess\PropertyPath} + * instead. */ -class PropertyPath implements \IteratorAggregate, PropertyPathInterface +class PropertyPath extends BasePropertyPath { - /** - * Character used for separating between plural and singular of an element. - * @var string - */ - const SINGULAR_SEPARATOR = '|'; - - const VALUE = 0; - const IS_REF = 1; - - /** - * The elements of the property path - * @var array - */ - private $elements = array(); - - /** - * The singular forms of the elements in the property path. - * @var array - */ - private $singulars = array(); - - /** - * The number of elements in the property path - * @var integer - */ - private $length; - - /** - * Contains a Boolean for each property in $elements denoting whether this - * element is an index. It is a property otherwise. - * @var array - */ - private $isIndex = array(); - - /** - * String representation of the path - * @var string - */ - private $pathAsString; - - /** - * Constructs a property path from a string. - * - * @param PropertyPath|string $propertyPath The property path as string or instance. - * - * @throws UnexpectedTypeException If the given path is not a string. - * @throws InvalidPropertyPathException If the syntax of the property path is not valid. - */ - public function __construct($propertyPath) - { - // Can be used as copy constructor - if ($propertyPath instanceof PropertyPath) { - /* @var PropertyPath $propertyPath */ - $this->elements = $propertyPath->elements; - $this->singulars = $propertyPath->singulars; - $this->length = $propertyPath->length; - $this->isIndex = $propertyPath->isIndex; - $this->pathAsString = $propertyPath->pathAsString; - - return; - } - if (!is_string($propertyPath)) { - throw new UnexpectedTypeException($propertyPath, 'string or Symfony\Component\Form\Util\PropertyPath'); - } - - if ('' === $propertyPath) { - throw new InvalidPropertyPathException('The property path should not be empty.'); - } - - $this->pathAsString = $propertyPath; - $position = 0; - $remaining = $propertyPath; - - // first element is evaluated differently - no leading dot for properties - $pattern = '/^(([^\.\[]+)|\[([^\]]+)\])(.*)/'; - - while (preg_match($pattern, $remaining, $matches)) { - if ('' !== $matches[2]) { - $element = $matches[2]; - $this->isIndex[] = false; - } else { - $element = $matches[3]; - $this->isIndex[] = true; - } - // Disabled this behaviour as the syntax is not yet final - //$pos = strpos($element, self::SINGULAR_SEPARATOR); - $pos = false; - $singular = null; - - if (false !== $pos) { - $singular = substr($element, $pos + 1); - $element = substr($element, 0, $pos); - } - - $this->elements[] = $element; - $this->singulars[] = $singular; - - $position += strlen($matches[1]); - $remaining = $matches[4]; - $pattern = '/^(\.(\w+)|\[([^\]]+)\])(.*)/'; - } - - if ('' !== $remaining) { - throw new InvalidPropertyPathException(sprintf( - 'Could not parse property path "%s". Unexpected token "%s" at position %d', - $propertyPath, - $remaining{0}, - $position - )); - } - - $this->length = count($this->elements); - } - /** * {@inheritdoc} */ - public function __toString() - { - return $this->pathAsString; - } - - /** - * {@inheritdoc} - */ - public function getLength() - { - return $this->length; - } - - /** - * {@inheritdoc} - */ - public function getParent() - { - if ($this->length <= 1) { - return null; - } - - $parent = clone $this; - - --$parent->length; - $parent->pathAsString = substr($parent->pathAsString, 0, max(strrpos($parent->pathAsString, '.'), strrpos($parent->pathAsString, '['))); - array_pop($parent->elements); - array_pop($parent->singulars); - array_pop($parent->isIndex); - - return $parent; - } - - /** - * Returns a new iterator for this path - * - * @return PropertyPathIteratorInterface - */ - public function getIterator() - { - return new PropertyPathIterator($this); - } - - /** - * {@inheritdoc} - */ - public function getElements() - { - return $this->elements; - } - - /** - * {@inheritdoc} - */ - public function getElement($index) - { - if (!isset($this->elements[$index])) { - throw new \OutOfBoundsException('The index ' . $index . ' is not within the property path'); - } - - return $this->elements[$index]; - } - - /** - * {@inheritdoc} - */ - public function isProperty($index) - { - if (!isset($this->isIndex[$index])) { - throw new \OutOfBoundsException('The index ' . $index . ' is not within the property path'); - } - - return !$this->isIndex[$index]; - } - - /** - * {@inheritdoc} - */ - public function isIndex($index) + public function __construct($propertyPath) { - if (!isset($this->isIndex[$index])) { - throw new \OutOfBoundsException('The index ' . $index . ' is not within the property path'); - } + parent::__construct($propertyPath); - return $this->isIndex[$index]; + trigger_error('\Symfony\Component\Form\Util\PropertyPath is deprecated since version 2.2 and will be removed in 2.3. Use \Symfony\Component\PropertyAccess\PropertyPath instead.', E_USER_DEPRECATED); } /** - * Returns the value at the end of the property path of the object - * - * Example: - * - * $path = new PropertyPath('child.name'); - * - * echo $path->getValue($object); - * // equals echo $object->getChild()->getName(); - * - * - * This method first tries to find a public getter for each property in the - * path. The name of the getter must be the camel-cased property name - * prefixed with "get", "is", or "has". - * - * If the getter does not exist, this method tries to find a public - * property. The value of the property is then returned. - * - * If none of them are found, an exception is thrown. - * - * @param object|array $objectOrArray The object or array to traverse - * - * @return mixed The value at the end of the property path - * - * @throws InvalidPropertyException If the property/getter does not exist - * @throws PropertyAccessDeniedException If the property/getter exists but is not public + * Alias for {@link PropertyAccessor::getValue()} */ public function getValue($objectOrArray) { - $propertyValues =& $this->readPropertiesUntil($objectOrArray, $this->length - 1); - - return $propertyValues[count($propertyValues) - 1][self::VALUE]; - } - - /** - * Sets the value at the end of the property path of the object - * - * Example: - * - * $path = new PropertyPath('child.name'); - * - * echo $path->setValue($object, 'Fabien'); - * // equals echo $object->getChild()->setName('Fabien'); - * - * - * This method first tries to find a public setter for each property in the - * path. The name of the setter must be the camel-cased property name - * prefixed with "set". - * - * If the setter does not exist, this method tries to find a public - * property. The value of the property is then changed. - * - * If neither is found, an exception is thrown. - * - * @param object|array $objectOrArray The object or array to modify. - * @param mixed $value The value to set at the end of the property path. - * - * @throws InvalidPropertyException If a property does not exist. - * @throws PropertyAccessDeniedException If a property cannot be accessed due to - * access restrictions (private or protected). - * @throws UnexpectedTypeException If a value within the path is neither object - * nor array. - */ - public function setValue(&$objectOrArray, $value) - { - $propertyValues =& $this->readPropertiesUntil($objectOrArray, $this->length - 2); - $overwrite = true; - - // Add the root object to the list - array_unshift($propertyValues, array( - self::VALUE => &$objectOrArray, - self::IS_REF => true, - )); - - for ($i = count($propertyValues) - 1; $i >= 0; --$i) { - $objectOrArray =& $propertyValues[$i][self::VALUE]; - - if ($overwrite) { - if (!is_object($objectOrArray) && !is_array($objectOrArray)) { - throw new UnexpectedTypeException($objectOrArray, 'object or array'); - } - - $property = $this->elements[$i]; - $singular = $this->singulars[$i]; - $isIndex = $this->isIndex[$i]; - - $this->writeProperty($objectOrArray, $property, $singular, $isIndex, $value); - } - - $value =& $objectOrArray; - $overwrite = !$propertyValues[$i][self::IS_REF]; - } - } - - /** - * Reads the path from an object up to a given path index. - * - * @param object|array $objectOrArray The object or array to read from. - * @param integer $lastIndex The integer up to which should be read. - * - * @return array The values read in the path. - * - * @throws UnexpectedTypeException If a value within the path is neither object nor array. - */ - private function &readPropertiesUntil(&$objectOrArray, $lastIndex) - { - $propertyValues = array(); - - for ($i = 0; $i <= $lastIndex; ++$i) { - if (!is_object($objectOrArray) && !is_array($objectOrArray)) { - throw new UnexpectedTypeException($objectOrArray, 'object or array'); - } - - $property = $this->elements[$i]; - $isIndex = $this->isIndex[$i]; - $isArrayAccess = is_array($objectOrArray) || $objectOrArray instanceof \ArrayAccess; - - // Create missing nested arrays on demand - if ($isIndex && $isArrayAccess && !isset($objectOrArray[$property])) { - $objectOrArray[$property] = $i + 1 < $this->length ? array() : null; - } - - $propertyValue =& $this->readProperty($objectOrArray, $property, $isIndex); - $objectOrArray =& $propertyValue[self::VALUE]; - - $propertyValues[] =& $propertyValue; - } - - return $propertyValues; - } - - /** - * Reads the a property from an object or array. - * - * @param object|array $objectOrArray The object or array to read from. - * @param string $property The property to read. - * @param Boolean $isIndex Whether to interpret the property as index. - * - * @return mixed The value of the read property - * - * @throws InvalidPropertyException If the property does not exist. - * @throws PropertyAccessDeniedException If the property cannot be accessed due to - * access restrictions (private or protected). - */ - private function &readProperty(&$objectOrArray, $property, $isIndex) - { - // Use an array instead of an object since performance is - // very crucial here - $result = array( - self::VALUE => null, - self::IS_REF => false - ); - - if ($isIndex) { - if (!$objectOrArray instanceof \ArrayAccess && !is_array($objectOrArray)) { - throw new InvalidPropertyException(sprintf('Index "%s" cannot be read from object of type "%s" because it doesn\'t implement \ArrayAccess', $property, get_class($objectOrArray))); - } - - if (isset($objectOrArray[$property])) { - if (is_array($objectOrArray)) { - $result[self::VALUE] =& $objectOrArray[$property]; - $result[self::IS_REF] = true; - } else { - $result[self::VALUE] = $objectOrArray[$property]; - } - } - } elseif (is_object($objectOrArray)) { - $camelProp = $this->camelize($property); - $reflClass = new ReflectionClass($objectOrArray); - $getter = 'get'.$camelProp; - $isser = 'is'.$camelProp; - $hasser = 'has'.$camelProp; - - if ($reflClass->hasMethod($getter)) { - if (!$reflClass->getMethod($getter)->isPublic()) { - throw new PropertyAccessDeniedException(sprintf('Method "%s()" is not public in class "%s"', $getter, $reflClass->name)); - } - - $result[self::VALUE] = $objectOrArray->$getter(); - } elseif ($reflClass->hasMethod($isser)) { - if (!$reflClass->getMethod($isser)->isPublic()) { - throw new PropertyAccessDeniedException(sprintf('Method "%s()" is not public in class "%s"', $isser, $reflClass->name)); - } - - $result[self::VALUE] = $objectOrArray->$isser(); - } elseif ($reflClass->hasMethod($hasser)) { - if (!$reflClass->getMethod($hasser)->isPublic()) { - throw new PropertyAccessDeniedException(sprintf('Method "%s()" is not public in class "%s"', $hasser, $reflClass->name)); - } - - $result[self::VALUE] = $objectOrArray->$hasser(); - } elseif ($reflClass->hasMethod('__get')) { - // needed to support magic method __get - $result[self::VALUE] = $objectOrArray->$property; - } elseif ($reflClass->hasProperty($property)) { - if (!$reflClass->getProperty($property)->isPublic()) { - throw new PropertyAccessDeniedException(sprintf('Property "%s" is not public in class "%s". Maybe you should create the method "%s()" or "%s()" or "%s()"?', $property, $reflClass->name, $getter, $isser, $hasser)); - } - - $result[self::VALUE] =& $objectOrArray->$property; - $result[self::IS_REF] = true; - } elseif (property_exists($objectOrArray, $property)) { - // needed to support \stdClass instances - $result[self::VALUE] =& $objectOrArray->$property; - $result[self::IS_REF] = true; - } else { - throw new InvalidPropertyException(sprintf('Neither property "%s" nor method "%s()" nor method "%s()" exists in class "%s"', $property, $getter, $isser, $reflClass->name)); - } - } else { - throw new InvalidPropertyException(sprintf('Cannot read property "%s" from an array. Maybe you should write the property path as "[%s]" instead?', $property, $property)); - } - - // Objects are always passed around by reference - if (is_object($result[self::VALUE])) { - $result[self::IS_REF] = true; - } - - return $result; - } - - /** - * Sets the value of the property at the given index in the path - * - * @param object|array $objectOrArray The object or array to write to. - * @param string $property The property to write. - * @param string|null $singular The singular form of the property name or null. - * @param Boolean $isIndex Whether to interpret the property as index. - * @param mixed $value The value to write. - * - * @throws InvalidPropertyException If the property does not exist. - * @throws PropertyAccessDeniedException If the property cannot be accessed due to - * access restrictions (private or protected). - */ - private function writeProperty(&$objectOrArray, $property, $singular, $isIndex, $value) - { - $adderRemoverError = null; - - if ($isIndex) { - if (!$objectOrArray instanceof \ArrayAccess && !is_array($objectOrArray)) { - throw new InvalidPropertyException(sprintf('Index "%s" cannot be modified in object of type "%s" because it doesn\'t implement \ArrayAccess', $property, get_class($objectOrArray))); - } - - $objectOrArray[$property] = $value; - } elseif (is_object($objectOrArray)) { - $reflClass = new ReflectionClass($objectOrArray); - - // The plural form is the last element of the property path - $plural = $this->camelize($this->elements[$this->length - 1]); - - // Any of the two methods is required, but not yet known - $singulars = null !== $singular ? array($singular) : (array) FormUtil::singularify($plural); - - if (is_array($value) || $value instanceof Traversable) { - $methods = $this->findAdderAndRemover($reflClass, $singulars); - if (null !== $methods) { - // At this point the add and remove methods have been found - // Use iterator_to_array() instead of clone in order to prevent side effects - // see https://github.com/symfony/symfony/issues/4670 - $itemsToAdd = is_object($value) ? iterator_to_array($value) : $value; - $itemToRemove = array(); - $propertyValue = $this->readProperty($objectOrArray, $property, $isIndex); - $previousValue = $propertyValue[self::VALUE]; - - if (is_array($previousValue) || $previousValue instanceof Traversable) { - foreach ($previousValue as $previousItem) { - foreach ($value as $key => $item) { - if ($item === $previousItem) { - // Item found, don't add - unset($itemsToAdd[$key]); - - // Next $previousItem - continue 2; - } - } - - // Item not found, add to remove list - $itemToRemove[] = $previousItem; - } - } - - foreach ($itemToRemove as $item) { - call_user_func(array($objectOrArray, $methods[1]), $item); - } - - foreach ($itemsToAdd as $item) { - call_user_func(array($objectOrArray, $methods[0]), $item); - } - - return; - } else { - $adderRemoverError = ', nor could adders and removers be found based on the '; - if (null === $singular) { - // $adderRemoverError .= 'guessed singulars: '.implode(', ', $singulars).' (provide a singular by suffixing the property path with "|{singular}" to override the guesser)'; - $adderRemoverError .= 'guessed singulars: '.implode(', ', $singulars); - } else { - $adderRemoverError .= 'passed singular: '.$singular; - } - } - } - - $setter = 'set'.$this->camelize($property); - if ($reflClass->hasMethod($setter)) { - if (!$reflClass->getMethod($setter)->isPublic()) { - throw new PropertyAccessDeniedException(sprintf('Method "%s()" is not public in class "%s"', $setter, $reflClass->name)); - } - - $objectOrArray->$setter($value); - } elseif ($reflClass->hasMethod('__set')) { - // needed to support magic method __set - $objectOrArray->$property = $value; - } elseif ($reflClass->hasProperty($property)) { - if (!$reflClass->getProperty($property)->isPublic()) { - throw new PropertyAccessDeniedException(sprintf('Property "%s" is not public in class "%s"%s. Maybe you should create the method "%s()"?', $property, $reflClass->name, $adderRemoverError, $setter)); - } - - $objectOrArray->$property = $value; - } elseif (property_exists($objectOrArray, $property)) { - // needed to support \stdClass instances - $objectOrArray->$property = $value; - } else { - throw new InvalidPropertyException(sprintf('Neither element "%s" nor method "%s()" exists in class "%s"%s', $property, $setter, $reflClass->name, $adderRemoverError)); - } - } else { - throw new InvalidPropertyException(sprintf('Cannot write property "%s" in an array. Maybe you should write the property path as "[%s]" instead?', $property, $property)); - } - } - - /** - * Camelizes a given string. - * - * @param string $string Some string. - * - * @return string The camelized version of the string. - */ - private function camelize($string) - { - return preg_replace_callback('/(^|_|\.)+(.)/', function ($match) { return ('.' === $match[1] ? '_' : '').strtoupper($match[2]); }, $string); - } - - /** - * Searches for add and remove methods. - * - * @param \ReflectionClass $reflClass The reflection class for the given object - * @param array $singulars The singular form of the property name or null. - * - * @return array|null An array containing the adder and remover when found, null otherwise. - * - * @throws InvalidPropertyException If the property does not exist. - */ - private function findAdderAndRemover(\ReflectionClass $reflClass, array $singulars) - { - foreach ($singulars as $singular) { - $addMethod = 'add' . $singular; - $removeMethod = 'remove' . $singular; + $propertyAccessor = PropertyAccess::getPropertyAccessor(); - $addMethodFound = $this->isAccessible($reflClass, $addMethod, 1); - $removeMethodFound = $this->isAccessible($reflClass, $removeMethod, 1); - - if ($addMethodFound && $removeMethodFound) { - return array($addMethod, $removeMethod); - } - - if ($addMethodFound xor $removeMethodFound) { - throw new InvalidPropertyException(sprintf( - 'Found the public method "%s", but did not find a public "%s" on class %s', - $addMethodFound ? $addMethod : $removeMethod, - $addMethodFound ? $removeMethod : $addMethod, - $reflClass->name - )); - } - } - - return null; + return $propertyAccessor->getValue($objectOrArray, $this); } /** - * Returns whether a method is public and has a specific number of required parameters. - * - * @param \ReflectionClass $class The class of the method. - * @param string $methodName The method name. - * @param integer $parameters The number of parameters. - * - * @return Boolean Whether the method is public and has $parameters - * required parameters. + * Alias for {@link PropertyAccessor::setValue()} */ - private function isAccessible(ReflectionClass $class, $methodName, $parameters) + public function setValue($objectOrArray, $value) { - if ($class->hasMethod($methodName)) { - $method = $class->getMethod($methodName); - - if ($method->isPublic() && $method->getNumberOfRequiredParameters() === $parameters) { - return true; - } - } + $propertyAccessor = PropertyAccess::getPropertyAccessor(); - return false; + return $propertyAccessor->getValue($objectOrArray, $this, $value); } } diff --git a/Util/PropertyPathBuilder.php b/Util/PropertyPathBuilder.php index f17c8b2258..31836b63bd 100644 --- a/Util/PropertyPathBuilder.php +++ b/Util/PropertyPathBuilder.php @@ -11,284 +11,26 @@ namespace Symfony\Component\Form\Util; +use Symfony\Component\PropertyAccess\PropertyPathBuilder as BasePropertyPathBuilder; + /** + * Alias for {@link \Symfony\Component\PropertyAccess\PropertyPathBuilder}. + * * @author Bernhard Schussek + * + * @deprecated deprecated since version 2.2, to be removed in 2.3. Use + * {@link \Symfony\Component\PropertyAccess\PropertyPathBuilder} + * instead. */ -class PropertyPathBuilder +class PropertyPathBuilder extends BasePropertyPathBuilder { /** - * @var array - */ - private $elements = array(); - - /** - * @var array - */ - private $isIndex = array(); - - /** - * Creates a new property path builder. - * - * @param null|PropertyPathInterface $path The path to initially store - * in the builder. Optional. - */ - public function __construct(PropertyPathInterface $path = null) - { - if (null !== $path) { - $this->append($path); - } - } - - /** - * Appends a (sub-) path to the current path. - * - * @param PropertyPathInterface $path The path to append. - * @param integer $offset The offset where the appended piece - * starts in $path. - * @param integer $length The length of the appended piece. - * If 0, the full path is appended. + * {@inheritdoc} */ - public function append(PropertyPathInterface $path, $offset = 0, $length = 0) + public function __construct($propertyPath) { - if (0 === $length) { - $end = $path->getLength(); - } else { - $end = $offset + $length; - } - - for (; $offset < $end; ++$offset) { - $this->elements[] = $path->getElement($offset); - $this->isIndex[] = $path->isIndex($offset); - } - } - - /** - * Appends an index element to the current path. - * - * @param string $name The name of the appended index. - */ - public function appendIndex($name) - { - $this->elements[] = $name; - $this->isIndex[] = true; - } - - /** - * Appends a property element to the current path. - * - * @param string $name The name of the appended property. - */ - public function appendProperty($name) - { - $this->elements[] = $name; - $this->isIndex[] = false; - } - - /** - * Removes elements from the current path. - * - * @param integer $offset The offset at which to remove. - * @param integer $length The length of the removed piece. - * - * @throws \OutOfBoundsException if offset is invalid - */ - public function remove($offset, $length = 1) - { - if (!isset($this->elements[$offset])) { - throw new \OutOfBoundsException('The offset ' . $offset . ' is not within the property path'); - } - - $this->resize($offset, $length, 0); - } - - /** - * Replaces a sub-path by a different (sub-) path. - * - * @param integer $offset The offset at which to replace. - * @param integer $length The length of the piece to replace. - * @param PropertyPathInterface $path The path to insert. - * @param integer $pathOffset The offset where the inserted piece - * starts in $path. - * @param integer $pathLength The length of the inserted piece. - * If 0, the full path is inserted. - * - * @throws \OutOfBoundsException If the offset is invalid. - */ - public function replace($offset, $length, PropertyPathInterface $path, $pathOffset = 0, $pathLength = 0) - { - if (!isset($this->elements[$offset])) { - throw new \OutOfBoundsException('The offset ' . $offset . ' is not within the property path'); - } - - if (0 === $pathLength) { - $pathLength = $path->getLength() - $pathOffset; - } - - $this->resize($offset, $length, $pathLength); - - for ($i = 0; $i < $pathLength; ++$i) { - $this->elements[$offset + $i] = $path->getElement($pathOffset + $i); - $this->isIndex[$offset + $i] = $path->isIndex($pathOffset + $i); - } - } - - /** - * Replaces a property element by an index element. - * - * @param integer $offset The offset at which to replace. - * @param string $name The new name of the element. Optional. - * - * @throws \OutOfBoundsException If the offset is invalid. - */ - public function replaceByIndex($offset, $name = null) - { - if (!isset($this->elements[$offset])) { - throw new \OutOfBoundsException('The offset ' . $offset . ' is not within the property path'); - } - - if (null !== $name) { - $this->elements[$offset] = $name; - } - - $this->isIndex[$offset] = true; - } - - /** - * Replaces an index element by a property element. - * - * @param integer $offset The offset at which to replace. - * @param string $name The new name of the element. Optional. - * - * @throws \OutOfBoundsException If the offset is invalid. - */ - public function replaceByProperty($offset, $name = null) - { - if (!isset($this->elements[$offset])) { - throw new \OutOfBoundsException('The offset ' . $offset . ' is not within the property path'); - } - - if (null !== $name) { - $this->elements[$offset] = $name; - } - - $this->isIndex[$offset] = false; - } - - /** - * Returns the length of the current path. - * - * @return integer The path length. - */ - public function getLength() - { - return count($this->elements); - } - - /** - * Returns the current property path. - * - * @return PropertyPathInterface The constructed property path. - */ - public function getPropertyPath() - { - $pathAsString = $this->__toString(); - - return '' !== $pathAsString ? new PropertyPath($pathAsString) : null; - } - - /** - * Returns the current property path as string. - * - * @return string The property path as string. - */ - public function __toString() - { - $string = ''; - - foreach ($this->elements as $offset => $element) { - if ($this->isIndex[$offset]) { - $element = '[' . $element . ']'; - } elseif ('' !== $string) { - $string .= '.'; - } - - $string .= $element; - } - - return $string; - } - - /** - * Resizes the path so that a chunk of length $cutLength is - * removed at $offset and another chunk of length $insertionLength - * can be inserted. - * - * @param integer $offset The offset where the removed chunk starts. - * @param integer $cutLength The length of the removed chunk. - * @param integer $insertionLength The length of the inserted chunk. - */ - private function resize($offset, $cutLength, $insertionLength) - { - // Nothing else to do in this case - if ($insertionLength === $cutLength) { - return; - } - - $length = count($this->elements); - - if ($cutLength > $insertionLength) { - // More elements should be removed than inserted - $diff = $cutLength - $insertionLength; - $newLength = $length - $diff; - - // Shift elements to the left (left-to-right until the new end) - // Max allowed offset to be shifted is such that - // $offset + $diff < $length (otherwise invalid index access) - // i.e. $offset < $length - $diff = $newLength - for ($i = $offset; $i < $newLength; ++$i) { - $this->elements[$i] = $this->elements[$i + $diff]; - $this->isIndex[$i] = $this->isIndex[$i + $diff]; - } - - // All remaining elements should be removed - for (; $i < $length; ++$i) { - unset($this->elements[$i]); - unset($this->isIndex[$i]); - } - } else { - $diff = $insertionLength - $cutLength; - - $newLength = $length + $diff; - $indexAfterInsertion = $offset + $insertionLength; - - // $diff <= $insertionLength - // $indexAfterInsertion >= $insertionLength - // => $diff <= $indexAfterInsertion - - // In each of the following loops, $i >= $diff must hold, - // otherwise ($i - $diff) becomes negative. - - // Shift old elements to the right to make up space for the - // inserted elements. This needs to be done left-to-right in - // order to preserve an ascending array index order - // Since $i = max($length, $indexAfterInsertion) and $indexAfterInsertion >= $diff, - // $i >= $diff is guaranteed. - for ($i = max($length, $indexAfterInsertion); $i < $newLength; ++$i) { - $this->elements[$i] = $this->elements[$i - $diff]; - $this->isIndex[$i] = $this->isIndex[$i - $diff]; - } + parent::__construct($propertyPath); - // Shift remaining elements to the right. Do this right-to-left - // so we don't overwrite elements before copying them - // The last written index is the immediate index after the inserted - // string, because the indices before that will be overwritten - // anyway. - // Since $i >= $indexAfterInsertion and $indexAfterInsertion >= $diff, - // $i >= $diff is guaranteed. - for ($i = $length - 1; $i >= $indexAfterInsertion; --$i) { - $this->elements[$i] = $this->elements[$i - $diff]; - $this->isIndex[$i] = $this->isIndex[$i - $diff]; - } - } + trigger_error('\Symfony\Component\Form\Util\PropertyPathBuilder is deprecated since version 2.2 and will be removed in 2.3. Use \Symfony\Component\PropertyAccess\PropertyPathBuilder instead.', E_USER_DEPRECATED); } } diff --git a/Util/PropertyPathInterface.php b/Util/PropertyPathInterface.php index bceca29d90..ec2d5e9efb 100644 --- a/Util/PropertyPathInterface.php +++ b/Util/PropertyPathInterface.php @@ -11,74 +11,17 @@ namespace Symfony\Component\Form\Util; +use Symfony\Component\PropertyAccess\PropertyPathInterface as BasePropertyPathInterface; + /** + * Alias for {@link \Symfony\Component\PropertyAccess\PropertyPathInterface}. + * * @author Bernhard Schussek + * + * @deprecated deprecated since version 2.2, to be removed in 2.3. Use + * {@link \Symfony\Component\PropertyAccess\PropertyPathInterface} + * instead. */ -interface PropertyPathInterface extends \Traversable +interface PropertyPathInterface extends BasePropertyPathInterface { - /** - * Returns the string representation of the property path - * - * @return string The path as string. - */ - public function __toString(); - - /** - * Returns the length of the property path, i.e. the number of elements. - * - * @return integer The path length. - */ - public function getLength(); - - /** - * Returns the parent property path. - * - * The parent property path is the one that contains the same items as - * this one except for the last one. - * - * If this property path only contains one item, null is returned. - * - * @return PropertyPath The parent path or null. - */ - public function getParent(); - - /** - * Returns the elements of the property path as array - * - * @return array An array of property/index names - */ - public function getElements(); - - /** - * Returns the element at the given index in the property path - * - * @param integer $index The index key - * - * @return string A property or index name - * - * @throws \OutOfBoundsException If the offset is invalid. - */ - public function getElement($index); - - /** - * Returns whether the element at the given index is a property - * - * @param integer $index The index in the property path - * - * @return Boolean Whether the element at this index is a property - * - * @throws \OutOfBoundsException If the offset is invalid. - */ - public function isProperty($index); - - /** - * Returns whether the element at the given index is an array index - * - * @param integer $index The index in the property path - * - * @return Boolean Whether the element at this index is an array index - * - * @throws \OutOfBoundsException If the offset is invalid. - */ - public function isIndex($index); } diff --git a/Util/PropertyPathIterator.php b/Util/PropertyPathIterator.php index c165d0854e..024ed6a653 100644 --- a/Util/PropertyPathIterator.php +++ b/Util/PropertyPathIterator.php @@ -11,45 +11,26 @@ namespace Symfony\Component\Form\Util; +use Symfony\Component\PropertyAccess\PropertyPathIterator as BasePropertyPathIterator; + /** - * Traverses a property path and provides additional methods to find out - * information about the current element + * Alias for {@link \Symfony\Component\PropertyAccess\PropertyPathIterator}. * * @author Bernhard Schussek + * + * @deprecated deprecated since version 2.2, to be removed in 2.3. Use + * {@link \Symfony\Component\PropertyAccess\PropertyPathIterator} + * instead. */ -class PropertyPathIterator extends \ArrayIterator implements PropertyPathIteratorInterface +class PropertyPathIterator extends BasePropertyPathIterator { - /** - * The traversed property path - * @var PropertyPathInterface - */ - protected $path; - - /** - * Constructor. - * - * @param PropertyPathInterface $path The property path to traverse - */ - public function __construct(PropertyPathInterface $path) - { - parent::__construct($path->getElements()); - - $this->path = $path; - } - /** * {@inheritdoc} */ - public function isIndex() + public function __construct($propertyPath) { - return $this->path->isIndex($this->key()); - } + parent::__construct($propertyPath); - /** - * {@inheritdoc} - */ - public function isProperty() - { - return $this->path->isProperty($this->key()); + trigger_error('\Symfony\Component\Form\Util\PropertyPathIterator is deprecated since version 2.2 and will be removed in 2.3. Use \Symfony\Component\PropertyAccess\PropertyPathIterator instead.', E_USER_DEPRECATED); } } diff --git a/Util/PropertyPathIteratorInterface.php b/Util/PropertyPathIteratorInterface.php index 35fb11ad73..3540639530 100644 --- a/Util/PropertyPathIteratorInterface.php +++ b/Util/PropertyPathIteratorInterface.php @@ -11,24 +11,17 @@ namespace Symfony\Component\Form\Util; +use Symfony\Component\PropertyAccess\PropertyPathIteratorInterface as BasePropertyPathIteratorInterface; + /** + * Alias for {@link \Symfony\Component\PropertyAccess\PropertyPathIteratorInterface}. + * * @author Bernhard Schussek + * + * @deprecated deprecated since version 2.2, to be removed in 2.3. Use + * {@link \Symfony\Component\PropertyAccess\PropertyPathIterator} + * instead. */ -interface PropertyPathIteratorInterface extends \Iterator, \SeekableIterator +interface PropertyPathIteratorInterface extends BasePropertyPathIteratorInterface { - /** - * Returns whether the current element in the property path is an array - * index. - * - * @return Boolean - */ - public function isIndex(); - - /** - * Returns whether the current element in the property path is a property - * name. - * - * @return Boolean - */ - public function isProperty(); } diff --git a/composer.json b/composer.json index 1e69cb140d..51afa67c3a 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,8 @@ "php": ">=5.3.3", "symfony/event-dispatcher": "2.2.*", "symfony/locale": "2.2.*", - "symfony/options-resolver": "2.2.*" + "symfony/options-resolver": "2.2.*", + "symfony/property-access": "2.2.*" }, "require-dev": { "symfony/validator": "2.2.*", From 8aa62f057b166c643db523c99980dee2af98fdb7 Mon Sep 17 00:00:00 2001 From: Jan Kramer Date: Fri, 11 Jan 2013 07:43:26 +0100 Subject: [PATCH 053/447] Fixed broken setter in Form/Util/PropertyPath --- Util/PropertyPath.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Util/PropertyPath.php b/Util/PropertyPath.php index 445fae81d5..41acf0d889 100644 --- a/Util/PropertyPath.php +++ b/Util/PropertyPath.php @@ -48,10 +48,10 @@ public function getValue($objectOrArray) /** * Alias for {@link PropertyAccessor::setValue()} */ - public function setValue($objectOrArray, $value) + public function setValue(&$objectOrArray, $value) { $propertyAccessor = PropertyAccess::getPropertyAccessor(); - return $propertyAccessor->getValue($objectOrArray, $this, $value); + return $propertyAccessor->setValue($objectOrArray, $this, $value); } } From 0e0771e8ce6eb7017e78bcde4a4036b6eea10f00 Mon Sep 17 00:00:00 2001 From: oscartv Date: Mon, 14 Jan 2013 14:48:41 +0100 Subject: [PATCH 054/447] Update src/Symfony/Component/Form/Resources/translations/validators.ca.xlf --- Resources/translations/validators.ca.xlf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/translations/validators.ca.xlf b/Resources/translations/validators.ca.xlf index c33bbab8f0..3a2fa484f8 100644 --- a/Resources/translations/validators.ca.xlf +++ b/Resources/translations/validators.ca.xlf @@ -12,7 +12,7 @@ The CSRF token is invalid. Please try to resubmit the form. - El token CSRF no és vàlid. Per favor, provi d'enviar novament el formulari + El token CSRF no és vàlid. Per favor, provi d'enviar novament el formulari. From 905017bdb1187c393b1eb44db110aec429f245be Mon Sep 17 00:00:00 2001 From: Maks Slesarenko Date: Fri, 11 Jan 2013 23:40:12 -0500 Subject: [PATCH 055/447] Fix for hardcode (#6384) in choice widget --- Tests/AbstractLayoutTest.php | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index e2801c2d8e..6bffae3a6b 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -524,7 +524,7 @@ public function testSingleChoiceWithNonRequiredEmptyValue() [@name="name"] [not(@required)] [ - ./option[@value=""][not(@selected)][@disabled][.="[trans]Select&Anything&Not&Me[/trans]"] + ./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Anything&Not&Me[/trans]"] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] @@ -790,7 +790,7 @@ public function testCountryWithEmptyValue() $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] - [./option[@value=""][not(@selected)][@disabled][.="[trans]Select&Country[/trans]"]] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Country[/trans]"]] [./option[@value="AT"][@selected="selected"][.="[trans]Austria[/trans]"]] [count(./option)>201] ' @@ -852,13 +852,13 @@ public function testDateTimeWithEmptyValueGlobal() [ ./select [@id="name_date_month"] - [./option[@value=""][@selected][@disabled][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] /following-sibling::select [@id="name_date_day"] - [./option[@value=""][@selected][@disabled][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] /following-sibling::select [@id="name_date_year"] - [./option[@value=""][@selected][@disabled][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] ] /following-sibling::div [@id="name_time"] @@ -907,10 +907,10 @@ public function testDateTimeWithEmptyValueOnTime() [ ./select [@id="name_time_hour"] - [./option[@value=""][not(@selected)][@disabled][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] /following-sibling::select [@id="name_time_minute"] - [./option[@value=""][not(@selected)][@disabled][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] ] ] [count(.//select)=5] @@ -1063,13 +1063,13 @@ public function testDateChoiceWithEmptyValueGlobal() [ ./select [@id="name_month"] - [./option[@value=""][@selected][@disabled][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] /following-sibling::select [@id="name_day"] - [./option[@value=""][@selected][@disabled][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] /following-sibling::select [@id="name_year"] - [./option[@value=""][@selected][@disabled][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] ] [count(./select)=3] ' @@ -1096,7 +1096,7 @@ public function testDateChoiceWithEmptyValueOnYear() [./option[@value="1"]] /following-sibling::select [@id="name_year"] - [./option[@value=""][@selected][@disabled][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] ] [count(./select)=3] ' @@ -1195,15 +1195,15 @@ public function testBirthDayWithEmptyValue() [ ./select [@id="name_month"] - [./option[@value=""][not(@selected)][@disabled][.="[trans][/trans]"]] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"]] [./option[@value="1"][@selected="selected"]] /following-sibling::select [@id="name_day"] - [./option[@value=""][not(@selected)][@disabled][.="[trans][/trans]"]] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"]] [./option[@value="1"][@selected="selected"]] /following-sibling::select [@id="name_year"] - [./option[@value=""][not(@selected)][@disabled][.="[trans][/trans]"]] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"]] [./option[@value="1950"][@selected="selected"]] ] [count(./select)=3] @@ -1635,11 +1635,11 @@ public function testTimeWithEmptyValueGlobal() [ ./select [@id="name_hour"] - [./option[@value=""][@selected][@disabled][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] [count(./option)>24] /following-sibling::select [@id="name_minute"] - [./option[@value=""][@selected][@disabled][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] [count(./option)>60] ] [count(./select)=2] @@ -1660,7 +1660,7 @@ public function testTimeWithEmptyValueOnYear() [ ./select [@id="name_hour"] - [./option[@value=""][@selected][@disabled][.="[trans]Change&Me[/trans]"]] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] [count(./option)>24] /following-sibling::select [@id="name_minute"] @@ -1710,7 +1710,7 @@ public function testTimezoneWithEmptyValue() $this->assertWidgetMatchesXpath($form->createView(), array(), '/select - [./option[@value=""][@selected][@disabled][.="[trans]Select&Timezone[/trans]"]] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Timezone[/trans]"]] [count(./optgroup)>10] [count(.//option)>201] ' From 664c16b6fd66bb86553022f4ccd121231eef2f9f Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 24 Jan 2013 13:42:16 +0100 Subject: [PATCH 056/447] updated ValidatorExtension to avoid using a deprecated method --- Extension/Validator/ValidatorExtension.php | 2 +- Tests/Extension/Validator/Type/TypeTestCase.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Extension/Validator/ValidatorExtension.php b/Extension/Validator/ValidatorExtension.php index 3a70b6215e..e6d6fea415 100644 --- a/Extension/Validator/ValidatorExtension.php +++ b/Extension/Validator/ValidatorExtension.php @@ -36,7 +36,7 @@ public function __construct(ValidatorInterface $validator) // code must be kept synchronized with validation.xml /** @var \Symfony\Component\Validator\Mapping\ClassMetadata $metadata */ - $metadata = $this->validator->getMetadataFactory()->getClassMetadata('Symfony\Component\Form\Form'); + $metadata = $this->validator->getMetadataFactory()->getMetadataFor('Symfony\Component\Form\Form'); $metadata->addConstraint(new Form()); $metadata->addPropertyConstraint('children', new Valid()); } diff --git a/Tests/Extension/Validator/Type/TypeTestCase.php b/Tests/Extension/Validator/Type/TypeTestCase.php index 9fbc17cb58..45c2690ded 100644 --- a/Tests/Extension/Validator/Type/TypeTestCase.php +++ b/Tests/Extension/Validator/Type/TypeTestCase.php @@ -25,10 +25,10 @@ protected function setUp() } $this->validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface'); - $metadataFactory = $this->getMock('Symfony\Component\Validator\Mapping\ClassMetadataFactoryInterface'); + $metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface'); $this->validator->expects($this->once())->method('getMetadataFactory')->will($this->returnValue($metadataFactory)); $metadata = $this->getMockBuilder('Symfony\Component\Validator\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); - $metadataFactory->expects($this->once())->method('getClassMetadata')->will($this->returnValue($metadata)); + $metadataFactory->expects($this->once())->method('getMetadataFor')->will($this->returnValue($metadata)); parent::setUp(); } From 07fae6c09460554f6bad4d52aff555f1c4ee35ce Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 24 Jan 2013 15:43:51 +0100 Subject: [PATCH 057/447] removed deprecated message in FieldType --- Extension/Core/Type/FieldType.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Extension/Core/Type/FieldType.php b/Extension/Core/Type/FieldType.php index 6a479623f5..dbafde1f65 100644 --- a/Extension/Core/Type/FieldType.php +++ b/Extension/Core/Type/FieldType.php @@ -22,11 +22,6 @@ */ class FieldType extends AbstractType { - public function __construct() - { - trigger_error('FieldType is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); - } - /** * {@inheritdoc} */ From 4b78231aecef06ad6e4d25517b04b98e41227ad8 Mon Sep 17 00:00:00 2001 From: TravisCarden Date: Thu, 31 Jan 2013 12:27:04 -0600 Subject: [PATCH 058/447] Remove executable bit from all PHP files --- Extension/Validator/ValidatorTypeGuesser.php | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 Extension/Validator/ValidatorTypeGuesser.php diff --git a/Extension/Validator/ValidatorTypeGuesser.php b/Extension/Validator/ValidatorTypeGuesser.php old mode 100755 new mode 100644 From 7d8c3fd42d28ec82133a989821a3bdd9ba1a4998 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 31 Jan 2013 22:39:01 +0100 Subject: [PATCH 059/447] updated the branch alias in composer files --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 51afa67c3a..b5f5a89682 100644 --- a/composer.json +++ b/composer.json @@ -37,7 +37,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "2.2-dev" + "dev-master": "2.3-dev" } } } From 7bf3e4f96f22b80050074cf99bd6a0a335361f87 Mon Sep 17 00:00:00 2001 From: Mahmoud Mostafa Date: Fri, 1 Feb 2013 23:17:59 +0200 Subject: [PATCH 060/447] Add Arabic translations. --- Resources/translations/validators.ar.xlf | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 Resources/translations/validators.ar.xlf diff --git a/Resources/translations/validators.ar.xlf b/Resources/translations/validators.ar.xlf new file mode 100644 index 0000000000..990b039d63 --- /dev/null +++ b/Resources/translations/validators.ar.xlf @@ -0,0 +1,19 @@ + + + + + + This form should not contain extra fields. + هذا النموذج يجب الا يحتوى على اى حقول اضافية. + + + The uploaded file was too large. Please try to upload a smaller file. + مساحة الملف المرسل كبيرة. من فضلك حاول ارسال ملف اصغر. + + + The CSRF token is invalid. Please try to resubmit the form. + قيمة رمز الموقع غير صحيحة. من فضلك اعد ارسال النموذج. + + + + From d5bbae3ae659aa74639536b130e5594eacab6515 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Perrin?= Date: Tue, 5 Feb 2013 11:48:13 +0100 Subject: [PATCH 061/447] Add "'property_path' => false" deprecation message for forms --- Extension/Core/Type/FormType.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Extension/Core/Type/FormType.php b/Extension/Core/Type/FormType.php index 44b60aaf86..93b20fdbd2 100644 --- a/Extension/Core/Type/FormType.php +++ b/Extension/Core/Type/FormType.php @@ -56,6 +56,10 @@ public function buildForm(FormBuilderInterface $builder, array $options) ->setDataMapper($options['compound'] ? new PropertyPathMapper($this->propertyAccessor) : null) ; + if (false === $options['property_path']) { + trigger_error('\'property_path\' => false is deprecated since version 2.1 and will be removed in 2.3. Use \'mapped\' => false instead.', E_USER_DEPRECATED); + } + if ($options['trim']) { $builder->addEventSubscriber(new TrimListener()); } From 7cdf5e56efb14f5f72aaa9c8e7f51b258f6c6c9e Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 5 Feb 2013 15:17:02 +0100 Subject: [PATCH 062/447] tweaked previous merge --- Extension/Core/Type/FormType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/Core/Type/FormType.php b/Extension/Core/Type/FormType.php index 93b20fdbd2..8e089bd4d6 100644 --- a/Extension/Core/Type/FormType.php +++ b/Extension/Core/Type/FormType.php @@ -57,7 +57,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) ; if (false === $options['property_path']) { - trigger_error('\'property_path\' => false is deprecated since version 2.1 and will be removed in 2.3. Use \'mapped\' => false instead.', E_USER_DEPRECATED); + trigger_error('Setting "property_path" to "false" is deprecated since version 2.1 and will be removed in 2.3. Set "mapped" to "false" instead.', E_USER_DEPRECATED); } if ($options['trim']) { From bae7b135b894e43f12974949c0cd4b50e2951aaa Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 8 Feb 2013 13:13:08 +0100 Subject: [PATCH 063/447] use ~2.0 when depending on the locale component Some methods have been added in 2.1 but none of them are used by the Symfony components. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 51afa67c3a..3dde43f23f 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "require": { "php": ">=5.3.3", "symfony/event-dispatcher": "2.2.*", - "symfony/locale": "2.2.*", + "symfony/locale": "~2.0", "symfony/options-resolver": "2.2.*", "symfony/property-access": "2.2.*" }, From b0c599d2336e61fb940251435b5e91110e0b1273 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 8 Feb 2013 15:05:11 +0100 Subject: [PATCH 064/447] updated required versions when depending on the PropertyAccess component --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 3dde43f23f..35779d95f5 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ "symfony/event-dispatcher": "2.2.*", "symfony/locale": "~2.0", "symfony/options-resolver": "2.2.*", - "symfony/property-access": "2.2.*" + "symfony/property-access": ">=2.2,<2.3-dev" }, "require-dev": { "symfony/validator": "2.2.*", From a0252c9e368c5c58830e0e0f1dd99653f9ddb08d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 8 Feb 2013 15:22:22 +0100 Subject: [PATCH 065/447] updated required versions when depending on the OptionsResolver component --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 35779d95f5..e47c3c5fe9 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,7 @@ "php": ">=5.3.3", "symfony/event-dispatcher": "2.2.*", "symfony/locale": "~2.0", - "symfony/options-resolver": "2.2.*", + "symfony/options-resolver": ">=2.1,<2.3-dev", "symfony/property-access": ">=2.2,<2.3-dev" }, "require-dev": { From 1047dc29d81ad690875d57b6ce9a25326e39ea39 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 8 Feb 2013 15:25:24 +0100 Subject: [PATCH 066/447] updated required versions when depending on the EventDispatcher component --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index e47c3c5fe9..10e87128de 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": ">=5.3.3", - "symfony/event-dispatcher": "2.2.*", + "symfony/event-dispatcher": "~2.1", "symfony/locale": "~2.0", "symfony/options-resolver": ">=2.1,<2.3-dev", "symfony/property-access": ">=2.2,<2.3-dev" From b6c9cb4acd36f9005e23cd9c369c6900b42f4fe6 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 8 Feb 2013 16:08:22 +0100 Subject: [PATCH 067/447] updated required versions when depending on the Validator component --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 10e87128de..1e42bf0be4 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,7 @@ "symfony/property-access": ">=2.2,<2.3-dev" }, "require-dev": { - "symfony/validator": "2.2.*", + "symfony/validator": ">=2.2,<2.3-dev", "symfony/http-foundation": "2.2.*" }, "suggest": { From b75a068239dcd3859e1da4811f71ab6a3a84466d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 8 Feb 2013 16:56:56 +0100 Subject: [PATCH 068/447] updated required versions when depending on the HttpFoundation component --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 1e42bf0be4..9f175f4e52 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ }, "require-dev": { "symfony/validator": ">=2.2,<2.3-dev", - "symfony/http-foundation": "2.2.*" + "symfony/http-foundation": ">=2.1,<2.3-dev" }, "suggest": { "symfony/validator": "2.2.*", From d027e7db87e05d774209d71241093f01b5dcf803 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 11 Feb 2013 11:13:05 +0100 Subject: [PATCH 069/447] changed dependencies to allow all 2.3 versions of the components (closes #6983) --- composer.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index e69593be7a..5ceb9095cc 100644 --- a/composer.json +++ b/composer.json @@ -19,12 +19,12 @@ "php": ">=5.3.3", "symfony/event-dispatcher": "~2.1", "symfony/locale": "~2.0", - "symfony/options-resolver": ">=2.1,<2.3-dev", - "symfony/property-access": ">=2.2,<2.3-dev" + "symfony/options-resolver": ">=2.1,<2.4-dev", + "symfony/property-access": ">=2.2,<2.4-dev" }, "require-dev": { - "symfony/validator": ">=2.2,<2.3-dev", - "symfony/http-foundation": ">=2.1,<2.3-dev" + "symfony/validator": ">=2.2,<2.4-dev", + "symfony/http-foundation": ">=2.1,<2.4-dev" }, "suggest": { "symfony/validator": "2.2.*", From 192906b466c712c165dbea92b70ca42801c4d73a Mon Sep 17 00:00:00 2001 From: 77web Date: Thu, 7 Feb 2013 18:53:06 +0900 Subject: [PATCH 070/447] [Form]fixed FormRenderer::humanize() to humanize camel cased label --- CHANGELOG.md | 6 ++++++ FormRenderer.php | 2 +- Tests/FormRendererTest.php | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 Tests/FormRendererTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 67f8e3c18e..08f1aec42f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= + +2.3.0 +------ + + * changed FormRenderer::humanize() to humanize also camel cased field name + 2.2.0 ----- diff --git a/FormRenderer.php b/FormRenderer.php index b2394742f5..ee781ffd26 100644 --- a/FormRenderer.php +++ b/FormRenderer.php @@ -280,6 +280,6 @@ public function searchAndRenderBlock(FormView $view, $blockNameSuffix, array $va */ public function humanize($text) { - return ucfirst(trim(strtolower(preg_replace('/[_\s]+/', ' ', $text)))); + return ucfirst(trim(strtolower(preg_replace(array('/([A-Z])/', '/[_\s]+/'), array('_$1', ' '), $text)))); } } diff --git a/Tests/FormRendererTest.php b/Tests/FormRendererTest.php new file mode 100644 index 0000000000..dc64762527 --- /dev/null +++ b/Tests/FormRendererTest.php @@ -0,0 +1,18 @@ +getMockBuilder('Symfony\Component\Form\FormRenderer') + ->setMethods(null) + ->disableOriginalConstructor() + ->getMock() + ; + + $this->assertEquals('Is active', $renderer->humanize('is_active')); + $this->assertEquals('Is active', $renderer->humanize('isActive')); + } +} \ No newline at end of file From a786485c4e62e3fedb905c88abb11ef3e9bf850f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=81nis=20Lukss?= Date: Thu, 14 Feb 2013 09:35:03 -0800 Subject: [PATCH 071/447] Create validators.lv.xlf Latvian translation of validators --- Resources/translations/validators.lv.xlf | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 Resources/translations/validators.lv.xlf diff --git a/Resources/translations/validators.lv.xlf b/Resources/translations/validators.lv.xlf new file mode 100644 index 0000000000..9cdfb2cd48 --- /dev/null +++ b/Resources/translations/validators.lv.xlf @@ -0,0 +1,19 @@ + + + + + + This form should not contain extra fields. + Šajā veidlapā nevajadzētu būt papildus ievades laukiem. + + + The uploaded file was too large. Please try to upload a smaller file. + Augšupielādētā faila izmērs bija par lielu. Lūdzu mēģiniet augšupielādēt mazāka izmēra failu. + + + The CSRF token is invalid. Please try to resubmit the form. + Dotais CSRF talons nav derīgs. Lūdzu mēģiniet vēlreiz iesniegt veidlapu. + + + + From 687c2575d9b4f65fb5b437c93efba5936e42c337 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Grzegorz=20=C5=81ukaszewicz?= Date: Tue, 12 Feb 2013 18:53:25 +0100 Subject: [PATCH 072/447] Remove unnecessary comment and change test name --- Tests/Extension/Core/Type/ChoiceTypeTest.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Tests/Extension/Core/Type/ChoiceTypeTest.php b/Tests/Extension/Core/Type/ChoiceTypeTest.php index 3b32ab38e8..844715c650 100644 --- a/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -86,10 +86,7 @@ public function testChoiceListOptionExpectsChoiceListInterface() )); } - /** - * expectedException \Symfony\Component\Form\Exception\Exception - */ - public function testEitherChoiceListOrChoicesMustBeSet() + public function testChoiceListAndChoicesCanBeEmpty() { $this->factory->create('choice', null, array( )); From 3c033fb6c88adca74fce145392e84c5a16cf107d Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Mon, 18 Feb 2013 23:37:06 +0100 Subject: [PATCH 073/447] Removed some leaking deprecation warning in the Form component Fixes #7101 --- ResolvedFormType.php | 2 ++ Tests/Extension/Core/Type/FormTypeTest.php | 2 ++ Tests/Extension/Core/Type/MoneyTypeTest.php | 4 ++-- Tests/Extension/Core/Type/TimeTypeTest.php | 2 +- Tests/FormIntegrationTestCase.php | 7 ------- 5 files changed, 7 insertions(+), 10 deletions(-) diff --git a/ResolvedFormType.php b/ResolvedFormType.php index d889d0df5a..d20f3b390f 100644 --- a/ResolvedFormType.php +++ b/ResolvedFormType.php @@ -62,7 +62,9 @@ public function __construct(FormTypeInterface $innerType, array $typeExtensions // BC if ($innerType instanceof AbstractType) { /* @var AbstractType $innerType */ + set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC')); $innerType->setExtensions($typeExtensions); + restore_error_handler(); } $this->innerType = $innerType; diff --git a/Tests/Extension/Core/Type/FormTypeTest.php b/Tests/Extension/Core/Type/FormTypeTest.php index fae4ae3e5b..f77b8517d4 100644 --- a/Tests/Extension/Core/Type/FormTypeTest.php +++ b/Tests/Extension/Core/Type/FormTypeTest.php @@ -601,9 +601,11 @@ public function testPropertyPathNullImpliesDefault() // BC public function testPropertyPathFalseImpliesDefaultNotMapped() { + set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); $form = $this->factory->createNamed('name', 'form', null, array( 'property_path' => false, )); + restore_error_handler(); $this->assertEquals(new PropertyPath('name'), $form->getPropertyPath()); $this->assertFalse($form->getConfig()->getMapped()); diff --git a/Tests/Extension/Core/Type/MoneyTypeTest.php b/Tests/Extension/Core/Type/MoneyTypeTest.php index d3e2932c01..9eadaac2c4 100644 --- a/Tests/Extension/Core/Type/MoneyTypeTest.php +++ b/Tests/Extension/Core/Type/MoneyTypeTest.php @@ -42,7 +42,7 @@ public function testPassDifferentPatternsForDifferentCurrencies() $view1 = $form1->createView(); $view2 = $form2->createView(); - $this->assertSame('{{ widget }} £', $view1->get('money_pattern')); - $this->assertSame('{{ widget }} €', $view2->get('money_pattern')); + $this->assertSame('{{ widget }} £', $view1->vars['money_pattern']); + $this->assertSame('{{ widget }} €', $view2->vars['money_pattern']); } } diff --git a/Tests/Extension/Core/Type/TimeTypeTest.php b/Tests/Extension/Core/Type/TimeTypeTest.php index 72270c7f9a..1277097103 100644 --- a/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/Tests/Extension/Core/Type/TimeTypeTest.php @@ -231,7 +231,7 @@ public function testSetDataWithoutMinutes() $form->setData(new \DateTime('03:04:05 UTC')); - $this->assertEquals(array('hour' => 3), $form->getClientData()); + $this->assertEquals(array('hour' => 3), $form->getViewData()); } public function testSetDataWithSeconds() diff --git a/Tests/FormIntegrationTestCase.php b/Tests/FormIntegrationTestCase.php index fad0616280..536ff4c824 100644 --- a/Tests/FormIntegrationTestCase.php +++ b/Tests/FormIntegrationTestCase.php @@ -32,13 +32,6 @@ protected function setUp() $this->factory = Forms::createFormFactoryBuilder() ->addExtensions($this->getExtensions()) ->getFormFactory(); - - set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); - } - - protected function tearDown() - { - restore_error_handler(); } protected function getExtensions() From 2346c75436dc60815382354b919290096d00e94a Mon Sep 17 00:00:00 2001 From: Pantelis Sampaziotis Date: Tue, 19 Feb 2013 12:43:38 +0200 Subject: [PATCH 074/447] Added greek translation --- Resources/translations/validators.el.xlf | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 Resources/translations/validators.el.xlf diff --git a/Resources/translations/validators.el.xlf b/Resources/translations/validators.el.xlf new file mode 100644 index 0000000000..ba2ced74b0 --- /dev/null +++ b/Resources/translations/validators.el.xlf @@ -0,0 +1,19 @@ + + + + + + This form should not contain extra fields. + Αυτή η φόρμα δεν πρέπει να περιέχει επιπλέον πεδία. + + + The uploaded file was too large. Please try to upload a smaller file. + Το αρχείο είναι πολύ μεγάλο. Παρακαλούμε προσπαθήστε να ανεβάσετε ένα μικρότερο αρχείο. + + + The CSRF token is invalid. Please try to resubmit the form. + Το CSRF token δεν είναι έγκυρο. Παρακαλούμε δοκιμάστε να υποβάλετε τη φόρμα ξανά. + + + + From 31ed332763a7e23f706c942cc60f824e055997af Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 1 Mar 2013 11:42:10 +0100 Subject: [PATCH 075/447] fixed CS --- Extension/Validator/ValidatorTypeGuesser.php | 2 +- .../Validator/EventListener/ValidationListenerTest.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Extension/Validator/ValidatorTypeGuesser.php b/Extension/Validator/ValidatorTypeGuesser.php index a9f40808db..387a724de2 100644 --- a/Extension/Validator/ValidatorTypeGuesser.php +++ b/Extension/Validator/ValidatorTypeGuesser.php @@ -291,4 +291,4 @@ protected function guess($class, $property, \Closure $closure, $defaultValue = n return Guess::getBestGuess($guesses); } -} \ No newline at end of file +} diff --git a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php index 47a51c6cc8..528f94633b 100644 --- a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php +++ b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php @@ -13,7 +13,6 @@ use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormEvent; -use Symfony\Component\Form\FormError; use Symfony\Component\Form\Extension\Validator\Constraints\Form; use Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener; use Symfony\Component\PropertyAccess\PropertyPath; From 513e4b73b05b9ad36d1b013a0746de81e14853b1 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 1 Mar 2013 11:46:19 +0100 Subject: [PATCH 076/447] fixed CS --- Tests/FormRendererTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/FormRendererTest.php b/Tests/FormRendererTest.php index dc64762527..614f300ce3 100644 --- a/Tests/FormRendererTest.php +++ b/Tests/FormRendererTest.php @@ -15,4 +15,4 @@ public function testHumanize() $this->assertEquals('Is active', $renderer->humanize('is_active')); $this->assertEquals('Is active', $renderer->humanize('isActive')); } -} \ No newline at end of file +} From eb3e0303da9e9d0bac19508d1c89491b7425841a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Simon?= Date: Mon, 18 Mar 2013 17:08:21 +0100 Subject: [PATCH 077/447] changed bytes conversion method --- Extension/Validator/Util/ServerParams.php | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/Extension/Validator/Util/ServerParams.php b/Extension/Validator/Util/ServerParams.php index cac6047ce2..b2a4f4b955 100644 --- a/Extension/Validator/Util/ServerParams.php +++ b/Extension/Validator/Util/ServerParams.php @@ -29,18 +29,12 @@ public function getPostMaxSize() return null; } - $max = (int) $iniMax; - - switch (substr($iniMax, -1)) { - case 'G': - $max *= 1024; - case 'M': - $max *= 1024; - case 'K': - $max *= 1024; + if (preg_match('#^(\d+)([bkmgt])#i', $iniMax, $match)) { + $shift = array('b' => 0, 'k' => 10, 'm' => 20, 'g' => 30, 't' => 40); + $iniMax = ($match[1] * (1 << $shift[strtolower($match[2])])); } - return $max; + return (int) $iniMax; } /** From 7fdfb2d80f0e09d86e6df93a5a7eceac18e31b96 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 1 Mar 2013 10:41:59 +0100 Subject: [PATCH 078/447] [Form] removed deprecated methods and classes --- AbstractType.php | 82 ------ AbstractTypeExtension.php | 40 --- CallbackValidator.php | 44 ---- Event/DataEvent.php | 74 ------ Event/FilterDataEvent.php | 22 -- Extension/Core/CoreExtension.php | 1 - Extension/Core/Type/CheckboxType.php | 8 - Extension/Core/Type/ChoiceType.php | 8 - Extension/Core/Type/DateTimeType.php | 8 - Extension/Core/Type/DateType.php | 8 - Extension/Core/Type/FieldType.php | 32 --- Extension/Core/Type/FileType.php | 8 - Extension/Core/Type/FormType.php | 14 +- Extension/Core/Type/HiddenType.php | 8 - Extension/Core/Type/IntegerType.php | 8 - Extension/Core/Type/MoneyType.php | 8 - Extension/Core/Type/NumberType.php | 8 - Extension/Core/Type/PercentType.php | 8 - Extension/Core/Type/TextType.php | 8 - Extension/Core/Type/TimeType.php | 8 - .../Type/FormTypeValidatorExtension.php | 9 +- Extension/Validator/ValidatorTypeGuesser.php | 8 - Form.php | 229 +---------------- FormBuilder.php | 28 --- FormBuilderInterface.php | 38 --- FormConfigBuilder.php | 188 -------------- FormConfigBuilderInterface.php | 11 - FormConfigInterface.php | 9 - FormEvent.php | 48 +++- FormEvents.php | 18 -- FormFactory.php | 70 ------ FormRegistry.php | 16 +- FormRegistryInterface.php | 11 - FormTypeGuesserChain.php | 12 - FormTypeGuesserInterface.php | 12 - FormValidatorInterface.php | 28 --- FormView.php | 233 ------------------ ResolvedFormType.php | 8 - Tests/CompoundFormTest.php | 16 -- Tests/Extension/Core/Type/FormTypeTest.php | 13 - Tests/FormFactoryTest.php | 118 --------- Tests/FormRegistryTest.php | 32 --- Tests/SimpleFormTest.php | 21 -- Util/FormUtil.php | 15 -- Util/PropertyPath.php | 57 ----- Util/PropertyPathBuilder.php | 36 --- Util/PropertyPathInterface.php | 27 -- Util/PropertyPathIterator.php | 36 --- Util/PropertyPathIteratorInterface.php | 27 -- 49 files changed, 54 insertions(+), 1725 deletions(-) delete mode 100644 CallbackValidator.php delete mode 100644 Event/DataEvent.php delete mode 100644 Event/FilterDataEvent.php delete mode 100644 Extension/Core/Type/FieldType.php delete mode 100644 FormValidatorInterface.php delete mode 100644 Util/PropertyPath.php delete mode 100644 Util/PropertyPathBuilder.php delete mode 100644 Util/PropertyPathInterface.php delete mode 100644 Util/PropertyPathIterator.php delete mode 100644 Util/PropertyPathIteratorInterface.php diff --git a/AbstractType.php b/AbstractType.php index 8769415ea6..6f7f5da653 100644 --- a/AbstractType.php +++ b/AbstractType.php @@ -18,13 +18,6 @@ */ abstract class AbstractType implements FormTypeInterface { - /** - * @var array - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. - */ - private $extensions = array(); - /** * {@inheritdoc} */ @@ -51,50 +44,6 @@ public function finishView(FormView $view, FormInterface $form, array $options) */ public function setDefaultOptions(OptionsResolverInterface $resolver) { - $defaults = $this->getDefaultOptions(array()); - $allowedTypes = $this->getAllowedOptionValues(array()); - - if (!empty($defaults)) { - trigger_error('getDefaultOptions() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED); - - $resolver->setDefaults($defaults); - } - - if (!empty($allowedTypes)) { - trigger_error('getAllowedOptionValues() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED); - - $resolver->addAllowedValues($allowedTypes); - } - } - - /** - * Returns the default options for this type. - * - * @param array $options Unsupported as of Symfony 2.1. - * - * @return array The default options - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. - * Use {@link setDefaultOptions()} instead. - */ - public function getDefaultOptions(array $options) - { - return array(); - } - - /** - * Returns the allowed option values for each option (if any). - * - * @param array $options Unsupported as of Symfony 2.1. - * - * @return array The allowed option values - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. - * Use {@link setDefaultOptions()} instead. - */ - public function getAllowedOptionValues(array $options) - { - return array(); } /** @@ -104,35 +53,4 @@ public function getParent() { return 'form'; } - - /** - * Sets the extensions for this type. - * - * @param FormTypeExtensionInterface[] $extensions An array of FormTypeExtensionInterface - * - * @throws Exception\UnexpectedTypeException if any extension does not implement FormTypeExtensionInterface - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. - */ - public function setExtensions(array $extensions) - { - trigger_error('setExtensions() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); - - $this->extensions = $extensions; - } - - /** - * Returns the extensions associated with this type. - * - * @return FormTypeExtensionInterface[] An array of FormTypeExtensionInterface - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * {@link ResolvedFormTypeInterface::getTypeExtensions()} instead. - */ - public function getExtensions() - { - trigger_error('getExtensions() is deprecated since version 2.1 and will be removed in 2.3. Use ResolvedFormTypeInterface::getTypeExtensions instead.', E_USER_DEPRECATED); - - return $this->extensions; - } } diff --git a/AbstractTypeExtension.php b/AbstractTypeExtension.php index 3e51ed442b..351c80097f 100644 --- a/AbstractTypeExtension.php +++ b/AbstractTypeExtension.php @@ -44,45 +44,5 @@ public function finishView(FormView $view, FormInterface $form, array $options) */ public function setDefaultOptions(OptionsResolverInterface $resolver) { - $defaults = $this->getDefaultOptions(array()); - $allowedTypes = $this->getAllowedOptionValues(array()); - - if (!empty($defaults)) { - trigger_error('getDefaultOptions() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED); - - $resolver->setDefaults($defaults); - } - - if (!empty($allowedTypes)) { - trigger_error('getAllowedOptionValues() is deprecated since version 2.1 and will be removed in 2.3. Use setDefaultOptions() instead.', E_USER_DEPRECATED); - - $resolver->addAllowedValues($allowedTypes); - } - } - - /** - * Overrides the default options form the extended type. - * - * @return array - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. - * Use {@link setDefaultOptions()} instead. - */ - public function getDefaultOptions() - { - return array(); - } - - /** - * Returns the allowed option values for each option (if any). - * - * @return array The allowed option values - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. - * Use {@link setDefaultOptions()} instead. - */ - public function getAllowedOptionValues() - { - return array(); } } diff --git a/CallbackValidator.php b/CallbackValidator.php deleted file mode 100644 index f769cc7cbd..0000000000 --- a/CallbackValidator.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -/** - * Deprecated. You should use FormEvents::POST_BIND event listeners instead. - * - * @author Bernhard Schussek - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. - */ -class CallbackValidator implements FormValidatorInterface -{ - private $callback; - - /** - * @deprecated Deprecated since version 2.1, to be removed in 2.3. - */ - public function __construct($callback) - { - trigger_error('CallbackValidator is deprecated since version 2.1 and will be removed in 2.3. Use the FormEvents::POST_BIND event instead.', E_USER_DEPRECATED); - - $this->callback = $callback; - } - - /** - * @deprecated Deprecated since version 2.1, to be removed in 2.3. - */ - public function validate(FormInterface $form) - { - trigger_error('validate() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); - - return call_user_func($this->callback, $form); - } -} diff --git a/Event/DataEvent.php b/Event/DataEvent.php deleted file mode 100644 index 7739688823..0000000000 --- a/Event/DataEvent.php +++ /dev/null @@ -1,74 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Event; - -use Symfony\Component\EventDispatcher\Event; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormEvent; - -/** - * @author Bernhard Schussek - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Code against - * {@link \Symfony\Component\Form\FormEvent} instead. - */ -class DataEvent extends Event -{ - private $form; - protected $data; - - /** - * Constructs an event. - * - * @param FormInterface $form The associated form - * @param mixed $data The data - */ - public function __construct(FormInterface $form, $data) - { - if (!$this instanceof FormEvent) { - trigger_error(sprintf('%s is deprecated since version 2.1 and will be removed in 2.3. Code against \Symfony\Component\Form\FormEvent instead.', get_class($this)), E_USER_DEPRECATED); - } - - $this->form = $form; - $this->data = $data; - } - - /** - * Returns the form at the source of the event. - * - * @return FormInterface - */ - public function getForm() - { - return $this->form; - } - - /** - * Returns the data associated with this event. - * - * @return mixed - */ - public function getData() - { - return $this->data; - } - - /** - * Allows updating with some filtered data. - * - * @param mixed $data - */ - public function setData($data) - { - $this->data = $data; - } -} diff --git a/Event/FilterDataEvent.php b/Event/FilterDataEvent.php deleted file mode 100644 index d20f483c69..0000000000 --- a/Event/FilterDataEvent.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Event; - -/** - * @author Bernhard Schussek - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Code against - * {@link \Symfony\Component\Form\FormEvent} instead. - */ -class FilterDataEvent extends DataEvent -{ -} diff --git a/Extension/Core/CoreExtension.php b/Extension/Core/CoreExtension.php index ab6529d6dc..ff7a1a3e0e 100644 --- a/Extension/Core/CoreExtension.php +++ b/Extension/Core/CoreExtension.php @@ -24,7 +24,6 @@ class CoreExtension extends AbstractExtension protected function loadTypes() { return array( - new Type\FieldType(), new Type\FormType(PropertyAccess::getPropertyAccessor()), new Type\BirthdayType(), new Type\CheckboxType(), diff --git a/Extension/Core/Type/CheckboxType.php b/Extension/Core/Type/CheckboxType.php index 8d489d6db0..214e581aff 100644 --- a/Extension/Core/Type/CheckboxType.php +++ b/Extension/Core/Type/CheckboxType.php @@ -57,14 +57,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) )); } - /** - * {@inheritdoc} - */ - public function getParent() - { - return 'field'; - } - /** * {@inheritdoc} */ diff --git a/Extension/Core/Type/ChoiceType.php b/Extension/Core/Type/ChoiceType.php index 28327b6291..20d72d7854 100644 --- a/Extension/Core/Type/ChoiceType.php +++ b/Extension/Core/Type/ChoiceType.php @@ -211,14 +211,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) )); } - /** - * {@inheritdoc} - */ - public function getParent() - { - return 'field'; - } - /** * {@inheritdoc} */ diff --git a/Extension/Core/Type/DateTimeType.php b/Extension/Core/Type/DateTimeType.php index 1ffc0a155f..383ab90b15 100644 --- a/Extension/Core/Type/DateTimeType.php +++ b/Extension/Core/Type/DateTimeType.php @@ -284,14 +284,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) )); } - /** - * {@inheritdoc} - */ - public function getParent() - { - return 'field'; - } - /** * {@inheritdoc} */ diff --git a/Extension/Core/Type/DateType.php b/Extension/Core/Type/DateType.php index 71ae631c67..ad5914aae8 100644 --- a/Extension/Core/Type/DateType.php +++ b/Extension/Core/Type/DateType.php @@ -247,14 +247,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) )); } - /** - * {@inheritdoc} - */ - public function getParent() - { - return 'field'; - } - /** * {@inheritdoc} */ diff --git a/Extension/Core/Type/FieldType.php b/Extension/Core/Type/FieldType.php deleted file mode 100644 index dbafde1f65..0000000000 --- a/Extension/Core/Type/FieldType.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Core\Type; - -use Symfony\Component\Form\AbstractType; - -/** - * Deprecated. You should extend FormType instead. - * - * @author Bernhard Schussek - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. - */ -class FieldType extends AbstractType -{ - /** - * {@inheritdoc} - */ - public function getName() - { - return 'field'; - } -} diff --git a/Extension/Core/Type/FileType.php b/Extension/Core/Type/FileType.php index d6c9932cc4..2c09da6f6b 100644 --- a/Extension/Core/Type/FileType.php +++ b/Extension/Core/Type/FileType.php @@ -51,14 +51,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) )); } - /** - * {@inheritdoc} - */ - public function getParent() - { - return 'field'; - } - /** * {@inheritdoc} */ diff --git a/Extension/Core/Type/FormType.php b/Extension/Core/Type/FormType.php index 8e089bd4d6..26c1f08934 100644 --- a/Extension/Core/Type/FormType.php +++ b/Extension/Core/Type/FormType.php @@ -45,8 +45,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) ->setDisabled($options['disabled']) ->setErrorBubbling($options['error_bubbling']) ->setEmptyData($options['empty_data']) - // BC compatibility, when "property_path" could be false - ->setPropertyPath(is_string($options['property_path']) ? $options['property_path'] : null) + ->setPropertyPath($options['property_path']) ->setMapped($options['mapped']) ->setByReference($options['by_reference']) ->setVirtual($options['virtual']) @@ -56,10 +55,6 @@ public function buildForm(FormBuilderInterface $builder, array $options) ->setDataMapper($options['compound'] ? new PropertyPathMapper($this->propertyAccessor) : null) ; - if (false === $options['property_path']) { - trigger_error('Setting "property_path" to "false" is deprecated since version 2.1 and will be removed in 2.3. Set "mapped" to "false" instead.', E_USER_DEPRECATED); - } - if ($options['trim']) { $builder->addEventSubscriber(new TrimListener()); } @@ -200,11 +195,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) return $options['compound']; }; - // BC clause: former property_path=false now equals mapped=false - $mapped = function (Options $options) { - return false !== $options['property_path']; - }; - // If data is given, the form is locked to that data // (independent of its value) $resolver->setOptional(array( @@ -222,7 +212,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'max_length' => null, 'pattern' => null, 'property_path' => null, - 'mapped' => $mapped, + 'mapped' => true, 'by_reference' => true, 'error_bubbling' => $errorBubbling, 'label' => null, diff --git a/Extension/Core/Type/HiddenType.php b/Extension/Core/Type/HiddenType.php index fc1533648b..bd4fa898e6 100644 --- a/Extension/Core/Type/HiddenType.php +++ b/Extension/Core/Type/HiddenType.php @@ -30,14 +30,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) )); } - /** - * {@inheritdoc} - */ - public function getParent() - { - return 'field'; - } - /** * {@inheritdoc} */ diff --git a/Extension/Core/Type/IntegerType.php b/Extension/Core/Type/IntegerType.php index c3ab0546da..b224cac5fd 100644 --- a/Extension/Core/Type/IntegerType.php +++ b/Extension/Core/Type/IntegerType.php @@ -58,14 +58,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) )); } - /** - * {@inheritdoc} - */ - public function getParent() - { - return 'field'; - } - /** * {@inheritdoc} */ diff --git a/Extension/Core/Type/MoneyType.php b/Extension/Core/Type/MoneyType.php index 433e8dddfe..9e36f9ce16 100644 --- a/Extension/Core/Type/MoneyType.php +++ b/Extension/Core/Type/MoneyType.php @@ -59,14 +59,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) )); } - /** - * {@inheritdoc} - */ - public function getParent() - { - return 'field'; - } - /** * {@inheritdoc} */ diff --git a/Extension/Core/Type/NumberType.php b/Extension/Core/Type/NumberType.php index 93a3d9824e..beb3c89a41 100644 --- a/Extension/Core/Type/NumberType.php +++ b/Extension/Core/Type/NumberType.php @@ -56,14 +56,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) )); } - /** - * {@inheritdoc} - */ - public function getParent() - { - return 'field'; - } - /** * {@inheritdoc} */ diff --git a/Extension/Core/Type/PercentType.php b/Extension/Core/Type/PercentType.php index 52ca820e93..b1df94364d 100644 --- a/Extension/Core/Type/PercentType.php +++ b/Extension/Core/Type/PercentType.php @@ -45,14 +45,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) )); } - /** - * {@inheritdoc} - */ - public function getParent() - { - return 'field'; - } - /** * {@inheritdoc} */ diff --git a/Extension/Core/Type/TextType.php b/Extension/Core/Type/TextType.php index ebfeaf6ac2..11503261c5 100644 --- a/Extension/Core/Type/TextType.php +++ b/Extension/Core/Type/TextType.php @@ -26,14 +26,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) )); } - /** - * {@inheritdoc} - */ - public function getParent() - { - return 'field'; - } - /** * {@inheritdoc} */ diff --git a/Extension/Core/Type/TimeType.php b/Extension/Core/Type/TimeType.php index bc661f66b9..22df9547f8 100644 --- a/Extension/Core/Type/TimeType.php +++ b/Extension/Core/Type/TimeType.php @@ -228,14 +228,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) )); } - /** - * {@inheritdoc} - */ - public function getParent() - { - return 'field'; - } - /** * {@inheritdoc} */ diff --git a/Extension/Validator/Type/FormTypeValidatorExtension.php b/Extension/Validator/Type/FormTypeValidatorExtension.php index fe55ed7971..6b9ac4e4f0 100644 --- a/Extension/Validator/Type/FormTypeValidatorExtension.php +++ b/Extension/Validator/Type/FormTypeValidatorExtension.php @@ -53,11 +53,6 @@ public function buildForm(FormBuilderInterface $builder, array $options) */ public function setDefaultOptions(OptionsResolverInterface $resolver) { - // BC clause - $constraints = function (Options $options) { - return $options['validation_constraint']; - }; - // Make sure that validation groups end up as null, closure or array $validationGroupsNormalizer = function (Options $options, $groups) { if (empty($groups)) { @@ -79,9 +74,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) $resolver->setDefaults(array( 'error_mapping' => array(), 'validation_groups' => null, - // "validation_constraint" is deprecated. Use "constraints". - 'validation_constraint' => null, - 'constraints' => $constraints, + 'constraints' => null, 'cascade_validation' => false, 'invalid_message' => 'This value is not valid.', 'invalid_message_parameters' => array(), diff --git a/Extension/Validator/ValidatorTypeGuesser.php b/Extension/Validator/ValidatorTypeGuesser.php index 387a724de2..dcd9cc552f 100644 --- a/Extension/Validator/ValidatorTypeGuesser.php +++ b/Extension/Validator/ValidatorTypeGuesser.php @@ -65,14 +65,6 @@ public function guessMaxLength($class, $property) }); } - /** - * {@inheritDoc} - */ - public function guessMinLength($class, $property) - { - trigger_error('guessMinLength() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); - } - /** * {@inheritDoc} */ diff --git a/Form.php b/Form.php index f1c8e5cc60..401d7a2872 100644 --- a/Form.php +++ b/Form.php @@ -16,7 +16,6 @@ use Symfony\Component\Form\Exception\AlreadyBoundException; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Util\FormUtil; -use Symfony\Component\HttpFoundation\Request; use Symfony\Component\PropertyAccess\PropertyPath; /** @@ -201,27 +200,6 @@ public function getPropertyPath() return new PropertyPath($this->getName()); } - /** - * Returns the types used by this form. - * - * @return FormTypeInterface[] An array of FormTypeInterface - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * {@link getConfig()} and {@link FormConfigInterface::getType()} instead. - */ - public function getTypes() - { - trigger_error('getTypes() is deprecated since version 2.1 and will be removed in 2.3. Use getConfig() and FormConfigInterface::getType() instead.', E_USER_DEPRECATED); - - $types = array(); - - for ($type = $this->config->getType(); null !== $type; $type = $type->getParent()) { - array_unshift($types, $type->getInnerType()); - } - - return $types; - } - /** * {@inheritdoc} */ @@ -272,21 +250,6 @@ public function getParent() return $this->parent; } - /** - * Returns whether the form has a parent. - * - * @return Boolean - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * {@link getParent()} or inverse {@link isRoot()} instead. - */ - public function hasParent() - { - trigger_error('hasParent() is deprecated since version 2.1 and will be removed in 2.3. Use getParent() or inverse isRoot() instead.', E_USER_DEPRECATED); - - return null !== $this->parent; - } - /** * {@inheritdoc} */ @@ -303,40 +266,6 @@ public function isRoot() return null === $this->parent; } - /** - * Returns whether the form has an attribute with the given name. - * - * @param string $name The name of the attribute. - * - * @return Boolean Whether the attribute exists. - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * {@link getConfig()} and {@link FormConfigInterface::hasAttribute()} instead. - */ - public function hasAttribute($name) - { - trigger_error('hasAttribute() is deprecated since version 2.1 and will be removed in 2.3. Use getConfig() and FormConfigInterface::hasAttribute() instead.', E_USER_DEPRECATED); - - return $this->config->hasAttribute($name); - } - - /** - * Returns the value of the attributes with the given name. - * - * @param string $name The name of the attribute - * - * @return mixed The attribute value. - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * {@link getConfig()} and {@link FormConfigInterface::getAttribute()} instead. - */ - public function getAttribute($name) - { - trigger_error('getAttribute() is deprecated since version 2.1 and will be removed in 2.3. Use getConfig() and FormConfigInterface::getAttribute() instead.', E_USER_DEPRECATED); - - return $this->config->getAttribute($name); - } - /** * {@inheritdoc} */ @@ -366,14 +295,9 @@ public function setData($modelData) $dispatcher = $this->config->getEventDispatcher(); // Hook to change content of the data - if ($dispatcher->hasListeners(FormEvents::PRE_SET_DATA) || $dispatcher->hasListeners(FormEvents::SET_DATA)) { + if ($dispatcher->hasListeners(FormEvents::PRE_SET_DATA)) { $event = new FormEvent($this, $modelData); $dispatcher->dispatch(FormEvents::PRE_SET_DATA, $event); - // BC until 2.3 - if ($dispatcher->hasListeners(FormEvents::SET_DATA)) { - trigger_error('The FormEvents::SET_DATA event is deprecated since 2.1 and will be removed in 2.3. Use the FormEvents::PRE_SET_DATA event instead.', E_USER_DEPRECATED); - } - $dispatcher->dispatch(FormEvents::SET_DATA, $event); $modelData = $event->getData(); } @@ -472,21 +396,6 @@ public function getViewData() return $this->viewData; } - /** - * Alias of {@link getViewData()}. - * - * @return string - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * {@link getViewData()} instead. - */ - public function getClientData() - { - trigger_error('getClientData() is deprecated since version 2.1 and will be removed in 2.3. Use getViewData() instead.', E_USER_DEPRECATED); - - return $this->getViewData(); - } - /** * {@inheritdoc} */ @@ -532,14 +441,9 @@ public function bind($submittedData) $dispatcher = $this->config->getEventDispatcher(); // Hook to change content of the data bound by the browser - if ($dispatcher->hasListeners(FormEvents::PRE_BIND) || $dispatcher->hasListeners(FormEvents::BIND_CLIENT_DATA)) { + if ($dispatcher->hasListeners(FormEvents::PRE_BIND)) { $event = new FormEvent($this, $submittedData); $dispatcher->dispatch(FormEvents::PRE_BIND, $event); - // BC until 2.3 - if ($dispatcher->hasListeners(FormEvents::BIND_CLIENT_DATA)) { - trigger_error('The FormEvents::BIND_CLIENT_DATA event is deprecated since 2.1 and will be removed in 2.3. Use the FormEvents::PRE_BIND event instead.', E_USER_DEPRECATED); - } - $dispatcher->dispatch(FormEvents::BIND_CLIENT_DATA, $event); $submittedData = $event->getData(); } @@ -595,14 +499,9 @@ public function bind($submittedData) // Hook to change content of the data into the normalized // representation - if ($dispatcher->hasListeners(FormEvents::BIND) || $dispatcher->hasListeners(FormEvents::BIND_NORM_DATA)) { + if ($dispatcher->hasListeners(FormEvents::BIND)) { $event = new FormEvent($this, $normData); $dispatcher->dispatch(FormEvents::BIND, $event); - // BC until 2.3 - if ($dispatcher->hasListeners(FormEvents::BIND_NORM_DATA)) { - trigger_error('The FormEvents::BIND_NORM_DATA event is deprecated since 2.1 and will be removed in 2.3. Use the FormEvents::BIND event instead.', E_USER_DEPRECATED); - } - $dispatcher->dispatch(FormEvents::BIND_NORM_DATA, $event); $normData = $event->getData(); } @@ -623,41 +522,9 @@ public function bind($submittedData) $dispatcher->dispatch(FormEvents::POST_BIND, $event); } - set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC')); - $validators = $this->config->getValidators(); - restore_error_handler(); - - foreach ($validators as $validator) { - trigger_error(sprintf('FormConfigInterface::getValidators() is deprecated since 2.1 and will be removed in 2.3. Convert your %s class to a listener on the FormEvents::POST_BIND event.', get_class($validator)), E_USER_DEPRECATED); - - $validator->validate($this); - } - return $this; } - /** - * Binds a request to the form. - * - * If the request method is POST, PUT or GET, the data is bound to the form, - * transformed and written into the form data (an object or an array). - * - * @param Request $request The request to bind to the form - * - * @return Form This form - * - * @throws FormException if the method of the request is not one of GET, POST or PUT - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * {@link FormConfigInterface::bind()} instead. - */ - public function bindRequest(Request $request) - { - trigger_error('bindRequest() is deprecated since version 2.1 and will be removed in 2.3. Use FormConfigInterface::bind() instead.', E_USER_DEPRECATED); - - return $this->bind($request); - } - /** * {@inheritdoc} */ @@ -672,21 +539,6 @@ public function addError(FormError $error) return $this; } - /** - * Returns whether errors bubble up to the parent. - * - * @return Boolean - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * {@link getConfig()} and {@link FormConfigInterface::getErrorBubbling()} instead. - */ - public function getErrorBubbling() - { - trigger_error('getErrorBubbling() is deprecated since version 2.1 and will be removed in 2.3. Use getConfig() and FormConfigInterface::getErrorBubbling() instead.', E_USER_DEPRECATED); - - return $this->config->getErrorBubbling(); - } - /** * {@inheritdoc} */ @@ -745,21 +597,6 @@ public function isValid() return true; } - /** - * Returns whether there are errors associated with this form. - * - * @return Boolean - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Count - * {@link getErrors()} instead. - */ - public function hasErrors() - { - trigger_error('hasErrors() is deprecated since version 2.1 and will be removed in 2.3. Count getErrors() instead.', E_USER_DEPRECATED); - - return count($this->errors) > 0; - } - /** * {@inheritdoc} */ @@ -796,36 +633,6 @@ public function getErrorsAsString($level = 0) return $errors; } - /** - * Returns the model transformers of the form. - * - * @return DataTransformerInterface[] An array of DataTransformerInterface - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * {@link getConfig()} and {@link FormConfigInterface::getModelTransformers()} instead. - */ - public function getNormTransformers() - { - trigger_error('getNormTransformers() is deprecated since version 2.1 and will be removed in 2.3. Use getConfig() and FormConfigInterface::getModelTransformers() instead.', E_USER_DEPRECATED); - - return $this->config->getModelTransformers(); - } - - /** - * Returns the view transformers of the form. - * - * @return DataTransformerInterface[] An array of DataTransformerInterface - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * {@link getConfig()} and {@link FormConfigInterface::getViewTransformers()} instead. - */ - public function getClientTransformers() - { - trigger_error('getClientTransformers() is deprecated since version 2.1 and will be removed in 2.3. Use getConfig() and FormConfigInterface::getViewTransformers() instead.', E_USER_DEPRECATED); - - return $this->config->getViewTransformers(); - } - /** * {@inheritdoc} */ @@ -834,36 +641,6 @@ public function all() return $this->children; } - /** - * Returns all children in this group. - * - * @return array - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * {@link all()} instead. - */ - public function getChildren() - { - trigger_error('getChildren() is deprecated since version 2.1 and will be removed in 2.3. Use all() instead.', E_USER_DEPRECATED); - - return $this->all(); - } - - /** - * Returns whether the form has children. - * - * @return Boolean - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * {@link count()} instead. - */ - public function hasChildren() - { - trigger_error('hasChildren() is deprecated since version 2.1 and will be removed in 2.3. Use count() instead.', E_USER_DEPRECATED); - - return count($this->children) > 0; - } - /** * {@inheritdoc} */ diff --git a/FormBuilder.php b/FormBuilder.php index a47d969e05..a626980c59 100644 --- a/FormBuilder.php +++ b/FormBuilder.php @@ -288,34 +288,6 @@ public function getIterator() return new \ArrayIterator($this->children); } - /** - * Returns the types used by this builder. - * - * @return FormTypeInterface[] An array of FormTypeInterface - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * {@link FormConfigInterface::getType()} instead. - * - * @throws BadMethodCallException If the builder was turned into a {@link FormConfigInterface} - * via {@link getFormConfig()}. - */ - public function getTypes() - { - trigger_error('getTypes() is deprecated since version 2.1 and will be removed in 2.3. Use getConfig() and FormConfigInterface::getType() instead.', E_USER_DEPRECATED); - - if ($this->locked) { - throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $types = array(); - - for ($type = $this->getType(); null !== $type; $type = $type->getParent()) { - array_unshift($types, $type->getInnerType()); - } - - return $types; - } - /** * Converts an unresolved child into a {@link FormBuilder} instance. * diff --git a/FormBuilderInterface.php b/FormBuilderInterface.php index 002bd43fc3..d862c49bf5 100644 --- a/FormBuilderInterface.php +++ b/FormBuilderInterface.php @@ -84,42 +84,4 @@ public function all(); * @return Form The form */ public function getForm(); - - /** - * Sets the parent builder. - * - * @param FormBuilderInterface $parent The parent builder - * - * @return FormBuilderInterface The builder object. - * - * @deprecated Deprecated since version 2.2, to be removed in 2.3. You - * should not rely on the parent of a builder, because it is - * likely that the parent is only set after turning the builder - * into a form. - */ - public function setParent(FormBuilderInterface $parent = null); - - /** - * Returns the parent builder. - * - * @return FormBuilderInterface The parent builder - * - * @deprecated Deprecated since version 2.2, to be removed in 2.3. You - * should not rely on the parent of a builder, because it is - * likely that the parent is only set after turning the builder - * into a form. - */ - public function getParent(); - - /** - * Returns whether the builder has a parent. - * - * @return Boolean - * - * @deprecated Deprecated since version 2.2, to be removed in 2.3. You - * should not rely on the parent of a builder, because it is - * likely that the parent is only set after turning the builder - * into a form. - */ - public function hasParent(); } diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index 5d1f3a2331..7d297ed33d 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -195,22 +195,6 @@ public function addEventSubscriber(EventSubscriberInterface $subscriber) return $this; } - /** - * {@inheritdoc} - */ - public function addValidator(FormValidatorInterface $validator) - { - trigger_error('addValidator() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); - - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->validators[] = $validator; - - return $this; - } - /** * {@inheritdoc} */ @@ -243,72 +227,6 @@ public function resetViewTransformers() return $this; } - /** - * Alias of {@link addViewTransformer()}. - * - * @param DataTransformerInterface $viewTransformer - * - * @return FormConfigBuilder The configuration object. - * - * @throws BadMethodCallException if the form configuration is locked - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * {@link addViewTransformer()} instead. - */ - public function appendClientTransformer(DataTransformerInterface $viewTransformer) - { - trigger_error('appendClientTransformer() is deprecated since version 2.1 and will be removed in 2.3. Use addViewTransformer() instead.', E_USER_DEPRECATED); - - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - return $this->addViewTransformer($viewTransformer); - } - - /** - * Prepends a transformer to the client transformer chain. - * - * @param DataTransformerInterface $viewTransformer - * - * @return FormConfigBuilder The configuration object. - * - * @throws BadMethodCallException if the form configuration is locked - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. - */ - public function prependClientTransformer(DataTransformerInterface $viewTransformer) - { - trigger_error('prependClientTransformer() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); - - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - return $this->addViewTransformer($viewTransformer, true); - } - - /** - * Alias of {@link resetViewTransformers()}. - * - * @return FormConfigBuilder The configuration object. - * - * @throws BadMethodCallException if the form configuration is locked - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * {@link resetViewTransformers()} instead. - */ - public function resetClientTransformers() - { - trigger_error('resetClientTransformers() is deprecated since version 2.1 and will be removed in 2.3. Use resetViewTransformers() instead.', E_USER_DEPRECATED); - - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - return $this->resetViewTransformers(); - } - /** * {@inheritdoc} */ @@ -341,72 +259,6 @@ public function resetModelTransformers() return $this; } - /** - * Appends a transformer to the normalization transformer chain - * - * @param DataTransformerInterface $modelTransformer - * - * @return FormConfigBuilder The configuration object. - * - * @throws BadMethodCallException if the form configuration is locked - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. - */ - public function appendNormTransformer(DataTransformerInterface $modelTransformer) - { - trigger_error('appendNormTransformer() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); - - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - return $this->addModelTransformer($modelTransformer, true); - } - - /** - * Alias of {@link addModelTransformer()}. - * - * @param DataTransformerInterface $modelTransformer - * - * @return FormConfigBuilder The configuration object. - * - * @throws BadMethodCallException if the form configuration is locked - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * {@link addModelTransformer()} instead. - */ - public function prependNormTransformer(DataTransformerInterface $modelTransformer) - { - trigger_error('prependNormTransformer() is deprecated since version 2.1 and will be removed in 2.3. Use addModelTransformer() instead.', E_USER_DEPRECATED); - - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - return $this->addModelTransformer($modelTransformer); - } - - /** - * Alias of {@link resetModelTransformers()}. - * - * @return FormConfigBuilder The configuration object. - * - * @throws BadMethodCallException if the form configuration is locked - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * {@link resetModelTransformers()} instead. - */ - public function resetNormTransformers() - { - trigger_error('resetNormTransformers() is deprecated since version 2.1 and will be removed in 2.3. Use resetModelTransformers() instead.', E_USER_DEPRECATED); - - if ($this->locked) { - throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - return $this->resetModelTransformers(); - } - /** * {@inheritdoc} */ @@ -479,21 +331,6 @@ public function getViewTransformers() return $this->viewTransformers; } - /** - * Alias of {@link getViewTransformers()}. - * - * @return array The view transformers. - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * {@link getViewTransformers()} instead. - */ - public function getClientTransformers() - { - trigger_error('getClientTransformers() is deprecated since version 2.1 and will be removed in 2.3. Use getViewTransformers() instead.', E_USER_DEPRECATED); - - return $this->getViewTransformers(); - } - /** * {@inheritdoc} */ @@ -502,21 +339,6 @@ public function getModelTransformers() return $this->modelTransformers; } - /** - * Alias of {@link getModelTransformers()}. - * - * @return array The model transformers. - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * {@link getModelTransformers()} instead. - */ - public function getNormTransformers() - { - trigger_error('getNormTransformers() is deprecated since version 2.1 and will be removed in 2.3. Use getModelTransformers() instead.', E_USER_DEPRECATED); - - return $this->getModelTransformers(); - } - /** * {@inheritdoc} */ @@ -525,16 +347,6 @@ public function getDataMapper() return $this->dataMapper; } - /** - * {@inheritdoc} - */ - public function getValidators() - { - trigger_error('getValidators() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); - - return $this->validators; - } - /** * {@inheritdoc} */ diff --git a/FormConfigBuilderInterface.php b/FormConfigBuilderInterface.php index c63f0e8aaa..c0d8c2b1f9 100644 --- a/FormConfigBuilderInterface.php +++ b/FormConfigBuilderInterface.php @@ -40,17 +40,6 @@ public function addEventListener($eventName, $listener, $priority = 0); */ public function addEventSubscriber(EventSubscriberInterface $subscriber); - /** - * Adds a validator to the form. - * - * @param FormValidatorInterface $validator The validator. - * - * @return self The configuration object. - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. - */ - public function addValidator(FormValidatorInterface $validator); - /** * Appends / prepends a transformer to the view transformer chain. * diff --git a/FormConfigInterface.php b/FormConfigInterface.php index 0a27c2a7fb..002b54cfac 100644 --- a/FormConfigInterface.php +++ b/FormConfigInterface.php @@ -104,15 +104,6 @@ public function getModelTransformers(); */ public function getDataMapper(); - /** - * Returns the validators of the form. - * - * @return FormValidatorInterface The form validator. - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. - */ - public function getValidators(); - /** * Returns whether the form is required. * diff --git a/FormEvent.php b/FormEvent.php index ed3fc77006..57cebade65 100644 --- a/FormEvent.php +++ b/FormEvent.php @@ -11,11 +11,55 @@ namespace Symfony\Component\Form; -use Symfony\Component\Form\Event\FilterDataEvent; +use Symfony\Component\EventDispatcher\Event; /** * @author Bernhard Schussek */ -class FormEvent extends FilterDataEvent +class FormEvent extends Event { + private $form; + protected $data; + + /** + * Constructs an event. + * + * @param FormInterface $form The associated form + * @param mixed $data The data + */ + public function __construct(FormInterface $form, $data) + { + $this->form = $form; + $this->data = $data; + } + + /** + * Returns the form at the source of the event. + * + * @return FormInterface + */ + public function getForm() + { + return $this->form; + } + + /** + * Returns the data associated with this event. + * + * @return mixed + */ + public function getData() + { + return $this->data; + } + + /** + * Allows updating with some filtered data. + * + * @param mixed $data + */ + public function setData($data) + { + $this->data = $data; + } } diff --git a/FormEvents.php b/FormEvents.php index 6ddfe3e8e4..114bfcd226 100644 --- a/FormEvents.php +++ b/FormEvents.php @@ -26,24 +26,6 @@ final class FormEvents const POST_SET_DATA = 'form.post_set_data'; - /** - * @deprecated Deprecated since version 2.1, to be removed in 2.3. - * Use {@link PRE_BIND} instead. - */ - const BIND_CLIENT_DATA = 'form.bind_client_data'; - - /** - * @deprecated Deprecated since version 2.1, to be removed in 2.3. - * Use {@link BIND} instead. - */ - const BIND_NORM_DATA = 'form.bind_norm_data'; - - /** - * @deprecated Deprecated since version 2.1, to be removed in 2.3. - * Use {@link PRE_SET_DATA} instead. - */ - const SET_DATA = 'form.set_data'; - private function __construct() { } diff --git a/FormFactory.php b/FormFactory.php index cf6c6c748f..36efc903d5 100644 --- a/FormFactory.php +++ b/FormFactory.php @@ -98,20 +98,14 @@ public function createBuilderForProperty($class, $property, $data = null, array $typeGuess = $guesser->guessType($class, $property); $maxLengthGuess = $guesser->guessMaxLength($class, $property); - // Keep $minLengthGuess for BC until Symfony 2.3 - set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC')); - $minLengthGuess = $guesser->guessMinLength($class, $property); - restore_error_handler(); $requiredGuess = $guesser->guessRequired($class, $property); $patternGuess = $guesser->guessPattern($class, $property); $type = $typeGuess ? $typeGuess->getType() : 'text'; $maxLength = $maxLengthGuess ? $maxLengthGuess->getValue() : null; - $minLength = $minLengthGuess ? $minLengthGuess->getValue() : null; $pattern = $patternGuess ? $patternGuess->getValue() : null; - // overrides $minLength, if set if (null !== $pattern) { $options = array_merge(array('pattern' => $pattern), $options); } @@ -120,10 +114,6 @@ public function createBuilderForProperty($class, $property, $data = null, array $options = array_merge(array('max_length' => $maxLength), $options); } - if (null !== $minLength && $minLength > 0) { - $options = array_merge(array('pattern' => '.{'.$minLength.','.$maxLength.'}'), $options); - } - if ($requiredGuess) { $options = array_merge(array('required' => $requiredGuess->getValue()), $options); } @@ -136,66 +126,6 @@ public function createBuilderForProperty($class, $property, $data = null, array return $this->createNamedBuilder($property, $type, $data, $options, $parent); } - /** - * Returns whether the given type is supported. - * - * @param string $name The name of the type - * - * @return Boolean Whether the type is supported - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * {@link FormRegistryInterface::hasType()} instead. - */ - public function hasType($name) - { - trigger_error('hasType() is deprecated since version 2.1 and will be removed in 2.3. Use FormRegistryInterface::hasType() instead.', E_USER_DEPRECATED); - - return $this->registry->hasType($name); - } - - /** - * Adds a type. - * - * @param FormTypeInterface $type The type - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * form extensions or type registration in the Dependency - * Injection Container instead. - */ - public function addType(FormTypeInterface $type) - { - trigger_error('addType() is deprecated since version 2.1 and will be removed in 2.3. Use form extensions or type registration in the Dependency Injection Container instead.', E_USER_DEPRECATED); - - $parentType = $type->getParent(); - - $this->registry->addType($this->resolvedTypeFactory->createResolvedType( - $type, - array(), - $parentType ? $this->registry->getType($parentType) : null - )); - } - - /** - * Returns a type by name. - * - * This methods registers the type extensions from the form extensions. - * - * @param string $name The name of the type - * - * @return FormTypeInterface The type - * - * @throws Exception\FormException if the type can not be retrieved from any extension - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * {@link FormRegistryInterface::getType()} instead. - */ - public function getType($name) - { - trigger_error('getType() is deprecated since version 2.1 and will be removed in 2.3. Use FormRegistryInterface::getType() instead.', E_USER_DEPRECATED); - - return $this->registry->getType($name)->getInnerType(); - } - /** * Wraps a type into a ResolvedFormTypeInterface implementation and connects * it with its parent type. diff --git a/FormRegistry.php b/FormRegistry.php index 53f6d906de..cb2599c932 100644 --- a/FormRegistry.php +++ b/FormRegistry.php @@ -64,16 +64,6 @@ public function __construct(array $extensions, ResolvedFormTypeFactoryInterface $this->resolvedTypeFactory = $resolvedTypeFactory; } - /** - * {@inheritdoc} - */ - public function addType(ResolvedFormTypeInterface $type) - { - trigger_error('addType() is deprecated since version 2.1 and will be removed in 2.3. Use form extensions or type registration in the Dependency Injection Container instead.', E_USER_DEPRECATED); - - $this->types[$type->getName()] = $type; - } - /** * {@inheritdoc} */ @@ -132,13 +122,11 @@ private function resolveAndAddType(FormTypeInterface $type) ); } - set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC')); - $this->addType($this->resolvedTypeFactory->createResolvedType( + $this->types[$type->getName()] = $this->resolvedTypeFactory->createResolvedType( $type, $typeExtensions, $parentType ? $this->getType($parentType) : null - )); - restore_error_handler(); + ); } /** diff --git a/FormRegistryInterface.php b/FormRegistryInterface.php index 49915ad68a..4edb9833c8 100644 --- a/FormRegistryInterface.php +++ b/FormRegistryInterface.php @@ -18,17 +18,6 @@ */ interface FormRegistryInterface { - /** - * Adds a form type. - * - * @param ResolvedFormTypeInterface $type The type - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * form extensions or type registration in the Dependency - * Injection Container instead. - */ - public function addType(ResolvedFormTypeInterface $type); - /** * Returns a form type by name. * diff --git a/FormTypeGuesserChain.php b/FormTypeGuesserChain.php index 5890e5b246..c7f8ece370 100644 --- a/FormTypeGuesserChain.php +++ b/FormTypeGuesserChain.php @@ -70,18 +70,6 @@ public function guessMaxLength($class, $property) }); } - /** - * {@inheritDoc} - */ - public function guessMinLength($class, $property) - { - trigger_error('guessMinLength() is deprecated since version 2.1 and will be removed in 2.3.', E_USER_DEPRECATED); - - return $this->guess(function ($guesser) use ($class, $property) { - return $guesser->guessMinLength($class, $property); - }); - } - /** * {@inheritDoc} */ diff --git a/FormTypeGuesserInterface.php b/FormTypeGuesserInterface.php index d5b570f33c..e8b603faa1 100644 --- a/FormTypeGuesserInterface.php +++ b/FormTypeGuesserInterface.php @@ -46,18 +46,6 @@ public function guessRequired($class, $property); */ public function guessMaxLength($class, $property); - /** - * Returns a guess about the field's minimum length - * - * @param string $class The fully qualified class name - * @param string $property The name of the property to guess for - * - * @return Guess\Guess A guess for the field's minimum length - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. - */ - public function guessMinLength($class, $property); - /** * Returns a guess about the field's pattern * diff --git a/FormValidatorInterface.php b/FormValidatorInterface.php deleted file mode 100644 index 2fdd51f831..0000000000 --- a/FormValidatorInterface.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form; - -/** - * This interface is deprecated. You should use a FormEvents::POST_BIND event - * listener instead. - * - * @author Bernhard Schussek - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. - */ -interface FormValidatorInterface -{ - /** - * @deprecated Deprecated since version 2.1, to be removed in 2.3. - */ - public function validate(FormInterface $form); -} diff --git a/FormView.php b/FormView.php index d4a3f93d82..8b9528c3b7 100644 --- a/FormView.php +++ b/FormView.php @@ -53,124 +53,6 @@ public function __construct(FormView $parent = null) $this->parent = $parent; } - /** - * Returns the name of the form. - * - * @return string The form name. - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Access - * the public property {@link vars} instead which contains an - * entry named "name". - */ - public function getName() - { - trigger_error('getName() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'vars\' instead which contains an entry named "name".', E_USER_DEPRECATED); - - return $this->vars['name']; - } - - /** - * @param string $name - * @param mixed $value - * - * @return FormView The current view - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Access - * the public property {@link vars} instead. - */ - public function set($name, $value) - { - trigger_error('set() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'vars\' instead.', E_USER_DEPRECATED); - - $this->vars[$name] = $value; - - return $this; - } - - /** - * @param $name - * - * @return Boolean - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Access - * the public property {@link vars} instead. - */ - public function has($name) - { - trigger_error('has() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'vars\' instead.', E_USER_DEPRECATED); - - return array_key_exists($name, $this->vars); - } - - /** - * @param $name - * @param $default - * - * @return mixed - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Access - * the public property {@link vars} instead. - */ - public function get($name, $default = null) - { - trigger_error('get() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'vars\' instead.', E_USER_DEPRECATED); - - if (false === $this->has($name)) { - return $default; - } - - return $this->vars[$name]; - } - - /** - * @return array - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Access - * the public property {@link vars} instead. - */ - public function all() - { - trigger_error('all() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'vars\' instead.', E_USER_DEPRECATED); - - return $this->vars; - } - - /** - * Returns the values of all view variables. - * - * @return array The values of all variables. - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Access - * the public property {@link vars} instead. - */ - public function getVars() - { - trigger_error('getVars() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'vars\' instead.', E_USER_DEPRECATED); - - return $this->vars; - } - - /** - * Sets the value for an attribute. - * - * @param string $name The name of the attribute - * @param string $value The value - * - * @return FormView The current view - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Access - * the public property {@link vars} instead which contains an - * entry named "attr". - */ - public function setAttribute($name, $value) - { - trigger_error('setAttribute() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'vars\' instead which contains an entry named "attr".', E_USER_DEPRECATED); - - $this->vars['attr'][$name] = $value; - - return $this; - } - /** * Returns whether the view was already rendered. * @@ -209,121 +91,6 @@ public function setRendered() return $this; } - /** - * Sets the parent view. - * - * @param FormView $parent The parent view. - * - * @return FormView The view object. - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Access - * the public property {@link parent} instead. - */ - public function setParent(FormView $parent = null) - { - trigger_error('setParent() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'parent\' instead.', E_USER_DEPRECATED); - - $this->parent = $parent; - - return $this; - } - - /** - * Returns the parent view. - * - * @return FormView The parent view. - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Access - * the public property {@link parent} instead. - */ - public function getParent() - { - trigger_error('getParent() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'parent\' instead.', E_USER_DEPRECATED); - - return $this->parent; - } - - /** - * Returns whether this view has a parent. - * - * @return Boolean Whether this view has a parent - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Access - * the public property {@link parent} instead. - */ - public function hasParent() - { - trigger_error('hasParent() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'parent\' instead.', E_USER_DEPRECATED); - - return null !== $this->parent; - } - - /** - * Sets the children view. - * - * @param array $children The children as instances of FormView - * - * @return FormView The current view - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Access - * the public property {@link children} instead. - */ - public function setChildren(array $children) - { - trigger_error('setChildren() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'children\' instead.', E_USER_DEPRECATED); - - $this->children = $children; - - return $this; - } - - /** - * Returns the children. - * - * @return array The children as instances of FormView - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Access - * the public property {@link children} instead. - */ - public function getChildren() - { - trigger_error('getChildren() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'children\' instead.', E_USER_DEPRECATED); - - return $this->children; - } - - /** - * Returns a given child. - * - * @param string $name The name of the child - * - * @return FormView The child view - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Access - * the public property {@link children} instead. - */ - public function getChild($name) - { - trigger_error('getChild() is deprecated since version 2.1 and will be removed in 2.3. Access the public property \'children\' instead.', E_USER_DEPRECATED); - - return $this->children[$name]; - } - - /** - * Returns whether this view has any children. - * - * @return Boolean Whether the view has children. - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * {@link count()} instead. - */ - public function hasChildren() - { - trigger_error('hasChildren() is deprecated since version 2.1 and will be removed in 2.3. Use count() instead.', E_USER_DEPRECATED); - - return count($this->children) > 0; - } - /** * Returns a child by name (implements \ArrayAccess). * diff --git a/ResolvedFormType.php b/ResolvedFormType.php index d20f3b390f..f2ef06c8b8 100644 --- a/ResolvedFormType.php +++ b/ResolvedFormType.php @@ -59,14 +59,6 @@ public function __construct(FormTypeInterface $innerType, array $typeExtensions } } - // BC - if ($innerType instanceof AbstractType) { - /* @var AbstractType $innerType */ - set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handleBC')); - $innerType->setExtensions($typeExtensions); - restore_error_handler(); - } - $this->innerType = $innerType; $this->typeExtensions = $typeExtensions; $this->parent = $parent; diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index ca97c8ec2a..06e9b4d19e 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -114,22 +114,6 @@ public function testNotValidIfChildNotValid() $this->assertFalse($this->form->isValid()); } - public function testHasChildren() - { - $this->form->add($this->getBuilder()->getForm()); - - set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); - $this->assertTrue($this->form->hasChildren()); - restore_error_handler(); - } - - public function testHasNoChildren() - { - set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); - $this->assertFalse($this->form->hasChildren()); - restore_error_handler(); - } - public function testAdd() { $child = $this->getBuilder('foo')->getForm(); diff --git a/Tests/Extension/Core/Type/FormTypeTest.php b/Tests/Extension/Core/Type/FormTypeTest.php index 2d0bf30455..6b906ea4f3 100644 --- a/Tests/Extension/Core/Type/FormTypeTest.php +++ b/Tests/Extension/Core/Type/FormTypeTest.php @@ -598,19 +598,6 @@ public function testPropertyPathNullImpliesDefault() $this->assertTrue($form->getConfig()->getMapped()); } - // BC - public function testPropertyPathFalseImpliesDefaultNotMapped() - { - set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); - $form = $this->factory->createNamed('name', 'form', null, array( - 'property_path' => false, - )); - restore_error_handler(); - - $this->assertEquals(new PropertyPath('name'), $form->getPropertyPath()); - $this->assertFalse($form->getConfig()->getMapped()); - } - public function testNotMapped() { $form = $this->factory->create('form', null, array( diff --git a/Tests/FormFactoryTest.php b/Tests/FormFactoryTest.php index aa43310850..cbb72f2bb3 100644 --- a/Tests/FormFactoryTest.php +++ b/Tests/FormFactoryTest.php @@ -71,56 +71,6 @@ protected function setUp() )))); } - public function testAddType() - { - $type = new FooType(); - $resolvedType = $this->getMockResolvedType(); - - $this->resolvedTypeFactory->expects($this->once()) - ->method('createResolvedType') - ->with($type) - ->will($this->returnValue($resolvedType)); - - $this->registry->expects($this->once()) - ->method('addType') - ->with($resolvedType); - - set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); - $this->factory->addType($type); - restore_error_handler(); - } - - public function testHasType() - { - $this->registry->expects($this->once()) - ->method('hasType') - ->with('name') - ->will($this->returnValue('RESULT')); - - set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); - $this->assertSame('RESULT', $this->factory->hasType('name')); - restore_error_handler(); - } - - public function testGetType() - { - $type = new FooType(); - $resolvedType = $this->getMockResolvedType(); - - $resolvedType->expects($this->once()) - ->method('getInnerType') - ->will($this->returnValue($type)); - - $this->registry->expects($this->once()) - ->method('getType') - ->with('name') - ->will($this->returnValue($resolvedType)); - - set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); - $this->assertEquals($type, $this->factory->getType('name')); - restore_error_handler(); - } - public function testCreateNamedBuilderWithTypeName() { $options = array('a' => '1', 'b' => '2'); @@ -484,74 +434,6 @@ public function testCreateBuilderUsesMaxLengthIfFound() $this->assertEquals('builderInstance', $builder); } - public function testCreateBuilderUsesMinLengthIfFound() - { - $this->guesser1->expects($this->once()) - ->method('guessMinLength') - ->with('Application\Author', 'firstName') - ->will($this->returnValue(new ValueGuess( - 2, - Guess::MEDIUM_CONFIDENCE - ))); - - $this->guesser2->expects($this->once()) - ->method('guessMinLength') - ->with('Application\Author', 'firstName') - ->will($this->returnValue(new ValueGuess( - 5, - Guess::HIGH_CONFIDENCE - ))); - - $factory = $this->getMockFactory(array('createNamedBuilder')); - - $factory->expects($this->once()) - ->method('createNamedBuilder') - ->with('firstName', 'text', null, array('pattern' => '.{5,}')) - ->will($this->returnValue('builderInstance')); - - $builder = $factory->createBuilderForProperty( - 'Application\Author', - 'firstName' - ); - - $this->assertEquals('builderInstance', $builder); - } - - public function testCreateBuilderPrefersPatternOverMinLength() - { - // min length is deprecated - $this->guesser1->expects($this->once()) - ->method('guessMinLength') - ->with('Application\Author', 'firstName') - ->will($this->returnValue(new ValueGuess( - 2, - Guess::HIGH_CONFIDENCE - ))); - - // pattern is preferred even though confidence is lower - $this->guesser2->expects($this->once()) - ->method('guessPattern') - ->with('Application\Author', 'firstName') - ->will($this->returnValue(new ValueGuess( - '.{5,10}', - Guess::LOW_CONFIDENCE - ))); - - $factory = $this->getMockFactory(array('createNamedBuilder')); - - $factory->expects($this->once()) - ->method('createNamedBuilder') - ->with('firstName', 'text', null, array('pattern' => '.{5,10}')) - ->will($this->returnValue('builderInstance')); - - $builder = $factory->createBuilderForProperty( - 'Application\Author', - 'firstName' - ); - - $this->assertEquals('builderInstance', $builder); - } - public function testCreateBuilderUsesRequiredSettingWithHighestConfidence() { $this->guesser1->expects($this->once()) diff --git a/Tests/FormRegistryTest.php b/Tests/FormRegistryTest.php index 50aec90d4f..d29631dcc1 100644 --- a/Tests/FormRegistryTest.php +++ b/Tests/FormRegistryTest.php @@ -68,21 +68,6 @@ protected function setUp() ), $this->resolvedTypeFactory); } - public function testGetTypeReturnsAddedType() - { - $resolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); - - $resolvedType->expects($this->any()) - ->method('getName') - ->will($this->returnValue('foo')); - - set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); - $this->registry->addType($resolvedType); - restore_error_handler(); - - $this->assertSame($resolvedType, $this->registry->getType('foo')); - } - public function testGetTypeFromExtension() { $type = new FooType(); @@ -215,23 +200,6 @@ public function testGetTypeThrowsExceptionIfNoString() $this->registry->getType(array()); } - public function testHasTypeAfterAdding() - { - $resolvedType = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); - - $resolvedType->expects($this->any()) - ->method('getName') - ->will($this->returnValue('foo')); - - $this->assertFalse($this->registry->hasType('foo')); - - set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); - $this->registry->addType($resolvedType); - restore_error_handler(); - - $this->assertTrue($this->registry->hasType('foo')); - } - public function testHasTypeAfterLoadingFromExtension() { $type = new FooType(); diff --git a/Tests/SimpleFormTest.php b/Tests/SimpleFormTest.php index eee38d80f7..c269919599 100644 --- a/Tests/SimpleFormTest.php +++ b/Tests/SimpleFormTest.php @@ -640,27 +640,6 @@ public function testEmptyDataFromClosure() $this->assertEquals('bar', $form->getData()); } - public function testBindValidatesAfterTransformation() - { - $test = $this; - $validator = $this->getFormValidator(); - set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); - $form = $this->getBuilder() - ->addValidator($validator) - ->getForm(); - - $validator->expects($this->once()) - ->method('validate') - ->with($form) - ->will($this->returnCallback(function ($form) use ($test) { - $test->assertEquals('foobar', $form->getData()); - })); - - $form->bind('foobar'); - - restore_error_handler(); - } - public function testBindResetsErrors() { $this->form->addError(new FormError('Error!')); diff --git a/Util/FormUtil.php b/Util/FormUtil.php index 481f6a5080..7647691e0a 100644 --- a/Util/FormUtil.php +++ b/Util/FormUtil.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Form\Util; -use Symfony\Component\PropertyAccess\StringUtil; - /** * @author Bernhard Schussek */ @@ -23,19 +21,6 @@ class FormUtil */ private function __construct() {} - /** - * Alias for {@link StringUtil::singularify()} - * - * @deprecated Deprecated since version 2.2, to be removed in 2.3. Use - * {@link StringUtil::singularify()} instead. - */ - public static function singularify($plural) - { - trigger_error('\Symfony\Component\Form\Util\FormUtil::singularify() is deprecated since version 2.2 and will be removed in 2.3. Use \Symfony\Component\PropertyAccess\StringUtil::singularify() in the PropertyAccess component instead.', E_USER_DEPRECATED); - - return StringUtil::singularify($plural); - } - /** * Returns whether the given data is empty. * diff --git a/Util/PropertyPath.php b/Util/PropertyPath.php deleted file mode 100644 index 41acf0d889..0000000000 --- a/Util/PropertyPath.php +++ /dev/null @@ -1,57 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Util; - -use Symfony\Component\PropertyAccess\PropertyPath as BasePropertyPath; -use Symfony\Component\PropertyAccess\PropertyAccess; - -/** - * Alias for {@link \Symfony\Component\PropertyAccess\PropertyPath}. - * - * @author Bernhard Schussek - * - * @deprecated deprecated since version 2.2, to be removed in 2.3. Use - * {@link \Symfony\Component\PropertyAccess\PropertyPath} - * instead. - */ -class PropertyPath extends BasePropertyPath -{ - /** - * {@inheritdoc} - */ - public function __construct($propertyPath) - { - parent::__construct($propertyPath); - - trigger_error('\Symfony\Component\Form\Util\PropertyPath is deprecated since version 2.2 and will be removed in 2.3. Use \Symfony\Component\PropertyAccess\PropertyPath instead.', E_USER_DEPRECATED); - } - - /** - * Alias for {@link PropertyAccessor::getValue()} - */ - public function getValue($objectOrArray) - { - $propertyAccessor = PropertyAccess::getPropertyAccessor(); - - return $propertyAccessor->getValue($objectOrArray, $this); - } - - /** - * Alias for {@link PropertyAccessor::setValue()} - */ - public function setValue(&$objectOrArray, $value) - { - $propertyAccessor = PropertyAccess::getPropertyAccessor(); - - return $propertyAccessor->setValue($objectOrArray, $this, $value); - } -} diff --git a/Util/PropertyPathBuilder.php b/Util/PropertyPathBuilder.php deleted file mode 100644 index 31836b63bd..0000000000 --- a/Util/PropertyPathBuilder.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Util; - -use Symfony\Component\PropertyAccess\PropertyPathBuilder as BasePropertyPathBuilder; - -/** - * Alias for {@link \Symfony\Component\PropertyAccess\PropertyPathBuilder}. - * - * @author Bernhard Schussek - * - * @deprecated deprecated since version 2.2, to be removed in 2.3. Use - * {@link \Symfony\Component\PropertyAccess\PropertyPathBuilder} - * instead. - */ -class PropertyPathBuilder extends BasePropertyPathBuilder -{ - /** - * {@inheritdoc} - */ - public function __construct($propertyPath) - { - parent::__construct($propertyPath); - - trigger_error('\Symfony\Component\Form\Util\PropertyPathBuilder is deprecated since version 2.2 and will be removed in 2.3. Use \Symfony\Component\PropertyAccess\PropertyPathBuilder instead.', E_USER_DEPRECATED); - } -} diff --git a/Util/PropertyPathInterface.php b/Util/PropertyPathInterface.php deleted file mode 100644 index ec2d5e9efb..0000000000 --- a/Util/PropertyPathInterface.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Util; - -use Symfony\Component\PropertyAccess\PropertyPathInterface as BasePropertyPathInterface; - -/** - * Alias for {@link \Symfony\Component\PropertyAccess\PropertyPathInterface}. - * - * @author Bernhard Schussek - * - * @deprecated deprecated since version 2.2, to be removed in 2.3. Use - * {@link \Symfony\Component\PropertyAccess\PropertyPathInterface} - * instead. - */ -interface PropertyPathInterface extends BasePropertyPathInterface -{ -} diff --git a/Util/PropertyPathIterator.php b/Util/PropertyPathIterator.php deleted file mode 100644 index 024ed6a653..0000000000 --- a/Util/PropertyPathIterator.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Util; - -use Symfony\Component\PropertyAccess\PropertyPathIterator as BasePropertyPathIterator; - -/** - * Alias for {@link \Symfony\Component\PropertyAccess\PropertyPathIterator}. - * - * @author Bernhard Schussek - * - * @deprecated deprecated since version 2.2, to be removed in 2.3. Use - * {@link \Symfony\Component\PropertyAccess\PropertyPathIterator} - * instead. - */ -class PropertyPathIterator extends BasePropertyPathIterator -{ - /** - * {@inheritdoc} - */ - public function __construct($propertyPath) - { - parent::__construct($propertyPath); - - trigger_error('\Symfony\Component\Form\Util\PropertyPathIterator is deprecated since version 2.2 and will be removed in 2.3. Use \Symfony\Component\PropertyAccess\PropertyPathIterator instead.', E_USER_DEPRECATED); - } -} diff --git a/Util/PropertyPathIteratorInterface.php b/Util/PropertyPathIteratorInterface.php deleted file mode 100644 index 3540639530..0000000000 --- a/Util/PropertyPathIteratorInterface.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Util; - -use Symfony\Component\PropertyAccess\PropertyPathIteratorInterface as BasePropertyPathIteratorInterface; - -/** - * Alias for {@link \Symfony\Component\PropertyAccess\PropertyPathIteratorInterface}. - * - * @author Bernhard Schussek - * - * @deprecated deprecated since version 2.2, to be removed in 2.3. Use - * {@link \Symfony\Component\PropertyAccess\PropertyPathIterator} - * instead. - */ -interface PropertyPathIteratorInterface extends BasePropertyPathIteratorInterface -{ -} From 535406fd5a506334f6f65461f35f01462d12d784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Simon?= Date: Sat, 23 Mar 2013 07:20:57 +0100 Subject: [PATCH 079/447] improved bytes conversion method --- Extension/Validator/Util/ServerParams.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Extension/Validator/Util/ServerParams.php b/Extension/Validator/Util/ServerParams.php index b2a4f4b955..f7f48e3357 100644 --- a/Extension/Validator/Util/ServerParams.php +++ b/Extension/Validator/Util/ServerParams.php @@ -29,12 +29,14 @@ public function getPostMaxSize() return null; } - if (preg_match('#^(\d+)([bkmgt])#i', $iniMax, $match)) { - $shift = array('b' => 0, 'k' => 10, 'm' => 20, 'g' => 30, 't' => 40); - $iniMax = ($match[1] * (1 << $shift[strtolower($match[2])])); + if (preg_match('#^\+?(0x?)?([^kmg]*)([KMG]?)#', $iniMax, $match)) { + $shifts = array('' => 0, 'K' => 10, 'M' => 20, 'G' => 30); + $bases = array('' => 10, '0' => 8, '0x' => 16); + + return (intval($match[2], $bases[$match[1]]) * (1 << $shifts[$match[3]])); } - return (int) $iniMax; + return 0; } /** From b7d1e30adcc9b78106c1fbc3a26d8b6c0d1863e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Simon?= Date: Tue, 26 Mar 2013 13:30:34 +0100 Subject: [PATCH 080/447] [Form] fixed ServerParams::getPostMaxSize() regex pattern --- Extension/Validator/Util/ServerParams.php | 4 +- .../Validator/Util/ServerParamsTest.php | 42 +++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 Tests/Extension/Validator/Util/ServerParamsTest.php diff --git a/Extension/Validator/Util/ServerParams.php b/Extension/Validator/Util/ServerParams.php index f7f48e3357..42eb7b7473 100644 --- a/Extension/Validator/Util/ServerParams.php +++ b/Extension/Validator/Util/ServerParams.php @@ -29,9 +29,9 @@ public function getPostMaxSize() return null; } - if (preg_match('#^\+?(0x?)?([^kmg]*)([KMG]?)#', $iniMax, $match)) { + if (preg_match('#^\+?(0X?)?([^KMG]*)([KMG]?)#', $iniMax, $match)) { $shifts = array('' => 0, 'K' => 10, 'M' => 20, 'G' => 30); - $bases = array('' => 10, '0' => 8, '0x' => 16); + $bases = array('' => 10, '0' => 8, '0X' => 16); return (intval($match[2], $bases[$match[1]]) * (1 << $shifts[$match[3]])); } diff --git a/Tests/Extension/Validator/Util/ServerParamsTest.php b/Tests/Extension/Validator/Util/ServerParamsTest.php new file mode 100644 index 0000000000..e9551df8ed --- /dev/null +++ b/Tests/Extension/Validator/Util/ServerParamsTest.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Validator\Util; + +class ServerParamsTest extends \PHPUnit_Framework_TestCase +{ + /** @dataProvider getGetPostMaxSizeTestData */ + public function testGetPostMaxSize($size, $bytes) + { + $serverParams = $this->getMock('Symfony\Component\Form\Extension\Validator\Util\ServerParams', array('getNormalizedIniPostMaxSize')); + $serverParams + ->expects($this->any()) + ->method('getNormalizedIniPostMaxSize') + ->will($this->returnValue(strtoupper($size))); + + $this->assertEquals($bytes, $serverParams->getPostMaxSize()); + } + + public function getGetPostMaxSizeTestData() + { + return array( + array('2k', 2048), + array('2 k', 2048), + array('+2 k', 2048), + array('+2???k', 2048), + array('0x10', 16), + array('0xf', 15), + array('010', 8), + array('+0x10 k', 16 * 1024), + array('1g', 1024 * 1024 * 1024), + ); + } +} From e19786e88c7a101937115b74cf350efa66546316 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Simon?= Date: Wed, 27 Mar 2013 09:25:50 +0100 Subject: [PATCH 081/447] fixed bytes convertion method, again --- Extension/Validator/Util/ServerParams.php | 4 ++-- Tests/Extension/Validator/Util/ServerParamsTest.php | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Extension/Validator/Util/ServerParams.php b/Extension/Validator/Util/ServerParams.php index 42eb7b7473..fab6ac2a61 100644 --- a/Extension/Validator/Util/ServerParams.php +++ b/Extension/Validator/Util/ServerParams.php @@ -29,11 +29,11 @@ public function getPostMaxSize() return null; } - if (preg_match('#^\+?(0X?)?([^KMG]*)([KMG]?)#', $iniMax, $match)) { + if (preg_match('#^\+?(0X?)?(.*?)([KMG]?)$#', $iniMax, $match)) { $shifts = array('' => 0, 'K' => 10, 'M' => 20, 'G' => 30); $bases = array('' => 10, '0' => 8, '0X' => 16); - return (intval($match[2], $bases[$match[1]]) * (1 << $shifts[$match[3]])); + return intval($match[2], $bases[$match[1]]) << $shifts[$match[3]]; } return 0; diff --git a/Tests/Extension/Validator/Util/ServerParamsTest.php b/Tests/Extension/Validator/Util/ServerParamsTest.php index e9551df8ed..7ad5b77106 100644 --- a/Tests/Extension/Validator/Util/ServerParamsTest.php +++ b/Tests/Extension/Validator/Util/ServerParamsTest.php @@ -30,6 +30,7 @@ public function getGetPostMaxSizeTestData() return array( array('2k', 2048), array('2 k', 2048), + array('8m', 8 * 1024 * 1024), array('+2 k', 2048), array('+2???k', 2048), array('0x10', 16), @@ -37,6 +38,9 @@ public function getGetPostMaxSizeTestData() array('010', 8), array('+0x10 k', 16 * 1024), array('1g', 1024 * 1024 * 1024), + array('-1', -1), + array('0', 0), + array('2mk', 2048), // the unit must be the last char, so in this case 'k', not 'm' ); } } From d36e357e11ca23382b234f5fa84fe9f15a2afd9d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 1 Apr 2013 10:06:05 +0200 Subject: [PATCH 082/447] fixed doc references (closes #7515) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index be607a4cdd..2bb5255556 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ https://github.com/fabpot/Silex/blob/master/src/Silex/Provider/FormServiceProvid Documentation: -http://symfony.com/doc/2.1/book/forms.html +http://symfony.com/doc/2.2/book/forms.html Resources --------- From 7183a959aebba06521bd9e38449a51fe7a43e9b1 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 1 Apr 2013 10:07:53 +0200 Subject: [PATCH 083/447] fixed doc references (closes #7515) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2bb5255556..38504bcac2 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ https://github.com/fabpot/Silex/blob/master/src/Silex/Provider/FormServiceProvid Documentation: -http://symfony.com/doc/2.2/book/forms.html +http://symfony.com/doc/2.3/book/forms.html Resources --------- From 88aabaccb1e9d5f7771c500ed0fc7a34c1a26684 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dariusz=20G=C3=B3recki?= Date: Tue, 2 Apr 2013 10:39:57 +0100 Subject: [PATCH 084/447] [CS Fix] Consistent coding-style of concatenation operator usage --- Extension/Core/ChoiceList/ChoiceList.php | 4 +- Extension/Core/ChoiceList/LazyChoiceList.php | 2 +- .../Core/ChoiceList/ObjectChoiceList.php | 2 +- .../ChoiceToBooleanArrayTransformer.php | 2 +- .../ChoiceToValueTransformer.php | 2 +- .../ChoicesToBooleanArrayTransformer.php | 2 +- Extension/Core/Type/CollectionType.php | 2 +- Extension/Core/Type/FormType.php | 6 +- .../Templating/TemplatingRendererEngine.php | 2 +- .../ViolationMapper/ViolationMapper.php | 4 +- .../ViolationMapper/ViolationPath.php | 10 +- Form.php | 18 +-- FormRenderer.php | 4 +- Tests/AbstractLayoutTest.php | 4 +- ...teTimeToLocalizedStringTransformerTest.php | 4 +- .../ViolationMapper/ViolationMapperTest.php | 110 +++++++++--------- Tests/ResolvedFormTypeTest.php | 4 +- Tests/SimpleFormTest.php | 8 +- 18 files changed, 95 insertions(+), 95 deletions(-) diff --git a/Extension/Core/ChoiceList/ChoiceList.php b/Extension/Core/ChoiceList/ChoiceList.php index 4fbca4b451..02341377a3 100644 --- a/Extension/Core/ChoiceList/ChoiceList.php +++ b/Extension/Core/ChoiceList/ChoiceList.php @@ -345,13 +345,13 @@ protected function addChoice(array &$bucketForPreferred, array &$bucketForRemain $index = $this->createIndex($choice); if ('' === $index || null === $index || !FormConfigBuilder::isValidName((string) $index)) { - throw new InvalidConfigurationException('The index "' . $index . '" created by the choice list is invalid. It should be a valid, non-empty Form name.'); + throw new InvalidConfigurationException('The index "'.$index.'" created by the choice list is invalid. It should be a valid, non-empty Form name.'); } $value = $this->createValue($choice); if (!is_string($value)) { - throw new InvalidConfigurationException('The value created by the choice list is of type "' . gettype($value) . '", but should be a string.'); + throw new InvalidConfigurationException('The value created by the choice list is of type "'.gettype($value).'", but should be a string.'); } $view = new ChoiceView($choice, $value, $label); diff --git a/Extension/Core/ChoiceList/LazyChoiceList.php b/Extension/Core/ChoiceList/LazyChoiceList.php index e690266fbc..c48b83bed8 100644 --- a/Extension/Core/ChoiceList/LazyChoiceList.php +++ b/Extension/Core/ChoiceList/LazyChoiceList.php @@ -141,7 +141,7 @@ private function load() $choiceList = $this->loadChoiceList(); if (!$choiceList instanceof ChoiceListInterface) { - throw new Exception('loadChoiceList() should return a ChoiceListInterface instance. Got ' . gettype($choiceList)); + throw new Exception('loadChoiceList() should return a ChoiceListInterface instance. Got '.gettype($choiceList)); } $this->choiceList = $choiceList; diff --git a/Extension/Core/ChoiceList/ObjectChoiceList.php b/Extension/Core/ChoiceList/ObjectChoiceList.php index 04be48ace4..603db4603a 100644 --- a/Extension/Core/ChoiceList/ObjectChoiceList.php +++ b/Extension/Core/ChoiceList/ObjectChoiceList.php @@ -176,7 +176,7 @@ private function extractLabels($choices, array &$labels) } elseif (method_exists($choice, '__toString')) { $labels[$i] = (string) $choice; } else { - throw new StringCastException('A "__toString()" method was not found on the objects of type "' . get_class($choice) . '" passed to the choice field. To read a custom getter instead, set the argument $labelPath to the desired property path.'); + throw new StringCastException('A "__toString()" method was not found on the objects of type "'.get_class($choice).'" passed to the choice field. To read a custom getter instead, set the argument $labelPath to the desired property path.'); } } } diff --git a/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php b/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php index 7e6203c64d..3fb9f13539 100644 --- a/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php +++ b/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php @@ -98,7 +98,7 @@ public function reverseTransform($values) if (isset($choices[$i])) { return $choices[$i] === '' ? null : $choices[$i]; } else { - throw new TransformationFailedException('The choice "' . $i . '" does not exist'); + throw new TransformationFailedException('The choice "'.$i.'" does not exist'); } } } diff --git a/Extension/Core/DataTransformer/ChoiceToValueTransformer.php b/Extension/Core/DataTransformer/ChoiceToValueTransformer.php index dfab6ec454..6aeb7ea256 100644 --- a/Extension/Core/DataTransformer/ChoiceToValueTransformer.php +++ b/Extension/Core/DataTransformer/ChoiceToValueTransformer.php @@ -53,7 +53,7 @@ public function reverseTransform($value) $choices = $this->choiceList->getChoicesForValues(array($value)); if (1 !== count($choices)) { - throw new TransformationFailedException('The choice "' . $value . '" does not exist or is not unique'); + throw new TransformationFailedException('The choice "'.$value.'" does not exist or is not unique'); } $choice = current($choices); diff --git a/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php b/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php index 9c3b6475d1..8ef776563f 100644 --- a/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php +++ b/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php @@ -109,7 +109,7 @@ public function reverseTransform($values) } if (count($unknown) > 0) { - throw new TransformationFailedException('The choices "' . implode('", "', $unknown) . '" were not found'); + throw new TransformationFailedException('The choices "'.implode('", "', $unknown).'" were not found'); } return $result; diff --git a/Extension/Core/Type/CollectionType.php b/Extension/Core/Type/CollectionType.php index 3ff36b9727..0cb3af1bb7 100644 --- a/Extension/Core/Type/CollectionType.php +++ b/Extension/Core/Type/CollectionType.php @@ -28,7 +28,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) { if ($options['allow_add'] && $options['prototype']) { $prototype = $builder->create($options['prototype_name'], $options['type'], array_replace(array( - 'label' => $options['prototype_name'] . 'label__', + 'label' => $options['prototype_name'].'label__', ), $options['options'])); $builder->setAttribute('prototype', $prototype->getForm()); } diff --git a/Extension/Core/Type/FormType.php b/Extension/Core/Type/FormType.php index 26c1f08934..16e7bbc7a0 100644 --- a/Extension/Core/Type/FormType.php +++ b/Extension/Core/Type/FormType.php @@ -82,7 +82,7 @@ public function buildView(FormView $view, FormInterface $form, array $options) } else { $id = $name; $fullName = $name; - $uniqueBlockPrefix = '_' . $blockName; + $uniqueBlockPrefix = '_'.$blockName; } // Complex fields are read-only if they themselves or their parents are. @@ -96,7 +96,7 @@ public function buildView(FormView $view, FormInterface $form, array $options) } else { $id = $name; $fullName = $name; - $uniqueBlockPrefix = '_' . $blockName; + $uniqueBlockPrefix = '_'.$blockName; // Strip leading underscores and digits. These are allowed in // form names, but not in HTML4 ID attributes. @@ -143,7 +143,7 @@ public function buildView(FormView $view, FormInterface $form, array $options) // collection form have different types (dynamically), they should // be rendered differently. // https://github.com/symfony/symfony/issues/5038 - 'cache_key' => $uniqueBlockPrefix . '_' . $form->getConfig()->getType()->getName(), + 'cache_key' => $uniqueBlockPrefix.'_'.$form->getConfig()->getType()->getName(), )); } diff --git a/Extension/Templating/TemplatingRendererEngine.php b/Extension/Templating/TemplatingRendererEngine.php index a6a303ad10..c1dda60b7a 100644 --- a/Extension/Templating/TemplatingRendererEngine.php +++ b/Extension/Templating/TemplatingRendererEngine.php @@ -114,7 +114,7 @@ protected function loadResourceForBlockName($cacheKey, FormView $view, $blockNam */ protected function loadResourceFromTheme($cacheKey, $blockName, $theme) { - if ($this->engine->exists($templateName = $theme . ':' . $blockName . '.html.php')) { + if ($this->engine->exists($templateName = $theme.':'.$blockName.'.html.php')) { $this->resources[$cacheKey][$blockName] = $templateName; return true; diff --git a/Extension/Validator/ViolationMapper/ViolationMapper.php b/Extension/Validator/ViolationMapper/ViolationMapper.php index 61d08c3e5d..1c1e64f94f 100644 --- a/Extension/Validator/ViolationMapper/ViolationMapper.php +++ b/Extension/Validator/ViolationMapper/ViolationMapper.php @@ -174,9 +174,9 @@ private function matchChild(FormInterface $form, PropertyPathIteratorInterface $ } if ($it->isIndex()) { - $chunk .= '[' . $it->current() . ']'; + $chunk .= '['.$it->current().']'; } else { - $chunk .= ('' === $chunk ? '' : '.') . $it->current(); + $chunk .= ('' === $chunk ? '' : '.').$it->current(); } // Test mapping rules as long as we have any diff --git a/Extension/Validator/ViolationMapper/ViolationPath.php b/Extension/Validator/ViolationMapper/ViolationPath.php index 9c99e8618f..2ee85c276a 100644 --- a/Extension/Validator/ViolationMapper/ViolationPath.php +++ b/Extension/Validator/ViolationMapper/ViolationPath.php @@ -155,7 +155,7 @@ public function getElements() public function getElement($index) { if (!isset($this->elements[$index])) { - throw new \OutOfBoundsException('The index ' . $index . ' is not within the violation path'); + throw new \OutOfBoundsException('The index '.$index.' is not within the violation path'); } return $this->elements[$index]; @@ -167,7 +167,7 @@ public function getElement($index) public function isProperty($index) { if (!isset($this->isIndex[$index])) { - throw new \OutOfBoundsException('The index ' . $index . ' is not within the violation path'); + throw new \OutOfBoundsException('The index '.$index.' is not within the violation path'); } return !$this->isIndex[$index]; @@ -179,7 +179,7 @@ public function isProperty($index) public function isIndex($index) { if (!isset($this->isIndex[$index])) { - throw new \OutOfBoundsException('The index ' . $index . ' is not within the violation path'); + throw new \OutOfBoundsException('The index '.$index.' is not within the violation path'); } return $this->isIndex[$index]; @@ -206,7 +206,7 @@ public function isIndex($index) public function mapsForm($index) { if (!isset($this->mapsForm[$index])) { - throw new \OutOfBoundsException('The index ' . $index . ' is not within the violation path'); + throw new \OutOfBoundsException('The index '.$index.' is not within the violation path'); } return $this->mapsForm[$index]; @@ -234,7 +234,7 @@ private function buildString() if ($this->mapsForm[$index]) { $this->pathAsString .= ".children[$element]"; } elseif (!$data) { - $this->pathAsString .= '.data' . ($this->isIndex[$index] ? "[$element]" : ".$element"); + $this->pathAsString .= '.data'.($this->isIndex[$index] ? "[$element]" : ".$element"); $data = true; } else { $this->pathAsString .= $this->isIndex[$index] ? "[$element]" : ".$element"; diff --git a/Form.php b/Form.php index 401d7a2872..3471979411 100644 --- a/Form.php +++ b/Form.php @@ -194,7 +194,7 @@ public function getPropertyPath() } if ($this->parent && null === $this->parent->getConfig()->getDataClass()) { - return new PropertyPath('[' . $this->getName() . ']'); + return new PropertyPath('['.$this->getName().']'); } return new PropertyPath($this->getName()); @@ -314,27 +314,27 @@ public function setData($modelData) if (!FormUtil::isEmpty($viewData)) { $dataClass = $this->config->getDataClass(); - $actualType = is_object($viewData) ? 'an instance of class ' . get_class($viewData) : ' a(n) ' . gettype($viewData); + $actualType = is_object($viewData) ? 'an instance of class '.get_class($viewData) : ' a(n) '.gettype($viewData); if (null === $dataClass && is_object($viewData) && !$viewData instanceof \ArrayAccess) { $expectedType = 'scalar, array or an instance of \ArrayAccess'; throw new Exception( - 'The form\'s view data is expected to be of type ' . $expectedType . ', ' . - 'but is ' . $actualType . '. You ' . + 'The form\'s view data is expected to be of type '.$expectedType.', ' . + 'but is '.$actualType.'. You ' . 'can avoid this error by setting the "data_class" option to ' . - '"' . get_class($viewData) . '" or by adding a view transformer ' . - 'that transforms ' . $actualType . ' to ' . $expectedType . '.' + '"'.get_class($viewData).'" or by adding a view transformer ' . + 'that transforms '.$actualType.' to '.$expectedType.'.' ); } if (null !== $dataClass && !$viewData instanceof $dataClass) { throw new Exception( 'The form\'s view data is expected to be an instance of class ' . - $dataClass . ', but is '. $actualType . '. You can avoid this error ' . + $dataClass.', but is '. $actualType.'. You can avoid this error ' . 'by setting the "data_class" option to null or by adding a view ' . - 'transformer that transforms ' . $actualType . ' to an instance of ' . - $dataClass . '.' + 'transformer that transforms '.$actualType.' to an instance of ' . + $dataClass.'.' ); } } diff --git a/FormRenderer.php b/FormRenderer.php index ee781ffd26..3d6cfa9792 100644 --- a/FormRenderer.php +++ b/FormRenderer.php @@ -138,7 +138,7 @@ public function searchAndRenderBlock(FormView $view, $blockNameSuffix, array $va // The cache key for storing the variables and types $viewCacheKey = $view->vars[self::CACHE_KEY_VAR]; - $viewAndSuffixCacheKey = $viewCacheKey . $blockNameSuffix; + $viewAndSuffixCacheKey = $viewCacheKey.$blockNameSuffix; // In templates, we have to deal with two kinds of block hierarchies: // @@ -173,7 +173,7 @@ public function searchAndRenderBlock(FormView $view, $blockNameSuffix, array $va // the bottom level of the hierarchy (= "__
" block) $blockNameHierarchy = array(); foreach ($view->vars['block_prefixes'] as $blockNamePrefix) { - $blockNameHierarchy[] = $blockNamePrefix . '_' . $blockNameSuffix; + $blockNameHierarchy[] = $blockNamePrefix.'_'.$blockNameSuffix; } $hierarchyLevel = count($blockNameHierarchy) - 1; diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index 15e6530818..bf2c29e8e1 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -79,8 +79,8 @@ protected function assertMatchesXpath($html, $expression, $count = 1) $this->fail(sprintf( "Failed asserting that \n\n%s\n\nmatches exactly %s. Matches %s in \n\n%s", $expression, - $count == 1 ? 'once' : $count . ' times', - $nodeList->length == 1 ? 'once' : $nodeList->length . ' times', + $count == 1 ? 'once' : $count.' times', + $nodeList->length == 1 ? 'once' : $nodeList->length.' times', // strip away and substr($dom->saveHTML(), 6, -8) )); diff --git a/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php index 25d582cfcb..df786a74fa 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php @@ -58,13 +58,13 @@ public function dataProvider() array(null, \IntlDateFormatter::SHORT, null, '03.02.2010 04:05', '2010-02-03 04:05:00 UTC'), array(null, \IntlDateFormatter::MEDIUM, null, '03.02.2010 04:05:06', '2010-02-03 04:05:06 UTC'), array(null, \IntlDateFormatter::LONG, null, - '03.02.2010 04:05:06 GMT' . ($this->isLowerThanIcuVersion('4.8') ? '+00:00' : ''), + '03.02.2010 04:05:06 GMT'.($this->isLowerThanIcuVersion('4.8') ? '+00:00' : ''), '2010-02-03 04:05:06 UTC'), // see below for extra test case for time format FULL array(\IntlDateFormatter::NONE, \IntlDateFormatter::SHORT, null, '04:05', '1970-01-01 04:05:00 UTC'), array(\IntlDateFormatter::NONE, \IntlDateFormatter::MEDIUM, null, '04:05:06', '1970-01-01 04:05:06 UTC'), array(\IntlDateFormatter::NONE, \IntlDateFormatter::LONG, null, - '04:05:06 GMT' . ($this->isLowerThanIcuVersion('4.8') ? '+00:00' : ''), + '04:05:06 GMT'.($this->isLowerThanIcuVersion('4.8') ? '+00:00' : ''), '1970-01-01 04:05:06 UTC'), array(null, null, 'yyyy-MM-dd HH:mm:00', '2010-02-03 04:05:00', '2010-02-03 04:05:00 UTC'), array(null, null, 'yyyy-MM-dd HH:mm', '2010-02-03 04:05', '2010-02-03 04:05:00 UTC'), diff --git a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php index ac529b213f..e8137df35c 100644 --- a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php +++ b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php @@ -130,9 +130,9 @@ public function testMapToVirtualFormIfDataDoesNotMatch() $this->mapper->mapViolation($violation, $parent); - $this->assertCount(0, $parent->getErrors(), $parent->getName() . ' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError()), $child->getErrors(), $child->getName() . ' should have an error, but has none'); - $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName() . ' should not have an error, but has one'); + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertEquals(array($this->getFormError()), $child->getErrors(), $child->getName().' should have an error, but has none'); + $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); } public function testFollowDotRules() @@ -155,10 +155,10 @@ public function testFollowDotRules() $this->mapper->mapViolation($violation, $parent); - $this->assertCount(0, $parent->getErrors(), $parent->getName() . ' should not have an error, but has one'); - $this->assertCount(0, $child->getErrors(), $child->getName() . ' should not have an error, but has one'); - $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName() . ' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError()), $grandGrandChild->getErrors(), $grandGrandChild->getName() . ' should have an error, but has none'); + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one'); + $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); + $this->assertEquals(array($this->getFormError()), $grandGrandChild->getErrors(), $grandGrandChild->getName().' should have an error, but has none'); } public function testAbortMappingIfNotSynchronized() @@ -178,9 +178,9 @@ public function testAbortMappingIfNotSynchronized() $this->mapper->mapViolation($violation, $parent); - $this->assertCount(0, $parent->getErrors(), $parent->getName() . ' should not have an error, but has one'); - $this->assertCount(0, $child->getErrors(), $child->getName() . ' should not have an error, but has one'); - $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName() . ' should not have an error, but has one'); + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one'); + $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); } public function testAbortVirtualFormMappingIfNotSynchronized() @@ -200,9 +200,9 @@ public function testAbortVirtualFormMappingIfNotSynchronized() $this->mapper->mapViolation($violation, $parent); - $this->assertCount(0, $parent->getErrors(), $parent->getName() . ' should not have an error, but has one'); - $this->assertCount(0, $child->getErrors(), $child->getName() . ' should not have an error, but has one'); - $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName() . ' should not have an error, but has one'); + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one'); + $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); } public function testAbortDotRuleMappingIfNotSynchronized() @@ -224,9 +224,9 @@ public function testAbortDotRuleMappingIfNotSynchronized() $this->mapper->mapViolation($violation, $parent); - $this->assertCount(0, $parent->getErrors(), $parent->getName() . ' should not have an error, but has one'); - $this->assertCount(0, $child->getErrors(), $child->getName() . ' should not have an error, but has one'); - $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName() . ' should not have an error, but has one'); + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one'); + $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); } public function provideDefaultTests() @@ -771,16 +771,16 @@ public function testDefaultErrorMapping($target, $childName, $childPath, $grandC $this->mapper->mapViolation($violation, $parent); if (self::LEVEL_0 === $target) { - $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName() . ' should have an error, but has none'); - $this->assertCount(0, $child->getErrors(), $childName . ' should not have an error, but has one'); - $this->assertCount(0, $grandChild->getErrors(), $grandChildName . ' should not have an error, but has one'); + $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none'); + $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); + $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { - $this->assertCount(0, $parent->getErrors(), $parent->getName() . ' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName . ' should have an error, but has none'); - $this->assertCount(0, $grandChild->getErrors(), $grandChildName . ' should not have an error, but has one'); + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none'); + $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } else { - $this->assertCount(0, $parent->getErrors(), $parent->getName() . ' should not have an error, but has one'); - $this->assertCount(0, $child->getErrors(), $childName . ' should not have an error, but has one'); + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName. ' should have an error, but has none'); } } @@ -1243,16 +1243,16 @@ public function testCustomDataErrorMapping($target, $mapFrom, $mapTo, $childName } if (self::LEVEL_0 === $target) { - $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName() . ' should have an error, but has none'); - $this->assertCount(0, $child->getErrors(), $childName . ' should not have an error, but has one'); - $this->assertCount(0, $grandChild->getErrors(), $grandChildName . ' should not have an error, but has one'); + $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none'); + $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); + $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { - $this->assertCount(0, $parent->getErrors(), $parent->getName() . ' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName . ' should have an error, but has none'); - $this->assertCount(0, $grandChild->getErrors(), $grandChildName . ' should not have an error, but has one'); + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none'); + $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } else { - $this->assertCount(0, $parent->getErrors(), $parent->getName() . ' should not have an error, but has one'); - $this->assertCount(0, $child->getErrors(), $childName . ' should not have an error, but has one'); + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName. ' should have an error, but has none'); } } @@ -1424,24 +1424,24 @@ public function testCustomFormErrorMapping($target, $mapFrom, $mapTo, $errorName $this->mapper->mapViolation($violation, $parent); if (self::LEVEL_0 === $target) { - $this->assertCount(0, $errorChild->getErrors(), $errorName . ' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName() . ' should have an error, but has none'); - $this->assertCount(0, $child->getErrors(), $childName . ' should not have an error, but has one'); - $this->assertCount(0, $grandChild->getErrors(), $grandChildName . ' should not have an error, but has one'); + $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one'); + $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none'); + $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); + $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { - $this->assertCount(0, $errorChild->getErrors(), $errorName . ' should not have an error, but has one'); - $this->assertCount(0, $parent->getErrors(), $parent->getName() . ' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName . ' should have an error, but has none'); - $this->assertCount(0, $grandChild->getErrors(), $grandChildName . ' should not have an error, but has one'); + $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one'); + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none'); + $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1B === $target) { - $this->assertEquals(array($this->getFormError()), $errorChild->getErrors(), $errorName . ' should have an error, but has none'); - $this->assertCount(0, $parent->getErrors(), $parent->getName() . ' should not have an error, but has one'); - $this->assertCount(0, $child->getErrors(), $childName . ' should not have an error, but has one'); - $this->assertCount(0, $grandChild->getErrors(), $grandChildName . ' should not have an error, but has one'); + $this->assertEquals(array($this->getFormError()), $errorChild->getErrors(), $errorName.' should have an error, but has none'); + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); + $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } else { - $this->assertCount(0, $errorChild->getErrors(), $errorName . ' should not have an error, but has one'); - $this->assertCount(0, $parent->getErrors(), $parent->getName() . ' should not have an error, but has one'); - $this->assertCount(0, $child->getErrors(), $childName . ' should not have an error, but has one'); + $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one'); + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName. ' should have an error, but has none'); } } @@ -1487,16 +1487,16 @@ public function testVirtualFormErrorMapping($target, $childName, $childPath, $gr $this->mapper->mapViolation($violation, $parent); if (self::LEVEL_0 === $target) { - $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName() . ' should have an error, but has none'); - $this->assertCount(0, $child->getErrors(), $childName . ' should not have an error, but has one'); - $this->assertCount(0, $grandChild->getErrors(), $grandChildName . ' should not have an error, but has one'); + $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none'); + $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); + $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { - $this->assertCount(0, $parent->getErrors(), $parent->getName() . ' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName . ' should have an error, but has none'); - $this->assertCount(0, $grandChild->getErrors(), $grandChildName . ' should not have an error, but has one'); + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none'); + $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } else { - $this->assertCount(0, $parent->getErrors(), $parent->getName() . ' should not have an error, but has one'); - $this->assertCount(0, $child->getErrors(), $childName . ' should not have an error, but has one'); + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName. ' should have an error, but has none'); } } diff --git a/Tests/ResolvedFormTypeTest.php b/Tests/ResolvedFormTypeTest.php index 9a676ad371..fd69dba171 100644 --- a/Tests/ResolvedFormTypeTest.php +++ b/Tests/ResolvedFormTypeTest.php @@ -72,7 +72,7 @@ public function testCreateBuilder() $assertIndex = function ($index) use (&$i, $test) { return function () use (&$i, $test, $index) { /* @var \PHPUnit_Framework_TestCase $test */ - $test->assertEquals($index, $i, 'Executed at index ' . $index); + $test->assertEquals($index, $i, 'Executed at index '.$index); ++$i; }; @@ -170,7 +170,7 @@ public function testCreateView() $assertIndexAndNbOfChildViews = function ($index, $nbOfChildViews) use (&$i, $test) { return function (FormView $view) use (&$i, $test, $index, $nbOfChildViews) { /* @var \PHPUnit_Framework_TestCase $test */ - $test->assertEquals($index, $i, 'Executed at index ' . $index); + $test->assertEquals($index, $i, 'Executed at index '.$index); $test->assertCount($nbOfChildViews, $view); ++$i; diff --git a/Tests/SimpleFormTest.php b/Tests/SimpleFormTest.php index c269919599..6d69f259dc 100644 --- a/Tests/SimpleFormTest.php +++ b/Tests/SimpleFormTest.php @@ -204,7 +204,7 @@ public function testEmptyIfEmptyArray() public function testEmptyIfEmptyCountable() { - $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__ . '\SimpleFormTest_Countable', $this->dispatcher)); + $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__.'\SimpleFormTest_Countable', $this->dispatcher)); $this->form->setData(new SimpleFormTest_Countable(0)); @@ -213,7 +213,7 @@ public function testEmptyIfEmptyCountable() public function testNotEmptyIfFilledCountable() { - $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__ . '\SimpleFormTest_Countable', $this->dispatcher)); + $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__.'\SimpleFormTest_Countable', $this->dispatcher)); $this->form->setData(new SimpleFormTest_Countable(1)); @@ -222,7 +222,7 @@ public function testNotEmptyIfFilledCountable() public function testEmptyIfEmptyTraversable() { - $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__ . '\SimpleFormTest_Traversable', $this->dispatcher)); + $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__.'\SimpleFormTest_Traversable', $this->dispatcher)); $this->form->setData(new SimpleFormTest_Traversable(0)); @@ -231,7 +231,7 @@ public function testEmptyIfEmptyTraversable() public function testNotEmptyIfFilledTraversable() { - $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__ . '\SimpleFormTest_Traversable', $this->dispatcher)); + $this->form = new Form(new FormConfigBuilder('name', __NAMESPACE__.'\SimpleFormTest_Traversable', $this->dispatcher)); $this->form->setData(new SimpleFormTest_Traversable(1)); From 375ffac358faf232c220a9fae666669bcc4ef562 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 15 Mar 2013 12:44:04 +0100 Subject: [PATCH 085/447] [Form] Changed component to use the Intl component --- Extension/Core/Type/CountryType.php | 3 ++- Extension/Core/Type/LanguageType.php | 3 ++- Extension/Core/Type/LocaleType.php | 3 ++- Tests/Extension/Core/Type/LocalizedTestCase.php | 12 +++++++++--- composer.json | 2 +- 5 files changed, 16 insertions(+), 7 deletions(-) diff --git a/Extension/Core/Type/CountryType.php b/Extension/Core/Type/CountryType.php index 4d5f29b995..cbb0c01fe9 100644 --- a/Extension/Core/Type/CountryType.php +++ b/Extension/Core/Type/CountryType.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; +use Symfony\Component\Intl\Intl; use Symfony\Component\Locale\Locale; use Symfony\Component\OptionsResolver\OptionsResolverInterface; @@ -23,7 +24,7 @@ class CountryType extends AbstractType public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( - 'choices' => Locale::getDisplayCountries(\Locale::getDefault()), + 'choices' => Intl::getRegionBundle()->getCountryNames(\Locale::getDefault()), )); } diff --git a/Extension/Core/Type/LanguageType.php b/Extension/Core/Type/LanguageType.php index 1255ea9afc..5c45cffde0 100644 --- a/Extension/Core/Type/LanguageType.php +++ b/Extension/Core/Type/LanguageType.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; +use Symfony\Component\Intl\Intl; use Symfony\Component\Locale\Locale; use Symfony\Component\OptionsResolver\OptionsResolverInterface; @@ -23,7 +24,7 @@ class LanguageType extends AbstractType public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( - 'choices' => Locale::getDisplayLanguages(\Locale::getDefault()), + 'choices' => Intl::getLanguageBundle()->getLanguageNames(\Locale::getDefault()), )); } diff --git a/Extension/Core/Type/LocaleType.php b/Extension/Core/Type/LocaleType.php index e9793aae30..43d1c4bbc3 100644 --- a/Extension/Core/Type/LocaleType.php +++ b/Extension/Core/Type/LocaleType.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; +use Symfony\Component\Intl\Intl; use Symfony\Component\Locale\Locale; use Symfony\Component\OptionsResolver\OptionsResolverInterface; @@ -23,7 +24,7 @@ class LocaleType extends AbstractType public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( - 'choices' => Locale::getDisplayLocales(\Locale::getDefault()), + 'choices' => Intl::getLocaleBundle()->getLocaleNames(\Locale::getDefault()), )); } diff --git a/Tests/Extension/Core/Type/LocalizedTestCase.php b/Tests/Extension/Core/Type/LocalizedTestCase.php index 1772d8cc55..18a939d1f4 100644 --- a/Tests/Extension/Core/Type/LocalizedTestCase.php +++ b/Tests/Extension/Core/Type/LocalizedTestCase.php @@ -11,18 +11,24 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use Symfony\Component\Intl\Intl; + abstract class LocalizedTestCase extends TypeTestCase { protected function setUp() { parent::setUp(); - if (!class_exists('Symfony\Component\Locale\Locale')) { - $this->markTestSkipped('The "Locale" component is not available'); + if (!class_exists('Symfony\Component\Intl\Intl')) { + $this->markTestSkipped('The "Intl" component is not available'); } - if (!extension_loaded('intl')) { + if (!Intl::isExtensionLoaded()) { $this->markTestSkipped('The "intl" extension is not available'); } + + Intl::setDataSource(Intl::STUB); + + \Locale::setDefault('en'); } } diff --git a/composer.json b/composer.json index 5ceb9095cc..107561edae 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "require": { "php": ">=5.3.3", "symfony/event-dispatcher": "~2.1", - "symfony/locale": "~2.0", + "symfony/intl": "~2.3", "symfony/options-resolver": ">=2.1,<2.4-dev", "symfony/property-access": ">=2.2,<2.4-dev" }, From 7adf22b1516132361add73bb7427d2c0e0cfce27 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 15 Mar 2013 13:04:12 +0100 Subject: [PATCH 086/447] [Form] Fixed failing tests --- Tests/Extension/Core/Type/CountryTypeTest.php | 10 ++++------ Tests/Extension/Core/Type/LanguageTypeTest.php | 12 +++++------- Tests/Extension/Core/Type/LocaleTypeTest.php | 8 +++----- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/Tests/Extension/Core/Type/CountryTypeTest.php b/Tests/Extension/Core/Type/CountryTypeTest.php index e5c24a38f9..97339d106e 100644 --- a/Tests/Extension/Core/Type/CountryTypeTest.php +++ b/Tests/Extension/Core/Type/CountryTypeTest.php @@ -17,17 +17,15 @@ class CountryTypeTest extends LocalizedTestCase { public function testCountriesAreSelectable() { - \Locale::setDefault('de_AT'); - $form = $this->factory->create('country'); $view = $form->createView(); $choices = $view->vars['choices']; // Don't check objects for identity - $this->assertContains(new ChoiceView('DE', 'DE', 'Deutschland'), $choices, '', false, false); - $this->assertContains(new ChoiceView('GB', 'GB', 'Vereinigtes Königreich'), $choices, '', false, false); - $this->assertContains(new ChoiceView('US', 'US', 'Vereinigte Staaten'), $choices, '', false, false); - $this->assertContains(new ChoiceView('FR', 'FR', 'Frankreich'), $choices, '', false, false); + $this->assertContains(new ChoiceView('DE', 'DE', 'Germany'), $choices, '', false, false); + $this->assertContains(new ChoiceView('GB', 'GB', 'United Kingdom'), $choices, '', false, false); + $this->assertContains(new ChoiceView('US', 'US', 'United States'), $choices, '', false, false); + $this->assertContains(new ChoiceView('FR', 'FR', 'France'), $choices, '', false, false); $this->assertContains(new ChoiceView('MY', 'MY', 'Malaysia'), $choices, '', false, false); } diff --git a/Tests/Extension/Core/Type/LanguageTypeTest.php b/Tests/Extension/Core/Type/LanguageTypeTest.php index 62ddae7635..5b78ed0b00 100644 --- a/Tests/Extension/Core/Type/LanguageTypeTest.php +++ b/Tests/Extension/Core/Type/LanguageTypeTest.php @@ -17,17 +17,15 @@ class LanguageTypeTest extends LocalizedTestCase { public function testCountriesAreSelectable() { - \Locale::setDefault('de_AT'); - $form = $this->factory->create('language'); $view = $form->createView(); $choices = $view->vars['choices']; - $this->assertContains(new ChoiceView('en', 'en', 'Englisch'), $choices, '', false, false); - $this->assertContains(new ChoiceView('en_GB', 'en_GB', 'Britisches Englisch'), $choices, '', false, false); - $this->assertContains(new ChoiceView('en_US', 'en_US', 'Amerikanisches Englisch'), $choices, '', false, false); - $this->assertContains(new ChoiceView('fr', 'fr', 'Französisch'), $choices, '', false, false); - $this->assertContains(new ChoiceView('my', 'my', 'Birmanisch'), $choices, '', false, false); + $this->assertContains(new ChoiceView('en', 'en', 'English'), $choices, '', false, false); + $this->assertContains(new ChoiceView('en_GB', 'en_GB', 'British English'), $choices, '', false, false); + $this->assertContains(new ChoiceView('en_US', 'en_US', 'U.S. English'), $choices, '', false, false); + $this->assertContains(new ChoiceView('fr', 'fr', 'French'), $choices, '', false, false); + $this->assertContains(new ChoiceView('my', 'my', 'Burmese'), $choices, '', false, false); } public function testMultipleLanguagesIsNotIncluded() diff --git a/Tests/Extension/Core/Type/LocaleTypeTest.php b/Tests/Extension/Core/Type/LocaleTypeTest.php index d02d2ba60c..56c0396143 100644 --- a/Tests/Extension/Core/Type/LocaleTypeTest.php +++ b/Tests/Extension/Core/Type/LocaleTypeTest.php @@ -17,14 +17,12 @@ class LocaleTypeTest extends LocalizedTestCase { public function testLocalesAreSelectable() { - \Locale::setDefault('de_AT'); - $form = $this->factory->create('locale'); $view = $form->createView(); $choices = $view->vars['choices']; - $this->assertContains(new ChoiceView('en', 'en', 'Englisch'), $choices, '', false, false); - $this->assertContains(new ChoiceView('en_GB', 'en_GB', 'Englisch (Vereinigtes Königreich)'), $choices, '', false, false); - $this->assertContains(new ChoiceView('zh_Hant_MO', 'zh_Hant_MO', 'Chinesisch (traditionell, Sonderverwaltungszone Macao)'), $choices, '', false, false); + $this->assertContains(new ChoiceView('en', 'en', 'English'), $choices, '', false, false); + $this->assertContains(new ChoiceView('en_GB', 'en_GB', 'English (United Kingdom)'), $choices, '', false, false); + $this->assertContains(new ChoiceView('zh_Hant_MO', 'zh_Hant_MO', 'Chinese (Traditional, Macau SAR China)'), $choices, '', false, false); } } From 5b25141b688ec4deb07e9f02a772d93da9a56923 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 15 Mar 2013 16:17:03 +0100 Subject: [PATCH 087/447] [Form] Adapted to latest Intl changes --- Extension/Core/Type/CountryType.php | 2 +- Extension/Core/Type/LanguageType.php | 2 +- Extension/Core/Type/LocaleType.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Extension/Core/Type/CountryType.php b/Extension/Core/Type/CountryType.php index cbb0c01fe9..c9c979a6e6 100644 --- a/Extension/Core/Type/CountryType.php +++ b/Extension/Core/Type/CountryType.php @@ -24,7 +24,7 @@ class CountryType extends AbstractType public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( - 'choices' => Intl::getRegionBundle()->getCountryNames(\Locale::getDefault()), + 'choices' => Intl::getRegionBundle()->getCountryNames(), )); } diff --git a/Extension/Core/Type/LanguageType.php b/Extension/Core/Type/LanguageType.php index 5c45cffde0..04994a0775 100644 --- a/Extension/Core/Type/LanguageType.php +++ b/Extension/Core/Type/LanguageType.php @@ -24,7 +24,7 @@ class LanguageType extends AbstractType public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( - 'choices' => Intl::getLanguageBundle()->getLanguageNames(\Locale::getDefault()), + 'choices' => Intl::getLanguageBundle()->getLanguageNames(), )); } diff --git a/Extension/Core/Type/LocaleType.php b/Extension/Core/Type/LocaleType.php index 43d1c4bbc3..c68c561a2d 100644 --- a/Extension/Core/Type/LocaleType.php +++ b/Extension/Core/Type/LocaleType.php @@ -24,7 +24,7 @@ class LocaleType extends AbstractType public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( - 'choices' => Intl::getLocaleBundle()->getLocaleNames(\Locale::getDefault()), + 'choices' => Intl::getLocaleBundle()->getLocaleNames(), )); } From ed32b0ae9ebe306986ca29f1e056f2af58fbc638 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Sat, 16 Mar 2013 01:38:38 +0100 Subject: [PATCH 088/447] [Form] Improved tests to use the IntlTestHelper class --- .../Core/DataTransformer/DateTimeTestCase.php | 2 +- ...teTimeToLocalizedStringTransformerTest.php | 28 +++----- ...ntegerToLocalizedStringTransformerTest.php | 6 +- .../DataTransformer/LocalizedTestCase.php | 70 ------------------- .../MoneyToLocalizedStringTransformerTest.php | 6 +- ...NumberToLocalizedStringTransformerTest.php | 32 ++------- ...ercentToLocalizedStringTransformerTest.php | 6 +- Tests/Extension/Core/Type/CountryTypeTest.php | 10 ++- .../Extension/Core/Type/DateTimeTypeTest.php | 10 ++- Tests/Extension/Core/Type/DateTypeTest.php | 8 ++- Tests/Extension/Core/Type/IntegerTypeTest.php | 11 ++- .../Extension/Core/Type/LanguageTypeTest.php | 10 ++- Tests/Extension/Core/Type/LocaleTypeTest.php | 10 ++- .../Extension/Core/Type/LocalizedTestCase.php | 34 --------- Tests/Extension/Core/Type/MoneyTypeTest.php | 13 +++- Tests/Extension/Core/Type/NumberTypeTest.php | 7 +- Tests/Extension/Core/Type/TimeTypeTest.php | 10 ++- Tests/Extension/Core/Type/UrlTypeTest.php | 2 +- 18 files changed, 111 insertions(+), 164 deletions(-) delete mode 100644 Tests/Extension/Core/DataTransformer/LocalizedTestCase.php delete mode 100644 Tests/Extension/Core/Type/LocalizedTestCase.php diff --git a/Tests/Extension/Core/DataTransformer/DateTimeTestCase.php b/Tests/Extension/Core/DataTransformer/DateTimeTestCase.php index e9596b3efb..f7722c496e 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeTestCase.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeTestCase.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; -abstract class DateTimeTestCase extends LocalizedTestCase +abstract class DateTimeTestCase extends \PHPUnit_Framework_TestCase { public static function assertDateTimeEquals(\DateTime $expected, \DateTime $actual) { diff --git a/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php index df786a74fa..abef21ba6d 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToLocalizedStringTransformer; +use Symfony\Component\Intl\Util\IntlTestHelper; class DateTimeToLocalizedStringTransformerTest extends DateTimeTestCase { @@ -22,6 +23,9 @@ protected function setUp() { parent::setUp(); + // Since we test against "de_AT", we need the full implementation + IntlTestHelper::requireFullIntl($this); + \Locale::setDefault('de_AT'); $this->dateTime = new \DateTime('2010-02-03 04:05:06 UTC'); @@ -57,15 +61,11 @@ public function dataProvider() array(\IntlDateFormatter::FULL, \IntlDateFormatter::NONE, null, 'Mittwoch, 03. Februar 2010', '2010-02-03 00:00:00 UTC'), array(null, \IntlDateFormatter::SHORT, null, '03.02.2010 04:05', '2010-02-03 04:05:00 UTC'), array(null, \IntlDateFormatter::MEDIUM, null, '03.02.2010 04:05:06', '2010-02-03 04:05:06 UTC'), - array(null, \IntlDateFormatter::LONG, null, - '03.02.2010 04:05:06 GMT'.($this->isLowerThanIcuVersion('4.8') ? '+00:00' : ''), - '2010-02-03 04:05:06 UTC'), + array(null, \IntlDateFormatter::LONG, null, '03.02.2010 04:05:06 GMT', '2010-02-03 04:05:06 UTC'), // see below for extra test case for time format FULL array(\IntlDateFormatter::NONE, \IntlDateFormatter::SHORT, null, '04:05', '1970-01-01 04:05:00 UTC'), array(\IntlDateFormatter::NONE, \IntlDateFormatter::MEDIUM, null, '04:05:06', '1970-01-01 04:05:06 UTC'), - array(\IntlDateFormatter::NONE, \IntlDateFormatter::LONG, null, - '04:05:06 GMT'.($this->isLowerThanIcuVersion('4.8') ? '+00:00' : ''), - '1970-01-01 04:05:06 UTC'), + array(\IntlDateFormatter::NONE, \IntlDateFormatter::LONG, null, '04:05:06 GMT', '1970-01-01 04:05:06 UTC'), array(null, null, 'yyyy-MM-dd HH:mm:00', '2010-02-03 04:05:00', '2010-02-03 04:05:00 UTC'), array(null, null, 'yyyy-MM-dd HH:mm', '2010-02-03 04:05', '2010-02-03 04:05:00 UTC'), array(null, null, 'yyyy-MM-dd HH', '2010-02-03 04', '2010-02-03 04:00:00 UTC'), @@ -101,15 +101,9 @@ public function testTransform($dateFormat, $timeFormat, $pattern, $output, $inpu public function testTransformFullTime() { - if ($this->isLowerThanIcuVersion('4.0')) { - $this->markTestSkipped('Please upgrade ICU version to 4.0+'); - } - $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, \IntlDateFormatter::FULL); - $expected = $this->isLowerThanIcuVersion('4.8') ? '03.02.2010 04:05:06 GMT+00:00' : '03.02.2010 04:05:06 GMT'; - - $this->assertEquals($expected, $transformer->transform($this->dateTime)); + $this->assertEquals('03.02.2010 04:05:06 GMT', $transformer->transform($this->dateTime)); } public function testTransformToDifferentLocale() @@ -118,7 +112,7 @@ public function testTransformToDifferentLocale() $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC'); - $this->assertEquals('Feb 3, 2010 4:05 AM', $transformer->transform($this->dateTime)); + $this->assertEquals('Feb 3, 2010, 4:05 AM', $transformer->transform($this->dateTime)); } public function testTransformEmpty() @@ -188,10 +182,6 @@ public function testReverseTransform($dateFormat, $timeFormat, $pattern, $input, public function testReverseTransformFullTime() { - if ($this->isLowerThanIcuVersion('4.0')) { - $this->markTestSkipped('Please upgrade ICU version to 4.0+'); - } - $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, \IntlDateFormatter::FULL); $this->assertDateTimeEquals($this->dateTime, $transformer->reverseTransform('03.02.2010 04:05:06 GMT+00:00')); @@ -203,7 +193,7 @@ public function testReverseTransformFromDifferentLocale() $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC'); - $this->assertDateTimeEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('Feb 3, 2010 04:05 AM')); + $this->assertDateTimeEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('Feb 3, 2010, 04:05 AM')); } public function testReverseTransformWithDifferentTimezones() diff --git a/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php index d099cde910..9aa3deee44 100644 --- a/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php @@ -12,13 +12,17 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\IntegerToLocalizedStringTransformer; +use Symfony\Component\Intl\Util\IntlTestHelper; -class IntegerToLocalizedStringTransformerTest extends LocalizedTestCase +class IntegerToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase { protected function setUp() { parent::setUp(); + // Since we test against "de_AT", we need the full implementation + IntlTestHelper::requireFullIntl($this); + \Locale::setDefault('de_AT'); } diff --git a/Tests/Extension/Core/DataTransformer/LocalizedTestCase.php b/Tests/Extension/Core/DataTransformer/LocalizedTestCase.php deleted file mode 100644 index 494928b7e1..0000000000 --- a/Tests/Extension/Core/DataTransformer/LocalizedTestCase.php +++ /dev/null @@ -1,70 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; - -abstract class LocalizedTestCase extends \PHPUnit_Framework_TestCase -{ - protected static $icuVersion = null; - - protected function setUp() - { - parent::setUp(); - - if (!$this->isIntlExtensionLoaded()) { - $this->markTestSkipped('The "intl" extension is not available'); - } - } - - protected function isIntlExtensionLoaded() - { - return extension_loaded('intl'); - } - - protected function isLowerThanIcuVersion($version) - { - $version = $this->normalizeIcuVersion($version); - $icuVersion = $this->normalizeIcuVersion($this->getIntlExtensionIcuVersion()); - - return $icuVersion < $version; - } - - protected function normalizeIcuVersion($version) - { - return ((float) $version) * 100; - } - - protected function getIntlExtensionIcuVersion() - { - if (isset(self::$icuVersion)) { - return self::$icuVersion; - } - - if (!$this->isIntlExtensionLoaded()) { - throw new \RuntimeException('The intl extension is not available'); - } - - if (defined('INTL_ICU_VERSION')) { - return INTL_ICU_VERSION; - } - - $reflector = new \ReflectionExtension('intl'); - - ob_start(); - $reflector->info(); - $output = ob_get_clean(); - - preg_match('/^ICU version => (.*)$/m', $output, $matches); - self::$icuVersion = $matches[1]; - - return self::$icuVersion; - } -} diff --git a/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php index 8ff5c16ac0..59606f5c47 100644 --- a/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php @@ -12,13 +12,17 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\MoneyToLocalizedStringTransformer; +use Symfony\Component\Intl\Util\IntlTestHelper; -class MoneyToLocalizedStringTransformerTest extends LocalizedTestCase +class MoneyToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase { protected function setUp() { parent::setUp(); + // Since we test against "de_AT", we need the full implementation + IntlTestHelper::requireFullIntl($this); + \Locale::setDefault('de_AT'); } diff --git a/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php index 151dbc80f6..fad6e32376 100644 --- a/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php @@ -12,13 +12,17 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\NumberToLocalizedStringTransformer; +use Symfony\Component\Intl\Util\IntlTestHelper; -class NumberToLocalizedStringTransformerTest extends LocalizedTestCase +class NumberToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase { protected function setUp() { parent::setUp(); + // Since we test against "de_AT", we need the full implementation + IntlTestHelper::requireFullIntl($this); + \Locale::setDefault('de_AT'); } @@ -96,10 +100,6 @@ public function testReverseTransformWithGrouping() public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsNotDot() { - if ($this->isLowerThanIcuVersion('4.7')) { - $this->markTestSkipped('Please upgrade ICU version to 4.7+'); - } - \Locale::setDefault('fr'); $transformer = new NumberToLocalizedStringTransformer(null, true); @@ -117,10 +117,6 @@ public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsNotDot() */ public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDot() { - if ($this->isLowerThanIcuVersion('4.7')) { - $this->markTestSkipped('Please upgrade ICU version to 4.7+'); - } - $transformer = new NumberToLocalizedStringTransformer(null, true); $transformer->reverseTransform('1.234.5'); @@ -131,10 +127,6 @@ public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDot() */ public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDotWithNoGroupSep() { - if ($this->isLowerThanIcuVersion('4.7')) { - $this->markTestSkipped('Please upgrade ICU version to 4.7+'); - } - $transformer = new NumberToLocalizedStringTransformer(null, true); $transformer->reverseTransform('1234.5'); @@ -151,11 +143,7 @@ public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsDotButNoGroupin public function testDecimalSeparatorMayBeCommaIfGroupingSeparatorIsNotComma() { - if ($this->isLowerThanIcuVersion('4.7')) { - $this->markTestSkipped('Please upgrade ICU version to 4.7+'); - } - - \Locale::setDefault('ak'); + \Locale::setDefault('bg'); $transformer = new NumberToLocalizedStringTransformer(null, true); // completely valid format @@ -172,10 +160,6 @@ public function testDecimalSeparatorMayBeCommaIfGroupingSeparatorIsNotComma() */ public function testDecimalSeparatorMayNotBeCommaIfGroupingSeparatorIsComma() { - if ($this->isLowerThanIcuVersion('4.7')) { - $this->markTestSkipped('Please upgrade ICU version to 4.7+'); - } - \Locale::setDefault('en'); $transformer = new NumberToLocalizedStringTransformer(null, true); @@ -187,10 +171,6 @@ public function testDecimalSeparatorMayNotBeCommaIfGroupingSeparatorIsComma() */ public function testDecimalSeparatorMayNotBeCommaIfGroupingSeparatorIsCommaWithNoGroupSep() { - if ($this->isLowerThanIcuVersion('4.7')) { - $this->markTestSkipped('Please upgrade ICU version to 4.7+'); - } - \Locale::setDefault('en'); $transformer = new NumberToLocalizedStringTransformer(null, true); diff --git a/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php index 6cbca5a402..4bc139e72d 100644 --- a/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php @@ -12,13 +12,17 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\DataTransformer\PercentToLocalizedStringTransformer; +use Symfony\Component\Intl\Util\IntlTestHelper; -class PercentToLocalizedStringTransformerTest extends LocalizedTestCase +class PercentToLocalizedStringTransformerTest extends \PHPUnit_Framework_TestCase { protected function setUp() { parent::setUp(); + // Since we test against "de_AT", we need the full implementation + IntlTestHelper::requireFullIntl($this); + \Locale::setDefault('de_AT'); } diff --git a/Tests/Extension/Core/Type/CountryTypeTest.php b/Tests/Extension/Core/Type/CountryTypeTest.php index 97339d106e..1d56e2a024 100644 --- a/Tests/Extension/Core/Type/CountryTypeTest.php +++ b/Tests/Extension/Core/Type/CountryTypeTest.php @@ -12,9 +12,17 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Extension\Core\View\ChoiceView; +use Symfony\Component\Intl\Util\IntlTestHelper; -class CountryTypeTest extends LocalizedTestCase +class CountryTypeTest extends TypeTestCase { + protected function setUp() + { + IntlTestHelper::requireIntl($this); + + parent::setUp(); + } + public function testCountriesAreSelectable() { $form = $this->factory->create('country'); diff --git a/Tests/Extension/Core/Type/DateTimeTypeTest.php b/Tests/Extension/Core/Type/DateTimeTypeTest.php index 568766cf20..b5aad87eee 100644 --- a/Tests/Extension/Core/Type/DateTimeTypeTest.php +++ b/Tests/Extension/Core/Type/DateTimeTypeTest.php @@ -12,9 +12,17 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\FormError; +use Symfony\Component\Intl\Util\IntlTestHelper; -class DateTimeTypeTest extends LocalizedTestCase +class DateTimeTypeTest extends TypeTestCase { + protected function setUp() + { + IntlTestHelper::requireIntl($this); + + parent::setUp(); + } + public function testSubmitDateTime() { $form = $this->factory->create('datetime', null, array( diff --git a/Tests/Extension/Core/Type/DateTypeTest.php b/Tests/Extension/Core/Type/DateTypeTest.php index c0d7da676b..abef0b18ba 100644 --- a/Tests/Extension/Core/Type/DateTypeTest.php +++ b/Tests/Extension/Core/Type/DateTypeTest.php @@ -13,13 +13,17 @@ use Symfony\Component\Form\Extension\Core\View\ChoiceView; use Symfony\Component\Form\FormError; +use Symfony\Component\Intl\Util\IntlTestHelper; -class DateTypeTest extends LocalizedTestCase +class DateTypeTest extends TypeTestCase { protected function setUp() { parent::setUp(); + // we test against "de_AT", so we need the full implementation + IntlTestHelper::requireFullIntl($this); + \Locale::setDefault('de_AT'); } @@ -385,7 +389,7 @@ public function testMonthsOptionShortFormat() $this->assertEquals(array( new ChoiceView('1', '1', 'Jän'), - new ChoiceView('4', '4', 'Apr') + new ChoiceView('4', '4', 'Apr.') ), $view['month']->vars['choices']); } diff --git a/Tests/Extension/Core/Type/IntegerTypeTest.php b/Tests/Extension/Core/Type/IntegerTypeTest.php index 435749a16b..d16cc867b5 100644 --- a/Tests/Extension/Core/Type/IntegerTypeTest.php +++ b/Tests/Extension/Core/Type/IntegerTypeTest.php @@ -11,8 +11,17 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; -class IntegerTypeTest extends LocalizedTestCase +use Symfony\Component\Intl\Util\IntlTestHelper; + +class IntegerTypeTest extends TypeTestCase { + protected function setUp() + { + IntlTestHelper::requireIntl($this); + + parent::setUp(); + } + public function testSubmitCastsToInteger() { $form = $this->factory->create('integer'); diff --git a/Tests/Extension/Core/Type/LanguageTypeTest.php b/Tests/Extension/Core/Type/LanguageTypeTest.php index 5b78ed0b00..24434b2148 100644 --- a/Tests/Extension/Core/Type/LanguageTypeTest.php +++ b/Tests/Extension/Core/Type/LanguageTypeTest.php @@ -12,9 +12,17 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Extension\Core\View\ChoiceView; +use Symfony\Component\Intl\Util\IntlTestHelper; -class LanguageTypeTest extends LocalizedTestCase +class LanguageTypeTest extends TypeTestCase { + protected function setUp() + { + IntlTestHelper::requireIntl($this); + + parent::setUp(); + } + public function testCountriesAreSelectable() { $form = $this->factory->create('language'); diff --git a/Tests/Extension/Core/Type/LocaleTypeTest.php b/Tests/Extension/Core/Type/LocaleTypeTest.php index 56c0396143..e402cb4bfb 100644 --- a/Tests/Extension/Core/Type/LocaleTypeTest.php +++ b/Tests/Extension/Core/Type/LocaleTypeTest.php @@ -12,9 +12,17 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Extension\Core\View\ChoiceView; +use Symfony\Component\Intl\Util\IntlTestHelper; -class LocaleTypeTest extends LocalizedTestCase +class LocaleTypeTest extends TypeTestCase { + protected function setUp() + { + IntlTestHelper::requireIntl($this); + + parent::setUp(); + } + public function testLocalesAreSelectable() { $form = $this->factory->create('locale'); diff --git a/Tests/Extension/Core/Type/LocalizedTestCase.php b/Tests/Extension/Core/Type/LocalizedTestCase.php deleted file mode 100644 index 18a939d1f4..0000000000 --- a/Tests/Extension/Core/Type/LocalizedTestCase.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Tests\Extension\Core\Type; - -use Symfony\Component\Intl\Intl; - -abstract class LocalizedTestCase extends TypeTestCase -{ - protected function setUp() - { - parent::setUp(); - - if (!class_exists('Symfony\Component\Intl\Intl')) { - $this->markTestSkipped('The "Intl" component is not available'); - } - - if (!Intl::isExtensionLoaded()) { - $this->markTestSkipped('The "intl" extension is not available'); - } - - Intl::setDataSource(Intl::STUB); - - \Locale::setDefault('en'); - } -} diff --git a/Tests/Extension/Core/Type/MoneyTypeTest.php b/Tests/Extension/Core/Type/MoneyTypeTest.php index 9eadaac2c4..97fc37fa3d 100644 --- a/Tests/Extension/Core/Type/MoneyTypeTest.php +++ b/Tests/Extension/Core/Type/MoneyTypeTest.php @@ -11,8 +11,19 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; -class MoneyTypeTest extends LocalizedTestCase +use Symfony\Component\Intl\Util\IntlTestHelper; + +class MoneyTypeTest extends TypeTestCase { + protected function setUp() + { + // we test against different locales, so we need the full + // implementation + IntlTestHelper::requireFullIntl($this); + + parent::setUp(); + } + public function testPassMoneyPatternToView() { \Locale::setDefault('de_DE'); diff --git a/Tests/Extension/Core/Type/NumberTypeTest.php b/Tests/Extension/Core/Type/NumberTypeTest.php index a282190520..e5b3dd747c 100644 --- a/Tests/Extension/Core/Type/NumberTypeTest.php +++ b/Tests/Extension/Core/Type/NumberTypeTest.php @@ -11,12 +11,17 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; -class NumberTypeTest extends LocalizedTestCase +use Symfony\Component\Intl\Util\IntlTestHelper; + +class NumberTypeTest extends TypeTestCase { protected function setUp() { parent::setUp(); + // we test against "de_DE", so we need the full implementation + IntlTestHelper::requireFullIntl($this); + \Locale::setDefault('de_DE'); } diff --git a/Tests/Extension/Core/Type/TimeTypeTest.php b/Tests/Extension/Core/Type/TimeTypeTest.php index 6d23250e04..fa630b2201 100644 --- a/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/Tests/Extension/Core/Type/TimeTypeTest.php @@ -13,9 +13,17 @@ use Symfony\Component\Form\Extension\Core\View\ChoiceView; use Symfony\Component\Form\FormError; +use Symfony\Component\Intl\Util\IntlTestHelper; -class TimeTypeTest extends LocalizedTestCase +class TimeTypeTest extends TypeTestCase { + protected function setUp() + { + IntlTestHelper::requireIntl($this); + + parent::setUp(); + } + public function testSubmitDateTime() { $form = $this->factory->create('time', null, array( diff --git a/Tests/Extension/Core/Type/UrlTypeTest.php b/Tests/Extension/Core/Type/UrlTypeTest.php index d1fa6dad8d..0782528884 100644 --- a/Tests/Extension/Core/Type/UrlTypeTest.php +++ b/Tests/Extension/Core/Type/UrlTypeTest.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; -class UrlTypeTest extends LocalizedTestCase +class UrlTypeTest extends TypeTestCase { public function testSubmitAddsDefaultProtocolIfNoneIsIncluded() { From 5525164c0dfbd35b2c6b8e17462f1f75c83ed24c Mon Sep 17 00:00:00 2001 From: dantleech Date: Wed, 10 Apr 2013 11:24:37 +0100 Subject: [PATCH 089/447] Enforce sprintf for exceptions --- Extension/Core/ChoiceList/ChoiceList.php | 4 ++-- Extension/Core/ChoiceList/LazyChoiceList.php | 2 +- Extension/Core/ChoiceList/ObjectChoiceList.php | 2 +- .../DataTransformer/ChoiceToBooleanArrayTransformer.php | 2 +- .../Core/DataTransformer/ChoiceToValueTransformer.php | 2 +- .../DataTransformer/ChoicesToBooleanArrayTransformer.php | 2 +- Extension/Validator/ViolationMapper/ViolationPath.php | 8 ++++---- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Extension/Core/ChoiceList/ChoiceList.php b/Extension/Core/ChoiceList/ChoiceList.php index 02341377a3..d8f2a16561 100644 --- a/Extension/Core/ChoiceList/ChoiceList.php +++ b/Extension/Core/ChoiceList/ChoiceList.php @@ -345,13 +345,13 @@ protected function addChoice(array &$bucketForPreferred, array &$bucketForRemain $index = $this->createIndex($choice); if ('' === $index || null === $index || !FormConfigBuilder::isValidName((string) $index)) { - throw new InvalidConfigurationException('The index "'.$index.'" created by the choice list is invalid. It should be a valid, non-empty Form name.'); + throw new InvalidConfigurationException(sprintf('The index "%s" created by the choice list is invalid. It should be a valid, non-empty Form name.', $index)); } $value = $this->createValue($choice); if (!is_string($value)) { - throw new InvalidConfigurationException('The value created by the choice list is of type "'.gettype($value).'", but should be a string.'); + throw new InvalidConfigurationException(sprintf('The value created by the choice list is of type "%s", but should be a string.', gettype($value))); } $view = new ChoiceView($choice, $value, $label); diff --git a/Extension/Core/ChoiceList/LazyChoiceList.php b/Extension/Core/ChoiceList/LazyChoiceList.php index c48b83bed8..75742a2d9c 100644 --- a/Extension/Core/ChoiceList/LazyChoiceList.php +++ b/Extension/Core/ChoiceList/LazyChoiceList.php @@ -141,7 +141,7 @@ private function load() $choiceList = $this->loadChoiceList(); if (!$choiceList instanceof ChoiceListInterface) { - throw new Exception('loadChoiceList() should return a ChoiceListInterface instance. Got '.gettype($choiceList)); + throw new Exception(sprintf('loadChoiceList() should return a ChoiceListInterface instance. Got %s', gettype($choiceList))); } $this->choiceList = $choiceList; diff --git a/Extension/Core/ChoiceList/ObjectChoiceList.php b/Extension/Core/ChoiceList/ObjectChoiceList.php index 603db4603a..6c3be2c4d1 100644 --- a/Extension/Core/ChoiceList/ObjectChoiceList.php +++ b/Extension/Core/ChoiceList/ObjectChoiceList.php @@ -176,7 +176,7 @@ private function extractLabels($choices, array &$labels) } elseif (method_exists($choice, '__toString')) { $labels[$i] = (string) $choice; } else { - throw new StringCastException('A "__toString()" method was not found on the objects of type "'.get_class($choice).'" passed to the choice field. To read a custom getter instead, set the argument $labelPath to the desired property path.'); + throw new StringCastException(sprintf('A "__toString()" method was not found on the objects of type "%s" passed to the choice field. To read a custom getter instead, set the argument $labelPath to the desired property path.', get_class($choice))); } } } diff --git a/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php b/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php index 3fb9f13539..59fe9dbcea 100644 --- a/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php +++ b/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php @@ -98,7 +98,7 @@ public function reverseTransform($values) if (isset($choices[$i])) { return $choices[$i] === '' ? null : $choices[$i]; } else { - throw new TransformationFailedException('The choice "'.$i.'" does not exist'); + throw new TransformationFailedException(sprintf('The choice "%s" does not exist', $i)); } } } diff --git a/Extension/Core/DataTransformer/ChoiceToValueTransformer.php b/Extension/Core/DataTransformer/ChoiceToValueTransformer.php index 6aeb7ea256..c769bd1570 100644 --- a/Extension/Core/DataTransformer/ChoiceToValueTransformer.php +++ b/Extension/Core/DataTransformer/ChoiceToValueTransformer.php @@ -53,7 +53,7 @@ public function reverseTransform($value) $choices = $this->choiceList->getChoicesForValues(array($value)); if (1 !== count($choices)) { - throw new TransformationFailedException('The choice "'.$value.'" does not exist or is not unique'); + throw new TransformationFailedException(sprintf('The choice "%s" does not exist or is not unique', $value)); } $choice = current($choices); diff --git a/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php b/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php index 8ef776563f..42d3e982a1 100644 --- a/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php +++ b/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php @@ -109,7 +109,7 @@ public function reverseTransform($values) } if (count($unknown) > 0) { - throw new TransformationFailedException('The choices "'.implode('", "', $unknown).'" were not found'); + throw new TransformationFailedException(sprintf('The choices "%s" were not found', implode('", "', $unknown))); } return $result; diff --git a/Extension/Validator/ViolationMapper/ViolationPath.php b/Extension/Validator/ViolationMapper/ViolationPath.php index 2ee85c276a..6035f66c8e 100644 --- a/Extension/Validator/ViolationMapper/ViolationPath.php +++ b/Extension/Validator/ViolationMapper/ViolationPath.php @@ -155,7 +155,7 @@ public function getElements() public function getElement($index) { if (!isset($this->elements[$index])) { - throw new \OutOfBoundsException('The index '.$index.' is not within the violation path'); + throw new \OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); } return $this->elements[$index]; @@ -167,7 +167,7 @@ public function getElement($index) public function isProperty($index) { if (!isset($this->isIndex[$index])) { - throw new \OutOfBoundsException('The index '.$index.' is not within the violation path'); + throw new \OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); } return !$this->isIndex[$index]; @@ -179,7 +179,7 @@ public function isProperty($index) public function isIndex($index) { if (!isset($this->isIndex[$index])) { - throw new \OutOfBoundsException('The index '.$index.' is not within the violation path'); + throw new \OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); } return $this->isIndex[$index]; @@ -206,7 +206,7 @@ public function isIndex($index) public function mapsForm($index) { if (!isset($this->mapsForm[$index])) { - throw new \OutOfBoundsException('The index '.$index.' is not within the violation path'); + throw new \OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); } return $this->mapsForm[$index]; From 3c1bc9d9a146b2828effcf24946d25130f6e1ebf Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Mon, 31 Dec 2012 15:29:36 +0100 Subject: [PATCH 090/447] [Form] Implemented support for buttons --- Button.php | 412 +++++++++ ButtonBuilder.php | 823 ++++++++++++++++++ ButtonTypeInterface.php | 21 + ClickableInterface.php | 27 + Extension/Core/CoreExtension.php | 3 + Extension/Core/Type/BaseType.php | 123 +++ Extension/Core/Type/ButtonType.php | 38 + Extension/Core/Type/FormType.php | 91 +- Extension/Core/Type/ResetType.php | 39 + Extension/Core/Type/SubmitType.php | 46 + .../Type/FormTypeValidatorExtension.php | 20 +- FormInterface.php | 4 +- ResolvedFormType.php | 43 +- SubmitButton.php | 51 ++ SubmitButtonBuilder.php | 30 + SubmitButtonTypeInterface.php | 21 + Tests/AbstractDivLayoutTest.php | 16 + Tests/AbstractLayoutTest.php | 34 + Tests/AbstractTableLayoutTest.php | 19 + Tests/Extension/Core/Type/BaseTypeTest.php | 129 +++ Tests/Extension/Core/Type/ButtonTypeTest.php | 28 + Tests/Extension/Core/Type/FormTypeTest.php | 122 +-- Tests/Extension/Core/Type/SubmitTypeTest.php | 54 ++ 23 files changed, 1993 insertions(+), 201 deletions(-) create mode 100644 Button.php create mode 100644 ButtonBuilder.php create mode 100644 ButtonTypeInterface.php create mode 100644 ClickableInterface.php create mode 100644 Extension/Core/Type/BaseType.php create mode 100644 Extension/Core/Type/ButtonType.php create mode 100644 Extension/Core/Type/ResetType.php create mode 100644 Extension/Core/Type/SubmitType.php create mode 100644 SubmitButton.php create mode 100644 SubmitButtonBuilder.php create mode 100644 SubmitButtonTypeInterface.php create mode 100644 Tests/Extension/Core/Type/BaseTypeTest.php create mode 100644 Tests/Extension/Core/Type/ButtonTypeTest.php create mode 100644 Tests/Extension/Core/Type/SubmitTypeTest.php diff --git a/Button.php b/Button.php new file mode 100644 index 0000000000..b1b0b00d65 --- /dev/null +++ b/Button.php @@ -0,0 +1,412 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form; + +use Symfony\Component\Form\Exception\AlreadyBoundException; + +/** + * Default implementation of {@link ButtonInterface}. + * + * @author Bernhard Schussek + */ +class Button implements \IteratorAggregate, FormInterface +{ + /** + * @var FormInterface + */ + private $parent; + + /** + * @var FormConfigInterface + */ + private $config; + + /** + * @var Boolean + */ + private $bound = false; + + /** + * Creates a new button from a form configuration. + * + * @param FormConfigInterface $config The button's configuration. + */ + public function __construct(FormConfigInterface $config) + { + $this->config = $config; + } + + /** + * Unsupported method. + * + * @param mixed $offset + * + * @return Boolean Always returns false. + */ + public function offsetExists($offset) + { + return false; + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param mixed $offset + * + * @throws \BadMethodCallException + */ + public function offsetGet($offset) + { + throw new \BadMethodCallException('Buttons cannot have children.'); + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param mixed $offset + * @param mixed $value + * + * @throws \BadMethodCallException + */ + public function offsetSet($offset, $value) + { + throw new \BadMethodCallException('Buttons cannot have children.'); + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param mixed $offset + * + * @throws \BadMethodCallException + */ + public function offsetUnset($offset) + { + throw new \BadMethodCallException('Buttons cannot have children.'); + } + + /** + * {@inheritdoc} + */ + public function setParent(FormInterface $parent = null) + { + $this->parent = $parent; + } + + /** + * {@inheritdoc} + */ + public function getParent() + { + return $this->parent; + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param int|string|FormInterface $child + * @param null $type + * @param array $options + * + * @throws \BadMethodCallException + */ + public function add($child, $type = null, array $options = array()) + { + throw new \BadMethodCallException('Buttons cannot have children.'); + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param string $name + * + * @throws \BadMethodCallException + */ + public function get($name) + { + throw new \BadMethodCallException('Buttons cannot have children.'); + } + + /** + * Unsupported method. + * + * @param string $name + * + * @return Boolean Always returns false. + */ + public function has($name) + { + return false; + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param string $name + * + * @throws \BadMethodCallException + */ + public function remove($name) + { + throw new \BadMethodCallException('Buttons cannot have children.'); + } + + /** + * {@inheritdoc} + */ + public function all() + { + return array(); + } + + /** + * {@inheritdoc} + */ + public function getErrors() + { + return array(); + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param string $modelData + * + * @throws \BadMethodCallException + */ + public function setData($modelData) + { + throw new \BadMethodCallException('Buttons cannot have data.'); + } + + /** + * Unsupported method. + * + * @return null Always returns null. + */ + public function getData() + { + return null; + } + + /** + * Unsupported method. + * + * @return null Always returns null. + */ + public function getNormData() + { + return null; + } + + /** + * Unsupported method. + * + * @return null Always returns null. + */ + public function getViewData() + { + return null; + } + + /** + * Unsupported method. + * + * @return array Always returns an empty array. + */ + public function getExtraData() + { + return array(); + } + + /** + * Returns the button's configuration. + * + * @return FormConfigInterface The configuration. + */ + public function getConfig() + { + return $this->config; + } + + /** + * Returns whether the button is submitted. + * + * @return Boolean true if the button was submitted. + */ + public function isBound() + { + return $this->bound; + } + + /** + * Returns the name by which the button is identified in forms. + * + * @return string The name of the button. + */ + public function getName() + { + return $this->config->getName(); + } + + /** + * Unsupported method. + * + * @return null Always returns null. + */ + public function getPropertyPath() + { + return null; + } + + /** + * Unsupported method. + * + * @param FormError $error + * + * @throws \BadMethodCallException + */ + public function addError(FormError $error) + { + throw new \BadMethodCallException('Buttons cannot have errors.'); + } + + /** + * Unsupported method. + * + * @return Boolean Always returns true. + */ + public function isValid() + { + return true; + } + + /** + * Unsupported method. + * + * @return Boolean Always returns false. + */ + public function isRequired() + { + return false; + } + + /** + * {@inheritdoc} + */ + public function isDisabled() + { + return $this->config->getDisabled(); + } + + /** + * Unsupported method. + * + * @return Boolean Always returns true. + */ + public function isEmpty() + { + return true; + } + + /** + * Unsupported method. + * + * @return Boolean Always returns true. + */ + public function isSynchronized() + { + return true; + } + + /** + * Binds data to the button. + * + * @param null|string $submittedData The data + * + * @return Button The button instance + * + * @throws Exception\AlreadyBoundException If the form has already been bound. + */ + public function bind($submittedData) + { + if ($this->bound) { + throw new AlreadyBoundException('A form can only be bound once'); + } + + $this->bound = true; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getRoot() + { + return $this->parent ? $this->parent->getRoot() : $this; + } + + /** + * {@inheritdoc} + */ + public function isRoot() + { + return null === $this->parent; + } + + /** + * {@inheritdoc} + */ + public function createView(FormView $parent = null) + { + if (null === $parent && $this->parent) { + $parent = $this->parent->createView(); + } + + return $this->config->getType()->createView($this, $parent); + } + + /** + * Unsupported method. + * + * @return integer Always returns 0. + */ + public function count() + { + return 0; + } + + /** + * Unsupported method. + * + * @return \EmptyIterator Always returns an empty iterator. + */ + public function getIterator() + { + return new \EmptyIterator(); + } +} diff --git a/ButtonBuilder.php b/ButtonBuilder.php new file mode 100644 index 0000000000..ce30b0ab26 --- /dev/null +++ b/ButtonBuilder.php @@ -0,0 +1,823 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form; + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\Form\Exception\FormException; + +/** + * A builder for {@link Button} instances. + * + * @author Bernhard Schussek + */ +class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface +{ + /** + * @var Boolean + */ + protected $locked = false; + + /** + * @var Boolean + */ + private $disabled; + + /** + * @var ResolvedFormTypeInterface + */ + private $type; + + /** + * @var string + */ + private $name; + + /** + * @var array + */ + private $attributes = array(); + + /** + * @var array + */ + private $options; + + /** + * Creates a new button builder. + * + * @param string $name The name of the button. + * @param array $options The button's options. + * + * @throws FormException If the name is empty. + */ + public function __construct($name, array $options) + { + if (empty($name) && 0 != $name) { + throw new FormException('Buttons cannot have empty names.'); + } + + $this->name = (string) $name; + $this->options = $options; + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param string|integer|FormBuilderInterface $child + * @param string|FormTypeInterface $type + * @param array $options + * + * @throws \BadMethodCallException + */ + public function add($child, $type = null, array $options = array()) + { + throw new \BadMethodCallException('Buttons cannot have children.'); + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param string $name + * @param string|FormTypeInterface $type + * @param array $options + * + * @throws \BadMethodCallException + */ + public function create($name, $type = null, array $options = array()) + { + throw new \BadMethodCallException('Buttons cannot have children.'); + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param string $name + * + * @throws \BadMethodCallException + */ + public function get($name) + { + throw new \BadMethodCallException('Buttons cannot have children.'); + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param string $name + * + * @throws \BadMethodCallException + */ + public function remove($name) + { + throw new \BadMethodCallException('Buttons cannot have children.'); + } + + /** + * Unsupported method. + * + * @param string $name + * + * @return Boolean Always returns false. + */ + public function has($name) + { + return false; + } + + /** + * Returns the children. + * + * @return array Always returns an empty array. + */ + public function all() + { + return array(); + } + + /** + * Creates the button. + * + * @return Button The button + */ + public function getForm() + { + return new Button($this->getFormConfig()); + } + + /** + * Unsupported method. + * + * Does nothing. + * + * @param FormBuilderInterface $parent The parent builder + * + * @deprecated Deprecated since version 2.2, to be removed in 2.3. You + * should not rely on the parent of a builder, because it is + * likely that the parent is only set after turning the builder + * into a form. + */ + public function setParent(FormBuilderInterface $parent = null) + { + } + + /** + * Unsupported method. + * + * @return null Always returns null. + * + * @deprecated Deprecated since version 2.2, to be removed in 2.3. You + * should not rely on the parent of a builder, because it is + * likely that the parent is only set after turning the builder + * into a form. + */ + public function getParent() + { + return null; + } + + /** + * Unsupported method. + * + * @return Boolean Always returns false. + * + * @deprecated Deprecated since version 2.2, to be removed in 2.3. You + * should not rely on the parent of a builder, because it is + * likely that the parent is only set after turning the builder + * into a form. + */ + public function hasParent() + { + return false; + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param string $eventName + * @param callable $listener + * @param integer $priority + * + * @throws \BadMethodCallException + */ + public function addEventListener($eventName, $listener, $priority = 0) + { + throw new \BadMethodCallException('Buttons do not support event listeners.'); + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param EventSubscriberInterface $subscriber + * + * @throws \BadMethodCallException + */ + public function addEventSubscriber(EventSubscriberInterface $subscriber) + { + throw new \BadMethodCallException('Buttons do not support event subscribers.'); + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param FormValidatorInterface $validator + * + * @throws \BadMethodCallException + * + * @deprecated Deprecated since version 2.1, to be removed in 2.3. + */ + public function addValidator(FormValidatorInterface $validator) + { + throw new \BadMethodCallException('Buttons do not support validators.'); + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param DataTransformerInterface $viewTransformer + * @param Boolean $forcePrepend + * + * @throws \BadMethodCallException + */ + public function addViewTransformer(DataTransformerInterface $viewTransformer, $forcePrepend = false) + { + throw new \BadMethodCallException('Buttons do not support data transformers.'); + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @throws \BadMethodCallException + */ + public function resetViewTransformers() + { + throw new \BadMethodCallException('Buttons do not support data transformers.'); + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param DataTransformerInterface $modelTransformer + * @param Boolean $forceAppend + * + * @throws \BadMethodCallException + */ + public function addModelTransformer(DataTransformerInterface $modelTransformer, $forceAppend = false) + { + throw new \BadMethodCallException('Buttons do not support data transformers.'); + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @throws \BadMethodCallException + */ + public function resetModelTransformers() + { + throw new \BadMethodCallException('Buttons do not support data transformers.'); + } + + /** + * {@inheritdoc} + */ + public function setAttribute($name, $value) + { + $this->attributes[$name] = $value; + } + + /** + * {@inheritdoc} + */ + public function setAttributes(array $attributes) + { + $this->attributes = $attributes; + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param DataMapperInterface $dataMapper + * + * @throws \BadMethodCallException + */ + public function setDataMapper(DataMapperInterface $dataMapper = null) + { + throw new \BadMethodCallException('Buttons do not support data mappers.'); + } + + /** + * Set whether the button is disabled. + * + * @param Boolean $disabled Whether the button is disabled + * + * @return ButtonBuilder The button builder. + */ + public function setDisabled($disabled) + { + $this->disabled = $disabled; + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param mixed $emptyData + * + * @throws \BadMethodCallException + */ + public function setEmptyData($emptyData) + { + throw new \BadMethodCallException('Buttons do not support empty data.'); + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param Boolean $errorBubbling + * + * @throws \BadMethodCallException + */ + public function setErrorBubbling($errorBubbling) + { + throw new \BadMethodCallException('Buttons do not support error bubbling.'); + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param Boolean $required + * + * @throws \BadMethodCallException + */ + public function setRequired($required) + { + throw new \BadMethodCallException('Buttons cannot be required.'); + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param null $propertyPath + * + * @throws \BadMethodCallException + */ + public function setPropertyPath($propertyPath) + { + throw new \BadMethodCallException('Buttons do not support property paths.'); + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param Boolean $mapped + * + * @throws \BadMethodCallException + */ + public function setMapped($mapped) + { + throw new \BadMethodCallException('Buttons do not support data mapping.'); + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param Boolean $byReference + * + * @throws \BadMethodCallException + */ + public function setByReference($byReference) + { + throw new \BadMethodCallException('Buttons do not support data mapping.'); + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param Boolean $virtual + * + * @throws \BadMethodCallException + */ + public function setVirtual($virtual) + { + throw new \BadMethodCallException('Buttons cannot be virtual.'); + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param Boolean $compound + * + * @throws \BadMethodCallException + */ + public function setCompound($compound) + { + throw new \BadMethodCallException('Buttons cannot be compound.'); + } + + /** + * Sets the type of the button. + * + * @param ResolvedFormTypeInterface $type The type of the button. + * + * @return ButtonBuilder The button builder. + */ + public function setType(ResolvedFormTypeInterface $type) + { + $this->type = $type; + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param array $data + * + * @throws \BadMethodCallException + */ + public function setData($data) + { + throw new \BadMethodCallException('Buttons do not support data.'); + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param Boolean $locked + * + * @throws \BadMethodCallException + */ + public function setDataLocked($locked) + { + throw new \BadMethodCallException('Buttons do not support data locking.'); + } + + /** + * Unsupported method. + * + * This method should not be invoked. + * + * @param FormFactoryInterface $formFactory + * + * @return void + * + * @throws \BadMethodCallException + */ + public function setFormFactory(FormFactoryInterface $formFactory) + { + throw new \BadMethodCallException('Buttons do not support form factories.'); + } + + /** + * Builds and returns the button configuration. + * + * @return FormConfigInterface + */ + public function getFormConfig() + { + // This method should be idempotent, so clone the builder + $config = clone $this; + $config->locked = true; + + return $config; + } + + /** + * Unsupported method. + * + * @return null Always returns null. + */ + public function getEventDispatcher() + { + return null; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return $this->name; + } + + /** + * Unsupported method. + * + * @return null Always returns null. + */ + public function getPropertyPath() + { + return null; + } + + /** + * Unsupported method. + * + * @return Boolean Always returns false. + */ + public function getMapped() + { + return false; + } + + /** + * Unsupported method. + * + * @return Boolean Always returns false. + */ + public function getByReference() + { + return false; + } + + /** + * Unsupported method. + * + * @return Boolean Always returns false. + */ + public function getVirtual() + { + return false; + } + + /** + * Unsupported method. + * + * @return Boolean Always returns false. + */ + public function getCompound() + { + return false; + } + + /** + * Returns the form type used to construct the button. + * + * @return ResolvedFormTypeInterface The button's type. + */ + public function getType() + { + return $this->type; + } + + /** + * Unsupported method. + * + * @return array Always returns an empty array. + */ + public function getViewTransformers() + { + return array(); + } + + /** + * Unsupported method. + * + * @return array Always returns an empty array. + */ + public function getModelTransformers() + { + return array(); + } + + /** + * Unsupported method. + * + * @return null Always returns null. + */ + public function getDataMapper() + { + return null; + } + + /** + * Unsupported method. + * + * @return array Always returns null. + * + * @deprecated Deprecated since version 2.1, to be removed in 2.3. + */ + public function getValidators() + { + return array(); + } + + /** + * Unsupported method. + * + * @return Boolean Always returns false. + */ + public function getRequired() + { + return false; + } + + /** + * Returns whether the button is disabled. + * + * @return Boolean Whether the button is disabled. + */ + public function getDisabled() + { + return $this->disabled; + } + + /** + * Unsupported method. + * + * @return Boolean Always returns false. + */ + public function getErrorBubbling() + { + return false; + } + + /** + * Unsupported method. + * + * @return null Always returns null. + */ + public function getEmptyData() + { + return null; + } + + /** + * Returns additional attributes of the button. + * + * @return array An array of key-value combinations. + */ + public function getAttributes() + { + return $this->attributes; + } + + /** + * Returns whether the attribute with the given name exists. + * + * @param string $name The attribute name. + * + * @return Boolean Whether the attribute exists. + */ + public function hasAttribute($name) + { + return isset($this->attributes[$name]); + } + + /** + * Returns the value of the given attribute. + * + * @param string $name The attribute name. + * @param mixed $default The value returned if the attribute does not exist. + * + * @return mixed The attribute value. + */ + public function getAttribute($name, $default = null) + { + return isset($this->attributes[$name]) ? $this->attributes[$name] : $default; + } + + /** + * Unsupported method. + * + * @return null Always returns null. + */ + public function getData() + { + return null; + } + + /** + * Unsupported method. + * + * @return null Always returns null. + */ + public function getDataClass() + { + return null; + } + + /** + * Unsupported method. + * + * @return Boolean Always returns false. + */ + public function getDataLocked() + { + return false; + } + + /** + * Unsupported method. + * + * @return null Always returns null. + */ + public function getFormFactory() + { + return null; + } + + /** + * Returns all options passed during the construction of the button. + * + * @return array The passed options. + */ + public function getOptions() + { + return $this->options; + } + + /** + * Returns whether a specific option exists. + * + * @param string $name The option name, + * + * @return Boolean Whether the option exists. + */ + public function hasOption($name) + { + return isset($this->options[$name]); + } + + /** + * Returns the value of a specific option. + * + * @param string $name The option name. + * @param mixed $default The value returned if the option does not exist. + * + * @return mixed The option value. + */ + public function getOption($name, $default = null) + { + return isset($this->options[$name]) ? $this->options[$name] : $default; + } + + /** + * Unsupported method. + * + * @return integer Always returns 0. + */ + public function count() + { + return 0; + } + + /** + * Unsupported method. + * + * @return \EmptyIterator Always returns an empty iterator. + */ + public function getIterator() + { + return new \EmptyIterator(); + } +} diff --git a/ButtonTypeInterface.php b/ButtonTypeInterface.php new file mode 100644 index 0000000000..dd5117c4da --- /dev/null +++ b/ButtonTypeInterface.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form; + +/** + * A type that should be converted into a {@link Button} instance. + * + * @author Bernhard Schussek + */ +interface ButtonTypeInterface extends FormTypeInterface +{ +} diff --git a/ClickableInterface.php b/ClickableInterface.php new file mode 100644 index 0000000000..893f02df0a --- /dev/null +++ b/ClickableInterface.php @@ -0,0 +1,27 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form; + +/** + * A clickable form element. + * + * @author Bernhard Schussek + */ +interface ClickableInterface +{ + /** + * Returns whether this element was clicked. + * + * @return Boolean Whether this element was clicked. + */ + public function isClicked(); +} diff --git a/Extension/Core/CoreExtension.php b/Extension/Core/CoreExtension.php index ff7a1a3e0e..3934d38261 100644 --- a/Extension/Core/CoreExtension.php +++ b/Extension/Core/CoreExtension.php @@ -50,6 +50,9 @@ protected function loadTypes() new Type\TimezoneType(), new Type\UrlType(), new Type\FileType(), + new Type\ButtonType(), + new Type\SubmitType(), + new Type\ResetType(), ); } } diff --git a/Extension/Core/Type/BaseType.php b/Extension/Core/Type/BaseType.php new file mode 100644 index 0000000000..ca47a7bc2f --- /dev/null +++ b/Extension/Core/Type/BaseType.php @@ -0,0 +1,123 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Extension\Core\Type; + +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\FormInterface; +use Symfony\Component\Form\FormView; +use Symfony\Component\OptionsResolver\OptionsResolverInterface; + +/** + * Encapsulates common logic of {@link FormType} and {@link ButtonType}. + * + * This type does not appear in the form's type inheritance chain and as such + * cannot be extended (via {@link FormTypeExtension}s) nor themed. + * + * @author Bernhard Schussek + */ +abstract class BaseType extends AbstractType +{ + /** + * {@inheritdoc} + */ + public function buildForm(FormBuilderInterface $builder, array $options) + { + $builder->setDisabled($options['disabled']); + } + + /** + * {@inheritdoc} + */ + public function buildView(FormView $view, FormInterface $form, array $options) + { + /* @var \Symfony\Component\Form\ClickableInterface $form */ + + $name = $form->getName(); + $blockName = $options['block_name'] ?: $form->getName(); + $translationDomain = $options['translation_domain']; + + if ($view->parent) { + if ('' !== ($parentFullName = $view->parent->vars['full_name'])) { + $id = sprintf('%s_%s', $view->parent->vars['id'], $name); + $fullName = sprintf('%s[%s]', $parentFullName, $name); + $uniqueBlockPrefix = sprintf('%s_%s', $view->parent->vars['unique_block_prefix'], $blockName); + } else { + $id = $name; + $fullName = $name; + $uniqueBlockPrefix = '_'.$blockName; + } + + if (!$translationDomain) { + $translationDomain = $view->parent->vars['translation_domain']; + } + } else { + $id = $name; + $fullName = $name; + $uniqueBlockPrefix = '_'.$blockName; + + // Strip leading underscores and digits. These are allowed in + // form names, but not in HTML4 ID attributes. + // http://www.w3.org/TR/html401/struct/global.html#adef-id + $id = ltrim($id, '_0123456789'); + } + + $blockPrefixes = array(); + for ($type = $form->getConfig()->getType(); null !== $type; $type = $type->getParent()) { + array_unshift($blockPrefixes, $type->getName()); + } + $blockPrefixes[] = $uniqueBlockPrefix; + + if (!$translationDomain) { + $translationDomain = 'messages'; + } + + $view->vars = array_replace($view->vars, array( + 'form' => $view, + 'id' => $id, + 'name' => $name, + 'full_name' => $fullName, + 'disabled' => $form->isDisabled(), + 'label' => $options['label'], + 'multipart' => false, + 'attr' => $options['attr'], + 'block_prefixes' => $blockPrefixes, + 'unique_block_prefix' => $uniqueBlockPrefix, + 'translation_domain' => $translationDomain, + // Using the block name here speeds up performance in collection + // forms, where each entry has the same full block name. + // Including the type is important too, because if rows of a + // collection form have different types (dynamically), they should + // be rendered differently. + // https://github.com/symfony/symfony/issues/5038 + 'cache_key' => $uniqueBlockPrefix.'_'.$form->getConfig()->getType()->getName(), + )); + } + + /** + * {@inheritdoc} + */ + public function setDefaultOptions(OptionsResolverInterface $resolver) + { + $resolver->setDefaults(array( + 'block_name' => null, + 'disabled' => false, + 'label' => null, + 'attr' => array(), + 'translation_domain' => null, + )); + + $resolver->setAllowedTypes(array( + 'attr' => 'array', + )); + } +} diff --git a/Extension/Core/Type/ButtonType.php b/Extension/Core/Type/ButtonType.php new file mode 100644 index 0000000000..3569963bc4 --- /dev/null +++ b/Extension/Core/Type/ButtonType.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Extension\Core\Type; + +use Symfony\Component\Form\ButtonTypeInterface; + +/** + * A form button. + * + * @author Bernhard Schussek + */ +class ButtonType extends BaseType implements ButtonTypeInterface +{ + /** + * {@inheritdoc} + */ + public function getParent() + { + return null; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'button'; + } +} diff --git a/Extension/Core/Type/FormType.php b/Extension/Core/Type/FormType.php index 16e7bbc7a0..bd01f8f040 100644 --- a/Extension/Core/Type/FormType.php +++ b/Extension/Core/Type/FormType.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Form\Extension\Core\Type; -use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; @@ -23,7 +22,7 @@ use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; -class FormType extends AbstractType +class FormType extends BaseType { /** * @var PropertyAccessorInterface @@ -40,9 +39,10 @@ public function __construct(PropertyAccessorInterface $propertyAccessor = null) */ public function buildForm(FormBuilderInterface $builder, array $options) { + parent::buildForm($builder, $options); + $builder ->setRequired($options['required']) - ->setDisabled($options['disabled']) ->setErrorBubbling($options['error_bubbling']) ->setEmptyData($options['empty_data']) ->setPropertyPath($options['property_path']) @@ -65,85 +65,34 @@ public function buildForm(FormBuilderInterface $builder, array $options) */ public function buildView(FormView $view, FormInterface $form, array $options) { + parent::buildView($view, $form, $options); + $name = $form->getName(); - $blockName = $options['block_name'] ?: $form->getName(); $readOnly = $options['read_only']; - $translationDomain = $options['translation_domain']; if ($view->parent) { if ('' === $name) { throw new Exception('Form node with empty name can be used only as root form node.'); } - if ('' !== ($parentFullName = $view->parent->vars['full_name'])) { - $id = sprintf('%s_%s', $view->parent->vars['id'], $name); - $fullName = sprintf('%s[%s]', $parentFullName, $name); - $uniqueBlockPrefix = sprintf('%s_%s', $view->parent->vars['unique_block_prefix'], $blockName); - } else { - $id = $name; - $fullName = $name; - $uniqueBlockPrefix = '_'.$blockName; - } - // Complex fields are read-only if they themselves or their parents are. if (!$readOnly) { $readOnly = $view->parent->vars['read_only']; } - - if (!$translationDomain) { - $translationDomain = $view->parent->vars['translation_domain']; - } - } else { - $id = $name; - $fullName = $name; - $uniqueBlockPrefix = '_'.$blockName; - - // Strip leading underscores and digits. These are allowed in - // form names, but not in HTML4 ID attributes. - // http://www.w3.org/TR/html401/struct/global.html#adef-id - $id = ltrim($id, '_0123456789'); - } - - $blockPrefixes = array(); - for ($type = $form->getConfig()->getType(); null !== $type; $type = $type->getParent()) { - array_unshift($blockPrefixes, $type->getName()); - } - $blockPrefixes[] = $uniqueBlockPrefix; - - if (!$translationDomain) { - $translationDomain = 'messages'; } $view->vars = array_replace($view->vars, array( - 'form' => $view, - 'id' => $id, - 'name' => $name, - 'full_name' => $fullName, - 'read_only' => $readOnly, - 'errors' => $form->getErrors(), - 'valid' => $form->isBound() ? $form->isValid() : true, - 'value' => $form->getViewData(), - 'data' => $form->getNormData(), - 'disabled' => $form->isDisabled(), - 'required' => $form->isRequired(), - 'max_length' => $options['max_length'], - 'pattern' => $options['pattern'], - 'size' => null, - 'label' => $options['label'], - 'multipart' => false, - 'attr' => $options['attr'], - 'label_attr' => $options['label_attr'], - 'compound' => $form->getConfig()->getCompound(), - 'block_prefixes' => $blockPrefixes, - 'unique_block_prefix' => $uniqueBlockPrefix, - 'translation_domain' => $translationDomain, - // Using the block name here speeds up performance in collection - // forms, where each entry has the same full block name. - // Including the type is important too, because if rows of a - // collection form have different types (dynamically), they should - // be rendered differently. - // https://github.com/symfony/symfony/issues/5038 - 'cache_key' => $uniqueBlockPrefix.'_'.$form->getConfig()->getType()->getName(), + 'read_only' => $readOnly, + 'errors' => $form->getErrors(), + 'valid' => $form->isBound() ? $form->isValid() : true, + 'value' => $form->getViewData(), + 'data' => $form->getNormData(), + 'required' => $form->isRequired(), + 'max_length' => $options['max_length'], + 'pattern' => $options['pattern'], + 'size' => null, + 'label_attr' => $options['label_attr'], + 'compound' => $form->getConfig()->getCompound(), )); } @@ -169,6 +118,8 @@ public function finishView(FormView $view, FormInterface $form, array $options) */ public function setDefaultOptions(OptionsResolverInterface $resolver) { + parent::setDefaultOptions($resolver); + // Derive "data_class" option from passed "data" object $dataClass = function (Options $options) { return isset($options['data']) && is_object($options['data']) ? get_class($options['data']) : null; @@ -202,29 +153,23 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) )); $resolver->setDefaults(array( - 'block_name' => null, 'data_class' => $dataClass, 'empty_data' => $emptyData, 'trim' => true, 'required' => true, 'read_only' => false, - 'disabled' => false, 'max_length' => null, 'pattern' => null, 'property_path' => null, 'mapped' => true, 'by_reference' => true, 'error_bubbling' => $errorBubbling, - 'label' => null, - 'attr' => array(), 'label_attr' => array(), 'virtual' => false, 'compound' => true, - 'translation_domain' => null, )); $resolver->setAllowedTypes(array( - 'attr' => 'array', 'label_attr' => 'array', )); } diff --git a/Extension/Core/Type/ResetType.php b/Extension/Core/Type/ResetType.php new file mode 100644 index 0000000000..cf55f7c591 --- /dev/null +++ b/Extension/Core/Type/ResetType.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Extension\Core\Type; + +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\ButtonTypeInterface; + +/** + * A reset button. + * + * @author Bernhard Schussek + */ +class ResetType extends AbstractType implements ButtonTypeInterface +{ + /** + * {@inheritdoc} + */ + public function getParent() + { + return 'button'; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'reset'; + } +} diff --git a/Extension/Core/Type/SubmitType.php b/Extension/Core/Type/SubmitType.php new file mode 100644 index 0000000000..6d160b9692 --- /dev/null +++ b/Extension/Core/Type/SubmitType.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Extension\Core\Type; + +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\FormInterface; +use Symfony\Component\Form\FormView; +use Symfony\Component\Form\SubmitButtonTypeInterface; + +/** + * A submit button. + * + * @author Bernhard Schussek + */ +class SubmitType extends AbstractType implements SubmitButtonTypeInterface +{ + public function buildView(FormView $view, FormInterface $form, array $options) + { + $view->vars['clicked'] = $form->isClicked(); + } + + /** + * {@inheritdoc} + */ + public function getParent() + { + return 'button'; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'submit'; + } +} diff --git a/Extension/Validator/Type/FormTypeValidatorExtension.php b/Extension/Validator/Type/FormTypeValidatorExtension.php index 6b9ac4e4f0..19c888e200 100644 --- a/Extension/Validator/Type/FormTypeValidatorExtension.php +++ b/Extension/Validator/Type/FormTypeValidatorExtension.php @@ -53,17 +53,9 @@ public function buildForm(FormBuilderInterface $builder, array $options) */ public function setDefaultOptions(OptionsResolverInterface $resolver) { - // Make sure that validation groups end up as null, closure or array - $validationGroupsNormalizer = function (Options $options, $groups) { - if (empty($groups)) { - return null; - } - - if (is_callable($groups)) { - return $groups; - } - - return (array) $groups; + // BC clause + $constraints = function (Options $options) { + return $options['validation_constraint']; }; // Constraint should always be converted to an array @@ -73,8 +65,9 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) $resolver->setDefaults(array( 'error_mapping' => array(), - 'validation_groups' => null, - 'constraints' => null, + // "validation_constraint" is deprecated. Use "constraints". + 'validation_constraint' => null, + 'constraints' => $constraints, 'cascade_validation' => false, 'invalid_message' => 'This value is not valid.', 'invalid_message_parameters' => array(), @@ -83,7 +76,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) )); $resolver->setNormalizers(array( - 'validation_groups' => $validationGroupsNormalizer, 'constraints' => $constraintsNormalizer, )); } diff --git a/FormInterface.php b/FormInterface.php index 94f6b3e29d..3e8fe525ec 100644 --- a/FormInterface.php +++ b/FormInterface.php @@ -150,9 +150,9 @@ public function getExtraData(); public function getConfig(); /** - * Returns whether the field is bound. + * Returns whether the form is submitted. * - * @return Boolean true if the form is bound to input values, false otherwise + * @return Boolean true if the form is submitted, false otherwise */ public function isBound(); diff --git a/ResolvedFormType.php b/ResolvedFormType.php index f2ef06c8b8..7203817b94 100644 --- a/ResolvedFormType.php +++ b/ResolvedFormType.php @@ -111,7 +111,7 @@ public function createBuilder(FormFactoryInterface $factory, $name, array $optio // Should be decoupled from the specific option at some point $dataClass = isset($options['data_class']) ? $options['data_class'] : null; - $builder = new FormBuilder($name, $dataClass, new EventDispatcher(), $factory, $options); + $builder = $this->newBuilder($name, $dataClass, $factory, $options); $builder->setType($this); $builder->setParent($parent); @@ -127,7 +127,7 @@ public function createView(FormInterface $form, FormView $parent = null) { $options = $form->getConfig()->getOptions(); - $view = new FormView($parent); + $view = $this->newView($parent); $this->buildView($view, $form, $options); @@ -243,4 +243,43 @@ public function getOptionsResolver() return $this->optionsResolver; } + + /** + * Creates a new builder instance. + * + * Override this method if you want to customize the builder class. + * + * @param string $name The name of the builder. + * @param string $dataClass The data class. + * @param FormFactoryInterface $factory The current form factory. + * @param array $options The builder options. + * + * @return FormBuilderInterface The new builder instance. + */ + protected function newBuilder($name, $dataClass, FormFactoryInterface $factory, array $options) + { + if ($this->innerType instanceof ButtonTypeInterface) { + return new ButtonBuilder($name, $options); + } + + if ($this->innerType instanceof SubmitButtonTypeInterface) { + return new SubmitButtonBuilder($name, $options); + } + + return new FormBuilder($name, $dataClass, new EventDispatcher(), $factory, $options); + } + + /** + * Creates a new view instance. + * + * Override this method if you want to customize the view class. + * + * @param FormView|null $parent The parent view, if available. + * + * @return FormView A new view instance. + */ + protected function newView(FormView $parent = null) + { + return new FormView($parent); + } } diff --git a/SubmitButton.php b/SubmitButton.php new file mode 100644 index 0000000000..01af5c2e72 --- /dev/null +++ b/SubmitButton.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form; + +/** + * A button that submits the form. + * + * @author Bernhard Schussek + */ +class SubmitButton extends Button implements ClickableInterface +{ + /** + * @var Boolean + */ + private $clicked = false; + + /** + * {@inheritdoc} + */ + public function isClicked() + { + return $this->clicked; + } + + /** + * Binds data to the button. + * + * @param null|string $submittedData The data + * + * @return SubmitButton The button instance + * + * @throws Exception\AlreadyBoundException If the form has already been bound. + */ + public function bind($submittedData) + { + parent::bind($submittedData); + + $this->clicked = null !== $submittedData; + + return $this; + } +} diff --git a/SubmitButtonBuilder.php b/SubmitButtonBuilder.php new file mode 100644 index 0000000000..088fb74819 --- /dev/null +++ b/SubmitButtonBuilder.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form; + +/** + * A builder for {@link SubmitButton} instances. + * + * @author Bernhard Schussek + */ +class SubmitButtonBuilder extends ButtonBuilder +{ + /** + * Creates the button. + * + * @return Button The button + */ + public function getForm() + { + return new SubmitButton($this->getFormConfig()); + } +} diff --git a/SubmitButtonTypeInterface.php b/SubmitButtonTypeInterface.php new file mode 100644 index 0000000000..f7ac13f7ec --- /dev/null +++ b/SubmitButtonTypeInterface.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form; + +/** + * A type that should be converted into a {@link SubmitButton} instance. + * + * @author Bernhard Schussek + */ +interface SubmitButtonTypeInterface extends FormTypeInterface +{ +} diff --git a/Tests/AbstractDivLayoutTest.php b/Tests/AbstractDivLayoutTest.php index 7fd743006e..391e81173e 100644 --- a/Tests/AbstractDivLayoutTest.php +++ b/Tests/AbstractDivLayoutTest.php @@ -82,6 +82,22 @@ public function testRepeatedRow() ); } + public function testButtonRow() + { + $form = $this->factory->createNamed('name', 'button'); + $view = $form->createView(); + $html = $this->renderRow($view); + + $this->assertMatchesXpath($html, +'/div + [ + ./button[@type="button"][@name="name"] + ] + [count(//label)=0] +' + ); + } + public function testRest() { $view = $this->factory->createNamedBuilder('name', 'form') diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index bf2c29e8e1..bad30f0679 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -1762,4 +1762,38 @@ public function testEmptyRootFormName() //input[@type="text"][@id="child"][@name="child"]' , 2); } + + public function testButton() + { + $form = $this->factory->createNamed('name', 'button'); + + $this->assertWidgetMatchesXpath($form->createView(), array(), + '/button[@type="button"][@name="name"]' + ); + } + + public function testButtonLabelIsEmpty() + { + $form = $this->factory->createNamed('name', 'button'); + + $this->assertSame('', $this->renderLabel($form->createView())); + } + + public function testSubmit() + { + $form = $this->factory->createNamed('name', 'submit'); + + $this->assertWidgetMatchesXpath($form->createView(), array(), + '/button[@type="submit"][@name="name"]' + ); + } + + public function testReset() + { + $form = $this->factory->createNamed('name', 'reset'); + + $this->assertWidgetMatchesXpath($form->createView(), array(), + '/button[@type="reset"][@name="name"]' + ); + } } diff --git a/Tests/AbstractTableLayoutTest.php b/Tests/AbstractTableLayoutTest.php index e0f62c4ab1..28fdba2dda 100644 --- a/Tests/AbstractTableLayoutTest.php +++ b/Tests/AbstractTableLayoutTest.php @@ -125,6 +125,25 @@ public function testRepeatedRowWithErrors() ); } + public function testButtonRow() + { + $form = $this->factory->createNamed('name', 'button'); + $view = $form->createView(); + $html = $this->renderRow($view); + + $this->assertMatchesXpath($html, +'/tr + [ + ./td + [.=""] + /following-sibling::td + [./button[@type="button"][@name="name"]] + ] + [count(//label)=0] +' + ); + } + public function testRest() { $view = $this->factory->createNamedBuilder('name', 'form') diff --git a/Tests/Extension/Core/Type/BaseTypeTest.php b/Tests/Extension/Core/Type/BaseTypeTest.php new file mode 100644 index 0000000000..d56355c644 --- /dev/null +++ b/Tests/Extension/Core/Type/BaseTypeTest.php @@ -0,0 +1,129 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +/** + * @author Bernhard Schussek + */ +abstract class BaseTypeTest extends TypeTestCase +{ + public function testPassDisabledAsOption() + { + $form = $this->factory->create($this->getTestedType(), null, array('disabled' => true)); + + $this->assertTrue($form->isDisabled()); + } + + public function testPassIdAndNameToView() + { + $form = $this->factory->createNamed('name', $this->getTestedType()); + $view = $form->createView(); + + $this->assertEquals('name', $view->vars['id']); + $this->assertEquals('name', $view->vars['name']); + $this->assertEquals('name', $view->vars['full_name']); + } + + public function testStripLeadingUnderscoresAndDigitsFromId() + { + $form = $this->factory->createNamed('_09name', $this->getTestedType()); + $view = $form->createView(); + + $this->assertEquals('name', $view->vars['id']); + $this->assertEquals('_09name', $view->vars['name']); + $this->assertEquals('_09name', $view->vars['full_name']); + } + + public function testPassIdAndNameToViewWithParent() + { + $parent = $this->factory->createNamed('parent', 'form'); + $parent->add($this->factory->createNamed('child', $this->getTestedType())); + $view = $parent->createView(); + + $this->assertEquals('parent_child', $view['child']->vars['id']); + $this->assertEquals('child', $view['child']->vars['name']); + $this->assertEquals('parent[child]', $view['child']->vars['full_name']); + } + + public function testPassIdAndNameToViewWithGrandParent() + { + $parent = $this->factory->createNamed('parent', 'form'); + $parent->add($this->factory->createNamed('child', 'form')); + $parent['child']->add($this->factory->createNamed('grand_child', $this->getTestedType())); + $view = $parent->createView(); + + $this->assertEquals('parent_child_grand_child', $view['child']['grand_child']->vars['id']); + $this->assertEquals('grand_child', $view['child']['grand_child']->vars['name']); + $this->assertEquals('parent[child][grand_child]', $view['child']['grand_child']->vars['full_name']); + } + + public function testPassTranslationDomainToView() + { + $form = $this->factory->create($this->getTestedType(), null, array( + 'translation_domain' => 'domain', + )); + $view = $form->createView(); + + $this->assertSame('domain', $view->vars['translation_domain']); + } + + public function testInheritTranslationDomainFromParent() + { + $parent = $this->factory->createNamed('parent', 'form', null, array( + 'translation_domain' => 'domain', + )); + $child = $this->factory->createNamed('child', $this->getTestedType()); + $view = $parent->add($child)->createView(); + + $this->assertEquals('domain', $view['child']->vars['translation_domain']); + } + + public function testPreferOwnTranslationDomain() + { + $parent = $this->factory->createNamed('parent', 'form', null, array( + 'translation_domain' => 'parent_domain', + )); + $child = $this->factory->createNamed('child', $this->getTestedType(), null, array( + 'translation_domain' => 'domain', + )); + $view = $parent->add($child)->createView(); + + $this->assertEquals('domain', $view['child']->vars['translation_domain']); + } + + public function testDefaultTranslationDomain() + { + $parent = $this->factory->createNamed('parent', 'form'); + $child = $this->factory->createNamed('child', $this->getTestedType()); + $view = $parent->add($child)->createView(); + + $this->assertEquals('messages', $view['child']->vars['translation_domain']); + } + + public function testPassLabelToView() + { + $form = $this->factory->createNamed('__test___field', $this->getTestedType(), null, array('label' => 'My label')); + $view = $form->createView(); + + $this->assertSame('My label', $view->vars['label']); + } + + public function testPassMultipartFalseToView() + { + $form = $this->factory->create($this->getTestedType()); + $view = $form->createView(); + + $this->assertFalse($view->vars['multipart']); + } + + abstract protected function getTestedType(); +} diff --git a/Tests/Extension/Core/Type/ButtonTypeTest.php b/Tests/Extension/Core/Type/ButtonTypeTest.php new file mode 100644 index 0000000000..55835e77fe --- /dev/null +++ b/Tests/Extension/Core/Type/ButtonTypeTest.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +/** + * @author Bernhard Schussek + */ +class ButtonTypeTest extends BaseTypeTest +{ + public function testCreateButtonInstances() + { + $this->assertInstanceOf('Symfony\Component\Form\Button', $this->factory->create('button')); + } + + protected function getTestedType() + { + return 'button'; + } +} diff --git a/Tests/Extension/Core/Type/FormTypeTest.php b/Tests/Extension/Core/Type/FormTypeTest.php index 6b906ea4f3..f6663d6b65 100644 --- a/Tests/Extension/Core/Type/FormTypeTest.php +++ b/Tests/Extension/Core/Type/FormTypeTest.php @@ -50,8 +50,13 @@ public function setReferenceCopy($reference) } } -class FormTypeTest extends TypeTestCase +class FormTypeTest extends BaseTypeTest { + public function testCreateFormInstances() + { + $this->assertInstanceOf('Symfony\Component\Form\Form', $this->factory->create('form')); + } + public function testPassRequiredAsOption() { $form = $this->factory->create('form', null, array('required' => false)); @@ -63,13 +68,6 @@ public function testPassRequiredAsOption() $this->assertTrue($form->isRequired()); } - public function testPassDisabledAsOption() - { - $form = $this->factory->create('form', null, array('disabled' => true)); - - $this->assertTrue($form->isDisabled()); - } - public function testBoundDataIsTrimmedBeforeTransforming() { $form = $this->factory->createBuilder('form') @@ -102,49 +100,6 @@ public function testBoundDataIsNotTrimmedBeforeTransformingIfNoTrimming() $this->assertEquals('reverse[ a ]', $form->getData()); } - public function testPassIdAndNameToView() - { - $form = $this->factory->createNamed('name', 'form'); - $view = $form->createView(); - - $this->assertEquals('name', $view->vars['id']); - $this->assertEquals('name', $view->vars['name']); - $this->assertEquals('name', $view->vars['full_name']); - } - - public function testStripLeadingUnderscoresAndDigitsFromId() - { - $form = $this->factory->createNamed('_09name', 'form'); - $view = $form->createView(); - - $this->assertEquals('name', $view->vars['id']); - $this->assertEquals('_09name', $view->vars['name']); - $this->assertEquals('_09name', $view->vars['full_name']); - } - - public function testPassIdAndNameToViewWithParent() - { - $parent = $this->factory->createNamed('parent', 'form'); - $parent->add($this->factory->createNamed('child', 'form')); - $view = $parent->createView(); - - $this->assertEquals('parent_child', $view['child']->vars['id']); - $this->assertEquals('child', $view['child']->vars['name']); - $this->assertEquals('parent[child]', $view['child']->vars['full_name']); - } - - public function testPassIdAndNameToViewWithGrandParent() - { - $parent = $this->factory->createNamed('parent', 'form'); - $parent->add($this->factory->createNamed('child', 'form')); - $parent['child']->add($this->factory->createNamed('grand_child', 'form')); - $view = $parent->createView(); - - $this->assertEquals('parent_child_grand_child', $view['child']['grand_child']->vars['id']); - $this->assertEquals('grand_child', $view['child']['grand_child']->vars['name']); - $this->assertEquals('parent[child][grand_child]', $view['child']['grand_child']->vars['full_name']); - } - public function testNonReadOnlyFormWithReadOnlyParentBeingReadOnly() { $parent = $this->factory->createNamed('parent', 'form', null, array('read_only' => true)); @@ -180,57 +135,6 @@ public function testPassMaxLengthToView() $this->assertSame(10, $view->vars['max_length']); } - public function testPassTranslationDomainToView() - { - $form = $this->factory->create('form', null, array('translation_domain' => 'test')); - $view = $form->createView(); - - $this->assertSame('test', $view->vars['translation_domain']); - } - - public function testNonTranslationDomainFormWithTranslationDomainParentBeingTranslationDomain() - { - $parent = $this->factory->createNamed('parent', 'form', null, array('translation_domain' => 'test')); - $child = $this->factory->createNamed('child', 'form'); - $view = $parent->add($child)->createView(); - - $this->assertEquals('test', $view['child']->vars['translation_domain']); - } - - public function testTranslationDomainFormWithNonTranslationDomainParentBeingTranslationDomain() - { - $parent = $this->factory->createNamed('parent', 'form'); - $child = $this->factory->createNamed('child', 'form', null, array('translation_domain' => 'test')); - $view = $parent->add($child)->createView(); - - $this->assertEquals('test', $view['child']->vars['translation_domain']); - } - - public function testNonTranslationDomainFormWithNonTranslationDomainParentBeingTranslationDomainDefault() - { - $parent = $this->factory->createNamed('parent', 'form'); - $child = $this->factory->createNamed('child', 'form'); - $view = $parent->add($child)->createView(); - - $this->assertEquals('messages', $view['child']->vars['translation_domain']); - } - - public function testPassLabelToView() - { - $form = $this->factory->createNamed('__test___field', 'form', null, array('label' => 'My label')); - $view = $form->createView(); - - $this->assertSame('My label', $view->vars['label']); - } - - public function testDefaultTranslationDomain() - { - $form = $this->factory->create('form'); - $view = $form->createView(); - - $this->assertSame('messages', $view->vars['translation_domain']); - } - public function testBindWithEmptyDataCreatesObjectIfClassAvailable() { $form = $this->factory->create('form', null, array( @@ -404,6 +308,7 @@ public function testNameCanBeEmptyString() $this->assertEquals('', $form->getName()); } + public function testSubformDoesntCallSetters() { $author = new FormTest_AuthorWithoutRefSetter(new Author()); @@ -523,14 +428,6 @@ function ($value) use ($ref2) { // reverseTransform $this->assertSame($ref2, $author['referenceCopy']); } - public function testPassMultipartFalseToView() - { - $form = $this->factory->create('form'); - $view = $form->createView(); - - $this->assertFalse($view->vars['multipart']); - } - public function testPassMultipartTrueIfAnyChildIsMultipartToView() { $form = $this->factory->create('form'); @@ -661,4 +558,9 @@ public function testPassZeroLabelToView() $this->assertSame('0', $view->vars['label']); } + + protected function getTestedType() + { + return 'form'; + } } diff --git a/Tests/Extension/Core/Type/SubmitTypeTest.php b/Tests/Extension/Core/Type/SubmitTypeTest.php new file mode 100644 index 0000000000..b85d72f568 --- /dev/null +++ b/Tests/Extension/Core/Type/SubmitTypeTest.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +/** + * @author Bernhard Schussek + */ +class SubmitTypeTest extends TypeTestCase +{ + public function testCreateSubmitButtonInstances() + { + $this->assertInstanceOf('Symfony\Component\Form\SubmitButton', $this->factory->create('submit')); + } + + public function testNotClickedByDefault() + { + $button = $this->factory->create('submit'); + + $this->assertFalse($button->isClicked()); + } + + public function testNotClickedIfBoundWithNull() + { + $button = $this->factory->create('submit'); + $button->bind(null); + + $this->assertFalse($button->isClicked()); + } + + public function testClickedIfBoundWithEmptyString() + { + $button = $this->factory->create('submit'); + $button->bind(''); + + $this->assertTrue($button->isClicked()); + } + + public function testClickedIfBoundWithUnemptyString() + { + $button = $this->factory->create('submit'); + $button->bind('foo'); + + $this->assertTrue($button->isClicked()); + } +} From e2d058d149753e5e228f94f122be33ac9bd9f041 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Wed, 2 Jan 2013 18:51:49 +0100 Subject: [PATCH 091/447] [Form] Made submit buttons able to convey validation groups --- Extension/Core/Type/BaseType.php | 2 - .../Validator/Constraints/FormValidator.php | 56 ++++++++++++-- .../Validator/Type/BaseValidatorExtension.php | 52 +++++++++++++ .../Type/FormTypeValidatorExtension.php | 4 +- .../Type/SubmitTypeValidatorExtension.php | 28 +++++++ Extension/Validator/ValidatorExtension.php | 1 + .../Constraints/FormValidatorTest.php | 73 ++++++++++++++++++- 7 files changed, 206 insertions(+), 10 deletions(-) create mode 100644 Extension/Validator/Type/BaseValidatorExtension.php create mode 100644 Extension/Validator/Type/SubmitTypeValidatorExtension.php diff --git a/Extension/Core/Type/BaseType.php b/Extension/Core/Type/BaseType.php index ca47a7bc2f..79333a6799 100644 --- a/Extension/Core/Type/BaseType.php +++ b/Extension/Core/Type/BaseType.php @@ -40,8 +40,6 @@ public function buildForm(FormBuilderInterface $builder, array $options) */ public function buildView(FormView $view, FormInterface $form, array $options) { - /* @var \Symfony\Component\Form\ClickableInterface $form */ - $name = $form->getName(); $blockName = $options['block_name'] ?: $form->getName(); $translationDomain = $options['translation_domain']; diff --git a/Extension/Validator/Constraints/FormValidator.php b/Extension/Validator/Constraints/FormValidator.php index 167fcd95e9..610329c030 100644 --- a/Extension/Validator/Constraints/FormValidator.php +++ b/Extension/Validator/Constraints/FormValidator.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Extension\Validator\Constraints; +use Symfony\Component\Form\ClickableInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\Extension\Validator\Util\ServerParams; use Symfony\Component\Validator\Constraint; @@ -171,15 +172,21 @@ private static function allowDataWalking(FormInterface $form) */ private static function getValidationGroups(FormInterface $form) { + $button = self::findClickedButton($form->getRoot()); + + if (null !== $button) { + $groups = $button->getConfig()->getOption('validation_groups'); + + if (null !== $groups) { + return self::resolveValidationGroups($groups, $form); + } + } + do { $groups = $form->getConfig()->getOption('validation_groups'); if (null !== $groups) { - if (is_callable($groups)) { - $groups = call_user_func($groups, $form); - } - - return (array) $groups; + return self::resolveValidationGroups($groups, $form); } $form = $form->getParent(); @@ -187,4 +194,43 @@ private static function getValidationGroups(FormInterface $form) return array(Constraint::DEFAULT_GROUP); } + + /** + * Extracts a clicked button from a form tree, if one exists. + * + * @param FormInterface $form The root form. + * + * @return ClickableInterface|null The clicked button or null. + */ + private static function findClickedButton(FormInterface $form) + { + if ($form instanceof ClickableInterface && $form->isClicked()) { + return $form; + } + + foreach ($form as $child) { + if (null !== ($button = self::findClickedButton($child))) { + return $button; + } + } + + return null; + } + + /** + * Post-processes the validation groups option for a given form. + * + * @param array|callable $groups The validation groups. + * @param FormInterface $form The validated form. + * + * @return array The validation groups. + */ + private static function resolveValidationGroups($groups, FormInterface $form) + { + if (is_callable($groups)) { + $groups = call_user_func($groups, $form); + } + + return (array) $groups; + } } diff --git a/Extension/Validator/Type/BaseValidatorExtension.php b/Extension/Validator/Type/BaseValidatorExtension.php new file mode 100644 index 0000000000..cf5713058d --- /dev/null +++ b/Extension/Validator/Type/BaseValidatorExtension.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Extension\Validator\Type; + +use Symfony\Component\Form\AbstractTypeExtension; +use Symfony\Component\OptionsResolver\Options; +use Symfony\Component\OptionsResolver\OptionsResolverInterface; + +/** + * Encapsulates common logic of {@link FormTypeValidatorExtension} and + * {@link SubmitTypeValidatorExtension}. + * + * @author Bernhard Schussek + */ +abstract class BaseValidatorExtension extends AbstractTypeExtension +{ + /** + * {@inheritdoc} + */ + public function setDefaultOptions(OptionsResolverInterface $resolver) + { + // Make sure that validation groups end up as null, closure or array + $validationGroupsNormalizer = function (Options $options, $groups) { + if (empty($groups)) { + return null; + } + + if (is_callable($groups)) { + return $groups; + } + + return (array) $groups; + }; + + $resolver->setDefaults(array( + 'validation_groups' => null, + )); + + $resolver->setNormalizers(array( + 'validation_groups' => $validationGroupsNormalizer, + )); + } +} diff --git a/Extension/Validator/Type/FormTypeValidatorExtension.php b/Extension/Validator/Type/FormTypeValidatorExtension.php index 19c888e200..ce106ecacc 100644 --- a/Extension/Validator/Type/FormTypeValidatorExtension.php +++ b/Extension/Validator/Type/FormTypeValidatorExtension.php @@ -22,7 +22,7 @@ /** * @author Bernhard Schussek */ -class FormTypeValidatorExtension extends AbstractTypeExtension +class FormTypeValidatorExtension extends BaseValidatorExtension { /** * @var ValidatorInterface @@ -53,6 +53,8 @@ public function buildForm(FormBuilderInterface $builder, array $options) */ public function setDefaultOptions(OptionsResolverInterface $resolver) { + parent::setDefaultOptions($resolver); + // BC clause $constraints = function (Options $options) { return $options['validation_constraint']; diff --git a/Extension/Validator/Type/SubmitTypeValidatorExtension.php b/Extension/Validator/Type/SubmitTypeValidatorExtension.php new file mode 100644 index 0000000000..5aad67fb3a --- /dev/null +++ b/Extension/Validator/Type/SubmitTypeValidatorExtension.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Extension\Validator\Type; + +use Symfony\Component\Form\AbstractTypeExtension; + +/** + * @author Bernhard Schussek + */ +class SubmitTypeValidatorExtension extends AbstractTypeExtension +{ + /** + * {@inheritdoc} + */ + public function getExtendedType() + { + return 'submit'; + } +} diff --git a/Extension/Validator/ValidatorExtension.php b/Extension/Validator/ValidatorExtension.php index e6d6fea415..9cff22a276 100644 --- a/Extension/Validator/ValidatorExtension.php +++ b/Extension/Validator/ValidatorExtension.php @@ -51,6 +51,7 @@ protected function loadTypeExtensions() return array( new Type\FormTypeValidatorExtension($this->validator), new Type\RepeatedTypeValidatorExtension(), + new Type\SubmitTypeValidatorExtension(), ); } } diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index a3d9f26d98..14accc9a3d 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -17,6 +17,7 @@ use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\Extension\Validator\Constraints\Form; use Symfony\Component\Form\Extension\Validator\Constraints\FormValidator; +use Symfony\Component\Form\SubmitButtonBuilder; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\NotBlank; @@ -313,6 +314,62 @@ public function testHandleClosureValidationGroups() $this->validator->validate($form, new Form()); } + public function testUseValidationGroupOfClickedButton() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + + $parent = $this->getBuilder('parent', null, array('cascade_validation' => true)) + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + $form = $this->getForm('name', '\stdClass', array( + 'validation_groups' => 'form_group', + )); + + $parent->add($form); + $parent->add($this->getClickedSubmitButton('submit', array( + 'validation_groups' => 'button_group', + ))); + + $form->setData($object); + + $context->expects($this->once()) + ->method('validate') + ->with($object, 'data', 'button_group', true); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + public function testDontUseValidationGroupOfUnclickedButton() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + + $parent = $this->getBuilder('parent', null, array('cascade_validation' => true)) + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + $form = $this->getForm('name', '\stdClass', array( + 'validation_groups' => 'form_group', + )); + + $parent->add($form); + $parent->add($this->getSubmitButton('submit', array( + 'validation_groups' => 'button_group', + ))); + + $form->setData($object); + + $context->expects($this->once()) + ->method('validate') + ->with($object, 'data', 'form_group', true); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + public function testUseInheritedValidationGroup() { $context = $this->getMockExecutionContext(); @@ -561,9 +618,21 @@ private function getBuilder($name = 'name', $dataClass = null, array $options = return new FormBuilder($name, $dataClass, $this->dispatcher, $this->factory, $options); } - private function getForm($name = 'name', $dataClass = null) + private function getForm($name = 'name', $dataClass = null, array $options = array()) + { + return $this->getBuilder($name, $dataClass, $options)->getForm(); + } + + private function getSubmitButton($name = 'name', array $options = array()) + { + $builder = new SubmitButtonBuilder($name, $options); + + return $builder->getForm(); + } + + private function getClickedSubmitButton($name = 'name', array $options = array()) { - return $this->getBuilder($name, $dataClass)->getForm(); + return $this->getSubmitButton($name, $options)->bind(''); } /** From d8a8625c283ab34e3517236424420ac0cbf96c14 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 3 Jan 2013 19:09:17 +0100 Subject: [PATCH 092/447] [Form] Changed isset() to array_key_exists() to be consistent with ParameterBag --- ButtonBuilder.php | 8 ++++---- FormConfigBuilder.php | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ButtonBuilder.php b/ButtonBuilder.php index ce30b0ab26..2f0cbee06d 100644 --- a/ButtonBuilder.php +++ b/ButtonBuilder.php @@ -710,7 +710,7 @@ public function getAttributes() */ public function hasAttribute($name) { - return isset($this->attributes[$name]); + return array_key_exists($name, $this->attributes); } /** @@ -723,7 +723,7 @@ public function hasAttribute($name) */ public function getAttribute($name, $default = null) { - return isset($this->attributes[$name]) ? $this->attributes[$name] : $default; + return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; } /** @@ -785,7 +785,7 @@ public function getOptions() */ public function hasOption($name) { - return isset($this->options[$name]); + return array_key_exists($name, $this->options); } /** @@ -798,7 +798,7 @@ public function hasOption($name) */ public function getOption($name, $default = null) { - return isset($this->options[$name]) ? $this->options[$name] : $default; + return array_key_exists($name, $this->options) ? $this->options[$name] : $default; } /** diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index 7d297ed33d..c52b4169e8 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -392,7 +392,7 @@ public function getAttributes() */ public function hasAttribute($name) { - return isset($this->attributes[$name]); + return array_key_exists($name, $this->attributes); } /** @@ -400,7 +400,7 @@ public function hasAttribute($name) */ public function getAttribute($name, $default = null) { - return isset($this->attributes[$name]) ? $this->attributes[$name] : $default; + return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; } /** @@ -448,7 +448,7 @@ public function getOptions() */ public function hasOption($name) { - return isset($this->options[$name]); + return array_key_exists($name, $this->options); } /** @@ -456,7 +456,7 @@ public function hasOption($name) */ public function getOption($name, $default = null) { - return isset($this->options[$name]) ? $this->options[$name] : $default; + return array_key_exists($name, $this->options) ? $this->options[$name] : $default; } /** From b792e07aa9c55add4cebdb1a16e59bf2a81754fc Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 11 Apr 2013 15:59:05 +0200 Subject: [PATCH 093/447] [Form] Fixed concatenation operator CS (see 7c47e34928c39e4797edc841423237a16588395e) --- .../Validator/ViolationMapper/ViolationMapperTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php index e8137df35c..83a5db6e10 100644 --- a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php +++ b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php @@ -781,7 +781,7 @@ public function testDefaultErrorMapping($target, $childName, $childPath, $grandC } else { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName. ' should have an error, but has none'); + $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); } } @@ -1253,7 +1253,7 @@ public function testCustomDataErrorMapping($target, $mapFrom, $mapTo, $childName } else { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName. ' should have an error, but has none'); + $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); } } @@ -1442,7 +1442,7 @@ public function testCustomFormErrorMapping($target, $mapFrom, $mapTo, $errorName $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one'); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName. ' should have an error, but has none'); + $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); } } @@ -1497,7 +1497,7 @@ public function testVirtualFormErrorMapping($target, $childName, $childPath, $gr } else { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName. ' should have an error, but has none'); + $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); } } } From 89041ef4ede98cae5416a8e2670e3d8b72ee5f72 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 11 Apr 2013 16:37:26 +0200 Subject: [PATCH 094/447] [Form] The option "validation_groups" can now be set to false to disable validation. This is identical to setting it to an empty array. --- CHANGELOG.md | 2 + .../Validator/Type/BaseValidatorExtension.php | 4 + .../Constraints/FormValidatorTest.php | 85 +++++++++++++++++++ .../Type/FormTypeValidatorExtensionTest.php | 9 ++ 4 files changed, 100 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08f1aec42f..b315af5cbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,8 @@ CHANGELOG * added an optional PropertyAccessorInterface parameter to FormType, ObjectChoiceList and PropertyPathMapper * [BC BREAK] PropertyPathMapper and FormType now have a constructor + * [BC BREAK] setting the option "validation_groups" to ``false`` now disables validation + instead of assuming group "Default" 2.1.0 ----- diff --git a/Extension/Validator/Type/BaseValidatorExtension.php b/Extension/Validator/Type/BaseValidatorExtension.php index cf5713058d..7c5e6784ae 100644 --- a/Extension/Validator/Type/BaseValidatorExtension.php +++ b/Extension/Validator/Type/BaseValidatorExtension.php @@ -30,6 +30,10 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) { // Make sure that validation groups end up as null, closure or array $validationGroupsNormalizer = function (Options $options, $groups) { + if (false === $groups) { + return array(); + } + if (empty($groups)) { return null; } diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index 14accc9a3d..ce5035717d 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -170,6 +170,51 @@ public function testValidateConstraintsEvenIfNoCascadeValidation() $this->validator->validate($form, new Form()); } + public function testDontValidateIfNoValidationGroups() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + + $form = $this->getBuilder('name', '\stdClass', array( + 'validation_groups' => array(), + )) + ->setData($object) + ->getForm(); + + $form->setData($object); + + $context->expects($this->never()) + ->method('validate'); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + + public function testDontValidateConstraintsIfNoValidationGroups() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + $constraint1 = $this->getMock('Symfony\Component\Validator\Constraint'); + $constraint2 = $this->getMock('Symfony\Component\Validator\Constraint'); + + $options = array( + 'validation_groups' => array(), + 'constraints' => array($constraint1, $constraint2), + ); + $form = $this->getBuilder('name', '\stdClass', $options) + ->setData($object) + ->getForm(); + + // Launch transformer + $form->bind(array()); + + $context->expects($this->never()) + ->method('validate'); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + public function testDontValidateIfNotSynchronized() { $context = $this->getMockExecutionContext(); @@ -209,6 +254,46 @@ function () { throw new TransformationFailedException(); } $this->validator->validate($form, new Form()); } + public function testAddInvalidErrorEvenIfNoValidationGroups() + { + $context = $this->getMockExecutionContext(); + $object = $this->getMock('\stdClass'); + + $form = $this->getBuilder('name', '\stdClass', array( + 'invalid_message' => 'invalid_message_key', + // Invalid message parameters must be supported, because the + // invalid message can be a translation key + // see https://github.com/symfony/symfony/issues/5144 + 'invalid_message_parameters' => array('{{ foo }}' => 'bar'), + 'validation_groups' => array(), + )) + ->setData($object) + ->addViewTransformer(new CallbackTransformer( + function ($data) { return $data; }, + function () { throw new TransformationFailedException(); } + )) + ->getForm(); + + // Launch transformer + $form->bind('foo'); + + $context->expects($this->never()) + ->method('validate'); + + $context->expects($this->once()) + ->method('addViolation') + ->with( + 'invalid_message_key', + array('{{ value }}' => 'foo', '{{ foo }}' => 'bar'), + 'foo' + ); + $context->expects($this->never()) + ->method('addViolationAt'); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + public function testDontValidateConstraintsIfNotSynchronized() { $context = $this->getMockExecutionContext(); diff --git a/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php b/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php index 13faefe956..094a26853b 100644 --- a/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php +++ b/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php @@ -40,6 +40,15 @@ public function testValidationGroupsCanBeSetToArray() $this->assertEquals(array('group1', 'group2'), $form->getConfig()->getOption('validation_groups')); } + public function testValidationGroupsCanBeSetToFalse() + { + $form = $this->factory->create('form', null, array( + 'validation_groups' => false, + )); + + $this->assertEquals(array(), $form->getConfig()->getOption('validation_groups')); + } + public function testValidationGroupsCanBeSetToCallback() { $form = $this->factory->create('form', null, array( From d95cc0ab1cce4c249841e4e81ed934536fa22a5d Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 11 Apr 2013 16:56:20 +0200 Subject: [PATCH 095/447] [Form] Fixed invalid use of FormException --- ButtonBuilder.php | 3 ++- Exception/InvalidArgumentException.php | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 Exception/InvalidArgumentException.php diff --git a/ButtonBuilder.php b/ButtonBuilder.php index 2f0cbee06d..e40eecccc9 100644 --- a/ButtonBuilder.php +++ b/ButtonBuilder.php @@ -13,6 +13,7 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\Exception\FormException; +use Symfony\Component\Form\Exception\InvalidArgumentException; /** * A builder for {@link Button} instances. @@ -62,7 +63,7 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface public function __construct($name, array $options) { if (empty($name) && 0 != $name) { - throw new FormException('Buttons cannot have empty names.'); + throw new InvalidArgumentException('Buttons cannot have empty names.'); } $this->name = (string) $name; diff --git a/Exception/InvalidArgumentException.php b/Exception/InvalidArgumentException.php new file mode 100644 index 0000000000..a270e0ce9e --- /dev/null +++ b/Exception/InvalidArgumentException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Exception; + +/** + * Base InvalidArgumentException for the Form component. + * + * @author Bernhard Schussek + */ +class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface +{ +} From 3e077ed02f61356a4b18190b5b6e4205fc6a809a Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 11 Apr 2013 16:58:10 +0200 Subject: [PATCH 096/447] [Form] Fixed incorrect doc comment --- Button.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Button.php b/Button.php index b1b0b00d65..23c4775530 100644 --- a/Button.php +++ b/Button.php @@ -14,7 +14,7 @@ use Symfony\Component\Form\Exception\AlreadyBoundException; /** - * Default implementation of {@link ButtonInterface}. + * A form button. * * @author Bernhard Schussek */ From 8b4e7dee8a888686b5dc9f4b51de4a00d2e4bb8e Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Sat, 13 Apr 2013 15:16:29 +0200 Subject: [PATCH 097/447] [Form] Removed deprecated code scheduled for removal in 2.3 --- ButtonBuilder.php | 74 ------------------- .../Type/FormTypeValidatorExtension.php | 8 +- FormBuilder.php | 54 +------------- FormEvents.php | 1 - FormFactory.php | 26 +++---- FormFactoryInterface.php | 34 ++++----- ResolvedFormType.php | 3 +- ResolvedFormTypeInterface.php | 3 +- Tests/FormBuilderTest.php | 43 ----------- Tests/FormFactoryTest.php | 19 ----- Tests/ResolvedFormTypeTest.php | 4 +- 11 files changed, 33 insertions(+), 236 deletions(-) diff --git a/ButtonBuilder.php b/ButtonBuilder.php index e40eecccc9..9e61cbf403 100644 --- a/ButtonBuilder.php +++ b/ButtonBuilder.php @@ -162,52 +162,6 @@ public function getForm() return new Button($this->getFormConfig()); } - /** - * Unsupported method. - * - * Does nothing. - * - * @param FormBuilderInterface $parent The parent builder - * - * @deprecated Deprecated since version 2.2, to be removed in 2.3. You - * should not rely on the parent of a builder, because it is - * likely that the parent is only set after turning the builder - * into a form. - */ - public function setParent(FormBuilderInterface $parent = null) - { - } - - /** - * Unsupported method. - * - * @return null Always returns null. - * - * @deprecated Deprecated since version 2.2, to be removed in 2.3. You - * should not rely on the parent of a builder, because it is - * likely that the parent is only set after turning the builder - * into a form. - */ - public function getParent() - { - return null; - } - - /** - * Unsupported method. - * - * @return Boolean Always returns false. - * - * @deprecated Deprecated since version 2.2, to be removed in 2.3. You - * should not rely on the parent of a builder, because it is - * likely that the parent is only set after turning the builder - * into a form. - */ - public function hasParent() - { - return false; - } - /** * Unsupported method. * @@ -238,22 +192,6 @@ public function addEventSubscriber(EventSubscriberInterface $subscriber) throw new \BadMethodCallException('Buttons do not support event subscribers.'); } - /** - * Unsupported method. - * - * This method should not be invoked. - * - * @param FormValidatorInterface $validator - * - * @throws \BadMethodCallException - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. - */ - public function addValidator(FormValidatorInterface $validator) - { - throw new \BadMethodCallException('Buttons do not support validators.'); - } - /** * Unsupported method. * @@ -640,18 +578,6 @@ public function getDataMapper() return null; } - /** - * Unsupported method. - * - * @return array Always returns null. - * - * @deprecated Deprecated since version 2.1, to be removed in 2.3. - */ - public function getValidators() - { - return array(); - } - /** * Unsupported method. * diff --git a/Extension/Validator/Type/FormTypeValidatorExtension.php b/Extension/Validator/Type/FormTypeValidatorExtension.php index ce106ecacc..99ef51f2bf 100644 --- a/Extension/Validator/Type/FormTypeValidatorExtension.php +++ b/Extension/Validator/Type/FormTypeValidatorExtension.php @@ -55,11 +55,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) { parent::setDefaultOptions($resolver); - // BC clause - $constraints = function (Options $options) { - return $options['validation_constraint']; - }; - // Constraint should always be converted to an array $constraintsNormalizer = function (Options $options, $constraints) { return is_object($constraints) ? array($constraints) : (array) $constraints; @@ -67,9 +62,8 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) $resolver->setDefaults(array( 'error_mapping' => array(), - // "validation_constraint" is deprecated. Use "constraints". 'validation_constraint' => null, - 'constraints' => $constraints, + 'constraints' => array(), 'cascade_validation' => false, 'invalid_message' => 'This value is not valid.', 'invalid_message_parameters' => array(), diff --git a/FormBuilder.php b/FormBuilder.php index a626980c59..a778c9e09d 100644 --- a/FormBuilder.php +++ b/FormBuilder.php @@ -37,13 +37,6 @@ class FormBuilder extends FormConfigBuilder implements \IteratorAggregate, FormB */ private $unresolvedChildren = array(); - /** - * The parent of this builder. - * - * @var FormBuilder - */ - private $parent; - /** * Creates a new form builder. * @@ -70,7 +63,6 @@ public function add($child, $type = null, array $options = array()) } if ($child instanceof self) { - $child->setParent($this); $this->children[$child->getName()] = $child; // In case an unresolved child with the same name exists @@ -111,10 +103,10 @@ public function create($name, $type = null, array $options = array()) } if (null !== $type) { - return $this->getFormFactory()->createNamedBuilder($name, $type, null, $options, $this); + return $this->getFormFactory()->createNamedBuilder($name, $type, null, $options); } - return $this->getFormFactory()->createBuilderForProperty($this->getDataClass(), $name, null, $options, $this); + return $this->getFormFactory()->createBuilderForProperty($this->getDataClass(), $name, null, $options); } /** @@ -149,9 +141,6 @@ public function remove($name) unset($this->unresolvedChildren[$name]); if (array_key_exists($name, $this->children)) { - if ($this->children[$name] instanceof self) { - $this->children[$name]->setParent(null); - } unset($this->children[$name]); } @@ -211,7 +200,6 @@ public function getFormConfig() { $config = parent::getFormConfig(); - $config->parent = null; $config->children = array(); $config->unresolvedChildren = array(); @@ -238,44 +226,6 @@ public function getForm() return $form; } - /** - * {@inheritdoc} - */ - public function getParent() - { - if ($this->locked) { - throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - return $this->parent; - } - - /** - * {@inheritdoc} - */ - public function setParent(FormBuilderInterface $parent = null) - { - if ($this->locked) { - throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - $this->parent = $parent; - - return $this; - } - - /** - * {@inheritdoc} - */ - public function hasParent() - { - if ($this->locked) { - throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); - } - - return null !== $this->parent; - } - /** * {@inheritdoc} */ diff --git a/FormEvents.php b/FormEvents.php index 114bfcd226..c46faf36ab 100644 --- a/FormEvents.php +++ b/FormEvents.php @@ -1,5 +1,4 @@ createBuilder($type, $data, $options, $parent)->getForm(); + return $this->createBuilder($type, $data, $options)->getForm(); } /** * {@inheritdoc} */ - public function createNamed($name, $type = 'form', $data = null, array $options = array(), FormBuilderInterface $parent = null) + public function createNamed($name, $type = 'form', $data = null, array $options = array()) { - return $this->createNamedBuilder($name, $type, $data, $options, $parent)->getForm(); + return $this->createNamedBuilder($name, $type, $data, $options)->getForm(); } /** * {@inheritdoc} */ - public function createForProperty($class, $property, $data = null, array $options = array(), FormBuilderInterface $parent = null) + public function createForProperty($class, $property, $data = null, array $options = array()) { - return $this->createBuilderForProperty($class, $property, $data, $options, $parent)->getForm(); + return $this->createBuilderForProperty($class, $property, $data, $options)->getForm(); } /** * {@inheritdoc} */ - public function createBuilder($type = 'form', $data = null, array $options = array(), FormBuilderInterface $parent = null) + public function createBuilder($type = 'form', $data = null, array $options = array()) { $name = $type instanceof FormTypeInterface || $type instanceof ResolvedFormTypeInterface ? $type->getName() : $type; - return $this->createNamedBuilder($name, $type, $data, $options, $parent); + return $this->createNamedBuilder($name, $type, $data, $options); } /** * {@inheritdoc} */ - public function createNamedBuilder($name, $type = 'form', $data = null, array $options = array(), FormBuilderInterface $parent = null) + public function createNamedBuilder($name, $type = 'form', $data = null, array $options = array()) { if (null !== $data && !array_key_exists('data', $options)) { $options['data'] = $data; @@ -84,16 +84,16 @@ public function createNamedBuilder($name, $type = 'form', $data = null, array $o throw new UnexpectedTypeException($type, 'string, Symfony\Component\Form\ResolvedFormTypeInterface or Symfony\Component\Form\FormTypeInterface'); } - return $type->createBuilder($this, $name, $options, $parent); + return $type->createBuilder($this, $name, $options); } /** * {@inheritdoc} */ - public function createBuilderForProperty($class, $property, $data = null, array $options = array(), FormBuilderInterface $parent = null) + public function createBuilderForProperty($class, $property, $data = null, array $options = array()) { if (null === $guesser = $this->registry->getTypeGuesser()) { - return $this->createNamedBuilder($property, 'text', $data, $options, $parent); + return $this->createNamedBuilder($property, 'text', $data, $options); } $typeGuess = $guesser->guessType($class, $property); @@ -123,7 +123,7 @@ public function createBuilderForProperty($class, $property, $data = null, array $options = array_merge($typeGuess->getOptions(), $options); } - return $this->createNamedBuilder($property, $type, $data, $options, $parent); + return $this->createNamedBuilder($property, $type, $data, $options); } /** diff --git a/FormFactoryInterface.php b/FormFactoryInterface.php index 98c53d9b53..8edfa95e52 100644 --- a/FormFactoryInterface.php +++ b/FormFactoryInterface.php @@ -24,13 +24,12 @@ interface FormFactoryInterface * @param string|FormTypeInterface $type The type of the form * @param mixed $data The initial data * @param array $options The options - * @param FormBuilderInterface $parent The parent builder * * @return FormInterface The form named after the type * * @throws Exception\FormException if any given option is not applicable to the given type */ - public function create($type = 'form', $data = null, array $options = array(), FormBuilderInterface $parent = null); + public function create($type = 'form', $data = null, array $options = array()); /** * Returns a form. @@ -41,30 +40,28 @@ public function create($type = 'form', $data = null, array $options = array(), F * @param string|FormTypeInterface $type The type of the form * @param mixed $data The initial data * @param array $options The options - * @param FormBuilderInterface $parent The parent builder * * @return FormInterface The form * * @throws Exception\FormException if any given option is not applicable to the given type */ - public function createNamed($name, $type = 'form', $data = null, array $options = array(), FormBuilderInterface $parent = null); + public function createNamed($name, $type = 'form', $data = null, array $options = array()); /** * Returns a form for a property of a class. * * @see createBuilderForProperty() * - * @param string $class The fully qualified class name - * @param string $property The name of the property to guess for - * @param mixed $data The initial data - * @param array $options The options for the builder - * @param FormBuilderInterface $parent The parent builder + * @param string $class The fully qualified class name + * @param string $property The name of the property to guess for + * @param mixed $data The initial data + * @param array $options The options for the builder * * @return FormInterface The form named after the property * * @throws Exception\FormException if any given option is not applicable to the form type */ - public function createForProperty($class, $property, $data = null, array $options = array(), FormBuilderInterface $parent = null); + public function createForProperty($class, $property, $data = null, array $options = array()); /** * Returns a form builder. @@ -72,13 +69,12 @@ public function createForProperty($class, $property, $data = null, array $option * @param string|FormTypeInterface $type The type of the form * @param mixed $data The initial data * @param array $options The options - * @param FormBuilderInterface $parent The parent builder * * @return FormBuilderInterface The form builder * * @throws Exception\FormException if any given option is not applicable to the given type */ - public function createBuilder($type = 'form', $data = null, array $options = array(), FormBuilderInterface $parent = null); + public function createBuilder($type = 'form', $data = null, array $options = array()); /** * Returns a form builder. @@ -87,13 +83,12 @@ public function createBuilder($type = 'form', $data = null, array $options = arr * @param string|FormTypeInterface $type The type of the form * @param mixed $data The initial data * @param array $options The options - * @param FormBuilderInterface $parent The parent builder * * @return FormBuilderInterface The form builder * * @throws Exception\FormException if any given option is not applicable to the given type */ - public function createNamedBuilder($name, $type = 'form', $data = null, array $options = array(), FormBuilderInterface $parent = null); + public function createNamedBuilder($name, $type = 'form', $data = null, array $options = array()); /** * Returns a form builder for a property of a class. @@ -101,15 +96,14 @@ public function createNamedBuilder($name, $type = 'form', $data = null, array $o * If any of the 'max_length', 'required' and type options can be guessed, * and are not provided in the options argument, the guessed value is used. * - * @param string $class The fully qualified class name - * @param string $property The name of the property to guess for - * @param mixed $data The initial data - * @param array $options The options for the builder - * @param FormBuilderInterface $parent The parent builder + * @param string $class The fully qualified class name + * @param string $property The name of the property to guess for + * @param mixed $data The initial data + * @param array $options The options for the builder * * @return FormBuilderInterface The form builder named after the property * * @throws Exception\FormException if any given option is not applicable to the form type */ - public function createBuilderForProperty($class, $property, $data = null, array $options = array(), FormBuilderInterface $parent = null); + public function createBuilderForProperty($class, $property, $data = null, array $options = array()); } diff --git a/ResolvedFormType.php b/ResolvedFormType.php index 7203817b94..e48ea5e64d 100644 --- a/ResolvedFormType.php +++ b/ResolvedFormType.php @@ -104,7 +104,7 @@ public function getTypeExtensions() /** * {@inheritdoc} */ - public function createBuilder(FormFactoryInterface $factory, $name, array $options = array(), FormBuilderInterface $parent = null) + public function createBuilder(FormFactoryInterface $factory, $name, array $options = array()) { $options = $this->getOptionsResolver()->resolve($options); @@ -113,7 +113,6 @@ public function createBuilder(FormFactoryInterface $factory, $name, array $optio $builder = $this->newBuilder($name, $dataClass, $factory, $options); $builder->setType($this); - $builder->setParent($parent); $this->buildForm($builder, $options); diff --git a/ResolvedFormTypeInterface.php b/ResolvedFormTypeInterface.php index 611bd3a25f..c999bcdc6d 100644 --- a/ResolvedFormTypeInterface.php +++ b/ResolvedFormTypeInterface.php @@ -52,11 +52,10 @@ public function getTypeExtensions(); * @param FormFactoryInterface $factory The form factory. * @param string $name The name for the builder. * @param array $options The builder options. - * @param FormBuilderInterface $parent The parent builder object or null. * * @return FormBuilderInterface The created form builder. */ - public function createBuilder(FormFactoryInterface $factory, $name, array $options = array(), FormBuilderInterface $parent = null); + public function createBuilder(FormFactoryInterface $factory, $name, array $options = array()); /** * Creates a new form view for a form of this type. diff --git a/Tests/FormBuilderTest.php b/Tests/FormBuilderTest.php index 14c8746f8b..4f8cf05da8 100644 --- a/Tests/FormBuilderTest.php +++ b/Tests/FormBuilderTest.php @@ -200,62 +200,19 @@ public function testGetGuessedType() $this->assertNotSame($builder, $this->builder); } - public function testGetParent() - { - $this->assertNull($this->builder->getParent()); - } - - public function testGetParentForAddedBuilder() - { - $builder = new FormBuilder('name', null, $this->dispatcher, $this->factory); - $this->builder->add($builder); - $this->assertSame($this->builder, $builder->getParent()); - } - - public function testGetParentForRemovedBuilder() - { - $builder = new FormBuilder('name', null, $this->dispatcher, $this->factory); - $this->builder->add($builder); - $this->builder->remove('name'); - $this->assertNull($builder->getParent()); - } - - public function testGetParentForCreatedBuilder() - { - $this->builder = new FormBuilder('name', 'stdClass', $this->dispatcher, $this->factory); - $this->factory - ->expects($this->once()) - ->method('createNamedBuilder') - ->with('bar', 'text', null, array(), $this->builder) - ; - - $this->factory - ->expects($this->once()) - ->method('createBuilderForProperty') - ->with('stdClass', 'foo', null, array(), $this->builder) - ; - - $this->builder->create('foo'); - $this->builder->create('bar', 'text'); - } - public function testGetFormConfigErasesReferences() { $builder = new FormBuilder('name', null, $this->dispatcher, $this->factory); - $builder->setParent(new FormBuilder('parent', null, $this->dispatcher, $this->factory)); $builder->add(new FormBuilder('child', null, $this->dispatcher, $this->factory)); $config = $builder->getFormConfig(); $reflClass = new \ReflectionClass($config); - $parent = $reflClass->getProperty('parent'); $children = $reflClass->getProperty('children'); $unresolvedChildren = $reflClass->getProperty('unresolvedChildren'); - $parent->setAccessible(true); $children->setAccessible(true); $unresolvedChildren->setAccessible(true); - $this->assertNull($parent->getValue($config)); $this->assertEmpty($children->getValue($config)); $this->assertEmpty($unresolvedChildren->getValue($config)); } diff --git a/Tests/FormFactoryTest.php b/Tests/FormFactoryTest.php index cbb72f2bb3..f3baa2ad9c 100644 --- a/Tests/FormFactoryTest.php +++ b/Tests/FormFactoryTest.php @@ -171,25 +171,6 @@ public function testCreateNamedBuilderWithResolvedTypeInstance() $this->assertSame('BUILDER', $this->factory->createNamedBuilder('name', $resolvedType, null, $options)); } - public function testCreateNamedBuilderWithParentBuilder() - { - $options = array('a' => '1', 'b' => '2'); - $parentBuilder = $this->getMockFormBuilder(); - $resolvedType = $this->getMockResolvedType(); - - $this->registry->expects($this->once()) - ->method('getType') - ->with('type') - ->will($this->returnValue($resolvedType)); - - $resolvedType->expects($this->once()) - ->method('createBuilder') - ->with($this->factory, 'name', $options, $parentBuilder) - ->will($this->returnValue('BUILDER')); - - $this->assertSame('BUILDER', $this->factory->createNamedBuilder('name', 'type', null, $options, $parentBuilder)); - } - public function testCreateNamedBuilderFillsDataOption() { $givenOptions = array('a' => '1', 'b' => '2'); diff --git a/Tests/ResolvedFormTypeTest.php b/Tests/ResolvedFormTypeTest.php index fd69dba171..bb32a24122 100644 --- a/Tests/ResolvedFormTypeTest.php +++ b/Tests/ResolvedFormTypeTest.php @@ -134,10 +134,8 @@ public function testCreateBuilder() ->will($this->returnCallback($assertIndex(7))); $factory = $this->getMockFormFactory(); - $parentBuilder = $this->getBuilder('parent'); - $builder = $resolvedType->createBuilder($factory, 'name', $givenOptions, $parentBuilder); + $builder = $resolvedType->createBuilder($factory, 'name', $givenOptions); - $this->assertSame($parentBuilder, $builder->getParent()); $this->assertSame($resolvedType, $builder->getType()); } From d54983de0fc5e1bd61d6e781262a1e26974716d2 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Sat, 13 Apr 2013 15:20:03 +0200 Subject: [PATCH 098/447] [Form] Added leading backslashes to @exceptionMessage doc blocks --- Tests/FormFactoryTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/FormFactoryTest.php b/Tests/FormFactoryTest.php index f3baa2ad9c..ea872b01ed 100644 --- a/Tests/FormFactoryTest.php +++ b/Tests/FormFactoryTest.php @@ -209,7 +209,7 @@ public function testCreateNamedBuilderDoesNotOverrideExistingDataOption() } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException * @expectedExceptionMessage Expected argument of type "string, Symfony\Component\Form\ResolvedFormTypeInterface or Symfony\Component\Form\FormTypeInterface", "stdClass" given */ public function testCreateNamedBuilderThrowsUnderstandableException() From 19df96070cdb4b806151cd11869bf1599121ec4a Mon Sep 17 00:00:00 2001 From: Joseph Bielawski Date: Mon, 15 Apr 2013 13:36:11 +0200 Subject: [PATCH 099/447] [Form] Remove deprecated code from Date & Time related fields --- Extension/Core/Type/DateTimeType.php | 17 ++--------------- Extension/Core/Type/DateType.php | 17 ++--------------- Extension/Core/Type/TimeType.php | 17 ++--------------- Tests/Extension/Core/Type/DateTimeTypeTest.php | 4 ++-- Tests/Extension/Core/Type/TimeTypeTest.php | 16 ++++++++-------- 5 files changed, 16 insertions(+), 55 deletions(-) diff --git a/Extension/Core/Type/DateTimeType.php b/Extension/Core/Type/DateTimeType.php index 383ab90b15..a612b6fc9c 100644 --- a/Extension/Core/Type/DateTimeType.php +++ b/Extension/Core/Type/DateTimeType.php @@ -207,23 +207,10 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) return $options['widget']; }; - // BC until Symfony 2.3 - $modelTimezone = function (Options $options) { - return $options['data_timezone']; - }; - - // BC until Symfony 2.3 - $viewTimezone = function (Options $options) { - return $options['user_timezone']; - }; - $resolver->setDefaults(array( 'input' => 'datetime', - 'model_timezone' => $modelTimezone, - 'view_timezone' => $viewTimezone, - // Deprecated timezone options - 'data_timezone' => null, - 'user_timezone' => null, + 'model_timezone' => null, + 'view_timezone' => null, 'format' => self::HTML5_FORMAT, 'date_format' => null, 'widget' => null, diff --git a/Extension/Core/Type/DateType.php b/Extension/Core/Type/DateType.php index ad5914aae8..a4a55a2af5 100644 --- a/Extension/Core/Type/DateType.php +++ b/Extension/Core/Type/DateType.php @@ -189,16 +189,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) return $options['widget'] === 'single_text' ? DateType::HTML5_FORMAT : DateType::DEFAULT_FORMAT; }; - // BC until Symfony 2.3 - $modelTimezone = function (Options $options) { - return $options['data_timezone']; - }; - - // BC until Symfony 2.3 - $viewTimezone = function (Options $options) { - return $options['user_timezone']; - }; - $resolver->setDefaults(array( 'years' => range(date('Y') - 5, date('Y') + 5), 'months' => range(1, 12), @@ -206,11 +196,8 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'widget' => 'choice', 'input' => 'datetime', 'format' => $format, - 'model_timezone' => $modelTimezone, - 'view_timezone' => $viewTimezone, - // Deprecated timezone options - 'data_timezone' => null, - 'user_timezone' => null, + 'model_timezone' => null, + 'view_timezone' => null, 'empty_value' => $emptyValue, // Don't modify \DateTime classes by reference, we treat // them like immutable value objects diff --git a/Extension/Core/Type/TimeType.php b/Extension/Core/Type/TimeType.php index 22df9547f8..d7a2a9efba 100644 --- a/Extension/Core/Type/TimeType.php +++ b/Extension/Core/Type/TimeType.php @@ -173,16 +173,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) ); }; - // BC until Symfony 2.3 - $modelTimezone = function (Options $options) { - return $options['data_timezone']; - }; - - // BC until Symfony 2.3 - $viewTimezone = function (Options $options) { - return $options['user_timezone']; - }; - $resolver->setDefaults(array( 'hours' => range(0, 23), 'minutes' => range(0, 59), @@ -191,11 +181,8 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'input' => 'datetime', 'with_minutes' => true, 'with_seconds' => false, - 'model_timezone' => $modelTimezone, - 'view_timezone' => $viewTimezone, - // Deprecated timezone options - 'data_timezone' => null, - 'user_timezone' => null, + 'model_timezone' => null, + 'view_timezone' => null, 'empty_value' => $emptyValue, // Don't modify \DateTime classes by reference, we treat // them like immutable value objects diff --git a/Tests/Extension/Core/Type/DateTimeTypeTest.php b/Tests/Extension/Core/Type/DateTimeTypeTest.php index 568766cf20..3f86fa69ad 100644 --- a/Tests/Extension/Core/Type/DateTimeTypeTest.php +++ b/Tests/Extension/Core/Type/DateTimeTypeTest.php @@ -97,8 +97,8 @@ public function testSubmitTimestamp() public function testSubmitWithoutMinutes() { $form = $this->factory->create('datetime', null, array( - 'data_timezone' => 'UTC', - 'user_timezone' => 'UTC', + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'date_widget' => 'choice', 'time_widget' => 'choice', 'input' => 'datetime', diff --git a/Tests/Extension/Core/Type/TimeTypeTest.php b/Tests/Extension/Core/Type/TimeTypeTest.php index 6d23250e04..29ee88086b 100644 --- a/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/Tests/Extension/Core/Type/TimeTypeTest.php @@ -114,8 +114,8 @@ public function testSubmitDatetimeSingleText() public function testSubmitDatetimeSingleTextWithoutMinutes() { $form = $this->factory->create('time', null, array( - 'data_timezone' => 'UTC', - 'user_timezone' => 'UTC', + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'input' => 'datetime', 'widget' => 'single_text', 'with_minutes' => false, @@ -150,8 +150,8 @@ public function testSubmitArraySingleText() public function testSubmitArraySingleTextWithoutMinutes() { $form = $this->factory->create('time', null, array( - 'data_timezone' => 'UTC', - 'user_timezone' => 'UTC', + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'input' => 'array', 'widget' => 'single_text', 'with_minutes' => false, @@ -207,8 +207,8 @@ public function testSubmitStringSingleText() public function testSubmitStringSingleTextWithoutMinutes() { $form = $this->factory->create('time', null, array( - 'data_timezone' => 'UTC', - 'user_timezone' => 'UTC', + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'input' => 'string', 'widget' => 'single_text', 'with_minutes' => false, @@ -223,8 +223,8 @@ public function testSubmitStringSingleTextWithoutMinutes() public function testSetDataWithoutMinutes() { $form = $this->factory->create('time', null, array( - 'data_timezone' => 'UTC', - 'user_timezone' => 'UTC', + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'input' => 'datetime', 'with_minutes' => false, )); From 56000d437683fb8d31c0d1234226168e254bbe38 Mon Sep 17 00:00:00 2001 From: Albert Casademont Date: Mon, 15 Apr 2013 20:28:05 +0300 Subject: [PATCH 100/447] [Form] Remove "value" attribute on empty_value option Today we faced a very strange issue with the newest Blackberry 10 browser, it was not submitting our forms. Finally we found that in a ```select``` element, if you have a disabled option, it can't have a value or the HTML5 validator will crash and not submit the form. Of course, setting the ```novalidate``` option for the whole form also solved the issue. Although I know this must be an issue with the WebKit version the BB10 has it can easily be solved in symfony with this change. In fact, it does make sense since we already have a disabled option with no value if the ```preferred_choices``` are not empty and a ```separator``` is set --- Tests/AbstractLayoutTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index bf2c29e8e1..c3d453fb50 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -548,7 +548,7 @@ public function testSingleChoiceRequiredWithEmptyValue() [@name="name"] [@required="required"] [ - ./option[@value=""][not(@selected)][@disabled][.="[trans]Test&Me[/trans]"] + ./option[not(@value)][not(@selected)][@disabled][.="[trans]Test&Me[/trans]"] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] @@ -571,7 +571,7 @@ public function testSingleChoiceRequiredWithEmptyValueViaView() [@name="name"] [@required="required"] [ - ./option[@value=""][not(@selected)][@disabled][.="[trans][/trans]"] + ./option[not(@value)][not(@selected)][@disabled][.="[trans][/trans]"] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] From 8d7bcf31807cc22698a01ee985ac72332ba0772d Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Sun, 30 Dec 2012 21:48:21 +0100 Subject: [PATCH 101/447] [Form] Improved FormRenderer::renderBlock() to be usable outside of form blocks --- FormRenderer.php | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/FormRenderer.php b/FormRenderer.php index 3d6cfa9792..09b830b43e 100644 --- a/FormRenderer.php +++ b/FormRenderer.php @@ -87,17 +87,29 @@ public function renderCsrfToken($intention) */ public function renderBlock(FormView $view, $blockName, array $variables = array()) { - if (0 == count($this->variableStack)) { - throw new Exception('This method should only be called while rendering a form element.'); + $resource = $this->engine->getResourceForBlockName($view, $blockName); + + if (!$resource) { + throw new Exception(sprintf('No block "%s" found while rendering the form.', $blockName)); } $viewCacheKey = $view->vars[self::CACHE_KEY_VAR]; - $scopeVariables = end($this->variableStack[$viewCacheKey]); - $resource = $this->engine->getResourceForBlockName($view, $blockName); + // The variables are cached globally for a view (instead of for the + // current suffix) + if (!isset($this->variableStack[$viewCacheKey])) { + $this->variableStack[$viewCacheKey] = array(); - if (!$resource) { - throw new Exception(sprintf('No block "%s" found while rendering the form.', $blockName)); + // The default variable scope contains all view variables, merged with + // the variables passed explicitly to the helper + $scopeVariables = $view->vars; + + $varInit = true; + } else { + // Reuse the current scope and merge it with the explicitly passed variables + $scopeVariables = end($this->variableStack[$viewCacheKey]); + + $varInit = false; } // Merge the passed with the existing attributes @@ -122,6 +134,10 @@ public function renderBlock(FormView $view, $blockName, array $variables = array // Clear the stack array_pop($this->variableStack[$viewCacheKey]); + if ($varInit) { + unset($this->variableStack[$viewCacheKey]); + } + return $html; } @@ -191,6 +207,8 @@ public function searchAndRenderBlock(FormView $view, $blockNameSuffix, array $va // The variables are cached globally for a view (instead of for the // current suffix) if (!isset($this->variableStack[$viewCacheKey])) { + $this->variableStack[$viewCacheKey] = array(); + // The default variable scope contains all view variables, merged with // the variables passed explicitly to the helper $scopeVariables = $view->vars; From 256bd7ab1a050c2c277139897b43eb58304a6ebb Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Sun, 30 Dec 2012 16:38:36 +0100 Subject: [PATCH 102/447] [Form] Implemented form processors --- Button.php | 13 + ButtonBuilder.php | 66 +++++ CHANGELOG.md | 3 + Extension/Core/Type/FormType.php | 8 + .../EventListener/BindRequestListener.php | 5 + .../HttpFoundation/RequestFormProcessor.php | 80 +++++ .../Type/FormTypeHttpFoundationExtension.php | 8 + Form.php | 12 +- FormConfigBuilder.php | 128 +++++++- FormConfigBuilderInterface.php | 25 ++ FormConfigInterface.php | 19 ++ FormInterface.php | 15 + FormProcessorInterface.php | 28 ++ NativeFormProcessor.php | 194 ++++++++++++ Test/DeprecationErrorHandler.php | 9 + Tests/AbstractDivLayoutTest.php | 90 ++++++ Tests/AbstractFormProcessorTest.php | 280 ++++++++++++++++++ Tests/AbstractLayoutTest.php | 85 +++++- Tests/AbstractTableLayoutTest.php | 106 +++++++ Tests/CompoundFormTest.php | 33 ++- .../EventListener/BindRequestListenerTest.php | 17 +- .../RequestFormProcessorTest.php | 54 ++++ Tests/FormConfigTest.php | 58 +++- Tests/FormIntegrationTestCase.php | 9 + Tests/NativeFormProcessorTest.php | 219 ++++++++++++++ Tests/SimpleFormTest.php | 20 +- 26 files changed, 1544 insertions(+), 40 deletions(-) create mode 100644 Extension/HttpFoundation/RequestFormProcessor.php create mode 100644 FormProcessorInterface.php create mode 100644 NativeFormProcessor.php create mode 100644 Tests/AbstractFormProcessorTest.php create mode 100644 Tests/Extension/HttpFoundation/RequestFormProcessorTest.php create mode 100644 Tests/NativeFormProcessorTest.php diff --git a/Button.php b/Button.php index 23c4775530..77af61b8d8 100644 --- a/Button.php +++ b/Button.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\AlreadyBoundException; +use Symfony\Component\Form\Exception\BadMethodCallException; /** * A form button. @@ -342,6 +343,18 @@ public function isSynchronized() return true; } + /** + * Unsupported method. + * + * @param mixed $request + * + * @throws BadMethodCallException + */ + public function process($request = null) + { + throw new BadMethodCallException('Buttons cannot be processed. Call process() on the root form instead.'); + } + /** * Binds data to the button. * diff --git a/ButtonBuilder.php b/ButtonBuilder.php index 9e61cbf403..fb77ef00ff 100644 --- a/ButtonBuilder.php +++ b/ButtonBuilder.php @@ -456,6 +456,42 @@ public function setFormFactory(FormFactoryInterface $formFactory) throw new \BadMethodCallException('Buttons do not support form factories.'); } + /** + * Unsupported method. + * + * @param string $action + * + * @throws \BadMethodCallException + */ + public function setAction($action) + { + throw new \BadMethodCallException('Buttons do not support actions.'); + } + + /** + * Unsupported method. + * + * @param string $method + * + * @throws \BadMethodCallException + */ + public function setMethod($method) + { + throw new \BadMethodCallException('Buttons do not support methods.'); + } + + /** + * Unsupported method. + * + * @param FormProcessorInterface $formProcessor + * + * @throws \BadMethodCallException + */ + public function setFormProcessor(FormProcessorInterface $formProcessor) + { + throw new \BadMethodCallException('Buttons do not support form processors.'); + } + /** * Builds and returns the button configuration. * @@ -693,6 +729,36 @@ public function getFormFactory() return null; } + /** + * Unsupported method. + * + * @return null Always returns null. + */ + public function getAction() + { + return null; + } + + /** + * Unsupported method. + * + * @return null Always returns null. + */ + public function getMethod() + { + return null; + } + + /** + * Unsupported method. + * + * @return null Always returns null. + */ + public function getFormProcessor() + { + return null; + } + /** * Returns all options passed during the construction of the button. * diff --git a/CHANGELOG.md b/CHANGELOG.md index b315af5cbc..40976fa8d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ CHANGELOG ------ * changed FormRenderer::humanize() to humanize also camel cased field name + * added FormProcessorInterface and FormInterface::process() + * deprecated passing a Request instance to FormInterface::bind() + * added options "method" and "action" to FormType 2.2.0 ----- diff --git a/Extension/Core/Type/FormType.php b/Extension/Core/Type/FormType.php index bd01f8f040..e51dba870e 100644 --- a/Extension/Core/Type/FormType.php +++ b/Extension/Core/Type/FormType.php @@ -53,6 +53,8 @@ public function buildForm(FormBuilderInterface $builder, array $options) ->setData(isset($options['data']) ? $options['data'] : null) ->setDataLocked(isset($options['data'])) ->setDataMapper($options['compound'] ? new PropertyPathMapper($this->propertyAccessor) : null) + ->setMethod($options['method']) + ->setAction($options['action']) ; if ($options['trim']) { @@ -93,6 +95,8 @@ public function buildView(FormView $view, FormInterface $form, array $options) 'size' => null, 'label_attr' => $options['label_attr'], 'compound' => $form->getConfig()->getCompound(), + 'method' => $form->getConfig()->getMethod(), + 'action' => $form->getConfig()->getAction(), )); } @@ -167,6 +171,10 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'label_attr' => array(), 'virtual' => false, 'compound' => true, + 'method' => 'POST', + // According to RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt) + // section 4.2., empty URIs are considered same-document references + 'action' => '', )); $resolver->setAllowedTypes(array( diff --git a/Extension/HttpFoundation/EventListener/BindRequestListener.php b/Extension/HttpFoundation/EventListener/BindRequestListener.php index b4d0ed7b13..1eb4e6f297 100644 --- a/Extension/HttpFoundation/EventListener/BindRequestListener.php +++ b/Extension/HttpFoundation/EventListener/BindRequestListener.php @@ -19,6 +19,9 @@ /** * @author Bernhard Schussek + * + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Pass the + * Request instance to {@link Form::process()} instead. */ class BindRequestListener implements EventSubscriberInterface { @@ -40,6 +43,8 @@ public function preBind(FormEvent $event) return; } + trigger_error('Passing a Request instance to Form::bind() is deprecated since version 2.3 and will be disabled in 3.0. Call Form::process($request) instead.', E_USER_DEPRECATED); + $name = $form->getConfig()->getName(); $default = $form->getConfig()->getCompound() ? array() : null; diff --git a/Extension/HttpFoundation/RequestFormProcessor.php b/Extension/HttpFoundation/RequestFormProcessor.php new file mode 100644 index 0000000000..c2f0b4de2c --- /dev/null +++ b/Extension/HttpFoundation/RequestFormProcessor.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Extension\HttpFoundation; + +use Symfony\Component\Form\Exception\InvalidArgumentException; +use Symfony\Component\Form\Exception\UnexpectedTypeException; +use Symfony\Component\Form\FormInterface; +use Symfony\Component\Form\FormProcessorInterface; +use Symfony\Component\HttpFoundation\Request; + +/** + * A form processor using the {@link Request} class of the HttpFoundation + * component. + * + * @author Bernhard Schussek + */ +class RequestFormProcessor implements FormProcessorInterface +{ + /** + * {@inheritdoc} + */ + public function processForm(FormInterface $form, $request = null) + { + if (!$request instanceof Request) { + throw new UnexpectedTypeException($request, 'Symfony\Component\HttpFoundation\Request'); + } + + $name = $form->getName(); + $method = $form->getConfig()->getMethod(); + + if ($method !== $request->getMethod()) { + return; + } + + if ('GET' === $method) { + if ('' === $name) { + $data = $request->query->all(); + } else { + // Don't bind GET requests if the form's name does not exist + // in the request + if (!$request->query->has($name)) { + return; + } + + $data = $request->query->get($name); + } + } else { + if ('' === $name) { + $params = $request->request->all(); + $files = $request->files->all(); + } else { + $default = $form->getConfig()->getCompound() ? array() : null; + $params = $request->request->get($name, $default); + $files = $request->files->get($name, $default); + } + + if (is_array($params) && is_array($files)) { + $data = array_replace_recursive($params, $files); + } else { + $data = $params ?: $files; + } + } + + // Don't auto-bind the form unless at least one field is submitted. + if ('' === $name && count(array_intersect_key($data, $form->all())) <= 0) { + return; + } + + $form->bind($data); + } +} diff --git a/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php b/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php index 936f58efdd..28e6e7c816 100644 --- a/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php +++ b/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php @@ -13,6 +13,7 @@ use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\Extension\HttpFoundation\EventListener\BindRequestListener; +use Symfony\Component\Form\Extension\HttpFoundation\RequestFormProcessor; use Symfony\Component\Form\FormBuilderInterface; /** @@ -25,9 +26,15 @@ class FormTypeHttpFoundationExtension extends AbstractTypeExtension */ private $listener; + /** + * @var RequestFormProcessor + */ + private $processor; + public function __construct() { $this->listener = new BindRequestListener(); + $this->processor = new RequestFormProcessor(); } /** @@ -36,6 +43,7 @@ public function __construct() public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addEventSubscriber($this->listener); + $builder->setFormProcessor($this->processor); } /** diff --git a/Form.php b/Form.php index 3471979411..3b95817be0 100644 --- a/Form.php +++ b/Form.php @@ -404,6 +404,16 @@ public function getExtraData() return $this->extraData; } + /** + * {@inheritdoc} + */ + public function process($request = null) + { + $this->config->getFormProcessor()->processForm($this, $request); + + return $this; + } + /** * {@inheritdoc} */ @@ -579,7 +589,7 @@ public function isEmpty() public function isValid() { if (!$this->bound) { - throw new \LogicException('You cannot call isValid() on a form that is not bound.'); + return false; } if (count($this->errors) > 0) { diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index c52b4169e8..694b94555e 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\BadMethodCallException; -use Symfony\Component\Form\Exception\Exception; +use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\PropertyAccess\PropertyPathInterface; @@ -27,6 +27,26 @@ */ class FormConfigBuilder implements FormConfigBuilderInterface { + /** + * Caches a globally unique {@link NativeFormProcessor} instance. + * + * @var NativeFormProcessor + */ + private static $nativeFormProcessor; + + /** + * The accepted request methods. + * + * @var array + */ + private static $allowedMethods = array( + 'GET', + 'PUT', + 'POST', + 'DELETE', + 'PATCH' + ); + /** * @var Boolean */ @@ -137,6 +157,21 @@ class FormConfigBuilder implements FormConfigBuilderInterface */ private $formFactory; + /** + * @var string + */ + private $action; + + /** + * @var string + */ + private $method = 'POST'; + + /** + * @var FormProcessorInterface + */ + private $formProcessor; + /** * @var array */ @@ -264,6 +299,10 @@ public function resetModelTransformers() */ public function getEventDispatcher() { + if ($this->locked && !$this->dispatcher instanceof ImmutableEventDispatcher) { + $this->dispatcher = new ImmutableEventDispatcher($this->dispatcher); + } + return $this->dispatcher; } @@ -435,6 +474,37 @@ public function getFormFactory() return $this->formFactory; } + /** + * {@inheritdoc} + */ + public function getAction() + { + return $this->action; + } + + /** + * {@inheritdoc} + */ + public function getMethod() + { + return $this->method; + } + + /** + * {@inheritdoc} + */ + public function getFormProcessor() + { + if (null === $this->formProcessor) { + if (null === self::$nativeFormProcessor) { + self::$nativeFormProcessor = new NativeFormProcessor(); + } + $this->formProcessor = self::$nativeFormProcessor; + } + + return $this->formProcessor; + } + /** * {@inheritdoc} */ @@ -687,6 +757,58 @@ public function setFormFactory(FormFactoryInterface $formFactory) return $this; } + /** + * {@inheritdoc} + */ + public function setAction($action) + { + if ($this->locked) { + throw new BadMethodCallException('The config builder cannot be modified anymore.'); + } + + $this->action = $action; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function setMethod($method) + { + if ($this->locked) { + throw new BadMethodCallException('The config builder cannot be modified anymore.'); + } + + $upperCaseMethod = strtoupper($method); + + if (!in_array($upperCaseMethod, self::$allowedMethods)) { + throw new InvalidArgumentException(sprintf( + 'The form method is "%s", but should be one of "%s".', + $method, + implode('", "', self::$allowedMethods) + )); + } + + $this->method = $upperCaseMethod; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function setFormProcessor(FormProcessorInterface $formProcessor) + { + if ($this->locked) { + throw new BadMethodCallException('The config builder cannot be modified anymore.'); + } + + $this->formProcessor = $formProcessor; + + return $this; + } + /** * {@inheritdoc} */ @@ -700,10 +822,6 @@ public function getFormConfig() $config = clone $this; $config->locked = true; - if (!$config->dispatcher instanceof ImmutableEventDispatcher) { - $config->dispatcher = new ImmutableEventDispatcher($config->dispatcher); - } - return $config; } diff --git a/FormConfigBuilderInterface.php b/FormConfigBuilderInterface.php index c0d8c2b1f9..34b217e623 100644 --- a/FormConfigBuilderInterface.php +++ b/FormConfigBuilderInterface.php @@ -237,6 +237,31 @@ public function setDataLocked($locked); */ public function setFormFactory(FormFactoryInterface $formFactory); + /** + * Sets the target URL of the form. + * + * @param string $action The target URL of the form. + * + * @return self The configuration object. + */ + public function setAction($action); + + /** + * Sets the HTTP method used by the form. + * + * @param string $method The HTTP method of the form. + * + * @return self The configuration object. + */ + public function setMethod($method); + + /** + * @param FormProcessorInterface $formProcessor + * + * @return self The configuration object. + */ + public function setFormProcessor(FormProcessorInterface $formProcessor); + /** * Builds and returns the form configuration. * diff --git a/FormConfigInterface.php b/FormConfigInterface.php index 002b54cfac..e00ce27f43 100644 --- a/FormConfigInterface.php +++ b/FormConfigInterface.php @@ -190,6 +190,25 @@ public function getDataLocked(); */ public function getFormFactory(); + /** + * Returns the target URL of the form. + * + * @return string The target URL of the form. + */ + public function getAction(); + + /** + * Returns the HTTP method used by the form. + * + * @return string The HTTP method of the form. + */ + public function getMethod(); + + /** + * @return FormProcessorInterface The form processor. + */ + public function getFormProcessor(); + /** * Returns all options passed during the construction of the form. * diff --git a/FormInterface.php b/FormInterface.php index 3e8fe525ec..05d95b2282 100644 --- a/FormInterface.php +++ b/FormInterface.php @@ -182,6 +182,8 @@ public function addError(FormError $error); /** * Returns whether the form and all children are valid. * + * If the form is not bound, this method always returns false. + * * @return Boolean */ public function isValid(); @@ -224,6 +226,19 @@ public function isEmpty(); */ public function isSynchronized(); + /** + * Processes the given request and binds the form if it was submitted. + * + * Internally, the request is forwarded to a {@link FormProcessorInterface} + * instance. This instance determines the allowed value of the + * $request parameter. + * + * @param mixed $request The request to check. + * + * @return FormInterface The form instance. + */ + public function process($request = null); + /** * Binds data to the form, transforms and validates it. * diff --git a/FormProcessorInterface.php b/FormProcessorInterface.php new file mode 100644 index 0000000000..3634524b8d --- /dev/null +++ b/FormProcessorInterface.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form; + +/** + * Binds forms from requests if they were submitted. + * + * @author Bernhard Schussek + */ +interface FormProcessorInterface +{ + /** + * Binds a form from a request if it was submitted. + * + * @param FormInterface $form The form to bind. + * @param mixed $request The current request. + */ + public function processForm(FormInterface $form, $request = null); +} diff --git a/NativeFormProcessor.php b/NativeFormProcessor.php new file mode 100644 index 0000000000..7494c84eaf --- /dev/null +++ b/NativeFormProcessor.php @@ -0,0 +1,194 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form; + +use Symfony\Component\Form\Exception\UnexpectedTypeException; +use Symfony\Component\Form\FormInterface; +use Symfony\Component\Form\FormProcessorInterface; + +/** + * A form processor using PHP's super globals $_GET, $_POST and $_SERVER. + * + * @author Bernhard Schussek + */ +class NativeFormProcessor implements FormProcessorInterface +{ + /** + * The allowed keys of the $_FILES array. + * + * @var array + */ + private static $fileKeys = array( + 'error', + 'name', + 'size', + 'tmp_name', + 'type', + ); + + /** + * {@inheritdoc} + */ + public function processForm(FormInterface $form, $request = null) + { + if (null !== $request) { + throw new UnexpectedTypeException($request, 'null'); + } + + $name = $form->getName(); + $method = $form->getConfig()->getMethod(); + + if ($method !== self::getRequestMethod()) { + return; + } + + if ('GET' === $method) { + if ('' === $name) { + $data = $_GET; + } else { + // Don't bind GET requests if the form's name does not exist + // in the request + if (!isset($_GET[$name])) { + return; + } + + $data = $_GET[$name]; + } + } else { + $fixedFiles = array(); + foreach ($_FILES as $name => $file) { + $fixedFiles[$name] = self::stripEmptyFiles(self::fixPhpFilesArray($file)); + } + + if ('' === $name) { + $params = $_POST; + $files = $fixedFiles; + } else { + $default = $form->getConfig()->getCompound() ? array() : null; + $params = isset($_POST[$name]) ? $_POST[$name] : $default; + $files = isset($fixedFiles[$name]) ? $fixedFiles[$name] : $default; + } + + if (is_array($params) && is_array($files)) { + $data = array_replace_recursive($params, $files); + } else { + $data = $params ?: $files; + } + } + + // Don't auto-bind the form unless at least one field is submitted. + if ('' === $name && count(array_intersect_key($data, $form->all())) <= 0) { + return; + } + + $form->bind($data); + } + + /** + * Returns the method used to submit the request to the server. + * + * @return string The request method. + */ + private static function getRequestMethod() + { + $method = isset($_SERVER['REQUEST_METHOD']) + ? strtoupper($_SERVER['REQUEST_METHOD']) + : 'GET'; + + if ('POST' === $method && isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) { + $method = strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']); + } + + return $method; + } + + /** + * Fixes a malformed PHP $_FILES array. + * + * PHP has a bug that the format of the $_FILES array differs, depending on + * whether the uploaded file fields had normal field names or array-like + * field names ("normal" vs. "parent[child]"). + * + * This method fixes the array to look like the "normal" $_FILES array. + * + * It's safe to pass an already converted array, in which case this method + * just returns the original array unmodified. + * + * This method is identical to {@link Symfony\Component\HttpFoundation\FileBag::fixPhpFilesArray} + * and should be kept as such in order to port fixes quickly and easily. + * + * @param array $data + * + * @return array + */ + private static function fixPhpFilesArray($data) + { + if (!is_array($data)) { + return $data; + } + + $keys = array_keys($data); + sort($keys); + + if (self::$fileKeys !== $keys || !isset($data['name']) || !is_array($data['name'])) { + return $data; + } + + $files = $data; + foreach (self::$fileKeys as $k) { + unset($files[$k]); + } + + foreach (array_keys($data['name']) as $key) { + $files[$key] = self::fixPhpFilesArray(array( + 'error' => $data['error'][$key], + 'name' => $data['name'][$key], + 'type' => $data['type'][$key], + 'tmp_name' => $data['tmp_name'][$key], + 'size' => $data['size'][$key] + )); + } + + return $files; + } + + /** + * Sets empty uploaded files to NULL in the given uploaded files array. + * + * @param mixed $data The file upload data. + * + * @return array|null Returns the stripped upload data. + */ + private static function stripEmptyFiles($data) + { + if (!is_array($data)) { + return $data; + } + + $keys = array_keys($data); + sort($keys); + + if (self::$fileKeys === $keys) { + if (UPLOAD_ERR_NO_FILE === $data['error']) { + return null; + } + + return $data; + } + + foreach ($data as $key => $value) { + $data[$key] = self::stripEmptyFiles($value); + } + + return $data; + } +} diff --git a/Test/DeprecationErrorHandler.php b/Test/DeprecationErrorHandler.php index 21b3a6e6b0..a2cce590be 100644 --- a/Test/DeprecationErrorHandler.php +++ b/Test/DeprecationErrorHandler.php @@ -2,6 +2,8 @@ namespace Symfony\Component\Form\Test; +use Symfony\Component\Form\FormEvent; + class DeprecationErrorHandler { public static function handle($errorNumber, $message, $file, $line, $context) @@ -21,4 +23,11 @@ public static function handleBC($errorNumber, $message, $file, $line, $context) return false; } + + public static function preBind($listener, FormEvent $event) + { + set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); + $listener->preBind($event); + restore_error_handler(); + } } diff --git a/Tests/AbstractDivLayoutTest.php b/Tests/AbstractDivLayoutTest.php index 391e81173e..23cecaee94 100644 --- a/Tests/AbstractDivLayoutTest.php +++ b/Tests/AbstractDivLayoutTest.php @@ -378,6 +378,50 @@ public function testCollectionRow() } public function testForm() + { + $form = $this->factory->createNamedBuilder('name', 'form') + ->setMethod('PUT') + ->setAction('http://example.com') + ->add('firstName', 'text') + ->add('lastName', 'text') + ->getForm(); + + // include ampersands everywhere to validate escaping + $html = $this->renderForm($form->createView(), array( + 'id' => 'my&id', + 'attr' => array('class' => 'my&class'), + )); + + $this->assertMatchesXpath($html, +'/form + [ + ./input[@type="hidden"][@name="_method"][@value="PUT"] + /following-sibling::div + [ + ./div + [ + ./label[@for="name_firstName"] + /following-sibling::input[@type="text"][@id="name_firstName"] + ] + /following-sibling::div + [ + ./label[@for="name_lastName"] + /following-sibling::input[@type="text"][@id="name_lastName"] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] + [count(.//input)=3] + [@id="my&id"] + [@class="my&class"] + ] + [@method="post"] + [@action="http://example.com"] + [@class="my&class"] +' + ); + } + + public function testFormWidget() { $form = $this->factory->createNamedBuilder('name', 'form') ->add('firstName', 'text') @@ -642,4 +686,50 @@ public function testCollectionRowWithCustomBlock() ' ); } + + public function testFormEndWithRest() + { + $view = $this->factory->createNamedBuilder('name', 'form') + ->add('field1', 'text') + ->add('field2', 'text') + ->getForm() + ->createView(); + + $this->renderWidget($view['field1']); + + // Rest should only contain field2 + $html = $this->renderEnd($view); + + // Insert the start tag, the end tag should be rendered by the helper + $this->assertMatchesXpath('
' . $html, +'/form + [ + ./div + [ + ./label[@for="name_field2"] + /following-sibling::input[@type="text"][@id="name_field2"] + ] + /following-sibling::input + [@type="hidden"] + [@id="name__token"] + ] +' + ); + } + + public function testFormEndWithoutRest() + { + $view = $this->factory->createNamedBuilder('name', 'form') + ->add('field1', 'text') + ->add('field2', 'text') + ->getForm() + ->createView(); + + $this->renderWidget($view['field1']); + + // Rest should only contain field2, but isn't rendered + $html = $this->renderEnd($view, array('render_rest' => false)); + + $this->assertEquals('
', $html); + } } diff --git a/Tests/AbstractFormProcessorTest.php b/Tests/AbstractFormProcessorTest.php new file mode 100644 index 0000000000..40270b2c0e --- /dev/null +++ b/Tests/AbstractFormProcessorTest.php @@ -0,0 +1,280 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +/** + * @author Bernhard Schussek + */ +abstract class AbstractFormProcessorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Symfony\Component\Form\FormProcessorInterface + */ + protected $processor; + + protected $request; + + protected function setUp() + { + $this->processor = $this->getFormProcessor(); + $this->request = null; + } + + public function methodExceptGetProvider() + { + return array( + array('POST'), + array('PUT'), + array('DELETE'), + array('PATCH'), + ); + } + + public function methodProvider() + { + return array_merge(array( + array('GET'), + ), $this->methodExceptGetProvider()); + } + + /** + * @dataProvider methodProvider + */ + public function testBindIfNameInRequest($method) + { + $form = $this->getMockForm('param1', $method); + + $this->setRequestData($method, array( + 'param1' => 'DATA', + )); + + $form->expects($this->once()) + ->method('bind') + ->with('DATA'); + + $this->processor->processForm($form, $this->request); + } + + /** + * @dataProvider methodProvider + */ + public function testDoNotBindIfWrongRequestMethod($method) + { + $form = $this->getMockForm('param1', $method); + + $otherMethod = 'POST' === $method ? 'PUT' : 'POST'; + + $this->setRequestData($otherMethod, array( + 'param1' => 'DATA', + )); + + $form->expects($this->never()) + ->method('bind'); + + $this->processor->processForm($form, $this->request); + } + + /** + * @dataProvider methodExceptGetProvider + */ + public function testBindSimpleFormWithNullIfNameNotInRequestAndNotGetRequest($method) + { + $form = $this->getMockForm('param1', $method, false); + + $this->setRequestData($method, array( + 'paramx' => array(), + )); + + $form->expects($this->once()) + ->method('bind') + ->with($this->identicalTo(null)); + + $this->processor->processForm($form, $this->request); + } + + /** + * @dataProvider methodExceptGetProvider + */ + public function testBindCompoundFormWithArrayIfNameNotInRequestAndNotGetRequest($method) + { + $form = $this->getMockForm('param1', $method, true); + + $this->setRequestData($method, array( + 'paramx' => array(), + )); + + $form->expects($this->once()) + ->method('bind') + ->with($this->identicalTo(array())); + + $this->processor->processForm($form, $this->request); + } + + public function testDoNotBindIfNameNotInRequestAndGetRequest() + { + $form = $this->getMockForm('param1', 'GET'); + + $this->setRequestData('GET', array( + 'paramx' => array(), + )); + + $form->expects($this->never()) + ->method('bind'); + + $this->processor->processForm($form, $this->request); + } + + /** + * @dataProvider methodProvider + */ + public function testBindFormWithEmptyNameIfAtLeastOneFieldInRequest($method) + { + $form = $this->getMockForm('', $method); + $form->expects($this->any()) + ->method('all') + ->will($this->returnValue(array( + 'param1' => $this->getMockForm('param1'), + 'param2' => $this->getMockForm('param2'), + ))); + + $this->setRequestData($method, $requestData = array( + 'param1' => 'submitted value', + 'paramx' => 'submitted value', + )); + + $form->expects($this->once()) + ->method('bind') + ->with($requestData); + + $this->processor->processForm($form, $this->request); + } + + /** + * @dataProvider methodProvider + */ + public function testDoNotBindFormWithEmptyNameIfNoFieldInRequest($method) + { + $form = $this->getMockForm('', $method); + $form->expects($this->any()) + ->method('all') + ->will($this->returnValue(array( + 'param1' => $this->getMockForm('param1'), + 'param2' => $this->getMockForm('param2'), + ))); + + $this->setRequestData($method, array( + 'paramx' => 'submitted value', + )); + + $form->expects($this->never()) + ->method('bind'); + + $this->processor->processForm($form, $this->request); + } + + /** + * @dataProvider methodExceptGetProvider + */ + public function testMergeParamsAndFiles($method) + { + $form = $this->getMockForm('param1', $method); + $file = $this->getMockFile(); + + $this->setRequestData($method, array( + 'param1' => array( + 'field1' => 'DATA', + ), + ), array( + 'param1' => array( + 'field2' => $file, + ), + )); + + $form->expects($this->once()) + ->method('bind') + ->with(array( + 'field1' => 'DATA', + 'field2' => $file, + )); + + $this->processor->processForm($form, $this->request); + } + + /** + * @dataProvider methodExceptGetProvider + */ + public function testParamTakesPrecedenceOverFile($method) + { + $form = $this->getMockForm('param1', $method); + $file = $this->getMockFile(); + + $this->setRequestData($method, array( + 'param1' => 'DATA', + ), array( + 'param1' => $file, + )); + + $form->expects($this->once()) + ->method('bind') + ->with('DATA'); + + $this->processor->processForm($form, $this->request); + } + + /** + * @dataProvider methodExceptGetProvider + */ + public function testBindFileIfNoParam($method) + { + $form = $this->getMockForm('param1', $method); + $file = $this->getMockFile(); + + $this->setRequestData($method, array( + 'param1' => null, + ), array( + 'param1' => $file, + )); + + $form->expects($this->once()) + ->method('bind') + ->with($file); + + $this->processor->processForm($form, $this->request); + } + + abstract protected function setRequestData($method, $data, $files = array()); + + abstract protected function getFormProcessor(); + + abstract protected function getMockFile(); + + protected function getMockForm($name, $method = null, $compound = true) + { + $config = $this->getMock('Symfony\Component\Form\FormConfigInterface'); + $config->expects($this->any()) + ->method('getMethod') + ->will($this->returnValue($method)); + $config->expects($this->any()) + ->method('getCompound') + ->will($this->returnValue($compound)); + + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); + $form->expects($this->any()) + ->method('getName') + ->will($this->returnValue($name)); + $form->expects($this->any()) + ->method('getConfig') + ->will($this->returnValue($config)); + + return $form; + } +} diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index 1dda383253..176fb17962 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -19,8 +19,6 @@ abstract class AbstractLayoutTest extends FormIntegrationTestCase { protected $csrfProvider; - protected $factory; - protected function setUp() { if (!extension_loaded('intl')) { @@ -44,7 +42,6 @@ protected function getExtensions() protected function tearDown() { $this->csrfProvider = null; - $this->factory = null; parent::tearDown(); } @@ -102,6 +99,8 @@ protected function assertWidgetMatchesXpath(FormView $view, array $vars, $xpath) $this->assertMatchesXpath($html, $xpath); } + abstract protected function renderForm(FormView $view, array $vars = array()); + abstract protected function renderEnctype(FormView $view); abstract protected function renderLabel(FormView $view, $label = null, array $vars = array()); @@ -114,6 +113,10 @@ abstract protected function renderRow(FormView $view, array $vars = array()); abstract protected function renderRest(FormView $view, array $vars = array()); + abstract protected function renderStart(FormView $view, array $vars = array()); + + abstract protected function renderEnd(FormView $view, array $vars = array()); + abstract protected function setTheme(FormView $view, array $themes); public function testEnctype() @@ -1744,9 +1747,7 @@ public function testCollectionPrototype() $this->assertMatchesXpath($html, '//div[@id="name_items"][@data-prototype] | - //table[@id="name_items"][@data-prototype] - -' + //table[@id="name_items"][@data-prototype]' ); } @@ -1796,4 +1797,76 @@ public function testReset() '/button[@type="reset"][@name="name"]' ); } + + public function testStartTag() + { + $form = $this->factory->create('form', null, array( + 'method' => 'get', + 'action' => 'http://example.com/directory' + )); + + $html = $this->renderStart($form->createView()); + + $this->assertSame('
', $html); + } + + public function testStartTagForPutRequest() + { + $form = $this->factory->create('form', null, array( + 'method' => 'put', + 'action' => 'http://example.com/directory' + )); + + $html = $this->renderStart($form->createView()); + + $this->assertMatchesXpath($html . '
', +'/form + [./input[@type="hidden"][@name="_method"][@value="PUT"]] + [@method="post"] + [@action="http://example.com/directory"]' + ); + } + + public function testStartTagWithOverriddenVars() + { + $form = $this->factory->create('form', null, array( + 'method' => 'put', + 'action' => 'http://example.com/directory', + )); + + $html = $this->renderStart($form->createView(), array( + 'method' => 'post', + 'action' => 'http://foo.com/directory' + )); + + $this->assertSame('
', $html); + } + + public function testStartTagForMultipartForm() + { + $form = $this->factory->createBuilder('form', null, array( + 'method' => 'get', + 'action' => 'http://example.com/directory' + )) + ->add('file', 'file') + ->getForm(); + + $html = $this->renderStart($form->createView()); + + $this->assertSame('', $html); + } + + public function testStartTagWithExtraAttributes() + { + $form = $this->factory->create('form', null, array( + 'method' => 'get', + 'action' => 'http://example.com/directory' + )); + + $html = $this->renderStart($form->createView(), array( + 'attr' => array('class' => 'foobar'), + )); + + $this->assertSame('', $html); + } } diff --git a/Tests/AbstractTableLayoutTest.php b/Tests/AbstractTableLayoutTest.php index 28fdba2dda..5c91195169 100644 --- a/Tests/AbstractTableLayoutTest.php +++ b/Tests/AbstractTableLayoutTest.php @@ -224,6 +224,58 @@ public function testEmptyCollection() } public function testForm() + { + $view = $this->factory->createNamedBuilder('name', 'form') + ->setMethod('PUT') + ->setAction('http://example.com') + ->add('firstName', 'text') + ->add('lastName', 'text') + ->getForm() + ->createView(); + + $html = $this->renderForm($view, array( + 'id' => 'my&id', + 'attr' => array('class' => 'my&class'), + )); + + $this->assertMatchesXpath($html, +'/form + [ + ./input[@type="hidden"][@name="_method"][@value="PUT"] + /following-sibling::table + [ + ./tr + [ + ./td + [./label[@for="name_firstName"]] + /following-sibling::td + [./input[@id="name_firstName"]] + ] + /following-sibling::tr + [ + ./td + [./label[@for="name_lastName"]] + /following-sibling::td + [./input[@id="name_lastName"]] + ] + /following-sibling::tr[@style="display: none"] + [./td[@colspan="2"]/input + [@type="hidden"] + [@id="name__token"] + ] + ] + [count(.//input)=3] + [@id="my&id"] + [@class="my&class"] + ] + [@method="post"] + [@action="http://example.com"] + [@class="my&class"] +' + ); + } + + public function testFormWidget() { $view = $this->factory->createNamedBuilder('name', 'form') ->add('firstName', 'text') @@ -400,4 +452,58 @@ public function testCollectionRowWithCustomBlock() ' ); } + + public function testFormEndWithRest() + { + $view = $this->factory->createNamedBuilder('name', 'form') + ->add('field1', 'text') + ->add('field2', 'text') + ->getForm() + ->createView(); + + $this->renderWidget($view['field1']); + + // Rest should only contain field2 + $html = $this->renderEnd($view); + + // Insert the start tag, the end tag should be rendered by the helper + // Unfortunately this is not valid HTML, because the surrounding table + // tag is missing. If someone renders a form with table layout + // manually, she should call form_rest() explicitly within the + // tag. + $this->assertMatchesXpath('' . $html, +'/form + [ + ./tr + [ + ./td + [./label[@for="name_field2"]] + /following-sibling::td + [./input[@id="name_field2"]] + ] + /following-sibling::tr[@style="display: none"] + [./td[@colspan="2"]/input + [@type="hidden"] + [@id="name__token"] + ] + ] +' + ); + } + + public function testFormEndWithoutRest() + { + $view = $this->factory->createNamedBuilder('name', 'form') + ->add('field1', 'text') + ->add('field2', 'text') + ->getForm() + ->createView(); + + $this->renderWidget($view['field1']); + + // Rest should only contain field2, but isn't rendered + $html = $this->renderEnd($view, array('render_rest' => false)); + + $this->assertEquals('', $html); + } } diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index 06e9b4d19e..1d52075d6c 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -11,9 +11,8 @@ namespace Symfony\Component\Form\Tests; -use Symfony\Component\Form\Form; +use Symfony\Component\Form\Extension\HttpFoundation\RequestFormProcessor; use Symfony\Component\Form\FormError; -use Symfony\Component\Form\Extension\HttpFoundation\EventListener\BindRequestListener; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer; @@ -421,14 +420,15 @@ public function testBindPostOrPutRequest($method) )); $form = $this->getBuilder('author') + ->setMethod($method) ->setCompound(true) ->setDataMapper($this->getDataMapper()) - ->addEventSubscriber(new BindRequestListener()) + ->setFormProcessor(new RequestFormProcessor()) ->getForm(); $form->add($this->getBuilder('name')->getForm()); $form->add($this->getBuilder('image')->getForm()); - $form->bind($request); + $form->process($request); $file = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK); @@ -470,14 +470,15 @@ public function testBindPostOrPutRequestWithEmptyRootFormName($method) )); $form = $this->getBuilder('') + ->setMethod($method) ->setCompound(true) ->setDataMapper($this->getDataMapper()) - ->addEventSubscriber(new BindRequestListener()) + ->setFormProcessor(new RequestFormProcessor()) ->getForm(); $form->add($this->getBuilder('name')->getForm()); $form->add($this->getBuilder('image')->getForm()); - $form->bind($request); + $form->process($request); $file = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK); @@ -515,10 +516,11 @@ public function testBindPostOrPutRequestWithSingleChildForm($method) )); $form = $this->getBuilder('image') - ->addEventSubscriber(new BindRequestListener()) + ->setMethod($method) + ->setFormProcessor(new RequestFormProcessor()) ->getForm(); - $form->bind($request); + $form->process($request); $file = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK); @@ -548,10 +550,11 @@ public function testBindPostOrPutRequestWithSingleChildFormUploadedFile($method) )); $form = $this->getBuilder('name') - ->addEventSubscriber(new BindRequestListener()) + ->setMethod($method) + ->setFormProcessor(new RequestFormProcessor()) ->getForm(); - $form->bind($request); + $form->process($request); $this->assertEquals('Bernhard', $form->getData()); @@ -576,14 +579,15 @@ public function testBindGetRequest() )); $form = $this->getBuilder('author') + ->setMethod('GET') ->setCompound(true) ->setDataMapper($this->getDataMapper()) - ->addEventSubscriber(new BindRequestListener()) + ->setFormProcessor(new RequestFormProcessor()) ->getForm(); $form->add($this->getBuilder('firstName')->getForm()); $form->add($this->getBuilder('lastName')->getForm()); - $form->bind($request); + $form->process($request); $this->assertEquals('Bernhard', $form['firstName']->getData()); $this->assertEquals('Schussek', $form['lastName']->getData()); @@ -606,14 +610,15 @@ public function testBindGetRequestWithEmptyRootFormName() )); $form = $this->getBuilder('') + ->setMethod('GET') ->setCompound(true) ->setDataMapper($this->getDataMapper()) - ->addEventSubscriber(new BindRequestListener()) + ->setFormProcessor(new RequestFormProcessor()) ->getForm(); $form->add($this->getBuilder('firstName')->getForm()); $form->add($this->getBuilder('lastName')->getForm()); - $form->bind($request); + $form->process($request); $this->assertEquals('Bernhard', $form['firstName']->getData()); $this->assertEquals('Schussek', $form['lastName']->getData()); diff --git a/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php b/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php index bfb9afa0a7..0c534fd0be 100644 --- a/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php +++ b/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php @@ -15,6 +15,7 @@ use Symfony\Component\Form\Form; use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\Form\FormEvent; +use Symfony\Component\Form\Test\DeprecationErrorHandler; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\File\UploadedFile; @@ -101,7 +102,7 @@ public function testBindRequest($method) $event = new FormEvent($form, $request); $listener = new BindRequestListener(); - $listener->preBind($event); + DeprecationErrorHandler::preBind($listener, $event); $this->assertEquals(array( 'name' => 'Bernhard', @@ -128,7 +129,7 @@ public function testBindRequestWithEmptyName($method) $event = new FormEvent($form, $request); $listener = new BindRequestListener(); - $listener->preBind($event); + DeprecationErrorHandler::preBind($listener, $event); $this->assertEquals(array( 'name' => 'Bernhard', @@ -157,7 +158,7 @@ public function testBindEmptyRequestToCompoundForm($method) $event = new FormEvent($form, $request); $listener = new BindRequestListener(); - $listener->preBind($event); + DeprecationErrorHandler::preBind($listener, $event); // Default to empty array $this->assertEquals(array(), $event->getData()); @@ -183,7 +184,7 @@ public function testBindEmptyRequestToSimpleForm($method) $event = new FormEvent($form, $request); $listener = new BindRequestListener(); - $listener->preBind($event); + DeprecationErrorHandler::preBind($listener, $event); // Default to null $this->assertNull($event->getData()); @@ -206,7 +207,7 @@ public function testBindGetRequest() $event = new FormEvent($form, $request); $listener = new BindRequestListener(); - $listener->preBind($event); + DeprecationErrorHandler::preBind($listener, $event); $this->assertEquals(array( 'name' => 'Bernhard', @@ -230,7 +231,7 @@ public function testBindGetRequestWithEmptyName() $event = new FormEvent($form, $request); $listener = new BindRequestListener(); - $listener->preBind($event); + DeprecationErrorHandler::preBind($listener, $event); $this->assertEquals(array( 'name' => 'Bernhard', @@ -256,7 +257,7 @@ public function testBindEmptyGetRequestToCompoundForm() $event = new FormEvent($form, $request); $listener = new BindRequestListener(); - $listener->preBind($event); + DeprecationErrorHandler::preBind($listener, $event); $this->assertEquals(array(), $event->getData()); } @@ -278,7 +279,7 @@ public function testBindEmptyGetRequestToSimpleForm() $event = new FormEvent($form, $request); $listener = new BindRequestListener(); - $listener->preBind($event); + DeprecationErrorHandler::preBind($listener, $event); $this->assertNull($event->getData()); } diff --git a/Tests/Extension/HttpFoundation/RequestFormProcessorTest.php b/Tests/Extension/HttpFoundation/RequestFormProcessorTest.php new file mode 100644 index 0000000000..95e522c474 --- /dev/null +++ b/Tests/Extension/HttpFoundation/RequestFormProcessorTest.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\HttpFoundation; + +use Symfony\Component\Form\Extension\HttpFoundation\RequestFormProcessor; +use Symfony\Component\Form\Tests\AbstractFormProcessorTest; +use Symfony\Component\HttpFoundation\Request; + +/** + * @author Bernhard Schussek + */ +class RequestFormProcessorTest extends AbstractFormProcessorTest +{ + /** + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException + */ + public function testRequestShouldNotBeNull() + { + $this->processor->processForm($this->getMockForm('name', 'GET')); + } + /** + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException + */ + public function testRequestShouldBeInstanceOfRequest() + { + $this->processor->processForm($this->getMockForm('name', 'GET'), new \stdClass()); + } + + protected function setRequestData($method, $data, $files = array()) + { + $this->request = Request::create('http://localhost', $method, $data, array(), $files); + } + + protected function getFormProcessor() + { + return new RequestFormProcessor(); + } + + protected function getMockFile() + { + return $this->getMockBuilder('Symfony\Component\HttpFoundation\File\UploadedFile') + ->disableOriginalConstructor() + ->getMock(); + } +} diff --git a/Tests/FormConfigTest.php b/Tests/FormConfigTest.php index a7626f86a6..4337a2ab68 100644 --- a/Tests/FormConfigTest.php +++ b/Tests/FormConfigTest.php @@ -12,12 +12,11 @@ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\Exception\UnexpectedTypeException; +use Symfony\Component\Form\FormConfigBuilder; /** * @author Bernhard Schussek */ -use Symfony\Component\Form\FormConfigBuilder; - class FormConfigTest extends \PHPUnit_Framework_TestCase { public function getHtml4Ids() @@ -90,4 +89,59 @@ public function testNameAcceptsOnlyNamesValidAsIdsInHtml4($name, $accepted) } } } + + public function testGetFormProcessorCreatesNativeFormProcessorIfNotSet() + { + $config = $this->getConfigBuilder()->getFormConfig(); + + $this->assertInstanceOf('Symfony\Component\Form\NativeFormProcessor', $config->getFormProcessor()); + } + + public function testGetFormProcessorReusesNativeFormProcessorInstance() + { + $config1 = $this->getConfigBuilder()->getFormConfig(); + $config2 = $this->getConfigBuilder()->getFormConfig(); + + $this->assertSame($config1->getFormProcessor(), $config2->getFormProcessor()); + } + + public function testSetMethodAllowsGet() + { + $this->getConfigBuilder()->setMethod('GET'); + } + + public function testSetMethodAllowsPost() + { + $this->getConfigBuilder()->setMethod('POST'); + } + + public function testSetMethodAllowsPut() + { + $this->getConfigBuilder()->setMethod('PUT'); + } + + public function testSetMethodAllowsDelete() + { + $this->getConfigBuilder()->setMethod('DELETE'); + } + + public function testSetMethodAllowsPatch() + { + $this->getConfigBuilder()->setMethod('PATCH'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\FormException + */ + public function testSetMethodDoesNotAllowOtherValues() + { + $this->getConfigBuilder()->setMethod('foo'); + } + + private function getConfigBuilder($name = 'name') + { + $dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + + return new FormConfigBuilder($name, null, $dispatcher); + } } diff --git a/Tests/FormIntegrationTestCase.php b/Tests/FormIntegrationTestCase.php index 536ff4c824..e72ec4723b 100644 --- a/Tests/FormIntegrationTestCase.php +++ b/Tests/FormIntegrationTestCase.php @@ -32,6 +32,15 @@ protected function setUp() $this->factory = Forms::createFormFactoryBuilder() ->addExtensions($this->getExtensions()) ->getFormFactory(); + + set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); + } + + protected function tearDown() + { + $this->factory = null; + + restore_error_handler(); } protected function getExtensions() diff --git a/Tests/NativeFormProcessorTest.php b/Tests/NativeFormProcessorTest.php new file mode 100644 index 0000000000..4e90e5276c --- /dev/null +++ b/Tests/NativeFormProcessorTest.php @@ -0,0 +1,219 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +use Symfony\Component\Form\NativeFormProcessor; + +/** + * @author Bernhard Schussek + */ +class NativeFormProcessorTest extends AbstractFormProcessorTest +{ + private static $serverBackup; + + public static function setUpBeforeClass() + { + self::$serverBackup = $_SERVER; + } + + protected function setUp() + { + parent::setUp(); + + $_GET = array(); + $_POST = array(); + $_FILES = array(); + $_SERVER = array( + // PHPUnit needs this entry + 'SCRIPT_NAME' => self::$serverBackup['SCRIPT_NAME'], + ); + } + + protected function tearDown() + { + parent::tearDown(); + + $_GET = array(); + $_POST = array(); + $_FILES = array(); + $_SERVER = self::$serverBackup; + } + + /** + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException + */ + public function testRequestShouldBeNull() + { + $this->processor->processForm($this->getMockForm('name', 'GET'), 'request'); + } + + public function testMethodOverrideHeaderTakesPrecedenceIfPost() + { + $form = $this->getMockForm('param1', 'PUT'); + + $this->setRequestData('POST', array( + 'param1' => 'DATA', + )); + + $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'PUT'; + + $form->expects($this->once()) + ->method('bind') + ->with('DATA'); + + $this->processor->processForm($form, $this->request); + } + + public function testConvertEmptyUploadedFilesToNull() + { + $form = $this->getMockForm('param1', 'POST', false); + + $this->setRequestData('POST', array(), array('param1' => array( + 'name' => '', + 'type' => '', + 'tmp_name' => '', + 'error' => UPLOAD_ERR_NO_FILE, + 'size' => 0 + ))); + + $form->expects($this->once()) + ->method('bind') + ->with($this->identicalTo(null)); + + $this->processor->processForm($form, $this->request); + } + + public function testFixBuggyFilesArray() + { + $form = $this->getMockForm('param1', 'POST', false); + + $this->setRequestData('POST', array(), array('param1' => array( + 'name' => array( + 'field' => 'upload.txt', + ), + 'type' => array( + 'field' => 'text/plain', + ), + 'tmp_name' => array( + 'field' => 'owfdskjasdfsa', + ), + 'error' => array( + 'field' => UPLOAD_ERR_OK, + ), + 'size' => array( + 'field' => 100, + ), + ))); + + $form->expects($this->once()) + ->method('bind') + ->with(array( + 'field' => array( + 'name' => 'upload.txt', + 'type' => 'text/plain', + 'tmp_name' => 'owfdskjasdfsa', + 'error' => UPLOAD_ERR_OK, + 'size' => 100, + ), + )); + + $this->processor->processForm($form, $this->request); + } + + public function testFixBuggyNestedFilesArray() + { + $form = $this->getMockForm('param1', 'POST'); + + $this->setRequestData('POST', array(), array('param1' => array( + 'name' => array( + 'field' => array('subfield' => 'upload.txt'), + ), + 'type' => array( + 'field' => array('subfield' => 'text/plain'), + ), + 'tmp_name' => array( + 'field' => array('subfield' => 'owfdskjasdfsa'), + ), + 'error' => array( + 'field' => array('subfield' => UPLOAD_ERR_OK), + ), + 'size' => array( + 'field' => array('subfield' => 100), + ), + ))); + + $form->expects($this->once()) + ->method('bind') + ->with(array( + 'field' => array( + 'subfield' => array( + 'name' => 'upload.txt', + 'type' => 'text/plain', + 'tmp_name' => 'owfdskjasdfsa', + 'error' => UPLOAD_ERR_OK, + 'size' => 100, + ), + ), + )); + + $this->processor->processForm($form, $this->request); + } + + public function testMethodOverrideHeaderIgnoredIfNotPost() + { + $form = $this->getMockForm('param1', 'POST'); + + $this->setRequestData('GET', array( + 'param1' => 'DATA', + )); + + $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'PUT'; + + $form->expects($this->never()) + ->method('bind'); + + $this->processor->processForm($form, $this->request); + } + + protected function setRequestData($method, $data, $files = array()) + { + if ('GET' === $method) { + $_GET = $data; + $_FILES = array(); + } else { + $_POST = $data; + $_FILES = $files; + } + + $_SERVER = array( + 'REQUEST_METHOD' => $method, + // PHPUnit needs this entry + 'SCRIPT_NAME' => self::$serverBackup['SCRIPT_NAME'], + ); + } + + protected function getFormProcessor() + { + return new NativeFormProcessor(); + } + + protected function getMockFile() + { + return array( + 'name' => 'upload.txt', + 'type' => 'text/plain', + 'tmp_name' => 'owfdskjasdfsa', + 'error' => UPLOAD_ERR_OK, + 'size' => 100, + ); + } +} diff --git a/Tests/SimpleFormTest.php b/Tests/SimpleFormTest.php index 6d69f259dc..9493b85ce1 100644 --- a/Tests/SimpleFormTest.php +++ b/Tests/SimpleFormTest.php @@ -275,12 +275,9 @@ public function testValidIfBoundAndDisabled() $this->assertTrue($form->isValid()); } - /** - * @expectedException \LogicException - */ public function testNotValidIfNotBound() { - $this->form->isValid(); + $this->assertFalse($this->form->isValid()); } public function testNotValidIfErrors() @@ -845,6 +842,21 @@ public function testBindingWrongDataIsIgnored() $parent->bind('not-an-array'); } + public function testProcessForwardsToFormProcessor() + { + $processor = $this->getMock('Symfony\Component\Form\FormProcessorInterface'); + + $form = $this->getBuilder() + ->setFormProcessor($processor) + ->getForm(); + + $processor->expects($this->once()) + ->method('processForm') + ->with($this->identicalTo($form), 'REQUEST'); + + $this->assertSame($form, $form->process('REQUEST')); + } + protected function createForm() { return $this->getBuilder()->getForm(); From 75e4c04aee5bd1f118315054bb6df78d5d0a726a Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Mon, 15 Apr 2013 11:15:47 +0200 Subject: [PATCH 103/447] [Form] Removed trigger_error() for deprecations as of 3.0 --- .../HttpFoundation/EventListener/BindRequestListener.php | 3 ++- Tests/FormIntegrationTestCase.php | 9 --------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/Extension/HttpFoundation/EventListener/BindRequestListener.php b/Extension/HttpFoundation/EventListener/BindRequestListener.php index 1eb4e6f297..3b4359ed5c 100644 --- a/Extension/HttpFoundation/EventListener/BindRequestListener.php +++ b/Extension/HttpFoundation/EventListener/BindRequestListener.php @@ -43,7 +43,8 @@ public function preBind(FormEvent $event) return; } - trigger_error('Passing a Request instance to Form::bind() is deprecated since version 2.3 and will be disabled in 3.0. Call Form::process($request) instead.', E_USER_DEPRECATED); + // Uncomment this as soon as the deprecation note should be shown + // trigger_error('Passing a Request instance to Form::bind() is deprecated since version 2.3 and will be disabled in 3.0. Call Form::process($request) instead.', E_USER_DEPRECATED); $name = $form->getConfig()->getName(); $default = $form->getConfig()->getCompound() ? array() : null; diff --git a/Tests/FormIntegrationTestCase.php b/Tests/FormIntegrationTestCase.php index e72ec4723b..536ff4c824 100644 --- a/Tests/FormIntegrationTestCase.php +++ b/Tests/FormIntegrationTestCase.php @@ -32,15 +32,6 @@ protected function setUp() $this->factory = Forms::createFormFactoryBuilder() ->addExtensions($this->getExtensions()) ->getFormFactory(); - - set_error_handler(array('Symfony\Component\Form\Test\DeprecationErrorHandler', 'handle')); - } - - protected function tearDown() - { - $this->factory = null; - - restore_error_handler(); } protected function getExtensions() From 3258222514d54f668da47d9b9bf3ce5e08c67a22 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 4 Jan 2013 16:34:38 +0100 Subject: [PATCH 104/447] [Form] Renamed option "virtual" to "inherit_data" --- ButtonBuilder.php | 22 ++++++++++ CHANGELOG.md | 1 + .../Core/DataMapper/PropertyPathMapper.php | 4 +- Extension/Core/Type/FormType.php | 8 ++-- .../ViolationMapper/ViolationMapper.php | 10 ++--- FormConfigBuilder.php | 40 +++++++++++++++++-- FormConfigBuilderInterface.php | 6 +-- FormConfigInterface.php | 10 ++--- .../DataMapper/PropertyPathMapperTest.php | 8 ++-- .../ViolationMapper/ViolationMapperTest.php | 14 +++---- Util/VirtualFormAwareIterator.php | 9 +++-- 11 files changed, 92 insertions(+), 40 deletions(-) diff --git a/ButtonBuilder.php b/ButtonBuilder.php index fb77ef00ff..66ce61ab53 100644 --- a/ButtonBuilder.php +++ b/ButtonBuilder.php @@ -492,6 +492,18 @@ public function setFormProcessor(FormProcessorInterface $formProcessor) throw new \BadMethodCallException('Buttons do not support form processors.'); } + /** + * Unsupported method. + * + * @param Boolean $inheritData + * + * @throws \BadMethodCallException + */ + public function setInheritData($inheritData) + { + throw new \BadMethodCallException('Buttons do not support data inheritance.'); + } + /** * Builds and returns the button configuration. * @@ -759,6 +771,16 @@ public function getFormProcessor() return null; } + /** + * Unsupported method. + * + * @return null Always returns null. + */ + public function getInheritData() + { + return null; + } + /** * Returns all options passed during the construction of the button. * diff --git a/CHANGELOG.md b/CHANGELOG.md index 40976fa8d0..b7b6b08245 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ CHANGELOG * added FormProcessorInterface and FormInterface::process() * deprecated passing a Request instance to FormInterface::bind() * added options "method" and "action" to FormType + * deprecated option "virtual", renamed it to "inherit_data" 2.2.0 ----- diff --git a/Extension/Core/DataMapper/PropertyPathMapper.php b/Extension/Core/DataMapper/PropertyPathMapper.php index f691ecca21..cb59baa075 100644 --- a/Extension/Core/DataMapper/PropertyPathMapper.php +++ b/Extension/Core/DataMapper/PropertyPathMapper.php @@ -56,7 +56,7 @@ public function mapDataToForms($data, array $forms) $iterator = new \RecursiveIteratorIterator($iterator); foreach ($iterator as $form) { - /* @var FormInterface $form */ + /* @var \Symfony\Component\Form\FormInterface $form */ $propertyPath = $form->getPropertyPath(); $config = $form->getConfig(); @@ -83,7 +83,7 @@ public function mapFormsToData(array $forms, &$data) $iterator = new \RecursiveIteratorIterator($iterator); foreach ($iterator as $form) { - /* @var FormInterface $form */ + /* @var \Symfony\Component\Form\FormInterface $form */ $propertyPath = $form->getPropertyPath(); $config = $form->getConfig(); diff --git a/Extension/Core/Type/FormType.php b/Extension/Core/Type/FormType.php index e51dba870e..31835357c1 100644 --- a/Extension/Core/Type/FormType.php +++ b/Extension/Core/Type/FormType.php @@ -48,7 +48,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) ->setPropertyPath($options['property_path']) ->setMapped($options['mapped']) ->setByReference($options['by_reference']) - ->setVirtual($options['virtual']) + ->setInheritData($options['inherit_data']) ->setCompound($options['compound']) ->setData(isset($options['data']) ? $options['data'] : null) ->setDataLocked(isset($options['data'])) @@ -95,8 +95,8 @@ public function buildView(FormView $view, FormInterface $form, array $options) 'size' => null, 'label_attr' => $options['label_attr'], 'compound' => $form->getConfig()->getCompound(), - 'method' => $form->getConfig()->getMethod(), - 'action' => $form->getConfig()->getAction(), + 'method' => $form->getConfig()->getMethod(), + 'action' => $form->getConfig()->getAction(), )); } @@ -169,7 +169,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'by_reference' => true, 'error_bubbling' => $errorBubbling, 'label_attr' => array(), - 'virtual' => false, + 'inherit_data' => false, 'compound' => true, 'method' => 'POST', // According to RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt) diff --git a/Extension/Validator/ViolationMapper/ViolationMapper.php b/Extension/Validator/ViolationMapper/ViolationMapper.php index 1c1e64f94f..4eb9126b6b 100644 --- a/Extension/Validator/ViolationMapper/ViolationMapper.php +++ b/Extension/Validator/ViolationMapper/ViolationMapper.php @@ -88,8 +88,8 @@ public function mapViolation(ConstraintViolation $violation, FormInterface $form } // This case happens if an error happened in the data under a - // virtual form that does not match any of the children of - // the virtual form. + // form inheriting its parent data that does not match any of the + // children of that form. if (null !== $violationPath && !$match) { // If we could not map the error to anything more specific // than the root element, map it to the innermost directly @@ -162,7 +162,7 @@ private function matchChild(FormInterface $form, PropertyPathIteratorInterface $ } } - // Ignore virtual forms when iterating the children + // Skip forms inheriting their parent data when iterating the children $childIterator = new \RecursiveIteratorIterator( new VirtualFormAwareIterator($form->all()) ); @@ -253,8 +253,8 @@ private function reconstructPath(ViolationPath $violationPath, FormInterface $or // Process child form $scope = $scope->get($it->current()); - if ($scope->getConfig()->getVirtual()) { - // Form is virtual + if ($scope->getConfig()->getInheritData()) { + // Form inherits its parent data // Cut the piece out of the property path and proceed $propertyPathBuilder->remove($i); } elseif (!$scope->getConfig()->getMapped()) { diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index 694b94555e..26cea6b7f4 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -80,7 +80,7 @@ class FormConfigBuilder implements FormConfigBuilderInterface /** * @var Boolean */ - private $virtual = false; + private $inheritData = false; /** * @var Boolean @@ -341,9 +341,24 @@ public function getByReference() /** * {@inheritdoc} */ + public function getInheritData() + { + return $this->inheritData; + } + + /** + * Alias of {@link getInheritData()}. + * + * @return FormConfigBuilder The configuration object. + * + * @deprecated Deprecated since version 2.2, to be removed in 2.3. Use + * {@link getInheritData()} instead. + */ public function getVirtual() { - return $this->virtual; + trigger_error('getVirtual() is deprecated since version 2.2 and will be removed in 2.3. Use getInheritData() instead.', E_USER_DEPRECATED); + + return $this->getInheritData(); } /** @@ -676,17 +691,34 @@ public function setByReference($byReference) /** * {@inheritdoc} */ - public function setVirtual($virtual) + public function setInheritData($inheritData) { if ($this->locked) { throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } - $this->virtual = $virtual; + $this->inheritData = $inheritData; return $this; } + /** + * Alias of {@link setInheritData()}. + * + * @param Boolean $inheritData Whether the form should inherit its parent's data. + * + * @return FormConfigBuilder The configuration object. + * + * @deprecated Deprecated since version 2.2, to be removed in 2.3. Use + * {@link setInheritData()} instead. + */ + public function setVirtual($inheritData) + { + trigger_error('setVirtual() is deprecated since version 2.2 and will be removed in 2.3. Use setInheritData() instead.', E_USER_DEPRECATED); + + $this->setInheritData($inheritData); + } + /** * {@inheritdoc} */ diff --git a/FormConfigBuilderInterface.php b/FormConfigBuilderInterface.php index 34b217e623..a35be27db2 100644 --- a/FormConfigBuilderInterface.php +++ b/FormConfigBuilderInterface.php @@ -180,13 +180,13 @@ public function setMapped($mapped); public function setByReference($byReference); /** - * Sets whether the form should be virtual. + * Sets whether the form should read and write the data of its parent. * - * @param Boolean $virtual Whether the form should be virtual. + * @param Boolean $inheritData Whether the form should inherit its parent's data. * * @return self The configuration object. */ - public function setVirtual($virtual); + public function setInheritData($inheritData); /** * Sets whether the form should be compound. diff --git a/FormConfigInterface.php b/FormConfigInterface.php index e00ce27f43..3aa00d4dbd 100644 --- a/FormConfigInterface.php +++ b/FormConfigInterface.php @@ -55,15 +55,11 @@ public function getMapped(); public function getByReference(); /** - * Returns whether the form should be virtual. + * Returns whether the form should read and write the data of its parent. * - * When mapping data to the children of a form, the data mapper - * should ignore virtual forms and map to the children of the - * virtual form instead. - * - * @return Boolean Whether the form is virtual. + * @return Boolean Whether the form should inherit its parent's data. */ - public function getVirtual(); + public function getInheritData(); /** * Returns whether the form is compound. diff --git a/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php b/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php index 8af2fd5f07..32ef587862 100644 --- a/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php +++ b/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php @@ -182,7 +182,7 @@ public function testMapDataToFormsIgnoresEmptyData() $this->assertNull($form->getData()); } - public function testMapDataToFormsSkipsVirtualForms() + public function testMapDataToFormsSkipsFormsInheritingParentData() { $car = new \stdClass(); $engine = new \stdClass(); @@ -195,7 +195,7 @@ public function testMapDataToFormsSkipsVirtualForms() $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); - $config->setVirtual(true); + $config->setInheritData(true); $config->setCompound(true); $config->setDataMapper($this->getDataMapper()); $form = $this->getForm($config); @@ -348,7 +348,7 @@ public function testMapFormsToDataIgnoresDisabled() $this->mapper->mapFormsToData(array($form), $car); } - public function testMapFormsToDataSkipsVirtualForms() + public function testMapFormsToDataSkipsFormsInheritingParentData() { $car = new \stdClass(); $engine = new \stdClass(); @@ -366,7 +366,7 @@ public function testMapFormsToDataSkipsVirtualForms() $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setPropertyPath($parentPath); - $config->setVirtual(true); + $config->setInheritData(true); $config->setCompound(true); $config->setDataMapper($this->getDataMapper()); $form = $this->getForm($config); diff --git a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php index 83a5db6e10..516b62299d 100644 --- a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php +++ b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php @@ -71,13 +71,13 @@ protected function setUp() $this->params = array('foo' => 'bar'); } - protected function getForm($name = 'name', $propertyPath = null, $dataClass = null, $errorMapping = array(), $virtual = false, $synchronized = true) + protected function getForm($name = 'name', $propertyPath = null, $dataClass = null, $errorMapping = array(), $inheritData = false, $synchronized = true) { $config = new FormConfigBuilder($name, $dataClass, $this->dispatcher, array( 'error_mapping' => $errorMapping, )); $config->setMapped(true); - $config->setVirtual($virtual); + $config->setInheritData($inheritData); $config->setPropertyPath($propertyPath); $config->setCompound(true); $config->setDataMapper($this->getDataMapper()); @@ -118,7 +118,7 @@ protected function getFormError() return new FormError($this->message, $this->messageTemplate, $this->params); } - public function testMapToVirtualFormIfDataDoesNotMatch() + public function testMapToFormInheritingParentDataIfDataDoesNotMatch() { $violation = $this->getConstraintViolation('children[address].data.foo'); $parent = $this->getForm('parent'); @@ -183,7 +183,7 @@ public function testAbortMappingIfNotSynchronized() $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); } - public function testAbortVirtualFormMappingIfNotSynchronized() + public function testAbortFormInheritingParentDataMappingIfNotSynchronized() { $violation = $this->getConstraintViolation('children[address].children[street].data.foo'); $parent = $this->getForm('parent'); @@ -1446,7 +1446,7 @@ public function testCustomFormErrorMapping($target, $mapFrom, $mapTo, $errorName } } - public function provideVirtualFormErrorTests() + public function provideFormInheritingParentDataErrorTests() { return array( // mapping target, child name, its property path, grand child name, its property path, violation path @@ -1472,9 +1472,9 @@ public function provideVirtualFormErrorTests() } /** - * @dataProvider provideVirtualFormErrorTests + * @dataProvider provideFormInheritingParentDataErrorTests */ - public function testVirtualFormErrorMapping($target, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath) + public function testFormInheritingParentDataErrorMapping($target, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath) { $violation = $this->getConstraintViolation($violationPath); $parent = $this->getForm('parent'); diff --git a/Util/VirtualFormAwareIterator.php b/Util/VirtualFormAwareIterator.php index c1322bb35d..92e9da0d51 100644 --- a/Util/VirtualFormAwareIterator.php +++ b/Util/VirtualFormAwareIterator.php @@ -12,10 +12,11 @@ namespace Symfony\Component\Form\Util; /** - * Iterator that traverses fields of a field group + * Iterator that returns only forms from a form tree that do not inherit their + * parent data. * - * If the iterator encounters a virtual field group, it enters the field - * group and traverses its children as well. + * If the iterator encounters a form that inherits its parent data, it enters + * the form and traverses its children as well. * * @author Bernhard Schussek */ @@ -28,6 +29,6 @@ public function getChildren() public function hasChildren() { - return $this->current()->getConfig()->getVirtual(); + return $this->current()->getConfig()->getInheritData(); } } From 71c85a74785766b1d1c7fc6d462ee3e10795dc7a Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Sat, 5 Jan 2013 14:26:33 +0100 Subject: [PATCH 105/447] [Form] Moved parent data inheritance from data mappers to Form --- CHANGELOG.md | 3 + DataMapperInterface.php | 12 +- Exception/RuntimeException.php | 21 ++ .../Core/DataMapper/PropertyPathMapper.php | 17 +- .../ViolationMapper/ViolationMapper.php | 7 +- Form.php | 186 ++++++++++++------ Tests/CompoundFormTest.php | 72 ++++++- .../DataMapper/PropertyPathMapperTest.php | 65 ------ .../ViolationMapper/ViolationMapperTest.php | 28 +-- Tests/SimpleFormTest.php | 135 ++++++++++++- Util/InheritDataAwareIterator.php | 35 ++++ Util/VirtualFormAwareIterator.php | 17 +- 12 files changed, 420 insertions(+), 178 deletions(-) create mode 100644 Exception/RuntimeException.php create mode 100644 Util/InheritDataAwareIterator.php diff --git a/CHANGELOG.md b/CHANGELOG.md index b7b6b08245..9fdeaffcdd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ CHANGELOG * deprecated passing a Request instance to FormInterface::bind() * added options "method" and "action" to FormType * deprecated option "virtual", renamed it to "inherit_data" + * deprecated VirtualFormAwareIterator in favor of InheritDataAwareIterator + * [BC BREAK] removed the "array" type hint from DataMapperInterface + * improved forms inheriting their parent data to actually return that data from getData(), getNormData() and getViewData() 2.2.0 ----- diff --git a/DataMapperInterface.php b/DataMapperInterface.php index a574cbc8de..6e03168291 100644 --- a/DataMapperInterface.php +++ b/DataMapperInterface.php @@ -19,20 +19,20 @@ interface DataMapperInterface /** * Maps properties of some data to a list of forms. * - * @param mixed $data Structured data. - * @param array $forms A list of {@link FormInterface} instances. + * @param mixed $data Structured data. + * @param FormInterface[] $forms A list of {@link FormInterface} instances. * * @throws Exception\UnexpectedTypeException if the type of the data parameter is not supported. */ - public function mapDataToForms($data, array $forms); + public function mapDataToForms($data, $forms); /** * Maps the data of a list of forms into the properties of some data. * - * @param array $forms A list of {@link FormInterface} instances. - * @param mixed $data Structured data. + * @param FormInterface[] $forms A list of {@link FormInterface} instances. + * @param mixed $data Structured data. * * @throws Exception\UnexpectedTypeException if the type of the data parameter is not supported. */ - public function mapFormsToData(array $forms, &$data); + public function mapFormsToData($forms, &$data); } diff --git a/Exception/RuntimeException.php b/Exception/RuntimeException.php new file mode 100644 index 0000000000..0af48a4a21 --- /dev/null +++ b/Exception/RuntimeException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Exception; + +/** + * Base RuntimeException for the Form component. + * + * @author Bernhard Schussek + */ +class RuntimeException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/Extension/Core/DataMapper/PropertyPathMapper.php b/Extension/Core/DataMapper/PropertyPathMapper.php index cb59baa075..d8bd9c715b 100644 --- a/Extension/Core/DataMapper/PropertyPathMapper.php +++ b/Extension/Core/DataMapper/PropertyPathMapper.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Form\Extension\Core\DataMapper; use Symfony\Component\Form\DataMapperInterface; -use Symfony\Component\Form\Util\VirtualFormAwareIterator; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\PropertyAccess\PropertyAccessorInterface; @@ -42,7 +41,7 @@ public function __construct(PropertyAccessorInterface $propertyAccessor = null) /** * {@inheritdoc} */ - public function mapDataToForms($data, array $forms) + public function mapDataToForms($data, $forms) { if (null === $data || array() === $data) { return; @@ -52,11 +51,7 @@ public function mapDataToForms($data, array $forms) throw new UnexpectedTypeException($data, 'object, array or empty'); } - $iterator = new VirtualFormAwareIterator($forms); - $iterator = new \RecursiveIteratorIterator($iterator); - - foreach ($iterator as $form) { - /* @var \Symfony\Component\Form\FormInterface $form */ + foreach ($forms as $form) { $propertyPath = $form->getPropertyPath(); $config = $form->getConfig(); @@ -69,7 +64,7 @@ public function mapDataToForms($data, array $forms) /** * {@inheritdoc} */ - public function mapFormsToData(array $forms, &$data) + public function mapFormsToData($forms, &$data) { if (null === $data) { return; @@ -79,11 +74,7 @@ public function mapFormsToData(array $forms, &$data) throw new UnexpectedTypeException($data, 'object, array or empty'); } - $iterator = new VirtualFormAwareIterator($forms); - $iterator = new \RecursiveIteratorIterator($iterator); - - foreach ($iterator as $form) { - /* @var \Symfony\Component\Form\FormInterface $form */ + foreach ($forms as $form) { $propertyPath = $form->getPropertyPath(); $config = $form->getConfig(); diff --git a/Extension/Validator/ViolationMapper/ViolationMapper.php b/Extension/Validator/ViolationMapper/ViolationMapper.php index 4eb9126b6b..8a7636c7e8 100644 --- a/Extension/Validator/ViolationMapper/ViolationMapper.php +++ b/Extension/Validator/ViolationMapper/ViolationMapper.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\Util\VirtualFormAwareIterator; +use Symfony\Component\Form\Util\InheritDataAwareIterator; use Symfony\Component\PropertyAccess\PropertyPathIterator; use Symfony\Component\PropertyAccess\PropertyPathBuilder; use Symfony\Component\PropertyAccess\PropertyPathIteratorInterface; @@ -100,6 +100,9 @@ public function mapViolation(ConstraintViolation $violation, FormInterface $form $scope = $form; $it = new ViolationPathIterator($violationPath); + // Note: acceptsErrors() will always return true for forms inheriting + // their parent data, because these forms can never be non-synchronized + // (they don't do any data transformation on their own) while ($this->acceptsErrors($scope) && $it->valid() && $it->mapsForm()) { if (!$scope->has($it->current())) { // Break if we find a reference to a non-existing child @@ -164,7 +167,7 @@ private function matchChild(FormInterface $form, PropertyPathIteratorInterface $ // Skip forms inheriting their parent data when iterating the children $childIterator = new \RecursiveIteratorIterator( - new VirtualFormAwareIterator($form->all()) + new InheritDataAwareIterator($form->all()) ); // Make the path longer until we find a matching child diff --git a/Form.php b/Form.php index 3b95817be0..db884cf6f5 100644 --- a/Form.php +++ b/Form.php @@ -11,11 +11,14 @@ namespace Symfony\Component\Form; +use Symfony\Component\Form\Exception\BadMethodCallException; use Symfony\Component\Form\Exception\Exception; +use Symfony\Component\Form\Exception\RuntimeException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Exception\AlreadyBoundException; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Util\FormUtil; +use Symfony\Component\Form\Util\InheritDataAwareIterator; use Symfony\Component\PropertyAccess\PropertyPath; /** @@ -130,7 +133,7 @@ class Form implements \IteratorAggregate, FormInterface * * @var Boolean */ - private $initialized = false; + private $defaultDataSet = false; /** * Whether setData() is currently being called. @@ -143,7 +146,7 @@ class Form implements \IteratorAggregate, FormInterface * * @param FormConfigInterface $config The form configuration. * - * @throws FormException if a data mapper is not provided for a compound form + * @throws Exception if a data mapper is not provided for a compound form */ public function __construct(FormConfigInterface $config) { @@ -154,6 +157,12 @@ public function __construct(FormConfigInterface $config) throw new Exception('Compound forms need a data mapper'); } + // If the form inherits the data from its parent, it is not necessary + // to call setData() with the default data. + if ($config->getInheritData()) { + $this->defaultDataSet = true; + } + $this->config = $config; } @@ -193,7 +202,13 @@ public function getPropertyPath() return null; } - if ($this->parent && null === $this->parent->getConfig()->getDataClass()) { + $parent = $this->parent; + + while ($parent && $parent->getConfig()->getInheritData()) { + $parent = $parent->getParent(); + } + + if ($parent && null === $parent->getConfig()->getDataClass()) { return new PropertyPath('['.$this->getName().']'); } @@ -274,8 +289,14 @@ public function setData($modelData) // If the form is bound while disabled, it is set to bound, but the data is not // changed. In such cases (i.e. when the form is not initialized yet) don't // abort this method. - if ($this->bound && $this->initialized) { - throw new AlreadyBoundException('You cannot change the data of a bound form'); + if ($this->bound && $this->defaultDataSet) { + throw new AlreadyBoundException('You cannot change the data of a bound form.'); + } + + // If the form inherits its parent's data, disallow data setting to + // prevent merge conflicts + if ($this->config->getInheritData()) { + throw new RuntimeException('You cannot change the data of a form inheriting its parent data.'); } // Don't allow modifications of the configured data if the data is locked @@ -288,7 +309,7 @@ public function setData($modelData) } if ($this->lockSetData) { - throw new Exception('A cycle was detected. Listeners to the PRE_SET_DATA event must not call setData(). You should call setData() on the FormEvent object instead.'); + throw new RuntimeException('A cycle was detected. Listeners to the PRE_SET_DATA event must not call setData(). You should call setData() on the FormEvent object instead.'); } $this->lockSetData = true; @@ -342,14 +363,16 @@ public function setData($modelData) $this->modelData = $modelData; $this->normData = $normData; $this->viewData = $viewData; - $this->initialized = true; + $this->defaultDataSet = true; $this->lockSetData = false; // It is not necessary to invoke this method if the form doesn't have children, // even if the form is compound. if (count($this->children) > 0) { // Update child forms from the data - $this->config->getDataMapper()->mapDataToForms($viewData, $this->children); + $childrenIterator = new InheritDataAwareIterator($this->children); + $childrenIterator = new \RecursiveIteratorIterator($childrenIterator); + $this->config->getDataMapper()->mapDataToForms($viewData, $childrenIterator); } if ($dispatcher->hasListeners(FormEvents::POST_SET_DATA)) { @@ -365,7 +388,15 @@ public function setData($modelData) */ public function getData() { - if (!$this->initialized) { + if ($this->config->getInheritData()) { + if (!$this->parent) { + throw new RuntimeException('The form is configured to inherit its parent\'s data, but does not have a parent.'); + } + + return $this->parent->getData(); + } + + if (!$this->defaultDataSet) { $this->setData($this->config->getData()); } @@ -377,7 +408,15 @@ public function getData() */ public function getNormData() { - if (!$this->initialized) { + if ($this->config->getInheritData()) { + if (!$this->parent) { + throw new RuntimeException('The form is configured to inherit its parent\'s data, but does not have a parent.'); + } + + return $this->parent->getNormData(); + } + + if (!$this->defaultDataSet) { $this->setData($this->config->getData()); } @@ -389,7 +428,15 @@ public function getNormData() */ public function getViewData() { - if (!$this->initialized) { + if ($this->config->getInheritData()) { + if (!$this->parent) { + throw new RuntimeException('The form is configured to inherit its parent\'s data, but does not have a parent.'); + } + + return $this->parent->getViewData(); + } + + if (!$this->defaultDataSet) { $this->setData($this->config->getData()); } @@ -423,6 +470,11 @@ public function bind($submittedData) throw new AlreadyBoundException('A form can only be bound once'); } + // Initialize errors in the very beginning so that we don't lose any + // errors added during listeners + $this->errors = array(); + + // Obviously, a disabled form should not change its data upon binding. if ($this->isDisabled()) { $this->bound = true; @@ -432,7 +484,7 @@ public function bind($submittedData) // The data must be initialized if it was not initialized yet. // This is necessary to guarantee that the *_SET_DATA listeners // are always invoked before bind() takes place. - if (!$this->initialized) { + if (!$this->defaultDataSet) { $this->setData($this->config->getData()); } @@ -444,10 +496,6 @@ public function bind($submittedData) $submittedData = (string) $submittedData; } - // Initialize errors in the very beginning so that we don't lose any - // errors added during listeners - $this->errors = array(); - $dispatcher = $this->config->getEventDispatcher(); // Hook to change content of the data bound by the browser @@ -472,63 +520,83 @@ public function bind($submittedData) } $this->extraData = $submittedData; + } + + // Forms that inherit their parents' data also are not processed, + // because then it would be too difficult to merge the changes in + // the child and the parent form. Instead, the parent form also takes + // changes in the grandchildren (i.e. children of the form that inherits + // its parent's data) into account. + // (see InheritDataAwareIterator below) + if ($this->config->getInheritData()) { + $this->bound = true; + // When POST_BIND is reached, the data is not yet updated, so pass + // NULL to prevent hard-to-debug bugs. + $dataForPostBind = null; + } else { // If the form is compound, the default data in view format // is reused. The data of the children is merged into this // default data using the data mapper. - $viewData = $this->viewData; - } else { // If the form is not compound, the submitted data is also the data in view format. - $viewData = $submittedData; - } + $viewData = $this->config->getCompound() ? $this->viewData : $submittedData; + + if (FormUtil::isEmpty($viewData)) { + $emptyData = $this->config->getEmptyData(); - if (FormUtil::isEmpty($viewData)) { - $emptyData = $this->config->getEmptyData(); + if ($emptyData instanceof \Closure) { + /* @var \Closure $emptyData */ + $emptyData = $emptyData($this, $viewData); + } - if ($emptyData instanceof \Closure) { - /* @var \Closure $emptyData */ - $emptyData = $emptyData($this, $viewData); + $viewData = $emptyData; } - $viewData = $emptyData; - } + // Merge form data from children into existing view data + // It is not necessary to invoke this method if the form has no children, + // even if it is compound. + if (count($this->children) > 0) { + // Use InheritDataAwareIterator to process children of + // descendants that inherit this form's data. + // These descendants will not be bound normally (see the check + // for $this->config->getInheritData() above) + $childrenIterator = new InheritDataAwareIterator($this->children); + $childrenIterator = new \RecursiveIteratorIterator($childrenIterator); + $this->config->getDataMapper()->mapFormsToData($childrenIterator, $viewData); + } - // Merge form data from children into existing view data - // It is not necessary to invoke this method if the form has no children, - // even if it is compound. - if (count($this->children) > 0) { - $this->config->getDataMapper()->mapFormsToData($this->children, $viewData); - } + $modelData = null; + $normData = null; - $modelData = null; - $normData = null; + try { + // Normalize data to unified representation + $normData = $this->viewToNorm($viewData); - try { - // Normalize data to unified representation - $normData = $this->viewToNorm($viewData); + // Hook to change content of the data into the normalized + // representation + if ($dispatcher->hasListeners(FormEvents::BIND)) { + $event = new FormEvent($this, $normData); + $dispatcher->dispatch(FormEvents::BIND, $event); + $normData = $event->getData(); + } - // Hook to change content of the data into the normalized - // representation - if ($dispatcher->hasListeners(FormEvents::BIND)) { - $event = new FormEvent($this, $normData); - $dispatcher->dispatch(FormEvents::BIND, $event); - $normData = $event->getData(); + // Synchronize representations - must not change the content! + $modelData = $this->normToModel($normData); + $viewData = $this->normToView($normData); + } catch (TransformationFailedException $e) { + $this->synchronized = false; } - // Synchronize representations - must not change the content! - $modelData = $this->normToModel($normData); - $viewData = $this->normToView($normData); - } catch (TransformationFailedException $e) { - $this->synchronized = false; - } + $this->bound = true; + $this->modelData = $modelData; + $this->normData = $normData; + $this->viewData = $viewData; - $this->bound = true; - $this->modelData = $modelData; - $this->normData = $normData; - $this->viewData = $viewData; + $dataForPostBind = $viewData; + } if ($dispatcher->hasListeners(FormEvents::POST_BIND)) { - $event = new FormEvent($this, $viewData); + $event = new FormEvent($this, $dataForPostBind); $dispatcher->dispatch(FormEvents::POST_BIND, $event); } @@ -679,7 +747,7 @@ public function add($child, $type = null, array $options = array()) // * getViewData() is called // * setData() is called since the form is not initialized yet // * ... endless recursion ... - if (!$this->lockSetData) { + if (!$this->lockSetData && !$this->config->getInheritData()) { $viewData = $this->getViewData(); } @@ -703,8 +771,10 @@ public function add($child, $type = null, array $options = array()) $child->setParent($this); - if (!$this->lockSetData) { - $this->config->getDataMapper()->mapDataToForms($viewData, array($child)); + if (!$this->lockSetData && !$this->config->getInheritData()) { + $childrenIterator = new InheritDataAwareIterator(array($child)); + $childrenIterator = new \RecursiveIteratorIterator($childrenIterator); + $this->config->getDataMapper()->mapDataToForms($viewData, $childrenIterator); } return $this; diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index 1d52075d6c..fc3b5a6d6d 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -264,6 +264,7 @@ public function testIterator() public function testAddMapsViewDataToForm() { + $test = $this; $mapper = $this->getDataMapper(); $form = $this->getBuilder() ->setCompound(true) @@ -278,13 +279,34 @@ public function testAddMapsViewDataToForm() $child = $this->getBuilder()->getForm(); $mapper->expects($this->once()) ->method('mapDataToForms') - ->with('bar', array($child)); + ->with('bar', $this->isInstanceOf('\RecursiveIteratorIterator')) + ->will($this->returnCallback(function ($data, \RecursiveIteratorIterator $iterator) use ($child, $test) { + $test->assertInstanceOf('Symfony\Component\Form\Util\InheritDataAwareIterator', $iterator->getInnerIterator()); + $test->assertSame(array($child), iterator_to_array($iterator)); + })); + + $form->add($child); + } + + public function testAddDoesNotMapViewDataToFormIfInheritData() + { + $mapper = $this->getDataMapper(); + $form = $this->getBuilder() + ->setCompound(true) + ->setDataMapper($mapper) + ->setInheritData(true) + ->getForm(); + + $child = $this->getBuilder()->getForm(); + $mapper->expects($this->never()) + ->method('mapDataToForms'); $form->add($child); } public function testSetDataMapsViewDataToChildren() { + $test = $this; $mapper = $this->getDataMapper(); $form = $this->getBuilder() ->setCompound(true) @@ -300,7 +322,11 @@ public function testSetDataMapsViewDataToChildren() $mapper->expects($this->once()) ->method('mapDataToForms') - ->with('bar', array('firstName' => $child1, 'lastName' => $child2)); + ->with('bar', $this->isInstanceOf('\RecursiveIteratorIterator')) + ->will($this->returnCallback(function ($data, \RecursiveIteratorIterator $iterator) use ($child1, $child2, $test) { + $test->assertInstanceOf('Symfony\Component\Form\Util\InheritDataAwareIterator', $iterator->getInnerIterator()); + $test->assertSame(array('firstName' => $child1, 'lastName' => $child2), iterator_to_array($iterator)); + })); $form->setData('foo'); } @@ -324,10 +350,12 @@ public function testBindMapsBoundChildrenOntoExistingViewData() $mapper->expects($this->once()) ->method('mapFormsToData') - ->with(array('firstName' => $child1, 'lastName' => $child2), 'bar') - ->will($this->returnCallback(function ($children, $bar) use ($test) { - $test->assertEquals('Bernhard', $children['firstName']->getData()); - $test->assertEquals('Schussek', $children['lastName']->getData()); + ->with($this->isInstanceOf('\RecursiveIteratorIterator'), 'bar') + ->will($this->returnCallback(function (\RecursiveIteratorIterator $iterator) use ($child1, $child2, $test) { + $test->assertInstanceOf('Symfony\Component\Form\Util\InheritDataAwareIterator', $iterator->getInnerIterator()); + $test->assertSame(array('firstName' => $child1, 'lastName' => $child2), iterator_to_array($iterator)); + $test->assertEquals('Bernhard', $child1->getData()); + $test->assertEquals('Schussek', $child2->getData()); })); $form->bind(array( @@ -336,6 +364,31 @@ public function testBindMapsBoundChildrenOntoExistingViewData() )); } + public function testMapFormsToDataIsNotInvokedIfInheritData() + { + $mapper = $this->getDataMapper(); + $form = $this->getBuilder() + ->setCompound(true) + ->setDataMapper($mapper) + ->setInheritData(true) + ->addViewTransformer(new FixedDataTransformer(array( + '' => '', + 'foo' => 'bar', + ))) + ->getForm(); + + $form->add($child1 = $this->getBuilder('firstName')->setCompound(false)->getForm()); + $form->add($child2 = $this->getBuilder('lastName')->setCompound(false)->getForm()); + + $mapper->expects($this->never()) + ->method('mapFormsToData'); + + $form->bind(array( + 'firstName' => 'Bernhard', + 'lastName' => 'Schussek', + )); + } + /* * https://github.com/symfony/symfony/issues/4480 */ @@ -356,6 +409,7 @@ public function testBindRestoresViewDataIfCompoundAndEmpty() public function testBindMapsBoundChildrenOntoEmptyData() { + $test = $this; $mapper = $this->getDataMapper(); $object = new \stdClass(); $form = $this->getBuilder() @@ -369,7 +423,11 @@ public function testBindMapsBoundChildrenOntoEmptyData() $mapper->expects($this->once()) ->method('mapFormsToData') - ->with(array('name' => $child), $object); + ->with($this->isInstanceOf('\RecursiveIteratorIterator'), $object) + ->will($this->returnCallback(function (\RecursiveIteratorIterator $iterator) use ($child, $test) { + $test->assertInstanceOf('Symfony\Component\Form\Util\InheritDataAwareIterator', $iterator->getInnerIterator()); + $test->assertSame(array('name' => $child), iterator_to_array($iterator)); + })); $form->bind(array( 'name' => 'Bernhard', diff --git a/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php b/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php index 32ef587862..ee2e3351ce 100644 --- a/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php +++ b/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php @@ -182,37 +182,6 @@ public function testMapDataToFormsIgnoresEmptyData() $this->assertNull($form->getData()); } - public function testMapDataToFormsSkipsFormsInheritingParentData() - { - $car = new \stdClass(); - $engine = new \stdClass(); - $propertyPath = $this->getPropertyPath('engine'); - - $this->propertyAccessor->expects($this->once()) - ->method('getValue') - ->with($car, $propertyPath) - ->will($this->returnValue($engine)); - - $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); - $config->setByReference(true); - $config->setInheritData(true); - $config->setCompound(true); - $config->setDataMapper($this->getDataMapper()); - $form = $this->getForm($config); - - $config = new FormConfigBuilder('engine', '\stdClass', $this->dispatcher); - $config->setByReference(true); - $config->setPropertyPath($propertyPath); - $child = $this->getForm($config); - - $form->add($child); - - $this->mapper->mapDataToForms($car, array($form)); - - $this->assertNull($form->getData()); - $this->assertSame($engine, $child->getData()); - } - public function testMapFormsToDataWritesBackIfNotByReference() { $car = new \stdClass(); @@ -347,38 +316,4 @@ public function testMapFormsToDataIgnoresDisabled() $this->mapper->mapFormsToData(array($form), $car); } - - public function testMapFormsToDataSkipsFormsInheritingParentData() - { - $car = new \stdClass(); - $engine = new \stdClass(); - $parentPath = $this->getPropertyPath('name'); - $childPath = $this->getPropertyPath('engine'); - - // getValue() and setValue() must never be invoked for $parentPath - - $this->propertyAccessor->expects($this->once()) - ->method('getValue') - ->with($car, $childPath); - $this->propertyAccessor->expects($this->once()) - ->method('setValue') - ->with($car, $childPath, $engine); - - $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); - $config->setPropertyPath($parentPath); - $config->setInheritData(true); - $config->setCompound(true); - $config->setDataMapper($this->getDataMapper()); - $form = $this->getForm($config); - - $config = new FormConfigBuilder('engine', '\stdClass', $this->dispatcher); - $config->setByReference(true); - $config->setPropertyPath($childPath); - $config->setData($engine); - $child = $this->getForm($config); - - $form->add($child); - - $this->mapper->mapFormsToData(array($form), $car); - } } diff --git a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php index 516b62299d..cbe1acbe9c 100644 --- a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php +++ b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php @@ -183,28 +183,6 @@ public function testAbortMappingIfNotSynchronized() $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); } - public function testAbortFormInheritingParentDataMappingIfNotSynchronized() - { - $violation = $this->getConstraintViolation('children[address].children[street].data.foo'); - $parent = $this->getForm('parent'); - $child = $this->getForm('address', 'address', null, array(), true, false); - // even though "street" is synchronized, it should not have any errors - // due to its parent not being synchronized - $grandChild = $this->getForm('street' , 'street', null, array(), true); - - $parent->add($child); - $child->add($grandChild); - - // bind to invoke the transformer and mark the form unsynchronized - $parent->bind(array()); - - $this->mapper->mapViolation($violation, $parent); - - $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); - $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one'); - $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); - } - public function testAbortDotRuleMappingIfNotSynchronized() { $violation = $this->getConstraintViolation('data.address'); @@ -1446,7 +1424,7 @@ public function testCustomFormErrorMapping($target, $mapFrom, $mapTo, $errorName } } - public function provideFormInheritingParentDataErrorTests() + public function provideErrorTestsForFormInheritingParentData() { return array( // mapping target, child name, its property path, grand child name, its property path, violation path @@ -1472,9 +1450,9 @@ public function provideFormInheritingParentDataErrorTests() } /** - * @dataProvider provideFormInheritingParentDataErrorTests + * @dataProvider provideErrorTestsForFormInheritingParentData */ - public function testFormInheritingParentDataErrorMapping($target, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath) + public function testErrorMappingForFormInheritingParentData($target, $childName, $childPath, $grandChildName, $grandChildPath, $violationPath) { $violation = $this->getConstraintViolation($violationPath); $parent = $this->getForm('parent'); diff --git a/Tests/SimpleFormTest.php b/Tests/SimpleFormTest.php index 9493b85ce1..65f3ee2949 100644 --- a/Tests/SimpleFormTest.php +++ b/Tests/SimpleFormTest.php @@ -763,6 +763,42 @@ public function testGetPropertyPathDefaultsToIndexedNameIfParentDataClassIsNull( $this->assertEquals(new PropertyPath('[name]'), $form->getPropertyPath()); } + public function testGetPropertyPathDefaultsToNameIfFirstParentWithoutInheritDataHasDataClass() + { + $grandParent = $this->getBuilder(null, null, 'stdClass') + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + $parent = $this->getBuilder() + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->setInheritData(true) + ->getForm(); + $form = $this->getBuilder('name')->getForm(); + $grandParent->add($parent); + $parent->add($form); + + $this->assertEquals(new PropertyPath('name'), $form->getPropertyPath()); + } + + public function testGetPropertyPathDefaultsToIndexedNameIfDataClassOfFirstParentWithoutInheritDataIsNull() + { + $grandParent = $this->getBuilder() + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + $parent = $this->getBuilder() + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->setInheritData(true) + ->getForm(); + $form = $this->getBuilder('name')->getForm(); + $grandParent->add($parent); + $parent->add($form); + + $this->assertEquals(new PropertyPath('[name]'), $form->getPropertyPath()); + } + /** * @expectedException \Symfony\Component\Form\Exception\Exception */ @@ -809,7 +845,7 @@ public function testViewDataMustBeObjectIfDataClassIsSet() } /** - * @expectedException \Symfony\Component\Form\Exception\Exception + * @expectedException \Symfony\Component\Form\Exception\RuntimeException */ public function testSetDataCannotInvokeItself() { @@ -857,6 +893,103 @@ public function testProcessForwardsToFormProcessor() $this->assertSame($form, $form->process('REQUEST')); } + public function testFormInheritsParentData() + { + $child = $this->getBuilder('child') + ->setInheritData(true); + + $parent = $this->getBuilder('parent') + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->setData('foo') + ->addModelTransformer(new FixedDataTransformer(array( + 'foo' => 'norm[foo]', + ))) + ->addViewTransformer(new FixedDataTransformer(array( + 'norm[foo]' => 'view[foo]', + ))) + ->add($child) + ->getForm(); + + $this->assertSame('foo', $parent->get('child')->getData()); + $this->assertSame('norm[foo]', $parent->get('child')->getNormData()); + $this->assertSame('view[foo]', $parent->get('child')->getViewData()); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\FormException + */ + public function testInheritDataDisallowsSetData() + { + $form = $this->getBuilder() + ->setInheritData(true) + ->getForm(); + + $form->setData('foo'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\FormException + */ + public function testGetDataRequiresParentToBeSetIfInheritData() + { + $form = $this->getBuilder() + ->setInheritData(true) + ->getForm(); + + $form->getData(); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\FormException + */ + public function testGetNormDataRequiresParentToBeSetIfInheritData() + { + $form = $this->getBuilder() + ->setInheritData(true) + ->getForm(); + + $form->getNormData(); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\FormException + */ + public function testGetViewDataRequiresParentToBeSetIfInheritData() + { + $form = $this->getBuilder() + ->setInheritData(true) + ->getForm(); + + $form->getViewData(); + } + + public function testPostBindDataIsNullIfInheritData() + { + $test = $this; + $form = $this->getBuilder() + ->addEventListener(FormEvents::POST_BIND, function (FormEvent $event) use ($test) { + $test->assertNull($event->getData()); + }) + ->setInheritData(true) + ->getForm(); + + $form->bind('foo'); + } + + public function testBindIsNeverFiredIfInheritData() + { + $test = $this; + $form = $this->getBuilder() + ->addEventListener(FormEvents::BIND, function (FormEvent $event) use ($test) { + $test->fail('The BIND event should not be fired'); + }) + ->setInheritData(true) + ->getForm(); + + $form->bind('foo'); + } + protected function createForm() { return $this->getBuilder()->getForm(); diff --git a/Util/InheritDataAwareIterator.php b/Util/InheritDataAwareIterator.php new file mode 100644 index 0000000000..5c2c5fadcc --- /dev/null +++ b/Util/InheritDataAwareIterator.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Util; + +/** + * Iterator that returns only forms from a form tree that do not inherit their + * parent data. + * + * If the iterator encounters a form that inherits its parent data, it enters + * the form and traverses its children as well. + * + * @author Bernhard Schussek + */ +class InheritDataAwareIterator extends VirtualFormAwareIterator +{ + /** + * Creates a new iterator. + * + * @param \Symfony\Component\Form\FormInterface[] $forms An array + */ + public function __construct(array $forms) + { + // Skip the deprecation error + \ArrayIterator::__construct($forms); + } +} diff --git a/Util/VirtualFormAwareIterator.php b/Util/VirtualFormAwareIterator.php index 92e9da0d51..55c82ab550 100644 --- a/Util/VirtualFormAwareIterator.php +++ b/Util/VirtualFormAwareIterator.php @@ -19,12 +19,27 @@ * the form and traverses its children as well. * * @author Bernhard Schussek + * + * @deprecated Deprecated since version 2.2, to be removed in 2.3. Use + * {@link InheritDataAwareIterator} instead. */ class VirtualFormAwareIterator extends \ArrayIterator implements \RecursiveIterator { + /** + * Creates a new iterator. + * + * @param \Symfony\Component\Form\FormInterface[] $forms An array + */ + public function __construct(array $forms) + { + trigger_error('VirtualFormAwareIterator is deprecated since version 2.2 and will be removed in 2.3. Use InheritDataAwareIterator instead.', E_USER_DEPRECATED); + + parent::__construct($forms); + } + public function getChildren() { - return new self($this->current()->all()); + return new static($this->current()->all()); } public function hasChildren() From da7e90712cbd457cdd141d667446b29c289caeb3 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 18 Apr 2013 12:09:11 +0200 Subject: [PATCH 106/447] [Form] Fixed the deprecation notes for the "virtual" option --- CHANGELOG.md | 2 +- Extension/Core/Type/FormType.php | 15 ++++++++++++++- FormConfigBuilder.php | 10 ++++++---- Util/VirtualFormAwareIterator.php | 5 +++-- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9fdeaffcdd..25fdc6d8f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ CHANGELOG * added FormProcessorInterface and FormInterface::process() * deprecated passing a Request instance to FormInterface::bind() * added options "method" and "action" to FormType - * deprecated option "virtual", renamed it to "inherit_data" + * deprecated option "virtual" in favor "inherit_data" * deprecated VirtualFormAwareIterator in favor of InheritDataAwareIterator * [BC BREAK] removed the "array" type hint from DataMapperInterface * improved forms inheriting their parent data to actually return that data from getData(), getNormData() and getViewData() diff --git a/Extension/Core/Type/FormType.php b/Extension/Core/Type/FormType.php index 31835357c1..473b009ea3 100644 --- a/Extension/Core/Type/FormType.php +++ b/Extension/Core/Type/FormType.php @@ -150,6 +150,18 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) return $options['compound']; }; + // BC with old "virtual" option + $inheritData = function (Options $options) { + if (null !== $options['virtual']) { + // Uncomment this as soon as the deprecation note should be shown + // trigger_error('The form option "virtual" is deprecated since version 2.3 and will be removed in 3.0. Use "inherit_data" instead.', E_USER_DEPRECATED); + + return $options['virtual']; + } + + return false; + }; + // If data is given, the form is locked to that data // (independent of its value) $resolver->setOptional(array( @@ -169,7 +181,8 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'by_reference' => true, 'error_bubbling' => $errorBubbling, 'label_attr' => array(), - 'inherit_data' => false, + 'virtual' => null, + 'inherit_data' => $inheritData, 'compound' => true, 'method' => 'POST', // According to RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt) diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index 26cea6b7f4..0927c72921 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -351,12 +351,13 @@ public function getInheritData() * * @return FormConfigBuilder The configuration object. * - * @deprecated Deprecated since version 2.2, to be removed in 2.3. Use + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link getInheritData()} instead. */ public function getVirtual() { - trigger_error('getVirtual() is deprecated since version 2.2 and will be removed in 2.3. Use getInheritData() instead.', E_USER_DEPRECATED); + // Uncomment this as soon as the deprecation note should be shown + // trigger_error('getVirtual() is deprecated since version 2.3 and will be removed in 3.0. Use getInheritData() instead.', E_USER_DEPRECATED); return $this->getInheritData(); } @@ -709,12 +710,13 @@ public function setInheritData($inheritData) * * @return FormConfigBuilder The configuration object. * - * @deprecated Deprecated since version 2.2, to be removed in 2.3. Use + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link setInheritData()} instead. */ public function setVirtual($inheritData) { - trigger_error('setVirtual() is deprecated since version 2.2 and will be removed in 2.3. Use setInheritData() instead.', E_USER_DEPRECATED); + // Uncomment this as soon as the deprecation note should be shown + // trigger_error('setVirtual() is deprecated since version 2.3 and will be removed in 3.0. Use setInheritData() instead.', E_USER_DEPRECATED); $this->setInheritData($inheritData); } diff --git a/Util/VirtualFormAwareIterator.php b/Util/VirtualFormAwareIterator.php index 55c82ab550..24fdc8bb9f 100644 --- a/Util/VirtualFormAwareIterator.php +++ b/Util/VirtualFormAwareIterator.php @@ -20,7 +20,7 @@ * * @author Bernhard Schussek * - * @deprecated Deprecated since version 2.2, to be removed in 2.3. Use + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link InheritDataAwareIterator} instead. */ class VirtualFormAwareIterator extends \ArrayIterator implements \RecursiveIterator @@ -32,7 +32,8 @@ class VirtualFormAwareIterator extends \ArrayIterator implements \RecursiveItera */ public function __construct(array $forms) { - trigger_error('VirtualFormAwareIterator is deprecated since version 2.2 and will be removed in 2.3. Use InheritDataAwareIterator instead.', E_USER_DEPRECATED); + // Uncomment this as soon as the deprecation note should be shown + // trigger_error('VirtualFormAwareIterator is deprecated since version 2.3 and will be removed in 3.0. Use InheritDataAwareIterator instead.', E_USER_DEPRECATED); parent::__construct($forms); } From 0a57cf3838e69c20d7603b91703c33f1f2e6be3c Mon Sep 17 00:00:00 2001 From: WouterJ Date: Fri, 12 Apr 2013 17:49:02 +0200 Subject: [PATCH 107/447] Moved TypeTestCase to it's own namespace --- CHANGELOG.md | 1 + Test/TypeTestCase.php | 42 +++++++++++++++++++ Tests/Extension/Core/Type/BaseTypeTest.php | 2 +- .../Extension/Core/Type/CheckboxTypeTest.php | 2 +- Tests/Extension/Core/Type/ChoiceTypeTest.php | 2 +- .../Core/Type/CollectionTypeTest.php | 2 +- Tests/Extension/Core/Type/FileTypeTest.php | 2 +- .../Extension/Core/Type/PasswordTypeTest.php | 2 +- .../Extension/Core/Type/RepeatedTypeTest.php | 2 +- .../Extension/Core/Type/TimezoneTypeTest.php | 2 +- Tests/Extension/Core/Type/TypeTestCase.php | 31 +++----------- .../Csrf/Type/FormTypeCsrfExtensionTest.php | 2 +- .../Extension/Validator/Type/TypeTestCase.php | 4 +- 13 files changed, 59 insertions(+), 37 deletions(-) create mode 100644 Test/TypeTestCase.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 40976fa8d0..a4d2bdb18c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG 2.3.0 ------ + * deprecated TypeTestCase in the Symfony\Component\Form\Tests\Extension\Core\Type namespace and moved it to the Symfony\Component\Form\Test namespace. * changed FormRenderer::humanize() to humanize also camel cased field name * added FormProcessorInterface and FormInterface::process() * deprecated passing a Request instance to FormInterface::bind() diff --git a/Test/TypeTestCase.php b/Test/TypeTestCase.php new file mode 100644 index 0000000000..bf65d10e33 --- /dev/null +++ b/Test/TypeTestCase.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Test; + +use Symfony\Component\Form\FormBuilder; +use Symfony\Component\Form\Tests\FormIntegrationTestCase; +use Symfony\Component\EventDispatcher\EventDispatcher; + +abstract class TypeTestCase extends FormIntegrationTestCase +{ + /** + * @var FormBuilder + */ + protected $builder; + + /** + * @var EventDispatcher + */ + protected $dispatcher; + + protected function setUp() + { + parent::setUp(); + + $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $this->builder = new FormBuilder(null, null, $this->dispatcher, $this->factory); + } + + public static function assertDateTimeEquals(\DateTime $expected, \DateTime $actual) + { + self::assertEquals($expected->format('c'), $actual->format('c')); + } +} diff --git a/Tests/Extension/Core/Type/BaseTypeTest.php b/Tests/Extension/Core/Type/BaseTypeTest.php index d56355c644..34a54ac95a 100644 --- a/Tests/Extension/Core/Type/BaseTypeTest.php +++ b/Tests/Extension/Core/Type/BaseTypeTest.php @@ -14,7 +14,7 @@ /** * @author Bernhard Schussek */ -abstract class BaseTypeTest extends TypeTestCase +abstract class BaseTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { public function testPassDisabledAsOption() { diff --git a/Tests/Extension/Core/Type/CheckboxTypeTest.php b/Tests/Extension/Core/Type/CheckboxTypeTest.php index 16a71d8f20..304958f768 100644 --- a/Tests/Extension/Core/Type/CheckboxTypeTest.php +++ b/Tests/Extension/Core/Type/CheckboxTypeTest.php @@ -13,7 +13,7 @@ use Symfony\Component\Form\CallbackTransformer; -class CheckboxTypeTest extends TypeTestCase +class CheckboxTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { public function testPassValueToView() { diff --git a/Tests/Extension/Core/Type/ChoiceTypeTest.php b/Tests/Extension/Core/Type/ChoiceTypeTest.php index 844715c650..6e01d37dab 100644 --- a/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -14,7 +14,7 @@ use Symfony\Component\Form\Extension\Core\ChoiceList\ObjectChoiceList; use Symfony\Component\Form\Extension\Core\View\ChoiceView; -class ChoiceTypeTest extends TypeTestCase +class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { private $choices = array( 'a' => 'Bernhard', diff --git a/Tests/Extension/Core/Type/CollectionTypeTest.php b/Tests/Extension/Core/Type/CollectionTypeTest.php index 15896dae22..5a4974ac50 100644 --- a/Tests/Extension/Core/Type/CollectionTypeTest.php +++ b/Tests/Extension/Core/Type/CollectionTypeTest.php @@ -13,7 +13,7 @@ use Symfony\Component\Form\Form; -class CollectionTypeTest extends TypeTestCase +class CollectionTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { public function testContainsNoChildByDefault() { diff --git a/Tests/Extension/Core/Type/FileTypeTest.php b/Tests/Extension/Core/Type/FileTypeTest.php index 68efc0cb20..c25c53fc69 100644 --- a/Tests/Extension/Core/Type/FileTypeTest.php +++ b/Tests/Extension/Core/Type/FileTypeTest.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; -class FileTypeTest extends TypeTestCase +class FileTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { // https://github.com/symfony/symfony/pull/5028 public function testSetData() diff --git a/Tests/Extension/Core/Type/PasswordTypeTest.php b/Tests/Extension/Core/Type/PasswordTypeTest.php index fdfd0083eb..a67564b987 100644 --- a/Tests/Extension/Core/Type/PasswordTypeTest.php +++ b/Tests/Extension/Core/Type/PasswordTypeTest.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; -class PasswordTypeTest extends TypeTestCase +class PasswordTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { public function testEmptyIfNotBound() { diff --git a/Tests/Extension/Core/Type/RepeatedTypeTest.php b/Tests/Extension/Core/Type/RepeatedTypeTest.php index 66510034d3..80fa9f045a 100644 --- a/Tests/Extension/Core/Type/RepeatedTypeTest.php +++ b/Tests/Extension/Core/Type/RepeatedTypeTest.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; -class RepeatedTypeTest extends TypeTestCase +class RepeatedTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { protected $form; diff --git a/Tests/Extension/Core/Type/TimezoneTypeTest.php b/Tests/Extension/Core/Type/TimezoneTypeTest.php index fcb8c7eeb4..81df20cbb9 100644 --- a/Tests/Extension/Core/Type/TimezoneTypeTest.php +++ b/Tests/Extension/Core/Type/TimezoneTypeTest.php @@ -13,7 +13,7 @@ use Symfony\Component\Form\Extension\Core\View\ChoiceView; -class TimezoneTypeTest extends TypeTestCase +class TimezoneTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { public function testTimezonesAreSelectable() { diff --git a/Tests/Extension/Core/Type/TypeTestCase.php b/Tests/Extension/Core/Type/TypeTestCase.php index 9101e45308..733546e382 100644 --- a/Tests/Extension/Core/Type/TypeTestCase.php +++ b/Tests/Extension/Core/Type/TypeTestCase.php @@ -11,32 +11,11 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; -use Symfony\Component\Form\FormBuilder; -use Symfony\Component\Form\Tests\FormIntegrationTestCase; -use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\Form\Test\TypeTestCase as BaseTypeTestCase; -abstract class TypeTestCase extends FormIntegrationTestCase +/** + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use Symfony\Component\Form\Test\TypeTestCase instead. + */ +abstract class TypeTestCase extends BaseTypeTestCase { - /** - * @var FormBuilder - */ - protected $builder; - - /** - * @var EventDispatcher - */ - protected $dispatcher; - - protected function setUp() - { - parent::setUp(); - - $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); - $this->builder = new FormBuilder(null, null, $this->dispatcher, $this->factory); - } - - public static function assertDateTimeEquals(\DateTime $expected, \DateTime $actual) - { - self::assertEquals($expected->format('c'), $actual->format('c')); - } } diff --git a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php index 47dd529270..8ee8988130 100644 --- a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php +++ b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php @@ -13,8 +13,8 @@ use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\Test\TypeTestCase; use Symfony\Component\Form\Extension\Csrf\CsrfExtension; -use Symfony\Component\Form\Tests\Extension\Core\Type\TypeTestCase; class FormTypeCsrfExtensionTest_ChildType extends AbstractType { diff --git a/Tests/Extension/Validator/Type/TypeTestCase.php b/Tests/Extension/Validator/Type/TypeTestCase.php index 45c2690ded..d94d896a1c 100644 --- a/Tests/Extension/Validator/Type/TypeTestCase.php +++ b/Tests/Extension/Validator/Type/TypeTestCase.php @@ -11,10 +11,10 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\Type; -use Symfony\Component\Form\Tests\Extension\Core\Type\TypeTestCase as BaseTestCase; +use Symfony\Component\Form\Test\TypeTestCase as BaseTypeTestCase; use Symfony\Component\Form\Extension\Validator\ValidatorExtension; -abstract class TypeTestCase extends BaseTestCase +abstract class TypeTestCase extends BaseTypeTestCase { protected $validator; From 89c68be33857a8f9905d581a0888133b7ab3d9a7 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Fri, 19 Apr 2013 14:16:57 +0200 Subject: [PATCH 108/447] Moved FormIntegrationTestCase and FormPerformanceTestCase to the Test namespace --- CHANGELOG.md | 3 +- Test/FormIntegrationTestCase.php | 41 +++++++++++ Test/FormPerformanceTestCase.php | 70 +++++++++++++++++++ Test/TypeTestCase.php | 1 - Tests/AbstractLayoutTest.php | 2 +- Tests/CompoundFormPerformanceTest.php | 2 +- .../Core/Type/ChoiceTypePerformanceTest.php | 2 +- Tests/FormIntegrationTestCase.php | 26 +------ Tests/FormPerformanceTestCase.php | 57 ++------------- 9 files changed, 123 insertions(+), 81 deletions(-) create mode 100644 Test/FormIntegrationTestCase.php create mode 100644 Test/FormPerformanceTestCase.php diff --git a/CHANGELOG.md b/CHANGELOG.md index a4d2bdb18c..5acff27ae3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,8 @@ CHANGELOG 2.3.0 ------ - * deprecated TypeTestCase in the Symfony\Component\Form\Tests\Extension\Core\Type namespace and moved it to the Symfony\Component\Form\Test namespace. + * deprecated FormPerformanceTestCase and FormIntegrationTestCase in the Symfony\Component\Form\Tests namespace and moved them to the Symfony\Component\Form\Test namespace + * deprecated TypeTestCase in the Symfony\Component\Form\Tests\Extension\Core\Type namespace and moved it to the Symfony\Component\Form\Test namespace * changed FormRenderer::humanize() to humanize also camel cased field name * added FormProcessorInterface and FormInterface::process() * deprecated passing a Request instance to FormInterface::bind() diff --git a/Test/FormIntegrationTestCase.php b/Test/FormIntegrationTestCase.php new file mode 100644 index 0000000000..68e5f2445e --- /dev/null +++ b/Test/FormIntegrationTestCase.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Test; + +use Symfony\Component\Form\Forms; + +/** + * @author Bernhard Schussek + */ +abstract class FormIntegrationTestCase extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Symfony\Component\Form\FormFactoryInterface + */ + protected $factory; + + protected function setUp() + { + if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { + $this->markTestSkipped('The "EventDispatcher" component is not available'); + } + + $this->factory = Forms::createFormFactoryBuilder() + ->addExtensions($this->getExtensions()) + ->getFormFactory(); + } + + protected function getExtensions() + { + return array(); + } +} diff --git a/Test/FormPerformanceTestCase.php b/Test/FormPerformanceTestCase.php new file mode 100644 index 0000000000..573f4e913c --- /dev/null +++ b/Test/FormPerformanceTestCase.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Test; + +/** + * Base class for performance tests. + * + * Copied from Doctrine 2's OrmPerformanceTestCase. + * + * @author robo + * @author Bernhard Schussek + */ +abstract class FormPerformanceTestCase extends FormIntegrationTestCase +{ + /** + * @var integer + */ + protected $maxRunningTime = 0; + + /** + */ + protected function runTest() + { + $s = microtime(true); + parent::runTest(); + $time = microtime(true) - $s; + + if ($this->maxRunningTime != 0 && $time > $this->maxRunningTime) { + $this->fail( + sprintf( + 'expected running time: <= %s but was: %s', + + $this->maxRunningTime, + $time + ) + ); + } + } + + /** + * @param integer $maxRunningTime + * @throws \InvalidArgumentException + */ + public function setMaxRunningTime($maxRunningTime) + { + if (is_integer($maxRunningTime) && $maxRunningTime >= 0) { + $this->maxRunningTime = $maxRunningTime; + } else { + throw new \InvalidArgumentException; + } + } + + /** + * @return integer + * @since Method available since Release 2.3.0 + */ + public function getMaxRunningTime() + { + return $this->maxRunningTime; + } +} diff --git a/Test/TypeTestCase.php b/Test/TypeTestCase.php index bf65d10e33..9d51a9eec1 100644 --- a/Test/TypeTestCase.php +++ b/Test/TypeTestCase.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Form\Test; use Symfony\Component\Form\FormBuilder; -use Symfony\Component\Form\Tests\FormIntegrationTestCase; use Symfony\Component\EventDispatcher\EventDispatcher; abstract class TypeTestCase extends FormIntegrationTestCase diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index 176fb17962..9f8200c095 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -15,7 +15,7 @@ use Symfony\Component\Form\FormView; use Symfony\Component\Form\Extension\Csrf\CsrfExtension; -abstract class AbstractLayoutTest extends FormIntegrationTestCase +abstract class AbstractLayoutTest extends \Symfony\Component\Form\Test\FormIntegrationTestCase { protected $csrfProvider; diff --git a/Tests/CompoundFormPerformanceTest.php b/Tests/CompoundFormPerformanceTest.php index b0191c5369..73c602c554 100644 --- a/Tests/CompoundFormPerformanceTest.php +++ b/Tests/CompoundFormPerformanceTest.php @@ -14,7 +14,7 @@ /** * @author Bernhard Schussek */ -class CompoundFormPerformanceTest extends FormPerformanceTestCase +class CompoundFormPerformanceTest extends \Symfony\Component\Form\Tests\FormPerformanceTestCase { /** * Create a compound form multiple times, as happens in a collection form diff --git a/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.php b/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.php index dbb3e0f997..0685946fc1 100644 --- a/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.php +++ b/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; -use Symfony\Component\Form\Tests\FormPerformanceTestCase; +use Symfony\Component\Form\Test\FormPerformanceTestCase; /** * @author Bernhard Schussek diff --git a/Tests/FormIntegrationTestCase.php b/Tests/FormIntegrationTestCase.php index 536ff4c824..763286c266 100644 --- a/Tests/FormIntegrationTestCase.php +++ b/Tests/FormIntegrationTestCase.php @@ -11,31 +11,11 @@ namespace Symfony\Component\Form\Tests; -use Symfony\Component\Form\Forms; +use Symfony\Component\Form\Test\FormIntegrationTestCase as BaseFormIntegrationTestCase; /** - * @author Bernhard Schussek + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use Symfony\Component\Form\Test\FormIntegrationTestCase instead. */ -abstract class FormIntegrationTestCase extends \PHPUnit_Framework_TestCase +abstract class FormIntegrationTestCase extends BaseFormIntegrationTestCase { - /** - * @var \Symfony\Component\Form\FormFactoryInterface - */ - protected $factory; - - protected function setUp() - { - if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - - $this->factory = Forms::createFormFactoryBuilder() - ->addExtensions($this->getExtensions()) - ->getFormFactory(); - } - - protected function getExtensions() - { - return array(); - } } diff --git a/Tests/FormPerformanceTestCase.php b/Tests/FormPerformanceTestCase.php index 04a855b3ba..39882e85e8 100644 --- a/Tests/FormPerformanceTestCase.php +++ b/Tests/FormPerformanceTestCase.php @@ -11,60 +11,11 @@ namespace Symfony\Component\Form\Tests; +use Symfony\Component\Form\Test\FormPerformanceTestCase as BaseFormPerformanceTestCase; + /** - * Base class for performance tests. - * - * Copied from Doctrine 2's OrmPerformanceTestCase. - * - * @author robo - * @author Bernhard Schussek + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use Symfony\Component\Form\Test\FormPerformanceTestCase instead. */ -abstract class FormPerformanceTestCase extends FormIntegrationTestCase +abstract class FormPerformanceTestCase extends BaseFormPerformanceTestCase { - /** - * @var integer - */ - protected $maxRunningTime = 0; - - /** - */ - protected function runTest() - { - $s = microtime(true); - parent::runTest(); - $time = microtime(true) - $s; - - if ($this->maxRunningTime != 0 && $time > $this->maxRunningTime) { - $this->fail( - sprintf( - 'expected running time: <= %s but was: %s', - - $this->maxRunningTime, - $time - ) - ); - } - } - - /** - * @param integer $maxRunningTime - * @throws \InvalidArgumentException - */ - public function setMaxRunningTime($maxRunningTime) - { - if (is_integer($maxRunningTime) && $maxRunningTime >= 0) { - $this->maxRunningTime = $maxRunningTime; - } else { - throw new \InvalidArgumentException; - } - } - - /** - * @return integer - * @since Method available since Release 2.3.0 - */ - public function getMaxRunningTime() - { - return $this->maxRunningTime; - } } From aef13fae752c392d7bc5ed1315926f60045a78ff Mon Sep 17 00:00:00 2001 From: Alexander Kotynia Date: Mon, 15 Apr 2013 23:11:02 +0300 Subject: [PATCH 109/447] [Form] Make exception handling consistent with other components --- AbstractExtension.php | 4 +- Button.php | 32 +++--- ButtonBuilder.php | 108 +++++++++--------- CHANGELOG.md | 3 + Exception/AlreadyBoundException.php | 2 +- Exception/ErrorMappingException.php | 2 +- Exception/InvalidConfigurationException.php | 2 +- ...eationException.php => LogicException.php} | 6 +- Exception/NotInitializedException.php | 16 --- Exception/NotValidException.php | 16 --- ...Exception.php => OutOfBoundsException.php} | 6 +- Exception/StringCastException.php | 2 +- Exception/TransformationFailedException.php | 2 +- Exception/TypeLoaderException.php | 16 --- Exception/UnexpectedTypeException.php | 2 +- Extension/Core/ChoiceList/ChoiceList.php | 5 +- Extension/Core/ChoiceList/LazyChoiceList.php | 4 +- .../Core/ChoiceList/ObjectChoiceList.php | 5 +- Extension/Core/Type/ChoiceType.php | 4 +- Extension/Core/Type/FormType.php | 4 +- .../DependencyInjectionExtension.php | 5 +- .../EventListener/BindRequestListener.php | 4 +- .../ViolationMapper/ViolationPath.php | 11 +- Form.php | 20 ++-- FormBuilder.php | 4 +- FormBuilderInterface.php | 2 +- FormConfigBuilder.php | 8 +- FormExtensionInterface.php | 2 +- FormFactoryInterface.php | 12 +- FormInterface.php | 6 +- FormRegistry.php | 4 +- FormRegistryInterface.php | 4 +- FormRenderer.php | 9 +- FormView.php | 6 +- Guess/Guess.php | 6 +- PreloadedExtension.php | 4 +- ResolvedFormType.php | 4 +- ResolvedFormTypeFactoryInterface.php | 4 +- .../Core/ChoiceList/LazyChoiceListTest.php | 2 +- .../Core/ChoiceList/ObjectChoiceListTest.php | 2 +- Tests/Fixtures/FixedDataTransformer.php | 5 +- Tests/FormBuilderTest.php | 2 +- Tests/FormConfigTest.php | 5 +- Tests/FormRegistryTest.php | 4 +- Tests/SimpleFormTest.php | 14 +-- 45 files changed, 178 insertions(+), 212 deletions(-) rename Exception/{CreationException.php => LogicException.php} (63%) delete mode 100644 Exception/NotInitializedException.php delete mode 100644 Exception/NotValidException.php rename Exception/{TypeDefinitionException.php => OutOfBoundsException.php} (60%) delete mode 100644 Exception/TypeLoaderException.php diff --git a/AbstractExtension.php b/AbstractExtension.php index daa57e768f..4db77b9bb5 100644 --- a/AbstractExtension.php +++ b/AbstractExtension.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form; -use Symfony\Component\Form\Exception\Exception; +use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\UnexpectedTypeException; /** @@ -53,7 +53,7 @@ public function getType($name) } if (!isset($this->types[$name])) { - throw new Exception(sprintf('The type "%s" can not be loaded by this extension', $name)); + throw new InvalidArgumentException(sprintf('The type "%s" can not be loaded by this extension', $name)); } return $this->types[$name]; diff --git a/Button.php b/Button.php index 77af61b8d8..d98ef87844 100644 --- a/Button.php +++ b/Button.php @@ -65,11 +65,11 @@ public function offsetExists($offset) * * @param mixed $offset * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function offsetGet($offset) { - throw new \BadMethodCallException('Buttons cannot have children.'); + throw new BadMethodCallException('Buttons cannot have children.'); } /** @@ -80,11 +80,11 @@ public function offsetGet($offset) * @param mixed $offset * @param mixed $value * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function offsetSet($offset, $value) { - throw new \BadMethodCallException('Buttons cannot have children.'); + throw new BadMethodCallException('Buttons cannot have children.'); } /** @@ -94,11 +94,11 @@ public function offsetSet($offset, $value) * * @param mixed $offset * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function offsetUnset($offset) { - throw new \BadMethodCallException('Buttons cannot have children.'); + throw new BadMethodCallException('Buttons cannot have children.'); } /** @@ -126,11 +126,11 @@ public function getParent() * @param null $type * @param array $options * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function add($child, $type = null, array $options = array()) { - throw new \BadMethodCallException('Buttons cannot have children.'); + throw new BadMethodCallException('Buttons cannot have children.'); } /** @@ -140,11 +140,11 @@ public function add($child, $type = null, array $options = array()) * * @param string $name * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function get($name) { - throw new \BadMethodCallException('Buttons cannot have children.'); + throw new BadMethodCallException('Buttons cannot have children.'); } /** @@ -166,11 +166,11 @@ public function has($name) * * @param string $name * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function remove($name) { - throw new \BadMethodCallException('Buttons cannot have children.'); + throw new BadMethodCallException('Buttons cannot have children.'); } /** @@ -196,11 +196,11 @@ public function getErrors() * * @param string $modelData * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function setData($modelData) { - throw new \BadMethodCallException('Buttons cannot have data.'); + throw new BadMethodCallException('Buttons cannot have data.'); } /** @@ -288,11 +288,11 @@ public function getPropertyPath() * * @param FormError $error * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function addError(FormError $error) { - throw new \BadMethodCallException('Buttons cannot have errors.'); + throw new BadMethodCallException('Buttons cannot have errors.'); } /** diff --git a/ButtonBuilder.php b/ButtonBuilder.php index 66ce61ab53..47892d8e1c 100644 --- a/ButtonBuilder.php +++ b/ButtonBuilder.php @@ -12,8 +12,8 @@ namespace Symfony\Component\Form; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\Form\Exception\FormException; use Symfony\Component\Form\Exception\InvalidArgumentException; +use Symfony\Component\Form\Exception\BadMethodCallException; /** * A builder for {@link Button} instances. @@ -58,7 +58,7 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @param string $name The name of the button. * @param array $options The button's options. * - * @throws FormException If the name is empty. + * @throws InvalidArgumentException If the name is empty. */ public function __construct($name, array $options) { @@ -79,11 +79,11 @@ public function __construct($name, array $options) * @param string|FormTypeInterface $type * @param array $options * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function add($child, $type = null, array $options = array()) { - throw new \BadMethodCallException('Buttons cannot have children.'); + throw new BadMethodCallException('Buttons cannot have children.'); } /** @@ -95,11 +95,11 @@ public function add($child, $type = null, array $options = array()) * @param string|FormTypeInterface $type * @param array $options * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function create($name, $type = null, array $options = array()) { - throw new \BadMethodCallException('Buttons cannot have children.'); + throw new BadMethodCallException('Buttons cannot have children.'); } /** @@ -109,11 +109,11 @@ public function create($name, $type = null, array $options = array()) * * @param string $name * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function get($name) { - throw new \BadMethodCallException('Buttons cannot have children.'); + throw new BadMethodCallException('Buttons cannot have children.'); } /** @@ -123,11 +123,11 @@ public function get($name) * * @param string $name * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function remove($name) { - throw new \BadMethodCallException('Buttons cannot have children.'); + throw new BadMethodCallException('Buttons cannot have children.'); } /** @@ -171,11 +171,11 @@ public function getForm() * @param callable $listener * @param integer $priority * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function addEventListener($eventName, $listener, $priority = 0) { - throw new \BadMethodCallException('Buttons do not support event listeners.'); + throw new BadMethodCallException('Buttons do not support event listeners.'); } /** @@ -185,11 +185,11 @@ public function addEventListener($eventName, $listener, $priority = 0) * * @param EventSubscriberInterface $subscriber * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function addEventSubscriber(EventSubscriberInterface $subscriber) { - throw new \BadMethodCallException('Buttons do not support event subscribers.'); + throw new BadMethodCallException('Buttons do not support event subscribers.'); } /** @@ -200,11 +200,11 @@ public function addEventSubscriber(EventSubscriberInterface $subscriber) * @param DataTransformerInterface $viewTransformer * @param Boolean $forcePrepend * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function addViewTransformer(DataTransformerInterface $viewTransformer, $forcePrepend = false) { - throw new \BadMethodCallException('Buttons do not support data transformers.'); + throw new BadMethodCallException('Buttons do not support data transformers.'); } /** @@ -212,11 +212,11 @@ public function addViewTransformer(DataTransformerInterface $viewTransformer, $f * * This method should not be invoked. * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function resetViewTransformers() { - throw new \BadMethodCallException('Buttons do not support data transformers.'); + throw new BadMethodCallException('Buttons do not support data transformers.'); } /** @@ -227,11 +227,11 @@ public function resetViewTransformers() * @param DataTransformerInterface $modelTransformer * @param Boolean $forceAppend * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function addModelTransformer(DataTransformerInterface $modelTransformer, $forceAppend = false) { - throw new \BadMethodCallException('Buttons do not support data transformers.'); + throw new BadMethodCallException('Buttons do not support data transformers.'); } /** @@ -239,11 +239,11 @@ public function addModelTransformer(DataTransformerInterface $modelTransformer, * * This method should not be invoked. * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function resetModelTransformers() { - throw new \BadMethodCallException('Buttons do not support data transformers.'); + throw new BadMethodCallException('Buttons do not support data transformers.'); } /** @@ -269,11 +269,11 @@ public function setAttributes(array $attributes) * * @param DataMapperInterface $dataMapper * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function setDataMapper(DataMapperInterface $dataMapper = null) { - throw new \BadMethodCallException('Buttons do not support data mappers.'); + throw new BadMethodCallException('Buttons do not support data mappers.'); } /** @@ -295,11 +295,11 @@ public function setDisabled($disabled) * * @param mixed $emptyData * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function setEmptyData($emptyData) { - throw new \BadMethodCallException('Buttons do not support empty data.'); + throw new BadMethodCallException('Buttons do not support empty data.'); } /** @@ -309,11 +309,11 @@ public function setEmptyData($emptyData) * * @param Boolean $errorBubbling * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function setErrorBubbling($errorBubbling) { - throw new \BadMethodCallException('Buttons do not support error bubbling.'); + throw new BadMethodCallException('Buttons do not support error bubbling.'); } /** @@ -323,11 +323,11 @@ public function setErrorBubbling($errorBubbling) * * @param Boolean $required * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function setRequired($required) { - throw new \BadMethodCallException('Buttons cannot be required.'); + throw new BadMethodCallException('Buttons cannot be required.'); } /** @@ -337,11 +337,11 @@ public function setRequired($required) * * @param null $propertyPath * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function setPropertyPath($propertyPath) { - throw new \BadMethodCallException('Buttons do not support property paths.'); + throw new BadMethodCallException('Buttons do not support property paths.'); } /** @@ -351,11 +351,11 @@ public function setPropertyPath($propertyPath) * * @param Boolean $mapped * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function setMapped($mapped) { - throw new \BadMethodCallException('Buttons do not support data mapping.'); + throw new BadMethodCallException('Buttons do not support data mapping.'); } /** @@ -365,11 +365,11 @@ public function setMapped($mapped) * * @param Boolean $byReference * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function setByReference($byReference) { - throw new \BadMethodCallException('Buttons do not support data mapping.'); + throw new BadMethodCallException('Buttons do not support data mapping.'); } /** @@ -379,11 +379,11 @@ public function setByReference($byReference) * * @param Boolean $virtual * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function setVirtual($virtual) { - throw new \BadMethodCallException('Buttons cannot be virtual.'); + throw new BadMethodCallException('Buttons cannot be virtual.'); } /** @@ -393,11 +393,11 @@ public function setVirtual($virtual) * * @param Boolean $compound * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function setCompound($compound) { - throw new \BadMethodCallException('Buttons cannot be compound.'); + throw new BadMethodCallException('Buttons cannot be compound.'); } /** @@ -419,11 +419,11 @@ public function setType(ResolvedFormTypeInterface $type) * * @param array $data * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function setData($data) { - throw new \BadMethodCallException('Buttons do not support data.'); + throw new BadMethodCallException('Buttons do not support data.'); } /** @@ -433,11 +433,11 @@ public function setData($data) * * @param Boolean $locked * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function setDataLocked($locked) { - throw new \BadMethodCallException('Buttons do not support data locking.'); + throw new BadMethodCallException('Buttons do not support data locking.'); } /** @@ -449,11 +449,11 @@ public function setDataLocked($locked) * * @return void * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function setFormFactory(FormFactoryInterface $formFactory) { - throw new \BadMethodCallException('Buttons do not support form factories.'); + throw new BadMethodCallException('Buttons do not support form factories.'); } /** @@ -461,11 +461,11 @@ public function setFormFactory(FormFactoryInterface $formFactory) * * @param string $action * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function setAction($action) { - throw new \BadMethodCallException('Buttons do not support actions.'); + throw new BadMethodCallException('Buttons do not support actions.'); } /** @@ -473,11 +473,11 @@ public function setAction($action) * * @param string $method * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function setMethod($method) { - throw new \BadMethodCallException('Buttons do not support methods.'); + throw new BadMethodCallException('Buttons do not support methods.'); } /** @@ -485,11 +485,11 @@ public function setMethod($method) * * @param FormProcessorInterface $formProcessor * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function setFormProcessor(FormProcessorInterface $formProcessor) { - throw new \BadMethodCallException('Buttons do not support form processors.'); + throw new BadMethodCallException('Buttons do not support form processors.'); } /** @@ -497,11 +497,11 @@ public function setFormProcessor(FormProcessorInterface $formProcessor) * * @param Boolean $inheritData * - * @throws \BadMethodCallException + * @throws BadMethodCallException */ public function setInheritData($inheritData) { - throw new \BadMethodCallException('Buttons do not support data inheritance.'); + throw new BadMethodCallException('Buttons do not support data inheritance.'); } /** diff --git a/CHANGELOG.md b/CHANGELOG.md index ecea1be9ac..ed966f03f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ CHANGELOG * deprecated VirtualFormAwareIterator in favor of InheritDataAwareIterator * [BC BREAK] removed the "array" type hint from DataMapperInterface * improved forms inheriting their parent data to actually return that data from getData(), getNormData() and getViewData() + * added component-level exceptions for various SPL exceptions + changed all uses of the deprecated Exception class to use more specialized exceptions instead + removed NotInitializedException, NotValidException, TypeDefinitionException, TypeLoaderException, CreationException 2.2.0 ----- diff --git a/Exception/AlreadyBoundException.php b/Exception/AlreadyBoundException.php index 9679725e9f..5c1b7c52bc 100644 --- a/Exception/AlreadyBoundException.php +++ b/Exception/AlreadyBoundException.php @@ -11,6 +11,6 @@ namespace Symfony\Component\Form\Exception; -class AlreadyBoundException extends Exception +class AlreadyBoundException extends LogicException { } diff --git a/Exception/ErrorMappingException.php b/Exception/ErrorMappingException.php index adbb2deb51..a696849264 100644 --- a/Exception/ErrorMappingException.php +++ b/Exception/ErrorMappingException.php @@ -11,6 +11,6 @@ namespace Symfony\Component\Form\Exception; -class ErrorMappingException extends Exception +class ErrorMappingException extends RuntimeException { } diff --git a/Exception/InvalidConfigurationException.php b/Exception/InvalidConfigurationException.php index 08c7b72815..daa0c42f58 100644 --- a/Exception/InvalidConfigurationException.php +++ b/Exception/InvalidConfigurationException.php @@ -11,6 +11,6 @@ namespace Symfony\Component\Form\Exception; -class InvalidConfigurationException extends Exception +class InvalidConfigurationException extends InvalidArgumentException { } diff --git a/Exception/CreationException.php b/Exception/LogicException.php similarity index 63% rename from Exception/CreationException.php rename to Exception/LogicException.php index e6c4b4e173..848780215b 100644 --- a/Exception/CreationException.php +++ b/Exception/LogicException.php @@ -12,10 +12,10 @@ namespace Symfony\Component\Form\Exception; /** - * Thrown when a form could not be constructed by a FormFactory + * Base LogicException for Form component. * - * @author Bernhard Schussek + * @author Alexander Kotynia */ -class CreationException extends Exception +class LogicException extends \LogicException implements ExceptionInterface { } diff --git a/Exception/NotInitializedException.php b/Exception/NotInitializedException.php deleted file mode 100644 index 2c416ede3f..0000000000 --- a/Exception/NotInitializedException.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Exception; - -class NotInitializedException extends Exception -{ -} diff --git a/Exception/NotValidException.php b/Exception/NotValidException.php deleted file mode 100644 index 42c5f4ffbd..0000000000 --- a/Exception/NotValidException.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Exception; - -class NotValidException extends Exception -{ -} diff --git a/Exception/TypeDefinitionException.php b/Exception/OutOfBoundsException.php similarity index 60% rename from Exception/TypeDefinitionException.php rename to Exception/OutOfBoundsException.php index 0567350502..44d3116630 100644 --- a/Exception/TypeDefinitionException.php +++ b/Exception/OutOfBoundsException.php @@ -12,10 +12,10 @@ namespace Symfony\Component\Form\Exception; /** - * Thrown when a form type is configured incorrectly + * Base OutOfBoundsException for Form component. * - * @author Bernhard Schussek + * @author Alexander Kotynia */ -class TypeDefinitionException extends Exception +class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface { } diff --git a/Exception/StringCastException.php b/Exception/StringCastException.php index d4bdf0a7fe..f9b51d6049 100644 --- a/Exception/StringCastException.php +++ b/Exception/StringCastException.php @@ -11,6 +11,6 @@ namespace Symfony\Component\Form\Exception; -class StringCastException extends Exception +class StringCastException extends RuntimeException { } diff --git a/Exception/TransformationFailedException.php b/Exception/TransformationFailedException.php index 2bbefbabc8..d32896e69c 100644 --- a/Exception/TransformationFailedException.php +++ b/Exception/TransformationFailedException.php @@ -16,6 +16,6 @@ * * @author Bernhard Schussek */ -class TransformationFailedException extends \RuntimeException implements ExceptionInterface +class TransformationFailedException extends RuntimeException { } diff --git a/Exception/TypeLoaderException.php b/Exception/TypeLoaderException.php deleted file mode 100644 index a257b504fa..0000000000 --- a/Exception/TypeLoaderException.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Exception; - -class TypeLoaderException extends Exception -{ -} diff --git a/Exception/UnexpectedTypeException.php b/Exception/UnexpectedTypeException.php index 77cabb7d7b..474e244bd8 100644 --- a/Exception/UnexpectedTypeException.php +++ b/Exception/UnexpectedTypeException.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form\Exception; -class UnexpectedTypeException extends Exception +class UnexpectedTypeException extends InvalidArgumentException { public function __construct($value, $expectedType) { diff --git a/Extension/Core/ChoiceList/ChoiceList.php b/Extension/Core/ChoiceList/ChoiceList.php index d8f2a16561..f9d381cd04 100644 --- a/Extension/Core/ChoiceList/ChoiceList.php +++ b/Extension/Core/ChoiceList/ChoiceList.php @@ -14,6 +14,7 @@ use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Exception\InvalidConfigurationException; +use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Extension\Core\View\ChoiceView; /** @@ -254,7 +255,7 @@ public function getIndicesForValues(array $values) * @param array $labels The labels corresponding to the choices. * @param array $preferredChoices The preferred choices. * - * @throws \InvalidArgumentException If the structures of the choices and labels array do not match. + * @throws InvalidArgumentException If the structures of the choices and labels array do not match. * @throws InvalidConfigurationException If no valid value or index could be created for a choice. */ protected function addChoices(array &$bucketForPreferred, array &$bucketForRemaining, $choices, array $labels, array $preferredChoices) @@ -262,7 +263,7 @@ protected function addChoices(array &$bucketForPreferred, array &$bucketForRemai // Add choices to the nested buckets foreach ($choices as $group => $choice) { if (!array_key_exists($group, $labels)) { - throw new \InvalidArgumentException('The structures of the choices and labels array do not match.'); + throw new InvalidArgumentException('The structures of the choices and labels array do not match.'); } if (is_array($choice)) { diff --git a/Extension/Core/ChoiceList/LazyChoiceList.php b/Extension/Core/ChoiceList/LazyChoiceList.php index 75742a2d9c..996f900cf3 100644 --- a/Extension/Core/ChoiceList/LazyChoiceList.php +++ b/Extension/Core/ChoiceList/LazyChoiceList.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form\Extension\Core\ChoiceList; -use Symfony\Component\Form\Exception\Exception; +use Symfony\Component\Form\Exception\InvalidArgumentException; /** * A choice list that is loaded lazily @@ -141,7 +141,7 @@ private function load() $choiceList = $this->loadChoiceList(); if (!$choiceList instanceof ChoiceListInterface) { - throw new Exception(sprintf('loadChoiceList() should return a ChoiceListInterface instance. Got %s', gettype($choiceList))); + throw new InvalidArgumentException(sprintf('loadChoiceList() should return a ChoiceListInterface instance. Got %s', gettype($choiceList))); } $this->choiceList = $choiceList; diff --git a/Extension/Core/ChoiceList/ObjectChoiceList.php b/Extension/Core/ChoiceList/ObjectChoiceList.php index 6c3be2c4d1..0a153883a3 100644 --- a/Extension/Core/ChoiceList/ObjectChoiceList.php +++ b/Extension/Core/ChoiceList/ObjectChoiceList.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Extension\Core\ChoiceList; use Symfony\Component\Form\Exception\StringCastException; +use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException; use Symfony\Component\PropertyAccess\PropertyAccess; @@ -103,7 +104,7 @@ public function __construct($choices, $labelPath = null, array $preferredChoices * @param array $labels Ignored. * @param array $preferredChoices The choices to display with priority. * - * @throws \InvalidArgumentException When passing a hierarchy of choices and using + * @throws InvalidArgumentException When passing a hierarchy of choices and using * the "groupPath" option at the same time. */ protected function initialize($choices, array $labels, array $preferredChoices) @@ -113,7 +114,7 @@ protected function initialize($choices, array $labels, array $preferredChoices) foreach ($choices as $i => $choice) { if (is_array($choice)) { - throw new \InvalidArgumentException('You should pass a plain object array (without groups) when using the "groupPath" option.'); + throw new InvalidArgumentException('You should pass a plain object array (without groups) when using the "groupPath" option.'); } try { diff --git a/Extension/Core/Type/ChoiceType.php b/Extension/Core/Type/ChoiceType.php index 20d72d7854..446a74dd6e 100644 --- a/Extension/Core/Type/ChoiceType.php +++ b/Extension/Core/Type/ChoiceType.php @@ -15,7 +15,7 @@ use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; -use Symfony\Component\Form\Exception\Exception; +use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; use Symfony\Component\Form\Extension\Core\EventListener\FixRadioInputListener; use Symfony\Component\Form\Extension\Core\EventListener\FixCheckboxInputListener; @@ -41,7 +41,7 @@ class ChoiceType extends AbstractType public function buildForm(FormBuilderInterface $builder, array $options) { if (!$options['choice_list'] && !is_array($options['choices']) && !$options['choices'] instanceof \Traversable) { - throw new Exception('Either the option "choices" or "choice_list" must be set.'); + throw new LogicException('Either the option "choices" or "choice_list" must be set.'); } if ($options['expanded']) { diff --git a/Extension/Core/Type/FormType.php b/Extension/Core/Type/FormType.php index 473b009ea3..39e16799c4 100644 --- a/Extension/Core/Type/FormType.php +++ b/Extension/Core/Type/FormType.php @@ -16,7 +16,7 @@ use Symfony\Component\Form\FormView; use Symfony\Component\Form\Extension\Core\EventListener\TrimListener; use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; -use Symfony\Component\Form\Exception\Exception; +use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; use Symfony\Component\PropertyAccess\PropertyAccess; @@ -74,7 +74,7 @@ public function buildView(FormView $view, FormInterface $form, array $options) if ($view->parent) { if ('' === $name) { - throw new Exception('Form node with empty name can be used only as root form node.'); + throw new LogicException('Form node with empty name can be used only as root form node.'); } // Complex fields are read-only if they themselves or their parents are. diff --git a/Extension/DependencyInjection/DependencyInjectionExtension.php b/Extension/DependencyInjection/DependencyInjectionExtension.php index 06936643a1..6637ac8c63 100644 --- a/Extension/DependencyInjection/DependencyInjectionExtension.php +++ b/Extension/DependencyInjection/DependencyInjectionExtension.php @@ -13,6 +13,7 @@ use Symfony\Component\Form\FormExtensionInterface; use Symfony\Component\Form\FormTypeGuesserChain; +use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\ContainerInterface; class DependencyInjectionExtension implements FormExtensionInterface @@ -40,13 +41,13 @@ public function __construct(ContainerInterface $container, public function getType($name) { if (!isset($this->typeServiceIds[$name])) { - throw new \InvalidArgumentException(sprintf('The field type "%s" is not registered with the service container.', $name)); + throw new InvalidArgumentException(sprintf('The field type "%s" is not registered with the service container.', $name)); } $type = $this->container->get($this->typeServiceIds[$name]); if ($type->getName() !== $name) { - throw new \InvalidArgumentException( + throw new InvalidArgumentException( sprintf('The type name specified for the service "%s" does not match the actual name. Expected "%s", given "%s"', $this->typeServiceIds[$name], $name, diff --git a/Extension/HttpFoundation/EventListener/BindRequestListener.php b/Extension/HttpFoundation/EventListener/BindRequestListener.php index 3b4359ed5c..f71113f01f 100644 --- a/Extension/HttpFoundation/EventListener/BindRequestListener.php +++ b/Extension/HttpFoundation/EventListener/BindRequestListener.php @@ -13,7 +13,7 @@ use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; -use Symfony\Component\Form\Exception\Exception; +use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; @@ -80,7 +80,7 @@ public function preBind(FormEvent $event) break; default: - throw new Exception(sprintf( + throw new LogicException(sprintf( 'The request method "%s" is not supported', $request->getMethod() )); diff --git a/Extension/Validator/ViolationMapper/ViolationPath.php b/Extension/Validator/ViolationMapper/ViolationPath.php index 6035f66c8e..06d091954e 100644 --- a/Extension/Validator/ViolationMapper/ViolationPath.php +++ b/Extension/Validator/ViolationMapper/ViolationPath.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Extension\Validator\ViolationMapper; +use Symfony\Component\Form\Exception\OutOfBoundsException; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\PropertyAccess\PropertyPathInterface; @@ -155,7 +156,7 @@ public function getElements() public function getElement($index) { if (!isset($this->elements[$index])) { - throw new \OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); + throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); } return $this->elements[$index]; @@ -167,7 +168,7 @@ public function getElement($index) public function isProperty($index) { if (!isset($this->isIndex[$index])) { - throw new \OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); + throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); } return !$this->isIndex[$index]; @@ -179,7 +180,7 @@ public function isProperty($index) public function isIndex($index) { if (!isset($this->isIndex[$index])) { - throw new \OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); + throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); } return $this->isIndex[$index]; @@ -201,12 +202,12 @@ public function isIndex($index) * * @return Boolean Whether the element maps to a form. * - * @throws \OutOfBoundsException If the offset is invalid. + * @throws OutOfBoundsException If the offset is invalid. */ public function mapsForm($index) { if (!isset($this->mapsForm[$index])) { - throw new \OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); + throw new OutOfBoundsException(sprintf('The index %s is not within the violation path', $index)); } return $this->mapsForm[$index]; diff --git a/Form.php b/Form.php index db884cf6f5..4600fd043a 100644 --- a/Form.php +++ b/Form.php @@ -11,12 +11,12 @@ namespace Symfony\Component\Form; -use Symfony\Component\Form\Exception\BadMethodCallException; -use Symfony\Component\Form\Exception\Exception; use Symfony\Component\Form\Exception\RuntimeException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Exception\AlreadyBoundException; use Symfony\Component\Form\Exception\TransformationFailedException; +use Symfony\Component\Form\Exception\LogicException; +use Symfony\Component\Form\Exception\OutOfBoundsException; use Symfony\Component\Form\Util\FormUtil; use Symfony\Component\Form\Util\InheritDataAwareIterator; use Symfony\Component\PropertyAccess\PropertyPath; @@ -146,7 +146,7 @@ class Form implements \IteratorAggregate, FormInterface * * @param FormConfigInterface $config The form configuration. * - * @throws Exception if a data mapper is not provided for a compound form + * @throws LogicException if a data mapper is not provided for a compound form */ public function __construct(FormConfigInterface $config) { @@ -154,7 +154,7 @@ public function __construct(FormConfigInterface $config) // `setData` and `add` will not lead to the correct population of // the child forms. if ($config->getCompound() && !$config->getDataMapper()) { - throw new Exception('Compound forms need a data mapper'); + throw new LogicException('Compound forms need a data mapper'); } // If the form inherits the data from its parent, it is not necessary @@ -249,7 +249,7 @@ public function setParent(FormInterface $parent = null) } if (null !== $parent && '' === $this->config->getName()) { - throw new Exception('A form with an empty name cannot have a parent form.'); + throw new LogicException('A form with an empty name cannot have a parent form.'); } $this->parent = $parent; @@ -340,7 +340,7 @@ public function setData($modelData) if (null === $dataClass && is_object($viewData) && !$viewData instanceof \ArrayAccess) { $expectedType = 'scalar, array or an instance of \ArrayAccess'; - throw new Exception( + throw new LogicException( 'The form\'s view data is expected to be of type '.$expectedType.', ' . 'but is '.$actualType.'. You ' . 'can avoid this error by setting the "data_class" option to ' . @@ -350,7 +350,7 @@ public function setData($modelData) } if (null !== $dataClass && !$viewData instanceof $dataClass) { - throw new Exception( + throw new LogicException( 'The form\'s view data is expected to be an instance of class ' . $dataClass.', but is '. $actualType.'. You can avoid this error ' . 'by setting the "data_class" option to null or by adding a view ' . @@ -729,7 +729,7 @@ public function add($child, $type = null, array $options = array()) } if (!$this->config->getCompound()) { - throw new Exception('You cannot add children to a simple form. Maybe you should set the option "compound" to true?'); + throw new LogicException('You cannot add children to a simple form. Maybe you should set the option "compound" to true?'); } // Obtain the view data @@ -815,7 +815,7 @@ public function get($name) return $this->children[$name]; } - throw new \OutOfBoundsException(sprintf('Child "%s" does not exist.', $name)); + throw new OutOfBoundsException(sprintf('Child "%s" does not exist.', $name)); } /** @@ -851,7 +851,7 @@ public function offsetGet($name) * @param FormInterface $child The child to be added. * * @throws AlreadyBoundException If the form has already been bound. - * @throws FormException When trying to add a child to a non-compound form. + * @throws LogicException When trying to add a child to a non-compound form. * * @see self::add() */ diff --git a/FormBuilder.php b/FormBuilder.php index a778c9e09d..986f43c5ae 100644 --- a/FormBuilder.php +++ b/FormBuilder.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\BadMethodCallException; -use Symfony\Component\Form\Exception\Exception; +use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -126,7 +126,7 @@ public function get($name) return $this->children[$name]; } - throw new Exception(sprintf('The child with the name "%s" does not exist.', $name)); + throw new InvalidArgumentException(sprintf('The child with the name "%s" does not exist.', $name)); } /** diff --git a/FormBuilderInterface.php b/FormBuilderInterface.php index d862c49bf5..1dc4a64e7b 100644 --- a/FormBuilderInterface.php +++ b/FormBuilderInterface.php @@ -49,7 +49,7 @@ public function create($name, $type = null, array $options = array()); * * @return FormBuilderInterface The builder for the child * - * @throws Exception\FormException if the given child does not exist + * @throws Exception\InvalidArgumentException if the given child does not exist */ public function get($name); diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index 0927c72921..b839fa1065 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -185,7 +185,7 @@ class FormConfigBuilder implements FormConfigBuilderInterface * @param EventDispatcherInterface $dispatcher The event dispatcher * @param array $options The form options * - * @throws \InvalidArgumentException If the data class is not a valid class or if + * @throws InvalidArgumentException If the data class is not a valid class or if * the name contains invalid characters. */ public function __construct($name, $dataClass, EventDispatcherInterface $dispatcher, array $options = array()) @@ -193,7 +193,7 @@ public function __construct($name, $dataClass, EventDispatcherInterface $dispatc self::validateName($name); if (null !== $dataClass && !class_exists($dataClass)) { - throw new \InvalidArgumentException(sprintf('The data class "%s" is not a valid class.', $dataClass)); + throw new InvalidArgumentException(sprintf('The data class "%s" is not a valid class.', $dataClass)); } $this->name = (string) $name; @@ -865,7 +865,7 @@ public function getFormConfig() * @param string|integer $name The tested form name. * * @throws UnexpectedTypeException If the name is not a string or an integer. - * @throws \InvalidArgumentException If the name contains invalid characters. + * @throws InvalidArgumentException If the name contains invalid characters. */ public static function validateName($name) { @@ -874,7 +874,7 @@ public static function validateName($name) } if (!self::isValidName($name)) { - throw new \InvalidArgumentException(sprintf( + throw new InvalidArgumentException(sprintf( 'The name "%s" contains illegal characters. Names should start with a letter, digit or underscore and only contain letters, digits, numbers, underscores ("_"), hyphens ("-") and colons (":").', $name )); diff --git a/FormExtensionInterface.php b/FormExtensionInterface.php index dc3ca46570..a67055b797 100644 --- a/FormExtensionInterface.php +++ b/FormExtensionInterface.php @@ -23,7 +23,7 @@ interface FormExtensionInterface * * @return FormTypeInterface The type * - * @throws Exception\FormException if the given type is not supported by this extension + * @throws Exception\InvalidArgumentException if the given type is not supported by this extension */ public function getType($name); diff --git a/FormFactoryInterface.php b/FormFactoryInterface.php index 8edfa95e52..31c46b55d7 100644 --- a/FormFactoryInterface.php +++ b/FormFactoryInterface.php @@ -27,7 +27,7 @@ interface FormFactoryInterface * * @return FormInterface The form named after the type * - * @throws Exception\FormException if any given option is not applicable to the given type + * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the given type */ public function create($type = 'form', $data = null, array $options = array()); @@ -43,7 +43,7 @@ public function create($type = 'form', $data = null, array $options = array()); * * @return FormInterface The form * - * @throws Exception\FormException if any given option is not applicable to the given type + * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the given type */ public function createNamed($name, $type = 'form', $data = null, array $options = array()); @@ -59,7 +59,7 @@ public function createNamed($name, $type = 'form', $data = null, array $options * * @return FormInterface The form named after the property * - * @throws Exception\FormException if any given option is not applicable to the form type + * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the form type */ public function createForProperty($class, $property, $data = null, array $options = array()); @@ -72,7 +72,7 @@ public function createForProperty($class, $property, $data = null, array $option * * @return FormBuilderInterface The form builder * - * @throws Exception\FormException if any given option is not applicable to the given type + * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the given type */ public function createBuilder($type = 'form', $data = null, array $options = array()); @@ -86,7 +86,7 @@ public function createBuilder($type = 'form', $data = null, array $options = arr * * @return FormBuilderInterface The form builder * - * @throws Exception\FormException if any given option is not applicable to the given type + * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the given type */ public function createNamedBuilder($name, $type = 'form', $data = null, array $options = array()); @@ -103,7 +103,7 @@ public function createNamedBuilder($name, $type = 'form', $data = null, array $o * * @return FormBuilderInterface The form builder named after the property * - * @throws Exception\FormException if any given option is not applicable to the form type + * @throws \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException if any given option is not applicable to the form type */ public function createBuilderForProperty($class, $property, $data = null, array $options = array()); } diff --git a/FormInterface.php b/FormInterface.php index 05d95b2282..00512f0833 100644 --- a/FormInterface.php +++ b/FormInterface.php @@ -26,7 +26,7 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable * @return FormInterface The form instance * * @throws Exception\AlreadyBoundException If the form has already been bound. - * @throws Exception\FormException When trying to set a parent for a form with + * @throws Exception\LogicException When trying to set a parent for a form with * an empty name. */ public function setParent(FormInterface $parent = null); @@ -48,7 +48,7 @@ public function getParent(); * @return FormInterface The form instance * * @throws Exception\AlreadyBoundException If the form has already been bound. - * @throws Exception\FormException When trying to add a child to a non-compound form. + * @throws Exception\LogicException When trying to add a child to a non-compound form. * @throws Exception\UnexpectedTypeException If $child or $type has an unexpected type. */ public function add($child, $type = null, array $options = array()); @@ -106,7 +106,7 @@ public function getErrors(); * @return FormInterface The form instance * * @throws Exception\AlreadyBoundException If the form has already been bound. - * @throws Exception\FormException If listeners try to call setData in a cycle. Or if + * @throws Exception\LogicException If listeners try to call setData in a cycle. Or if * the view data does not match the expected type * according to {@link FormConfigInterface::getDataClass}. */ diff --git a/FormRegistry.php b/FormRegistry.php index cb2599c932..0267a5657b 100644 --- a/FormRegistry.php +++ b/FormRegistry.php @@ -13,7 +13,7 @@ use Symfony\Component\Form\Exception\ExceptionInterface; use Symfony\Component\Form\Exception\UnexpectedTypeException; -use Symfony\Component\Form\Exception\Exception; +use Symfony\Component\Form\Exception\InvalidArgumentException; /** * The central registry of the Form component. @@ -86,7 +86,7 @@ public function getType($name) } if (!$type) { - throw new Exception(sprintf('Could not load type "%s"', $name)); + throw new InvalidArgumentException(sprintf('Could not load type "%s"', $name)); } $this->resolveAndAddType($type); diff --git a/FormRegistryInterface.php b/FormRegistryInterface.php index 4edb9833c8..16cd938441 100644 --- a/FormRegistryInterface.php +++ b/FormRegistryInterface.php @@ -27,8 +27,8 @@ interface FormRegistryInterface * * @return ResolvedFormTypeInterface The type * - * @throws Exception\UnexpectedTypeException if the passed name is not a string - * @throws Exception\FormException if the type can not be retrieved from any extension + * @throws Exception\UnexpectedTypeException if the passed name is not a string + * @throws Exception\InvalidArgumentException if the type can not be retrieved from any extension */ public function getType($name); diff --git a/FormRenderer.php b/FormRenderer.php index 09b830b43e..09b010563f 100644 --- a/FormRenderer.php +++ b/FormRenderer.php @@ -11,7 +11,8 @@ namespace Symfony\Component\Form; -use Symfony\Component\Form\Exception\Exception; +use Symfony\Component\Form\Exception\LogicException; +use Symfony\Component\Form\Exception\BadMethodCallException; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; /** @@ -76,7 +77,7 @@ public function setTheme(FormView $view, $themes) public function renderCsrfToken($intention) { if (null === $this->csrfProvider) { - throw new \BadMethodCallException('CSRF token can only be generated if a CsrfProviderInterface is injected in the constructor.'); + throw new BadMethodCallException('CSRF token can only be generated if a CsrfProviderInterface is injected in the constructor.'); } return $this->csrfProvider->generateCsrfToken($intention); @@ -90,7 +91,7 @@ public function renderBlock(FormView $view, $blockName, array $variables = array $resource = $this->engine->getResourceForBlockName($view, $blockName); if (!$resource) { - throw new Exception(sprintf('No block "%s" found while rendering the form.', $blockName)); + throw new LogicException(sprintf('No block "%s" found while rendering the form.', $blockName)); } $viewCacheKey = $view->vars[self::CACHE_KEY_VAR]; @@ -235,7 +236,7 @@ public function searchAndRenderBlock(FormView $view, $blockNameSuffix, array $va // Escape if no resource exists for this block if (!$resource) { - throw new Exception(sprintf( + throw new LogicException(sprintf( 'Unable to render the form as none of the following blocks exist: "%s".', implode('", "', array_reverse($blockNameHierarchy)) )); diff --git a/FormView.php b/FormView.php index 8b9528c3b7..1f53ec6a40 100644 --- a/FormView.php +++ b/FormView.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Form; +use Symfony\Component\Form\Exception\BadMethodCallException; + /** * @author Bernhard Schussek */ @@ -118,11 +120,11 @@ public function offsetExists($name) /** * Implements \ArrayAccess. * - * @throws \BadMethodCallException always as setting a child by name is not allowed + * @throws BadMethodCallException always as setting a child by name is not allowed */ public function offsetSet($name, $value) { - throw new \BadMethodCallException('Not supported'); + throw new BadMethodCallException('Not supported'); } /** diff --git a/Guess/Guess.php b/Guess/Guess.php index f24407dd73..b33c3d802d 100644 --- a/Guess/Guess.php +++ b/Guess/Guess.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Form\Guess; +use Symfony\Component\Form\Exception\InvalidArgumentException; + /** * Base class for guesses made by TypeGuesserInterface implementation * @@ -86,13 +88,13 @@ public static function getBestGuess(array $guesses) * * @param integer $confidence The confidence * - * @throws \InvalidArgumentException if the given value of confidence is unknown + * @throws InvalidArgumentException if the given value of confidence is unknown */ public function __construct($confidence) { if (self::VERY_HIGH_CONFIDENCE !== $confidence && self::HIGH_CONFIDENCE !== $confidence && self::MEDIUM_CONFIDENCE !== $confidence && self::LOW_CONFIDENCE !== $confidence) { - throw new \InvalidArgumentException('The confidence should be one of the constants defined in Guess.'); + throw new InvalidArgumentException('The confidence should be one of the constants defined in Guess.'); } $this->confidence = $confidence; diff --git a/PreloadedExtension.php b/PreloadedExtension.php index eac7b0582d..2d3e9efb08 100644 --- a/PreloadedExtension.php +++ b/PreloadedExtension.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form; -use Symfony\Component\Form\Exception\Exception; +use Symfony\Component\Form\Exception\InvalidArgumentException; /** * A form extension with preloaded types, type exceptions and type guessers. @@ -55,7 +55,7 @@ public function __construct(array $types, array $typeExtensions, FormTypeGuesser public function getType($name) { if (!isset($this->types[$name])) { - throw new Exception(sprintf('The type "%s" can not be loaded by this extension', $name)); + throw new InvalidArgumentException(sprintf('The type "%s" can not be loaded by this extension', $name)); } return $this->types[$name]; diff --git a/ResolvedFormType.php b/ResolvedFormType.php index e48ea5e64d..47d43553cd 100644 --- a/ResolvedFormType.php +++ b/ResolvedFormType.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form; -use Symfony\Component\Form\Exception\Exception; +use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -46,7 +46,7 @@ class ResolvedFormType implements ResolvedFormTypeInterface public function __construct(FormTypeInterface $innerType, array $typeExtensions = array(), ResolvedFormTypeInterface $parent = null) { if (!preg_match('/^[a-z0-9_]*$/i', $innerType->getName())) { - throw new Exception(sprintf( + throw new InvalidArgumentException(sprintf( 'The "%s" form type name ("%s") is not valid. Names must only contain letters, numbers, and "_".', get_class($innerType), $innerType->getName() diff --git a/ResolvedFormTypeFactoryInterface.php b/ResolvedFormTypeFactoryInterface.php index fb2aa4acce..f0ec23308f 100644 --- a/ResolvedFormTypeFactoryInterface.php +++ b/ResolvedFormTypeFactoryInterface.php @@ -31,8 +31,8 @@ interface ResolvedFormTypeFactoryInterface * * @return ResolvedFormTypeInterface * - * @throws Exception\UnexpectedTypeException if the types parent {@link FormTypeInterface::getParent()} is not a string - * @throws Exception\FormException if the types parent can not be retrieved from any extension + * @throws Exception\UnexpectedTypeException if the types parent {@link FormTypeInterface::getParent()} is not a string + * @throws Exception\InvalidArgumentException if the types parent can not be retrieved from any extension */ public function createResolvedType(FormTypeInterface $type, array $typeExtensions, ResolvedFormTypeInterface $parent = null); } diff --git a/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php b/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php index 6a6a48c7d6..bcd309e050 100644 --- a/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php @@ -82,7 +82,7 @@ public function testGetValuesForChoices() } /** - * @expectedException \Symfony\Component\Form\Exception\Exception + * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException */ public function testLoadChoiceListShouldReturnChoiceList() { diff --git a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php index b7487377e6..69c5aa0fcb 100644 --- a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php @@ -196,7 +196,7 @@ public function testInitArrayUsesToString() } /** - * @expectedException \Symfony\Component\Form\Exception\Exception + * @expectedException \Symfony\Component\Form\Exception\StringCastException */ public function testInitArrayThrowsExceptionIfToStringNotFound() { diff --git a/Tests/Fixtures/FixedDataTransformer.php b/Tests/Fixtures/FixedDataTransformer.php index 37c2771385..a5a31248f5 100644 --- a/Tests/Fixtures/FixedDataTransformer.php +++ b/Tests/Fixtures/FixedDataTransformer.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\DataTransformerInterface; +use Symfony\Component\Form\Exception\RuntimeException; class FixedDataTransformer implements DataTransformerInterface { @@ -25,7 +26,7 @@ public function __construct(array $mapping) public function transform($value) { if (!array_key_exists($value, $this->mapping)) { - throw new \RuntimeException(sprintf('No mapping for value "%s"', $value)); + throw new RuntimeException(sprintf('No mapping for value "%s"', $value)); } return $this->mapping[$value]; @@ -36,7 +37,7 @@ public function reverseTransform($value) $result = array_search($value, $this->mapping, true); if ($result === false) { - throw new \RuntimeException(sprintf('No reverse mapping for value "%s"', $value)); + throw new RuntimeException(sprintf('No reverse mapping for value "%s"', $value)); } return $result; diff --git a/Tests/FormBuilderTest.php b/Tests/FormBuilderTest.php index 4f8cf05da8..e076c97e78 100644 --- a/Tests/FormBuilderTest.php +++ b/Tests/FormBuilderTest.php @@ -162,7 +162,7 @@ public function testCreateNoTypeNo() public function testGetUnknown() { - $this->setExpectedException('Symfony\Component\Form\Exception\Exception', 'The child with the name "foo" does not exist.'); + $this->setExpectedException('Symfony\Component\Form\Exception\InvalidArgumentException', 'The child with the name "foo" does not exist.'); $this->builder->get('foo'); } diff --git a/Tests/FormConfigTest.php b/Tests/FormConfigTest.php index 4337a2ab68..90c882f1f1 100644 --- a/Tests/FormConfigTest.php +++ b/Tests/FormConfigTest.php @@ -13,6 +13,7 @@ use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\FormConfigBuilder; +use Symfony\Component\Form\Exception\InvalidArgumentException; /** * @author Bernhard Schussek @@ -82,7 +83,7 @@ public function testNameAcceptsOnlyNamesValidAsIdsInHtml4($name, $accepted) if ($accepted) { throw $e; } - } catch (\InvalidArgumentException $e) { + } catch (InvalidArgumentException $e) { // if the value was not accepted, but should be, rethrow exception if ($accepted) { throw $e; @@ -131,7 +132,7 @@ public function testSetMethodAllowsPatch() } /** - * @expectedException \Symfony\Component\Form\Exception\FormException + * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException */ public function testSetMethodDoesNotAllowOtherValues() { diff --git a/Tests/FormRegistryTest.php b/Tests/FormRegistryTest.php index d29631dcc1..0c8bb6b441 100644 --- a/Tests/FormRegistryTest.php +++ b/Tests/FormRegistryTest.php @@ -173,7 +173,7 @@ public function testGetTypeConnectsParentIfGetParentReturnsInstance() } /** - * @expectedException \Symfony\Component\Form\Exception\Exception + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testGetTypeThrowsExceptionIfParentNotFound() { @@ -185,7 +185,7 @@ public function testGetTypeThrowsExceptionIfParentNotFound() } /** - * @expectedException \Symfony\Component\Form\Exception\Exception + * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException */ public function testGetTypeThrowsExceptionIfTypeNotFound() { diff --git a/Tests/SimpleFormTest.php b/Tests/SimpleFormTest.php index 65f3ee2949..01c0a947d0 100644 --- a/Tests/SimpleFormTest.php +++ b/Tests/SimpleFormTest.php @@ -718,7 +718,7 @@ public function testSetNullParentWorksWithEmptyName() } /** - * @expectedException \Symfony\Component\Form\Exception\Exception + * @expectedException \Symfony\Component\Form\Exception\LogicException * @expectedExceptionMessage A form with an empty name cannot have a parent form. */ public function testFormCannotHaveEmptyNameNotInRootLevel() @@ -800,7 +800,7 @@ public function testGetPropertyPathDefaultsToIndexedNameIfDataClassOfFirstParent } /** - * @expectedException \Symfony\Component\Form\Exception\Exception + * @expectedException \Symfony\Component\Form\Exception\LogicException */ public function testViewDataMustNotBeObjectIfDataClassIsNull() { @@ -830,7 +830,7 @@ public function testViewDataMayBeArrayAccessIfDataClassIsNull() } /** - * @expectedException \Symfony\Component\Form\Exception\Exception + * @expectedException \Symfony\Component\Form\Exception\LogicException */ public function testViewDataMustBeObjectIfDataClassIsSet() { @@ -917,7 +917,7 @@ public function testFormInheritsParentData() } /** - * @expectedException \Symfony\Component\Form\Exception\FormException + * @expectedException \Symfony\Component\Form\Exception\RuntimeException */ public function testInheritDataDisallowsSetData() { @@ -929,7 +929,7 @@ public function testInheritDataDisallowsSetData() } /** - * @expectedException \Symfony\Component\Form\Exception\FormException + * @expectedException \Symfony\Component\Form\Exception\RuntimeException */ public function testGetDataRequiresParentToBeSetIfInheritData() { @@ -941,7 +941,7 @@ public function testGetDataRequiresParentToBeSetIfInheritData() } /** - * @expectedException \Symfony\Component\Form\Exception\FormException + * @expectedException \Symfony\Component\Form\Exception\RuntimeException */ public function testGetNormDataRequiresParentToBeSetIfInheritData() { @@ -953,7 +953,7 @@ public function testGetNormDataRequiresParentToBeSetIfInheritData() } /** - * @expectedException \Symfony\Component\Form\Exception\FormException + * @expectedException \Symfony\Component\Form\Exception\RuntimeException */ public function testGetViewDataRequiresParentToBeSetIfInheritData() { From 766255182f41071c6412804a0c893a7d4ad22170 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Sat, 20 Apr 2013 15:56:42 +0200 Subject: [PATCH 110/447] [Form] Renamed form processors to request handlers --- Button.php | 2 +- ButtonBuilder.php | 6 ++-- CHANGELOG.md | 2 +- ...r.php => HttpFoundationRequestHandler.php} | 8 ++--- .../Type/FormTypeHttpFoundationExtension.php | 10 +++---- Form.php | 4 +-- FormConfigBuilder.php | 26 ++++++++-------- FormConfigBuilderInterface.php | 4 +-- FormConfigInterface.php | 4 +-- FormInterface.php | 4 +-- ...mProcessor.php => NativeRequestHandler.php | 8 ++--- ...terface.php => RequestHandlerInterface.php | 4 +-- ...est.php => AbstractRequestHandlerTest.php} | 30 +++++++++---------- Tests/CompoundFormTest.php | 26 ++++++++-------- ...p => HttpFoundationRequestHandlerTest.php} | 14 ++++----- Tests/FormConfigTest.php | 8 ++--- ...rTest.php => NativeRequestHandlerTest.php} | 20 ++++++------- Tests/SimpleFormTest.php | 10 +++---- 18 files changed, 95 insertions(+), 95 deletions(-) rename Extension/HttpFoundation/{RequestFormProcessor.php => HttpFoundationRequestHandler.php} (89%) rename NativeFormProcessor.php => NativeRequestHandler.php (95%) rename FormProcessorInterface.php => RequestHandlerInterface.php (84%) rename Tests/{AbstractFormProcessorTest.php => AbstractRequestHandlerTest.php} (87%) rename Tests/Extension/HttpFoundation/{RequestFormProcessorTest.php => HttpFoundationRequestHandlerTest.php} (70%) rename Tests/{NativeFormProcessorTest.php => NativeRequestHandlerTest.php} (89%) diff --git a/Button.php b/Button.php index d98ef87844..55606d24da 100644 --- a/Button.php +++ b/Button.php @@ -350,7 +350,7 @@ public function isSynchronized() * * @throws BadMethodCallException */ - public function process($request = null) + public function handleRequest($request = null) { throw new BadMethodCallException('Buttons cannot be processed. Call process() on the root form instead.'); } diff --git a/ButtonBuilder.php b/ButtonBuilder.php index 47892d8e1c..3d6b840299 100644 --- a/ButtonBuilder.php +++ b/ButtonBuilder.php @@ -483,11 +483,11 @@ public function setMethod($method) /** * Unsupported method. * - * @param FormProcessorInterface $formProcessor + * @param RequestHandlerInterface $requestHandler * * @throws BadMethodCallException */ - public function setFormProcessor(FormProcessorInterface $formProcessor) + public function setRequestHandler(RequestHandlerInterface $requestHandler) { throw new BadMethodCallException('Buttons do not support form processors.'); } @@ -766,7 +766,7 @@ public function getMethod() * * @return null Always returns null. */ - public function getFormProcessor() + public function getRequestHandler() { return null; } diff --git a/CHANGELOG.md b/CHANGELOG.md index ed966f03f1..0263c09b79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ CHANGELOG * deprecated FormPerformanceTestCase and FormIntegrationTestCase in the Symfony\Component\Form\Tests namespace and moved them to the Symfony\Component\Form\Test namespace * deprecated TypeTestCase in the Symfony\Component\Form\Tests\Extension\Core\Type namespace and moved it to the Symfony\Component\Form\Test namespace * changed FormRenderer::humanize() to humanize also camel cased field name - * added FormProcessorInterface and FormInterface::process() + * added RequestHandlerInterface and FormInterface::handleRequest() * deprecated passing a Request instance to FormInterface::bind() * added options "method" and "action" to FormType * deprecated option "virtual" in favor "inherit_data" diff --git a/Extension/HttpFoundation/RequestFormProcessor.php b/Extension/HttpFoundation/HttpFoundationRequestHandler.php similarity index 89% rename from Extension/HttpFoundation/RequestFormProcessor.php rename to Extension/HttpFoundation/HttpFoundationRequestHandler.php index c2f0b4de2c..e33cdf6b41 100644 --- a/Extension/HttpFoundation/RequestFormProcessor.php +++ b/Extension/HttpFoundation/HttpFoundationRequestHandler.php @@ -14,21 +14,21 @@ use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormProcessorInterface; +use Symfony\Component\Form\RequestHandlerInterface; use Symfony\Component\HttpFoundation\Request; /** - * A form processor using the {@link Request} class of the HttpFoundation + * A request processor using the {@link Request} class of the HttpFoundation * component. * * @author Bernhard Schussek */ -class RequestFormProcessor implements FormProcessorInterface +class HttpFoundationRequestHandler implements RequestHandlerInterface { /** * {@inheritdoc} */ - public function processForm(FormInterface $form, $request = null) + public function handleRequest(FormInterface $form, $request = null) { if (!$request instanceof Request) { throw new UnexpectedTypeException($request, 'Symfony\Component\HttpFoundation\Request'); diff --git a/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php b/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php index 28e6e7c816..9b09b05c39 100644 --- a/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php +++ b/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php @@ -13,7 +13,7 @@ use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\Extension\HttpFoundation\EventListener\BindRequestListener; -use Symfony\Component\Form\Extension\HttpFoundation\RequestFormProcessor; +use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; use Symfony\Component\Form\FormBuilderInterface; /** @@ -27,14 +27,14 @@ class FormTypeHttpFoundationExtension extends AbstractTypeExtension private $listener; /** - * @var RequestFormProcessor + * @var HttpFoundationRequestHandler */ - private $processor; + private $requestHandler; public function __construct() { $this->listener = new BindRequestListener(); - $this->processor = new RequestFormProcessor(); + $this->requestHandler = new HttpFoundationRequestHandler(); } /** @@ -43,7 +43,7 @@ public function __construct() public function buildForm(FormBuilderInterface $builder, array $options) { $builder->addEventSubscriber($this->listener); - $builder->setFormProcessor($this->processor); + $builder->setRequestHandler($this->requestHandler); } /** diff --git a/Form.php b/Form.php index 4600fd043a..a7a057dd09 100644 --- a/Form.php +++ b/Form.php @@ -454,9 +454,9 @@ public function getExtraData() /** * {@inheritdoc} */ - public function process($request = null) + public function handleRequest($request = null) { - $this->config->getFormProcessor()->processForm($this, $request); + $this->config->getRequestHandler()->handleRequest($this, $request); return $this; } diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index b839fa1065..b6e57f6201 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -28,11 +28,11 @@ class FormConfigBuilder implements FormConfigBuilderInterface { /** - * Caches a globally unique {@link NativeFormProcessor} instance. + * Caches a globally unique {@link NativeRequestHandler} instance. * - * @var NativeFormProcessor + * @var NativeRequestHandler */ - private static $nativeFormProcessor; + private static $nativeRequestProcessor; /** * The accepted request methods. @@ -168,9 +168,9 @@ class FormConfigBuilder implements FormConfigBuilderInterface private $method = 'POST'; /** - * @var FormProcessorInterface + * @var RequestHandlerInterface */ - private $formProcessor; + private $requestHandler; /** * @var array @@ -509,16 +509,16 @@ public function getMethod() /** * {@inheritdoc} */ - public function getFormProcessor() + public function getRequestHandler() { - if (null === $this->formProcessor) { - if (null === self::$nativeFormProcessor) { - self::$nativeFormProcessor = new NativeFormProcessor(); + if (null === $this->requestHandler) { + if (null === self::$nativeRequestProcessor) { + self::$nativeRequestProcessor = new NativeRequestHandler(); } - $this->formProcessor = self::$nativeFormProcessor; + $this->requestHandler = self::$nativeRequestProcessor; } - return $this->formProcessor; + return $this->requestHandler; } /** @@ -832,13 +832,13 @@ public function setMethod($method) /** * {@inheritdoc} */ - public function setFormProcessor(FormProcessorInterface $formProcessor) + public function setRequestHandler(RequestHandlerInterface $requestHandler) { if ($this->locked) { throw new BadMethodCallException('The config builder cannot be modified anymore.'); } - $this->formProcessor = $formProcessor; + $this->requestHandler = $requestHandler; return $this; } diff --git a/FormConfigBuilderInterface.php b/FormConfigBuilderInterface.php index a35be27db2..45fa4275e4 100644 --- a/FormConfigBuilderInterface.php +++ b/FormConfigBuilderInterface.php @@ -256,11 +256,11 @@ public function setAction($action); public function setMethod($method); /** - * @param FormProcessorInterface $formProcessor + * @param RequestHandlerInterface $requestHandler * * @return self The configuration object. */ - public function setFormProcessor(FormProcessorInterface $formProcessor); + public function setRequestHandler(RequestHandlerInterface $requestHandler); /** * Builds and returns the form configuration. diff --git a/FormConfigInterface.php b/FormConfigInterface.php index 3aa00d4dbd..a3e8026314 100644 --- a/FormConfigInterface.php +++ b/FormConfigInterface.php @@ -201,9 +201,9 @@ public function getAction(); public function getMethod(); /** - * @return FormProcessorInterface The form processor. + * @return RequestHandlerInterface The form processor. */ - public function getFormProcessor(); + public function getRequestHandler(); /** * Returns all options passed during the construction of the form. diff --git a/FormInterface.php b/FormInterface.php index 00512f0833..e1a64e626a 100644 --- a/FormInterface.php +++ b/FormInterface.php @@ -229,7 +229,7 @@ public function isSynchronized(); /** * Processes the given request and binds the form if it was submitted. * - * Internally, the request is forwarded to a {@link FormProcessorInterface} + * Internally, the request is forwarded to a {@link RequestHandlerInterface} * instance. This instance determines the allowed value of the * $request parameter. * @@ -237,7 +237,7 @@ public function isSynchronized(); * * @return FormInterface The form instance. */ - public function process($request = null); + public function handleRequest($request = null); /** * Binds data to the form, transforms and validates it. diff --git a/NativeFormProcessor.php b/NativeRequestHandler.php similarity index 95% rename from NativeFormProcessor.php rename to NativeRequestHandler.php index 7494c84eaf..ac343c4898 100644 --- a/NativeFormProcessor.php +++ b/NativeRequestHandler.php @@ -13,14 +13,14 @@ use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\FormProcessorInterface; +use Symfony\Component\Form\RequestHandlerInterface; /** - * A form processor using PHP's super globals $_GET, $_POST and $_SERVER. + * A request handler using PHP's super globals $_GET, $_POST and $_SERVER. * * @author Bernhard Schussek */ -class NativeFormProcessor implements FormProcessorInterface +class NativeRequestHandler implements RequestHandlerInterface { /** * The allowed keys of the $_FILES array. @@ -38,7 +38,7 @@ class NativeFormProcessor implements FormProcessorInterface /** * {@inheritdoc} */ - public function processForm(FormInterface $form, $request = null) + public function handleRequest(FormInterface $form, $request = null) { if (null !== $request) { throw new UnexpectedTypeException($request, 'null'); diff --git a/FormProcessorInterface.php b/RequestHandlerInterface.php similarity index 84% rename from FormProcessorInterface.php rename to RequestHandlerInterface.php index 3634524b8d..d62b950a9c 100644 --- a/FormProcessorInterface.php +++ b/RequestHandlerInterface.php @@ -16,7 +16,7 @@ * * @author Bernhard Schussek */ -interface FormProcessorInterface +interface RequestHandlerInterface { /** * Binds a form from a request if it was submitted. @@ -24,5 +24,5 @@ interface FormProcessorInterface * @param FormInterface $form The form to bind. * @param mixed $request The current request. */ - public function processForm(FormInterface $form, $request = null); + public function handleRequest(FormInterface $form, $request = null); } diff --git a/Tests/AbstractFormProcessorTest.php b/Tests/AbstractRequestHandlerTest.php similarity index 87% rename from Tests/AbstractFormProcessorTest.php rename to Tests/AbstractRequestHandlerTest.php index 40270b2c0e..d9f693622c 100644 --- a/Tests/AbstractFormProcessorTest.php +++ b/Tests/AbstractRequestHandlerTest.php @@ -14,18 +14,18 @@ /** * @author Bernhard Schussek */ -abstract class AbstractFormProcessorTest extends \PHPUnit_Framework_TestCase +abstract class AbstractRequestHandlerTest extends \PHPUnit_Framework_TestCase { /** - * @var \Symfony\Component\Form\FormProcessorInterface + * @var \Symfony\Component\Form\RequestHandlerInterface */ - protected $processor; + protected $requestHandler; protected $request; protected function setUp() { - $this->processor = $this->getFormProcessor(); + $this->requestHandler = $this->getRequestHandler(); $this->request = null; } @@ -61,7 +61,7 @@ public function testBindIfNameInRequest($method) ->method('bind') ->with('DATA'); - $this->processor->processForm($form, $this->request); + $this->requestHandler->handleRequest($form, $this->request); } /** @@ -80,7 +80,7 @@ public function testDoNotBindIfWrongRequestMethod($method) $form->expects($this->never()) ->method('bind'); - $this->processor->processForm($form, $this->request); + $this->requestHandler->handleRequest($form, $this->request); } /** @@ -98,7 +98,7 @@ public function testBindSimpleFormWithNullIfNameNotInRequestAndNotGetRequest($me ->method('bind') ->with($this->identicalTo(null)); - $this->processor->processForm($form, $this->request); + $this->requestHandler->handleRequest($form, $this->request); } /** @@ -116,7 +116,7 @@ public function testBindCompoundFormWithArrayIfNameNotInRequestAndNotGetRequest( ->method('bind') ->with($this->identicalTo(array())); - $this->processor->processForm($form, $this->request); + $this->requestHandler->handleRequest($form, $this->request); } public function testDoNotBindIfNameNotInRequestAndGetRequest() @@ -130,7 +130,7 @@ public function testDoNotBindIfNameNotInRequestAndGetRequest() $form->expects($this->never()) ->method('bind'); - $this->processor->processForm($form, $this->request); + $this->requestHandler->handleRequest($form, $this->request); } /** @@ -155,7 +155,7 @@ public function testBindFormWithEmptyNameIfAtLeastOneFieldInRequest($method) ->method('bind') ->with($requestData); - $this->processor->processForm($form, $this->request); + $this->requestHandler->handleRequest($form, $this->request); } /** @@ -178,7 +178,7 @@ public function testDoNotBindFormWithEmptyNameIfNoFieldInRequest($method) $form->expects($this->never()) ->method('bind'); - $this->processor->processForm($form, $this->request); + $this->requestHandler->handleRequest($form, $this->request); } /** @@ -206,7 +206,7 @@ public function testMergeParamsAndFiles($method) 'field2' => $file, )); - $this->processor->processForm($form, $this->request); + $this->requestHandler->handleRequest($form, $this->request); } /** @@ -227,7 +227,7 @@ public function testParamTakesPrecedenceOverFile($method) ->method('bind') ->with('DATA'); - $this->processor->processForm($form, $this->request); + $this->requestHandler->handleRequest($form, $this->request); } /** @@ -248,12 +248,12 @@ public function testBindFileIfNoParam($method) ->method('bind') ->with($file); - $this->processor->processForm($form, $this->request); + $this->requestHandler->handleRequest($form, $this->request); } abstract protected function setRequestData($method, $data, $files = array()); - abstract protected function getFormProcessor(); + abstract protected function getRequestHandler(); abstract protected function getMockFile(); diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index fc3b5a6d6d..95fdd4632e 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form\Tests; -use Symfony\Component\Form\Extension\HttpFoundation\RequestFormProcessor; +use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; use Symfony\Component\Form\FormError; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\File\UploadedFile; @@ -481,12 +481,12 @@ public function testBindPostOrPutRequest($method) ->setMethod($method) ->setCompound(true) ->setDataMapper($this->getDataMapper()) - ->setFormProcessor(new RequestFormProcessor()) + ->setRequestHandler(new HttpFoundationRequestHandler()) ->getForm(); $form->add($this->getBuilder('name')->getForm()); $form->add($this->getBuilder('image')->getForm()); - $form->process($request); + $form->handleRequest($request); $file = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK); @@ -531,12 +531,12 @@ public function testBindPostOrPutRequestWithEmptyRootFormName($method) ->setMethod($method) ->setCompound(true) ->setDataMapper($this->getDataMapper()) - ->setFormProcessor(new RequestFormProcessor()) + ->setRequestHandler(new HttpFoundationRequestHandler()) ->getForm(); $form->add($this->getBuilder('name')->getForm()); $form->add($this->getBuilder('image')->getForm()); - $form->process($request); + $form->handleRequest($request); $file = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK); @@ -575,10 +575,10 @@ public function testBindPostOrPutRequestWithSingleChildForm($method) $form = $this->getBuilder('image') ->setMethod($method) - ->setFormProcessor(new RequestFormProcessor()) + ->setRequestHandler(new HttpFoundationRequestHandler()) ->getForm(); - $form->process($request); + $form->handleRequest($request); $file = new UploadedFile($path, 'upload.png', 'image/png', 123, UPLOAD_ERR_OK); @@ -609,10 +609,10 @@ public function testBindPostOrPutRequestWithSingleChildFormUploadedFile($method) $form = $this->getBuilder('name') ->setMethod($method) - ->setFormProcessor(new RequestFormProcessor()) + ->setRequestHandler(new HttpFoundationRequestHandler()) ->getForm(); - $form->process($request); + $form->handleRequest($request); $this->assertEquals('Bernhard', $form->getData()); @@ -640,12 +640,12 @@ public function testBindGetRequest() ->setMethod('GET') ->setCompound(true) ->setDataMapper($this->getDataMapper()) - ->setFormProcessor(new RequestFormProcessor()) + ->setRequestHandler(new HttpFoundationRequestHandler()) ->getForm(); $form->add($this->getBuilder('firstName')->getForm()); $form->add($this->getBuilder('lastName')->getForm()); - $form->process($request); + $form->handleRequest($request); $this->assertEquals('Bernhard', $form['firstName']->getData()); $this->assertEquals('Schussek', $form['lastName']->getData()); @@ -671,12 +671,12 @@ public function testBindGetRequestWithEmptyRootFormName() ->setMethod('GET') ->setCompound(true) ->setDataMapper($this->getDataMapper()) - ->setFormProcessor(new RequestFormProcessor()) + ->setRequestHandler(new HttpFoundationRequestHandler()) ->getForm(); $form->add($this->getBuilder('firstName')->getForm()); $form->add($this->getBuilder('lastName')->getForm()); - $form->process($request); + $form->handleRequest($request); $this->assertEquals('Bernhard', $form['firstName']->getData()); $this->assertEquals('Schussek', $form['lastName']->getData()); diff --git a/Tests/Extension/HttpFoundation/RequestFormProcessorTest.php b/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php similarity index 70% rename from Tests/Extension/HttpFoundation/RequestFormProcessorTest.php rename to Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php index 95e522c474..2d5cf7764b 100644 --- a/Tests/Extension/HttpFoundation/RequestFormProcessorTest.php +++ b/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php @@ -11,28 +11,28 @@ namespace Symfony\Component\Form\Tests\Extension\HttpFoundation; -use Symfony\Component\Form\Extension\HttpFoundation\RequestFormProcessor; -use Symfony\Component\Form\Tests\AbstractFormProcessorTest; +use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; +use Symfony\Component\Form\Tests\AbstractRequestHandlerTest; use Symfony\Component\HttpFoundation\Request; /** * @author Bernhard Schussek */ -class RequestFormProcessorTest extends AbstractFormProcessorTest +class HttpFoundationRequestHandlerTest extends AbstractRequestHandlerTest { /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testRequestShouldNotBeNull() { - $this->processor->processForm($this->getMockForm('name', 'GET')); + $this->requestHandler->handleRequest($this->getMockForm('name', 'GET')); } /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testRequestShouldBeInstanceOfRequest() { - $this->processor->processForm($this->getMockForm('name', 'GET'), new \stdClass()); + $this->requestHandler->handleRequest($this->getMockForm('name', 'GET'), new \stdClass()); } protected function setRequestData($method, $data, $files = array()) @@ -40,9 +40,9 @@ protected function setRequestData($method, $data, $files = array()) $this->request = Request::create('http://localhost', $method, $data, array(), $files); } - protected function getFormProcessor() + protected function getRequestHandler() { - return new RequestFormProcessor(); + return new HttpFoundationRequestHandler(); } protected function getMockFile() diff --git a/Tests/FormConfigTest.php b/Tests/FormConfigTest.php index 90c882f1f1..961dfd3367 100644 --- a/Tests/FormConfigTest.php +++ b/Tests/FormConfigTest.php @@ -91,19 +91,19 @@ public function testNameAcceptsOnlyNamesValidAsIdsInHtml4($name, $accepted) } } - public function testGetFormProcessorCreatesNativeFormProcessorIfNotSet() + public function testGetRequestHandlerCreatesNativeRequestHandlerIfNotSet() { $config = $this->getConfigBuilder()->getFormConfig(); - $this->assertInstanceOf('Symfony\Component\Form\NativeFormProcessor', $config->getFormProcessor()); + $this->assertInstanceOf('Symfony\Component\Form\NativeRequestHandler', $config->getRequestHandler()); } - public function testGetFormProcessorReusesNativeFormProcessorInstance() + public function testGetRequestHandlerReusesNativeRequestHandlerInstance() { $config1 = $this->getConfigBuilder()->getFormConfig(); $config2 = $this->getConfigBuilder()->getFormConfig(); - $this->assertSame($config1->getFormProcessor(), $config2->getFormProcessor()); + $this->assertSame($config1->getRequestHandler(), $config2->getRequestHandler()); } public function testSetMethodAllowsGet() diff --git a/Tests/NativeFormProcessorTest.php b/Tests/NativeRequestHandlerTest.php similarity index 89% rename from Tests/NativeFormProcessorTest.php rename to Tests/NativeRequestHandlerTest.php index 4e90e5276c..1a7bb0f9e4 100644 --- a/Tests/NativeFormProcessorTest.php +++ b/Tests/NativeRequestHandlerTest.php @@ -11,12 +11,12 @@ namespace Symfony\Component\Form\Tests; -use Symfony\Component\Form\NativeFormProcessor; +use Symfony\Component\Form\NativeRequestHandler; /** * @author Bernhard Schussek */ -class NativeFormProcessorTest extends AbstractFormProcessorTest +class NativeRequestHandlerTest extends AbstractRequestHandlerTest { private static $serverBackup; @@ -53,7 +53,7 @@ protected function tearDown() */ public function testRequestShouldBeNull() { - $this->processor->processForm($this->getMockForm('name', 'GET'), 'request'); + $this->requestHandler->handleRequest($this->getMockForm('name', 'GET'), 'request'); } public function testMethodOverrideHeaderTakesPrecedenceIfPost() @@ -70,7 +70,7 @@ public function testMethodOverrideHeaderTakesPrecedenceIfPost() ->method('bind') ->with('DATA'); - $this->processor->processForm($form, $this->request); + $this->requestHandler->handleRequest($form, $this->request); } public function testConvertEmptyUploadedFilesToNull() @@ -89,7 +89,7 @@ public function testConvertEmptyUploadedFilesToNull() ->method('bind') ->with($this->identicalTo(null)); - $this->processor->processForm($form, $this->request); + $this->requestHandler->handleRequest($form, $this->request); } public function testFixBuggyFilesArray() @@ -126,7 +126,7 @@ public function testFixBuggyFilesArray() ), )); - $this->processor->processForm($form, $this->request); + $this->requestHandler->handleRequest($form, $this->request); } public function testFixBuggyNestedFilesArray() @@ -165,7 +165,7 @@ public function testFixBuggyNestedFilesArray() ), )); - $this->processor->processForm($form, $this->request); + $this->requestHandler->handleRequest($form, $this->request); } public function testMethodOverrideHeaderIgnoredIfNotPost() @@ -181,7 +181,7 @@ public function testMethodOverrideHeaderIgnoredIfNotPost() $form->expects($this->never()) ->method('bind'); - $this->processor->processForm($form, $this->request); + $this->requestHandler->handleRequest($form, $this->request); } protected function setRequestData($method, $data, $files = array()) @@ -201,9 +201,9 @@ protected function setRequestData($method, $data, $files = array()) ); } - protected function getFormProcessor() + protected function getRequestHandler() { - return new NativeFormProcessor(); + return new NativeRequestHandler(); } protected function getMockFile() diff --git a/Tests/SimpleFormTest.php b/Tests/SimpleFormTest.php index 01c0a947d0..09dea71d25 100644 --- a/Tests/SimpleFormTest.php +++ b/Tests/SimpleFormTest.php @@ -878,19 +878,19 @@ public function testBindingWrongDataIsIgnored() $parent->bind('not-an-array'); } - public function testProcessForwardsToFormProcessor() + public function testHandleRequestForwardsToRequestHandler() { - $processor = $this->getMock('Symfony\Component\Form\FormProcessorInterface'); + $processor = $this->getMock('Symfony\Component\Form\RequestHandlerInterface'); $form = $this->getBuilder() - ->setFormProcessor($processor) + ->setRequestHandler($processor) ->getForm(); $processor->expects($this->once()) - ->method('processForm') + ->method('handleRequest') ->with($this->identicalTo($form), 'REQUEST'); - $this->assertSame($form, $form->process('REQUEST')); + $this->assertSame($form, $form->handleRequest('REQUEST')); } public function testFormInheritsParentData() From 47d44b75fe6cd170bd0e893199c3e7a67453bb4e Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Sat, 20 Apr 2013 17:32:55 +0200 Subject: [PATCH 111/447] [Form] Deprecated bind() and isBound() in favor of submit() and isSubmitted() --- Button.php | 20 +- CHANGELOG.md | 6 + DataTransformerInterface.php | 8 +- Exception/AlreadyBoundException.php | 6 + Exception/AlreadySubmittedException.php | 22 ++ .../FixCheckboxInputListener.php | 15 +- .../EventListener/FixRadioInputListener.php | 15 +- .../EventListener/FixUrlProtocolListener.php | 15 +- .../EventListener/MergeCollectionListener.php | 16 +- .../Core/EventListener/ResizeFormListener.php | 31 ++- Extension/Core/EventListener/TrimListener.php | 15 +- Extension/Core/Type/FormType.php | 2 +- Extension/Core/Type/PasswordType.php | 2 +- .../CsrfProvider/CsrfProviderInterface.php | 2 +- .../EventListener/CsrfValidationListener.php | 15 +- .../EventListener/BindRequestListener.php | 2 +- .../HttpFoundationRequestHandler.php | 6 +- .../EventListener/ValidationListener.php | 2 +- Form.php | 100 +++++---- FormConfigBuilderInterface.php | 6 +- FormConfigInterface.php | 2 +- FormEvents.php | 24 +- FormInterface.php | 30 +-- NativeRequestHandler.php | 6 +- README.md | 2 +- RequestHandlerInterface.php | 6 +- SubmitButton.php | 8 +- Tests/AbstractFormTest.php | 2 +- Tests/AbstractLayoutTest.php | 4 +- Tests/AbstractRequestHandlerTest.php | 36 +-- Tests/CompoundFormTest.php | 54 ++--- .../FixRadioInputListenerTest.php | 6 +- .../FixUrlProtocolListenerTest.php | 6 +- .../MergeCollectionListenerTest.php | 18 +- .../EventListener/ResizeFormListenerTest.php | 44 ++-- .../Core/EventListener/TrimListenerTest.php | 6 +- .../Extension/Core/Type/CheckboxTypeTest.php | 20 +- Tests/Extension/Core/Type/ChoiceTypeTest.php | 60 ++--- .../Core/Type/CollectionTypeTest.php | 16 +- .../Extension/Core/Type/DateTimeTypeTest.php | 20 +- Tests/Extension/Core/Type/DateTypeTest.php | 32 +-- Tests/Extension/Core/Type/FileTypeTest.php | 10 +- Tests/Extension/Core/Type/FormTypeTest.php | 58 ++--- Tests/Extension/Core/Type/IntegerTypeTest.php | 2 +- .../Extension/Core/Type/PasswordTypeTest.php | 12 +- .../Extension/Core/Type/RepeatedTypeTest.php | 4 +- Tests/Extension/Core/Type/SubmitTypeTest.php | 12 +- Tests/Extension/Core/Type/TimeTypeTest.php | 36 +-- Tests/Extension/Core/Type/UrlTypeTest.php | 8 +- .../CsrfValidationListenerTest.php | 2 +- .../Csrf/Type/FormTypeCsrfExtensionTest.php | 10 +- .../EventListener/BindRequestListenerTest.php | 16 +- .../Constraints/FormValidatorTest.php | 14 +- .../Type/FormTypeValidatorExtensionTest.php | 4 +- .../ViolationMapper/ViolationMapperTest.php | 8 +- Tests/Fixtures/FixedFilterListener.php | 20 +- Tests/NativeRequestHandlerTest.php | 10 +- Tests/SimpleFormTest.php | 212 +++++++++--------- 58 files changed, 655 insertions(+), 491 deletions(-) create mode 100644 Exception/AlreadySubmittedException.php diff --git a/Button.php b/Button.php index 55606d24da..6961dd8d78 100644 --- a/Button.php +++ b/Button.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Form; -use Symfony\Component\Form\Exception\AlreadyBoundException; +use Symfony\Component\Form\Exception\AlreadySubmittedException; use Symfony\Component\Form\Exception\BadMethodCallException; /** @@ -34,7 +34,7 @@ class Button implements \IteratorAggregate, FormInterface /** * @var Boolean */ - private $bound = false; + private $submitted = false; /** * Creates a new button from a form configuration. @@ -258,9 +258,9 @@ public function getConfig() * * @return Boolean true if the button was submitted. */ - public function isBound() + public function isSubmitted() { - return $this->bound; + return $this->submitted; } /** @@ -356,21 +356,21 @@ public function handleRequest($request = null) } /** - * Binds data to the button. + * Submits data to the button. * * @param null|string $submittedData The data * * @return Button The button instance * - * @throws Exception\AlreadyBoundException If the form has already been bound. + * @throws Exception\AlreadySubmittedException If the button has already been submitted. */ - public function bind($submittedData) + public function submit($submittedData) { - if ($this->bound) { - throw new AlreadyBoundException('A form can only be bound once'); + if ($this->submitted) { + throw new AlreadySubmittedException('A form can only be submitted once'); } - $this->bound = true; + $this->submitted = true; return $this; } diff --git a/CHANGELOG.md b/CHANGELOG.md index 0263c09b79..c0fc6d06de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,12 @@ CHANGELOG * added component-level exceptions for various SPL exceptions changed all uses of the deprecated Exception class to use more specialized exceptions instead removed NotInitializedException, NotValidException, TypeDefinitionException, TypeLoaderException, CreationException + * added events PRE_SUBMIT, SUBMIT and POST_SUBMIT + * deprecated events PRE_BIND, BIND and POST_BIND + * [BC BREAK] renamed bind() and isBound() in FormInterface to submit() and isSubmitted() + * added methods submit() and isSubmitted() to Form + * deprecated bind() and isBound() in Form + * deprecated AlreadyBoundException in favor of AlreadySubmittedException 2.2.0 ----- diff --git a/DataTransformerInterface.php b/DataTransformerInterface.php index 07183d54b3..3994b20d56 100644 --- a/DataTransformerInterface.php +++ b/DataTransformerInterface.php @@ -24,9 +24,9 @@ interface DataTransformerInterface * This method is called on two occasions inside a form field: * * 1. When the form field is initialized with the data attached from the datasource (object or array). - * 2. When data from a request is bound using {@link Form::bind()} to transform the new input data - * back into the renderable format. For example if you have a date field and bind '2009-10-10' onto - * it you might accept this value because its easily parsed, but the transformer still writes back + * 2. When data from a request is submitted using {@link Form::submit()} to transform the new input data + * back into the renderable format. For example if you have a date field and submit '2009-10-10' + * you might accept this value because its easily parsed, but the transformer still writes back * "2009/10/10" onto the form field (for further displaying or other purposes). * * This method must be able to deal with empty values. Usually this will @@ -52,7 +52,7 @@ public function transform($value); * Transforms a value from the transformed representation to its original * representation. * - * This method is called when {@link Form::bind()} is called to transform the requests tainted data + * This method is called when {@link Form::submit()} is called to transform the requests tainted data * into an acceptable format for your data processing/model layer. * * This method must be able to deal with empty values. Usually this will diff --git a/Exception/AlreadyBoundException.php b/Exception/AlreadyBoundException.php index 5c1b7c52bc..7ef0ca02e8 100644 --- a/Exception/AlreadyBoundException.php +++ b/Exception/AlreadyBoundException.php @@ -11,6 +11,12 @@ namespace Symfony\Component\Form\Exception; +/** + * Alias of {@link AlreadySubmittedException}. + * + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use + * {@link AlreadySubmittedException} instead. + */ class AlreadyBoundException extends LogicException { } diff --git a/Exception/AlreadySubmittedException.php b/Exception/AlreadySubmittedException.php new file mode 100644 index 0000000000..7be212494a --- /dev/null +++ b/Exception/AlreadySubmittedException.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Exception; + +/** + * Thrown when an operation is called that is not acceptable after submitting + * a form. + * + * @author Bernhard Schussek + */ +class AlreadySubmittedException extends AlreadyBoundException +{ +} diff --git a/Extension/Core/EventListener/FixCheckboxInputListener.php b/Extension/Core/EventListener/FixCheckboxInputListener.php index 083e23e946..1f62e060ff 100644 --- a/Extension/Core/EventListener/FixCheckboxInputListener.php +++ b/Extension/Core/EventListener/FixCheckboxInputListener.php @@ -36,7 +36,7 @@ public function __construct(ChoiceListInterface $choiceList) $this->choiceList = $choiceList; } - public function preBind(FormEvent $event) + public function preSubmit(FormEvent $event) { $values = (array) $event->getData(); $indices = $this->choiceList->getIndicesForValues($values); @@ -44,8 +44,19 @@ public function preBind(FormEvent $event) $event->setData(count($indices) > 0 ? array_combine($indices, $values) : array()); } + /** + * Alias of {@link preSubmit()}. + * + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use + * {@link preSubmit()} instead. + */ + public function preBind(FormEvent $event) + { + $this->preSubmit($event); + } + public static function getSubscribedEvents() { - return array(FormEvents::PRE_BIND => 'preBind'); + return array(FormEvents::PRE_SUBMIT => 'preSubmit'); } } diff --git a/Extension/Core/EventListener/FixRadioInputListener.php b/Extension/Core/EventListener/FixRadioInputListener.php index c60bd26b53..b045ca8fd1 100644 --- a/Extension/Core/EventListener/FixRadioInputListener.php +++ b/Extension/Core/EventListener/FixRadioInputListener.php @@ -36,7 +36,7 @@ public function __construct(ChoiceListInterface $choiceList) $this->choiceList = $choiceList; } - public function preBind(FormEvent $event) + public function preSubmit(FormEvent $event) { $value = $event->getData(); $index = current($this->choiceList->getIndicesForValues(array($value))); @@ -44,8 +44,19 @@ public function preBind(FormEvent $event) $event->setData(false !== $index ? array($index => $value) : array()); } + /** + * Alias of {@link preSubmit()}. + * + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use + * {@link preSubmit()} instead. + */ + public function preBind(FormEvent $event) + { + $this->preSubmit($event); + } + public static function getSubscribedEvents() { - return array(FormEvents::PRE_BIND => 'preBind'); + return array(FormEvents::PRE_SUBMIT => 'preSubmit'); } } diff --git a/Extension/Core/EventListener/FixUrlProtocolListener.php b/Extension/Core/EventListener/FixUrlProtocolListener.php index 1079903b59..e25dacf237 100644 --- a/Extension/Core/EventListener/FixUrlProtocolListener.php +++ b/Extension/Core/EventListener/FixUrlProtocolListener.php @@ -29,7 +29,7 @@ public function __construct($defaultProtocol = 'http') $this->defaultProtocol = $defaultProtocol; } - public function onBind(FormEvent $event) + public function onSubmit(FormEvent $event) { $data = $event->getData(); @@ -38,8 +38,19 @@ public function onBind(FormEvent $event) } } + /** + * Alias of {@link onSubmit()}. + * + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use + * {@link onSubmit()} instead. + */ + public function onBind(FormEvent $event) + { + $this->onSubmit($event); + } + public static function getSubscribedEvents() { - return array(FormEvents::BIND => 'onBind'); + return array(FormEvents::SUBMIT => 'onSubmit'); } } diff --git a/Extension/Core/EventListener/MergeCollectionListener.php b/Extension/Core/EventListener/MergeCollectionListener.php index ec887015b1..b6f8fb70cb 100644 --- a/Extension/Core/EventListener/MergeCollectionListener.php +++ b/Extension/Core/EventListener/MergeCollectionListener.php @@ -50,11 +50,11 @@ public function __construct($allowAdd = false, $allowDelete = false) public static function getSubscribedEvents() { return array( - FormEvents::BIND => 'onBind', + FormEvents::SUBMIT => 'onSubmit', ); } - public function onBind(FormEvent $event) + public function onSubmit(FormEvent $event) { $dataToMergeInto = $event->getForm()->getNormData(); $data = $event->getData(); @@ -123,4 +123,16 @@ public function onBind(FormEvent $event) $event->setData($dataToMergeInto); } + + + /** + * Alias of {@link onSubmit()}. + * + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use + * {@link onSubmit()} instead. + */ + public function onBind(FormEvent $event) + { + $this->onSubmit($event); + } } diff --git a/Extension/Core/EventListener/ResizeFormListener.php b/Extension/Core/EventListener/ResizeFormListener.php index 12d1cba505..fabeb3664a 100644 --- a/Extension/Core/EventListener/ResizeFormListener.php +++ b/Extension/Core/EventListener/ResizeFormListener.php @@ -57,9 +57,9 @@ public static function getSubscribedEvents() { return array( FormEvents::PRE_SET_DATA => 'preSetData', - FormEvents::PRE_BIND => 'preBind', + FormEvents::PRE_SUBMIT => 'preSubmit', // (MergeCollectionListener, MergeDoctrineCollectionListener) - FormEvents::BIND => array('onBind', 50), + FormEvents::SUBMIT => array('onSubmit', 50), ); } @@ -89,7 +89,7 @@ public function preSetData(FormEvent $event) } } - public function preBind(FormEvent $event) + public function preSubmit(FormEvent $event) { $form = $event->getForm(); $data = $event->getData(); @@ -123,7 +123,7 @@ public function preBind(FormEvent $event) } } - public function onBind(FormEvent $event) + public function onSubmit(FormEvent $event) { $form = $event->getForm(); $data = $event->getData(); @@ -148,4 +148,27 @@ public function onBind(FormEvent $event) $event->setData($data); } + + + /** + * Alias of {@link preSubmit()}. + * + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use + * {@link preSubmit()} instead. + */ + public function preBind(FormEvent $event) + { + $this->preSubmit($event); + } + + /** + * Alias of {@link onSubmit()}. + * + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use + * {@link onSubmit()} instead. + */ + public function onBind(FormEvent $event) + { + $this->onSubmit($event); + } } diff --git a/Extension/Core/EventListener/TrimListener.php b/Extension/Core/EventListener/TrimListener.php index 46167726f5..cbe6e0ab79 100644 --- a/Extension/Core/EventListener/TrimListener.php +++ b/Extension/Core/EventListener/TrimListener.php @@ -22,7 +22,7 @@ */ class TrimListener implements EventSubscriberInterface { - public function preBind(FormEvent $event) + public function preSubmit(FormEvent $event) { $data = $event->getData(); @@ -37,8 +37,19 @@ public function preBind(FormEvent $event) } } + /** + * Alias of {@link preSubmit()}. + * + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use + * {@link preSubmit()} instead. + */ + public function preBind(FormEvent $event) + { + $this->preSubmit($event); + } + public static function getSubscribedEvents() { - return array(FormEvents::PRE_BIND => 'preBind'); + return array(FormEvents::PRE_SUBMIT => 'preSubmit'); } } diff --git a/Extension/Core/Type/FormType.php b/Extension/Core/Type/FormType.php index 39e16799c4..190bb52cec 100644 --- a/Extension/Core/Type/FormType.php +++ b/Extension/Core/Type/FormType.php @@ -86,7 +86,7 @@ public function buildView(FormView $view, FormInterface $form, array $options) $view->vars = array_replace($view->vars, array( 'read_only' => $readOnly, 'errors' => $form->getErrors(), - 'valid' => $form->isBound() ? $form->isValid() : true, + 'valid' => $form->isSubmitted() ? $form->isValid() : true, 'value' => $form->getViewData(), 'data' => $form->getNormData(), 'required' => $form->isRequired(), diff --git a/Extension/Core/Type/PasswordType.php b/Extension/Core/Type/PasswordType.php index d76281e567..5a5b1635d1 100644 --- a/Extension/Core/Type/PasswordType.php +++ b/Extension/Core/Type/PasswordType.php @@ -23,7 +23,7 @@ class PasswordType extends AbstractType */ public function buildView(FormView $view, FormInterface $form, array $options) { - if ($options['always_empty'] || !$form->isBound()) { + if ($options['always_empty'] || !$form->isSubmitted()) { $view->vars['value'] = ''; } } diff --git a/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php b/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php index 322a4f8326..7143b130c8 100644 --- a/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php +++ b/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php @@ -22,7 +22,7 @@ * * If you want to secure a form submission against CSRF attacks, you could * supply an "intention" string. This way you make sure that the form can only - * be bound to pages that are designed to handle the form, that is, that use + * be submitted to pages that are designed to handle the form, that is, that use * the same intention string to validate the CSRF token with isCsrfTokenValid(). * * @author Bernhard Schussek diff --git a/Extension/Csrf/EventListener/CsrfValidationListener.php b/Extension/Csrf/EventListener/CsrfValidationListener.php index 976312f78f..9d062f9546 100644 --- a/Extension/Csrf/EventListener/CsrfValidationListener.php +++ b/Extension/Csrf/EventListener/CsrfValidationListener.php @@ -47,7 +47,7 @@ class CsrfValidationListener implements EventSubscriberInterface public static function getSubscribedEvents() { return array( - FormEvents::PRE_BIND => 'preBind', + FormEvents::PRE_SUBMIT => 'preSubmit', ); } @@ -58,7 +58,7 @@ public function __construct($fieldName, CsrfProviderInterface $csrfProvider, $in $this->intention = $intention; } - public function preBind(FormEvent $event) + public function preSubmit(FormEvent $event) { $form = $event->getForm(); $data = $event->getData(); @@ -75,4 +75,15 @@ public function preBind(FormEvent $event) $event->setData($data); } + + /** + * Alias of {@link preSubmit()}. + * + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use + * {@link preSubmit()} instead. + */ + public function preBind(FormEvent $event) + { + $this->preSubmit($event); + } } diff --git a/Extension/HttpFoundation/EventListener/BindRequestListener.php b/Extension/HttpFoundation/EventListener/BindRequestListener.php index f71113f01f..6205b98d70 100644 --- a/Extension/HttpFoundation/EventListener/BindRequestListener.php +++ b/Extension/HttpFoundation/EventListener/BindRequestListener.php @@ -44,7 +44,7 @@ public function preBind(FormEvent $event) } // Uncomment this as soon as the deprecation note should be shown - // trigger_error('Passing a Request instance to Form::bind() is deprecated since version 2.3 and will be disabled in 3.0. Call Form::process($request) instead.', E_USER_DEPRECATED); + // trigger_error('Passing a Request instance to Form::submit() is deprecated since version 2.3 and will be disabled in 3.0. Call Form::process($request) instead.', E_USER_DEPRECATED); $name = $form->getConfig()->getName(); $default = $form->getConfig()->getCompound() ? array() : null; diff --git a/Extension/HttpFoundation/HttpFoundationRequestHandler.php b/Extension/HttpFoundation/HttpFoundationRequestHandler.php index e33cdf6b41..6457de7477 100644 --- a/Extension/HttpFoundation/HttpFoundationRequestHandler.php +++ b/Extension/HttpFoundation/HttpFoundationRequestHandler.php @@ -45,7 +45,7 @@ public function handleRequest(FormInterface $form, $request = null) if ('' === $name) { $data = $request->query->all(); } else { - // Don't bind GET requests if the form's name does not exist + // Don't submit GET requests if the form's name does not exist // in the request if (!$request->query->has($name)) { return; @@ -70,11 +70,11 @@ public function handleRequest(FormInterface $form, $request = null) } } - // Don't auto-bind the form unless at least one field is submitted. + // Don't auto-submit the form unless at least one field is present. if ('' === $name && count(array_intersect_key($data, $form->all())) <= 0) { return; } - $form->bind($data); + $form->submit($data); } } diff --git a/Extension/Validator/EventListener/ValidationListener.php b/Extension/Validator/EventListener/ValidationListener.php index dd2c51ab57..1414753153 100644 --- a/Extension/Validator/EventListener/ValidationListener.php +++ b/Extension/Validator/EventListener/ValidationListener.php @@ -32,7 +32,7 @@ class ValidationListener implements EventSubscriberInterface */ public static function getSubscribedEvents() { - return array(FormEvents::POST_BIND => 'validateForm'); + return array(FormEvents::POST_SUBMIT => 'validateForm'); } public function __construct(ValidatorInterface $validator, ViolationMapperInterface $violationMapper) diff --git a/Form.php b/Form.php index a7a057dd09..aa6d8f5330 100644 --- a/Form.php +++ b/Form.php @@ -13,7 +13,7 @@ use Symfony\Component\Form\Exception\RuntimeException; use Symfony\Component\Form\Exception\UnexpectedTypeException; -use Symfony\Component\Form\Exception\AlreadyBoundException; +use Symfony\Component\Form\Exception\AlreadySubmittedException; use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\Exception\OutOfBoundsException; @@ -84,10 +84,10 @@ class Form implements \IteratorAggregate, FormInterface private $errors = array(); /** - * Whether this form is bound + * Whether this form was submitted * @var Boolean */ - private $bound = false; + private $submitted = false; /** * The form data in model format @@ -108,7 +108,7 @@ class Form implements \IteratorAggregate, FormInterface private $viewData; /** - * The bound values that don't belong to any children + * The submitted values that don't belong to any children * @var array */ private $extraData = array(); @@ -244,8 +244,8 @@ public function isDisabled() */ public function setParent(FormInterface $parent = null) { - if ($this->bound) { - throw new AlreadyBoundException('You cannot set the parent of a bound form'); + if ($this->submitted) { + throw new AlreadySubmittedException('You cannot set the parent of a submitted form'); } if (null !== $parent && '' === $this->config->getName()) { @@ -286,11 +286,11 @@ public function isRoot() */ public function setData($modelData) { - // If the form is bound while disabled, it is set to bound, but the data is not + // If the form is submitted while disabled, it is set to submitted, but the data is not // changed. In such cases (i.e. when the form is not initialized yet) don't // abort this method. - if ($this->bound && $this->defaultDataSet) { - throw new AlreadyBoundException('You cannot change the data of a bound form.'); + if ($this->submitted && $this->defaultDataSet) { + throw new AlreadySubmittedException('You cannot change the data of a submitted form.'); } // If the form inherits its parent's data, disallow data setting to @@ -464,26 +464,26 @@ public function handleRequest($request = null) /** * {@inheritdoc} */ - public function bind($submittedData) + public function submit($submittedData) { - if ($this->bound) { - throw new AlreadyBoundException('A form can only be bound once'); + if ($this->submitted) { + throw new AlreadySubmittedException('A form can only be submitted once'); } // Initialize errors in the very beginning so that we don't lose any // errors added during listeners $this->errors = array(); - // Obviously, a disabled form should not change its data upon binding. + // Obviously, a disabled form should not change its data upon submission. if ($this->isDisabled()) { - $this->bound = true; + $this->submitted = true; return $this; } // The data must be initialized if it was not initialized yet. // This is necessary to guarantee that the *_SET_DATA listeners - // are always invoked before bind() takes place. + // are always invoked before submit() takes place. if (!$this->defaultDataSet) { $this->setData($this->config->getData()); } @@ -498,10 +498,10 @@ public function bind($submittedData) $dispatcher = $this->config->getEventDispatcher(); - // Hook to change content of the data bound by the browser - if ($dispatcher->hasListeners(FormEvents::PRE_BIND)) { + // Hook to change content of the data submitted by the browser + if ($dispatcher->hasListeners(FormEvents::PRE_SUBMIT)) { $event = new FormEvent($this, $submittedData); - $dispatcher->dispatch(FormEvents::PRE_BIND, $event); + $dispatcher->dispatch(FormEvents::PRE_SUBMIT, $event); $submittedData = $event->getData(); } @@ -515,7 +515,7 @@ public function bind($submittedData) } foreach ($this->children as $name => $child) { - $child->bind(isset($submittedData[$name]) ? $submittedData[$name] : null); + $child->submit(isset($submittedData[$name]) ? $submittedData[$name] : null); unset($submittedData[$name]); } @@ -529,11 +529,11 @@ public function bind($submittedData) // its parent's data) into account. // (see InheritDataAwareIterator below) if ($this->config->getInheritData()) { - $this->bound = true; + $this->submitted = true; - // When POST_BIND is reached, the data is not yet updated, so pass + // When POST_SUBMIT is reached, the data is not yet updated, so pass // NULL to prevent hard-to-debug bugs. - $dataForPostBind = null; + $dataForPostSubmit = null; } else { // If the form is compound, the default data in view format // is reused. The data of the children is merged into this @@ -558,7 +558,7 @@ public function bind($submittedData) if (count($this->children) > 0) { // Use InheritDataAwareIterator to process children of // descendants that inherit this form's data. - // These descendants will not be bound normally (see the check + // These descendants will not be submitted normally (see the check // for $this->config->getInheritData() above) $childrenIterator = new InheritDataAwareIterator($this->children); $childrenIterator = new \RecursiveIteratorIterator($childrenIterator); @@ -574,9 +574,9 @@ public function bind($submittedData) // Hook to change content of the data into the normalized // representation - if ($dispatcher->hasListeners(FormEvents::BIND)) { + if ($dispatcher->hasListeners(FormEvents::SUBMIT)) { $event = new FormEvent($this, $normData); - $dispatcher->dispatch(FormEvents::BIND, $event); + $dispatcher->dispatch(FormEvents::SUBMIT, $event); $normData = $event->getData(); } @@ -587,22 +587,33 @@ public function bind($submittedData) $this->synchronized = false; } - $this->bound = true; + $this->submitted = true; $this->modelData = $modelData; $this->normData = $normData; $this->viewData = $viewData; - $dataForPostBind = $viewData; + $dataForPostSubmit = $viewData; } - if ($dispatcher->hasListeners(FormEvents::POST_BIND)) { - $event = new FormEvent($this, $dataForPostBind); - $dispatcher->dispatch(FormEvents::POST_BIND, $event); + if ($dispatcher->hasListeners(FormEvents::POST_SUBMIT)) { + $event = new FormEvent($this, $dataForPostSubmit); + $dispatcher->dispatch(FormEvents::POST_SUBMIT, $event); } return $this; } + /** + * Alias of {@link submit()}. + * + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use + * {@link submit()} instead. + */ + public function bind($submittedData) + { + return $this->submit($submittedData); + } + /** * {@inheritdoc} */ @@ -620,9 +631,20 @@ public function addError(FormError $error) /** * {@inheritdoc} */ + public function isSubmitted() + { + return $this->submitted; + } + + /** + * Alias of {@link isSubmitted()}. + * + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use + * {@link isSubmitted()} instead. + */ public function isBound() { - return $this->bound; + return $this->submitted; } /** @@ -656,7 +678,7 @@ public function isEmpty() */ public function isValid() { - if (!$this->bound) { + if (!$this->submitted) { return false; } @@ -724,8 +746,8 @@ public function all() */ public function add($child, $type = null, array $options = array()) { - if ($this->bound) { - throw new AlreadyBoundException('You cannot add children to a bound form'); + if ($this->submitted) { + throw new AlreadySubmittedException('You cannot add children to a submitted form'); } if (!$this->config->getCompound()) { @@ -785,8 +807,8 @@ public function add($child, $type = null, array $options = array()) */ public function remove($name) { - if ($this->bound) { - throw new AlreadyBoundException('You cannot remove children from a bound form'); + if ($this->submitted) { + throw new AlreadySubmittedException('You cannot remove children from a submitted form'); } if (isset($this->children[$name])) { @@ -850,8 +872,8 @@ public function offsetGet($name) * @param string $name Ignored. The name of the child is used. * @param FormInterface $child The child to be added. * - * @throws AlreadyBoundException If the form has already been bound. - * @throws LogicException When trying to add a child to a non-compound form. + * @throws AlreadySubmittedException If the form has already been submitted. + * @throws LogicException When trying to add a child to a non-compound form. * * @see self::add() */ @@ -865,7 +887,7 @@ public function offsetSet($name, $child) * * @param string $name The name of the child to remove * - * @throws AlreadyBoundException If the form has already been bound. + * @throws AlreadySubmittedException If the form has already been submitted. */ public function offsetUnset($name) { diff --git a/FormConfigBuilderInterface.php b/FormConfigBuilderInterface.php index 45fa4275e4..60a8d11116 100644 --- a/FormConfigBuilderInterface.php +++ b/FormConfigBuilderInterface.php @@ -122,7 +122,7 @@ public function setDataMapper(DataMapperInterface $dataMapper = null); public function setDisabled($disabled); /** - * Sets the data used for the client data when no value is bound. + * Sets the data used for the client data when no value is submitted. * * @param mixed $emptyData The empty data. * @@ -140,7 +140,7 @@ public function setEmptyData($emptyData); public function setErrorBubbling($errorBubbling); /** - * Sets whether this field is required to be filled out when bound. + * Sets whether this field is required to be filled out when submitted. * * @param Boolean $required * @@ -222,7 +222,7 @@ public function setData($data); * * A form with locked data is restricted to the data passed in * this configuration. The data can only be modified then by - * binding the form. + * submitting the form. * * @param Boolean $locked Whether to lock the default data. * diff --git a/FormConfigInterface.php b/FormConfigInterface.php index a3e8026314..5e944775b8 100644 --- a/FormConfigInterface.php +++ b/FormConfigInterface.php @@ -173,7 +173,7 @@ public function getDataClass(); * * A form with locked data is restricted to the data passed in * this configuration. The data can only be modified then by - * binding the form. + * submitting the form. * * @return Boolean Whether the data is locked. */ diff --git a/FormEvents.php b/FormEvents.php index c46faf36ab..6c4efc5be1 100644 --- a/FormEvents.php +++ b/FormEvents.php @@ -15,16 +15,34 @@ */ final class FormEvents { - const PRE_BIND = 'form.pre_bind'; + const PRE_SUBMIT = 'form.pre_bind'; - const BIND = 'form.bind'; + const SUBMIT = 'form.bind'; - const POST_BIND = 'form.post_bind'; + const POST_SUBMIT = 'form.post_bind'; const PRE_SET_DATA = 'form.pre_set_data'; const POST_SET_DATA = 'form.post_set_data'; + /** + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use + * {@link PRE_SUBMIT} instead. + */ + const PRE_BIND = 'form.pre_bind'; + + /** + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use + * {@link SUBMIT} instead. + */ + const BIND = 'form.bind'; + + /** + * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use + * {@link POST_SUBMIT} instead. + */ + const POST_BIND = 'form.post_bind'; + private function __construct() { } diff --git a/FormInterface.php b/FormInterface.php index e1a64e626a..1069398ba8 100644 --- a/FormInterface.php +++ b/FormInterface.php @@ -25,7 +25,7 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable * * @return FormInterface The form instance * - * @throws Exception\AlreadyBoundException If the form has already been bound. + * @throws Exception\AlreadySubmittedException If the form has already been submitted. * @throws Exception\LogicException When trying to set a parent for a form with * an empty name. */ @@ -47,7 +47,7 @@ public function getParent(); * * @return FormInterface The form instance * - * @throws Exception\AlreadyBoundException If the form has already been bound. + * @throws Exception\AlreadySubmittedException If the form has already been submitted. * @throws Exception\LogicException When trying to add a child to a non-compound form. * @throws Exception\UnexpectedTypeException If $child or $type has an unexpected type. */ @@ -80,7 +80,7 @@ public function has($name); * * @return FormInterface The form instance * - * @throws Exception\AlreadyBoundException If the form has already been bound. + * @throws Exception\AlreadySubmittedException If the form has already been submitted. */ public function remove($name); @@ -94,7 +94,7 @@ public function all(); /** * Returns all errors. * - * @return FormError[] An array of FormError instances that occurred during binding + * @return FormError[] An array of FormError instances that occurred during validation */ public function getErrors(); @@ -105,7 +105,7 @@ public function getErrors(); * * @return FormInterface The form instance * - * @throws Exception\AlreadyBoundException If the form has already been bound. + * @throws Exception\AlreadySubmittedException If the form has already been submitted. * @throws Exception\LogicException If listeners try to call setData in a cycle. Or if * the view data does not match the expected type * according to {@link FormConfigInterface::getDataClass}. @@ -122,8 +122,8 @@ public function getData(); /** * Returns the normalized data of the field. * - * @return mixed When the field is not bound, the default data is returned. - * When the field is bound, the normalized bound data is + * @return mixed When the field is not submitted, the default data is returned. + * When the field is submitted, the normalized submitted data is * returned if the field is valid, null otherwise. */ public function getNormData(); @@ -138,7 +138,7 @@ public function getViewData(); /** * Returns the extra data. * - * @return array The bound data which do not belong to a child + * @return array The submitted data which do not belong to a child */ public function getExtraData(); @@ -154,7 +154,7 @@ public function getConfig(); * * @return Boolean true if the form is submitted, false otherwise */ - public function isBound(); + public function isSubmitted(); /** * Returns the name by which the form is identified in forms. @@ -182,7 +182,7 @@ public function addError(FormError $error); /** * Returns whether the form and all children are valid. * - * If the form is not bound, this method always returns false. + * If the form is not submitted, this method always returns false. * * @return Boolean */ @@ -227,7 +227,7 @@ public function isEmpty(); public function isSynchronized(); /** - * Processes the given request and binds the form if it was submitted. + * Processes the given request and calls {@link submit()} if it was submitted. * * Internally, the request is forwarded to a {@link RequestHandlerInterface} * instance. This instance determines the allowed value of the @@ -240,15 +240,15 @@ public function isSynchronized(); public function handleRequest($request = null); /** - * Binds data to the form, transforms and validates it. + * Submits data to the form, transforms and validates it. * - * @param null|string|array $submittedData The data + * @param null|string|array $submittedData The submitted data. * * @return FormInterface The form instance * - * @throws Exception\AlreadyBoundException If the form has already been bound. + * @throws Exception\AlreadySubmittedException If the form has already been submitted. */ - public function bind($submittedData); + public function submit($submittedData); /** * Returns the root of the form tree. diff --git a/NativeRequestHandler.php b/NativeRequestHandler.php index ac343c4898..6ddb8d72a3 100644 --- a/NativeRequestHandler.php +++ b/NativeRequestHandler.php @@ -55,7 +55,7 @@ public function handleRequest(FormInterface $form, $request = null) if ('' === $name) { $data = $_GET; } else { - // Don't bind GET requests if the form's name does not exist + // Don't submit GET requests if the form's name does not exist // in the request if (!isset($_GET[$name])) { return; @@ -85,12 +85,12 @@ public function handleRequest(FormInterface $form, $request = null) } } - // Don't auto-bind the form unless at least one field is submitted. + // Don't auto-submit the form unless at least one field is present. if ('' === $name && count(array_intersect_key($data, $form->all())) <= 0) { return; } - $form->bind($data); + $form->submit($data); } /** diff --git a/README.md b/README.md index 38504bcac2..7bfff7fd22 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Form Component ============== -Form provides tools for defining forms, rendering and binding request data to +Form provides tools for defining forms, rendering and mapping request data to related models. Furthermore it provides integration with the Validation component. diff --git a/RequestHandlerInterface.php b/RequestHandlerInterface.php index d62b950a9c..d0a58e6973 100644 --- a/RequestHandlerInterface.php +++ b/RequestHandlerInterface.php @@ -12,16 +12,16 @@ namespace Symfony\Component\Form; /** - * Binds forms from requests if they were submitted. + * Submits forms if they were submitted. * * @author Bernhard Schussek */ interface RequestHandlerInterface { /** - * Binds a form from a request if it was submitted. + * Submits a form if it was submitted. * - * @param FormInterface $form The form to bind. + * @param FormInterface $form The form to submit. * @param mixed $request The current request. */ public function handleRequest(FormInterface $form, $request = null); diff --git a/SubmitButton.php b/SubmitButton.php index 01af5c2e72..a169ba6529 100644 --- a/SubmitButton.php +++ b/SubmitButton.php @@ -32,17 +32,17 @@ public function isClicked() } /** - * Binds data to the button. + * Submits data to the button. * * @param null|string $submittedData The data * * @return SubmitButton The button instance * - * @throws Exception\AlreadyBoundException If the form has already been bound. + * @throws Exception\AlreadySubmittedException If the form has already been submitted. */ - public function bind($submittedData) + public function submit($submittedData) { - parent::bind($submittedData); + parent::submit($submittedData); $this->clicked = null !== $submittedData; diff --git a/Tests/AbstractFormTest.php b/Tests/AbstractFormTest.php index 5e13863aa9..42543b63cf 100644 --- a/Tests/AbstractFormTest.php +++ b/Tests/AbstractFormTest.php @@ -38,7 +38,7 @@ protected function setUp() $this->markTestSkipped('The "EventDispatcher" component is not available'); } - // We need an actual dispatcher to bind the deprecated + // We need an actual dispatcher to use the deprecated // bindRequest() method $this->dispatcher = new EventDispatcher(); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index 9f8200c095..b7c27b70c9 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -1378,12 +1378,12 @@ public function testPassword() ); } - public function testPasswordBoundNotAlwaysEmpty() + public function testPasswordSubmittedWithNotAlwaysEmpty() { $form = $this->factory->createNamed('name', 'password', null, array( 'always_empty' => false, )); - $form->bind('foo&bar'); + $form->submit('foo&bar'); $this->assertWidgetMatchesXpath($form->createView(), array(), '/input diff --git a/Tests/AbstractRequestHandlerTest.php b/Tests/AbstractRequestHandlerTest.php index d9f693622c..1890ec00aa 100644 --- a/Tests/AbstractRequestHandlerTest.php +++ b/Tests/AbstractRequestHandlerTest.php @@ -49,7 +49,7 @@ public function methodProvider() /** * @dataProvider methodProvider */ - public function testBindIfNameInRequest($method) + public function testSubmitIfNameInRequest($method) { $form = $this->getMockForm('param1', $method); @@ -58,7 +58,7 @@ public function testBindIfNameInRequest($method) )); $form->expects($this->once()) - ->method('bind') + ->method('Submit') ->with('DATA'); $this->requestHandler->handleRequest($form, $this->request); @@ -67,7 +67,7 @@ public function testBindIfNameInRequest($method) /** * @dataProvider methodProvider */ - public function testDoNotBindIfWrongRequestMethod($method) + public function testDoNotSubmitIfWrongRequestMethod($method) { $form = $this->getMockForm('param1', $method); @@ -78,7 +78,7 @@ public function testDoNotBindIfWrongRequestMethod($method) )); $form->expects($this->never()) - ->method('bind'); + ->method('Submit'); $this->requestHandler->handleRequest($form, $this->request); } @@ -86,7 +86,7 @@ public function testDoNotBindIfWrongRequestMethod($method) /** * @dataProvider methodExceptGetProvider */ - public function testBindSimpleFormWithNullIfNameNotInRequestAndNotGetRequest($method) + public function testSubmitSimpleFormWithNullIfNameNotInRequestAndNotGetRequest($method) { $form = $this->getMockForm('param1', $method, false); @@ -95,7 +95,7 @@ public function testBindSimpleFormWithNullIfNameNotInRequestAndNotGetRequest($me )); $form->expects($this->once()) - ->method('bind') + ->method('Submit') ->with($this->identicalTo(null)); $this->requestHandler->handleRequest($form, $this->request); @@ -104,7 +104,7 @@ public function testBindSimpleFormWithNullIfNameNotInRequestAndNotGetRequest($me /** * @dataProvider methodExceptGetProvider */ - public function testBindCompoundFormWithArrayIfNameNotInRequestAndNotGetRequest($method) + public function testSubmitCompoundFormWithArrayIfNameNotInRequestAndNotGetRequest($method) { $form = $this->getMockForm('param1', $method, true); @@ -113,13 +113,13 @@ public function testBindCompoundFormWithArrayIfNameNotInRequestAndNotGetRequest( )); $form->expects($this->once()) - ->method('bind') + ->method('Submit') ->with($this->identicalTo(array())); $this->requestHandler->handleRequest($form, $this->request); } - public function testDoNotBindIfNameNotInRequestAndGetRequest() + public function testDoNotSubmitIfNameNotInRequestAndGetRequest() { $form = $this->getMockForm('param1', 'GET'); @@ -128,7 +128,7 @@ public function testDoNotBindIfNameNotInRequestAndGetRequest() )); $form->expects($this->never()) - ->method('bind'); + ->method('Submit'); $this->requestHandler->handleRequest($form, $this->request); } @@ -136,7 +136,7 @@ public function testDoNotBindIfNameNotInRequestAndGetRequest() /** * @dataProvider methodProvider */ - public function testBindFormWithEmptyNameIfAtLeastOneFieldInRequest($method) + public function testSubmitFormWithEmptyNameIfAtLeastOneFieldInRequest($method) { $form = $this->getMockForm('', $method); $form->expects($this->any()) @@ -152,7 +152,7 @@ public function testBindFormWithEmptyNameIfAtLeastOneFieldInRequest($method) )); $form->expects($this->once()) - ->method('bind') + ->method('Submit') ->with($requestData); $this->requestHandler->handleRequest($form, $this->request); @@ -161,7 +161,7 @@ public function testBindFormWithEmptyNameIfAtLeastOneFieldInRequest($method) /** * @dataProvider methodProvider */ - public function testDoNotBindFormWithEmptyNameIfNoFieldInRequest($method) + public function testDoNotSubmitFormWithEmptyNameIfNoFieldInRequest($method) { $form = $this->getMockForm('', $method); $form->expects($this->any()) @@ -176,7 +176,7 @@ public function testDoNotBindFormWithEmptyNameIfNoFieldInRequest($method) )); $form->expects($this->never()) - ->method('bind'); + ->method('Submit'); $this->requestHandler->handleRequest($form, $this->request); } @@ -200,7 +200,7 @@ public function testMergeParamsAndFiles($method) )); $form->expects($this->once()) - ->method('bind') + ->method('Submit') ->with(array( 'field1' => 'DATA', 'field2' => $file, @@ -224,7 +224,7 @@ public function testParamTakesPrecedenceOverFile($method) )); $form->expects($this->once()) - ->method('bind') + ->method('Submit') ->with('DATA'); $this->requestHandler->handleRequest($form, $this->request); @@ -233,7 +233,7 @@ public function testParamTakesPrecedenceOverFile($method) /** * @dataProvider methodExceptGetProvider */ - public function testBindFileIfNoParam($method) + public function testSubmitFileIfNoParam($method) { $form = $this->getMockForm('param1', $method); $file = $this->getMockFile(); @@ -245,7 +245,7 @@ public function testBindFileIfNoParam($method) )); $form->expects($this->once()) - ->method('bind') + ->method('Submit') ->with($file); $this->requestHandler->handleRequest($form, $this->request); diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index 95fdd4632e..f213db3126 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -24,7 +24,7 @@ public function testValidIfAllChildrenAreValid() $this->form->add($this->getValidForm('firstName')); $this->form->add($this->getValidForm('lastName')); - $this->form->bind(array( + $this->form->submit(array( 'firstName' => 'Bernhard', 'lastName' => 'Schussek', )); @@ -37,7 +37,7 @@ public function testInvalidIfChildIsInvalid() $this->form->add($this->getValidForm('firstName')); $this->form->add($this->getInvalidForm('lastName')); - $this->form->bind(array( + $this->form->submit(array( 'firstName' => 'Bernhard', 'lastName' => 'Schussek', )); @@ -45,17 +45,17 @@ public function testInvalidIfChildIsInvalid() $this->assertFalse($this->form->isValid()); } - public function testBindForwardsNullIfValueIsMissing() + public function testSubmitForwardsNullIfValueIsMissing() { $child = $this->getMockForm('firstName'); $this->form->add($child); $child->expects($this->once()) - ->method('bind') + ->method('submit') ->with($this->equalTo(null)); - $this->form->bind(array()); + $this->form->submit(array()); } public function testCloneChildren() @@ -82,7 +82,7 @@ public function testNotEmptyIfChildNotEmpty() $this->assertFalse($this->form->isEmpty()); } - public function testValidIfBoundAndDisabledWithChildren() + public function testValidIfSubmittedAndDisabledWithChildren() { $this->factory->expects($this->once()) ->method('createNamedBuilder') @@ -95,7 +95,7 @@ public function testValidIfBoundAndDisabledWithChildren() ->setDataMapper($this->getDataMapper()) ->add('name', 'text') ->getForm(); - $form->bind(array('name' => 'Jacques Doe')); + $form->submit(array('name' => 'Jacques Doe')); $this->assertTrue($form->isValid()); } @@ -108,7 +108,7 @@ public function testNotValidIfChildNotValid() ->will($this->returnValue(false)); $this->form->add($child); - $this->form->bind(array()); + $this->form->submit(array()); $this->assertFalse($this->form->isValid()); } @@ -199,11 +199,11 @@ public function testAddUsingNameButNoTypeAndOptions() } /** - * @expectedException \Symfony\Component\Form\Exception\AlreadyBoundException + * @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException */ - public function testAddThrowsExceptionIfAlreadyBound() + public function testAddThrowsExceptionIfAlreadySubmitted() { - $this->form->bind(array()); + $this->form->submit(array()); $this->form->add($this->getBuilder('foo')->getForm()); } @@ -218,12 +218,12 @@ public function testRemove() } /** - * @expectedException \Symfony\Component\Form\Exception\AlreadyBoundException + * @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException */ - public function testRemoveThrowsExceptionIfAlreadyBound() + public function testRemoveThrowsExceptionIfAlreadySubmitted() { $this->form->add($this->getBuilder('foo')->setCompound(false)->getForm()); - $this->form->bind(array('foo' => 'bar')); + $this->form->submit(array('foo' => 'bar')); $this->form->remove('foo'); } @@ -331,7 +331,7 @@ public function testSetDataMapsViewDataToChildren() $form->setData('foo'); } - public function testBindMapsBoundChildrenOntoExistingViewData() + public function testSubmitMapsSubmittedChildrenOntoExistingViewData() { $test = $this; $mapper = $this->getDataMapper(); @@ -358,7 +358,7 @@ public function testBindMapsBoundChildrenOntoExistingViewData() $test->assertEquals('Schussek', $child2->getData()); })); - $form->bind(array( + $form->submit(array( 'firstName' => 'Bernhard', 'lastName' => 'Schussek', )); @@ -383,7 +383,7 @@ public function testMapFormsToDataIsNotInvokedIfInheritData() $mapper->expects($this->never()) ->method('mapFormsToData'); - $form->bind(array( + $form->submit(array( 'firstName' => 'Bernhard', 'lastName' => 'Schussek', )); @@ -392,7 +392,7 @@ public function testMapFormsToDataIsNotInvokedIfInheritData() /* * https://github.com/symfony/symfony/issues/4480 */ - public function testBindRestoresViewDataIfCompoundAndEmpty() + public function testSubmitRestoresViewDataIfCompoundAndEmpty() { $mapper = $this->getDataMapper(); $object = new \stdClass(); @@ -402,12 +402,12 @@ public function testBindRestoresViewDataIfCompoundAndEmpty() ->setData($object) ->getForm(); - $form->bind(array()); + $form->submit(array()); $this->assertSame($object, $form->getData()); } - public function testBindMapsBoundChildrenOntoEmptyData() + public function testSubmitMapsSubmittedChildrenOntoEmptyData() { $test = $this; $mapper = $this->getDataMapper(); @@ -429,7 +429,7 @@ public function testBindMapsBoundChildrenOntoEmptyData() $test->assertSame(array('name' => $child), iterator_to_array($iterator)); })); - $form->bind(array( + $form->submit(array( 'name' => 'Bernhard', )); } @@ -447,7 +447,7 @@ public function requestMethodProvider() /** * @dataProvider requestMethodProvider */ - public function testBindPostOrPutRequest($method) + public function testSubmitPostOrPutRequest($method) { if (!class_exists('Symfony\Component\HttpFoundation\Request')) { $this->markTestSkipped('The "HttpFoundation" component is not available'); @@ -499,7 +499,7 @@ public function testBindPostOrPutRequest($method) /** * @dataProvider requestMethodProvider */ - public function testBindPostOrPutRequestWithEmptyRootFormName($method) + public function testSubmitPostOrPutRequestWithEmptyRootFormName($method) { if (!class_exists('Symfony\Component\HttpFoundation\Request')) { $this->markTestSkipped('The "HttpFoundation" component is not available'); @@ -550,7 +550,7 @@ public function testBindPostOrPutRequestWithEmptyRootFormName($method) /** * @dataProvider requestMethodProvider */ - public function testBindPostOrPutRequestWithSingleChildForm($method) + public function testSubmitPostOrPutRequestWithSingleChildForm($method) { if (!class_exists('Symfony\Component\HttpFoundation\Request')) { $this->markTestSkipped('The "HttpFoundation" component is not available'); @@ -590,7 +590,7 @@ public function testBindPostOrPutRequestWithSingleChildForm($method) /** * @dataProvider requestMethodProvider */ - public function testBindPostOrPutRequestWithSingleChildFormUploadedFile($method) + public function testSubmitPostOrPutRequestWithSingleChildFormUploadedFile($method) { if (!class_exists('Symfony\Component\HttpFoundation\Request')) { $this->markTestSkipped('The "HttpFoundation" component is not available'); @@ -619,7 +619,7 @@ public function testBindPostOrPutRequestWithSingleChildFormUploadedFile($method) unlink($path); } - public function testBindGetRequest() + public function testSubmitGetRequest() { if (!class_exists('Symfony\Component\HttpFoundation\Request')) { $this->markTestSkipped('The "HttpFoundation" component is not available'); @@ -651,7 +651,7 @@ public function testBindGetRequest() $this->assertEquals('Schussek', $form['lastName']->getData()); } - public function testBindGetRequestWithEmptyRootFormName() + public function testSubmitGetRequestWithEmptyRootFormName() { if (!class_exists('Symfony\Component\HttpFoundation\Request')) { $this->markTestSkipped('The "HttpFoundation" component is not available'); diff --git a/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php b/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php index 35bc7323dd..955f56663f 100644 --- a/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php +++ b/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php @@ -44,7 +44,7 @@ public function testFixRadio() $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); - $this->listener->preBind($event); + $this->listener->preSubmit($event); $this->assertEquals(array(1 => '1'), $event->getData()); } @@ -55,7 +55,7 @@ public function testFixZero() $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); - $this->listener->preBind($event); + $this->listener->preSubmit($event); $this->assertEquals(array(0 => '0'), $event->getData()); } @@ -66,7 +66,7 @@ public function testIgnoreEmptyString() $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); - $this->listener->preBind($event); + $this->listener->preSubmit($event); $this->assertEquals(array(), $event->getData()); } diff --git a/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php b/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php index 2517f40b04..2b84e4fd82 100644 --- a/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php +++ b/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php @@ -30,7 +30,7 @@ public function testFixHttpUrl() $event = new FormEvent($form, $data); $filter = new FixUrlProtocolListener('http'); - $filter->onBind($event); + $filter->onSubmit($event); $this->assertEquals('http://www.symfony.com', $event->getData()); } @@ -42,7 +42,7 @@ public function testSkipKnownUrl() $event = new FormEvent($form, $data); $filter = new FixUrlProtocolListener('http'); - $filter->onBind($event); + $filter->onSubmit($event); $this->assertEquals('http://www.symfony.com', $event->getData()); } @@ -54,7 +54,7 @@ public function testSkipOtherProtocol() $event = new FormEvent($form, $data); $filter = new FixUrlProtocolListener('http'); - $filter->onBind($event); + $filter->onSubmit($event); $this->assertEquals('ftp://www.symfony.com', $event->getData()); } diff --git a/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php b/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php index b6ca56e7a4..dbd28c6b55 100644 --- a/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php +++ b/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php @@ -85,7 +85,7 @@ public function testAddExtraEntriesIfAllowAdd($allowDelete) $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); - $listener->onBind($event); + $listener->onSubmit($event); // The original object was modified if (is_object($originalData)) { @@ -109,7 +109,7 @@ public function testAddExtraEntriesIfAllowAddDontOverwriteExistingIndices($allow $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); - $listener->onBind($event); + $listener->onSubmit($event); // The original object was modified if (is_object($originalData)) { @@ -134,7 +134,7 @@ public function testDoNothingIfNotAllowAdd($allowDelete) $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); - $listener->onBind($event); + $listener->onSubmit($event); // We still have the original object if (is_object($originalData)) { @@ -158,7 +158,7 @@ public function testRemoveMissingEntriesIfAllowDelete($allowAdd) $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); - $listener->onBind($event); + $listener->onSubmit($event); // The original object was modified if (is_object($originalData)) { @@ -183,7 +183,7 @@ public function testDoNothingIfNotAllowDelete($allowAdd) $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); - $listener->onBind($event); + $listener->onSubmit($event); // We still have the original object if (is_object($originalData)) { @@ -203,7 +203,7 @@ public function testRequireArrayOrTraversable($allowAdd, $allowDelete) $newData = 'no array or traversable'; $event = new FormEvent($this->form, $newData); $listener = new MergeCollectionListener($allowAdd, $allowDelete); - $listener->onBind($event); + $listener->onSubmit($event); } public function testDealWithNullData() @@ -216,7 +216,7 @@ public function testDealWithNullData() $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); - $listener->onBind($event); + $listener->onSubmit($event); $this->assertSame($originalData, $event->getData()); } @@ -234,7 +234,7 @@ public function testDealWithNullOriginalDataIfAllowAdd($allowDelete) $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); - $listener->onBind($event); + $listener->onSubmit($event); $this->assertSame($newData, $event->getData()); } @@ -252,7 +252,7 @@ public function testDontDealWithNullOriginalDataIfNotAllowAdd($allowDelete) $this->form->setData($originalData); $event = new FormEvent($this->form, $newData); - $listener->onBind($event); + $listener->onSubmit($event); $this->assertNull($event->getData()); } diff --git a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php index 5dfcc3d789..d77531ede4 100644 --- a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php +++ b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php @@ -110,7 +110,7 @@ public function testPreSetDataDealsWithNullData() $listener->preSetData($event); } - public function testPreBindResizesUpIfAllowAdd() + public function testPreSubmitResizesUpIfAllowAdd() { $this->form->add($this->getForm('0')); @@ -122,13 +122,13 @@ public function testPreBindResizesUpIfAllowAdd() $data = array(0 => 'string', 1 => 'string'); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array('max_length' => 10), true, false); - $listener->preBind($event); + $listener->preSubmit($event); $this->assertTrue($this->form->has('0')); $this->assertTrue($this->form->has('1')); } - public function testPreBindResizesDownIfAllowDelete() + public function testPreSubmitResizesDownIfAllowDelete() { $this->form->add($this->getForm('0')); $this->form->add($this->getForm('1')); @@ -136,26 +136,26 @@ public function testPreBindResizesDownIfAllowDelete() $data = array(0 => 'string'); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); - $listener->preBind($event); + $listener->preSubmit($event); $this->assertTrue($this->form->has('0')); $this->assertFalse($this->form->has('1')); } // fix for https://github.com/symfony/symfony/pull/493 - public function testPreBindRemovesZeroKeys() + public function testPreSubmitRemovesZeroKeys() { $this->form->add($this->getForm('0')); $data = array(); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); - $listener->preBind($event); + $listener->preSubmit($event); $this->assertFalse($this->form->has('0')); } - public function testPreBindDoesNothingIfNotAllowAddNorAllowDelete() + public function testPreSubmitDoesNothingIfNotAllowAddNorAllowDelete() { $this->form->add($this->getForm('0')); $this->form->add($this->getForm('1')); @@ -163,7 +163,7 @@ public function testPreBindDoesNothingIfNotAllowAddNorAllowDelete() $data = array(0 => 'string', 2 => 'string'); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, false); - $listener->preBind($event); + $listener->preSubmit($event); $this->assertTrue($this->form->has('0')); $this->assertTrue($this->form->has('1')); @@ -173,59 +173,59 @@ public function testPreBindDoesNothingIfNotAllowAddNorAllowDelete() /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ - public function testPreBindRequiresArrayOrTraversable() + public function testPreSubmitRequiresArrayOrTraversable() { $data = 'no array or traversable'; $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, false); - $listener->preBind($event); + $listener->preSubmit($event); } - public function testPreBindDealsWithNullData() + public function testPreSubmitDealsWithNullData() { $this->form->add($this->getForm('1')); $data = null; $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); - $listener->preBind($event); + $listener->preSubmit($event); $this->assertFalse($this->form->has('1')); } // fixes https://github.com/symfony/symfony/pull/40 - public function testPreBindDealsWithEmptyData() + public function testPreSubmitDealsWithEmptyData() { $this->form->add($this->getForm('1')); $data = ''; $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); - $listener->preBind($event); + $listener->preSubmit($event); $this->assertFalse($this->form->has('1')); } - public function testOnBindNormDataRemovesEntriesMissingInTheFormIfAllowDelete() + public function testOnSubmitNormDataRemovesEntriesMissingInTheFormIfAllowDelete() { $this->form->add($this->getForm('1')); $data = array(0 => 'first', 1 => 'second', 2 => 'third'); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); - $listener->onBind($event); + $listener->onSubmit($event); $this->assertEquals(array(1 => 'second'), $event->getData()); } - public function testOnBindNormDataDoesNothingIfNotAllowDelete() + public function testOnSubmitNormDataDoesNothingIfNotAllowDelete() { $this->form->add($this->getForm('1')); $data = array(0 => 'first', 1 => 'second', 2 => 'third'); $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, false); - $listener->onBind($event); + $listener->onSubmit($event); $this->assertEquals($data, $event->getData()); } @@ -233,22 +233,22 @@ public function testOnBindNormDataDoesNothingIfNotAllowDelete() /** * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ - public function testOnBindNormDataRequiresArrayOrTraversable() + public function testOnSubmitNormDataRequiresArrayOrTraversable() { $data = 'no array or traversable'; $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, false); - $listener->onBind($event); + $listener->onSubmit($event); } - public function testOnBindNormDataDealsWithNullData() + public function testOnSubmitNormDataDealsWithNullData() { $this->form->add($this->getForm('1')); $data = null; $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, true); - $listener->onBind($event); + $listener->onSubmit($event); $this->assertEquals(array(), $event->getData()); } diff --git a/Tests/Extension/Core/EventListener/TrimListenerTest.php b/Tests/Extension/Core/EventListener/TrimListenerTest.php index 9e5d20db71..4e36893380 100644 --- a/Tests/Extension/Core/EventListener/TrimListenerTest.php +++ b/Tests/Extension/Core/EventListener/TrimListenerTest.php @@ -30,7 +30,7 @@ public function testTrim() $event = new FormEvent($form, $data); $filter = new TrimListener(); - $filter->preBind($event); + $filter->preSubmit($event); $this->assertEquals('Foo!', $event->getData()); } @@ -42,7 +42,7 @@ public function testTrimSkipNonStrings() $event = new FormEvent($form, $data); $filter = new TrimListener(); - $filter->preBind($event); + $filter->preSubmit($event); $this->assertSame(1234, $event->getData()); } @@ -63,7 +63,7 @@ public function testTrimUtf8($chars) $event = new FormEvent($form, $data); $filter = new TrimListener(); - $filter->preBind($event); + $filter->preSubmit($event); $this->assertSame("ab\ncd", $event->getData(), 'TrimListener should trim character(s): '.implode(', ', $chars)); } diff --git a/Tests/Extension/Core/Type/CheckboxTypeTest.php b/Tests/Extension/Core/Type/CheckboxTypeTest.php index 304958f768..1e5b30a856 100644 --- a/Tests/Extension/Core/Type/CheckboxTypeTest.php +++ b/Tests/Extension/Core/Type/CheckboxTypeTest.php @@ -50,56 +50,56 @@ public function testNotCheckedIfDataFalse() $this->assertFalse($view->vars['checked']); } - public function testBindWithValueChecked() + public function testSubmitWithValueChecked() { $form = $this->factory->create('checkbox', null, array( 'value' => 'foobar', )); - $form->bind('foobar'); + $form->submit('foobar'); $this->assertTrue($form->getData()); $this->assertEquals('foobar', $form->getViewData()); } - public function testBindWithRandomValueChecked() + public function testSubmitWithRandomValueChecked() { $form = $this->factory->create('checkbox', null, array( 'value' => 'foobar', )); - $form->bind('krixikraxi'); + $form->submit('krixikraxi'); $this->assertTrue($form->getData()); $this->assertEquals('foobar', $form->getViewData()); } - public function testBindWithValueUnchecked() + public function testSubmitWithValueUnchecked() { $form = $this->factory->create('checkbox', null, array( 'value' => 'foobar', )); - $form->bind(null); + $form->submit(null); $this->assertFalse($form->getData()); $this->assertNull($form->getViewData()); } - public function testBindWithEmptyValueChecked() + public function testSubmitWithEmptyValueChecked() { $form = $this->factory->create('checkbox', null, array( 'value' => '', )); - $form->bind(''); + $form->submit(''); $this->assertTrue($form->getData()); $this->assertSame('', $form->getViewData()); } - public function testBindWithEmptyValueUnchecked() + public function testSubmitWithEmptyValueUnchecked() { $form = $this->factory->create('checkbox', null, array( 'value' => '', )); - $form->bind(null); + $form->submit(null); $this->assertFalse($form->getData()); $this->assertNull($form->getViewData()); diff --git a/Tests/Extension/Core/Type/ChoiceTypeTest.php b/Tests/Extension/Core/Type/ChoiceTypeTest.php index 6e01d37dab..9499d7607f 100644 --- a/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -163,7 +163,7 @@ public function testExpandedRadiosAreNotRequiredIfChoiceChildIsNotRequired() } } - public function testBindSingleNonExpanded() + public function testSubmitSingleNonExpanded() { $form = $this->factory->create('choice', null, array( 'multiple' => false, @@ -171,13 +171,13 @@ public function testBindSingleNonExpanded() 'choices' => $this->choices, )); - $form->bind('b'); + $form->submit('b'); $this->assertEquals('b', $form->getData()); $this->assertEquals('b', $form->getViewData()); } - public function testBindSingleNonExpandedObjectChoices() + public function testSubmitSingleNonExpandedObjectChoices() { $form = $this->factory->create('choice', null, array( 'multiple' => false, @@ -194,13 +194,13 @@ public function testBindSingleNonExpandedObjectChoices() )); // "id" value of the second entry - $form->bind('2'); + $form->submit('2'); $this->assertEquals($this->objectChoices[1], $form->getData()); $this->assertEquals('2', $form->getViewData()); } - public function testBindMultipleNonExpanded() + public function testSubmitMultipleNonExpanded() { $form = $this->factory->create('choice', null, array( 'multiple' => true, @@ -208,13 +208,13 @@ public function testBindMultipleNonExpanded() 'choices' => $this->choices, )); - $form->bind(array('a', 'b')); + $form->submit(array('a', 'b')); $this->assertEquals(array('a', 'b'), $form->getData()); $this->assertEquals(array('a', 'b'), $form->getViewData()); } - public function testBindMultipleNonExpandedObjectChoices() + public function testSubmitMultipleNonExpandedObjectChoices() { $form = $this->factory->create('choice', null, array( 'multiple' => true, @@ -230,13 +230,13 @@ public function testBindMultipleNonExpandedObjectChoices() ), )); - $form->bind(array('2', '3')); + $form->submit(array('2', '3')); $this->assertEquals(array($this->objectChoices[1], $this->objectChoices[2]), $form->getData()); $this->assertEquals(array('2', '3'), $form->getViewData()); } - public function testBindSingleExpanded() + public function testSubmitSingleExpanded() { $form = $this->factory->create('choice', null, array( 'multiple' => false, @@ -244,7 +244,7 @@ public function testBindSingleExpanded() 'choices' => $this->choices, )); - $form->bind('b'); + $form->submit('b'); $this->assertSame('b', $form->getData()); $this->assertFalse($form[0]->getData()); @@ -259,7 +259,7 @@ public function testBindSingleExpanded() $this->assertNull($form[4]->getViewData()); } - public function testBindSingleExpandedNothingChecked() + public function testSubmitSingleExpandedNothingChecked() { $form = $this->factory->create('choice', null, array( 'multiple' => false, @@ -267,7 +267,7 @@ public function testBindSingleExpandedNothingChecked() 'choices' => $this->choices, )); - $form->bind(null); + $form->submit(null); $this->assertNull($form->getData()); $this->assertFalse($form[0]->getData()); @@ -282,7 +282,7 @@ public function testBindSingleExpandedNothingChecked() $this->assertNull($form[4]->getViewData()); } - public function testBindSingleExpandedWithFalseDoesNotHaveExtraChildren() + public function testSubmitSingleExpandedWithFalseDoesNotHaveExtraChildren() { $form = $this->factory->create('choice', null, array( 'multiple' => false, @@ -290,13 +290,13 @@ public function testBindSingleExpandedWithFalseDoesNotHaveExtraChildren() 'choices' => $this->choices, )); - $form->bind(false); + $form->submit(false); $this->assertEmpty($form->getExtraData()); $this->assertNull($form->getData()); } - public function testBindSingleExpandedWithEmptyChild() + public function testSubmitSingleExpandedWithEmptyChild() { $form = $this->factory->create('choice', null, array( 'multiple' => false, @@ -307,7 +307,7 @@ public function testBindSingleExpandedWithEmptyChild() ), )); - $form->bind(''); + $form->submit(''); $this->assertNull($form->getData()); $this->assertTrue($form[0]->getData()); @@ -316,7 +316,7 @@ public function testBindSingleExpandedWithEmptyChild() $this->assertNull($form[1]->getViewData()); } - public function testBindSingleExpandedObjectChoices() + public function testSubmitSingleExpandedObjectChoices() { $form = $this->factory->create('choice', null, array( 'multiple' => false, @@ -332,7 +332,7 @@ public function testBindSingleExpandedObjectChoices() ), )); - $form->bind('2'); + $form->submit('2'); $this->assertSame($this->objectChoices[1], $form->getData()); $this->assertFalse($form[0]->getData()); @@ -347,7 +347,7 @@ public function testBindSingleExpandedObjectChoices() $this->assertNull($form[4]->getViewData()); } - public function testBindSingleExpandedNumericChoices() + public function testSubmitSingleExpandedNumericChoices() { $form = $this->factory->create('choice', null, array( 'multiple' => false, @@ -355,7 +355,7 @@ public function testBindSingleExpandedNumericChoices() 'choices' => $this->numericChoices, )); - $form->bind('1'); + $form->submit('1'); $this->assertSame(1, $form->getData()); $this->assertFalse($form[0]->getData()); @@ -370,7 +370,7 @@ public function testBindSingleExpandedNumericChoices() $this->assertNull($form[4]->getViewData()); } - public function testBindMultipleExpanded() + public function testSubmitMultipleExpanded() { $form = $this->factory->create('choice', null, array( 'multiple' => true, @@ -378,7 +378,7 @@ public function testBindMultipleExpanded() 'choices' => $this->choices, )); - $form->bind(array('a', 'c')); + $form->submit(array('a', 'c')); $this->assertSame(array('a', 'c'), $form->getData()); $this->assertTrue($form[0]->getData()); @@ -393,7 +393,7 @@ public function testBindMultipleExpanded() $this->assertNull($form[4]->getViewData()); } - public function testBindMultipleExpandedEmpty() + public function testSubmitMultipleExpandedEmpty() { $form = $this->factory->create('choice', null, array( 'multiple' => true, @@ -401,7 +401,7 @@ public function testBindMultipleExpandedEmpty() 'choices' => $this->choices, )); - $form->bind(array()); + $form->submit(array()); $this->assertSame(array(), $form->getData()); $this->assertFalse($form[0]->getData()); @@ -416,7 +416,7 @@ public function testBindMultipleExpandedEmpty() $this->assertNull($form[4]->getViewData()); } - public function testBindMultipleExpandedWithEmptyChild() + public function testSubmitMultipleExpandedWithEmptyChild() { $form = $this->factory->create('choice', null, array( 'multiple' => true, @@ -428,7 +428,7 @@ public function testBindMultipleExpandedWithEmptyChild() ) )); - $form->bind(array('', '2')); + $form->submit(array('', '2')); $this->assertSame(array('', 2), $form->getData()); $this->assertTrue($form[0]->getData()); @@ -439,7 +439,7 @@ public function testBindMultipleExpandedWithEmptyChild() $this->assertSame('2', $form[2]->getViewData()); } - public function testBindMultipleExpandedObjectChoices() + public function testSubmitMultipleExpandedObjectChoices() { $form = $this->factory->create('choice', null, array( 'multiple' => true, @@ -455,7 +455,7 @@ public function testBindMultipleExpandedObjectChoices() ), )); - $form->bind(array('1', '2')); + $form->submit(array('1', '2')); $this->assertSame(array($this->objectChoices[0], $this->objectChoices[1]), $form->getData()); $this->assertTrue($form[0]->getData()); @@ -470,7 +470,7 @@ public function testBindMultipleExpandedObjectChoices() $this->assertNull($form[4]->getViewData()); } - public function testBindMultipleExpandedNumericChoices() + public function testSubmitMultipleExpandedNumericChoices() { $form = $this->factory->create('choice', null, array( 'multiple' => true, @@ -478,7 +478,7 @@ public function testBindMultipleExpandedNumericChoices() 'choices' => $this->numericChoices, )); - $form->bind(array('1', '2')); + $form->submit(array('1', '2')); $this->assertSame(array(1, 2), $form->getData()); $this->assertFalse($form[0]->getData()); diff --git a/Tests/Extension/Core/Type/CollectionTypeTest.php b/Tests/Extension/Core/Type/CollectionTypeTest.php index 5a4974ac50..be3ad9db5c 100644 --- a/Tests/Extension/Core/Type/CollectionTypeTest.php +++ b/Tests/Extension/Core/Type/CollectionTypeTest.php @@ -59,13 +59,13 @@ public function testThrowsExceptionIfObjectIsNotTraversable() $form->setData(new \stdClass()); } - public function testNotResizedIfBoundWithMissingData() + public function testNotResizedIfSubmittedWithMissingData() { $form = $this->factory->create('collection', null, array( 'type' => 'text', )); $form->setData(array('foo@foo.com', 'bar@bar.com')); - $form->bind(array('foo@bar.com')); + $form->submit(array('foo@bar.com')); $this->assertTrue($form->has('0')); $this->assertTrue($form->has('1')); @@ -73,14 +73,14 @@ public function testNotResizedIfBoundWithMissingData() $this->assertEquals('', $form[1]->getData()); } - public function testResizedDownIfBoundWithMissingDataAndAllowDelete() + public function testResizedDownIfSubmittedWithMissingDataAndAllowDelete() { $form = $this->factory->create('collection', null, array( 'type' => 'text', 'allow_delete' => true, )); $form->setData(array('foo@foo.com', 'bar@bar.com')); - $form->bind(array('foo@foo.com')); + $form->submit(array('foo@foo.com')); $this->assertTrue($form->has('0')); $this->assertFalse($form->has('1')); @@ -88,27 +88,27 @@ public function testResizedDownIfBoundWithMissingDataAndAllowDelete() $this->assertEquals(array('foo@foo.com'), $form->getData()); } - public function testNotResizedIfBoundWithExtraData() + public function testNotResizedIfSubmittedWithExtraData() { $form = $this->factory->create('collection', null, array( 'type' => 'text', )); $form->setData(array('foo@bar.com')); - $form->bind(array('foo@foo.com', 'bar@bar.com')); + $form->submit(array('foo@foo.com', 'bar@bar.com')); $this->assertTrue($form->has('0')); $this->assertFalse($form->has('1')); $this->assertEquals('foo@foo.com', $form[0]->getData()); } - public function testResizedUpIfBoundWithExtraDataAndAllowAdd() + public function testResizedUpIfSubmittedWithExtraDataAndAllowAdd() { $form = $this->factory->create('collection', null, array( 'type' => 'text', 'allow_add' => true, )); $form->setData(array('foo@bar.com')); - $form->bind(array('foo@bar.com', 'bar@bar.com')); + $form->submit(array('foo@bar.com', 'bar@bar.com')); $this->assertTrue($form->has('0')); $this->assertTrue($form->has('1')); diff --git a/Tests/Extension/Core/Type/DateTimeTypeTest.php b/Tests/Extension/Core/Type/DateTimeTypeTest.php index 4e62da5b9f..b9c1ebad38 100644 --- a/Tests/Extension/Core/Type/DateTimeTypeTest.php +++ b/Tests/Extension/Core/Type/DateTimeTypeTest.php @@ -33,7 +33,7 @@ public function testSubmitDateTime() 'input' => 'datetime', )); - $form->bind(array( + $form->submit(array( 'date' => array( 'day' => '2', 'month' => '6', @@ -60,7 +60,7 @@ public function testSubmitString() 'time_widget' => 'choice', )); - $form->bind(array( + $form->submit(array( 'date' => array( 'day' => '2', 'month' => '6', @@ -85,7 +85,7 @@ public function testSubmitTimestamp() 'time_widget' => 'choice', )); - $form->bind(array( + $form->submit(array( 'date' => array( 'day' => '2', 'month' => '6', @@ -126,7 +126,7 @@ public function testSubmitWithoutMinutes() ), ); - $form->bind($input); + $form->submit($input); $this->assertDateTimeEquals(new \DateTime('2010-06-02 03:00:00 UTC'), $form->getData()); } @@ -157,7 +157,7 @@ public function testSubmitWithSeconds() ), ); - $form->bind($input); + $form->submit($input); $this->assertDateTimeEquals(new \DateTime('2010-06-02 03:04:05 UTC'), $form->getData()); } @@ -175,7 +175,7 @@ public function testSubmitDifferentTimezones() $dateTime = new \DateTime('2010-06-02 03:04:05 Pacific/Tahiti'); - $form->bind(array( + $form->submit(array( 'date' => array( 'day' => (int) $dateTime->format('d'), 'month' => (int) $dateTime->format('m'), @@ -204,7 +204,7 @@ public function testSubmitDifferentTimezonesDateTime() $outputTime = new \DateTime('2010-06-02 03:04:00 Pacific/Tahiti'); - $form->bind('2010-06-02T03:04:00-10:00'); + $form->submit('2010-06-02T03:04:00-10:00'); $outputTime->setTimezone(new \DateTimeZone('America/New_York')); @@ -221,7 +221,7 @@ public function testSubmitStringSingleText() 'widget' => 'single_text', )); - $form->bind('2010-06-02T03:04:00Z'); + $form->submit('2010-06-02T03:04:00Z'); $this->assertEquals('2010-06-02 03:04:00', $form->getData()); $this->assertEquals('2010-06-02T03:04:00Z', $form->getViewData()); @@ -237,7 +237,7 @@ public function testSubmitStringSingleTextWithSeconds() 'with_seconds' => true, )); - $form->bind('2010-06-02T03:04:05Z'); + $form->submit('2010-06-02T03:04:05Z'); $this->assertEquals('2010-06-02 03:04:05', $form->getData()); $this->assertEquals('2010-06-02T03:04:05Z', $form->getViewData()); @@ -254,7 +254,7 @@ public function testSubmitDifferentPattern() $dateTime = new \DateTime('2010-06-02 03:04'); - $form->bind(array( + $form->submit(array( 'date' => '06*2010*02', 'time' => '03:04', )); diff --git a/Tests/Extension/Core/Type/DateTypeTest.php b/Tests/Extension/Core/Type/DateTypeTest.php index abef0b18ba..da6b4657fa 100644 --- a/Tests/Extension/Core/Type/DateTypeTest.php +++ b/Tests/Extension/Core/Type/DateTypeTest.php @@ -56,7 +56,7 @@ public function testSubmitFromSingleTextDateTimeWithDefaultFormat() 'input' => 'datetime', )); - $form->bind('2010-06-02'); + $form->submit('2010-06-02'); $this->assertDateTimeEquals(new \DateTime('2010-06-02 UTC'), $form->getData()); $this->assertEquals('2010-06-02', $form->getViewData()); @@ -72,7 +72,7 @@ public function testSubmitFromSingleTextDateTime() 'input' => 'datetime', )); - $form->bind('2.6.2010'); + $form->submit('2.6.2010'); $this->assertDateTimeEquals(new \DateTime('2010-06-02 UTC'), $form->getData()); $this->assertEquals('02.06.2010', $form->getViewData()); @@ -88,7 +88,7 @@ public function testSubmitFromSingleTextString() 'input' => 'string', )); - $form->bind('2.6.2010'); + $form->submit('2.6.2010'); $this->assertEquals('2010-06-02', $form->getData()); $this->assertEquals('02.06.2010', $form->getViewData()); @@ -104,7 +104,7 @@ public function testSubmitFromSingleTextTimestamp() 'input' => 'timestamp', )); - $form->bind('2.6.2010'); + $form->submit('2.6.2010'); $dateTime = new \DateTime('2010-06-02 UTC'); @@ -122,7 +122,7 @@ public function testSubmitFromSingleTextRaw() 'input' => 'array', )); - $form->bind('2.6.2010'); + $form->submit('2.6.2010'); $output = array( 'day' => '2', @@ -148,7 +148,7 @@ public function testSubmitFromText() 'year' => '2010', ); - $form->bind($text); + $form->submit($text); $dateTime = new \DateTime('2010-06-02 UTC'); @@ -170,7 +170,7 @@ public function testSubmitFromChoice() 'year' => '2010', ); - $form->bind($text); + $form->submit($text); $dateTime = new \DateTime('2010-06-02 UTC'); @@ -193,7 +193,7 @@ public function testSubmitFromChoiceEmpty() 'year' => '', ); - $form->bind($text); + $form->submit($text); $this->assertNull($form->getData()); $this->assertEquals($text, $form->getViewData()); @@ -209,7 +209,7 @@ public function testSubmitFromInputDateTimeDifferentPattern() 'input' => 'datetime', )); - $form->bind('06*2010*02'); + $form->submit('06*2010*02'); $this->assertDateTimeEquals(new \DateTime('2010-06-02 UTC'), $form->getData()); $this->assertEquals('06*2010*02', $form->getViewData()); @@ -225,7 +225,7 @@ public function testSubmitFromInputStringDifferentPattern() 'input' => 'string', )); - $form->bind('06*2010*02'); + $form->submit('06*2010*02'); $this->assertEquals('2010-06-02', $form->getData()); $this->assertEquals('06*2010*02', $form->getViewData()); @@ -241,7 +241,7 @@ public function testSubmitFromInputTimestampDifferentPattern() 'input' => 'timestamp', )); - $form->bind('06*2010*02'); + $form->submit('06*2010*02'); $dateTime = new \DateTime('2010-06-02 UTC'); @@ -259,7 +259,7 @@ public function testSubmitFromInputRawDifferentPattern() 'input' => 'array', )); - $form->bind('06*2010*02'); + $form->submit('06*2010*02'); $output = array( 'day' => '2', @@ -447,7 +447,7 @@ public function testIsPartiallyFilledReturnsFalseIfSingleText() 'widget' => 'single_text', )); - $form->bind('7.6.2010'); + $form->submit('7.6.2010'); $this->assertFalse($form->isPartiallyFilled()); } @@ -462,7 +462,7 @@ public function testIsPartiallyFilledReturnsFalseIfChoiceAndCompletelyEmpty() 'widget' => 'choice', )); - $form->bind(array( + $form->submit(array( 'day' => '', 'month' => '', 'year' => '', @@ -481,7 +481,7 @@ public function testIsPartiallyFilledReturnsFalseIfChoiceAndCompletelyFilled() 'widget' => 'choice', )); - $form->bind(array( + $form->submit(array( 'day' => '2', 'month' => '6', 'year' => '2010', @@ -500,7 +500,7 @@ public function testIsPartiallyFilledReturnsTrueIfChoiceAndDayEmpty() 'widget' => 'choice', )); - $form->bind(array( + $form->submit(array( 'day' => '', 'month' => '6', 'year' => '2010', diff --git a/Tests/Extension/Core/Type/FileTypeTest.php b/Tests/Extension/Core/Type/FileTypeTest.php index c25c53fc69..63556eb5a6 100644 --- a/Tests/Extension/Core/Type/FileTypeTest.php +++ b/Tests/Extension/Core/Type/FileTypeTest.php @@ -24,22 +24,22 @@ public function testSetData() $this->assertSame($data, $form->getData()); } - public function testBind() + public function testSubmit() { $form = $this->factory->createBuilder('file')->getForm(); $data = $this->createUploadedFileMock('abcdef', 'original.jpg', true); - $form->bind($data); + $form->submit($data); $this->assertSame($data, $form->getData()); } // https://github.com/symfony/symfony/issues/6134 - public function testBindEmpty() + public function testSubmitEmpty() { $form = $this->factory->createBuilder('file')->getForm(); - $form->bind(null); + $form->submit(null); $this->assertNull($form->getData()); } @@ -47,7 +47,7 @@ public function testBindEmpty() public function testDontPassValueToView() { $form = $this->factory->create('file'); - $form->bind(array( + $form->submit(array( 'file' => $this->createUploadedFileMock('abcdef', 'original.jpg', true), )); $view = $form->createView(); diff --git a/Tests/Extension/Core/Type/FormTypeTest.php b/Tests/Extension/Core/Type/FormTypeTest.php index f6663d6b65..3bc648a3d8 100644 --- a/Tests/Extension/Core/Type/FormTypeTest.php +++ b/Tests/Extension/Core/Type/FormTypeTest.php @@ -68,7 +68,7 @@ public function testPassRequiredAsOption() $this->assertTrue($form->isRequired()); } - public function testBoundDataIsTrimmedBeforeTransforming() + public function testSubmittedDataIsTrimmedBeforeTransforming() { $form = $this->factory->createBuilder('form') ->addViewTransformer(new FixedDataTransformer(array( @@ -78,13 +78,13 @@ public function testBoundDataIsTrimmedBeforeTransforming() ->setCompound(false) ->getForm(); - $form->bind(' a '); + $form->submit(' a '); $this->assertEquals('a', $form->getViewData()); $this->assertEquals('reverse[a]', $form->getData()); } - public function testBoundDataIsNotTrimmedBeforeTransformingIfNoTrimming() + public function testSubmittedDataIsNotTrimmedBeforeTransformingIfNoTrimming() { $form = $this->factory->createBuilder('form', null, array('trim' => false)) ->addViewTransformer(new FixedDataTransformer(array( @@ -94,7 +94,7 @@ public function testBoundDataIsNotTrimmedBeforeTransformingIfNoTrimming() ->setCompound(false) ->getForm(); - $form->bind(' a '); + $form->submit(' a '); $this->assertEquals(' a ', $form->getViewData()); $this->assertEquals('reverse[ a ]', $form->getData()); @@ -135,7 +135,7 @@ public function testPassMaxLengthToView() $this->assertSame(10, $view->vars['max_length']); } - public function testBindWithEmptyDataCreatesObjectIfClassAvailable() + public function testSubmitWithEmptyDataCreatesObjectIfClassAvailable() { $form = $this->factory->create('form', null, array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', @@ -146,7 +146,7 @@ public function testBindWithEmptyDataCreatesObjectIfClassAvailable() $form->setData(null); // partially empty, still an object is created - $form->bind(array('firstName' => 'Bernhard', 'lastName' => '')); + $form->submit(array('firstName' => 'Bernhard', 'lastName' => '')); $author = new Author(); $author->firstName = 'Bernhard'; @@ -155,7 +155,7 @@ public function testBindWithEmptyDataCreatesObjectIfClassAvailable() $this->assertEquals($author, $form->getData()); } - public function testBindWithEmptyDataCreatesObjectIfInitiallyBoundWithObject() + public function testSubmitWithEmptyDataCreatesObjectIfInitiallySubmittedWithObject() { $form = $this->factory->create('form', null, array( // data class is inferred from the passed object @@ -167,7 +167,7 @@ public function testBindWithEmptyDataCreatesObjectIfInitiallyBoundWithObject() $form->setData(null); // partially empty, still an object is created - $form->bind(array('firstName' => 'Bernhard', 'lastName' => '')); + $form->submit(array('firstName' => 'Bernhard', 'lastName' => '')); $author = new Author(); $author->firstName = 'Bernhard'; @@ -176,7 +176,7 @@ public function testBindWithEmptyDataCreatesObjectIfInitiallyBoundWithObject() $this->assertEquals($author, $form->getData()); } - public function testBindWithEmptyDataCreatesArrayIfDataClassIsNull() + public function testSubmitWithEmptyDataCreatesArrayIfDataClassIsNull() { $form = $this->factory->create('form', null, array( 'data_class' => null, @@ -185,12 +185,12 @@ public function testBindWithEmptyDataCreatesArrayIfDataClassIsNull() $form->add($this->factory->createNamed('firstName', 'text')); $form->setData(null); - $form->bind(array('firstName' => 'Bernhard')); + $form->submit(array('firstName' => 'Bernhard')); $this->assertSame(array('firstName' => 'Bernhard'), $form->getData()); } - public function testBindEmptyWithEmptyDataCreatesNoObjectIfNotRequired() + public function testSubmitEmptyWithEmptyDataCreatesNoObjectIfNotRequired() { $form = $this->factory->create('form', null, array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', @@ -200,12 +200,12 @@ public function testBindEmptyWithEmptyDataCreatesNoObjectIfNotRequired() $form->add($this->factory->createNamed('lastName', 'text')); $form->setData(null); - $form->bind(array('firstName' => '', 'lastName' => '')); + $form->submit(array('firstName' => '', 'lastName' => '')); $this->assertNull($form->getData()); } - public function testBindEmptyWithEmptyDataCreatesObjectIfRequired() + public function testSubmitEmptyWithEmptyDataCreatesObjectIfRequired() { $form = $this->factory->create('form', null, array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', @@ -215,7 +215,7 @@ public function testBindEmptyWithEmptyDataCreatesObjectIfRequired() $form->add($this->factory->createNamed('lastName', 'text')); $form->setData(null); - $form->bind(array('firstName' => '', 'lastName' => '')); + $form->submit(array('firstName' => '', 'lastName' => '')); $this->assertEquals(new Author(), $form->getData()); } @@ -223,35 +223,35 @@ public function testBindEmptyWithEmptyDataCreatesObjectIfRequired() /* * We need something to write the field values into */ - public function testBindWithEmptyDataStoresArrayIfNoClassAvailable() + public function testSubmitWithEmptyDataStoresArrayIfNoClassAvailable() { $form = $this->factory->create('form'); $form->add($this->factory->createNamed('firstName', 'text')); $form->setData(null); - $form->bind(array('firstName' => 'Bernhard')); + $form->submit(array('firstName' => 'Bernhard')); $this->assertSame(array('firstName' => 'Bernhard'), $form->getData()); } - public function testBindWithEmptyDataPassesEmptyStringToTransformerIfNotCompound() + public function testSubmitWithEmptyDataPassesEmptyStringToTransformerIfNotCompound() { $form = $this->factory->createBuilder('form') ->addViewTransformer(new FixedDataTransformer(array( // required for the initial, internal setData(null) null => 'null', - // required to test that bind(null) is converted to '' + // required to test that submit(null) is converted to '' 'empty' => '', ))) ->setCompound(false) ->getForm(); - $form->bind(null); + $form->submit(null); $this->assertSame('empty', $form->getData()); } - public function testBindWithEmptyDataUsesEmptyDataOption() + public function testSubmitWithEmptyDataUsesEmptyDataOption() { $author = new Author(); @@ -261,7 +261,7 @@ public function testBindWithEmptyDataUsesEmptyDataOption() )); $form->add($this->factory->createNamed('firstName', 'text')); - $form->bind(array('firstName' => 'Bernhard')); + $form->submit(array('firstName' => 'Bernhard')); $this->assertSame($author, $form->getData()); $this->assertEquals('Bernhard', $author->firstName); @@ -320,7 +320,7 @@ public function testSubformDoesntCallSetters() $builder->get('reference')->add('firstName', 'text'); $form = $builder->getForm(); - $form->bind(array( + $form->submit(array( // reference has a getter, but not setter 'reference' => array( 'firstName' => 'Foo', @@ -345,7 +345,7 @@ public function testSubformCallsSettersIfTheObjectChanged() $form['referenceCopy']->setData($newReference); // new author object - $form->bind(array( + $form->submit(array( // referenceCopy has a getter that returns a copy 'referenceCopy' => array( 'firstName' => 'Foo', @@ -367,7 +367,7 @@ public function testSubformCallsSettersIfByReferenceIsFalse() $builder->get('referenceCopy')->add('firstName', 'text'); $form = $builder->getForm(); - $form->bind(array( + $form->submit(array( // referenceCopy has a getter that returns a copy 'referenceCopy' => array( 'firstName' => 'Foo', @@ -393,7 +393,7 @@ function ($value) { // reverseTransform )); $form = $builder->getForm(); - $form->bind(array( + $form->submit(array( 'referenceCopy' => array(), // doesn't matter actually )); @@ -419,7 +419,7 @@ function ($value) use ($ref2) { // reverseTransform )); $form = $builder->getForm(); - $form->bind(array( + $form->submit(array( 'referenceCopy' => array('a' => 'b'), // doesn't matter actually )); @@ -506,17 +506,17 @@ public function testNotMapped() $this->assertFalse($form->getConfig()->getMapped()); } - public function testViewValidUnbound() + public function testViewValidNotSubmitted() { $form = $this->factory->create('form'); $view = $form->createView(); $this->assertTrue($view->vars['valid']); } - public function testViewNotValidBound() + public function testViewNotValidSubmitted() { $form = $this->factory->create('form'); - $form->bind(array()); + $form->submit(array()); $form->addError(new FormError('An error')); $view = $form->createView(); $this->assertFalse($view->vars['valid']); diff --git a/Tests/Extension/Core/Type/IntegerTypeTest.php b/Tests/Extension/Core/Type/IntegerTypeTest.php index d16cc867b5..998bbe0120 100644 --- a/Tests/Extension/Core/Type/IntegerTypeTest.php +++ b/Tests/Extension/Core/Type/IntegerTypeTest.php @@ -26,7 +26,7 @@ public function testSubmitCastsToInteger() { $form = $this->factory->create('integer'); - $form->bind('1.678'); + $form->submit('1.678'); $this->assertSame(1, $form->getData()); $this->assertSame('1', $form->getViewData()); diff --git a/Tests/Extension/Core/Type/PasswordTypeTest.php b/Tests/Extension/Core/Type/PasswordTypeTest.php index a67564b987..bccb6f7b77 100644 --- a/Tests/Extension/Core/Type/PasswordTypeTest.php +++ b/Tests/Extension/Core/Type/PasswordTypeTest.php @@ -13,7 +13,7 @@ class PasswordTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { - public function testEmptyIfNotBound() + public function testEmptyIfNotSubmitted() { $form = $this->factory->create('password'); $form->setData('pAs5w0rd'); @@ -22,19 +22,19 @@ public function testEmptyIfNotBound() $this->assertSame('', $view->vars['value']); } - public function testEmptyIfBound() + public function testEmptyIfSubmitted() { $form = $this->factory->create('password'); - $form->bind('pAs5w0rd'); + $form->submit('pAs5w0rd'); $view = $form->createView(); $this->assertSame('', $view->vars['value']); } - public function testNotEmptyIfBoundAndNotAlwaysEmpty() + public function testNotEmptyIfSubmittedAndNotAlwaysEmpty() { $form = $this->factory->create('password', null, array('always_empty' => false)); - $form->bind('pAs5w0rd'); + $form->submit('pAs5w0rd'); $view = $form->createView(); $this->assertSame('pAs5w0rd', $view->vars['value']); @@ -43,7 +43,7 @@ public function testNotEmptyIfBoundAndNotAlwaysEmpty() public function testNotTrimmed() { $form = $this->factory->create('password', null); - $form->bind(' pAs5w0rd '); + $form->submit(' pAs5w0rd '); $data = $form->getData(); $this->assertSame(' pAs5w0rd ', $data); diff --git a/Tests/Extension/Core/Type/RepeatedTypeTest.php b/Tests/Extension/Core/Type/RepeatedTypeTest.php index 80fa9f045a..9e125d781b 100644 --- a/Tests/Extension/Core/Type/RepeatedTypeTest.php +++ b/Tests/Extension/Core/Type/RepeatedTypeTest.php @@ -125,7 +125,7 @@ public function testSubmitUnequal() { $input = array('first' => 'foo', 'second' => 'bar'); - $this->form->bind($input); + $this->form->submit($input); $this->assertEquals('foo', $this->form['first']->getViewData()); $this->assertEquals('bar', $this->form['second']->getViewData()); @@ -138,7 +138,7 @@ public function testSubmitEqual() { $input = array('first' => 'foo', 'second' => 'foo'); - $this->form->bind($input); + $this->form->submit($input); $this->assertEquals('foo', $this->form['first']->getViewData()); $this->assertEquals('foo', $this->form['second']->getViewData()); diff --git a/Tests/Extension/Core/Type/SubmitTypeTest.php b/Tests/Extension/Core/Type/SubmitTypeTest.php index b85d72f568..8cc72281b2 100644 --- a/Tests/Extension/Core/Type/SubmitTypeTest.php +++ b/Tests/Extension/Core/Type/SubmitTypeTest.php @@ -28,26 +28,26 @@ public function testNotClickedByDefault() $this->assertFalse($button->isClicked()); } - public function testNotClickedIfBoundWithNull() + public function testNotClickedIfSubmittedWithNull() { $button = $this->factory->create('submit'); - $button->bind(null); + $button->submit(null); $this->assertFalse($button->isClicked()); } - public function testClickedIfBoundWithEmptyString() + public function testClickedIfSubmittedWithEmptyString() { $button = $this->factory->create('submit'); - $button->bind(''); + $button->submit(''); $this->assertTrue($button->isClicked()); } - public function testClickedIfBoundWithUnemptyString() + public function testClickedIfSubmittedWithUnemptyString() { $button = $this->factory->create('submit'); - $button->bind('foo'); + $button->submit('foo'); $this->assertTrue($button->isClicked()); } diff --git a/Tests/Extension/Core/Type/TimeTypeTest.php b/Tests/Extension/Core/Type/TimeTypeTest.php index d7f429b580..9bdfe1567b 100644 --- a/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/Tests/Extension/Core/Type/TimeTypeTest.php @@ -37,7 +37,7 @@ public function testSubmitDateTime() 'minute' => '4', ); - $form->bind($input); + $form->submit($input); $dateTime = new \DateTime('1970-01-01 03:04:00 UTC'); @@ -58,7 +58,7 @@ public function testSubmitString() 'minute' => '4', ); - $form->bind($input); + $form->submit($input); $this->assertEquals('03:04:00', $form->getData()); $this->assertEquals($input, $form->getViewData()); @@ -77,7 +77,7 @@ public function testSubmitTimestamp() 'minute' => '4', ); - $form->bind($input); + $form->submit($input); $dateTime = new \DateTime('1970-01-01 03:04:00 UTC'); @@ -98,7 +98,7 @@ public function testSubmitArray() 'minute' => '4', ); - $form->bind($input); + $form->submit($input); $this->assertEquals($input, $form->getData()); $this->assertEquals($input, $form->getViewData()); @@ -113,7 +113,7 @@ public function testSubmitDatetimeSingleText() 'widget' => 'single_text', )); - $form->bind('03:04'); + $form->submit('03:04'); $this->assertEquals(new \DateTime('1970-01-01 03:04:00 UTC'), $form->getData()); $this->assertEquals('03:04', $form->getViewData()); @@ -129,7 +129,7 @@ public function testSubmitDatetimeSingleTextWithoutMinutes() 'with_minutes' => false, )); - $form->bind('03'); + $form->submit('03'); $this->assertEquals(new \DateTime('1970-01-01 03:00:00 UTC'), $form->getData()); $this->assertEquals('03', $form->getViewData()); @@ -149,7 +149,7 @@ public function testSubmitArraySingleText() 'minute' => '4', ); - $form->bind('03:04'); + $form->submit('03:04'); $this->assertEquals($data, $form->getData()); $this->assertEquals('03:04', $form->getViewData()); @@ -169,7 +169,7 @@ public function testSubmitArraySingleTextWithoutMinutes() 'hour' => '3', ); - $form->bind('03'); + $form->submit('03'); $this->assertEquals($data, $form->getData()); $this->assertEquals('03', $form->getViewData()); @@ -191,7 +191,7 @@ public function testSubmitArraySingleTextWithSeconds() 'second' => '5', ); - $form->bind('03:04:05'); + $form->submit('03:04:05'); $this->assertEquals($data, $form->getData()); $this->assertEquals('03:04:05', $form->getViewData()); @@ -206,7 +206,7 @@ public function testSubmitStringSingleText() 'widget' => 'single_text', )); - $form->bind('03:04'); + $form->submit('03:04'); $this->assertEquals('03:04:00', $form->getData()); $this->assertEquals('03:04', $form->getViewData()); @@ -222,7 +222,7 @@ public function testSubmitStringSingleTextWithoutMinutes() 'with_minutes' => false, )); - $form->bind('03'); + $form->submit('03'); $this->assertEquals('03:00:00', $form->getData()); $this->assertEquals('03', $form->getViewData()); @@ -360,7 +360,7 @@ public function testIsPartiallyFilledReturnsFalseIfCompletelyEmpty() 'widget' => 'choice', )); - $form->bind(array( + $form->submit(array( 'hour' => '', 'minute' => '', )); @@ -377,7 +377,7 @@ public function testIsPartiallyFilledReturnsFalseIfCompletelyEmptyWithSeconds() 'with_seconds' => true, )); - $form->bind(array( + $form->submit(array( 'hour' => '', 'minute' => '', 'second' => '', @@ -394,7 +394,7 @@ public function testIsPartiallyFilledReturnsFalseIfCompletelyFilled() 'widget' => 'choice', )); - $form->bind(array( + $form->submit(array( 'hour' => '0', 'minute' => '0', )); @@ -411,7 +411,7 @@ public function testIsPartiallyFilledReturnsFalseIfCompletelyFilledWithSeconds() 'with_seconds' => true, )); - $form->bind(array( + $form->submit(array( 'hour' => '0', 'minute' => '0', 'second' => '0', @@ -429,7 +429,7 @@ public function testIsPartiallyFilledReturnsTrueIfChoiceAndHourEmpty() 'with_seconds' => true, )); - $form->bind(array( + $form->submit(array( 'hour' => '', 'minute' => '0', 'second' => '0', @@ -447,7 +447,7 @@ public function testIsPartiallyFilledReturnsTrueIfChoiceAndMinuteEmpty() 'with_seconds' => true, )); - $form->bind(array( + $form->submit(array( 'hour' => '0', 'minute' => '', 'second' => '0', @@ -465,7 +465,7 @@ public function testIsPartiallyFilledReturnsTrueIfChoiceAndSecondsEmpty() 'with_seconds' => true, )); - $form->bind(array( + $form->submit(array( 'hour' => '0', 'minute' => '0', 'second' => '', diff --git a/Tests/Extension/Core/Type/UrlTypeTest.php b/Tests/Extension/Core/Type/UrlTypeTest.php index 0782528884..254b2a8e4e 100644 --- a/Tests/Extension/Core/Type/UrlTypeTest.php +++ b/Tests/Extension/Core/Type/UrlTypeTest.php @@ -17,7 +17,7 @@ public function testSubmitAddsDefaultProtocolIfNoneIsIncluded() { $form = $this->factory->create('url', 'name'); - $form->bind('www.domain.com'); + $form->submit('www.domain.com'); $this->assertSame('http://www.domain.com', $form->getData()); $this->assertSame('http://www.domain.com', $form->getViewData()); @@ -29,7 +29,7 @@ public function testSubmitAddsNoDefaultProtocolIfAlreadyIncluded() 'default_protocol' => 'http', )); - $form->bind('ftp://www.domain.com'); + $form->submit('ftp://www.domain.com'); $this->assertSame('ftp://www.domain.com', $form->getData()); $this->assertSame('ftp://www.domain.com', $form->getViewData()); @@ -41,7 +41,7 @@ public function testSubmitAddsNoDefaultProtocolIfEmpty() 'default_protocol' => 'http', )); - $form->bind(''); + $form->submit(''); $this->assertNull($form->getData()); $this->assertSame('', $form->getViewData()); @@ -53,7 +53,7 @@ public function testSubmitAddsNoDefaultProtocolIfSetToNull() 'default_protocol' => null, )); - $form->bind('www.domain.com'); + $form->submit('www.domain.com'); $this->assertSame('www.domain.com', $form->getData()); $this->assertSame('www.domain.com', $form->getViewData()); diff --git a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php index 136ddbc1e0..33184c029d 100644 --- a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php +++ b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php @@ -70,7 +70,7 @@ public function testStringFormData() $event = new FormEvent($this->form, $data); $validation = new CsrfValidationListener('csrf', $this->csrfProvider, 'unknown'); - $validation->preBind($event); + $validation->preSubmit($event); // Validate accordingly $this->assertSame($data, $event->getData()); diff --git a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php index 8ee8988130..13b305fe4b 100644 --- a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php +++ b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php @@ -140,7 +140,7 @@ public function provideBoolean() /** * @dataProvider provideBoolean */ - public function testValidateTokenOnBindIfRootAndCompound($valid) + public function testValidateTokenOnSubmitIfRootAndCompound($valid) { $this->csrfProvider->expects($this->once()) ->method('isCsrfTokenValid') @@ -157,7 +157,7 @@ public function testValidateTokenOnBindIfRootAndCompound($valid) ->add('child', 'text') ->getForm(); - $form->bind(array( + $form->submit(array( 'child' => 'foobar', 'csrf' => 'token', )); @@ -184,7 +184,7 @@ public function testFailIfRootAndCompoundAndTokenMissing() ->add('child', 'text') ->getForm(); - $form->bind(array( + $form->submit(array( 'child' => 'foobar', // token is missing )); @@ -214,7 +214,7 @@ public function testDontValidateTokenIfCompoundButNoRoot() ->getForm() ->get('form'); - $form->bind(array( + $form->submit(array( 'child' => 'foobar', 'csrf' => 'token', )); @@ -233,7 +233,7 @@ public function testDontValidateTokenIfRootButNotCompound() 'compound' => false, )); - $form->bind(array( + $form->submit(array( 'csrf' => 'token', )); } diff --git a/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php b/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php index 0c534fd0be..2ff072b2eb 100644 --- a/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php +++ b/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php @@ -84,7 +84,7 @@ public function requestMethodProvider() /** * @dataProvider requestMethodProvider */ - public function testBindRequest($method) + public function testSubmitRequest($method) { if (!class_exists('Symfony\Component\HttpFoundation\Request')) { $this->markTestSkipped('The "HttpFoundation" component is not available'); @@ -113,7 +113,7 @@ public function testBindRequest($method) /** * @dataProvider requestMethodProvider */ - public function testBindRequestWithEmptyName($method) + public function testSubmitRequestWithEmptyName($method) { if (!class_exists('Symfony\Component\HttpFoundation\Request')) { $this->markTestSkipped('The "HttpFoundation" component is not available'); @@ -140,7 +140,7 @@ public function testBindRequestWithEmptyName($method) /** * @dataProvider requestMethodProvider */ - public function testBindEmptyRequestToCompoundForm($method) + public function testSubmitEmptyRequestToCompoundForm($method) { if (!class_exists('Symfony\Component\HttpFoundation\Request')) { $this->markTestSkipped('The "HttpFoundation" component is not available'); @@ -167,7 +167,7 @@ public function testBindEmptyRequestToCompoundForm($method) /** * @dataProvider requestMethodProvider */ - public function testBindEmptyRequestToSimpleForm($method) + public function testSubmitEmptyRequestToSimpleForm($method) { if (!class_exists('Symfony\Component\HttpFoundation\Request')) { $this->markTestSkipped('The "HttpFoundation" component is not available'); @@ -190,7 +190,7 @@ public function testBindEmptyRequestToSimpleForm($method) $this->assertNull($event->getData()); } - public function testBindGetRequest() + public function testSubmitGetRequest() { if (!class_exists('Symfony\Component\HttpFoundation\Request')) { $this->markTestSkipped('The "HttpFoundation" component is not available'); @@ -215,7 +215,7 @@ public function testBindGetRequest() ), $event->getData()); } - public function testBindGetRequestWithEmptyName() + public function testSubmitGetRequestWithEmptyName() { if (!class_exists('Symfony\Component\HttpFoundation\Request')) { $this->markTestSkipped('The "HttpFoundation" component is not available'); @@ -239,7 +239,7 @@ public function testBindGetRequestWithEmptyName() ), $event->getData()); } - public function testBindEmptyGetRequestToCompoundForm() + public function testSubmitEmptyGetRequestToCompoundForm() { if (!class_exists('Symfony\Component\HttpFoundation\Request')) { $this->markTestSkipped('The "HttpFoundation" component is not available'); @@ -262,7 +262,7 @@ public function testBindEmptyGetRequestToCompoundForm() $this->assertEquals(array(), $event->getData()); } - public function testBindEmptyGetRequestToSimpleForm() + public function testSubmitEmptyGetRequestToSimpleForm() { if (!class_exists('Symfony\Component\HttpFoundation\Request')) { $this->markTestSkipped('The "HttpFoundation" component is not available'); diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index ce5035717d..dabeff1eb9 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -206,7 +206,7 @@ public function testDontValidateConstraintsIfNoValidationGroups() ->getForm(); // Launch transformer - $form->bind(array()); + $form->submit(array()); $context->expects($this->never()) ->method('validate'); @@ -235,7 +235,7 @@ function () { throw new TransformationFailedException(); } ->getForm(); // Launch transformer - $form->bind('foo'); + $form->submit('foo'); $context->expects($this->never()) ->method('validate'); @@ -275,7 +275,7 @@ function () { throw new TransformationFailedException(); } ->getForm(); // Launch transformer - $form->bind('foo'); + $form->submit('foo'); $context->expects($this->never()) ->method('validate'); @@ -314,7 +314,7 @@ function () { throw new TransformationFailedException(); } ->getForm(); // Launch transformer - $form->bind(array()); + $form->submit(array()); $context->expects($this->never()) ->method('validate'); @@ -346,7 +346,7 @@ function () { throw new TransformationFailedException(); } ->getForm(); // Launch transformer - $form->bind(array('child' => 'foo')); + $form->submit(array('child' => 'foo')); $context->expects($this->never()) ->method('addViolation'); @@ -582,7 +582,7 @@ public function testViolationIfExtraData() ->add($this->getBuilder('child')) ->getForm(); - $form->bind(array('foo' => 'bar')); + $form->submit(array('foo' => 'bar')); $context->expects($this->once()) ->method('addViolation') @@ -717,7 +717,7 @@ private function getSubmitButton($name = 'name', array $options = array()) private function getClickedSubmitButton($name = 'name', array $options = array()) { - return $this->getSubmitButton($name, $options)->bind(''); + return $this->getSubmitButton($name, $options)->submit(''); } /** diff --git a/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php b/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php index 094a26853b..6619410599 100644 --- a/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php +++ b/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php @@ -67,7 +67,7 @@ public function testValidationGroupsCanBeSetToClosure() $this->assertTrue(is_callable($form->getConfig()->getOption('validation_groups'))); } - public function testBindValidatesData() + public function testSubmitValidatesData() { $builder = $this->factory->createBuilder('form', null, array( 'validation_groups' => 'group', @@ -80,6 +80,6 @@ public function testBindValidatesData() ->with($this->equalTo($form)); // specific data is irrelevant - $form->bind(array()); + $form->submit(array()); } } diff --git a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php index cbe1acbe9c..c802ea7e80 100644 --- a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php +++ b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php @@ -173,8 +173,8 @@ public function testAbortMappingIfNotSynchronized() $parent->add($child); $child->add($grandChild); - // bind to invoke the transformer and mark the form unsynchronized - $parent->bind(array()); + // submit to invoke the transformer and mark the form unsynchronized + $parent->submit(array()); $this->mapper->mapViolation($violation, $parent); @@ -197,8 +197,8 @@ public function testAbortDotRuleMappingIfNotSynchronized() $parent->add($child); $child->add($grandChild); - // bind to invoke the transformer and mark the form unsynchronized - $parent->bind(array()); + // submit to invoke the transformer and mark the form unsynchronized + $parent->submit(array()); $this->mapper->mapViolation($violation, $parent); diff --git a/Tests/Fixtures/FixedFilterListener.php b/Tests/Fixtures/FixedFilterListener.php index 60f9ffdfb6..762a10b8c9 100644 --- a/Tests/Fixtures/FixedFilterListener.php +++ b/Tests/Fixtures/FixedFilterListener.php @@ -22,27 +22,27 @@ class FixedFilterListener implements EventSubscriberInterface public function __construct(array $mapping) { $this->mapping = array_merge(array( - 'preBind' => array(), - 'onBind' => array(), + 'preSubmit' => array(), + 'onSubmit' => array(), 'preSetData' => array(), ), $mapping); } - public function preBind(FormEvent $event) + public function preSubmit(FormEvent $event) { $data = $event->getData(); - if (isset($this->mapping['preBind'][$data])) { - $event->setData($this->mapping['preBind'][$data]); + if (isset($this->mapping['preSubmit'][$data])) { + $event->setData($this->mapping['preSubmit'][$data]); } } - public function onBind(FormEvent $event) + public function onSubmit(FormEvent $event) { $data = $event->getData(); - if (isset($this->mapping['onBind'][$data])) { - $event->setData($this->mapping['onBind'][$data]); + if (isset($this->mapping['onSubmit'][$data])) { + $event->setData($this->mapping['onSubmit'][$data]); } } @@ -58,8 +58,8 @@ public function preSetData(FormEvent $event) public static function getSubscribedEvents() { return array( - FormEvents::PRE_BIND => 'preBind', - FormEvents::BIND => 'onBind', + FormEvents::PRE_SUBMIT => 'preSubmit', + FormEvents::SUBMIT => 'onSubmit', FormEvents::PRE_SET_DATA => 'preSetData', ); } diff --git a/Tests/NativeRequestHandlerTest.php b/Tests/NativeRequestHandlerTest.php index 1a7bb0f9e4..9d3a997fec 100644 --- a/Tests/NativeRequestHandlerTest.php +++ b/Tests/NativeRequestHandlerTest.php @@ -67,7 +67,7 @@ public function testMethodOverrideHeaderTakesPrecedenceIfPost() $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'PUT'; $form->expects($this->once()) - ->method('bind') + ->method('submit') ->with('DATA'); $this->requestHandler->handleRequest($form, $this->request); @@ -86,7 +86,7 @@ public function testConvertEmptyUploadedFilesToNull() ))); $form->expects($this->once()) - ->method('bind') + ->method('submit') ->with($this->identicalTo(null)); $this->requestHandler->handleRequest($form, $this->request); @@ -115,7 +115,7 @@ public function testFixBuggyFilesArray() ))); $form->expects($this->once()) - ->method('bind') + ->method('submit') ->with(array( 'field' => array( 'name' => 'upload.txt', @@ -152,7 +152,7 @@ public function testFixBuggyNestedFilesArray() ))); $form->expects($this->once()) - ->method('bind') + ->method('submit') ->with(array( 'field' => array( 'subfield' => array( @@ -179,7 +179,7 @@ public function testMethodOverrideHeaderIgnoredIfNotPost() $_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'] = 'PUT'; $form->expects($this->never()) - ->method('bind'); + ->method('submit'); $this->requestHandler->handleRequest($form, $this->request); } diff --git a/Tests/SimpleFormTest.php b/Tests/SimpleFormTest.php index 09dea71d25..17a8fd7b13 100644 --- a/Tests/SimpleFormTest.php +++ b/Tests/SimpleFormTest.php @@ -75,47 +75,47 @@ public function testDataIsInitializedToConfiguredValue() } // https://github.com/symfony/symfony/commit/d4f4038f6daf7cf88ca7c7ab089473cce5ebf7d8#commitcomment-1632879 - public function testDataIsInitializedFromBind() + public function testDataIsInitializedFromSubmit() { $mock = $this->getMockBuilder('\stdClass') - ->setMethods(array('preSetData', 'preBind')) + ->setMethods(array('preSetData', 'preSubmit')) ->getMock(); $mock->expects($this->at(0)) ->method('preSetData'); $mock->expects($this->at(1)) - ->method('preBind'); + ->method('preSubmit'); $config = new FormConfigBuilder('name', null, $this->dispatcher); $config->addEventListener(FormEvents::PRE_SET_DATA, array($mock, 'preSetData')); - $config->addEventListener(FormEvents::PRE_BIND, array($mock, 'preBind')); + $config->addEventListener(FormEvents::PRE_SUBMIT, array($mock, 'preSubmit')); $form = new Form($config); // no call to setData() or similar where the object would be // initialized otherwise - $form->bind('foobar'); + $form->submit('foobar'); } /** - * @expectedException \Symfony\Component\Form\Exception\AlreadyBoundException + * @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException */ - public function testBindThrowsExceptionIfAlreadyBound() + public function testSubmitThrowsExceptionIfAlreadySubmitted() { - $this->form->bind(array()); - $this->form->bind(array()); + $this->form->submit(array()); + $this->form->submit(array()); } - public function testBindIsIgnoredIfDisabled() + public function testSubmitIsIgnoredIfDisabled() { $form = $this->getBuilder() ->setDisabled(true) ->setData('initial') ->getForm(); - $form->bind('new'); + $form->submit('new'); $this->assertEquals('initial', $form->getData()); - $this->assertTrue($form->isBound()); + $this->assertTrue($form->isSubmitted()); } public function testNeverRequiredIfParentNotRequired() @@ -259,23 +259,23 @@ public function testNotEmptyIfText() $this->assertFalse($this->form->isEmpty()); } - public function testValidIfBound() + public function testValidIfSubmitted() { $form = $this->getBuilder()->getForm(); - $form->bind('foobar'); + $form->submit('foobar'); $this->assertTrue($form->isValid()); } - public function testValidIfBoundAndDisabled() + public function testValidIfSubmittedAndDisabled() { $form = $this->getBuilder()->setDisabled(true)->getForm(); - $form->bind('foobar'); + $form->submit('foobar'); $this->assertTrue($form->isValid()); } - public function testNotValidIfNotBound() + public function testNotValidIfNotSubmitted() { $this->assertFalse($this->form->isValid()); } @@ -283,7 +283,7 @@ public function testNotValidIfNotBound() public function testNotValidIfErrors() { $form = $this->getBuilder()->getForm(); - $form->bind('foobar'); + $form->submit('foobar'); $form->addError(new FormError('Error!')); $this->assertFalse($form->isValid()); @@ -302,33 +302,33 @@ public function testHasNoErrors() } /** - * @expectedException \Symfony\Component\Form\Exception\AlreadyBoundException + * @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException */ - public function testSetParentThrowsExceptionIfAlreadyBound() + public function testSetParentThrowsExceptionIfAlreadySubmitted() { - $this->form->bind(array()); + $this->form->submit(array()); $this->form->setParent($this->getBuilder('parent')->getForm()); } - public function testBound() + public function testSubmitted() { $form = $this->getBuilder()->getForm(); - $form->bind('foobar'); + $form->submit('foobar'); - $this->assertTrue($form->isBound()); + $this->assertTrue($form->isSubmitted()); } - public function testNotBound() + public function testNotSubmitted() { - $this->assertFalse($this->form->isBound()); + $this->assertFalse($this->form->isSubmitted()); } /** - * @expectedException \Symfony\Component\Form\Exception\AlreadyBoundException + * @expectedException \Symfony\Component\Form\Exception\AlreadySubmittedException */ - public function testSetDataThrowsExceptionIfAlreadyBound() + public function testSetDataThrowsExceptionIfAlreadySubmitted() { - $this->form->bind(array()); + $this->form->submit(array()); $this->form->setData(null); } @@ -356,18 +356,18 @@ public function testSetDataExecutesTransformationChain() // use real event dispatcher now $form = $this->getBuilder('name', new EventDispatcher()) ->addEventSubscriber(new FixedFilterListener(array( - 'preSetData' => array( - 'app' => 'filtered', - ), - ))) + 'preSetData' => array( + 'app' => 'filtered', + ), + ))) ->addModelTransformer(new FixedDataTransformer(array( - '' => '', - 'filtered' => 'norm', - ))) + '' => '', + 'filtered' => 'norm', + ))) ->addViewTransformer(new FixedDataTransformer(array( - '' => '', - 'norm' => 'client', - ))) + '' => '', + 'norm' => 'client', + ))) ->getForm(); $form->setData('app'); @@ -381,13 +381,13 @@ public function testSetDataExecutesViewTransformersInOrder() { $form = $this->getBuilder() ->addViewTransformer(new FixedDataTransformer(array( - '' => '', - 'first' => 'second', - ))) + '' => '', + 'first' => 'second', + ))) ->addViewTransformer(new FixedDataTransformer(array( - '' => '', - 'second' => 'third', - ))) + '' => '', + 'second' => 'third', + ))) ->getForm(); $form->setData('first'); @@ -399,13 +399,13 @@ public function testSetDataExecutesModelTransformersInReverseOrder() { $form = $this->getBuilder() ->addModelTransformer(new FixedDataTransformer(array( - '' => '', - 'second' => 'third', - ))) + '' => '', + 'second' => 'third', + ))) ->addModelTransformer(new FixedDataTransformer(array( - '' => '', - 'first' => 'second', - ))) + '' => '', + 'first' => 'second', + ))) ->getForm(); $form->setData('first'); @@ -475,81 +475,81 @@ public function testSetDataIsIgnoredIfDataIsLocked() $this->assertSame('default', $form->getData()); } - public function testBindConvertsEmptyToNullIfNoTransformer() + public function testSubmitConvertsEmptyToNullIfNoTransformer() { $form = $this->getBuilder()->getForm(); - $form->bind(''); + $form->submit(''); $this->assertNull($form->getData()); $this->assertNull($form->getNormData()); $this->assertSame('', $form->getViewData()); } - public function testBindExecutesTransformationChain() + public function testSubmitExecutesTransformationChain() { // use real event dispatcher now $form = $this->getBuilder('name', new EventDispatcher()) ->addEventSubscriber(new FixedFilterListener(array( - 'preBind' => array( - 'client' => 'filteredclient', - ), - 'onBind' => array( - 'norm' => 'filterednorm', - ), - ))) + 'preSubmit' => array( + 'client' => 'filteredclient', + ), + 'onSubmit' => array( + 'norm' => 'filterednorm', + ), + ))) ->addViewTransformer(new FixedDataTransformer(array( - '' => '', - // direction is reversed! - 'norm' => 'filteredclient', - 'filterednorm' => 'cleanedclient' - ))) + '' => '', + // direction is reversed! + 'norm' => 'filteredclient', + 'filterednorm' => 'cleanedclient' + ))) ->addModelTransformer(new FixedDataTransformer(array( - '' => '', - // direction is reversed! - 'app' => 'filterednorm', - ))) + '' => '', + // direction is reversed! + 'app' => 'filterednorm', + ))) ->getForm(); - $form->bind('client'); + $form->submit('client'); $this->assertEquals('app', $form->getData()); $this->assertEquals('filterednorm', $form->getNormData()); $this->assertEquals('cleanedclient', $form->getViewData()); } - public function testBindExecutesViewTransformersInReverseOrder() + public function testSubmitExecutesViewTransformersInReverseOrder() { $form = $this->getBuilder() ->addViewTransformer(new FixedDataTransformer(array( - '' => '', - 'third' => 'second', - ))) + '' => '', + 'third' => 'second', + ))) ->addViewTransformer(new FixedDataTransformer(array( - '' => '', - 'second' => 'first', - ))) + '' => '', + 'second' => 'first', + ))) ->getForm(); - $form->bind('first'); + $form->submit('first'); $this->assertEquals('third', $form->getNormData()); } - public function testBindExecutesModelTransformersInOrder() + public function testSubmitExecutesModelTransformersInOrder() { $form = $this->getBuilder() ->addModelTransformer(new FixedDataTransformer(array( - '' => '', - 'second' => 'first', - ))) + '' => '', + 'second' => 'first', + ))) ->addModelTransformer(new FixedDataTransformer(array( - '' => '', - 'third' => 'second', - ))) + '' => '', + 'third' => 'second', + ))) ->getForm(); - $form->bind('first'); + $form->submit('first'); $this->assertEquals('third', $form->getData()); } @@ -559,9 +559,9 @@ public function testSynchronizedByDefault() $this->assertTrue($this->form->isSynchronized()); } - public function testSynchronizedAfterBinding() + public function testSynchronizedAfterSubmission() { - $this->form->bind('foobar'); + $this->form->submit('foobar'); $this->assertTrue($this->form->isSynchronized()); } @@ -577,7 +577,7 @@ public function testNotSynchronizedIfViewReverseTransformationFailed() ->addViewTransformer($transformer) ->getForm(); - $form->bind('foobar'); + $form->submit('foobar'); $this->assertFalse($form->isSynchronized()); } @@ -593,7 +593,7 @@ public function testNotSynchronizedIfModelReverseTransformationFailed() ->addModelTransformer($transformer) ->getForm(); - $form->bind('foobar'); + $form->submit('foobar'); $this->assertFalse($form->isSynchronized()); } @@ -609,7 +609,7 @@ public function testEmptyDataCreatedBeforeTransforming() ))) ->getForm(); - $form->bind(''); + $form->submit(''); $this->assertEquals('bar', $form->getData()); } @@ -632,15 +632,15 @@ public function testEmptyDataFromClosure() ))) ->getForm(); - $form->bind(''); + $form->submit(''); $this->assertEquals('bar', $form->getData()); } - public function testBindResetsErrors() + public function testSubmitResetsErrors() { $this->form->addError(new FormError('Error!')); - $this->form->bind('foobar'); + $this->form->submit('foobar'); $this->assertSame(array(), $this->form->getErrors()); } @@ -859,13 +859,13 @@ public function testSetDataCannotInvokeItself() $form->setData('foo'); } - public function testBindingWrongDataIsIgnored() + public function testSubmittingWrongDataIsIgnored() { $test = $this; $child = $this->getBuilder('child', $this->dispatcher); - $child->addEventListener(FormEvents::PRE_BIND, function (FormEvent $event) use ($test) { - // child form doesn't receive the wrong data that is bound on parent + $child->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use ($test) { + // child form doesn't receive the wrong data that is submitted on parent $test->assertNull($event->getData()); }); @@ -875,7 +875,7 @@ public function testBindingWrongDataIsIgnored() ->add($child) ->getForm(); - $parent->bind('not-an-array'); + $parent->submit('not-an-array'); } public function testHandleRequestForwardsToRequestHandler() @@ -964,30 +964,30 @@ public function testGetViewDataRequiresParentToBeSetIfInheritData() $form->getViewData(); } - public function testPostBindDataIsNullIfInheritData() + public function testPostSubmitDataIsNullIfInheritData() { $test = $this; $form = $this->getBuilder() - ->addEventListener(FormEvents::POST_BIND, function (FormEvent $event) use ($test) { + ->addEventListener(FormEvents::POST_SUBMIT, function (FormEvent $event) use ($test) { $test->assertNull($event->getData()); }) ->setInheritData(true) ->getForm(); - $form->bind('foo'); + $form->submit('foo'); } - public function testBindIsNeverFiredIfInheritData() + public function testSubmitIsNeverFiredIfInheritData() { $test = $this; $form = $this->getBuilder() - ->addEventListener(FormEvents::BIND, function (FormEvent $event) use ($test) { - $test->fail('The BIND event should not be fired'); + ->addEventListener(FormEvents::SUBMIT, function (FormEvent $event) use ($test) { + $test->fail('The SUBMIT event should not be fired'); }) ->setInheritData(true) ->getForm(); - $form->bind('foo'); + $form->submit('foo'); } protected function createForm() From 8f8b559b27c2af3fb4bbabee6aa61b24276ba1cf Mon Sep 17 00:00:00 2001 From: jaugustin Date: Fri, 12 Apr 2013 10:36:24 +0200 Subject: [PATCH 112/447] fix DateTimeToLocalizedStringTransformer issue #7561, add tests --- .../DateTimeToLocalizedStringTransformer.php | 8 ++++++-- .../DateTimeToLocalizedStringTransformerTest.php | 9 +++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php index 673fd5fde2..2972b3f686 100644 --- a/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php @@ -130,8 +130,12 @@ public function reverseTransform($value) throw new TransformationFailedException(intl_get_error_message()); } - // read timestamp into DateTime object - the formatter delivers in UTC - $dateTime = new \DateTime(sprintf('@%s UTC', $timestamp)); + try { + // read timestamp into DateTime object - the formatter delivers in UTC + $dateTime = new \DateTime(sprintf('@%s UTC', $timestamp)); + } catch (\Exception $e) { + throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); + } if ('UTC' !== $this->inputTimezone) { try { diff --git a/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php index abef21ba6d..16415ee4c2 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php @@ -263,4 +263,13 @@ public function testReverseTransformWithNonExistingDate() $this->assertDateTimeEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('31.04.10 04:05')); } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformOutOfTimestampRange() + { + $transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC'); + $transformer->reverseTransform('1789-07-14'); + } } From e67ff9501abc8e2926ce280d6ff427eb85ccb990 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 22 Apr 2013 06:29:54 +0200 Subject: [PATCH 113/447] added missing license blocks --- Test/DeprecationErrorHandler.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Test/DeprecationErrorHandler.php b/Test/DeprecationErrorHandler.php index 21b3a6e6b0..8a736fde2c 100644 --- a/Test/DeprecationErrorHandler.php +++ b/Test/DeprecationErrorHandler.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Component\Form\Test; class DeprecationErrorHandler From 61ed5600067f7d0ff30bd58fb088a5a71854ae55 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 22 Apr 2013 06:31:56 +0200 Subject: [PATCH 114/447] added missing license blocks --- Tests/FormRendererTest.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Tests/FormRendererTest.php b/Tests/FormRendererTest.php index 614f300ce3..69b048f7db 100644 --- a/Tests/FormRendererTest.php +++ b/Tests/FormRendererTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Component\Form\Test; class FormRendererTest extends \PHPUnit_Framework_TestCase From 16b36673d856ee4ac565a108c90ec4b00626122e Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Mon, 22 Apr 2013 13:33:42 +0100 Subject: [PATCH 115/447] [Form] Allowed binding false to a checkbox. --- Form.php | 5 ++++- .../Extension/Core/Type/CheckboxTypeTest.php | 22 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/Form.php b/Form.php index a7a057dd09..1b3b0f3120 100644 --- a/Form.php +++ b/Form.php @@ -488,11 +488,14 @@ public function bind($submittedData) $this->setData($this->config->getData()); } + // Treat false as NULL to support binding false to checkboxes. // Don't convert NULL to a string here in order to determine later // whether an empty value has been submitted or whether no value has // been submitted at all. This is important for processing checkboxes // and radio buttons with empty values. - if (is_scalar($submittedData)) { + if (false === $submittedData) { + $submittedData = null; + } elseif (is_scalar($submittedData)) { $submittedData = (string) $submittedData; } diff --git a/Tests/Extension/Core/Type/CheckboxTypeTest.php b/Tests/Extension/Core/Type/CheckboxTypeTest.php index 304958f768..d4b7e8c086 100644 --- a/Tests/Extension/Core/Type/CheckboxTypeTest.php +++ b/Tests/Extension/Core/Type/CheckboxTypeTest.php @@ -105,6 +105,28 @@ public function testBindWithEmptyValueUnchecked() $this->assertNull($form->getViewData()); } + public function testBindWithEmptyValueAndFalseUnchecked() + { + $form = $this->factory->create('checkbox', null, array( + 'value' => '', + )); + $form->bind(false); + + $this->assertFalse($form->getData()); + $this->assertNull($form->getViewData()); + } + + public function testBindWithEmptyValueAndTrueChecked() + { + $form = $this->factory->create('checkbox', null, array( + 'value' => '', + )); + $form->bind(true); + + $this->assertTrue($form->getData()); + $this->assertSame('', $form->getViewData()); + } + /** * @dataProvider provideTransformedData */ From 4ad559de43e53c54ceecbf563f48767dca5be032 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Mon, 22 Apr 2013 14:11:14 +0100 Subject: [PATCH 116/447] [Form] Added a SimpleFormTest test case. --- Tests/SimpleFormTest.php | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Tests/SimpleFormTest.php b/Tests/SimpleFormTest.php index 09dea71d25..c80a03005e 100644 --- a/Tests/SimpleFormTest.php +++ b/Tests/SimpleFormTest.php @@ -96,6 +96,28 @@ public function testDataIsInitializedFromBind() $form->bind('foobar'); } + // https://github.com/symfony/symfony/pull/7789 + public function testFalseIsConvertedToNull() + { + $mock = $this->getMockBuilder('\stdClass') + ->setMethods(array('preBind')) + ->getMock(); + $mock->expects($this->once()) + ->method('preBind') + ->with($this->callback(function ($event) { + return null === $event->getData(); + })); + + $config = new FormConfigBuilder('name', null, $this->dispatcher); + $config->addEventListener(FormEvents::PRE_BIND, array($mock, 'preBind')); + $form = new Form($config); + + $form->bind(false); + + $this->assertTrue($form->isValid()); + $this->assertNull($form->getData()); + } + /** * @expectedException \Symfony\Component\Form\Exception\AlreadyBoundException */ From 6c39eeac7f1bd1614ef3db7a5752d06ec4c507e7 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Mon, 22 Apr 2013 16:22:02 +0200 Subject: [PATCH 117/447] [Form] Fixed missing label in button --- Tests/AbstractLayoutTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index 9f8200c095..358f4efdcd 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -1769,7 +1769,7 @@ public function testButton() $form = $this->factory->createNamed('name', 'button'); $this->assertWidgetMatchesXpath($form->createView(), array(), - '/button[@type="button"][@name="name"]' + '/button[@type="button"][@name="name"][.="[trans]Name[/trans]"]' ); } From a1dd8b782a3859ed4a2f75c25cb75f63a67a69cf Mon Sep 17 00:00:00 2001 From: Miha Vrhovnik Date: Sat, 5 Jan 2013 10:58:46 +0100 Subject: [PATCH 118/447] Added currency form type and validator --- Extension/Core/CoreExtension.php | 1 + Extension/Core/Type/CurrencyType.php | 46 +++++++++++++++++++ .../Extension/Core/Type/CurrencyTypeTest.php | 37 +++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 Extension/Core/Type/CurrencyType.php create mode 100644 Tests/Extension/Core/Type/CurrencyTypeTest.php diff --git a/Extension/Core/CoreExtension.php b/Extension/Core/CoreExtension.php index 3934d38261..bbcac4baea 100644 --- a/Extension/Core/CoreExtension.php +++ b/Extension/Core/CoreExtension.php @@ -53,6 +53,7 @@ protected function loadTypes() new Type\ButtonType(), new Type\SubmitType(), new Type\ResetType(), + new Type\CurrencyType(), ); } } diff --git a/Extension/Core/Type/CurrencyType.php b/Extension/Core/Type/CurrencyType.php new file mode 100644 index 0000000000..07b820d823 --- /dev/null +++ b/Extension/Core/Type/CurrencyType.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Extension\Core\Type; + +use Symfony\Component\Form\AbstractType; +use Symfony\Component\Intl\Intl; +use Symfony\Component\Locale\Locale; +use Symfony\Component\OptionsResolver\OptionsResolverInterface; + +class CurrencyType extends AbstractType +{ + /** + * {@inheritdoc} + */ + public function setDefaultOptions(OptionsResolverInterface $resolver) + { + $resolver->setDefaults(array( + 'choices' => Intl::getCurrencyBundle()->getCurrencyNames(), + )); + } + + /** + * {@inheritdoc} + */ + public function getParent() + { + return 'choice'; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'currency'; + } +} diff --git a/Tests/Extension/Core/Type/CurrencyTypeTest.php b/Tests/Extension/Core/Type/CurrencyTypeTest.php new file mode 100644 index 0000000000..b0eb6dc01c --- /dev/null +++ b/Tests/Extension/Core/Type/CurrencyTypeTest.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +use Symfony\Component\Form\Extension\Core\View\ChoiceView; +use Symfony\Component\Intl\Util\IntlTestHelper; + +class CurrencyTypeTest extends TypeTestCase +{ + protected function setUp() + { + IntlTestHelper::requireIntl($this); + + parent::setUp(); + } + + public function testCurrenciesAreSelectable() + { + $form = $this->factory->create('currency'); + $view = $form->createView(); + $choices = $view->vars['choices']; + + $this->assertContains(new ChoiceView('EUR', 'EUR', 'Euro'), $choices, '', false, false); + $this->assertContains(new ChoiceView('USD', 'USD', 'US Dollar'), $choices, '', false, false); + $this->assertContains(new ChoiceView('SIT', 'SIT', 'Slovenian Tolar'), $choices, '', false, false); + } + +} From 175f4fa35f2d37fba91bc283184bb697a0e90f55 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 25 Apr 2013 16:08:09 +0200 Subject: [PATCH 119/447] [Form] Added support for PATCH requests --- Button.php | 5 +-- CHANGELOG.md | 1 + .../HttpFoundationRequestHandler.php | 2 +- Form.php | 8 +++-- FormInterface.php | 7 ++-- NativeRequestHandler.php | 2 +- SubmitButton.php | 7 ++-- Tests/AbstractRequestHandlerTest.php | 34 +++++++++---------- Tests/CompoundFormTest.php | 25 ++++++++++++++ 9 files changed, 62 insertions(+), 29 deletions(-) diff --git a/Button.php b/Button.php index 6961dd8d78..8c5247d45f 100644 --- a/Button.php +++ b/Button.php @@ -358,13 +358,14 @@ public function handleRequest($request = null) /** * Submits data to the button. * - * @param null|string $submittedData The data + * @param null|string $submittedData The data. + * @param Boolean $clearMissing Not used. * * @return Button The button instance * * @throws Exception\AlreadySubmittedException If the button has already been submitted. */ - public function submit($submittedData) + public function submit($submittedData, $clearMissing = true) { if ($this->submitted) { throw new AlreadySubmittedException('A form can only be submitted once'); diff --git a/CHANGELOG.md b/CHANGELOG.md index c0fc6d06de..9a9f577a9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ CHANGELOG * added methods submit() and isSubmitted() to Form * deprecated bind() and isBound() in Form * deprecated AlreadyBoundException in favor of AlreadySubmittedException + * added support for PATCH requests 2.2.0 ----- diff --git a/Extension/HttpFoundation/HttpFoundationRequestHandler.php b/Extension/HttpFoundation/HttpFoundationRequestHandler.php index 6457de7477..dcb6ede2b3 100644 --- a/Extension/HttpFoundation/HttpFoundationRequestHandler.php +++ b/Extension/HttpFoundation/HttpFoundationRequestHandler.php @@ -75,6 +75,6 @@ public function handleRequest(FormInterface $form, $request = null) return; } - $form->submit($data); + $form->submit($data, 'PATCH' !== $method); } } diff --git a/Form.php b/Form.php index 9ad47905ad..974168a9a7 100644 --- a/Form.php +++ b/Form.php @@ -464,7 +464,7 @@ public function handleRequest($request = null) /** * {@inheritdoc} */ - public function submit($submittedData) + public function submit($submittedData, $clearMissing = true) { if ($this->submitted) { throw new AlreadySubmittedException('A form can only be submitted once'); @@ -518,8 +518,10 @@ public function submit($submittedData) } foreach ($this->children as $name => $child) { - $child->submit(isset($submittedData[$name]) ? $submittedData[$name] : null); - unset($submittedData[$name]); + if (isset($submittedData[$name]) || $clearMissing) { + $child->submit(isset($submittedData[$name]) ? $submittedData[$name] : null, $clearMissing); + unset($submittedData[$name]); + } } $this->extraData = $submittedData; diff --git a/FormInterface.php b/FormInterface.php index 1069398ba8..1e35f788cb 100644 --- a/FormInterface.php +++ b/FormInterface.php @@ -242,13 +242,16 @@ public function handleRequest($request = null); /** * Submits data to the form, transforms and validates it. * - * @param null|string|array $submittedData The submitted data. + * @param null|string|array $submittedData The submitted data. + * @param Boolean $clearMissing Whether to set fields to NULL + * when they are missing in the + * submitted data. * * @return FormInterface The form instance * * @throws Exception\AlreadySubmittedException If the form has already been submitted. */ - public function submit($submittedData); + public function submit($submittedData, $clearMissing = true); /** * Returns the root of the form tree. diff --git a/NativeRequestHandler.php b/NativeRequestHandler.php index 6ddb8d72a3..aaa4e4c0f2 100644 --- a/NativeRequestHandler.php +++ b/NativeRequestHandler.php @@ -90,7 +90,7 @@ public function handleRequest(FormInterface $form, $request = null) return; } - $form->submit($data); + $form->submit($data, 'PATCH' !== $method); } /** diff --git a/SubmitButton.php b/SubmitButton.php index a169ba6529..47d4be0e28 100644 --- a/SubmitButton.php +++ b/SubmitButton.php @@ -34,15 +34,16 @@ public function isClicked() /** * Submits data to the button. * - * @param null|string $submittedData The data + * @param null|string $submittedData The data. + * @param Boolean $clearMissing Not used. * * @return SubmitButton The button instance * * @throws Exception\AlreadySubmittedException If the form has already been submitted. */ - public function submit($submittedData) + public function submit($submittedData, $clearMissing = true) { - parent::submit($submittedData); + parent::submit($submittedData, $clearMissing); $this->clicked = null !== $submittedData; diff --git a/Tests/AbstractRequestHandlerTest.php b/Tests/AbstractRequestHandlerTest.php index 1890ec00aa..cef8f3bf0d 100644 --- a/Tests/AbstractRequestHandlerTest.php +++ b/Tests/AbstractRequestHandlerTest.php @@ -58,8 +58,8 @@ public function testSubmitIfNameInRequest($method) )); $form->expects($this->once()) - ->method('Submit') - ->with('DATA'); + ->method('submit') + ->with('DATA', 'PATCH' !== $method); $this->requestHandler->handleRequest($form, $this->request); } @@ -78,7 +78,7 @@ public function testDoNotSubmitIfWrongRequestMethod($method) )); $form->expects($this->never()) - ->method('Submit'); + ->method('submit'); $this->requestHandler->handleRequest($form, $this->request); } @@ -95,8 +95,8 @@ public function testSubmitSimpleFormWithNullIfNameNotInRequestAndNotGetRequest($ )); $form->expects($this->once()) - ->method('Submit') - ->with($this->identicalTo(null)); + ->method('submit') + ->with($this->identicalTo(null), 'PATCH' !== $method); $this->requestHandler->handleRequest($form, $this->request); } @@ -113,8 +113,8 @@ public function testSubmitCompoundFormWithArrayIfNameNotInRequestAndNotGetReques )); $form->expects($this->once()) - ->method('Submit') - ->with($this->identicalTo(array())); + ->method('submit') + ->with($this->identicalTo(array()), 'PATCH' !== $method); $this->requestHandler->handleRequest($form, $this->request); } @@ -128,7 +128,7 @@ public function testDoNotSubmitIfNameNotInRequestAndGetRequest() )); $form->expects($this->never()) - ->method('Submit'); + ->method('submit'); $this->requestHandler->handleRequest($form, $this->request); } @@ -152,8 +152,8 @@ public function testSubmitFormWithEmptyNameIfAtLeastOneFieldInRequest($method) )); $form->expects($this->once()) - ->method('Submit') - ->with($requestData); + ->method('submit') + ->with($requestData, 'PATCH' !== $method); $this->requestHandler->handleRequest($form, $this->request); } @@ -176,7 +176,7 @@ public function testDoNotSubmitFormWithEmptyNameIfNoFieldInRequest($method) )); $form->expects($this->never()) - ->method('Submit'); + ->method('submit'); $this->requestHandler->handleRequest($form, $this->request); } @@ -200,11 +200,11 @@ public function testMergeParamsAndFiles($method) )); $form->expects($this->once()) - ->method('Submit') + ->method('submit') ->with(array( 'field1' => 'DATA', 'field2' => $file, - )); + ), 'PATCH' !== $method); $this->requestHandler->handleRequest($form, $this->request); } @@ -224,8 +224,8 @@ public function testParamTakesPrecedenceOverFile($method) )); $form->expects($this->once()) - ->method('Submit') - ->with('DATA'); + ->method('submit') + ->with('DATA', 'PATCH' !== $method); $this->requestHandler->handleRequest($form, $this->request); } @@ -245,8 +245,8 @@ public function testSubmitFileIfNoParam($method) )); $form->expects($this->once()) - ->method('Submit') - ->with($file); + ->method('submit') + ->with($file, 'PATCH' !== $method); $this->requestHandler->handleRequest($form, $this->request); } diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index f213db3126..fdd1a0e9b7 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -58,6 +58,31 @@ public function testSubmitForwardsNullIfValueIsMissing() $this->form->submit(array()); } + public function testSubmitDoesNotForwardNullIfNotClearMissing() + { + $child = $this->getMockForm('firstName'); + + $this->form->add($child); + + $child->expects($this->never()) + ->method('submit'); + + $this->form->submit(array(), false); + } + + public function testClearMissingFlagIsForwarded() + { + $child = $this->getMockForm('firstName'); + + $this->form->add($child); + + $child->expects($this->once()) + ->method('submit') + ->with($this->equalTo('foo'), false); + + $this->form->submit(array('firstName' => 'foo'), false); + } + public function testCloneChildren() { $child = $this->getBuilder('child')->getForm(); From 3c36394dc170f16e0f33a61e53a900c9494ea146 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Mon, 29 Apr 2013 17:31:30 +0200 Subject: [PATCH 120/447] [Form] *_SET_DATA events are now guaranteed to be fired *after* the initial children were added --- Button.php | 12 ++- ButtonBuilder.php | 26 ++++++ CHANGELOG.md | 6 ++ Extension/Core/Type/FormType.php | 2 + Form.php | 36 +++++++- FormBuilder.php | 10 ++- FormConfigBuilder.php | 28 ++++-- FormConfigBuilderInterface.php | 16 ++++ FormConfigInterface.php | 12 ++- FormInterface.php | 20 +++-- Tests/AbstractDivLayoutTest.php | 13 ++- Tests/AbstractFormTest.php | 4 + Tests/AbstractLayoutTest.php | 14 +-- Tests/CompoundFormTest.php | 34 ++++++- .../EventListener/ResizeFormListenerTest.php | 6 +- Tests/Extension/Core/Type/BaseTypeTest.php | 58 ++++++------ Tests/Extension/Core/Type/FormTypeTest.php | 88 +++++++++++-------- Tests/Fixtures/AlternatingRowType.php | 2 +- Tests/SimpleFormTest.php | 32 ++++++- 19 files changed, 314 insertions(+), 105 deletions(-) diff --git a/Button.php b/Button.php index 8c5247d45f..7d75ecaa5a 100644 --- a/Button.php +++ b/Button.php @@ -343,6 +343,16 @@ public function isSynchronized() return true; } + /** + * Unsupported method. + * + * @throws BadMethodCallException + */ + public function initialize() + { + throw new BadMethodCallException('Buttons cannot be initialized. Call initialized() on the root form instead.'); + } + /** * Unsupported method. * @@ -352,7 +362,7 @@ public function isSynchronized() */ public function handleRequest($request = null) { - throw new BadMethodCallException('Buttons cannot be processed. Call process() on the root form instead.'); + throw new BadMethodCallException('Buttons cannot handle requests. Call handleRequest() on the root form instead.'); } /** diff --git a/ButtonBuilder.php b/ButtonBuilder.php index 3d6b840299..1c8e9244a2 100644 --- a/ButtonBuilder.php +++ b/ButtonBuilder.php @@ -492,6 +492,22 @@ public function setRequestHandler(RequestHandlerInterface $requestHandler) throw new BadMethodCallException('Buttons do not support form processors.'); } + /** + * Unsupported method. + * + * @param Boolean $initialize + * + * @throws BadMethodCallException + */ + public function setAutoInitialize($initialize) + { + if (true === $initialize) { + throw new BadMethodCallException('Buttons do not support automatic initialization.'); + } + + return $this; + } + /** * Unsupported method. * @@ -771,6 +787,16 @@ public function getRequestHandler() return null; } + /** + * Unsupported method. + * + * @return null Always returns null. + */ + public function getAutoInitialize() + { + return null; + } + /** * Unsupported method. * diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a9f577a9b..88a5714053 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,12 @@ CHANGELOG * deprecated bind() and isBound() in Form * deprecated AlreadyBoundException in favor of AlreadySubmittedException * added support for PATCH requests + * [BC BREAK] added initialize() to FormInterface + * [BC BREAK] added getAutoInitialize() to FormConfigInterface + * [BC BREAK] added setAutoInitialize() to FormConfigBuilderInterface + * [BC BREAK] initialization for Form instances added to a form tree must be manually disabled + * PRE_SET_DATA is now guaranteed to be called after children were added by the form builder, + unless FormInterface::setData() is called manually 2.2.0 ----- diff --git a/Extension/Core/Type/FormType.php b/Extension/Core/Type/FormType.php index 190bb52cec..eb1897cee4 100644 --- a/Extension/Core/Type/FormType.php +++ b/Extension/Core/Type/FormType.php @@ -55,6 +55,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) ->setDataMapper($options['compound'] ? new PropertyPathMapper($this->propertyAccessor) : null) ->setMethod($options['method']) ->setAction($options['action']) + ->setAutoInitialize($options['auto_initialize']) ; if ($options['trim']) { @@ -188,6 +189,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) // According to RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt) // section 4.2., empty URIs are considered same-document references 'action' => '', + 'auto_initialize' => true, )); $resolver->setAllowedTypes(array( diff --git a/Form.php b/Form.php index 974168a9a7..35135274a7 100644 --- a/Form.php +++ b/Form.php @@ -451,6 +451,25 @@ public function getExtraData() return $this->extraData; } + /** + * {@inheritdoc} + */ + public function initialize() + { + if (null !== $this->parent) { + throw new RuntimeException('Only root forms should be initialized.'); + } + + // Guarantee that the *_SET_DATA events have been triggered once the + // form is initialized. This makes sure that dynamically added or + // removed fields are already visible after initialization. + if (!$this->defaultDataSet) { + $this->setData($this->config->getData()); + } + + return $this; + } + /** * {@inheritdoc} */ @@ -774,7 +793,11 @@ public function add($child, $type = null, array $options = array()) // * getViewData() is called // * setData() is called since the form is not initialized yet // * ... endless recursion ... - if (!$this->lockSetData && !$this->config->getInheritData()) { + // + // Also skip data mapping if setData() has not been called yet. + // setData() will be called upon form initialization and data mapping + // will take place by then. + if (!$this->lockSetData && $this->defaultDataSet && !$this->config->getInheritData()) { $viewData = $this->getViewData(); } @@ -787,18 +810,27 @@ public function add($child, $type = null, array $options = array()) throw new UnexpectedTypeException($type, 'string or Symfony\Component\Form\FormTypeInterface'); } + // Never initialize child forms automatically + $options['auto_initialize'] = false; + if (null === $type) { $child = $this->config->getFormFactory()->createForProperty($this->config->getDataClass(), $child, null, $options); } else { $child = $this->config->getFormFactory()->createNamed($child, $type, null, $options); } + } elseif ($child->getConfig()->getAutoInitialize()) { + throw new RuntimeException(sprintf( + 'Automatic initialization is only supported on root forms. You '. + 'should set the "auto_initialize" option to false on the field "%s".', + $child->getName() + )); } $this->children[$child->getName()] = $child; $child->setParent($this); - if (!$this->lockSetData && !$this->config->getInheritData()) { + if (!$this->lockSetData && $this->defaultDataSet && !$this->config->getInheritData()) { $childrenIterator = new InheritDataAwareIterator(array($child)); $childrenIterator = new \RecursiveIteratorIterator($childrenIterator); $this->config->getDataMapper()->mapDataToForms($viewData, $childrenIterator); diff --git a/FormBuilder.php b/FormBuilder.php index 986f43c5ae..2caefe48be 100644 --- a/FormBuilder.php +++ b/FormBuilder.php @@ -26,7 +26,7 @@ class FormBuilder extends FormConfigBuilder implements \IteratorAggregate, FormB /** * The children of the form builder. * - * @var array + * @var FormBuilderInterface[] */ private $children = array(); @@ -220,7 +220,13 @@ public function getForm() $form = new Form($this->getFormConfig()); foreach ($this->children as $child) { - $form->add($child->getForm()); + // Automatic initialization is only supported on root forms + $form->add($child->setAutoInitialize(false)->getForm()); + } + + if ($this->getAutoInitialize()) { + // Automatically initialize the form if it is configured so + $form->initialize(); } return $form; diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index b6e57f6201..dc9c8f038e 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -107,11 +107,6 @@ class FormConfigBuilder implements FormConfigBuilderInterface */ private $dataMapper; - /** - * @var array - */ - private $validators = array(); - /** * @var Boolean */ @@ -172,6 +167,11 @@ class FormConfigBuilder implements FormConfigBuilderInterface */ private $requestHandler; + /** + * @var Boolean + */ + private $autoInitialize = false; + /** * @var array */ @@ -521,6 +521,14 @@ public function getRequestHandler() return $this->requestHandler; } + /** + * {@inheritdoc} + */ + public function getAutoInitialize() + { + return $this->autoInitialize; + } + /** * {@inheritdoc} */ @@ -843,6 +851,16 @@ public function setRequestHandler(RequestHandlerInterface $requestHandler) return $this; } + /** + * {@inheritdoc} + */ + public function setAutoInitialize($initialize) + { + $this->autoInitialize = (Boolean) $initialize; + + return $this; + } + /** * {@inheritdoc} */ diff --git a/FormConfigBuilderInterface.php b/FormConfigBuilderInterface.php index 60a8d11116..62d12c09cb 100644 --- a/FormConfigBuilderInterface.php +++ b/FormConfigBuilderInterface.php @@ -256,12 +256,28 @@ public function setAction($action); public function setMethod($method); /** + * Sets the request handler used by the form. + * * @param RequestHandlerInterface $requestHandler * * @return self The configuration object. */ public function setRequestHandler(RequestHandlerInterface $requestHandler); + /** + * Sets whether the form should be initialized automatically. + * + * Should be set to true only for root forms. + * + * @param Boolean $initialize True to initialize the form automatically, + * false to suppress automatic initialization. + * In the second case, you need to call + * {@link FormInterface::initialize()} manually. + * + * @return self The configuration object. + */ + public function setAutoInitialize($initialize); + /** * Builds and returns the form configuration. * diff --git a/FormConfigInterface.php b/FormConfigInterface.php index 5e944775b8..576fcd8142 100644 --- a/FormConfigInterface.php +++ b/FormConfigInterface.php @@ -201,10 +201,20 @@ public function getAction(); public function getMethod(); /** - * @return RequestHandlerInterface The form processor. + * Returns the request handler used by the form. + * + * @return RequestHandlerInterface The request handler. */ public function getRequestHandler(); + /** + * Returns whether the form should be initialized upon creation. + * + * @return Boolean Returns true if the form should be initialized + * when created, false otherwise. + */ + public function getAutoInitialize(); + /** * Returns all options passed during the construction of the form. * diff --git a/FormInterface.php b/FormInterface.php index 1e35f788cb..5a852e864f 100644 --- a/FormInterface.php +++ b/FormInterface.php @@ -227,13 +227,23 @@ public function isEmpty(); public function isSynchronized(); /** - * Processes the given request and calls {@link submit()} if it was submitted. + * Initializes the form tree. * - * Internally, the request is forwarded to a {@link RequestHandlerInterface} - * instance. This instance determines the allowed value of the - * $request parameter. + * Should be called on the root form after constructing the tree. * - * @param mixed $request The request to check. + * @return FormInterface The form instance. + */ + public function initialize(); + + /** + * Inspects the given request and calls {@link submit()} if the form was + * submitted. + * + * Internally, the request is forwarded to the configured + * {@link RequestHandlerInterface} instance, which determines whether to + * submit the form or not. + * + * @param mixed $request The request to handle. * * @return FormInterface The form instance. */ diff --git a/Tests/AbstractDivLayoutTest.php b/Tests/AbstractDivLayoutTest.php index 23cecaee94..ee9ed8f2a6 100644 --- a/Tests/AbstractDivLayoutTest.php +++ b/Tests/AbstractDivLayoutTest.php @@ -143,18 +143,16 @@ public function testRestWithChildrenForms() { $child1 = $this->factory->createNamedBuilder('child1', 'form') ->add('field1', 'text') - ->add('field2', 'text') - ->getForm(); + ->add('field2', 'text'); $child2 = $this->factory->createNamedBuilder('child2', 'form') ->add('field1', 'text') - ->add('field2', 'text') - ->getForm(); + ->add('field2', 'text'); $view = $this->factory->createNamedBuilder('parent', 'form') - ->getForm() ->add($child1) ->add($child2) + ->getForm() ->createView(); // Render child1.field1 row @@ -627,13 +625,12 @@ public function testThemeBlockInheritance($theme) public function testThemeInheritance($parentTheme, $childTheme) { $child = $this->factory->createNamedBuilder('child', 'form') - ->add('field', 'text') - ->getForm(); + ->add('field', 'text'); $view = $this->factory->createNamedBuilder('parent', 'form') ->add('field', 'text') - ->getForm() ->add($child) + ->getForm() ->createView() ; diff --git a/Tests/AbstractFormTest.php b/Tests/AbstractFormTest.php index 42543b63cf..2911818752 100644 --- a/Tests/AbstractFormTest.php +++ b/Tests/AbstractFormTest.php @@ -77,10 +77,14 @@ protected function getBuilder($name = 'name', EventDispatcherInterface $dispatch protected function getMockForm($name = 'name') { $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); + $config = $this->getMock('Symfony\Component\Form\FormConfigInterface'); $form->expects($this->any()) ->method('getName') ->will($this->returnValue($name)); + $form->expects($this->any()) + ->method('getConfig') + ->will($this->returnValue($config)); return $form; } diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index 8049b85013..1a48fae194 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -1152,9 +1152,10 @@ public function testDateSingleText() public function testDateErrorBubbling() { - $child = $this->factory->createNamed('date', 'date'); - $form = $this->factory->createNamed('form', 'form')->add($child); - $child->addError(new FormError('[trans]Error![/trans]')); + $form = $this->factory->createNamedBuilder('form', 'form') + ->add('date', 'date') + ->getForm(); + $form->get('date')->addError(new FormError('[trans]Error![/trans]')); $view = $form->createView(); $this->assertEmpty($this->renderErrors($view)); @@ -1678,9 +1679,10 @@ public function testTimeWithEmptyValueOnYear() public function testTimeErrorBubbling() { - $child = $this->factory->createNamed('time', 'time'); - $form = $this->factory->createNamed('form', 'form')->add($child); - $child->addError(new FormError('[trans]Error![/trans]')); + $form = $this->factory->createNamedBuilder('form', 'form') + ->add('time', 'time') + ->getForm(); + $form->get('time')->addError(new FormError('[trans]Error![/trans]')); $view = $form->createView(); $this->assertEmpty($this->renderErrors($view)); diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index fdd1a0e9b7..b240d2d0b3 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -154,7 +154,10 @@ public function testAddUsingNameAndType() $this->factory->expects($this->once()) ->method('createNamed') - ->with('foo', 'text', null, array('bar' => 'baz')) + ->with('foo', 'text', null, array( + 'bar' => 'baz', + 'auto_initialize' => false, + )) ->will($this->returnValue($child)); $this->form->add('foo', 'text', array('bar' => 'baz')); @@ -170,7 +173,10 @@ public function testAddUsingIntegerNameAndType() $this->factory->expects($this->once()) ->method('createNamed') - ->with('0', 'text', null, array('bar' => 'baz')) + ->with('0', 'text', null, array( + 'bar' => 'baz', + 'auto_initialize' => false, + )) ->will($this->returnValue($child)); // in order to make casting unnecessary @@ -213,7 +219,10 @@ public function testAddUsingNameButNoTypeAndOptions() $this->factory->expects($this->once()) ->method('createForProperty') - ->with('\stdClass', 'foo', null, array('bar' => 'baz')) + ->with('\stdClass', 'foo', null, array( + 'bar' => 'baz', + 'auto_initialize' => false, + )) ->will($this->returnValue($child)); $this->form->add('foo', null, array('bar' => 'baz')); @@ -287,7 +296,7 @@ public function testIterator() $this->assertSame($this->form->all(), iterator_to_array($this->form)); } - public function testAddMapsViewDataToForm() + public function testAddMapsViewDataToFormIfInitialized() { $test = $this; $mapper = $this->getDataMapper(); @@ -310,6 +319,22 @@ public function testAddMapsViewDataToForm() $test->assertSame(array($child), iterator_to_array($iterator)); })); + $form->initialize(); + $form->add($child); + } + + public function testAddDoesNotMapViewDataToFormIfNotInitialized() + { + $mapper = $this->getDataMapper(); + $form = $this->getBuilder() + ->setCompound(true) + ->setDataMapper($mapper) + ->getForm(); + + $child = $this->getBuilder()->getForm(); + $mapper->expects($this->never()) + ->method('mapDataToForms'); + $form->add($child); } @@ -326,6 +351,7 @@ public function testAddDoesNotMapViewDataToFormIfInheritData() $mapper->expects($this->never()) ->method('mapDataToForms'); + $form->initialize(); $form->add($child); } diff --git a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php index d77531ede4..1367b3ef02 100644 --- a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php +++ b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php @@ -72,11 +72,11 @@ public function testPreSetDataResizesForm() $this->factory->expects($this->at(0)) ->method('createNamed') - ->with(1, 'text', null, array('property_path' => '[1]', 'max_length' => 10)) + ->with(1, 'text', null, array('property_path' => '[1]', 'max_length' => 10, 'auto_initialize' => false)) ->will($this->returnValue($this->getForm('1'))); $this->factory->expects($this->at(1)) ->method('createNamed') - ->with(2, 'text', null, array('property_path' => '[2]', 'max_length' => 10)) + ->with(2, 'text', null, array('property_path' => '[2]', 'max_length' => 10, 'auto_initialize' => false)) ->will($this->returnValue($this->getForm('2'))); $data = array(1 => 'string', 2 => 'string'); @@ -116,7 +116,7 @@ public function testPreSubmitResizesUpIfAllowAdd() $this->factory->expects($this->once()) ->method('createNamed') - ->with(1, 'text', null, array('property_path' => '[1]', 'max_length' => 10)) + ->with(1, 'text', null, array('property_path' => '[1]', 'max_length' => 10, 'auto_initialize' => false)) ->will($this->returnValue($this->getForm('1'))); $data = array(0 => 'string', 1 => 'string'); diff --git a/Tests/Extension/Core/Type/BaseTypeTest.php b/Tests/Extension/Core/Type/BaseTypeTest.php index 34a54ac95a..ef36f1c052 100644 --- a/Tests/Extension/Core/Type/BaseTypeTest.php +++ b/Tests/Extension/Core/Type/BaseTypeTest.php @@ -25,8 +25,8 @@ public function testPassDisabledAsOption() public function testPassIdAndNameToView() { - $form = $this->factory->createNamed('name', $this->getTestedType()); - $view = $form->createView(); + $view = $this->factory->createNamed('name', $this->getTestedType()) + ->createView(); $this->assertEquals('name', $view->vars['id']); $this->assertEquals('name', $view->vars['name']); @@ -35,8 +35,8 @@ public function testPassIdAndNameToView() public function testStripLeadingUnderscoresAndDigitsFromId() { - $form = $this->factory->createNamed('_09name', $this->getTestedType()); - $view = $form->createView(); + $view = $this->factory->createNamed('_09name', $this->getTestedType()) + ->createView(); $this->assertEquals('name', $view->vars['id']); $this->assertEquals('_09name', $view->vars['name']); @@ -45,9 +45,10 @@ public function testStripLeadingUnderscoresAndDigitsFromId() public function testPassIdAndNameToViewWithParent() { - $parent = $this->factory->createNamed('parent', 'form'); - $parent->add($this->factory->createNamed('child', $this->getTestedType())); - $view = $parent->createView(); + $view = $this->factory->createNamedBuilder('parent', 'form') + ->add('child', $this->getTestedType()) + ->getForm() + ->createView(); $this->assertEquals('parent_child', $view['child']->vars['id']); $this->assertEquals('child', $view['child']->vars['name']); @@ -56,10 +57,10 @@ public function testPassIdAndNameToViewWithParent() public function testPassIdAndNameToViewWithGrandParent() { - $parent = $this->factory->createNamed('parent', 'form'); - $parent->add($this->factory->createNamed('child', 'form')); - $parent['child']->add($this->factory->createNamed('grand_child', $this->getTestedType())); - $view = $parent->createView(); + $builder = $this->factory->createNamedBuilder('parent', 'form') + ->add('child', 'form'); + $builder->get('child')->add('grand_child', $this->getTestedType()); + $view = $builder->getForm()->createView(); $this->assertEquals('parent_child_grand_child', $view['child']['grand_child']->vars['id']); $this->assertEquals('grand_child', $view['child']['grand_child']->vars['name']); @@ -78,33 +79,38 @@ public function testPassTranslationDomainToView() public function testInheritTranslationDomainFromParent() { - $parent = $this->factory->createNamed('parent', 'form', null, array( - 'translation_domain' => 'domain', - )); - $child = $this->factory->createNamed('child', $this->getTestedType()); - $view = $parent->add($child)->createView(); + $view = $this->factory + ->createNamedBuilder('parent', 'form', null, array( + 'translation_domain' => 'domain', + )) + ->add('child', $this->getTestedType()) + ->getForm() + ->createView(); $this->assertEquals('domain', $view['child']->vars['translation_domain']); } public function testPreferOwnTranslationDomain() { - $parent = $this->factory->createNamed('parent', 'form', null, array( - 'translation_domain' => 'parent_domain', - )); - $child = $this->factory->createNamed('child', $this->getTestedType(), null, array( - 'translation_domain' => 'domain', - )); - $view = $parent->add($child)->createView(); + $view = $this->factory + ->createNamedBuilder('parent', 'form', null, array( + 'translation_domain' => 'parent_domain', + )) + ->add('child', $this->getTestedType(), array( + 'translation_domain' => 'domain', + )) + ->getForm() + ->createView(); $this->assertEquals('domain', $view['child']->vars['translation_domain']); } public function testDefaultTranslationDomain() { - $parent = $this->factory->createNamed('parent', 'form'); - $child = $this->factory->createNamed('child', $this->getTestedType()); - $view = $parent->add($child)->createView(); + $view = $this->factory->createNamedBuilder('parent', 'form') + ->add('child', $this->getTestedType()) + ->getForm() + ->createView(); $this->assertEquals('messages', $view['child']->vars['translation_domain']); } diff --git a/Tests/Extension/Core/Type/FormTypeTest.php b/Tests/Extension/Core/Type/FormTypeTest.php index 3bc648a3d8..cced82f4cf 100644 --- a/Tests/Extension/Core/Type/FormTypeTest.php +++ b/Tests/Extension/Core/Type/FormTypeTest.php @@ -100,29 +100,32 @@ public function testSubmittedDataIsNotTrimmedBeforeTransformingIfNoTrimming() $this->assertEquals('reverse[ a ]', $form->getData()); } - public function testNonReadOnlyFormWithReadOnlyParentBeingReadOnly() + public function testNonReadOnlyFormWithReadOnlyParentIsReadOnly() { - $parent = $this->factory->createNamed('parent', 'form', null, array('read_only' => true)); - $child = $this->factory->createNamed('child', 'form'); - $view = $parent->add($child)->createView(); + $view = $this->factory->createNamedBuilder('parent', 'form', null, array('read_only' => true)) + ->add('child', 'form') + ->getForm() + ->createView(); $this->assertTrue($view['child']->vars['read_only']); } - public function testReadOnlyFormWithNonReadOnlyParentBeingReadOnly() + public function testReadOnlyFormWithNonReadOnlyParentIsReadOnly() { - $parent = $this->factory->createNamed('parent', 'form'); - $child = $this->factory->createNamed('child', 'form', null, array('read_only' => true)); - $view = $parent->add($child)->createView(); + $view = $this->factory->createNamedBuilder('parent', 'form') + ->add('child', 'form', array('read_only' => true)) + ->getForm() + ->createView(); $this->assertTrue($view['child']->vars['read_only']); } - public function testNonReadOnlyFormWithNonReadOnlyParentBeingNonReadOnly() + public function testNonReadOnlyFormWithNonReadOnlyParentIsNotReadOnly() { - $parent = $this->factory->createNamed('parent', 'form'); - $child = $this->factory->createNamed('child', 'form'); - $view = $parent->add($child)->createView(); + $view = $this->factory->createNamedBuilder('parent', 'form') + ->add('child', 'form') + ->getForm() + ->createView(); $this->assertFalse($view['child']->vars['read_only']); } @@ -137,12 +140,13 @@ public function testPassMaxLengthToView() public function testSubmitWithEmptyDataCreatesObjectIfClassAvailable() { - $form = $this->factory->create('form', null, array( + $builder = $this->factory->createBuilder('form', null, array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', 'required' => false, )); - $form->add($this->factory->createNamed('firstName', 'text')); - $form->add($this->factory->createNamed('lastName', 'text')); + $builder->add('firstName', 'text'); + $builder->add('lastName', 'text'); + $form = $builder->getForm(); $form->setData(null); // partially empty, still an object is created @@ -157,13 +161,14 @@ public function testSubmitWithEmptyDataCreatesObjectIfClassAvailable() public function testSubmitWithEmptyDataCreatesObjectIfInitiallySubmittedWithObject() { - $form = $this->factory->create('form', null, array( + $builder = $this->factory->createBuilder('form', null, array( // data class is inferred from the passed object 'data' => new Author(), 'required' => false, )); - $form->add($this->factory->createNamed('firstName', 'text')); - $form->add($this->factory->createNamed('lastName', 'text')); + $builder->add('firstName', 'text'); + $builder->add('lastName', 'text'); + $form = $builder->getForm(); $form->setData(null); // partially empty, still an object is created @@ -178,11 +183,12 @@ public function testSubmitWithEmptyDataCreatesObjectIfInitiallySubmittedWithObje public function testSubmitWithEmptyDataCreatesArrayIfDataClassIsNull() { - $form = $this->factory->create('form', null, array( + $builder = $this->factory->createBuilder('form', null, array( 'data_class' => null, 'required' => false, )); - $form->add($this->factory->createNamed('firstName', 'text')); + $builder->add('firstName', 'text'); + $form = $builder->getForm(); $form->setData(null); $form->submit(array('firstName' => 'Bernhard')); @@ -192,12 +198,13 @@ public function testSubmitWithEmptyDataCreatesArrayIfDataClassIsNull() public function testSubmitEmptyWithEmptyDataCreatesNoObjectIfNotRequired() { - $form = $this->factory->create('form', null, array( + $builder = $this->factory->createBuilder('form', null, array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', 'required' => false, )); - $form->add($this->factory->createNamed('firstName', 'text')); - $form->add($this->factory->createNamed('lastName', 'text')); + $builder->add('firstName', 'text'); + $builder->add('lastName', 'text'); + $form = $builder->getForm(); $form->setData(null); $form->submit(array('firstName' => '', 'lastName' => '')); @@ -207,12 +214,13 @@ public function testSubmitEmptyWithEmptyDataCreatesNoObjectIfNotRequired() public function testSubmitEmptyWithEmptyDataCreatesObjectIfRequired() { - $form = $this->factory->create('form', null, array( + $builder = $this->factory->createBuilder('form', null, array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', 'required' => true, )); - $form->add($this->factory->createNamed('firstName', 'text')); - $form->add($this->factory->createNamed('lastName', 'text')); + $builder->add('firstName', 'text'); + $builder->add('lastName', 'text'); + $form = $builder->getForm(); $form->setData(null); $form->submit(array('firstName' => '', 'lastName' => '')); @@ -225,8 +233,9 @@ public function testSubmitEmptyWithEmptyDataCreatesObjectIfRequired() */ public function testSubmitWithEmptyDataStoresArrayIfNoClassAvailable() { - $form = $this->factory->create('form'); - $form->add($this->factory->createNamed('firstName', 'text')); + $form = $this->factory->createBuilder('form') + ->add('firstName', 'text') + ->getForm(); $form->setData(null); $form->submit(array('firstName' => 'Bernhard')); @@ -255,11 +264,12 @@ public function testSubmitWithEmptyDataUsesEmptyDataOption() { $author = new Author(); - $form = $this->factory->create('form', null, array( + $builder = $this->factory->createBuilder('form', null, array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', 'empty_data' => $author, )); - $form->add($this->factory->createNamed('firstName', 'text')); + $builder->add('firstName', 'text'); + $form = $builder->getForm(); $form->submit(array('firstName' => 'Bernhard')); @@ -430,19 +440,21 @@ function ($value) use ($ref2) { // reverseTransform public function testPassMultipartTrueIfAnyChildIsMultipartToView() { - $form = $this->factory->create('form'); - $form->add($this->factory->create('text')); - $form->add($this->factory->create('file')); - $view = $form->createView(); + $view = $this->factory->createBuilder('form') + ->add('foo', 'text') + ->add('bar', 'file') + ->getForm() + ->createView(); $this->assertTrue($view->vars['multipart']); } - public function testCreateViewDoNoMarkItAsRendered() + public function testViewIsNotRenderedByDefault() { - $form = $this->factory->create('form'); - $form->add($this->factory->create('form')); - $view = $form->createView(); + $view = $this->factory->createBuilder('form') + ->add('foo', 'form') + ->getForm() + ->createView(); $this->assertFalse($view->isRendered()); } diff --git a/Tests/Fixtures/AlternatingRowType.php b/Tests/Fixtures/AlternatingRowType.php index e53d19ffe9..ee7d135339 100644 --- a/Tests/Fixtures/AlternatingRowType.php +++ b/Tests/Fixtures/AlternatingRowType.php @@ -16,7 +16,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($formFactory) { $form = $event->getForm(); $type = $form->getName() % 2 === 0 ? 'text' : 'textarea'; - $form->add($formFactory->createNamed('title', $type)); + $form->add('title', $type); }); } diff --git a/Tests/SimpleFormTest.php b/Tests/SimpleFormTest.php index 79232df7d0..bedad6761f 100644 --- a/Tests/SimpleFormTest.php +++ b/Tests/SimpleFormTest.php @@ -902,13 +902,13 @@ public function testSubmittingWrongDataIsIgnored() public function testHandleRequestForwardsToRequestHandler() { - $processor = $this->getMock('Symfony\Component\Form\RequestHandlerInterface'); + $handler = $this->getMock('Symfony\Component\Form\RequestHandlerInterface'); $form = $this->getBuilder() - ->setRequestHandler($processor) + ->setRequestHandler($handler) ->getForm(); - $processor->expects($this->once()) + $handler->expects($this->once()) ->method('handleRequest') ->with($this->identicalTo($form), 'REQUEST'); @@ -1012,6 +1012,32 @@ public function testSubmitIsNeverFiredIfInheritData() $form->submit('foo'); } + public function testInitializeSetsDefaultData() + { + $config = $this->getBuilder()->setData('DEFAULT')->getFormConfig(); + $form = $this->getMock('Symfony\Component\Form\Form', array('setData'), array($config)); + + $form->expects($this->once()) + ->method('setData') + ->with($this->identicalTo('DEFAULT')); + + /* @var Form $form */ + $form->initialize(); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\RuntimeException + */ + public function testInitializeFailsIfParent() + { + $parent = $this->getBuilder()->setRequired(false)->getForm(); + $child = $this->getBuilder()->setRequired(true)->getForm(); + + $child->setParent($parent); + + $child->initialize(); + } + protected function createForm() { return $this->getBuilder()->getForm(); From f2cf8e74a75eb802e59c6dee54a7bee0fe78818a Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 2 May 2013 09:53:57 +0200 Subject: [PATCH 121/447] [Form] Fixed stofs from #7878 --- Button.php | 2 +- ButtonBuilder.php | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Button.php b/Button.php index 7d75ecaa5a..6e12ba163c 100644 --- a/Button.php +++ b/Button.php @@ -350,7 +350,7 @@ public function isSynchronized() */ public function initialize() { - throw new BadMethodCallException('Buttons cannot be initialized. Call initialized() on the root form instead.'); + throw new BadMethodCallException('Buttons cannot be initialized. Call initialize() on the root form instead.'); } /** diff --git a/ButtonBuilder.php b/ButtonBuilder.php index 1c8e9244a2..2a19d58e06 100644 --- a/ButtonBuilder.php +++ b/ButtonBuilder.php @@ -790,21 +790,21 @@ public function getRequestHandler() /** * Unsupported method. * - * @return null Always returns null. + * @return Boolean Always returns false. */ public function getAutoInitialize() { - return null; + return false; } /** * Unsupported method. * - * @return null Always returns null. + * @return Boolean Always returns false. */ public function getInheritData() { - return null; + return false; } /** From 618d7299adb6a8b8854bacecb005d49d0d3c9b6a Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 2 May 2013 11:05:04 +0200 Subject: [PATCH 122/447] [Form] Fixed CSRF error messages to be translated and added "csrf_message" option --- CHANGELOG.md | 2 + Extension/Csrf/CsrfExtension.php | 26 +++++++++-- .../EventListener/CsrfValidationListener.php | 30 ++++++++++++- Extension/Csrf/Type/FormTypeCsrfExtension.php | 36 ++++++++++++++- .../Csrf/Type/FormTypeCsrfExtensionTest.php | 45 ++++++++++++++++++- 5 files changed, 131 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88a5714053..6cc800d0af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,8 @@ CHANGELOG * [BC BREAK] initialization for Form instances added to a form tree must be manually disabled * PRE_SET_DATA is now guaranteed to be called after children were added by the form builder, unless FormInterface::setData() is called manually + * fixed CSRF error message to be translated + * custom CSRF error messages can now be set through the "csrf_message" option 2.2.0 ----- diff --git a/Extension/Csrf/CsrfExtension.php b/Extension/Csrf/CsrfExtension.php index 71d06381ad..f9d9e40aa8 100644 --- a/Extension/Csrf/CsrfExtension.php +++ b/Extension/Csrf/CsrfExtension.php @@ -14,22 +14,42 @@ use Symfony\Component\Form\Extension\Csrf\Type; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Form\AbstractExtension; +use Symfony\Component\Translation\TranslatorInterface; /** * This extension protects forms by using a CSRF token. + * + * @author Bernhard Schussek */ class CsrfExtension extends AbstractExtension { + /** + * @var CsrfProviderInterface + */ private $csrfProvider; + /** + * @var TranslatorInterface + */ + private $translator; + + /** + * @var null|string + */ + private $translationDomain; + /** * Constructor. * - * @param CsrfProviderInterface $csrfProvider The CSRF provider + * @param CsrfProviderInterface $csrfProvider The CSRF provider + * @param TranslatorInterface $translator The translator for translating error messages. + * @param null|string $translationDomain The translation domain for translating. */ - public function __construct(CsrfProviderInterface $csrfProvider) + public function __construct(CsrfProviderInterface $csrfProvider, TranslatorInterface $translator = null, $translationDomain = null) { $this->csrfProvider = $csrfProvider; + $this->translator = $translator; + $this->translationDomain = $translationDomain; } /** @@ -38,7 +58,7 @@ public function __construct(CsrfProviderInterface $csrfProvider) protected function loadTypeExtensions() { return array( - new Type\FormTypeCsrfExtension($this->csrfProvider), + new Type\FormTypeCsrfExtension($this->csrfProvider, true, '_token', $this->translator, $this->translationDomain), ); } } diff --git a/Extension/Csrf/EventListener/CsrfValidationListener.php b/Extension/Csrf/EventListener/CsrfValidationListener.php index 9d062f9546..547e9d756c 100644 --- a/Extension/Csrf/EventListener/CsrfValidationListener.php +++ b/Extension/Csrf/EventListener/CsrfValidationListener.php @@ -16,6 +16,7 @@ use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; +use Symfony\Component\Translation\TranslatorInterface; /** * @author Bernhard Schussek @@ -44,6 +45,22 @@ class CsrfValidationListener implements EventSubscriberInterface */ private $intention; + /** + * The message displayed in case of an error. + * @var string + */ + private $errorMessage; + + /** + * @var TranslatorInterface + */ + private $translator; + + /** + * @var null|string + */ + private $translationDomain; + public static function getSubscribedEvents() { return array( @@ -51,11 +68,14 @@ public static function getSubscribedEvents() ); } - public function __construct($fieldName, CsrfProviderInterface $csrfProvider, $intention) + public function __construct($fieldName, CsrfProviderInterface $csrfProvider, $intention, $errorMessage, TranslatorInterface $translator = null, $translationDomain = null) { $this->fieldName = $fieldName; $this->csrfProvider = $csrfProvider; $this->intention = $intention; + $this->errorMessage = $errorMessage; + $this->translator = $translator; + $this->translationDomain = $translationDomain; } public function preSubmit(FormEvent $event) @@ -65,7 +85,13 @@ public function preSubmit(FormEvent $event) if ($form->isRoot() && $form->getConfig()->getOption('compound')) { if (!isset($data[$this->fieldName]) || !$this->csrfProvider->isCsrfTokenValid($this->intention, $data[$this->fieldName])) { - $form->addError(new FormError('The CSRF token is invalid. Please try to resubmit the form.')); + $errorMessage = $this->errorMessage; + + if (null !== $this->translator) { + $errorMessage = $this->translator->trans($errorMessage, array(), $this->translationDomain); + } + + $form->addError(new FormError($errorMessage)); } if (is_array($data)) { diff --git a/Extension/Csrf/Type/FormTypeCsrfExtension.php b/Extension/Csrf/Type/FormTypeCsrfExtension.php index ea13056c86..336cf04756 100644 --- a/Extension/Csrf/Type/FormTypeCsrfExtension.php +++ b/Extension/Csrf/Type/FormTypeCsrfExtension.php @@ -18,21 +18,45 @@ use Symfony\Component\Form\FormView; use Symfony\Component\Form\FormInterface; use Symfony\Component\OptionsResolver\OptionsResolverInterface; +use Symfony\Component\Translation\TranslatorInterface; /** * @author Bernhard Schussek */ class FormTypeCsrfExtension extends AbstractTypeExtension { + /** + * @var CsrfProviderInterface + */ private $defaultCsrfProvider; + + /** + * @var Boolean + */ private $defaultEnabled; + + /** + * @var string + */ private $defaultFieldName; - public function __construct(CsrfProviderInterface $defaultCsrfProvider, $defaultEnabled = true, $defaultFieldName = '_token') + /** + * @var TranslatorInterface + */ + private $translator; + + /** + * @var null|string + */ + private $translationDomain; + + public function __construct(CsrfProviderInterface $defaultCsrfProvider, $defaultEnabled = true, $defaultFieldName = '_token', TranslatorInterface $translator = null, $translationDomain = null) { $this->defaultCsrfProvider = $defaultCsrfProvider; $this->defaultEnabled = $defaultEnabled; $this->defaultFieldName = $defaultFieldName; + $this->translator = $translator; + $this->translationDomain = $translationDomain; } /** @@ -49,7 +73,14 @@ public function buildForm(FormBuilderInterface $builder, array $options) $builder ->setAttribute('csrf_factory', $builder->getFormFactory()) - ->addEventSubscriber(new CsrfValidationListener($options['csrf_field_name'], $options['csrf_provider'], $options['intention'])) + ->addEventSubscriber(new CsrfValidationListener( + $options['csrf_field_name'], + $options['csrf_provider'], + $options['intention'], + $options['csrf_message'], + $this->translator, + $this->translationDomain + )) ; } @@ -83,6 +114,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'csrf_protection' => $this->defaultEnabled, 'csrf_field_name' => $this->defaultFieldName, 'csrf_provider' => $this->defaultCsrfProvider, + 'csrf_message' => 'The CSRF token is invalid. Please try to resubmit the form.', 'intention' => 'unknown', )); } diff --git a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php index 13b305fe4b..0a1f0dc481 100644 --- a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php +++ b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php @@ -13,6 +13,7 @@ use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\FormError; use Symfony\Component\Form\Test\TypeTestCase; use Symfony\Component\Form\Extension\Csrf\CsrfExtension; @@ -33,11 +34,20 @@ public function getName() class FormTypeCsrfExtensionTest extends TypeTestCase { + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ protected $csrfProvider; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $translator; + protected function setUp() { $this->csrfProvider = $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface'); + $this->translator = $this->getMock('Symfony\Component\Translation\TranslatorInterface'); parent::setUp(); } @@ -45,6 +55,7 @@ protected function setUp() protected function tearDown() { $this->csrfProvider = null; + $this->translator = null; parent::tearDown(); } @@ -52,7 +63,7 @@ protected function tearDown() protected function getExtensions() { return array_merge(parent::getExtensions(), array( - new CsrfExtension($this->csrfProvider), + new CsrfExtension($this->csrfProvider, $this->translator), )); } @@ -255,4 +266,36 @@ public function testNoCsrfProtectionOnPrototype() $this->assertFalse(isset($prototypeView['csrf'])); $this->assertCount(1, $prototypeView); } + + public function testsTranslateCustomErrorMessage() + { + $this->csrfProvider->expects($this->once()) + ->method('isCsrfTokenValid') + ->with('%INTENTION%', 'token') + ->will($this->returnValue(false)); + + $this->translator->expects($this->once()) + ->method('trans') + ->with('Foobar') + ->will($this->returnValue('[trans]Foobar[/trans]')); + + $form = $this->factory + ->createBuilder('form', null, array( + 'csrf_field_name' => 'csrf', + 'csrf_provider' => $this->csrfProvider, + 'csrf_message' => 'Foobar', + 'intention' => '%INTENTION%', + 'compound' => true, + )) + ->getForm(); + + $form->submit(array( + 'csrf' => 'token', + )); + + $errors = $form->getErrors(); + + $this->assertGreaterThan(0, count($errors)); + $this->assertEquals(new FormError('[trans]Foobar[/trans]'), $errors[0]); + } } From a882ee0d94e70a3ea693e913fcd3e4be02c3b8e9 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 2 May 2013 11:57:20 +0200 Subject: [PATCH 123/447] [Form] Improved multi-byte handling of NumberToLocalizedStringTransformer --- .../NumberToLocalizedStringTransformer.php | 31 +++- ...NumberToLocalizedStringTransformerTest.php | 142 +++++++++++++++--- 2 files changed, 141 insertions(+), 32 deletions(-) diff --git a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php index b5cdae110d..7c21249fad 100644 --- a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php @@ -80,6 +80,9 @@ public function transform($value) throw new TransformationFailedException($formatter->getErrorMessage()); } + // Convert fixed spaces to normal ones + $value = str_replace("\xc2\xa0", ' ', $value); + return $value; } @@ -130,19 +133,31 @@ public function reverseTransform($value) throw new TransformationFailedException('I don\'t have a clear idea what infinity looks like'); } + if (function_exists('mb_detect_encoding') && false !== $encoding = mb_detect_encoding($value)) { + $strlen = function ($string) use ($encoding) { + return mb_strlen($string, $encoding); + }; + $substr = function ($string, $offset, $length) use ($encoding) { + return mb_substr($string, $offset, $length, $encoding); + }; + } else { + $strlen = 'strlen'; + $substr = 'substr'; + } + + $length = $strlen($value); + // After parsing, position holds the index of the character where the // parsing stopped - if ($position < strlen($value)) { + if ($position < $length) { // Check if there are unrecognized characters at the end of the - // number - $remainder = substr($value, $position); + // number (excluding whitespace characters) + $remainder = trim($substr($value, $position, $length), " \t\n\r\0\x0b\xc2\xa0"); - // Remove all whitespace characters - if ('' !== preg_replace('/[\s\xc2\xa0]*/', '', $remainder)) { + if ('' !== $remainder) { throw new TransformationFailedException( - sprintf('The number contains unrecognized characters: "%s"', - $remainder - )); + sprintf('The number contains unrecognized characters: "%s"', $remainder) + ); } } diff --git a/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php index 151dbc80f6..09af7243d6 100644 --- a/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php @@ -22,29 +22,52 @@ protected function setUp() \Locale::setDefault('de_AT'); } - public function testTransform() + public function provideTransformations() { - $transformer = new NumberToLocalizedStringTransformer(); - - $this->assertEquals('1', $transformer->transform(1)); - $this->assertEquals('1,5', $transformer->transform(1.5)); - $this->assertEquals('1234,5', $transformer->transform(1234.5)); - $this->assertEquals('12345,912', $transformer->transform(12345.9123)); + return array( + array(null, '', 'de_AT'), + array(1, '1', 'de_AT'), + array(1.5, '1,5', 'de_AT'), + array(1234.5, '1234,5', 'de_AT'), + array(12345.912, '12345,912', 'de_AT'), + array(1234.5, '1234,5', 'ru'), + array(1234.5, '1234,5', 'fi'), + ); } - public function testTransformEmpty() + /** + * @dataProvider provideTransformations + */ + public function testTransform($from, $to, $locale) { + \Locale::setDefault($locale); + $transformer = new NumberToLocalizedStringTransformer(); - $this->assertSame('', $transformer->transform(null)); + $this->assertSame($to, $transformer->transform($from)); + } + + public function provideTransformationsWithGrouping() + { + return array( + array(1234.5, '1.234,5', 'de_AT'), + array(12345.912, '12.345,912', 'de_AT'), + array(1234.5, '1 234,5', 'fr'), + array(1234.5, '1 234,5', 'ru'), + array(1234.5, '1 234,5', 'fi'), + ); } - public function testTransformWithGrouping() + /** + * @dataProvider provideTransformationsWithGrouping + */ + public function testTransformWithGrouping($from, $to, $locale) { + \Locale::setDefault($locale); + $transformer = new NumberToLocalizedStringTransformer(null, true); - $this->assertEquals('1.234,5', $transformer->transform(1234.5)); - $this->assertEquals('12.345,912', $transformer->transform(12345.9123)); + $this->assertSame($to, $transformer->transform($from)); } public function testTransformWithPrecision() @@ -65,30 +88,48 @@ public function testTransformWithRoundingMode() } - public function testReverseTransform() + /** + * @dataProvider provideTransformations + */ + public function testReverseTransform($to, $from, $locale) { + \Locale::setDefault($locale); + $transformer = new NumberToLocalizedStringTransformer(); - $this->assertEquals(1, $transformer->reverseTransform('1')); - $this->assertEquals(1.5, $transformer->reverseTransform('1,5')); - $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); - $this->assertEquals(12345.912, $transformer->reverseTransform('12345,912')); + $this->assertEquals($to, $transformer->reverseTransform($from)); } - public function testReverseTransformEmpty() + /** + * @dataProvider provideTransformationsWithGrouping + */ + public function testReverseTransformWithGrouping($to, $from, $locale) { - $transformer = new NumberToLocalizedStringTransformer(); + \Locale::setDefault($locale); + + $transformer = new NumberToLocalizedStringTransformer(null, true); + + $this->assertEquals($to, $transformer->reverseTransform($from)); + } + + // https://github.com/symfony/symfony/issues/7609 + public function testReverseTransformWithGroupingAndFixedSpaces() + { + if (!extension_loaded('mbstring')) { + $this->markTestSkipped('The "mbstring" extension is required for this test.'); + } + + \Locale::setDefault('ru'); + + $transformer = new NumberToLocalizedStringTransformer(null, true); - $this->assertNull($transformer->reverseTransform('')); + $this->assertEquals(1234.5, $transformer->reverseTransform("1\xc2\xa0234,5")); } - public function testReverseTransformWithGrouping() + public function testReverseTransformWithGroupingButWithoutGroupSeparator() { $transformer = new NumberToLocalizedStringTransformer(null, true); - // completely valid format - $this->assertEquals(1234.5, $transformer->reverseTransform('1.234,5')); - $this->assertEquals(12345.912, $transformer->reverseTransform('12.345,912')); // omit group separator $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); $this->assertEquals(12345.912, $transformer->reverseTransform('12345,912')); @@ -299,6 +340,7 @@ public function testReverseTransformDisallowsLeadingExtraCharacters() /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + * @expectedExceptionMessage The number contains unrecognized characters: "foo3" */ public function testReverseTransformDisallowsCenteredExtraCharacters() { @@ -309,6 +351,41 @@ public function testReverseTransformDisallowsCenteredExtraCharacters() /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + * @expectedExceptionMessage The number contains unrecognized characters: "foo8" + */ + public function testReverseTransformDisallowsCenteredExtraCharactersMultibyte() + { + if (!extension_loaded('mbstring')) { + $this->markTestSkipped('The "mbstring" extension is required for this test.'); + } + + \Locale::setDefault('ru'); + + $transformer = new NumberToLocalizedStringTransformer(null, true); + + $transformer->reverseTransform("12\xc2\xa0345,67foo8"); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + * @expectedExceptionMessage The number contains unrecognized characters: "foo8" + */ + public function testReverseTransformIgnoresTrailingSpacesInExceptionMessage() + { + if (!extension_loaded('mbstring')) { + $this->markTestSkipped('The "mbstring" extension is required for this test.'); + } + + \Locale::setDefault('ru'); + + $transformer = new NumberToLocalizedStringTransformer(null, true); + + $transformer->reverseTransform("12\xc2\xa0345,67foo8 \xc2\xa0\t"); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + * @expectedExceptionMessage The number contains unrecognized characters: "foo" */ public function testReverseTransformDisallowsTrailingExtraCharacters() { @@ -316,4 +393,21 @@ public function testReverseTransformDisallowsTrailingExtraCharacters() $transformer->reverseTransform('123foo'); } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + * @expectedExceptionMessage The number contains unrecognized characters: "foo" + */ + public function testReverseTransformDisallowsTrailingExtraCharactersMultibyte() + { + if (!extension_loaded('mbstring')) { + $this->markTestSkipped('The "mbstring" extension is required for this test.'); + } + + \Locale::setDefault('ru'); + + $transformer = new NumberToLocalizedStringTransformer(null, true); + + $transformer->reverseTransform("12\xc2\xa0345,678foo"); + } } From 6ba80cea677b6765ca97da4d7bcdc32e542d5805 Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Sat, 4 May 2013 02:14:05 +0200 Subject: [PATCH 124/447] [Form] removed deprecated exceptions --- Exception/Exception.php | 26 -------------------------- Exception/ExceptionInterface.php | 2 +- Exception/FormException.php | 24 ------------------------ 3 files changed, 1 insertion(+), 51 deletions(-) delete mode 100644 Exception/Exception.php delete mode 100644 Exception/FormException.php diff --git a/Exception/Exception.php b/Exception/Exception.php deleted file mode 100644 index b882d70396..0000000000 --- a/Exception/Exception.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Exception; - -/** - * Base exception class. - * - * @author Bernhard Schussek - * - * @deprecated This class is a replacement for when class FormException was - * used previously. It should not be used and will be removed. - * Occurrences of this class should be replaced by more specialized - * exception classes, preferably derived from SPL exceptions. - */ -class Exception extends \Exception implements ExceptionInterface -{ -} diff --git a/Exception/ExceptionInterface.php b/Exception/ExceptionInterface.php index 975bdb89ad..d455932edf 100644 --- a/Exception/ExceptionInterface.php +++ b/Exception/ExceptionInterface.php @@ -16,6 +16,6 @@ * * @author Bernhard Schussek */ -interface ExceptionInterface extends FormException +interface ExceptionInterface { } diff --git a/Exception/FormException.php b/Exception/FormException.php deleted file mode 100644 index dbc6d06499..0000000000 --- a/Exception/FormException.php +++ /dev/null @@ -1,24 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Exception; - -/** - * Alias of {@link ExceptionInterface}. - * - * @author Bernhard Schussek - * - * @deprecated This interface was deprecated and will be removed in Symfony 2.3. - * You should code against {@link ExceptionInterface} instead. - */ -interface FormException -{ -} From 36fc35842853b5ce45ccb4c11eca2c863c9ba86f Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Sat, 4 May 2013 13:21:24 +0200 Subject: [PATCH 125/447] [Form] Fixed failing test --- .../Extension/Csrf/EventListener/CsrfValidationListenerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php index 33184c029d..0bcfe74e99 100644 --- a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php +++ b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php @@ -69,7 +69,7 @@ public function testStringFormData() $data = "XP4HUzmHPi"; $event = new FormEvent($this->form, $data); - $validation = new CsrfValidationListener('csrf', $this->csrfProvider, 'unknown'); + $validation = new CsrfValidationListener('csrf', $this->csrfProvider, 'unknown', 'Invalid.'); $validation->preSubmit($event); // Validate accordingly From eee28e5bf121a9af4c3c340689c192f0aa6fc3c8 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Sun, 5 May 2013 20:21:56 +0200 Subject: [PATCH 126/447] [Form] Added radio button for empty value to expanded single-choice fields --- CHANGELOG.md | 1 + .../Core/ChoiceList/ChoiceListInterface.php | 18 +- .../ChoiceToBooleanArrayTransformer.php | 12 +- .../EventListener/FixRadioInputListener.php | 8 +- Extension/Core/Type/ChoiceType.php | 45 ++-- Tests/AbstractLayoutTest.php | 10 +- .../FixRadioInputListenerTest.php | 53 ++++- Tests/Extension/Core/Type/ChoiceTypeTest.php | 212 +++++++++++++++++- 8 files changed, 315 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cc800d0af..a696c7be9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ CHANGELOG unless FormInterface::setData() is called manually * fixed CSRF error message to be translated * custom CSRF error messages can now be set through the "csrf_message" option + * fixed: expanded single-choice fields now show a radio button for the empty value 2.2.0 ----- diff --git a/Extension/Core/ChoiceList/ChoiceListInterface.php b/Extension/Core/ChoiceList/ChoiceListInterface.php index c81c560f4f..e0ba818b18 100644 --- a/Extension/Core/ChoiceList/ChoiceListInterface.php +++ b/Extension/Core/ChoiceList/ChoiceListInterface.php @@ -95,6 +95,8 @@ public function getRemainingViews(); /** * Returns the choices corresponding to the given values. * + * The choices can have any data type. + * * @param array $values An array of choice values. Not existing values in * this array are ignored. * @@ -105,6 +107,8 @@ public function getChoicesForValues(array $values); /** * Returns the values corresponding to the given choices. * + * The values must be a strings. + * * @param array $choices An array of choices. Not existing choices in this * array are ignored. * @@ -116,20 +120,30 @@ public function getValuesForChoices(array $choices); /** * Returns the indices corresponding to the given choices. * + * The indices must be positive integers or strings accepted by + * {@link FormConfigBuilder::validateName()}. + * + * The index "placeholder" is internally reserved. + * * @param array $choices An array of choices. Not existing choices in this * array are ignored. * - * @return array An array of indices with ascending, 0-based numeric keys + * @return array An array of indices with ascending, 0-based numeric keys. */ public function getIndicesForChoices(array $choices); /** * Returns the indices corresponding to the given values. * + * The indices must be positive integers or strings accepted by + * {@link FormConfigBuilder::validateName()}. + * + * The index "placeholder" is internally reserved. + * * @param array $values An array of choice values. Not existing values in * this array are ignored. * - * @return array An array of indices with ascending, 0-based numeric keys + * @return array An array of indices with ascending, 0-based numeric keys. */ public function getIndicesForValues(array $values); } diff --git a/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php b/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php index 59fe9dbcea..edd58e144d 100644 --- a/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php +++ b/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php @@ -23,14 +23,18 @@ class ChoiceToBooleanArrayTransformer implements DataTransformerInterface { private $choiceList; + private $placeholderPresent; + /** * Constructor. * * @param ChoiceListInterface $choiceList + * @param Boolean $placeholderPresent */ - public function __construct(ChoiceListInterface $choiceList) + public function __construct(ChoiceListInterface $choiceList, $placeholderPresent) { $this->choiceList = $choiceList; + $this->placeholderPresent = $placeholderPresent; } /** @@ -63,6 +67,10 @@ public function transform($choice) $values[$i] = $i === $index; } + if ($this->placeholderPresent) { + $values['placeholder'] = false === $index; + } + return $values; } @@ -97,6 +105,8 @@ public function reverseTransform($values) if ($selected) { if (isset($choices[$i])) { return $choices[$i] === '' ? null : $choices[$i]; + } elseif ($this->placeholderPresent && 'placeholder' === $i) { + return null; } else { throw new TransformationFailedException(sprintf('The choice "%s" does not exist', $i)); } diff --git a/Extension/Core/EventListener/FixRadioInputListener.php b/Extension/Core/EventListener/FixRadioInputListener.php index b045ca8fd1..bf03792fed 100644 --- a/Extension/Core/EventListener/FixRadioInputListener.php +++ b/Extension/Core/EventListener/FixRadioInputListener.php @@ -26,14 +26,18 @@ class FixRadioInputListener implements EventSubscriberInterface { private $choiceList; + private $placeholderPresent; + /** * Constructor. * * @param ChoiceListInterface $choiceList + * @param Boolean $placeholderPresent */ - public function __construct(ChoiceListInterface $choiceList) + public function __construct(ChoiceListInterface $choiceList, $placeholderPresent) { $this->choiceList = $choiceList; + $this->placeholderPresent = $placeholderPresent; } public function preSubmit(FormEvent $event) @@ -41,7 +45,7 @@ public function preSubmit(FormEvent $event) $value = $event->getData(); $index = current($this->choiceList->getIndicesForValues(array($value))); - $event->setData(false !== $index ? array($index => $value) : array()); + $event->setData(false !== $index ? array($index => $value) : ($this->placeholderPresent ? array('placeholder' => '') : array())) ; } /** diff --git a/Extension/Core/Type/ChoiceType.php b/Extension/Core/Type/ChoiceType.php index 446a74dd6e..9a3fdef12b 100644 --- a/Extension/Core/Type/ChoiceType.php +++ b/Extension/Core/Type/ChoiceType.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\Extension\Core\View\ChoiceView; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; @@ -45,19 +46,34 @@ public function buildForm(FormBuilderInterface $builder, array $options) } if ($options['expanded']) { - $this->addSubForms($builder, $options['choice_list']->getPreferredViews(), $options); - $this->addSubForms($builder, $options['choice_list']->getRemainingViews(), $options); + // Initialize all choices before doing the index check below. + // This helps in cases where index checks are optimized for non + // initialized choice lists. For example, when using an SQL driver, + // the index check would read in one SQL query and the initialization + // requires another SQL query. When the initialization is done first, + // one SQL query is sufficient. + $preferredViews = $options['choice_list']->getPreferredViews(); + $remainingViews = $options['choice_list']->getRemainingViews(); + + // Check if the choices already contain the empty value + // Only add the empty value option if this is not the case + if (null !== $options['empty_value'] && 0 === count($options['choice_list']->getIndicesForValues(array('')))) { + $placeholderView = new ChoiceView(null, '', $options['empty_value']); + + // "placeholder" is a reserved index + // see also ChoiceListInterface::getIndicesForChoices() + $this->addSubForms($builder, array('placeholder' => $placeholderView), $options); + } + + $this->addSubForms($builder, $preferredViews, $options); + $this->addSubForms($builder, $remainingViews, $options); if ($options['multiple']) { - $builder - ->addViewTransformer(new ChoicesToBooleanArrayTransformer($options['choice_list'])) - ->addEventSubscriber(new FixCheckboxInputListener($options['choice_list']), 10) - ; + $builder->addViewTransformer(new ChoicesToBooleanArrayTransformer($options['choice_list'])); + $builder->addEventSubscriber(new FixCheckboxInputListener($options['choice_list']), 10); } else { - $builder - ->addViewTransformer(new ChoiceToBooleanArrayTransformer($options['choice_list'])) - ->addEventSubscriber(new FixRadioInputListener($options['choice_list']), 10) - ; + $builder->addViewTransformer(new ChoiceToBooleanArrayTransformer($options['choice_list'], $builder->has('placeholder'))); + $builder->addEventSubscriber(new FixRadioInputListener($options['choice_list'], $builder->has('placeholder')), 10); } } else { if ($options['multiple']) { @@ -104,7 +120,7 @@ public function buildView(FormView $view, FormInterface $form, array $options) // Check if the choices already contain the empty value // Only add the empty value option if this is not the case - if (0 === count($options['choice_list']->getIndicesForValues(array('')))) { + if (null !== $options['empty_value'] && 0 === count($options['choice_list']->getIndicesForValues(array('')))) { $view->vars['empty_value'] = $options['empty_value']; } @@ -170,12 +186,15 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) }; $emptyValueNormalizer = function (Options $options, $emptyValue) { - if ($options['multiple'] || $options['expanded']) { - // never use an empty value for these cases + if ($options['multiple']) { + // never use an empty value for this case return null; } elseif (false === $emptyValue) { // an empty value should be added but the user decided otherwise return null; + } elseif ($options['expanded'] && '' === $emptyValue) { + // never use an empty label for radio buttons + return 'None'; } // empty value has been set explicitly diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index 1a48fae194..8f632a2b50 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -634,7 +634,7 @@ public function testMultipleChoice() ); } - public function testMultipleChoiceSkipEmptyValue() + public function testMultipleChoiceSkipsEmptyValue() { $form = $this->factory->createNamed('name', 'choice', array('&a'), array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), @@ -700,7 +700,7 @@ public function testSingleChoiceExpanded() ); } - public function testSingleChoiceExpandedSkipEmptyValue() + public function testSingleChoiceExpandedWithEmptyValue() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), @@ -712,13 +712,15 @@ public function testSingleChoiceExpandedSkipEmptyValue() $this->assertWidgetMatchesXpath($form->createView(), array(), '/div [ - ./input[@type="radio"][@name="name"][@id="name_0"][@checked] + ./input[@type="radio"][@name="name"][@id="name_placeholder"][not(@checked)] + /following-sibling::label[@for="name_placeholder"][.="[trans]Test&Me[/trans]"] + /following-sibling::input[@type="radio"][@name="name"][@id="name_0"][@checked] /following-sibling::label[@for="name_0"][.="[trans]Choice&A[/trans]"] /following-sibling::input[@type="radio"][@name="name"][@id="name_1"][not(@checked)] /following-sibling::label[@for="name_1"][.="[trans]Choice&B[/trans]"] /following-sibling::input[@type="hidden"][@id="name__token"] ] - [count(./input)=3] + [count(./input)=4] ' ); } diff --git a/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php b/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php index 955f56663f..a5d5c78a81 100644 --- a/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php +++ b/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php @@ -17,7 +17,7 @@ class FixRadioInputListenerTest extends \PHPUnit_Framework_TestCase { - private $listener; + private $choiceList; protected function setUp() { @@ -27,15 +27,14 @@ protected function setUp() parent::setUp(); - $list = new SimpleChoiceList(array(0 => 'A', 1 => 'B')); - $this->listener = new FixRadioInputListener($list); + $this->choiceList = new SimpleChoiceList(array('' => 'Empty', 0 => 'A', 1 => 'B')); } protected function tearDown() { parent::tearDown(); - $this->listener = null; + $listener = null; } public function testFixRadio() @@ -44,9 +43,11 @@ public function testFixRadio() $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); - $this->listener->preSubmit($event); + $listener = new FixRadioInputListener($this->choiceList, true); + $listener->preSubmit($event); - $this->assertEquals(array(1 => '1'), $event->getData()); + // Indices in SimpleChoiceList are zero-based generated integers + $this->assertEquals(array(2 => '1'), $event->getData()); } public function testFixZero() @@ -55,18 +56,50 @@ public function testFixZero() $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); - $this->listener->preSubmit($event); + $listener = new FixRadioInputListener($this->choiceList, true); + $listener->preSubmit($event); - $this->assertEquals(array(0 => '0'), $event->getData()); + // Indices in SimpleChoiceList are zero-based generated integers + $this->assertEquals(array(1 => '0'), $event->getData()); } - public function testIgnoreEmptyString() + public function testFixEmptyString() { $data = ''; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); - $this->listener->preSubmit($event); + $listener = new FixRadioInputListener($this->choiceList, true); + $listener->preSubmit($event); + + // Indices in SimpleChoiceList are zero-based generated integers + $this->assertEquals(array(0 => ''), $event->getData()); + } + + public function testConvertEmptyStringToPlaceholderIfNotFound() + { + $list = new SimpleChoiceList(array(0 => 'A', 1 => 'B')); + + $data = ''; + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); + $event = new FormEvent($form, $data); + + $listener = new FixRadioInputListener($list, true); + $listener->preSubmit($event); + + $this->assertEquals(array('placeholder' => ''), $event->getData()); + } + + public function testDontConvertEmptyStringToPlaceholderIfNoPlaceholderUsed() + { + $list = new SimpleChoiceList(array(0 => 'A', 1 => 'B')); + + $data = ''; + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); + $event = new FormEvent($form, $data); + + $listener = new FixRadioInputListener($list, false); + $listener->preSubmit($event); $this->assertEquals(array(), $event->getData()); } diff --git a/Tests/Extension/Core/Type/ChoiceTypeTest.php b/Tests/Extension/Core/Type/ChoiceTypeTest.php index 9499d7607f..219e8181c0 100644 --- a/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -88,8 +88,7 @@ public function testChoiceListOptionExpectsChoiceListInterface() public function testChoiceListAndChoicesCanBeEmpty() { - $this->factory->create('choice', null, array( - )); + $this->factory->create('choice'); } public function testExpandedChoicesOptionsTurnIntoChildren() @@ -99,7 +98,62 @@ public function testExpandedChoicesOptionsTurnIntoChildren() 'choices' => $this->choices, )); - $this->assertCount($form->count(), $this->choices, 'Each choice should become a new field'); + $this->assertCount(count($this->choices), $form, 'Each choice should become a new field'); + } + + public function testPlaceholderPresentOnNonRequiredExpandedSingleChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => false, + 'choices' => $this->choices, + )); + + $this->assertTrue(isset($form['placeholder'])); + $this->assertCount(count($this->choices) + 1, $form, 'Each choice should become a new field'); + } + + public function testPlaceholderNotPresentIfRequired() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => true, + 'choices' => $this->choices, + )); + + $this->assertFalse(isset($form['placeholder'])); + $this->assertCount(count($this->choices), $form, 'Each choice should become a new field'); + } + + public function testPlaceholderNotPresentIfMultiple() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'expanded' => true, + 'required' => false, + 'choices' => $this->choices, + )); + + $this->assertFalse(isset($form['placeholder'])); + $this->assertCount(count($this->choices), $form, 'Each choice should become a new field'); + } + + public function testPlaceholderNotPresentIfEmptyChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => false, + 'choices' => array( + '' => 'Empty', + 1 => 'Not empty', + ), + )); + + $this->assertFalse(isset($form['placeholder'])); + $this->assertCount(2, $form, 'Each choice should become a new field'); } public function testExpandedChoicesOptionsAreFlattened() @@ -236,17 +290,26 @@ public function testSubmitMultipleNonExpandedObjectChoices() $this->assertEquals(array('2', '3'), $form->getViewData()); } - public function testSubmitSingleExpanded() + public function testSubmitSingleExpandedRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, + 'required' => true, 'choices' => $this->choices, )); $form->submit('b'); $this->assertSame('b', $form->getData()); + $this->assertSame(array( + 0 => false, + 1 => true, + 2 => false, + 3 => false, + 4 => false, + ), $form->getViewData()); + $this->assertFalse($form[0]->getData()); $this->assertTrue($form[1]->getData()); $this->assertFalse($form[2]->getData()); @@ -259,22 +322,101 @@ public function testSubmitSingleExpanded() $this->assertNull($form[4]->getViewData()); } - public function testSubmitSingleExpandedNothingChecked() + public function testSubmitSingleExpandedNonRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, + 'required' => false, + 'choices' => $this->choices, + )); + + $form->submit('b'); + + $this->assertSame('b', $form->getData()); + $this->assertSame(array( + 0 => false, + 1 => true, + 2 => false, + 3 => false, + 4 => false, + 'placeholder' => false, + ), $form->getViewData()); + + $this->assertFalse($form['placeholder']->getData()); + $this->assertFalse($form[0]->getData()); + $this->assertTrue($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form['placeholder']->getViewData()); + $this->assertNull($form[0]->getViewData()); + $this->assertSame('b', $form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testSubmitSingleExpandedRequiredNothingChecked() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => true, + 'choices' => $this->choices, + )); + + $form->submit(null); + + $this->assertNull($form->getData()); + $this->assertSame(array( + 0 => false, + 1 => false, + 2 => false, + 3 => false, + 4 => false, + ), $form->getViewData()); + + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testSubmitSingleExpandedNonRequiredNothingChecked() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => false, 'choices' => $this->choices, )); $form->submit(null); $this->assertNull($form->getData()); + $this->assertSame(array( + 0 => false, + 1 => false, + 2 => false, + 3 => false, + 4 => false, + 'placeholder' => true, + ), $form->getViewData()); + + $this->assertTrue($form['placeholder']->getData()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); $this->assertFalse($form[3]->getData()); $this->assertFalse($form[4]->getData()); + $this->assertSame('', $form['placeholder']->getViewData()); $this->assertNull($form[0]->getViewData()); $this->assertNull($form[1]->getViewData()); $this->assertNull($form[2]->getViewData()); @@ -282,11 +424,27 @@ public function testSubmitSingleExpandedNothingChecked() $this->assertNull($form[4]->getViewData()); } - public function testSubmitSingleExpandedWithFalseDoesNotHaveExtraChildren() + public function testSubmitFalseToSingleExpandedRequiredDoesNotProduceExtraChildrenError() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => true, + 'choices' => $this->choices, + )); + + $form->submit(false); + + $this->assertEmpty($form->getExtraData()); + $this->assertNull($form->getData()); + } + + public function testSubmitFalseToSingleExpandedNonRequiredDoesNotProduceExtraChildrenError() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, + 'required' => false, 'choices' => $this->choices, )); @@ -568,10 +726,11 @@ public function testPassExpandedToView() $this->assertTrue($view->vars['expanded']); } - public function testNotPassedEmptyValueToViewIsNull() + public function testEmptyValueIsNullByDefaultIfRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => false, + 'required' => true, 'choices' => $this->choices, )); $view = $form->createView(); @@ -579,7 +738,7 @@ public function testNotPassedEmptyValueToViewIsNull() $this->assertNull($view->vars['empty_value']); } - public function testPassEmptyValueToViewIsEmpty() + public function testEmptyValueIsEmptyStringByDefaultIfNotRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => false, @@ -588,7 +747,7 @@ public function testPassEmptyValueToViewIsEmpty() )); $view = $form->createView(); - $this->assertEmpty($view->vars['empty_value']); + $this->assertSame('', $view->vars['empty_value']); } /** @@ -628,15 +787,44 @@ public function testDontPassEmptyValueIfContainedInChoices($multiple, $expanded, public function getOptionsWithEmptyValue() { return array( + // single non-expanded array(false, false, false, 'foobar', 'foobar'), - array(true, false, false, 'foobar', null), - array(false, true, false, 'foobar', null), + array(false, false, false, '', ''), + array(false, false, false, null, null), + array(false, false, false, false, null), array(false, false, true, 'foobar', 'foobar'), array(false, false, true, '', ''), array(false, false, true, null, null), - array(false, true, true, 'foobar', null), + array(false, false, true, false, null), + // single expanded + array(false, true, false, 'foobar', 'foobar'), + // radios should never have an empty label + array(false, true, false, '', 'None'), + array(false, true, false, null, null), + array(false, true, false, false, null), + array(false, true, true, 'foobar', 'foobar'), + // radios should never have an empty label + array(false, true, true, '', 'None'), + array(false, true, true, null, null), + array(false, true, true, false, null), + // multiple non-expanded + array(true, false, false, 'foobar', null), + array(true, false, false, '', null), + array(true, false, false, null, null), + array(true, false, false, false, null), + array(true, false, true, 'foobar', null), + array(true, false, true, '', null), + array(true, false, true, null, null), + array(true, false, true, false, null), + // multiple expanded array(true, true, false, 'foobar', null), + array(true, true, false, '', null), + array(true, true, false, null, null), + array(true, true, false, false, null), array(true, true, true, 'foobar', null), + array(true, true, true, '', null), + array(true, true, true, null, null), + array(true, true, true, false, null), ); } From 41bbd2a41638cdbc5c85e6230c18e782668b19ce Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 6 May 2013 08:14:04 +0200 Subject: [PATCH 127/447] fixed CS --- .../Core/ChoiceList/ChoiceListInterface.php | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Extension/Core/ChoiceList/ChoiceListInterface.php b/Extension/Core/ChoiceList/ChoiceListInterface.php index e0ba818b18..099ace8253 100644 --- a/Extension/Core/ChoiceList/ChoiceListInterface.php +++ b/Extension/Core/ChoiceList/ChoiceListInterface.php @@ -31,14 +31,14 @@ interface ChoiceListInterface /** * Returns the list of choices * - * @return array The choices with their indices as keys. + * @return array The choices with their indices as keys */ public function getChoices(); /** * Returns the values for the choices * - * @return array The values with the corresponding choice indices as keys. + * @return array The values with the corresponding choice indices as keys */ public function getValues(); @@ -62,7 +62,7 @@ public function getValues(); * * @return array A nested array containing the views with the corresponding * choice indices as keys on the lowest levels and the choice - * group names in the keys of the higher levels. + * group names in the keys of the higher levels */ public function getPreferredViews(); @@ -86,7 +86,7 @@ public function getPreferredViews(); * * @return array A nested array containing the views with the corresponding * choice indices as keys on the lowest levels and the choice - * group names in the keys of the higher levels. + * group names in the keys of the higher levels * * @see getPreferredValues */ @@ -98,7 +98,7 @@ public function getRemainingViews(); * The choices can have any data type. * * @param array $values An array of choice values. Not existing values in - * this array are ignored. + * this array are ignored * * @return array An array of choices with ascending, 0-based numeric keys */ @@ -107,10 +107,10 @@ public function getChoicesForValues(array $values); /** * Returns the values corresponding to the given choices. * - * The values must be a strings. + * The values must be strings. * * @param array $choices An array of choices. Not existing choices in this - * array are ignored. + * array are ignored * * @return array An array of choice values with ascending, 0-based numeric * keys @@ -126,9 +126,9 @@ public function getValuesForChoices(array $choices); * The index "placeholder" is internally reserved. * * @param array $choices An array of choices. Not existing choices in this - * array are ignored. + * array are ignored * - * @return array An array of indices with ascending, 0-based numeric keys. + * @return array An array of indices with ascending, 0-based numeric keys */ public function getIndicesForChoices(array $choices); @@ -141,9 +141,9 @@ public function getIndicesForChoices(array $choices); * The index "placeholder" is internally reserved. * * @param array $values An array of choice values. Not existing values in - * this array are ignored. + * this array are ignored * - * @return array An array of indices with ascending, 0-based numeric keys. + * @return array An array of indices with ascending, 0-based numeric keys */ public function getIndicesForValues(array $values); } From 9a12820fa23ee07315200256a1e6e262c3c0f1bf Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Thu, 9 May 2013 23:31:20 +0100 Subject: [PATCH 128/447] [Form] Fixed a method name. 1858b96b7dc473fcab09533b17ace9a24b8d3d86 introduced a mocked context and therefore getExecutionContext() is now called getMockExectionContext(). --- .../Validator/Constraints/FormValidatorTest.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index 48f6123426..f1ee046551 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -293,17 +293,16 @@ public function testHandleCallbackValidationGroups() public function testDontExecuteFunctionNames() { - $context = $this->getExecutionContext(); - $graphWalker = $context->getGraphWalker(); + $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => 'header'); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); - $graphWalker->expects($this->once()) - ->method('walkReference') - ->with($object, 'header', 'data', true); + $context->expects($this->once()) + ->method('validate') + ->with($object, 'data', 'header', true); $this->validator->initialize($context); $this->validator->validate($form, new Form()); From 24d67f58267b4f5457be16288ff0bf49dd0d8439 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 13 May 2013 09:33:35 +0200 Subject: [PATCH 129/447] changed all version deps to accepts all upcoming Symfony versions --- composer.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 107561edae..2a141646d4 100644 --- a/composer.json +++ b/composer.json @@ -19,12 +19,12 @@ "php": ">=5.3.3", "symfony/event-dispatcher": "~2.1", "symfony/intl": "~2.3", - "symfony/options-resolver": ">=2.1,<2.4-dev", - "symfony/property-access": ">=2.2,<2.4-dev" + "symfony/options-resolver": "~2.1", + "symfony/property-access": "~2.2" }, "require-dev": { - "symfony/validator": ">=2.2,<2.4-dev", - "symfony/http-foundation": ">=2.1,<2.4-dev" + "symfony/validator": "~2.2", + "symfony/http-foundation": "~2.2" }, "suggest": { "symfony/validator": "2.2.*", From 4d652cc0c38a5e35de01716b98cefdddbf06c61c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 13 May 2013 16:36:40 +0200 Subject: [PATCH 130/447] removed versions in composer.json files --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 2a141646d4..734150118b 100644 --- a/composer.json +++ b/composer.json @@ -27,8 +27,8 @@ "symfony/http-foundation": "~2.2" }, "suggest": { - "symfony/validator": "2.2.*", - "symfony/http-foundation": "2.2.*" + "symfony/validator": "", + "symfony/http-foundation": "" }, "autoload": { "psr-0": { "Symfony\\Component\\Form\\": "" } From 208488ac743310d803f3e931f28a67f04f9f4efd Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 16 May 2013 09:54:39 +0200 Subject: [PATCH 131/447] updated version to 2.4 --- README.md | 2 +- composer.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7bfff7fd22..865d36ecad 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ https://github.com/fabpot/Silex/blob/master/src/Silex/Provider/FormServiceProvid Documentation: -http://symfony.com/doc/2.3/book/forms.html +http://symfony.com/doc/2.4/book/forms.html Resources --------- diff --git a/composer.json b/composer.json index 734150118b..dda5959c9a 100644 --- a/composer.json +++ b/composer.json @@ -37,7 +37,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "2.3-dev" + "dev-master": "2.4-dev" } } } From 78d1f2398a3af5d24b969566767f1a9709478253 Mon Sep 17 00:00:00 2001 From: Bilal Amarni Date: Fri, 24 May 2013 03:04:47 +0300 Subject: [PATCH 132/447] [Form] [2.3] removed old option --- Extension/Validator/Type/FormTypeValidatorExtension.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Extension/Validator/Type/FormTypeValidatorExtension.php b/Extension/Validator/Type/FormTypeValidatorExtension.php index 99ef51f2bf..2105997242 100644 --- a/Extension/Validator/Type/FormTypeValidatorExtension.php +++ b/Extension/Validator/Type/FormTypeValidatorExtension.php @@ -62,7 +62,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) $resolver->setDefaults(array( 'error_mapping' => array(), - 'validation_constraint' => null, 'constraints' => array(), 'cascade_validation' => false, 'invalid_message' => 'This value is not valid.', From c1bba3459f45c4e6473eb9ea850d9bc3f4763bd6 Mon Sep 17 00:00:00 2001 From: Felds Liscia Date: Fri, 24 May 2013 14:02:19 -0300 Subject: [PATCH 133/447] add allow_extra_fields option --- .../Validator/Constraints/FormValidator.php | 2 +- .../Type/FormTypeValidatorExtension.php | 1 + .../Constraints/FormValidatorTest.php | 22 +++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Extension/Validator/Constraints/FormValidator.php b/Extension/Validator/Constraints/FormValidator.php index 1b8b68ed83..b14523755f 100644 --- a/Extension/Validator/Constraints/FormValidator.php +++ b/Extension/Validator/Constraints/FormValidator.php @@ -107,7 +107,7 @@ public function validate($form, Constraint $constraint) } // Mark the form with an error if it contains extra fields - if (count($form->getExtraData()) > 0) { + if (!$config->getOption('allow_extra_fields') && count($form->getExtraData()) > 0) { $this->context->addViolation( $config->getOption('extra_fields_message'), array('{{ extra_fields }}' => implode('", "', array_keys($form->getExtraData()))), diff --git a/Extension/Validator/Type/FormTypeValidatorExtension.php b/Extension/Validator/Type/FormTypeValidatorExtension.php index 99ef51f2bf..38e1ca5d31 100644 --- a/Extension/Validator/Type/FormTypeValidatorExtension.php +++ b/Extension/Validator/Type/FormTypeValidatorExtension.php @@ -67,6 +67,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'cascade_validation' => false, 'invalid_message' => 'This value is not valid.', 'invalid_message_parameters' => array(), + 'allow_extra_fields' => false, 'extra_fields_message' => 'This form should not contain extra fields.', 'post_max_size_message' => 'The uploaded file was too large. Please try to upload a smaller file.', )); diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index 79d004cd6f..2c4a239ae8 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -615,6 +615,28 @@ public function testViolationIfExtraData() $this->validator->validate($form, new Form()); } + public function testNoViolationIfAllowExtraData() + { + $context = $this->getMockExecutionContext(); + + $form = $this + ->getBuilder('parent', null, array('allow_extra_fields' => true)) + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->add($this->getBuilder('child')) + ->getForm(); + + $form->bind(array('foo' => 'bar')); + + $context->expects($this->never()) + ->method('addViolation'); + $context->expects($this->never()) + ->method('addViolationAt'); + + $this->validator->initialize($context); + $this->validator->validate($form, new Form()); + } + /** * @dataProvider getPostMaxSizeFixtures */ From c1ebbbdb07e1c1cde5c00b110fc575a717bd3538 Mon Sep 17 00:00:00 2001 From: Douglas Greenshields Date: Tue, 11 Jun 2013 12:21:03 +0100 Subject: [PATCH 134/447] [Form] corrected interface bind() method defined against in deprecation notice --- Form.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Form.php b/Form.php index f1c8e5cc60..55d80c2f9f 100644 --- a/Form.php +++ b/Form.php @@ -649,11 +649,11 @@ public function bind($submittedData) * @throws FormException if the method of the request is not one of GET, POST or PUT * * @deprecated Deprecated since version 2.1, to be removed in 2.3. Use - * {@link FormConfigInterface::bind()} instead. + * {@link FormInterface::bind()} instead. */ public function bindRequest(Request $request) { - trigger_error('bindRequest() is deprecated since version 2.1 and will be removed in 2.3. Use FormConfigInterface::bind() instead.', E_USER_DEPRECATED); + trigger_error('bindRequest() is deprecated since version 2.1 and will be removed in 2.3. Use FormInterface::bind() instead.', E_USER_DEPRECATED); return $this->bind($request); } From 12af2417a7209a6b9ace1f5a12c1c07c2b636a0b Mon Sep 17 00:00:00 2001 From: Bilal Amarni Date: Wed, 5 Jun 2013 16:35:05 +0200 Subject: [PATCH 135/447] fixed date type format pattern regex --- Extension/Core/Type/DateType.php | 2 +- Tests/Extension/Core/Type/DateTypeTest.php | 23 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Extension/Core/Type/DateType.php b/Extension/Core/Type/DateType.php index 71ae631c67..648ab1b7e5 100644 --- a/Extension/Core/Type/DateType.php +++ b/Extension/Core/Type/DateType.php @@ -144,7 +144,7 @@ public function finishView(FormView $view, FormInterface $form, array $options) // set right order with respect to locale (e.g.: de_DE=dd.MM.yy; en_US=M/d/yy) // lookup various formats at http://userguide.icu-project.org/formatparse/datetime - if (preg_match('/^([yMd]+).+([yMd]+).+([yMd]+)$/', $pattern)) { + if (preg_match('/^([yMd]+)[^yMd]*([yMd]+)[^yMd]*([yMd]+)$/', $pattern)) { $pattern = preg_replace(array('/y+/', '/M+/', '/d+/'), array('{{ year }}', '{{ month }}', '{{ day }}'), $pattern); } else { // default fallback diff --git a/Tests/Extension/Core/Type/DateTypeTest.php b/Tests/Extension/Core/Type/DateTypeTest.php index c0d7da676b..6d4dd2c8a7 100644 --- a/Tests/Extension/Core/Type/DateTypeTest.php +++ b/Tests/Extension/Core/Type/DateTypeTest.php @@ -267,6 +267,29 @@ public function testSubmitFromInputRawDifferentPattern() $this->assertEquals('06*2010*02', $form->getViewData()); } + /** + * @dataProvider provideDateFormats + */ + public function testDatePatternWithFormatOption($format, $pattern) + { + $form = $this->factory->create('date', null, array( + 'format' => $format, + )); + + $view = $form->createView(); + + $this->assertEquals($pattern, $view->vars['date_pattern']); + } + + public function provideDateFormats() + { + return array( + array('dMy', '{{ day }}{{ month }}{{ year }}'), + array('d-M-yyyy', '{{ day }}-{{ month }}-{{ year }}'), + array('M d y', '{{ month }} {{ day }} {{ year }}'), + ); + } + /** * This test is to check that the strings '0', '1', '2', '3' are no accepted * as valid IntlDateFormatter constants for FULL, LONG, MEDIUM or SHORT respectively. From 442db17a080425a7fa87d48ae43767c2fdb1eee2 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 23 Jun 2013 09:35:41 +0200 Subject: [PATCH 136/447] [Form] fixed INF usage which does not work on Solaris (closes #8246) --- .../Core/DataTransformer/NumberToLocalizedStringTransformer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php index 689c74a94a..b0c59b3ede 100644 --- a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php @@ -128,7 +128,7 @@ public function reverseTransform($value) throw new TransformationFailedException($formatter->getErrorMessage()); } - if ($result >= INF || $result <= -INF) { + if ($result >= PHP_INT_MAX || $result <= -PHP_INT_MAX) { throw new TransformationFailedException('I don\'t have a clear idea what infinity looks like'); } From bc45153813bdeafd17c95296f1ea8a5f6289da59 Mon Sep 17 00:00:00 2001 From: Artem Lopata Date: Thu, 27 Jun 2013 01:20:19 +0300 Subject: [PATCH 137/447] [Form] Fix of "PATCH'ed forms are never valid" | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #8111 | License | MIT --- Form.php | 14 ++++++- Tests/CompoundFormTest.php | 75 +++++++++++++++++++++++++++++++++++++- 2 files changed, 85 insertions(+), 4 deletions(-) diff --git a/Form.php b/Form.php index 35135274a7..e151484708 100644 --- a/Form.php +++ b/Form.php @@ -500,6 +500,14 @@ public function submit($submittedData, $clearMissing = true) return $this; } + // In order to process patch requests we need to "submit" null values + // Later this value will be mapped via DataMapper and InheritDataAwareIterator + if ($submittedData === null && !$clearMissing) { + $this->submitted = true; + + return $this; + } + // The data must be initialized if it was not initialized yet. // This is necessary to guarantee that the *_SET_DATA listeners // are always invoked before submit() takes place. @@ -537,10 +545,12 @@ public function submit($submittedData, $clearMissing = true) } foreach ($this->children as $name => $child) { - if (isset($submittedData[$name]) || $clearMissing) { - $child->submit(isset($submittedData[$name]) ? $submittedData[$name] : null, $clearMissing); + $fieldValue = null; + if (isset($submittedData[$name])) { + $fieldValue = $submittedData[$name]; unset($submittedData[$name]); } + $child->submit($fieldValue, $clearMissing); } $this->extraData = $submittedData; diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index b240d2d0b3..71c7b2a734 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -58,15 +58,18 @@ public function testSubmitForwardsNullIfValueIsMissing() $this->form->submit(array()); } - public function testSubmitDoesNotForwardNullIfNotClearMissing() + public function testSubmitDoesNotSaveNullIfNotClearMissing() { $child = $this->getMockForm('firstName'); $this->form->add($child); - $child->expects($this->never()) + $child->expects($this->once()) ->method('submit'); + $child->expects($this->never()) + ->method('setData'); + $this->form->submit(array(), false); } @@ -547,6 +550,74 @@ public function testSubmitPostOrPutRequest($method) unlink($path); } + public function testSubmitPatchRequest() + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + $this->markTestSkipped('The "HttpFoundation" component is not available'); + } + + $object = new \stdClass(); + $object->name = 'Bernhard'; + $object->name2 = 'Me'; + + //$values = array(); + $values = array( + 'author' => array( + 'name2' => 'Artem', + ), + ); + + $request = new Request(array(), $values, array(), array(), array(), array( + 'REQUEST_METHOD' => 'PATCH', + )); + + $mapper = $this->getDataMapper(); + $mapper->expects($this->any()) + ->method('mapDataToForms') + ->will($this->returnCallback(function($data, $forms){ + foreach ($forms as $form) { + $propertyPath = $form->getPropertyPath(); + + if (null !== $propertyPath) { + $form->setData($data->{$propertyPath}); + } + } + })); + + + $mapper->expects($this->any()) + ->method('mapFormsToData') + ->will($this->returnCallback(function($forms, &$data){ + foreach ($forms as $form) { + $propertyPath = $form->getPropertyPath(); + + if (null !== $propertyPath) { + if (!is_object($data) || $form->getData() !== $data->{$propertyPath}) { + $data->{$propertyPath} = $form->getData(); + } + } + } + })); + + /** @var Form $form */ + $form = $this->getBuilder('author', null, 'stdClass') + ->setMethod('PATCH') + ->setData($object) + ->setCompound(true) + ->setDataMapper($mapper) + ->setRequestHandler(new HttpFoundationRequestHandler()) + ->getForm(); + $form->add($this->getBuilder('name')->getForm()); + $form->add($this->getBuilder('name2')->getForm()); + + $form->handleRequest($request); + + $this->assertTrue($form->isValid()); + + $this->assertEquals('Bernhard', $form['name']->getData()); + $this->assertEquals('Artem', $form['name2']->getData()); + } + /** * @dataProvider requestMethodProvider */ From 8f55e9d4b49940d7490b9ab20a08820f99a1062e Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 1 Jul 2013 14:24:43 +0200 Subject: [PATCH 138/447] fixed CS --- ButtonBuilder.php | 2 +- Extension/Core/EventListener/MergeCollectionListener.php | 1 - Extension/Core/EventListener/ResizeFormListener.php | 1 - Extension/Core/Type/CountryType.php | 1 - Extension/Core/Type/CurrencyType.php | 1 - Extension/Core/Type/FormType.php | 1 - Extension/Core/Type/LanguageType.php | 1 - Extension/HttpFoundation/HttpFoundationRequestHandler.php | 1 - Extension/Validator/Type/FormTypeValidatorExtension.php | 1 - FormConfigBuilder.php | 1 - Tests/Extension/Core/Type/BaseTypeTest.php | 2 +- 11 files changed, 2 insertions(+), 11 deletions(-) diff --git a/ButtonBuilder.php b/ButtonBuilder.php index 2a19d58e06..3addedbde9 100644 --- a/ButtonBuilder.php +++ b/ButtonBuilder.php @@ -446,7 +446,7 @@ public function setDataLocked($locked) * This method should not be invoked. * * @param FormFactoryInterface $formFactory - * + * * @return void * * @throws BadMethodCallException diff --git a/Extension/Core/EventListener/MergeCollectionListener.php b/Extension/Core/EventListener/MergeCollectionListener.php index b6f8fb70cb..4d0bdfaae0 100644 --- a/Extension/Core/EventListener/MergeCollectionListener.php +++ b/Extension/Core/EventListener/MergeCollectionListener.php @@ -124,7 +124,6 @@ public function onSubmit(FormEvent $event) $event->setData($dataToMergeInto); } - /** * Alias of {@link onSubmit()}. * diff --git a/Extension/Core/EventListener/ResizeFormListener.php b/Extension/Core/EventListener/ResizeFormListener.php index fabeb3664a..f1c39db245 100644 --- a/Extension/Core/EventListener/ResizeFormListener.php +++ b/Extension/Core/EventListener/ResizeFormListener.php @@ -149,7 +149,6 @@ public function onSubmit(FormEvent $event) $event->setData($data); } - /** * Alias of {@link preSubmit()}. * diff --git a/Extension/Core/Type/CountryType.php b/Extension/Core/Type/CountryType.php index c9c979a6e6..3482ba6634 100644 --- a/Extension/Core/Type/CountryType.php +++ b/Extension/Core/Type/CountryType.php @@ -13,7 +13,6 @@ use Symfony\Component\Form\AbstractType; use Symfony\Component\Intl\Intl; -use Symfony\Component\Locale\Locale; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class CountryType extends AbstractType diff --git a/Extension/Core/Type/CurrencyType.php b/Extension/Core/Type/CurrencyType.php index 07b820d823..3a925e3a3d 100644 --- a/Extension/Core/Type/CurrencyType.php +++ b/Extension/Core/Type/CurrencyType.php @@ -13,7 +13,6 @@ use Symfony\Component\Form\AbstractType; use Symfony\Component\Intl\Intl; -use Symfony\Component\Locale\Locale; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class CurrencyType extends AbstractType diff --git a/Extension/Core/Type/FormType.php b/Extension/Core/Type/FormType.php index eb1897cee4..0c39d3eb6c 100644 --- a/Extension/Core/Type/FormType.php +++ b/Extension/Core/Type/FormType.php @@ -156,7 +156,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) if (null !== $options['virtual']) { // Uncomment this as soon as the deprecation note should be shown // trigger_error('The form option "virtual" is deprecated since version 2.3 and will be removed in 3.0. Use "inherit_data" instead.', E_USER_DEPRECATED); - return $options['virtual']; } diff --git a/Extension/Core/Type/LanguageType.php b/Extension/Core/Type/LanguageType.php index 04994a0775..37b2bf3300 100644 --- a/Extension/Core/Type/LanguageType.php +++ b/Extension/Core/Type/LanguageType.php @@ -13,7 +13,6 @@ use Symfony\Component\Form\AbstractType; use Symfony\Component\Intl\Intl; -use Symfony\Component\Locale\Locale; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class LanguageType extends AbstractType diff --git a/Extension/HttpFoundation/HttpFoundationRequestHandler.php b/Extension/HttpFoundation/HttpFoundationRequestHandler.php index dcb6ede2b3..cc4851566d 100644 --- a/Extension/HttpFoundation/HttpFoundationRequestHandler.php +++ b/Extension/HttpFoundation/HttpFoundationRequestHandler.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Form\Extension\HttpFoundation; -use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\RequestHandlerInterface; diff --git a/Extension/Validator/Type/FormTypeValidatorExtension.php b/Extension/Validator/Type/FormTypeValidatorExtension.php index 2105997242..344bddadc1 100644 --- a/Extension/Validator/Type/FormTypeValidatorExtension.php +++ b/Extension/Validator/Type/FormTypeValidatorExtension.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Form\Extension\Validator\Type; -use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapper; use Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener; diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index dc9c8f038e..1015da4f51 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -358,7 +358,6 @@ public function getVirtual() { // Uncomment this as soon as the deprecation note should be shown // trigger_error('getVirtual() is deprecated since version 2.3 and will be removed in 3.0. Use getInheritData() instead.', E_USER_DEPRECATED); - return $this->getInheritData(); } diff --git a/Tests/Extension/Core/Type/BaseTypeTest.php b/Tests/Extension/Core/Type/BaseTypeTest.php index ef36f1c052..bfa1e21805 100644 --- a/Tests/Extension/Core/Type/BaseTypeTest.php +++ b/Tests/Extension/Core/Type/BaseTypeTest.php @@ -130,6 +130,6 @@ public function testPassMultipartFalseToView() $this->assertFalse($view->vars['multipart']); } - + abstract protected function getTestedType(); } From 9f6e120574fdf73df9b44fa9c02c335ce740eb7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Tue, 16 Jul 2013 12:31:14 +0200 Subject: [PATCH 139/447] Added missing files .gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 44de97a36a..c49a5d8df5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ vendor/ composer.lock phpunit.xml - From 91f547fa0a1e54faec58cd09cd7c3b186f5ec42e Mon Sep 17 00:00:00 2001 From: entering Date: Sun, 7 Jul 2013 00:46:16 +0100 Subject: [PATCH 140/447] [Form] Validation listener remove count() --- .../EventListener/ValidationListener.php | 12 +++++------ .../EventListener/ValidationListenerTest.php | 20 +++++++++++++++++++ .../Type/FormTypeValidatorExtensionTest.php | 14 +++++++++---- 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/Extension/Validator/EventListener/ValidationListener.php b/Extension/Validator/EventListener/ValidationListener.php index 1414753153..26d2bfdaa7 100644 --- a/Extension/Validator/EventListener/ValidationListener.php +++ b/Extension/Validator/EventListener/ValidationListener.php @@ -54,14 +54,12 @@ public function validateForm(FormEvent $event) // Validate the form in group "Default" $violations = $this->validator->validate($form); - if (count($violations) > 0) { - foreach ($violations as $violation) { - // Allow the "invalid" constraint to be put onto - // non-synchronized forms - $allowNonSynchronized = Form::ERR_INVALID === $violation->getCode(); + foreach ($violations as $violation) { + // Allow the "invalid" constraint to be put onto + // non-synchronized forms + $allowNonSynchronized = Form::ERR_INVALID === $violation->getCode(); - $this->violationMapper->mapViolation($violation, $form, $allowNonSynchronized); - } + $this->violationMapper->mapViolation($violation, $form, $allowNonSynchronized); } } } diff --git a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php index 528f94633b..57e0a48185 100644 --- a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php +++ b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php @@ -17,6 +17,7 @@ use Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\Validator\ConstraintViolation; +use Symfony\Component\Validator\ConstraintViolationList; class ValidationListenerTest extends \PHPUnit_Framework_TestCase { @@ -142,4 +143,23 @@ public function testValidateIgnoresNonRoot() $this->listener->validateForm(new FormEvent($form, null)); } + + public function testValidateWithEmptyViolationList() + { + $form = $this->getMockForm(); + $form->expects($this->once()) + ->method('isRoot') + ->will($this->returnValue(true)); + + $this->validator + ->expects($this->once()) + ->method('validate') + ->will($this->returnValue(new ConstraintViolationList())); + + $this->violationMapper + ->expects($this->never()) + ->method('mapViolation'); + + $this->listener->validateForm(new FormEvent($form, null)); + } } diff --git a/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php b/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php index 6619410599..a859b49998 100644 --- a/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php +++ b/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\Type; use Symfony\Component\Form\FormInterface; +use Symfony\Component\Validator\ConstraintViolationList; class FormTypeValidatorExtensionTest extends TypeTestCase { @@ -69,15 +70,20 @@ public function testValidationGroupsCanBeSetToClosure() public function testSubmitValidatesData() { - $builder = $this->factory->createBuilder('form', null, array( - 'validation_groups' => 'group', - )); + $builder = $this->factory->createBuilder( + 'form', + null, + array( + 'validation_groups' => 'group', + ) + ); $builder->add('firstName', 'form'); $form = $builder->getForm(); $this->validator->expects($this->once()) ->method('validate') - ->with($this->equalTo($form)); + ->with($this->equalTo($form)) + ->will($this->returnValue(new ConstraintViolationList())); // specific data is irrelevant $form->submit(array()); From 68d32e849df74a6cd9e664554594ffd2b94c1032 Mon Sep 17 00:00:00 2001 From: Flavian Sierk Date: Thu, 25 Jul 2013 11:50:20 +0200 Subject: [PATCH 141/447] [Form] fixes empty file-inputs get treated as extra field --- Form.php | 2 +- Tests/CompoundFormTest.php | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Form.php b/Form.php index e151484708..43f46ca228 100644 --- a/Form.php +++ b/Form.php @@ -546,7 +546,7 @@ public function submit($submittedData, $clearMissing = true) foreach ($this->children as $name => $child) { $fieldValue = null; - if (isset($submittedData[$name])) { + if (array_key_exists($name, $submittedData)) { $fieldValue = $submittedData[$name]; unset($submittedData[$name]); } diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index 71c7b2a734..34b11d3949 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -13,6 +13,7 @@ use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; use Symfony\Component\Form\FormError; +use Symfony\Component\Form\Forms; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer; @@ -73,6 +74,19 @@ public function testSubmitDoesNotSaveNullIfNotClearMissing() $this->form->submit(array(), false); } + public function testSubmitDoesNotAddExtraFieldForNullValues() + { + $factory = Forms::createFormFactoryBuilder() + ->getFormFactory(); + + $child = $factory->create('file', null, array('auto_initialize' => false)); + + $this->form->add($child); + $this->form->submit(array('file' => null)); + + $this->assertCount(0, $this->form->getExtraData()); + } + public function testClearMissingFlagIsForwarded() { $child = $this->getMockForm('firstName'); From a6323cc8c68554de2509e51456c407ef1d64ebe3 Mon Sep 17 00:00:00 2001 From: bronze1man Date: Sat, 27 Jul 2013 12:44:48 +0800 Subject: [PATCH 142/447] [template] fixed test failure introduted from #8585 --- Tests/AbstractLayoutTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index 8f632a2b50..9bfdd7dcf6 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -1811,7 +1811,7 @@ public function testStartTag() $html = $this->renderStart($form->createView()); - $this->assertSame('
', $html); + $this->assertSame('', $html); } public function testStartTagForPutRequest() @@ -1843,7 +1843,7 @@ public function testStartTagWithOverriddenVars() 'action' => 'http://foo.com/directory' )); - $this->assertSame('', $html); + $this->assertSame('', $html); } public function testStartTagForMultipartForm() @@ -1857,7 +1857,7 @@ public function testStartTagForMultipartForm() $html = $this->renderStart($form->createView()); - $this->assertSame('', $html); + $this->assertSame('', $html); } public function testStartTagWithExtraAttributes() @@ -1871,6 +1871,6 @@ public function testStartTagWithExtraAttributes() 'attr' => array('class' => 'foobar'), )); - $this->assertSame('', $html); + $this->assertSame('', $html); } } From bbfed3edaa7c841967af2b4a93b724357a3e2540 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 25 Jul 2013 07:46:36 +0200 Subject: [PATCH 143/447] removed dead code and fixed CS --- FormConfigBuilder.php | 1 - 1 file changed, 1 deletion(-) diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index 5d1f3a2331..380266e7be 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\BadMethodCallException; -use Symfony\Component\Form\Exception\Exception; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\PropertyAccess\PropertyPathInterface; From c279d792ac087caa4d7bca0409723243d72a616f Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 1 Aug 2013 10:34:30 +0200 Subject: [PATCH 144/447] Revert "[Form] Remove "value" attribute on empty_value option" This reverts commit 9e849eb78bcc668a2b8aad39cb47e2ad32c73a47. Reasons for the revert: * https://github.com/symfony/symfony/issues/8478 * https://github.com/symfony/symfony/issues/8526 --- Tests/AbstractLayoutTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index 8f632a2b50..49342d0c39 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -551,7 +551,7 @@ public function testSingleChoiceRequiredWithEmptyValue() [@name="name"] [@required="required"] [ - ./option[not(@value)][not(@selected)][@disabled][.="[trans]Test&Me[/trans]"] + ./option[@value=""][not(@selected)][@disabled][.="[trans]Test&Me[/trans]"] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] @@ -574,7 +574,7 @@ public function testSingleChoiceRequiredWithEmptyValueViaView() [@name="name"] [@required="required"] [ - ./option[not(@value)][not(@selected)][@disabled][.="[trans][/trans]"] + ./option[@value=""][not(@selected)][@disabled][.="[trans][/trans]"] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] From c6811f6d3cafc874357c3e22bd9c95dd23fbadbb Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 1 Aug 2013 10:40:05 +0200 Subject: [PATCH 145/447] [Form] Removed the "disabled" attribute from the placeholder option in select fields due to problems with the BlackBerry 10 browser --- Tests/AbstractLayoutTest.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index 15e6530818..74b9063a3f 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -543,12 +543,15 @@ public function testSingleChoiceRequiredWithEmptyValue() 'empty_value' => 'Test&Me' )); + // The "disabled" attribute was removed again due to a bug in the + // BlackBerry 10 browser. + // See https://github.com/symfony/symfony/pull/7678 $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name"] [@required="required"] [ - ./option[@value=""][not(@selected)][@disabled][.="[trans]Test&Me[/trans]"] + ./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Test&Me[/trans]"] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] @@ -566,12 +569,15 @@ public function testSingleChoiceRequiredWithEmptyValueViaView() 'expanded' => false, )); + // The "disabled" attribute was removed again due to a bug in the + // BlackBerry 10 browser. + // See https://github.com/symfony/symfony/pull/7678 $this->assertWidgetMatchesXpath($form->createView(), array('empty_value' => ''), '/select [@name="name"] [@required="required"] [ - ./option[@value=""][not(@selected)][@disabled][.="[trans][/trans]"] + ./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] From ee9110b6b2ecd77d005fd0d741ef7b23a6b859a8 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 1 Aug 2013 15:31:18 +0200 Subject: [PATCH 146/447] [Form] Changed (Number|Integer)ToLocalizedStringTransformer::reverseTransform() to do rounding --- .../IntegerToLocalizedStringTransformer.php | 40 ++-- .../NumberToLocalizedStringTransformer.php | 123 +++++++++- ...ntegerToLocalizedStringTransformerTest.php | 122 ++++++++++ ...NumberToLocalizedStringTransformerTest.php | 212 +++++++++++++++++- 4 files changed, 461 insertions(+), 36 deletions(-) diff --git a/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php index 6bb48a9a03..c22dad5100 100644 --- a/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Form\Extension\Core\DataTransformer; -use Symfony\Component\Form\Exception\TransformationFailedException; - /** * Transforms between an integer and a localized number with grouping * (each thousand) and comma separators. @@ -22,32 +20,28 @@ class IntegerToLocalizedStringTransformer extends NumberToLocalizedStringTransformer { /** - * {@inheritDoc} + * Constructs a transformer. + * + * @param integer $precision Unused. + * @param Boolean $grouping Whether thousands should be grouped. + * @param integer $roundingMode One of the ROUND_ constants in this class. */ - public function reverseTransform($value) + public function __construct($precision = null, $grouping = null, $roundingMode = self::ROUND_DOWN) { - if (!is_string($value)) { - throw new TransformationFailedException('Expected a string.'); - } - - if ('' === $value) { - return null; - } - - if ('NaN' === $value) { - throw new TransformationFailedException('"NaN" is not a valid integer'); + if (null === $roundingMode) { + $roundingMode = self::ROUND_DOWN; } - $formatter = $this->getNumberFormatter(); - $value = $formatter->parse( - $value, - PHP_INT_SIZE == 8 ? $formatter::TYPE_INT64 : $formatter::TYPE_INT32 - ); + parent::__construct(0, $grouping, $roundingMode); + } - if (intl_is_failure($formatter->getErrorCode())) { - throw new TransformationFailedException($formatter->getErrorMessage()); - } + /** + * {@inheritDoc} + */ + public function reverseTransform($value) + { + $result = parent::reverseTransform($value); - return $value; + return null !== $result ? (int) $result : null; } } diff --git a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php index b0c59b3ede..61f2f4441e 100644 --- a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php @@ -23,13 +23,75 @@ */ class NumberToLocalizedStringTransformer implements DataTransformerInterface { - const ROUND_FLOOR = \NumberFormatter::ROUND_FLOOR; - const ROUND_DOWN = \NumberFormatter::ROUND_DOWN; - const ROUND_HALFDOWN = \NumberFormatter::ROUND_HALFDOWN; - const ROUND_HALFEVEN = \NumberFormatter::ROUND_HALFEVEN; - const ROUND_HALFUP = \NumberFormatter::ROUND_HALFUP; - const ROUND_UP = \NumberFormatter::ROUND_UP; - const ROUND_CEILING = \NumberFormatter::ROUND_CEILING; + /** + * Rounds a number towards positive infinity. + * + * Rounds 1.4 to 2 and -1.4 to -1. + */ + const ROUND_CEILING = \NumberFormatter::ROUND_CEILING; + + /** + * Rounds a number towards negative infinity. + * + * Rounds 1.4 to 1 and -1.4 to -2. + */ + const ROUND_FLOOR = \NumberFormatter::ROUND_FLOOR; + + /** + * Rounds a number away from zero. + * + * Rounds 1.4 to 2 and -1.4 to -2. + */ + const ROUND_UP = \NumberFormatter::ROUND_UP; + + /** + * Rounds a number towards zero. + * + * Rounds 1.4 to 1 and -1.4 to -1. + */ + const ROUND_DOWN = \NumberFormatter::ROUND_DOWN; + + /** + * Rounds to the nearest number and halves to the next even number. + * + * Rounds 2.5, 1.6 and 1.5 to 2 and 1.4 to 1. + */ + const ROUND_HALF_EVEN = \NumberFormatter::ROUND_HALFEVEN; + + /** + * Rounds to the nearest number and halves away from zero. + * + * Rounds 2.5 to 3, 1.6 and 1.5 to 2 and 1.4 to 1. + */ + const ROUND_HALF_UP = \NumberFormatter::ROUND_HALFUP; + + /** + * Rounds to the nearest number and halves towards zero. + * + * Rounds 2.5 and 1.6 to 2, 1.5 and 1.4 to 1. + */ + const ROUND_HALF_DOWN = \NumberFormatter::ROUND_HALFDOWN; + + /** + * Alias for {@link self::ROUND_HALF_EVEN}. + * + * @deprecated Deprecated as of Symfony 2.4, to be removed in Symfony 3.0. + */ + const ROUND_HALFEVEN = self::ROUND_HALF_EVEN; + + /** + * Alias for {@link self::ROUND_HALF_UP}. + * + * @deprecated Deprecated as of Symfony 2.4, to be removed in Symfony 3.0. + */ + const ROUND_HALFUP = self::ROUND_HALF_UP; + + /** + * Alias for {@link self::ROUND_HALF_DOWN}. + * + * @deprecated Deprecated as of Symfony 2.4, to be removed in Symfony 3.0. + */ + const ROUND_HALFDOWN = self::ROUND_HALF_DOWN; protected $precision; @@ -160,7 +222,8 @@ public function reverseTransform($value) } } - return $result; + // NumberFormatter::parse() does not round + return $this->round($result); } /** @@ -181,4 +244,48 @@ protected function getNumberFormatter() return $formatter; } + + /** + * Rounds a number according to the configured precision and rounding mode. + * + * @param integer|float $number A number. + * + * @return integer|float The rounded number. + */ + private function round($number) + { + if (null !== $this->precision && null !== $this->roundingMode) { + // shift number to maintain the correct precision during rounding + $roundingCoef = pow(10, $this->precision); + $number *= $roundingCoef; + + switch ($this->roundingMode) { + case self::ROUND_CEILING: + $number = ceil($number); + break; + case self::ROUND_FLOOR: + $number = floor($number); + break; + case self::ROUND_UP: + $number = $number > 0 ? ceil($number) : floor($number); + break; + case self::ROUND_DOWN: + $number = $number > 0 ? floor($number) : ceil($number); + break; + case self::ROUND_HALF_EVEN: + $number = round($number, 0, PHP_ROUND_HALF_EVEN); + break; + case self::ROUND_HALF_UP: + $number = round($number, 0, PHP_ROUND_HALF_UP); + break; + case self::ROUND_HALF_DOWN: + $number = round($number, 0, PHP_ROUND_HALF_DOWN); + break; + } + + $number /= $roundingCoef; + } + + return $number; + } } diff --git a/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php index a90fa91bb0..840134da95 100644 --- a/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformerTest.php @@ -26,6 +26,67 @@ protected function setUp() \Locale::setDefault('de_AT'); } + public function transformWithRoundingProvider() + { + return array( + // towards positive infinity (1.6 -> 2, -1.6 -> -1) + array(1234.5, '1235', IntegerToLocalizedStringTransformer::ROUND_CEILING), + array(1234.4, '1235', IntegerToLocalizedStringTransformer::ROUND_CEILING), + array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_CEILING), + array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_CEILING), + // towards negative infinity (1.6 -> 1, -1.6 -> -2) + array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_FLOOR), + array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_FLOOR), + array(-1234.5, '-1235', IntegerToLocalizedStringTransformer::ROUND_FLOOR), + array(-1234.4, '-1235', IntegerToLocalizedStringTransformer::ROUND_FLOOR), + // away from zero (1.6 -> 2, -1.6 -> 2) + array(1234.5, '1235', IntegerToLocalizedStringTransformer::ROUND_UP), + array(1234.4, '1235', IntegerToLocalizedStringTransformer::ROUND_UP), + array(-1234.5, '-1235', IntegerToLocalizedStringTransformer::ROUND_UP), + array(-1234.4, '-1235', IntegerToLocalizedStringTransformer::ROUND_UP), + // towards zero (1.6 -> 1, -1.6 -> -1) + array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_DOWN), + array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_DOWN), + array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_DOWN), + array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_DOWN), + // round halves (.5) to the next even number + array(1234.6, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1233.5, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1232.5, '1232', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(-1234.6, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(-1233.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(-1232.5, '-1232', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), + // round halves (.5) away from zero + array(1234.6, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP), + array(1234.5, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP), + array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_UP), + array(-1234.6, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP), + array(-1234.5, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP), + array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_UP), + // round halves (.5) towards zero + array(1234.6, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(-1234.6, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), + ); + } + + /** + * @dataProvider transformWithRoundingProvider + */ + public function testTransformWithRounding($input, $output, $roundingMode) + { + $transformer = new IntegerToLocalizedStringTransformer(null, null, $roundingMode); + + $this->assertEquals($output, $transformer->transform($input)); + } + public function testReverseTransform() { $transformer = new IntegerToLocalizedStringTransformer(); @@ -53,6 +114,67 @@ public function testReverseTransformWithGrouping() $this->assertEquals(12345, $transformer->reverseTransform('12345,912')); } + public function reverseTransformWithRoundingProvider() + { + return array( + // towards positive infinity (1.6 -> 2, -1.6 -> -1) + array('1234,5', 1235, IntegerToLocalizedStringTransformer::ROUND_CEILING), + array('1234,4', 1235, IntegerToLocalizedStringTransformer::ROUND_CEILING), + array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_CEILING), + array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_CEILING), + // towards negative infinity (1.6 -> 1, -1.6 -> -2) + array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_FLOOR), + array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_FLOOR), + array('-1234,5', -1235, IntegerToLocalizedStringTransformer::ROUND_FLOOR), + array('-1234,4', -1235, IntegerToLocalizedStringTransformer::ROUND_FLOOR), + // away from zero (1.6 -> 2, -1.6 -> 2) + array('1234,5', 1235, IntegerToLocalizedStringTransformer::ROUND_UP), + array('1234,4', 1235, IntegerToLocalizedStringTransformer::ROUND_UP), + array('-1234,5', -1235, IntegerToLocalizedStringTransformer::ROUND_UP), + array('-1234,4', -1235, IntegerToLocalizedStringTransformer::ROUND_UP), + // towards zero (1.6 -> 1, -1.6 -> -1) + array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_DOWN), + array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_DOWN), + array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_DOWN), + array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_DOWN), + // round halves (.5) to the next even number + array('1234,6', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), + array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), + array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), + array('1233,5', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), + array('1232,5', 1232, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), + array('-1234,6', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), + array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), + array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), + array('-1233,5', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), + array('-1232,5', -1232, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN), + // round halves (.5) away from zero + array('1234,6', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP), + array('1234,5', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP), + array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_UP), + array('-1234,6', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP), + array('-1234,5', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP), + array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_UP), + // round halves (.5) towards zero + array('1234,6', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), + array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), + array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), + array('-1234,6', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), + array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), + array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN), + ); + } + + /** + * @dataProvider reverseTransformWithRoundingProvider + */ + public function testReverseTransformWithRounding($input, $output, $roundingMode) + { + $transformer = new IntegerToLocalizedStringTransformer(null, null, $roundingMode); + + $this->assertEquals($output, $transformer->reverseTransform($input)); + } + /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ diff --git a/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php index c58e3f60e7..183935e7ab 100644 --- a/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php @@ -82,14 +82,110 @@ public function testTransformWithPrecision() $this->assertEquals('678,92', $transformer->transform(678.916)); } - public function testTransformWithRoundingMode() + public function transformWithRoundingProvider() { - $transformer = new NumberToLocalizedStringTransformer(null, null, NumberToLocalizedStringTransformer::ROUND_DOWN); - $this->assertEquals('1234,547', $transformer->transform(1234.547), '->transform() only applies rounding mode if precision set'); + return array( + // towards positive infinity (1.6 -> 2, -1.6 -> -1) + array(0, 1234.5, '1235', NumberToLocalizedStringTransformer::ROUND_CEILING), + array(0, 1234.4, '1235', NumberToLocalizedStringTransformer::ROUND_CEILING), + array(0, -1234.5, '-1234', NumberToLocalizedStringTransformer::ROUND_CEILING), + array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_CEILING), + array(1, 123.45, '123,5', NumberToLocalizedStringTransformer::ROUND_CEILING), + array(1, 123.44, '123,5', NumberToLocalizedStringTransformer::ROUND_CEILING), + array(1, -123.45, '-123,4', NumberToLocalizedStringTransformer::ROUND_CEILING), + array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_CEILING), + // towards negative infinity (1.6 -> 1, -1.6 -> -2) + array(0, 1234.5, '1234', NumberToLocalizedStringTransformer::ROUND_FLOOR), + array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_FLOOR), + array(0, -1234.5, '-1235', NumberToLocalizedStringTransformer::ROUND_FLOOR), + array(0, -1234.4, '-1235', NumberToLocalizedStringTransformer::ROUND_FLOOR), + array(1, 123.45, '123,4', NumberToLocalizedStringTransformer::ROUND_FLOOR), + array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_FLOOR), + array(1, -123.45, '-123,5', NumberToLocalizedStringTransformer::ROUND_FLOOR), + array(1, -123.44, '-123,5', NumberToLocalizedStringTransformer::ROUND_FLOOR), + // away from zero (1.6 -> 2, -1.6 -> 2) + array(0, 1234.5, '1235', NumberToLocalizedStringTransformer::ROUND_UP), + array(0, 1234.4, '1235', NumberToLocalizedStringTransformer::ROUND_UP), + array(0, -1234.5, '-1235', NumberToLocalizedStringTransformer::ROUND_UP), + array(0, -1234.4, '-1235', NumberToLocalizedStringTransformer::ROUND_UP), + array(1, 123.45, '123,5', NumberToLocalizedStringTransformer::ROUND_UP), + array(1, 123.44, '123,5', NumberToLocalizedStringTransformer::ROUND_UP), + array(1, -123.45, '-123,5', NumberToLocalizedStringTransformer::ROUND_UP), + array(1, -123.44, '-123,5', NumberToLocalizedStringTransformer::ROUND_UP), + // towards zero (1.6 -> 1, -1.6 -> -1) + array(0, 1234.5, '1234', NumberToLocalizedStringTransformer::ROUND_DOWN), + array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_DOWN), + array(0, -1234.5, '-1234', NumberToLocalizedStringTransformer::ROUND_DOWN), + array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_DOWN), + array(1, 123.45, '123,4', NumberToLocalizedStringTransformer::ROUND_DOWN), + array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_DOWN), + array(1, -123.45, '-123,4', NumberToLocalizedStringTransformer::ROUND_DOWN), + array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_DOWN), + // round halves (.5) to the next even number + array(0, 1234.6, '1235', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(0, 1234.5, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(0, 1233.5, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(0, 1232.5, '1232', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(0, -1234.6, '-1235', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(0, -1234.5, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(0, -1233.5, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(0, -1232.5, '-1232', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1, 123.46, '123,5', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1, 123.45, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1, 123.35, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1, 123.25, '123,2', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1, -123.46, '-123,5', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1, -123.45, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1, -123.35, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1, -123.25, '-123,2', NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + // round halves (.5) away from zero + array(0, 1234.6, '1235', NumberToLocalizedStringTransformer::ROUND_HALF_UP), + array(0, 1234.5, '1235', NumberToLocalizedStringTransformer::ROUND_HALF_UP), + array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_UP), + array(0, -1234.6, '-1235', NumberToLocalizedStringTransformer::ROUND_HALF_UP), + array(0, -1234.5, '-1235', NumberToLocalizedStringTransformer::ROUND_HALF_UP), + array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_UP), + array(1, 123.46, '123,5', NumberToLocalizedStringTransformer::ROUND_HALF_UP), + array(1, 123.45, '123,5', NumberToLocalizedStringTransformer::ROUND_HALF_UP), + array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_UP), + array(1, -123.46, '-123,5', NumberToLocalizedStringTransformer::ROUND_HALF_UP), + array(1, -123.45, '-123,5', NumberToLocalizedStringTransformer::ROUND_HALF_UP), + array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_UP), + // round halves (.5) towards zero + array(0, 1234.6, '1235', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(0, 1234.5, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(0, 1234.4, '1234', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(0, -1234.6, '-1235', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(0, -1234.5, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(0, -1234.4, '-1234', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(1, 123.46, '123,5', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(1, 123.45, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(1, 123.44, '123,4', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(1, -123.46, '-123,5', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(1, -123.45, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(1, -123.44, '-123,4', NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + ); + } + + /** + * @dataProvider transformWithRoundingProvider + */ + public function testTransformWithRounding($precision, $input, $output, $roundingMode) + { + $transformer = new NumberToLocalizedStringTransformer($precision, null, $roundingMode); - $transformer = new NumberToLocalizedStringTransformer(2, null, NumberToLocalizedStringTransformer::ROUND_DOWN); - $this->assertEquals('1234,54', $transformer->transform(1234.547), '->transform() rounding-mode works'); + $this->assertEquals($output, $transformer->transform($input)); + } + public function testTransformDoesNotRoundIfNoPrecision() + { + $transformer = new NumberToLocalizedStringTransformer(null, null, NumberToLocalizedStringTransformer::ROUND_DOWN); + + $this->assertEquals('1234,547', $transformer->transform(1234.547)); } /** @@ -139,6 +235,112 @@ public function testReverseTransformWithGroupingButWithoutGroupSeparator() $this->assertEquals(12345.912, $transformer->reverseTransform('12345,912')); } + public function reverseTransformWithRoundingProvider() + { + return array( + // towards positive infinity (1.6 -> 2, -1.6 -> -1) + array(0, '1234,5', 1235, NumberToLocalizedStringTransformer::ROUND_CEILING), + array(0, '1234,4', 1235, NumberToLocalizedStringTransformer::ROUND_CEILING), + array(0, '-1234,5', -1234, NumberToLocalizedStringTransformer::ROUND_CEILING), + array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_CEILING), + array(1, '123,45', 123.5, NumberToLocalizedStringTransformer::ROUND_CEILING), + array(1, '123,44', 123.5, NumberToLocalizedStringTransformer::ROUND_CEILING), + array(1, '-123,45', -123.4, NumberToLocalizedStringTransformer::ROUND_CEILING), + array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_CEILING), + // towards negative infinity (1.6 -> 1, -1.6 -> -2) + array(0, '1234,5', 1234, NumberToLocalizedStringTransformer::ROUND_FLOOR), + array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_FLOOR), + array(0, '-1234,5', -1235, NumberToLocalizedStringTransformer::ROUND_FLOOR), + array(0, '-1234,4', -1235, NumberToLocalizedStringTransformer::ROUND_FLOOR), + array(1, '123,45', 123.4, NumberToLocalizedStringTransformer::ROUND_FLOOR), + array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_FLOOR), + array(1, '-123,45', -123.5, NumberToLocalizedStringTransformer::ROUND_FLOOR), + array(1, '-123,44', -123.5, NumberToLocalizedStringTransformer::ROUND_FLOOR), + // away from zero (1.6 -> 2, -1.6 -> 2) + array(0, '1234,5', 1235, NumberToLocalizedStringTransformer::ROUND_UP), + array(0, '1234,4', 1235, NumberToLocalizedStringTransformer::ROUND_UP), + array(0, '-1234,5', -1235, NumberToLocalizedStringTransformer::ROUND_UP), + array(0, '-1234,4', -1235, NumberToLocalizedStringTransformer::ROUND_UP), + array(1, '123,45', 123.5, NumberToLocalizedStringTransformer::ROUND_UP), + array(1, '123,44', 123.5, NumberToLocalizedStringTransformer::ROUND_UP), + array(1, '-123,45', -123.5, NumberToLocalizedStringTransformer::ROUND_UP), + array(1, '-123,44', -123.5, NumberToLocalizedStringTransformer::ROUND_UP), + // towards zero (1.6 -> 1, -1.6 -> -1) + array(0, '1234,5', 1234, NumberToLocalizedStringTransformer::ROUND_DOWN), + array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_DOWN), + array(0, '-1234,5', -1234, NumberToLocalizedStringTransformer::ROUND_DOWN), + array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_DOWN), + array(1, '123,45', 123.4, NumberToLocalizedStringTransformer::ROUND_DOWN), + array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_DOWN), + array(1, '-123,45', -123.4, NumberToLocalizedStringTransformer::ROUND_DOWN), + array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_DOWN), + // round halves (.5) to the next even number + array(0, '1234,6', 1235, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(0, '1234,5', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(0, '1233,5', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(0, '1232,5', 1232, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(0, '-1234,6', -1235, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(0, '-1234,5', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(0, '-1233,5', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(0, '-1232,5', -1232, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1, '123,46', 123.5, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1, '123,45', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1, '123,35', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1, '123,25', 123.2, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1, '-123,46', -123.5, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1, '-123,45', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1, '-123,35', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + array(1, '-123,25', -123.2, NumberToLocalizedStringTransformer::ROUND_HALF_EVEN), + // round halves (.5) away from zero + array(0, '1234,6', 1235, NumberToLocalizedStringTransformer::ROUND_HALF_UP), + array(0, '1234,5', 1235, NumberToLocalizedStringTransformer::ROUND_HALF_UP), + array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_UP), + array(0, '-1234,6', -1235, NumberToLocalizedStringTransformer::ROUND_HALF_UP), + array(0, '-1234,5', -1235, NumberToLocalizedStringTransformer::ROUND_HALF_UP), + array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_UP), + array(1, '123,46', 123.5, NumberToLocalizedStringTransformer::ROUND_HALF_UP), + array(1, '123,45', 123.5, NumberToLocalizedStringTransformer::ROUND_HALF_UP), + array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_UP), + array(1, '-123,46', -123.5, NumberToLocalizedStringTransformer::ROUND_HALF_UP), + array(1, '-123,45', -123.5, NumberToLocalizedStringTransformer::ROUND_HALF_UP), + array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_UP), + // round halves (.5) towards zero + array(0, '1234,6', 1235, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(0, '1234,5', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(0, '1234,4', 1234, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(0, '-1234,6', -1235, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(0, '-1234,5', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(0, '-1234,4', -1234, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(1, '123,46', 123.5, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(1, '123,45', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(1, '123,44', 123.4, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(1, '-123,46', -123.5, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(1, '-123,45', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + array(1, '-123,44', -123.4, NumberToLocalizedStringTransformer::ROUND_HALF_DOWN), + ); + } + + /** + * @dataProvider reverseTransformWithRoundingProvider + */ + public function testReverseTransformWithRounding($precision, $input, $output, $roundingMode) + { + $transformer = new NumberToLocalizedStringTransformer($precision, null, $roundingMode); + + $this->assertEquals($output, $transformer->reverseTransform($input)); + } + + public function testReverseTransformDoesNotRoundIfNoPrecision() + { + $transformer = new NumberToLocalizedStringTransformer(null, null, NumberToLocalizedStringTransformer::ROUND_DOWN); + + $this->assertEquals(1234.547, $transformer->reverseTransform('1234,547')); + } + public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsNotDot() { \Locale::setDefault('fr'); From 861d8b176d413d873d4ce3f427b13b550951ac61 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 1 Aug 2013 17:20:43 +0200 Subject: [PATCH 147/447] [Form] Fixed: If a form is not present in a request, it is not automatically submitted --- .../HttpFoundationRequestHandler.php | 5 ++++- NativeRequestHandler.php | 9 ++++++--- Tests/AbstractRequestHandlerTest.php | 14 ++++++-------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/Extension/HttpFoundation/HttpFoundationRequestHandler.php b/Extension/HttpFoundation/HttpFoundationRequestHandler.php index cc4851566d..2094699481 100644 --- a/Extension/HttpFoundation/HttpFoundationRequestHandler.php +++ b/Extension/HttpFoundation/HttpFoundationRequestHandler.php @@ -56,10 +56,13 @@ public function handleRequest(FormInterface $form, $request = null) if ('' === $name) { $params = $request->request->all(); $files = $request->files->all(); - } else { + } elseif ($request->request->has($name) || $request->files->has($name)) { $default = $form->getConfig()->getCompound() ? array() : null; $params = $request->request->get($name, $default); $files = $request->files->get($name, $default); + } else { + // Don't submit the form if it is not present in the request + return; } if (is_array($params) && is_array($files)) { diff --git a/NativeRequestHandler.php b/NativeRequestHandler.php index aaa4e4c0f2..359df670ff 100644 --- a/NativeRequestHandler.php +++ b/NativeRequestHandler.php @@ -72,10 +72,13 @@ public function handleRequest(FormInterface $form, $request = null) if ('' === $name) { $params = $_POST; $files = $fixedFiles; - } else { + } elseif (array_key_exists($name, $_POST) || array_key_exists($name, $fixedFiles)) { $default = $form->getConfig()->getCompound() ? array() : null; - $params = isset($_POST[$name]) ? $_POST[$name] : $default; - $files = isset($fixedFiles[$name]) ? $fixedFiles[$name] : $default; + $params = array_key_exists($name, $_POST) ? $_POST[$name] : $default; + $files = array_key_exists($name, $fixedFiles) ? $fixedFiles[$name] : $default; + } else { + // Don't submit the form if it is not present in the request + return; } if (is_array($params) && is_array($files)) { diff --git a/Tests/AbstractRequestHandlerTest.php b/Tests/AbstractRequestHandlerTest.php index cef8f3bf0d..fbba16ba17 100644 --- a/Tests/AbstractRequestHandlerTest.php +++ b/Tests/AbstractRequestHandlerTest.php @@ -86,7 +86,7 @@ public function testDoNotSubmitIfWrongRequestMethod($method) /** * @dataProvider methodExceptGetProvider */ - public function testSubmitSimpleFormWithNullIfNameNotInRequestAndNotGetRequest($method) + public function testDoNoSubmitSimpleFormIfNameNotInRequestAndNotGetRequest($method) { $form = $this->getMockForm('param1', $method, false); @@ -94,9 +94,8 @@ public function testSubmitSimpleFormWithNullIfNameNotInRequestAndNotGetRequest($ 'paramx' => array(), )); - $form->expects($this->once()) - ->method('submit') - ->with($this->identicalTo(null), 'PATCH' !== $method); + $form->expects($this->never()) + ->method('submit'); $this->requestHandler->handleRequest($form, $this->request); } @@ -104,7 +103,7 @@ public function testSubmitSimpleFormWithNullIfNameNotInRequestAndNotGetRequest($ /** * @dataProvider methodExceptGetProvider */ - public function testSubmitCompoundFormWithArrayIfNameNotInRequestAndNotGetRequest($method) + public function testDoNotSubmitCompoundFormIfNameNotInRequestAndNotGetRequest($method) { $form = $this->getMockForm('param1', $method, true); @@ -112,9 +111,8 @@ public function testSubmitCompoundFormWithArrayIfNameNotInRequestAndNotGetReques 'paramx' => array(), )); - $form->expects($this->once()) - ->method('submit') - ->with($this->identicalTo(array()), 'PATCH' !== $method); + $form->expects($this->never()) + ->method('submit'); $this->requestHandler->handleRequest($form, $this->request); } From c01e6fe3f94f6eda8b55749f1422a3c54ab454d7 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 1 Aug 2013 17:40:17 +0200 Subject: [PATCH 148/447] Revert "[Form] Fix of "PATCH'ed forms are never valid"" This reverts commit a2b15359d81563d52b62b4357407efa949a0706a. Conflicts: src/Symfony/Component/Form/Form.php The commit is reverted because it introduces a bug demonstrated by a currently failing test. --- Form.php | 14 +------ Tests/CompoundFormTest.php | 75 +------------------------------------- 2 files changed, 4 insertions(+), 85 deletions(-) diff --git a/Form.php b/Form.php index 43f46ca228..2e7dac77a4 100644 --- a/Form.php +++ b/Form.php @@ -500,14 +500,6 @@ public function submit($submittedData, $clearMissing = true) return $this; } - // In order to process patch requests we need to "submit" null values - // Later this value will be mapped via DataMapper and InheritDataAwareIterator - if ($submittedData === null && !$clearMissing) { - $this->submitted = true; - - return $this; - } - // The data must be initialized if it was not initialized yet. // This is necessary to guarantee that the *_SET_DATA listeners // are always invoked before submit() takes place. @@ -545,12 +537,10 @@ public function submit($submittedData, $clearMissing = true) } foreach ($this->children as $name => $child) { - $fieldValue = null; - if (array_key_exists($name, $submittedData)) { - $fieldValue = $submittedData[$name]; + if (array_key_exists($name, $submittedData) || $clearMissing) { + $child->submit(isset($submittedData[$name]) ? $submittedData[$name] : null, $clearMissing); unset($submittedData[$name]); } - $child->submit($fieldValue, $clearMissing); } $this->extraData = $submittedData; diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index 34b11d3949..8557d8eb93 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -59,17 +59,14 @@ public function testSubmitForwardsNullIfValueIsMissing() $this->form->submit(array()); } - public function testSubmitDoesNotSaveNullIfNotClearMissing() + public function testSubmitDoesNotForwardNullIfNotClearMissing() { $child = $this->getMockForm('firstName'); $this->form->add($child); - $child->expects($this->once()) - ->method('submit'); - $child->expects($this->never()) - ->method('setData'); + ->method('submit'); $this->form->submit(array(), false); } @@ -564,74 +561,6 @@ public function testSubmitPostOrPutRequest($method) unlink($path); } - public function testSubmitPatchRequest() - { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - - $object = new \stdClass(); - $object->name = 'Bernhard'; - $object->name2 = 'Me'; - - //$values = array(); - $values = array( - 'author' => array( - 'name2' => 'Artem', - ), - ); - - $request = new Request(array(), $values, array(), array(), array(), array( - 'REQUEST_METHOD' => 'PATCH', - )); - - $mapper = $this->getDataMapper(); - $mapper->expects($this->any()) - ->method('mapDataToForms') - ->will($this->returnCallback(function($data, $forms){ - foreach ($forms as $form) { - $propertyPath = $form->getPropertyPath(); - - if (null !== $propertyPath) { - $form->setData($data->{$propertyPath}); - } - } - })); - - - $mapper->expects($this->any()) - ->method('mapFormsToData') - ->will($this->returnCallback(function($forms, &$data){ - foreach ($forms as $form) { - $propertyPath = $form->getPropertyPath(); - - if (null !== $propertyPath) { - if (!is_object($data) || $form->getData() !== $data->{$propertyPath}) { - $data->{$propertyPath} = $form->getData(); - } - } - } - })); - - /** @var Form $form */ - $form = $this->getBuilder('author', null, 'stdClass') - ->setMethod('PATCH') - ->setData($object) - ->setCompound(true) - ->setDataMapper($mapper) - ->setRequestHandler(new HttpFoundationRequestHandler()) - ->getForm(); - $form->add($this->getBuilder('name')->getForm()); - $form->add($this->getBuilder('name2')->getForm()); - - $form->handleRequest($request); - - $this->assertTrue($form->isValid()); - - $this->assertEquals('Bernhard', $form['name']->getData()); - $this->assertEquals('Artem', $form['name2']->getData()); - } - /** * @dataProvider requestMethodProvider */ From b37babf04545f9811190703d03fa9f78cb4b9f86 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 1 Aug 2013 18:06:16 +0200 Subject: [PATCH 149/447] [Form] Fixed patched forms to be valid even if children are not submitted --- .../Core/DataMapper/PropertyPathMapper.php | 6 +- Form.php | 12 +-- Tests/AbstractFormTest.php | 32 -------- Tests/CompoundFormTest.php | 73 ++++++++++--------- .../DataMapper/PropertyPathMapperTest.php | 26 ++++++- 5 files changed, 72 insertions(+), 77 deletions(-) diff --git a/Extension/Core/DataMapper/PropertyPathMapper.php b/Extension/Core/DataMapper/PropertyPathMapper.php index d8bd9c715b..ae4796e5e7 100644 --- a/Extension/Core/DataMapper/PropertyPathMapper.php +++ b/Extension/Core/DataMapper/PropertyPathMapper.php @@ -78,9 +78,9 @@ public function mapFormsToData($forms, &$data) $propertyPath = $form->getPropertyPath(); $config = $form->getConfig(); - // Write-back is disabled if the form is not synchronized (transformation failed) - // and if the form is disabled (modification not allowed) - if (null !== $propertyPath && $config->getMapped() && $form->isSynchronized() && !$form->isDisabled()) { + // Write-back is disabled if the form is not synchronized (transformation failed), + // if the form was not submitted and if the form is disabled (modification not allowed) + if (null !== $propertyPath && $config->getMapped() && $form->isSubmitted() && $form->isSynchronized() && !$form->isDisabled()) { // If the data is identical to the value in $data, we are // dealing with a reference if (!is_object($data) || !$config->getByReference() || $form->getData() !== $this->propertyAccessor->getValue($data, $propertyPath)) { diff --git a/Form.php b/Form.php index 2e7dac77a4..bcab8afdc2 100644 --- a/Form.php +++ b/Form.php @@ -710,11 +710,13 @@ public function isValid() return false; } - if (!$this->isDisabled()) { - foreach ($this->children as $child) { - if (!$child->isValid()) { - return false; - } + if ($this->isDisabled()) { + return true; + } + + foreach ($this->children as $child) { + if ($child->isSubmitted() && !$child->isValid()) { + return false; } } diff --git a/Tests/AbstractFormTest.php b/Tests/AbstractFormTest.php index 2911818752..77b0188a03 100644 --- a/Tests/AbstractFormTest.php +++ b/Tests/AbstractFormTest.php @@ -89,38 +89,6 @@ protected function getMockForm($name = 'name') return $form; } - /** - * @param string $name - * - * @return \PHPUnit_Framework_MockObject_MockObject - */ - protected function getValidForm($name) - { - $form = $this->getMockForm($name); - - $form->expects($this->any()) - ->method('isValid') - ->will($this->returnValue(true)); - - return $form; - } - - /** - * @param string $name - * - * @return \PHPUnit_Framework_MockObject_MockObject - */ - protected function getInvalidForm($name) - { - $form = $this->getMockForm($name); - - $form->expects($this->any()) - ->method('isValid') - ->will($this->returnValue(false)); - - return $form; - } - /** * @return \PHPUnit_Framework_MockObject_MockObject */ diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index 8557d8eb93..4c5cfb9a48 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -22,8 +22,8 @@ class CompoundFormTest extends AbstractFormTest { public function testValidIfAllChildrenAreValid() { - $this->form->add($this->getValidForm('firstName')); - $this->form->add($this->getValidForm('lastName')); + $this->form->add($this->getBuilder('firstName')->getForm()); + $this->form->add($this->getBuilder('lastName')->getForm()); $this->form->submit(array( 'firstName' => 'Bernhard', @@ -35,17 +35,51 @@ public function testValidIfAllChildrenAreValid() public function testInvalidIfChildIsInvalid() { - $this->form->add($this->getValidForm('firstName')); - $this->form->add($this->getInvalidForm('lastName')); + $this->form->add($this->getBuilder('firstName')->getForm()); + $this->form->add($this->getBuilder('lastName')->getForm()); $this->form->submit(array( 'firstName' => 'Bernhard', 'lastName' => 'Schussek', )); + $this->form->get('lastName')->addError(new FormError('Invalid')); + $this->assertFalse($this->form->isValid()); } + public function testValidIfChildIsNotSubmitted() + { + $this->form->add($this->getBuilder('firstName')->getForm()); + $this->form->add($this->getBuilder('lastName')->getForm()); + + $this->form->submit(array( + 'firstName' => 'Bernhard', + )); + + // "lastName" is not "valid" because it was not submitted. This happens + // for example in PATCH requests. The parent form should still be + // considered valid. + + $this->assertTrue($this->form->isValid()); + } + + public function testDisabledFormsValidEvenIfChildrenInvalid() + { + $form = $this->getBuilder('person') + ->setDisabled(true) + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->add($this->getBuilder('name')) + ->getForm(); + + $form->submit(array('name' => 'Jacques Doe')); + + $form->get('name')->addError(new FormError('Invalid')); + + $this->assertTrue($form->isValid()); + } + public function testSubmitForwardsNullIfValueIsMissing() { $child = $this->getMockForm('firstName'); @@ -121,37 +155,6 @@ public function testNotEmptyIfChildNotEmpty() $this->assertFalse($this->form->isEmpty()); } - public function testValidIfSubmittedAndDisabledWithChildren() - { - $this->factory->expects($this->once()) - ->method('createNamedBuilder') - ->with('name', 'text', null, array()) - ->will($this->returnValue($this->getBuilder('name'))); - - $form = $this->getBuilder('person') - ->setDisabled(true) - ->setCompound(true) - ->setDataMapper($this->getDataMapper()) - ->add('name', 'text') - ->getForm(); - $form->submit(array('name' => 'Jacques Doe')); - - $this->assertTrue($form->isValid()); - } - - public function testNotValidIfChildNotValid() - { - $child = $this->getMockForm(); - $child->expects($this->once()) - ->method('isValid') - ->will($this->returnValue(false)); - - $this->form->add($child); - $this->form->submit(array()); - - $this->assertFalse($this->form->isValid()); - } - public function testAdd() { $child = $this->getBuilder('foo')->getForm(); diff --git a/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php b/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php index ee2e3351ce..ed6d8cb01e 100644 --- a/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php +++ b/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php @@ -64,17 +64,21 @@ private function getPropertyPath($path) * @param Boolean $synchronized * @return \PHPUnit_Framework_MockObject_MockObject */ - private function getForm(FormConfigInterface $config, $synchronized = true) + private function getForm(FormConfigInterface $config, $synchronized = true, $submitted = true) { $form = $this->getMockBuilder('Symfony\Component\Form\Form') ->setConstructorArgs(array($config)) - ->setMethods(array('isSynchronized')) + ->setMethods(array('isSynchronized', 'isSubmitted')) ->getMock(); $form->expects($this->any()) ->method('isSynchronized') ->will($this->returnValue($synchronized)); + $form->expects($this->any()) + ->method('isSubmitted') + ->will($this->returnValue($submitted)); + return $form; } @@ -263,6 +267,24 @@ public function testMapFormsToDataIgnoresUnmapped() $this->mapper->mapFormsToData(array($form), $car); } + public function testMapFormsToDataIgnoresUnsubmittedForms() + { + $car = new \stdClass(); + $engine = new \stdClass(); + $propertyPath = $this->getPropertyPath('engine'); + + $this->propertyAccessor->expects($this->never()) + ->method('setValue'); + + $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); + $config->setByReference(true); + $config->setPropertyPath($propertyPath); + $config->setData($engine); + $form = $this->getForm($config, true, false); + + $this->mapper->mapFormsToData(array($form), $car); + } + public function testMapFormsToDataIgnoresEmptyData() { $car = new \stdClass(); From ca017cee65972b5269bcea698f2765b52119e873 Mon Sep 17 00:00:00 2001 From: Bob den Otter Date: Fri, 2 Aug 2013 13:14:00 +0200 Subject: [PATCH 150/447] Fix issue with \DateTimeZone::UTC / 'UTC' for PHP 5.4 --- Extension/Core/Type/DateType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/Core/Type/DateType.php b/Extension/Core/Type/DateType.php index 648ab1b7e5..667b7db3d1 100644 --- a/Extension/Core/Type/DateType.php +++ b/Extension/Core/Type/DateType.php @@ -271,7 +271,7 @@ private function formatTimestamps(\IntlDateFormatter $formatter, $regex, array $ if (version_compare(\PHP_VERSION, '5.5.0-dev', '>=')) { $formatter->setTimeZone(\DateTimeZone::UTC); } else { - $formatter->setTimeZoneId(\DateTimeZone::UTC); + $formatter->setTimeZoneId('UTC'); } if (preg_match($regex, $pattern, $matches)) { From 5869441247ae40893a0ab704aba92d5eab470e7b Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 2 Aug 2013 15:04:40 +0200 Subject: [PATCH 151/447] [Form] fixed wrong call to setTimeZone() (closes #8644) --- Extension/Core/Type/DateType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/Core/Type/DateType.php b/Extension/Core/Type/DateType.php index 667b7db3d1..05b2aaedc1 100644 --- a/Extension/Core/Type/DateType.php +++ b/Extension/Core/Type/DateType.php @@ -269,7 +269,7 @@ private function formatTimestamps(\IntlDateFormatter $formatter, $regex, array $ $timezone = $formatter->getTimezoneId(); if (version_compare(\PHP_VERSION, '5.5.0-dev', '>=')) { - $formatter->setTimeZone(\DateTimeZone::UTC); + $formatter->setTimeZone('UTC'); } else { $formatter->setTimeZoneId('UTC'); } From 8c9c2cf3df114e65d1c75e99531d19f152c812f9 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Mon, 24 Jun 2013 15:42:05 +0100 Subject: [PATCH 152/447] [Form] Moved auto_initialize option to the BaseType --- Extension/Core/Type/BaseType.php | 2 ++ Extension/Core/Type/ButtonType.php | 13 +++++++++++++ Extension/Core/Type/FormType.php | 2 -- Tests/Extension/Core/Type/SubmitTypeTest.php | 9 +++++++++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/Extension/Core/Type/BaseType.php b/Extension/Core/Type/BaseType.php index 79333a6799..a6f8c430e1 100644 --- a/Extension/Core/Type/BaseType.php +++ b/Extension/Core/Type/BaseType.php @@ -33,6 +33,7 @@ abstract class BaseType extends AbstractType public function buildForm(FormBuilderInterface $builder, array $options) { $builder->setDisabled($options['disabled']); + $builder->setAutoInitialize($options['auto_initialize']); } /** @@ -112,6 +113,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'label' => null, 'attr' => array(), 'translation_domain' => null, + 'auto_initialize' => true, )); $resolver->setAllowedTypes(array( diff --git a/Extension/Core/Type/ButtonType.php b/Extension/Core/Type/ButtonType.php index 3569963bc4..75e95ab41e 100644 --- a/Extension/Core/Type/ButtonType.php +++ b/Extension/Core/Type/ButtonType.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\ButtonTypeInterface; +use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** * A form button. @@ -35,4 +36,16 @@ public function getName() { return 'button'; } + + /** + * {@inheritdoc} + */ + public function setDefaultOptions(OptionsResolverInterface $resolver) + { + parent::setDefaultOptions($resolver); + + $resolver->setDefaults(array( + 'auto_initialize' => false, + )); + } } diff --git a/Extension/Core/Type/FormType.php b/Extension/Core/Type/FormType.php index eb1897cee4..190bb52cec 100644 --- a/Extension/Core/Type/FormType.php +++ b/Extension/Core/Type/FormType.php @@ -55,7 +55,6 @@ public function buildForm(FormBuilderInterface $builder, array $options) ->setDataMapper($options['compound'] ? new PropertyPathMapper($this->propertyAccessor) : null) ->setMethod($options['method']) ->setAction($options['action']) - ->setAutoInitialize($options['auto_initialize']) ; if ($options['trim']) { @@ -189,7 +188,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) // According to RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt) // section 4.2., empty URIs are considered same-document references 'action' => '', - 'auto_initialize' => true, )); $resolver->setAllowedTypes(array( diff --git a/Tests/Extension/Core/Type/SubmitTypeTest.php b/Tests/Extension/Core/Type/SubmitTypeTest.php index 8cc72281b2..2319a4fe75 100644 --- a/Tests/Extension/Core/Type/SubmitTypeTest.php +++ b/Tests/Extension/Core/Type/SubmitTypeTest.php @@ -51,4 +51,13 @@ public function testClickedIfSubmittedWithUnemptyString() $this->assertTrue($button->isClicked()); } + + public function testSubmitCanBeAddedToForm() + { + $form = $this->factory + ->createBuilder('form') + ->getForm(); + + $this->assertSame($form, $form->add('send', 'submit')); + } } From e6538acf052b7ea5781bd40ba73e4101e2f3ae8a Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 15 Aug 2013 14:37:02 +0200 Subject: [PATCH 153/447] [Form] Fixed: Added "validation_groups" option to submit button --- .../Type/SubmitTypeValidatorExtension.php | 4 +- .../Type/BaseValidatorExtensionTest.php | 74 +++++++++++++++++++ .../Type/FormTypeValidatorExtensionTest.php | 61 ++------------- .../Type/SubmitTypeValidatorExtensionTest.php | 20 +++++ 4 files changed, 101 insertions(+), 58 deletions(-) create mode 100644 Tests/Extension/Validator/Type/BaseValidatorExtensionTest.php create mode 100644 Tests/Extension/Validator/Type/SubmitTypeValidatorExtensionTest.php diff --git a/Extension/Validator/Type/SubmitTypeValidatorExtension.php b/Extension/Validator/Type/SubmitTypeValidatorExtension.php index 5aad67fb3a..ff1c762ef0 100644 --- a/Extension/Validator/Type/SubmitTypeValidatorExtension.php +++ b/Extension/Validator/Type/SubmitTypeValidatorExtension.php @@ -11,12 +11,10 @@ namespace Symfony\Component\Form\Extension\Validator\Type; -use Symfony\Component\Form\AbstractTypeExtension; - /** * @author Bernhard Schussek */ -class SubmitTypeValidatorExtension extends AbstractTypeExtension +class SubmitTypeValidatorExtension extends BaseValidatorExtension { /** * {@inheritdoc} diff --git a/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.php b/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.php new file mode 100644 index 0000000000..fd437c50ea --- /dev/null +++ b/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.php @@ -0,0 +1,74 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Validator\Type; + +use Symfony\Component\Form\Test\FormInterface; + +/** + * @author Bernhard Schussek + */ +abstract class BaseValidatorExtensionTest extends TypeTestCase +{ + public function testValidationGroupNullByDefault() + { + $form = $this->createForm(); + + $this->assertNull($form->getConfig()->getOption('validation_groups')); + } + + public function testValidationGroupsTransformedToArray() + { + $form = $this->createForm(array( + 'validation_groups' => 'group', + )); + + $this->assertEquals(array('group'), $form->getConfig()->getOption('validation_groups')); + } + + public function testValidationGroupsCanBeSetToArray() + { + $form = $this->createForm(array( + 'validation_groups' => array('group1', 'group2'), + )); + + $this->assertEquals(array('group1', 'group2'), $form->getConfig()->getOption('validation_groups')); + } + + public function testValidationGroupsCanBeSetToFalse() + { + $form = $this->createForm(array( + 'validation_groups' => false, + )); + + $this->assertEquals(array(), $form->getConfig()->getOption('validation_groups')); + } + + public function testValidationGroupsCanBeSetToCallback() + { + $form = $this->createForm(array( + 'validation_groups' => array($this, 'testValidationGroupsCanBeSetToCallback'), + )); + + $this->assertTrue(is_callable($form->getConfig()->getOption('validation_groups'))); + } + + public function testValidationGroupsCanBeSetToClosure() + { + $form = $this->createForm(array( + 'validation_groups' => function(FormInterface $form){ return null; }, + )); + + $this->assertTrue(is_callable($form->getConfig()->getOption('validation_groups'))); + } + + abstract protected function createForm(array $options = array()); +} diff --git a/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php b/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php index 6619410599..0eef62d29c 100644 --- a/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php +++ b/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php @@ -11,62 +11,8 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\Type; -use Symfony\Component\Form\FormInterface; - -class FormTypeValidatorExtensionTest extends TypeTestCase +class FormTypeValidatorExtensionTest extends BaseValidatorExtensionTest { - public function testValidationGroupNullByDefault() - { - $form = $this->factory->create('form'); - - $this->assertNull($form->getConfig()->getOption('validation_groups')); - } - - public function testValidationGroupsTransformedToArray() - { - $form = $this->factory->create('form', null, array( - 'validation_groups' => 'group', - )); - - $this->assertEquals(array('group'), $form->getConfig()->getOption('validation_groups')); - } - - public function testValidationGroupsCanBeSetToArray() - { - $form = $this->factory->create('form', null, array( - 'validation_groups' => array('group1', 'group2'), - )); - - $this->assertEquals(array('group1', 'group2'), $form->getConfig()->getOption('validation_groups')); - } - - public function testValidationGroupsCanBeSetToFalse() - { - $form = $this->factory->create('form', null, array( - 'validation_groups' => false, - )); - - $this->assertEquals(array(), $form->getConfig()->getOption('validation_groups')); - } - - public function testValidationGroupsCanBeSetToCallback() - { - $form = $this->factory->create('form', null, array( - 'validation_groups' => array($this, 'testValidationGroupsCanBeSetToCallback'), - )); - - $this->assertTrue(is_callable($form->getConfig()->getOption('validation_groups'))); - } - - public function testValidationGroupsCanBeSetToClosure() - { - $form = $this->factory->create('form', null, array( - 'validation_groups' => function(FormInterface $form){ return null; }, - )); - - $this->assertTrue(is_callable($form->getConfig()->getOption('validation_groups'))); - } - public function testSubmitValidatesData() { $builder = $this->factory->createBuilder('form', null, array( @@ -82,4 +28,9 @@ public function testSubmitValidatesData() // specific data is irrelevant $form->submit(array()); } + + protected function createForm(array $options = array()) + { + return $this->factory->create('form', null, $options); + } } diff --git a/Tests/Extension/Validator/Type/SubmitTypeValidatorExtensionTest.php b/Tests/Extension/Validator/Type/SubmitTypeValidatorExtensionTest.php new file mode 100644 index 0000000000..c37cf6733c --- /dev/null +++ b/Tests/Extension/Validator/Type/SubmitTypeValidatorExtensionTest.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Validator\Type; + +class SubmitTypeValidatorExtensionTest extends BaseValidatorExtensionTest +{ + protected function createForm(array $options = array()) + { + return $this->factory->create('submit', null, $options); + } +} From f0cacb2f26f1d135bbb406945b42749ef9fbd8b5 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 19 Aug 2013 22:44:13 +0200 Subject: [PATCH 154/447] removed deps checks in unit tests As Composer is now widely used in the PHP world, having to run composer install before running the test suite is expected. This also has the nice benefit of removing a bunch of code, making things easier to maintain (there is only one place to declare a dev dependency), and probably more. --- Test/FormIntegrationTestCase.php | 4 --- Tests/AbstractFormTest.php | 4 --- Tests/CompoundFormTest.php | 24 -------------- .../DataMapper/PropertyPathMapperTest.php | 8 ----- .../FixRadioInputListenerTest.php | 4 --- .../FixUrlProtocolListenerTest.php | 7 ---- .../MergeCollectionListenerTest.php | 4 --- .../EventListener/ResizeFormListenerTest.php | 4 --- .../Core/EventListener/TrimListenerTest.php | 7 ---- .../CsrfProvider/SessionCsrfProviderTest.php | 4 --- .../CsrfValidationListenerTest.php | 4 --- .../EventListener/BindRequestListenerTest.php | 32 ------------------- .../Constraints/FormValidatorTest.php | 4 --- .../EventListener/ValidationListenerTest.php | 4 --- .../Extension/Validator/Type/TypeTestCase.php | 4 --- .../ViolationMapper/ViolationMapperTest.php | 4 --- Tests/FormBuilderTest.php | 4 --- Tests/FormFactoryTest.php | 4 --- Tests/ResolvedFormTypeTest.php | 8 ----- 19 files changed, 138 deletions(-) diff --git a/Test/FormIntegrationTestCase.php b/Test/FormIntegrationTestCase.php index 68e5f2445e..82894d5522 100644 --- a/Test/FormIntegrationTestCase.php +++ b/Test/FormIntegrationTestCase.php @@ -25,10 +25,6 @@ abstract class FormIntegrationTestCase extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - $this->factory = Forms::createFormFactoryBuilder() ->addExtensions($this->getExtensions()) ->getFormFactory(); diff --git a/Tests/AbstractFormTest.php b/Tests/AbstractFormTest.php index 77b0188a03..28f0e389e5 100644 --- a/Tests/AbstractFormTest.php +++ b/Tests/AbstractFormTest.php @@ -34,10 +34,6 @@ abstract class AbstractFormTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - // We need an actual dispatcher to use the deprecated // bindRequest() method $this->dispatcher = new EventDispatcher(); diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index 4c5cfb9a48..6f360ec385 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -517,10 +517,6 @@ public function requestMethodProvider() */ public function testSubmitPostOrPutRequest($method) { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $path = tempnam(sys_get_temp_dir(), 'sf2'); touch($path); @@ -569,10 +565,6 @@ public function testSubmitPostOrPutRequest($method) */ public function testSubmitPostOrPutRequestWithEmptyRootFormName($method) { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $path = tempnam(sys_get_temp_dir(), 'sf2'); touch($path); @@ -620,10 +612,6 @@ public function testSubmitPostOrPutRequestWithEmptyRootFormName($method) */ public function testSubmitPostOrPutRequestWithSingleChildForm($method) { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $path = tempnam(sys_get_temp_dir(), 'sf2'); touch($path); @@ -660,10 +648,6 @@ public function testSubmitPostOrPutRequestWithSingleChildForm($method) */ public function testSubmitPostOrPutRequestWithSingleChildFormUploadedFile($method) { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $path = tempnam(sys_get_temp_dir(), 'sf2'); touch($path); @@ -689,10 +673,6 @@ public function testSubmitPostOrPutRequestWithSingleChildFormUploadedFile($metho public function testSubmitGetRequest() { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $values = array( 'author' => array( 'firstName' => 'Bernhard', @@ -721,10 +701,6 @@ public function testSubmitGetRequest() public function testSubmitGetRequestWithEmptyRootFormName() { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $values = array( 'firstName' => 'Bernhard', 'lastName' => 'Schussek', diff --git a/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php b/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php index ed6d8cb01e..2878644e9c 100644 --- a/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php +++ b/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php @@ -34,14 +34,6 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\Event')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - - if (!class_exists('Symfony\Component\PropertyAccess\PropertyAccess')) { - $this->markTestSkipped('The "PropertyAccess" component is not available'); - } - $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->propertyAccessor = $this->getMock('Symfony\Component\PropertyAccess\PropertyAccessorInterface'); $this->mapper = new PropertyPathMapper($this->propertyAccessor); diff --git a/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php b/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php index a5d5c78a81..426293395c 100644 --- a/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php +++ b/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php @@ -21,10 +21,6 @@ class FixRadioInputListenerTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - parent::setUp(); $this->choiceList = new SimpleChoiceList(array('' => 'Empty', 0 => 'A', 1 => 'B')); diff --git a/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php b/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php index 2b84e4fd82..475681a053 100644 --- a/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php +++ b/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php @@ -16,13 +16,6 @@ class FixUrlProtocolListenerTest extends \PHPUnit_Framework_TestCase { - protected function setUp() - { - if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - } - public function testFixHttpUrl() { $data = "www.symfony.com"; diff --git a/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php b/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php index dbd28c6b55..2d7ecfec75 100644 --- a/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php +++ b/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php @@ -22,10 +22,6 @@ abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->form = $this->getForm('axes'); diff --git a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php index 1367b3ef02..67a71e462a 100644 --- a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php +++ b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php @@ -23,10 +23,6 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->form = $this->getBuilder() diff --git a/Tests/Extension/Core/EventListener/TrimListenerTest.php b/Tests/Extension/Core/EventListener/TrimListenerTest.php index 4e36893380..6e81ed404c 100644 --- a/Tests/Extension/Core/EventListener/TrimListenerTest.php +++ b/Tests/Extension/Core/EventListener/TrimListenerTest.php @@ -16,13 +16,6 @@ class TrimListenerTest extends \PHPUnit_Framework_TestCase { - protected function setUp() - { - if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - } - public function testTrim() { $data = " Foo! "; diff --git a/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.php b/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.php index 1dcc6b4c63..99e87158b5 100644 --- a/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.php +++ b/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.php @@ -20,10 +20,6 @@ class SessionCsrfProviderTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\HttpFoundation\Session\Session')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $this->session = $this->getMock( 'Symfony\Component\HttpFoundation\Session\Session', array(), diff --git a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php index 0bcfe74e99..7f2220af72 100644 --- a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php +++ b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php @@ -23,10 +23,6 @@ class CsrfValidationListenerTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->csrfProvider = $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface'); diff --git a/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php b/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php index 2ff072b2eb..a60145f2db 100644 --- a/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php +++ b/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php @@ -86,10 +86,6 @@ public function requestMethodProvider() */ public function testSubmitRequest($method) { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $values = array('author' => $this->values); $files = array('author' => $this->filesNested); $request = new Request(array(), $values, array(), array(), $files, array( @@ -115,10 +111,6 @@ public function testSubmitRequest($method) */ public function testSubmitRequestWithEmptyName($method) { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $request = new Request(array(), $this->values, array(), array(), $this->filesPlain, array( 'REQUEST_METHOD' => $method, )); @@ -142,10 +134,6 @@ public function testSubmitRequestWithEmptyName($method) */ public function testSubmitEmptyRequestToCompoundForm($method) { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $request = new Request(array(), array(), array(), array(), array(), array( 'REQUEST_METHOD' => $method, )); @@ -169,10 +157,6 @@ public function testSubmitEmptyRequestToCompoundForm($method) */ public function testSubmitEmptyRequestToSimpleForm($method) { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $request = new Request(array(), array(), array(), array(), array(), array( 'REQUEST_METHOD' => $method, )); @@ -192,10 +176,6 @@ public function testSubmitEmptyRequestToSimpleForm($method) public function testSubmitGetRequest() { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $values = array('author' => $this->values); $request = new Request($values, array(), array(), array(), array(), array( 'REQUEST_METHOD' => 'GET', @@ -217,10 +197,6 @@ public function testSubmitGetRequest() public function testSubmitGetRequestWithEmptyName() { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $request = new Request($this->values, array(), array(), array(), array(), array( 'REQUEST_METHOD' => 'GET', )); @@ -241,10 +217,6 @@ public function testSubmitGetRequestWithEmptyName() public function testSubmitEmptyGetRequestToCompoundForm() { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $request = new Request(array(), array(), array(), array(), array(), array( 'REQUEST_METHOD' => 'GET', )); @@ -264,10 +236,6 @@ public function testSubmitEmptyGetRequestToCompoundForm() public function testSubmitEmptyGetRequestToSimpleForm() { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $request = new Request(array(), array(), array(), array(), array(), array( 'REQUEST_METHOD' => 'GET', )); diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index a8bdde8a4d..7fc8eadcce 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -49,10 +49,6 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\Event')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->serverParams = $this->getMock( diff --git a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php index 57e0a48185..8d8f9235d1 100644 --- a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php +++ b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php @@ -54,10 +54,6 @@ class ValidationListenerTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\Event')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface'); diff --git a/Tests/Extension/Validator/Type/TypeTestCase.php b/Tests/Extension/Validator/Type/TypeTestCase.php index d94d896a1c..f197b19857 100644 --- a/Tests/Extension/Validator/Type/TypeTestCase.php +++ b/Tests/Extension/Validator/Type/TypeTestCase.php @@ -20,10 +20,6 @@ abstract class TypeTestCase extends BaseTypeTestCase protected function setUp() { - if (!class_exists('Symfony\Component\Validator\Constraint')) { - $this->markTestSkipped('The "Validator" component is not available'); - } - $this->validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface'); $metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface'); $this->validator->expects($this->once())->method('getMetadataFactory')->will($this->returnValue($metadataFactory)); diff --git a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php index c802ea7e80..a84d5b951a 100644 --- a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php +++ b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php @@ -60,10 +60,6 @@ class ViolationMapperTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\Event')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->mapper = new ViolationMapper(); $this->message = 'Message'; diff --git a/Tests/FormBuilderTest.php b/Tests/FormBuilderTest.php index e076c97e78..be85ff322a 100644 --- a/Tests/FormBuilderTest.php +++ b/Tests/FormBuilderTest.php @@ -23,10 +23,6 @@ class FormBuilderTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->builder = new FormBuilder('name', null, $this->dispatcher, $this->factory); diff --git a/Tests/FormFactoryTest.php b/Tests/FormFactoryTest.php index ea872b01ed..bb24079450 100644 --- a/Tests/FormFactoryTest.php +++ b/Tests/FormFactoryTest.php @@ -53,10 +53,6 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - $this->resolvedTypeFactory = $this->getMock('Symfony\Component\Form\ResolvedFormTypeFactoryInterface'); $this->guesser1 = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface'); $this->guesser2 = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface'); diff --git a/Tests/ResolvedFormTypeTest.php b/Tests/ResolvedFormTypeTest.php index bb32a24122..de19e9783e 100644 --- a/Tests/ResolvedFormTypeTest.php +++ b/Tests/ResolvedFormTypeTest.php @@ -39,14 +39,6 @@ class ResolvedFormTypeTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\OptionsResolver\OptionsResolver')) { - $this->markTestSkipped('The "OptionsResolver" component is not available'); - } - - if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->dataMapper = $this->getMock('Symfony\Component\Form\DataMapperInterface'); From 9490bb9617752aa75b471b446e3819e932e2de72 Mon Sep 17 00:00:00 2001 From: Bart van den Burg Date: Wed, 21 Aug 2013 13:31:00 +0200 Subject: [PATCH 155/447] [Form] check the required output timezone against the actual timezone of the input datetime object, rather than the expected timezone supplied --- Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php | 2 +- .../Core/DataTransformer/DateTimeToRfc3339TransformerTest.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php b/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php index 0eb0742277..0723704ae1 100644 --- a/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php +++ b/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php @@ -58,7 +58,7 @@ public function reverseTransform($rfc3339) throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } - if ($this->outputTimezone !== $this->inputTimezone) { + if ($this->outputTimezone !== $dateTime->getTimezone()->getName()) { try { $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone)); } catch (\Exception $e) { diff --git a/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php b/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php index 98aeb77292..c8f3806086 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php @@ -65,6 +65,7 @@ public function reverseTransformProvider() // format without seconds, as appears in some browsers array('UTC', 'UTC', '2010-02-03 04:05:00 UTC', '2010-02-03T04:05Z'), array('America/New_York', 'Asia/Hong_Kong', '2010-02-03 04:05:00 America/New_York', '2010-02-03T17:05+08:00'), + array('Europe/Amsterdam', 'Europe/Amsterdam', '2013-08-21 10:30:00 Europe/Amsterdam', '2013-08-21T08:30:00Z') )); } From f41b2f214c98da8942e0f6b924dbc432d0f0e8e2 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 15 Aug 2013 21:04:26 +0200 Subject: [PATCH 156/447] [Form] Fixed: submit() reacts to dynamic modifications of the form children --- Form.php | 9 +- Tests/AbstractFormTest.php | 3 + Tests/CompoundFormTest.php | 55 ++++++--- Tests/Util/VirtualFormAwareIteratorTest.php | 122 ++++++++++++++++++++ Util/VirtualFormAwareIterator.php | 74 +++++++++++- 5 files changed, 242 insertions(+), 21 deletions(-) create mode 100644 Tests/Util/VirtualFormAwareIteratorTest.php diff --git a/Form.php b/Form.php index 55d80c2f9f..2cf0c9dff8 100644 --- a/Form.php +++ b/Form.php @@ -552,7 +552,12 @@ public function bind($submittedData) $submittedData = array(); } - foreach ($this->children as $name => $child) { + reset($this->children); + + for (reset($this->children); false !== current($this->children); next($this->children)) { + $child = current($this->children); + $name = key($this->children); + $child->bind(isset($submittedData[$name]) ? $submittedData[$name] : null); unset($submittedData[$name]); } @@ -829,7 +834,7 @@ public function getClientTransformers() /** * {@inheritdoc} */ - public function all() + public function &all() { return $this->children; } diff --git a/Tests/AbstractFormTest.php b/Tests/AbstractFormTest.php index 5e13863aa9..46be43eb0d 100644 --- a/Tests/AbstractFormTest.php +++ b/Tests/AbstractFormTest.php @@ -81,6 +81,9 @@ protected function getMockForm($name = 'name') $form->expects($this->any()) ->method('getName') ->will($this->returnValue($name)); + $form->expects($this->any()) + ->method('getConfig') + ->will($this->returnValue($this->getMock('Symfony\Component\Form\FormConfigInterface'))); return $form; } diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index ca97c8ec2a..d719133da1 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Form\Tests; -use Symfony\Component\Form\Form; use Symfony\Component\Form\FormError; use Symfony\Component\Form\Extension\HttpFoundation\EventListener\BindRequestListener; use Symfony\Component\HttpFoundation\Request; @@ -46,19 +45,6 @@ public function testInvalidIfChildIsInvalid() $this->assertFalse($this->form->isValid()); } - public function testBindForwardsNullIfValueIsMissing() - { - $child = $this->getMockForm('firstName'); - - $this->form->add($child); - - $child->expects($this->once()) - ->method('bind') - ->with($this->equalTo(null)); - - $this->form->bind(array()); - } - public function testCloneChildren() { $child = $this->getBuilder('child')->getForm(); @@ -322,6 +308,47 @@ public function testSetDataMapsViewDataToChildren() $form->setData('foo'); } + public function testBindForwardsNullIfValueIsMissing() + { + $child = $this->getMockForm('firstName'); + + $this->form->add($child); + + $child->expects($this->once()) + ->method('bind') + ->with($this->equalTo(null)); + + $this->form->bind(array()); + } + + public function testBindSupportsDynamicAdditionAndRemovalOfChildren() + { + $child = $this->getMockForm('child'); + $childToBeRemoved = $this->getMockForm('removed'); + $childToBeAdded = $this->getMockForm('added'); + + $this->form->add($child); + $this->form->add($childToBeRemoved); + + $form = $this->form; + + $child->expects($this->once()) + ->method('bind') + ->will($this->returnCallback(function () use ($form, $childToBeAdded) { + $form->remove('removed'); + $form->add($childToBeAdded); + })); + + $childToBeRemoved->expects($this->never()) + ->method('bind'); + + $childToBeAdded->expects($this->once()) + ->method('bind'); + + // pass NULL to all children + $this->form->bind(array()); + } + public function testBindMapsBoundChildrenOntoExistingViewData() { $test = $this; diff --git a/Tests/Util/VirtualFormAwareIteratorTest.php b/Tests/Util/VirtualFormAwareIteratorTest.php new file mode 100644 index 0000000000..805acad903 --- /dev/null +++ b/Tests/Util/VirtualFormAwareIteratorTest.php @@ -0,0 +1,122 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Util; + +use Symfony\Component\Form\Util\VirtualFormAwareIterator; + +/** + * @author Bernhard Schussek + */ +class VirtualFormAwareIteratorTest extends \PHPUnit_Framework_TestCase +{ + public function testSupportDynamicModification() + { + $form = $this->getMockForm('form'); + $formToBeAdded = $this->getMockForm('added'); + $formToBeRemoved = $this->getMockForm('removed'); + + $forms = array('form' => $form, 'removed' => $formToBeRemoved); + $iterator = new VirtualFormAwareIterator($forms); + + $iterator->rewind(); + $this->assertTrue($iterator->valid()); + $this->assertSame('form', $iterator->key()); + $this->assertSame($form, $iterator->current()); + + // dynamic modification + unset($forms['removed']); + $forms['added'] = $formToBeAdded; + + // continue iteration + $iterator->next(); + $this->assertTrue($iterator->valid()); + $this->assertSame('added', $iterator->key()); + $this->assertSame($formToBeAdded, $iterator->current()); + + // end of array + $iterator->next(); + $this->assertFalse($iterator->valid()); + } + + public function testSupportDynamicModificationInRecursiveCall() + { + $virtualForm = $this->getMockForm('virtual'); + $form = $this->getMockForm('form'); + $formToBeAdded = $this->getMockForm('added'); + $formToBeRemoved = $this->getMockForm('removed'); + + $virtualForm->getConfig()->expects($this->any()) + ->method('getVirtual') + ->will($this->returnValue(true)); + + $virtualForm->add($form); + $virtualForm->add($formToBeRemoved); + + $forms = array('virtual' => $virtualForm); + $iterator = new VirtualFormAwareIterator($forms); + + $iterator->rewind(); + $this->assertTrue($iterator->valid()); + $this->assertSame('virtual', $iterator->key()); + $this->assertSame($virtualForm, $iterator->current()); + $this->assertTrue($iterator->hasChildren()); + + // enter nested iterator + $nestedIterator = $iterator->getChildren(); + $this->assertSame('form', $nestedIterator->key()); + $this->assertSame($form, $nestedIterator->current()); + $this->assertFalse($nestedIterator->hasChildren()); + + // dynamic modification + $virtualForm->remove('removed'); + $virtualForm->add($formToBeAdded); + + // continue iteration - nested iterator discovers change in the form + $nestedIterator->next(); + $this->assertTrue($nestedIterator->valid()); + $this->assertSame('added', $nestedIterator->key()); + $this->assertSame($formToBeAdded, $nestedIterator->current()); + + // end of array + $nestedIterator->next(); + $this->assertFalse($nestedIterator->valid()); + } + + /** + * @param string $name + * + * @return \PHPUnit_Framework_MockObject_MockObject + */ + protected function getMockForm($name = 'name') + { + $config = $this->getMock('Symfony\Component\Form\FormConfigInterface'); + + $config->expects($this->any()) + ->method('getName') + ->will($this->returnValue($name)); + $config->expects($this->any()) + ->method('getCompound') + ->will($this->returnValue(true)); + $config->expects($this->any()) + ->method('getDataMapper') + ->will($this->returnValue($this->getMock('Symfony\Component\Form\DataMapperInterface'))); + $config->expects($this->any()) + ->method('getEventDispatcher') + ->will($this->returnValue($this->getMock('Symfony\Component\EventDispatcher\EventDispatcher'))); + + return $this->getMockBuilder('Symfony\Component\Form\Form') + ->setConstructorArgs(array($config)) + ->disableArgumentCloning() + ->setMethods(array('getViewData')) + ->getMock(); + } +} diff --git a/Util/VirtualFormAwareIterator.php b/Util/VirtualFormAwareIterator.php index c1322bb35d..9b9abb36e7 100644 --- a/Util/VirtualFormAwareIterator.php +++ b/Util/VirtualFormAwareIterator.php @@ -12,22 +12,86 @@ namespace Symfony\Component\Form\Util; /** - * Iterator that traverses fields of a field group + * Iterator that traverses an array of forms. * - * If the iterator encounters a virtual field group, it enters the field - * group and traverses its children as well. + * Contrary to \ArrayIterator, this iterator recognizes changes in the original + * array during iteration. + * + * You can wrap the iterator into a {@link \RecursiveIterator} in order to + * enter any virtual child form and iterate the children of that virtual form. * * @author Bernhard Schussek */ -class VirtualFormAwareIterator extends \ArrayIterator implements \RecursiveIterator +class VirtualFormAwareIterator implements \RecursiveIterator { + /** + * @var \Symfony\Component\Form\FormInterface[] + */ + private $forms; + + /** + * Creates a new iterator. + * + * @param \Symfony\Component\Form\FormInterface[] $forms An array of forms + */ + public function __construct(array &$forms) + { + $this->forms = &$forms; + } + + /** + *{@inheritdoc} + */ + public function current() + { + return current($this->forms); + } + + /** + *{@inheritdoc} + */ + public function next() + { + next($this->forms); + } + + /** + *{@inheritdoc} + */ + public function key() + { + return key($this->forms); + } + + /** + *{@inheritdoc} + */ + public function valid() + { + return null !== key($this->forms); + } + + /** + *{@inheritdoc} + */ + public function rewind() + { + reset($this->forms); + } + + /** + *{@inheritdoc} + */ public function getChildren() { return new self($this->current()->all()); } + /** + *{@inheritdoc} + */ public function hasChildren() { - return $this->current()->getConfig()->getVirtual(); + return (bool) $this->current()->getConfig()->getVirtual(); } } From a4869e56fa613284565351ea60d712d8342f3100 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 22 Aug 2013 13:38:57 +0200 Subject: [PATCH 157/447] [Form] Removed superfluous reset() call --- Form.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/Form.php b/Form.php index 2cf0c9dff8..c4f744f1de 100644 --- a/Form.php +++ b/Form.php @@ -552,8 +552,6 @@ public function bind($submittedData) $submittedData = array(); } - reset($this->children); - for (reset($this->children); false !== current($this->children); next($this->children)) { $child = current($this->children); $name = key($this->children); From 4a1651c1ab97e41df48a0038b395f8b34909a9bc Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 22 Aug 2013 14:10:15 +0200 Subject: [PATCH 158/447] [Form] PropertyPathMapper::mapDataToForms() *always* calls setData() on every child to ensure that all *_DATA events were fired when the initialization phase is over (except for virtual forms) --- .../Core/DataMapper/PropertyPathMapper.php | 14 +++---- .../DataMapper/PropertyPathMapperTest.php | 39 +++++++++++++++++-- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/Extension/Core/DataMapper/PropertyPathMapper.php b/Extension/Core/DataMapper/PropertyPathMapper.php index f691ecca21..3280e008f5 100644 --- a/Extension/Core/DataMapper/PropertyPathMapper.php +++ b/Extension/Core/DataMapper/PropertyPathMapper.php @@ -44,11 +44,9 @@ public function __construct(PropertyAccessorInterface $propertyAccessor = null) */ public function mapDataToForms($data, array $forms) { - if (null === $data || array() === $data) { - return; - } + $empty = null === $data || array() === $data; - if (!is_array($data) && !is_object($data)) { + if (!$empty && !is_array($data) && !is_object($data)) { throw new UnexpectedTypeException($data, 'object, array or empty'); } @@ -56,12 +54,14 @@ public function mapDataToForms($data, array $forms) $iterator = new \RecursiveIteratorIterator($iterator); foreach ($iterator as $form) { - /* @var FormInterface $form */ + /* @var \Symfony\Component\Form\FormInterface $form */ $propertyPath = $form->getPropertyPath(); $config = $form->getConfig(); - if (null !== $propertyPath && $config->getMapped()) { + if (!$empty && null !== $propertyPath && $config->getMapped()) { $form->setData($this->propertyAccessor->getValue($data, $propertyPath)); + } else { + $form->setData($form->getConfig()->getData()); } } } @@ -83,7 +83,7 @@ public function mapFormsToData(array $forms, &$data) $iterator = new \RecursiveIteratorIterator($iterator); foreach ($iterator as $form) { - /* @var FormInterface $form */ + /* @var \Symfony\Component\Form\FormInterface $form */ $propertyPath = $form->getPropertyPath(); $config = $form->getConfig(); diff --git a/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php b/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php index 8af2fd5f07..0a76ec9576 100644 --- a/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php +++ b/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php @@ -165,8 +165,9 @@ public function testMapDataToFormsIgnoresUnmapped() $this->assertNull($form->getData()); } - public function testMapDataToFormsIgnoresEmptyData() + public function testMapDataToFormsSetsDefaultDataIfPassedDataIsNull() { + $default = new \stdClass(); $propertyPath = $this->getPropertyPath('engine'); $this->propertyAccessor->expects($this->never()) @@ -175,11 +176,43 @@ public function testMapDataToFormsIgnoresEmptyData() $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); $config->setByReference(true); $config->setPropertyPath($propertyPath); - $form = $this->getForm($config); + $config->setData($default); + + $form = $this->getMockBuilder('Symfony\Component\Form\Form') + ->setConstructorArgs(array($config)) + ->setMethods(array('setData')) + ->getMock(); + + $form->expects($this->once()) + ->method('setData') + ->with($default); $this->mapper->mapDataToForms(null, array($form)); + } - $this->assertNull($form->getData()); + public function testMapDataToFormsSetsDefaultDataIfPassedDataIsEmptyArray() + { + $default = new \stdClass(); + $propertyPath = $this->getPropertyPath('engine'); + + $this->propertyAccessor->expects($this->never()) + ->method('getValue'); + + $config = new FormConfigBuilder('name', '\stdClass', $this->dispatcher); + $config->setByReference(true); + $config->setPropertyPath($propertyPath); + $config->setData($default); + + $form = $this->getMockBuilder('Symfony\Component\Form\Form') + ->setConstructorArgs(array($config)) + ->setMethods(array('setData')) + ->getMock(); + + $form->expects($this->once()) + ->method('setData') + ->with($default); + + $this->mapper->mapDataToForms(array(), array($form)); } public function testMapDataToFormsSkipsVirtualForms() From 8b43c0a816c7b2f4816f731cd4e69ea9e6b84159 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 22 Aug 2013 14:18:47 +0200 Subject: [PATCH 159/447] [Form] Removed call to deprecated method --- Extension/Core/DataMapper/PropertyPathMapper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/Core/DataMapper/PropertyPathMapper.php b/Extension/Core/DataMapper/PropertyPathMapper.php index ff571d6392..d5942f2a55 100644 --- a/Extension/Core/DataMapper/PropertyPathMapper.php +++ b/Extension/Core/DataMapper/PropertyPathMapper.php @@ -35,7 +35,7 @@ class PropertyPathMapper implements DataMapperInterface */ public function __construct(PropertyAccessorInterface $propertyAccessor = null) { - $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::getPropertyAccessor(); + $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); } /** From ea2f347ac35ed2a9bd9d4011be1052e075de1ffe Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 22 Aug 2013 14:19:04 +0200 Subject: [PATCH 160/447] [Form] Removed exception in Button::setData(): setData() is now always called for all elements in the form tree during the initialization of the tree --- Button.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Button.php b/Button.php index 6e12ba163c..aecbabaebe 100644 --- a/Button.php +++ b/Button.php @@ -200,7 +200,8 @@ public function getErrors() */ public function setData($modelData) { - throw new BadMethodCallException('Buttons cannot have data.'); + // called during initialization of the form tree + // noop } /** From 18d1da45e05554b4ab5de35746f503f7fc53b512 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 22 Aug 2013 14:20:52 +0200 Subject: [PATCH 161/447] [Form] Added a test that ensures that setData() reacts to dynamic modifications of a form's children --- Tests/CompoundFormTest.php | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index 61f91963c1..bc0c57d33f 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests; +use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; use Symfony\Component\Form\FormError; use Symfony\Component\Form\Forms; @@ -372,6 +373,41 @@ public function testAddDoesNotMapViewDataToFormIfInheritData() $form->add($child); } + public function testSetDataSupportsDynamicAdditionAndRemovalOfChildren() + { + $form = $this->getBuilder() + ->setCompound(true) + // We test using PropertyPathMapper on purpose. The traversal logic + // is currently contained in InheritDataAwareIterator, but even + // if that changes, this test should still function. + ->setDataMapper(new PropertyPathMapper()) + ->getForm(); + + $child = $this->getMockForm('child'); + $childToBeRemoved = $this->getMockForm('removed'); + $childToBeAdded = $this->getMockForm('added'); + + $form->add($child); + $form->add($childToBeRemoved); + + $child->expects($this->once()) + ->method('setData') + ->will($this->returnCallback(function () use ($form, $childToBeAdded) { + $form->remove('removed'); + $form->add($childToBeAdded); + })); + + $childToBeRemoved->expects($this->never()) + ->method('setData'); + + // once when it it is created, once when it is added + $childToBeAdded->expects($this->exactly(2)) + ->method('setData'); + + // pass NULL to all children + $form->setData(array()); + } + public function testSetDataMapsViewDataToChildren() { $test = $this; From f8823ddbe7ca7d744ea3d8dde5670746031a6f3b Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 23 Aug 2013 13:16:42 +0200 Subject: [PATCH 162/447] [Form] Extracted ReferencingArrayIterator out of VirtualFormAwareIterator --- Util/ReferencingArrayIterator.php | 78 +++++++++++++++++++++++++++++++ Util/VirtualFormAwareIterator.php | 61 ++---------------------- 2 files changed, 81 insertions(+), 58 deletions(-) create mode 100644 Util/ReferencingArrayIterator.php diff --git a/Util/ReferencingArrayIterator.php b/Util/ReferencingArrayIterator.php new file mode 100644 index 0000000000..9bb64d79d2 --- /dev/null +++ b/Util/ReferencingArrayIterator.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Util; + +/** + * Iterator that traverses an array. + * + * Contrary to {@link \ArrayIterator}, this iterator recognizes changes in the + * original array during iteration. + * + * @author Bernhard Schussek + */ +class ReferencingArrayIterator implements \Iterator +{ + /** + * @var array + */ + private $array; + + /** + * Creates a new iterator. + * + * @param array $array An array + */ + public function __construct(array &$array) + { + $this->array = &$array; + } + + /** + *{@inheritdoc} + */ + public function current() + { + return current($this->array); + } + + /** + *{@inheritdoc} + */ + public function next() + { + next($this->array); + } + + /** + *{@inheritdoc} + */ + public function key() + { + return key($this->array); + } + + /** + *{@inheritdoc} + */ + public function valid() + { + return null !== key($this->array); + } + + /** + *{@inheritdoc} + */ + public function rewind() + { + reset($this->array); + } +} diff --git a/Util/VirtualFormAwareIterator.php b/Util/VirtualFormAwareIterator.php index 9b9abb36e7..2648c3a501 100644 --- a/Util/VirtualFormAwareIterator.php +++ b/Util/VirtualFormAwareIterator.php @@ -14,71 +14,16 @@ /** * Iterator that traverses an array of forms. * - * Contrary to \ArrayIterator, this iterator recognizes changes in the original - * array during iteration. + * Contrary to {@link \ArrayIterator}, this iterator recognizes changes in the + * original array during iteration. * * You can wrap the iterator into a {@link \RecursiveIterator} in order to * enter any virtual child form and iterate the children of that virtual form. * * @author Bernhard Schussek */ -class VirtualFormAwareIterator implements \RecursiveIterator +class VirtualFormAwareIterator extends ReferencingArrayIterator implements \RecursiveIterator { - /** - * @var \Symfony\Component\Form\FormInterface[] - */ - private $forms; - - /** - * Creates a new iterator. - * - * @param \Symfony\Component\Form\FormInterface[] $forms An array of forms - */ - public function __construct(array &$forms) - { - $this->forms = &$forms; - } - - /** - *{@inheritdoc} - */ - public function current() - { - return current($this->forms); - } - - /** - *{@inheritdoc} - */ - public function next() - { - next($this->forms); - } - - /** - *{@inheritdoc} - */ - public function key() - { - return key($this->forms); - } - - /** - *{@inheritdoc} - */ - public function valid() - { - return null !== key($this->forms); - } - - /** - *{@inheritdoc} - */ - public function rewind() - { - reset($this->forms); - } - /** *{@inheritdoc} */ From 103249b4a782c55c7529f99804bb4ff52d27fdca Mon Sep 17 00:00:00 2001 From: Pascal Borreli Date: Sat, 24 Aug 2013 07:54:37 +0100 Subject: [PATCH 163/447] Fixed typos --- Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php b/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php index c0754f86cb..a15d7e0d54 100644 --- a/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php +++ b/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php @@ -54,6 +54,7 @@ private function getPropertyPath($path) /** * @param FormConfigInterface $config * @param Boolean $synchronized + * @param Boolean $submitted * @return \PHPUnit_Framework_MockObject_MockObject */ private function getForm(FormConfigInterface $config, $synchronized = true, $submitted = true) From dfac955da00a826dc24f4233b054ab72ab121fa0 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Sat, 24 Aug 2013 17:43:39 +0200 Subject: [PATCH 164/447] [Form] Fixed Form::all() signature for PHP 5.3.3 --- Form.php | 2 +- Tests/Util/VirtualFormAwareIteratorTest.php | 122 -------------------- Util/ReferencingArrayIterator.php | 78 ------------- Util/VirtualFormAwareIterator.php | 5 +- 4 files changed, 2 insertions(+), 205 deletions(-) delete mode 100644 Tests/Util/VirtualFormAwareIteratorTest.php delete mode 100644 Util/ReferencingArrayIterator.php diff --git a/Form.php b/Form.php index c4f744f1de..92014de3ed 100644 --- a/Form.php +++ b/Form.php @@ -832,7 +832,7 @@ public function getClientTransformers() /** * {@inheritdoc} */ - public function &all() + public function all() { return $this->children; } diff --git a/Tests/Util/VirtualFormAwareIteratorTest.php b/Tests/Util/VirtualFormAwareIteratorTest.php deleted file mode 100644 index 805acad903..0000000000 --- a/Tests/Util/VirtualFormAwareIteratorTest.php +++ /dev/null @@ -1,122 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Tests\Util; - -use Symfony\Component\Form\Util\VirtualFormAwareIterator; - -/** - * @author Bernhard Schussek - */ -class VirtualFormAwareIteratorTest extends \PHPUnit_Framework_TestCase -{ - public function testSupportDynamicModification() - { - $form = $this->getMockForm('form'); - $formToBeAdded = $this->getMockForm('added'); - $formToBeRemoved = $this->getMockForm('removed'); - - $forms = array('form' => $form, 'removed' => $formToBeRemoved); - $iterator = new VirtualFormAwareIterator($forms); - - $iterator->rewind(); - $this->assertTrue($iterator->valid()); - $this->assertSame('form', $iterator->key()); - $this->assertSame($form, $iterator->current()); - - // dynamic modification - unset($forms['removed']); - $forms['added'] = $formToBeAdded; - - // continue iteration - $iterator->next(); - $this->assertTrue($iterator->valid()); - $this->assertSame('added', $iterator->key()); - $this->assertSame($formToBeAdded, $iterator->current()); - - // end of array - $iterator->next(); - $this->assertFalse($iterator->valid()); - } - - public function testSupportDynamicModificationInRecursiveCall() - { - $virtualForm = $this->getMockForm('virtual'); - $form = $this->getMockForm('form'); - $formToBeAdded = $this->getMockForm('added'); - $formToBeRemoved = $this->getMockForm('removed'); - - $virtualForm->getConfig()->expects($this->any()) - ->method('getVirtual') - ->will($this->returnValue(true)); - - $virtualForm->add($form); - $virtualForm->add($formToBeRemoved); - - $forms = array('virtual' => $virtualForm); - $iterator = new VirtualFormAwareIterator($forms); - - $iterator->rewind(); - $this->assertTrue($iterator->valid()); - $this->assertSame('virtual', $iterator->key()); - $this->assertSame($virtualForm, $iterator->current()); - $this->assertTrue($iterator->hasChildren()); - - // enter nested iterator - $nestedIterator = $iterator->getChildren(); - $this->assertSame('form', $nestedIterator->key()); - $this->assertSame($form, $nestedIterator->current()); - $this->assertFalse($nestedIterator->hasChildren()); - - // dynamic modification - $virtualForm->remove('removed'); - $virtualForm->add($formToBeAdded); - - // continue iteration - nested iterator discovers change in the form - $nestedIterator->next(); - $this->assertTrue($nestedIterator->valid()); - $this->assertSame('added', $nestedIterator->key()); - $this->assertSame($formToBeAdded, $nestedIterator->current()); - - // end of array - $nestedIterator->next(); - $this->assertFalse($nestedIterator->valid()); - } - - /** - * @param string $name - * - * @return \PHPUnit_Framework_MockObject_MockObject - */ - protected function getMockForm($name = 'name') - { - $config = $this->getMock('Symfony\Component\Form\FormConfigInterface'); - - $config->expects($this->any()) - ->method('getName') - ->will($this->returnValue($name)); - $config->expects($this->any()) - ->method('getCompound') - ->will($this->returnValue(true)); - $config->expects($this->any()) - ->method('getDataMapper') - ->will($this->returnValue($this->getMock('Symfony\Component\Form\DataMapperInterface'))); - $config->expects($this->any()) - ->method('getEventDispatcher') - ->will($this->returnValue($this->getMock('Symfony\Component\EventDispatcher\EventDispatcher'))); - - return $this->getMockBuilder('Symfony\Component\Form\Form') - ->setConstructorArgs(array($config)) - ->disableArgumentCloning() - ->setMethods(array('getViewData')) - ->getMock(); - } -} diff --git a/Util/ReferencingArrayIterator.php b/Util/ReferencingArrayIterator.php deleted file mode 100644 index 9bb64d79d2..0000000000 --- a/Util/ReferencingArrayIterator.php +++ /dev/null @@ -1,78 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Util; - -/** - * Iterator that traverses an array. - * - * Contrary to {@link \ArrayIterator}, this iterator recognizes changes in the - * original array during iteration. - * - * @author Bernhard Schussek - */ -class ReferencingArrayIterator implements \Iterator -{ - /** - * @var array - */ - private $array; - - /** - * Creates a new iterator. - * - * @param array $array An array - */ - public function __construct(array &$array) - { - $this->array = &$array; - } - - /** - *{@inheritdoc} - */ - public function current() - { - return current($this->array); - } - - /** - *{@inheritdoc} - */ - public function next() - { - next($this->array); - } - - /** - *{@inheritdoc} - */ - public function key() - { - return key($this->array); - } - - /** - *{@inheritdoc} - */ - public function valid() - { - return null !== key($this->array); - } - - /** - *{@inheritdoc} - */ - public function rewind() - { - reset($this->array); - } -} diff --git a/Util/VirtualFormAwareIterator.php b/Util/VirtualFormAwareIterator.php index 2648c3a501..3060bedc0c 100644 --- a/Util/VirtualFormAwareIterator.php +++ b/Util/VirtualFormAwareIterator.php @@ -14,15 +14,12 @@ /** * Iterator that traverses an array of forms. * - * Contrary to {@link \ArrayIterator}, this iterator recognizes changes in the - * original array during iteration. - * * You can wrap the iterator into a {@link \RecursiveIterator} in order to * enter any virtual child form and iterate the children of that virtual form. * * @author Bernhard Schussek */ -class VirtualFormAwareIterator extends ReferencingArrayIterator implements \RecursiveIterator +class VirtualFormAwareIterator extends \ArrayIterator implements \RecursiveIterator { /** *{@inheritdoc} From 5c71e3fc520f28a281bb07ee80b1fd105369feb3 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Sat, 24 Aug 2013 17:43:39 +0200 Subject: [PATCH 165/447] [Form] Fixed Form::all() signature for PHP 5.3.3 --- .../ViolationMapper/ViolationMapper.php | 2 +- Form.php | 38 +- Tests/Util/InheritDataAwareIteratorTest.php | 122 ----- Tests/Util/OrderedHashMapTest.php | 487 ++++++++++++++++++ Util/OrderedHashMap.php | 190 +++++++ Util/OrderedHashMapIterator.php | 163 ++++++ Util/ReferencingArrayIterator.php | 78 --- Util/VirtualFormAwareIterator.php | 7 +- 8 files changed, 861 insertions(+), 226 deletions(-) delete mode 100644 Tests/Util/InheritDataAwareIteratorTest.php create mode 100644 Tests/Util/OrderedHashMapTest.php create mode 100644 Util/OrderedHashMap.php create mode 100644 Util/OrderedHashMapIterator.php delete mode 100644 Util/ReferencingArrayIterator.php diff --git a/Extension/Validator/ViolationMapper/ViolationMapper.php b/Extension/Validator/ViolationMapper/ViolationMapper.php index 8a7636c7e8..3be55e64c1 100644 --- a/Extension/Validator/ViolationMapper/ViolationMapper.php +++ b/Extension/Validator/ViolationMapper/ViolationMapper.php @@ -167,7 +167,7 @@ private function matchChild(FormInterface $form, PropertyPathIteratorInterface $ // Skip forms inheriting their parent data when iterating the children $childIterator = new \RecursiveIteratorIterator( - new InheritDataAwareIterator($form->all()) + new InheritDataAwareIterator($form) ); // Make the path longer until we find a matching child diff --git a/Form.php b/Form.php index 556c190d8e..f7fa834b35 100644 --- a/Form.php +++ b/Form.php @@ -19,6 +19,7 @@ use Symfony\Component\Form\Exception\OutOfBoundsException; use Symfony\Component\Form\Util\FormUtil; use Symfony\Component\Form\Util\InheritDataAwareIterator; +use Symfony\Component\Form\Util\OrderedHashMap; use Symfony\Component\PropertyAccess\PropertyPath; /** @@ -73,9 +74,9 @@ class Form implements \IteratorAggregate, FormInterface /** * The children of this form - * @var FormInterface[] An array of FormInterface instances + * @var FormInterface[] A map of FormInterface instances */ - private $children = array(); + private $children; /** * The errors of this form @@ -164,6 +165,7 @@ public function __construct(FormConfigInterface $config) } $this->config = $config; + $this->children = new OrderedHashMap(); } public function __clone() @@ -370,9 +372,9 @@ public function setData($modelData) // even if the form is compound. if (count($this->children) > 0) { // Update child forms from the data - $childrenIterator = new InheritDataAwareIterator($this->children); - $childrenIterator = new \RecursiveIteratorIterator($childrenIterator); - $this->config->getDataMapper()->mapDataToForms($viewData, $childrenIterator); + $iterator = new InheritDataAwareIterator($this->children); + $iterator = new \RecursiveIteratorIterator($iterator); + $this->config->getDataMapper()->mapDataToForms($viewData, $iterator); } if ($dispatcher->hasListeners(FormEvents::POST_SET_DATA)) { @@ -536,10 +538,7 @@ public function submit($submittedData, $clearMissing = true) $submittedData = array(); } - for (reset($this->children); false !== current($this->children); next($this->children)) { - $child = current($this->children); - $name = key($this->children); - + foreach ($this->children as $name => $child) { if (array_key_exists($name, $submittedData) || $clearMissing) { $child->submit(isset($submittedData[$name]) ? $submittedData[$name] : null, $clearMissing); unset($submittedData[$name]); @@ -587,9 +586,9 @@ public function submit($submittedData, $clearMissing = true) // descendants that inherit this form's data. // These descendants will not be submitted normally (see the check // for $this->config->getInheritData() above) - $childrenIterator = new InheritDataAwareIterator($this->children); - $childrenIterator = new \RecursiveIteratorIterator($childrenIterator); - $this->config->getDataMapper()->mapFormsToData($childrenIterator, $viewData); + $iterator = new InheritDataAwareIterator($this->children); + $iterator = new \RecursiveIteratorIterator($iterator); + $this->config->getDataMapper()->mapFormsToData($iterator, $viewData); } $modelData = null; @@ -765,9 +764,9 @@ public function getErrorsAsString($level = 0) /** * {@inheritdoc} */ - public function &all() + public function all() { - return $this->children; + return iterator_to_array($this->children); } /** @@ -836,10 +835,9 @@ public function add($child, $type = null, array $options = array()) $child->setParent($this); if (!$this->lockSetData && $this->defaultDataSet && !$this->config->getInheritData()) { - $children = array($child); - $childrenIterator = new InheritDataAwareIterator($children); - $childrenIterator = new \RecursiveIteratorIterator($childrenIterator); - $this->config->getDataMapper()->mapDataToForms($viewData, $childrenIterator); + $iterator = new InheritDataAwareIterator(new \ArrayIterator(array($child))); + $iterator = new \RecursiveIteratorIterator($iterator); + $this->config->getDataMapper()->mapDataToForms($viewData, $iterator); } return $this; @@ -940,11 +938,11 @@ public function offsetUnset($name) /** * Returns the iterator for this group. * - * @return \ArrayIterator + * @return \Iterator */ public function getIterator() { - return new \ArrayIterator($this->children); + return $this->children; } /** diff --git a/Tests/Util/InheritDataAwareIteratorTest.php b/Tests/Util/InheritDataAwareIteratorTest.php deleted file mode 100644 index 19a0940bc0..0000000000 --- a/Tests/Util/InheritDataAwareIteratorTest.php +++ /dev/null @@ -1,122 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Tests\Util; - -use Symfony\Component\Form\Util\InheritDataAwareIterator; - -/** - * @author Bernhard Schussek - */ -class InheritDataAwareIteratorTest extends \PHPUnit_Framework_TestCase -{ - public function testSupportDynamicModification() - { - $form = $this->getMockForm('form'); - $formToBeAdded = $this->getMockForm('added'); - $formToBeRemoved = $this->getMockForm('removed'); - - $forms = array('form' => $form, 'removed' => $formToBeRemoved); - $iterator = new InheritDataAwareIterator($forms); - - $iterator->rewind(); - $this->assertTrue($iterator->valid()); - $this->assertSame('form', $iterator->key()); - $this->assertSame($form, $iterator->current()); - - // dynamic modification - unset($forms['removed']); - $forms['added'] = $formToBeAdded; - - // continue iteration - $iterator->next(); - $this->assertTrue($iterator->valid()); - $this->assertSame('added', $iterator->key()); - $this->assertSame($formToBeAdded, $iterator->current()); - - // end of array - $iterator->next(); - $this->assertFalse($iterator->valid()); - } - - public function testSupportDynamicModificationInRecursiveCall() - { - $inheritingForm = $this->getMockForm('inheriting'); - $form = $this->getMockForm('form'); - $formToBeAdded = $this->getMockForm('added'); - $formToBeRemoved = $this->getMockForm('removed'); - - $inheritingForm->getConfig()->expects($this->any()) - ->method('getInheritData') - ->will($this->returnValue(true)); - - $inheritingForm->add($form); - $inheritingForm->add($formToBeRemoved); - - $forms = array('inheriting' => $inheritingForm); - $iterator = new InheritDataAwareIterator($forms); - - $iterator->rewind(); - $this->assertTrue($iterator->valid()); - $this->assertSame('inheriting', $iterator->key()); - $this->assertSame($inheritingForm, $iterator->current()); - $this->assertTrue($iterator->hasChildren()); - - // enter nested iterator - $nestedIterator = $iterator->getChildren(); - $this->assertSame('form', $nestedIterator->key()); - $this->assertSame($form, $nestedIterator->current()); - $this->assertFalse($nestedIterator->hasChildren()); - - // dynamic modification - $inheritingForm->remove('removed'); - $inheritingForm->add($formToBeAdded); - - // continue iteration - nested iterator discovers change in the form - $nestedIterator->next(); - $this->assertTrue($nestedIterator->valid()); - $this->assertSame('added', $nestedIterator->key()); - $this->assertSame($formToBeAdded, $nestedIterator->current()); - - // end of array - $nestedIterator->next(); - $this->assertFalse($nestedIterator->valid()); - } - - /** - * @param string $name - * - * @return \PHPUnit_Framework_MockObject_MockObject - */ - protected function getMockForm($name = 'name') - { - $config = $this->getMock('Symfony\Component\Form\FormConfigInterface'); - - $config->expects($this->any()) - ->method('getName') - ->will($this->returnValue($name)); - $config->expects($this->any()) - ->method('getCompound') - ->will($this->returnValue(true)); - $config->expects($this->any()) - ->method('getDataMapper') - ->will($this->returnValue($this->getMock('Symfony\Component\Form\DataMapperInterface'))); - $config->expects($this->any()) - ->method('getEventDispatcher') - ->will($this->returnValue($this->getMock('Symfony\Component\EventDispatcher\EventDispatcher'))); - - return $this->getMockBuilder('Symfony\Component\Form\Form') - ->setConstructorArgs(array($config)) - ->disableArgumentCloning() - ->setMethods(array('getViewData')) - ->getMock(); - } -} diff --git a/Tests/Util/OrderedHashMapTest.php b/Tests/Util/OrderedHashMapTest.php new file mode 100644 index 0000000000..60703c5b3b --- /dev/null +++ b/Tests/Util/OrderedHashMapTest.php @@ -0,0 +1,487 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Util; + +use Symfony\Component\Form\Util\OrderedHashMap; + +/** + * @author Bernhard Schussek + */ +class OrderedHashMapTest extends \PHPUnit_Framework_TestCase +{ + public function testGet() + { + $map = new OrderedHashMap(); + $map['first'] = 1; + + $this->assertSame(1, $map['first']); + } + + /** + * @expectedException \OutOfBoundsException + */ + public function testGetNonExistingFails() + { + $map = new OrderedHashMap(); + + $map['first']; + } + + public function testInsertStringKeys() + { + $map = new OrderedHashMap(); + $map['first'] = 1; + $map['second'] = 2; + + $this->assertSame(array('first' => 1, 'second' => 2), iterator_to_array($map)); + } + + public function testInsertNullKeys() + { + $map = new OrderedHashMap(); + $map[] = 1; + $map['foo'] = 2; + $map[] = 3; + + $this->assertSame(array(0 => 1, 'foo' => 2, 1 => 3), iterator_to_array($map)); + } + + /** + * Updates should not change the position of an element, otherwise we could + * turn foreach loops into endless loops if they change the current + * element: + * + * foreach ($map as $index => $value) { + * $map[$index] = $value + 1; + * } + * + * And we don't want this, right? :) + */ + public function testUpdateDoesNotChangeElementPosition() + { + $map = new OrderedHashMap(); + $map['first'] = 1; + $map['second'] = 2; + $map['first'] = 1; + + $this->assertSame(array('first' => 1, 'second' => 2), iterator_to_array($map)); + } + + public function testIsset() + { + $map = new OrderedHashMap(); + $map['first'] = 1; + + $this->assertTrue(isset($map['first'])); + } + + public function testIssetReturnsFalseForNonExisting() + { + $map = new OrderedHashMap(); + + $this->assertFalse(isset($map['first'])); + } + + public function testIssetReturnsFalseForNull() + { + $map = new OrderedHashMap(); + $map['first'] = null; + + $this->assertFalse(isset($map['first'])); + } + + public function testUnset() + { + $map = new OrderedHashMap(); + $map['first'] = 1; + $map['second'] = 2; + + unset($map['first']); + + $this->assertSame(array('second' => 2), iterator_to_array($map)); + } + + public function testUnsetNonExistingSucceeds() + { + $map = new OrderedHashMap(); + + unset($map['first']); + } + + public function testEmptyIteration() + { + $map = new OrderedHashMap(); + $it = $map->getIterator(); + + $it->rewind(); + $this->assertFalse($it->valid()); + $this->assertNull($it->key()); + $this->assertNull($it->current()); + } + + public function testIterationSupportsInsertion() + { + $map = new OrderedHashMap(array('first' => 1)); + $it = $map->getIterator(); + + $it->rewind(); + $this->assertTrue($it->valid()); + $this->assertSame('first', $it->key()); + $this->assertSame(1, $it->current()); + + // dynamic modification + $map['added'] = 2; + + // iterator is unchanged + $this->assertTrue($it->valid()); + $this->assertSame('first', $it->key()); + $this->assertSame(1, $it->current()); + + // continue iteration + $it->next(); + $this->assertTrue($it->valid()); + $this->assertSame('added', $it->key()); + $this->assertSame(2, $it->current()); + + // end of map + $it->next(); + $this->assertFalse($it->valid()); + $this->assertNull($it->key()); + $this->assertNull($it->current()); + } + + public function testIterationSupportsDeletionAndInsertion() + { + $map = new OrderedHashMap(array('first' => 1, 'removed' => 2)); + $it = $map->getIterator(); + + $it->rewind(); + $this->assertTrue($it->valid()); + $this->assertSame('first', $it->key()); + $this->assertSame(1, $it->current()); + + // dynamic modification + unset($map['removed']); + $map['added'] = 3; + + // iterator is unchanged + $this->assertTrue($it->valid()); + $this->assertSame('first', $it->key()); + $this->assertSame(1, $it->current()); + + // continue iteration + $it->next(); + $this->assertTrue($it->valid()); + $this->assertSame('added', $it->key()); + $this->assertSame(3, $it->current()); + + // end of map + $it->next(); + $this->assertFalse($it->valid()); + $this->assertNull($it->key()); + $this->assertNull($it->current()); + } + + public function testIterationSupportsDeletionOfCurrentElement() + { + $map = new OrderedHashMap(array('removed' => 1, 'next' => 2)); + $it = $map->getIterator(); + + $it->rewind(); + $this->assertTrue($it->valid()); + $this->assertSame('removed', $it->key()); + $this->assertSame(1, $it->current()); + + unset($map['removed']); + + // iterator is unchanged + $this->assertTrue($it->valid()); + $this->assertSame('removed', $it->key()); + $this->assertSame(1, $it->current()); + + // continue iteration + $it->next(); + $this->assertTrue($it->valid()); + $this->assertSame('next', $it->key()); + $this->assertSame(2, $it->current()); + + // end of map + $it->next(); + $this->assertFalse($it->valid()); + $this->assertNull($it->key()); + $this->assertNull($it->current()); + } + + public function testIterationIgnoresReplacementOfCurrentElement() + { + $map = new OrderedHashMap(array('replaced' => 1, 'next' => 2)); + $it = $map->getIterator(); + + $it->rewind(); + $this->assertTrue($it->valid()); + $this->assertSame('replaced', $it->key()); + $this->assertSame(1, $it->current()); + + $map['replaced'] = 3; + + // iterator is unchanged + $this->assertTrue($it->valid()); + $this->assertSame('replaced', $it->key()); + $this->assertSame(1, $it->current()); + + // continue iteration + $it->next(); + $this->assertTrue($it->valid()); + $this->assertSame('next', $it->key()); + $this->assertSame(2, $it->current()); + + // end of map + $it->next(); + $this->assertFalse($it->valid()); + $this->assertNull($it->key()); + $this->assertNull($it->current()); + } + + public function testIterationSupportsDeletionOfCurrentAndLastElement() + { + $map = new OrderedHashMap(array('removed' => 1)); + $it = $map->getIterator(); + + $it->rewind(); + $this->assertTrue($it->valid()); + $this->assertSame('removed', $it->key()); + $this->assertSame(1, $it->current()); + + unset($map['removed']); + + // iterator is unchanged + $this->assertTrue($it->valid()); + $this->assertSame('removed', $it->key()); + $this->assertSame(1, $it->current()); + + // end of map + $it->next(); + $this->assertFalse($it->valid()); + $this->assertNull($it->key()); + $this->assertNull($it->current()); + } + + public function testIterationIgnoresReplacementOfCurrentAndLastElement() + { + $map = new OrderedHashMap(array('replaced' => 1)); + $it = $map->getIterator(); + + $it->rewind(); + $this->assertTrue($it->valid()); + $this->assertSame('replaced', $it->key()); + $this->assertSame(1, $it->current()); + + $map['replaced'] = 2; + + // iterator is unchanged + $this->assertTrue($it->valid()); + $this->assertSame('replaced', $it->key()); + $this->assertSame(1, $it->current()); + + // end of map + $it->next(); + $this->assertFalse($it->valid()); + $this->assertNull($it->key()); + $this->assertNull($it->current()); + } + + public function testIterationSupportsDeletionOfPreviousElement() + { + $map = new OrderedHashMap(array('removed' => 1, 'next' => 2, 'onemore' => 3)); + $it = $map->getIterator(); + + $it->rewind(); + $this->assertTrue($it->valid()); + $this->assertSame('removed', $it->key()); + $this->assertSame(1, $it->current()); + + // continue iteration + $it->next(); + $this->assertTrue($it->valid()); + $this->assertSame('next', $it->key()); + $this->assertSame(2, $it->current()); + + unset($map['removed']); + + // iterator is unchanged + $this->assertTrue($it->valid()); + $this->assertSame('next', $it->key()); + $this->assertSame(2, $it->current()); + + // continue iteration + $it->next(); + $this->assertTrue($it->valid()); + $this->assertSame('onemore', $it->key()); + $this->assertSame(3, $it->current()); + + // end of map + $it->next(); + $this->assertFalse($it->valid()); + $this->assertNull($it->key()); + $this->assertNull($it->current()); + } + + public function testIterationIgnoresReplacementOfPreviousElement() + { + $map = new OrderedHashMap(array('replaced' => 1, 'next' => 2, 'onemore' => 3)); + $it = $map->getIterator(); + + $it->rewind(); + $this->assertTrue($it->valid()); + $this->assertSame('replaced', $it->key()); + $this->assertSame(1, $it->current()); + + // continue iteration + $it->next(); + $this->assertTrue($it->valid()); + $this->assertSame('next', $it->key()); + $this->assertSame(2, $it->current()); + + $map['replaced'] = 4; + + // iterator is unchanged + $this->assertTrue($it->valid()); + $this->assertSame('next', $it->key()); + $this->assertSame(2, $it->current()); + + // continue iteration + $it->next(); + $this->assertTrue($it->valid()); + $this->assertSame('onemore', $it->key()); + $this->assertSame(3, $it->current()); + + // end of map + $it->next(); + $this->assertFalse($it->valid()); + $this->assertNull($it->key()); + $this->assertNull($it->current()); + } + + public function testIterationSupportsDeletionOfMultiplePreviousElements() + { + $map = new OrderedHashMap(array('removed' => 1, 'alsoremoved' => 2, 'next' => 3, 'onemore' => 4)); + $it = $map->getIterator(); + + $it->rewind(); + $this->assertTrue($it->valid()); + $this->assertSame('removed', $it->key()); + $this->assertSame(1, $it->current()); + + // continue iteration + $it->next(); + $this->assertTrue($it->valid()); + $this->assertSame('alsoremoved', $it->key()); + $this->assertSame(2, $it->current()); + + // continue iteration + $it->next(); + $this->assertTrue($it->valid()); + $this->assertSame('next', $it->key()); + $this->assertSame(3, $it->current()); + + unset($map['removed'], $map['alsoremoved']); + + // iterator is unchanged + $this->assertTrue($it->valid()); + $this->assertSame('next', $it->key()); + $this->assertSame(3, $it->current()); + + // continue iteration + $it->next(); + $this->assertTrue($it->valid()); + $this->assertSame('onemore', $it->key()); + $this->assertSame(4, $it->current()); + + // end of map + $it->next(); + $this->assertFalse($it->valid()); + $this->assertNull($it->key()); + $this->assertNull($it->current()); + } + + public function testParallelIteration() + { + $map = new OrderedHashMap(array('first' => 1, 'second' => 2)); + $it1 = $map->getIterator(); + $it2 = $map->getIterator(); + + $it1->rewind(); + $this->assertTrue($it1->valid()); + $this->assertSame('first', $it1->key()); + $this->assertSame(1, $it1->current()); + + $it2->rewind(); + $this->assertTrue($it2->valid()); + $this->assertSame('first', $it2->key()); + $this->assertSame(1, $it2->current()); + + // 1: continue iteration + $it1->next(); + $this->assertTrue($it1->valid()); + $this->assertSame('second', $it1->key()); + $this->assertSame(2, $it1->current()); + + // 2: remains unchanged + $this->assertTrue($it2->valid()); + $this->assertSame('first', $it2->key()); + $this->assertSame(1, $it2->current()); + + // 1: advance to end of map + $it1->next(); + $this->assertFalse($it1->valid()); + $this->assertNull($it1->key()); + $this->assertNull($it1->current()); + + // 2: remains unchanged + $this->assertTrue($it2->valid()); + $this->assertSame('first', $it2->key()); + $this->assertSame(1, $it2->current()); + + // 2: continue iteration + $it2->next(); + $this->assertTrue($it2->valid()); + $this->assertSame('second', $it2->key()); + $this->assertSame(2, $it2->current()); + + // 1: remains unchanged + $this->assertFalse($it1->valid()); + $this->assertNull($it1->key()); + $this->assertNull($it1->current()); + + // 2: advance to end of map + $it2->next(); + $this->assertFalse($it2->valid()); + $this->assertNull($it2->key()); + $this->assertNull($it2->current()); + + // 1: remains unchanged + $this->assertFalse($it1->valid()); + $this->assertNull($it1->key()); + $this->assertNull($it1->current()); + } + + public function testCount() + { + $map = new OrderedHashMap(); + $map[] = 1; + $map['foo'] = 2; + unset($map[0]); + $map[] = 3; + + $this->assertSame(2, count($map)); + } +} diff --git a/Util/OrderedHashMap.php b/Util/OrderedHashMap.php new file mode 100644 index 0000000000..bf5b08cda6 --- /dev/null +++ b/Util/OrderedHashMap.php @@ -0,0 +1,190 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Util; + +/** + * A hash map which keeps track of deletions and additions. + * + * Like in associative arrays, elements can be mapped to integer or string keys. + * Unlike associative arrays, the map keeps track of the order in which keys + * were added and removed. This order is reflected during iteration. + * + * The map supports concurrent modification during iteration. That means that + * you can insert and remove elements from within a foreach loop and the + * iterator will reflect those changes accordingly. + * + * While elements that are added during the loop are recognized by the iterator, + * changed elements are not. Otherwise the loop could be infinite if each loop + * changes the current element: + * + * $map = new OrderedHashMap(); + * $map[1] = 1; + * $map[2] = 2; + * $map[3] = 3; + * + * foreach ($map as $index => $value) { + * echo "$index: $value\n" + * if (1 === $index) { + * $map[1] = 4; + * $map[] = 5; + * } + * } + * + * print_r(iterator_to_array($map)); + * + * // => 1: 1 + * // 2: 2 + * // 3: 3 + * // 4: 5 + * // Array + * // ( + * // [1] => 4 + * // [2] => 2 + * // [3] => 3 + * // [4] => 5 + * // ) + * + * The map also supports multiple parallel iterators. That means that you can + * nest foreach loops without affecting each other's iteration: + * + * foreach ($map as $index => $value) { + * foreach ($map as $index2 => $value2) { + * // ... + * } + * } + * + * @author Bernhard Schussek + * + * @since 2.2.6 + */ +class OrderedHashMap implements \ArrayAccess, \IteratorAggregate, \Countable +{ + /** + * The elements of the map, indexed by their keys. + * + * @var array + */ + private $elements = array(); + + /** + * The keys of the map in the order in which they were inserted or changed. + * + * @var array + */ + private $orderedKeys = array(); + + /** + * References to the cursors of all open iterators. + * + * @var array + */ + private $managedCursors = array(); + + /** + * Creates a new map. + * + * @param array $elements The elements to insert initially. + * + * @since 2.2.6 + */ + public function __construct(array $elements = array()) + { + $this->elements = $elements; + $this->orderedKeys = array_keys($elements); + } + + /** + * {@inheritdoc} + * + * @since 2.2.6 + */ + public function offsetExists($key) + { + return isset($this->elements[$key]); + } + + /** + * {@inheritdoc} + * + * @since 2.2.6 + */ + public function offsetGet($key) + { + if (!isset($this->elements[$key])) { + throw new \OutOfBoundsException('The offset "' . $key . '" does not exist.'); + } + + return $this->elements[$key]; + } + + /** + * {@inheritdoc} + * + * @since 2.2.6 + */ + public function offsetSet($key, $value) + { + if (null === $key || !isset($this->elements[$key])) { + if (null === $key) { + $key = array() === $this->orderedKeys + // If the array is empty, use 0 as key + ? 0 + // Imitate PHP's behavior of generating a key that equals + // the highest existing integer key + 1 + : max($this->orderedKeys) + 1; + } + + $this->orderedKeys[] = $key; + } + + $this->elements[$key] = $value; + } + + /** + * {@inheritdoc} + * + * @since 2.2.6 + */ + public function offsetUnset($key) + { + if (false !== ($position = array_search($key, $this->orderedKeys))) { + array_splice($this->orderedKeys, $position, 1); + unset($this->elements[$key]); + + foreach ($this->managedCursors as $i => $cursor) { + if ($cursor >= $position) { + --$this->managedCursors[$i]; + } + } + } + } + + /** + * {@inheritdoc} + * + * @since 2.2.6 + */ + public function getIterator() + { + return new OrderedHashMapIterator($this->elements, $this->orderedKeys, $this->managedCursors); + } + + /** + * {@inheritdoc} + * + * @since 2.2.6 + */ + public function count() + { + return count($this->elements); + } +} diff --git a/Util/OrderedHashMapIterator.php b/Util/OrderedHashMapIterator.php new file mode 100644 index 0000000000..87cf6a9d39 --- /dev/null +++ b/Util/OrderedHashMapIterator.php @@ -0,0 +1,163 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Util; + +/** + * Iterator for {@link OrderedHashMap} objects. + * + * This class is internal and should not be used. + * + * @author Bernhard Schussek + * + * @since 2.2.6 + */ +class OrderedHashMapIterator implements \Iterator +{ + /** + * @var array + */ + private $elements; + + /** + * @var array + */ + private $orderedKeys; + + /** + * @var integer + */ + private $cursor; + + /** + * @var integer + */ + private $cursorId; + + /** + * @var array + */ + private $managedCursors; + + /** + * @var string|integer|null + */ + private $key; + + /** + * @var mixed + */ + private $current; + + /** + * Creates a new iterator. + * + * @param array $elements The elements of the map, indexed by their + * keys. + * @param array $orderedKeys The keys of the map in the order in which + * they should be iterated. + * @param array $managedCursors An array from which to reference the + * iterator's cursor as long as it is alive. + * This array is managed by the corresponding + * {@link OrderedHashMap} instance to support + * recognizing the deletion of elements. + * + * @since 2.2.6 + */ + public function __construct(array &$elements, array &$orderedKeys, array &$managedCursors) + { + $this->elements = &$elements; + $this->orderedKeys = &$orderedKeys; + $this->managedCursors = &$managedCursors; + $this->cursorId = count($managedCursors); + + $this->managedCursors[$this->cursorId] = &$this->cursor; + } + + /** + * Removes the iterator's cursors from the managed cursors of the + * corresponding {@link OrderedHashMap} instance. + * + * @since 2.2.6 + */ + public function __destruct() + { + // Use array_splice() instead of isset() to prevent holes in the + // array indices, which would break the initialization of $cursorId + array_splice($this->managedCursors, $this->cursorId, 1); + } + + /** + *{@inheritdoc} + * + * @since 2.2.6 + */ + public function current() + { + return $this->current; + } + + /** + * {@inheritdoc} + * + * @since 2.2.6 + */ + public function next() + { + ++$this->cursor; + + if (isset($this->orderedKeys[$this->cursor])) { + $this->key = $this->orderedKeys[$this->cursor]; + $this->current = $this->elements[$this->key]; + } else { + $this->key = null; + $this->current = null; + } + } + + /** + *{@inheritdoc} + * + * @since 2.2.6 + */ + public function key() + { + return $this->key; + } + + /** + *{@inheritdoc} + * + * @since 2.2.6 + */ + public function valid() + { + return null !== $this->key; + } + + /** + *{@inheritdoc} + * + * @since 2.2.6 + */ + public function rewind() + { + $this->cursor = 0; + + if (isset($this->orderedKeys[0])) { + $this->key = $this->orderedKeys[0]; + $this->current = $this->elements[$this->key]; + } else { + $this->key = null; + $this->current = null; + } + } +} diff --git a/Util/ReferencingArrayIterator.php b/Util/ReferencingArrayIterator.php deleted file mode 100644 index 9bb64d79d2..0000000000 --- a/Util/ReferencingArrayIterator.php +++ /dev/null @@ -1,78 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Util; - -/** - * Iterator that traverses an array. - * - * Contrary to {@link \ArrayIterator}, this iterator recognizes changes in the - * original array during iteration. - * - * @author Bernhard Schussek - */ -class ReferencingArrayIterator implements \Iterator -{ - /** - * @var array - */ - private $array; - - /** - * Creates a new iterator. - * - * @param array $array An array - */ - public function __construct(array &$array) - { - $this->array = &$array; - } - - /** - *{@inheritdoc} - */ - public function current() - { - return current($this->array); - } - - /** - *{@inheritdoc} - */ - public function next() - { - next($this->array); - } - - /** - *{@inheritdoc} - */ - public function key() - { - return key($this->array); - } - - /** - *{@inheritdoc} - */ - public function valid() - { - return null !== key($this->array); - } - - /** - *{@inheritdoc} - */ - public function rewind() - { - reset($this->array); - } -} diff --git a/Util/VirtualFormAwareIterator.php b/Util/VirtualFormAwareIterator.php index 708726dedf..581e3540e4 100644 --- a/Util/VirtualFormAwareIterator.php +++ b/Util/VirtualFormAwareIterator.php @@ -14,9 +14,6 @@ /** * Iterator that traverses an array of forms. * - * Contrary to {@link \ArrayIterator}, this iterator recognizes changes in the - * original array during iteration. - * * You can wrap the iterator into a {@link \RecursiveIterator} in order to * enter any child form that inherits its parent's data and iterate the children * of that form as well. @@ -26,14 +23,14 @@ * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link InheritDataAwareIterator} instead. */ -class VirtualFormAwareIterator extends ReferencingArrayIterator implements \RecursiveIterator +class VirtualFormAwareIterator extends \IteratorIterator implements \RecursiveIterator { /** * {@inheritdoc} */ public function getChildren() { - return new static($this->current()->all()); + return new static($this->current()); } /** From f85201a6aeb9e8193ca08d763ddbbe78672754c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Simon?= Date: Tue, 30 Jul 2013 14:08:17 +0200 Subject: [PATCH 166/447] Replace sha1 and md5 hashing with sha256 algorithm --- Extension/Core/Type/ChoiceType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/Core/Type/ChoiceType.php b/Extension/Core/Type/ChoiceType.php index 9a3fdef12b..d26ee5f72a 100644 --- a/Extension/Core/Type/ChoiceType.php +++ b/Extension/Core/Type/ChoiceType.php @@ -164,7 +164,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) $choices = null !== $options['choices'] ? $options['choices'] : array(); // Reuse existing choice lists in order to increase performance - $hash = md5(json_encode(array($choices, $options['preferred_choices']))); + $hash = hash('sha256', json_encode(array($choices, $options['preferred_choices']))); if (!isset($choiceListCache[$hash])) { $choiceListCache[$hash] = new SimpleChoiceList($choices, $options['preferred_choices']); From 9e9127528c97bf6f8344690991daad42f461237d Mon Sep 17 00:00:00 2001 From: Christian Raue Date: Sun, 1 Sep 2013 20:32:33 +0200 Subject: [PATCH 167/447] fixed typo --- Tests/Extension/Core/Type/DateTypeTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Extension/Core/Type/DateTypeTest.php b/Tests/Extension/Core/Type/DateTypeTest.php index 6d4dd2c8a7..7c71b1a033 100644 --- a/Tests/Extension/Core/Type/DateTypeTest.php +++ b/Tests/Extension/Core/Type/DateTypeTest.php @@ -291,7 +291,7 @@ public function provideDateFormats() } /** - * This test is to check that the strings '0', '1', '2', '3' are no accepted + * This test is to check that the strings '0', '1', '2', '3' are not accepted * as valid IntlDateFormatter constants for FULL, LONG, MEDIUM or SHORT respectively. * * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException From cfd06e231ed7d5d90d1e17d148e6424c53cf80e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timothe=CC=81e=20Barray?= Date: Mon, 2 Sep 2013 15:03:07 +0200 Subject: [PATCH 168/447] [Form] Add missing default property typeExtensionServiceIds --- Extension/DependencyInjection/DependencyInjectionExtension.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Extension/DependencyInjection/DependencyInjectionExtension.php b/Extension/DependencyInjection/DependencyInjectionExtension.php index 6637ac8c63..915c43fa62 100644 --- a/Extension/DependencyInjection/DependencyInjectionExtension.php +++ b/Extension/DependencyInjection/DependencyInjectionExtension.php @@ -22,6 +22,8 @@ class DependencyInjectionExtension implements FormExtensionInterface private $typeServiceIds; + private $typeExtensionServiceIds; + private $guesserServiceIds; private $guesser; From d0701f576e93b9834d6288f991c3aefcce27281a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1chym=20Tou=C5=A1ek?= Date: Mon, 2 Sep 2013 10:09:18 +0200 Subject: [PATCH 169/447] Fixed annotation --- Extension/HttpFoundation/EventListener/BindRequestListener.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/HttpFoundation/EventListener/BindRequestListener.php b/Extension/HttpFoundation/EventListener/BindRequestListener.php index 6205b98d70..2930c5b36a 100644 --- a/Extension/HttpFoundation/EventListener/BindRequestListener.php +++ b/Extension/HttpFoundation/EventListener/BindRequestListener.php @@ -21,7 +21,7 @@ * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Pass the - * Request instance to {@link Form::process()} instead. + * Request instance to {@link Form::handleRequest()} instead. */ class BindRequestListener implements EventSubscriberInterface { From 6bdcfc6f6d4e3cc5cb190cd9485c7c50a8517511 Mon Sep 17 00:00:00 2001 From: mike Date: Tue, 11 Jun 2013 23:05:51 +0200 Subject: [PATCH 170/447] Button missing getErrorsAsString() fixes #8084 Debug: Not calling undefined method anymore. If the form contained a submit button the call would fail and the debug of the form wasn't possible. Now it will work in all cases. This fixes #8084 Adding a test for the fix of getErrorAsString on Form. Was throwing a fatal because of a method that did not exist on the new element type button. --- Form.php | 2 +- Tests/Extension/Core/Type/FormTypeTest.php | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Form.php b/Form.php index f7fa834b35..767232392c 100644 --- a/Form.php +++ b/Form.php @@ -751,7 +751,7 @@ public function getErrorsAsString($level = 0) foreach ($this->children as $key => $child) { $errors .= str_repeat(' ', $level).$key.":\n"; - if ($err = $child->getErrorsAsString($level + 4)) { + if ($child instanceof self && $err = $child->getErrorsAsString($level + 4)) { $errors .= $err; } else { $errors .= str_repeat(' ', $level + 4)."No errors\n"; diff --git a/Tests/Extension/Core/Type/FormTypeTest.php b/Tests/Extension/Core/Type/FormTypeTest.php index cced82f4cf..60b6afa6c8 100644 --- a/Tests/Extension/Core/Type/FormTypeTest.php +++ b/Tests/Extension/Core/Type/FormTypeTest.php @@ -571,6 +571,20 @@ public function testPassZeroLabelToView() $this->assertSame('0', $view->vars['label']); } + public function testCanGetErrorsWhenButtonInForm() + { + $builder = $this->factory->createBuilder('form', null, array( + 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', + 'required' => false, + )); + $builder->add('foo', 'text'); + $builder->add('submit', 'submit'); + $form = $builder->getForm(); + + //This method should not throw a Fatal Error Exception. + $form->getErrorsAsString(); + } + protected function getTestedType() { return 'form'; From 59a32c977ca8c456a8f5c1ff44f6bed18b75138f Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Wed, 4 Sep 2013 00:28:35 +0200 Subject: [PATCH 171/447] [Form] fix iterator typehint --- Form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Form.php b/Form.php index 767232392c..5399cc99cc 100644 --- a/Form.php +++ b/Form.php @@ -938,7 +938,7 @@ public function offsetUnset($name) /** * Returns the iterator for this group. * - * @return \Iterator + * @return \Traversable */ public function getIterator() { From 98affb5b2c98edf4ced268eae815f4c8a465e071 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Sun, 5 May 2013 23:28:39 +0200 Subject: [PATCH 172/447] [Form] Removed usage of the ChoiceList::getIndicesFor*() methods where they don't offer any performance benefit --- .../DataTransformer/ChoiceToBooleanArrayTransformer.php | 6 +++--- .../DataTransformer/ChoicesToBooleanArrayTransformer.php | 4 ++-- Extension/Core/Type/ChoiceType.php | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php b/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php index 79b3f7ac89..b521c95572 100644 --- a/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php +++ b/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php @@ -60,14 +60,14 @@ public function transform($choice) throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e); } - $index = current($this->choiceList->getIndicesForChoices(array($choice))); + $valueMap = array_flip($this->choiceList->getValuesForChoices(array($choice))); foreach ($values as $i => $value) { - $values[$i] = $i === $index; + $values[$i] = isset($valueMap[$value]); } if ($this->placeholderPresent) { - $values['placeholder'] = false === $index; + $values['placeholder'] = 0 === count($valueMap); } return $values; diff --git a/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php b/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php index a13c0d4d43..f1f13fda28 100644 --- a/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php +++ b/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php @@ -58,10 +58,10 @@ public function transform($array) throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e); } - $indexMap = array_flip($this->choiceList->getIndicesForChoices($array)); + $valueMap = array_flip($this->choiceList->getValuesForChoices($array)); foreach ($values as $i => $value) { - $values[$i] = isset($indexMap[$i]); + $values[$i] = isset($valueMap[$value]); } return $values; diff --git a/Extension/Core/Type/ChoiceType.php b/Extension/Core/Type/ChoiceType.php index d26ee5f72a..d3d9187c0c 100644 --- a/Extension/Core/Type/ChoiceType.php +++ b/Extension/Core/Type/ChoiceType.php @@ -57,7 +57,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) // Check if the choices already contain the empty value // Only add the empty value option if this is not the case - if (null !== $options['empty_value'] && 0 === count($options['choice_list']->getIndicesForValues(array('')))) { + if (null !== $options['empty_value'] && 0 === count($options['choice_list']->getChoicesForValues(array('')))) { $placeholderView = new ChoiceView(null, '', $options['empty_value']); // "placeholder" is a reserved index @@ -120,7 +120,7 @@ public function buildView(FormView $view, FormInterface $form, array $options) // Check if the choices already contain the empty value // Only add the empty value option if this is not the case - if (null !== $options['empty_value'] && 0 === count($options['choice_list']->getIndicesForValues(array('')))) { + if (null !== $options['empty_value'] && 0 === count($options['choice_list']->getChoicesForValues(array('')))) { $view->vars['empty_value'] = $options['empty_value']; } From d000e7a160fcfa544c36b548e74aecf6eadbda56 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Sun, 5 May 2013 23:50:06 +0200 Subject: [PATCH 173/447] [Form] Fixed ChoiceList::get*By*() methods to preserve order and array keys --- Extension/Core/ChoiceList/ChoiceList.php | 32 ++++++------- .../Core/ChoiceList/ChoiceListInterface.php | 12 +++++ .../Core/ChoiceList/ChoiceListTest.php | 48 ++++++++++++++++++- .../Core/ChoiceList/SimpleChoiceListTest.php | 48 +++++++++++++++++++ 4 files changed, 123 insertions(+), 17 deletions(-) diff --git a/Extension/Core/ChoiceList/ChoiceList.php b/Extension/Core/ChoiceList/ChoiceList.php index f9d381cd04..17ae0a3d9e 100644 --- a/Extension/Core/ChoiceList/ChoiceList.php +++ b/Extension/Core/ChoiceList/ChoiceList.php @@ -156,11 +156,11 @@ public function getChoicesForValues(array $values) $values = $this->fixValues($values); $choices = array(); - foreach ($values as $j => $givenValue) { - foreach ($this->values as $i => $value) { + foreach ($values as $i => $givenValue) { + foreach ($this->values as $j => $value) { if ($value === $givenValue) { - $choices[] = $this->choices[$i]; - unset($values[$j]); + $choices[$i] = $this->choices[$j]; + unset($values[$i]); if (0 === count($values)) { break 2; @@ -180,11 +180,11 @@ public function getValuesForChoices(array $choices) $choices = $this->fixChoices($choices); $values = array(); - foreach ($this->choices as $i => $choice) { - foreach ($choices as $j => $givenChoice) { + foreach ($choices as $i => $givenChoice) { + foreach ($this->choices as $j => $choice) { if ($choice === $givenChoice) { - $values[] = $this->values[$i]; - unset($choices[$j]); + $values[$i] = $this->values[$j]; + unset($choices[$i]); if (0 === count($choices)) { break 2; @@ -204,11 +204,11 @@ public function getIndicesForChoices(array $choices) $choices = $this->fixChoices($choices); $indices = array(); - foreach ($this->choices as $i => $choice) { - foreach ($choices as $j => $givenChoice) { + foreach ($choices as $i => $givenChoice) { + foreach ($this->choices as $j => $choice) { if ($choice === $givenChoice) { - $indices[] = $i; - unset($choices[$j]); + $indices[$i] = $j; + unset($choices[$i]); if (0 === count($choices)) { break 2; @@ -228,11 +228,11 @@ public function getIndicesForValues(array $values) $values = $this->fixValues($values); $indices = array(); - foreach ($this->values as $i => $value) { - foreach ($values as $j => $givenValue) { + foreach ($values as $i => $givenValue) { + foreach ($this->values as $j => $value) { if ($value === $givenValue) { - $indices[] = $i; - unset($values[$j]); + $indices[$i] = $j; + unset($values[$i]); if (0 === count($values)) { break 2; diff --git a/Extension/Core/ChoiceList/ChoiceListInterface.php b/Extension/Core/ChoiceList/ChoiceListInterface.php index 099ace8253..febf80ef05 100644 --- a/Extension/Core/ChoiceList/ChoiceListInterface.php +++ b/Extension/Core/ChoiceList/ChoiceListInterface.php @@ -97,6 +97,9 @@ public function getRemainingViews(); * * The choices can have any data type. * + * The choices must be returned with the same keys and in the same order + * as the corresponding values in the given array. + * * @param array $values An array of choice values. Not existing values in * this array are ignored * @@ -109,6 +112,9 @@ public function getChoicesForValues(array $values); * * The values must be strings. * + * The values must be returned with the same keys and in the same order + * as the corresponding choices in the given array. + * * @param array $choices An array of choices. Not existing choices in this * array are ignored * @@ -125,6 +131,9 @@ public function getValuesForChoices(array $choices); * * The index "placeholder" is internally reserved. * + * The indices must be returned with the same keys and in the same order + * as the corresponding choices in the given array. + * * @param array $choices An array of choices. Not existing choices in this * array are ignored * @@ -140,6 +149,9 @@ public function getIndicesForChoices(array $choices); * * The index "placeholder" is internally reserved. * + * The indices must be returned with the same keys and in the same order + * as the corresponding values in the given array. + * * @param array $values An array of choice values. Not existing values in * this array are ignored * diff --git a/Tests/Extension/Core/ChoiceList/ChoiceListTest.php b/Tests/Extension/Core/ChoiceList/ChoiceListTest.php index 63eae9bf7f..531bb561b4 100644 --- a/Tests/Extension/Core/ChoiceList/ChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/ChoiceListTest.php @@ -125,6 +125,18 @@ public function testGetIndicesForChoices() $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); } + public function testGetIndicesForChoicesPreservesKeys() + { + $choices = array(5 => $this->obj2, 8 => $this->obj3); + $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesPreservesOrder() + { + $choices = array($this->obj3, $this->obj2); + $this->assertSame(array(2, 1), $this->list->getIndicesForChoices($choices)); + } + public function testGetIndicesForChoicesIgnoresNonExistingChoices() { $choices = array($this->obj2, $this->obj3, 'foobar'); @@ -138,6 +150,20 @@ public function testGetIndicesForValues() $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); } + public function testGetIndicesForValuesPreservesKeys() + { + // values and indices are always the same + $values = array(5 => '1', 8 => '2'); + $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForValues($values)); + } + + public function testGetIndicesForValuesPreservesOrder() + { + // values and indices are always the same + $values = array('2', '1'); + $this->assertSame(array(2, 1), $this->list->getIndicesForValues($values)); + } + public function testGetIndicesForValuesIgnoresNonExistingValues() { $values = array('1', '2', '5'); @@ -150,7 +176,13 @@ public function testGetChoicesForValues() $this->assertSame(array($this->obj2, $this->obj3), $this->list->getChoicesForValues($values)); } - public function testGetChoicesForValuesCorrectOrderingOfResult() + public function testGetChoicesForValuesPreservesKeys() + { + $values = array(5 => '1', 8 => '2'); + $this->assertSame(array(5 => $this->obj2, 8 => $this->obj3), $this->list->getChoicesForValues($values)); + } + + public function testGetChoicesForValuesPreservesOrder() { $values = array('2', '1'); $this->assertSame(array($this->obj3, $this->obj2), $this->list->getChoicesForValues($values)); @@ -168,6 +200,20 @@ public function testGetValuesForChoices() $this->assertSame(array('1', '2'), $this->list->getValuesForChoices($choices)); } + + public function testGetValuesForChoicesPreservesKeys() + { + $choices = array(5 => $this->obj2, 8 => $this->obj3); + $this->assertSame(array(5 => '1', 8 => '2'), $this->list->getValuesForChoices($choices)); + } + + + public function testGetValuesForChoicesPreservesOrder() + { + $choices = array($this->obj3, $this->obj2); + $this->assertSame(array('2', '1'), $this->list->getValuesForChoices($choices)); + } + public function testGetValuesForChoicesIgnoresNonExistingChoices() { $choices = array($this->obj2, $this->obj3, 'foobar'); diff --git a/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php b/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php index 69d27a18fd..85b0ed7485 100644 --- a/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php @@ -79,6 +79,18 @@ public function testGetIndicesForChoices() $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); } + public function testGetIndicesForChoicesPreservesKeys() + { + $choices = array(5 => 'b', 8 => 'c'); + $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesPreservesOrder() + { + $choices = array('c', 'b'); + $this->assertSame(array(2, 1), $this->list->getIndicesForChoices($choices)); + } + public function testGetIndicesForChoicesIgnoresNonExistingChoices() { $choices = array('b', 'c', 'foobar'); @@ -98,6 +110,18 @@ public function testGetIndicesForValues() $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); } + public function testGetIndicesForValuesPreservesKeys() + { + $values = array(5 => 'b', 8 => 'c'); + $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForValues($values)); + } + + public function testGetIndicesForValuesPreservesOrder() + { + $values = array('c', 'b'); + $this->assertSame(array(2, 1), $this->list->getIndicesForValues($values)); + } + public function testGetIndicesForValuesIgnoresNonExistingValues() { $values = array('b', 'c', '100'); @@ -117,6 +141,18 @@ public function testGetChoicesForValues() $this->assertSame(array('b', 'c'), $this->list->getChoicesForValues($values)); } + public function testGetChoicesForValuesPreservesKeys() + { + $values = array(5 => 'b', 8 => 'c'); + $this->assertSame(array(5 => 'b', 8 => 'c'), $this->list->getChoicesForValues($values)); + } + + public function testGetChoicesForValuesPreservesOrder() + { + $values = array('c', 'b'); + $this->assertSame(array('c', 'b'), $this->list->getChoicesForValues($values)); + } + public function testGetChoicesForValuesIgnoresNonExistingValues() { $values = array('b', 'c', '100'); @@ -136,6 +172,18 @@ public function testGetValuesForChoices() $this->assertSame(array('b', 'c'), $this->list->getValuesForChoices($choices)); } + public function testGetValuesForChoicesPreservesKeys() + { + $choices = array(5 => 'b', 8 => 'c'); + $this->assertSame(array(5 => 'b', 8 => 'c'), $this->list->getValuesForChoices($choices)); + } + + public function testGetValuesForChoicesPreservesOrder() + { + $choices = array('c', 'b'); + $this->assertSame(array('c', 'b'), $this->list->getValuesForChoices($choices)); + } + public function testGetValuesForChoicesIgnoresNonExistingValues() { $choices = array('b', 'c', 'foobar'); From 45124923e32f877591580e4aa49d1a245f0d9854 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Mon, 6 May 2013 00:28:29 +0200 Subject: [PATCH 174/447] [Form] Fixed expanded choice field to be marked invalid when unknown choices are submitted --- .../BooleanToStringTransformer.php | 6 +- .../FixCheckboxInputListener.php | 40 ++- .../EventListener/FixRadioInputListener.php | 18 +- Extension/Core/Type/CheckboxType.php | 15 +- Form.php | 149 ++++----- .../BooleanToStringTransformerTest.php | 24 +- .../Extension/Core/Type/CheckboxTypeTest.php | 39 ++- Tests/Extension/Core/Type/ChoiceTypeTest.php | 301 +++++++++++++++++- 8 files changed, 476 insertions(+), 116 deletions(-) diff --git a/Extension/Core/DataTransformer/BooleanToStringTransformer.php b/Extension/Core/DataTransformer/BooleanToStringTransformer.php index 95e7332d3e..f8e3b5bfcb 100644 --- a/Extension/Core/DataTransformer/BooleanToStringTransformer.php +++ b/Extension/Core/DataTransformer/BooleanToStringTransformer.php @@ -49,15 +49,11 @@ public function __construct($trueValue) */ public function transform($value) { - if (null === $value) { - return null; - } - if (!is_bool($value)) { throw new TransformationFailedException('Expected a Boolean.'); } - return true === $value ? $this->trueValue : null; + return $value ? $this->trueValue : null; } /** diff --git a/Extension/Core/EventListener/FixCheckboxInputListener.php b/Extension/Core/EventListener/FixCheckboxInputListener.php index 1f62e060ff..8e72b04137 100644 --- a/Extension/Core/EventListener/FixCheckboxInputListener.php +++ b/Extension/Core/EventListener/FixCheckboxInputListener.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Extension\Core\EventListener; +use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -38,10 +39,43 @@ public function __construct(ChoiceListInterface $choiceList) public function preSubmit(FormEvent $event) { - $values = (array) $event->getData(); - $indices = $this->choiceList->getIndicesForValues($values); + $data = $event->getData(); - $event->setData(count($indices) > 0 ? array_combine($indices, $values) : array()); + if (is_array($data)) { + // Flip the submitted values for faster lookup + // It's better to flip this array than $existingValues because + // $submittedValues is generally smaller. + $submittedValues = array_flip($data); + + // Since expanded choice fields are completely loaded anyway, we + // can just as well get the values again without losing performance. + $existingValues = $this->choiceList->getValues(); + + // Clear the data array and fill it with correct indices + $data = array(); + + foreach ($existingValues as $index => $value) { + if (isset($submittedValues[$value])) { + // Value was submitted + $data[$index] = $value; + unset($submittedValues[$value]); + } + } + + if (count($submittedValues) > 0) { + throw new TransformationFailedException(sprintf( + 'The following choices were not found: "%s"', + implode('", "', array_keys($submittedValues)) + )); + } + } elseif ('' === $data || null === $data) { + // Empty values are always accepted. + $data = array(); + } + + // Else leave the data unchanged to provoke an error during submission + + $event->setData($data); } /** diff --git a/Extension/Core/EventListener/FixRadioInputListener.php b/Extension/Core/EventListener/FixRadioInputListener.php index bf03792fed..925585db40 100644 --- a/Extension/Core/EventListener/FixRadioInputListener.php +++ b/Extension/Core/EventListener/FixRadioInputListener.php @@ -42,10 +42,22 @@ public function __construct(ChoiceListInterface $choiceList, $placeholderPresent public function preSubmit(FormEvent $event) { - $value = $event->getData(); - $index = current($this->choiceList->getIndicesForValues(array($value))); + $data = $event->getData(); - $event->setData(false !== $index ? array($index => $value) : ($this->placeholderPresent ? array('placeholder' => '') : array())) ; + // Since expanded choice fields are completely loaded anyway, we + // can just as well get the values again without losing performance. + $existingValues = $this->choiceList->getValues(); + + if (false !== ($index = array_search($data, $existingValues, true))) { + $data = array($index => $data); + } elseif ('' === $data || null === $data) { + // Empty values are always accepted. + $data = $this->placeholderPresent ? array('placeholder' => '') : array(); + } + + // Else leave the data unchanged to provoke an error during submission + + $event->setData($data); } /** diff --git a/Extension/Core/Type/CheckboxType.php b/Extension/Core/Type/CheckboxType.php index 214e581aff..3952bb3316 100644 --- a/Extension/Core/Type/CheckboxType.php +++ b/Extension/Core/Type/CheckboxType.php @@ -25,9 +25,14 @@ class CheckboxType extends AbstractType */ public function buildForm(FormBuilderInterface $builder, array $options) { - $builder - ->addViewTransformer(new BooleanToStringTransformer($options['value'])) - ; + // Unlike in other types, where the data is NULL by default, it + // needs to be a Boolean here. setData(null) is not acceptable + // for checkboxes and radio buttons (unless a custom model + // transformer handles this case). + // We cannot solve this case via overriding the "data" option, because + // doing so also calls setDataLocked(true). + $builder->setData(isset($options['data']) ? $options['data'] : false); + $builder->addViewTransformer(new BooleanToStringTransformer($options['value'])); } /** @@ -46,8 +51,8 @@ public function buildView(FormView $view, FormInterface $form, array $options) */ public function setDefaultOptions(OptionsResolverInterface $resolver) { - $emptyData = function (FormInterface $form, $clientData) { - return $clientData; + $emptyData = function (FormInterface $form, $viewData) { + return $viewData; }; $resolver->setDefaults(array( diff --git a/Form.php b/Form.php index 5399cc99cc..f3324986c8 100644 --- a/Form.php +++ b/Form.php @@ -522,83 +522,82 @@ public function submit($submittedData, $clearMissing = true) $dispatcher = $this->config->getEventDispatcher(); - // Hook to change content of the data submitted by the browser - if ($dispatcher->hasListeners(FormEvents::PRE_SUBMIT)) { - $event = new FormEvent($this, $submittedData); - $dispatcher->dispatch(FormEvents::PRE_SUBMIT, $event); - $submittedData = $event->getData(); - } + $modelData = null; + $normData = null; + $viewData = null; - // Check whether the form is compound. - // This check is preferable over checking the number of children, - // since forms without children may also be compound. - // (think of empty collection forms) - if ($this->config->getCompound()) { - if (!is_array($submittedData)) { - $submittedData = array(); + try { + // Hook to change content of the data submitted by the browser + if ($dispatcher->hasListeners(FormEvents::PRE_SUBMIT)) { + $event = new FormEvent($this, $submittedData); + $dispatcher->dispatch(FormEvents::PRE_SUBMIT, $event); + $submittedData = $event->getData(); } - foreach ($this->children as $name => $child) { - if (array_key_exists($name, $submittedData) || $clearMissing) { - $child->submit(isset($submittedData[$name]) ? $submittedData[$name] : null, $clearMissing); - unset($submittedData[$name]); + // Check whether the form is compound. + // This check is preferable over checking the number of children, + // since forms without children may also be compound. + // (think of empty collection forms) + if ($this->config->getCompound()) { + if (null === $submittedData) { + $submittedData = array(); } - } - - $this->extraData = $submittedData; - } - // Forms that inherit their parents' data also are not processed, - // because then it would be too difficult to merge the changes in - // the child and the parent form. Instead, the parent form also takes - // changes in the grandchildren (i.e. children of the form that inherits - // its parent's data) into account. - // (see InheritDataAwareIterator below) - if ($this->config->getInheritData()) { - $this->submitted = true; + if (!is_array($submittedData)) { + throw new TransformationFailedException('Compound forms expect an array or NULL on submission.'); + } - // When POST_SUBMIT is reached, the data is not yet updated, so pass - // NULL to prevent hard-to-debug bugs. - $dataForPostSubmit = null; - } else { - // If the form is compound, the default data in view format - // is reused. The data of the children is merged into this - // default data using the data mapper. - // If the form is not compound, the submitted data is also the data in view format. - $viewData = $this->config->getCompound() ? $this->viewData : $submittedData; - - if (FormUtil::isEmpty($viewData)) { - $emptyData = $this->config->getEmptyData(); - - if ($emptyData instanceof \Closure) { - /* @var \Closure $emptyData */ - $emptyData = $emptyData($this, $viewData); + foreach ($this->children as $name => $child) { + if (isset($submittedData[$name]) || $clearMissing) { + $child->submit(isset($submittedData[$name]) ? $submittedData[$name] : null, $clearMissing); + unset($submittedData[$name]); + } } - $viewData = $emptyData; + $this->extraData = $submittedData; } - // Merge form data from children into existing view data - // It is not necessary to invoke this method if the form has no children, - // even if it is compound. - if (count($this->children) > 0) { - // Use InheritDataAwareIterator to process children of - // descendants that inherit this form's data. - // These descendants will not be submitted normally (see the check - // for $this->config->getInheritData() above) - $iterator = new InheritDataAwareIterator($this->children); - $iterator = new \RecursiveIteratorIterator($iterator); - $this->config->getDataMapper()->mapFormsToData($iterator, $viewData); - } + // Forms that inherit their parents' data also are not processed, + // because then it would be too difficult to merge the changes in + // the child and the parent form. Instead, the parent form also takes + // changes in the grandchildren (i.e. children of the form that inherits + // its parent's data) into account. + // (see InheritDataAwareIterator below) + if (!$this->config->getInheritData()) { + // If the form is compound, the default data in view format + // is reused. The data of the children is merged into this + // default data using the data mapper. + // If the form is not compound, the submitted data is also the data in view format. + $viewData = $this->config->getCompound() ? $this->viewData : $submittedData; + + if (FormUtil::isEmpty($viewData)) { + $emptyData = $this->config->getEmptyData(); + + if ($emptyData instanceof \Closure) { + /* @var \Closure $emptyData */ + $emptyData = $emptyData($this, $viewData); + } + + $viewData = $emptyData; + } - $modelData = null; - $normData = null; + // Merge form data from children into existing view data + // It is not necessary to invoke this method if the form has no children, + // even if it is compound. + if (count($this->children) > 0) { + // Use InheritDataAwareIterator to process children of + // descendants that inherit this form's data. + // These descendants will not be submitted normally (see the check + // for $this->config->getInheritData() above) + $childrenIterator = new InheritDataAwareIterator($this->children); + $childrenIterator = new \RecursiveIteratorIterator($childrenIterator); + $this->config->getDataMapper()->mapFormsToData($childrenIterator, $viewData); + } - try { // Normalize data to unified representation $normData = $this->viewToNorm($viewData); - // Hook to change content of the data into the normalized + // Hook to change content of the data in the normalized // representation if ($dispatcher->hasListeners(FormEvents::SUBMIT)) { $event = new FormEvent($this, $normData); @@ -609,20 +608,26 @@ public function submit($submittedData, $clearMissing = true) // Synchronize representations - must not change the content! $modelData = $this->normToModel($normData); $viewData = $this->normToView($normData); - } catch (TransformationFailedException $e) { - $this->synchronized = false; } - - $this->submitted = true; - $this->modelData = $modelData; - $this->normData = $normData; - $this->viewData = $viewData; - - $dataForPostSubmit = $viewData; + } catch (TransformationFailedException $e) { + $this->synchronized = false; + + // If $viewData was not yet set, set it to $submittedData so that + // the erroneous data is accessible on the form. + // Forms that inherit data never set any data, because the getters + // forward to the parent form's getters anyway. + if (null === $viewData && !$this->config->getInheritData()) { + $viewData = $submittedData; + } } + $this->submitted = true; + $this->modelData = $modelData; + $this->normData = $normData; + $this->viewData = $viewData; + if ($dispatcher->hasListeners(FormEvents::POST_SUBMIT)) { - $event = new FormEvent($this, $dataForPostSubmit); + $event = new FormEvent($this, $viewData); $dispatcher->dispatch(FormEvents::POST_SUBMIT, $event); } diff --git a/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php index 41f8f956d7..4f6238aee0 100644 --- a/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php @@ -17,6 +17,9 @@ class BooleanToStringTransformerTest extends \PHPUnit_Framework_TestCase { const TRUE_VALUE = '1'; + /** + * @var BooleanToStringTransformer + */ protected $transformer; protected function setUp() @@ -33,20 +36,29 @@ public function testTransform() { $this->assertEquals(self::TRUE_VALUE, $this->transformer->transform(true)); $this->assertNull($this->transformer->transform(false)); - $this->assertNull($this->transformer->transform(null)); } - public function testTransformExpectsBoolean() + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testTransformFailsIfNull() { - $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); + $this->transformer->transform(null); + } + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testTransformFailsIfString() + { $this->transformer->transform('1'); } - public function testReverseTransformExpectsString() + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformFailsIfInteger() { - $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); - $this->transformer->reverseTransform(1); } diff --git a/Tests/Extension/Core/Type/CheckboxTypeTest.php b/Tests/Extension/Core/Type/CheckboxTypeTest.php index c782adab04..9437bd7eea 100644 --- a/Tests/Extension/Core/Type/CheckboxTypeTest.php +++ b/Tests/Extension/Core/Type/CheckboxTypeTest.php @@ -15,6 +15,15 @@ class CheckboxTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { + public function testDataIsFalseByDefault() + { + $form = $this->factory->create('checkbox'); + + $this->assertFalse($form->getData()); + $this->assertFalse($form->getNormData()); + $this->assertNull($form->getViewData()); + } + public function testPassValueToView() { $form = $this->factory->create('checkbox', null, array('value' => 'foobar')); @@ -105,58 +114,60 @@ public function testSubmitWithEmptyValueUnchecked() $this->assertNull($form->getViewData()); } - public function testBindWithEmptyValueAndFalseUnchecked() + public function testSubmitWithEmptyValueAndFalseUnchecked() { $form = $this->factory->create('checkbox', null, array( 'value' => '', )); - $form->bind(false); + $form->submit(false); $this->assertFalse($form->getData()); $this->assertNull($form->getViewData()); } - public function testBindWithEmptyValueAndTrueChecked() + public function testSubmitWithEmptyValueAndTrueChecked() { $form = $this->factory->create('checkbox', null, array( 'value' => '', )); - $form->bind(true); + $form->submit(true); $this->assertTrue($form->getData()); $this->assertSame('', $form->getViewData()); } /** - * @dataProvider provideTransformedData + * @dataProvider provideCustomModelTransformerData */ - public function testTransformedData($data, $expected) + public function testCustomModelTransformer($data, $checked) { // present a binary status field as a checkbox $transformer = new CallbackTransformer( function ($value) { - return 'expedited' == $value; + return 'checked' == $value; }, function ($value) { - return $value ? 'expedited' : 'standard'; + return $value ? 'checked' : 'unchecked'; } ); - $form = $this->builder - ->create('expedited_shipping', 'checkbox') + $form = $this->factory->createBuilder('checkbox') ->addModelTransformer($transformer) ->getForm(); + $form->setData($data); $view = $form->createView(); - $this->assertEquals($expected, $view->vars['checked']); + $this->assertSame($data, $form->getData()); + $this->assertSame($checked, $form->getNormData()); + $this->assertEquals($checked, $view->vars['checked']); } - public function provideTransformedData() + public function provideCustomModelTransformerData() { return array( - array('expedited', true), - array('standard', false), + array('checked', true), + array('unchecked', false), ); } } diff --git a/Tests/Extension/Core/Type/ChoiceTypeTest.php b/Tests/Extension/Core/Type/ChoiceTypeTest.php index 219e8181c0..ee40e74268 100644 --- a/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -231,6 +231,21 @@ public function testSubmitSingleNonExpanded() $this->assertEquals('b', $form->getViewData()); } + public function testSubmitSingleNonExpandedInvalidChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => false, + 'choices' => $this->choices, + )); + + $form->submit('foobar'); + + $this->assertNull($form->getData()); + $this->assertEquals('foobar', $form->getViewData()); + $this->assertFalse($form->isSynchronized()); + } + public function testSubmitSingleNonExpandedObjectChoices() { $form = $this->factory->create('choice', null, array( @@ -268,6 +283,36 @@ public function testSubmitMultipleNonExpanded() $this->assertEquals(array('a', 'b'), $form->getViewData()); } + public function testSubmitMultipleNonExpandedInvalidScalarChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'expanded' => false, + 'choices' => $this->choices, + )); + + $form->submit('foobar'); + + $this->assertNull($form->getData()); + $this->assertEquals('foobar', $form->getViewData()); + $this->assertFalse($form->isSynchronized()); + } + + public function testSubmitMultipleNonExpandedInvalidArrayChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'expanded' => false, + 'choices' => $this->choices, + )); + + $form->submit(array('a', 'foobar')); + + $this->assertNull($form->getData()); + $this->assertEquals(array('a', 'foobar'), $form->getViewData()); + $this->assertFalse($form->isSynchronized()); + } + public function testSubmitMultipleNonExpandedObjectChoices() { $form = $this->factory->create('choice', null, array( @@ -309,6 +354,8 @@ public function testSubmitSingleExpandedRequired() 3 => false, 4 => false, ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); $this->assertFalse($form[0]->getData()); $this->assertTrue($form[1]->getData()); @@ -322,6 +369,34 @@ public function testSubmitSingleExpandedRequired() $this->assertNull($form[4]->getViewData()); } + public function testSubmitSingleExpandedRequiredInvalidChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => true, + 'choices' => $this->choices, + )); + + $form->submit('foobar'); + + $this->assertSame(null, $form->getData()); + $this->assertSame('foobar', $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertFalse($form->isSynchronized()); + + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + public function testSubmitSingleExpandedNonRequired() { $form = $this->factory->create('choice', null, array( @@ -342,6 +417,8 @@ public function testSubmitSingleExpandedNonRequired() 4 => false, 'placeholder' => false, ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); $this->assertFalse($form['placeholder']->getData()); $this->assertFalse($form[0]->getData()); @@ -357,7 +434,35 @@ public function testSubmitSingleExpandedNonRequired() $this->assertNull($form[4]->getViewData()); } - public function testSubmitSingleExpandedRequiredNothingChecked() + public function testSubmitSingleExpandedNonRequiredInvalidChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => false, + 'choices' => $this->choices, + )); + + $form->submit('foobar'); + + $this->assertSame(null, $form->getData()); + $this->assertSame('foobar', $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertFalse($form->isSynchronized()); + + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testSubmitSingleExpandedRequiredNull() { $form = $this->factory->create('choice', null, array( 'multiple' => false, @@ -376,6 +481,76 @@ public function testSubmitSingleExpandedRequiredNothingChecked() 3 => false, 4 => false, ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); + + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testSubmitSingleExpandedRequiredEmpty() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => true, + 'choices' => $this->choices, + )); + + $form->submit(''); + + $this->assertNull($form->getData()); + $this->assertSame(array( + 0 => false, + 1 => false, + 2 => false, + 3 => false, + 4 => false, + ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); + + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testSubmitSingleExpandedRequiredFalse() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => true, + 'choices' => $this->choices, + )); + + $form->submit(false); + + $this->assertNull($form->getData()); + $this->assertSame(array( + 0 => false, + 1 => false, + 2 => false, + 3 => false, + 4 => false, + ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); @@ -389,7 +564,7 @@ public function testSubmitSingleExpandedRequiredNothingChecked() $this->assertNull($form[4]->getViewData()); } - public function testSubmitSingleExpandedNonRequiredNothingChecked() + public function testSubmitSingleExpandedNonRequiredNull() { $form = $this->factory->create('choice', null, array( 'multiple' => false, @@ -409,6 +584,8 @@ public function testSubmitSingleExpandedNonRequiredNothingChecked() 4 => false, 'placeholder' => true, ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); $this->assertTrue($form['placeholder']->getData()); $this->assertFalse($form[0]->getData()); @@ -424,22 +601,44 @@ public function testSubmitSingleExpandedNonRequiredNothingChecked() $this->assertNull($form[4]->getViewData()); } - public function testSubmitFalseToSingleExpandedRequiredDoesNotProduceExtraChildrenError() + public function testSubmitSingleExpandedNonRequiredEmpty() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, - 'required' => true, + 'required' => false, 'choices' => $this->choices, )); - $form->submit(false); + $form->submit(''); - $this->assertEmpty($form->getExtraData()); $this->assertNull($form->getData()); + $this->assertSame(array( + 0 => false, + 1 => false, + 2 => false, + 3 => false, + 4 => false, + 'placeholder' => true, + ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); + + $this->assertTrue($form['placeholder']->getData()); + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertSame('', $form['placeholder']->getViewData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); } - public function testSubmitFalseToSingleExpandedNonRequiredDoesNotProduceExtraChildrenError() + public function testSubmitSingleExpandedNonRequiredFalse() { $form = $this->factory->create('choice', null, array( 'multiple' => false, @@ -450,8 +649,30 @@ public function testSubmitFalseToSingleExpandedNonRequiredDoesNotProduceExtraChi $form->submit(false); - $this->assertEmpty($form->getExtraData()); $this->assertNull($form->getData()); + $this->assertSame(array( + 0 => false, + 1 => false, + 2 => false, + 3 => false, + 4 => false, + 'placeholder' => true, + ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); + + $this->assertTrue($form['placeholder']->getData()); + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertSame('', $form['placeholder']->getViewData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedWithEmptyChild() @@ -539,6 +760,16 @@ public function testSubmitMultipleExpanded() $form->submit(array('a', 'c')); $this->assertSame(array('a', 'c'), $form->getData()); + $this->assertSame(array( + 0 => true, + 1 => false, + 2 => true, + 3 => false, + 4 => false, + ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); + $this->assertTrue($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertTrue($form[2]->getData()); @@ -551,6 +782,60 @@ public function testSubmitMultipleExpanded() $this->assertNull($form[4]->getViewData()); } + public function testSubmitMultipleExpandedInvalidScalarChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'expanded' => true, + 'choices' => $this->choices, + )); + + $form->submit('foobar'); + + $this->assertNull($form->getData()); + $this->assertSame('foobar', $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertFalse($form->isSynchronized()); + + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testSubmitMultipleExpandedInvalidArrayChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'expanded' => true, + 'choices' => $this->choices, + )); + + $form->submit(array('a', 'foobar')); + + $this->assertNull($form->getData()); + $this->assertSame(array('a', 'foobar'), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertFalse($form->isSynchronized()); + + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + public function testSubmitMultipleExpandedEmpty() { $form = $this->factory->create('choice', null, array( From 54e289a47128eb5cb2d95dab4970c18643f4da67 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Tue, 10 Sep 2013 12:41:39 +0200 Subject: [PATCH 175/447] [Form] Improved test coverage of ChoiceList classes --- .../ChoiceList/AbstractChoiceListTest.php | 297 ++++++++++++++++++ .../Core/ChoiceList/ChoiceListTest.php | 172 +++------- .../Core/ChoiceList/ObjectChoiceListTest.php | 64 ++-- .../Core/ChoiceList/SimpleChoiceListTest.php | 191 ++--------- .../SimpleNumericChoiceListTest.php | 78 +++++ 5 files changed, 486 insertions(+), 316 deletions(-) create mode 100644 Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php create mode 100644 Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php diff --git a/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php b/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php new file mode 100644 index 0000000000..0e2b6321cc --- /dev/null +++ b/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php @@ -0,0 +1,297 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; + +/** + * @author Bernhard Schussek + */ +abstract class AbstractChoiceListTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface + */ + protected $list; + + /** + * @var array + */ + protected $choices; + + /** + * @var array + */ + protected $values; + + /** + * @var array + */ + protected $indices; + + /** + * @var array + */ + protected $labels; + + /** + * @var mixed + */ + protected $choice1; + + /** + * @var mixed + */ + protected $choice2; + + /** + * @var mixed + */ + protected $choice3; + + /** + * @var mixed + */ + protected $choice4; + + /** + * @var string + */ + protected $value1; + + /** + * @var string + */ + protected $value2; + + /** + * @var string + */ + protected $value3; + + /** + * @var string + */ + protected $value4; + + /** + * @var int|string + */ + protected $index1; + + /** + * @var int|string + */ + protected $index2; + + /** + * @var int|string + */ + protected $index3; + + /** + * @var int|string + */ + protected $index4; + + /** + * @var string + */ + protected $label1; + + /** + * @var string + */ + protected $label2; + + /** + * @var string + */ + protected $label3; + + /** + * @var string + */ + protected $label4; + + protected function setUp() + { + parent::setUp(); + + $this->list = $this->createChoiceList(); + + $this->choices = $this->getChoices(); + $this->indices = $this->getIndices(); + $this->values = $this->getValues(); + $this->labels = $this->getLabels(); + + // allow access to the individual entries without relying on their indices + reset($this->choices); + reset($this->indices); + reset($this->values); + reset($this->labels); + + for ($i = 1; $i <= 4; ++$i) { + $this->{'choice'.$i} = current($this->choices); + $this->{'index'.$i} = current($this->indices); + $this->{'value'.$i} = current($this->values); + $this->{'label'.$i} = current($this->labels); + + next($this->choices); + next($this->indices); + next($this->values); + next($this->labels); + } + } + + public function testGetChoices() + { + $this->assertSame($this->choices, $this->list->getChoices()); + } + + public function testGetValues() + { + $this->assertSame($this->values, $this->list->getValues()); + } + + public function testGetIndicesForChoices() + { + $choices = array($this->choice1, $this->choice2); + $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesPreservesKeys() + { + $choices = array(5 => $this->choice1, 8 => $this->choice2); + $this->assertSame(array(5 => $this->index1, 8 => $this->index2), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesPreservesOrder() + { + $choices = array($this->choice2, $this->choice1); + $this->assertSame(array($this->index2, $this->index1), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesIgnoresNonExistingChoices() + { + $choices = array($this->choice1, $this->choice2, 'foobar'); + $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesEmpty() + { + $this->assertSame(array(), $this->list->getIndicesForChoices(array())); + } + + public function testGetIndicesForValues() + { + // values and indices are always the same + $values = array($this->value1, $this->value2); + $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForValues($values)); + } + + public function testGetIndicesForValuesPreservesKeys() + { + // values and indices are always the same + $values = array(5 => $this->value1, 8 => $this->value2); + $this->assertSame(array(5 => $this->index1, 8 => $this->index2), $this->list->getIndicesForValues($values)); + } + + public function testGetIndicesForValuesPreservesOrder() + { + $values = array($this->value2, $this->value1); + $this->assertSame(array($this->index2, $this->index1), $this->list->getIndicesForValues($values)); + } + + public function testGetIndicesForValuesIgnoresNonExistingValues() + { + $values = array($this->value1, $this->value2, 'foobar'); + $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForValues($values)); + } + + public function testGetIndicesForValuesEmpty() + { + $this->assertSame(array(), $this->list->getIndicesForValues(array())); + } + + public function testGetChoicesForValues() + { + $values = array($this->value1, $this->value2); + $this->assertSame(array($this->choice1, $this->choice2), $this->list->getChoicesForValues($values)); + } + + public function testGetChoicesForValuesPreservesKeys() + { + $values = array(5 => $this->value1, 8 => $this->value2); + $this->assertSame(array(5 => $this->choice1, 8 => $this->choice2), $this->list->getChoicesForValues($values)); + } + + public function testGetChoicesForValuesPreservesOrder() + { + $values = array($this->value2, $this->value1); + $this->assertSame(array($this->choice2, $this->choice1), $this->list->getChoicesForValues($values)); + } + + public function testGetChoicesForValuesIgnoresNonExistingValues() + { + $values = array($this->value1, $this->value2, 'foobar'); + $this->assertSame(array($this->choice1, $this->choice2), $this->list->getChoicesForValues($values)); + } + + // https://github.com/symfony/symfony/issues/3446 + public function testGetChoicesForValuesEmpty() + { + $this->assertSame(array(), $this->list->getChoicesForValues(array())); + } + + public function testGetValuesForChoices() + { + $choices = array($this->choice1, $this->choice2); + $this->assertSame(array($this->value1, $this->value2), $this->list->getValuesForChoices($choices)); + } + + + public function testGetValuesForChoicesPreservesKeys() + { + $choices = array(5 => $this->choice1, 8 => $this->choice2); + $this->assertSame(array(5 => $this->value1, 8 => $this->value2), $this->list->getValuesForChoices($choices)); + } + + + public function testGetValuesForChoicesPreservesOrder() + { + $choices = array($this->choice2, $this->choice1); + $this->assertSame(array($this->value2, $this->value1), $this->list->getValuesForChoices($choices)); + } + + public function testGetValuesForChoicesIgnoresNonExistingChoices() + { + $choices = array($this->choice1, $this->choice2, 'foobar'); + $this->assertSame(array($this->value1, $this->value2), $this->list->getValuesForChoices($choices)); + } + + public function testGetValuesForChoicesEmpty() + { + $this->assertSame(array(), $this->list->getValuesForChoices(array())); + } + + /** + * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface + */ + abstract protected function createChoiceList(); + + abstract protected function getChoices(); + + abstract protected function getLabels(); + + abstract protected function getValues(); + + abstract protected function getIndices(); +} diff --git a/Tests/Extension/Core/ChoiceList/ChoiceListTest.php b/Tests/Extension/Core/ChoiceList/ChoiceListTest.php index 531bb561b4..59f002d8cc 100644 --- a/Tests/Extension/Core/ChoiceList/ChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/ChoiceListTest.php @@ -14,7 +14,7 @@ use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList; use Symfony\Component\Form\Extension\Core\View\ChoiceView; -class ChoiceListTest extends \PHPUnit_Framework_TestCase +class ChoiceListTest extends AbstractChoiceListTest { private $obj1; @@ -24,39 +24,14 @@ class ChoiceListTest extends \PHPUnit_Framework_TestCase private $obj4; - private $list; - protected function setUp() { - parent::setUp(); - $this->obj1 = new \stdClass(); $this->obj2 = new \stdClass(); $this->obj3 = new \stdClass(); $this->obj4 = new \stdClass(); - $this->list = new ChoiceList( - array( - 'Group 1' => array($this->obj1, $this->obj2), - 'Group 2' => array($this->obj3, $this->obj4), - ), - array( - 'Group 1' => array('A', 'B'), - 'Group 2' => array('C', 'D'), - ), - array($this->obj2, $this->obj3) - ); - } - - protected function tearDown() - { - parent::tearDown(); - - $this->obj1 = null; - $this->obj2 = null; - $this->obj3 = null; - $this->obj4 = null; - $this->list = null; + parent::setUp(); } public function testInitArray() @@ -119,111 +94,10 @@ public function testInitNestedArray() ), $this->list->getRemainingViews()); } - public function testGetIndicesForChoices() - { - $choices = array($this->obj2, $this->obj3); - $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForChoicesPreservesKeys() - { - $choices = array(5 => $this->obj2, 8 => $this->obj3); - $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForChoicesPreservesOrder() - { - $choices = array($this->obj3, $this->obj2); - $this->assertSame(array(2, 1), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForChoicesIgnoresNonExistingChoices() - { - $choices = array($this->obj2, $this->obj3, 'foobar'); - $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForValues() - { - // values and indices are always the same - $values = array('1', '2'); - $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); - } - - public function testGetIndicesForValuesPreservesKeys() - { - // values and indices are always the same - $values = array(5 => '1', 8 => '2'); - $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForValues($values)); - } - - public function testGetIndicesForValuesPreservesOrder() - { - // values and indices are always the same - $values = array('2', '1'); - $this->assertSame(array(2, 1), $this->list->getIndicesForValues($values)); - } - - public function testGetIndicesForValuesIgnoresNonExistingValues() - { - $values = array('1', '2', '5'); - $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); - } - - public function testGetChoicesForValues() - { - $values = array('1', '2'); - $this->assertSame(array($this->obj2, $this->obj3), $this->list->getChoicesForValues($values)); - } - - public function testGetChoicesForValuesPreservesKeys() - { - $values = array(5 => '1', 8 => '2'); - $this->assertSame(array(5 => $this->obj2, 8 => $this->obj3), $this->list->getChoicesForValues($values)); - } - - public function testGetChoicesForValuesPreservesOrder() - { - $values = array('2', '1'); - $this->assertSame(array($this->obj3, $this->obj2), $this->list->getChoicesForValues($values)); - } - - public function testGetChoicesForValuesIgnoresNonExistingValues() - { - $values = array('1', '2', '5'); - $this->assertSame(array($this->obj2, $this->obj3), $this->list->getChoicesForValues($values)); - } - - public function testGetValuesForChoices() - { - $choices = array($this->obj2, $this->obj3); - $this->assertSame(array('1', '2'), $this->list->getValuesForChoices($choices)); - } - - - public function testGetValuesForChoicesPreservesKeys() - { - $choices = array(5 => $this->obj2, 8 => $this->obj3); - $this->assertSame(array(5 => '1', 8 => '2'), $this->list->getValuesForChoices($choices)); - } - - - public function testGetValuesForChoicesPreservesOrder() - { - $choices = array($this->obj3, $this->obj2); - $this->assertSame(array('2', '1'), $this->list->getValuesForChoices($choices)); - } - - public function testGetValuesForChoicesIgnoresNonExistingChoices() - { - $choices = array($this->obj2, $this->obj3, 'foobar'); - $this->assertSame(array('1', '2'), $this->list->getValuesForChoices($choices)); - } - /** * @expectedException \InvalidArgumentException */ - public function testNonMatchingLabels() + public function testInitWithInsufficientLabels() { $this->list = new ChoiceList( array($this->obj1, $this->obj2), @@ -231,7 +105,7 @@ public function testNonMatchingLabels() ); } - public function testLabelsContainingNull() + public function testInitWithLabelsContainingNull() { $this->list = new ChoiceList( array($this->obj1, $this->obj2), @@ -243,4 +117,42 @@ public function testLabelsContainingNull() $this->list->getRemainingViews() ); } + + /** + * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface + */ + protected function createChoiceList() + { + return new ChoiceList( + array( + 'Group 1' => array($this->obj1, $this->obj2), + 'Group 2' => array($this->obj3, $this->obj4), + ), + array( + 'Group 1' => array('A', 'B'), + 'Group 2' => array('C', 'D'), + ), + array($this->obj2, $this->obj3) + ); + } + + protected function getChoices() + { + return array(0 => $this->obj1, 1 => $this->obj2, 2 => $this->obj3, 3 => $this->obj4); + } + + protected function getLabels() + { + return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D'); + } + + protected function getValues() + { + return array(0 => '0', 1 => '1', 2 => '2', 3 => '3'); + } + + protected function getIndices() + { + return array(0, 1, 2, 3); + } } diff --git a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php index 69c5aa0fcb..27effd9f5c 100644 --- a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php @@ -29,7 +29,7 @@ public function __toString() } } -class ObjectChoiceListTest extends \PHPUnit_Framework_TestCase +class ObjectChoiceListTest extends AbstractChoiceListTest { private $obj1; @@ -39,39 +39,14 @@ class ObjectChoiceListTest extends \PHPUnit_Framework_TestCase private $obj4; - /** - * @var ObjectChoiceList - */ - private $list; - protected function setUp() { - parent::setUp(); - $this->obj1 = (object) array('name' => 'A'); $this->obj2 = (object) array('name' => 'B'); $this->obj3 = (object) array('name' => 'C'); $this->obj4 = (object) array('name' => 'D'); - $this->list = new ObjectChoiceList( - array( - 'Group 1' => array($this->obj1, $this->obj2), - 'Group 2' => array($this->obj3, $this->obj4), - ), - 'name', - array($this->obj2, $this->obj3) - ); - } - - protected function tearDown() - { - parent::tearDown(); - - $this->obj1 = null; - $this->obj2 = null; - $this->obj3 = null; - $this->obj4 = null; - $this->list = null; + parent::setUp(); } public function testInitArray() @@ -209,4 +184,39 @@ public function testInitArrayThrowsExceptionIfToStringNotFound() array($this->obj1, $this->obj2, $this->obj3, $this->obj4) ); } + + /** + * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface + */ + protected function createChoiceList() + { + return new ObjectChoiceList( + array( + 'Group 1' => array($this->obj1, $this->obj2), + 'Group 2' => array($this->obj3, $this->obj4), + ), + 'name', + array($this->obj2, $this->obj3) + ); + } + + protected function getChoices() + { + return array(0 => $this->obj1, 1 => $this->obj2, 2 => $this->obj3, 3 => $this->obj4); + } + + protected function getLabels() + { + return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D'); + } + + protected function getValues() + { + return array(0 => '0', 1 => '1', 2 => '2', 3 => '3'); + } + + protected function getIndices() + { + return array(0, 1, 2, 3); + } } diff --git a/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php b/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php index 85b0ed7485..838a8e0864 100644 --- a/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php @@ -11,43 +11,11 @@ namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; -use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; use Symfony\Component\Form\Extension\Core\View\ChoiceView; -class SimpleChoiceListTest extends \PHPUnit_Framework_TestCase +class SimpleChoiceListTest extends AbstractChoiceListTest { - private $list; - - private $numericList; - - protected function setUp() - { - parent::setUp(); - - $choices = array( - 'Group 1' => array('a' => 'A', 'b' => 'B'), - 'Group 2' => array('c' => 'C', 'd' => 'D'), - ); - $numericChoices = array( - 'Group 1' => array(0 => 'A', 1 => 'B'), - 'Group 2' => array(2 => 'C', 3 => 'D'), - ); - - $this->list = new SimpleChoiceList($choices, array('b', 'c')); - - // Use COPY_CHOICE strategy to test for the various associated problems - $this->numericList = new SimpleChoiceList($numericChoices, array(1, 2)); - } - - protected function tearDown() - { - parent::tearDown(); - - $this->list = null; - $this->numericList = null; - } - public function testInitArray() { $choices = array('a' => 'A', 'b' => 'B', 'c' => 'C'); @@ -73,131 +41,6 @@ public function testInitNestedArray() ), $this->list->getRemainingViews()); } - public function testGetIndicesForChoices() - { - $choices = array('b', 'c'); - $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForChoicesPreservesKeys() - { - $choices = array(5 => 'b', 8 => 'c'); - $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForChoicesPreservesOrder() - { - $choices = array('c', 'b'); - $this->assertSame(array(2, 1), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForChoicesIgnoresNonExistingChoices() - { - $choices = array('b', 'c', 'foobar'); - $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForChoicesDealsWithNumericChoices() - { - // Pass choices as strings although they are integers - $choices = array('0', '1'); - $this->assertSame(array(0, 1), $this->numericList->getIndicesForChoices($choices)); - } - - public function testGetIndicesForValues() - { - $values = array('b', 'c'); - $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); - } - - public function testGetIndicesForValuesPreservesKeys() - { - $values = array(5 => 'b', 8 => 'c'); - $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForValues($values)); - } - - public function testGetIndicesForValuesPreservesOrder() - { - $values = array('c', 'b'); - $this->assertSame(array(2, 1), $this->list->getIndicesForValues($values)); - } - - public function testGetIndicesForValuesIgnoresNonExistingValues() - { - $values = array('b', 'c', '100'); - $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); - } - - public function testGetIndicesForValuesDealsWithNumericValues() - { - // Pass values as strings although they are integers - $values = array('0', '1'); - $this->assertSame(array(0, 1), $this->numericList->getIndicesForValues($values)); - } - - public function testGetChoicesForValues() - { - $values = array('b', 'c'); - $this->assertSame(array('b', 'c'), $this->list->getChoicesForValues($values)); - } - - public function testGetChoicesForValuesPreservesKeys() - { - $values = array(5 => 'b', 8 => 'c'); - $this->assertSame(array(5 => 'b', 8 => 'c'), $this->list->getChoicesForValues($values)); - } - - public function testGetChoicesForValuesPreservesOrder() - { - $values = array('c', 'b'); - $this->assertSame(array('c', 'b'), $this->list->getChoicesForValues($values)); - } - - public function testGetChoicesForValuesIgnoresNonExistingValues() - { - $values = array('b', 'c', '100'); - $this->assertSame(array('b', 'c'), $this->list->getChoicesForValues($values)); - } - - public function testGetChoicesForValuesDealsWithNumericValues() - { - // Pass values as strings although they are integers - $values = array('0', '1'); - $this->assertSame(array(0, 1), $this->numericList->getChoicesForValues($values)); - } - - public function testGetValuesForChoices() - { - $choices = array('b', 'c'); - $this->assertSame(array('b', 'c'), $this->list->getValuesForChoices($choices)); - } - - public function testGetValuesForChoicesPreservesKeys() - { - $choices = array(5 => 'b', 8 => 'c'); - $this->assertSame(array(5 => 'b', 8 => 'c'), $this->list->getValuesForChoices($choices)); - } - - public function testGetValuesForChoicesPreservesOrder() - { - $choices = array('c', 'b'); - $this->assertSame(array('c', 'b'), $this->list->getValuesForChoices($choices)); - } - - public function testGetValuesForChoicesIgnoresNonExistingValues() - { - $choices = array('b', 'c', 'foobar'); - $this->assertSame(array('b', 'c'), $this->list->getValuesForChoices($choices)); - } - - public function testGetValuesForChoicesDealsWithNumericValues() - { - // Pass values as strings although they are integers - $values = array('0', '1'); - - $this->assertSame(array('0', '1'), $this->numericList->getValuesForChoices($values)); - } - /** * @dataProvider dirtyValuesProvider */ @@ -212,7 +55,6 @@ public function testGetValuesForChoicesDealsWithDirtyValues($choice, $value) 'foo10' => 'Foo 10', ); - // use COPY_CHOICE strategy to test the problems $this->list = new SimpleChoiceList($choices, array()); $this->assertSame(array($value), $this->list->getValuesForChoices(array($choice))); @@ -233,4 +75,35 @@ public function dirtyValuesProvider() array('foo10', 'foo10'), ); } + + /** + * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface + */ + protected function createChoiceList() + { + return new SimpleChoiceList(array( + 'Group 1' => array('a' => 'A', 'b' => 'B'), + 'Group 2' => array('c' => 'C', 'd' => 'D'), + ), array('b', 'c')); + } + + protected function getChoices() + { + return array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd'); + } + + protected function getLabels() + { + return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D'); + } + + protected function getValues() + { + return array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd'); + } + + protected function getIndices() + { + return array(0, 1, 2, 3); + } } diff --git a/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php b/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php new file mode 100644 index 0000000000..2b57288fb7 --- /dev/null +++ b/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; + +use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; +use Symfony\Component\Form\Extension\Core\View\ChoiceView; + +class SimpleNumericChoiceListTest extends AbstractChoiceListTest +{ + public function testGetIndicesForChoicesDealsWithNumericChoices() + { + // Pass choices as strings although they are integers + $choices = array('0', '1'); + $this->assertSame(array(0, 1), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForValuesDealsWithNumericValues() + { + // Pass values as strings although they are integers + $values = array('0', '1'); + $this->assertSame(array(0, 1), $this->list->getIndicesForValues($values)); + } + + public function testGetChoicesForValuesDealsWithNumericValues() + { + // Pass values as strings although they are integers + $values = array('0', '1'); + $this->assertSame(array(0, 1), $this->list->getChoicesForValues($values)); + } + + public function testGetValuesForChoicesDealsWithNumericValues() + { + // Pass values as strings although they are integers + $values = array('0', '1'); + + $this->assertSame(array('0', '1'), $this->list->getValuesForChoices($values)); + } + + /** + * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface + */ + protected function createChoiceList() + { + return new SimpleChoiceList(array( + 'Group 1' => array(0 => 'A', 1 => 'B'), + 'Group 2' => array(2 => 'C', 3 => 'D'), + ), array(1, 2)); + } + + protected function getChoices() + { + return array(0 => 0, 1 => 1, 2 => 2, 3 => 3); + } + + protected function getLabels() + { + return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D'); + } + + protected function getValues() + { + return array(0 => '0', 1 => '1', 2 => '2', 3 => '3'); + } + + protected function getIndices() + { + return array(0, 1, 2, 3); + } +} From e599c258edd126dd968f0f0246c4c4c38c5103b8 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Tue, 10 Sep 2013 15:56:14 +0200 Subject: [PATCH 176/447] [Form] Fixed FormValidator::findClickedButton() not to be called exponentially --- .../Validator/Constraints/FormValidator.php | 27 +++++++++- .../FormValidatorPerformanceTest.php | 54 +++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.php diff --git a/Extension/Validator/Constraints/FormValidator.php b/Extension/Validator/Constraints/FormValidator.php index bad5a00720..8f02364e81 100644 --- a/Extension/Validator/Constraints/FormValidator.php +++ b/Extension/Validator/Constraints/FormValidator.php @@ -22,6 +22,11 @@ */ class FormValidator extends ConstraintValidator { + /** + * @var \SplObjectStorage + */ + private static $clickedButtons; + /** * @var ServerParams */ @@ -47,6 +52,16 @@ public function validate($form, Constraint $constraint) return; } + if (null === static::$clickedButtons) { + static::$clickedButtons = new \SplObjectStorage(); + } + + // If the form was previously validated, remove it from the cache in + // case the clicked button has changed + if (static::$clickedButtons->contains($form)) { + static::$clickedButtons->detach($form); + } + /* @var FormInterface $form */ $config = $form->getConfig(); @@ -172,7 +187,17 @@ private static function allowDataWalking(FormInterface $form) */ private static function getValidationGroups(FormInterface $form) { - $button = self::findClickedButton($form->getRoot()); + $root = $form->getRoot(); + + // Determine the clicked button of the complete form tree + if (!static::$clickedButtons->contains($root)) { + // Only call findClickedButton() once to prevent an exponential + // runtime + // https://github.com/symfony/symfony/issues/8317 + static::$clickedButtons->attach($root, self::findClickedButton($root)); + } + + $button = static::$clickedButtons->offsetGet($root); if (null !== $button) { $groups = $button->getConfig()->getOption('validation_groups'); diff --git a/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.php b/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.php new file mode 100644 index 0000000000..487e6e0b50 --- /dev/null +++ b/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Validator\Constraints; + +use Symfony\Component\Form\Extension\Validator\ValidatorExtension; +use Symfony\Component\Form\Test\FormPerformanceTestCase; +use Symfony\Component\Validator\Validation; + +/** + * @author Bernhard Schussek + */ +class FormValidatorPerformanceTest extends FormPerformanceTestCase +{ + protected function getExtensions() + { + return array( + new ValidatorExtension(Validation::createValidator()), + ); + } + + /** + * findClickedButton() used to have an exponential number of calls + * + * @group benchmark + */ + public function testValidationPerformance() + { + $this->setMaxRunningTime(1); + + $builder = $this->factory->createBuilder('form'); + + for ($i = 0; $i < 100; ++$i) { + $builder->add($i, 'form'); + + $builder->get($i) + ->add('a') + ->add('b') + ->add('c'); + } + + $form = $builder->getForm(); + + $form->submit(null); + } +} From 6a8b6e3329ae6a68928b26cf1ef4e98250fc5be4 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Sun, 5 May 2013 23:28:39 +0200 Subject: [PATCH 177/447] [Form] Removed usage of the ChoiceList::getIndicesFor*() methods where they don't offer any performance benefit --- .../Core/DataTransformer/ChoiceToBooleanArrayTransformer.php | 4 ++-- .../Core/DataTransformer/ChoicesToBooleanArrayTransformer.php | 4 ++-- Extension/Core/Type/ChoiceType.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php b/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php index b8aa95effc..12e1efd081 100644 --- a/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php +++ b/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php @@ -56,10 +56,10 @@ public function transform($choice) throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e); } - $index = current($this->choiceList->getIndicesForChoices(array($choice))); + $valueMap = array_flip($this->choiceList->getValuesForChoices(array($choice))); foreach ($values as $i => $value) { - $values[$i] = $i === $index; + $values[$i] = isset($valueMap[$value]); } return $values; diff --git a/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php b/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php index 0c2ea3a394..d3b8cc345b 100644 --- a/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php +++ b/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php @@ -58,10 +58,10 @@ public function transform($array) throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e); } - $indexMap = array_flip($this->choiceList->getIndicesForChoices($array)); + $valueMap = array_flip($this->choiceList->getValuesForChoices($array)); foreach ($values as $i => $value) { - $values[$i] = isset($indexMap[$i]); + $values[$i] = isset($valueMap[$value]); } return $values; diff --git a/Extension/Core/Type/ChoiceType.php b/Extension/Core/Type/ChoiceType.php index 28327b6291..2f65199692 100644 --- a/Extension/Core/Type/ChoiceType.php +++ b/Extension/Core/Type/ChoiceType.php @@ -104,7 +104,7 @@ public function buildView(FormView $view, FormInterface $form, array $options) // Check if the choices already contain the empty value // Only add the empty value option if this is not the case - if (0 === count($options['choice_list']->getIndicesForValues(array('')))) { + if (0 === count($options['choice_list']->getChoicesForValues(array('')))) { $view->vars['empty_value'] = $options['empty_value']; } From 5e1eac761fed86838c16e6a0b692bf1d1bb8a793 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Sun, 5 May 2013 23:50:06 +0200 Subject: [PATCH 178/447] [Form] Fixed ChoiceList::get*By*() methods to preserve order and array keys --- Extension/Core/ChoiceList/ChoiceList.php | 32 ++++++------- .../Core/ChoiceList/ChoiceListInterface.php | 24 ++++++++++ .../Core/ChoiceList/ChoiceListTest.php | 48 ++++++++++++++++++- .../Core/ChoiceList/SimpleChoiceListTest.php | 48 +++++++++++++++++++ 4 files changed, 135 insertions(+), 17 deletions(-) diff --git a/Extension/Core/ChoiceList/ChoiceList.php b/Extension/Core/ChoiceList/ChoiceList.php index 4fbca4b451..18220a8c42 100644 --- a/Extension/Core/ChoiceList/ChoiceList.php +++ b/Extension/Core/ChoiceList/ChoiceList.php @@ -155,11 +155,11 @@ public function getChoicesForValues(array $values) $values = $this->fixValues($values); $choices = array(); - foreach ($values as $j => $givenValue) { - foreach ($this->values as $i => $value) { + foreach ($values as $i => $givenValue) { + foreach ($this->values as $j => $value) { if ($value === $givenValue) { - $choices[] = $this->choices[$i]; - unset($values[$j]); + $choices[$i] = $this->choices[$j]; + unset($values[$i]); if (0 === count($values)) { break 2; @@ -179,11 +179,11 @@ public function getValuesForChoices(array $choices) $choices = $this->fixChoices($choices); $values = array(); - foreach ($this->choices as $i => $choice) { - foreach ($choices as $j => $givenChoice) { + foreach ($choices as $i => $givenChoice) { + foreach ($this->choices as $j => $choice) { if ($choice === $givenChoice) { - $values[] = $this->values[$i]; - unset($choices[$j]); + $values[$i] = $this->values[$j]; + unset($choices[$i]); if (0 === count($choices)) { break 2; @@ -203,11 +203,11 @@ public function getIndicesForChoices(array $choices) $choices = $this->fixChoices($choices); $indices = array(); - foreach ($this->choices as $i => $choice) { - foreach ($choices as $j => $givenChoice) { + foreach ($choices as $i => $givenChoice) { + foreach ($this->choices as $j => $choice) { if ($choice === $givenChoice) { - $indices[] = $i; - unset($choices[$j]); + $indices[$i] = $j; + unset($choices[$i]); if (0 === count($choices)) { break 2; @@ -227,11 +227,11 @@ public function getIndicesForValues(array $values) $values = $this->fixValues($values); $indices = array(); - foreach ($this->values as $i => $value) { - foreach ($values as $j => $givenValue) { + foreach ($values as $i => $givenValue) { + foreach ($this->values as $j => $value) { if ($value === $givenValue) { - $indices[] = $i; - unset($values[$j]); + $indices[$i] = $j; + unset($values[$i]); if (0 === count($values)) { break 2; diff --git a/Extension/Core/ChoiceList/ChoiceListInterface.php b/Extension/Core/ChoiceList/ChoiceListInterface.php index c81c560f4f..996dbe2591 100644 --- a/Extension/Core/ChoiceList/ChoiceListInterface.php +++ b/Extension/Core/ChoiceList/ChoiceListInterface.php @@ -95,6 +95,11 @@ public function getRemainingViews(); /** * Returns the choices corresponding to the given values. * + * The choices can have any data type. + * + * The choices must be returned with the same keys and in the same order + * as the corresponding values in the given array. + * * @param array $values An array of choice values. Not existing values in * this array are ignored. * @@ -105,6 +110,11 @@ public function getChoicesForValues(array $values); /** * Returns the values corresponding to the given choices. * + * The values must be strings. + * + * The values must be returned with the same keys and in the same order + * as the corresponding choices in the given array. + * * @param array $choices An array of choices. Not existing choices in this * array are ignored. * @@ -116,6 +126,12 @@ public function getValuesForChoices(array $choices); /** * Returns the indices corresponding to the given choices. * + * The indices must be positive integers or strings accepted by + * {@link FormConfigBuilder::validateName()}. + * + * The indices must be returned with the same keys and in the same order + * as the corresponding choices in the given array. + * * @param array $choices An array of choices. Not existing choices in this * array are ignored. * @@ -126,6 +142,14 @@ public function getIndicesForChoices(array $choices); /** * Returns the indices corresponding to the given values. * + * The indices must be positive integers or strings accepted by + * {@link FormConfigBuilder::validateName()}. + * + * The index "placeholder" is internally reserved. + * + * The indices must be returned with the same keys and in the same order + * as the corresponding values in the given array. + * * @param array $values An array of choice values. Not existing values in * this array are ignored. * diff --git a/Tests/Extension/Core/ChoiceList/ChoiceListTest.php b/Tests/Extension/Core/ChoiceList/ChoiceListTest.php index 63eae9bf7f..531bb561b4 100644 --- a/Tests/Extension/Core/ChoiceList/ChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/ChoiceListTest.php @@ -125,6 +125,18 @@ public function testGetIndicesForChoices() $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); } + public function testGetIndicesForChoicesPreservesKeys() + { + $choices = array(5 => $this->obj2, 8 => $this->obj3); + $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesPreservesOrder() + { + $choices = array($this->obj3, $this->obj2); + $this->assertSame(array(2, 1), $this->list->getIndicesForChoices($choices)); + } + public function testGetIndicesForChoicesIgnoresNonExistingChoices() { $choices = array($this->obj2, $this->obj3, 'foobar'); @@ -138,6 +150,20 @@ public function testGetIndicesForValues() $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); } + public function testGetIndicesForValuesPreservesKeys() + { + // values and indices are always the same + $values = array(5 => '1', 8 => '2'); + $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForValues($values)); + } + + public function testGetIndicesForValuesPreservesOrder() + { + // values and indices are always the same + $values = array('2', '1'); + $this->assertSame(array(2, 1), $this->list->getIndicesForValues($values)); + } + public function testGetIndicesForValuesIgnoresNonExistingValues() { $values = array('1', '2', '5'); @@ -150,7 +176,13 @@ public function testGetChoicesForValues() $this->assertSame(array($this->obj2, $this->obj3), $this->list->getChoicesForValues($values)); } - public function testGetChoicesForValuesCorrectOrderingOfResult() + public function testGetChoicesForValuesPreservesKeys() + { + $values = array(5 => '1', 8 => '2'); + $this->assertSame(array(5 => $this->obj2, 8 => $this->obj3), $this->list->getChoicesForValues($values)); + } + + public function testGetChoicesForValuesPreservesOrder() { $values = array('2', '1'); $this->assertSame(array($this->obj3, $this->obj2), $this->list->getChoicesForValues($values)); @@ -168,6 +200,20 @@ public function testGetValuesForChoices() $this->assertSame(array('1', '2'), $this->list->getValuesForChoices($choices)); } + + public function testGetValuesForChoicesPreservesKeys() + { + $choices = array(5 => $this->obj2, 8 => $this->obj3); + $this->assertSame(array(5 => '1', 8 => '2'), $this->list->getValuesForChoices($choices)); + } + + + public function testGetValuesForChoicesPreservesOrder() + { + $choices = array($this->obj3, $this->obj2); + $this->assertSame(array('2', '1'), $this->list->getValuesForChoices($choices)); + } + public function testGetValuesForChoicesIgnoresNonExistingChoices() { $choices = array($this->obj2, $this->obj3, 'foobar'); diff --git a/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php b/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php index 69d27a18fd..85b0ed7485 100644 --- a/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php @@ -79,6 +79,18 @@ public function testGetIndicesForChoices() $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); } + public function testGetIndicesForChoicesPreservesKeys() + { + $choices = array(5 => 'b', 8 => 'c'); + $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesPreservesOrder() + { + $choices = array('c', 'b'); + $this->assertSame(array(2, 1), $this->list->getIndicesForChoices($choices)); + } + public function testGetIndicesForChoicesIgnoresNonExistingChoices() { $choices = array('b', 'c', 'foobar'); @@ -98,6 +110,18 @@ public function testGetIndicesForValues() $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); } + public function testGetIndicesForValuesPreservesKeys() + { + $values = array(5 => 'b', 8 => 'c'); + $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForValues($values)); + } + + public function testGetIndicesForValuesPreservesOrder() + { + $values = array('c', 'b'); + $this->assertSame(array(2, 1), $this->list->getIndicesForValues($values)); + } + public function testGetIndicesForValuesIgnoresNonExistingValues() { $values = array('b', 'c', '100'); @@ -117,6 +141,18 @@ public function testGetChoicesForValues() $this->assertSame(array('b', 'c'), $this->list->getChoicesForValues($values)); } + public function testGetChoicesForValuesPreservesKeys() + { + $values = array(5 => 'b', 8 => 'c'); + $this->assertSame(array(5 => 'b', 8 => 'c'), $this->list->getChoicesForValues($values)); + } + + public function testGetChoicesForValuesPreservesOrder() + { + $values = array('c', 'b'); + $this->assertSame(array('c', 'b'), $this->list->getChoicesForValues($values)); + } + public function testGetChoicesForValuesIgnoresNonExistingValues() { $values = array('b', 'c', '100'); @@ -136,6 +172,18 @@ public function testGetValuesForChoices() $this->assertSame(array('b', 'c'), $this->list->getValuesForChoices($choices)); } + public function testGetValuesForChoicesPreservesKeys() + { + $choices = array(5 => 'b', 8 => 'c'); + $this->assertSame(array(5 => 'b', 8 => 'c'), $this->list->getValuesForChoices($choices)); + } + + public function testGetValuesForChoicesPreservesOrder() + { + $choices = array('c', 'b'); + $this->assertSame(array('c', 'b'), $this->list->getValuesForChoices($choices)); + } + public function testGetValuesForChoicesIgnoresNonExistingValues() { $choices = array('b', 'c', 'foobar'); From 7257d4068124ff14a4150e862ff6a0b70694b245 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Mon, 6 May 2013 00:28:29 +0200 Subject: [PATCH 179/447] [Form] Fixed expanded choice field to be marked invalid when unknown choices are submitted --- .../BooleanToStringTransformer.php | 6 +- .../FixCheckboxInputListener.php | 40 +- .../EventListener/FixRadioInputListener.php | 18 +- Extension/Core/Type/CheckboxType.php | 15 +- Form.php | 109 ++--- .../BooleanToStringTransformerTest.php | 24 +- .../Extension/Core/Type/CheckboxTypeTest.php | 31 +- Tests/Extension/Core/Type/ChoiceTypeTest.php | 380 +++++++++++++++++- 8 files changed, 539 insertions(+), 84 deletions(-) diff --git a/Extension/Core/DataTransformer/BooleanToStringTransformer.php b/Extension/Core/DataTransformer/BooleanToStringTransformer.php index 95e7332d3e..f8e3b5bfcb 100644 --- a/Extension/Core/DataTransformer/BooleanToStringTransformer.php +++ b/Extension/Core/DataTransformer/BooleanToStringTransformer.php @@ -49,15 +49,11 @@ public function __construct($trueValue) */ public function transform($value) { - if (null === $value) { - return null; - } - if (!is_bool($value)) { throw new TransformationFailedException('Expected a Boolean.'); } - return true === $value ? $this->trueValue : null; + return $value ? $this->trueValue : null; } /** diff --git a/Extension/Core/EventListener/FixCheckboxInputListener.php b/Extension/Core/EventListener/FixCheckboxInputListener.php index 083e23e946..d5bd573ff8 100644 --- a/Extension/Core/EventListener/FixCheckboxInputListener.php +++ b/Extension/Core/EventListener/FixCheckboxInputListener.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Extension\Core\EventListener; +use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -38,10 +39,43 @@ public function __construct(ChoiceListInterface $choiceList) public function preBind(FormEvent $event) { - $values = (array) $event->getData(); - $indices = $this->choiceList->getIndicesForValues($values); + $data = $event->getData(); - $event->setData(count($indices) > 0 ? array_combine($indices, $values) : array()); + if (is_array($data)) { + // Flip the submitted values for faster lookup + // It's better to flip this array than $existingValues because + // $submittedValues is generally smaller. + $submittedValues = array_flip($data); + + // Since expanded choice fields are completely loaded anyway, we + // can just as well get the values again without losing performance. + $existingValues = $this->choiceList->getValues(); + + // Clear the data array and fill it with correct indices + $data = array(); + + foreach ($existingValues as $index => $value) { + if (isset($submittedValues[$value])) { + // Value was submitted + $data[$index] = $value; + unset($submittedValues[$value]); + } + } + + if (count($submittedValues) > 0) { + throw new TransformationFailedException(sprintf( + 'The following choices were not found: "%s"', + implode('", "', array_keys($submittedValues)) + )); + } + } elseif ('' === $data || null === $data) { + // Empty values are always accepted. + $data = array(); + } + + // Else leave the data unchanged to provoke an error during submission + + $event->setData($data); } public static function getSubscribedEvents() diff --git a/Extension/Core/EventListener/FixRadioInputListener.php b/Extension/Core/EventListener/FixRadioInputListener.php index c60bd26b53..40de4b2d6a 100644 --- a/Extension/Core/EventListener/FixRadioInputListener.php +++ b/Extension/Core/EventListener/FixRadioInputListener.php @@ -38,10 +38,22 @@ public function __construct(ChoiceListInterface $choiceList) public function preBind(FormEvent $event) { - $value = $event->getData(); - $index = current($this->choiceList->getIndicesForValues(array($value))); + $data = $event->getData(); - $event->setData(false !== $index ? array($index => $value) : array()); + // Since expanded choice fields are completely loaded anyway, we + // can just as well get the values again without losing performance. + $existingValues = $this->choiceList->getValues(); + + if (false !== ($index = array_search($data, $existingValues, true))) { + $data = array($index => $data); + } elseif ('' === $data || null === $data) { + // Empty values are always accepted. + $data = array(); + } + + // Else leave the data unchanged to provoke an error during submission + + $event->setData($data); } public static function getSubscribedEvents() diff --git a/Extension/Core/Type/CheckboxType.php b/Extension/Core/Type/CheckboxType.php index 8d489d6db0..10e84fd57b 100644 --- a/Extension/Core/Type/CheckboxType.php +++ b/Extension/Core/Type/CheckboxType.php @@ -25,9 +25,14 @@ class CheckboxType extends AbstractType */ public function buildForm(FormBuilderInterface $builder, array $options) { - $builder - ->addViewTransformer(new BooleanToStringTransformer($options['value'])) - ; + // Unlike in other types, where the data is NULL by default, it + // needs to be a Boolean here. setData(null) is not acceptable + // for checkboxes and radio buttons (unless a custom model + // transformer handles this case). + // We cannot solve this case via overriding the "data" option, because + // doing so also calls setDataLocked(true). + $builder->setData(isset($options['data']) ? $options['data'] : false); + $builder->addViewTransformer(new BooleanToStringTransformer($options['value'])); } /** @@ -46,8 +51,8 @@ public function buildView(FormView $view, FormInterface $form, array $options) */ public function setDefaultOptions(OptionsResolverInterface $resolver) { - $emptyData = function (FormInterface $form, $clientData) { - return $clientData; + $emptyData = function (FormInterface $form, $viewData) { + return $viewData; }; $resolver->setDefaults(array( diff --git a/Form.php b/Form.php index 92014de3ed..6f96732d6e 100644 --- a/Form.php +++ b/Form.php @@ -531,68 +531,73 @@ public function bind($submittedData) $dispatcher = $this->config->getEventDispatcher(); - // Hook to change content of the data bound by the browser - if ($dispatcher->hasListeners(FormEvents::PRE_BIND) || $dispatcher->hasListeners(FormEvents::BIND_CLIENT_DATA)) { - $event = new FormEvent($this, $submittedData); - $dispatcher->dispatch(FormEvents::PRE_BIND, $event); - // BC until 2.3 - if ($dispatcher->hasListeners(FormEvents::BIND_CLIENT_DATA)) { - trigger_error('The FormEvents::BIND_CLIENT_DATA event is deprecated since 2.1 and will be removed in 2.3. Use the FormEvents::PRE_BIND event instead.', E_USER_DEPRECATED); - } - $dispatcher->dispatch(FormEvents::BIND_CLIENT_DATA, $event); - $submittedData = $event->getData(); - } + $modelData = null; + $normData = null; + $viewData = null; - // Check whether the form is compound. - // This check is preferable over checking the number of children, - // since forms without children may also be compound. - // (think of empty collection forms) - if ($this->config->getCompound()) { - if (!is_array($submittedData)) { - $submittedData = array(); + try { + // Hook to change content of the data bound by the browser + if ($dispatcher->hasListeners(FormEvents::PRE_BIND) || $dispatcher->hasListeners(FormEvents::BIND_CLIENT_DATA)) { + $event = new FormEvent($this, $submittedData); + $dispatcher->dispatch(FormEvents::PRE_BIND, $event); + // BC until 2.3 + if ($dispatcher->hasListeners(FormEvents::BIND_CLIENT_DATA)) { + trigger_error('The FormEvents::BIND_CLIENT_DATA event is deprecated since 2.1 and will be removed in 2.3. Use the FormEvents::PRE_BIND event instead.', E_USER_DEPRECATED); + } + $dispatcher->dispatch(FormEvents::BIND_CLIENT_DATA, $event); + $submittedData = $event->getData(); } - for (reset($this->children); false !== current($this->children); next($this->children)) { - $child = current($this->children); - $name = key($this->children); + // Check whether the form is compound. + // This check is preferable over checking the number of children, + // since forms without children may also be compound. + // (think of empty collection forms) + if ($this->config->getCompound()) { + if (null === $submittedData) { + $submittedData = array(); + } - $child->bind(isset($submittedData[$name]) ? $submittedData[$name] : null); - unset($submittedData[$name]); - } + if (!is_array($submittedData)) { + throw new TransformationFailedException('Compound forms expect an array or NULL on submission.'); + } - $this->extraData = $submittedData; + for (reset($this->children); false !== current($this->children); next($this->children)) { + $child = current($this->children); + $name = key($this->children); - // If the form is compound, the default data in view format - // is reused. The data of the children is merged into this - // default data using the data mapper. - $viewData = $this->viewData; - } else { - // If the form is not compound, the submitted data is also the data in view format. - $viewData = $submittedData; - } + $child->bind(isset($submittedData[$name]) ? $submittedData[$name] : null); + unset($submittedData[$name]); + } - if (FormUtil::isEmpty($viewData)) { - $emptyData = $this->config->getEmptyData(); + $this->extraData = $submittedData; - if ($emptyData instanceof \Closure) { - /* @var \Closure $emptyData */ - $emptyData = $emptyData($this, $viewData); + // If the form is compound, the default data in view format + // is reused. The data of the children is merged into this + // default data using the data mapper. + $viewData = $this->viewData; + } else { + // If the form is not compound, the submitted data is also the data in view format. + $viewData = $submittedData; } - $viewData = $emptyData; - } + if (FormUtil::isEmpty($viewData)) { + $emptyData = $this->config->getEmptyData(); - // Merge form data from children into existing view data - // It is not necessary to invoke this method if the form has no children, - // even if it is compound. - if (count($this->children) > 0) { - $this->config->getDataMapper()->mapFormsToData($this->children, $viewData); - } + if ($emptyData instanceof \Closure) { + /* @var \Closure $emptyData */ + $emptyData = $emptyData($this, $viewData); + } - $modelData = null; - $normData = null; + $viewData = $emptyData; + } + + // Merge form data from children into existing view data + // It is not necessary to invoke this method if the form has no children, + // even if it is compound. + if (count($this->children) > 0) { + $this->config->getDataMapper()->mapFormsToData($this->children, $viewData); + } - try { // Normalize data to unified representation $normData = $this->viewToNorm($viewData); @@ -614,6 +619,12 @@ public function bind($submittedData) $viewData = $this->normToView($normData); } catch (TransformationFailedException $e) { $this->synchronized = false; + + // If $viewData was not yet set, set it to $submittedData so that + // the erroneous data is accessible on the form. + if (null === $viewData) { + $viewData = $submittedData; + } } $this->bound = true; diff --git a/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php index 41f8f956d7..4f6238aee0 100644 --- a/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php @@ -17,6 +17,9 @@ class BooleanToStringTransformerTest extends \PHPUnit_Framework_TestCase { const TRUE_VALUE = '1'; + /** + * @var BooleanToStringTransformer + */ protected $transformer; protected function setUp() @@ -33,20 +36,29 @@ public function testTransform() { $this->assertEquals(self::TRUE_VALUE, $this->transformer->transform(true)); $this->assertNull($this->transformer->transform(false)); - $this->assertNull($this->transformer->transform(null)); } - public function testTransformExpectsBoolean() + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testTransformFailsIfNull() { - $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); + $this->transformer->transform(null); + } + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testTransformFailsIfString() + { $this->transformer->transform('1'); } - public function testReverseTransformExpectsString() + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformFailsIfInteger() { - $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); - $this->transformer->reverseTransform(1); } diff --git a/Tests/Extension/Core/Type/CheckboxTypeTest.php b/Tests/Extension/Core/Type/CheckboxTypeTest.php index 16a71d8f20..868635d2d2 100644 --- a/Tests/Extension/Core/Type/CheckboxTypeTest.php +++ b/Tests/Extension/Core/Type/CheckboxTypeTest.php @@ -15,6 +15,15 @@ class CheckboxTypeTest extends TypeTestCase { + public function testDataIsFalseByDefault() + { + $form = $this->factory->create('checkbox'); + + $this->assertFalse($form->getData()); + $this->assertFalse($form->getNormData()); + $this->assertNull($form->getViewData()); + } + public function testPassValueToView() { $form = $this->factory->create('checkbox', null, array('value' => 'foobar')); @@ -106,35 +115,37 @@ public function testBindWithEmptyValueUnchecked() } /** - * @dataProvider provideTransformedData + * @dataProvider provideCustomModelTransformerData */ - public function testTransformedData($data, $expected) + public function testCustomModelTransformer($data, $checked) { // present a binary status field as a checkbox $transformer = new CallbackTransformer( function ($value) { - return 'expedited' == $value; + return 'checked' == $value; }, function ($value) { - return $value ? 'expedited' : 'standard'; + return $value ? 'checked' : 'unchecked'; } ); - $form = $this->builder - ->create('expedited_shipping', 'checkbox') + $form = $this->factory->createBuilder('checkbox') ->addModelTransformer($transformer) ->getForm(); + $form->setData($data); $view = $form->createView(); - $this->assertEquals($expected, $view->vars['checked']); + $this->assertSame($data, $form->getData()); + $this->assertSame($checked, $form->getNormData()); + $this->assertEquals($checked, $view->vars['checked']); } - public function provideTransformedData() + public function provideCustomModelTransformerData() { return array( - array('expedited', true), - array('standard', false), + array('checked', true), + array('unchecked', false), ); } } diff --git a/Tests/Extension/Core/Type/ChoiceTypeTest.php b/Tests/Extension/Core/Type/ChoiceTypeTest.php index 844715c650..6869601f90 100644 --- a/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -177,6 +177,21 @@ public function testBindSingleNonExpanded() $this->assertEquals('b', $form->getViewData()); } + public function testBindSingleNonExpandedInvalidChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => false, + 'choices' => $this->choices, + )); + + $form->bind('foobar'); + + $this->assertNull($form->getData()); + $this->assertEquals('foobar', $form->getViewData()); + $this->assertFalse($form->isSynchronized()); + } + public function testBindSingleNonExpandedObjectChoices() { $form = $this->factory->create('choice', null, array( @@ -214,6 +229,36 @@ public function testBindMultipleNonExpanded() $this->assertEquals(array('a', 'b'), $form->getViewData()); } + public function testBindMultipleNonExpandedInvalidScalarChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'expanded' => false, + 'choices' => $this->choices, + )); + + $form->bind('foobar'); + + $this->assertNull($form->getData()); + $this->assertEquals('foobar', $form->getViewData()); + $this->assertFalse($form->isSynchronized()); + } + + public function testBindMultipleNonExpandedInvalidArrayChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'expanded' => false, + 'choices' => $this->choices, + )); + + $form->bind(array('a', 'foobar')); + + $this->assertNull($form->getData()); + $this->assertEquals(array('a', 'foobar'), $form->getViewData()); + $this->assertFalse($form->isSynchronized()); + } + public function testBindMultipleNonExpandedObjectChoices() { $form = $this->factory->create('choice', null, array( @@ -236,7 +281,69 @@ public function testBindMultipleNonExpandedObjectChoices() $this->assertEquals(array('2', '3'), $form->getViewData()); } - public function testBindSingleExpanded() + public function testBindSingleExpandedRequired() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => true, + 'choices' => $this->choices, + )); + + $form->bind('b'); + + $this->assertSame('b', $form->getData()); + $this->assertSame(array( + 0 => false, + 1 => true, + 2 => false, + 3 => false, + 4 => false, + ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); + + $this->assertFalse($form[0]->getData()); + $this->assertTrue($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertSame('b', $form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testBindSingleExpandedRequiredInvalidChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => true, + 'choices' => $this->choices, + )); + + $form->bind('foobar'); + + $this->assertSame(null, $form->getData()); + $this->assertSame('foobar', $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertFalse($form->isSynchronized()); + + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testBindSingleExpandedNonRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => false, @@ -247,6 +354,16 @@ public function testBindSingleExpanded() $form->bind('b'); $this->assertSame('b', $form->getData()); + $this->assertSame(array( + 0 => false, + 1 => true, + 2 => false, + 3 => false, + 4 => false, + ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); + $this->assertFalse($form[0]->getData()); $this->assertTrue($form[1]->getData()); $this->assertFalse($form[2]->getData()); @@ -259,7 +376,35 @@ public function testBindSingleExpanded() $this->assertNull($form[4]->getViewData()); } - public function testBindSingleExpandedNothingChecked() + public function testBindSingleExpandedNonRequiredInvalidChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => false, + 'choices' => $this->choices, + )); + + $form->bind('foobar'); + + $this->assertSame(null, $form->getData()); + $this->assertSame('foobar', $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertFalse($form->isSynchronized()); + + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testBindSingleExpandedRequiredNull() { $form = $this->factory->create('choice', null, array( 'multiple' => false, @@ -270,6 +415,16 @@ public function testBindSingleExpandedNothingChecked() $form->bind(null); $this->assertNull($form->getData()); + $this->assertSame(array( + 0 => false, + 1 => false, + 2 => false, + 3 => false, + 4 => false, + ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); + $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertFalse($form[2]->getData()); @@ -282,18 +437,173 @@ public function testBindSingleExpandedNothingChecked() $this->assertNull($form[4]->getViewData()); } - public function testBindSingleExpandedWithFalseDoesNotHaveExtraChildren() + public function testBindSingleExpandedRequiredEmpty() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, + 'required' => true, + 'choices' => $this->choices, + )); + + $form->bind(''); + + $this->assertNull($form->getData()); + $this->assertSame(array( + 0 => false, + 1 => false, + 2 => false, + 3 => false, + 4 => false, + ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); + + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testBindSingleExpandedRequiredFalse() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => true, 'choices' => $this->choices, )); $form->bind(false); + $this->assertNull($form->getData()); + $this->assertSame(array( + 0 => false, + 1 => false, + 2 => false, + 3 => false, + 4 => false, + ), $form->getViewData()); $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); + + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testBindSingleExpandedNonRequiredNull() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'choices' => $this->choices, + )); + + $form->bind(null); + $this->assertNull($form->getData()); + $this->assertSame(array( + 0 => false, + 1 => false, + 2 => false, + 3 => false, + 4 => false, + ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); + + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testBindSingleExpandedNonRequiredEmpty() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => false, + 'choices' => $this->choices, + )); + + $form->bind(''); + + $this->assertNull($form->getData()); + $this->assertSame(array( + 0 => false, + 1 => false, + 2 => false, + 3 => false, + 4 => false, + ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); + + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testBindSingleExpandedNonRequiredFalse() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => false, + 'choices' => $this->choices, + )); + + $form->bind(false); + + $this->assertNull($form->getData()); + $this->assertSame(array( + 0 => false, + 1 => false, + 2 => false, + 3 => false, + 4 => false, + ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); + + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); } public function testBindSingleExpandedWithEmptyChild() @@ -381,6 +691,16 @@ public function testBindMultipleExpanded() $form->bind(array('a', 'c')); $this->assertSame(array('a', 'c'), $form->getData()); + $this->assertSame(array( + 0 => true, + 1 => false, + 2 => true, + 3 => false, + 4 => false, + ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); + $this->assertTrue($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertTrue($form[2]->getData()); @@ -393,6 +713,60 @@ public function testBindMultipleExpanded() $this->assertNull($form[4]->getViewData()); } + public function testBindMultipleExpandedInvalidScalarChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'expanded' => true, + 'choices' => $this->choices, + )); + + $form->bind('foobar'); + + $this->assertNull($form->getData()); + $this->assertSame('foobar', $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertFalse($form->isSynchronized()); + + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testBindMultipleExpandedInvalidArrayChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'expanded' => true, + 'choices' => $this->choices, + )); + + $form->bind(array('a', 'foobar')); + + $this->assertNull($form->getData()); + $this->assertSame(array('a', 'foobar'), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertFalse($form->isSynchronized()); + + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + public function testBindMultipleExpandedEmpty() { $form = $this->factory->create('choice', null, array( From 67a1be255434b64610a5dccac380b642c5664ca2 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Tue, 10 Sep 2013 12:41:39 +0200 Subject: [PATCH 180/447] [Form] Improved test coverage of ChoiceList classes --- .../ChoiceList/AbstractChoiceListTest.php | 297 ++++++++++++++++++ .../Core/ChoiceList/ChoiceListTest.php | 172 +++------- .../Core/ChoiceList/ObjectChoiceListTest.php | 64 ++-- .../Core/ChoiceList/SimpleChoiceListTest.php | 191 ++--------- .../SimpleNumericChoiceListTest.php | 78 +++++ 5 files changed, 486 insertions(+), 316 deletions(-) create mode 100644 Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php create mode 100644 Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php diff --git a/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php b/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php new file mode 100644 index 0000000000..0e2b6321cc --- /dev/null +++ b/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php @@ -0,0 +1,297 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; + +/** + * @author Bernhard Schussek + */ +abstract class AbstractChoiceListTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface + */ + protected $list; + + /** + * @var array + */ + protected $choices; + + /** + * @var array + */ + protected $values; + + /** + * @var array + */ + protected $indices; + + /** + * @var array + */ + protected $labels; + + /** + * @var mixed + */ + protected $choice1; + + /** + * @var mixed + */ + protected $choice2; + + /** + * @var mixed + */ + protected $choice3; + + /** + * @var mixed + */ + protected $choice4; + + /** + * @var string + */ + protected $value1; + + /** + * @var string + */ + protected $value2; + + /** + * @var string + */ + protected $value3; + + /** + * @var string + */ + protected $value4; + + /** + * @var int|string + */ + protected $index1; + + /** + * @var int|string + */ + protected $index2; + + /** + * @var int|string + */ + protected $index3; + + /** + * @var int|string + */ + protected $index4; + + /** + * @var string + */ + protected $label1; + + /** + * @var string + */ + protected $label2; + + /** + * @var string + */ + protected $label3; + + /** + * @var string + */ + protected $label4; + + protected function setUp() + { + parent::setUp(); + + $this->list = $this->createChoiceList(); + + $this->choices = $this->getChoices(); + $this->indices = $this->getIndices(); + $this->values = $this->getValues(); + $this->labels = $this->getLabels(); + + // allow access to the individual entries without relying on their indices + reset($this->choices); + reset($this->indices); + reset($this->values); + reset($this->labels); + + for ($i = 1; $i <= 4; ++$i) { + $this->{'choice'.$i} = current($this->choices); + $this->{'index'.$i} = current($this->indices); + $this->{'value'.$i} = current($this->values); + $this->{'label'.$i} = current($this->labels); + + next($this->choices); + next($this->indices); + next($this->values); + next($this->labels); + } + } + + public function testGetChoices() + { + $this->assertSame($this->choices, $this->list->getChoices()); + } + + public function testGetValues() + { + $this->assertSame($this->values, $this->list->getValues()); + } + + public function testGetIndicesForChoices() + { + $choices = array($this->choice1, $this->choice2); + $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesPreservesKeys() + { + $choices = array(5 => $this->choice1, 8 => $this->choice2); + $this->assertSame(array(5 => $this->index1, 8 => $this->index2), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesPreservesOrder() + { + $choices = array($this->choice2, $this->choice1); + $this->assertSame(array($this->index2, $this->index1), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesIgnoresNonExistingChoices() + { + $choices = array($this->choice1, $this->choice2, 'foobar'); + $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesEmpty() + { + $this->assertSame(array(), $this->list->getIndicesForChoices(array())); + } + + public function testGetIndicesForValues() + { + // values and indices are always the same + $values = array($this->value1, $this->value2); + $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForValues($values)); + } + + public function testGetIndicesForValuesPreservesKeys() + { + // values and indices are always the same + $values = array(5 => $this->value1, 8 => $this->value2); + $this->assertSame(array(5 => $this->index1, 8 => $this->index2), $this->list->getIndicesForValues($values)); + } + + public function testGetIndicesForValuesPreservesOrder() + { + $values = array($this->value2, $this->value1); + $this->assertSame(array($this->index2, $this->index1), $this->list->getIndicesForValues($values)); + } + + public function testGetIndicesForValuesIgnoresNonExistingValues() + { + $values = array($this->value1, $this->value2, 'foobar'); + $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForValues($values)); + } + + public function testGetIndicesForValuesEmpty() + { + $this->assertSame(array(), $this->list->getIndicesForValues(array())); + } + + public function testGetChoicesForValues() + { + $values = array($this->value1, $this->value2); + $this->assertSame(array($this->choice1, $this->choice2), $this->list->getChoicesForValues($values)); + } + + public function testGetChoicesForValuesPreservesKeys() + { + $values = array(5 => $this->value1, 8 => $this->value2); + $this->assertSame(array(5 => $this->choice1, 8 => $this->choice2), $this->list->getChoicesForValues($values)); + } + + public function testGetChoicesForValuesPreservesOrder() + { + $values = array($this->value2, $this->value1); + $this->assertSame(array($this->choice2, $this->choice1), $this->list->getChoicesForValues($values)); + } + + public function testGetChoicesForValuesIgnoresNonExistingValues() + { + $values = array($this->value1, $this->value2, 'foobar'); + $this->assertSame(array($this->choice1, $this->choice2), $this->list->getChoicesForValues($values)); + } + + // https://github.com/symfony/symfony/issues/3446 + public function testGetChoicesForValuesEmpty() + { + $this->assertSame(array(), $this->list->getChoicesForValues(array())); + } + + public function testGetValuesForChoices() + { + $choices = array($this->choice1, $this->choice2); + $this->assertSame(array($this->value1, $this->value2), $this->list->getValuesForChoices($choices)); + } + + + public function testGetValuesForChoicesPreservesKeys() + { + $choices = array(5 => $this->choice1, 8 => $this->choice2); + $this->assertSame(array(5 => $this->value1, 8 => $this->value2), $this->list->getValuesForChoices($choices)); + } + + + public function testGetValuesForChoicesPreservesOrder() + { + $choices = array($this->choice2, $this->choice1); + $this->assertSame(array($this->value2, $this->value1), $this->list->getValuesForChoices($choices)); + } + + public function testGetValuesForChoicesIgnoresNonExistingChoices() + { + $choices = array($this->choice1, $this->choice2, 'foobar'); + $this->assertSame(array($this->value1, $this->value2), $this->list->getValuesForChoices($choices)); + } + + public function testGetValuesForChoicesEmpty() + { + $this->assertSame(array(), $this->list->getValuesForChoices(array())); + } + + /** + * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface + */ + abstract protected function createChoiceList(); + + abstract protected function getChoices(); + + abstract protected function getLabels(); + + abstract protected function getValues(); + + abstract protected function getIndices(); +} diff --git a/Tests/Extension/Core/ChoiceList/ChoiceListTest.php b/Tests/Extension/Core/ChoiceList/ChoiceListTest.php index 531bb561b4..59f002d8cc 100644 --- a/Tests/Extension/Core/ChoiceList/ChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/ChoiceListTest.php @@ -14,7 +14,7 @@ use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList; use Symfony\Component\Form\Extension\Core\View\ChoiceView; -class ChoiceListTest extends \PHPUnit_Framework_TestCase +class ChoiceListTest extends AbstractChoiceListTest { private $obj1; @@ -24,39 +24,14 @@ class ChoiceListTest extends \PHPUnit_Framework_TestCase private $obj4; - private $list; - protected function setUp() { - parent::setUp(); - $this->obj1 = new \stdClass(); $this->obj2 = new \stdClass(); $this->obj3 = new \stdClass(); $this->obj4 = new \stdClass(); - $this->list = new ChoiceList( - array( - 'Group 1' => array($this->obj1, $this->obj2), - 'Group 2' => array($this->obj3, $this->obj4), - ), - array( - 'Group 1' => array('A', 'B'), - 'Group 2' => array('C', 'D'), - ), - array($this->obj2, $this->obj3) - ); - } - - protected function tearDown() - { - parent::tearDown(); - - $this->obj1 = null; - $this->obj2 = null; - $this->obj3 = null; - $this->obj4 = null; - $this->list = null; + parent::setUp(); } public function testInitArray() @@ -119,111 +94,10 @@ public function testInitNestedArray() ), $this->list->getRemainingViews()); } - public function testGetIndicesForChoices() - { - $choices = array($this->obj2, $this->obj3); - $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForChoicesPreservesKeys() - { - $choices = array(5 => $this->obj2, 8 => $this->obj3); - $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForChoicesPreservesOrder() - { - $choices = array($this->obj3, $this->obj2); - $this->assertSame(array(2, 1), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForChoicesIgnoresNonExistingChoices() - { - $choices = array($this->obj2, $this->obj3, 'foobar'); - $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForValues() - { - // values and indices are always the same - $values = array('1', '2'); - $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); - } - - public function testGetIndicesForValuesPreservesKeys() - { - // values and indices are always the same - $values = array(5 => '1', 8 => '2'); - $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForValues($values)); - } - - public function testGetIndicesForValuesPreservesOrder() - { - // values and indices are always the same - $values = array('2', '1'); - $this->assertSame(array(2, 1), $this->list->getIndicesForValues($values)); - } - - public function testGetIndicesForValuesIgnoresNonExistingValues() - { - $values = array('1', '2', '5'); - $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); - } - - public function testGetChoicesForValues() - { - $values = array('1', '2'); - $this->assertSame(array($this->obj2, $this->obj3), $this->list->getChoicesForValues($values)); - } - - public function testGetChoicesForValuesPreservesKeys() - { - $values = array(5 => '1', 8 => '2'); - $this->assertSame(array(5 => $this->obj2, 8 => $this->obj3), $this->list->getChoicesForValues($values)); - } - - public function testGetChoicesForValuesPreservesOrder() - { - $values = array('2', '1'); - $this->assertSame(array($this->obj3, $this->obj2), $this->list->getChoicesForValues($values)); - } - - public function testGetChoicesForValuesIgnoresNonExistingValues() - { - $values = array('1', '2', '5'); - $this->assertSame(array($this->obj2, $this->obj3), $this->list->getChoicesForValues($values)); - } - - public function testGetValuesForChoices() - { - $choices = array($this->obj2, $this->obj3); - $this->assertSame(array('1', '2'), $this->list->getValuesForChoices($choices)); - } - - - public function testGetValuesForChoicesPreservesKeys() - { - $choices = array(5 => $this->obj2, 8 => $this->obj3); - $this->assertSame(array(5 => '1', 8 => '2'), $this->list->getValuesForChoices($choices)); - } - - - public function testGetValuesForChoicesPreservesOrder() - { - $choices = array($this->obj3, $this->obj2); - $this->assertSame(array('2', '1'), $this->list->getValuesForChoices($choices)); - } - - public function testGetValuesForChoicesIgnoresNonExistingChoices() - { - $choices = array($this->obj2, $this->obj3, 'foobar'); - $this->assertSame(array('1', '2'), $this->list->getValuesForChoices($choices)); - } - /** * @expectedException \InvalidArgumentException */ - public function testNonMatchingLabels() + public function testInitWithInsufficientLabels() { $this->list = new ChoiceList( array($this->obj1, $this->obj2), @@ -231,7 +105,7 @@ public function testNonMatchingLabels() ); } - public function testLabelsContainingNull() + public function testInitWithLabelsContainingNull() { $this->list = new ChoiceList( array($this->obj1, $this->obj2), @@ -243,4 +117,42 @@ public function testLabelsContainingNull() $this->list->getRemainingViews() ); } + + /** + * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface + */ + protected function createChoiceList() + { + return new ChoiceList( + array( + 'Group 1' => array($this->obj1, $this->obj2), + 'Group 2' => array($this->obj3, $this->obj4), + ), + array( + 'Group 1' => array('A', 'B'), + 'Group 2' => array('C', 'D'), + ), + array($this->obj2, $this->obj3) + ); + } + + protected function getChoices() + { + return array(0 => $this->obj1, 1 => $this->obj2, 2 => $this->obj3, 3 => $this->obj4); + } + + protected function getLabels() + { + return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D'); + } + + protected function getValues() + { + return array(0 => '0', 1 => '1', 2 => '2', 3 => '3'); + } + + protected function getIndices() + { + return array(0, 1, 2, 3); + } } diff --git a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php index b7487377e6..752f39b6dc 100644 --- a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php @@ -29,7 +29,7 @@ public function __toString() } } -class ObjectChoiceListTest extends \PHPUnit_Framework_TestCase +class ObjectChoiceListTest extends AbstractChoiceListTest { private $obj1; @@ -39,39 +39,14 @@ class ObjectChoiceListTest extends \PHPUnit_Framework_TestCase private $obj4; - /** - * @var ObjectChoiceList - */ - private $list; - protected function setUp() { - parent::setUp(); - $this->obj1 = (object) array('name' => 'A'); $this->obj2 = (object) array('name' => 'B'); $this->obj3 = (object) array('name' => 'C'); $this->obj4 = (object) array('name' => 'D'); - $this->list = new ObjectChoiceList( - array( - 'Group 1' => array($this->obj1, $this->obj2), - 'Group 2' => array($this->obj3, $this->obj4), - ), - 'name', - array($this->obj2, $this->obj3) - ); - } - - protected function tearDown() - { - parent::tearDown(); - - $this->obj1 = null; - $this->obj2 = null; - $this->obj3 = null; - $this->obj4 = null; - $this->list = null; + parent::setUp(); } public function testInitArray() @@ -209,4 +184,39 @@ public function testInitArrayThrowsExceptionIfToStringNotFound() array($this->obj1, $this->obj2, $this->obj3, $this->obj4) ); } + + /** + * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface + */ + protected function createChoiceList() + { + return new ObjectChoiceList( + array( + 'Group 1' => array($this->obj1, $this->obj2), + 'Group 2' => array($this->obj3, $this->obj4), + ), + 'name', + array($this->obj2, $this->obj3) + ); + } + + protected function getChoices() + { + return array(0 => $this->obj1, 1 => $this->obj2, 2 => $this->obj3, 3 => $this->obj4); + } + + protected function getLabels() + { + return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D'); + } + + protected function getValues() + { + return array(0 => '0', 1 => '1', 2 => '2', 3 => '3'); + } + + protected function getIndices() + { + return array(0, 1, 2, 3); + } } diff --git a/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php b/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php index 85b0ed7485..838a8e0864 100644 --- a/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php @@ -11,43 +11,11 @@ namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; -use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; use Symfony\Component\Form\Extension\Core\View\ChoiceView; -class SimpleChoiceListTest extends \PHPUnit_Framework_TestCase +class SimpleChoiceListTest extends AbstractChoiceListTest { - private $list; - - private $numericList; - - protected function setUp() - { - parent::setUp(); - - $choices = array( - 'Group 1' => array('a' => 'A', 'b' => 'B'), - 'Group 2' => array('c' => 'C', 'd' => 'D'), - ); - $numericChoices = array( - 'Group 1' => array(0 => 'A', 1 => 'B'), - 'Group 2' => array(2 => 'C', 3 => 'D'), - ); - - $this->list = new SimpleChoiceList($choices, array('b', 'c')); - - // Use COPY_CHOICE strategy to test for the various associated problems - $this->numericList = new SimpleChoiceList($numericChoices, array(1, 2)); - } - - protected function tearDown() - { - parent::tearDown(); - - $this->list = null; - $this->numericList = null; - } - public function testInitArray() { $choices = array('a' => 'A', 'b' => 'B', 'c' => 'C'); @@ -73,131 +41,6 @@ public function testInitNestedArray() ), $this->list->getRemainingViews()); } - public function testGetIndicesForChoices() - { - $choices = array('b', 'c'); - $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForChoicesPreservesKeys() - { - $choices = array(5 => 'b', 8 => 'c'); - $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForChoicesPreservesOrder() - { - $choices = array('c', 'b'); - $this->assertSame(array(2, 1), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForChoicesIgnoresNonExistingChoices() - { - $choices = array('b', 'c', 'foobar'); - $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForChoicesDealsWithNumericChoices() - { - // Pass choices as strings although they are integers - $choices = array('0', '1'); - $this->assertSame(array(0, 1), $this->numericList->getIndicesForChoices($choices)); - } - - public function testGetIndicesForValues() - { - $values = array('b', 'c'); - $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); - } - - public function testGetIndicesForValuesPreservesKeys() - { - $values = array(5 => 'b', 8 => 'c'); - $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForValues($values)); - } - - public function testGetIndicesForValuesPreservesOrder() - { - $values = array('c', 'b'); - $this->assertSame(array(2, 1), $this->list->getIndicesForValues($values)); - } - - public function testGetIndicesForValuesIgnoresNonExistingValues() - { - $values = array('b', 'c', '100'); - $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); - } - - public function testGetIndicesForValuesDealsWithNumericValues() - { - // Pass values as strings although they are integers - $values = array('0', '1'); - $this->assertSame(array(0, 1), $this->numericList->getIndicesForValues($values)); - } - - public function testGetChoicesForValues() - { - $values = array('b', 'c'); - $this->assertSame(array('b', 'c'), $this->list->getChoicesForValues($values)); - } - - public function testGetChoicesForValuesPreservesKeys() - { - $values = array(5 => 'b', 8 => 'c'); - $this->assertSame(array(5 => 'b', 8 => 'c'), $this->list->getChoicesForValues($values)); - } - - public function testGetChoicesForValuesPreservesOrder() - { - $values = array('c', 'b'); - $this->assertSame(array('c', 'b'), $this->list->getChoicesForValues($values)); - } - - public function testGetChoicesForValuesIgnoresNonExistingValues() - { - $values = array('b', 'c', '100'); - $this->assertSame(array('b', 'c'), $this->list->getChoicesForValues($values)); - } - - public function testGetChoicesForValuesDealsWithNumericValues() - { - // Pass values as strings although they are integers - $values = array('0', '1'); - $this->assertSame(array(0, 1), $this->numericList->getChoicesForValues($values)); - } - - public function testGetValuesForChoices() - { - $choices = array('b', 'c'); - $this->assertSame(array('b', 'c'), $this->list->getValuesForChoices($choices)); - } - - public function testGetValuesForChoicesPreservesKeys() - { - $choices = array(5 => 'b', 8 => 'c'); - $this->assertSame(array(5 => 'b', 8 => 'c'), $this->list->getValuesForChoices($choices)); - } - - public function testGetValuesForChoicesPreservesOrder() - { - $choices = array('c', 'b'); - $this->assertSame(array('c', 'b'), $this->list->getValuesForChoices($choices)); - } - - public function testGetValuesForChoicesIgnoresNonExistingValues() - { - $choices = array('b', 'c', 'foobar'); - $this->assertSame(array('b', 'c'), $this->list->getValuesForChoices($choices)); - } - - public function testGetValuesForChoicesDealsWithNumericValues() - { - // Pass values as strings although they are integers - $values = array('0', '1'); - - $this->assertSame(array('0', '1'), $this->numericList->getValuesForChoices($values)); - } - /** * @dataProvider dirtyValuesProvider */ @@ -212,7 +55,6 @@ public function testGetValuesForChoicesDealsWithDirtyValues($choice, $value) 'foo10' => 'Foo 10', ); - // use COPY_CHOICE strategy to test the problems $this->list = new SimpleChoiceList($choices, array()); $this->assertSame(array($value), $this->list->getValuesForChoices(array($choice))); @@ -233,4 +75,35 @@ public function dirtyValuesProvider() array('foo10', 'foo10'), ); } + + /** + * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface + */ + protected function createChoiceList() + { + return new SimpleChoiceList(array( + 'Group 1' => array('a' => 'A', 'b' => 'B'), + 'Group 2' => array('c' => 'C', 'd' => 'D'), + ), array('b', 'c')); + } + + protected function getChoices() + { + return array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd'); + } + + protected function getLabels() + { + return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D'); + } + + protected function getValues() + { + return array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd'); + } + + protected function getIndices() + { + return array(0, 1, 2, 3); + } } diff --git a/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php b/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php new file mode 100644 index 0000000000..2b57288fb7 --- /dev/null +++ b/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; + +use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; +use Symfony\Component\Form\Extension\Core\View\ChoiceView; + +class SimpleNumericChoiceListTest extends AbstractChoiceListTest +{ + public function testGetIndicesForChoicesDealsWithNumericChoices() + { + // Pass choices as strings although they are integers + $choices = array('0', '1'); + $this->assertSame(array(0, 1), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForValuesDealsWithNumericValues() + { + // Pass values as strings although they are integers + $values = array('0', '1'); + $this->assertSame(array(0, 1), $this->list->getIndicesForValues($values)); + } + + public function testGetChoicesForValuesDealsWithNumericValues() + { + // Pass values as strings although they are integers + $values = array('0', '1'); + $this->assertSame(array(0, 1), $this->list->getChoicesForValues($values)); + } + + public function testGetValuesForChoicesDealsWithNumericValues() + { + // Pass values as strings although they are integers + $values = array('0', '1'); + + $this->assertSame(array('0', '1'), $this->list->getValuesForChoices($values)); + } + + /** + * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface + */ + protected function createChoiceList() + { + return new SimpleChoiceList(array( + 'Group 1' => array(0 => 'A', 1 => 'B'), + 'Group 2' => array(2 => 'C', 3 => 'D'), + ), array(1, 2)); + } + + protected function getChoices() + { + return array(0 => 0, 1 => 1, 2 => 2, 3 => 3); + } + + protected function getLabels() + { + return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D'); + } + + protected function getValues() + { + return array(0 => '0', 1 => '1', 2 => '2', 3 => '3'); + } + + protected function getIndices() + { + return array(0, 1, 2, 3); + } +} From 7ac7a11167c05b2a6fb7b97ecea47612ad477e1b Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Sun, 5 May 2013 23:28:39 +0200 Subject: [PATCH 181/447] [Form] Removed usage of the ChoiceList::getIndicesFor*() methods where they don't offer any performance benefit --- .../DataTransformer/ChoiceToBooleanArrayTransformer.php | 6 +++--- .../DataTransformer/ChoicesToBooleanArrayTransformer.php | 4 ++-- Extension/Core/Type/ChoiceType.php | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php b/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php index 79b3f7ac89..b521c95572 100644 --- a/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php +++ b/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php @@ -60,14 +60,14 @@ public function transform($choice) throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e); } - $index = current($this->choiceList->getIndicesForChoices(array($choice))); + $valueMap = array_flip($this->choiceList->getValuesForChoices(array($choice))); foreach ($values as $i => $value) { - $values[$i] = $i === $index; + $values[$i] = isset($valueMap[$value]); } if ($this->placeholderPresent) { - $values['placeholder'] = false === $index; + $values['placeholder'] = 0 === count($valueMap); } return $values; diff --git a/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php b/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php index a13c0d4d43..f1f13fda28 100644 --- a/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php +++ b/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php @@ -58,10 +58,10 @@ public function transform($array) throw new TransformationFailedException('Can not get the choice list', $e->getCode(), $e); } - $indexMap = array_flip($this->choiceList->getIndicesForChoices($array)); + $valueMap = array_flip($this->choiceList->getValuesForChoices($array)); foreach ($values as $i => $value) { - $values[$i] = isset($indexMap[$i]); + $values[$i] = isset($valueMap[$value]); } return $values; diff --git a/Extension/Core/Type/ChoiceType.php b/Extension/Core/Type/ChoiceType.php index 9a3fdef12b..d678a6854a 100644 --- a/Extension/Core/Type/ChoiceType.php +++ b/Extension/Core/Type/ChoiceType.php @@ -57,7 +57,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) // Check if the choices already contain the empty value // Only add the empty value option if this is not the case - if (null !== $options['empty_value'] && 0 === count($options['choice_list']->getIndicesForValues(array('')))) { + if (null !== $options['empty_value'] && 0 === count($options['choice_list']->getChoicesForValues(array('')))) { $placeholderView = new ChoiceView(null, '', $options['empty_value']); // "placeholder" is a reserved index @@ -120,7 +120,7 @@ public function buildView(FormView $view, FormInterface $form, array $options) // Check if the choices already contain the empty value // Only add the empty value option if this is not the case - if (null !== $options['empty_value'] && 0 === count($options['choice_list']->getIndicesForValues(array('')))) { + if (null !== $options['empty_value'] && 0 === count($options['choice_list']->getChoicesForValues(array('')))) { $view->vars['empty_value'] = $options['empty_value']; } From 5c1e6f3fb919a742eb5b4bd3c6679f0e9668f50a Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Sun, 5 May 2013 23:50:06 +0200 Subject: [PATCH 182/447] [Form] Fixed ChoiceList::get*By*() methods to preserve order and array keys --- Extension/Core/ChoiceList/ChoiceList.php | 32 ++++++------- .../Core/ChoiceList/ChoiceListInterface.php | 12 +++++ .../Core/ChoiceList/ChoiceListTest.php | 48 ++++++++++++++++++- .../Core/ChoiceList/SimpleChoiceListTest.php | 48 +++++++++++++++++++ 4 files changed, 123 insertions(+), 17 deletions(-) diff --git a/Extension/Core/ChoiceList/ChoiceList.php b/Extension/Core/ChoiceList/ChoiceList.php index f9d381cd04..17ae0a3d9e 100644 --- a/Extension/Core/ChoiceList/ChoiceList.php +++ b/Extension/Core/ChoiceList/ChoiceList.php @@ -156,11 +156,11 @@ public function getChoicesForValues(array $values) $values = $this->fixValues($values); $choices = array(); - foreach ($values as $j => $givenValue) { - foreach ($this->values as $i => $value) { + foreach ($values as $i => $givenValue) { + foreach ($this->values as $j => $value) { if ($value === $givenValue) { - $choices[] = $this->choices[$i]; - unset($values[$j]); + $choices[$i] = $this->choices[$j]; + unset($values[$i]); if (0 === count($values)) { break 2; @@ -180,11 +180,11 @@ public function getValuesForChoices(array $choices) $choices = $this->fixChoices($choices); $values = array(); - foreach ($this->choices as $i => $choice) { - foreach ($choices as $j => $givenChoice) { + foreach ($choices as $i => $givenChoice) { + foreach ($this->choices as $j => $choice) { if ($choice === $givenChoice) { - $values[] = $this->values[$i]; - unset($choices[$j]); + $values[$i] = $this->values[$j]; + unset($choices[$i]); if (0 === count($choices)) { break 2; @@ -204,11 +204,11 @@ public function getIndicesForChoices(array $choices) $choices = $this->fixChoices($choices); $indices = array(); - foreach ($this->choices as $i => $choice) { - foreach ($choices as $j => $givenChoice) { + foreach ($choices as $i => $givenChoice) { + foreach ($this->choices as $j => $choice) { if ($choice === $givenChoice) { - $indices[] = $i; - unset($choices[$j]); + $indices[$i] = $j; + unset($choices[$i]); if (0 === count($choices)) { break 2; @@ -228,11 +228,11 @@ public function getIndicesForValues(array $values) $values = $this->fixValues($values); $indices = array(); - foreach ($this->values as $i => $value) { - foreach ($values as $j => $givenValue) { + foreach ($values as $i => $givenValue) { + foreach ($this->values as $j => $value) { if ($value === $givenValue) { - $indices[] = $i; - unset($values[$j]); + $indices[$i] = $j; + unset($values[$i]); if (0 === count($values)) { break 2; diff --git a/Extension/Core/ChoiceList/ChoiceListInterface.php b/Extension/Core/ChoiceList/ChoiceListInterface.php index 099ace8253..febf80ef05 100644 --- a/Extension/Core/ChoiceList/ChoiceListInterface.php +++ b/Extension/Core/ChoiceList/ChoiceListInterface.php @@ -97,6 +97,9 @@ public function getRemainingViews(); * * The choices can have any data type. * + * The choices must be returned with the same keys and in the same order + * as the corresponding values in the given array. + * * @param array $values An array of choice values. Not existing values in * this array are ignored * @@ -109,6 +112,9 @@ public function getChoicesForValues(array $values); * * The values must be strings. * + * The values must be returned with the same keys and in the same order + * as the corresponding choices in the given array. + * * @param array $choices An array of choices. Not existing choices in this * array are ignored * @@ -125,6 +131,9 @@ public function getValuesForChoices(array $choices); * * The index "placeholder" is internally reserved. * + * The indices must be returned with the same keys and in the same order + * as the corresponding choices in the given array. + * * @param array $choices An array of choices. Not existing choices in this * array are ignored * @@ -140,6 +149,9 @@ public function getIndicesForChoices(array $choices); * * The index "placeholder" is internally reserved. * + * The indices must be returned with the same keys and in the same order + * as the corresponding values in the given array. + * * @param array $values An array of choice values. Not existing values in * this array are ignored * diff --git a/Tests/Extension/Core/ChoiceList/ChoiceListTest.php b/Tests/Extension/Core/ChoiceList/ChoiceListTest.php index 63eae9bf7f..531bb561b4 100644 --- a/Tests/Extension/Core/ChoiceList/ChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/ChoiceListTest.php @@ -125,6 +125,18 @@ public function testGetIndicesForChoices() $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); } + public function testGetIndicesForChoicesPreservesKeys() + { + $choices = array(5 => $this->obj2, 8 => $this->obj3); + $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesPreservesOrder() + { + $choices = array($this->obj3, $this->obj2); + $this->assertSame(array(2, 1), $this->list->getIndicesForChoices($choices)); + } + public function testGetIndicesForChoicesIgnoresNonExistingChoices() { $choices = array($this->obj2, $this->obj3, 'foobar'); @@ -138,6 +150,20 @@ public function testGetIndicesForValues() $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); } + public function testGetIndicesForValuesPreservesKeys() + { + // values and indices are always the same + $values = array(5 => '1', 8 => '2'); + $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForValues($values)); + } + + public function testGetIndicesForValuesPreservesOrder() + { + // values and indices are always the same + $values = array('2', '1'); + $this->assertSame(array(2, 1), $this->list->getIndicesForValues($values)); + } + public function testGetIndicesForValuesIgnoresNonExistingValues() { $values = array('1', '2', '5'); @@ -150,7 +176,13 @@ public function testGetChoicesForValues() $this->assertSame(array($this->obj2, $this->obj3), $this->list->getChoicesForValues($values)); } - public function testGetChoicesForValuesCorrectOrderingOfResult() + public function testGetChoicesForValuesPreservesKeys() + { + $values = array(5 => '1', 8 => '2'); + $this->assertSame(array(5 => $this->obj2, 8 => $this->obj3), $this->list->getChoicesForValues($values)); + } + + public function testGetChoicesForValuesPreservesOrder() { $values = array('2', '1'); $this->assertSame(array($this->obj3, $this->obj2), $this->list->getChoicesForValues($values)); @@ -168,6 +200,20 @@ public function testGetValuesForChoices() $this->assertSame(array('1', '2'), $this->list->getValuesForChoices($choices)); } + + public function testGetValuesForChoicesPreservesKeys() + { + $choices = array(5 => $this->obj2, 8 => $this->obj3); + $this->assertSame(array(5 => '1', 8 => '2'), $this->list->getValuesForChoices($choices)); + } + + + public function testGetValuesForChoicesPreservesOrder() + { + $choices = array($this->obj3, $this->obj2); + $this->assertSame(array('2', '1'), $this->list->getValuesForChoices($choices)); + } + public function testGetValuesForChoicesIgnoresNonExistingChoices() { $choices = array($this->obj2, $this->obj3, 'foobar'); diff --git a/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php b/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php index 69d27a18fd..85b0ed7485 100644 --- a/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php @@ -79,6 +79,18 @@ public function testGetIndicesForChoices() $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); } + public function testGetIndicesForChoicesPreservesKeys() + { + $choices = array(5 => 'b', 8 => 'c'); + $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesPreservesOrder() + { + $choices = array('c', 'b'); + $this->assertSame(array(2, 1), $this->list->getIndicesForChoices($choices)); + } + public function testGetIndicesForChoicesIgnoresNonExistingChoices() { $choices = array('b', 'c', 'foobar'); @@ -98,6 +110,18 @@ public function testGetIndicesForValues() $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); } + public function testGetIndicesForValuesPreservesKeys() + { + $values = array(5 => 'b', 8 => 'c'); + $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForValues($values)); + } + + public function testGetIndicesForValuesPreservesOrder() + { + $values = array('c', 'b'); + $this->assertSame(array(2, 1), $this->list->getIndicesForValues($values)); + } + public function testGetIndicesForValuesIgnoresNonExistingValues() { $values = array('b', 'c', '100'); @@ -117,6 +141,18 @@ public function testGetChoicesForValues() $this->assertSame(array('b', 'c'), $this->list->getChoicesForValues($values)); } + public function testGetChoicesForValuesPreservesKeys() + { + $values = array(5 => 'b', 8 => 'c'); + $this->assertSame(array(5 => 'b', 8 => 'c'), $this->list->getChoicesForValues($values)); + } + + public function testGetChoicesForValuesPreservesOrder() + { + $values = array('c', 'b'); + $this->assertSame(array('c', 'b'), $this->list->getChoicesForValues($values)); + } + public function testGetChoicesForValuesIgnoresNonExistingValues() { $values = array('b', 'c', '100'); @@ -136,6 +172,18 @@ public function testGetValuesForChoices() $this->assertSame(array('b', 'c'), $this->list->getValuesForChoices($choices)); } + public function testGetValuesForChoicesPreservesKeys() + { + $choices = array(5 => 'b', 8 => 'c'); + $this->assertSame(array(5 => 'b', 8 => 'c'), $this->list->getValuesForChoices($choices)); + } + + public function testGetValuesForChoicesPreservesOrder() + { + $choices = array('c', 'b'); + $this->assertSame(array('c', 'b'), $this->list->getValuesForChoices($choices)); + } + public function testGetValuesForChoicesIgnoresNonExistingValues() { $choices = array('b', 'c', 'foobar'); From 8a0c341e7df23467534c24762904171fef67635b Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Mon, 6 May 2013 00:28:29 +0200 Subject: [PATCH 183/447] [Form] Fixed expanded choice field to be marked invalid when unknown choices are submitted --- .../BooleanToStringTransformer.php | 6 +- .../FixCheckboxInputListener.php | 40 ++- .../EventListener/FixRadioInputListener.php | 18 +- Extension/Core/Type/CheckboxType.php | 15 +- Form.php | 149 ++++----- .../BooleanToStringTransformerTest.php | 24 +- .../Extension/Core/Type/CheckboxTypeTest.php | 39 ++- Tests/Extension/Core/Type/ChoiceTypeTest.php | 301 +++++++++++++++++- 8 files changed, 476 insertions(+), 116 deletions(-) diff --git a/Extension/Core/DataTransformer/BooleanToStringTransformer.php b/Extension/Core/DataTransformer/BooleanToStringTransformer.php index 95e7332d3e..f8e3b5bfcb 100644 --- a/Extension/Core/DataTransformer/BooleanToStringTransformer.php +++ b/Extension/Core/DataTransformer/BooleanToStringTransformer.php @@ -49,15 +49,11 @@ public function __construct($trueValue) */ public function transform($value) { - if (null === $value) { - return null; - } - if (!is_bool($value)) { throw new TransformationFailedException('Expected a Boolean.'); } - return true === $value ? $this->trueValue : null; + return $value ? $this->trueValue : null; } /** diff --git a/Extension/Core/EventListener/FixCheckboxInputListener.php b/Extension/Core/EventListener/FixCheckboxInputListener.php index 1f62e060ff..8e72b04137 100644 --- a/Extension/Core/EventListener/FixCheckboxInputListener.php +++ b/Extension/Core/EventListener/FixCheckboxInputListener.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Extension\Core\EventListener; +use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -38,10 +39,43 @@ public function __construct(ChoiceListInterface $choiceList) public function preSubmit(FormEvent $event) { - $values = (array) $event->getData(); - $indices = $this->choiceList->getIndicesForValues($values); + $data = $event->getData(); - $event->setData(count($indices) > 0 ? array_combine($indices, $values) : array()); + if (is_array($data)) { + // Flip the submitted values for faster lookup + // It's better to flip this array than $existingValues because + // $submittedValues is generally smaller. + $submittedValues = array_flip($data); + + // Since expanded choice fields are completely loaded anyway, we + // can just as well get the values again without losing performance. + $existingValues = $this->choiceList->getValues(); + + // Clear the data array and fill it with correct indices + $data = array(); + + foreach ($existingValues as $index => $value) { + if (isset($submittedValues[$value])) { + // Value was submitted + $data[$index] = $value; + unset($submittedValues[$value]); + } + } + + if (count($submittedValues) > 0) { + throw new TransformationFailedException(sprintf( + 'The following choices were not found: "%s"', + implode('", "', array_keys($submittedValues)) + )); + } + } elseif ('' === $data || null === $data) { + // Empty values are always accepted. + $data = array(); + } + + // Else leave the data unchanged to provoke an error during submission + + $event->setData($data); } /** diff --git a/Extension/Core/EventListener/FixRadioInputListener.php b/Extension/Core/EventListener/FixRadioInputListener.php index bf03792fed..925585db40 100644 --- a/Extension/Core/EventListener/FixRadioInputListener.php +++ b/Extension/Core/EventListener/FixRadioInputListener.php @@ -42,10 +42,22 @@ public function __construct(ChoiceListInterface $choiceList, $placeholderPresent public function preSubmit(FormEvent $event) { - $value = $event->getData(); - $index = current($this->choiceList->getIndicesForValues(array($value))); + $data = $event->getData(); - $event->setData(false !== $index ? array($index => $value) : ($this->placeholderPresent ? array('placeholder' => '') : array())) ; + // Since expanded choice fields are completely loaded anyway, we + // can just as well get the values again without losing performance. + $existingValues = $this->choiceList->getValues(); + + if (false !== ($index = array_search($data, $existingValues, true))) { + $data = array($index => $data); + } elseif ('' === $data || null === $data) { + // Empty values are always accepted. + $data = $this->placeholderPresent ? array('placeholder' => '') : array(); + } + + // Else leave the data unchanged to provoke an error during submission + + $event->setData($data); } /** diff --git a/Extension/Core/Type/CheckboxType.php b/Extension/Core/Type/CheckboxType.php index 214e581aff..3952bb3316 100644 --- a/Extension/Core/Type/CheckboxType.php +++ b/Extension/Core/Type/CheckboxType.php @@ -25,9 +25,14 @@ class CheckboxType extends AbstractType */ public function buildForm(FormBuilderInterface $builder, array $options) { - $builder - ->addViewTransformer(new BooleanToStringTransformer($options['value'])) - ; + // Unlike in other types, where the data is NULL by default, it + // needs to be a Boolean here. setData(null) is not acceptable + // for checkboxes and radio buttons (unless a custom model + // transformer handles this case). + // We cannot solve this case via overriding the "data" option, because + // doing so also calls setDataLocked(true). + $builder->setData(isset($options['data']) ? $options['data'] : false); + $builder->addViewTransformer(new BooleanToStringTransformer($options['value'])); } /** @@ -46,8 +51,8 @@ public function buildView(FormView $view, FormInterface $form, array $options) */ public function setDefaultOptions(OptionsResolverInterface $resolver) { - $emptyData = function (FormInterface $form, $clientData) { - return $clientData; + $emptyData = function (FormInterface $form, $viewData) { + return $viewData; }; $resolver->setDefaults(array( diff --git a/Form.php b/Form.php index 5399cc99cc..f3324986c8 100644 --- a/Form.php +++ b/Form.php @@ -522,83 +522,82 @@ public function submit($submittedData, $clearMissing = true) $dispatcher = $this->config->getEventDispatcher(); - // Hook to change content of the data submitted by the browser - if ($dispatcher->hasListeners(FormEvents::PRE_SUBMIT)) { - $event = new FormEvent($this, $submittedData); - $dispatcher->dispatch(FormEvents::PRE_SUBMIT, $event); - $submittedData = $event->getData(); - } + $modelData = null; + $normData = null; + $viewData = null; - // Check whether the form is compound. - // This check is preferable over checking the number of children, - // since forms without children may also be compound. - // (think of empty collection forms) - if ($this->config->getCompound()) { - if (!is_array($submittedData)) { - $submittedData = array(); + try { + // Hook to change content of the data submitted by the browser + if ($dispatcher->hasListeners(FormEvents::PRE_SUBMIT)) { + $event = new FormEvent($this, $submittedData); + $dispatcher->dispatch(FormEvents::PRE_SUBMIT, $event); + $submittedData = $event->getData(); } - foreach ($this->children as $name => $child) { - if (array_key_exists($name, $submittedData) || $clearMissing) { - $child->submit(isset($submittedData[$name]) ? $submittedData[$name] : null, $clearMissing); - unset($submittedData[$name]); + // Check whether the form is compound. + // This check is preferable over checking the number of children, + // since forms without children may also be compound. + // (think of empty collection forms) + if ($this->config->getCompound()) { + if (null === $submittedData) { + $submittedData = array(); } - } - - $this->extraData = $submittedData; - } - // Forms that inherit their parents' data also are not processed, - // because then it would be too difficult to merge the changes in - // the child and the parent form. Instead, the parent form also takes - // changes in the grandchildren (i.e. children of the form that inherits - // its parent's data) into account. - // (see InheritDataAwareIterator below) - if ($this->config->getInheritData()) { - $this->submitted = true; + if (!is_array($submittedData)) { + throw new TransformationFailedException('Compound forms expect an array or NULL on submission.'); + } - // When POST_SUBMIT is reached, the data is not yet updated, so pass - // NULL to prevent hard-to-debug bugs. - $dataForPostSubmit = null; - } else { - // If the form is compound, the default data in view format - // is reused. The data of the children is merged into this - // default data using the data mapper. - // If the form is not compound, the submitted data is also the data in view format. - $viewData = $this->config->getCompound() ? $this->viewData : $submittedData; - - if (FormUtil::isEmpty($viewData)) { - $emptyData = $this->config->getEmptyData(); - - if ($emptyData instanceof \Closure) { - /* @var \Closure $emptyData */ - $emptyData = $emptyData($this, $viewData); + foreach ($this->children as $name => $child) { + if (isset($submittedData[$name]) || $clearMissing) { + $child->submit(isset($submittedData[$name]) ? $submittedData[$name] : null, $clearMissing); + unset($submittedData[$name]); + } } - $viewData = $emptyData; + $this->extraData = $submittedData; } - // Merge form data from children into existing view data - // It is not necessary to invoke this method if the form has no children, - // even if it is compound. - if (count($this->children) > 0) { - // Use InheritDataAwareIterator to process children of - // descendants that inherit this form's data. - // These descendants will not be submitted normally (see the check - // for $this->config->getInheritData() above) - $iterator = new InheritDataAwareIterator($this->children); - $iterator = new \RecursiveIteratorIterator($iterator); - $this->config->getDataMapper()->mapFormsToData($iterator, $viewData); - } + // Forms that inherit their parents' data also are not processed, + // because then it would be too difficult to merge the changes in + // the child and the parent form. Instead, the parent form also takes + // changes in the grandchildren (i.e. children of the form that inherits + // its parent's data) into account. + // (see InheritDataAwareIterator below) + if (!$this->config->getInheritData()) { + // If the form is compound, the default data in view format + // is reused. The data of the children is merged into this + // default data using the data mapper. + // If the form is not compound, the submitted data is also the data in view format. + $viewData = $this->config->getCompound() ? $this->viewData : $submittedData; + + if (FormUtil::isEmpty($viewData)) { + $emptyData = $this->config->getEmptyData(); + + if ($emptyData instanceof \Closure) { + /* @var \Closure $emptyData */ + $emptyData = $emptyData($this, $viewData); + } + + $viewData = $emptyData; + } - $modelData = null; - $normData = null; + // Merge form data from children into existing view data + // It is not necessary to invoke this method if the form has no children, + // even if it is compound. + if (count($this->children) > 0) { + // Use InheritDataAwareIterator to process children of + // descendants that inherit this form's data. + // These descendants will not be submitted normally (see the check + // for $this->config->getInheritData() above) + $childrenIterator = new InheritDataAwareIterator($this->children); + $childrenIterator = new \RecursiveIteratorIterator($childrenIterator); + $this->config->getDataMapper()->mapFormsToData($childrenIterator, $viewData); + } - try { // Normalize data to unified representation $normData = $this->viewToNorm($viewData); - // Hook to change content of the data into the normalized + // Hook to change content of the data in the normalized // representation if ($dispatcher->hasListeners(FormEvents::SUBMIT)) { $event = new FormEvent($this, $normData); @@ -609,20 +608,26 @@ public function submit($submittedData, $clearMissing = true) // Synchronize representations - must not change the content! $modelData = $this->normToModel($normData); $viewData = $this->normToView($normData); - } catch (TransformationFailedException $e) { - $this->synchronized = false; } - - $this->submitted = true; - $this->modelData = $modelData; - $this->normData = $normData; - $this->viewData = $viewData; - - $dataForPostSubmit = $viewData; + } catch (TransformationFailedException $e) { + $this->synchronized = false; + + // If $viewData was not yet set, set it to $submittedData so that + // the erroneous data is accessible on the form. + // Forms that inherit data never set any data, because the getters + // forward to the parent form's getters anyway. + if (null === $viewData && !$this->config->getInheritData()) { + $viewData = $submittedData; + } } + $this->submitted = true; + $this->modelData = $modelData; + $this->normData = $normData; + $this->viewData = $viewData; + if ($dispatcher->hasListeners(FormEvents::POST_SUBMIT)) { - $event = new FormEvent($this, $dataForPostSubmit); + $event = new FormEvent($this, $viewData); $dispatcher->dispatch(FormEvents::POST_SUBMIT, $event); } diff --git a/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php index 41f8f956d7..4f6238aee0 100644 --- a/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php @@ -17,6 +17,9 @@ class BooleanToStringTransformerTest extends \PHPUnit_Framework_TestCase { const TRUE_VALUE = '1'; + /** + * @var BooleanToStringTransformer + */ protected $transformer; protected function setUp() @@ -33,20 +36,29 @@ public function testTransform() { $this->assertEquals(self::TRUE_VALUE, $this->transformer->transform(true)); $this->assertNull($this->transformer->transform(false)); - $this->assertNull($this->transformer->transform(null)); } - public function testTransformExpectsBoolean() + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testTransformFailsIfNull() { - $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); + $this->transformer->transform(null); + } + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testTransformFailsIfString() + { $this->transformer->transform('1'); } - public function testReverseTransformExpectsString() + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformFailsIfInteger() { - $this->setExpectedException('Symfony\Component\Form\Exception\TransformationFailedException'); - $this->transformer->reverseTransform(1); } diff --git a/Tests/Extension/Core/Type/CheckboxTypeTest.php b/Tests/Extension/Core/Type/CheckboxTypeTest.php index c782adab04..9437bd7eea 100644 --- a/Tests/Extension/Core/Type/CheckboxTypeTest.php +++ b/Tests/Extension/Core/Type/CheckboxTypeTest.php @@ -15,6 +15,15 @@ class CheckboxTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { + public function testDataIsFalseByDefault() + { + $form = $this->factory->create('checkbox'); + + $this->assertFalse($form->getData()); + $this->assertFalse($form->getNormData()); + $this->assertNull($form->getViewData()); + } + public function testPassValueToView() { $form = $this->factory->create('checkbox', null, array('value' => 'foobar')); @@ -105,58 +114,60 @@ public function testSubmitWithEmptyValueUnchecked() $this->assertNull($form->getViewData()); } - public function testBindWithEmptyValueAndFalseUnchecked() + public function testSubmitWithEmptyValueAndFalseUnchecked() { $form = $this->factory->create('checkbox', null, array( 'value' => '', )); - $form->bind(false); + $form->submit(false); $this->assertFalse($form->getData()); $this->assertNull($form->getViewData()); } - public function testBindWithEmptyValueAndTrueChecked() + public function testSubmitWithEmptyValueAndTrueChecked() { $form = $this->factory->create('checkbox', null, array( 'value' => '', )); - $form->bind(true); + $form->submit(true); $this->assertTrue($form->getData()); $this->assertSame('', $form->getViewData()); } /** - * @dataProvider provideTransformedData + * @dataProvider provideCustomModelTransformerData */ - public function testTransformedData($data, $expected) + public function testCustomModelTransformer($data, $checked) { // present a binary status field as a checkbox $transformer = new CallbackTransformer( function ($value) { - return 'expedited' == $value; + return 'checked' == $value; }, function ($value) { - return $value ? 'expedited' : 'standard'; + return $value ? 'checked' : 'unchecked'; } ); - $form = $this->builder - ->create('expedited_shipping', 'checkbox') + $form = $this->factory->createBuilder('checkbox') ->addModelTransformer($transformer) ->getForm(); + $form->setData($data); $view = $form->createView(); - $this->assertEquals($expected, $view->vars['checked']); + $this->assertSame($data, $form->getData()); + $this->assertSame($checked, $form->getNormData()); + $this->assertEquals($checked, $view->vars['checked']); } - public function provideTransformedData() + public function provideCustomModelTransformerData() { return array( - array('expedited', true), - array('standard', false), + array('checked', true), + array('unchecked', false), ); } } diff --git a/Tests/Extension/Core/Type/ChoiceTypeTest.php b/Tests/Extension/Core/Type/ChoiceTypeTest.php index 219e8181c0..ee40e74268 100644 --- a/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -231,6 +231,21 @@ public function testSubmitSingleNonExpanded() $this->assertEquals('b', $form->getViewData()); } + public function testSubmitSingleNonExpandedInvalidChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => false, + 'choices' => $this->choices, + )); + + $form->submit('foobar'); + + $this->assertNull($form->getData()); + $this->assertEquals('foobar', $form->getViewData()); + $this->assertFalse($form->isSynchronized()); + } + public function testSubmitSingleNonExpandedObjectChoices() { $form = $this->factory->create('choice', null, array( @@ -268,6 +283,36 @@ public function testSubmitMultipleNonExpanded() $this->assertEquals(array('a', 'b'), $form->getViewData()); } + public function testSubmitMultipleNonExpandedInvalidScalarChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'expanded' => false, + 'choices' => $this->choices, + )); + + $form->submit('foobar'); + + $this->assertNull($form->getData()); + $this->assertEquals('foobar', $form->getViewData()); + $this->assertFalse($form->isSynchronized()); + } + + public function testSubmitMultipleNonExpandedInvalidArrayChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'expanded' => false, + 'choices' => $this->choices, + )); + + $form->submit(array('a', 'foobar')); + + $this->assertNull($form->getData()); + $this->assertEquals(array('a', 'foobar'), $form->getViewData()); + $this->assertFalse($form->isSynchronized()); + } + public function testSubmitMultipleNonExpandedObjectChoices() { $form = $this->factory->create('choice', null, array( @@ -309,6 +354,8 @@ public function testSubmitSingleExpandedRequired() 3 => false, 4 => false, ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); $this->assertFalse($form[0]->getData()); $this->assertTrue($form[1]->getData()); @@ -322,6 +369,34 @@ public function testSubmitSingleExpandedRequired() $this->assertNull($form[4]->getViewData()); } + public function testSubmitSingleExpandedRequiredInvalidChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => true, + 'choices' => $this->choices, + )); + + $form->submit('foobar'); + + $this->assertSame(null, $form->getData()); + $this->assertSame('foobar', $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertFalse($form->isSynchronized()); + + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + public function testSubmitSingleExpandedNonRequired() { $form = $this->factory->create('choice', null, array( @@ -342,6 +417,8 @@ public function testSubmitSingleExpandedNonRequired() 4 => false, 'placeholder' => false, ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); $this->assertFalse($form['placeholder']->getData()); $this->assertFalse($form[0]->getData()); @@ -357,7 +434,35 @@ public function testSubmitSingleExpandedNonRequired() $this->assertNull($form[4]->getViewData()); } - public function testSubmitSingleExpandedRequiredNothingChecked() + public function testSubmitSingleExpandedNonRequiredInvalidChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => false, + 'choices' => $this->choices, + )); + + $form->submit('foobar'); + + $this->assertSame(null, $form->getData()); + $this->assertSame('foobar', $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertFalse($form->isSynchronized()); + + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testSubmitSingleExpandedRequiredNull() { $form = $this->factory->create('choice', null, array( 'multiple' => false, @@ -376,6 +481,76 @@ public function testSubmitSingleExpandedRequiredNothingChecked() 3 => false, 4 => false, ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); + + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testSubmitSingleExpandedRequiredEmpty() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => true, + 'choices' => $this->choices, + )); + + $form->submit(''); + + $this->assertNull($form->getData()); + $this->assertSame(array( + 0 => false, + 1 => false, + 2 => false, + 3 => false, + 4 => false, + ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); + + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testSubmitSingleExpandedRequiredFalse() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => false, + 'expanded' => true, + 'required' => true, + 'choices' => $this->choices, + )); + + $form->submit(false); + + $this->assertNull($form->getData()); + $this->assertSame(array( + 0 => false, + 1 => false, + 2 => false, + 3 => false, + 4 => false, + ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); $this->assertFalse($form[0]->getData()); $this->assertFalse($form[1]->getData()); @@ -389,7 +564,7 @@ public function testSubmitSingleExpandedRequiredNothingChecked() $this->assertNull($form[4]->getViewData()); } - public function testSubmitSingleExpandedNonRequiredNothingChecked() + public function testSubmitSingleExpandedNonRequiredNull() { $form = $this->factory->create('choice', null, array( 'multiple' => false, @@ -409,6 +584,8 @@ public function testSubmitSingleExpandedNonRequiredNothingChecked() 4 => false, 'placeholder' => true, ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); $this->assertTrue($form['placeholder']->getData()); $this->assertFalse($form[0]->getData()); @@ -424,22 +601,44 @@ public function testSubmitSingleExpandedNonRequiredNothingChecked() $this->assertNull($form[4]->getViewData()); } - public function testSubmitFalseToSingleExpandedRequiredDoesNotProduceExtraChildrenError() + public function testSubmitSingleExpandedNonRequiredEmpty() { $form = $this->factory->create('choice', null, array( 'multiple' => false, 'expanded' => true, - 'required' => true, + 'required' => false, 'choices' => $this->choices, )); - $form->submit(false); + $form->submit(''); - $this->assertEmpty($form->getExtraData()); $this->assertNull($form->getData()); + $this->assertSame(array( + 0 => false, + 1 => false, + 2 => false, + 3 => false, + 4 => false, + 'placeholder' => true, + ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); + + $this->assertTrue($form['placeholder']->getData()); + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertSame('', $form['placeholder']->getViewData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); } - public function testSubmitFalseToSingleExpandedNonRequiredDoesNotProduceExtraChildrenError() + public function testSubmitSingleExpandedNonRequiredFalse() { $form = $this->factory->create('choice', null, array( 'multiple' => false, @@ -450,8 +649,30 @@ public function testSubmitFalseToSingleExpandedNonRequiredDoesNotProduceExtraChi $form->submit(false); - $this->assertEmpty($form->getExtraData()); $this->assertNull($form->getData()); + $this->assertSame(array( + 0 => false, + 1 => false, + 2 => false, + 3 => false, + 4 => false, + 'placeholder' => true, + ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); + + $this->assertTrue($form['placeholder']->getData()); + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertSame('', $form['placeholder']->getViewData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); } public function testSubmitSingleExpandedWithEmptyChild() @@ -539,6 +760,16 @@ public function testSubmitMultipleExpanded() $form->submit(array('a', 'c')); $this->assertSame(array('a', 'c'), $form->getData()); + $this->assertSame(array( + 0 => true, + 1 => false, + 2 => true, + 3 => false, + 4 => false, + ), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertTrue($form->isSynchronized()); + $this->assertTrue($form[0]->getData()); $this->assertFalse($form[1]->getData()); $this->assertTrue($form[2]->getData()); @@ -551,6 +782,60 @@ public function testSubmitMultipleExpanded() $this->assertNull($form[4]->getViewData()); } + public function testSubmitMultipleExpandedInvalidScalarChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'expanded' => true, + 'choices' => $this->choices, + )); + + $form->submit('foobar'); + + $this->assertNull($form->getData()); + $this->assertSame('foobar', $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertFalse($form->isSynchronized()); + + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + + public function testSubmitMultipleExpandedInvalidArrayChoice() + { + $form = $this->factory->create('choice', null, array( + 'multiple' => true, + 'expanded' => true, + 'choices' => $this->choices, + )); + + $form->submit(array('a', 'foobar')); + + $this->assertNull($form->getData()); + $this->assertSame(array('a', 'foobar'), $form->getViewData()); + $this->assertEmpty($form->getExtraData()); + $this->assertFalse($form->isSynchronized()); + + $this->assertFalse($form[0]->getData()); + $this->assertFalse($form[1]->getData()); + $this->assertFalse($form[2]->getData()); + $this->assertFalse($form[3]->getData()); + $this->assertFalse($form[4]->getData()); + $this->assertNull($form[0]->getViewData()); + $this->assertNull($form[1]->getViewData()); + $this->assertNull($form[2]->getViewData()); + $this->assertNull($form[3]->getViewData()); + $this->assertNull($form[4]->getViewData()); + } + public function testSubmitMultipleExpandedEmpty() { $form = $this->factory->create('choice', null, array( From 088c3d38b45566017c627e6021316f7c2d8be694 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Tue, 10 Sep 2013 12:41:39 +0200 Subject: [PATCH 184/447] [Form] Improved test coverage of ChoiceList classes --- .../ChoiceList/AbstractChoiceListTest.php | 297 ++++++++++++++++++ .../Core/ChoiceList/ChoiceListTest.php | 172 +++------- .../Core/ChoiceList/ObjectChoiceListTest.php | 64 ++-- .../Core/ChoiceList/SimpleChoiceListTest.php | 191 ++--------- .../SimpleNumericChoiceListTest.php | 78 +++++ 5 files changed, 486 insertions(+), 316 deletions(-) create mode 100644 Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php create mode 100644 Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php diff --git a/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php b/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php new file mode 100644 index 0000000000..0e2b6321cc --- /dev/null +++ b/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php @@ -0,0 +1,297 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; + +/** + * @author Bernhard Schussek + */ +abstract class AbstractChoiceListTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface + */ + protected $list; + + /** + * @var array + */ + protected $choices; + + /** + * @var array + */ + protected $values; + + /** + * @var array + */ + protected $indices; + + /** + * @var array + */ + protected $labels; + + /** + * @var mixed + */ + protected $choice1; + + /** + * @var mixed + */ + protected $choice2; + + /** + * @var mixed + */ + protected $choice3; + + /** + * @var mixed + */ + protected $choice4; + + /** + * @var string + */ + protected $value1; + + /** + * @var string + */ + protected $value2; + + /** + * @var string + */ + protected $value3; + + /** + * @var string + */ + protected $value4; + + /** + * @var int|string + */ + protected $index1; + + /** + * @var int|string + */ + protected $index2; + + /** + * @var int|string + */ + protected $index3; + + /** + * @var int|string + */ + protected $index4; + + /** + * @var string + */ + protected $label1; + + /** + * @var string + */ + protected $label2; + + /** + * @var string + */ + protected $label3; + + /** + * @var string + */ + protected $label4; + + protected function setUp() + { + parent::setUp(); + + $this->list = $this->createChoiceList(); + + $this->choices = $this->getChoices(); + $this->indices = $this->getIndices(); + $this->values = $this->getValues(); + $this->labels = $this->getLabels(); + + // allow access to the individual entries without relying on their indices + reset($this->choices); + reset($this->indices); + reset($this->values); + reset($this->labels); + + for ($i = 1; $i <= 4; ++$i) { + $this->{'choice'.$i} = current($this->choices); + $this->{'index'.$i} = current($this->indices); + $this->{'value'.$i} = current($this->values); + $this->{'label'.$i} = current($this->labels); + + next($this->choices); + next($this->indices); + next($this->values); + next($this->labels); + } + } + + public function testGetChoices() + { + $this->assertSame($this->choices, $this->list->getChoices()); + } + + public function testGetValues() + { + $this->assertSame($this->values, $this->list->getValues()); + } + + public function testGetIndicesForChoices() + { + $choices = array($this->choice1, $this->choice2); + $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesPreservesKeys() + { + $choices = array(5 => $this->choice1, 8 => $this->choice2); + $this->assertSame(array(5 => $this->index1, 8 => $this->index2), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesPreservesOrder() + { + $choices = array($this->choice2, $this->choice1); + $this->assertSame(array($this->index2, $this->index1), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesIgnoresNonExistingChoices() + { + $choices = array($this->choice1, $this->choice2, 'foobar'); + $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesEmpty() + { + $this->assertSame(array(), $this->list->getIndicesForChoices(array())); + } + + public function testGetIndicesForValues() + { + // values and indices are always the same + $values = array($this->value1, $this->value2); + $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForValues($values)); + } + + public function testGetIndicesForValuesPreservesKeys() + { + // values and indices are always the same + $values = array(5 => $this->value1, 8 => $this->value2); + $this->assertSame(array(5 => $this->index1, 8 => $this->index2), $this->list->getIndicesForValues($values)); + } + + public function testGetIndicesForValuesPreservesOrder() + { + $values = array($this->value2, $this->value1); + $this->assertSame(array($this->index2, $this->index1), $this->list->getIndicesForValues($values)); + } + + public function testGetIndicesForValuesIgnoresNonExistingValues() + { + $values = array($this->value1, $this->value2, 'foobar'); + $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForValues($values)); + } + + public function testGetIndicesForValuesEmpty() + { + $this->assertSame(array(), $this->list->getIndicesForValues(array())); + } + + public function testGetChoicesForValues() + { + $values = array($this->value1, $this->value2); + $this->assertSame(array($this->choice1, $this->choice2), $this->list->getChoicesForValues($values)); + } + + public function testGetChoicesForValuesPreservesKeys() + { + $values = array(5 => $this->value1, 8 => $this->value2); + $this->assertSame(array(5 => $this->choice1, 8 => $this->choice2), $this->list->getChoicesForValues($values)); + } + + public function testGetChoicesForValuesPreservesOrder() + { + $values = array($this->value2, $this->value1); + $this->assertSame(array($this->choice2, $this->choice1), $this->list->getChoicesForValues($values)); + } + + public function testGetChoicesForValuesIgnoresNonExistingValues() + { + $values = array($this->value1, $this->value2, 'foobar'); + $this->assertSame(array($this->choice1, $this->choice2), $this->list->getChoicesForValues($values)); + } + + // https://github.com/symfony/symfony/issues/3446 + public function testGetChoicesForValuesEmpty() + { + $this->assertSame(array(), $this->list->getChoicesForValues(array())); + } + + public function testGetValuesForChoices() + { + $choices = array($this->choice1, $this->choice2); + $this->assertSame(array($this->value1, $this->value2), $this->list->getValuesForChoices($choices)); + } + + + public function testGetValuesForChoicesPreservesKeys() + { + $choices = array(5 => $this->choice1, 8 => $this->choice2); + $this->assertSame(array(5 => $this->value1, 8 => $this->value2), $this->list->getValuesForChoices($choices)); + } + + + public function testGetValuesForChoicesPreservesOrder() + { + $choices = array($this->choice2, $this->choice1); + $this->assertSame(array($this->value2, $this->value1), $this->list->getValuesForChoices($choices)); + } + + public function testGetValuesForChoicesIgnoresNonExistingChoices() + { + $choices = array($this->choice1, $this->choice2, 'foobar'); + $this->assertSame(array($this->value1, $this->value2), $this->list->getValuesForChoices($choices)); + } + + public function testGetValuesForChoicesEmpty() + { + $this->assertSame(array(), $this->list->getValuesForChoices(array())); + } + + /** + * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface + */ + abstract protected function createChoiceList(); + + abstract protected function getChoices(); + + abstract protected function getLabels(); + + abstract protected function getValues(); + + abstract protected function getIndices(); +} diff --git a/Tests/Extension/Core/ChoiceList/ChoiceListTest.php b/Tests/Extension/Core/ChoiceList/ChoiceListTest.php index 531bb561b4..59f002d8cc 100644 --- a/Tests/Extension/Core/ChoiceList/ChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/ChoiceListTest.php @@ -14,7 +14,7 @@ use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList; use Symfony\Component\Form\Extension\Core\View\ChoiceView; -class ChoiceListTest extends \PHPUnit_Framework_TestCase +class ChoiceListTest extends AbstractChoiceListTest { private $obj1; @@ -24,39 +24,14 @@ class ChoiceListTest extends \PHPUnit_Framework_TestCase private $obj4; - private $list; - protected function setUp() { - parent::setUp(); - $this->obj1 = new \stdClass(); $this->obj2 = new \stdClass(); $this->obj3 = new \stdClass(); $this->obj4 = new \stdClass(); - $this->list = new ChoiceList( - array( - 'Group 1' => array($this->obj1, $this->obj2), - 'Group 2' => array($this->obj3, $this->obj4), - ), - array( - 'Group 1' => array('A', 'B'), - 'Group 2' => array('C', 'D'), - ), - array($this->obj2, $this->obj3) - ); - } - - protected function tearDown() - { - parent::tearDown(); - - $this->obj1 = null; - $this->obj2 = null; - $this->obj3 = null; - $this->obj4 = null; - $this->list = null; + parent::setUp(); } public function testInitArray() @@ -119,111 +94,10 @@ public function testInitNestedArray() ), $this->list->getRemainingViews()); } - public function testGetIndicesForChoices() - { - $choices = array($this->obj2, $this->obj3); - $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForChoicesPreservesKeys() - { - $choices = array(5 => $this->obj2, 8 => $this->obj3); - $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForChoicesPreservesOrder() - { - $choices = array($this->obj3, $this->obj2); - $this->assertSame(array(2, 1), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForChoicesIgnoresNonExistingChoices() - { - $choices = array($this->obj2, $this->obj3, 'foobar'); - $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForValues() - { - // values and indices are always the same - $values = array('1', '2'); - $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); - } - - public function testGetIndicesForValuesPreservesKeys() - { - // values and indices are always the same - $values = array(5 => '1', 8 => '2'); - $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForValues($values)); - } - - public function testGetIndicesForValuesPreservesOrder() - { - // values and indices are always the same - $values = array('2', '1'); - $this->assertSame(array(2, 1), $this->list->getIndicesForValues($values)); - } - - public function testGetIndicesForValuesIgnoresNonExistingValues() - { - $values = array('1', '2', '5'); - $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); - } - - public function testGetChoicesForValues() - { - $values = array('1', '2'); - $this->assertSame(array($this->obj2, $this->obj3), $this->list->getChoicesForValues($values)); - } - - public function testGetChoicesForValuesPreservesKeys() - { - $values = array(5 => '1', 8 => '2'); - $this->assertSame(array(5 => $this->obj2, 8 => $this->obj3), $this->list->getChoicesForValues($values)); - } - - public function testGetChoicesForValuesPreservesOrder() - { - $values = array('2', '1'); - $this->assertSame(array($this->obj3, $this->obj2), $this->list->getChoicesForValues($values)); - } - - public function testGetChoicesForValuesIgnoresNonExistingValues() - { - $values = array('1', '2', '5'); - $this->assertSame(array($this->obj2, $this->obj3), $this->list->getChoicesForValues($values)); - } - - public function testGetValuesForChoices() - { - $choices = array($this->obj2, $this->obj3); - $this->assertSame(array('1', '2'), $this->list->getValuesForChoices($choices)); - } - - - public function testGetValuesForChoicesPreservesKeys() - { - $choices = array(5 => $this->obj2, 8 => $this->obj3); - $this->assertSame(array(5 => '1', 8 => '2'), $this->list->getValuesForChoices($choices)); - } - - - public function testGetValuesForChoicesPreservesOrder() - { - $choices = array($this->obj3, $this->obj2); - $this->assertSame(array('2', '1'), $this->list->getValuesForChoices($choices)); - } - - public function testGetValuesForChoicesIgnoresNonExistingChoices() - { - $choices = array($this->obj2, $this->obj3, 'foobar'); - $this->assertSame(array('1', '2'), $this->list->getValuesForChoices($choices)); - } - /** * @expectedException \InvalidArgumentException */ - public function testNonMatchingLabels() + public function testInitWithInsufficientLabels() { $this->list = new ChoiceList( array($this->obj1, $this->obj2), @@ -231,7 +105,7 @@ public function testNonMatchingLabels() ); } - public function testLabelsContainingNull() + public function testInitWithLabelsContainingNull() { $this->list = new ChoiceList( array($this->obj1, $this->obj2), @@ -243,4 +117,42 @@ public function testLabelsContainingNull() $this->list->getRemainingViews() ); } + + /** + * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface + */ + protected function createChoiceList() + { + return new ChoiceList( + array( + 'Group 1' => array($this->obj1, $this->obj2), + 'Group 2' => array($this->obj3, $this->obj4), + ), + array( + 'Group 1' => array('A', 'B'), + 'Group 2' => array('C', 'D'), + ), + array($this->obj2, $this->obj3) + ); + } + + protected function getChoices() + { + return array(0 => $this->obj1, 1 => $this->obj2, 2 => $this->obj3, 3 => $this->obj4); + } + + protected function getLabels() + { + return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D'); + } + + protected function getValues() + { + return array(0 => '0', 1 => '1', 2 => '2', 3 => '3'); + } + + protected function getIndices() + { + return array(0, 1, 2, 3); + } } diff --git a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php index 69c5aa0fcb..27effd9f5c 100644 --- a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php @@ -29,7 +29,7 @@ public function __toString() } } -class ObjectChoiceListTest extends \PHPUnit_Framework_TestCase +class ObjectChoiceListTest extends AbstractChoiceListTest { private $obj1; @@ -39,39 +39,14 @@ class ObjectChoiceListTest extends \PHPUnit_Framework_TestCase private $obj4; - /** - * @var ObjectChoiceList - */ - private $list; - protected function setUp() { - parent::setUp(); - $this->obj1 = (object) array('name' => 'A'); $this->obj2 = (object) array('name' => 'B'); $this->obj3 = (object) array('name' => 'C'); $this->obj4 = (object) array('name' => 'D'); - $this->list = new ObjectChoiceList( - array( - 'Group 1' => array($this->obj1, $this->obj2), - 'Group 2' => array($this->obj3, $this->obj4), - ), - 'name', - array($this->obj2, $this->obj3) - ); - } - - protected function tearDown() - { - parent::tearDown(); - - $this->obj1 = null; - $this->obj2 = null; - $this->obj3 = null; - $this->obj4 = null; - $this->list = null; + parent::setUp(); } public function testInitArray() @@ -209,4 +184,39 @@ public function testInitArrayThrowsExceptionIfToStringNotFound() array($this->obj1, $this->obj2, $this->obj3, $this->obj4) ); } + + /** + * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface + */ + protected function createChoiceList() + { + return new ObjectChoiceList( + array( + 'Group 1' => array($this->obj1, $this->obj2), + 'Group 2' => array($this->obj3, $this->obj4), + ), + 'name', + array($this->obj2, $this->obj3) + ); + } + + protected function getChoices() + { + return array(0 => $this->obj1, 1 => $this->obj2, 2 => $this->obj3, 3 => $this->obj4); + } + + protected function getLabels() + { + return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D'); + } + + protected function getValues() + { + return array(0 => '0', 1 => '1', 2 => '2', 3 => '3'); + } + + protected function getIndices() + { + return array(0, 1, 2, 3); + } } diff --git a/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php b/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php index 85b0ed7485..838a8e0864 100644 --- a/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php @@ -11,43 +11,11 @@ namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; -use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceList; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; use Symfony\Component\Form\Extension\Core\View\ChoiceView; -class SimpleChoiceListTest extends \PHPUnit_Framework_TestCase +class SimpleChoiceListTest extends AbstractChoiceListTest { - private $list; - - private $numericList; - - protected function setUp() - { - parent::setUp(); - - $choices = array( - 'Group 1' => array('a' => 'A', 'b' => 'B'), - 'Group 2' => array('c' => 'C', 'd' => 'D'), - ); - $numericChoices = array( - 'Group 1' => array(0 => 'A', 1 => 'B'), - 'Group 2' => array(2 => 'C', 3 => 'D'), - ); - - $this->list = new SimpleChoiceList($choices, array('b', 'c')); - - // Use COPY_CHOICE strategy to test for the various associated problems - $this->numericList = new SimpleChoiceList($numericChoices, array(1, 2)); - } - - protected function tearDown() - { - parent::tearDown(); - - $this->list = null; - $this->numericList = null; - } - public function testInitArray() { $choices = array('a' => 'A', 'b' => 'B', 'c' => 'C'); @@ -73,131 +41,6 @@ public function testInitNestedArray() ), $this->list->getRemainingViews()); } - public function testGetIndicesForChoices() - { - $choices = array('b', 'c'); - $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForChoicesPreservesKeys() - { - $choices = array(5 => 'b', 8 => 'c'); - $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForChoicesPreservesOrder() - { - $choices = array('c', 'b'); - $this->assertSame(array(2, 1), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForChoicesIgnoresNonExistingChoices() - { - $choices = array('b', 'c', 'foobar'); - $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); - } - - public function testGetIndicesForChoicesDealsWithNumericChoices() - { - // Pass choices as strings although they are integers - $choices = array('0', '1'); - $this->assertSame(array(0, 1), $this->numericList->getIndicesForChoices($choices)); - } - - public function testGetIndicesForValues() - { - $values = array('b', 'c'); - $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); - } - - public function testGetIndicesForValuesPreservesKeys() - { - $values = array(5 => 'b', 8 => 'c'); - $this->assertSame(array(5 => 1, 8 => 2), $this->list->getIndicesForValues($values)); - } - - public function testGetIndicesForValuesPreservesOrder() - { - $values = array('c', 'b'); - $this->assertSame(array(2, 1), $this->list->getIndicesForValues($values)); - } - - public function testGetIndicesForValuesIgnoresNonExistingValues() - { - $values = array('b', 'c', '100'); - $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); - } - - public function testGetIndicesForValuesDealsWithNumericValues() - { - // Pass values as strings although they are integers - $values = array('0', '1'); - $this->assertSame(array(0, 1), $this->numericList->getIndicesForValues($values)); - } - - public function testGetChoicesForValues() - { - $values = array('b', 'c'); - $this->assertSame(array('b', 'c'), $this->list->getChoicesForValues($values)); - } - - public function testGetChoicesForValuesPreservesKeys() - { - $values = array(5 => 'b', 8 => 'c'); - $this->assertSame(array(5 => 'b', 8 => 'c'), $this->list->getChoicesForValues($values)); - } - - public function testGetChoicesForValuesPreservesOrder() - { - $values = array('c', 'b'); - $this->assertSame(array('c', 'b'), $this->list->getChoicesForValues($values)); - } - - public function testGetChoicesForValuesIgnoresNonExistingValues() - { - $values = array('b', 'c', '100'); - $this->assertSame(array('b', 'c'), $this->list->getChoicesForValues($values)); - } - - public function testGetChoicesForValuesDealsWithNumericValues() - { - // Pass values as strings although they are integers - $values = array('0', '1'); - $this->assertSame(array(0, 1), $this->numericList->getChoicesForValues($values)); - } - - public function testGetValuesForChoices() - { - $choices = array('b', 'c'); - $this->assertSame(array('b', 'c'), $this->list->getValuesForChoices($choices)); - } - - public function testGetValuesForChoicesPreservesKeys() - { - $choices = array(5 => 'b', 8 => 'c'); - $this->assertSame(array(5 => 'b', 8 => 'c'), $this->list->getValuesForChoices($choices)); - } - - public function testGetValuesForChoicesPreservesOrder() - { - $choices = array('c', 'b'); - $this->assertSame(array('c', 'b'), $this->list->getValuesForChoices($choices)); - } - - public function testGetValuesForChoicesIgnoresNonExistingValues() - { - $choices = array('b', 'c', 'foobar'); - $this->assertSame(array('b', 'c'), $this->list->getValuesForChoices($choices)); - } - - public function testGetValuesForChoicesDealsWithNumericValues() - { - // Pass values as strings although they are integers - $values = array('0', '1'); - - $this->assertSame(array('0', '1'), $this->numericList->getValuesForChoices($values)); - } - /** * @dataProvider dirtyValuesProvider */ @@ -212,7 +55,6 @@ public function testGetValuesForChoicesDealsWithDirtyValues($choice, $value) 'foo10' => 'Foo 10', ); - // use COPY_CHOICE strategy to test the problems $this->list = new SimpleChoiceList($choices, array()); $this->assertSame(array($value), $this->list->getValuesForChoices(array($choice))); @@ -233,4 +75,35 @@ public function dirtyValuesProvider() array('foo10', 'foo10'), ); } + + /** + * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface + */ + protected function createChoiceList() + { + return new SimpleChoiceList(array( + 'Group 1' => array('a' => 'A', 'b' => 'B'), + 'Group 2' => array('c' => 'C', 'd' => 'D'), + ), array('b', 'c')); + } + + protected function getChoices() + { + return array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd'); + } + + protected function getLabels() + { + return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D'); + } + + protected function getValues() + { + return array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd'); + } + + protected function getIndices() + { + return array(0, 1, 2, 3); + } } diff --git a/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php b/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php new file mode 100644 index 0000000000..2b57288fb7 --- /dev/null +++ b/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; + +use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; +use Symfony\Component\Form\Extension\Core\View\ChoiceView; + +class SimpleNumericChoiceListTest extends AbstractChoiceListTest +{ + public function testGetIndicesForChoicesDealsWithNumericChoices() + { + // Pass choices as strings although they are integers + $choices = array('0', '1'); + $this->assertSame(array(0, 1), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForValuesDealsWithNumericValues() + { + // Pass values as strings although they are integers + $values = array('0', '1'); + $this->assertSame(array(0, 1), $this->list->getIndicesForValues($values)); + } + + public function testGetChoicesForValuesDealsWithNumericValues() + { + // Pass values as strings although they are integers + $values = array('0', '1'); + $this->assertSame(array(0, 1), $this->list->getChoicesForValues($values)); + } + + public function testGetValuesForChoicesDealsWithNumericValues() + { + // Pass values as strings although they are integers + $values = array('0', '1'); + + $this->assertSame(array('0', '1'), $this->list->getValuesForChoices($values)); + } + + /** + * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface + */ + protected function createChoiceList() + { + return new SimpleChoiceList(array( + 'Group 1' => array(0 => 'A', 1 => 'B'), + 'Group 2' => array(2 => 'C', 3 => 'D'), + ), array(1, 2)); + } + + protected function getChoices() + { + return array(0 => 0, 1 => 1, 2 => 2, 3 => 3); + } + + protected function getLabels() + { + return array(0 => 'A', 1 => 'B', 2 => 'C', 3 => 'D'); + } + + protected function getValues() + { + return array(0 => '0', 1 => '1', 2 => '2', 3 => '3'); + } + + protected function getIndices() + { + return array(0, 1, 2, 3); + } +} From 4b0787c873969caa923dc3a5810c835a7d161e5d Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Tue, 10 Sep 2013 14:28:39 +0200 Subject: [PATCH 185/447] [Form] Deprecated ChoiceList::getIndicesFor*() methods --- Extension/Core/ChoiceList/ChoiceList.php | 24 +++++++++++-------- .../Core/ChoiceList/ChoiceListInterface.php | 4 ++++ Extension/Core/ChoiceList/LazyChoiceList.php | 4 ++++ .../Core/ChoiceList/SimpleChoiceList.php | 4 ++-- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/Extension/Core/ChoiceList/ChoiceList.php b/Extension/Core/ChoiceList/ChoiceList.php index 17ae0a3d9e..413f7c4f74 100644 --- a/Extension/Core/ChoiceList/ChoiceList.php +++ b/Extension/Core/ChoiceList/ChoiceList.php @@ -198,6 +198,8 @@ public function getValuesForChoices(array $choices) /** * {@inheritdoc} + * + * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForChoices(array $choices) { @@ -222,6 +224,8 @@ public function getIndicesForChoices(array $choices) /** * {@inheritdoc} + * + * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForValues(array $values) { @@ -485,9 +489,9 @@ protected function fixIndices(array $indices) * Extension point. In this implementation, choices are guaranteed to * always maintain their type and thus can be typesafely compared. * - * @param mixed $choice The choice. + * @param mixed $choice The choice * - * @return mixed The fixed choice. + * @return mixed The fixed choice */ protected function fixChoice($choice) { @@ -495,14 +499,14 @@ protected function fixChoice($choice) } /** - * Fixes the data type of the given choices to avoid comparison problems. - * - * @param array $choices The choices. - * - * @return array The fixed choices. - * - * @see fixChoice - */ + * Fixes the data type of the given choices to avoid comparison problems. + * + * @param array $choices The choices. + * + * @return array The fixed choices. + * + * @see fixChoice + */ protected function fixChoices(array $choices) { return $choices; diff --git a/Extension/Core/ChoiceList/ChoiceListInterface.php b/Extension/Core/ChoiceList/ChoiceListInterface.php index febf80ef05..0e5f9459b9 100644 --- a/Extension/Core/ChoiceList/ChoiceListInterface.php +++ b/Extension/Core/ChoiceList/ChoiceListInterface.php @@ -138,6 +138,8 @@ public function getValuesForChoices(array $choices); * array are ignored * * @return array An array of indices with ascending, 0-based numeric keys + * + * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForChoices(array $choices); @@ -156,6 +158,8 @@ public function getIndicesForChoices(array $choices); * this array are ignored * * @return array An array of indices with ascending, 0-based numeric keys + * + * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForValues(array $values); } diff --git a/Extension/Core/ChoiceList/LazyChoiceList.php b/Extension/Core/ChoiceList/LazyChoiceList.php index 996f900cf3..23f3cccbe2 100644 --- a/Extension/Core/ChoiceList/LazyChoiceList.php +++ b/Extension/Core/ChoiceList/LazyChoiceList.php @@ -105,6 +105,8 @@ public function getValuesForChoices(array $choices) /** * {@inheritdoc} + * + * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForChoices(array $choices) { @@ -117,6 +119,8 @@ public function getIndicesForChoices(array $choices) /** * {@inheritdoc} + * + * @deprecated Deprecated since version 2.4, to be removed in 3.0. */ public function getIndicesForValues(array $values) { diff --git a/Extension/Core/ChoiceList/SimpleChoiceList.php b/Extension/Core/ChoiceList/SimpleChoiceList.php index 914dbe5fdb..e173e742c7 100644 --- a/Extension/Core/ChoiceList/SimpleChoiceList.php +++ b/Extension/Core/ChoiceList/SimpleChoiceList.php @@ -135,9 +135,9 @@ protected function isPreferred($choice, array $preferredChoices) /** * Converts the choice to a valid PHP array key. * - * @param mixed $choice The choice. + * @param mixed $choice The choice * - * @return string|integer A valid PHP array key. + * @return string|integer A valid PHP array key */ protected function fixChoice($choice) { From fa405e18a8b926decad86eddf39d2e75bf2d414b Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 12 Sep 2013 09:25:54 +0200 Subject: [PATCH 186/447] [Form] Fixed regression in BooleanToStringTransformer from ed83752 --- .../Core/DataTransformer/BooleanToStringTransformer.php | 4 ++++ .../DataTransformer/BooleanToStringTransformerTest.php | 8 +++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Extension/Core/DataTransformer/BooleanToStringTransformer.php b/Extension/Core/DataTransformer/BooleanToStringTransformer.php index f8e3b5bfcb..4f6b12275b 100644 --- a/Extension/Core/DataTransformer/BooleanToStringTransformer.php +++ b/Extension/Core/DataTransformer/BooleanToStringTransformer.php @@ -49,6 +49,10 @@ public function __construct($trueValue) */ public function transform($value) { + if (null === $value) { + return null; + } + if (!is_bool($value)) { throw new TransformationFailedException('Expected a Boolean.'); } diff --git a/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php index 4f6238aee0..a1217783d1 100644 --- a/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php @@ -38,12 +38,10 @@ public function testTransform() $this->assertNull($this->transformer->transform(false)); } - /** - * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException - */ - public function testTransformFailsIfNull() + // https://github.com/symfony/symfony/issues/8989 + public function testTransformAcceptsNull() { - $this->transformer->transform(null); + $this->assertNull($this->transformer->transform(null)); } /** From c091320e93e88807bde56da4485805c1cfe0c896 Mon Sep 17 00:00:00 2001 From: dropfen Date: Thu, 12 Sep 2013 23:36:40 +0200 Subject: [PATCH 187/447] Use setTimeZone if this method exists. The php version is not a critical factor to choose the method, but we have to use setTimeZone, if it exists. --- Extension/Core/Type/DateType.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Extension/Core/Type/DateType.php b/Extension/Core/Type/DateType.php index 05b2aaedc1..158f9a91f3 100644 --- a/Extension/Core/Type/DateType.php +++ b/Extension/Core/Type/DateType.php @@ -267,8 +267,10 @@ private function formatTimestamps(\IntlDateFormatter $formatter, $regex, array $ { $pattern = $formatter->getPattern(); $timezone = $formatter->getTimezoneId(); + // Use it, if exists. + $setTimeZone = method_exists($formatter, 'setTimeZone'); - if (version_compare(\PHP_VERSION, '5.5.0-dev', '>=')) { + if ($setTimeZone) { $formatter->setTimeZone('UTC'); } else { $formatter->setTimeZoneId('UTC'); @@ -286,7 +288,7 @@ private function formatTimestamps(\IntlDateFormatter $formatter, $regex, array $ $formatter->setPattern($pattern); } - if (version_compare(\PHP_VERSION, '5.5.0-dev', '>=')) { + if ($setTimeZone) { $formatter->setTimeZone($timezone); } else { $formatter->setTimeZoneId($timezone); From d0413fc6219f9034f881217c13bb48397899187b Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 13 Sep 2013 10:54:34 +0200 Subject: [PATCH 188/447] removed unneeded comment --- Extension/Core/Type/DateType.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Extension/Core/Type/DateType.php b/Extension/Core/Type/DateType.php index 158f9a91f3..2ac2f0436e 100644 --- a/Extension/Core/Type/DateType.php +++ b/Extension/Core/Type/DateType.php @@ -267,10 +267,8 @@ private function formatTimestamps(\IntlDateFormatter $formatter, $regex, array $ { $pattern = $formatter->getPattern(); $timezone = $formatter->getTimezoneId(); - // Use it, if exists. - $setTimeZone = method_exists($formatter, 'setTimeZone'); - if ($setTimeZone) { + if ($setTimeZone = method_exists($formatter, 'setTimeZone')) { $formatter->setTimeZone('UTC'); } else { $formatter->setTimeZoneId('UTC'); From e8981a1fa71507eb2c9a4b468e4cf002bb8a0727 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 13 Sep 2013 16:55:54 +0200 Subject: [PATCH 189/447] [Form] Fixed: "required" attribute is not added to * * - * Check the token in your action using the same intention. + * Check the token in your action using the same token ID. * * - * $csrfProvider = $this->get('form.csrf_provider'); + * $csrfProvider = $this->get('security.csrf.token_generator'); * if (!$csrfProvider->isCsrfTokenValid('rm_user_'.$user->getId(), $token)) { * throw new \RuntimeException('CSRF attack detected.'); * } * * - * @param string $intention The intention of the protected action + * @param string $tokenId The ID of the CSRF token * * @return string A CSRF token */ - public function renderCsrfToken($intention); + public function renderCsrfToken($tokenId); /** * Makes a technical name human readable. diff --git a/Tests/AbstractDivLayoutTest.php b/Tests/AbstractDivLayoutTest.php index ee9ed8f2a6..c40e3e5a89 100644 --- a/Tests/AbstractDivLayoutTest.php +++ b/Tests/AbstractDivLayoutTest.php @@ -471,7 +471,7 @@ public function testNestedFormError() public function testCsrf() { - $this->csrfProvider->expects($this->any()) + $this->csrfTokenGenerator->expects($this->any()) ->method('generateCsrfToken') ->will($this->returnValue('foo&bar')); diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index d2ed7711ba..c68895a643 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -17,7 +17,7 @@ abstract class AbstractLayoutTest extends \Symfony\Component\Form\Test\FormIntegrationTestCase { - protected $csrfProvider; + protected $csrfTokenGenerator; protected function setUp() { @@ -27,7 +27,7 @@ protected function setUp() \Locale::setDefault('en'); - $this->csrfProvider = $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface'); + $this->csrfTokenGenerator = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenGeneratorInterface'); parent::setUp(); } @@ -35,13 +35,13 @@ protected function setUp() protected function getExtensions() { return array( - new CsrfExtension($this->csrfProvider), + new CsrfExtension($this->csrfTokenGenerator), ); } protected function tearDown() { - $this->csrfProvider = null; + $this->csrfTokenGenerator = null; parent::tearDown(); } diff --git a/Tests/AbstractTableLayoutTest.php b/Tests/AbstractTableLayoutTest.php index 5c91195169..adcb440cc7 100644 --- a/Tests/AbstractTableLayoutTest.php +++ b/Tests/AbstractTableLayoutTest.php @@ -336,7 +336,7 @@ public function testNestedFormError() public function testCsrf() { - $this->csrfProvider->expects($this->any()) + $this->csrfTokenGenerator->expects($this->any()) ->method('generateCsrfToken') ->will($this->returnValue('foo&bar')); diff --git a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php index 7f2220af72..b3e45ab984 100644 --- a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php +++ b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php @@ -19,13 +19,14 @@ class CsrfValidationListenerTest extends \PHPUnit_Framework_TestCase { protected $dispatcher; protected $factory; - protected $csrfProvider; + protected $tokenGenerator; + protected $form; protected function setUp() { $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); - $this->csrfProvider = $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface'); + $this->tokenGenerator = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenGeneratorInterface'); $this->form = $this->getBuilder('post') ->setDataMapper($this->getDataMapper()) ->getForm(); @@ -35,7 +36,7 @@ protected function tearDown() { $this->dispatcher = null; $this->factory = null; - $this->csrfProvider = null; + $this->tokenGenerator = null; $this->form = null; } @@ -65,7 +66,7 @@ public function testStringFormData() $data = "XP4HUzmHPi"; $event = new FormEvent($this->form, $data); - $validation = new CsrfValidationListener('csrf', $this->csrfProvider, 'unknown', 'Invalid.'); + $validation = new CsrfValidationListener('csrf', $this->tokenGenerator, 'unknown', 'Invalid.'); $validation->preSubmit($event); // Validate accordingly diff --git a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php index 0a1f0dc481..ccd7dccbca 100644 --- a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php +++ b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php @@ -37,7 +37,7 @@ class FormTypeCsrfExtensionTest extends TypeTestCase /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $csrfProvider; + protected $tokenGenerator; /** * @var \PHPUnit_Framework_MockObject_MockObject @@ -46,7 +46,7 @@ class FormTypeCsrfExtensionTest extends TypeTestCase protected function setUp() { - $this->csrfProvider = $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface'); + $this->tokenGenerator = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenGeneratorInterface'); $this->translator = $this->getMock('Symfony\Component\Translation\TranslatorInterface'); parent::setUp(); @@ -54,7 +54,7 @@ protected function setUp() protected function tearDown() { - $this->csrfProvider = null; + $this->tokenGenerator = null; $this->translator = null; parent::tearDown(); @@ -63,7 +63,7 @@ protected function tearDown() protected function getExtensions() { return array_merge(parent::getExtensions(), array( - new CsrfExtension($this->csrfProvider, $this->translator), + new CsrfExtension($this->tokenGenerator, $this->translator), )); } @@ -123,7 +123,7 @@ public function testCsrfProtectionCanBeDisabled() public function testGenerateCsrfToken() { - $this->csrfProvider->expects($this->once()) + $this->tokenGenerator->expects($this->once()) ->method('generateCsrfToken') ->with('%INTENTION%') ->will($this->returnValue('token')); @@ -131,7 +131,7 @@ public function testGenerateCsrfToken() $view = $this->factory ->create('form', null, array( 'csrf_field_name' => 'csrf', - 'csrf_provider' => $this->csrfProvider, + 'csrf_provider' => $this->tokenGenerator, 'intention' => '%INTENTION%', 'compound' => true, )) @@ -153,7 +153,7 @@ public function provideBoolean() */ public function testValidateTokenOnSubmitIfRootAndCompound($valid) { - $this->csrfProvider->expects($this->once()) + $this->tokenGenerator->expects($this->once()) ->method('isCsrfTokenValid') ->with('%INTENTION%', 'token') ->will($this->returnValue($valid)); @@ -161,7 +161,7 @@ public function testValidateTokenOnSubmitIfRootAndCompound($valid) $form = $this->factory ->createBuilder('form', null, array( 'csrf_field_name' => 'csrf', - 'csrf_provider' => $this->csrfProvider, + 'csrf_provider' => $this->tokenGenerator, 'intention' => '%INTENTION%', 'compound' => true, )) @@ -182,13 +182,13 @@ public function testValidateTokenOnSubmitIfRootAndCompound($valid) public function testFailIfRootAndCompoundAndTokenMissing() { - $this->csrfProvider->expects($this->never()) + $this->tokenGenerator->expects($this->never()) ->method('isCsrfTokenValid'); $form = $this->factory ->createBuilder('form', null, array( 'csrf_field_name' => 'csrf', - 'csrf_provider' => $this->csrfProvider, + 'csrf_provider' => $this->tokenGenerator, 'intention' => '%INTENTION%', 'compound' => true, )) @@ -209,7 +209,7 @@ public function testFailIfRootAndCompoundAndTokenMissing() public function testDontValidateTokenIfCompoundButNoRoot() { - $this->csrfProvider->expects($this->never()) + $this->tokenGenerator->expects($this->never()) ->method('isCsrfTokenValid'); $form = $this->factory @@ -217,7 +217,7 @@ public function testDontValidateTokenIfCompoundButNoRoot() ->add($this->factory ->createNamedBuilder('form', 'form', null, array( 'csrf_field_name' => 'csrf', - 'csrf_provider' => $this->csrfProvider, + 'csrf_provider' => $this->tokenGenerator, 'intention' => '%INTENTION%', 'compound' => true, )) @@ -233,13 +233,13 @@ public function testDontValidateTokenIfCompoundButNoRoot() public function testDontValidateTokenIfRootButNotCompound() { - $this->csrfProvider->expects($this->never()) + $this->tokenGenerator->expects($this->never()) ->method('isCsrfTokenValid'); $form = $this->factory ->create('form', null, array( 'csrf_field_name' => 'csrf', - 'csrf_provider' => $this->csrfProvider, + 'csrf_provider' => $this->tokenGenerator, 'intention' => '%INTENTION%', 'compound' => false, )); @@ -269,7 +269,7 @@ public function testNoCsrfProtectionOnPrototype() public function testsTranslateCustomErrorMessage() { - $this->csrfProvider->expects($this->once()) + $this->tokenGenerator->expects($this->once()) ->method('isCsrfTokenValid') ->with('%INTENTION%', 'token') ->will($this->returnValue(false)); @@ -282,7 +282,7 @@ public function testsTranslateCustomErrorMessage() $form = $this->factory ->createBuilder('form', null, array( 'csrf_field_name' => 'csrf', - 'csrf_provider' => $this->csrfProvider, + 'csrf_provider' => $this->tokenGenerator, 'csrf_message' => 'Foobar', 'intention' => '%INTENTION%', 'compound' => true, diff --git a/composer.json b/composer.json index dda5959c9a..87905eaa69 100644 --- a/composer.json +++ b/composer.json @@ -27,8 +27,8 @@ "symfony/http-foundation": "~2.2" }, "suggest": { - "symfony/validator": "", - "symfony/http-foundation": "" + "symfony/validator": "For form validation.", + "symfony/security-csrf": "For protecting forms against CSRF attacks." }, "autoload": { "psr-0": { "Symfony\\Component\\Form\\": "" } From d6ac2054fa5448bca915aad196171ae1760751c9 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Mon, 30 Sep 2013 14:07:24 +0200 Subject: [PATCH 199/447] [Form] Improved test coverage of widget_attributes and widget_container_attributes blocks --- Tests/AbstractDivLayoutTest.php | 38 +++++++++++++++ Tests/AbstractLayoutTest.php | 81 ++++++++++++++++++++++++++++++- Tests/AbstractTableLayoutTest.php | 38 +++++++++++++++ 3 files changed, 156 insertions(+), 1 deletion(-) diff --git a/Tests/AbstractDivLayoutTest.php b/Tests/AbstractDivLayoutTest.php index ee9ed8f2a6..9e1fb8663a 100644 --- a/Tests/AbstractDivLayoutTest.php +++ b/Tests/AbstractDivLayoutTest.php @@ -729,4 +729,42 @@ public function testFormEndWithoutRest() $this->assertEquals('', $html); } + + public function testWidgetContainerAttributes() + { + $form = $this->factory->createNamed('form', 'form', null, array( + 'attr' => array('class' => 'foobar', 'data-foo' => 'bar'), + )); + + $form->add('text', 'text'); + + $html = $this->renderWidget($form->createView()); + + // compare plain HTML to check the whitespace + $this->assertContains('
', $html); + } + + public function testWidgetContainerAttributeNameRepeatedIfTrue() + { + $form = $this->factory->createNamed('form', 'form', null, array( + 'attr' => array('foo' => true), + )); + + $html = $this->renderWidget($form->createView()); + + // foo="foo" + $this->assertContains('
', $html); + } + + public function testWidgetContainerAttributeHiddenIfFalse() + { + $form = $this->factory->createNamed('form', 'form', null, array( + 'attr' => array('foo' => false), + )); + + $html = $this->renderWidget($form->createView()); + + // no foo + $this->assertContains('
', $html); + } } diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index d2ed7711ba..fc8317e9e3 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -302,8 +302,9 @@ public function testErrors() ); } - public function testWidgetById() + public function testOverrideWidgetBlock() { + // see custom_widgets.html.twig $form = $this->factory->createNamed('text_id', 'text'); $html = $this->renderWidget($form->createView()); @@ -1891,4 +1892,82 @@ public function testStartTagWithExtraAttributes() $this->assertSame('
', $html); } + + public function testWidgetAttributes() + { + $form = $this->factory->createNamed('text', 'text', 'value', array( + 'required' => true, + 'disabled' => true, + 'read_only' => true, + 'max_length' => 10, + 'pattern' => '\d+', + 'attr' => array('class' => 'foobar', 'data-foo' => 'bar'), + )); + + $html = $this->renderWidget($form->createView()); + + // compare plain HTML to check the whitespace + $this->assertSame('', $html); + } + + public function testWidgetAttributeNameRepeatedIfTrue() + { + $form = $this->factory->createNamed('text', 'text', 'value', array( + 'attr' => array('foo' => true), + )); + + $html = $this->renderWidget($form->createView()); + + // foo="foo" + $this->assertSame('', $html); + } + + public function testWidgetAttributeHiddenIfFalse() + { + $form = $this->factory->createNamed('text', 'text', 'value', array( + 'attr' => array('foo' => false), + )); + + $html = $this->renderWidget($form->createView()); + + // no foo + $this->assertSame('', $html); + } + + public function testButtonAttributes() + { + $form = $this->factory->createNamed('button', 'button', null, array( + 'disabled' => true, + 'attr' => array('class' => 'foobar', 'data-foo' => 'bar'), + )); + + $html = $this->renderWidget($form->createView()); + + // compare plain HTML to check the whitespace + $this->assertSame('', $html); + } + + public function testButtonAttributeNameRepeatedIfTrue() + { + $form = $this->factory->createNamed('button', 'button', null, array( + 'attr' => array('foo' => true), + )); + + $html = $this->renderWidget($form->createView()); + + // foo="foo" + $this->assertSame('', $html); + } + + public function testButtonAttributeHiddenIfFalse() + { + $form = $this->factory->createNamed('button', 'button', null, array( + 'attr' => array('foo' => false), + )); + + $html = $this->renderWidget($form->createView()); + + // no foo + $this->assertSame('', $html); + } } diff --git a/Tests/AbstractTableLayoutTest.php b/Tests/AbstractTableLayoutTest.php index 5c91195169..70e1c7ccbc 100644 --- a/Tests/AbstractTableLayoutTest.php +++ b/Tests/AbstractTableLayoutTest.php @@ -506,4 +506,42 @@ public function testFormEndWithoutRest() $this->assertEquals('', $html); } + + public function testWidgetContainerAttributes() + { + $form = $this->factory->createNamed('form', 'form', null, array( + 'attr' => array('class' => 'foobar', 'data-foo' => 'bar'), + )); + + $form->add('text', 'text'); + + $html = $this->renderWidget($form->createView()); + + // compare plain HTML to check the whitespace + $this->assertContains('
', $html); + } + + public function testWidgetContainerAttributeNameRepeatedIfTrue() + { + $form = $this->factory->createNamed('form', 'form', null, array( + 'attr' => array('foo' => true), + )); + + $html = $this->renderWidget($form->createView()); + + // foo="foo" + $this->assertContains('
', $html); + } + + public function testWidgetContainerAttributeHiddenIfFalse() + { + $form = $this->factory->createNamed('form', 'form', null, array( + 'attr' => array('foo' => false), + )); + + $html = $this->renderWidget($form->createView()); + + // no foo + $this->assertContains('
', $html); + } } From 6bbbf5c531ebfb5b726655128427d1c2f4e4f00f Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Mon, 30 Sep 2013 14:23:39 +0200 Subject: [PATCH 200/447] Updated Composer dependencies to require the Security\Csrf component where necessary --- composer.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 87905eaa69..8e6f419b68 100644 --- a/composer.json +++ b/composer.json @@ -24,11 +24,14 @@ }, "require-dev": { "symfony/validator": "~2.2", - "symfony/http-foundation": "~2.2" + "symfony/http-foundation": "~2.2", + "symfony/security-csrf": "~2.4" }, "suggest": { "symfony/validator": "For form validation.", - "symfony/security-csrf": "For protecting forms against CSRF attacks." + "symfony/security-csrf": "For protecting forms against CSRF attacks.", + "symfony/twig-bridge": "For templating with Twig.", + "symfony/framework-bundle": "For templating with PHP." }, "autoload": { "psr-0": { "Symfony\\Component\\Form\\": "" } From 81b11a77330c846969a7b3bc57d31691735d9c2c Mon Sep 17 00:00:00 2001 From: Alessandro Tagliapietra Date: Fri, 27 Sep 2013 13:47:53 +0200 Subject: [PATCH 201/447] [Form] Let null values to unset fields in PATCH requests --- Form.php | 2 +- Tests/CompoundFormTest.php | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Form.php b/Form.php index e03e329ff8..6dabd380e0 100644 --- a/Form.php +++ b/Form.php @@ -548,7 +548,7 @@ public function submit($submittedData, $clearMissing = true) } foreach ($this->children as $name => $child) { - if (isset($submittedData[$name]) || $clearMissing) { + if (array_key_exists($name, $submittedData) || $clearMissing) { $child->submit(isset($submittedData[$name]) ? $submittedData[$name] : null, $clearMissing); unset($submittedData[$name]); } diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index 225cc93391..2b35a8fc28 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -82,6 +82,19 @@ public function testDisabledFormsValidEvenIfChildrenInvalid() $this->assertTrue($form->isValid()); } + public function testSubmitForwardsNullIfNotClearMissingButValueIsExplicitlyNull() + { + $child = $this->getMockForm('firstName'); + + $this->form->add($child); + + $child->expects($this->once()) + ->method('submit') + ->with($this->equalTo(null)); + + $this->form->submit(array('firstName' => null), false); + } + public function testSubmitForwardsNullIfValueIsMissing() { $child = $this->getMockForm('firstName'); From 1566b315f923aeb61e254fcab4e8c61fc87d8b07 Mon Sep 17 00:00:00 2001 From: franek Date: Tue, 1 Oct 2013 13:52:53 +0200 Subject: [PATCH 202/447] [Form] add support for Length and Range constraint in order to replace MaxLength, MinLength, Max and Min constraints in next release (2.3) --- Extension/Validator/ValidatorTypeGuesser.php | 26 +++++++ .../Validator/ValidatorTypeGuesserTest.php | 77 +++++++++++++++++++ 2 files changed, 103 insertions(+) create mode 100644 Tests/Extension/Validator/ValidatorTypeGuesserTest.php diff --git a/Extension/Validator/ValidatorTypeGuesser.php b/Extension/Validator/ValidatorTypeGuesser.php index 387a724de2..75be62749c 100644 --- a/Extension/Validator/ValidatorTypeGuesser.php +++ b/Extension/Validator/ValidatorTypeGuesser.php @@ -155,11 +155,13 @@ public function guessTypeForConstraint(Constraint $constraint) case 'Symfony\Component\Validator\Constraints\MaxLength': case 'Symfony\Component\Validator\Constraints\MinLength': + case 'Symfony\Component\Validator\Constraints\Length': case 'Symfony\Component\Validator\Constraints\Regex': return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\Min': case 'Symfony\Component\Validator\Constraints\Max': + case 'Symfony\Component\Validator\Constraints\Range': return new TypeGuess('number', array(), Guess::LOW_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\MinCount': @@ -206,6 +208,12 @@ public function guessMaxLengthForConstraint(Constraint $constraint) case 'Symfony\Component\Validator\Constraints\MaxLength': return new ValueGuess($constraint->limit, Guess::HIGH_CONFIDENCE); + case 'Symfony\Component\Validator\Constraints\Length': + if (is_numeric($constraint->max)) { + return new ValueGuess($constraint->max, Guess::HIGH_CONFIDENCE); + } + break; + case 'Symfony\Component\Validator\Constraints\Type': if (in_array($constraint->type, array('double', 'float', 'numeric', 'real'))) { return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); @@ -214,6 +222,12 @@ public function guessMaxLengthForConstraint(Constraint $constraint) case 'Symfony\Component\Validator\Constraints\Max': return new ValueGuess(strlen((string) $constraint->limit), Guess::LOW_CONFIDENCE); + + case 'Symfony\Component\Validator\Constraints\Range': + if (is_numeric($constraint->max)) { + return new ValueGuess(strlen((string) $constraint->max), Guess::LOW_CONFIDENCE); + } + break; } return null; @@ -232,6 +246,12 @@ public function guessPatternForConstraint(Constraint $constraint) case 'Symfony\Component\Validator\Constraints\MinLength': return new ValueGuess(sprintf('.{%s,}', (string) $constraint->limit), Guess::LOW_CONFIDENCE); + case 'Symfony\Component\Validator\Constraints\Length': + if (is_numeric($constraint->min)) { + return new ValueGuess(sprintf('.{%s,}', (string) $constraint->min), Guess::LOW_CONFIDENCE); + } + break; + case 'Symfony\Component\Validator\Constraints\Regex': $htmlPattern = $constraint->getHtmlPattern(); @@ -243,6 +263,12 @@ public function guessPatternForConstraint(Constraint $constraint) case 'Symfony\Component\Validator\Constraints\Min': return new ValueGuess(sprintf('.{%s,}', strlen((string) $constraint->limit)), Guess::LOW_CONFIDENCE); + case 'Symfony\Component\Validator\Constraints\Range': + if (is_numeric($constraint->min)) { + return new ValueGuess(sprintf('.{%s,}', strlen((string) $constraint->min)), Guess::LOW_CONFIDENCE); + } + break; + case 'Symfony\Component\Validator\Constraints\Type': if (in_array($constraint->type, array('double', 'float', 'numeric', 'real'))) { return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); diff --git a/Tests/Extension/Validator/ValidatorTypeGuesserTest.php b/Tests/Extension/Validator/ValidatorTypeGuesserTest.php new file mode 100644 index 0000000000..f42003d214 --- /dev/null +++ b/Tests/Extension/Validator/ValidatorTypeGuesserTest.php @@ -0,0 +1,77 @@ + +* +* For the full copyright and license information, please view the LICENSE +* file that was distributed with this source code. +*/ + +namespace Symfony\Component\Form\Tests\Extension\Validator; + +use Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser; +use Symfony\Component\Form\Guess\Guess; +use Symfony\Component\Validator\Constraints\Length; +use Symfony\Component\Validator\Constraints\Type; + +/** +* @author franek +*/ +class ValidatorTypeGuesserTest extends \PHPUnit_Framework_TestCase +{ + private $typeGuesser; + + public function setUp() + { + if (!class_exists('Symfony\Component\Validator\Constraint')) { + $this->markTestSkipped('The "Validator" component is not available'); + } + + $metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface'); + + $this->typeGuesser = new ValidatorTypeGuesser($metadataFactory); + } + + public function testGuessMaxLengthForConstraintWithMaxValue() + { + $constraint = new Length(array('max' => '2')); + + $result = $this->typeGuesser->guessMaxLengthForConstraint($constraint); + $this->assertInstanceOf('Symfony\Component\Form\Guess\ValueGuess', $result); + $this->assertEquals(2, $result->getValue()); + $this->assertEquals(Guess::HIGH_CONFIDENCE, $result->getConfidence()); + } + + public function testGuessMaxLengthForConstraintWithMinValue() + { + $constraint = new Length(array('min' => '2')); + + $result = $this->typeGuesser->guessMaxLengthForConstraint($constraint); + $this->assertNull($result); + } + + /** +* @dataProvider dataProviderTestGuessMaxLengthForConstraintWithType +*/ + public function testGuessMaxLengthForConstraintWithType($type) + { + $constraint = new Type($type); + + $result = $this->typeGuesser->guessMaxLengthForConstraint($constraint); + $this->assertInstanceOf('Symfony\Component\Form\Guess\ValueGuess', $result); + $this->assertEquals(null, $result->getValue()); + $this->assertEquals(Guess::MEDIUM_CONFIDENCE, $result->getConfidence()); + } + + public static function dataProviderTestGuessMaxLengthForConstraintWithType() + { + return array ( + array('double'), + array('float'), + array('numeric'), + array('real') + ); + } +} From 79de75abf77582722af163f637f8e76705e54343 Mon Sep 17 00:00:00 2001 From: franek Date: Tue, 1 Oct 2013 14:55:47 +0200 Subject: [PATCH 203/447] remove deprecated constraints calls (Min, Max, MaxLength, MinLength) --- Extension/Validator/ValidatorTypeGuesser.php | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/Extension/Validator/ValidatorTypeGuesser.php b/Extension/Validator/ValidatorTypeGuesser.php index e5942858bb..84df7e4c89 100644 --- a/Extension/Validator/ValidatorTypeGuesser.php +++ b/Extension/Validator/ValidatorTypeGuesser.php @@ -145,14 +145,10 @@ public function guessTypeForConstraint(Constraint $constraint) case 'Symfony\Component\Validator\Constraints\Ip': return new TypeGuess('text', array(), Guess::MEDIUM_CONFIDENCE); - case 'Symfony\Component\Validator\Constraints\MaxLength': - case 'Symfony\Component\Validator\Constraints\MinLength': case 'Symfony\Component\Validator\Constraints\Length': case 'Symfony\Component\Validator\Constraints\Regex': return new TypeGuess('text', array(), Guess::LOW_CONFIDENCE); - case 'Symfony\Component\Validator\Constraints\Min': - case 'Symfony\Component\Validator\Constraints\Max': case 'Symfony\Component\Validator\Constraints\Range': return new TypeGuess('number', array(), Guess::LOW_CONFIDENCE); @@ -197,9 +193,6 @@ public function guessRequiredForConstraint(Constraint $constraint) public function guessMaxLengthForConstraint(Constraint $constraint) { switch (get_class($constraint)) { - case 'Symfony\Component\Validator\Constraints\MaxLength': - return new ValueGuess($constraint->limit, Guess::HIGH_CONFIDENCE); - case 'Symfony\Component\Validator\Constraints\Length': if (is_numeric($constraint->max)) { return new ValueGuess($constraint->max, Guess::HIGH_CONFIDENCE); @@ -212,9 +205,6 @@ public function guessMaxLengthForConstraint(Constraint $constraint) } break; - case 'Symfony\Component\Validator\Constraints\Max': - return new ValueGuess(strlen((string) $constraint->limit), Guess::LOW_CONFIDENCE); - case 'Symfony\Component\Validator\Constraints\Range': if (is_numeric($constraint->max)) { return new ValueGuess(strlen((string) $constraint->max), Guess::LOW_CONFIDENCE); @@ -235,9 +225,6 @@ public function guessMaxLengthForConstraint(Constraint $constraint) public function guessPatternForConstraint(Constraint $constraint) { switch (get_class($constraint)) { - case 'Symfony\Component\Validator\Constraints\MinLength': - return new ValueGuess(sprintf('.{%s,}', (string) $constraint->limit), Guess::LOW_CONFIDENCE); - case 'Symfony\Component\Validator\Constraints\Length': if (is_numeric($constraint->min)) { return new ValueGuess(sprintf('.{%s,}', (string) $constraint->min), Guess::LOW_CONFIDENCE); @@ -252,9 +239,6 @@ public function guessPatternForConstraint(Constraint $constraint) } break; - case 'Symfony\Component\Validator\Constraints\Min': - return new ValueGuess(sprintf('.{%s,}', strlen((string) $constraint->limit)), Guess::LOW_CONFIDENCE); - case 'Symfony\Component\Validator\Constraints\Range': if (is_numeric($constraint->min)) { return new ValueGuess(sprintf('.{%s,}', strlen((string) $constraint->min)), Guess::LOW_CONFIDENCE); From 56857e3c57c6c67694ff410e2ae9bc9864b351de Mon Sep 17 00:00:00 2001 From: franek Date: Tue, 1 Oct 2013 16:29:34 +0200 Subject: [PATCH 204/447] remove MinCount and MaxCount contraints. It has been replaced by Count constraints. --- Extension/Validator/ValidatorTypeGuesser.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Extension/Validator/ValidatorTypeGuesser.php b/Extension/Validator/ValidatorTypeGuesser.php index 75be62749c..6441df67c7 100644 --- a/Extension/Validator/ValidatorTypeGuesser.php +++ b/Extension/Validator/ValidatorTypeGuesser.php @@ -164,8 +164,7 @@ public function guessTypeForConstraint(Constraint $constraint) case 'Symfony\Component\Validator\Constraints\Range': return new TypeGuess('number', array(), Guess::LOW_CONFIDENCE); - case 'Symfony\Component\Validator\Constraints\MinCount': - case 'Symfony\Component\Validator\Constraints\MaxCount': + case 'Symfony\Component\Validator\Constraints\Count': return new TypeGuess('collection', array(), Guess::LOW_CONFIDENCE); case 'Symfony\Component\Validator\Constraints\True': From 8289998eec2b4509dd4c3c5f1e088d31bf017df8 Mon Sep 17 00:00:00 2001 From: Adrien Brault Date: Fri, 13 Sep 2013 08:21:38 -0700 Subject: [PATCH 205/447] [Form] Choice children can be template customized like collection --- Extension/Core/Type/ChoiceType.php | 1 + Tests/AbstractDivLayoutTest.php | 32 +++++++++++++++++++++++++----- Tests/AbstractTableLayoutTest.php | 10 +++++----- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/Extension/Core/Type/ChoiceType.php b/Extension/Core/Type/ChoiceType.php index d3d9187c0c..eb7ae3b1e2 100644 --- a/Extension/Core/Type/ChoiceType.php +++ b/Extension/Core/Type/ChoiceType.php @@ -256,6 +256,7 @@ private function addSubForms(FormBuilderInterface $builder, array $choiceViews, 'value' => $choiceView->value, 'label' => $choiceView->label, 'translation_domain' => $options['translation_domain'], + 'block_name' => 'entry', ); if ($options['multiple']) { diff --git a/Tests/AbstractDivLayoutTest.php b/Tests/AbstractDivLayoutTest.php index ee9ed8f2a6..c4a825bd2d 100644 --- a/Tests/AbstractDivLayoutTest.php +++ b/Tests/AbstractDivLayoutTest.php @@ -283,7 +283,7 @@ public function testRestAndRepeatedWithWidgetPerChild() public function testCollection() { - $form = $this->factory->createNamed('name', 'collection', array('a', 'b'), array( + $form = $this->factory->createNamed('names', 'collection', array('a', 'b'), array( 'type' => 'text', )); @@ -305,7 +305,7 @@ public function testCollectionWithAlternatingRowTypes() array('title' => 'a'), array('title' => 'b'), ); - $form = $this->factory->createNamed('name', 'collection', $data, array( + $form = $this->factory->createNamed('names', 'collection', $data, array( 'type' => new AlternatingRowType(), )); @@ -323,13 +323,13 @@ public function testCollectionWithAlternatingRowTypes() public function testEmptyCollection() { - $form = $this->factory->createNamed('name', 'collection', array(), array( + $form = $this->factory->createNamed('names', 'collection', array(), array( 'type' => 'text', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div - [./input[@type="hidden"][@id="name__token"]] + [./input[@type="hidden"][@id="names__token"]] [count(./div)=0] ' ); @@ -670,7 +670,7 @@ public function testThemeInheritance($parentTheme, $childTheme) public function testCollectionRowWithCustomBlock() { $collection = array('one', 'two', 'three'); - $form = $this->factory->createNamedBuilder('name', 'collection', $collection) + $form = $this->factory->createNamedBuilder('names', 'collection', $collection) ->getForm(); $this->assertWidgetMatchesXpath($form->createView(), array(), @@ -684,6 +684,28 @@ public function testCollectionRowWithCustomBlock() ); } + /** + * The block "_name_c_entry_label" should be overridden in the theme of the + * implemented driver. + */ + public function testChoiceRowWithCustomBlock() + { + $form = $this->factory->createNamedBuilder('name_c', 'choice', 'a', array( + 'choices' => array('a' => 'ChoiceA', 'b' => 'ChoiceB'), + 'expanded' => true, + )) + ->getForm(); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./label[.="Custom name label: [trans]ChoiceA[/trans]"] + /following-sibling::label[.="Custom name label: [trans]ChoiceB[/trans]"] + ] +' + ); + } + public function testFormEndWithRest() { $view = $this->factory->createNamedBuilder('name', 'form') diff --git a/Tests/AbstractTableLayoutTest.php b/Tests/AbstractTableLayoutTest.php index 5c91195169..7e7c8f33eb 100644 --- a/Tests/AbstractTableLayoutTest.php +++ b/Tests/AbstractTableLayoutTest.php @@ -193,7 +193,7 @@ public function testRest() public function testCollection() { - $form = $this->factory->createNamed('name', 'collection', array('a', 'b'), array( + $form = $this->factory->createNamed('names', 'collection', array('a', 'b'), array( 'type' => 'text', )); @@ -202,7 +202,7 @@ public function testCollection() [ ./tr[./td/input[@type="text"][@value="a"]] /following-sibling::tr[./td/input[@type="text"][@value="b"]] - /following-sibling::tr[@style="display: none"][./td[@colspan="2"]/input[@type="hidden"][@id="name__token"]] + /following-sibling::tr[@style="display: none"][./td[@colspan="2"]/input[@type="hidden"][@id="names__token"]] ] [count(./tr[./td/input])=3] ' @@ -211,13 +211,13 @@ public function testCollection() public function testEmptyCollection() { - $form = $this->factory->createNamed('name', 'collection', array(), array( + $form = $this->factory->createNamed('names', 'collection', array(), array( 'type' => 'text', )); $this->assertWidgetMatchesXpath($form->createView(), array(), '/table - [./tr[@style="display: none"][./td[@colspan="2"]/input[@type="hidden"][@id="name__token"]]] + [./tr[@style="display: none"][./td[@colspan="2"]/input[@type="hidden"][@id="names__token"]]] [count(./tr[./td/input])=1] ' ); @@ -439,7 +439,7 @@ public function testRepeatedWithCustomOptions() public function testCollectionRowWithCustomBlock() { $collection = array('one', 'two', 'three'); - $form = $this->factory->createNamedBuilder('name', 'collection', $collection) + $form = $this->factory->createNamedBuilder('names', 'collection', $collection) ->getForm(); $this->assertWidgetMatchesXpath($form->createView(), array(), From bd9949d0a82c705b8ffca4e4cfd296cca7e340d7 Mon Sep 17 00:00:00 2001 From: Eric GELOEN Date: Fri, 4 Oct 2013 00:18:53 +0200 Subject: [PATCH 206/447] [Form] Add a 'submitted' attribute to the form view --- Extension/Core/Type/FormType.php | 1 + Tests/Extension/Core/Type/FormTypeTest.php | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/Extension/Core/Type/FormType.php b/Extension/Core/Type/FormType.php index a64b5ac465..9f6f81ef8d 100644 --- a/Extension/Core/Type/FormType.php +++ b/Extension/Core/Type/FormType.php @@ -97,6 +97,7 @@ public function buildView(FormView $view, FormInterface $form, array $options) 'compound' => $form->getConfig()->getCompound(), 'method' => $form->getConfig()->getMethod(), 'action' => $form->getConfig()->getAction(), + 'submitted' => $form->isSubmitted(), )); } diff --git a/Tests/Extension/Core/Type/FormTypeTest.php b/Tests/Extension/Core/Type/FormTypeTest.php index 60b6afa6c8..e087397d54 100644 --- a/Tests/Extension/Core/Type/FormTypeTest.php +++ b/Tests/Extension/Core/Type/FormTypeTest.php @@ -534,6 +534,21 @@ public function testViewNotValidSubmitted() $this->assertFalse($view->vars['valid']); } + public function testViewSubmittedNotSubmitted() + { + $form = $this->factory->create('form'); + $view = $form->createView(); + $this->assertFalse($view->vars['submitted']); + } + + public function testViewSubmittedSubmitted() + { + $form = $this->factory->create('form'); + $form->submit(array()); + $view = $form->createView(); + $this->assertTrue($view->vars['submitted']); + } + public function testDataOptionSupersedesSetDataCalls() { $form = $this->factory->create('form', null, array( From 97096d1c4b0b610f0c95ff14395c9b40388ea3e9 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 4 Oct 2013 09:21:40 +0200 Subject: [PATCH 207/447] [Form] Fixed memory leak in FormValidator --- .../Validator/Constraints/FormValidator.php | 19 +++++++------------ .../FormValidatorPerformanceTest.php | 2 +- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/Extension/Validator/Constraints/FormValidator.php b/Extension/Validator/Constraints/FormValidator.php index 8f02364e81..1c4dd3c3ea 100644 --- a/Extension/Validator/Constraints/FormValidator.php +++ b/Extension/Validator/Constraints/FormValidator.php @@ -23,9 +23,9 @@ class FormValidator extends ConstraintValidator { /** - * @var \SplObjectStorage + * @var array */ - private static $clickedButtons; + private static $clickedButtons = array(); /** * @var ServerParams @@ -52,15 +52,9 @@ public function validate($form, Constraint $constraint) return; } - if (null === static::$clickedButtons) { - static::$clickedButtons = new \SplObjectStorage(); - } - // If the form was previously validated, remove it from the cache in // case the clicked button has changed - if (static::$clickedButtons->contains($form)) { - static::$clickedButtons->detach($form); - } + unset(self::$clickedButtons[spl_object_hash($form)]); /* @var FormInterface $form */ $config = $form->getConfig(); @@ -188,16 +182,17 @@ private static function allowDataWalking(FormInterface $form) private static function getValidationGroups(FormInterface $form) { $root = $form->getRoot(); + $rootHash = spl_object_hash($root); // Determine the clicked button of the complete form tree - if (!static::$clickedButtons->contains($root)) { + if (!array_key_exists($rootHash, self::$clickedButtons)) { // Only call findClickedButton() once to prevent an exponential // runtime // https://github.com/symfony/symfony/issues/8317 - static::$clickedButtons->attach($root, self::findClickedButton($root)); + self::$clickedButtons[$rootHash] = self::findClickedButton($root); } - $button = static::$clickedButtons->offsetGet($root); + $button = self::$clickedButtons[$rootHash]; if (null !== $button) { $groups = $button->getConfig()->getOption('validation_groups'); diff --git a/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.php b/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.php index 487e6e0b50..b46f993a62 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.php @@ -38,7 +38,7 @@ public function testValidationPerformance() $builder = $this->factory->createBuilder('form'); - for ($i = 0; $i < 100; ++$i) { + for ($i = 0; $i < 40; ++$i) { $builder->add($i, 'form'); $builder->get($i) From 6d2edb8390c40d8b0a006fb6ba9ff82be5fbe989 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 4 Oct 2013 15:25:38 +0200 Subject: [PATCH 208/447] [Security\Csrf] Split CsrfTokenGenerator into CsrfTokenManager and TokenGenerator --- Extension/Csrf/CsrfExtension.php | 27 ++++--- .../Csrf/CsrfProvider/CsrfProviderAdapter.php | 75 +++++++++++++++++++ .../CsrfProvider/CsrfProviderInterface.php | 39 ++++++++-- .../CsrfTokenGeneratorAdapter.php | 26 ------- .../CsrfProvider/CsrfTokenManagerAdapter.php | 57 ++++++++++++++ .../Csrf/CsrfProvider/DefaultCsrfProvider.php | 2 +- .../Csrf/CsrfProvider/SessionCsrfProvider.php | 2 +- .../EventListener/CsrfValidationListener.php | 22 ++++-- Extension/Csrf/Type/FormTypeCsrfExtension.php | 44 +++++++---- Extension/Templating/TemplatingExtension.php | 15 +++- FormRenderer.php | 22 ++++-- Tests/AbstractDivLayoutTest.php | 7 +- Tests/AbstractLayoutTest.php | 8 +- Tests/AbstractTableLayoutTest.php | 7 +- .../CsrfValidationListenerTest.php | 8 +- .../Csrf/Type/FormTypeCsrfExtensionTest.php | 65 ++++++++-------- 16 files changed, 305 insertions(+), 121 deletions(-) create mode 100644 Extension/Csrf/CsrfProvider/CsrfProviderAdapter.php delete mode 100644 Extension/Csrf/CsrfProvider/CsrfTokenGeneratorAdapter.php create mode 100644 Extension/Csrf/CsrfProvider/CsrfTokenManagerAdapter.php diff --git a/Extension/Csrf/CsrfExtension.php b/Extension/Csrf/CsrfExtension.php index bdaa94fe36..32345a1a1a 100644 --- a/Extension/Csrf/CsrfExtension.php +++ b/Extension/Csrf/CsrfExtension.php @@ -11,9 +11,12 @@ namespace Symfony\Component\Form\Extension\Csrf; +use Symfony\Component\Form\Exception\UnexpectedTypeException; +use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; +use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Form\Extension\Csrf\Type; use Symfony\Component\Form\AbstractExtension; -use Symfony\Component\Security\Csrf\CsrfTokenGeneratorInterface; +use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Translation\TranslatorInterface; /** @@ -24,9 +27,9 @@ class CsrfExtension extends AbstractExtension { /** - * @var CsrfTokenGeneratorInterface + * @var CsrfTokenManagerInterface */ - private $tokenGenerator; + private $tokenManager; /** * @var TranslatorInterface @@ -41,13 +44,19 @@ class CsrfExtension extends AbstractExtension /** * Constructor. * - * @param CsrfTokenGeneratorInterface $tokenGenerator The CSRF token generator - * @param TranslatorInterface $translator The translator for translating error messages - * @param null|string $translationDomain The translation domain for translating + * @param CsrfTokenManagerInterface $tokenManager The CSRF token manager + * @param TranslatorInterface $translator The translator for translating error messages + * @param null|string $translationDomain The translation domain for translating */ - public function __construct(CsrfTokenGeneratorInterface $tokenGenerator, TranslatorInterface $translator = null, $translationDomain = null) + public function __construct($tokenManager, TranslatorInterface $translator = null, $translationDomain = null) { - $this->tokenGenerator = $tokenGenerator; + if ($tokenManager instanceof CsrfProviderInterface) { + $tokenManager = new CsrfProviderAdapter($tokenManager); + } elseif (!$tokenManager instanceof CsrfTokenManagerInterface) { + throw new UnexpectedTypeException($tokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface'); + } + + $this->tokenManager = $tokenManager; $this->translator = $translator; $this->translationDomain = $translationDomain; } @@ -58,7 +67,7 @@ public function __construct(CsrfTokenGeneratorInterface $tokenGenerator, Transla protected function loadTypeExtensions() { return array( - new Type\FormTypeCsrfExtension($this->tokenGenerator, true, '_token', $this->translator, $this->translationDomain), + new Type\FormTypeCsrfExtension($this->tokenManager, true, '_token', $this->translator, $this->translationDomain), ); } } diff --git a/Extension/Csrf/CsrfProvider/CsrfProviderAdapter.php b/Extension/Csrf/CsrfProvider/CsrfProviderAdapter.php new file mode 100644 index 0000000000..01753135eb --- /dev/null +++ b/Extension/Csrf/CsrfProvider/CsrfProviderAdapter.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider; + +use Symfony\Component\Form\Exception\BadMethodCallException; +use Symfony\Component\Security\Csrf\CsrfToken; +use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; + +/** + * Adapter for using old CSRF providers where the new {@link CsrfTokenManagerInterface} + * is expected. + * + * @since 2.4 + * @author Bernhard Schussek + * + * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. + */ +class CsrfProviderAdapter implements CsrfTokenManagerInterface +{ + /** + * @var CsrfProviderInterface + */ + private $csrfProvider; + + public function __construct(CsrfProviderInterface $csrfProvider) + { + $this->csrfProvider = $csrfProvider; + } + + public function getCsrfProvider() + { + return $this->csrfProvider; + } + + /** + * {@inheritdoc} + */ + public function getToken($tokenId) + { + return $this->csrfProvider->generateCsrfToken($tokenId); + } + + /** + * {@inheritdoc} + */ + public function refreshToken($tokenId) + { + throw new BadMethodCallException('Not supported'); + } + + /** + * {@inheritdoc} + */ + public function removeToken($tokenId) + { + throw new BadMethodCallException('Not supported'); + } + + /** + * {@inheritdoc} + */ + public function isTokenValid(CsrfToken $token) + { + return $this->csrfProvider->isCsrfTokenValid($token->getId(), $token->getValue()); + } +} diff --git a/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php b/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php index 1f10f56b68..abd681626c 100644 --- a/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php +++ b/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php @@ -11,16 +11,45 @@ namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider; -use Symfony\Component\Security\Csrf\CsrfTokenGeneratorInterface; - /** - * Alias interface of {@link CsrfTokenGeneratorInterface}. + * Marks classes able to provide CSRF protection + * + * You can generate a CSRF token by using the method generateCsrfToken(). To + * this method you should pass a value that is unique to the page that should + * be secured against CSRF attacks. This value doesn't necessarily have to be + * secret. Implementations of this interface are responsible for adding more + * secret information. + * + * If you want to secure a form submission against CSRF attacks, you could + * supply an "intention" string. This way you make sure that the form can only + * be submitted to pages that are designed to handle the form, that is, that use + * the same intention string to validate the CSRF token with isCsrfTokenValid(). * * @author Bernhard Schussek * * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. Use - * {@link CsrfTokenGeneratorInterface} instead. + * {@link \Symfony\Component\Security\Csrf\CsrfTokenManagerInterface} + * instead. */ -interface CsrfProviderInterface extends CsrfTokenGeneratorInterface +interface CsrfProviderInterface { + /** + * Generates a CSRF token for a page of your application. + * + * @param string $intention Some value that identifies the action intention + * (i.e. "authenticate"). Doesn't have to be a secret value. + * + * @return string The generated token + */ + public function generateCsrfToken($intention); + + /** + * Validates a CSRF token. + * + * @param string $intention The intention used when generating the CSRF token + * @param string $token The token supplied by the browser + * + * @return Boolean Whether the token supplied by the browser is correct + */ + public function isCsrfTokenValid($intention, $token); } diff --git a/Extension/Csrf/CsrfProvider/CsrfTokenGeneratorAdapter.php b/Extension/Csrf/CsrfProvider/CsrfTokenGeneratorAdapter.php deleted file mode 100644 index 07af17d237..0000000000 --- a/Extension/Csrf/CsrfProvider/CsrfTokenGeneratorAdapter.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider; - -use Symfony\Component\Security\Csrf\CsrfTokenGenerator; - -/** - * Adapter for using the new token generator with the old interface. - * - * @since 2.4 - * @author Bernhard Schussek - * - * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. - */ -class CsrfTokenGeneratorAdapter extends CsrfTokenGenerator implements CsrfProviderInterface -{ -} diff --git a/Extension/Csrf/CsrfProvider/CsrfTokenManagerAdapter.php b/Extension/Csrf/CsrfProvider/CsrfTokenManagerAdapter.php new file mode 100644 index 0000000000..5dbffc2cbc --- /dev/null +++ b/Extension/Csrf/CsrfProvider/CsrfTokenManagerAdapter.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider; + +use Symfony\Component\Security\Csrf\CsrfToken; +use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; + +/** + * Adapter for using the new token generator with the old interface. + * + * @since 2.4 + * @author Bernhard Schussek + * + * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. + */ +class CsrfTokenManagerAdapter implements CsrfProviderInterface +{ + /** + * @var CsrfTokenManagerInterface + */ + private $tokenManager; + + public function __construct(CsrfTokenManagerInterface $tokenManager) + { + $this->tokenManager = $tokenManager; + } + + public function getTokenManager() + { + return $this->tokenManager; + } + + /** + * {@inheritdoc} + */ + public function generateCsrfToken($intention) + { + return $this->tokenManager->getToken($intention)->getValue(); + } + + /** + * {@inheritdoc} + */ + public function isCsrfTokenValid($intention, $token) + { + return $this->tokenManager->isTokenValid(new CsrfToken($intention, $token)); + } +} diff --git a/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php b/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php index 9fb971f966..db6cde97fc 100644 --- a/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php +++ b/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php @@ -20,7 +20,7 @@ * @author Bernhard Schussek * * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. Use - * {@link \Symfony\Component\Security\Csrf\CsrfTokenGenerator} in + * {@link \Symfony\Component\Security\Csrf\CsrfTokenManager} in * combination with {@link \Symfony\Component\Security\Csrf\TokenStorage\NativeSessionTokenStorage} * instead. */ diff --git a/Extension/Csrf/CsrfProvider/SessionCsrfProvider.php b/Extension/Csrf/CsrfProvider/SessionCsrfProvider.php index 84381adfc8..741db1ec23 100644 --- a/Extension/Csrf/CsrfProvider/SessionCsrfProvider.php +++ b/Extension/Csrf/CsrfProvider/SessionCsrfProvider.php @@ -22,7 +22,7 @@ * @author Bernhard Schussek * * @deprecated Deprecated since version 2.4, to be removed in Symfony 3.0. Use - * {@link \Symfony\Component\Security\Csrf\CsrfTokenGenerator} in + * {@link \Symfony\Component\Security\Csrf\CsrfTokenManager} in * combination with {@link \Symfony\Component\Security\Csrf\TokenStorage\SessionTokenStorage} * instead. */ diff --git a/Extension/Csrf/EventListener/CsrfValidationListener.php b/Extension/Csrf/EventListener/CsrfValidationListener.php index 70665f0fb7..4e7bc553a9 100644 --- a/Extension/Csrf/EventListener/CsrfValidationListener.php +++ b/Extension/Csrf/EventListener/CsrfValidationListener.php @@ -12,10 +12,14 @@ namespace Symfony\Component\Form\Extension\Csrf\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\Form\Exception\UnexpectedTypeException; +use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; +use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormEvent; -use Symfony\Component\Security\Csrf\CsrfTokenGeneratorInterface; +use Symfony\Component\Security\Csrf\CsrfToken; +use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Translation\TranslatorInterface; /** @@ -31,9 +35,9 @@ class CsrfValidationListener implements EventSubscriberInterface /** * The generator for CSRF tokens - * @var CsrfTokenGeneratorInterface + * @var CsrfTokenManagerInterface */ - private $tokenGenerator; + private $tokenManager; /** * A text mentioning the tokenId of the CSRF token @@ -68,10 +72,16 @@ public static function getSubscribedEvents() ); } - public function __construct($fieldName, CsrfTokenGeneratorInterface $tokenGenerator, $tokenId, $errorMessage, TranslatorInterface $translator = null, $translationDomain = null) + public function __construct($fieldName, $tokenManager, $tokenId, $errorMessage, TranslatorInterface $translator = null, $translationDomain = null) { + if ($tokenManager instanceof CsrfProviderInterface) { + $tokenManager = new CsrfProviderAdapter($tokenManager); + } elseif (!$tokenManager instanceof CsrfTokenManagerInterface) { + throw new UnexpectedTypeException($tokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface'); + } + $this->fieldName = $fieldName; - $this->tokenGenerator = $tokenGenerator; + $this->tokenManager = $tokenManager; $this->tokenId = $tokenId; $this->errorMessage = $errorMessage; $this->translator = $translator; @@ -84,7 +94,7 @@ public function preSubmit(FormEvent $event) $data = $event->getData(); if ($form->isRoot() && $form->getConfig()->getOption('compound')) { - if (!isset($data[$this->fieldName]) || !$this->tokenGenerator->isCsrfTokenValid($this->tokenId, $data[$this->fieldName])) { + if (!isset($data[$this->fieldName]) || !$this->tokenManager->isTokenValid(new CsrfToken($this->tokenId, $data[$this->fieldName]))) { $errorMessage = $this->errorMessage; if (null !== $this->translator) { diff --git a/Extension/Csrf/Type/FormTypeCsrfExtension.php b/Extension/Csrf/Type/FormTypeCsrfExtension.php index 1958c0f266..2f90a924fa 100644 --- a/Extension/Csrf/Type/FormTypeCsrfExtension.php +++ b/Extension/Csrf/Type/FormTypeCsrfExtension.php @@ -12,13 +12,17 @@ namespace Symfony\Component\Form\Extension\Csrf\Type; use Symfony\Component\Form\AbstractTypeExtension; +use Symfony\Component\Form\Exception\UnexpectedTypeException; +use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; +use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; +use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfTokenManagerAdapter; use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormView; use Symfony\Component\Form\FormInterface; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; -use Symfony\Component\Security\Csrf\CsrfTokenGeneratorInterface; +use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Translation\TranslatorInterface; /** @@ -27,9 +31,9 @@ class FormTypeCsrfExtension extends AbstractTypeExtension { /** - * @var CsrfTokenGeneratorInterface + * @var CsrfTokenManagerInterface */ - private $defaultTokenGenerator; + private $defaultTokenManager; /** * @var Boolean @@ -51,9 +55,15 @@ class FormTypeCsrfExtension extends AbstractTypeExtension */ private $translationDomain; - public function __construct(CsrfTokenGeneratorInterface $defaultTokenGenerator, $defaultEnabled = true, $defaultFieldName = '_token', TranslatorInterface $translator = null, $translationDomain = null) + public function __construct($defaultTokenManager, $defaultEnabled = true, $defaultFieldName = '_token', TranslatorInterface $translator = null, $translationDomain = null) { - $this->defaultTokenGenerator = $defaultTokenGenerator; + if ($defaultTokenManager instanceof CsrfProviderInterface) { + $defaultTokenManager = new CsrfProviderAdapter($defaultTokenManager); + } elseif (!$defaultTokenManager instanceof CsrfTokenManagerInterface) { + throw new UnexpectedTypeException($defaultTokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface'); + } + + $this->defaultTokenManager = $defaultTokenManager; $this->defaultEnabled = $defaultEnabled; $this->defaultFieldName = $defaultFieldName; $this->translator = $translator; @@ -75,7 +85,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) $builder ->addEventSubscriber(new CsrfValidationListener( $options['csrf_field_name'], - $options['csrf_token_generator'], + $options['csrf_token_manager'], $options['csrf_token_id'], $options['csrf_message'], $this->translator, @@ -95,7 +105,7 @@ public function finishView(FormView $view, FormInterface $form, array $options) { if ($options['csrf_protection'] && !$view->parent && $options['compound']) { $factory = $form->getConfig()->getFormFactory(); - $data = $options['csrf_token_generator']->generateCsrfToken($options['csrf_token_id']); + $data = (string) $options['csrf_token_manager']->getToken($options['csrf_token_id']); $csrfForm = $factory->createNamed($options['csrf_field_name'], 'hidden', $data, array( 'mapped' => false, @@ -116,18 +126,20 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) }; // BC clause for the "csrf_provider" option - $csrfTokenGenerator = function (Options $options) { - return $options['csrf_provider']; + $csrfTokenManager = function (Options $options) { + return $options['csrf_provider'] instanceof CsrfTokenManagerAdapter + ? $options['csrf_provider']->getTokenManager() + : new CsrfProviderAdapter($options['csrf_provider']); }; $resolver->setDefaults(array( - 'csrf_protection' => $this->defaultEnabled, - 'csrf_field_name' => $this->defaultFieldName, - 'csrf_message' => 'The CSRF token is invalid. Please try to resubmit the form.', - 'csrf_token_generator' => $csrfTokenGenerator, - 'csrf_token_id' => $csrfTokenId, - 'csrf_provider' => $this->defaultTokenGenerator, - 'intention' => 'unknown', + 'csrf_protection' => $this->defaultEnabled, + 'csrf_field_name' => $this->defaultFieldName, + 'csrf_message' => 'The CSRF token is invalid. Please try to resubmit the form.', + 'csrf_token_manager' => $csrfTokenManager, + 'csrf_token_id' => $csrfTokenId, + 'csrf_provider' => new CsrfTokenManagerAdapter($this->defaultTokenManager), + 'intention' => 'unknown', )); } diff --git a/Extension/Templating/TemplatingExtension.php b/Extension/Templating/TemplatingExtension.php index e3b239873e..09185a3e4d 100644 --- a/Extension/Templating/TemplatingExtension.php +++ b/Extension/Templating/TemplatingExtension.php @@ -12,8 +12,11 @@ namespace Symfony\Component\Form\Extension\Templating; use Symfony\Component\Form\AbstractExtension; +use Symfony\Component\Form\Exception\UnexpectedTypeException; +use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; +use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Form\FormRenderer; -use Symfony\Component\Security\Csrf\CsrfTokenGeneratorInterface; +use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Symfony\Component\Templating\PhpEngine; use Symfony\Bundle\FrameworkBundle\Templating\Helper\FormHelper; @@ -24,10 +27,16 @@ */ class TemplatingExtension extends AbstractExtension { - public function __construct(PhpEngine $engine, CsrfTokenGeneratorInterface $csrfTokenGenerator = null, array $defaultThemes = array()) + public function __construct(PhpEngine $engine, $csrfTokenManager = null, array $defaultThemes = array()) { + if ($csrfTokenManager instanceof CsrfProviderInterface) { + $csrfTokenManager = new CsrfProviderAdapter($csrfTokenManager); + } elseif (null !== $csrfTokenManager && !$csrfTokenManager instanceof CsrfTokenManagerInterface) { + throw new UnexpectedTypeException($csrfTokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface'); + } + $engine->addHelpers(array( - new FormHelper(new FormRenderer(new TemplatingRendererEngine($engine, $defaultThemes), $csrfTokenGenerator)) + new FormHelper(new FormRenderer(new TemplatingRendererEngine($engine, $defaultThemes), $csrfTokenManager)) )); } } diff --git a/FormRenderer.php b/FormRenderer.php index 59ccc0c31a..207c1ed6b2 100644 --- a/FormRenderer.php +++ b/FormRenderer.php @@ -13,7 +13,7 @@ use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\Exception\BadMethodCallException; -use Symfony\Component\Security\Csrf\CsrfTokenGeneratorInterface; +use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; /** * Renders a form into HTML using a rendering engine. @@ -30,9 +30,9 @@ class FormRenderer implements FormRendererInterface private $engine; /** - * @var CsrfTokenGeneratorInterface + * @var CsrfTokenManagerInterface */ - private $csrfTokenGenerator; + private $csrfTokenManager; /** * @var array @@ -49,10 +49,16 @@ class FormRenderer implements FormRendererInterface */ private $variableStack = array(); - public function __construct(FormRendererEngineInterface $engine, CsrfTokenGeneratorInterface $csrfTokenGenerator = null) + public function __construct(FormRendererEngineInterface $engine, $csrfTokenManager = null) { + if ($csrfTokenManager instanceof CsrfProviderInterface) { + $csrfTokenManager = new CsrfProviderAdapter($csrfTokenManager); + } elseif (null !== $csrfTokenManager && !$csrfTokenManager instanceof CsrfTokenManagerInterface) { + throw new UnexpectedTypeException($csrfTokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface'); + } + $this->engine = $engine; - $this->csrfTokenGenerator = $csrfTokenGenerator; + $this->csrfTokenManager = $csrfTokenManager; } /** @@ -76,11 +82,11 @@ public function setTheme(FormView $view, $themes) */ public function renderCsrfToken($tokenId) { - if (null === $this->csrfTokenGenerator) { - throw new BadMethodCallException('CSRF tokens can only be generated if a CsrfTokenGeneratorInterface is injected in FormRenderer::__construct().'); + if (null === $this->csrfTokenManager) { + throw new BadMethodCallException('CSRF tokens can only be generated if a CsrfTokenManagerInterface is injected in FormRenderer::__construct().'); } - return $this->csrfTokenGenerator->generateCsrfToken($tokenId); + return $this->csrfTokenManager->getToken($tokenId)->getValue(); } /** diff --git a/Tests/AbstractDivLayoutTest.php b/Tests/AbstractDivLayoutTest.php index 7395c7e097..2d32aa38a3 100644 --- a/Tests/AbstractDivLayoutTest.php +++ b/Tests/AbstractDivLayoutTest.php @@ -13,6 +13,7 @@ use Symfony\Component\Form\FormError; use Symfony\Component\Form\Tests\Fixtures\AlternatingRowType; +use Symfony\Component\Security\Csrf\CsrfToken; abstract class AbstractDivLayoutTest extends AbstractLayoutTest { @@ -471,9 +472,9 @@ public function testNestedFormError() public function testCsrf() { - $this->csrfTokenGenerator->expects($this->any()) - ->method('generateCsrfToken') - ->will($this->returnValue('foo&bar')); + $this->csrfTokenManager->expects($this->any()) + ->method('getToken') + ->will($this->returnValue(new CsrfToken('token_id', 'foo&bar'))); $form = $this->factory->createNamedBuilder('name', 'form') ->add($this->factory diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index c35235b862..edecb30a89 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -17,7 +17,7 @@ abstract class AbstractLayoutTest extends \Symfony\Component\Form\Test\FormIntegrationTestCase { - protected $csrfTokenGenerator; + protected $csrfTokenManager; protected function setUp() { @@ -27,7 +27,7 @@ protected function setUp() \Locale::setDefault('en'); - $this->csrfTokenGenerator = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenGeneratorInterface'); + $this->csrfTokenManager = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface'); parent::setUp(); } @@ -35,13 +35,13 @@ protected function setUp() protected function getExtensions() { return array( - new CsrfExtension($this->csrfTokenGenerator), + new CsrfExtension($this->csrfTokenManager), ); } protected function tearDown() { - $this->csrfTokenGenerator = null; + $this->csrfTokenManager = null; parent::tearDown(); } diff --git a/Tests/AbstractTableLayoutTest.php b/Tests/AbstractTableLayoutTest.php index f43188a914..5c8a9be2d5 100644 --- a/Tests/AbstractTableLayoutTest.php +++ b/Tests/AbstractTableLayoutTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\FormError; +use Symfony\Component\Security\Csrf\CsrfToken; abstract class AbstractTableLayoutTest extends AbstractLayoutTest { @@ -336,9 +337,9 @@ public function testNestedFormError() public function testCsrf() { - $this->csrfTokenGenerator->expects($this->any()) - ->method('generateCsrfToken') - ->will($this->returnValue('foo&bar')); + $this->csrfTokenManager->expects($this->any()) + ->method('getToken') + ->will($this->returnValue(new CsrfToken('token_id', 'foo&bar'))); $form = $this->factory->createNamedBuilder('name', 'form') ->add($this->factory diff --git a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php index b3e45ab984..ef013ca82b 100644 --- a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php +++ b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php @@ -19,14 +19,14 @@ class CsrfValidationListenerTest extends \PHPUnit_Framework_TestCase { protected $dispatcher; protected $factory; - protected $tokenGenerator; + protected $tokenManager; protected $form; protected function setUp() { $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); - $this->tokenGenerator = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenGeneratorInterface'); + $this->tokenManager = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface'); $this->form = $this->getBuilder('post') ->setDataMapper($this->getDataMapper()) ->getForm(); @@ -36,7 +36,7 @@ protected function tearDown() { $this->dispatcher = null; $this->factory = null; - $this->tokenGenerator = null; + $this->tokenManager = null; $this->form = null; } @@ -66,7 +66,7 @@ public function testStringFormData() $data = "XP4HUzmHPi"; $event = new FormEvent($this->form, $data); - $validation = new CsrfValidationListener('csrf', $this->tokenGenerator, 'unknown', 'Invalid.'); + $validation = new CsrfValidationListener('csrf', $this->tokenManager, 'unknown', 'Invalid.'); $validation->preSubmit($event); // Validate accordingly diff --git a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php index ccd7dccbca..962cbdf134 100644 --- a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php +++ b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php @@ -16,6 +16,7 @@ use Symfony\Component\Form\FormError; use Symfony\Component\Form\Test\TypeTestCase; use Symfony\Component\Form\Extension\Csrf\CsrfExtension; +use Symfony\Component\Security\Csrf\CsrfToken; class FormTypeCsrfExtensionTest_ChildType extends AbstractType { @@ -37,7 +38,7 @@ class FormTypeCsrfExtensionTest extends TypeTestCase /** * @var \PHPUnit_Framework_MockObject_MockObject */ - protected $tokenGenerator; + protected $tokenManager; /** * @var \PHPUnit_Framework_MockObject_MockObject @@ -46,7 +47,7 @@ class FormTypeCsrfExtensionTest extends TypeTestCase protected function setUp() { - $this->tokenGenerator = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenGeneratorInterface'); + $this->tokenManager = $this->getMock('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface'); $this->translator = $this->getMock('Symfony\Component\Translation\TranslatorInterface'); parent::setUp(); @@ -54,7 +55,7 @@ protected function setUp() protected function tearDown() { - $this->tokenGenerator = null; + $this->tokenManager = null; $this->translator = null; parent::tearDown(); @@ -63,7 +64,7 @@ protected function tearDown() protected function getExtensions() { return array_merge(parent::getExtensions(), array( - new CsrfExtension($this->tokenGenerator, $this->translator), + new CsrfExtension($this->tokenManager, $this->translator), )); } @@ -123,16 +124,16 @@ public function testCsrfProtectionCanBeDisabled() public function testGenerateCsrfToken() { - $this->tokenGenerator->expects($this->once()) - ->method('generateCsrfToken') - ->with('%INTENTION%') - ->will($this->returnValue('token')); + $this->tokenManager->expects($this->once()) + ->method('getToken') + ->with('TOKEN_ID') + ->will($this->returnValue(new CsrfToken('TOKEN_ID', 'token'))); $view = $this->factory ->create('form', null, array( 'csrf_field_name' => 'csrf', - 'csrf_provider' => $this->tokenGenerator, - 'intention' => '%INTENTION%', + 'csrf_token_manager' => $this->tokenManager, + 'csrf_token_id' => 'TOKEN_ID', 'compound' => true, )) ->createView(); @@ -153,16 +154,16 @@ public function provideBoolean() */ public function testValidateTokenOnSubmitIfRootAndCompound($valid) { - $this->tokenGenerator->expects($this->once()) - ->method('isCsrfTokenValid') - ->with('%INTENTION%', 'token') + $this->tokenManager->expects($this->once()) + ->method('isTokenValid') + ->with(new CsrfToken('TOKEN_ID', 'token')) ->will($this->returnValue($valid)); $form = $this->factory ->createBuilder('form', null, array( 'csrf_field_name' => 'csrf', - 'csrf_provider' => $this->tokenGenerator, - 'intention' => '%INTENTION%', + 'csrf_token_manager' => $this->tokenManager, + 'csrf_token_id' => 'TOKEN_ID', 'compound' => true, )) ->add('child', 'text') @@ -182,14 +183,14 @@ public function testValidateTokenOnSubmitIfRootAndCompound($valid) public function testFailIfRootAndCompoundAndTokenMissing() { - $this->tokenGenerator->expects($this->never()) - ->method('isCsrfTokenValid'); + $this->tokenManager->expects($this->never()) + ->method('isTokenValid'); $form = $this->factory ->createBuilder('form', null, array( 'csrf_field_name' => 'csrf', - 'csrf_provider' => $this->tokenGenerator, - 'intention' => '%INTENTION%', + 'csrf_token_manager' => $this->tokenManager, + 'csrf_token_id' => 'TOKEN_ID', 'compound' => true, )) ->add('child', 'text') @@ -209,16 +210,16 @@ public function testFailIfRootAndCompoundAndTokenMissing() public function testDontValidateTokenIfCompoundButNoRoot() { - $this->tokenGenerator->expects($this->never()) - ->method('isCsrfTokenValid'); + $this->tokenManager->expects($this->never()) + ->method('isTokenValid'); $form = $this->factory ->createNamedBuilder('root', 'form') ->add($this->factory ->createNamedBuilder('form', 'form', null, array( 'csrf_field_name' => 'csrf', - 'csrf_provider' => $this->tokenGenerator, - 'intention' => '%INTENTION%', + 'csrf_token_manager' => $this->tokenManager, + 'csrf_token_id' => 'TOKEN_ID', 'compound' => true, )) ) @@ -233,14 +234,14 @@ public function testDontValidateTokenIfCompoundButNoRoot() public function testDontValidateTokenIfRootButNotCompound() { - $this->tokenGenerator->expects($this->never()) - ->method('isCsrfTokenValid'); + $this->tokenManager->expects($this->never()) + ->method('isTokenValid'); $form = $this->factory ->create('form', null, array( 'csrf_field_name' => 'csrf', - 'csrf_provider' => $this->tokenGenerator, - 'intention' => '%INTENTION%', + 'csrf_token_manager' => $this->tokenManager, + 'csrf_token_id' => 'TOKEN_ID', 'compound' => false, )); @@ -269,9 +270,9 @@ public function testNoCsrfProtectionOnPrototype() public function testsTranslateCustomErrorMessage() { - $this->tokenGenerator->expects($this->once()) - ->method('isCsrfTokenValid') - ->with('%INTENTION%', 'token') + $this->tokenManager->expects($this->once()) + ->method('isTokenValid') + ->with(new CsrfToken('TOKEN_ID', 'token')) ->will($this->returnValue(false)); $this->translator->expects($this->once()) @@ -282,9 +283,9 @@ public function testsTranslateCustomErrorMessage() $form = $this->factory ->createBuilder('form', null, array( 'csrf_field_name' => 'csrf', - 'csrf_provider' => $this->tokenGenerator, + 'csrf_token_manager' => $this->tokenManager, 'csrf_message' => 'Foobar', - 'intention' => '%INTENTION%', + 'csrf_token_id' => 'TOKEN_ID', 'compound' => true, )) ->getForm(); From 9fc1671df63980893545cb2a7381139d3932880f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Augustin?= Date: Mon, 7 Oct 2013 19:12:10 +0200 Subject: [PATCH 209/447] [form] fix missing use statement for exception UnexpectedTypeException --- FormRenderer.php | 1 + 1 file changed, 1 insertion(+) diff --git a/FormRenderer.php b/FormRenderer.php index 207c1ed6b2..c3d0548977 100644 --- a/FormRenderer.php +++ b/FormRenderer.php @@ -13,6 +13,7 @@ use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\Exception\BadMethodCallException; +use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; /** From 705b54067519f9f96cbb99a18c424cfe9c3e8c20 Mon Sep 17 00:00:00 2001 From: Eric GELOEN Date: Tue, 15 Oct 2013 21:08:05 +0200 Subject: [PATCH 210/447] [Form] Add missing use in form renderer --- FormRenderer.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/FormRenderer.php b/FormRenderer.php index c3d0548977..b81483bce2 100644 --- a/FormRenderer.php +++ b/FormRenderer.php @@ -14,6 +14,8 @@ use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\Exception\BadMethodCallException; use Symfony\Component\Form\Exception\UnexpectedTypeException; +use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; +use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; /** From aecac53a91237f7d4796941d58e3437f431dbfc6 Mon Sep 17 00:00:00 2001 From: Hugo Hamon Date: Wed, 16 Oct 2013 13:59:56 +0200 Subject: [PATCH 211/447] Removed dead code (unused use statements). --- .../Proxy/ResolvedTypeFactoryDataCollectorProxy.php | 1 - Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php | 1 - Tests/Extension/DataCollector/FormDataCollectorTest.php | 1 - 3 files changed, 3 deletions(-) diff --git a/Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.php b/Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.php index f15b720585..c2cb3a0346 100644 --- a/Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.php +++ b/Extension/DataCollector/Proxy/ResolvedTypeFactoryDataCollectorProxy.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Form\Extension\DataCollector\Proxy; -use Symfony\Component\Form\Exception; use Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface; use Symfony\Component\Form\FormTypeInterface; use Symfony\Component\Form\ResolvedFormTypeFactoryInterface; diff --git a/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php b/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php index 2b57288fb7..fea0dad9ea 100644 --- a/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; -use Symfony\Component\Form\Extension\Core\View\ChoiceView; class SimpleNumericChoiceListTest extends AbstractChoiceListTest { diff --git a/Tests/Extension/DataCollector/FormDataCollectorTest.php b/Tests/Extension/DataCollector/FormDataCollectorTest.php index c31f62c7e0..c1e21d8c51 100644 --- a/Tests/Extension/DataCollector/FormDataCollectorTest.php +++ b/Tests/Extension/DataCollector/FormDataCollectorTest.php @@ -13,7 +13,6 @@ use Symfony\Component\Form\Extension\DataCollector\FormDataCollector; use Symfony\Component\Form\Form; use Symfony\Component\Form\FormBuilder; -use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\FormView; class FormDataCollectorTest extends \PHPUnit_Framework_TestCase From 6ce41db0098ec3072bb4ff3fa26bd1dbe90d02ff Mon Sep 17 00:00:00 2001 From: Hugo Hamon Date: Wed, 16 Oct 2013 14:19:20 +0200 Subject: [PATCH 212/447] Removed unused use statements. --- Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php b/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php index 2b57288fb7..fea0dad9ea 100644 --- a/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Form\Tests\Extension\Core\ChoiceList; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; -use Symfony\Component\Form\Extension\Core\View\ChoiceView; class SimpleNumericChoiceListTest extends AbstractChoiceListTest { From 31e086a829079890e5f2302c7c11365ba2d10997 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 17 Oct 2013 17:52:50 +0200 Subject: [PATCH 213/447] [Form] Changed FormTypeCsrfExtension to use the form's name as default intention --- Extension/Csrf/Type/FormTypeCsrfExtension.php | 10 ++-- .../Csrf/Type/FormTypeCsrfExtensionTest.php | 49 +++++++++++++++++++ 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/Extension/Csrf/Type/FormTypeCsrfExtension.php b/Extension/Csrf/Type/FormTypeCsrfExtension.php index ea13056c86..6ccc5be5e4 100644 --- a/Extension/Csrf/Type/FormTypeCsrfExtension.php +++ b/Extension/Csrf/Type/FormTypeCsrfExtension.php @@ -49,7 +49,11 @@ public function buildForm(FormBuilderInterface $builder, array $options) $builder ->setAttribute('csrf_factory', $builder->getFormFactory()) - ->addEventSubscriber(new CsrfValidationListener($options['csrf_field_name'], $options['csrf_provider'], $options['intention'])) + ->addEventSubscriber(new CsrfValidationListener( + $options['csrf_field_name'], + $options['csrf_provider'], + $options['intention'] ?: $builder->getName() + )) ; } @@ -64,7 +68,7 @@ public function finishView(FormView $view, FormInterface $form, array $options) { if ($options['csrf_protection'] && !$view->parent && $options['compound']) { $factory = $form->getConfig()->getAttribute('csrf_factory'); - $data = $options['csrf_provider']->generateCsrfToken($options['intention']); + $data = $options['csrf_provider']->generateCsrfToken($options['intention'] ?: $form->getName()); $csrfForm = $factory->createNamed($options['csrf_field_name'], 'hidden', $data, array( 'mapped' => false, @@ -83,7 +87,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'csrf_protection' => $this->defaultEnabled, 'csrf_field_name' => $this->defaultFieldName, 'csrf_provider' => $this->defaultCsrfProvider, - 'intention' => 'unknown', + 'intention' => null, )); } diff --git a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php index 47dd529270..3ee91e01e9 100644 --- a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php +++ b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php @@ -129,6 +129,24 @@ public function testGenerateCsrfToken() $this->assertEquals('token', $view['csrf']->vars['value']); } + public function testGenerateCsrfTokenUsesFormNameAsIntentionByDefault() + { + $this->csrfProvider->expects($this->once()) + ->method('generateCsrfToken') + ->with('FORM_NAME') + ->will($this->returnValue('token')); + + $view = $this->factory + ->createNamed('FORM_NAME', 'form', null, array( + 'csrf_field_name' => 'csrf', + 'csrf_provider' => $this->csrfProvider, + 'compound' => true, + )) + ->createView(); + + $this->assertEquals('token', $view['csrf']->vars['value']); + } + public function provideBoolean() { return array( @@ -169,6 +187,37 @@ public function testValidateTokenOnBindIfRootAndCompound($valid) $this->assertSame($valid, $form->isValid()); } + /** + * @dataProvider provideBoolean + */ + public function testValidateTokenOnBindIfRootAndCompoundUsesFormNameAsIntentionByDefault($valid) + { + $this->csrfProvider->expects($this->once()) + ->method('isCsrfTokenValid') + ->with('FORM_NAME', 'token') + ->will($this->returnValue($valid)); + + $form = $this->factory + ->createNamedBuilder('FORM_NAME', 'form', null, array( + 'csrf_field_name' => 'csrf', + 'csrf_provider' => $this->csrfProvider, + 'compound' => true, + )) + ->add('child', 'text') + ->getForm(); + + $form->bind(array( + 'child' => 'foobar', + 'csrf' => 'token', + )); + + // Remove token from data + $this->assertSame(array('child' => 'foobar'), $form->getData()); + + // Validate accordingly + $this->assertSame($valid, $form->isValid()); + } + public function testFailIfRootAndCompoundAndTokenMissing() { $this->csrfProvider->expects($this->never()) From 314d7fe0d52b5b71e97a9054d57e5a4b4f83d04a Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 18 Oct 2013 13:07:56 +0200 Subject: [PATCH 214/447] [Intl] Improved FormTypeCsrfExtension to use the type class as default intention if the form name is empty --- Extension/Csrf/Type/FormTypeCsrfExtension.php | 5 +- .../Csrf/Type/FormTypeCsrfExtensionTest.php | 49 +++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/Extension/Csrf/Type/FormTypeCsrfExtension.php b/Extension/Csrf/Type/FormTypeCsrfExtension.php index 6ccc5be5e4..360121da8d 100644 --- a/Extension/Csrf/Type/FormTypeCsrfExtension.php +++ b/Extension/Csrf/Type/FormTypeCsrfExtension.php @@ -52,7 +52,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) ->addEventSubscriber(new CsrfValidationListener( $options['csrf_field_name'], $options['csrf_provider'], - $options['intention'] ?: $builder->getName() + $options['intention'] ?: ($builder->getName() ?: get_class($builder->getType()->getInnerType())) )) ; } @@ -68,7 +68,8 @@ public function finishView(FormView $view, FormInterface $form, array $options) { if ($options['csrf_protection'] && !$view->parent && $options['compound']) { $factory = $form->getConfig()->getAttribute('csrf_factory'); - $data = $options['csrf_provider']->generateCsrfToken($options['intention'] ?: $form->getName()); + $intention = $options['intention'] ?: ($form->getName() ?: get_class($form->getConfig()->getType()->getInnerType())); + $data = $options['csrf_provider']->generateCsrfToken($intention); $csrfForm = $factory->createNamed($options['csrf_field_name'], 'hidden', $data, array( 'mapped' => false, diff --git a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php index 3ee91e01e9..36fc0d44e9 100644 --- a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php +++ b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php @@ -147,6 +147,24 @@ public function testGenerateCsrfTokenUsesFormNameAsIntentionByDefault() $this->assertEquals('token', $view['csrf']->vars['value']); } + public function testGenerateCsrfTokenUsesTypeClassAsIntentionIfEmptyFormName() + { + $this->csrfProvider->expects($this->once()) + ->method('generateCsrfToken') + ->with('Symfony\Component\Form\Extension\Core\Type\FormType') + ->will($this->returnValue('token')); + + $view = $this->factory + ->createNamed('', 'form', null, array( + 'csrf_field_name' => 'csrf', + 'csrf_provider' => $this->csrfProvider, + 'compound' => true, + )) + ->createView(); + + $this->assertEquals('token', $view['csrf']->vars['value']); + } + public function provideBoolean() { return array( @@ -218,6 +236,37 @@ public function testValidateTokenOnBindIfRootAndCompoundUsesFormNameAsIntentionB $this->assertSame($valid, $form->isValid()); } + /** + * @dataProvider provideBoolean + */ + public function testValidateTokenOnBindIfRootAndCompoundUsesTypeClassAsIntentionIfEmptyFormName($valid) + { + $this->csrfProvider->expects($this->once()) + ->method('isCsrfTokenValid') + ->with('Symfony\Component\Form\Extension\Core\Type\FormType', 'token') + ->will($this->returnValue($valid)); + + $form = $this->factory + ->createNamedBuilder('', 'form', null, array( + 'csrf_field_name' => 'csrf', + 'csrf_provider' => $this->csrfProvider, + 'compound' => true, + )) + ->add('child', 'text') + ->getForm(); + + $form->bind(array( + 'child' => 'foobar', + 'csrf' => 'token', + )); + + // Remove token from data + $this->assertSame(array('child' => 'foobar'), $form->getData()); + + // Validate accordingly + $this->assertSame($valid, $form->isValid()); + } + public function testFailIfRootAndCompoundAndTokenMissing() { $this->csrfProvider->expects($this->never()) From 95373ba8061c6ba3a931afbb05598652d56c9dd4 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 18 Oct 2013 13:07:56 +0200 Subject: [PATCH 215/447] [Intl] Improved FormTypeCsrfExtension to use the type class as default intention if the form name is empty --- Extension/Csrf/Type/FormTypeCsrfExtension.php | 5 +- .../Csrf/Type/FormTypeCsrfExtensionTest.php | 51 ++++++++++++++++++- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/Extension/Csrf/Type/FormTypeCsrfExtension.php b/Extension/Csrf/Type/FormTypeCsrfExtension.php index c42a88904e..49d97bb395 100644 --- a/Extension/Csrf/Type/FormTypeCsrfExtension.php +++ b/Extension/Csrf/Type/FormTypeCsrfExtension.php @@ -76,7 +76,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) ->addEventSubscriber(new CsrfValidationListener( $options['csrf_field_name'], $options['csrf_provider'], - $options['intention'] ?: $builder->getName(), + $options['intention'] ?: ($builder->getName() ?: get_class($builder->getType()->getInnerType())), $options['csrf_message'], $this->translator, $this->translationDomain @@ -95,7 +95,8 @@ public function finishView(FormView $view, FormInterface $form, array $options) { if ($options['csrf_protection'] && !$view->parent && $options['compound']) { $factory = $form->getConfig()->getAttribute('csrf_factory'); - $data = $options['csrf_provider']->generateCsrfToken($options['intention'] ?: $form->getName()); + $intention = $options['intention'] ?: ($form->getName() ?: get_class($form->getConfig()->getType()->getInnerType())); + $data = $options['csrf_provider']->generateCsrfToken($intention); $csrfForm = $factory->createNamed($options['csrf_field_name'], 'hidden', $data, array( 'mapped' => false, diff --git a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php index 1fa5667871..b05b1f29b1 100644 --- a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php +++ b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php @@ -158,6 +158,24 @@ public function testGenerateCsrfTokenUsesFormNameAsIntentionByDefault() $this->assertEquals('token', $view['csrf']->vars['value']); } + public function testGenerateCsrfTokenUsesTypeClassAsIntentionIfEmptyFormName() + { + $this->csrfProvider->expects($this->once()) + ->method('generateCsrfToken') + ->with('Symfony\Component\Form\Extension\Core\Type\FormType') + ->will($this->returnValue('token')); + + $view = $this->factory + ->createNamed('', 'form', null, array( + 'csrf_field_name' => 'csrf', + 'csrf_provider' => $this->csrfProvider, + 'compound' => true, + )) + ->createView(); + + $this->assertEquals('token', $view['csrf']->vars['value']); + } + public function provideBoolean() { return array( @@ -201,7 +219,7 @@ public function testValidateTokenOnSubmitIfRootAndCompound($valid) /** * @dataProvider provideBoolean */ - public function testValidateTokenOnBindIfRootAndCompoundUsesFormNameAsIntentionByDefault($valid) + public function testValidateTokenOnSubmitIfRootAndCompoundUsesFormNameAsIntentionByDefault($valid) { $this->csrfProvider->expects($this->once()) ->method('isCsrfTokenValid') @@ -229,6 +247,37 @@ public function testValidateTokenOnBindIfRootAndCompoundUsesFormNameAsIntentionB $this->assertSame($valid, $form->isValid()); } + /** + * @dataProvider provideBoolean + */ + public function testValidateTokenOnSubmitIfRootAndCompoundUsesTypeClassAsIntentionIfEmptyFormName($valid) + { + $this->csrfProvider->expects($this->once()) + ->method('isCsrfTokenValid') + ->with('Symfony\Component\Form\Extension\Core\Type\FormType', 'token') + ->will($this->returnValue($valid)); + + $form = $this->factory + ->createNamedBuilder('', 'form', null, array( + 'csrf_field_name' => 'csrf', + 'csrf_provider' => $this->csrfProvider, + 'compound' => true, + )) + ->add('child', 'text') + ->getForm(); + + $form->submit(array( + 'child' => 'foobar', + 'csrf' => 'token', + )); + + // Remove token from data + $this->assertSame(array('child' => 'foobar'), $form->getData()); + + // Validate accordingly + $this->assertSame($valid, $form->isValid()); + } + public function testFailIfRootAndCompoundAndTokenMissing() { $this->csrfProvider->expects($this->never()) From 2e9e26639b60427a62c03570b64afd257fc9ee0b Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Mon, 28 Oct 2013 10:50:26 +0100 Subject: [PATCH 216/447] [Form] Fixed: The "data" option is taken into account even if it is NULL --- Extension/Core/Type/FormType.php | 6 ++++-- Tests/Extension/Core/Type/FormTypeTest.php | 12 ++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Extension/Core/Type/FormType.php b/Extension/Core/Type/FormType.php index 8e089bd4d6..9232857b77 100644 --- a/Extension/Core/Type/FormType.php +++ b/Extension/Core/Type/FormType.php @@ -40,6 +40,8 @@ public function __construct(PropertyAccessorInterface $propertyAccessor = null) */ public function buildForm(FormBuilderInterface $builder, array $options) { + $isDataOptionSet = array_key_exists('data', $options); + $builder ->setRequired($options['required']) ->setDisabled($options['disabled']) @@ -51,8 +53,8 @@ public function buildForm(FormBuilderInterface $builder, array $options) ->setByReference($options['by_reference']) ->setVirtual($options['virtual']) ->setCompound($options['compound']) - ->setData(isset($options['data']) ? $options['data'] : null) - ->setDataLocked(isset($options['data'])) + ->setData($isDataOptionSet ? $options['data'] : null) + ->setDataLocked($isDataOptionSet) ->setDataMapper($options['compound'] ? new PropertyPathMapper($this->propertyAccessor) : null) ; diff --git a/Tests/Extension/Core/Type/FormTypeTest.php b/Tests/Extension/Core/Type/FormTypeTest.php index 2d0bf30455..68e62e8bda 100644 --- a/Tests/Extension/Core/Type/FormTypeTest.php +++ b/Tests/Extension/Core/Type/FormTypeTest.php @@ -650,6 +650,18 @@ public function testDataOptionSupersedesSetDataCalls() $this->assertSame('default', $form->getData()); } + public function testDataOptionSupersedesSetDataCallsIfNull() + { + $form = $this->factory->create('form', null, array( + 'data' => null, + 'compound' => false, + )); + + $form->setData('foobar'); + + $this->assertNull($form->getData()); + } + public function testNormDataIsPassedToView() { $view = $this->factory->createBuilder('form') From aad44de23ae97556b7a5967d731792987bf149f4 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Mon, 28 Oct 2013 14:22:47 +0100 Subject: [PATCH 217/447] [Form] Fixed form debugger to work even when no view variables are logged (e.g. upon redirects) --- Extension/DataCollector/FormDataExtractor.php | 19 ++++++++++ .../DataCollector/FormDataExtractorTest.php | 38 +++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/Extension/DataCollector/FormDataExtractor.php b/Extension/DataCollector/FormDataExtractor.php index ad401796bd..6c0e41002a 100644 --- a/Extension/DataCollector/FormDataExtractor.php +++ b/Extension/DataCollector/FormDataExtractor.php @@ -42,6 +42,7 @@ public function __construct(ValueExporter $valueExporter = null) public function extractConfiguration(FormInterface $form) { $data = array( + 'id' => $this->buildId($form), 'type' => $form->getConfig()->getType()->getName(), 'type_class' => get_class($form->getConfig()->getType()->getInnerType()), 'synchronized' => $this->valueExporter->exportValue($form->isSynchronized()), @@ -132,4 +133,22 @@ public function extractViewVariables(FormView $view) return $data; } + + /** + * Recursively builds an HTML ID for a form. + * + * @param FormInterface $form The form + * + * @return string The HTML ID + */ + private function buildId(FormInterface $form) + { + $id = $form->getName(); + + if (null !== $form->getParent()) { + $id = $this->buildId($form->getParent()).'_'.$id; + } + + return $id; + } } diff --git a/Tests/Extension/DataCollector/FormDataExtractorTest.php b/Tests/Extension/DataCollector/FormDataExtractorTest.php index d9c1bb3180..70473cc1ba 100644 --- a/Tests/Extension/DataCollector/FormDataExtractorTest.php +++ b/Tests/Extension/DataCollector/FormDataExtractorTest.php @@ -79,6 +79,7 @@ public function testExtractConfiguration() ->getForm(); $this->assertSame(array( + 'id' => 'name', 'type' => 'type_name', 'type_class' => 'stdClass', 'synchronized' => 'true', @@ -111,6 +112,7 @@ public function testExtractConfigurationSortsPassedOptions() ->getForm(); $this->assertSame(array( + 'id' => 'name', 'type' => 'type_name', 'type_class' => 'stdClass', 'synchronized' => 'true', @@ -144,6 +146,7 @@ public function testExtractConfigurationSortsResolvedOptions() ->getForm(); $this->assertSame(array( + 'id' => 'name', 'type' => 'type_name', 'type_class' => 'stdClass', 'synchronized' => 'true', @@ -156,6 +159,41 @@ public function testExtractConfigurationSortsResolvedOptions() ), $this->dataExtractor->extractConfiguration($form)); } + public function testExtractConfigurationBuildsIdRecursively() + { + $type = $this->getMock('Symfony\Component\Form\ResolvedFormTypeInterface'); + $type->expects($this->any()) + ->method('getName') + ->will($this->returnValue('type_name')); + $type->expects($this->any()) + ->method('getInnerType') + ->will($this->returnValue(new \stdClass())); + + $grandParent = $this->createBuilder('grandParent') + ->setCompound(true) + ->setDataMapper($this->getMock('Symfony\Component\Form\DataMapperInterface')) + ->getForm(); + $parent = $this->createBuilder('parent') + ->setCompound(true) + ->setDataMapper($this->getMock('Symfony\Component\Form\DataMapperInterface')) + ->getForm(); + $form = $this->createBuilder('name') + ->setType($type) + ->getForm(); + + $grandParent->add($parent); + $parent->add($form); + + $this->assertSame(array( + 'id' => 'grandParent_parent_name', + 'type' => 'type_name', + 'type_class' => 'stdClass', + 'synchronized' => 'true', + 'passed_options' => array(), + 'resolved_options' => array(), + ), $this->dataExtractor->extractConfiguration($form)); + } + public function testExtractDefaultData() { $form = $this->createBuilder('name')->getForm(); From d7fbb6ceeeb2b748a36eac6afdb312f532a15f40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Pluchino?= Date: Mon, 28 Oct 2013 17:47:24 +0100 Subject: [PATCH 218/447] Fix nonexistent key id in twig of data collector --- Extension/DataCollector/FormDataExtractor.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Extension/DataCollector/FormDataExtractor.php b/Extension/DataCollector/FormDataExtractor.php index 6c0e41002a..652232d37a 100644 --- a/Extension/DataCollector/FormDataExtractor.php +++ b/Extension/DataCollector/FormDataExtractor.php @@ -123,7 +123,9 @@ public function extractSubmittedData(FormInterface $form) */ public function extractViewVariables(FormView $view) { - $data = array(); + $data = array( + 'id' => $view->vars['id'] + ); foreach ($view->vars as $varName => $value) { $data['view_vars'][$varName] = $this->valueExporter->exportValue($value); From bb2390168412a13b4f0570813750f0a99a1a2e70 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 30 Oct 2013 09:27:36 +0100 Subject: [PATCH 219/447] fixed CS --- Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php b/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php index 0e2b6321cc..c762064e0b 100644 --- a/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php @@ -257,14 +257,12 @@ public function testGetValuesForChoices() $this->assertSame(array($this->value1, $this->value2), $this->list->getValuesForChoices($choices)); } - public function testGetValuesForChoicesPreservesKeys() { $choices = array(5 => $this->choice1, 8 => $this->choice2); $this->assertSame(array(5 => $this->value1, 8 => $this->value2), $this->list->getValuesForChoices($choices)); } - public function testGetValuesForChoicesPreservesOrder() { $choices = array($this->choice2, $this->choice1); From acdc74bab13102fa43f01eef6c1cc3d41a060220 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 30 Oct 2013 09:33:58 +0100 Subject: [PATCH 220/447] fixed CS --- Button.php | 1 - Tests/Extension/DataCollector/FormDataCollectorTest.php | 1 - Tests/ResolvedFormTypeTest.php | 1 - 3 files changed, 3 deletions(-) diff --git a/Button.php b/Button.php index cecf27b696..f2365a95f3 100644 --- a/Button.php +++ b/Button.php @@ -412,7 +412,6 @@ public function createView(FormView $parent = null) $parent = $this->parent->createView(); } - $type = $this->config->getType(); $options = $this->config->getOptions(); diff --git a/Tests/Extension/DataCollector/FormDataCollectorTest.php b/Tests/Extension/DataCollector/FormDataCollectorTest.php index c1e21d8c51..99ac76ac23 100644 --- a/Tests/Extension/DataCollector/FormDataCollectorTest.php +++ b/Tests/Extension/DataCollector/FormDataCollectorTest.php @@ -62,7 +62,6 @@ class FormDataCollectorTest extends \PHPUnit_Framework_TestCase */ private $childView; - protected function setUp() { $this->dataExtractor = $this->getMock('Symfony\Component\Form\Extension\DataCollector\FormDataExtractorInterface'); diff --git a/Tests/ResolvedFormTypeTest.php b/Tests/ResolvedFormTypeTest.php index cf2275f8d4..23c599e3f5 100644 --- a/Tests/ResolvedFormTypeTest.php +++ b/Tests/ResolvedFormTypeTest.php @@ -167,7 +167,6 @@ public function testCreateBuilderWithDataClassOption() $this->assertSame('\stdClass', $builder->getDataClass()); } - public function testBuildForm() { if (version_compare(\PHPUnit_Runner_Version::id(), '3.7', '<')) { From e323b6018ba7fbefe68e7f8b2a0003628d25f668 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Wed, 30 Oct 2013 13:42:39 +0100 Subject: [PATCH 221/447] [Form] Fixed failing FormDataExtractorTest --- Extension/DataCollector/FormDataExtractor.php | 10 +++++++--- .../Extension/DataCollector/FormDataExtractorTest.php | 3 +++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Extension/DataCollector/FormDataExtractor.php b/Extension/DataCollector/FormDataExtractor.php index 652232d37a..8765b13ca4 100644 --- a/Extension/DataCollector/FormDataExtractor.php +++ b/Extension/DataCollector/FormDataExtractor.php @@ -123,9 +123,13 @@ public function extractSubmittedData(FormInterface $form) */ public function extractViewVariables(FormView $view) { - $data = array( - 'id' => $view->vars['id'] - ); + $data = array(); + + // Set the ID in case no FormInterface object was collected for this + // view + if (isset($view->vars['id'])) { + $data['id'] = $view->vars['id']; + } foreach ($view->vars as $varName => $value) { $data['view_vars'][$varName] = $this->valueExporter->exportValue($value); diff --git a/Tests/Extension/DataCollector/FormDataExtractorTest.php b/Tests/Extension/DataCollector/FormDataExtractorTest.php index 70473cc1ba..bf3cd71975 100644 --- a/Tests/Extension/DataCollector/FormDataExtractorTest.php +++ b/Tests/Extension/DataCollector/FormDataExtractorTest.php @@ -352,13 +352,16 @@ public function testExtractViewVariables() 'b' => 'foo', 'a' => 'bar', 'c' => 'baz', + 'id' => 'foo_bar', ); $this->assertSame(array( + 'id' => 'foo_bar', 'view_vars' => array( 'a' => "'bar'", 'b' => "'foo'", 'c' => "'baz'", + 'id' => "'foo_bar'", ), ), $this->dataExtractor->extractViewVariables($view)); } From 54c84988855bef5e738445ec9ec6b03d33d46e08 Mon Sep 17 00:00:00 2001 From: Joseph Deray Date: Wed, 30 Oct 2013 18:44:30 -0400 Subject: [PATCH 222/447] fixed issue with clone now the children of the original form are preserved and the clone form is given new children --- Form.php | 2 ++ Tests/CompoundFormTest.php | 1 + 2 files changed, 3 insertions(+) diff --git a/Form.php b/Form.php index f3324986c8..cde5ebf4cd 100644 --- a/Form.php +++ b/Form.php @@ -170,6 +170,8 @@ public function __construct(FormConfigInterface $config) public function __clone() { + $this->children = clone $this->children; + foreach ($this->children as $key => $child) { $this->children[$key] = clone $child; } diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index bc0c57d33f..51193e05bb 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -141,6 +141,7 @@ public function testCloneChildren() $this->assertNotSame($this->form, $clone); $this->assertNotSame($child, $clone['child']); + $this->assertNotSame($this->form['child'], $clone['child']); } public function testNotEmptyIfChildNotEmpty() From 82a7be527e18efeda89b3099f9857f45cf15f09f Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Thu, 31 Oct 2013 14:22:03 +0100 Subject: [PATCH 223/447] [Form] fix CsrfProviderAdapter --- Extension/Csrf/CsrfProvider/CsrfProviderAdapter.php | 2 +- FormRenderer.php | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Extension/Csrf/CsrfProvider/CsrfProviderAdapter.php b/Extension/Csrf/CsrfProvider/CsrfProviderAdapter.php index 01753135eb..39d52e5c6d 100644 --- a/Extension/Csrf/CsrfProvider/CsrfProviderAdapter.php +++ b/Extension/Csrf/CsrfProvider/CsrfProviderAdapter.php @@ -46,7 +46,7 @@ public function getCsrfProvider() */ public function getToken($tokenId) { - return $this->csrfProvider->generateCsrfToken($tokenId); + return new CsrfToken($tokenId, $this->csrfProvider->generateCsrfToken($tokenId)); } /** diff --git a/FormRenderer.php b/FormRenderer.php index b81483bce2..c5faee1548 100644 --- a/FormRenderer.php +++ b/FormRenderer.php @@ -52,12 +52,20 @@ class FormRenderer implements FormRendererInterface */ private $variableStack = array(); + /** + * Constructor. + * + * @param FormRendererEngineInterface $engine + * @param CsrfTokenManagerInterface|null $csrfTokenManager + * + * @throws UnexpectedTypeException + */ public function __construct(FormRendererEngineInterface $engine, $csrfTokenManager = null) { if ($csrfTokenManager instanceof CsrfProviderInterface) { $csrfTokenManager = new CsrfProviderAdapter($csrfTokenManager); } elseif (null !== $csrfTokenManager && !$csrfTokenManager instanceof CsrfTokenManagerInterface) { - throw new UnexpectedTypeException($csrfTokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface'); + throw new UnexpectedTypeException($csrfTokenManager, 'CsrfProviderInterface or CsrfTokenManagerInterface or null'); } $this->engine = $engine; From 7cf508bf793a609266562cc71c87d22ff5806913 Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Thu, 31 Oct 2013 15:11:32 +0100 Subject: [PATCH 224/447] [Form] fix and unify phpdoc --- Button.php | 2 +- Extension/Validator/ValidatorTypeGuesser.php | 10 +++++----- FormFactoryBuilderInterface.php | 8 ++++---- FormRegistryInterface.php | 2 +- FormTypeGuesserChain.php | 4 ++-- FormTypeGuesserInterface.php | 8 ++++---- Guess/Guess.php | 10 +++++----- PreloadedExtension.php | 6 +++--- ResolvedFormType.php | 4 ++-- ResolvedFormTypeFactoryInterface.php | 6 +++--- ResolvedFormTypeInterface.php | 2 +- SubmitButtonBuilder.php | 2 +- 12 files changed, 32 insertions(+), 32 deletions(-) diff --git a/Button.php b/Button.php index aecbabaebe..f12d11afe4 100644 --- a/Button.php +++ b/Button.php @@ -22,7 +22,7 @@ class Button implements \IteratorAggregate, FormInterface { /** - * @var FormInterface + * @var FormInterface|null */ private $parent; diff --git a/Extension/Validator/ValidatorTypeGuesser.php b/Extension/Validator/ValidatorTypeGuesser.php index dcd9cc552f..fbe5ee4135 100644 --- a/Extension/Validator/ValidatorTypeGuesser.php +++ b/Extension/Validator/ValidatorTypeGuesser.php @@ -82,7 +82,7 @@ public function guessPattern($class, $property) * * @param Constraint $constraint The constraint to guess for * - * @return TypeGuess The guessed field class and options + * @return TypeGuess|null The guessed field class and options */ public function guessTypeForConstraint(Constraint $constraint) { @@ -171,7 +171,7 @@ public function guessTypeForConstraint(Constraint $constraint) * * @param Constraint $constraint The constraint to guess for * - * @return Guess The guess whether the field is required + * @return ValueGuess|null The guess whether the field is required */ public function guessRequiredForConstraint(Constraint $constraint) { @@ -190,7 +190,7 @@ public function guessRequiredForConstraint(Constraint $constraint) * * @param Constraint $constraint The constraint to guess for * - * @return Guess The guess for the maximum length + * @return ValueGuess|null The guess for the maximum length */ public function guessMaxLengthForConstraint(Constraint $constraint) { @@ -216,7 +216,7 @@ public function guessMaxLengthForConstraint(Constraint $constraint) * * @param Constraint $constraint The constraint to guess for * - * @return Guess The guess for the pattern + * @return ValueGuess|null The guess for the pattern */ public function guessPatternForConstraint(Constraint $constraint) { @@ -256,7 +256,7 @@ public function guessPatternForConstraint(Constraint $constraint) * @param mixed $defaultValue The default value assumed if no other value * can be guessed. * - * @return Guess The guessed value with the highest confidence + * @return Guess|null The guessed value with the highest confidence */ protected function guess($class, $property, \Closure $closure, $defaultValue = null) { diff --git a/FormFactoryBuilderInterface.php b/FormFactoryBuilderInterface.php index 9370c573a6..e32f1ce766 100644 --- a/FormFactoryBuilderInterface.php +++ b/FormFactoryBuilderInterface.php @@ -39,7 +39,7 @@ public function addExtension(FormExtensionInterface $extension); /** * Adds a list of extensions to be loaded by the factory. * - * @param array $extensions The extensions. + * @param FormExtensionInterface[] $extensions The extensions. * * @return FormFactoryBuilderInterface The builder. */ @@ -57,7 +57,7 @@ public function addType(FormTypeInterface $type); /** * Adds a list of form types to the factory. * - * @param array $types The form types. + * @param FormTypeInterface[] $types The form types. * * @return FormFactoryBuilderInterface The builder. */ @@ -75,7 +75,7 @@ public function addTypeExtension(FormTypeExtensionInterface $typeExtension); /** * Adds a list of form type extensions to the factory. * - * @param array $typeExtensions The form type extensions. + * @param FormTypeExtensionInterface[] $typeExtensions The form type extensions. * * @return FormFactoryBuilderInterface The builder. */ @@ -93,7 +93,7 @@ public function addTypeGuesser(FormTypeGuesserInterface $typeGuesser); /** * Adds a list of type guessers to the factory. * - * @param array $typeGuessers The type guessers. + * @param FormTypeGuesserInterface[] $typeGuessers The type guessers. * * @return FormFactoryBuilderInterface The builder. */ diff --git a/FormRegistryInterface.php b/FormRegistryInterface.php index 16cd938441..141c4721c5 100644 --- a/FormRegistryInterface.php +++ b/FormRegistryInterface.php @@ -51,7 +51,7 @@ public function getTypeGuesser(); /** * Returns the extensions loaded by the framework. * - * @return array + * @return FormExtensionInterface[] */ public function getExtensions(); } diff --git a/FormTypeGuesserChain.php b/FormTypeGuesserChain.php index c7f8ece370..6e858ddffe 100644 --- a/FormTypeGuesserChain.php +++ b/FormTypeGuesserChain.php @@ -21,7 +21,7 @@ class FormTypeGuesserChain implements FormTypeGuesserInterface /** * Constructor. * - * @param array $guessers Guessers as instances of FormTypeGuesserInterface + * @param FormTypeGuesserInterface[] $guessers Guessers as instances of FormTypeGuesserInterface * * @throws UnexpectedTypeException if any guesser does not implement FormTypeGuesserInterface */ @@ -87,7 +87,7 @@ public function guessPattern($class, $property) * @param \Closure $closure The closure to execute. Accepts a guesser * as argument and should return a Guess instance * - * @return Guess The guess with the highest confidence + * @return Guess|null The guess with the highest confidence */ private function guess(\Closure $closure) { diff --git a/FormTypeGuesserInterface.php b/FormTypeGuesserInterface.php index e8b603faa1..7cd384a798 100644 --- a/FormTypeGuesserInterface.php +++ b/FormTypeGuesserInterface.php @@ -22,7 +22,7 @@ interface FormTypeGuesserInterface * @param string $class The fully qualified class name * @param string $property The name of the property to guess for * - * @return Guess\TypeGuess A guess for the field's type and options + * @return Guess\TypeGuess|null A guess for the field's type and options */ public function guessType($class, $property); @@ -32,7 +32,7 @@ public function guessType($class, $property); * @param string $class The fully qualified class name * @param string $property The name of the property to guess for * - * @return Guess\Guess A guess for the field's required setting + * @return Guess\ValueGuess A guess for the field's required setting */ public function guessRequired($class, $property); @@ -42,7 +42,7 @@ public function guessRequired($class, $property); * @param string $class The fully qualified class name * @param string $property The name of the property to guess for * - * @return Guess\Guess A guess for the field's maximum length + * @return Guess\ValueGuess|null A guess for the field's maximum length */ public function guessMaxLength($class, $property); @@ -58,7 +58,7 @@ public function guessMaxLength($class, $property); * @param string $class The fully qualified class name * @param string $property The name of the property to guess for * - * @return Guess\Guess A guess for the field's required pattern + * @return Guess\ValueGuess|null A guess for the field's required pattern */ public function guessPattern($class, $property); } diff --git a/Guess/Guess.php b/Guess/Guess.php index b33c3d802d..6616ff5092 100644 --- a/Guess/Guess.php +++ b/Guess/Guess.php @@ -59,14 +59,14 @@ abstract class Guess private $confidence; /** - * Returns the guess most likely to be correct from a list of guesses + * Returns the guess most likely to be correct from a list of guesses. * * If there are multiple guesses with the same, highest confidence, the * returned guess is any of them. * - * @param array $guesses A list of guesses + * @param Guess[] $guesses An array of guesses * - * @return Guess The guess with the highest confidence + * @return Guess|null The guess with the highest confidence */ public static function getBestGuess(array $guesses) { @@ -84,7 +84,7 @@ public static function getBestGuess(array $guesses) } /** - * Constructor + * Constructor. * * @param integer $confidence The confidence * @@ -101,7 +101,7 @@ public function __construct($confidence) } /** - * Returns the confidence that the guessed value is correct + * Returns the confidence that the guessed value is correct. * * @return integer One of the constants VERY_HIGH_CONFIDENCE, * HIGH_CONFIDENCE, MEDIUM_CONFIDENCE and LOW_CONFIDENCE diff --git a/PreloadedExtension.php b/PreloadedExtension.php index 2d3e9efb08..454affd3eb 100644 --- a/PreloadedExtension.php +++ b/PreloadedExtension.php @@ -38,9 +38,9 @@ class PreloadedExtension implements FormExtensionInterface /** * Creates a new preloaded extension. * - * @param array $types The types that the extension should support. - * @param array $typeExtensions The type extensions that the extension should support. - * @param FormTypeGuesserInterface|null $typeGuesser The guesser that the extension should support. + * @param FormTypeInterface[] $types The types that the extension should support. + * @param array[FormTypeExtensionInterface[]] typeExtensions The type extensions that the extension should support. + * @param FormTypeGuesserInterface|null $typeGuesser The guesser that the extension should support. */ public function __construct(array $types, array $typeExtensions, FormTypeGuesserInterface $typeGuesser = null) { diff --git a/ResolvedFormType.php b/ResolvedFormType.php index 47d43553cd..0f676e53de 100644 --- a/ResolvedFormType.php +++ b/ResolvedFormType.php @@ -29,12 +29,12 @@ class ResolvedFormType implements ResolvedFormTypeInterface private $innerType; /** - * @var array + * @var FormTypeExtensionInterface[] */ private $typeExtensions; /** - * @var ResolvedFormTypeInterface + * @var ResolvedFormTypeInterface|null */ private $parent; diff --git a/ResolvedFormTypeFactoryInterface.php b/ResolvedFormTypeFactoryInterface.php index f0ec23308f..3240d77f4f 100644 --- a/ResolvedFormTypeFactoryInterface.php +++ b/ResolvedFormTypeFactoryInterface.php @@ -25,9 +25,9 @@ interface ResolvedFormTypeFactoryInterface /** * Resolves a form type. * - * @param FormTypeInterface $type - * @param array $typeExtensions - * @param ResolvedFormTypeInterface $parent + * @param FormTypeInterface $type + * @param FormTypeExtensionInterface[] $typeExtensions + * @param ResolvedFormTypeInterface|null $parent * * @return ResolvedFormTypeInterface * diff --git a/ResolvedFormTypeInterface.php b/ResolvedFormTypeInterface.php index c999bcdc6d..5fd37f4b46 100644 --- a/ResolvedFormTypeInterface.php +++ b/ResolvedFormTypeInterface.php @@ -28,7 +28,7 @@ public function getName(); /** * Returns the parent type. * - * @return ResolvedFormTypeInterface The parent type or null. + * @return ResolvedFormTypeInterface|null The parent type or null. */ public function getParent(); diff --git a/SubmitButtonBuilder.php b/SubmitButtonBuilder.php index 088fb74819..931f399daf 100644 --- a/SubmitButtonBuilder.php +++ b/SubmitButtonBuilder.php @@ -21,7 +21,7 @@ class SubmitButtonBuilder extends ButtonBuilder /** * Creates the button. * - * @return Button The button + * @return SubmitButton The button */ public function getForm() { From 16f60d594d55ab414f5dd049e6d9d5820403bf84 Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Sun, 3 Nov 2013 21:48:28 +0100 Subject: [PATCH 225/447] slovenian translations fixed --- Resources/translations/validators.sl.xlf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Resources/translations/validators.sl.xlf b/Resources/translations/validators.sl.xlf index 103124d0a8..cd68c1a1e5 100644 --- a/Resources/translations/validators.sl.xlf +++ b/Resources/translations/validators.sl.xlf @@ -4,11 +4,11 @@ This form should not contain extra fields. - To področje ne sme vsebovati dodatnih polj. + Ta obrazec ne sme vsebovati dodatnih polj. The uploaded file was too large. Please try to upload a smaller file. - Naložena datoteka je prevelika. Prosim, poizkusite naložiti manjšo. + Naložena datoteka je prevelika. Prosimo, poizkusite naložiti manjšo. The CSRF token is invalid. Please try to resubmit the form. From e304242e3ddf14fd39864aab3fcdb27de292c965 Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Sun, 3 Nov 2013 20:38:50 +0100 Subject: [PATCH 226/447] slovenian translations fixed --- Resources/translations/validators.sl.xlf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Resources/translations/validators.sl.xlf b/Resources/translations/validators.sl.xlf index 103124d0a8..cd68c1a1e5 100644 --- a/Resources/translations/validators.sl.xlf +++ b/Resources/translations/validators.sl.xlf @@ -4,11 +4,11 @@ This form should not contain extra fields. - To področje ne sme vsebovati dodatnih polj. + Ta obrazec ne sme vsebovati dodatnih polj. The uploaded file was too large. Please try to upload a smaller file. - Naložena datoteka je prevelika. Prosim, poizkusite naložiti manjšo. + Naložena datoteka je prevelika. Prosimo, poizkusite naložiti manjšo. The CSRF token is invalid. Please try to resubmit the form. From 7dc28b0ad218b4b3d441fae6c7ab641403cf3b7c Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Sat, 9 Nov 2013 16:25:41 +0100 Subject: [PATCH 227/447] [Form] Added method Form::getClickedButton() to remove memory leak in FormValidator --- ButtonBuilder.php | 2 +- .../Validator/Constraints/FormValidator.php | 49 ++--------- Form.php | 39 +++++++++ Tests/CompoundFormTest.php | 84 +++++++++++++++++++ .../Constraints/FormValidatorTest.php | 9 +- 5 files changed, 132 insertions(+), 51 deletions(-) diff --git a/ButtonBuilder.php b/ButtonBuilder.php index 3addedbde9..9146c69352 100644 --- a/ButtonBuilder.php +++ b/ButtonBuilder.php @@ -60,7 +60,7 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * * @throws InvalidArgumentException If the name is empty. */ - public function __construct($name, array $options) + public function __construct($name, array $options = array()) { if (empty($name) && 0 != $name) { throw new InvalidArgumentException('Buttons cannot have empty names.'); diff --git a/Extension/Validator/Constraints/FormValidator.php b/Extension/Validator/Constraints/FormValidator.php index 1c4dd3c3ea..ccf89f0613 100644 --- a/Extension/Validator/Constraints/FormValidator.php +++ b/Extension/Validator/Constraints/FormValidator.php @@ -22,11 +22,6 @@ */ class FormValidator extends ConstraintValidator { - /** - * @var array - */ - private static $clickedButtons = array(); - /** * @var ServerParams */ @@ -52,10 +47,6 @@ public function validate($form, Constraint $constraint) return; } - // If the form was previously validated, remove it from the cache in - // case the clicked button has changed - unset(self::$clickedButtons[spl_object_hash($form)]); - /* @var FormInterface $form */ $config = $form->getConfig(); @@ -181,21 +172,15 @@ private static function allowDataWalking(FormInterface $form) */ private static function getValidationGroups(FormInterface $form) { - $root = $form->getRoot(); - $rootHash = spl_object_hash($root); - // Determine the clicked button of the complete form tree - if (!array_key_exists($rootHash, self::$clickedButtons)) { - // Only call findClickedButton() once to prevent an exponential - // runtime - // https://github.com/symfony/symfony/issues/8317 - self::$clickedButtons[$rootHash] = self::findClickedButton($root); - } + $clickedButton = null; - $button = self::$clickedButtons[$rootHash]; + if (method_exists($form, 'getClickedButton')) { + $clickedButton = $form->getClickedButton(); + } - if (null !== $button) { - $groups = $button->getConfig()->getOption('validation_groups'); + if (null !== $clickedButton) { + $groups = $clickedButton->getConfig()->getOption('validation_groups'); if (null !== $groups) { return self::resolveValidationGroups($groups, $form); @@ -215,28 +200,6 @@ private static function getValidationGroups(FormInterface $form) return array(Constraint::DEFAULT_GROUP); } - /** - * Extracts a clicked button from a form tree, if one exists. - * - * @param FormInterface $form The root form. - * - * @return ClickableInterface|null The clicked button or null. - */ - private static function findClickedButton(FormInterface $form) - { - if ($form instanceof ClickableInterface && $form->isClicked()) { - return $form; - } - - foreach ($form as $child) { - if (null !== ($button = self::findClickedButton($child))) { - return $button; - } - } - - return null; - } - /** * Post-processes the validation groups option for a given form. * diff --git a/Form.php b/Form.php index f3324986c8..ae23053b50 100644 --- a/Form.php +++ b/Form.php @@ -90,6 +90,12 @@ class Form implements \IteratorAggregate, FormInterface */ private $submitted = false; + /** + * The button that was used to submit the form + * @var Button + */ + private $clickedButton; + /** * The form data in model format * @var mixed @@ -551,6 +557,20 @@ public function submit($submittedData, $clearMissing = true) if (isset($submittedData[$name]) || $clearMissing) { $child->submit(isset($submittedData[$name]) ? $submittedData[$name] : null, $clearMissing); unset($submittedData[$name]); + + if (null !== $this->clickedButton) { + continue; + } + + if ($child instanceof ClickableInterface && $child->isClicked()) { + $this->clickedButton = $child; + + continue; + } + + if (method_exists($child, 'getClickedButton') && null !== $child->getClickedButton()) { + $this->clickedButton = $child->getClickedButton(); + } } } @@ -730,6 +750,25 @@ public function isValid() return true; } + /** + * Returns the button that was used to submit the form. + * + * @return Button|null The clicked button or NULL if the form was not + * submitted + */ + public function getClickedButton() + { + if ($this->clickedButton) { + return $this->clickedButton; + } + + if ($this->parent && method_exists($this->parent, 'getClickedButton')) { + return $this->parent->getClickedButton(); + } + + return null; + } + /** * {@inheritdoc} */ diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index bc0c57d33f..61563272b5 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -13,8 +13,10 @@ use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; +use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormError; use Symfony\Component\Form\Forms; +use Symfony\Component\Form\SubmitButtonBuilder; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer; @@ -830,6 +832,88 @@ public function testGetErrorsAsStringDeep() $this->assertEquals("name:\n ERROR: Error!\nfoo:\n No errors\n", $parent->getErrorsAsString()); } + public function testNoClickedButtonBeforeSubmission() + { + $this->assertNull($this->form->getClickedButton()); + } + + public function testNoClickedButton() + { + $button = $this->getMockBuilder('Symfony\Component\Form\SubmitButton') + ->setConstructorArgs(array(new SubmitButtonBuilder('submit'))) + ->setMethods(array('isClicked')) + ->getMock(); + + $button->expects($this->any()) + ->method('isClicked') + ->will($this->returnValue(false)); + + $parentForm = $this->getBuilder('parent')->getForm(); + $nestedForm = $this->getBuilder('nested')->getForm(); + + $this->form->setParent($parentForm); + $this->form->add($button); + $this->form->add($nestedForm); + $this->form->submit(array()); + + $this->assertNull($this->form->getClickedButton()); + } + + public function testClickedButton() + { + $button = $this->getMockBuilder('Symfony\Component\Form\SubmitButton') + ->setConstructorArgs(array(new SubmitButtonBuilder('submit'))) + ->setMethods(array('isClicked')) + ->getMock(); + + $button->expects($this->any()) + ->method('isClicked') + ->will($this->returnValue(true)); + + $this->form->add($button); + $this->form->submit(array()); + + $this->assertSame($button, $this->form->getClickedButton()); + } + + public function testClickedButtonFromNestedForm() + { + $button = $this->getBuilder('submit')->getForm(); + + $nestedForm = $this->getMockBuilder('Symfony\Component\Form\Form') + ->setConstructorArgs(array($this->getBuilder('nested'))) + ->setMethods(array('getClickedButton')) + ->getMock(); + + $nestedForm->expects($this->any()) + ->method('getClickedButton') + ->will($this->returnValue($button)); + + $this->form->add($nestedForm); + $this->form->submit(array()); + + $this->assertSame($button, $this->form->getClickedButton()); + } + + public function testClickedButtonFromParentForm() + { + $button = $this->getBuilder('submit')->getForm(); + + $parentForm = $this->getMockBuilder('Symfony\Component\Form\Form') + ->setConstructorArgs(array($this->getBuilder('parent'))) + ->setMethods(array('getClickedButton')) + ->getMock(); + + $parentForm->expects($this->any()) + ->method('getClickedButton') + ->will($this->returnValue($button)); + + $this->form->setParent($parentForm); + $this->form->submit(array()); + + $this->assertSame($button, $this->form->getClickedButton()); + } + protected function createForm() { return $this->getBuilder() diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index a8bdde8a4d..cbe66f7249 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -430,11 +430,11 @@ public function testUseValidationGroupOfClickedButton() )); $parent->add($form); - $parent->add($this->getClickedSubmitButton('submit', array( + $parent->add($this->getSubmitButton('submit', array( 'validation_groups' => 'button_group', ))); - $form->setData($object); + $parent->submit(array('name' => $object, 'submit' => '')); $context->expects($this->once()) ->method('validate') @@ -733,11 +733,6 @@ private function getSubmitButton($name = 'name', array $options = array()) return $builder->getForm(); } - private function getClickedSubmitButton($name = 'name', array $options = array()) - { - return $this->getSubmitButton($name, $options)->submit(''); - } - /** * @return \PHPUnit_Framework_MockObject_MockObject */ From 52808679fba725f66c393258e3bdb8aebcbde483 Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Thu, 14 Nov 2013 15:30:56 +0100 Subject: [PATCH 228/447] unify missing parentheses --- Tests/FormFactoryBuilderTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tests/FormFactoryBuilderTest.php b/Tests/FormFactoryBuilderTest.php index a1292dbe72..2c3ab000ff 100644 --- a/Tests/FormFactoryBuilderTest.php +++ b/Tests/FormFactoryBuilderTest.php @@ -27,12 +27,12 @@ protected function setUp() $this->registry->setAccessible(true); $this->guesser = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface'); - $this->type = new FooType; + $this->type = new FooType(); } public function testAddType() { - $factoryBuilder = new FormFactoryBuilder; + $factoryBuilder = new FormFactoryBuilder(); $factoryBuilder->addType($this->type); $factory = $factoryBuilder->getFormFactory(); @@ -46,7 +46,7 @@ public function testAddType() public function testAddTypeGuesser() { - $factoryBuilder = new FormFactoryBuilder; + $factoryBuilder = new FormFactoryBuilder(); $factoryBuilder->addTypeGuesser($this->guesser); $factory = $factoryBuilder->getFormFactory(); From 3b1ae531d13b4a9ebdfb1fc58b326ad920edc08d Mon Sep 17 00:00:00 2001 From: Pascal Borreli Date: Sat, 16 Nov 2013 15:13:54 +0000 Subject: [PATCH 229/447] Fixed typos --- Extension/DataCollector/FormDataCollector.php | 6 +++--- Tests/AbstractFormTest.php | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Extension/DataCollector/FormDataCollector.php b/Extension/DataCollector/FormDataCollector.php index 543d6c5b04..2119248132 100644 --- a/Extension/DataCollector/FormDataCollector.php +++ b/Extension/DataCollector/FormDataCollector.php @@ -34,7 +34,7 @@ class FormDataCollector extends DataCollector implements FormDataCollectorInterf /** * Stores the collected data per {@link FormInterface} instance. * - * Uses the hashes of the forms as keys. This is preferrable over using + * Uses the hashes of the forms as keys. This is preferable over using * {@link \SplObjectStorage}, because in this way no references are kept * to the {@link FormInterface} instances. * @@ -45,7 +45,7 @@ class FormDataCollector extends DataCollector implements FormDataCollectorInterf /** * Stores the collected data per {@link FormView} instance. * - * Uses the hashes of the views as keys. This is preferrable over using + * Uses the hashes of the views as keys. This is preferable over using * {@link \SplObjectStorage}, because in this way no references are kept * to the {@link FormView} instances. * @@ -57,7 +57,7 @@ class FormDataCollector extends DataCollector implements FormDataCollectorInterf * Connects {@link FormView} with {@link FormInterface} instances. * * Uses the hashes of the views as keys and the hashes of the forms as - * values. This is preferrable over storing the objects directly, because + * values. This is preferable over storing the objects directly, because * this way they can safely be discarded by the GC. * * @var array diff --git a/Tests/AbstractFormTest.php b/Tests/AbstractFormTest.php index 083176e670..b6cd54cd82 100644 --- a/Tests/AbstractFormTest.php +++ b/Tests/AbstractFormTest.php @@ -57,6 +57,7 @@ abstract protected function createForm(); * @param string $name * @param EventDispatcherInterface $dispatcher * @param string $dataClass + * @param array $options * * @return FormBuilder */ From e17115709daa05276bab4344ff4a08eae4c20448 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 22 Nov 2013 18:29:47 +0100 Subject: [PATCH 230/447] fixed CS --- Form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Form.php b/Form.php index f16701cdd1..78e1296704 100644 --- a/Form.php +++ b/Form.php @@ -171,7 +171,7 @@ public function __construct(FormConfigInterface $config) public function __clone() { $this->children = clone $this->children; - + foreach ($this->children as $key => $child) { $this->children[$key] = clone $child; } From bcb037811429e307d9c758227adcefc56d20ed22 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 24 Nov 2013 21:15:22 +0100 Subject: [PATCH 231/447] updated version to 2.5 --- README.md | 2 +- composer.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d2da3fa073..340bc6e631 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ https://github.com/fabpot/Silex/blob/master/src/Silex/Provider/FormServiceProvid Documentation: -http://symfony.com/doc/2.4/book/forms.html +http://symfony.com/doc/2.5/book/forms.html Resources --------- diff --git a/composer.json b/composer.json index 8e6f419b68..dcd7ed088d 100644 --- a/composer.json +++ b/composer.json @@ -40,7 +40,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.5-dev" } } } From 17ee2f643e6e665af23f38c3dced7c24815ccb1f Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 25 Nov 2013 09:44:14 +0100 Subject: [PATCH 232/447] fixed @expectedException class names --- Tests/FormFactoryTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/FormFactoryTest.php b/Tests/FormFactoryTest.php index aa43310850..8e5f340a0f 100644 --- a/Tests/FormFactoryTest.php +++ b/Tests/FormFactoryTest.php @@ -278,7 +278,7 @@ public function testCreateNamedBuilderDoesNotOverrideExistingDataOption() } /** - * @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException * @expectedExceptionMessage Expected argument of type "string, Symfony\Component\Form\ResolvedFormTypeInterface or Symfony\Component\Form\FormTypeInterface", "stdClass" given */ public function testCreateNamedBuilderThrowsUnderstandableException() From b671293180b9a88bbb9fb32d791b29faf05129e8 Mon Sep 17 00:00:00 2001 From: WedgeSama Date: Thu, 17 Oct 2013 09:16:34 +0200 Subject: [PATCH 233/447] Fix DateType for 32bits computers. --- Extension/Core/Type/DateType.php | 4 +++- Tests/Extension/Core/Type/DateTypeTest.php | 21 +++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Extension/Core/Type/DateType.php b/Extension/Core/Type/DateType.php index 2ac2f0436e..3e3f5b185a 100644 --- a/Extension/Core/Type/DateType.php +++ b/Extension/Core/Type/DateType.php @@ -300,7 +300,9 @@ private function listYears(array $years) $result = array(); foreach ($years as $year) { - $result[$year] = gmmktime(0, 0, 0, 6, 15, $year); + if (false !== $y = gmmktime(0, 0, 0, 6, 15, $year)) { + $result[$year] = $y; + } } return $result; diff --git a/Tests/Extension/Core/Type/DateTypeTest.php b/Tests/Extension/Core/Type/DateTypeTest.php index 7c71b1a033..8674216fa2 100644 --- a/Tests/Extension/Core/Type/DateTypeTest.php +++ b/Tests/Extension/Core/Type/DateTypeTest.php @@ -774,4 +774,25 @@ public function testDayErrorsBubbleUp($widget) $this->assertSame(array(), $form['day']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } + + public function testYearsFor32BitsMachines() + { + if (4 !== PHP_INT_SIZE) { + $this->markTestSkipped( + 'PHP must be compiled in 32 bit mode to run this test'); + } + + $form = $this->factory->create('date', null, array( + 'years' => range(1900, 2040), + )); + + $view = $form->createView(); + + $listChoices = array(); + foreach(range(1902, 2037) as $y) { + $listChoices[] = new ChoiceView($y, $y, $y); + } + + $this->assertEquals($listChoices, $view['year']->vars['choices']); + } } From 422aa05c10e5d3ab8883ce7d3fd8a7a1dc7673ea Mon Sep 17 00:00:00 2001 From: Christian Raue Date: Tue, 3 Dec 2013 11:59:03 +0100 Subject: [PATCH 234/447] fixed typos in several translations --- Resources/translations/validators.es.xlf | 2 +- Resources/translations/validators.gl.xlf | 2 +- Resources/translations/validators.ja.xlf | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Resources/translations/validators.es.xlf b/Resources/translations/validators.es.xlf index ebfacfd487..175096ae8a 100644 --- a/Resources/translations/validators.es.xlf +++ b/Resources/translations/validators.es.xlf @@ -12,7 +12,7 @@ The CSRF token is invalid. Please try to resubmit the form. - El token CSRF no es válido. Por favor, pruebe de enviar nuevamente el formulario + El token CSRF no es válido. Por favor, pruebe de enviar nuevamente el formulario. diff --git a/Resources/translations/validators.gl.xlf b/Resources/translations/validators.gl.xlf index db23fe2be6..88cc6536ea 100644 --- a/Resources/translations/validators.gl.xlf +++ b/Resources/translations/validators.gl.xlf @@ -12,7 +12,7 @@ The CSRF token is invalid. Please try to resubmit the form. - O token CSRF non é válido. Por favor, probe a enviar novamente o formulario + O token CSRF non é válido. Por favor, probe a enviar novamente o formulario. diff --git a/Resources/translations/validators.ja.xlf b/Resources/translations/validators.ja.xlf index 4559af1769..2e8585a75c 100644 --- a/Resources/translations/validators.ja.xlf +++ b/Resources/translations/validators.ja.xlf @@ -4,15 +4,15 @@ This form should not contain extra fields. - フィールドグループに追加のフィールドを含んではなりません. + フィールドグループに追加のフィールドを含んではなりません。 The uploaded file was too large. Please try to upload a smaller file. - アップロードされたファイルが大きすぎます。小さなファイルで再度アップロードしてください. + アップロードされたファイルが大きすぎます。小さなファイルで再度アップロードしてください。 The CSRF token is invalid. - CSRFトークンが無効です. + CSRFトークンが無効です。 From 762e3c62ab226e3e471eea50e6836764c0629623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20G=C3=A4rtner?= Date: Tue, 3 Dec 2013 20:56:02 +0100 Subject: [PATCH 235/447] Switched to correct gender of "Token" The neutral gender "das Token" is used in science to describe an array of bits or chars, where as the masculin "der Token" is commenly used for keys in communications and authentication in the network. I guess the a CSRF-Token is more a key for authentication then a bit array. --- Resources/translations/validators.de.xlf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Resources/translations/validators.de.xlf b/Resources/translations/validators.de.xlf index c801d67706..a9a183197e 100644 --- a/Resources/translations/validators.de.xlf +++ b/Resources/translations/validators.de.xlf @@ -12,8 +12,8 @@ The CSRF token is invalid. Please try to resubmit the form. - Das CSRF-Token ist ungültig. Versuchen Sie bitte das Formular erneut zu senden. + Der CSRF-Token ist ungültig. Versuchen Sie bitte das Formular erneut zu senden. - \ No newline at end of file + From 16527335b40cc0d795e3daafd9167bab2046fb9a Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 12 Dec 2013 17:08:59 +0100 Subject: [PATCH 236/447] fixed CS --- Extension/Validator/Constraints/FormValidator.php | 1 - Form.php | 2 +- Tests/CompoundFormTest.php | 1 - Tests/Extension/Core/Type/DateTypeTest.php | 8 ++++---- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/Extension/Validator/Constraints/FormValidator.php b/Extension/Validator/Constraints/FormValidator.php index ccf89f0613..0df176f7d7 100644 --- a/Extension/Validator/Constraints/FormValidator.php +++ b/Extension/Validator/Constraints/FormValidator.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Form\Extension\Validator\Constraints; -use Symfony\Component\Form\ClickableInterface; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\Extension\Validator\Util\ServerParams; use Symfony\Component\Validator\Constraint; diff --git a/Form.php b/Form.php index d038ae3b64..86cf7921a1 100644 --- a/Form.php +++ b/Form.php @@ -177,7 +177,7 @@ public function __construct(FormConfigInterface $config) public function __clone() { $this->children = clone $this->children; - + foreach ($this->children as $key => $child) { $this->children[$key] = clone $child; } diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index 4e795e9ee5..fe3755c172 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -13,7 +13,6 @@ use Symfony\Component\Form\Extension\Core\DataMapper\PropertyPathMapper; use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; -use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormError; use Symfony\Component\Form\Forms; use Symfony\Component\Form\SubmitButtonBuilder; diff --git a/Tests/Extension/Core/Type/DateTypeTest.php b/Tests/Extension/Core/Type/DateTypeTest.php index e6361b1759..508ab410b0 100644 --- a/Tests/Extension/Core/Type/DateTypeTest.php +++ b/Tests/Extension/Core/Type/DateTypeTest.php @@ -778,14 +778,14 @@ public function testDayErrorsBubbleUp($widget) $this->assertSame(array(), $form['day']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } - + public function testYearsFor32BitsMachines() { if (4 !== PHP_INT_SIZE) { $this->markTestSkipped( 'PHP must be compiled in 32 bit mode to run this test'); } - + $form = $this->factory->create('date', null, array( 'years' => range(1900, 2040), )); @@ -793,10 +793,10 @@ public function testYearsFor32BitsMachines() $view = $form->createView(); $listChoices = array(); - foreach(range(1902, 2037) as $y) { + foreach (range(1902, 2037) as $y) { $listChoices[] = new ChoiceView($y, $y, $y); } - + $this->assertEquals($listChoices, $view['year']->vars['choices']); } } From d7e6dd19f41aa7bb419182589f381d3ba42506d6 Mon Sep 17 00:00:00 2001 From: Christian Raue Date: Sun, 1 Dec 2013 20:02:34 +0100 Subject: [PATCH 237/447] renamed validators.ua.xlf to validators.uk.xlf ISO 639-1 code for Ukrainian is "uk" --- Resources/translations/{validators.ua.xlf => validators.uk.xlf} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Resources/translations/{validators.ua.xlf => validators.uk.xlf} (100%) diff --git a/Resources/translations/validators.ua.xlf b/Resources/translations/validators.uk.xlf similarity index 100% rename from Resources/translations/validators.ua.xlf rename to Resources/translations/validators.uk.xlf From d8d772b638dc4434f52e4b7a072c2a9ac4da32bd Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Sun, 10 Nov 2013 19:02:42 +0100 Subject: [PATCH 238/447] fix deprecated usage and clarify constructor defaults for number formatter by using the real default one can see the actual value without having to look into the implementation what NULL stands for --- .../IntegerToLocalizedStringTransformer.php | 2 +- .../MoneyToLocalizedStringTransformer.php | 3 +-- .../NumberToLocalizedStringTransformer.php | 4 ++-- Extension/Core/Type/IntegerType.php | 16 ++++++++-------- Extension/Core/Type/NumberType.php | 16 ++++++++-------- 5 files changed, 20 insertions(+), 21 deletions(-) diff --git a/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php index c22dad5100..3f6463eb5a 100644 --- a/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php @@ -26,7 +26,7 @@ class IntegerToLocalizedStringTransformer extends NumberToLocalizedStringTransfo * @param Boolean $grouping Whether thousands should be grouped. * @param integer $roundingMode One of the ROUND_ constants in this class. */ - public function __construct($precision = null, $grouping = null, $roundingMode = self::ROUND_DOWN) + public function __construct($precision = 0, $grouping = false, $roundingMode = self::ROUND_DOWN) { if (null === $roundingMode) { $roundingMode = self::ROUND_DOWN; diff --git a/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php index 5b8e9d9664..cfe4b95470 100644 --- a/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php @@ -21,10 +21,9 @@ */ class MoneyToLocalizedStringTransformer extends NumberToLocalizedStringTransformer { - private $divisor; - public function __construct($precision = null, $grouping = null, $roundingMode = null, $divisor = null) + public function __construct($precision = 2, $grouping = true, $roundingMode = self::ROUND_HALF_UP, $divisor = 1) { if (null === $grouping) { $grouping = true; diff --git a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php index 61f2f4441e..57416710d8 100644 --- a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php @@ -99,14 +99,14 @@ class NumberToLocalizedStringTransformer implements DataTransformerInterface protected $roundingMode; - public function __construct($precision = null, $grouping = null, $roundingMode = null) + public function __construct($precision = null, $grouping = false, $roundingMode = self::ROUND_HALF_UP) { if (null === $grouping) { $grouping = false; } if (null === $roundingMode) { - $roundingMode = self::ROUND_HALFUP; + $roundingMode = self::ROUND_HALF_UP; } $this->precision = $precision; diff --git a/Extension/Core/Type/IntegerType.php b/Extension/Core/Type/IntegerType.php index b224cac5fd..8e69f89661 100644 --- a/Extension/Core/Type/IntegerType.php +++ b/Extension/Core/Type/IntegerType.php @@ -41,19 +41,19 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'precision' => null, 'grouping' => false, // Integer cast rounds towards 0, so do the same when displaying fractions - 'rounding_mode' => \NumberFormatter::ROUND_DOWN, + 'rounding_mode' => IntegerToLocalizedStringTransformer::ROUND_DOWN, 'compound' => false, )); $resolver->setAllowedValues(array( 'rounding_mode' => array( - \NumberFormatter::ROUND_FLOOR, - \NumberFormatter::ROUND_DOWN, - \NumberFormatter::ROUND_HALFDOWN, - \NumberFormatter::ROUND_HALFEVEN, - \NumberFormatter::ROUND_HALFUP, - \NumberFormatter::ROUND_UP, - \NumberFormatter::ROUND_CEILING, + IntegerToLocalizedStringTransformer::ROUND_FLOOR, + IntegerToLocalizedStringTransformer::ROUND_DOWN, + IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN, + IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN, + IntegerToLocalizedStringTransformer::ROUND_HALF_UP, + IntegerToLocalizedStringTransformer::ROUND_UP, + IntegerToLocalizedStringTransformer::ROUND_CEILING, ), )); } diff --git a/Extension/Core/Type/NumberType.php b/Extension/Core/Type/NumberType.php index beb3c89a41..321f25990b 100644 --- a/Extension/Core/Type/NumberType.php +++ b/Extension/Core/Type/NumberType.php @@ -39,19 +39,19 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) // default precision is locale specific (usually around 3) 'precision' => null, 'grouping' => false, - 'rounding_mode' => \NumberFormatter::ROUND_HALFUP, + 'rounding_mode' => NumberToLocalizedStringTransformer::ROUND_HALF_UP, 'compound' => false, )); $resolver->setAllowedValues(array( 'rounding_mode' => array( - \NumberFormatter::ROUND_FLOOR, - \NumberFormatter::ROUND_DOWN, - \NumberFormatter::ROUND_HALFDOWN, - \NumberFormatter::ROUND_HALFEVEN, - \NumberFormatter::ROUND_HALFUP, - \NumberFormatter::ROUND_UP, - \NumberFormatter::ROUND_CEILING, + NumberToLocalizedStringTransformer::ROUND_FLOOR, + NumberToLocalizedStringTransformer::ROUND_DOWN, + NumberToLocalizedStringTransformer::ROUND_HALF_DOWN, + NumberToLocalizedStringTransformer::ROUND_HALF_EVEN, + NumberToLocalizedStringTransformer::ROUND_HALF_UP, + NumberToLocalizedStringTransformer::ROUND_UP, + NumberToLocalizedStringTransformer::ROUND_CEILING, ), )); } From 50c8850a5abca1f834d24eff2ab8b751e72878f0 Mon Sep 17 00:00:00 2001 From: artem kolesnikov Date: Mon, 16 Dec 2013 23:03:11 +0200 Subject: [PATCH 239/447] Fixed issue in BaseDateTimeTransformer when invalid timezone cause Transformation filed exception (closes #9403). --- .../BaseDateTimeTransformer.php | 15 +++++++ .../BaseDateTimeTransformerTest.php | 41 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 Tests/Extension/Core/DataTransformer/BaseDateTimeTransformerTest.php diff --git a/Extension/Core/DataTransformer/BaseDateTimeTransformer.php b/Extension/Core/DataTransformer/BaseDateTimeTransformer.php index e4e8932ee9..9c1b92d741 100644 --- a/Extension/Core/DataTransformer/BaseDateTimeTransformer.php +++ b/Extension/Core/DataTransformer/BaseDateTimeTransformer.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\DataTransformerInterface; +use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\UnexpectedTypeException; abstract class BaseDateTimeTransformer implements DataTransformerInterface @@ -35,6 +36,7 @@ abstract class BaseDateTimeTransformer implements DataTransformerInterface * @param string $outputTimezone The name of the output timezone * * @throws UnexpectedTypeException if a timezone is not a string + * @throws InvalidArgumentException if a timezone is not valid */ public function __construct($inputTimezone = null, $outputTimezone = null) { @@ -48,5 +50,18 @@ public function __construct($inputTimezone = null, $outputTimezone = null) $this->inputTimezone = $inputTimezone ?: date_default_timezone_get(); $this->outputTimezone = $outputTimezone ?: date_default_timezone_get(); + + // Check if input and output timezones are valid + try { + new \DateTimeZone($this->inputTimezone); + } catch (\Exception $e) { + throw new InvalidArgumentException(sprintf('Input timezone is invalid: %s.', $this->inputTimezone), $e->getCode(), $e); + } + + try { + new \DateTimeZone($this->outputTimezone); + } catch (\Exception $e) { + throw new InvalidArgumentException(sprintf('Output timezone is invalid: %s.', $this->outputTimezone), $e->getCode(), $e); + } } } diff --git a/Tests/Extension/Core/DataTransformer/BaseDateTimeTransformerTest.php b/Tests/Extension/Core/DataTransformer/BaseDateTimeTransformerTest.php new file mode 100644 index 0000000000..8f2d16bb1b --- /dev/null +++ b/Tests/Extension/Core/DataTransformer/BaseDateTimeTransformerTest.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; + +class BaseDateTimeTransformerTest extends \PHPUnit_Framework_TestCase +{ + /** + * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException + * @expectedExceptionMessage this_timezone_does_not_exist + */ + public function testConstructFailsIfInputTimezoneIsInvalid() + { + $this->getMock( + 'Symfony\Component\Form\Extension\Core\DataTransformer\BaseDateTimeTransformer', + array(), + array('this_timezone_does_not_exist') + ); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException + * @expectedExceptionMessage that_timezone_does_not_exist + */ + public function testConstructFailsIfOutputTimezoneIsInvalid() + { + $this->getMock( + 'Symfony\Component\Form\Extension\Core\DataTransformer\BaseDateTimeTransformer', + array(), + array(null, 'that_timezone_does_not_exist') + ); + } +} From 04f0a68cea799eaaca6bc681a31fa14f4b761282 Mon Sep 17 00:00:00 2001 From: Peter Rehm Date: Sat, 14 Dec 2013 15:36:37 +0100 Subject: [PATCH 240/447] [Form] Added delete_empty option to allow proper emptyData handling of collections --- .../Core/EventListener/ResizeFormListener.php | 28 ++++++- Extension/Core/Type/CollectionType.php | 4 +- Form.php | 4 +- .../Core/Type/CollectionTypeTest.php | 74 +++++++++++++++++++ Tests/Fixtures/Author.php | 6 ++ 5 files changed, 112 insertions(+), 4 deletions(-) diff --git a/Extension/Core/EventListener/ResizeFormListener.php b/Extension/Core/EventListener/ResizeFormListener.php index f1c39db245..15cfd095d8 100644 --- a/Extension/Core/EventListener/ResizeFormListener.php +++ b/Extension/Core/EventListener/ResizeFormListener.php @@ -45,12 +45,18 @@ class ResizeFormListener implements EventSubscriberInterface */ protected $allowDelete; - public function __construct($type, array $options = array(), $allowAdd = false, $allowDelete = false) + /** + * @var bool + */ + private $deleteEmpty; + + public function __construct($type, array $options = array(), $allowAdd = false, $allowDelete = false, $deleteEmpty = false) { $this->type = $type; $this->allowAdd = $allowAdd; $this->allowDelete = $allowDelete; $this->options = $options; + $this->deleteEmpty = $deleteEmpty; } public static function getSubscribedEvents() @@ -126,8 +132,13 @@ public function preSubmit(FormEvent $event) public function onSubmit(FormEvent $event) { $form = $event->getForm(); + $previousData = $event->getForm()->getData(); $data = $event->getData(); + // At this point, $data is an array or an array-like object that already contains the + // new entries, which were added by the data mapper. The data mapper ignores existing + // entries, so we need to manually unset removed entries in the collection. + if (null === $data) { $data = array(); } @@ -136,10 +147,23 @@ public function onSubmit(FormEvent $event) throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)'); } + if ($this->deleteEmpty) { + foreach ($form as $name => $child) { + $isNew = !isset($previousData[$name]); + + // $isNew can only be true if allowAdd is true, so we don't + // need to check allowAdd again + if ($child->isEmpty() && ($isNew || $this->allowDelete)) { + unset($data[$name]); + $form->remove($name); + } + } + } + // The data mapper only adds, but does not remove items, so do this // here if ($this->allowDelete) { - foreach ($data as $name => $child) { + foreach ($data as $name => $childData) { if (!$form->has($name)) { unset($data[$name]); } diff --git a/Extension/Core/Type/CollectionType.php b/Extension/Core/Type/CollectionType.php index 0cb3af1bb7..d039f98d68 100644 --- a/Extension/Core/Type/CollectionType.php +++ b/Extension/Core/Type/CollectionType.php @@ -37,7 +37,8 @@ public function buildForm(FormBuilderInterface $builder, array $options) $options['type'], $options['options'], $options['allow_add'], - $options['allow_delete'] + $options['allow_delete'], + $options['delete_empty'] ); $builder->addEventSubscriber($resizeListener); @@ -86,6 +87,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'prototype_name' => '__name__', 'type' => 'text', 'options' => array(), + 'delete_empty' => false, )); $resolver->setNormalizers(array( diff --git a/Form.php b/Form.php index 22207c2c48..e677fff629 100644 --- a/Form.php +++ b/Form.php @@ -899,7 +899,9 @@ public function remove($name) } if (isset($this->children[$name])) { - $this->children[$name]->setParent(null); + if (!$this->children[$name]->isSubmitted()) { + $this->children[$name]->setParent(null); + } unset($this->children[$name]); } diff --git a/Tests/Extension/Core/Type/CollectionTypeTest.php b/Tests/Extension/Core/Type/CollectionTypeTest.php index be3ad9db5c..58bbfad782 100644 --- a/Tests/Extension/Core/Type/CollectionTypeTest.php +++ b/Tests/Extension/Core/Type/CollectionTypeTest.php @@ -12,6 +12,8 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Form; +use Symfony\Component\Form\Tests\Fixtures\Author; +use Symfony\Component\Form\Tests\Fixtures\AuthorType; class CollectionTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { @@ -88,6 +90,78 @@ public function testResizedDownIfSubmittedWithMissingDataAndAllowDelete() $this->assertEquals(array('foo@foo.com'), $form->getData()); } + public function testResizedDownIfSubmittedWithEmptyDataAndDeleteEmpty() + { + $form = $this->factory->create('collection', null, array( + 'type' => 'text', + 'allow_delete' => true, + 'delete_empty' => true, + )); + + $form->setData(array('foo@foo.com', 'bar@bar.com')); + $form->submit(array('foo@foo.com', '')); + + $this->assertTrue($form->has('0')); + $this->assertFalse($form->has('1')); + $this->assertEquals('foo@foo.com', $form[0]->getData()); + $this->assertEquals(array('foo@foo.com'), $form->getData()); + } + + public function testDontAddEmptyDataIfDeleteEmpty() + { + $form = $this->factory->create('collection', null, array( + 'type' => 'text', + 'allow_add' => true, + 'delete_empty' => true, + )); + + $form->setData(array('foo@foo.com')); + $form->submit(array('foo@foo.com', '')); + + $this->assertTrue($form->has('0')); + $this->assertFalse($form->has('1')); + $this->assertEquals('foo@foo.com', $form[0]->getData()); + $this->assertEquals(array('foo@foo.com'), $form->getData()); + } + + public function testNoDeleteEmptyIfDeleteNotAllowed() + { + $form = $this->factory->create('collection', null, array( + 'type' => 'text', + 'allow_delete' => false, + 'delete_empty' => true, + )); + + $form->setData(array('foo@foo.com')); + $form->submit(array('')); + + $this->assertTrue($form->has('0')); + $this->assertEquals('', $form[0]->getData()); + } + + public function testResizedDownIfSubmittedWithCompoundEmptyDataAndDeleteEmpty() + { + $form = $this->factory->create('collection', null, array( + 'type' => new AuthorType(), + // If the field is not required, no new Author will be created if the + // form is completely empty + 'options' => array('required' => false), + 'allow_add' => true, + 'delete_empty' => true, + )); + + $form->setData(array(new Author('first', 'last'))); + $form->submit(array( + array('firstName' => 's_first', 'lastName' => 's_last'), + array('firstName' => '', 'lastName' => ''), + )); + + $this->assertTrue($form->has('0')); + $this->assertFalse($form->has('1')); + $this->assertEquals(new Author('s_first', 's_last'), $form[0]->getData()); + $this->assertEquals(array(new Author('s_first', 's_last')), $form->getData()); + } + public function testNotResizedIfSubmittedWithExtraData() { $form = $this->factory->create('collection', null, array( diff --git a/Tests/Fixtures/Author.php b/Tests/Fixtures/Author.php index 1120489469..39765d9df3 100644 --- a/Tests/Fixtures/Author.php +++ b/Tests/Fixtures/Author.php @@ -21,6 +21,12 @@ class Author private $privateProperty; + public function __construct($firstName = null, $lastName = null) + { + $this->firstName = $firstName; + $this->lastName = $lastName; + } + public function setLastName($lastName) { $this->lastName = $lastName; From 99906be36bfd1807fd8312764b753bbf135e4033 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 17 Dec 2013 12:11:39 +0100 Subject: [PATCH 241/447] fixed CS --- Extension/Core/EventListener/ResizeFormListener.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Extension/Core/EventListener/ResizeFormListener.php b/Extension/Core/EventListener/ResizeFormListener.php index 15cfd095d8..3f6fb439d7 100644 --- a/Extension/Core/EventListener/ResizeFormListener.php +++ b/Extension/Core/EventListener/ResizeFormListener.php @@ -46,7 +46,7 @@ class ResizeFormListener implements EventSubscriberInterface protected $allowDelete; /** - * @var bool + * @var Boolean */ private $deleteEmpty; @@ -132,7 +132,6 @@ public function preSubmit(FormEvent $event) public function onSubmit(FormEvent $event) { $form = $event->getForm(); - $previousData = $event->getForm()->getData(); $data = $event->getData(); // At this point, $data is an array or an array-like object that already contains the @@ -148,6 +147,7 @@ public function onSubmit(FormEvent $event) } if ($this->deleteEmpty) { + $previousData = $event->getForm()->getData(); foreach ($form as $name => $child) { $isNew = !isset($previousData[$name]); From 141fafc12a6b1d3c03984efac5c2e0105faa8ae2 Mon Sep 17 00:00:00 2001 From: Bilal Amarni Date: Fri, 7 Jun 2013 16:12:58 +0200 Subject: [PATCH 242/447] [Form][2.4] added an option for multiple files upload (closes #1400) --- CHANGELOG.md | 4 ++++ Extension/Core/Type/FileType.php | 6 ++++++ Tests/Extension/Core/Type/FileTypeTest.php | 19 +++++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a696c7be9a..0c0035810d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ CHANGELOG ========= +2.5.0 +------ + +* added an option for multiple files upload 2.3.0 ------ diff --git a/Extension/Core/Type/FileType.php b/Extension/Core/Type/FileType.php index 2c09da6f6b..26dd9f13bb 100644 --- a/Extension/Core/Type/FileType.php +++ b/Extension/Core/Type/FileType.php @@ -23,6 +23,11 @@ class FileType extends AbstractType */ public function buildView(FormView $view, FormInterface $form, array $options) { + if ($options['multiple']) { + $view->vars['full_name'] .= '[]'; + $view->vars['attr']['multiple'] = 'multiple'; + } + $view->vars = array_replace($view->vars, array( 'type' => 'file', 'value' => '', @@ -48,6 +53,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'compound' => false, 'data_class' => 'Symfony\Component\HttpFoundation\File\File', 'empty_data' => null, + 'multiple' => false, )); } diff --git a/Tests/Extension/Core/Type/FileTypeTest.php b/Tests/Extension/Core/Type/FileTypeTest.php index 63556eb5a6..0227af4f23 100644 --- a/Tests/Extension/Core/Type/FileTypeTest.php +++ b/Tests/Extension/Core/Type/FileTypeTest.php @@ -44,6 +44,25 @@ public function testSubmitEmpty() $this->assertNull($form->getData()); } + public function testSubmitMultiple() + { + $form = $this->factory->createBuilder('file', null, array( + 'multiple' => true + ))->getForm(); + + $data = array( + $this->createUploadedFileMock('abcdef', 'first.jpg', true), + $this->createUploadedFileMock('zyxwvu', 'second.jpg', true), + ); + + $form->submit($data); + $this->assertSame($data, $form->getData()); + + $view = $form->createView(); + $this->assertSame('file[]', $view->vars['full_name']); + $this->assertArrayHasKey('multiple', $view->vars['attr']); + } + public function testDontPassValueToView() { $form = $this->factory->create('file'); From 75ca3baa1581453f4f3f80a26a82c06b4ea915ee Mon Sep 17 00:00:00 2001 From: Luis Cordova Date: Sun, 22 Dec 2013 03:11:18 -0500 Subject: [PATCH 243/447] added getter to transformer chain --- Extension/Core/DataTransformer/DataTransformerChain.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Extension/Core/DataTransformer/DataTransformerChain.php b/Extension/Core/DataTransformer/DataTransformerChain.php index 9cc185e1ab..800fc7a98b 100644 --- a/Extension/Core/DataTransformer/DataTransformerChain.php +++ b/Extension/Core/DataTransformer/DataTransformerChain.php @@ -83,4 +83,12 @@ public function reverseTransform($value) return $value; } + + /** + * @return DataTransformerInterface[] + */ + public function getTransformers() + { + return $this->transformers; + } } From 50c84e580e76cf8e15840fa0b2a1e38dc2f65eac Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 27 Dec 2013 16:08:19 +0100 Subject: [PATCH 244/447] fixed various typos --- .../DataTransformer/DateTimeToStringTransformerTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php index 987df1d81c..d6a6568b86 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php @@ -36,9 +36,9 @@ public function dataProvider() array('z', '33', '1970-02-03 00:00:00 UTC'), // not bijective - // this will not work as php will use actual date to replace missing info + // this will not work as PHP will use actual date to replace missing info // and after change of date will lookup for closest Wednesday - // i.e. value: 2010-02, php value: 2010-02-(today i.e. 20), parsed date: 2010-02-24 + // i.e. value: 2010-02, PHP value: 2010-02-(today i.e. 20), parsed date: 2010-02-24 //array('Y-m-D', '2010-02-Wed', '2010-02-03 00:00:00 UTC'), //array('Y-m-l', '2010-02-Wednesday', '2010-02-03 00:00:00 UTC'), @@ -55,7 +55,7 @@ public function dataProvider() array('g:i:s a', '4:05:06 pm', '1970-01-01 16:05:06 UTC'), array('h:i:s a', '04:05:06 pm', '1970-01-01 16:05:06 UTC'), - // seconds since unix + // seconds since Unix array('U', '1265213106', '2010-02-03 16:05:06 UTC'), ); From aafac0fdb27bbafe5e96744f91bf79272e2e42a7 Mon Sep 17 00:00:00 2001 From: Eric GELOEN Date: Mon, 4 Nov 2013 21:38:50 +0100 Subject: [PATCH 245/447] Check for hour, minute & second validity --- .../DateTimeToArrayTransformer.php | 18 +++++-- Tests/AbstractLayoutTest.php | 9 ++-- .../DateTimeToArrayTransformerTest.php | 48 +++++++++++++++++++ 3 files changed, 67 insertions(+), 8 deletions(-) diff --git a/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php b/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php index 34af282057..e746d00ed5 100644 --- a/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php @@ -144,15 +144,15 @@ public function reverseTransform($value) )); } - if (isset($value['month']) && !ctype_digit($value['month']) && !is_int($value['month'])) { + if (isset($value['month']) && !ctype_digit((string) $value['month'])) { throw new TransformationFailedException('This month is invalid'); } - if (isset($value['day']) && !ctype_digit($value['day']) && !is_int($value['day'])) { + if (isset($value['day']) && !ctype_digit((string) $value['day'])) { throw new TransformationFailedException('This day is invalid'); } - if (isset($value['year']) && !ctype_digit($value['year']) && !is_int($value['year'])) { + if (isset($value['year']) && !ctype_digit((string) $value['year'])) { throw new TransformationFailedException('This year is invalid'); } @@ -160,6 +160,18 @@ public function reverseTransform($value) throw new TransformationFailedException('This is an invalid date'); } + if (isset($value['hour']) && !ctype_digit((string) $value['hour'])) { + throw new TransformationFailedException('This hour is invalid'); + } + + if (isset($value['minute']) && !ctype_digit((string) $value['minute'])) { + throw new TransformationFailedException('This minute is invalid'); + } + + if (isset($value['second']) && !ctype_digit((string) $value['second'])) { + throw new TransformationFailedException('This second is invalid'); + } + try { $dateTime = new \DateTime(sprintf( '%s-%s-%s %s:%s:%s %s', diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index 4e922caf0b..10650e5998 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -899,13 +899,12 @@ public function testDateTimeWithEmptyValueGlobal() ); } - public function testDateTimeWithEmptyValueOnTime() + public function testDateTimeWithHourAndMinute() { - $data = array('year' => '2011', 'month' => '2', 'day' => '3', 'hour' => '', 'minute' => ''); + $data = array('year' => '2011', 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '5'); $form = $this->factory->createNamed('name', 'datetime', $data, array( 'input' => 'array', - 'empty_value' => array('hour' => 'Change&Me', 'minute' => 'Change&Me'), 'required' => false, )); @@ -930,10 +929,10 @@ public function testDateTimeWithEmptyValueOnTime() [ ./select [@id="name_time_hour"] - [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + [./option[@value="4"][@selected="selected"]] /following-sibling::select [@id="name_time_minute"] - [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + [./option[@value="5"][@selected="selected"]] ] ] [count(.//select)=5] diff --git a/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.php b/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.php index 4898b88d34..db5f2b1638 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.php @@ -509,4 +509,52 @@ public function testReverseTransformWithStringYear() 'second' => '6', )); } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformWithEmptyStringHour() + { + $transformer = new DateTimeToArrayTransformer(); + $transformer->reverseTransform(array( + 'year' => '2010', + 'month' => '2', + 'day' => '31', + 'hour' => '', + 'minute' => '5', + 'second' => '6', + )); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformWithEmptyStringMinute() + { + $transformer = new DateTimeToArrayTransformer(); + $transformer->reverseTransform(array( + 'year' => '2010', + 'month' => '2', + 'day' => '31', + 'hour' => '4', + 'minute' => '', + 'second' => '6', + )); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformWithEmptyStringSecond() + { + $transformer = new DateTimeToArrayTransformer(); + $transformer->reverseTransform(array( + 'year' => '2010', + 'month' => '2', + 'day' => '31', + 'hour' => '4', + 'minute' => '5', + 'second' => '', + )); + } } From 332e9b6d0c4f0d72ffcdd18ea46ff76e061573db Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 28 Dec 2013 08:46:05 +0100 Subject: [PATCH 246/447] fixed CS for lambdas --- Tests/Extension/Validator/Constraints/FormValidatorTest.php | 4 ++-- Tests/Extension/Validator/Type/BaseValidatorExtensionTest.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index cbe66f7249..dc504172a0 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -398,7 +398,7 @@ public function testHandleClosureValidationGroups() { $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); - $options = array('validation_groups' => function(FormInterface $form){ + $options = array('validation_groups' => function (FormInterface $form) { return array('group1', 'group2'); }); $form = $this->getBuilder('name', '\stdClass', $options) @@ -533,7 +533,7 @@ public function testUseInheritedClosureValidationGroup() $object = $this->getMock('\stdClass'); $parentOptions = array( - 'validation_groups' => function(FormInterface $form){ + 'validation_groups' => function (FormInterface $form) { return array('group1', 'group2'); }, 'cascade_validation' => true, diff --git a/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.php b/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.php index fd437c50ea..527de1616b 100644 --- a/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.php +++ b/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.php @@ -64,7 +64,7 @@ public function testValidationGroupsCanBeSetToCallback() public function testValidationGroupsCanBeSetToClosure() { $form = $this->createForm(array( - 'validation_groups' => function(FormInterface $form){ return null; }, + 'validation_groups' => function (FormInterface $form) { return null; }, )); $this->assertTrue(is_callable($form->getConfig()->getOption('validation_groups'))); From 5231cc45b031affa6a7f4182a708a2a86c4b8490 Mon Sep 17 00:00:00 2001 From: Wouter J Date: Sun, 20 Oct 2013 22:36:31 +0200 Subject: [PATCH 247/447] Fixed deprecated method calls --- Extension/Core/ChoiceList/ObjectChoiceList.php | 2 +- Extension/Core/CoreExtension.php | 2 +- Extension/Core/Type/FormType.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Extension/Core/ChoiceList/ObjectChoiceList.php b/Extension/Core/ChoiceList/ObjectChoiceList.php index 0a153883a3..7c7aa0c768 100644 --- a/Extension/Core/ChoiceList/ObjectChoiceList.php +++ b/Extension/Core/ChoiceList/ObjectChoiceList.php @@ -87,7 +87,7 @@ class ObjectChoiceList extends ChoiceList */ public function __construct($choices, $labelPath = null, array $preferredChoices = array(), $groupPath = null, $valuePath = null, PropertyAccessorInterface $propertyAccessor = null) { - $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::getPropertyAccessor(); + $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); $this->labelPath = null !== $labelPath ? new PropertyPath($labelPath) : null; $this->groupPath = null !== $groupPath ? new PropertyPath($groupPath) : null; $this->valuePath = null !== $valuePath ? new PropertyPath($valuePath) : null; diff --git a/Extension/Core/CoreExtension.php b/Extension/Core/CoreExtension.php index bbcac4baea..a0153a57eb 100644 --- a/Extension/Core/CoreExtension.php +++ b/Extension/Core/CoreExtension.php @@ -24,7 +24,7 @@ class CoreExtension extends AbstractExtension protected function loadTypes() { return array( - new Type\FormType(PropertyAccess::getPropertyAccessor()), + new Type\FormType(PropertyAccess::createPropertyAccessor()), new Type\BirthdayType(), new Type\CheckboxType(), new Type\ChoiceType(), diff --git a/Extension/Core/Type/FormType.php b/Extension/Core/Type/FormType.php index a64b5ac465..a4fce33272 100644 --- a/Extension/Core/Type/FormType.php +++ b/Extension/Core/Type/FormType.php @@ -31,7 +31,7 @@ class FormType extends BaseType public function __construct(PropertyAccessorInterface $propertyAccessor = null) { - $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::getPropertyAccessor(); + $this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); } /** From b99eb68ebe2c5cdd1a9fbafd8391c27632315a6c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 30 Dec 2013 08:13:22 +0100 Subject: [PATCH 248/447] fixes PSR-0 issues in tests --- Tests/FormRendererTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/FormRendererTest.php b/Tests/FormRendererTest.php index 69b048f7db..eda35e36ac 100644 --- a/Tests/FormRendererTest.php +++ b/Tests/FormRendererTest.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Form\Test; +namespace Symfony\Component\Form\Tests; class FormRendererTest extends \PHPUnit_Framework_TestCase { From 32efe008fe1b53eaa072f107be686f9cd434bd8e Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 1 Jan 2014 08:52:14 +0100 Subject: [PATCH 249/447] removed unneeded use statements --- Extension/Csrf/CsrfExtension.php | 1 - Extension/Validator/ValidatorExtension.php | 1 - Extension/Validator/ViolationMapper/ViolationMapper.php | 1 - NativeRequestHandler.php | 2 -- 4 files changed, 5 deletions(-) diff --git a/Extension/Csrf/CsrfExtension.php b/Extension/Csrf/CsrfExtension.php index f9d9e40aa8..7653e97ee4 100644 --- a/Extension/Csrf/CsrfExtension.php +++ b/Extension/Csrf/CsrfExtension.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Form\Extension\Csrf; -use Symfony\Component\Form\Extension\Csrf\Type; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; use Symfony\Component\Form\AbstractExtension; use Symfony\Component\Translation\TranslatorInterface; diff --git a/Extension/Validator/ValidatorExtension.php b/Extension/Validator/ValidatorExtension.php index 9cff22a276..572a4ac938 100644 --- a/Extension/Validator/ValidatorExtension.php +++ b/Extension/Validator/ValidatorExtension.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Form\Extension\Validator; -use Symfony\Component\Form\Extension\Validator\Type; use Symfony\Component\Form\Extension\Validator\Constraints\Form; use Symfony\Component\Form\AbstractExtension; use Symfony\Component\Validator\ValidatorInterface; diff --git a/Extension/Validator/ViolationMapper/ViolationMapper.php b/Extension/Validator/ViolationMapper/ViolationMapper.php index 3be55e64c1..6ea56eb03b 100644 --- a/Extension/Validator/ViolationMapper/ViolationMapper.php +++ b/Extension/Validator/ViolationMapper/ViolationMapper.php @@ -16,7 +16,6 @@ use Symfony\Component\PropertyAccess\PropertyPathIterator; use Symfony\Component\PropertyAccess\PropertyPathBuilder; use Symfony\Component\PropertyAccess\PropertyPathIteratorInterface; -use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationPathIterator; use Symfony\Component\Form\FormError; use Symfony\Component\Validator\ConstraintViolation; diff --git a/NativeRequestHandler.php b/NativeRequestHandler.php index 359df670ff..c79159b3d3 100644 --- a/NativeRequestHandler.php +++ b/NativeRequestHandler.php @@ -12,8 +12,6 @@ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\UnexpectedTypeException; -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\RequestHandlerInterface; /** * A request handler using PHP's super globals $_GET, $_POST and $_SERVER. From 553abdb71ae597fd0ff6e195d3e238432058fbca Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 1 Jan 2014 09:20:41 +0100 Subject: [PATCH 250/447] removed unneeded use statements --- Extension/Csrf/CsrfExtension.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Extension/Csrf/CsrfExtension.php b/Extension/Csrf/CsrfExtension.php index 9cc186c42e..765a012e8d 100644 --- a/Extension/Csrf/CsrfExtension.php +++ b/Extension/Csrf/CsrfExtension.php @@ -13,6 +13,10 @@ use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderAdapter; +use Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface; +use Symfony\Component\Form\AbstractExtension; +use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; +use Symfony\Component\Translation\TranslatorInterface; /** * This extension protects forms by using a CSRF token. From a71f35797788aa4dbcdc804e27f9d713649d1d48 Mon Sep 17 00:00:00 2001 From: Joseph Bielawski Date: Tue, 7 Jan 2014 09:39:31 +0100 Subject: [PATCH 251/447] [Form] Update minimal requirement in composer.json Minimal requirement for PropertyAccess component needs to be `~2.3` as Form component depends on new method `PropertyAccess::createPropertyAccessor()` --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 734150118b..14f9dadce4 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ "symfony/event-dispatcher": "~2.1", "symfony/intl": "~2.3", "symfony/options-resolver": "~2.1", - "symfony/property-access": "~2.2" + "symfony/property-access": "~2.3" }, "require-dev": { "symfony/validator": "~2.2", From 16df054075663d6f1b6cf1df519ccdd0d6dcedac Mon Sep 17 00:00:00 2001 From: Luis Cordova Date: Mon, 6 Jan 2014 17:25:20 -0500 Subject: [PATCH 252/447] update year on licenses --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 88a57f8d8d..0b3292cf90 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2013 Fabien Potencier +Copyright (c) 2004-2014 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From f8e4d5879671360d5c73ffc79cc62d6b045b2af5 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 10 Jan 2014 11:44:16 +0100 Subject: [PATCH 253/447] [Form] Errors now reference the field they were added to and the violation/exception that caused them --- CHANGELOG.md | 2 + Extension/DataCollector/FormDataCollector.php | 17 +- Extension/DataCollector/FormDataExtractor.php | 29 +- .../ViolationMapper/ViolationMapper.php | 3 +- Form.php | 4 + FormError.php | 86 +++++- .../DataCollector/FormDataCollectorTest.php | 257 +++++++++++------- .../DataCollector/FormDataExtractorTest.php | 52 +++- .../ViolationMapper/ViolationMapperTest.php | 35 +-- 9 files changed, 360 insertions(+), 125 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b9c8256b5a..ff4e46284f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ CHANGELOG ------ * added an option for multiple files upload + * form errors now reference their cause (constraint violation, exception, ...) + * form errors now remember which form they were originally added to 2.4.0 ----- diff --git a/Extension/DataCollector/FormDataCollector.php b/Extension/DataCollector/FormDataCollector.php index 2119248132..bcadfc5977 100644 --- a/Extension/DataCollector/FormDataCollector.php +++ b/Extension/DataCollector/FormDataCollector.php @@ -69,6 +69,7 @@ public function __construct(FormDataExtractorInterface $dataExtractor) $this->dataExtractor = $dataExtractor; $this->data = array( 'forms' => array(), + 'forms_by_hash' => array(), 'nb_errors' => 0, ); } @@ -184,7 +185,7 @@ public function buildPreliminaryFormTree(FormInterface $form) { $this->data['forms'][$form->getName()] = array(); - $this->recursiveBuildPreliminaryFormTree($form, $this->data['forms'][$form->getName()]); + $this->recursiveBuildPreliminaryFormTree($form, $this->data['forms'][$form->getName()], $this->data['forms_by_hash']); } /** @@ -194,7 +195,7 @@ public function buildFinalFormTree(FormInterface $form, FormView $view) { $this->data['forms'][$form->getName()] = array(); - $this->recursiveBuildFinalFormTree($form, $view, $this->data['forms'][$form->getName()]); + $this->recursiveBuildFinalFormTree($form, $view, $this->data['forms'][$form->getName()], $this->data['forms_by_hash']); } /** @@ -213,7 +214,7 @@ public function getData() return $this->data; } - private function recursiveBuildPreliminaryFormTree(FormInterface $form, &$output = null) + private function recursiveBuildPreliminaryFormTree(FormInterface $form, &$output = null, array &$outputByHash) { $hash = spl_object_hash($form); @@ -221,16 +222,18 @@ private function recursiveBuildPreliminaryFormTree(FormInterface $form, &$output ? $this->dataByForm[$hash] : array(); + $outputByHash[$hash] = &$output; + $output['children'] = array(); foreach ($form as $name => $child) { $output['children'][$name] = array(); - $this->recursiveBuildPreliminaryFormTree($child, $output['children'][$name]); + $this->recursiveBuildPreliminaryFormTree($child, $output['children'][$name], $outputByHash); } } - private function recursiveBuildFinalFormTree(FormInterface $form = null, FormView $view, &$output = null) + private function recursiveBuildFinalFormTree(FormInterface $form = null, FormView $view, &$output = null, array &$outputByHash) { $viewHash = spl_object_hash($view); $formHash = null; @@ -255,6 +258,8 @@ private function recursiveBuildFinalFormTree(FormInterface $form = null, FormVie ? $this->dataByForm[$formHash] : array() ); + + $outputByHash[$formHash] = &$output; } $output['children'] = array(); @@ -268,7 +273,7 @@ private function recursiveBuildFinalFormTree(FormInterface $form = null, FormVie $output['children'][$name] = array(); - $this->recursiveBuildFinalFormTree($childForm, $childView, $output['children'][$name]); + $this->recursiveBuildFinalFormTree($childForm, $childView, $output['children'][$name], $outputByHash); } } } diff --git a/Extension/DataCollector/FormDataExtractor.php b/Extension/DataCollector/FormDataExtractor.php index 8765b13ca4..80e910177a 100644 --- a/Extension/DataCollector/FormDataExtractor.php +++ b/Extension/DataCollector/FormDataExtractor.php @@ -14,6 +14,7 @@ use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter; +use Symfony\Component\Validator\ConstraintViolationInterface; /** * Default implementation of {@link FormDataExtractorInterface}. @@ -43,6 +44,7 @@ public function extractConfiguration(FormInterface $form) { $data = array( 'id' => $this->buildId($form), + 'name' => $form->getName(), 'type' => $form->getConfig()->getType()->getName(), 'type_class' => get_class($form->getConfig()->getType()->getInnerType()), 'synchronized' => $this->valueExporter->exportValue($form->isSynchronized()), @@ -108,9 +110,26 @@ public function extractSubmittedData(FormInterface $form) } foreach ($form->getErrors() as $error) { - $data['errors'][] = array( + $errorData = array( 'message' => $error->getMessage(), + 'origin' => is_object($error->getOrigin()) + ? spl_object_hash($error->getOrigin()) + : null, ); + + $cause = $error->getCause(); + + if ($cause instanceof ConstraintViolationInterface) { + $errorData['cause'] = array( + 'root' => $this->valueExporter->exportValue($cause->getRoot()), + 'path' => $this->valueExporter->exportValue($cause->getPropertyPath()), + 'value' => $this->valueExporter->exportValue($cause->getInvalidValue()), + ); + } else { + $errorData['cause'] = null !== $cause ? $this->valueExporter->exportValue($cause) : null; + } + + $data['errors'][] = $errorData; } $data['synchronized'] = $this->valueExporter->exportValue($form->isSynchronized()); @@ -127,8 +146,12 @@ public function extractViewVariables(FormView $view) // Set the ID in case no FormInterface object was collected for this // view - if (isset($view->vars['id'])) { - $data['id'] = $view->vars['id']; + if (!isset($data['id'])) { + $data['id'] = isset($view->vars['id']) ? $view->vars['id'] : null; + } + + if (!isset($data['name'])) { + $data['name'] = isset($view->vars['name']) ? $view->vars['name'] : null; } foreach ($view->vars as $varName => $value) { diff --git a/Extension/Validator/ViolationMapper/ViolationMapper.php b/Extension/Validator/ViolationMapper/ViolationMapper.php index 6ea56eb03b..15ceb0cf08 100644 --- a/Extension/Validator/ViolationMapper/ViolationMapper.php +++ b/Extension/Validator/ViolationMapper/ViolationMapper.php @@ -128,7 +128,8 @@ public function mapViolation(ConstraintViolation $violation, FormInterface $form $violation->getMessage(), $violation->getMessageTemplate(), $violation->getMessageParameters(), - $violation->getMessagePluralization() + $violation->getMessagePluralization(), + $violation )); } } diff --git a/Form.php b/Form.php index e677fff629..f4696c0dfe 100644 --- a/Form.php +++ b/Form.php @@ -673,6 +673,10 @@ public function bind($submittedData) public function addError(FormError $error) { if ($this->parent && $this->config->getErrorBubbling()) { + if (null === $error->getOrigin()) { + $error->setOrigin($this); + } + $this->parent->addError($error); } else { $this->errors[] = $error; diff --git a/FormError.php b/FormError.php index 343165ca46..6970244cf7 100644 --- a/FormError.php +++ b/FormError.php @@ -11,12 +11,14 @@ namespace Symfony\Component\Form; +use Symfony\Component\Form\Exception\BadMethodCallException; + /** * Wraps errors in forms * * @author Bernhard Schussek */ -class FormError +class FormError implements \Serializable { /** * @var string @@ -41,6 +43,18 @@ class FormError */ protected $messagePluralization; + /** + * The cause for this error + * @var mixed + */ + private $cause; + + /** + * The form that spawned this error + * @var FormInterface + */ + private $origin; + /** * Constructor * @@ -50,17 +64,19 @@ class FormError * @param string $message The translated error message * @param string|null $messageTemplate The template for the error message * @param array $messageParameters The parameters that should be - * substituted in the message template. + * substituted in the message template * @param integer|null $messagePluralization The value for error message pluralization + * @param mixed $cause The cause of the error * * @see \Symfony\Component\Translation\Translator */ - public function __construct($message, $messageTemplate = null, array $messageParameters = array(), $messagePluralization = null) + public function __construct($message, $messageTemplate = null, array $messageParameters = array(), $messagePluralization = null, $cause = null) { $this->message = $message; $this->messageTemplate = $messageTemplate ?: $message; $this->messageParameters = $messageParameters; $this->messagePluralization = $messagePluralization; + $this->cause = $cause; } /** @@ -102,4 +118,68 @@ public function getMessagePluralization() { return $this->messagePluralization; } + + /** + * Returns the cause of this error. + * + * @return mixed The cause of this error + */ + public function getCause() + { + return $this->cause; + } + + /** + * Sets the form that caused this error. + * + * This method must only be called once. + * + * @param FormInterface $origin The form that caused this error + * + * @throws BadMethodCallException If the method is called more than once + */ + public function setOrigin(FormInterface $origin) + { + if (null !== $this->origin) { + throw new BadMethodCallException('setOrigin() must only be called once.'); + } + + $this->origin = $origin; + } + + /** + * Returns the form that caused this error. + * + * @return FormInterface The form that caused this error + */ + public function getOrigin() + { + return $this->origin; + } + + /** + * Serializes this error. + * + * @return string The serialized error + */ + public function serialize() + { + return serialize(array( + $this->message, + $this->messageTemplate, + $this->messageParameters, + $this->messagePluralization, + $this->cause + )); + } + + /** + * Unserializes a serialized error. + * + * @param string $serialized The serialized error + */ + public function unserialize($serialized) + { + list($this->message, $this->messageTemplate, $this->messageParameters, $this->messagePluralization, $this->cause) = unserialize($serialized); + } } diff --git a/Tests/Extension/DataCollector/FormDataCollectorTest.php b/Tests/Extension/DataCollector/FormDataCollectorTest.php index 99ac76ac23..885b4b68d1 100644 --- a/Tests/Extension/DataCollector/FormDataCollectorTest.php +++ b/Tests/Extension/DataCollector/FormDataCollectorTest.php @@ -111,23 +111,31 @@ public function testBuildPreliminaryFormTree() $this->dataCollector->collectSubmittedData($this->form); $this->dataCollector->buildPreliminaryFormTree($this->form); - $this->assertSame(array( - 'forms' => array( - 'name' => array( - 'config' => 'foo', - 'default_data' => 'foo', - 'submitted_data' => 'foo', - 'children' => array( - 'child' => array( - 'config' => 'bar', - 'default_data' => 'bar', - 'submitted_data' => 'bar', - 'children' => array(), - ), - ), - ), + $childFormData = array( + 'config' => 'bar', + 'default_data' => 'bar', + 'submitted_data' => 'bar', + 'children' => array(), + ); + + $formData = array( + 'config' => 'foo', + 'default_data' => 'foo', + 'submitted_data' => 'foo', + 'children' => array( + 'child' => $childFormData, ), - 'nb_errors' => 0, + ); + + $this->assertSame(array( + 'forms' => array( + 'name' => $formData, + ), + 'forms_by_hash' => array( + spl_object_hash($this->form) => $formData, + spl_object_hash($this->childForm) => $childFormData, + ), + 'nb_errors' => 0, ), $this->dataCollector->getData()); } @@ -149,28 +157,36 @@ public function testBuildMultiplePreliminaryFormTrees() $this->dataCollector->collectConfiguration($form2); $this->dataCollector->buildPreliminaryFormTree($form1); + $form1Data = array( + 'config' => 'foo', + 'children' => array(), + ); + $this->assertSame(array( 'forms' => array( - 'form1' => array( - 'config' => 'foo', - 'children' => array(), - ), + 'form1' => $form1Data, + ), + 'forms_by_hash' => array( + spl_object_hash($form1) => $form1Data, ), 'nb_errors' => 0, ), $this->dataCollector->getData()); $this->dataCollector->buildPreliminaryFormTree($form2); + $form2Data = array( + 'config' => 'bar', + 'children' => array(), + ); + $this->assertSame(array( 'forms' => array( - 'form1' => array( - 'config' => 'foo', - 'children' => array(), - ), - 'form2' => array( - 'config' => 'bar', - 'children' => array(), - ), + 'form1' => $form1Data, + 'form2' => $form2Data, + ), + 'forms_by_hash' => array( + spl_object_hash($form1) => $form1Data, + spl_object_hash($form2) => $form2Data, ), 'nb_errors' => 0, ), $this->dataCollector->getData()); @@ -191,12 +207,17 @@ public function testBuildSamePreliminaryFormTreeMultipleTimes() $this->dataCollector->collectConfiguration($this->form); $this->dataCollector->buildPreliminaryFormTree($this->form); + $formData = array( + 'config' => 'foo', + 'children' => array(), + ); + $this->assertSame(array( 'forms' => array( - 'name' => array( - 'config' => 'foo', - 'children' => array(), - ), + 'name' => $formData, + ), + 'forms_by_hash' => array( + spl_object_hash($this->form) => $formData, ), 'nb_errors' => 0, ), $this->dataCollector->getData()); @@ -204,13 +225,18 @@ public function testBuildSamePreliminaryFormTreeMultipleTimes() $this->dataCollector->collectDefaultData($this->form); $this->dataCollector->buildPreliminaryFormTree($this->form); + $formData = array( + 'config' => 'foo', + 'default_data' => 'foo', + 'children' => array(), + ); + $this->assertSame(array( 'forms' => array( - 'name' => array( - 'config' => 'foo', - 'default_data' => 'foo', - 'children' => array(), - ), + 'name' => $formData, + ), + 'forms_by_hash' => array( + spl_object_hash($this->form) => $formData, ), 'nb_errors' => 0, ), $this->dataCollector->getData()); @@ -220,11 +246,16 @@ public function testBuildPreliminaryFormTreeWithoutCollectingAnyData() { $this->dataCollector->buildPreliminaryFormTree($this->form); + $formData = array( + 'children' => array(), + ); + $this->assertSame(array( 'forms' => array( - 'name' => array( - 'children' => array(), - ), + 'name' => $formData, + ), + 'forms_by_hash' => array( + spl_object_hash($this->form) => $formData, ), 'nb_errors' => 0, ), $this->dataCollector->getData()); @@ -278,23 +309,31 @@ public function testBuildFinalFormTree() $this->dataCollector->collectViewVariables($this->view); $this->dataCollector->buildFinalFormTree($this->form, $this->view); + $childFormData = array( + 'view_vars' => 'bar', + 'config' => 'bar', + 'default_data' => 'bar', + 'submitted_data' => 'bar', + 'children' => array(), + ); + + $formData = array( + 'view_vars' => 'foo', + 'config' => 'foo', + 'default_data' => 'foo', + 'submitted_data' => 'foo', + 'children' => array( + 'child' => $childFormData, + ), + ); + $this->assertSame(array( 'forms' => array( - 'name' => array( - 'view_vars' => 'foo', - 'config' => 'foo', - 'default_data' => 'foo', - 'submitted_data' => 'foo', - 'children' => array( - 'child' => array( - 'view_vars' => 'bar', - 'config' => 'bar', - 'default_data' => 'bar', - 'submitted_data' => 'bar', - 'children' => array(), - ), - ), - ), + 'name' => $formData, + ), + 'forms_by_hash' => array( + spl_object_hash($this->form) => $formData, + spl_object_hash($this->childForm) => $childFormData, ), 'nb_errors' => 0, ), $this->dataCollector->getData()); @@ -302,41 +341,57 @@ public function testBuildFinalFormTree() public function testFinalFormReliesOnFormViewStructure() { - $this->form->add($this->createForm('first')); - $this->form->add($this->createForm('second')); + $this->form->add($child1 = $this->createForm('first')); + $this->form->add($child2 = $this->createForm('second')); $this->view->children['second'] = $this->childView; $this->dataCollector->buildPreliminaryFormTree($this->form); + $child1Data = array( + 'children' => array(), + ); + + $child2Data = array( + 'children' => array(), + ); + + $formData = array( + 'children' => array( + 'first' => $child1Data, + 'second' => $child2Data, + ), + ); + $this->assertSame(array( 'forms' => array( - 'name' => array( - 'children' => array( - 'first' => array( - 'children' => array(), - ), - 'second' => array( - 'children' => array(), - ), - ), - ), + 'name' => $formData, + ), + 'forms_by_hash' => array( + spl_object_hash($this->form) => $formData, + spl_object_hash($child1) => $child1Data, + spl_object_hash($child2) => $child2Data, ), 'nb_errors' => 0, ), $this->dataCollector->getData()); $this->dataCollector->buildFinalFormTree($this->form, $this->view); + $formData = array( + 'children' => array( + // "first" not present in FormView + 'second' => $child2Data, + ), + ); + $this->assertSame(array( 'forms' => array( - 'name' => array( - 'children' => array( - // "first" not present in FormView - 'second' => array( - 'children' => array(), - ), - ), - ), + 'name' => $formData, + ), + 'forms_by_hash' => array( + spl_object_hash($this->form) => $formData, + spl_object_hash($child1) => $child1Data, + spl_object_hash($child2) => $child2Data, ), 'nb_errors' => 0, ), $this->dataCollector->getData()); @@ -363,17 +418,25 @@ public function testChildViewsCanBeWithoutCorrespondingChildForms() $this->dataCollector->collectConfiguration($this->childForm); $this->dataCollector->buildFinalFormTree($this->form, $this->view); + $childFormData = array( + // no "config" key + 'children' => array(), + ); + + $formData = array( + 'config' => 'foo', + 'children' => array( + 'child' => $childFormData, + ), + ); + $this->assertSame(array( 'forms' => array( - 'name' => array( - 'config' => 'foo', - 'children' => array( - 'child' => array( - // no "config" key - 'children' => array(), - ), - ), - ), + 'name' => $formData, + ), + 'forms_by_hash' => array( + spl_object_hash($this->form) => $formData, + // no child entry ), 'nb_errors' => 0, ), $this->dataCollector->getData()); @@ -403,17 +466,25 @@ public function testChildViewsWithoutCorrespondingChildFormsMayBeExplicitlyAssoc $this->dataCollector->collectConfiguration($this->childForm); $this->dataCollector->buildFinalFormTree($this->form, $this->view); + $childFormData = array( + 'config' => 'bar', + 'children' => array(), + ); + + $formData = array( + 'config' => 'foo', + 'children' => array( + 'child' => $childFormData, + ), + ); + $this->assertSame(array( 'forms' => array( - 'name' => array( - 'config' => 'foo', - 'children' => array( - 'child' => array( - 'config' => 'bar', - 'children' => array(), - ), - ), - ), + 'name' => $formData, + ), + 'forms_by_hash' => array( + spl_object_hash($this->form) => $formData, + spl_object_hash($this->childForm) => $childFormData, ), 'nb_errors' => 0, ), $this->dataCollector->getData()); diff --git a/Tests/Extension/DataCollector/FormDataExtractorTest.php b/Tests/Extension/DataCollector/FormDataExtractorTest.php index bf3cd71975..37b5b7d86c 100644 --- a/Tests/Extension/DataCollector/FormDataExtractorTest.php +++ b/Tests/Extension/DataCollector/FormDataExtractorTest.php @@ -27,7 +27,7 @@ class FormDataExtractorTest_SimpleValueExporter extends ValueExporter */ public function exportValue($value) { - return var_export($value, true); + return is_object($value) ? sprintf('object(%s)', get_class($value)) : var_export($value, true); } } @@ -80,6 +80,7 @@ public function testExtractConfiguration() $this->assertSame(array( 'id' => 'name', + 'name' => 'name', 'type' => 'type_name', 'type_class' => 'stdClass', 'synchronized' => 'true', @@ -113,6 +114,7 @@ public function testExtractConfigurationSortsPassedOptions() $this->assertSame(array( 'id' => 'name', + 'name' => 'name', 'type' => 'type_name', 'type_class' => 'stdClass', 'synchronized' => 'true', @@ -147,6 +149,7 @@ public function testExtractConfigurationSortsResolvedOptions() $this->assertSame(array( 'id' => 'name', + 'name' => 'name', 'type' => 'type_name', 'type_class' => 'stdClass', 'synchronized' => 'true', @@ -186,6 +189,7 @@ public function testExtractConfigurationBuildsIdRecursively() $this->assertSame(array( 'id' => 'grandParent_parent_name', + 'name' => 'name', 'type' => 'type_name', 'type_class' => 'stdClass', 'synchronized' => 'true', @@ -315,7 +319,48 @@ public function testExtractSubmittedDataStoresErrors() 'norm' => "'Foobar'", ), 'errors' => array( - array('message' => 'Invalid!'), + array('message' => 'Invalid!', 'origin' => null, 'cause' => null), + ), + 'synchronized' => 'true', + ), $this->dataExtractor->extractSubmittedData($form)); + } + + public function testExtractSubmittedDataStoresErrorOrigin() + { + $form = $this->createBuilder('name')->getForm(); + + $error = new FormError('Invalid!'); + $error->setOrigin($form); + + $form->submit('Foobar'); + $form->addError($error); + + $this->assertSame(array( + 'submitted_data' => array( + 'norm' => "'Foobar'", + ), + 'errors' => array( + array('message' => 'Invalid!', 'origin' => spl_object_hash($form), 'cause' => null), + ), + 'synchronized' => 'true', + ), $this->dataExtractor->extractSubmittedData($form)); + } + + public function testExtractSubmittedDataStoresErrorCause() + { + $form = $this->createBuilder('name')->getForm(); + + $exception = new \Exception(); + + $form->submit('Foobar'); + $form->addError(new FormError('Invalid!', null, array(), null, $exception)); + + $this->assertSame(array( + 'submitted_data' => array( + 'norm' => "'Foobar'", + ), + 'errors' => array( + array('message' => 'Invalid!', 'origin' => null, 'cause' => 'object(Exception)'), ), 'synchronized' => 'true', ), $this->dataExtractor->extractSubmittedData($form)); @@ -353,15 +398,18 @@ public function testExtractViewVariables() 'a' => 'bar', 'c' => 'baz', 'id' => 'foo_bar', + 'name' => 'bar', ); $this->assertSame(array( 'id' => 'foo_bar', + 'name' => 'bar', 'view_vars' => array( 'a' => "'bar'", 'b' => "'foo'", 'c' => "'baz'", 'id' => "'foo_bar'", + 'name' => "'bar'", ), ), $this->dataExtractor->extractViewVariables($view)); } diff --git a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php index a84d5b951a..3c9886d7cf 100644 --- a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php +++ b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php @@ -19,6 +19,7 @@ use Symfony\Component\Form\FormError; use Symfony\Component\PropertyAccess\PropertyPath; use Symfony\Component\Validator\ConstraintViolation; +use Symfony\Component\Validator\ConstraintViolationInterface; /** * @author Bernhard Schussek @@ -109,9 +110,9 @@ protected function getConstraintViolation($propertyPath) /** * @return FormError */ - protected function getFormError() + protected function getFormError(ConstraintViolationInterface $violation) { - return new FormError($this->message, $this->messageTemplate, $this->params); + return new FormError($this->message, $this->messageTemplate, $this->params, null, $violation); } public function testMapToFormInheritingParentDataIfDataDoesNotMatch() @@ -127,7 +128,7 @@ public function testMapToFormInheritingParentDataIfDataDoesNotMatch() $this->mapper->mapViolation($violation, $parent); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError()), $child->getErrors(), $child->getName().' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), $child->getErrors(), $child->getName().' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); } @@ -154,7 +155,7 @@ public function testFollowDotRules() $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError()), $grandGrandChild->getErrors(), $grandGrandChild->getName().' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), $grandGrandChild->getErrors(), $grandGrandChild->getName().' should have an error, but has none'); } public function testAbortMappingIfNotSynchronized() @@ -745,17 +746,17 @@ public function testDefaultErrorMapping($target, $childName, $childPath, $grandC $this->mapper->mapViolation($violation, $parent); if (self::LEVEL_0 === $target) { - $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), $parent->getErrors(), $parent->getName().' should have an error, but has none'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), $child->getErrors(), $childName.' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } else { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); } } @@ -1217,17 +1218,17 @@ public function testCustomDataErrorMapping($target, $mapFrom, $mapTo, $childName } if (self::LEVEL_0 === $target) { - $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), $parent->getErrors(), $parent->getName().' should have an error, but has none'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), $child->getErrors(), $childName.' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } else { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); } } @@ -1399,16 +1400,16 @@ public function testCustomFormErrorMapping($target, $mapFrom, $mapTo, $errorName if (self::LEVEL_0 === $target) { $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), $parent->getErrors(), $parent->getName().' should have an error, but has none'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one'); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), $child->getErrors(), $childName.' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1B === $target) { - $this->assertEquals(array($this->getFormError()), $errorChild->getErrors(), $errorName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), $errorChild->getErrors(), $errorName.' should have an error, but has none'); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); @@ -1416,7 +1417,7 @@ public function testCustomFormErrorMapping($target, $mapFrom, $mapTo, $errorName $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one'); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); } } @@ -1461,17 +1462,17 @@ public function testErrorMappingForFormInheritingParentData($target, $childName, $this->mapper->mapViolation($violation, $parent); if (self::LEVEL_0 === $target) { - $this->assertEquals(array($this->getFormError()), $parent->getErrors(), $parent->getName().' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), $parent->getErrors(), $parent->getName().' should have an error, but has none'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError()), $child->getErrors(), $childName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), $child->getErrors(), $childName.' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } else { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError()), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); } } } From 2f470e97ff3a65199af01ca2c4f6962325a5f442 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Tue, 31 Dec 2013 17:24:28 +0100 Subject: [PATCH 254/447] [Form] Changed Form::getErrors() to return an iterator and added two optional parameters $deep and $flatten --- Button.php | 6 +- CHANGELOG.md | 3 + Form.php | 38 ++- FormErrorIterator.php | 310 ++++++++++++++++++ FormInterface.php | 14 +- Tests/CompoundFormTest.php | 96 +++++- .../ViolationMapper/ViolationMapperTest.php | 30 +- Tests/SimpleFormTest.php | 2 +- 8 files changed, 460 insertions(+), 39 deletions(-) create mode 100644 FormErrorIterator.php diff --git a/Button.php b/Button.php index 25ec861735..14ffaef8bc 100644 --- a/Button.php +++ b/Button.php @@ -184,9 +184,11 @@ public function all() /** * {@inheritdoc} */ - public function getErrors() + public function getErrors($deep = false, $flatten = false) { - return array(); + $errors = array(); + + return new FormErrorIterator($errors, $this, $deep, $flatten); } /** diff --git a/CHANGELOG.md b/CHANGELOG.md index ff4e46284f..bebbceffd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ CHANGELOG * added an option for multiple files upload * form errors now reference their cause (constraint violation, exception, ...) * form errors now remember which form they were originally added to + * [BC BREAK] added two optional parameters to FormInterface::getErrors() and + changed the method to return a Symfony\Component\Form\FormErrorIterator + instance instead of an array 2.4.0 ----- diff --git a/Form.php b/Form.php index f4696c0dfe..418800d7c3 100644 --- a/Form.php +++ b/Form.php @@ -778,9 +778,9 @@ public function getClickedButton() /** * {@inheritdoc} */ - public function getErrors() + public function getErrors($deep = false, $flatten = false) { - return $this->errors; + return new FormErrorIterator($this->errors, $this, $deep, $flatten); } /** @@ -791,24 +791,13 @@ public function getErrors() * @param integer $level The indentation level (used internally) * * @return string A string representation of all errors + * + * @deprecated Deprecated since version 2.5, to be removed in 3.0. Use + * {@link getErrors()} instead and cast the result to a string. */ public function getErrorsAsString($level = 0) { - $errors = ''; - foreach ($this->errors as $error) { - $errors .= str_repeat(' ', $level).'ERROR: '.$error->getMessage()."\n"; - } - - foreach ($this->children as $key => $child) { - $errors .= str_repeat(' ', $level).$key.":\n"; - if ($child instanceof self && $err = $child->getErrorsAsString($level + 4)) { - $errors .= $err; - } else { - $errors .= str_repeat(' ', $level + 4)."No errors\n"; - } - } - - return $errors; + return self::indent((string) $this->getErrors(true), $level); } /** @@ -1115,4 +1104,19 @@ private function viewToNorm($value) return $value; } + + /** + * Utility function for indenting multi-line strings. + * + * @param string $string The string + * @param integer $level The number of spaces to use for indentation + * + * @return string The indented string + */ + private static function indent($string, $level) + { + $indentation = str_repeat(' ', $level); + + return rtrim($indentation.str_replace("\n", "\n".$indentation, $string), ' '); + } } diff --git a/FormErrorIterator.php b/FormErrorIterator.php new file mode 100644 index 0000000000..c9dd4e5a67 --- /dev/null +++ b/FormErrorIterator.php @@ -0,0 +1,310 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form; + +use Symfony\Component\Form\Exception\OutOfBoundsException; +use Symfony\Component\Form\Exception\BadMethodCallException; + +/** + * Iterates over the errors of a form. + * + * Optionally, this class supports recursive iteration. In order to iterate + * recursively, set the constructor argument $deep to true. Now each element + * returned by the iterator is either an instance of {@link FormError} or of + * {@link FormErrorIterator}, in case the errors belong to a sub-form. + * + * You can also wrap the iterator into a {@link \RecursiveIteratorIterator} to + * flatten the recursive structure into a flat list of errors. + * + * @author Bernhard Schussek + * + * @since 2.5 + */ +class FormErrorIterator implements \RecursiveIterator, \SeekableIterator, \ArrayAccess, \Countable +{ + /** + * The prefix used for indenting nested error messages. + * + * @var string + */ + const INDENTATION = ' '; + + /** + * @var FormInterface + */ + private $form; + + /** + * @var Boolean + */ + private $deep; + + /** + * @var Boolean + */ + private $flatten; + + /** + * @var array + */ + private $elements; + + /** + * Creates a new iterator. + * + * @param array $errors The iterated errors + * @param FormInterface $form The form the errors belong to + * @param Boolean $deep Whether to include the errors of child + * forms + * @param Boolean $flatten Whether to flatten the recursive list of + * errors into a flat list + */ + public function __construct(array &$errors, FormInterface $form, $deep = false, $flatten = false) + { + $this->errors = &$errors; + $this->form = $form; + $this->deep = $deep; + $this->flatten = $flatten; + + $this->rewind(); + } + + /** + * Returns all iterated error messages as string. + * + * @return string The iterated error messages + */ + public function __toString() + { + $string = ''; + + foreach ($this->elements as $element) { + if ($element instanceof FormError) { + $string .= 'ERROR: '.$element->getMessage()."\n"; + } else { + /** @var $element FormErrorIterator */ + $string .= $element->form->getName().":\n"; + $string .= self::indent((string) $element); + } + } + + return $string; + } + + /** + * Returns the iterated form. + * + * @return FormInterface The form whose errors are iterated by this object. + */ + public function getForm() + { + return $this->form; + } + + /** + * Returns the current element of the iterator. + * + * @return FormError|FormErrorIterator An error or an iterator for nested + * errors. + */ + public function current() + { + return current($this->elements); + } + + /** + * Advances the iterator to the next position. + */ + public function next() + { + next($this->elements); + } + + /** + * Returns the current position of the iterator. + * + * @return integer The 0-indexed position. + */ + public function key() + { + return key($this->elements); + } + + /** + * Returns whether the iterator's position is valid. + * + * @return Boolean Whether the iterator is valid. + */ + public function valid() + { + return null !== key($this->elements); + } + + /** + * Sets the iterator's position to the beginning. + * + * This method detects if errors have been added to the form since the + * construction of the iterator. + */ + public function rewind() + { + $this->elements = $this->errors; + + if ($this->deep) { + foreach ($this->form as $child) { + /** @var FormInterface $child */ + if ($child->isSubmitted() && $child->isValid()) { + continue; + } + + $iterator = $child->getErrors(true, $this->flatten); + + if (0 === count($iterator)) { + continue; + } + + if ($this->flatten) { + foreach ($iterator as $error) { + $this->elements[] = $error; + } + } else { + $this->elements[] = $iterator; + } + } + } + + reset($this->elements); + } + + /** + * Returns whether a position exists in the iterator. + * + * @param integer $position The position + * + * @return Boolean Whether that position exists + */ + public function offsetExists($position) + { + return isset($this->elements[$position]); + } + + /** + * Returns the element at a position in the iterator. + * + * @param integer $position The position + * + * @return FormError|FormErrorIterator The element at the given position + * + * @throws OutOfBoundsException If the given position does not exist + */ + public function offsetGet($position) + { + if (!isset($this->elements[$position])) { + throw new OutOfBoundsException('The offset '.$position.' does not exist.'); + } + + return $this->elements[$position]; + } + + /** + * Unsupported method. + * + * @throws BadMethodCallException + */ + public function offsetSet($position, $value) + { + throw new BadMethodCallException('The iterator doesn\'t support modification of elements.'); + } + + /** + * Unsupported method. + * + * @throws BadMethodCallException + */ + public function offsetUnset($position) + { + throw new BadMethodCallException('The iterator doesn\'t support modification of elements.'); + } + + /** + * Returns whether the current element of the iterator can be recursed + * into. + * + * @return Boolean Whether the current element is an instance of this class + */ + public function hasChildren() + { + return current($this->elements) instanceof self; + } + + /** + * Alias of {@link current()}. + */ + public function getChildren() + { + return current($this->elements); + } + + /** + * Returns the number of elements in the iterator. + * + * Note that this is not the total number of errors, if the constructor + * parameter $deep was set to true! In that case, you should wrap the + * iterator into a {@link \RecursiveIteratorIterator} with the standard mode + * {@link \RecursiveIteratorIterator::LEAVES_ONLY} and count the result. + * + * $iterator = new \RecursiveIteratorIterator($form->getErrors(true)); + * $count = count(iterator_to_array($iterator)); + * + * Alternatively, set the constructor argument $flatten to true as well. + * + * $count = count($form->getErrors(true, true)); + * + * @return integer The number of iterated elements + */ + public function count() + { + return count($this->elements); + } + + /** + * Sets the position of the iterator. + * + * @param integer $position The new position + * + * @throws OutOfBoundsException If the position is invalid + */ + public function seek($position) + { + if (!isset($this->elements[$position])) { + throw new OutOfBoundsException('The offset '.$position.' does not exist.'); + } + + reset($this->elements); + + while ($position !== key($this->elements)) { + next($this->elements); + } + } + + /** + * Utility function for indenting multi-line strings. + * + * @param string $string The string + * + * @return string The indented string + */ + private static function indent($string) + { + return rtrim(self::INDENTATION.str_replace("\n", "\n".self::INDENTATION, $string), ' '); + } +} diff --git a/FormInterface.php b/FormInterface.php index 5a852e864f..2665017179 100644 --- a/FormInterface.php +++ b/FormInterface.php @@ -92,11 +92,19 @@ public function remove($name); public function all(); /** - * Returns all errors. + * Returns the errors of this form. * - * @return FormError[] An array of FormError instances that occurred during validation + * @param Boolean $deep Whether to include errors of child forms as well + * @param Boolean $flatten Whether to flatten the list of errors in case + * $deep is set to true + * + * @return FormErrorIterator An iterator over the {@link FormError} + * instances that where added to this form + * + * @since 2.5 Since version 2.5 this method returns a + * {@link FormErrorIterator} instance instead of an array */ - public function getErrors(); + public function getErrors($deep = false, $flatten = false); /** * Updates the form with default data. diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index 32a09719ae..59bfce7b9b 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -819,7 +819,101 @@ public function testGetErrorsAsStringDeep() $parent->add($this->form); $parent->add($this->getBuilder('foo')->getForm()); - $this->assertEquals("name:\n ERROR: Error!\nfoo:\n No errors\n", $parent->getErrorsAsString()); + $this->assertSame( + "name:\n". + " ERROR: Error!\n", + $parent->getErrorsAsString() + ); + } + + public function testGetErrorsAsStringDeepWithIndentation() + { + $parent = $this->getBuilder() + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + + $this->form->addError(new FormError('Error!')); + + $parent->add($this->form); + $parent->add($this->getBuilder('foo')->getForm()); + + $this->assertSame( + " name:\n". + " ERROR: Error!\n", + $parent->getErrorsAsString(4) + ); + } + + public function testGetErrors() + { + $this->form->addError($error1 = new FormError('Error 1')); + $this->form->addError($error2 = new FormError('Error 2')); + + $errors = $this->form->getErrors(); + + $this->assertSame( + "ERROR: Error 1\n". + "ERROR: Error 2\n", + (string) $errors + ); + + $this->assertSame(array($error1, $error2), iterator_to_array($errors)); + } + + public function testGetErrorsDeep() + { + $this->form->addError($error1 = new FormError('Error 1')); + $this->form->addError($error2 = new FormError('Error 2')); + + $childForm = $this->getBuilder('Child')->getForm(); + $childForm->addError($nestedError = new FormError('Nested Error')); + $this->form->add($childForm); + + $errors = $this->form->getErrors(true); + + $this->assertSame( + "ERROR: Error 1\n". + "ERROR: Error 2\n". + "Child:\n". + " ERROR: Nested Error\n", + (string) $errors + ); + + $errorsAsArray = iterator_to_array($errors); + + $this->assertSame($error1, $errorsAsArray[0]); + $this->assertSame($error2, $errorsAsArray[1]); + $this->assertInstanceOf('Symfony\Component\Form\FormErrorIterator', $errorsAsArray[2]); + + $nestedErrorsAsArray = iterator_to_array($errorsAsArray[2]); + + $this->assertCount(1, $nestedErrorsAsArray); + $this->assertSame($nestedError, $nestedErrorsAsArray[0]); + } + + public function testGetErrorsDeepFlat() + { + $this->form->addError($error1 = new FormError('Error 1')); + $this->form->addError($error2 = new FormError('Error 2')); + + $childForm = $this->getBuilder('Child')->getForm(); + $childForm->addError($nestedError = new FormError('Nested Error')); + $this->form->add($childForm); + + $errors = $this->form->getErrors(true, true); + + $this->assertSame( + "ERROR: Error 1\n". + "ERROR: Error 2\n". + "ERROR: Nested Error\n", + (string) $errors + ); + + $this->assertSame( + array($error1, $error2, $nestedError), + iterator_to_array($errors) + ); } // Basic cases are covered in SimpleFormTest diff --git a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php index 3c9886d7cf..c2db73eb77 100644 --- a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php +++ b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php @@ -128,7 +128,7 @@ public function testMapToFormInheritingParentDataIfDataDoesNotMatch() $this->mapper->mapViolation($violation, $parent); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError($violation)), $child->getErrors(), $child->getName().' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($child->getErrors()), $child->getName().' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); } @@ -155,7 +155,7 @@ public function testFollowDotRules() $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError($violation)), $grandGrandChild->getErrors(), $grandGrandChild->getName().' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($grandGrandChild->getErrors()), $grandGrandChild->getName().' should have an error, but has none'); } public function testAbortMappingIfNotSynchronized() @@ -746,17 +746,17 @@ public function testDefaultErrorMapping($target, $childName, $childPath, $grandC $this->mapper->mapViolation($violation, $parent); if (self::LEVEL_0 === $target) { - $this->assertEquals(array($this->getFormError($violation)), $parent->getErrors(), $parent->getName().' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($parent->getErrors()), $parent->getName().' should have an error, but has none'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError($violation)), $child->getErrors(), $childName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($child->getErrors()), $childName.' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } else { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError($violation)), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($grandChild->getErrors()), $grandChildName.' should have an error, but has none'); } } @@ -1218,17 +1218,17 @@ public function testCustomDataErrorMapping($target, $mapFrom, $mapTo, $childName } if (self::LEVEL_0 === $target) { - $this->assertEquals(array($this->getFormError($violation)), $parent->getErrors(), $parent->getName().' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($parent->getErrors()), $parent->getName().' should have an error, but has none'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError($violation)), $child->getErrors(), $childName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($child->getErrors()), $childName.' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } else { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError($violation)), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($grandChild->getErrors()), $grandChildName.' should have an error, but has none'); } } @@ -1400,16 +1400,16 @@ public function testCustomFormErrorMapping($target, $mapFrom, $mapTo, $errorName if (self::LEVEL_0 === $target) { $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError($violation)), $parent->getErrors(), $parent->getName().' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($parent->getErrors()), $parent->getName().' should have an error, but has none'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one'); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError($violation)), $child->getErrors(), $childName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($child->getErrors()), $childName.' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1B === $target) { - $this->assertEquals(array($this->getFormError($violation)), $errorChild->getErrors(), $errorName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($errorChild->getErrors()), $errorName.' should have an error, but has none'); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); @@ -1417,7 +1417,7 @@ public function testCustomFormErrorMapping($target, $mapFrom, $mapTo, $errorName $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one'); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError($violation)), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($grandChild->getErrors()), $grandChildName.' should have an error, but has none'); } } @@ -1462,17 +1462,17 @@ public function testErrorMappingForFormInheritingParentData($target, $childName, $this->mapper->mapViolation($violation, $parent); if (self::LEVEL_0 === $target) { - $this->assertEquals(array($this->getFormError($violation)), $parent->getErrors(), $parent->getName().' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($parent->getErrors()), $parent->getName().' should have an error, but has none'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError($violation)), $child->getErrors(), $childName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($child->getErrors()), $childName.' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } else { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError($violation)), $grandChild->getErrors(), $grandChildName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($grandChild->getErrors()), $grandChildName.' should have an error, but has none'); } } } diff --git a/Tests/SimpleFormTest.php b/Tests/SimpleFormTest.php index bedad6761f..528114257a 100644 --- a/Tests/SimpleFormTest.php +++ b/Tests/SimpleFormTest.php @@ -664,7 +664,7 @@ public function testSubmitResetsErrors() $this->form->addError(new FormError('Error!')); $this->form->submit('foobar'); - $this->assertSame(array(), $this->form->getErrors()); + $this->assertCount(0, $this->form->getErrors()); } public function testCreateView() From 18c6d453c383615538e7bf8ed8af0636409d6bca Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 10 Jan 2014 13:53:52 +0100 Subject: [PATCH 255/447] [Form] Changed the default value of $flatten in Form::getErrors() to true --- Button.php | 2 +- Form.php | 4 ++-- FormErrorIterator.php | 2 +- FormInterface.php | 2 +- Tests/CompoundFormTest.php | 38 +++++++++++++++++++------------------- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Button.php b/Button.php index 14ffaef8bc..795404b417 100644 --- a/Button.php +++ b/Button.php @@ -184,7 +184,7 @@ public function all() /** * {@inheritdoc} */ - public function getErrors($deep = false, $flatten = false) + public function getErrors($deep = false, $flatten = true) { $errors = array(); diff --git a/Form.php b/Form.php index 418800d7c3..e05adda3e7 100644 --- a/Form.php +++ b/Form.php @@ -778,7 +778,7 @@ public function getClickedButton() /** * {@inheritdoc} */ - public function getErrors($deep = false, $flatten = false) + public function getErrors($deep = false, $flatten = true) { return new FormErrorIterator($this->errors, $this, $deep, $flatten); } @@ -797,7 +797,7 @@ public function getErrors($deep = false, $flatten = false) */ public function getErrorsAsString($level = 0) { - return self::indent((string) $this->getErrors(true), $level); + return self::indent((string) $this->getErrors(true, false), $level); } /** diff --git a/FormErrorIterator.php b/FormErrorIterator.php index c9dd4e5a67..32ddf2e485 100644 --- a/FormErrorIterator.php +++ b/FormErrorIterator.php @@ -68,7 +68,7 @@ class FormErrorIterator implements \RecursiveIterator, \SeekableIterator, \Array * @param Boolean $flatten Whether to flatten the recursive list of * errors into a flat list */ - public function __construct(array &$errors, FormInterface $form, $deep = false, $flatten = false) + public function __construct(array &$errors, FormInterface $form, $deep = false, $flatten = true) { $this->errors = &$errors; $this->form = $form; diff --git a/FormInterface.php b/FormInterface.php index 2665017179..3b7fb7b3a0 100644 --- a/FormInterface.php +++ b/FormInterface.php @@ -104,7 +104,7 @@ public function all(); * @since 2.5 Since version 2.5 this method returns a * {@link FormErrorIterator} instance instead of an array */ - public function getErrors($deep = false, $flatten = false); + public function getErrors($deep = false, $flatten = true); /** * Updates the form with default data. diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index 59bfce7b9b..d72fd66390 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -875,24 +875,17 @@ public function testGetErrorsDeep() $this->assertSame( "ERROR: Error 1\n". "ERROR: Error 2\n". - "Child:\n". - " ERROR: Nested Error\n", + "ERROR: Nested Error\n", (string) $errors ); - $errorsAsArray = iterator_to_array($errors); - - $this->assertSame($error1, $errorsAsArray[0]); - $this->assertSame($error2, $errorsAsArray[1]); - $this->assertInstanceOf('Symfony\Component\Form\FormErrorIterator', $errorsAsArray[2]); - - $nestedErrorsAsArray = iterator_to_array($errorsAsArray[2]); - - $this->assertCount(1, $nestedErrorsAsArray); - $this->assertSame($nestedError, $nestedErrorsAsArray[0]); + $this->assertSame( + array($error1, $error2, $nestedError), + iterator_to_array($errors) + ); } - public function testGetErrorsDeepFlat() + public function testGetErrorsDeepRecursive() { $this->form->addError($error1 = new FormError('Error 1')); $this->form->addError($error2 = new FormError('Error 2')); @@ -901,19 +894,26 @@ public function testGetErrorsDeepFlat() $childForm->addError($nestedError = new FormError('Nested Error')); $this->form->add($childForm); - $errors = $this->form->getErrors(true, true); + $errors = $this->form->getErrors(true, false); $this->assertSame( "ERROR: Error 1\n". "ERROR: Error 2\n". - "ERROR: Nested Error\n", + "Child:\n". + " ERROR: Nested Error\n", (string) $errors ); - $this->assertSame( - array($error1, $error2, $nestedError), - iterator_to_array($errors) - ); + $errorsAsArray = iterator_to_array($errors); + + $this->assertSame($error1, $errorsAsArray[0]); + $this->assertSame($error2, $errorsAsArray[1]); + $this->assertInstanceOf('Symfony\Component\Form\FormErrorIterator', $errorsAsArray[2]); + + $nestedErrorsAsArray = iterator_to_array($errorsAsArray[2]); + + $this->assertCount(1, $nestedErrorsAsArray); + $this->assertSame($nestedError, $nestedErrorsAsArray[0]); } // Basic cases are covered in SimpleFormTest From bad0eccbfd554b657f97edba92a46f9b063536ef Mon Sep 17 00:00:00 2001 From: Bill Hance Date: Fri, 24 Jan 2014 15:53:20 -0800 Subject: [PATCH 256/447] [Form] Make FormInterface::add docblock more explicit | Q | A | ------------- | --- | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | | License | MIT | Doc PR | When replacing a child form from within a form event, it's not obvious that you have to use the 'add' method. Though it's minor, this will save somebody a google search. --- FormInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FormInterface.php b/FormInterface.php index 5a852e864f..7a77e0f3f4 100644 --- a/FormInterface.php +++ b/FormInterface.php @@ -39,7 +39,7 @@ public function setParent(FormInterface $parent = null); public function getParent(); /** - * Adds a child to the form. + * Adds or replaces a child to the form. * * @param FormInterface|string|integer $child The FormInterface instance or the name of the child. * @param string|null $type The child's type, if a name was passed. From 653ad52e667cda2052623999e15d356efb0972f8 Mon Sep 17 00:00:00 2001 From: r1pp3rj4ck Date: Mon, 27 Jan 2014 23:45:52 +0100 Subject: [PATCH 257/447] Fixed grammar in Hungarian translations --- Resources/translations/validators.hu.xlf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Resources/translations/validators.hu.xlf b/Resources/translations/validators.hu.xlf index d1491e7e2a..374cfaaea3 100644 --- a/Resources/translations/validators.hu.xlf +++ b/Resources/translations/validators.hu.xlf @@ -8,11 +8,11 @@ The uploaded file was too large. Please try to upload a smaller file. - A feltöltött fájl túl nagy. Kérem próbáljon egy kisebb fájlt feltölteni. + A feltöltött fájl túl nagy. Kérem, próbáljon egy kisebb fájlt feltölteni. The CSRF token is invalid. Please try to resubmit the form. - Érvénytelen CSRF token. Kérem próbálja újra elküldeni az űrlapot. + Érvénytelen CSRF token. Kérem, próbálja újra elküldeni az űrlapot. From 2688adf919018b924796458c4e1228282c61b520 Mon Sep 17 00:00:00 2001 From: Peter Rehm Date: Tue, 28 Jan 2014 10:33:47 +0100 Subject: [PATCH 258/447] [Form] Update DateTime objects only if the actual value has changed --- Extension/Core/DataMapper/PropertyPathMapper.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Extension/Core/DataMapper/PropertyPathMapper.php b/Extension/Core/DataMapper/PropertyPathMapper.php index d5942f2a55..d07f3f15e6 100644 --- a/Extension/Core/DataMapper/PropertyPathMapper.php +++ b/Extension/Core/DataMapper/PropertyPathMapper.php @@ -81,6 +81,13 @@ public function mapFormsToData($forms, &$data) // Write-back is disabled if the form is not synchronized (transformation failed), // if the form was not submitted and if the form is disabled (modification not allowed) if (null !== $propertyPath && $config->getMapped() && $form->isSubmitted() && $form->isSynchronized() && !$form->isDisabled()) { + + // If the field is of type DateTime and the data is the same skip the update to + // keep the original object hash + if ($form->getData() instanceof \DateTime && $form->getData() == $this->propertyAccessor->getValue($data, $propertyPath)) { + continue; + } + // If the data is identical to the value in $data, we are // dealing with a reference if (!is_object($data) || !$config->getByReference() || $form->getData() !== $this->propertyAccessor->getValue($data, $propertyPath)) { From e7907386581dcf4a6213448c20e56626e4550bc5 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 11 Feb 2014 08:51:18 +0100 Subject: [PATCH 259/447] fixed various inconsistencies --- .../DependencyInjection/DependencyInjectionExtension.php | 5 +---- Test/FormPerformanceTestCase.php | 2 +- Tests/FormFactoryBuilderTest.php | 6 +++--- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Extension/DependencyInjection/DependencyInjectionExtension.php b/Extension/DependencyInjection/DependencyInjectionExtension.php index 6637ac8c63..2d78f80830 100644 --- a/Extension/DependencyInjection/DependencyInjectionExtension.php +++ b/Extension/DependencyInjection/DependencyInjectionExtension.php @@ -19,14 +19,11 @@ class DependencyInjectionExtension implements FormExtensionInterface { private $container; - private $typeServiceIds; - private $guesserServiceIds; - private $guesser; - private $guesserLoaded = false; + private $typeExtensionServiceIds; public function __construct(ContainerInterface $container, array $typeServiceIds, array $typeExtensionServiceIds, diff --git a/Test/FormPerformanceTestCase.php b/Test/FormPerformanceTestCase.php index 573f4e913c..b57aa9da8d 100644 --- a/Test/FormPerformanceTestCase.php +++ b/Test/FormPerformanceTestCase.php @@ -55,7 +55,7 @@ public function setMaxRunningTime($maxRunningTime) if (is_integer($maxRunningTime) && $maxRunningTime >= 0) { $this->maxRunningTime = $maxRunningTime; } else { - throw new \InvalidArgumentException; + throw new \InvalidArgumentException(); } } diff --git a/Tests/FormFactoryBuilderTest.php b/Tests/FormFactoryBuilderTest.php index a1292dbe72..2c3ab000ff 100644 --- a/Tests/FormFactoryBuilderTest.php +++ b/Tests/FormFactoryBuilderTest.php @@ -27,12 +27,12 @@ protected function setUp() $this->registry->setAccessible(true); $this->guesser = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface'); - $this->type = new FooType; + $this->type = new FooType(); } public function testAddType() { - $factoryBuilder = new FormFactoryBuilder; + $factoryBuilder = new FormFactoryBuilder(); $factoryBuilder->addType($this->type); $factory = $factoryBuilder->getFormFactory(); @@ -46,7 +46,7 @@ public function testAddType() public function testAddTypeGuesser() { - $factoryBuilder = new FormFactoryBuilder; + $factoryBuilder = new FormFactoryBuilder(); $factoryBuilder->addTypeGuesser($this->guesser); $factory = $factoryBuilder->getFormFactory(); From 765cd020536be58fe1f7b2a82c10ff2b49cc62a3 Mon Sep 17 00:00:00 2001 From: Chekote Date: Mon, 10 Feb 2014 15:46:13 -0600 Subject: [PATCH 260/447] Fix "Array was modified outside object" in ResizeFormListener. The onSubmit() method of the ResizeFormListener class is assuming the data is an array, and calling unset directly inside a foreach. This works fine in most scenarios, but if data is an instance of IteratorAggregate, it breaks with the following error: Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener::onSubmit(): ArrayIterator::next(): Array was modified outside object and internal position is no longer valid in ./vendor/symfony/symfony/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php line 142 This is because the foreach loop is using an Iterator in the background, but the ResizeFormListener has unset the underlying data directly, causing the Iterator and data to be out of sync. When the data is an instance of IteratorAggregate, the loop should use the iterator directly and not rely on foreach. The onSubmit method has been updated accordingly. --- .../Core/EventListener/ResizeFormListener.php | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/Extension/Core/EventListener/ResizeFormListener.php b/Extension/Core/EventListener/ResizeFormListener.php index f1c39db245..d2b13e4a96 100644 --- a/Extension/Core/EventListener/ResizeFormListener.php +++ b/Extension/Core/EventListener/ResizeFormListener.php @@ -139,9 +139,21 @@ public function onSubmit(FormEvent $event) // The data mapper only adds, but does not remove items, so do this // here if ($this->allowDelete) { - foreach ($data as $name => $child) { - if (!$form->has($name)) { - unset($data[$name]); + if ($data instanceof \IteratorAggregate) { + $iter = $data->getIterator(); + while ($iter->valid()) { + $name = $iter->key(); + if ($form->has($name)) { + $iter->next(); + } else { + $iter->offsetUnset($name); + } + } + } else { + foreach ($data as $name => $child) { + if (!$form->has($name)) { + unset($data[$name]); + } } } } From 279bcd48ff6aef297d9a80d80ac09b5469d11736 Mon Sep 17 00:00:00 2001 From: Norbert Orzechowicz Date: Sat, 15 Feb 2014 12:00:54 +0100 Subject: [PATCH 261/447] Added failing test --- .../Core/EventListener/ResizeFormListenerTest.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php index 1367b3ef02..3c162654dd 100644 --- a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php +++ b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\EventListener; +use Doctrine\Common\Collections\ArrayCollection; use Symfony\Component\Form\Extension\Core\EventListener\ResizeFormListener; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormEvent; @@ -252,4 +253,17 @@ public function testOnSubmitNormDataDealsWithNullData() $this->assertEquals(array(), $event->getData()); } + + public function testOnSubmitDealsWithIteratorAggregate() + { + $this->form->add($this->getForm('1')); + + $data = new ArrayCollection(array(0 => 'first', 1 => 'second', 2 => 'third')); + $event = new FormEvent($this->form, $data); + $listener = new ResizeFormListener('text', array(), false, true); + $listener->onSubmit($event); + + $this->assertArrayNotHasKey(0, $event->getData()); + $this->assertArrayNotHasKey(2, $event->getData()); + } } From c94b5d6a922e7974ecd219ec8a8f9513d1e2f962 Mon Sep 17 00:00:00 2001 From: Norbert Orzechowicz Date: Sat, 15 Feb 2014 12:03:01 +0100 Subject: [PATCH 262/447] Revert "Fix "Array was modified outside object" in ResizeFormListener." --- .../Core/EventListener/ResizeFormListener.php | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/Extension/Core/EventListener/ResizeFormListener.php b/Extension/Core/EventListener/ResizeFormListener.php index d2b13e4a96..f1c39db245 100644 --- a/Extension/Core/EventListener/ResizeFormListener.php +++ b/Extension/Core/EventListener/ResizeFormListener.php @@ -139,21 +139,9 @@ public function onSubmit(FormEvent $event) // The data mapper only adds, but does not remove items, so do this // here if ($this->allowDelete) { - if ($data instanceof \IteratorAggregate) { - $iter = $data->getIterator(); - while ($iter->valid()) { - $name = $iter->key(); - if ($form->has($name)) { - $iter->next(); - } else { - $iter->offsetUnset($name); - } - } - } else { - foreach ($data as $name => $child) { - if (!$form->has($name)) { - unset($data[$name]); - } + foreach ($data as $name => $child) { + if (!$form->has($name)) { + unset($data[$name]); } } } From 4e69f4321576ade72d5f06f801e67d10665972e5 Mon Sep 17 00:00:00 2001 From: Quentin Schuler Date: Tue, 28 Jan 2014 22:02:25 +0100 Subject: [PATCH 263/447] Improves the readability of the collected arrays in the profiler. --- Tests/Extension/DataCollector/FormDataExtractorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Extension/DataCollector/FormDataExtractorTest.php b/Tests/Extension/DataCollector/FormDataExtractorTest.php index 37b5b7d86c..1244ba3731 100644 --- a/Tests/Extension/DataCollector/FormDataExtractorTest.php +++ b/Tests/Extension/DataCollector/FormDataExtractorTest.php @@ -25,7 +25,7 @@ class FormDataExtractorTest_SimpleValueExporter extends ValueExporter /** * {@inheritdoc} */ - public function exportValue($value) + public function exportValue($value, $depth = 0) { return is_object($value) ? sprintf('object(%s)', get_class($value)) : var_export($value, true); } From c1bd9b278b4f44c8d005b18cff35d2ece09cbb49 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 28 Feb 2014 14:42:27 +0100 Subject: [PATCH 264/447] removed double-stringification of values in the profiler --- Tests/Extension/DataCollector/FormDataExtractorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Extension/DataCollector/FormDataExtractorTest.php b/Tests/Extension/DataCollector/FormDataExtractorTest.php index 1244ba3731..06f7f8866d 100644 --- a/Tests/Extension/DataCollector/FormDataExtractorTest.php +++ b/Tests/Extension/DataCollector/FormDataExtractorTest.php @@ -25,7 +25,7 @@ class FormDataExtractorTest_SimpleValueExporter extends ValueExporter /** * {@inheritdoc} */ - public function exportValue($value, $depth = 0) + public function exportValue($value, $depth = 1, $deep = false) { return is_object($value) ? sprintf('object(%s)', get_class($value)) : var_export($value, true); } From 6214b40414797718209b66fa7a7d1361e548b7d5 Mon Sep 17 00:00:00 2001 From: Ian Jenkins Date: Thu, 27 Feb 2014 22:38:05 +0000 Subject: [PATCH 265/447] [Form][2.3] Fixes empty file-inputs getting treated as extra field. --- Form.php | 2 +- Tests/CompoundFormTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Form.php b/Form.php index 86cf7921a1..5d16f9ca02 100644 --- a/Form.php +++ b/Form.php @@ -556,7 +556,7 @@ public function submit($submittedData, $clearMissing = true) } foreach ($this->children as $name => $child) { - if (isset($submittedData[$name]) || $clearMissing) { + if (array_key_exists($name, $submittedData) || $clearMissing) { $child->submit(isset($submittedData[$name]) ? $submittedData[$name] : null, $clearMissing); unset($submittedData[$name]); diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index fe3755c172..565b6ce646 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -115,7 +115,7 @@ public function testSubmitDoesNotAddExtraFieldForNullValues() $child = $factory->create('file', null, array('auto_initialize' => false)); $this->form->add($child); - $this->form->submit(array('file' => null)); + $this->form->submit(array('file' => null), false); $this->assertCount(0, $this->form->getExtraData()); } From b09a8f95cd15a55c93b00e9590d31d5defd3e7bc Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Mon, 10 Mar 2014 12:51:04 +0000 Subject: [PATCH 266/447] [Validator] Checked the constraint class in constraint validators --- Extension/Validator/Constraints/FormValidator.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Extension/Validator/Constraints/FormValidator.php b/Extension/Validator/Constraints/FormValidator.php index 0df176f7d7..b03e4ee66b 100644 --- a/Extension/Validator/Constraints/FormValidator.php +++ b/Extension/Validator/Constraints/FormValidator.php @@ -15,6 +15,7 @@ use Symfony\Component\Form\Extension\Validator\Util\ServerParams; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; +use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** * @author Bernhard Schussek @@ -42,6 +43,10 @@ public function __construct(ServerParams $params = null) */ public function validate($form, Constraint $constraint) { + if (!$constraint instanceof Form) { + throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Form'); + } + if (!$form instanceof FormInterface) { return; } From 0a28464fc1768bec6bf675e9837ce8932760cccb Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Tue, 11 Mar 2014 16:57:35 +0100 Subject: [PATCH 267/447] [Form] Removed "magic" from FormErrorIterator --- Button.php | 4 +- Form.php | 28 +++++++++- FormErrorIterator.php | 115 ++++++++++++++++-------------------------- 3 files changed, 71 insertions(+), 76 deletions(-) diff --git a/Button.php b/Button.php index 795404b417..2fd9306f30 100644 --- a/Button.php +++ b/Button.php @@ -186,9 +186,7 @@ public function all() */ public function getErrors($deep = false, $flatten = true) { - $errors = array(); - - return new FormErrorIterator($errors, $this, $deep, $flatten); + return new FormErrorIterator($this, array()); } /** diff --git a/Form.php b/Form.php index e05adda3e7..a5f98c16f5 100644 --- a/Form.php +++ b/Form.php @@ -780,7 +780,33 @@ public function getClickedButton() */ public function getErrors($deep = false, $flatten = true) { - return new FormErrorIterator($this->errors, $this, $deep, $flatten); + $errors = $this->errors; + + // Copy the errors of nested forms to the $errors array + if ($deep) { + foreach ($this as $child) { + /** @var FormInterface $child */ + if ($child->isSubmitted() && $child->isValid()) { + continue; + } + + $iterator = $child->getErrors(true, $flatten); + + if (0 === count($iterator)) { + continue; + } + + if ($flatten) { + foreach ($iterator as $error) { + $errors[] = $error; + } + } else { + $errors[] = $iterator; + } + } + } + + return new FormErrorIterator($this, $errors); } /** diff --git a/FormErrorIterator.php b/FormErrorIterator.php index 32ddf2e485..bc2bdb1e50 100644 --- a/FormErrorIterator.php +++ b/FormErrorIterator.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form; +use Symfony\Component\Form\Exception\InvalidArgumentException; use Symfony\Component\Form\Exception\OutOfBoundsException; use Symfony\Component\Form\Exception\BadMethodCallException; @@ -44,38 +45,33 @@ class FormErrorIterator implements \RecursiveIterator, \SeekableIterator, \Array private $form; /** - * @var Boolean + * @var FormError[]|FormErrorIterator[] */ - private $deep; - - /** - * @var Boolean - */ - private $flatten; - - /** - * @var array - */ - private $elements; + private $errors; /** * Creates a new iterator. * - * @param array $errors The iterated errors - * @param FormInterface $form The form the errors belong to - * @param Boolean $deep Whether to include the errors of child - * forms - * @param Boolean $flatten Whether to flatten the recursive list of - * errors into a flat list + * @param FormInterface $form The erroneous form + * @param array $errors The form errors + * + * @throws InvalidArgumentException If the errors are invalid */ - public function __construct(array &$errors, FormInterface $form, $deep = false, $flatten = true) + public function __construct(FormInterface $form, array $errors) { - $this->errors = &$errors; - $this->form = $form; - $this->deep = $deep; - $this->flatten = $flatten; + foreach ($errors as $error) { + if (!($error instanceof FormError || $error instanceof self)) { + throw new InvalidArgumentException(sprintf( + 'The errors must be instances of '. + '"\Symfony\Component\Form\FormError" or "%s". Got: "%s".', + __CLASS__, + is_object($error) ? get_class($error) : gettype($error) + )); + } + } - $this->rewind(); + $this->form = $form; + $this->errors = $errors; } /** @@ -87,13 +83,13 @@ public function __toString() { $string = ''; - foreach ($this->elements as $element) { - if ($element instanceof FormError) { - $string .= 'ERROR: '.$element->getMessage()."\n"; + foreach ($this->errors as $error) { + if ($error instanceof FormError) { + $string .= 'ERROR: '.$error->getMessage()."\n"; } else { - /** @var $element FormErrorIterator */ - $string .= $element->form->getName().":\n"; - $string .= self::indent((string) $element); + /** @var $error FormErrorIterator */ + $string .= $error->form->getName().":\n"; + $string .= self::indent((string) $error); } } @@ -113,12 +109,12 @@ public function getForm() /** * Returns the current element of the iterator. * - * @return FormError|FormErrorIterator An error or an iterator for nested - * errors. + * @return FormError|FormErrorIterator An error or an iterator containing + * nested errors. */ public function current() { - return current($this->elements); + return current($this->errors); } /** @@ -126,7 +122,7 @@ public function current() */ public function next() { - next($this->elements); + next($this->errors); } /** @@ -136,7 +132,7 @@ public function next() */ public function key() { - return key($this->elements); + return key($this->errors); } /** @@ -146,7 +142,7 @@ public function key() */ public function valid() { - return null !== key($this->elements); + return null !== key($this->errors); } /** @@ -157,32 +153,7 @@ public function valid() */ public function rewind() { - $this->elements = $this->errors; - - if ($this->deep) { - foreach ($this->form as $child) { - /** @var FormInterface $child */ - if ($child->isSubmitted() && $child->isValid()) { - continue; - } - - $iterator = $child->getErrors(true, $this->flatten); - - if (0 === count($iterator)) { - continue; - } - - if ($this->flatten) { - foreach ($iterator as $error) { - $this->elements[] = $error; - } - } else { - $this->elements[] = $iterator; - } - } - } - - reset($this->elements); + reset($this->errors); } /** @@ -194,7 +165,7 @@ public function rewind() */ public function offsetExists($position) { - return isset($this->elements[$position]); + return isset($this->errors[$position]); } /** @@ -208,11 +179,11 @@ public function offsetExists($position) */ public function offsetGet($position) { - if (!isset($this->elements[$position])) { + if (!isset($this->errors[$position])) { throw new OutOfBoundsException('The offset '.$position.' does not exist.'); } - return $this->elements[$position]; + return $this->errors[$position]; } /** @@ -243,7 +214,7 @@ public function offsetUnset($position) */ public function hasChildren() { - return current($this->elements) instanceof self; + return current($this->errors) instanceof self; } /** @@ -251,7 +222,7 @@ public function hasChildren() */ public function getChildren() { - return current($this->elements); + return current($this->errors); } /** @@ -273,7 +244,7 @@ public function getChildren() */ public function count() { - return count($this->elements); + return count($this->errors); } /** @@ -285,14 +256,14 @@ public function count() */ public function seek($position) { - if (!isset($this->elements[$position])) { + if (!isset($this->errors[$position])) { throw new OutOfBoundsException('The offset '.$position.' does not exist.'); } - reset($this->elements); + reset($this->errors); - while ($position !== key($this->elements)) { - next($this->elements); + while ($position !== key($this->errors)) { + next($this->errors); } } From dda218d324d440762a5c674e25aae01315ed71b9 Mon Sep 17 00:00:00 2001 From: Nick Stemerdink Date: Tue, 21 Jan 2014 02:02:35 +0100 Subject: [PATCH 268/447] Fixed bug that incorrectly causes the "required" attribute to be omitted from select even though it contains the "multiple" attribute --- Tests/AbstractLayoutTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index 10650e5998..9e3647a2b2 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -635,6 +635,7 @@ public function testMultipleChoice() { $form = $this->factory->createNamed('name', 'choice', array('&a'), array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'required' => true, 'multiple' => true, 'expanded' => false, )); @@ -642,6 +643,7 @@ public function testMultipleChoice() $this->assertWidgetMatchesXpath($form->createView(), array(), '/select [@name="name[]"] + [@required="required"] [@multiple="multiple"] [ ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] From 9b58fcee4d81a93cbfa87afdfabd7b9db8fc529f Mon Sep 17 00:00:00 2001 From: Chekote Date: Mon, 10 Mar 2014 10:10:33 -0500 Subject: [PATCH 269/447] [Form] Fix "Array was modified outside object" in ResizeFormListener. --- .../Core/EventListener/ResizeFormListener.php | 8 +++++++- .../Core/EventListener/ResizeFormListenerTest.php | 15 ++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Extension/Core/EventListener/ResizeFormListener.php b/Extension/Core/EventListener/ResizeFormListener.php index f1c39db245..207cbd3d38 100644 --- a/Extension/Core/EventListener/ResizeFormListener.php +++ b/Extension/Core/EventListener/ResizeFormListener.php @@ -139,11 +139,17 @@ public function onSubmit(FormEvent $event) // The data mapper only adds, but does not remove items, so do this // here if ($this->allowDelete) { + $toDelete = array(); + foreach ($data as $name => $child) { if (!$form->has($name)) { - unset($data[$name]); + $toDelete[] = $name; } } + + foreach ($toDelete as $name) { + unset($data[$name]); + } } $event->setData($data); diff --git a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php index 3c162654dd..07620dc635 100644 --- a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php +++ b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php @@ -254,7 +254,20 @@ public function testOnSubmitNormDataDealsWithNullData() $this->assertEquals(array(), $event->getData()); } - public function testOnSubmitDealsWithIteratorAggregate() + public function testOnSubmitDealsWithObjectBackedIteratorAggregate() + { + $this->form->add($this->getForm('1')); + + $data = new \ArrayObject(array(0 => 'first', 1 => 'second', 2 => 'third')); + $event = new FormEvent($this->form, $data); + $listener = new ResizeFormListener('text', array(), false, true); + $listener->onSubmit($event); + + $this->assertArrayNotHasKey(0, $event->getData()); + $this->assertArrayNotHasKey(2, $event->getData()); + } + + public function testOnSubmitDealsWithArrayBackedIteratorAggregate() { $this->form->add($this->getForm('1')); From 1536e767150448531e6c2dfb3c7d85193d61edc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luiz=20=E2=80=9CFelds=E2=80=9D=20Liscia?= Date: Tue, 11 Mar 2014 11:49:06 -0300 Subject: [PATCH 270/447] Cast the group name as a string This allows the options to be grouped by association fields. --- Extension/Core/ChoiceList/ObjectChoiceList.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Extension/Core/ChoiceList/ObjectChoiceList.php b/Extension/Core/ChoiceList/ObjectChoiceList.php index 7c7aa0c768..0f1437db21 100644 --- a/Extension/Core/ChoiceList/ObjectChoiceList.php +++ b/Extension/Core/ChoiceList/ObjectChoiceList.php @@ -128,11 +128,13 @@ protected function initialize($choices, array $labels, array $preferredChoices) if (null === $group) { $groupedChoices[$i] = $choice; } else { - if (!isset($groupedChoices[$group])) { - $groupedChoices[$group] = array(); + $groupName = (string) $group; + + if (!isset($groupedChoices[$groupName])) { + $groupedChoices[$groupName] = array(); } - $groupedChoices[$group][$i] = $choice; + $groupedChoices[$groupName][$i] = $choice; } } From 40e89d815f3a93e1d9de422dbbef0e08bf81aef6 Mon Sep 17 00:00:00 2001 From: Stefano Sala Date: Sat, 11 Jan 2014 10:24:07 +0100 Subject: [PATCH 271/447] Deprecated max_length and pattern options --- CHANGELOG.md | 1 + Extension/Core/Type/FormType.php | 21 +++++++++++++++++-- FormFactory.php | 4 ++-- Tests/AbstractLayoutTest.php | 12 +++++------ .../EventListener/ResizeFormListenerTest.php | 10 ++++----- .../Core/Type/CollectionTypeTest.php | 11 ++++++---- Tests/Extension/Core/Type/FormTypeTest.php | 10 ++++++++- Tests/FormFactoryTest.php | 16 +++++++------- 8 files changed, 56 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bebbceffd7..c210f9e792 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 2.5.0 ------ + * deprecated options "max_length" and "pattern" in favor of putting these values in "attr" option * added an option for multiple files upload * form errors now reference their cause (constraint violation, exception, ...) * form errors now remember which form they were originally added to diff --git a/Extension/Core/Type/FormType.php b/Extension/Core/Type/FormType.php index 7c6e602783..c66c7b3fb9 100644 --- a/Extension/Core/Type/FormType.php +++ b/Extension/Core/Type/FormType.php @@ -92,8 +92,8 @@ public function buildView(FormView $view, FormInterface $form, array $options) 'value' => $form->getViewData(), 'data' => $form->getNormData(), 'required' => $form->isRequired(), - 'max_length' => $options['max_length'], - 'pattern' => $options['pattern'], + 'max_length' => isset($options['attr']['maxlength']) ? $options['attr']['maxlength'] : null, // Deprecated + 'pattern' => isset($options['attr']['pattern']) ? $options['attr']['pattern'] : null, // Deprecated 'size' => null, 'label_attr' => $options['label_attr'], 'compound' => $form->getConfig()->getCompound(), @@ -170,6 +170,22 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'data', )); + // BC clause for the "max_length" and "pattern" option + // Add these values to the "attr" option instead + $defaultAttr = function (Options $options) { + $attributes = array(); + + if (null !== $options['max_length']) { + $attributes['maxlength'] = $options['max_length']; + } + + if (null !== $options['pattern']) { + $attributes['pattern'] = $options['pattern']; + } + + return $attributes; + }; + $resolver->setDefaults(array( 'data_class' => $dataClass, 'empty_data' => $emptyData, @@ -190,6 +206,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) // According to RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt) // section 4.2., empty URIs are considered same-document references 'action' => '', + 'attr' => $defaultAttr )); $resolver->setAllowedTypes(array( diff --git a/FormFactory.php b/FormFactory.php index d76e73101b..63b2fe442c 100644 --- a/FormFactory.php +++ b/FormFactory.php @@ -113,11 +113,11 @@ public function createBuilderForProperty($class, $property, $data = null, array $pattern = $patternGuess ? $patternGuess->getValue() : null; if (null !== $pattern) { - $options = array_merge(array('pattern' => $pattern), $options); + $options = array_merge(array('attr' => array('pattern' => $pattern)), $options); } if (null !== $maxLength) { - $options = array_merge(array('max_length' => $maxLength), $options); + $options = array_merge(array('attr' => array('maxlength' => $maxLength)), $options); } if ($requiredGuess) { diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index 28827e51b7..11696eccb8 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -1252,7 +1252,7 @@ public function testEmail() public function testEmailWithMaxLength() { $form = $this->factory->createNamed('name', 'email', 'foo&bar', array( - 'max_length' => 123, + 'attr' => array('maxlength' => 123), )); $this->assertWidgetMatchesXpath($form->createView(), array(), @@ -1418,7 +1418,7 @@ public function testPasswordSubmittedWithNotAlwaysEmpty() public function testPasswordWithMaxLength() { $form = $this->factory->createNamed('name', 'password', 'foo&bar', array( - 'max_length' => 123, + 'attr' => array('maxlength' => 123), )); $this->assertWidgetMatchesXpath($form->createView(), array(), @@ -1489,7 +1489,7 @@ public function testRadioWithValue() public function testTextarea() { $form = $this->factory->createNamed('name', 'textarea', 'foo&bar', array( - 'pattern' => 'foo', + 'attr' => array('pattern' => 'foo'), )); $this->assertWidgetMatchesXpath($form->createView(), array(), @@ -1518,7 +1518,7 @@ public function testText() public function testTextWithMaxLength() { $form = $this->factory->createNamed('name', 'text', 'foo&bar', array( - 'max_length' => 123, + 'attr' => array('maxlength' => 123), )); $this->assertWidgetMatchesXpath($form->createView(), array(), @@ -1898,9 +1898,7 @@ public function testWidgetAttributes() 'required' => true, 'disabled' => true, 'read_only' => true, - 'max_length' => 10, - 'pattern' => '\d+', - 'attr' => array('class' => 'foobar', 'data-foo' => 'bar'), + 'attr' => array('maxlength' => 10, 'pattern' => '\d+', 'class' => 'foobar', 'data-foo' => 'bar'), )); $html = $this->renderWidget($form->createView()); diff --git a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php index b70735f5d5..bbb0cf689f 100644 --- a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php +++ b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php @@ -69,16 +69,16 @@ public function testPreSetDataResizesForm() $this->factory->expects($this->at(0)) ->method('createNamed') - ->with(1, 'text', null, array('property_path' => '[1]', 'max_length' => 10, 'auto_initialize' => false)) + ->with(1, 'text', null, array('property_path' => '[1]', 'attr' => array('maxlength' => 10), 'auto_initialize' => false)) ->will($this->returnValue($this->getForm('1'))); $this->factory->expects($this->at(1)) ->method('createNamed') - ->with(2, 'text', null, array('property_path' => '[2]', 'max_length' => 10, 'auto_initialize' => false)) + ->with(2, 'text', null, array('property_path' => '[2]', 'attr' => array('maxlength' => 10), 'auto_initialize' => false)) ->will($this->returnValue($this->getForm('2'))); $data = array(1 => 'string', 2 => 'string'); $event = new FormEvent($this->form, $data); - $listener = new ResizeFormListener('text', array('max_length' => '10'), false, false); + $listener = new ResizeFormListener('text', array('attr' => array('maxlength' => 10)), false, false); $listener->preSetData($event); $this->assertFalse($this->form->has('0')); @@ -113,12 +113,12 @@ public function testPreSubmitResizesUpIfAllowAdd() $this->factory->expects($this->once()) ->method('createNamed') - ->with(1, 'text', null, array('property_path' => '[1]', 'max_length' => 10, 'auto_initialize' => false)) + ->with(1, 'text', null, array('property_path' => '[1]', 'attr' => array('maxlength' => 10), 'auto_initialize' => false)) ->will($this->returnValue($this->getForm('1'))); $data = array(0 => 'string', 1 => 'string'); $event = new FormEvent($this->form, $data); - $listener = new ResizeFormListener('text', array('max_length' => 10), true, false); + $listener = new ResizeFormListener('text', array('attr' => array('maxlength' => 10)), true, false); $listener->preSubmit($event); $this->assertTrue($this->form->has('0')); diff --git a/Tests/Extension/Core/Type/CollectionTypeTest.php b/Tests/Extension/Core/Type/CollectionTypeTest.php index 58bbfad782..77be4b01e6 100644 --- a/Tests/Extension/Core/Type/CollectionTypeTest.php +++ b/Tests/Extension/Core/Type/CollectionTypeTest.php @@ -31,7 +31,7 @@ public function testSetDataAdjustsSize() $form = $this->factory->create('collection', null, array( 'type' => 'text', 'options' => array( - 'max_length' => 20, + 'attr' => array('maxlength' => 20), ), )); $form->setData(array('foo@foo.com', 'foo@bar.com')); @@ -41,15 +41,18 @@ public function testSetDataAdjustsSize() $this->assertCount(2, $form); $this->assertEquals('foo@foo.com', $form[0]->getData()); $this->assertEquals('foo@bar.com', $form[1]->getData()); - $this->assertEquals(20, $form[0]->getConfig()->getOption('max_length')); - $this->assertEquals(20, $form[1]->getConfig()->getOption('max_length')); + $formAttrs0 = $form[0]->getConfig()->getOption('attr'); + $formAttrs1 = $form[1]->getConfig()->getOption('attr'); + $this->assertEquals(20, $formAttrs0['maxlength']); + $this->assertEquals(20, $formAttrs1['maxlength']); $form->setData(array('foo@baz.com')); $this->assertInstanceOf('Symfony\Component\Form\Form', $form[0]); $this->assertFalse(isset($form[1])); $this->assertCount(1, $form); $this->assertEquals('foo@baz.com', $form[0]->getData()); - $this->assertEquals(20, $form[0]->getConfig()->getOption('max_length')); + $formAttrs0 = $form[0]->getConfig()->getOption('attr'); + $this->assertEquals(20, $formAttrs0['maxlength']); } public function testThrowsExceptionIfObjectIsNotTraversable() diff --git a/Tests/Extension/Core/Type/FormTypeTest.php b/Tests/Extension/Core/Type/FormTypeTest.php index 4568807c77..6a6a17d84a 100644 --- a/Tests/Extension/Core/Type/FormTypeTest.php +++ b/Tests/Extension/Core/Type/FormTypeTest.php @@ -131,11 +131,19 @@ public function testNonReadOnlyFormWithNonReadOnlyParentIsNotReadOnly() } public function testPassMaxLengthToView() + { + $form = $this->factory->create('form', null, array('attr' => array('maxlength' => 10))); + $view = $form->createView(); + + $this->assertSame(10, $view->vars['attr']['maxlength']); + } + + public function testPassMaxLengthBCToView() { $form = $this->factory->create('form', null, array('max_length' => 10)); $view = $form->createView(); - $this->assertSame(10, $view->vars['max_length']); + $this->assertSame(10, $view->vars['attr']['maxlength']); } public function testSubmitWithEmptyDataCreatesObjectIfClassAvailable() diff --git a/Tests/FormFactoryTest.php b/Tests/FormFactoryTest.php index cdd06e1594..a06b49876e 100644 --- a/Tests/FormFactoryTest.php +++ b/Tests/FormFactoryTest.php @@ -399,7 +399,7 @@ public function testCreateBuilderForPropertyCreatesFormWithHighestConfidence() ->with('Application\Author', 'firstName') ->will($this->returnValue(new TypeGuess( 'text', - array('max_length' => 10), + array('attr' => array('maxlength' => 10)), Guess::MEDIUM_CONFIDENCE ))); @@ -408,7 +408,7 @@ public function testCreateBuilderForPropertyCreatesFormWithHighestConfidence() ->with('Application\Author', 'firstName') ->will($this->returnValue(new TypeGuess( 'password', - array('max_length' => 7), + array('attr' => array('maxlength' => 7)), Guess::HIGH_CONFIDENCE ))); @@ -416,7 +416,7 @@ public function testCreateBuilderForPropertyCreatesFormWithHighestConfidence() $factory->expects($this->once()) ->method('createNamedBuilder') - ->with('firstName', 'password', null, array('max_length' => 7)) + ->with('firstName', 'password', null, array('attr' => array('maxlength' => 7))) ->will($this->returnValue('builderInstance')); $this->builder = $factory->createBuilderForProperty('Application\Author', 'firstName'); @@ -450,7 +450,7 @@ public function testOptionsCanBeOverridden() ->with('Application\Author', 'firstName') ->will($this->returnValue(new TypeGuess( 'text', - array('max_length' => 10), + array('attr' => array('maxlength' => 10)), Guess::MEDIUM_CONFIDENCE ))); @@ -458,14 +458,14 @@ public function testOptionsCanBeOverridden() $factory->expects($this->once()) ->method('createNamedBuilder') - ->with('firstName', 'text', null, array('max_length' => 11)) + ->with('firstName', 'text', null, array('attr' => array('maxlength' => 11))) ->will($this->returnValue('builderInstance')); $this->builder = $factory->createBuilderForProperty( 'Application\Author', 'firstName', null, - array('max_length' => 11) + array('attr' => array('maxlength' => 11)) ); $this->assertEquals('builderInstance', $this->builder); @@ -493,7 +493,7 @@ public function testCreateBuilderUsesMaxLengthIfFound() $factory->expects($this->once()) ->method('createNamedBuilder') - ->with('firstName', 'text', null, array('max_length' => 20)) + ->with('firstName', 'text', null, array('attr' => array('maxlength' => 20))) ->will($this->returnValue('builderInstance')); $this->builder = $factory->createBuilderForProperty( @@ -559,7 +559,7 @@ public function testCreateBuilderUsesPatternIfFound() $factory->expects($this->once()) ->method('createNamedBuilder') - ->with('firstName', 'text', null, array('pattern' => '[a-zA-Z]')) + ->with('firstName', 'text', null, array('attr' => array('pattern' => '[a-zA-Z]'))) ->will($this->returnValue('builderInstance')); $this->builder = $factory->createBuilderForProperty( From 03110fc756d2351002bd8cb37551f62560bfd121 Mon Sep 17 00:00:00 2001 From: kor3k Date: Mon, 30 Sep 2013 19:22:43 +0200 Subject: [PATCH 272/447] made HttpFoundationRequestHandler a service --- .../Type/FormTypeHttpFoundationExtension.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php b/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php index 9b09b05c39..9cb0dc4476 100644 --- a/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php +++ b/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php @@ -13,8 +13,9 @@ use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\Extension\HttpFoundation\EventListener\BindRequestListener; -use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; +use Symfony\Component\Form\RequestHandlerInterface; use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; /** * @author Bernhard Schussek @@ -27,14 +28,17 @@ class FormTypeHttpFoundationExtension extends AbstractTypeExtension private $listener; /** - * @var HttpFoundationRequestHandler + * @var RequestHandlerInterface */ private $requestHandler; - public function __construct() + /** + * @param RequestHandlerInterface $requestHandler + */ + public function __construct(RequestHandlerInterface $requestHandler = null) { $this->listener = new BindRequestListener(); - $this->requestHandler = new HttpFoundationRequestHandler(); + $this->requestHandler = $requestHandler ?: new HttpFoundationRequestHandler(); } /** From 739fc7cd51f0e8a9f8ddea775dfaa2cd371790c9 Mon Sep 17 00:00:00 2001 From: Stefano Sala Date: Wed, 26 Mar 2014 14:06:37 +0100 Subject: [PATCH 273/447] Fixed tests after merging pattern deprecation --- Tests/AbstractLayoutTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index 7ef9c17d3d..532dc41be7 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -1497,7 +1497,7 @@ public function testTextarea() $this->assertWidgetMatchesXpath($form->createView(), array(), '/textarea [@name="name"] - [not(@pattern)] + [@pattern="foo"] [.="foo&bar"] ' ); From 82854ab90324586273b62ec2b75d63caa5997af4 Mon Sep 17 00:00:00 2001 From: Koen Kuipers Date: Thu, 27 Mar 2014 13:42:59 +0100 Subject: [PATCH 274/447] Fixed bug in ChoiceType triggering a warning when not using utf-8 This fixes issue #10409 by not using json_encode anymore, but serialize instead. --- Extension/Core/Type/ChoiceType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/Core/Type/ChoiceType.php b/Extension/Core/Type/ChoiceType.php index 692f91e95c..83fe717f0d 100644 --- a/Extension/Core/Type/ChoiceType.php +++ b/Extension/Core/Type/ChoiceType.php @@ -166,7 +166,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) $choices = null !== $options['choices'] ? $options['choices'] : array(); // Reuse existing choice lists in order to increase performance - $hash = md5(json_encode(array($choices, $options['preferred_choices']))); + $hash = hash('sha256', serialize(array($choices, $options['preferred_choices']))); if (!isset($choiceListCache[$hash])) { $choiceListCache[$hash] = new SimpleChoiceList($choices, $options['preferred_choices']); From f0429417978866e16529c9f7e44179f7e4d731fe Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 28 Mar 2014 11:13:11 +0100 Subject: [PATCH 275/447] Added test case for 4c6a2d15095c13b2a35751b2b2712b183be489c4 --- Tests/Extension/Core/Type/ChoiceTypeTest.php | 41 ++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/Tests/Extension/Core/Type/ChoiceTypeTest.php b/Tests/Extension/Core/Type/ChoiceTypeTest.php index 3da49dfa6a..2e99c2c774 100644 --- a/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -1216,6 +1216,47 @@ public function testInitializeWithEmptyChoices() )); } + // https://github.com/symfony/symfony/issues/10409 + public function testReuseNonUtf8ChoiceLists() + { + $form1 = $this->factory->createNamed('name', 'choice', null, array( + 'choices' => array( + 'meter' => 'm', + 'millimeter' => 'mm', + 'micrometer' => chr(181).'meter', + ), + )); + + $form2 = $this->factory->createNamed('name', 'choice', null, array( + 'choices' => array( + 'meter' => 'm', + 'millimeter' => 'mm', + 'micrometer' => chr(181).'meter', + ), + )); + + $form3 = $this->factory->createNamed('name', 'choice', null, array( + 'choices' => array( + 'meter' => 'm', + 'millimeter' => 'mm', + 'micrometer' => null, + ), + )); + + // $form1 and $form2 use the same ChoiceList + $this->assertSame( + $form1->getConfig()->getOption('choice_list'), + $form2->getConfig()->getOption('choice_list') + ); + + // $form3 doesn't, but used to use the same when using json_encode() + // instead of serialize for the hashing algorithm + $this->assertNotSame( + $form1->getConfig()->getOption('choice_list'), + $form3->getConfig()->getOption('choice_list') + ); + } + public function testInitializeWithDefaultObjectChoice() { $obj1 = (object) array('value' => 'a', 'label' => 'A'); From edf249fd703ddbbc97491d47469ce7db4abc340a Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 28 Mar 2014 11:34:27 +0100 Subject: [PATCH 276/447] fixed CS --- Tests/Extension/Core/Type/ChoiceTypeTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/Extension/Core/Type/ChoiceTypeTest.php b/Tests/Extension/Core/Type/ChoiceTypeTest.php index 2e99c2c774..b251da031c 100644 --- a/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -380,7 +380,7 @@ public function testSubmitSingleExpandedRequiredInvalidChoice() $form->submit('foobar'); - $this->assertSame(null, $form->getData()); + $this->assertNull($form->getData()); $this->assertSame('foobar', $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertFalse($form->isSynchronized()); @@ -445,7 +445,7 @@ public function testSubmitSingleExpandedNonRequiredInvalidChoice() $form->submit('foobar'); - $this->assertSame(null, $form->getData()); + $this->assertNull($form->getData()); $this->assertSame('foobar', $form->getViewData()); $this->assertEmpty($form->getExtraData()); $this->assertFalse($form->isSynchronized()); From e5f70f07b6b120c4bba85022eb0629f32de0e248 Mon Sep 17 00:00:00 2001 From: Matt Janssen Date: Mon, 30 Sep 2013 22:14:37 -0500 Subject: [PATCH 277/447] [Form] Accept interfaces to be passed to "data_class" --- FormConfigBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index 1015da4f51..391c5cd5e2 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -192,7 +192,7 @@ public function __construct($name, $dataClass, EventDispatcherInterface $dispatc { self::validateName($name); - if (null !== $dataClass && !class_exists($dataClass)) { + if (null !== $dataClass && !class_exists($dataClass) && !interface_exists($dataClass)) { throw new InvalidArgumentException(sprintf('The data class "%s" is not a valid class.', $dataClass)); } From 611a4e1ad943b69e33e9ae8a8b1d4437184fab4f Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 28 Mar 2014 12:44:24 +0100 Subject: [PATCH 278/447] [Form] Added test case for 4759e062ed004749dbdc2ba31aef0f8ac2601895 --- CHANGELOG.md | 1 + Tests/Extension/Core/Type/FormTypeTest.php | 31 ++++++++++++++++++++++ Tests/Fixtures/AbstractAuthor.php | 16 +++++++++++ Tests/Fixtures/AuthorInterface.php | 16 +++++++++++ 4 files changed, 64 insertions(+) create mode 100644 Tests/Fixtures/AbstractAuthor.php create mode 100644 Tests/Fixtures/AuthorInterface.php diff --git a/CHANGELOG.md b/CHANGELOG.md index c210f9e792..dc7a59bbde 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ CHANGELOG * [BC BREAK] added two optional parameters to FormInterface::getErrors() and changed the method to return a Symfony\Component\Form\FormErrorIterator instance instead of an array + * you can now pass interface names in the "data_class" option 2.4.0 ----- diff --git a/Tests/Extension/Core/Type/FormTypeTest.php b/Tests/Extension/Core/Type/FormTypeTest.php index 6a6a17d84a..a8465dc990 100644 --- a/Tests/Extension/Core/Type/FormTypeTest.php +++ b/Tests/Extension/Core/Type/FormTypeTest.php @@ -146,6 +146,37 @@ public function testPassMaxLengthBCToView() $this->assertSame(10, $view->vars['attr']['maxlength']); } + public function testDataClassMayBeNull() + { + $this->factory->createBuilder('form', null, array( + 'data_class' => null, + )); + } + + public function testDataClassMayBeAbstractClass() + { + $this->factory->createBuilder('form', null, array( + 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\AbstractAuthor', + )); + } + + public function testDataClassMayBeInterface() + { + $this->factory->createBuilder('form', null, array( + 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\AuthorInterface', + )); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException + */ + public function testDataClassMustBeValidClassOrInterface() + { + $this->factory->createBuilder('form', null, array( + 'data_class' => 'foobar', + )); + } + public function testSubmitWithEmptyDataCreatesObjectIfClassAvailable() { $builder = $this->factory->createBuilder('form', null, array( diff --git a/Tests/Fixtures/AbstractAuthor.php b/Tests/Fixtures/AbstractAuthor.php new file mode 100644 index 0000000000..03a6b724f3 --- /dev/null +++ b/Tests/Fixtures/AbstractAuthor.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Fixtures; + +abstract class AbstractAuthor +{ +} diff --git a/Tests/Fixtures/AuthorInterface.php b/Tests/Fixtures/AuthorInterface.php new file mode 100644 index 0000000000..984cb541ec --- /dev/null +++ b/Tests/Fixtures/AuthorInterface.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Fixtures; + +interface AuthorInterface +{ +} From e83763b5f70e5ea01fbf409fce20ef3fc1c9066b Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 28 Mar 2014 18:03:44 +0100 Subject: [PATCH 279/447] [Form] ObjectChoiceList now compares choices by their value, if a value path is given --- CHANGELOG.md | 2 + Extension/Core/ChoiceList/ChoiceList.php | 4 +- .../Core/ChoiceList/ObjectChoiceList.php | 74 ++++++++++++ .../Core/ChoiceList/ObjectChoiceListTest.php | 113 ++++++++++++++++++ 4 files changed, 191 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c210f9e792..f7071663d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ CHANGELOG * [BC BREAK] added two optional parameters to FormInterface::getErrors() and changed the method to return a Symfony\Component\Form\FormErrorIterator instance instead of an array + * ObjectChoiceList now compares choices by their value, if a value path is + given 2.4.0 ----- diff --git a/Extension/Core/ChoiceList/ChoiceList.php b/Extension/Core/ChoiceList/ChoiceList.php index 413f7c4f74..3266ca38e2 100644 --- a/Extension/Core/ChoiceList/ChoiceList.php +++ b/Extension/Core/ChoiceList/ChoiceList.php @@ -41,14 +41,14 @@ class ChoiceList implements ChoiceListInterface * * @var array */ - private $choices = array(); + protected $choices = array(); /** * The choice values with the indices of the matching choices as keys. * * @var array */ - private $values = array(); + protected $values = array(); /** * The preferred view objects as hierarchy containing also the choice groups diff --git a/Extension/Core/ChoiceList/ObjectChoiceList.php b/Extension/Core/ChoiceList/ObjectChoiceList.php index 0f1437db21..9c6c3ab598 100644 --- a/Extension/Core/ChoiceList/ObjectChoiceList.php +++ b/Extension/Core/ChoiceList/ObjectChoiceList.php @@ -148,6 +148,80 @@ protected function initialize($choices, array $labels, array $preferredChoices) parent::initialize($choices, $labels, $preferredChoices); } + /** + * {@inheritdoc} + */ + public function getValuesForChoices(array $choices) + { + if (!$this->valuePath) { + return parent::getValuesForChoices($choices); + } + + // Use the value path to compare the choices + $choices = $this->fixChoices($choices); + $values = array(); + + foreach ($choices as $i => $givenChoice) { + // Ignore non-readable choices + if (!is_object($givenChoice) && !is_array($givenChoice)) { + continue; + } + + $givenValue = (string) $this->propertyAccessor->getValue($givenChoice, $this->valuePath); + + foreach ($this->values as $value) { + if ($value === $givenValue) { + $values[$i] = $value; + unset($choices[$i]); + + if (0 === count($choices)) { + break 2; + } + } + } + } + + return $values; + } + + /** + * {@inheritdoc} + * + * @deprecated Deprecated since version 2.4, to be removed in 3.0. + */ + public function getIndicesForChoices(array $choices) + { + if (!$this->valuePath) { + return parent::getIndicesForChoices($choices); + } + + // Use the value path to compare the choices + $choices = $this->fixChoices($choices); + $indices = array(); + + foreach ($choices as $i => $givenChoice) { + // Ignore non-readable choices + if (!is_object($givenChoice) && !is_array($givenChoice)) { + continue; + } + + $givenValue = (string) $this->propertyAccessor->getValue($givenChoice, $this->valuePath); + + foreach ($this->values as $j => $value) { + if ($value === $givenValue) { + $indices[$i] = $j; + unset($choices[$i]); + + if (0 === count($choices)) { + break 2; + } + } + } + } + + return $indices; + } + /** * Creates a new unique value for this choice. * diff --git a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php index 27effd9f5c..655101ca1a 100644 --- a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php @@ -185,6 +185,119 @@ public function testInitArrayThrowsExceptionIfToStringNotFound() ); } + public function testGetIndicesForChoicesWithValuePath() + { + $this->list = new ObjectChoiceList( + array($this->obj1, $this->obj2, $this->obj3, $this->obj4), + 'name', + array(), + null, + 'name' + ); + + // Compare by value, not by identity + $choices = array(clone $this->obj1, clone $this->obj2); + $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesWithValuePathPreservesKeys() + { + $this->list = new ObjectChoiceList( + array($this->obj1, $this->obj2, $this->obj3, $this->obj4), + 'name', + array(), + null, + 'name' + ); + + $choices = array(5 => clone $this->obj1, 8 => clone $this->obj2); + $this->assertSame(array(5 => $this->index1, 8 => $this->index2), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesWithValuePathPreservesOrder() + { + $this->list = new ObjectChoiceList( + array($this->obj1, $this->obj2, $this->obj3, $this->obj4), + 'name', + array(), + null, + 'name' + ); + + $choices = array(clone $this->obj2, clone $this->obj1); + $this->assertSame(array($this->index2, $this->index1), $this->list->getIndicesForChoices($choices)); + } + + public function testGetIndicesForChoicesWithValuePathIgnoresNonExistingChoices() + { + $this->list = new ObjectChoiceList( + array($this->obj1, $this->obj2, $this->obj3, $this->obj4), + 'name', + array(), + null, + 'name' + ); + + $choices = array(clone $this->obj1, clone $this->obj2, 'foobar'); + $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices)); + } + + public function testGetValuesForChoicesWithValuePath() + { + $this->list = new ObjectChoiceList( + array($this->obj1, $this->obj2, $this->obj3, $this->obj4), + 'name', + array(), + null, + 'name' + ); + + $choices = array(clone $this->obj1, clone $this->obj2); + $this->assertSame(array('A', 'B'), $this->list->getValuesForChoices($choices)); + } + + public function testGetValuesForChoicesWithValuePathPreservesKeys() + { + $this->list = new ObjectChoiceList( + array($this->obj1, $this->obj2, $this->obj3, $this->obj4), + 'name', + array(), + null, + 'name' + ); + + $choices = array(5 => clone $this->obj1, 8 => clone $this->obj2); + $this->assertSame(array(5 => 'A', 8 => 'B'), $this->list->getValuesForChoices($choices)); + } + + public function testGetValuesForChoicesWithValuePathPreservesOrder() + { + $this->list = new ObjectChoiceList( + array($this->obj1, $this->obj2, $this->obj3, $this->obj4), + 'name', + array(), + null, + 'name' + ); + + $choices = array(clone $this->obj2, clone $this->obj1); + $this->assertSame(array('B', 'A'), $this->list->getValuesForChoices($choices)); + } + + public function testGetValuesForChoicesWithValuePathIgnoresNonExistingChoices() + { + $this->list = new ObjectChoiceList( + array($this->obj1, $this->obj2, $this->obj3, $this->obj4), + 'name', + array(), + null, + 'name' + ); + + $choices = array(clone $this->obj1, clone $this->obj2, 'foobar'); + $this->assertSame(array('A', 'B'), $this->list->getValuesForChoices($choices)); + } + /** * @return \Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface */ From 88c70c391ee1adf95b04b43d81175b80850a61eb Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 28 Mar 2014 18:26:06 +0100 Subject: [PATCH 280/447] [Form] Fixed infinite tests when ICU is available --- Tests/Extension/Core/Type/DateTimeTypeTest.php | 16 ++++++++-------- Tests/Extension/Core/Type/DateTypeTest.php | 12 ++++++------ Tests/Extension/Core/Type/TimeTypeTest.php | 12 ++++++------ 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Tests/Extension/Core/Type/DateTimeTypeTest.php b/Tests/Extension/Core/Type/DateTimeTypeTest.php index b9c1ebad38..c76039262d 100644 --- a/Tests/Extension/Core/Type/DateTimeTypeTest.php +++ b/Tests/Extension/Core/Type/DateTimeTypeTest.php @@ -433,8 +433,8 @@ public function testDateTypeChoiceErrorsBubbleUp() $form['date']->addError($error); - $this->assertSame(array(), $form['date']->getErrors()); - $this->assertSame(array($error), $form->getErrors()); + $this->assertSame(array(), iterator_to_array($form['date']->getErrors())); + $this->assertSame(array($error), iterator_to_array($form->getErrors())); } public function testDateTypeSingleTextErrorsBubbleUp() @@ -446,8 +446,8 @@ public function testDateTypeSingleTextErrorsBubbleUp() $form['date']->addError($error); - $this->assertSame(array(), $form['date']->getErrors()); - $this->assertSame(array($error), $form->getErrors()); + $this->assertSame(array(), iterator_to_array($form['date']->getErrors())); + $this->assertSame(array($error), iterator_to_array($form->getErrors())); } public function testTimeTypeChoiceErrorsBubbleUp() @@ -457,8 +457,8 @@ public function testTimeTypeChoiceErrorsBubbleUp() $form['time']->addError($error); - $this->assertSame(array(), $form['time']->getErrors()); - $this->assertSame(array($error), $form->getErrors()); + $this->assertSame(array(), iterator_to_array($form['time']->getErrors())); + $this->assertSame(array($error), iterator_to_array($form->getErrors())); } public function testTimeTypeSingleTextErrorsBubbleUp() @@ -470,8 +470,8 @@ public function testTimeTypeSingleTextErrorsBubbleUp() $form['time']->addError($error); - $this->assertSame(array(), $form['time']->getErrors()); - $this->assertSame(array($error), $form->getErrors()); + $this->assertSame(array(), iterator_to_array($form['time']->getErrors())); + $this->assertSame(array($error), iterator_to_array($form->getErrors())); } } diff --git a/Tests/Extension/Core/Type/DateTypeTest.php b/Tests/Extension/Core/Type/DateTypeTest.php index 508ab410b0..e38bfe0ebb 100644 --- a/Tests/Extension/Core/Type/DateTypeTest.php +++ b/Tests/Extension/Core/Type/DateTypeTest.php @@ -745,8 +745,8 @@ public function testYearErrorsBubbleUp($widget) )); $form['year']->addError($error); - $this->assertSame(array(), $form['year']->getErrors()); - $this->assertSame(array($error), $form->getErrors()); + $this->assertSame(array(), iterator_to_array($form['year']->getErrors())); + $this->assertSame(array($error), iterator_to_array($form->getErrors())); } /** @@ -760,8 +760,8 @@ public function testMonthErrorsBubbleUp($widget) )); $form['month']->addError($error); - $this->assertSame(array(), $form['month']->getErrors()); - $this->assertSame(array($error), $form->getErrors()); + $this->assertSame(array(), iterator_to_array($form['month']->getErrors())); + $this->assertSame(array($error), iterator_to_array($form->getErrors())); } /** @@ -775,8 +775,8 @@ public function testDayErrorsBubbleUp($widget) )); $form['day']->addError($error); - $this->assertSame(array(), $form['day']->getErrors()); - $this->assertSame(array($error), $form->getErrors()); + $this->assertSame(array(), iterator_to_array($form['day']->getErrors())); + $this->assertSame(array($error), iterator_to_array($form->getErrors())); } public function testYearsFor32BitsMachines() diff --git a/Tests/Extension/Core/Type/TimeTypeTest.php b/Tests/Extension/Core/Type/TimeTypeTest.php index 9bdfe1567b..3dc5cff438 100644 --- a/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/Tests/Extension/Core/Type/TimeTypeTest.php @@ -601,8 +601,8 @@ public function testHourErrorsBubbleUp($widget) )); $form['hour']->addError($error); - $this->assertSame(array(), $form['hour']->getErrors()); - $this->assertSame(array($error), $form->getErrors()); + $this->assertSame(array(), iterator_to_array($form['hour']->getErrors())); + $this->assertSame(array($error), iterator_to_array($form->getErrors())); } /** @@ -616,8 +616,8 @@ public function testMinuteErrorsBubbleUp($widget) )); $form['minute']->addError($error); - $this->assertSame(array(), $form['minute']->getErrors()); - $this->assertSame(array($error), $form->getErrors()); + $this->assertSame(array(), iterator_to_array($form['minute']->getErrors())); + $this->assertSame(array($error), iterator_to_array($form->getErrors())); } /** @@ -632,8 +632,8 @@ public function testSecondErrorsBubbleUp($widget) )); $form['second']->addError($error); - $this->assertSame(array(), $form['second']->getErrors()); - $this->assertSame(array($error), $form->getErrors()); + $this->assertSame(array(), iterator_to_array($form['second']->getErrors())); + $this->assertSame(array($error), iterator_to_array($form->getErrors())); } /** From ac1b472566ee4371e8f34edcf7fc7b6bb3286e4b Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 28 Mar 2014 10:30:00 +0100 Subject: [PATCH 281/447] [Form] Disabled violation mapping of unsubmitted forms --- CHANGELOG.md | 1 + .../ViolationMapper/ViolationMapper.php | 5 +- Form.php | 16 ++--- Tests/CompoundFormTest.php | 16 ----- .../ViolationMapper/ViolationMapperTest.php | 64 ++++++++++++++++++- 5 files changed, 73 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c210f9e792..344bd9c0ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ CHANGELOG * [BC BREAK] added two optional parameters to FormInterface::getErrors() and changed the method to return a Symfony\Component\Form\FormErrorIterator instance instead of an array + * errors mapped to unsubmitted forms are discarded now 2.4.0 ----- diff --git a/Extension/Validator/ViolationMapper/ViolationMapper.php b/Extension/Validator/ViolationMapper/ViolationMapper.php index 15ceb0cf08..e0eac4dacd 100644 --- a/Extension/Validator/ViolationMapper/ViolationMapper.php +++ b/Extension/Validator/ViolationMapper/ViolationMapper.php @@ -294,6 +294,9 @@ private function reconstructPath(ViolationPath $violationPath, FormInterface $or */ private function acceptsErrors(FormInterface $form) { - return $this->allowNonSynchronized || $form->isSynchronized(); + // Ignore non-submitted forms. This happens, for example, in PATCH + // requests. + // https://github.com/symfony/symfony/pull/10567 + return $form->isSubmitted() && ($this->allowNonSynchronized || $form->isSynchronized()); } } diff --git a/Form.php b/Form.php index a5f98c16f5..5bc97b12ee 100644 --- a/Form.php +++ b/Form.php @@ -556,8 +556,10 @@ public function submit($submittedData, $clearMissing = true) } foreach ($this->children as $name => $child) { - if (array_key_exists($name, $submittedData) || $clearMissing) { - $child->submit(isset($submittedData[$name]) ? $submittedData[$name] : null, $clearMissing); + $isSubmitted = array_key_exists($name, $submittedData); + + if ($isSubmitted || $clearMissing) { + $child->submit($isSubmitted ? $submittedData[$name] : null, $clearMissing); unset($submittedData[$name]); if (null !== $this->clickedButton) { @@ -739,18 +741,12 @@ public function isValid() return false; } - if (count($this->errors) > 0) { - return false; - } - if ($this->isDisabled()) { return true; } - foreach ($this->children as $child) { - if ($child->isSubmitted() && !$child->isValid()) { - return false; - } + if (count($this->getErrors(true)) > 0) { + return false; } return true; diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index 8f861788d3..59dd36d138 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -51,22 +51,6 @@ public function testInvalidIfChildIsInvalid() $this->assertFalse($this->form->isValid()); } - public function testValidIfChildIsNotSubmitted() - { - $this->form->add($this->getBuilder('firstName')->getForm()); - $this->form->add($this->getBuilder('lastName')->getForm()); - - $this->form->submit(array( - 'firstName' => 'Bernhard', - )); - - // "lastName" is not "valid" because it was not submitted. This happens - // for example in PATCH requests. The parent form should still be - // considered valid. - - $this->assertTrue($this->form->isValid()); - } - public function testDisabledFormsValidEvenIfChildrenInvalid() { $form = $this->getBuilder('person') diff --git a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php index c2db73eb77..7e063fc466 100644 --- a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php +++ b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php @@ -125,6 +125,8 @@ public function testMapToFormInheritingParentDataIfDataDoesNotMatch() $parent->add($child); $child->add($grandChild); + $parent->submit(array()); + $this->mapper->mapViolation($violation, $parent); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); @@ -150,6 +152,8 @@ public function testFollowDotRules() $child->add($grandChild); $grandChild->add($grandGrandChild); + $parent->submit(array()); + $this->mapper->mapViolation($violation, $parent); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); @@ -170,7 +174,7 @@ public function testAbortMappingIfNotSynchronized() $parent->add($child); $child->add($grandChild); - // submit to invoke the transformer and mark the form unsynchronized + // invoke the transformer and mark the form unsynchronized $parent->submit(array()); $this->mapper->mapViolation($violation, $parent); @@ -194,7 +198,7 @@ public function testAbortDotRuleMappingIfNotSynchronized() $parent->add($child); $child->add($grandChild); - // submit to invoke the transformer and mark the form unsynchronized + // invoke the transformer and mark the form unsynchronized $parent->submit(array()); $this->mapper->mapViolation($violation, $parent); @@ -204,6 +208,54 @@ public function testAbortDotRuleMappingIfNotSynchronized() $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); } + public function testAbortMappingIfNotSubmitted() + { + $violation = $this->getConstraintViolation('children[address].data.street'); + $parent = $this->getForm('parent'); + $child = $this->getForm('address', 'address'); + $grandChild = $this->getForm('street' , 'street'); + + $parent->add($child); + $child->add($grandChild); + + // Disable automatic submission of missing fields + $parent->submit(array(), false); + $child->submit(array(), false); + + // $grandChild is not submitted + + $this->mapper->mapViolation($violation, $parent); + + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one'); + $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); + } + + public function testAbortDotRuleMappingIfNotSubmitted() + { + $violation = $this->getConstraintViolation('data.address'); + $parent = $this->getForm('parent'); + $child = $this->getForm('address', 'address', null, array( + '.' => 'street', + )); + $grandChild = $this->getForm('street'); + + $parent->add($child); + $child->add($grandChild); + + // Disable automatic submission of missing fields + $parent->submit(array(), false); + $child->submit(array(), false); + + // $grandChild is not submitted + + $this->mapper->mapViolation($violation, $parent); + + $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); + $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one'); + $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); + } + public function provideDefaultTests() { // The mapping must be deterministic! If a child has the property path "[street]", @@ -743,6 +795,8 @@ public function testDefaultErrorMapping($target, $childName, $childPath, $grandC $parent->add($child); $child->add($grandChild); + $parent->submit(array()); + $this->mapper->mapViolation($violation, $parent); if (self::LEVEL_0 === $target) { @@ -1211,6 +1265,8 @@ public function testCustomDataErrorMapping($target, $mapFrom, $mapTo, $childName $parent->add($distraction); } + $parent->submit(array()); + $this->mapper->mapViolation($violation, $parent); if ($target !== self::LEVEL_0) { @@ -1396,6 +1452,8 @@ public function testCustomFormErrorMapping($target, $mapFrom, $mapTo, $errorName $parent->add($errorChild); $child->add($grandChild); + $parent->submit(array()); + $this->mapper->mapViolation($violation, $parent); if (self::LEVEL_0 === $target) { @@ -1459,6 +1517,8 @@ public function testErrorMappingForFormInheritingParentData($target, $childName, $parent->add($child); $child->add($grandChild); + $parent->submit(array()); + $this->mapper->mapViolation($violation, $parent); if (self::LEVEL_0 === $target) { From d574beb73194cfea18c55100f7d8d7c4bc1a8e90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adria=CC=80=20Lo=CC=81pez=20Lozano?= Date: Wed, 22 Jan 2014 16:19:57 +0100 Subject: [PATCH 282/447] [Form] Added check for parent disabled status in Button form elements The Button form element did not check for the parent disabled configuration status, making them behave differently to all other form widgets. --- Button.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Button.php b/Button.php index f12d11afe4..2d7ccd1569 100644 --- a/Button.php +++ b/Button.php @@ -321,7 +321,11 @@ public function isRequired() */ public function isDisabled() { - return $this->config->getDisabled(); + if (null === $this->parent || !$this->parent->isDisabled()) { + return $this->config->getDisabled(); + } + + return true; } /** From 85c10dd4719a3b3611a8ce80faa858513babb5fe Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Mon, 31 Mar 2014 11:59:34 +0200 Subject: [PATCH 283/447] [Form] Added test for disabling buttons --- ButtonBuilder.php | 8 +++++ Tests/ButtonTest.php | 70 ++++++++++++++++++++++++++++++++++++++++ Tests/SimpleFormTest.php | 36 +++++++++------------ 3 files changed, 93 insertions(+), 21 deletions(-) create mode 100644 Tests/ButtonTest.php diff --git a/ButtonBuilder.php b/ButtonBuilder.php index 9146c69352..f9b0546b1f 100644 --- a/ButtonBuilder.php +++ b/ButtonBuilder.php @@ -252,6 +252,8 @@ public function resetModelTransformers() public function setAttribute($name, $value) { $this->attributes[$name] = $value; + + return $this; } /** @@ -260,6 +262,8 @@ public function setAttribute($name, $value) public function setAttributes(array $attributes) { $this->attributes = $attributes; + + return $this; } /** @@ -286,6 +290,8 @@ public function setDataMapper(DataMapperInterface $dataMapper = null) public function setDisabled($disabled) { $this->disabled = $disabled; + + return $this; } /** @@ -410,6 +416,8 @@ public function setCompound($compound) public function setType(ResolvedFormTypeInterface $type) { $this->type = $type; + + return $this; } /** diff --git a/Tests/ButtonTest.php b/Tests/ButtonTest.php new file mode 100644 index 0000000000..b0c766c73c --- /dev/null +++ b/Tests/ButtonTest.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +use Symfony\Component\Form\ButtonBuilder; +use Symfony\Component\Form\FormBuilder; + +/** + * @author Bernhard Schussek + */ +class ButtonTest extends \PHPUnit_Framework_TestCase +{ + private $dispatcher; + + private $factory; + + protected function setUp() + { + $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); + $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); + } + + /** + * @dataProvider getDisabledStates + */ + public function testDisabledIfParentIsDisabled($parentDisabled, $buttonDisabled, $result) + { + $form = $this->getFormBuilder('form') + ->setDisabled($parentDisabled) + ->getForm(); + + $button = $this->getButtonBuilder('button') + ->setDisabled($buttonDisabled) + ->getForm(); + + $button->setParent($form); + + $this->assertSame($result, $button->isDisabled()); + } + + public function getDisabledStates() + { + return array( + // parent, button, result + array(true, true, true), + array(true, false, true), + array(false, true, true), + array(false, false, false), + ); + } + + private function getButtonBuilder($name) + { + return new ButtonBuilder($name); + } + + private function getFormBuilder($name) + { + return new FormBuilder($name, null, $this->dispatcher, $this->factory); + } +} diff --git a/Tests/SimpleFormTest.php b/Tests/SimpleFormTest.php index bedad6761f..d6d3238b42 100644 --- a/Tests/SimpleFormTest.php +++ b/Tests/SimpleFormTest.php @@ -170,34 +170,28 @@ public function testNotRequired() $this->assertFalse($child->isRequired()); } - public function testAlwaysDisabledIfParentDisabled() - { - $parent = $this->getBuilder()->setDisabled(true)->getForm(); - $child = $this->getBuilder()->setDisabled(false)->getForm(); - - $child->setParent($parent); - - $this->assertTrue($child->isDisabled()); - } - - public function testDisabled() + /** + * @dataProvider getDisabledStates + */ + public function testAlwaysDisabledIfParentDisabled($parentDisabled, $disabled, $result) { - $parent = $this->getBuilder()->setDisabled(false)->getForm(); - $child = $this->getBuilder()->setDisabled(true)->getForm(); + $parent = $this->getBuilder()->setDisabled($parentDisabled)->getForm(); + $child = $this->getBuilder()->setDisabled($disabled)->getForm(); $child->setParent($parent); - $this->assertTrue($child->isDisabled()); + $this->assertSame($result, $child->isDisabled()); } - public function testNotDisabled() + public function getDisabledStates() { - $parent = $this->getBuilder()->setDisabled(false)->getForm(); - $child = $this->getBuilder()->setDisabled(false)->getForm(); - - $child->setParent($parent); - - $this->assertFalse($child->isDisabled()); + return array( + // parent, button, result + array(true, true, true), + array(true, false, true), + array(false, true, true), + array(false, false, false), + ); } public function testGetRootReturnsRootOfParent() From 7dae46c4ee8e662741350ef62a121f5ea8b94e3b Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Tue, 8 Apr 2014 11:43:59 +0200 Subject: [PATCH 284/447] [Form] Improved test coverage of UrlType --- Tests/Extension/Core/Type/UrlTypeTest.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Tests/Extension/Core/Type/UrlTypeTest.php b/Tests/Extension/Core/Type/UrlTypeTest.php index 254b2a8e4e..718d4cd650 100644 --- a/Tests/Extension/Core/Type/UrlTypeTest.php +++ b/Tests/Extension/Core/Type/UrlTypeTest.php @@ -47,6 +47,18 @@ public function testSubmitAddsNoDefaultProtocolIfEmpty() $this->assertSame('', $form->getViewData()); } + public function testSubmitAddsNoDefaultProtocolIfNull() + { + $form = $this->factory->create('url', null, array( + 'default_protocol' => 'http', + )); + + $form->submit(null); + + $this->assertNull($form->getData()); + $this->assertSame('', $form->getViewData()); + } + public function testSubmitAddsNoDefaultProtocolIfSetToNull() { $form = $this->factory->create('url', null, array( From 8c655725e60ed2117a3f75f08f9e2c91a85e11dc Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 12 Apr 2014 19:44:00 +0200 Subject: [PATCH 285/447] made types consistent with those defined in Hack --- .../Core/DataTransformer/DateTimeToArrayTransformer.php | 2 +- FormConfigBuilder.php | 8 ++++---- Tests/Extension/Core/Type/MoneyTypeTest.php | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php b/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php index e746d00ed5..3b7678ddef 100644 --- a/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php @@ -45,7 +45,7 @@ public function __construct($inputTimezone = null, $outputTimezone = null, array } $this->fields = $fields; - $this->pad = (Boolean) $pad; + $this->pad = (bool) $pad; } /** diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index 1015da4f51..6cc686d53e 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -603,7 +603,7 @@ public function setDisabled($disabled) throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } - $this->disabled = (Boolean) $disabled; + $this->disabled = (bool) $disabled; return $this; } @@ -631,7 +631,7 @@ public function setErrorBubbling($errorBubbling) throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } - $this->errorBubbling = null === $errorBubbling ? null : (Boolean) $errorBubbling; + $this->errorBubbling = null === $errorBubbling ? null : (bool) $errorBubbling; return $this; } @@ -645,7 +645,7 @@ public function setRequired($required) throw new BadMethodCallException('FormConfigBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } - $this->required = (Boolean) $required; + $this->required = (bool) $required; return $this; } @@ -855,7 +855,7 @@ public function setRequestHandler(RequestHandlerInterface $requestHandler) */ public function setAutoInitialize($initialize) { - $this->autoInitialize = (Boolean) $initialize; + $this->autoInitialize = (bool) $initialize; return $this; } diff --git a/Tests/Extension/Core/Type/MoneyTypeTest.php b/Tests/Extension/Core/Type/MoneyTypeTest.php index 97fc37fa3d..e42c89c5a8 100644 --- a/Tests/Extension/Core/Type/MoneyTypeTest.php +++ b/Tests/Extension/Core/Type/MoneyTypeTest.php @@ -40,7 +40,7 @@ public function testMoneyPatternWorksForYen() $form = $this->factory->create('money', null, array('currency' => 'JPY')); $view = $form->createView(); - $this->assertTrue((Boolean) strstr($view->vars['money_pattern'], '¥')); + $this->assertTrue((bool) strstr($view->vars['money_pattern'], '¥')); } // https://github.com/symfony/symfony/issues/5458 From 130d877d080a99a2758b54c30beb8bc1c32d64a1 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 12 Apr 2014 19:54:57 +0200 Subject: [PATCH 286/447] made phpdoc types consistent with those defined in Hack --- AbstractRendererEngine.php | 2 +- Button.php | 2 +- ButtonBuilder.php | 26 +++++++++---------- .../BooleanToStringTransformer.php | 2 +- .../ChoiceToBooleanArrayTransformer.php | 2 +- .../DateTimeToArrayTransformer.php | 2 +- .../DateTimeToLocalizedStringTransformer.php | 6 ++--- .../DateTimeToStringTransformer.php | 2 +- .../NumberToLocalizedStringTransformer.php | 2 +- .../PercentToLocalizedStringTransformer.php | 2 +- .../EventListener/FixRadioInputListener.php | 2 +- .../EventListener/MergeCollectionListener.php | 4 +-- .../ViolationMapperInterface.php | 2 +- .../ViolationMapper/ViolationPath.php | 2 +- Form.php | 2 +- FormConfigBuilder.php | 2 +- FormConfigBuilderInterface.php | 24 ++++++++--------- FormError.php | 2 +- FormInterface.php | 2 +- FormRendererEngineInterface.php | 4 +-- Guess/Guess.php | 2 +- Guess/TypeGuess.php | 2 +- Guess/ValueGuess.php | 2 +- SubmitButton.php | 2 +- Test/FormPerformanceTestCase.php | 2 +- .../DataMapper/PropertyPathMapperTest.php | 2 +- 26 files changed, 53 insertions(+), 53 deletions(-) diff --git a/AbstractRendererEngine.php b/AbstractRendererEngine.php index 347be10d29..76506b73a0 100644 --- a/AbstractRendererEngine.php +++ b/AbstractRendererEngine.php @@ -146,7 +146,7 @@ abstract protected function loadResourceForBlockName($cacheKey, FormView $view, * themes. * @param array $blockNameHierarchy The block hierarchy, with the most * specific block name at the end. - * @param integer $hierarchyLevel The level in the block hierarchy that + * @param int $hierarchyLevel The level in the block hierarchy that * should be loaded. * * @return Boolean True if the resource could be loaded, false otherwise. diff --git a/Button.php b/Button.php index 2d7ccd1569..fe0ab1ad65 100644 --- a/Button.php +++ b/Button.php @@ -374,7 +374,7 @@ public function handleRequest($request = null) * Submits data to the button. * * @param null|string $submittedData The data. - * @param Boolean $clearMissing Not used. + * @param bool $clearMissing Not used. * * @return Button The button instance * diff --git a/ButtonBuilder.php b/ButtonBuilder.php index f9b0546b1f..352ca88ea5 100644 --- a/ButtonBuilder.php +++ b/ButtonBuilder.php @@ -169,7 +169,7 @@ public function getForm() * * @param string $eventName * @param callable $listener - * @param integer $priority + * @param int $priority * * @throws BadMethodCallException */ @@ -198,7 +198,7 @@ public function addEventSubscriber(EventSubscriberInterface $subscriber) * This method should not be invoked. * * @param DataTransformerInterface $viewTransformer - * @param Boolean $forcePrepend + * @param bool $forcePrepend * * @throws BadMethodCallException */ @@ -225,7 +225,7 @@ public function resetViewTransformers() * This method should not be invoked. * * @param DataTransformerInterface $modelTransformer - * @param Boolean $forceAppend + * @param bool $forceAppend * * @throws BadMethodCallException */ @@ -283,7 +283,7 @@ public function setDataMapper(DataMapperInterface $dataMapper = null) /** * Set whether the button is disabled. * - * @param Boolean $disabled Whether the button is disabled + * @param bool $disabled Whether the button is disabled * * @return ButtonBuilder The button builder. */ @@ -313,7 +313,7 @@ public function setEmptyData($emptyData) * * This method should not be invoked. * - * @param Boolean $errorBubbling + * @param bool $errorBubbling * * @throws BadMethodCallException */ @@ -327,7 +327,7 @@ public function setErrorBubbling($errorBubbling) * * This method should not be invoked. * - * @param Boolean $required + * @param bool $required * * @throws BadMethodCallException */ @@ -355,7 +355,7 @@ public function setPropertyPath($propertyPath) * * This method should not be invoked. * - * @param Boolean $mapped + * @param bool $mapped * * @throws BadMethodCallException */ @@ -369,7 +369,7 @@ public function setMapped($mapped) * * This method should not be invoked. * - * @param Boolean $byReference + * @param bool $byReference * * @throws BadMethodCallException */ @@ -383,7 +383,7 @@ public function setByReference($byReference) * * This method should not be invoked. * - * @param Boolean $virtual + * @param bool $virtual * * @throws BadMethodCallException */ @@ -397,7 +397,7 @@ public function setVirtual($virtual) * * This method should not be invoked. * - * @param Boolean $compound + * @param bool $compound * * @throws BadMethodCallException */ @@ -439,7 +439,7 @@ public function setData($data) * * This method should not be invoked. * - * @param Boolean $locked + * @param bool $locked * * @throws BadMethodCallException */ @@ -503,7 +503,7 @@ public function setRequestHandler(RequestHandlerInterface $requestHandler) /** * Unsupported method. * - * @param Boolean $initialize + * @param bool $initialize * * @throws BadMethodCallException */ @@ -519,7 +519,7 @@ public function setAutoInitialize($initialize) /** * Unsupported method. * - * @param Boolean $inheritData + * @param bool $inheritData * * @throws BadMethodCallException */ diff --git a/Extension/Core/DataTransformer/BooleanToStringTransformer.php b/Extension/Core/DataTransformer/BooleanToStringTransformer.php index 4f6b12275b..cf0e9c1102 100644 --- a/Extension/Core/DataTransformer/BooleanToStringTransformer.php +++ b/Extension/Core/DataTransformer/BooleanToStringTransformer.php @@ -41,7 +41,7 @@ public function __construct($trueValue) /** * Transforms a Boolean into a string. * - * @param Boolean $value Boolean value. + * @param bool $value Boolean value. * * @return string String value. * diff --git a/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php b/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php index b521c95572..1ca1da41c0 100644 --- a/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php +++ b/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php @@ -28,7 +28,7 @@ class ChoiceToBooleanArrayTransformer implements DataTransformerInterface * Constructor. * * @param ChoiceListInterface $choiceList - * @param Boolean $placeholderPresent + * @param bool $placeholderPresent */ public function __construct(ChoiceListInterface $choiceList, $placeholderPresent) { diff --git a/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php b/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php index 3b7678ddef..922d3c5bd8 100644 --- a/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php @@ -32,7 +32,7 @@ class DateTimeToArrayTransformer extends BaseDateTimeTransformer * @param string $inputTimezone The input timezone * @param string $outputTimezone The output timezone * @param array $fields The date fields - * @param Boolean $pad Whether to use padding + * @param bool $pad Whether to use padding * * @throws UnexpectedTypeException if a timezone is not a string */ diff --git a/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php index d755e48547..f04b867599 100644 --- a/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php @@ -34,9 +34,9 @@ class DateTimeToLocalizedStringTransformer extends BaseDateTimeTransformer * * @param string $inputTimezone The name of the input timezone * @param string $outputTimezone The name of the output timezone - * @param integer $dateFormat The date format - * @param integer $timeFormat The time format - * @param integer $calendar One of the \IntlDateFormatter calendar constants + * @param int $dateFormat The date format + * @param int $timeFormat The time format + * @param int $calendar One of the \IntlDateFormatter calendar constants * @param string $pattern A pattern to pass to \IntlDateFormatter * * @throws UnexpectedTypeException If a format is not supported or if a timezone is not a string diff --git a/Extension/Core/DataTransformer/DateTimeToStringTransformer.php b/Extension/Core/DataTransformer/DateTimeToStringTransformer.php index 131f45cb2f..32068b06c5 100644 --- a/Extension/Core/DataTransformer/DateTimeToStringTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToStringTransformer.php @@ -56,7 +56,7 @@ class DateTimeToStringTransformer extends BaseDateTimeTransformer * @param string $inputTimezone The name of the input timezone * @param string $outputTimezone The name of the output timezone * @param string $format The date format - * @param Boolean $parseUsingPipe Whether to parse by appending a pipe "|" to the parse format + * @param bool $parseUsingPipe Whether to parse by appending a pipe "|" to the parse format * * @throws UnexpectedTypeException if a timezone is not a string */ diff --git a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php index b0c59b3ede..199c996f1b 100644 --- a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php @@ -55,7 +55,7 @@ public function __construct($precision = null, $grouping = null, $roundingMode = /** * Transforms a number type into localized number. * - * @param integer|float $value Number value. + * @param int |float $value Number value. * * @return string Localized value. * diff --git a/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php index e099d436bf..ff43697379 100644 --- a/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php @@ -40,7 +40,7 @@ class PercentToLocalizedStringTransformer implements DataTransformerInterface * * @see self::$types for a list of supported types * - * @param integer $precision The precision + * @param int $precision The precision * @param string $type One of the supported types * * @throws UnexpectedTypeException if the given value of type is unknown diff --git a/Extension/Core/EventListener/FixRadioInputListener.php b/Extension/Core/EventListener/FixRadioInputListener.php index 925585db40..a3e27d57e3 100644 --- a/Extension/Core/EventListener/FixRadioInputListener.php +++ b/Extension/Core/EventListener/FixRadioInputListener.php @@ -32,7 +32,7 @@ class FixRadioInputListener implements EventSubscriberInterface * Constructor. * * @param ChoiceListInterface $choiceList - * @param Boolean $placeholderPresent + * @param bool $placeholderPresent */ public function __construct(ChoiceListInterface $choiceList, $placeholderPresent) { diff --git a/Extension/Core/EventListener/MergeCollectionListener.php b/Extension/Core/EventListener/MergeCollectionListener.php index 4d0bdfaae0..51ca781a36 100644 --- a/Extension/Core/EventListener/MergeCollectionListener.php +++ b/Extension/Core/EventListener/MergeCollectionListener.php @@ -36,9 +36,9 @@ class MergeCollectionListener implements EventSubscriberInterface /** * Creates a new listener. * - * @param Boolean $allowAdd Whether values might be added to the + * @param bool $allowAdd Whether values might be added to the * collection. - * @param Boolean $allowDelete Whether values might be removed from the + * @param bool $allowDelete Whether values might be removed from the * collection. */ public function __construct($allowAdd = false, $allowDelete = false) diff --git a/Extension/Validator/ViolationMapper/ViolationMapperInterface.php b/Extension/Validator/ViolationMapper/ViolationMapperInterface.php index eb8907f1af..e53046caf5 100644 --- a/Extension/Validator/ViolationMapper/ViolationMapperInterface.php +++ b/Extension/Validator/ViolationMapper/ViolationMapperInterface.php @@ -26,7 +26,7 @@ interface ViolationMapperInterface * @param ConstraintViolation $violation The violation to map. * @param FormInterface $form The root form of the tree * to map it to. - * @param Boolean $allowNonSynchronized Whether to allow + * @param bool $allowNonSynchronized Whether to allow * mapping to non-synchronized forms. */ public function mapViolation(ConstraintViolation $violation, FormInterface $form, $allowNonSynchronized = false); diff --git a/Extension/Validator/ViolationMapper/ViolationPath.php b/Extension/Validator/ViolationMapper/ViolationPath.php index 06d091954e..12a4241077 100644 --- a/Extension/Validator/ViolationMapper/ViolationPath.php +++ b/Extension/Validator/ViolationMapper/ViolationPath.php @@ -198,7 +198,7 @@ public function isIndex($index) * In this example, "address" and "office" map to forms, while * "street does not. * - * @param integer $index The element index. + * @param int $index The element index. * * @return Boolean Whether the element maps to a form. * diff --git a/Form.php b/Form.php index 5d16f9ca02..952c67f9e7 100644 --- a/Form.php +++ b/Form.php @@ -784,7 +784,7 @@ public function getErrors() * * This method should only be used to help debug a form. * - * @param integer $level The indentation level (used internally) + * @param int $level The indentation level (used internally) * * @return string A string representation of all errors */ diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index 6cc686d53e..d73c403d98 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -713,7 +713,7 @@ public function setInheritData($inheritData) /** * Alias of {@link setInheritData()}. * - * @param Boolean $inheritData Whether the form should inherit its parent's data. + * @param bool $inheritData Whether the form should inherit its parent's data. * * @return FormConfigBuilder The configuration object. * diff --git a/FormConfigBuilderInterface.php b/FormConfigBuilderInterface.php index 62d12c09cb..276a2fa446 100644 --- a/FormConfigBuilderInterface.php +++ b/FormConfigBuilderInterface.php @@ -23,7 +23,7 @@ interface FormConfigBuilderInterface extends FormConfigInterface * * @param string $eventName The name of the event to listen to. * @param callable $listener The listener to execute. - * @param integer $priority The priority of the listener. Listeners + * @param int $priority The priority of the listener. Listeners * with a higher priority are called before * listeners with a lower priority. * @@ -49,7 +49,7 @@ public function addEventSubscriber(EventSubscriberInterface $subscriber); * view to the normalized format. * * @param DataTransformerInterface $viewTransformer - * @param Boolean $forcePrepend if set to true, prepend instead of appending + * @param bool $forcePrepend if set to true, prepend instead of appending * * @return self The configuration object. */ @@ -71,7 +71,7 @@ public function resetViewTransformers(); * normalized to the model format. * * @param DataTransformerInterface $modelTransformer - * @param Boolean $forceAppend if set to true, append instead of prepending + * @param bool $forceAppend if set to true, append instead of prepending * * @return self The configuration object. */ @@ -115,7 +115,7 @@ public function setDataMapper(DataMapperInterface $dataMapper = null); /** * Set whether the form is disabled. * - * @param Boolean $disabled Whether the form is disabled + * @param bool $disabled Whether the form is disabled * * @return self The configuration object. */ @@ -133,7 +133,7 @@ public function setEmptyData($emptyData); /** * Sets whether errors bubble up to the parent. * - * @param Boolean $errorBubbling + * @param bool $errorBubbling * * @return self The configuration object. */ @@ -142,7 +142,7 @@ public function setErrorBubbling($errorBubbling); /** * Sets whether this field is required to be filled out when submitted. * - * @param Boolean $required + * @param bool $required * * @return self The configuration object. */ @@ -163,7 +163,7 @@ public function setPropertyPath($propertyPath); * Sets whether the form should be mapped to an element of its * parent's data. * - * @param Boolean $mapped Whether the form should be mapped. + * @param bool $mapped Whether the form should be mapped. * * @return self The configuration object. */ @@ -172,7 +172,7 @@ public function setMapped($mapped); /** * Sets whether the form's data should be modified by reference. * - * @param Boolean $byReference Whether the data should be + * @param bool $byReference Whether the data should be * modified by reference. * * @return self The configuration object. @@ -182,7 +182,7 @@ public function setByReference($byReference); /** * Sets whether the form should read and write the data of its parent. * - * @param Boolean $inheritData Whether the form should inherit its parent's data. + * @param bool $inheritData Whether the form should inherit its parent's data. * * @return self The configuration object. */ @@ -191,7 +191,7 @@ public function setInheritData($inheritData); /** * Sets whether the form should be compound. * - * @param Boolean $compound Whether the form should be compound. + * @param bool $compound Whether the form should be compound. * * @return self The configuration object. * @@ -224,7 +224,7 @@ public function setData($data); * this configuration. The data can only be modified then by * submitting the form. * - * @param Boolean $locked Whether to lock the default data. + * @param bool $locked Whether to lock the default data. * * @return self The configuration object. */ @@ -269,7 +269,7 @@ public function setRequestHandler(RequestHandlerInterface $requestHandler); * * Should be set to true only for root forms. * - * @param Boolean $initialize True to initialize the form automatically, + * @param bool $initialize True to initialize the form automatically, * false to suppress automatic initialization. * In the second case, you need to call * {@link FormInterface::initialize()} manually. diff --git a/FormError.php b/FormError.php index 343165ca46..d9b23aa368 100644 --- a/FormError.php +++ b/FormError.php @@ -51,7 +51,7 @@ class FormError * @param string|null $messageTemplate The template for the error message * @param array $messageParameters The parameters that should be * substituted in the message template. - * @param integer|null $messagePluralization The value for error message pluralization + * @param int |null $messagePluralization The value for error message pluralization * * @see \Symfony\Component\Translation\Translator */ diff --git a/FormInterface.php b/FormInterface.php index 7a77e0f3f4..5ffe76d1ce 100644 --- a/FormInterface.php +++ b/FormInterface.php @@ -253,7 +253,7 @@ public function handleRequest($request = null); * Submits data to the form, transforms and validates it. * * @param null|string|array $submittedData The submitted data. - * @param Boolean $clearMissing Whether to set fields to NULL + * @param bool $clearMissing Whether to set fields to NULL * when they are missing in the * submitted data. * diff --git a/FormRendererEngineInterface.php b/FormRendererEngineInterface.php index e06824ec95..ba92e14e37 100644 --- a/FormRendererEngineInterface.php +++ b/FormRendererEngineInterface.php @@ -78,7 +78,7 @@ public function getResourceForBlockName(FormView $view, $blockName); * its parent etc. * @param array $blockNameHierarchy The block name hierarchy, with * the root block at the beginning. - * @param integer $hierarchyLevel The level in the hierarchy at + * @param int $hierarchyLevel The level in the hierarchy at * which to start looking. Level 0 * indicates the root block, i.e. * the first element of @@ -122,7 +122,7 @@ public function getResourceForBlockNameHierarchy(FormView $view, array $blockNam * its parent etc. * @param array $blockNameHierarchy The block name hierarchy, with * the root block at the beginning. - * @param integer $hierarchyLevel The level in the hierarchy at + * @param int $hierarchyLevel The level in the hierarchy at * which to start looking. Level 0 * indicates the root block, i.e. * the first element of diff --git a/Guess/Guess.php b/Guess/Guess.php index 6616ff5092..0deb838d80 100644 --- a/Guess/Guess.php +++ b/Guess/Guess.php @@ -86,7 +86,7 @@ public static function getBestGuess(array $guesses) /** * Constructor. * - * @param integer $confidence The confidence + * @param int $confidence The confidence * * @throws InvalidArgumentException if the given value of confidence is unknown */ diff --git a/Guess/TypeGuess.php b/Guess/TypeGuess.php index 3241e603df..7136b7874b 100644 --- a/Guess/TypeGuess.php +++ b/Guess/TypeGuess.php @@ -37,7 +37,7 @@ class TypeGuess extends Guess * @param string $type The guessed field type * @param array $options The options for creating instances of the * guessed class - * @param integer $confidence The confidence that the guessed class name + * @param int $confidence The confidence that the guessed class name * is correct */ public function __construct($type, array $options, $confidence) diff --git a/Guess/ValueGuess.php b/Guess/ValueGuess.php index 2e3333ba5b..bf450d6002 100644 --- a/Guess/ValueGuess.php +++ b/Guess/ValueGuess.php @@ -28,7 +28,7 @@ class ValueGuess extends Guess * Constructor * * @param string $value The guessed value - * @param integer $confidence The confidence that the guessed class name + * @param int $confidence The confidence that the guessed class name * is correct */ public function __construct($value, $confidence) diff --git a/SubmitButton.php b/SubmitButton.php index 47d4be0e28..1ff65bcbe1 100644 --- a/SubmitButton.php +++ b/SubmitButton.php @@ -35,7 +35,7 @@ public function isClicked() * Submits data to the button. * * @param null|string $submittedData The data. - * @param Boolean $clearMissing Not used. + * @param bool $clearMissing Not used. * * @return SubmitButton The button instance * diff --git a/Test/FormPerformanceTestCase.php b/Test/FormPerformanceTestCase.php index b57aa9da8d..435bdf1b2d 100644 --- a/Test/FormPerformanceTestCase.php +++ b/Test/FormPerformanceTestCase.php @@ -47,7 +47,7 @@ protected function runTest() } /** - * @param integer $maxRunningTime + * @param int $maxRunningTime * @throws \InvalidArgumentException */ public function setMaxRunningTime($maxRunningTime) diff --git a/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php b/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php index faa10e2a7a..06a2cb088f 100644 --- a/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php +++ b/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php @@ -61,7 +61,7 @@ private function getPropertyPath($path) /** * @param FormConfigInterface $config - * @param Boolean $synchronized + * @param bool $synchronized * @return \PHPUnit_Framework_MockObject_MockObject */ private function getForm(FormConfigInterface $config, $synchronized = true, $submitted = true) From db699a470530ee1b451d9d3ee3177c6e2c1ce6a5 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 16 Apr 2014 08:51:57 +0200 Subject: [PATCH 287/447] fixed types in phpdocs --- ButtonBuilder.php | 2 +- .../DataTransformer/NumberToLocalizedStringTransformer.php | 2 +- FormBuilderInterface.php | 2 +- FormConfigBuilder.php | 4 ++-- FormError.php | 2 +- FormFactoryInterface.php | 4 ++-- FormInterface.php | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ButtonBuilder.php b/ButtonBuilder.php index 352ca88ea5..b89e01b02f 100644 --- a/ButtonBuilder.php +++ b/ButtonBuilder.php @@ -75,7 +75,7 @@ public function __construct($name, array $options = array()) * * This method should not be invoked. * - * @param string|integer|FormBuilderInterface $child + * @param string|int|FormBuilderInterface $child * @param string|FormTypeInterface $type * @param array $options * diff --git a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php index 199c996f1b..2270240d20 100644 --- a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php @@ -55,7 +55,7 @@ public function __construct($precision = null, $grouping = null, $roundingMode = /** * Transforms a number type into localized number. * - * @param int |float $value Number value. + * @param int|float $value Number value. * * @return string Localized value. * diff --git a/FormBuilderInterface.php b/FormBuilderInterface.php index 1dc4a64e7b..c0eb8c32c7 100644 --- a/FormBuilderInterface.php +++ b/FormBuilderInterface.php @@ -23,7 +23,7 @@ interface FormBuilderInterface extends \Traversable, \Countable, FormConfigBuild * If you add a nested group, this group should also be represented in the * object hierarchy. * - * @param string|integer|FormBuilderInterface $child + * @param string|int|FormBuilderInterface $child * @param string|FormTypeInterface $type * @param array $options * diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index d73c403d98..99a9df2add 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -180,7 +180,7 @@ class FormConfigBuilder implements FormConfigBuilderInterface /** * Creates an empty form configuration. * - * @param string|integer $name The form name + * @param string|int $name The form name * @param string $dataClass The class of the form's data * @param EventDispatcherInterface $dispatcher The event dispatcher * @param array $options The form options @@ -879,7 +879,7 @@ public function getFormConfig() /** * Validates whether the given variable is a valid form name. * - * @param string|integer $name The tested form name. + * @param string|int $name The tested form name. * * @throws UnexpectedTypeException If the name is not a string or an integer. * @throws InvalidArgumentException If the name contains invalid characters. diff --git a/FormError.php b/FormError.php index d9b23aa368..871db9c0dd 100644 --- a/FormError.php +++ b/FormError.php @@ -51,7 +51,7 @@ class FormError * @param string|null $messageTemplate The template for the error message * @param array $messageParameters The parameters that should be * substituted in the message template. - * @param int |null $messagePluralization The value for error message pluralization + * @param int|null $messagePluralization The value for error message pluralization * * @see \Symfony\Component\Translation\Translator */ diff --git a/FormFactoryInterface.php b/FormFactoryInterface.php index 31c46b55d7..220b470496 100644 --- a/FormFactoryInterface.php +++ b/FormFactoryInterface.php @@ -36,7 +36,7 @@ public function create($type = 'form', $data = null, array $options = array()); * * @see createNamedBuilder() * - * @param string|integer $name The name of the form + * @param string|int $name The name of the form * @param string|FormTypeInterface $type The type of the form * @param mixed $data The initial data * @param array $options The options @@ -79,7 +79,7 @@ public function createBuilder($type = 'form', $data = null, array $options = arr /** * Returns a form builder. * - * @param string|integer $name The name of the form + * @param string|int $name The name of the form * @param string|FormTypeInterface $type The type of the form * @param mixed $data The initial data * @param array $options The options diff --git a/FormInterface.php b/FormInterface.php index 5ffe76d1ce..f5a575e69f 100644 --- a/FormInterface.php +++ b/FormInterface.php @@ -41,7 +41,7 @@ public function getParent(); /** * Adds or replaces a child to the form. * - * @param FormInterface|string|integer $child The FormInterface instance or the name of the child. + * @param FormInterface|string|int $child The FormInterface instance or the name of the child. * @param string|null $type The child's type, if a name was passed. * @param array $options The child's options, if a name was passed. * From c4921d43732ffe62c1d16c0a226cefe0ddc0af8f Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 15 Apr 2014 07:57:34 +0200 Subject: [PATCH 288/447] made {@inheritdoc} annotations consistent across the board --- .../Core/DataTransformer/DateTimeToRfc3339Transformer.php | 4 ++-- .../IntegerToLocalizedStringTransformer.php | 2 +- Extension/Csrf/CsrfExtension.php | 2 +- Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php | 4 ++-- Extension/Csrf/Type/FormTypeCsrfExtension.php | 4 ++-- Extension/Validator/ValidatorTypeGuesser.php | 8 ++++---- Form.php | 2 +- FormTypeGuesserChain.php | 8 ++++---- ReversedTransformer.php | 4 ++-- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php b/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php index 0723704ae1..6d0b284708 100644 --- a/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php +++ b/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php @@ -19,7 +19,7 @@ class DateTimeToRfc3339Transformer extends BaseDateTimeTransformer { /** - * {@inheritDoc} + * {@inheritdoc} */ public function transform($dateTime) { @@ -40,7 +40,7 @@ public function transform($dateTime) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function reverseTransform($rfc3339) { diff --git a/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php index 6bb48a9a03..a3f2af42b8 100644 --- a/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php @@ -22,7 +22,7 @@ class IntegerToLocalizedStringTransformer extends NumberToLocalizedStringTransformer { /** - * {@inheritDoc} + * {@inheritdoc} */ public function reverseTransform($value) { diff --git a/Extension/Csrf/CsrfExtension.php b/Extension/Csrf/CsrfExtension.php index 7653e97ee4..d90f3734b9 100644 --- a/Extension/Csrf/CsrfExtension.php +++ b/Extension/Csrf/CsrfExtension.php @@ -52,7 +52,7 @@ public function __construct(CsrfProviderInterface $csrfProvider, TranslatorInter } /** - * {@inheritDoc} + * {@inheritdoc} */ protected function loadTypeExtensions() { diff --git a/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php b/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php index 5354886cba..f0a74b4962 100644 --- a/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php +++ b/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php @@ -41,7 +41,7 @@ public function __construct($secret) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function generateCsrfToken($intention) { @@ -49,7 +49,7 @@ public function generateCsrfToken($intention) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function isCsrfTokenValid($intention, $token) { diff --git a/Extension/Csrf/Type/FormTypeCsrfExtension.php b/Extension/Csrf/Type/FormTypeCsrfExtension.php index 49d97bb395..28c752a115 100644 --- a/Extension/Csrf/Type/FormTypeCsrfExtension.php +++ b/Extension/Csrf/Type/FormTypeCsrfExtension.php @@ -107,7 +107,7 @@ public function finishView(FormView $view, FormInterface $form, array $options) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function setDefaultOptions(OptionsResolverInterface $resolver) { @@ -121,7 +121,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function getExtendedType() { diff --git a/Extension/Validator/ValidatorTypeGuesser.php b/Extension/Validator/ValidatorTypeGuesser.php index 5cd02daa91..333fe3cd40 100644 --- a/Extension/Validator/ValidatorTypeGuesser.php +++ b/Extension/Validator/ValidatorTypeGuesser.php @@ -28,7 +28,7 @@ public function __construct(MetadataFactoryInterface $metadataFactory) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function guessType($class, $property) { @@ -40,7 +40,7 @@ public function guessType($class, $property) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function guessRequired($class, $property) { @@ -54,7 +54,7 @@ public function guessRequired($class, $property) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function guessMaxLength($class, $property) { @@ -66,7 +66,7 @@ public function guessMaxLength($class, $property) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function guessPattern($class, $property) { diff --git a/Form.php b/Form.php index 952c67f9e7..990d4cb125 100644 --- a/Form.php +++ b/Form.php @@ -238,7 +238,7 @@ public function isRequired() } /** - * {@inheritDoc} + * {@inheritdoc} */ public function isDisabled() { diff --git a/FormTypeGuesserChain.php b/FormTypeGuesserChain.php index 6e858ddffe..27db889026 100644 --- a/FormTypeGuesserChain.php +++ b/FormTypeGuesserChain.php @@ -41,7 +41,7 @@ public function __construct(array $guessers) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function guessType($class, $property) { @@ -51,7 +51,7 @@ public function guessType($class, $property) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function guessRequired($class, $property) { @@ -61,7 +61,7 @@ public function guessRequired($class, $property) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function guessMaxLength($class, $property) { @@ -71,7 +71,7 @@ public function guessMaxLength($class, $property) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function guessPattern($class, $property) { diff --git a/ReversedTransformer.php b/ReversedTransformer.php index 7069705feb..4fd2456462 100644 --- a/ReversedTransformer.php +++ b/ReversedTransformer.php @@ -38,7 +38,7 @@ public function __construct(DataTransformerInterface $reversedTransformer) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function transform($value) { @@ -46,7 +46,7 @@ public function transform($value) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function reverseTransform($value) { From cc1008647ca5a62722551fee0d2addfee6c5c869 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 16 Apr 2014 09:15:58 +0200 Subject: [PATCH 289/447] unified return null usages --- AbstractExtension.php | 1 - Button.php | 4 ---- ButtonBuilder.php | 10 ---------- .../Core/DataTransformer/ArrayToPartsTransformer.php | 2 +- .../DataTransformer/BooleanToStringTransformer.php | 2 +- .../ChoiceToBooleanArrayTransformer.php | 4 +--- .../Core/DataTransformer/ChoiceToValueTransformer.php | 2 +- .../DataTransformer/DateTimeToArrayTransformer.php | 4 ++-- .../DateTimeToLocalizedStringTransformer.php | 2 +- .../DataTransformer/DateTimeToRfc3339Transformer.php | 2 +- .../DataTransformer/DateTimeToStringTransformer.php | 2 +- .../DataTransformer/DateTimeToTimestampTransformer.php | 4 ++-- .../IntegerToLocalizedStringTransformer.php | 2 +- .../NumberToLocalizedStringTransformer.php | 2 +- .../PercentToLocalizedStringTransformer.php | 2 +- .../DataTransformer/ValueToDuplicatesTransformer.php | 2 +- Extension/Core/Type/ButtonType.php | 1 - Extension/Core/Type/ChoiceType.php | 4 ++-- Extension/Core/Type/FormType.php | 1 - Extension/Validator/Type/BaseValidatorExtension.php | 2 +- Extension/Validator/Util/ServerParams.php | 2 +- Extension/Validator/ValidatorTypeGuesser.php | 8 -------- Extension/Validator/ViolationMapper/MappingRule.php | 2 -- .../Validator/ViolationMapper/ViolationMapper.php | 4 +--- Extension/Validator/ViolationMapper/ViolationPath.php | 2 +- Form.php | 4 +--- NativeRequestHandler.php | 2 +- .../Validator/Type/BaseValidatorExtensionTest.php | 2 +- Tests/Fixtures/FooType.php | 1 - 29 files changed, 24 insertions(+), 58 deletions(-) diff --git a/AbstractExtension.php b/AbstractExtension.php index 4db77b9bb5..dcc41ff484 100644 --- a/AbstractExtension.php +++ b/AbstractExtension.php @@ -136,7 +136,6 @@ protected function loadTypeExtensions() */ protected function loadTypeGuesser() { - return null; } /** diff --git a/Button.php b/Button.php index fe0ab1ad65..e39f121a4a 100644 --- a/Button.php +++ b/Button.php @@ -211,7 +211,6 @@ public function setData($modelData) */ public function getData() { - return null; } /** @@ -221,7 +220,6 @@ public function getData() */ public function getNormData() { - return null; } /** @@ -231,7 +229,6 @@ public function getNormData() */ public function getViewData() { - return null; } /** @@ -281,7 +278,6 @@ public function getName() */ public function getPropertyPath() { - return null; } /** diff --git a/ButtonBuilder.php b/ButtonBuilder.php index b89e01b02f..b4305fb68c 100644 --- a/ButtonBuilder.php +++ b/ButtonBuilder.php @@ -549,7 +549,6 @@ public function getFormConfig() */ public function getEventDispatcher() { - return null; } /** @@ -567,7 +566,6 @@ public function getName() */ public function getPropertyPath() { - return null; } /** @@ -647,7 +645,6 @@ public function getModelTransformers() */ public function getDataMapper() { - return null; } /** @@ -687,7 +684,6 @@ public function getErrorBubbling() */ public function getEmptyData() { - return null; } /** @@ -732,7 +728,6 @@ public function getAttribute($name, $default = null) */ public function getData() { - return null; } /** @@ -742,7 +737,6 @@ public function getData() */ public function getDataClass() { - return null; } /** @@ -762,7 +756,6 @@ public function getDataLocked() */ public function getFormFactory() { - return null; } /** @@ -772,7 +765,6 @@ public function getFormFactory() */ public function getAction() { - return null; } /** @@ -782,7 +774,6 @@ public function getAction() */ public function getMethod() { - return null; } /** @@ -792,7 +783,6 @@ public function getMethod() */ public function getRequestHandler() { - return null; } /** diff --git a/Extension/Core/DataTransformer/ArrayToPartsTransformer.php b/Extension/Core/DataTransformer/ArrayToPartsTransformer.php index fc080f25c1..6cc3a836e5 100644 --- a/Extension/Core/DataTransformer/ArrayToPartsTransformer.php +++ b/Extension/Core/DataTransformer/ArrayToPartsTransformer.php @@ -73,7 +73,7 @@ public function reverseTransform($array) if (count($emptyKeys) > 0) { if (count($emptyKeys) === count($this->partMapping)) { // All parts empty - return null; + return; } throw new TransformationFailedException( diff --git a/Extension/Core/DataTransformer/BooleanToStringTransformer.php b/Extension/Core/DataTransformer/BooleanToStringTransformer.php index cf0e9c1102..ad65b01a2c 100644 --- a/Extension/Core/DataTransformer/BooleanToStringTransformer.php +++ b/Extension/Core/DataTransformer/BooleanToStringTransformer.php @@ -50,7 +50,7 @@ public function __construct($trueValue) public function transform($value) { if (null === $value) { - return null; + return; } if (!is_bool($value)) { diff --git a/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php b/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php index 1ca1da41c0..a91ed55c31 100644 --- a/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php +++ b/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php @@ -106,13 +106,11 @@ public function reverseTransform($values) if (isset($choices[$i])) { return $choices[$i] === '' ? null : $choices[$i]; } elseif ($this->placeholderPresent && 'placeholder' === $i) { - return null; + return; } else { throw new TransformationFailedException(sprintf('The choice "%s" does not exist', $i)); } } } - - return null; } } diff --git a/Extension/Core/DataTransformer/ChoiceToValueTransformer.php b/Extension/Core/DataTransformer/ChoiceToValueTransformer.php index 5a818558d3..087faf4d3b 100644 --- a/Extension/Core/DataTransformer/ChoiceToValueTransformer.php +++ b/Extension/Core/DataTransformer/ChoiceToValueTransformer.php @@ -46,7 +46,7 @@ public function reverseTransform($value) // These are now valid ChoiceList values, so we can return null // right away if ('' === $value || null === $value) { - return null; + return; } $choices = $this->choiceList->getChoicesForValues(array($value)); diff --git a/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php b/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php index 922d3c5bd8..ea2ab40e6f 100644 --- a/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php @@ -119,7 +119,7 @@ public function transform($dateTime) public function reverseTransform($value) { if (null === $value) { - return null; + return; } if (!is_array($value)) { @@ -127,7 +127,7 @@ public function reverseTransform($value) } if ('' === implode('', $value)) { - return null; + return; } $emptyFields = array(); diff --git a/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php index f04b867599..56a3ca928b 100644 --- a/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php @@ -121,7 +121,7 @@ public function reverseTransform($value) } if ('' === $value) { - return null; + return; } $timestamp = $this->getIntlDateFormatter()->parse($value); diff --git a/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php b/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php index 6d0b284708..e3297ffef3 100644 --- a/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php +++ b/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php @@ -49,7 +49,7 @@ public function reverseTransform($rfc3339) } if ('' === $rfc3339) { - return null; + return; } try { diff --git a/Extension/Core/DataTransformer/DateTimeToStringTransformer.php b/Extension/Core/DataTransformer/DateTimeToStringTransformer.php index 32068b06c5..6f699040b5 100644 --- a/Extension/Core/DataTransformer/DateTimeToStringTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToStringTransformer.php @@ -131,7 +131,7 @@ public function transform($value) public function reverseTransform($value) { if (empty($value)) { - return null; + return; } if (!is_string($value)) { diff --git a/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php b/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php index d2ca6604db..69ca67bbad 100644 --- a/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php @@ -35,7 +35,7 @@ class DateTimeToTimestampTransformer extends BaseDateTimeTransformer public function transform($value) { if (null === $value) { - return null; + return; } if (!$value instanceof \DateTime) { @@ -65,7 +65,7 @@ public function transform($value) public function reverseTransform($value) { if (null === $value) { - return null; + return; } if (!is_numeric($value)) { diff --git a/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php index a3f2af42b8..8b0b241c47 100644 --- a/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php @@ -31,7 +31,7 @@ public function reverseTransform($value) } if ('' === $value) { - return null; + return; } if ('NaN' === $value) { diff --git a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php index 2270240d20..f8f78b2e53 100644 --- a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php @@ -102,7 +102,7 @@ public function reverseTransform($value) } if ('' === $value) { - return null; + return; } if ('NaN' === $value) { diff --git a/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php index ff43697379..bbf4761fa0 100644 --- a/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php @@ -115,7 +115,7 @@ public function reverseTransform($value) } if ('' === $value) { - return null; + return; } $formatter = $this->getNumberFormatter(); diff --git a/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php b/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php index c34a0139fa..618fc6b4a4 100644 --- a/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php +++ b/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php @@ -78,7 +78,7 @@ public function reverseTransform($array) if (count($emptyKeys) > 0) { if (count($emptyKeys) == count($this->keys)) { // All keys empty - return null; + return; } throw new TransformationFailedException( diff --git a/Extension/Core/Type/ButtonType.php b/Extension/Core/Type/ButtonType.php index 75e95ab41e..c4b97652cd 100644 --- a/Extension/Core/Type/ButtonType.php +++ b/Extension/Core/Type/ButtonType.php @@ -26,7 +26,6 @@ class ButtonType extends BaseType implements ButtonTypeInterface */ public function getParent() { - return null; } /** diff --git a/Extension/Core/Type/ChoiceType.php b/Extension/Core/Type/ChoiceType.php index 83fe717f0d..712f5b6de8 100644 --- a/Extension/Core/Type/ChoiceType.php +++ b/Extension/Core/Type/ChoiceType.php @@ -190,10 +190,10 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) $emptyValueNormalizer = function (Options $options, $emptyValue) { if ($options['multiple']) { // never use an empty value for this case - return null; + return; } elseif (false === $emptyValue) { // an empty value should be added but the user decided otherwise - return null; + return; } elseif ($options['expanded'] && '' === $emptyValue) { // never use an empty label for radio buttons return 'None'; diff --git a/Extension/Core/Type/FormType.php b/Extension/Core/Type/FormType.php index 8cbfa6fc99..6da2034731 100644 --- a/Extension/Core/Type/FormType.php +++ b/Extension/Core/Type/FormType.php @@ -201,7 +201,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) */ public function getParent() { - return null; } /** diff --git a/Extension/Validator/Type/BaseValidatorExtension.php b/Extension/Validator/Type/BaseValidatorExtension.php index 7c5e6784ae..f5bc00daa6 100644 --- a/Extension/Validator/Type/BaseValidatorExtension.php +++ b/Extension/Validator/Type/BaseValidatorExtension.php @@ -35,7 +35,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) } if (empty($groups)) { - return null; + return; } if (is_callable($groups)) { diff --git a/Extension/Validator/Util/ServerParams.php b/Extension/Validator/Util/ServerParams.php index a20bf5ad64..b2a5ec155a 100644 --- a/Extension/Validator/Util/ServerParams.php +++ b/Extension/Validator/Util/ServerParams.php @@ -26,7 +26,7 @@ public function getPostMaxSize() $iniMax = strtolower($this->getNormalizedIniPostMaxSize()); if ('' === $iniMax) { - return null; + return; } $max = ltrim($iniMax, '+'); diff --git a/Extension/Validator/ValidatorTypeGuesser.php b/Extension/Validator/ValidatorTypeGuesser.php index 333fe3cd40..63d06dca71 100644 --- a/Extension/Validator/ValidatorTypeGuesser.php +++ b/Extension/Validator/ValidatorTypeGuesser.php @@ -159,8 +159,6 @@ public function guessTypeForConstraint(Constraint $constraint) case 'Symfony\Component\Validator\Constraints\False': return new TypeGuess('checkbox', array(), Guess::MEDIUM_CONFIDENCE); } - - return null; } /** @@ -178,8 +176,6 @@ public function guessRequiredForConstraint(Constraint $constraint) case 'Symfony\Component\Validator\Constraints\True': return new ValueGuess(true, Guess::HIGH_CONFIDENCE); } - - return null; } /** @@ -210,8 +206,6 @@ public function guessMaxLengthForConstraint(Constraint $constraint) } break; } - - return null; } /** @@ -250,8 +244,6 @@ public function guessPatternForConstraint(Constraint $constraint) } break; } - - return null; } /** diff --git a/Extension/Validator/ViolationMapper/MappingRule.php b/Extension/Validator/ViolationMapper/MappingRule.php index 7b96efb4d6..9b370f06ba 100644 --- a/Extension/Validator/ViolationMapper/MappingRule.php +++ b/Extension/Validator/ViolationMapper/MappingRule.php @@ -64,8 +64,6 @@ public function match($propertyPath) if ($propertyPath === (string) $this->propertyPath) { return $this->getTarget(); } - - return null; } /** diff --git a/Extension/Validator/ViolationMapper/ViolationMapper.php b/Extension/Validator/ViolationMapper/ViolationMapper.php index 6ea56eb03b..1913577695 100644 --- a/Extension/Validator/ViolationMapper/ViolationMapper.php +++ b/Extension/Validator/ViolationMapper/ViolationMapper.php @@ -172,7 +172,7 @@ private function matchChild(FormInterface $form, PropertyPathIteratorInterface $ // Make the path longer until we find a matching child while (true) { if (!$it->valid()) { - return null; + return; } if ($it->isIndex()) { @@ -223,8 +223,6 @@ private function matchChild(FormInterface $form, PropertyPathIteratorInterface $ return $foundChild; } } - - return null; } /** diff --git a/Extension/Validator/ViolationMapper/ViolationPath.php b/Extension/Validator/ViolationMapper/ViolationPath.php index 12a4241077..3941ef8422 100644 --- a/Extension/Validator/ViolationMapper/ViolationPath.php +++ b/Extension/Validator/ViolationMapper/ViolationPath.php @@ -127,7 +127,7 @@ public function getLength() public function getParent() { if ($this->length <= 1) { - return null; + return; } $parent = clone $this; diff --git a/Form.php b/Form.php index 990d4cb125..9be5279411 100644 --- a/Form.php +++ b/Form.php @@ -209,7 +209,7 @@ public function getPropertyPath() } if (null === $this->getName() || '' === $this->getName()) { - return null; + return; } $parent = $this->parent; @@ -767,8 +767,6 @@ public function getClickedButton() if ($this->parent && method_exists($this->parent, 'getClickedButton')) { return $this->parent->getClickedButton(); } - - return null; } /** diff --git a/NativeRequestHandler.php b/NativeRequestHandler.php index c79159b3d3..c76534473c 100644 --- a/NativeRequestHandler.php +++ b/NativeRequestHandler.php @@ -180,7 +180,7 @@ private static function stripEmptyFiles($data) if (self::$fileKeys === $keys) { if (UPLOAD_ERR_NO_FILE === $data['error']) { - return null; + return; } return $data; diff --git a/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.php b/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.php index 527de1616b..e26bf7f1b6 100644 --- a/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.php +++ b/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.php @@ -64,7 +64,7 @@ public function testValidationGroupsCanBeSetToCallback() public function testValidationGroupsCanBeSetToClosure() { $form = $this->createForm(array( - 'validation_groups' => function (FormInterface $form) { return null; }, + 'validation_groups' => function (FormInterface $form) { return; }, )); $this->assertTrue(is_callable($form->getConfig()->getOption('validation_groups'))); diff --git a/Tests/Fixtures/FooType.php b/Tests/Fixtures/FooType.php index d26d3f7683..626ccf08ed 100644 --- a/Tests/Fixtures/FooType.php +++ b/Tests/Fixtures/FooType.php @@ -27,6 +27,5 @@ public function getName() public function getParent() { - return null; } } From bafbe7f9b91211c69d00ce697332da5010b7434c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 16 Apr 2014 10:03:46 +0200 Subject: [PATCH 290/447] made {@inheritdoc} annotations consistent across the board --- .../DataTransformer/IntegerToLocalizedStringTransformer.php | 2 +- Extension/DataCollector/DataCollectorExtension.php | 2 +- .../DataCollector/EventListener/DataCollectorListener.php | 2 +- Extension/DataCollector/FormDataCollector.php | 2 +- Extension/DataCollector/Type/DataCollectorTypeExtension.php | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php index 58d91894cf..a14074ce9f 100644 --- a/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/IntegerToLocalizedStringTransformer.php @@ -36,7 +36,7 @@ public function __construct($precision = 0, $grouping = false, $roundingMode = s } /** - * {@inheritDoc} + * {@inheritdoc} */ public function reverseTransform($value) { diff --git a/Extension/DataCollector/DataCollectorExtension.php b/Extension/DataCollector/DataCollectorExtension.php index 941bd2102e..3c15012109 100644 --- a/Extension/DataCollector/DataCollectorExtension.php +++ b/Extension/DataCollector/DataCollectorExtension.php @@ -34,7 +34,7 @@ public function __construct(FormDataCollectorInterface $dataCollector) } /** - * {@inheritDoc} + * {@inheritdoc} */ protected function loadTypeExtensions() { diff --git a/Extension/DataCollector/EventListener/DataCollectorListener.php b/Extension/DataCollector/EventListener/DataCollectorListener.php index 4822989b58..2baceb989a 100644 --- a/Extension/DataCollector/EventListener/DataCollectorListener.php +++ b/Extension/DataCollector/EventListener/DataCollectorListener.php @@ -36,7 +36,7 @@ public function __construct(FormDataCollectorInterface $dataCollector) } /** - * {@inheritDoc} + * {@inheritdoc} */ public static function getSubscribedEvents() { diff --git a/Extension/DataCollector/FormDataCollector.php b/Extension/DataCollector/FormDataCollector.php index 2119248132..be2f07a586 100644 --- a/Extension/DataCollector/FormDataCollector.php +++ b/Extension/DataCollector/FormDataCollector.php @@ -198,7 +198,7 @@ public function buildFinalFormTree(FormInterface $form, FormView $view) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function getName() { diff --git a/Extension/DataCollector/Type/DataCollectorTypeExtension.php b/Extension/DataCollector/Type/DataCollectorTypeExtension.php index 1b5cfb695d..2c6ddfe3e5 100644 --- a/Extension/DataCollector/Type/DataCollectorTypeExtension.php +++ b/Extension/DataCollector/Type/DataCollectorTypeExtension.php @@ -36,7 +36,7 @@ public function __construct(FormDataCollectorInterface $dataCollector) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function buildForm(FormBuilderInterface $builder, array $options) { @@ -44,7 +44,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function getExtendedType() { From db2ec0faad99f8b5d8f0794b7a2dea63ff76c90e Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 16 Apr 2014 10:04:32 +0200 Subject: [PATCH 291/447] made types consistent with those defined in Hack --- .../Core/DataTransformer/NumberToLocalizedStringTransformer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php index be4d3f5c15..60621550ad 100644 --- a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php @@ -248,7 +248,7 @@ protected function getNumberFormatter() /** * Rounds a number according to the configured precision and rounding mode. * - * @param integer|float $number A number. + * @param int|float $number A number. * * @return integer|float The rounded number. */ From 0ad42e550f49bd68999de52d332db85ea7282acf Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 16 Apr 2014 10:09:01 +0200 Subject: [PATCH 292/447] made types consistent with those defined in Hack --- Form.php | 2 +- FormErrorIterator.php | 6 +++--- FormInterface.php | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Form.php b/Form.php index ec0ad9a20d..4fb1b1ee65 100644 --- a/Form.php +++ b/Form.php @@ -1131,7 +1131,7 @@ private function viewToNorm($value) * Utility function for indenting multi-line strings. * * @param string $string The string - * @param integer $level The number of spaces to use for indentation + * @param int $level The number of spaces to use for indentation * * @return string The indented string */ diff --git a/FormErrorIterator.php b/FormErrorIterator.php index bc2bdb1e50..83d7aefc36 100644 --- a/FormErrorIterator.php +++ b/FormErrorIterator.php @@ -159,7 +159,7 @@ public function rewind() /** * Returns whether a position exists in the iterator. * - * @param integer $position The position + * @param int $position The position * * @return Boolean Whether that position exists */ @@ -171,7 +171,7 @@ public function offsetExists($position) /** * Returns the element at a position in the iterator. * - * @param integer $position The position + * @param int $position The position * * @return FormError|FormErrorIterator The element at the given position * @@ -250,7 +250,7 @@ public function count() /** * Sets the position of the iterator. * - * @param integer $position The new position + * @param int $position The new position * * @throws OutOfBoundsException If the position is invalid */ diff --git a/FormInterface.php b/FormInterface.php index 391c9b1e1e..d4709eaea5 100644 --- a/FormInterface.php +++ b/FormInterface.php @@ -94,8 +94,8 @@ public function all(); /** * Returns the errors of this form. * - * @param Boolean $deep Whether to include errors of child forms as well - * @param Boolean $flatten Whether to flatten the list of errors in case + * @param bool $deep Whether to include errors of child forms as well + * @param bool $flatten Whether to flatten the list of errors in case * $deep is set to true * * @return FormErrorIterator An iterator over the {@link FormError} From ecb616bb1073eba2236aa57bc94988c68a3d6450 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 16 Apr 2014 12:30:19 +0200 Subject: [PATCH 293/447] fixed types in phpdocs --- AbstractExtension.php | 2 +- AbstractRendererEngine.php | 4 +-- Button.php | 18 +++++------ ButtonBuilder.php | 32 +++++++++---------- ClickableInterface.php | 2 +- Extension/Core/ChoiceList/ChoiceList.php | 6 ++-- .../Core/ChoiceList/ObjectChoiceList.php | 2 +- .../Core/ChoiceList/SimpleChoiceList.php | 4 +-- .../BooleanToStringTransformer.php | 2 +- .../DateTimeToStringTransformer.php | 2 +- .../DateTimeToTimestampTransformer.php | 2 +- .../NumberToLocalizedStringTransformer.php | 2 +- .../EventListener/MergeCollectionListener.php | 4 +-- .../Core/EventListener/ResizeFormListener.php | 4 +-- .../CsrfProvider/CsrfProviderInterface.php | 2 +- Extension/Csrf/Type/FormTypeCsrfExtension.php | 2 +- .../Templating/TemplatingRendererEngine.php | 4 +-- .../Validator/Constraints/FormValidator.php | 2 +- Extension/Validator/Util/ServerParams.php | 2 +- .../Validator/ViolationMapper/MappingRule.php | 2 +- .../ViolationMapper/ViolationMapper.php | 4 +-- .../ViolationMapper/ViolationPath.php | 4 +-- Form.php | 12 +++---- FormBuilderInterface.php | 2 +- FormConfigBuilder.php | 22 ++++++------- FormConfigInterface.php | 22 ++++++------- FormError.php | 4 +-- FormExtensionInterface.php | 4 +-- FormInterface.php | 16 +++++----- FormRegistryInterface.php | 2 +- FormRendererEngineInterface.php | 2 +- FormView.php | 8 ++--- Guess/Guess.php | 12 +++---- SubmitButton.php | 2 +- Test/FormPerformanceTestCase.php | 4 +-- .../BooleanToStringTransformerTest.php | 2 +- Util/FormUtil.php | 2 +- Util/OrderedHashMapIterator.php | 6 ++-- 38 files changed, 115 insertions(+), 115 deletions(-) diff --git a/AbstractExtension.php b/AbstractExtension.php index 4db77b9bb5..f55fbf940c 100644 --- a/AbstractExtension.php +++ b/AbstractExtension.php @@ -39,7 +39,7 @@ abstract class AbstractExtension implements FormExtensionInterface /** * Whether the type guesser has been loaded - * @var Boolean + * @var bool */ private $typeGuesserLoaded = false; diff --git a/AbstractRendererEngine.php b/AbstractRendererEngine.php index 76506b73a0..764fe1de70 100644 --- a/AbstractRendererEngine.php +++ b/AbstractRendererEngine.php @@ -131,7 +131,7 @@ public function getResourceHierarchyLevel(FormView $view, array $blockNameHierar * @param FormView $view The form view for finding the applying themes. * @param string $blockName The name of the block to load. * - * @return Boolean True if the resource could be loaded, false otherwise. + * @return bool True if the resource could be loaded, false otherwise. */ abstract protected function loadResourceForBlockName($cacheKey, FormView $view, $blockName); @@ -149,7 +149,7 @@ abstract protected function loadResourceForBlockName($cacheKey, FormView $view, * @param int $hierarchyLevel The level in the block hierarchy that * should be loaded. * - * @return Boolean True if the resource could be loaded, false otherwise. + * @return bool True if the resource could be loaded, false otherwise. */ private function loadResourceForBlockNameHierarchy($cacheKey, FormView $view, array $blockNameHierarchy, $hierarchyLevel) { diff --git a/Button.php b/Button.php index fe0ab1ad65..27277755a6 100644 --- a/Button.php +++ b/Button.php @@ -32,7 +32,7 @@ class Button implements \IteratorAggregate, FormInterface private $config; /** - * @var Boolean + * @var bool */ private $submitted = false; @@ -51,7 +51,7 @@ public function __construct(FormConfigInterface $config) * * @param mixed $offset * - * @return Boolean Always returns false. + * @return bool Always returns false. */ public function offsetExists($offset) { @@ -152,7 +152,7 @@ public function get($name) * * @param string $name * - * @return Boolean Always returns false. + * @return bool Always returns false. */ public function has($name) { @@ -257,7 +257,7 @@ public function getConfig() /** * Returns whether the button is submitted. * - * @return Boolean true if the button was submitted. + * @return bool true if the button was submitted. */ public function isSubmitted() { @@ -299,7 +299,7 @@ public function addError(FormError $error) /** * Unsupported method. * - * @return Boolean Always returns true. + * @return bool Always returns true. */ public function isValid() { @@ -309,7 +309,7 @@ public function isValid() /** * Unsupported method. * - * @return Boolean Always returns false. + * @return bool Always returns false. */ public function isRequired() { @@ -331,7 +331,7 @@ public function isDisabled() /** * Unsupported method. * - * @return Boolean Always returns true. + * @return bool Always returns true. */ public function isEmpty() { @@ -341,7 +341,7 @@ public function isEmpty() /** * Unsupported method. * - * @return Boolean Always returns true. + * @return bool Always returns true. */ public function isSynchronized() { @@ -422,7 +422,7 @@ public function createView(FormView $parent = null) /** * Unsupported method. * - * @return integer Always returns 0. + * @return int Always returns 0. */ public function count() { diff --git a/ButtonBuilder.php b/ButtonBuilder.php index b89e01b02f..b6cf6e7125 100644 --- a/ButtonBuilder.php +++ b/ButtonBuilder.php @@ -23,12 +23,12 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface { /** - * @var Boolean + * @var bool */ protected $locked = false; /** - * @var Boolean + * @var bool */ private $disabled; @@ -135,7 +135,7 @@ public function remove($name) * * @param string $name * - * @return Boolean Always returns false. + * @return bool Always returns false. */ public function has($name) { @@ -573,7 +573,7 @@ public function getPropertyPath() /** * Unsupported method. * - * @return Boolean Always returns false. + * @return bool Always returns false. */ public function getMapped() { @@ -583,7 +583,7 @@ public function getMapped() /** * Unsupported method. * - * @return Boolean Always returns false. + * @return bool Always returns false. */ public function getByReference() { @@ -593,7 +593,7 @@ public function getByReference() /** * Unsupported method. * - * @return Boolean Always returns false. + * @return bool Always returns false. */ public function getVirtual() { @@ -603,7 +603,7 @@ public function getVirtual() /** * Unsupported method. * - * @return Boolean Always returns false. + * @return bool Always returns false. */ public function getCompound() { @@ -653,7 +653,7 @@ public function getDataMapper() /** * Unsupported method. * - * @return Boolean Always returns false. + * @return bool Always returns false. */ public function getRequired() { @@ -663,7 +663,7 @@ public function getRequired() /** * Returns whether the button is disabled. * - * @return Boolean Whether the button is disabled. + * @return bool Whether the button is disabled. */ public function getDisabled() { @@ -673,7 +673,7 @@ public function getDisabled() /** * Unsupported method. * - * @return Boolean Always returns false. + * @return bool Always returns false. */ public function getErrorBubbling() { @@ -705,7 +705,7 @@ public function getAttributes() * * @param string $name The attribute name. * - * @return Boolean Whether the attribute exists. + * @return bool Whether the attribute exists. */ public function hasAttribute($name) { @@ -748,7 +748,7 @@ public function getDataClass() /** * Unsupported method. * - * @return Boolean Always returns false. + * @return bool Always returns false. */ public function getDataLocked() { @@ -798,7 +798,7 @@ public function getRequestHandler() /** * Unsupported method. * - * @return Boolean Always returns false. + * @return bool Always returns false. */ public function getAutoInitialize() { @@ -808,7 +808,7 @@ public function getAutoInitialize() /** * Unsupported method. * - * @return Boolean Always returns false. + * @return bool Always returns false. */ public function getInheritData() { @@ -830,7 +830,7 @@ public function getOptions() * * @param string $name The option name, * - * @return Boolean Whether the option exists. + * @return bool Whether the option exists. */ public function hasOption($name) { @@ -853,7 +853,7 @@ public function getOption($name, $default = null) /** * Unsupported method. * - * @return integer Always returns 0. + * @return int Always returns 0. */ public function count() { diff --git a/ClickableInterface.php b/ClickableInterface.php index 893f02df0a..9df55449fb 100644 --- a/ClickableInterface.php +++ b/ClickableInterface.php @@ -21,7 +21,7 @@ interface ClickableInterface /** * Returns whether this element was clicked. * - * @return Boolean Whether this element was clicked. + * @return bool Whether this element was clicked. */ public function isClicked(); } diff --git a/Extension/Core/ChoiceList/ChoiceList.php b/Extension/Core/ChoiceList/ChoiceList.php index 17ae0a3d9e..d3d8e7dd09 100644 --- a/Extension/Core/ChoiceList/ChoiceList.php +++ b/Extension/Core/ChoiceList/ChoiceList.php @@ -377,7 +377,7 @@ protected function addChoice(array &$bucketForPreferred, array &$bucketForRemain * @param mixed $choice The choice to test. * @param array $preferredChoices An array of preferred choices. * - * @return Boolean Whether the choice is preferred. + * @return bool Whether the choice is preferred. */ protected function isPreferred($choice, array $preferredChoices) { @@ -391,7 +391,7 @@ protected function isPreferred($choice, array $preferredChoices) * * @param mixed $choice The choice to create an index for * - * @return integer|string A unique index containing only ASCII letters, + * @return int|string A unique index containing only ASCII letters, * digits and underscores. */ protected function createIndex($choice) @@ -451,7 +451,7 @@ protected function fixValues(array $values) * * @param mixed $index The choice index. * - * @return integer|string The index as PHP array key. + * @return int|string The index as PHP array key. */ protected function fixIndex($index) { diff --git a/Extension/Core/ChoiceList/ObjectChoiceList.php b/Extension/Core/ChoiceList/ObjectChoiceList.php index 0f1437db21..22035b8f75 100644 --- a/Extension/Core/ChoiceList/ObjectChoiceList.php +++ b/Extension/Core/ChoiceList/ObjectChoiceList.php @@ -157,7 +157,7 @@ protected function initialize($choices, array $labels, array $preferredChoices) * * @param mixed $choice The choice to create a value for * - * @return integer|string A unique value without character limitations. + * @return int|string A unique value without character limitations. */ protected function createValue($choice) { diff --git a/Extension/Core/ChoiceList/SimpleChoiceList.php b/Extension/Core/ChoiceList/SimpleChoiceList.php index 914dbe5fdb..dbe54265b1 100644 --- a/Extension/Core/ChoiceList/SimpleChoiceList.php +++ b/Extension/Core/ChoiceList/SimpleChoiceList.php @@ -124,7 +124,7 @@ protected function addChoices(array &$bucketForPreferred, array &$bucketForRemai * @param mixed $choice The choice to test. * @param array $preferredChoices An array of preferred choices. * - * @return Boolean Whether the choice is preferred. + * @return bool Whether the choice is preferred. */ protected function isPreferred($choice, array $preferredChoices) { @@ -137,7 +137,7 @@ protected function isPreferred($choice, array $preferredChoices) * * @param mixed $choice The choice. * - * @return string|integer A valid PHP array key. + * @return string|int A valid PHP array key. */ protected function fixChoice($choice) { diff --git a/Extension/Core/DataTransformer/BooleanToStringTransformer.php b/Extension/Core/DataTransformer/BooleanToStringTransformer.php index cf0e9c1102..aef299b3af 100644 --- a/Extension/Core/DataTransformer/BooleanToStringTransformer.php +++ b/Extension/Core/DataTransformer/BooleanToStringTransformer.php @@ -65,7 +65,7 @@ public function transform($value) * * @param string $value String value. * - * @return Boolean Boolean value. + * @return bool Boolean value. * * @throws TransformationFailedException If the given value is not a string. */ diff --git a/Extension/Core/DataTransformer/DateTimeToStringTransformer.php b/Extension/Core/DataTransformer/DateTimeToStringTransformer.php index 32068b06c5..6719a72df3 100644 --- a/Extension/Core/DataTransformer/DateTimeToStringTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToStringTransformer.php @@ -44,7 +44,7 @@ class DateTimeToStringTransformer extends BaseDateTimeTransformer * * This only works as of PHP 5.3.7. * - * @var Boolean + * @var bool */ private $parseUsingPipe; diff --git a/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php b/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php index d2ca6604db..707ebfc61f 100644 --- a/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php @@ -26,7 +26,7 @@ class DateTimeToTimestampTransformer extends BaseDateTimeTransformer * * @param \DateTime $value A \DateTime object * - * @return integer A timestamp + * @return int A timestamp * * @throws TransformationFailedException If the given value is not an instance * of \DateTime or if the output diff --git a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php index 2270240d20..78594bf79e 100644 --- a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php @@ -90,7 +90,7 @@ public function transform($value) * * @param string $value The localized value * - * @return integer|float The numeric value + * @return int|float The numeric value * * @throws TransformationFailedException If the given value is not a string * or if the value can not be transformed. diff --git a/Extension/Core/EventListener/MergeCollectionListener.php b/Extension/Core/EventListener/MergeCollectionListener.php index 51ca781a36..b0fbdb54c3 100644 --- a/Extension/Core/EventListener/MergeCollectionListener.php +++ b/Extension/Core/EventListener/MergeCollectionListener.php @@ -23,13 +23,13 @@ class MergeCollectionListener implements EventSubscriberInterface { /** * Whether elements may be added to the collection - * @var Boolean + * @var bool */ private $allowAdd; /** * Whether elements may be removed from the collection - * @var Boolean + * @var bool */ private $allowDelete; diff --git a/Extension/Core/EventListener/ResizeFormListener.php b/Extension/Core/EventListener/ResizeFormListener.php index 207cbd3d38..022ddc5df3 100644 --- a/Extension/Core/EventListener/ResizeFormListener.php +++ b/Extension/Core/EventListener/ResizeFormListener.php @@ -35,13 +35,13 @@ class ResizeFormListener implements EventSubscriberInterface /** * Whether children could be added to the group - * @var Boolean + * @var bool */ protected $allowAdd; /** * Whether children could be removed from the group - * @var Boolean + * @var bool */ protected $allowDelete; diff --git a/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php b/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php index 7143b130c8..b1f255e35e 100644 --- a/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php +++ b/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php @@ -43,7 +43,7 @@ public function generateCsrfToken($intention); * @param string $intention The intention used when generating the CSRF token * @param string $token The token supplied by the browser * - * @return Boolean Whether the token supplied by the browser is correct + * @return bool Whether the token supplied by the browser is correct */ public function isCsrfTokenValid($intention, $token); } diff --git a/Extension/Csrf/Type/FormTypeCsrfExtension.php b/Extension/Csrf/Type/FormTypeCsrfExtension.php index 28c752a115..845e18b2a2 100644 --- a/Extension/Csrf/Type/FormTypeCsrfExtension.php +++ b/Extension/Csrf/Type/FormTypeCsrfExtension.php @@ -31,7 +31,7 @@ class FormTypeCsrfExtension extends AbstractTypeExtension private $defaultCsrfProvider; /** - * @var Boolean + * @var bool */ private $defaultEnabled; diff --git a/Extension/Templating/TemplatingRendererEngine.php b/Extension/Templating/TemplatingRendererEngine.php index c1dda60b7a..74790ba330 100644 --- a/Extension/Templating/TemplatingRendererEngine.php +++ b/Extension/Templating/TemplatingRendererEngine.php @@ -52,7 +52,7 @@ public function renderBlock(FormView $view, $resource, $blockName, array $variab * @param FormView $view The form view for finding the applying themes. * @param string $blockName The name of the block to load. * - * @return Boolean True if the resource could be loaded, false otherwise. + * @return bool True if the resource could be loaded, false otherwise. */ protected function loadResourceForBlockName($cacheKey, FormView $view, $blockName) { @@ -110,7 +110,7 @@ protected function loadResourceForBlockName($cacheKey, FormView $view, $blockNam * @param string $blockName The name of the block to load a resource for. * @param mixed $theme The theme to load the block from. * - * @return Boolean True if the resource could be loaded, false otherwise. + * @return bool True if the resource could be loaded, false otherwise. */ protected function loadResourceFromTheme($cacheKey, $blockName, $theme) { diff --git a/Extension/Validator/Constraints/FormValidator.php b/Extension/Validator/Constraints/FormValidator.php index 0df176f7d7..154e865923 100644 --- a/Extension/Validator/Constraints/FormValidator.php +++ b/Extension/Validator/Constraints/FormValidator.php @@ -135,7 +135,7 @@ public function validate($form, Constraint $constraint) * * @param FormInterface $form The form to test. * - * @return Boolean Whether the graph walker may walk the data. + * @return bool Whether the graph walker may walk the data. */ private static function allowDataWalking(FormInterface $form) { diff --git a/Extension/Validator/Util/ServerParams.php b/Extension/Validator/Util/ServerParams.php index a20bf5ad64..070170980d 100644 --- a/Extension/Validator/Util/ServerParams.php +++ b/Extension/Validator/Util/ServerParams.php @@ -19,7 +19,7 @@ class ServerParams /** * Returns maximum post size in bytes. * - * @return null|integer The maximum post size in bytes + * @return null|int The maximum post size in bytes */ public function getPostMaxSize() { diff --git a/Extension/Validator/ViolationMapper/MappingRule.php b/Extension/Validator/ViolationMapper/MappingRule.php index 7b96efb4d6..a4df0767b7 100644 --- a/Extension/Validator/ViolationMapper/MappingRule.php +++ b/Extension/Validator/ViolationMapper/MappingRule.php @@ -73,7 +73,7 @@ public function match($propertyPath) * * @param string $propertyPath The property path to match against the rule. * - * @return Boolean Whether the property path is a prefix of the rule or not. + * @return bool Whether the property path is a prefix of the rule or not. */ public function isPrefix($propertyPath) { diff --git a/Extension/Validator/ViolationMapper/ViolationMapper.php b/Extension/Validator/ViolationMapper/ViolationMapper.php index 6ea56eb03b..6e680a08fa 100644 --- a/Extension/Validator/ViolationMapper/ViolationMapper.php +++ b/Extension/Validator/ViolationMapper/ViolationMapper.php @@ -25,7 +25,7 @@ class ViolationMapper implements ViolationMapperInterface { /** - * @var Boolean + * @var bool */ private $allowNonSynchronized; @@ -289,7 +289,7 @@ private function reconstructPath(ViolationPath $violationPath, FormInterface $or /** * @param FormInterface $form * - * @return Boolean + * @return bool */ private function acceptsErrors(FormInterface $form) { diff --git a/Extension/Validator/ViolationMapper/ViolationPath.php b/Extension/Validator/ViolationMapper/ViolationPath.php index 12a4241077..83a7d60478 100644 --- a/Extension/Validator/ViolationMapper/ViolationPath.php +++ b/Extension/Validator/ViolationMapper/ViolationPath.php @@ -41,7 +41,7 @@ class ViolationPath implements \IteratorAggregate, PropertyPathInterface private $pathAsString = ''; /** - * @var integer + * @var int */ private $length = 0; @@ -200,7 +200,7 @@ public function isIndex($index) * * @param int $index The element index. * - * @return Boolean Whether the element maps to a form. + * @return bool Whether the element maps to a form. * * @throws OutOfBoundsException If the offset is invalid. */ diff --git a/Form.php b/Form.php index 990d4cb125..dc3ac58d6f 100644 --- a/Form.php +++ b/Form.php @@ -86,7 +86,7 @@ class Form implements \IteratorAggregate, FormInterface /** * Whether this form was submitted - * @var Boolean + * @var bool */ private $submitted = false; @@ -124,7 +124,7 @@ class Form implements \IteratorAggregate, FormInterface * Whether the data in model, normalized and view format is * synchronized. Data may not be synchronized if transformation errors * occur. - * @var Boolean + * @var bool */ private $synchronized = true; @@ -138,13 +138,13 @@ class Form implements \IteratorAggregate, FormInterface * manually, making the initialization with the configured default value * superfluous. * - * @var Boolean + * @var bool */ private $defaultDataSet = false; /** * Whether setData() is currently being called. - * @var Boolean + * @var bool */ private $lockSetData = false; @@ -932,7 +932,7 @@ public function get($name) * * @param string $name The name of the child * - * @return Boolean + * @return bool */ public function offsetExists($name) { @@ -994,7 +994,7 @@ public function getIterator() /** * Returns the number of form children (implements the \Countable interface). * - * @return integer The number of embedded form children + * @return int The number of embedded form children */ public function count() { diff --git a/FormBuilderInterface.php b/FormBuilderInterface.php index c0eb8c32c7..3294a3d3bd 100644 --- a/FormBuilderInterface.php +++ b/FormBuilderInterface.php @@ -67,7 +67,7 @@ public function remove($name); * * @param string $name * - * @return Boolean + * @return bool */ public function has($name); diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index 99a9df2add..730c63527a 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -48,7 +48,7 @@ class FormConfigBuilder implements FormConfigBuilderInterface ); /** - * @var Boolean + * @var bool */ protected $locked = false; @@ -68,22 +68,22 @@ class FormConfigBuilder implements FormConfigBuilderInterface private $propertyPath; /** - * @var Boolean + * @var bool */ private $mapped = true; /** - * @var Boolean + * @var bool */ private $byReference = true; /** - * @var Boolean + * @var bool */ private $inheritData = false; /** - * @var Boolean + * @var bool */ private $compound = false; @@ -108,17 +108,17 @@ class FormConfigBuilder implements FormConfigBuilderInterface private $dataMapper; /** - * @var Boolean + * @var bool */ private $required = true; /** - * @var Boolean + * @var bool */ private $disabled = false; /** - * @var Boolean + * @var bool */ private $errorBubbling = false; @@ -143,7 +143,7 @@ class FormConfigBuilder implements FormConfigBuilderInterface private $dataClass; /** - * @var Boolean + * @var bool */ private $dataLocked; @@ -168,7 +168,7 @@ class FormConfigBuilder implements FormConfigBuilderInterface private $requestHandler; /** - * @var Boolean + * @var bool */ private $autoInitialize = false; @@ -910,7 +910,7 @@ public static function validateName($name) * * @param string $name The tested form name. * - * @return Boolean Whether the name is valid. + * @return bool Whether the name is valid. */ public static function isValidName($name) { diff --git a/FormConfigInterface.php b/FormConfigInterface.php index 576fcd8142..ea19165407 100644 --- a/FormConfigInterface.php +++ b/FormConfigInterface.php @@ -43,21 +43,21 @@ public function getPropertyPath(); * Returns whether the form should be mapped to an element of its * parent's data. * - * @return Boolean Whether the form is mapped. + * @return bool Whether the form is mapped. */ public function getMapped(); /** * Returns whether the form's data should be modified by reference. * - * @return Boolean Whether to modify the form's data by reference. + * @return bool Whether to modify the form's data by reference. */ public function getByReference(); /** * Returns whether the form should read and write the data of its parent. * - * @return Boolean Whether the form should inherit its parent's data. + * @return bool Whether the form should inherit its parent's data. */ public function getInheritData(); @@ -68,7 +68,7 @@ public function getInheritData(); * children. A form can be compound and have no children at all, like * for example an empty collection form. * - * @return Boolean Whether the form is compound. + * @return bool Whether the form is compound. */ public function getCompound(); @@ -103,21 +103,21 @@ public function getDataMapper(); /** * Returns whether the form is required. * - * @return Boolean Whether the form is required. + * @return bool Whether the form is required. */ public function getRequired(); /** * Returns whether the form is disabled. * - * @return Boolean Whether the form is disabled. + * @return bool Whether the form is disabled. */ public function getDisabled(); /** * Returns whether errors attached to the form will bubble to its parent. * - * @return Boolean Whether errors will bubble up. + * @return bool Whether errors will bubble up. */ public function getErrorBubbling(); @@ -140,7 +140,7 @@ public function getAttributes(); * * @param string $name The attribute name. * - * @return Boolean Whether the attribute exists. + * @return bool Whether the attribute exists. */ public function hasAttribute($name); @@ -175,7 +175,7 @@ public function getDataClass(); * this configuration. The data can only be modified then by * submitting the form. * - * @return Boolean Whether the data is locked. + * @return bool Whether the data is locked. */ public function getDataLocked(); @@ -210,7 +210,7 @@ public function getRequestHandler(); /** * Returns whether the form should be initialized upon creation. * - * @return Boolean Returns true if the form should be initialized + * @return bool Returns true if the form should be initialized * when created, false otherwise. */ public function getAutoInitialize(); @@ -227,7 +227,7 @@ public function getOptions(); * * @param string $name The option name, * - * @return Boolean Whether the option exists. + * @return bool Whether the option exists. */ public function hasOption($name); diff --git a/FormError.php b/FormError.php index 871db9c0dd..8927a76065 100644 --- a/FormError.php +++ b/FormError.php @@ -37,7 +37,7 @@ class FormError /** * The value for error message pluralization - * @var integer|null + * @var int|null */ protected $messagePluralization; @@ -96,7 +96,7 @@ public function getMessageParameters() /** * Returns the value for error message pluralization. * - * @return integer|null + * @return int|null */ public function getMessagePluralization() { diff --git a/FormExtensionInterface.php b/FormExtensionInterface.php index a67055b797..4fcf0b8f73 100644 --- a/FormExtensionInterface.php +++ b/FormExtensionInterface.php @@ -32,7 +32,7 @@ public function getType($name); * * @param string $name The name of the type * - * @return Boolean Whether the type is supported by this extension + * @return bool Whether the type is supported by this extension */ public function hasType($name); @@ -50,7 +50,7 @@ public function getTypeExtensions($name); * * @param string $name The name of the type * - * @return Boolean Whether the given type has extensions + * @return bool Whether the given type has extensions */ public function hasTypeExtensions($name); diff --git a/FormInterface.php b/FormInterface.php index f5a575e69f..67dbb2319b 100644 --- a/FormInterface.php +++ b/FormInterface.php @@ -69,7 +69,7 @@ public function get($name); * * @param string $name The name of the child * - * @return Boolean + * @return bool */ public function has($name); @@ -152,7 +152,7 @@ public function getConfig(); /** * Returns whether the form is submitted. * - * @return Boolean true if the form is submitted, false otherwise + * @return bool true if the form is submitted, false otherwise */ public function isSubmitted(); @@ -184,7 +184,7 @@ public function addError(FormError $error); * * If the form is not submitted, this method always returns false. * - * @return Boolean + * @return bool */ public function isValid(); @@ -195,7 +195,7 @@ public function isValid(); * will always return false. Otherwise the value set with setRequired() * is returned. * - * @return Boolean + * @return bool */ public function isRequired(); @@ -208,21 +208,21 @@ public function isRequired(); * Forms whose parents are disabled are considered disabled regardless of * their own state. * - * @return Boolean + * @return bool */ public function isDisabled(); /** * Returns whether the form is empty. * - * @return Boolean + * @return bool */ public function isEmpty(); /** * Returns whether the data in the different formats is synchronized. * - * @return Boolean + * @return bool */ public function isSynchronized(); @@ -273,7 +273,7 @@ public function getRoot(); /** * Returns whether the field is the root of the form tree. * - * @return Boolean + * @return bool */ public function isRoot(); diff --git a/FormRegistryInterface.php b/FormRegistryInterface.php index 141c4721c5..b15131c39b 100644 --- a/FormRegistryInterface.php +++ b/FormRegistryInterface.php @@ -37,7 +37,7 @@ public function getType($name); * * @param string $name The name of the type * - * @return Boolean Whether the type is supported + * @return bool Whether the type is supported */ public function hasType($name); diff --git a/FormRendererEngineInterface.php b/FormRendererEngineInterface.php index ba92e14e37..9f04e1999a 100644 --- a/FormRendererEngineInterface.php +++ b/FormRendererEngineInterface.php @@ -128,7 +128,7 @@ public function getResourceForBlockNameHierarchy(FormView $view, array $blockNam * the first element of * $blockNameHierarchy. * - * @return integer|Boolean The hierarchy level or false, if no resource was found. + * @return int|bool The hierarchy level or false, if no resource was found. */ public function getResourceHierarchyLevel(FormView $view, array $blockNameHierarchy, $hierarchyLevel); diff --git a/FormView.php b/FormView.php index 1f53ec6a40..a807551854 100644 --- a/FormView.php +++ b/FormView.php @@ -46,7 +46,7 @@ class FormView implements \ArrayAccess, \IteratorAggregate, \Countable * Row implicitly includes widget, however certain rendering mechanisms * have to skip widget rendering when a row is rendered. * - * @var Boolean + * @var bool */ private $rendered = false; @@ -58,7 +58,7 @@ public function __construct(FormView $parent = null) /** * Returns whether the view was already rendered. * - * @return Boolean Whether this view's widget is rendered. + * @return bool Whether this view's widget is rendered. */ public function isRendered() { @@ -110,7 +110,7 @@ public function offsetGet($name) * * @param string $name The child name * - * @return Boolean Whether the child view exists + * @return bool Whether the child view exists */ public function offsetExists($name) { @@ -150,7 +150,7 @@ public function getIterator() /** * Implements \Countable. * - * @return integer The number of children views + * @return int The number of children views */ public function count() { diff --git a/Guess/Guess.php b/Guess/Guess.php index 0deb838d80..93568c3c52 100644 --- a/Guess/Guess.php +++ b/Guess/Guess.php @@ -26,25 +26,25 @@ abstract class Guess { /** * Marks an instance with a value that is extremely likely to be correct - * @var integer + * @var int */ const VERY_HIGH_CONFIDENCE = 3; /** * Marks an instance with a value that is very likely to be correct - * @var integer + * @var int */ const HIGH_CONFIDENCE = 2; /** * Marks an instance with a value that is likely to be correct - * @var integer + * @var int */ const MEDIUM_CONFIDENCE = 1; /** * Marks an instance with a value that may be correct - * @var integer + * @var int */ const LOW_CONFIDENCE = 0; @@ -54,7 +54,7 @@ abstract class Guess * One of VERY_HIGH_CONFIDENCE, HIGH_CONFIDENCE, MEDIUM_CONFIDENCE * and LOW_CONFIDENCE. * - * @var integer + * @var int */ private $confidence; @@ -103,7 +103,7 @@ public function __construct($confidence) /** * Returns the confidence that the guessed value is correct. * - * @return integer One of the constants VERY_HIGH_CONFIDENCE, + * @return int One of the constants VERY_HIGH_CONFIDENCE, * HIGH_CONFIDENCE, MEDIUM_CONFIDENCE and LOW_CONFIDENCE */ public function getConfidence() diff --git a/SubmitButton.php b/SubmitButton.php index 1ff65bcbe1..e95cdeeff7 100644 --- a/SubmitButton.php +++ b/SubmitButton.php @@ -19,7 +19,7 @@ class SubmitButton extends Button implements ClickableInterface { /** - * @var Boolean + * @var bool */ private $clicked = false; diff --git a/Test/FormPerformanceTestCase.php b/Test/FormPerformanceTestCase.php index 435bdf1b2d..b0d07555d9 100644 --- a/Test/FormPerformanceTestCase.php +++ b/Test/FormPerformanceTestCase.php @@ -22,7 +22,7 @@ abstract class FormPerformanceTestCase extends FormIntegrationTestCase { /** - * @var integer + * @var int */ protected $maxRunningTime = 0; @@ -60,7 +60,7 @@ public function setMaxRunningTime($maxRunningTime) } /** - * @return integer + * @return int * @since Method available since Release 2.3.0 */ public function getMaxRunningTime() diff --git a/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php index a1217783d1..4149160c9c 100644 --- a/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php @@ -18,7 +18,7 @@ class BooleanToStringTransformerTest extends \PHPUnit_Framework_TestCase const TRUE_VALUE = '1'; /** - * @var BooleanToStringTransformer + * @var boolToStringTransformer */ protected $transformer; diff --git a/Util/FormUtil.php b/Util/FormUtil.php index 7647691e0a..b3beb458be 100644 --- a/Util/FormUtil.php +++ b/Util/FormUtil.php @@ -30,7 +30,7 @@ private function __construct() {} * * @param mixed $data * - * @return Boolean + * @return bool */ public static function isEmpty($data) { diff --git a/Util/OrderedHashMapIterator.php b/Util/OrderedHashMapIterator.php index 87cf6a9d39..f606626814 100644 --- a/Util/OrderedHashMapIterator.php +++ b/Util/OrderedHashMapIterator.php @@ -33,12 +33,12 @@ class OrderedHashMapIterator implements \Iterator private $orderedKeys; /** - * @var integer + * @var int */ private $cursor; /** - * @var integer + * @var int */ private $cursorId; @@ -48,7 +48,7 @@ class OrderedHashMapIterator implements \Iterator private $managedCursors; /** - * @var string|integer|null + * @var string|int|null */ private $key; From a9714a1e8716786a920156e6cc01d6c6a772b45b Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 16 Apr 2014 12:34:42 +0200 Subject: [PATCH 294/447] fixed types in phpdocs --- .../Core/DataTransformer/NumberToLocalizedStringTransformer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php index 32ba6da89b..e0430bd07c 100644 --- a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php @@ -250,7 +250,7 @@ protected function getNumberFormatter() * * @param int|float $number A number. * - * @return integer|float The rounded number. + * @return int|float The rounded number. */ private function round($number) { From 085fa66d5eb61dd89445b8e17002cf99e2af75a3 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 16 Apr 2014 12:36:34 +0200 Subject: [PATCH 295/447] fixed types in phpdocs --- Extension/Core/EventListener/ResizeFormListener.php | 2 +- FormErrorIterator.php | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Extension/Core/EventListener/ResizeFormListener.php b/Extension/Core/EventListener/ResizeFormListener.php index 6f2be3c44d..e88db69402 100644 --- a/Extension/Core/EventListener/ResizeFormListener.php +++ b/Extension/Core/EventListener/ResizeFormListener.php @@ -46,7 +46,7 @@ class ResizeFormListener implements EventSubscriberInterface protected $allowDelete; /** - * @var Boolean + * @var bool */ private $deleteEmpty; diff --git a/FormErrorIterator.php b/FormErrorIterator.php index 83d7aefc36..58a94f815a 100644 --- a/FormErrorIterator.php +++ b/FormErrorIterator.php @@ -128,7 +128,7 @@ public function next() /** * Returns the current position of the iterator. * - * @return integer The 0-indexed position. + * @return int The 0-indexed position. */ public function key() { @@ -138,7 +138,7 @@ public function key() /** * Returns whether the iterator's position is valid. * - * @return Boolean Whether the iterator is valid. + * @return bool Whether the iterator is valid. */ public function valid() { @@ -161,7 +161,7 @@ public function rewind() * * @param int $position The position * - * @return Boolean Whether that position exists + * @return bool Whether that position exists */ public function offsetExists($position) { @@ -210,7 +210,7 @@ public function offsetUnset($position) * Returns whether the current element of the iterator can be recursed * into. * - * @return Boolean Whether the current element is an instance of this class + * @return bool Whether the current element is an instance of this class */ public function hasChildren() { @@ -240,7 +240,7 @@ public function getChildren() * * $count = count($form->getErrors(true, true)); * - * @return integer The number of iterated elements + * @return int The number of iterated elements */ public function count() { From 8088cb364c2b6be216d4f1bee71fa8f798c87727 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 8 May 2014 17:33:56 +0200 Subject: [PATCH 296/447] [Form] Fixed TrimListenerTest as of PHP 5.5 --- .../Core/EventListener/TrimListenerTest.php | 53 +++++++++++++++---- 1 file changed, 43 insertions(+), 10 deletions(-) diff --git a/Tests/Extension/Core/EventListener/TrimListenerTest.php b/Tests/Extension/Core/EventListener/TrimListenerTest.php index 4e36893380..358620b9c4 100644 --- a/Tests/Extension/Core/EventListener/TrimListenerTest.php +++ b/Tests/Extension/Core/EventListener/TrimListenerTest.php @@ -48,32 +48,65 @@ public function testTrimSkipNonStrings() } /** - * @dataProvider codePointProvider + * @dataProvider spaceProvider */ - public function testTrimUtf8($chars) + public function testTrimUtf8Separators($hex) { if (!function_exists('mb_check_encoding')) { $this->markTestSkipped('The "mb_check_encoding" function is not available'); } - $data = mb_convert_encoding(pack('H*', implode('', $chars)), 'UTF-8', 'UCS-2BE'); - $data = $data."ab\ncd".$data; + // Convert hexadecimal representation into binary + // H: hex string, high nibble first (UCS-2BE) + // *: repeat until end of string + $binary = pack('H*', $hex); + + // Convert UCS-2BE to UTF-8 + $symbol = mb_convert_encoding($binary, 'UTF-8', 'UCS-2BE'); + $symbol = $symbol."ab\ncd".$symbol; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); - $event = new FormEvent($form, $data); + $event = new FormEvent($form, $symbol); $filter = new TrimListener(); $filter->preSubmit($event); - $this->assertSame("ab\ncd", $event->getData(), 'TrimListener should trim character(s): '.implode(', ', $chars)); + $this->assertSame("ab\ncd", $event->getData()); } - public function codePointProvider() + public function spaceProvider() { return array( - 'General category: Separator' => array(array('0020', '00A0', '1680', '180E', '2000', '2001', '2002', '2003', '2004', '2005', '2006', '2007', '2008', '2009', '200A', '2028', '2029', '202F', '205F', '3000')), - 'General category: Other, control' => array(array('0009', '000A', '000B', '000C', '000D', '0085')), - //'General category: Other, format. ZERO WIDTH SPACE' => array(array('200B')), + // separators + array('0020'), + array('00A0'), + array('1680'), +// array('180E'), + array('2000'), + array('2001'), + array('2002'), + array('2003'), + array('2004'), + array('2005'), + array('2006'), + array('2007'), + array('2008'), + array('2009'), + array('200A'), + array('2028'), + array('2029'), + array('202F'), + array('205F'), + array('3000'), + // controls + array('0009'), + array('000A'), + array('000B'), + array('000C'), + array('000D'), + array('0085'), + // zero width space +// array('200B'), ); } } From ab983060f6c8ffd094492bb57d99ade896f94355 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 12 May 2014 10:37:25 +0200 Subject: [PATCH 297/447] Lower mbstring dep, remove it for Yaml and CssSelector components --- .../NumberToLocalizedStringTransformer.php | 16 +++++----------- .../NumberToLocalizedStringTransformerTest.php | 8 ++++---- .../Core/EventListener/TrimListenerTest.php | 4 ++-- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php index bb8da2fc75..c3a7609a5f 100644 --- a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php @@ -133,25 +133,19 @@ public function reverseTransform($value) } if (function_exists('mb_detect_encoding') && false !== $encoding = mb_detect_encoding($value)) { - $strlen = function ($string) use ($encoding) { - return mb_strlen($string, $encoding); - }; - $substr = function ($string, $offset, $length) use ($encoding) { - return mb_substr($string, $offset, $length, $encoding); - }; + $length = mb_strlen($value, $encoding); + $remainder = mb_substr($value, $position, $length, $encoding); } else { - $strlen = 'strlen'; - $substr = 'substr'; + $length = strlen($value); + $remainder = substr($value, $position, $length); } - $length = $strlen($value); - // After parsing, position holds the index of the character where the // parsing stopped if ($position < $length) { // Check if there are unrecognized characters at the end of the // number (excluding whitespace characters) - $remainder = trim($substr($value, $position, $length), " \t\n\r\0\x0b\xc2\xa0"); + $remainder = trim($remainder, " \t\n\r\0\x0b\xc2\xa0"); if ('' !== $remainder) { throw new TransformationFailedException( diff --git a/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php index c58e3f60e7..971dd0a738 100644 --- a/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php @@ -119,7 +119,7 @@ public function testReverseTransformWithGrouping($to, $from, $locale) // https://github.com/symfony/symfony/issues/7609 public function testReverseTransformWithGroupingAndFixedSpaces() { - if (!extension_loaded('mbstring')) { + if (!function_exists('mb_detect_encoding')) { $this->markTestSkipped('The "mbstring" extension is required for this test.'); } @@ -335,7 +335,7 @@ public function testReverseTransformDisallowsCenteredExtraCharacters() */ public function testReverseTransformDisallowsCenteredExtraCharactersMultibyte() { - if (!extension_loaded('mbstring')) { + if (!function_exists('mb_detect_encoding')) { $this->markTestSkipped('The "mbstring" extension is required for this test.'); } @@ -352,7 +352,7 @@ public function testReverseTransformDisallowsCenteredExtraCharactersMultibyte() */ public function testReverseTransformIgnoresTrailingSpacesInExceptionMessage() { - if (!extension_loaded('mbstring')) { + if (!function_exists('mb_detect_encoding')) { $this->markTestSkipped('The "mbstring" extension is required for this test.'); } @@ -380,7 +380,7 @@ public function testReverseTransformDisallowsTrailingExtraCharacters() */ public function testReverseTransformDisallowsTrailingExtraCharactersMultibyte() { - if (!extension_loaded('mbstring')) { + if (!function_exists('mb_detect_encoding')) { $this->markTestSkipped('The "mbstring" extension is required for this test.'); } diff --git a/Tests/Extension/Core/EventListener/TrimListenerTest.php b/Tests/Extension/Core/EventListener/TrimListenerTest.php index 358620b9c4..606f6a2b05 100644 --- a/Tests/Extension/Core/EventListener/TrimListenerTest.php +++ b/Tests/Extension/Core/EventListener/TrimListenerTest.php @@ -52,8 +52,8 @@ public function testTrimSkipNonStrings() */ public function testTrimUtf8Separators($hex) { - if (!function_exists('mb_check_encoding')) { - $this->markTestSkipped('The "mb_check_encoding" function is not available'); + if (!function_exists('mb_convert_encoding')) { + $this->markTestSkipped('The "mb_convert_encoding" function is not available'); } // Convert hexadecimal representation into binary From 8af130d651c347b42c458a0e9e288ea9f6d895e2 Mon Sep 17 00:00:00 2001 From: Tugdual Saunier Date: Tue, 4 Mar 2014 11:12:50 +0000 Subject: [PATCH 298/447] [Form] Automatically add step attribute to HTML5 time widgets to display seconds if needed --- Extension/Core/Type/TimeType.php | 8 +++++++ Tests/Extension/Core/Type/TimeTypeTest.php | 27 ++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/Extension/Core/Type/TimeType.php b/Extension/Core/Type/TimeType.php index d7a2a9efba..6bf41517ac 100644 --- a/Extension/Core/Type/TimeType.php +++ b/Extension/Core/Type/TimeType.php @@ -140,6 +140,14 @@ public function buildView(FormView $view, FormInterface $form, array $options) if ('single_text' === $options['widget']) { $view->vars['type'] = 'time'; + + // we need to force the browser to display the seconds by + // adding the HTML attribute step if not already defined. + // Otherwise the browser will not display and so not send the seconds + // therefore the value will always be considered as invalid. + if ($options['with_seconds'] && !isset($view->vars['attr']['step'])) { + $view->vars['attr']['step'] = 1; + } } } diff --git a/Tests/Extension/Core/Type/TimeTypeTest.php b/Tests/Extension/Core/Type/TimeTypeTest.php index 9bdfe1567b..ca186207ac 100644 --- a/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/Tests/Extension/Core/Type/TimeTypeTest.php @@ -492,6 +492,33 @@ public function testSingleTextWidgetShouldUseTheRightInputType() $this->assertEquals('time', $view->vars['type']); } + public function testSingleTextWidgetWithSecondsShouldHaveRightStepAttribute() + { + $form = $this->factory->create('time', null, array( + 'widget' => 'single_text', + 'with_seconds' => true, + )); + + $view = $form->createView(); + $this->assertArrayHasKey('step', $view->vars['attr']); + $this->assertEquals(1, $view->vars['attr']['step']); + } + + public function testSingleTextWidgetWithSecondsShouldNotOverrideStepAttribute() + { + $form = $this->factory->create('time', null, array( + 'widget' => 'single_text', + 'with_seconds' => true, + 'attr' => array( + 'step' => 30 + ) + )); + + $view = $form->createView(); + $this->assertArrayHasKey('step', $view->vars['attr']); + $this->assertEquals(30, $view->vars['attr']['step']); + } + public function testPassDefaultEmptyValueToViewIfNotRequired() { $form = $this->factory->create('time', null, array( From f2f6a06ffe19dbb35f57be2f609e9a0c60a58065 Mon Sep 17 00:00:00 2001 From: Charles Sarrazin Date: Fri, 16 May 2014 13:58:11 +0200 Subject: [PATCH 299/447] Updated form dev dependencies --- composer.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 024298b0f3..d52484a375 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,9 @@ "require-dev": { "symfony/validator": "~2.2", "symfony/http-foundation": "~2.2", - "symfony/security-csrf": "~2.4" + "symfony/http-kernel": "~2.4", + "symfony/security-csrf": "~2.4", + "doctrine/collections": "~1.0" }, "suggest": { "symfony/validator": "For form validation.", From 4e5c947e82d55c3d0629a292edeabf4ca7811855 Mon Sep 17 00:00:00 2001 From: Charles Sarrazin Date: Fri, 16 May 2014 13:59:23 +0200 Subject: [PATCH 300/447] Fixed FormDataExtractorTest_SimpleValueExporter::exportValue not implementing the interface correctly --- Tests/Extension/DataCollector/FormDataExtractorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Extension/DataCollector/FormDataExtractorTest.php b/Tests/Extension/DataCollector/FormDataExtractorTest.php index bf3cd71975..6f6ca2f265 100644 --- a/Tests/Extension/DataCollector/FormDataExtractorTest.php +++ b/Tests/Extension/DataCollector/FormDataExtractorTest.php @@ -25,7 +25,7 @@ class FormDataExtractorTest_SimpleValueExporter extends ValueExporter /** * {@inheritdoc} */ - public function exportValue($value) + public function exportValue($value, $depth = 1, $deep = false) { return var_export($value, true); } From 55a056f6577a5750f8d89b069e12b2c649cffbe3 Mon Sep 17 00:00:00 2001 From: Charles Sarrazin Date: Fri, 16 May 2014 14:30:08 +0200 Subject: [PATCH 301/447] Added support for injecting HttpFoundation's RequestStack in ServerParams --- Extension/Validator/Util/ServerParams.php | 13 ++++++++++ .../Validator/Util/ServerParamsTest.php | 25 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/Extension/Validator/Util/ServerParams.php b/Extension/Validator/Util/ServerParams.php index 93a1dd7d6f..6623edd568 100644 --- a/Extension/Validator/Util/ServerParams.php +++ b/Extension/Validator/Util/ServerParams.php @@ -11,11 +11,20 @@ namespace Symfony\Component\Form\Extension\Validator\Util; +use Symfony\Component\HttpFoundation\RequestStack; + /** * @author Bernhard Schussek */ class ServerParams { + private $requestStack; + + public function __construct(RequestStack $requestStack = null) + { + $this->requestStack = $requestStack; + } + /** * Returns maximum post size in bytes. * @@ -65,6 +74,10 @@ public function getNormalizedIniPostMaxSize() */ public function getContentLength() { + if (null !== $this->requestStack && null !== $request = $this->requestStack->getCurrentRequest()) { + return $request->server->get('CONTENT_LENGTH'); + } + return isset($_SERVER['CONTENT_LENGTH']) ? (int) $_SERVER['CONTENT_LENGTH'] : null; diff --git a/Tests/Extension/Validator/Util/ServerParamsTest.php b/Tests/Extension/Validator/Util/ServerParamsTest.php index 7ad5b77106..957b59702e 100644 --- a/Tests/Extension/Validator/Util/ServerParamsTest.php +++ b/Tests/Extension/Validator/Util/ServerParamsTest.php @@ -11,8 +11,33 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\Util; +use Symfony\Component\Form\Extension\Validator\Util\ServerParams; +use Symfony\Component\HttpFoundation\Request; + class ServerParamsTest extends \PHPUnit_Framework_TestCase { + public function testGetContentLengthFromSuperglobals() + { + $serverParams = new ServerParams(); + $this->assertNull($serverParams->getContentLength()); + + $_SERVER['CONTENT_LENGTH'] = 1024; + + $this->assertEquals(1024, $serverParams->getContentLength()); + + unset($_SERVER['CONTENT_LENGTH']); + } + + public function testGetContentLengthFromRequest() + { + $request = Request::create('http://foo', 'GET', array(), array(), array(), array('CONTENT_LENGTH' => 1024)); + $requestStack = $this->getMock('Symfony\Component\HttpFoundation\RequestStack', array('getCurrentRequest')); + $requestStack->expects($this->once())->method('getCurrentRequest')->will($this->returnValue($request)); + $serverParams = new ServerParams($requestStack); + + $this->assertEquals(1024, $serverParams->getContentLength()); + } + /** @dataProvider getGetPostMaxSizeTestData */ public function testGetPostMaxSize($size, $bytes) { From 44480e1c101baeb366ae252764448e4a90a3aa4c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 23 May 2014 16:36:49 +0200 Subject: [PATCH 302/447] updated version to 2.6 --- README.md | 2 +- composer.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 340bc6e631..ff353701f2 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ https://github.com/fabpot/Silex/blob/master/src/Silex/Provider/FormServiceProvid Documentation: -http://symfony.com/doc/2.5/book/forms.html +http://symfony.com/doc/2.6/book/forms.html Resources --------- diff --git a/composer.json b/composer.json index 56176c234f..14412e1f61 100644 --- a/composer.json +++ b/composer.json @@ -42,7 +42,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "2.5-dev" + "dev-master": "2.6-dev" } } } From 93a63da5dd81bc82c1efc4109e8a588e747da55c Mon Sep 17 00:00:00 2001 From: "Hans N. Hjort" Date: Thu, 12 Jun 2014 11:43:49 +0200 Subject: [PATCH 303/447] Minor doc fix. --- FormTypeInterface.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/FormTypeInterface.php b/FormTypeInterface.php index bcef73c6d7..5f6850b7cd 100644 --- a/FormTypeInterface.php +++ b/FormTypeInterface.php @@ -21,7 +21,7 @@ interface FormTypeInterface /** * Builds the form. * - * This method is called for each type in the hierarchy starting form the + * This method is called for each type in the hierarchy starting from the * top most type. Type extensions can further modify the form. * * @see FormTypeExtensionInterface::buildForm() @@ -34,7 +34,7 @@ public function buildForm(FormBuilderInterface $builder, array $options); /** * Builds the form view. * - * This method is called for each type in the hierarchy starting form the + * This method is called for each type in the hierarchy starting from the * top most type. Type extensions can further modify the view. * * A view of a form is built before the views of the child forms are built. @@ -52,7 +52,7 @@ public function buildView(FormView $view, FormInterface $form, array $options); /** * Finishes the form view. * - * This method gets called for each type in the hierarchy starting form the + * This method gets called for each type in the hierarchy starting from the * top most type. Type extensions can further modify the view. * * When this method is called, views of the form's children have already From 8231fd6acf923f8e5df681f267fde892e570cbcb Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 20 Jun 2014 15:25:51 +0200 Subject: [PATCH 304/447] don't disable constructor calls to mockups of classes that extend internal PHP classes --- Tests/Extension/Core/Type/FileTypeTest.php | 2 +- .../HttpFoundation/HttpFoundationRequestHandlerTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/Extension/Core/Type/FileTypeTest.php b/Tests/Extension/Core/Type/FileTypeTest.php index 63556eb5a6..ed38ab2886 100644 --- a/Tests/Extension/Core/Type/FileTypeTest.php +++ b/Tests/Extension/Core/Type/FileTypeTest.php @@ -59,7 +59,7 @@ private function createUploadedFileMock($name, $originalName, $valid) { $file = $this ->getMockBuilder('Symfony\Component\HttpFoundation\File\UploadedFile') - ->disableOriginalConstructor() + ->setConstructorArgs(array(__DIR__.'/../../../Fixtures/foo', 'foo')) ->getMock() ; $file diff --git a/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php b/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php index 2d5cf7764b..b25380aea7 100644 --- a/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php +++ b/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php @@ -48,7 +48,7 @@ protected function getRequestHandler() protected function getMockFile() { return $this->getMockBuilder('Symfony\Component\HttpFoundation\File\UploadedFile') - ->disableOriginalConstructor() + ->setConstructorArgs(array(__DIR__.'/../../Fixtures/foo', 'foo')) ->getMock(); } } From 570116fc90efc5070abcebc73a9d2eab5ebf8fbc Mon Sep 17 00:00:00 2001 From: Julien Pauli Date: Wed, 25 Jun 2014 18:49:15 +0200 Subject: [PATCH 305/447] Fix mocks to support >=5.5.14 and >=5.4.30 --- .../HttpFoundation/HttpFoundationRequestHandlerTest.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php b/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php index b25380aea7..cf5d63d90e 100644 --- a/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php +++ b/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php @@ -14,6 +14,7 @@ use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; use Symfony\Component\Form\Tests\AbstractRequestHandlerTest; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\File\UploadedFile; /** * @author Bernhard Schussek @@ -47,8 +48,6 @@ protected function getRequestHandler() protected function getMockFile() { - return $this->getMockBuilder('Symfony\Component\HttpFoundation\File\UploadedFile') - ->setConstructorArgs(array(__DIR__.'/../../Fixtures/foo', 'foo')) - ->getMock(); + return new UploadedFile(__DIR__.'/../../Fixtures/foo', 'foo'); } } From 105ec067111ec9dd03916ac3c525dd2c5d5c2e47 Mon Sep 17 00:00:00 2001 From: Christian Raue Date: Sun, 6 Jul 2014 11:04:43 +0200 Subject: [PATCH 306/447] added XSD to PHPUnit configuration --- phpunit.xml.dist | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index d0d261f194..83736cbe5f 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,6 +1,8 @@ - From 45fa09375100a6bffba2d18f8747565f15744506 Mon Sep 17 00:00:00 2001 From: Christian Raue Date: Mon, 7 Jul 2014 12:13:42 +0200 Subject: [PATCH 307/447] removed defaults from PHPUnit configuration --- phpunit.xml.dist | 6 ------ 1 file changed, 6 deletions(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 83736cbe5f..bd91d7b831 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -3,13 +3,7 @@ From 26a38f42330a8ba6ea629ebeb78ab105aa5d41af Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Sun, 6 Jul 2014 15:41:58 +0200 Subject: [PATCH 308/447] [Form] Check if IntlDateFormatter constructor returned a valid object before using it --- .../DateTimeToLocalizedStringTransformer.php | 8 ++++++++ Extension/Core/Type/DateType.php | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php index 56a3ca928b..e992b01fc1 100644 --- a/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php @@ -152,6 +152,8 @@ public function reverseTransform($value) * Returns a preconfigured IntlDateFormatter instance * * @return \IntlDateFormatter + * + * @throws TransformationFailedException in case the date formatter can not be constructed. */ protected function getIntlDateFormatter() { @@ -162,6 +164,12 @@ protected function getIntlDateFormatter() $pattern = $this->pattern; $intlDateFormatter = new \IntlDateFormatter(\Locale::getDefault(), $dateFormat, $timeFormat, $timezone, $calendar, $pattern); + + // new \intlDateFormatter may return null instead of false in case of failure, see https://bugs.php.net/bug.php?id=66323 + if (!$intlDateFormatter) { + throw new TransformationFailedException(intl_get_error_message(), intl_get_error_code()); + } + $intlDateFormatter->setLenient(false); return $intlDateFormatter; diff --git a/Extension/Core/Type/DateType.php b/Extension/Core/Type/DateType.php index 022a414932..1748d2e31f 100644 --- a/Extension/Core/Type/DateType.php +++ b/Extension/Core/Type/DateType.php @@ -77,6 +77,12 @@ public function buildForm(FormBuilderInterface $builder, array $options) $calendar, $pattern ); + + // new \intlDateFormatter may return null instead of false in case of failure, see https://bugs.php.net/bug.php?id=66323 + if (!$formatter) { + throw new InvalidOptionsException(intl_get_error_message(), intl_get_error_code()); + } + $formatter->setLenient(false); if ('choice' === $options['widget']) { From d50008c7c40bd1f67cd22f697caf4cce6bf07cb6 Mon Sep 17 00:00:00 2001 From: jubianchi Date: Sat, 5 Jul 2014 16:13:07 +0200 Subject: [PATCH 309/447] [WIP][Form] Improve transformation failure message by providing property path --- Form.php | 58 +++++++++++++++++++++---- Tests/Fixtures/FixedDataTransformer.php | 6 +-- Tests/SimpleFormTest.php | 22 ++++++++++ 3 files changed, 74 insertions(+), 12 deletions(-) diff --git a/Form.php b/Form.php index 3e9f9b1058..6c893221ac 100644 --- a/Form.php +++ b/Form.php @@ -1049,12 +1049,22 @@ public function createView(FormView $parent = null) * * @param mixed $value The value to transform * + * @throws TransformationFailedException If the value cannot be transformed to "normalized" format + * * @return mixed */ private function modelToNorm($value) { - foreach ($this->config->getModelTransformers() as $transformer) { - $value = $transformer->transform($value); + try { + foreach ($this->config->getModelTransformers() as $transformer) { + $value = $transformer->transform($value); + } + } catch (TransformationFailedException $exception) { + throw new TransformationFailedException( + 'Unable to transform value for property path "' . $this->getPropertyPath() . '": ' . $exception->getMessage(), + $exception->getCode(), + $exception + ); } return $value; @@ -1065,14 +1075,24 @@ private function modelToNorm($value) * * @param string $value The value to reverse transform * + * @throws TransformationFailedException If the value cannot be transformed to "model" format + * * @return mixed */ private function normToModel($value) { - $transformers = $this->config->getModelTransformers(); + try { + $transformers = $this->config->getModelTransformers(); - for ($i = count($transformers) - 1; $i >= 0; --$i) { - $value = $transformers[$i]->reverseTransform($value); + for ($i = count($transformers) - 1; $i >= 0; --$i) { + $value = $transformers[$i]->reverseTransform($value); + } + } catch (TransformationFailedException $exception) { + throw new TransformationFailedException( + 'Unable to reverse value for property path "' . $this->getPropertyPath() . '": ' . $exception->getMessage(), + $exception->getCode(), + $exception + ); } return $value; @@ -1083,6 +1103,8 @@ private function normToModel($value) * * @param mixed $value The value to transform * + * @throws TransformationFailedException If the value cannot be transformed to "view" format + * * @return mixed */ private function normToView($value) @@ -1096,8 +1118,16 @@ private function normToView($value) return null === $value || is_scalar($value) ? (string) $value : $value; } - foreach ($this->config->getViewTransformers() as $transformer) { - $value = $transformer->transform($value); + try { + foreach ($this->config->getViewTransformers() as $transformer) { + $value = $transformer->transform($value); + } + } catch (TransformationFailedException $exception) { + throw new TransformationFailedException( + 'Unable to transform value for property path "' . $this->getPropertyPath() . '": ' . $exception->getMessage(), + $exception->getCode(), + $exception + ); } return $value; @@ -1108,6 +1138,8 @@ private function normToView($value) * * @param string $value The value to reverse transform * + * @throws TransformationFailedException If the value cannot be transformed to "normalized" format + * * @return mixed */ private function viewToNorm($value) @@ -1118,8 +1150,16 @@ private function viewToNorm($value) return '' === $value ? null : $value; } - for ($i = count($transformers) - 1; $i >= 0; --$i) { - $value = $transformers[$i]->reverseTransform($value); + try { + for ($i = count($transformers) - 1; $i >= 0; --$i) { + $value = $transformers[$i]->reverseTransform($value); + } + } catch (TransformationFailedException $exception) { + throw new TransformationFailedException( + 'Unable to reverse value for property path "' . $this->getPropertyPath() . '": ' . $exception->getMessage(), + $exception->getCode(), + $exception + ); } return $value; diff --git a/Tests/Fixtures/FixedDataTransformer.php b/Tests/Fixtures/FixedDataTransformer.php index a5a31248f5..f7fba56c42 100644 --- a/Tests/Fixtures/FixedDataTransformer.php +++ b/Tests/Fixtures/FixedDataTransformer.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\DataTransformerInterface; -use Symfony\Component\Form\Exception\RuntimeException; +use Symfony\Component\Form\Exception\TransformationFailedException; class FixedDataTransformer implements DataTransformerInterface { @@ -26,7 +26,7 @@ public function __construct(array $mapping) public function transform($value) { if (!array_key_exists($value, $this->mapping)) { - throw new RuntimeException(sprintf('No mapping for value "%s"', $value)); + throw new TransformationFailedException(sprintf('No mapping for value "%s"', $value)); } return $this->mapping[$value]; @@ -37,7 +37,7 @@ public function reverseTransform($value) $result = array_search($value, $this->mapping, true); if ($result === false) { - throw new RuntimeException(sprintf('No reverse mapping for value "%s"', $value)); + throw new TransformationFailedException(sprintf('No reverse mapping for value "%s"', $value)); } return $result; diff --git a/Tests/SimpleFormTest.php b/Tests/SimpleFormTest.php index 11b616b1b3..6f2ffdd5cf 100644 --- a/Tests/SimpleFormTest.php +++ b/Tests/SimpleFormTest.php @@ -74,6 +74,28 @@ public function testDataIsInitializedToConfiguredValue() $this->assertSame('bar', $form->getViewData()); } + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + * @expectedExceptionMessage Unable to transform value for property path "name": No mapping for value "arg" + */ + public function testDataTransformationFailure() + { + $model = new FixedDataTransformer(array( + 'default' => 'foo', + )); + $view = new FixedDataTransformer(array( + 'foo' => 'bar', + )); + + $config = new FormConfigBuilder('name', null, $this->dispatcher); + $config->addViewTransformer($view); + $config->addModelTransformer($model); + $config->setData('arg'); + $form = new Form($config); + + $form->getData(); + } + // https://github.com/symfony/symfony/commit/d4f4038f6daf7cf88ca7c7ab089473cce5ebf7d8#commitcomment-1632879 public function testDataIsInitializedFromSubmit() { From 9c8544d3e373da3a7eef239ab5413ad6b227d492 Mon Sep 17 00:00:00 2001 From: Joseph Bielawski Date: Wed, 9 Jul 2014 12:03:33 +0200 Subject: [PATCH 310/447] [2.3][Form] Cleanup & fix phpdocs --- Button.php | 16 +++--- ButtonBuilder.php | 56 +++++++++---------- CallbackTransformer.php | 8 +-- ClickableInterface.php | 2 +- Extension/Core/ChoiceList/ChoiceList.php | 18 +++--- .../Core/ChoiceList/ObjectChoiceList.php | 6 +- .../Core/ChoiceList/SimpleChoiceList.php | 4 +- .../BaseDateTimeTransformer.php | 2 +- .../BooleanToStringTransformer.php | 4 +- .../DateTimeToArrayTransformer.php | 8 +-- .../DateTimeToTimestampTransformer.php | 2 +- .../MoneyToLocalizedStringTransformer.php | 5 +- .../NumberToLocalizedStringTransformer.php | 4 +- .../PercentToLocalizedStringTransformer.php | 12 ++-- .../EventListener/MergeCollectionListener.php | 8 +-- FormBuilder.php | 1 + FormBuilderInterface.php | 6 +- FormConfigBuilder.php | 10 ++-- FormConfigBuilderInterface.php | 29 +++++----- FormConfigInterface.php | 43 +++++++------- FormError.php | 10 ++-- FormExtensionInterface.php | 4 +- FormFactoryBuilder.php | 8 +-- FormRegistry.php | 6 +- FormRegistryInterface.php | 2 +- FormRendererEngineInterface.php | 52 ++++++++--------- FormRendererInterface.php | 4 +- FormTypeExtensionInterface.php | 12 ++-- FormTypeGuesserChain.php | 2 +- FormTypeInterface.php | 12 ++-- FormView.php | 6 +- Guess/Guess.php | 6 +- Guess/TypeGuess.php | 10 ++-- Guess/ValueGuess.php | 6 +- PreloadedExtension.php | 4 +- ResolvedFormType.php | 3 - ResolvedFormTypeInterface.php | 8 ++- Test/FormBuilderInterface.php | 4 +- Test/FormIntegrationTestCase.php | 3 +- Test/FormInterface.php | 4 +- Test/FormPerformanceTestCase.php | 9 ++- 41 files changed, 208 insertions(+), 211 deletions(-) diff --git a/Button.php b/Button.php index 5003460637..b6404a97d9 100644 --- a/Button.php +++ b/Button.php @@ -51,7 +51,7 @@ public function __construct(FormConfigInterface $config) * * @param mixed $offset * - * @return bool Always returns false. + * @return bool Always returns false. */ public function offsetExists($offset) { @@ -152,7 +152,7 @@ public function get($name) * * @param string $name * - * @return bool Always returns false. + * @return bool Always returns false. */ public function has($name) { @@ -254,7 +254,7 @@ public function getConfig() /** * Returns whether the button is submitted. * - * @return bool true if the button was submitted. + * @return bool true if the button was submitted. */ public function isSubmitted() { @@ -295,7 +295,7 @@ public function addError(FormError $error) /** * Unsupported method. * - * @return bool Always returns true. + * @return bool Always returns true. */ public function isValid() { @@ -305,7 +305,7 @@ public function isValid() /** * Unsupported method. * - * @return bool Always returns false. + * @return bool Always returns false. */ public function isRequired() { @@ -327,7 +327,7 @@ public function isDisabled() /** * Unsupported method. * - * @return bool Always returns true. + * @return bool Always returns true. */ public function isEmpty() { @@ -337,7 +337,7 @@ public function isEmpty() /** * Unsupported method. * - * @return bool Always returns true. + * @return bool Always returns true. */ public function isSynchronized() { @@ -418,7 +418,7 @@ public function createView(FormView $parent = null) /** * Unsupported method. * - * @return int Always returns 0. + * @return int Always returns 0. */ public function count() { diff --git a/ButtonBuilder.php b/ButtonBuilder.php index 325b4a3c16..9302af4190 100644 --- a/ButtonBuilder.php +++ b/ButtonBuilder.php @@ -75,9 +75,9 @@ public function __construct($name, array $options = array()) * * This method should not be invoked. * - * @param string|int|FormBuilderInterface $child - * @param string|FormTypeInterface $type - * @param array $options + * @param string|int|FormBuilderInterface $child + * @param string|FormTypeInterface $type + * @param array $options * * @throws BadMethodCallException */ @@ -135,7 +135,7 @@ public function remove($name) * * @param string $name * - * @return bool Always returns false. + * @return bool Always returns false. */ public function has($name) { @@ -283,7 +283,7 @@ public function setDataMapper(DataMapperInterface $dataMapper = null) /** * Set whether the button is disabled. * - * @param bool $disabled Whether the button is disabled + * @param bool $disabled Whether the button is disabled * * @return ButtonBuilder The button builder. */ @@ -313,7 +313,7 @@ public function setEmptyData($emptyData) * * This method should not be invoked. * - * @param bool $errorBubbling + * @param bool $errorBubbling * * @throws BadMethodCallException */ @@ -327,7 +327,7 @@ public function setErrorBubbling($errorBubbling) * * This method should not be invoked. * - * @param bool $required + * @param bool $required * * @throws BadMethodCallException */ @@ -355,7 +355,7 @@ public function setPropertyPath($propertyPath) * * This method should not be invoked. * - * @param bool $mapped + * @param bool $mapped * * @throws BadMethodCallException */ @@ -369,7 +369,7 @@ public function setMapped($mapped) * * This method should not be invoked. * - * @param bool $byReference + * @param bool $byReference * * @throws BadMethodCallException */ @@ -383,7 +383,7 @@ public function setByReference($byReference) * * This method should not be invoked. * - * @param bool $virtual + * @param bool $virtual * * @throws BadMethodCallException */ @@ -397,7 +397,7 @@ public function setVirtual($virtual) * * This method should not be invoked. * - * @param bool $compound + * @param bool $compound * * @throws BadMethodCallException */ @@ -439,7 +439,7 @@ public function setData($data) * * This method should not be invoked. * - * @param bool $locked + * @param bool $locked * * @throws BadMethodCallException */ @@ -455,8 +455,6 @@ public function setDataLocked($locked) * * @param FormFactoryInterface $formFactory * - * @return void - * * @throws BadMethodCallException */ public function setFormFactory(FormFactoryInterface $formFactory) @@ -503,7 +501,7 @@ public function setRequestHandler(RequestHandlerInterface $requestHandler) /** * Unsupported method. * - * @param bool $initialize + * @param bool $initialize * * @throws BadMethodCallException */ @@ -519,7 +517,7 @@ public function setAutoInitialize($initialize) /** * Unsupported method. * - * @param bool $inheritData + * @param bool $inheritData * * @throws BadMethodCallException */ @@ -571,7 +569,7 @@ public function getPropertyPath() /** * Unsupported method. * - * @return bool Always returns false. + * @return bool Always returns false. */ public function getMapped() { @@ -581,7 +579,7 @@ public function getMapped() /** * Unsupported method. * - * @return bool Always returns false. + * @return bool Always returns false. */ public function getByReference() { @@ -591,7 +589,7 @@ public function getByReference() /** * Unsupported method. * - * @return bool Always returns false. + * @return bool Always returns false. */ public function getVirtual() { @@ -601,7 +599,7 @@ public function getVirtual() /** * Unsupported method. * - * @return bool Always returns false. + * @return bool Always returns false. */ public function getCompound() { @@ -650,7 +648,7 @@ public function getDataMapper() /** * Unsupported method. * - * @return bool Always returns false. + * @return bool Always returns false. */ public function getRequired() { @@ -660,7 +658,7 @@ public function getRequired() /** * Returns whether the button is disabled. * - * @return bool Whether the button is disabled. + * @return bool Whether the button is disabled. */ public function getDisabled() { @@ -670,7 +668,7 @@ public function getDisabled() /** * Unsupported method. * - * @return bool Always returns false. + * @return bool Always returns false. */ public function getErrorBubbling() { @@ -701,7 +699,7 @@ public function getAttributes() * * @param string $name The attribute name. * - * @return bool Whether the attribute exists. + * @return bool Whether the attribute exists. */ public function hasAttribute($name) { @@ -742,7 +740,7 @@ public function getDataClass() /** * Unsupported method. * - * @return bool Always returns false. + * @return bool Always returns false. */ public function getDataLocked() { @@ -788,7 +786,7 @@ public function getRequestHandler() /** * Unsupported method. * - * @return bool Always returns false. + * @return bool Always returns false. */ public function getAutoInitialize() { @@ -798,7 +796,7 @@ public function getAutoInitialize() /** * Unsupported method. * - * @return bool Always returns false. + * @return bool Always returns false. */ public function getInheritData() { @@ -820,7 +818,7 @@ public function getOptions() * * @param string $name The option name, * - * @return bool Whether the option exists. + * @return bool Whether the option exists. */ public function hasOption($name) { @@ -843,7 +841,7 @@ public function getOption($name, $default = null) /** * Unsupported method. * - * @return int Always returns 0. + * @return int Always returns 0. */ public function count() { diff --git a/CallbackTransformer.php b/CallbackTransformer.php index b35da45bc7..c53c6df788 100644 --- a/CallbackTransformer.php +++ b/CallbackTransformer.php @@ -47,8 +47,8 @@ public function __construct(\Closure $transform, \Closure $reverseTransform) * * @return mixed The value in the transformed representation * - * @throws UnexpectedTypeException when the argument is not a string - * @throws TransformationFailedException when the transformation fails + * @throws UnexpectedTypeException when the argument is not a string + * @throws TransformationFailedException when the transformation fails */ public function transform($data) { @@ -63,8 +63,8 @@ public function transform($data) * * @return mixed The value in the original representation * - * @throws UnexpectedTypeException when the argument is not of the expected type - * @throws TransformationFailedException when the transformation fails + * @throws UnexpectedTypeException when the argument is not of the expected type + * @throws TransformationFailedException when the transformation fails */ public function reverseTransform($data) { diff --git a/ClickableInterface.php b/ClickableInterface.php index 9df55449fb..6e45eff1a7 100644 --- a/ClickableInterface.php +++ b/ClickableInterface.php @@ -21,7 +21,7 @@ interface ClickableInterface /** * Returns whether this element was clicked. * - * @return bool Whether this element was clicked. + * @return bool Whether this element was clicked. */ public function isClicked(); } diff --git a/Extension/Core/ChoiceList/ChoiceList.php b/Extension/Core/ChoiceList/ChoiceList.php index d3d8e7dd09..db21fc2c99 100644 --- a/Extension/Core/ChoiceList/ChoiceList.php +++ b/Extension/Core/ChoiceList/ChoiceList.php @@ -75,10 +75,10 @@ class ChoiceList implements ChoiceListInterface * the sub-hierarchy can be stored in the array * key pointing to the nested array. The topmost * level of the hierarchy may also be a \Traversable. - * @param array $labels The array of labels. The structure of this array - * should match the structure of $choices. - * @param array $preferredChoices A flat array of choices that should be - * presented to the user with priority. + * @param array $labels The array of labels. The structure of this array + * should match the structure of $choices. + * @param array $preferredChoices A flat array of choices that should be + * presented to the user with priority. * * @throws UnexpectedTypeException If the choices are not an array or \Traversable. */ @@ -255,7 +255,7 @@ public function getIndicesForValues(array $values) * @param array $labels The labels corresponding to the choices. * @param array $preferredChoices The preferred choices. * - * @throws InvalidArgumentException If the structures of the choices and labels array do not match. + * @throws InvalidArgumentException If the structures of the choices and labels array do not match. * @throws InvalidConfigurationException If no valid value or index could be created for a choice. */ protected function addChoices(array &$bucketForPreferred, array &$bucketForRemaining, $choices, array $labels, array $preferredChoices) @@ -377,7 +377,7 @@ protected function addChoice(array &$bucketForPreferred, array &$bucketForRemain * @param mixed $choice The choice to test. * @param array $preferredChoices An array of preferred choices. * - * @return bool Whether the choice is preferred. + * @return bool Whether the choice is preferred. */ protected function isPreferred($choice, array $preferredChoices) { @@ -391,8 +391,8 @@ protected function isPreferred($choice, array $preferredChoices) * * @param mixed $choice The choice to create an index for * - * @return int|string A unique index containing only ASCII letters, - * digits and underscores. + * @return int|string A unique index containing only ASCII letters, + * digits and underscores. */ protected function createIndex($choice) { @@ -451,7 +451,7 @@ protected function fixValues(array $values) * * @param mixed $index The choice index. * - * @return int|string The index as PHP array key. + * @return int|string The index as PHP array key. */ protected function fixIndex($index) { diff --git a/Extension/Core/ChoiceList/ObjectChoiceList.php b/Extension/Core/ChoiceList/ObjectChoiceList.php index 22035b8f75..14c6f238d3 100644 --- a/Extension/Core/ChoiceList/ObjectChoiceList.php +++ b/Extension/Core/ChoiceList/ObjectChoiceList.php @@ -72,7 +72,7 @@ class ObjectChoiceList extends ChoiceList * be a \Traversable. * @param string $labelPath A property path pointing to the property used * for the choice labels. The value is obtained - * by calling the getter on the object. If the + * by calling the getter on the object. If the * path is NULL, the object's __toString() method * is used instead. * @param array $preferredChoices A flat array of choices that should be @@ -105,7 +105,7 @@ public function __construct($choices, $labelPath = null, array $preferredChoices * @param array $preferredChoices The choices to display with priority. * * @throws InvalidArgumentException When passing a hierarchy of choices and using - * the "groupPath" option at the same time. + * the "groupPath" option at the same time. */ protected function initialize($choices, array $labels, array $preferredChoices) { @@ -157,7 +157,7 @@ protected function initialize($choices, array $labels, array $preferredChoices) * * @param mixed $choice The choice to create a value for * - * @return int|string A unique value without character limitations. + * @return int|string A unique value without character limitations. */ protected function createValue($choice) { diff --git a/Extension/Core/ChoiceList/SimpleChoiceList.php b/Extension/Core/ChoiceList/SimpleChoiceList.php index dbe54265b1..7a5fb346ce 100644 --- a/Extension/Core/ChoiceList/SimpleChoiceList.php +++ b/Extension/Core/ChoiceList/SimpleChoiceList.php @@ -124,7 +124,7 @@ protected function addChoices(array &$bucketForPreferred, array &$bucketForRemai * @param mixed $choice The choice to test. * @param array $preferredChoices An array of preferred choices. * - * @return bool Whether the choice is preferred. + * @return bool Whether the choice is preferred. */ protected function isPreferred($choice, array $preferredChoices) { @@ -137,7 +137,7 @@ protected function isPreferred($choice, array $preferredChoices) * * @param mixed $choice The choice. * - * @return string|int A valid PHP array key. + * @return string|int A valid PHP array key. */ protected function fixChoice($choice) { diff --git a/Extension/Core/DataTransformer/BaseDateTimeTransformer.php b/Extension/Core/DataTransformer/BaseDateTimeTransformer.php index 9c1b92d741..0cf9741dce 100644 --- a/Extension/Core/DataTransformer/BaseDateTimeTransformer.php +++ b/Extension/Core/DataTransformer/BaseDateTimeTransformer.php @@ -35,7 +35,7 @@ abstract class BaseDateTimeTransformer implements DataTransformerInterface * @param string $inputTimezone The name of the input timezone * @param string $outputTimezone The name of the output timezone * - * @throws UnexpectedTypeException if a timezone is not a string + * @throws UnexpectedTypeException if a timezone is not a string * @throws InvalidArgumentException if a timezone is not valid */ public function __construct($inputTimezone = null, $outputTimezone = null) diff --git a/Extension/Core/DataTransformer/BooleanToStringTransformer.php b/Extension/Core/DataTransformer/BooleanToStringTransformer.php index c6b47803af..d839427877 100644 --- a/Extension/Core/DataTransformer/BooleanToStringTransformer.php +++ b/Extension/Core/DataTransformer/BooleanToStringTransformer.php @@ -41,7 +41,7 @@ public function __construct($trueValue) /** * Transforms a Boolean into a string. * - * @param bool $value Boolean value. + * @param bool $value Boolean value. * * @return string String value. * @@ -65,7 +65,7 @@ public function transform($value) * * @param string $value String value. * - * @return bool Boolean value. + * @return bool Boolean value. * * @throws TransformationFailedException If the given value is not a string. */ diff --git a/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php b/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php index ea2ab40e6f..eeeb9fafac 100644 --- a/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php @@ -29,10 +29,10 @@ class DateTimeToArrayTransformer extends BaseDateTimeTransformer /** * Constructor. * - * @param string $inputTimezone The input timezone - * @param string $outputTimezone The output timezone - * @param array $fields The date fields - * @param bool $pad Whether to use padding + * @param string $inputTimezone The input timezone + * @param string $outputTimezone The output timezone + * @param array $fields The date fields + * @param bool $pad Whether to use padding * * @throws UnexpectedTypeException if a timezone is not a string */ diff --git a/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php b/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php index 7c40b4f6ca..38073f8291 100644 --- a/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php @@ -26,7 +26,7 @@ class DateTimeToTimestampTransformer extends BaseDateTimeTransformer * * @param \DateTime $value A \DateTime object * - * @return int A timestamp + * @return int A timestamp * * @throws TransformationFailedException If the given value is not an instance * of \DateTime or if the output diff --git a/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php index 5b8e9d9664..d746961d2d 100644 --- a/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php @@ -21,7 +21,6 @@ */ class MoneyToLocalizedStringTransformer extends NumberToLocalizedStringTransformer { - private $divisor; public function __construct($precision = null, $grouping = null, $roundingMode = null, $divisor = null) @@ -46,7 +45,7 @@ public function __construct($precision = null, $grouping = null, $roundingMode = /** * Transforms a normalized format into a localized money string. * - * @param number $value Normalized number + * @param int|float $value Normalized number * * @return string Localized money string. * @@ -71,7 +70,7 @@ public function transform($value) * * @param string $value Localized money string * - * @return number Normalized number + * @return int|float Normalized number * * @throws TransformationFailedException If the given value is not a string * or if the value can not be transformed. diff --git a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php index c3a7609a5f..8b30c7f696 100644 --- a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php @@ -55,7 +55,7 @@ public function __construct($precision = null, $grouping = null, $roundingMode = /** * Transforms a number type into localized number. * - * @param int|float $value Number value. + * @param int|float $value Number value. * * @return string Localized value. * @@ -90,7 +90,7 @@ public function transform($value) * * @param string $value The localized value * - * @return int|float The numeric value + * @return int|float The numeric value * * @throws TransformationFailedException If the given value is not a string * or if the value can not be transformed. diff --git a/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php index bbf4761fa0..2e02478e81 100644 --- a/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php @@ -40,8 +40,8 @@ class PercentToLocalizedStringTransformer implements DataTransformerInterface * * @see self::$types for a list of supported types * - * @param int $precision The precision - * @param string $type One of the supported types + * @param int $precision The precision + * @param string $type One of the supported types * * @throws UnexpectedTypeException if the given value of type is unknown */ @@ -66,9 +66,9 @@ public function __construct($precision = null, $type = null) /** * Transforms between a normalized format (integer or float) into a percentage value. * - * @param number $value Normalized value + * @param int|float $value Normalized value * - * @return number Percentage value + * @return string Percentage value * * @throws TransformationFailedException If the given value is not numeric or * if the value could not be transformed. @@ -101,9 +101,9 @@ public function transform($value) /** * Transforms between a percentage value into a normalized format (integer or float). * - * @param number $value Percentage value. + * @param string $value Percentage value. * - * @return number Normalized value. + * @return int|float Normalized value. * * @throws TransformationFailedException If the given value is not a string or * if the value could not be transformed. diff --git a/Extension/Core/EventListener/MergeCollectionListener.php b/Extension/Core/EventListener/MergeCollectionListener.php index b0fbdb54c3..982a78679b 100644 --- a/Extension/Core/EventListener/MergeCollectionListener.php +++ b/Extension/Core/EventListener/MergeCollectionListener.php @@ -36,10 +36,10 @@ class MergeCollectionListener implements EventSubscriberInterface /** * Creates a new listener. * - * @param bool $allowAdd Whether values might be added to the - * collection. - * @param bool $allowDelete Whether values might be removed from the - * collection. + * @param bool $allowAdd Whether values might be added to the + * collection. + * @param bool $allowDelete Whether values might be removed from the + * collection. */ public function __construct($allowAdd = false, $allowDelete = false) { diff --git a/FormBuilder.php b/FormBuilder.php index 2caefe48be..434afa861a 100644 --- a/FormBuilder.php +++ b/FormBuilder.php @@ -198,6 +198,7 @@ public function count() */ public function getFormConfig() { + /** @var $config self */ $config = parent::getFormConfig(); $config->children = array(); diff --git a/FormBuilderInterface.php b/FormBuilderInterface.php index 3294a3d3bd..998d3ec0d3 100644 --- a/FormBuilderInterface.php +++ b/FormBuilderInterface.php @@ -23,9 +23,9 @@ interface FormBuilderInterface extends \Traversable, \Countable, FormConfigBuild * If you add a nested group, this group should also be represented in the * object hierarchy. * - * @param string|int|FormBuilderInterface $child - * @param string|FormTypeInterface $type - * @param array $options + * @param string|int|FormBuilderInterface $child + * @param string|FormTypeInterface $type + * @param array $options * * @return FormBuilderInterface The builder object. */ diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index 730c63527a..733b79dfdd 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -186,7 +186,7 @@ class FormConfigBuilder implements FormConfigBuilderInterface * @param array $options The form options * * @throws InvalidArgumentException If the data class is not a valid class or if - * the name contains invalid characters. + * the name contains invalid characters. */ public function __construct($name, $dataClass, EventDispatcherInterface $dispatcher, array $options = array()) { @@ -713,7 +713,7 @@ public function setInheritData($inheritData) /** * Alias of {@link setInheritData()}. * - * @param bool $inheritData Whether the form should inherit its parent's data. + * @param bool $inheritData Whether the form should inherit its parent's data. * * @return FormConfigBuilder The configuration object. * @@ -879,9 +879,9 @@ public function getFormConfig() /** * Validates whether the given variable is a valid form name. * - * @param string|int $name The tested form name. + * @param string|int $name The tested form name. * - * @throws UnexpectedTypeException If the name is not a string or an integer. + * @throws UnexpectedTypeException If the name is not a string or an integer. * @throws InvalidArgumentException If the name contains invalid characters. */ public static function validateName($name) @@ -910,7 +910,7 @@ public static function validateName($name) * * @param string $name The tested form name. * - * @return bool Whether the name is valid. + * @return bool Whether the name is valid. */ public static function isValidName($name) { diff --git a/FormConfigBuilderInterface.php b/FormConfigBuilderInterface.php index 276a2fa446..da2da0b668 100644 --- a/FormConfigBuilderInterface.php +++ b/FormConfigBuilderInterface.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form; use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\PropertyAccess\PropertyPathInterface; /** * @author Bernhard Schussek @@ -88,7 +89,7 @@ public function resetModelTransformers(); * Sets the value for an attribute. * * @param string $name The name of the attribute - * @param string $value The value of the attribute + * @param mixed $value The value of the attribute * * @return self The configuration object. */ @@ -115,7 +116,7 @@ public function setDataMapper(DataMapperInterface $dataMapper = null); /** * Set whether the form is disabled. * - * @param bool $disabled Whether the form is disabled + * @param bool $disabled Whether the form is disabled * * @return self The configuration object. */ @@ -133,7 +134,7 @@ public function setEmptyData($emptyData); /** * Sets whether errors bubble up to the parent. * - * @param bool $errorBubbling + * @param bool $errorBubbling * * @return self The configuration object. */ @@ -142,7 +143,7 @@ public function setErrorBubbling($errorBubbling); /** * Sets whether this field is required to be filled out when submitted. * - * @param bool $required + * @param bool $required * * @return self The configuration object. */ @@ -151,7 +152,7 @@ public function setRequired($required); /** * Sets the property path that the form should be mapped to. * - * @param null|string|\Symfony\Component\PropertyAccess\PropertyPathInterface $propertyPath + * @param null|string|PropertyPathInterface $propertyPath * The property path or null if the path should be set * automatically based on the form's name. * @@ -163,7 +164,7 @@ public function setPropertyPath($propertyPath); * Sets whether the form should be mapped to an element of its * parent's data. * - * @param bool $mapped Whether the form should be mapped. + * @param bool $mapped Whether the form should be mapped. * * @return self The configuration object. */ @@ -172,7 +173,7 @@ public function setMapped($mapped); /** * Sets whether the form's data should be modified by reference. * - * @param bool $byReference Whether the data should be + * @param bool $byReference Whether the data should be * modified by reference. * * @return self The configuration object. @@ -182,7 +183,7 @@ public function setByReference($byReference); /** * Sets whether the form should read and write the data of its parent. * - * @param bool $inheritData Whether the form should inherit its parent's data. + * @param bool $inheritData Whether the form should inherit its parent's data. * * @return self The configuration object. */ @@ -191,7 +192,7 @@ public function setInheritData($inheritData); /** * Sets whether the form should be compound. * - * @param bool $compound Whether the form should be compound. + * @param bool $compound Whether the form should be compound. * * @return self The configuration object. * @@ -224,7 +225,7 @@ public function setData($data); * this configuration. The data can only be modified then by * submitting the form. * - * @param bool $locked Whether to lock the default data. + * @param bool $locked Whether to lock the default data. * * @return self The configuration object. */ @@ -269,10 +270,10 @@ public function setRequestHandler(RequestHandlerInterface $requestHandler); * * Should be set to true only for root forms. * - * @param bool $initialize True to initialize the form automatically, - * false to suppress automatic initialization. - * In the second case, you need to call - * {@link FormInterface::initialize()} manually. + * @param bool $initialize True to initialize the form automatically, + * false to suppress automatic initialization. + * In the second case, you need to call + * {@link FormInterface::initialize()} manually. * * @return self The configuration object. */ diff --git a/FormConfigInterface.php b/FormConfigInterface.php index ea19165407..179905850f 100644 --- a/FormConfigInterface.php +++ b/FormConfigInterface.php @@ -11,6 +11,9 @@ namespace Symfony\Component\Form; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\PropertyAccess\PropertyPathInterface; + /** * The configuration of a {@link Form} object. * @@ -21,7 +24,7 @@ interface FormConfigInterface /** * Returns the event dispatcher used to dispatch form events. * - * @return \Symfony\Component\EventDispatcher\EventDispatcherInterface The dispatcher. + * @return EventDispatcherInterface The dispatcher. */ public function getEventDispatcher(); @@ -35,7 +38,7 @@ public function getName(); /** * Returns the property path that the form should be mapped to. * - * @return null|\Symfony\Component\PropertyAccess\PropertyPathInterface The property path. + * @return null|PropertyPathInterface The property path. */ public function getPropertyPath(); @@ -43,21 +46,21 @@ public function getPropertyPath(); * Returns whether the form should be mapped to an element of its * parent's data. * - * @return bool Whether the form is mapped. + * @return bool Whether the form is mapped. */ public function getMapped(); /** * Returns whether the form's data should be modified by reference. * - * @return bool Whether to modify the form's data by reference. + * @return bool Whether to modify the form's data by reference. */ public function getByReference(); /** * Returns whether the form should read and write the data of its parent. * - * @return bool Whether the form should inherit its parent's data. + * @return bool Whether the form should inherit its parent's data. */ public function getInheritData(); @@ -68,7 +71,7 @@ public function getInheritData(); * children. A form can be compound and have no children at all, like * for example an empty collection form. * - * @return bool Whether the form is compound. + * @return bool Whether the form is compound. */ public function getCompound(); @@ -103,21 +106,21 @@ public function getDataMapper(); /** * Returns whether the form is required. * - * @return bool Whether the form is required. + * @return bool Whether the form is required. */ public function getRequired(); /** * Returns whether the form is disabled. * - * @return bool Whether the form is disabled. + * @return bool Whether the form is disabled. */ public function getDisabled(); /** * Returns whether errors attached to the form will bubble to its parent. * - * @return bool Whether errors will bubble up. + * @return bool Whether errors will bubble up. */ public function getErrorBubbling(); @@ -138,17 +141,17 @@ public function getAttributes(); /** * Returns whether the attribute with the given name exists. * - * @param string $name The attribute name. + * @param string $name The attribute name. * - * @return bool Whether the attribute exists. + * @return bool Whether the attribute exists. */ public function hasAttribute($name); /** * Returns the value of the given attribute. * - * @param string $name The attribute name. - * @param mixed $default The value returned if the attribute does not exist. + * @param string $name The attribute name. + * @param mixed $default The value returned if the attribute does not exist. * * @return mixed The attribute value. */ @@ -175,7 +178,7 @@ public function getDataClass(); * this configuration. The data can only be modified then by * submitting the form. * - * @return bool Whether the data is locked. + * @return bool Whether the data is locked. */ public function getDataLocked(); @@ -210,8 +213,8 @@ public function getRequestHandler(); /** * Returns whether the form should be initialized upon creation. * - * @return bool Returns true if the form should be initialized - * when created, false otherwise. + * @return bool Returns true if the form should be initialized + * when created, false otherwise. */ public function getAutoInitialize(); @@ -225,17 +228,17 @@ public function getOptions(); /** * Returns whether a specific option exists. * - * @param string $name The option name, + * @param string $name The option name, * - * @return bool Whether the option exists. + * @return bool Whether the option exists. */ public function hasOption($name); /** * Returns the value of a specific option. * - * @param string $name The option name. - * @param mixed $default The value returned if the option does not exist. + * @param string $name The option name. + * @param mixed $default The value returned if the option does not exist. * * @return mixed The option value. */ diff --git a/FormError.php b/FormError.php index 8927a76065..e29147be79 100644 --- a/FormError.php +++ b/FormError.php @@ -47,11 +47,11 @@ class FormError * Any array key in $messageParameters will be used as a placeholder in * $messageTemplate. * - * @param string $message The translated error message - * @param string|null $messageTemplate The template for the error message - * @param array $messageParameters The parameters that should be - * substituted in the message template. - * @param int|null $messagePluralization The value for error message pluralization + * @param string $message The translated error message + * @param string|null $messageTemplate The template for the error message + * @param array $messageParameters The parameters that should be + * substituted in the message template. + * @param int|null $messagePluralization The value for error message pluralization * * @see \Symfony\Component\Translation\Translator */ diff --git a/FormExtensionInterface.php b/FormExtensionInterface.php index 4fcf0b8f73..1449b1f1e7 100644 --- a/FormExtensionInterface.php +++ b/FormExtensionInterface.php @@ -32,7 +32,7 @@ public function getType($name); * * @param string $name The name of the type * - * @return bool Whether the type is supported by this extension + * @return bool Whether the type is supported by this extension */ public function hasType($name); @@ -50,7 +50,7 @@ public function getTypeExtensions($name); * * @param string $name The name of the type * - * @return bool Whether the given type has extensions + * @return bool Whether the given type has extensions */ public function hasTypeExtensions($name); diff --git a/FormFactoryBuilder.php b/FormFactoryBuilder.php index 10383e841c..a5bf5b38fd 100644 --- a/FormFactoryBuilder.php +++ b/FormFactoryBuilder.php @@ -24,22 +24,22 @@ class FormFactoryBuilder implements FormFactoryBuilderInterface private $resolvedTypeFactory; /** - * @var array + * @var FormExtensionInterface[] */ private $extensions = array(); /** - * @var array + * @var FormTypeInterface[] */ private $types = array(); /** - * @var array + * @var FormTypeExtensionInterface[] */ private $typeExtensions = array(); /** - * @var array + * @var FormTypeGuesserInterface[] */ private $typeGuessers = array(); diff --git a/FormRegistry.php b/FormRegistry.php index 0267a5657b..b2912fb052 100644 --- a/FormRegistry.php +++ b/FormRegistry.php @@ -30,7 +30,7 @@ class FormRegistry implements FormRegistryInterface private $extensions = array(); /** - * @var array + * @var FormTypeInterface[] */ private $types = array(); @@ -74,11 +74,9 @@ public function getType($name) } if (!isset($this->types[$name])) { - /** @var FormTypeInterface $type */ $type = null; foreach ($this->extensions as $extension) { - /* @var FormExtensionInterface $extension */ if ($extension->hasType($name)) { $type = $extension->getType($name); break; @@ -115,7 +113,6 @@ private function resolveAndAddType(FormTypeInterface $type) $typeExtensions = array(); foreach ($this->extensions as $extension) { - /* @var FormExtensionInterface $extension */ $typeExtensions = array_merge( $typeExtensions, $extension->getTypeExtensions($type->getName()) @@ -156,7 +153,6 @@ public function getTypeGuesser() $guessers = array(); foreach ($this->extensions as $extension) { - /* @var FormExtensionInterface $extension */ $guesser = $extension->getTypeGuesser(); if ($guesser) { diff --git a/FormRegistryInterface.php b/FormRegistryInterface.php index b15131c39b..b42b2b5818 100644 --- a/FormRegistryInterface.php +++ b/FormRegistryInterface.php @@ -37,7 +37,7 @@ public function getType($name); * * @param string $name The name of the type * - * @return bool Whether the type is supported + * @return bool Whether the type is supported */ public function hasType($name); diff --git a/FormRendererEngineInterface.php b/FormRendererEngineInterface.php index 9f04e1999a..31528e0531 100644 --- a/FormRendererEngineInterface.php +++ b/FormRendererEngineInterface.php @@ -70,19 +70,15 @@ public function getResourceForBlockName(FormView $view, $blockName); * The type of the resource is decided by the implementation. The resource * is later passed to {@link renderBlock()} by the rendering algorithm. * - * @param FormView $view The view for determining the - * used themes. First the themes - * attached directly to the view - * with {@link setTheme()} are - * considered, then the ones of - * its parent etc. - * @param array $blockNameHierarchy The block name hierarchy, with - * the root block at the beginning. - * @param int $hierarchyLevel The level in the hierarchy at - * which to start looking. Level 0 - * indicates the root block, i.e. - * the first element of - * $blockNameHierarchy. + * @param FormView $view The view for determining the used themes. + * First the themes attached directly to + * the view with {@link setTheme()} are + * considered, then the ones of its parent etc. + * @param array $blockNameHierarchy The block name hierarchy, with the root block + * at the beginning. + * @param int $hierarchyLevel The level in the hierarchy at which to start + * looking. Level 0 indicates the root block, i.e. + * the first element of $blockNameHierarchy. * * @return mixed The renderer resource or false, if none was found. */ @@ -114,19 +110,15 @@ public function getResourceForBlockNameHierarchy(FormView $view, array $blockNam * The type of the resource is decided by the implementation. The resource * is later passed to {@link renderBlock()} by the rendering algorithm. * - * @param FormView $view The view for determining the - * used themes. First the themes - * attached directly to the view - * with {@link setTheme()} are - * considered, then the ones of - * its parent etc. - * @param array $blockNameHierarchy The block name hierarchy, with - * the root block at the beginning. - * @param int $hierarchyLevel The level in the hierarchy at - * which to start looking. Level 0 - * indicates the root block, i.e. - * the first element of - * $blockNameHierarchy. + * @param FormView $view The view for determining the used themes. + * First the themes attached directly to + * the view with {@link setTheme()} are + * considered, then the ones of its parent etc. + * @param array $blockNameHierarchy The block name hierarchy, with the root block + * at the beginning. + * @param int $hierarchyLevel The level in the hierarchy at which to start + * looking. Level 0 indicates the root block, i.e. + * the first element of $blockNameHierarchy. * * @return int|bool The hierarchy level or false, if no resource was found. */ @@ -139,10 +131,10 @@ public function getResourceHierarchyLevel(FormView $view, array $blockNameHierar * or {@link getResourceForBlockHierarchy()}. The type of the resource is * decided by the implementation. * - * @param FormView $view The view to render. - * @param mixed $resource The renderer resource. - * @param string $blockName The name of the block to render. - * @param array $variables The variables to pass to the template. + * @param FormView $view The view to render. + * @param mixed $resource The renderer resource. + * @param string $blockName The name of the block to render. + * @param array $variables The variables to pass to the template. * * @return string The HTML markup. */ diff --git a/FormRendererInterface.php b/FormRendererInterface.php index 848e7125ca..76e305c352 100644 --- a/FormRendererInterface.php +++ b/FormRendererInterface.php @@ -29,8 +29,8 @@ public function getEngine(); * Sets the theme(s) to be used for rendering a view and its children. * * @param FormView $view The view to assign the theme(s) to. - * @param mixed $themes The theme(s). The type of these themes - * is open to the implementation. + * @param mixed $themes The theme(s). The type of these themes + * is open to the implementation. */ public function setTheme(FormView $view, $themes); diff --git a/FormTypeExtensionInterface.php b/FormTypeExtensionInterface.php index 9866b28b64..946c7a74b3 100644 --- a/FormTypeExtensionInterface.php +++ b/FormTypeExtensionInterface.php @@ -39,9 +39,9 @@ public function buildForm(FormBuilderInterface $builder, array $options); * * @see FormTypeInterface::buildView() * - * @param FormView $view The view - * @param FormInterface $form The form - * @param array $options The options + * @param FormView $view The view + * @param FormInterface $form The form + * @param array $options The options */ public function buildView(FormView $view, FormInterface $form, array $options); @@ -53,9 +53,9 @@ public function buildView(FormView $view, FormInterface $form, array $options); * * @see FormTypeInterface::finishView() * - * @param FormView $view The view - * @param FormInterface $form The form - * @param array $options The options + * @param FormView $view The view + * @param FormInterface $form The form + * @param array $options The options */ public function finishView(FormView $view, FormInterface $form, array $options); diff --git a/FormTypeGuesserChain.php b/FormTypeGuesserChain.php index 27db889026..979a7214d8 100644 --- a/FormTypeGuesserChain.php +++ b/FormTypeGuesserChain.php @@ -85,7 +85,7 @@ public function guessPattern($class, $property) * return values * * @param \Closure $closure The closure to execute. Accepts a guesser - * as argument and should return a Guess instance + * as argument and should return a Guess instance * * @return Guess|null The guess with the highest confidence */ diff --git a/FormTypeInterface.php b/FormTypeInterface.php index 5f6850b7cd..78f8bd0083 100644 --- a/FormTypeInterface.php +++ b/FormTypeInterface.php @@ -43,9 +43,9 @@ public function buildForm(FormBuilderInterface $builder, array $options); * * @see FormTypeExtensionInterface::buildView() * - * @param FormView $view The view - * @param FormInterface $form The form - * @param array $options The options + * @param FormView $view The view + * @param FormInterface $form The form + * @param array $options The options */ public function buildView(FormView $view, FormInterface $form, array $options); @@ -62,9 +62,9 @@ public function buildView(FormView $view, FormInterface $form, array $options); * * @see FormTypeExtensionInterface::finishView() * - * @param FormView $view The view - * @param FormInterface $form The form - * @param array $options The options + * @param FormView $view The view + * @param FormInterface $form The form + * @param array $options The options */ public function finishView(FormView $view, FormInterface $form, array $options); diff --git a/FormView.php b/FormView.php index a807551854..c2c3679f0b 100644 --- a/FormView.php +++ b/FormView.php @@ -35,7 +35,7 @@ class FormView implements \ArrayAccess, \IteratorAggregate, \Countable /** * The child views. - * @var array + * @var FormView[] */ public $children = array(); @@ -110,7 +110,7 @@ public function offsetGet($name) * * @param string $name The child name * - * @return bool Whether the child view exists + * @return bool Whether the child view exists */ public function offsetExists($name) { @@ -150,7 +150,7 @@ public function getIterator() /** * Implements \Countable. * - * @return int The number of children views + * @return int The number of children views */ public function count() { diff --git a/Guess/Guess.php b/Guess/Guess.php index 93568c3c52..e999f5421a 100644 --- a/Guess/Guess.php +++ b/Guess/Guess.php @@ -86,7 +86,7 @@ public static function getBestGuess(array $guesses) /** * Constructor. * - * @param int $confidence The confidence + * @param int $confidence The confidence * * @throws InvalidArgumentException if the given value of confidence is unknown */ @@ -103,8 +103,8 @@ public function __construct($confidence) /** * Returns the confidence that the guessed value is correct. * - * @return int One of the constants VERY_HIGH_CONFIDENCE, - * HIGH_CONFIDENCE, MEDIUM_CONFIDENCE and LOW_CONFIDENCE + * @return int One of the constants VERY_HIGH_CONFIDENCE, HIGH_CONFIDENCE, + * MEDIUM_CONFIDENCE and LOW_CONFIDENCE */ public function getConfidence() { diff --git a/Guess/TypeGuess.php b/Guess/TypeGuess.php index 7136b7874b..50ab944d6f 100644 --- a/Guess/TypeGuess.php +++ b/Guess/TypeGuess.php @@ -34,11 +34,11 @@ class TypeGuess extends Guess /** * Constructor * - * @param string $type The guessed field type - * @param array $options The options for creating instances of the - * guessed class - * @param int $confidence The confidence that the guessed class name - * is correct + * @param string $type The guessed field type + * @param array $options The options for creating instances of the + * guessed class + * @param int $confidence The confidence that the guessed class name + * is correct */ public function __construct($type, array $options, $confidence) { diff --git a/Guess/ValueGuess.php b/Guess/ValueGuess.php index bf450d6002..c101201ff8 100644 --- a/Guess/ValueGuess.php +++ b/Guess/ValueGuess.php @@ -27,9 +27,9 @@ class ValueGuess extends Guess /** * Constructor * - * @param string $value The guessed value - * @param int $confidence The confidence that the guessed class name - * is correct + * @param string $value The guessed value + * @param int $confidence The confidence that the guessed class name + * is correct */ public function __construct($value, $confidence) { diff --git a/PreloadedExtension.php b/PreloadedExtension.php index 454affd3eb..804841e7b7 100644 --- a/PreloadedExtension.php +++ b/PreloadedExtension.php @@ -21,12 +21,12 @@ class PreloadedExtension implements FormExtensionInterface { /** - * @var array + * @var FormTypeInterface[] */ private $types = array(); /** - * @var array + * @var array[FormTypeExtensionInterface[]] */ private $typeExtensions = array(); diff --git a/ResolvedFormType.php b/ResolvedFormType.php index 0f676e53de..b922e32561 100644 --- a/ResolvedFormType.php +++ b/ResolvedFormType.php @@ -158,7 +158,6 @@ public function buildForm(FormBuilderInterface $builder, array $options) $this->innerType->buildForm($builder, $options); foreach ($this->typeExtensions as $extension) { - /* @var FormTypeExtensionInterface $extension */ $extension->buildForm($builder, $options); } } @@ -184,7 +183,6 @@ public function buildView(FormView $view, FormInterface $form, array $options) $this->innerType->buildView($view, $form, $options); foreach ($this->typeExtensions as $extension) { - /* @var FormTypeExtensionInterface $extension */ $extension->buildView($view, $form, $options); } } @@ -235,7 +233,6 @@ public function getOptionsResolver() $this->innerType->setDefaultOptions($this->optionsResolver); foreach ($this->typeExtensions as $extension) { - /* @var FormTypeExtensionInterface $extension */ $extension->setDefaultOptions($this->optionsResolver); } } diff --git a/ResolvedFormTypeInterface.php b/ResolvedFormTypeInterface.php index 5fd37f4b46..e6a61c753b 100644 --- a/ResolvedFormTypeInterface.php +++ b/ResolvedFormTypeInterface.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Form; +use Symfony\Component\OptionsResolver\OptionsResolverInterface; + /** * A wrapper for a form type and its extensions. * @@ -60,8 +62,8 @@ public function createBuilder(FormFactoryInterface $factory, $name, array $optio /** * Creates a new form view for a form of this type. * - * @param FormInterface $form The form to create a view for. - * @param FormView $parent The parent view or null. + * @param FormInterface $form The form to create a view for. + * @param FormView $parent The parent view or null. * * @return FormView The created form view. */ @@ -100,7 +102,7 @@ public function finishView(FormView $view, FormInterface $form, array $options); /** * Returns the configured options resolver used for this type. * - * @return \Symfony\Component\OptionsResolver\OptionsResolverInterface The options resolver. + * @return OptionsResolverInterface The options resolver. */ public function getOptionsResolver(); } diff --git a/Test/FormBuilderInterface.php b/Test/FormBuilderInterface.php index 711cecd0b8..185a8a12d6 100644 --- a/Test/FormBuilderInterface.php +++ b/Test/FormBuilderInterface.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Form\Test; -interface FormBuilderInterface extends \Iterator, \Symfony\Component\Form\FormBuilderInterface +use Symfony\Component\Form\FormBuilderInterface as BaseFormBuilderInterface; + +interface FormBuilderInterface extends \Iterator, BaseFormBuilderInterface { } diff --git a/Test/FormIntegrationTestCase.php b/Test/FormIntegrationTestCase.php index 68e5f2445e..a5cf86c412 100644 --- a/Test/FormIntegrationTestCase.php +++ b/Test/FormIntegrationTestCase.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Test; use Symfony\Component\Form\Forms; +use Symfony\Component\Form\FormFactoryInterface; /** * @author Bernhard Schussek @@ -19,7 +20,7 @@ abstract class FormIntegrationTestCase extends \PHPUnit_Framework_TestCase { /** - * @var \Symfony\Component\Form\FormFactoryInterface + * @var FormFactoryInterface */ protected $factory; diff --git a/Test/FormInterface.php b/Test/FormInterface.php index 22a83fd76f..4af4603087 100644 --- a/Test/FormInterface.php +++ b/Test/FormInterface.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Form\Test; -interface FormInterface extends \Iterator, \Symfony\Component\Form\FormInterface +use Symfony\Component\Form\FormInterface as BaseFormInterface; + +interface FormInterface extends \Iterator, BaseFormInterface { } diff --git a/Test/FormPerformanceTestCase.php b/Test/FormPerformanceTestCase.php index b0d07555d9..3060472975 100644 --- a/Test/FormPerformanceTestCase.php +++ b/Test/FormPerformanceTestCase.php @@ -22,11 +22,12 @@ abstract class FormPerformanceTestCase extends FormIntegrationTestCase { /** - * @var int + * @var int */ protected $maxRunningTime = 0; /** + * {@inheritdoc} */ protected function runTest() { @@ -47,7 +48,8 @@ protected function runTest() } /** - * @param int $maxRunningTime + * @param int $maxRunningTime + * * @throws \InvalidArgumentException */ public function setMaxRunningTime($maxRunningTime) @@ -60,8 +62,9 @@ public function setMaxRunningTime($maxRunningTime) } /** + * @since Method available since Release 2.3.0 + * * @return int - * @since Method available since Release 2.3.0 */ public function getMaxRunningTime() { From b43cd8f17f6058e4114638716d48b631ba13572b Mon Sep 17 00:00:00 2001 From: Christopher Davis Date: Wed, 2 Jul 2014 21:40:29 -0400 Subject: [PATCH 311/447] Remove Spaceless Blocks From Twig Templates --- Tests/AbstractDivLayoutTest.php | 12 ----------- Tests/AbstractLayoutTest.php | 36 ++++++++++++++++++++++++++++--- Tests/AbstractTableLayoutTest.php | 12 ----------- 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/Tests/AbstractDivLayoutTest.php b/Tests/AbstractDivLayoutTest.php index 2d32aa38a3..fd58443709 100644 --- a/Tests/AbstractDivLayoutTest.php +++ b/Tests/AbstractDivLayoutTest.php @@ -756,16 +756,4 @@ public function testWidgetContainerAttributeNameRepeatedIfTrue() // foo="foo" $this->assertContains('
', $html); } - - public function testWidgetContainerAttributeHiddenIfFalse() - { - $form = $this->factory->createNamed('form', 'form', null, array( - 'attr' => array('foo' => false), - )); - - $html = $this->renderWidget($form->createView()); - - // no foo - $this->assertContains('
', $html); - } } diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index 7aee4694e3..9c26e26fbf 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -1931,8 +1931,7 @@ public function testWidgetAttributeHiddenIfFalse() $html = $this->renderWidget($form->createView()); - // no foo - $this->assertSame('', $html); + $this->assertNotContains('foo="', $html); } public function testButtonAttributes() @@ -1968,7 +1967,38 @@ public function testButtonAttributeHiddenIfFalse() $html = $this->renderWidget($form->createView()); + $this->assertNotContains('foo="', $html); + } + + public function testTextareaWithWhitespaceOnlyContentRetainsValue() + { + $form = $this->factory->createNamed('textarea', 'textarea', ' '); + + $html = $this->renderWidget($form->createView()); + + $this->assertContains('> ', $html); + } + + public function testTextareaWithWhitespaceOnlyContentRetainsValueWhenRenderingForm() + { + $form = $this->factory->createBuilder('form', array('textarea' => ' ')) + ->add('textarea', 'textarea') + ->getForm(); + + $html = $this->renderForm($form->createView()); + + $this->assertContains('> ', $html); + } + + public function testWidgetContainerAttributeHiddenIfFalse() + { + $form = $this->factory->createNamed('form', 'form', null, array( + 'attr' => array('foo' => false), + )); + + $html = $this->renderWidget($form->createView()); + // no foo - $this->assertSame('', $html); + $this->assertNotContains('foo="', $html); } } diff --git a/Tests/AbstractTableLayoutTest.php b/Tests/AbstractTableLayoutTest.php index 5c8a9be2d5..d7213c33fe 100644 --- a/Tests/AbstractTableLayoutTest.php +++ b/Tests/AbstractTableLayoutTest.php @@ -533,16 +533,4 @@ public function testWidgetContainerAttributeNameRepeatedIfTrue() // foo="foo" $this->assertContains('
', $html); } - - public function testWidgetContainerAttributeHiddenIfFalse() - { - $form = $this->factory->createNamed('form', 'form', null, array( - 'attr' => array('foo' => false), - )); - - $html = $this->renderWidget($form->createView()); - - // no foo - $this->assertContains('
', $html); - } } From 6281e30f81d0463cd8e9a7d8805a62d066ae4b14 Mon Sep 17 00:00:00 2001 From: Sebastian Blum Date: Tue, 8 Jul 2014 13:46:05 +0200 Subject: [PATCH 312/447] [2.5][Form] solved dependency to ValidatorInterface, fix #11036 --- .../EventListener/ValidationListener.php | 13 ++- .../Type/FormTypeValidatorExtension.php | 12 ++- Extension/Validator/ValidatorExtension.php | 27 +++++- .../EventListener/ValidationListenerTest.php | 26 ++++++ .../Type/FormTypeValidatorExtensionTest.php | 27 ++++++ .../Validator/ValidatorExtensionTest.php | 93 +++++++++++++++++++ 6 files changed, 189 insertions(+), 9 deletions(-) create mode 100644 Tests/Extension/Validator/ValidatorExtensionTest.php diff --git a/Extension/Validator/EventListener/ValidationListener.php b/Extension/Validator/EventListener/ValidationListener.php index 26d2bfdaa7..62c59ddc43 100644 --- a/Extension/Validator/EventListener/ValidationListener.php +++ b/Extension/Validator/EventListener/ValidationListener.php @@ -13,7 +13,8 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapperInterface; -use Symfony\Component\Validator\ValidatorInterface; +use Symfony\Component\Validator\Validator\ValidatorInterface; +use Symfony\Component\Validator\ValidatorInterface as LegacyValidatorInterface; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Validator\Constraints\Form; @@ -35,8 +36,16 @@ public static function getSubscribedEvents() return array(FormEvents::POST_SUBMIT => 'validateForm'); } - public function __construct(ValidatorInterface $validator, ViolationMapperInterface $violationMapper) + /** + * @param ValidatorInterface|LegacyValidatorInterface $validator + * @param ViolationMapperInterface $violationMapper + */ + public function __construct($validator, ViolationMapperInterface $violationMapper) { + if (!$validator instanceof ValidatorInterface && !$validator instanceof LegacyValidatorInterface) { + throw new \InvalidArgumentException('Validator must be instance of Symfony\Component\Validator\Validator\ValidatorInterface or Symfony\Component\Validator\ValidatorInterface'); + } + $this->validator = $validator; $this->violationMapper = $violationMapper; } diff --git a/Extension/Validator/Type/FormTypeValidatorExtension.php b/Extension/Validator/Type/FormTypeValidatorExtension.php index 8d4e3d5642..87abd9320a 100644 --- a/Extension/Validator/Type/FormTypeValidatorExtension.php +++ b/Extension/Validator/Type/FormTypeValidatorExtension.php @@ -14,7 +14,8 @@ use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapper; use Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener; -use Symfony\Component\Validator\ValidatorInterface; +use Symfony\Component\Validator\Validator\ValidatorInterface; +use Symfony\Component\Validator\ValidatorInterface as LegacyValidatorInterface; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; @@ -33,8 +34,15 @@ class FormTypeValidatorExtension extends BaseValidatorExtension */ private $violationMapper; - public function __construct(ValidatorInterface $validator) + /** + * @param ValidatorInterface|LegacyValidatorInterface $validator + */ + public function __construct($validator) { + if (!$validator instanceof ValidatorInterface && !$validator instanceof LegacyValidatorInterface) { + throw new \InvalidArgumentException('Validator must be instance of Symfony\Component\Validator\Validator\ValidatorInterface or Symfony\Component\Validator\ValidatorInterface'); + } + $this->validator = $validator; $this->violationMapper = new ViolationMapper(); } diff --git a/Extension/Validator/ValidatorExtension.php b/Extension/Validator/ValidatorExtension.php index 572a4ac938..88890ae651 100644 --- a/Extension/Validator/ValidatorExtension.php +++ b/Extension/Validator/ValidatorExtension.php @@ -13,8 +13,10 @@ use Symfony\Component\Form\Extension\Validator\Constraints\Form; use Symfony\Component\Form\AbstractExtension; -use Symfony\Component\Validator\ValidatorInterface; use Symfony\Component\Validator\Constraints\Valid; +use Symfony\Component\Validator\Mapping\ClassMetadata; +use Symfony\Component\Validator\Validator\ValidatorInterface; +use Symfony\Component\Validator\ValidatorInterface as LegacyValidatorInterface; /** * Extension supporting the Symfony2 Validator component in forms. @@ -25,17 +27,32 @@ class ValidatorExtension extends AbstractExtension { private $validator; - public function __construct(ValidatorInterface $validator) + /** + * @param ValidatorInterface|LegacyValidatorInterface $validator + */ + public function __construct($validator) { - $this->validator = $validator; + // since validator apiVersion 2.5 + if ($validator instanceof ValidatorInterface) { + $this->validator = $validator; + + /** @var $metadata ClassMetadata */ + $metadata = $this->validator->getMetadataFor('Symfony\Component\Form\Form'); + // until validator apiVersion 2.4 + } elseif ($validator instanceof LegacyValidatorInterface) { + $this->validator = $validator; + + /** @var $metadata ClassMetadata */ + $metadata = $this->validator->getMetadataFactory()->getMetadataFor('Symfony\Component\Form\Form'); + } else { + throw new \InvalidArgumentException('Validator must be instance of Symfony\Component\Validator\Validator\ValidatorInterface or Symfony\Component\Validator\ValidatorInterface'); + } // Register the form constraints in the validator programmatically. // This functionality is required when using the Form component without // the DIC, where the XML file is loaded automatically. Thus the following // code must be kept synchronized with validation.xml - /** @var \Symfony\Component\Validator\Mapping\ClassMetadata $metadata */ - $metadata = $this->validator->getMetadataFactory()->getMetadataFor('Symfony\Component\Form\Form'); $metadata->addConstraint(new Form()); $metadata->addPropertyConstraint('children', new Valid()); } diff --git a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php index 8d8f9235d1..d819277db0 100644 --- a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php +++ b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php @@ -158,4 +158,30 @@ public function testValidateWithEmptyViolationList() $this->listener->validateForm(new FormEvent($form, null)); } + + public function testValidatorInterfaceSinceSymfony25() + { + // Mock of ValidatorInterface since apiVersion 2.5 + $validator = $this->getMock('Symfony\Component\Validator\Validator\ValidatorInterface'); + + $listener = new ValidationListener($validator, $this->violationMapper); + $this->assertAttributeSame($validator, 'validator', $listener); + } + + public function testValidatorInterfaceUntilSymfony24() + { + // Mock of ValidatorInterface until apiVersion 2.4 + $validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface'); + + $listener = new ValidationListener($validator, $this->violationMapper); + $this->assertAttributeSame($validator, 'validator', $listener); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testInvalidValidatorInterface() + { + new ValidationListener(null, $this->violationMapper); + } } diff --git a/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php b/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php index 298306b57d..4ca10da50e 100644 --- a/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php +++ b/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\Type; +use Symfony\Component\Form\Extension\Validator\Type\FormTypeValidatorExtension; use Symfony\Component\Validator\ConstraintViolationList; class FormTypeValidatorExtensionTest extends BaseValidatorExtensionTest @@ -36,6 +37,32 @@ public function testSubmitValidatesData() $form->submit(array()); } + public function testValidatorInterfaceSinceSymfony25() + { + // Mock of ValidatorInterface since apiVersion 2.5 + $validator = $this->getMock('Symfony\Component\Validator\Validator\ValidatorInterface'); + + $formTypeValidatorExtension = new FormTypeValidatorExtension($validator); + $this->assertAttributeSame($validator, 'validator', $formTypeValidatorExtension); + } + + public function testValidatorInterfaceUntilSymfony24() + { + // Mock of ValidatorInterface until apiVersion 2.4 + $validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface'); + + $formTypeValidatorExtension = new FormTypeValidatorExtension($validator); + $this->assertAttributeSame($validator, 'validator', $formTypeValidatorExtension); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testInvalidValidatorInterface() + { + new FormTypeValidatorExtension(null); + } + protected function createForm(array $options = array()) { return $this->factory->create('form', null, $options); diff --git a/Tests/Extension/Validator/ValidatorExtensionTest.php b/Tests/Extension/Validator/ValidatorExtensionTest.php new file mode 100644 index 0000000000..bc69231fe2 --- /dev/null +++ b/Tests/Extension/Validator/ValidatorExtensionTest.php @@ -0,0 +1,93 @@ + +* +* For the full copyright and license information, please view the LICENSE +* file that was distributed with this source code. +*/ + +namespace Symfony\Component\Form\Tests\Extension\Validator; + +use Symfony\Component\Form\Extension\Validator\ValidatorExtension; + +class ValidatorExtensionTest extends \PHPUnit_Framework_TestCase +{ + public function testValidatorInterfaceSinceSymfony25() + { + $classMetaData = $this->createClassMetaDataMock(); + + // Mock of ValidatorInterface since apiVersion 2.5 + $validator = $this->getMock('Symfony\Component\Validator\Validator\ValidatorInterface'); + + $validator + ->expects($this->once()) + ->method('getMetadataFor') + ->with($this->identicalTo('Symfony\Component\Form\Form')) + ->will($this->returnValue($classMetaData)) + ; + + $validatorExtension = new ValidatorExtension($validator); + $this->assertAttributeSame($validator, 'validator', $validatorExtension); + } + + public function testValidatorInterfaceUntilSymfony24() + { + $classMetaData = $this->createClassMetaDataMock(); + + $metaDataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface'); + + $metaDataFactory + ->expects($this->once()) + ->method('getMetadataFor') + ->with($this->identicalTo('Symfony\Component\Form\Form')) + ->will($this->returnValue($classMetaData)) + ; + + // Mock of ValidatorInterface until apiVersion 2.4 + $validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface'); + + $validator + ->expects($this->once()) + ->method('getMetadataFactory') + ->will($this->returnValue($metaDataFactory)) + ; + + $validatorExtension = new ValidatorExtension($validator); + $this->assertAttributeSame($validator, 'validator', $validatorExtension); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testInvalidValidatorInterface() + { + new ValidatorExtension(null); + } + + /** + * @return mixed + */ + private function createClassMetaDataMock() + { + $classMetaData = $this->getMockBuilder('Symfony\Component\Validator\Mapping\ClassMetadata') + ->disableOriginalConstructor() + ->getMock(); + + $classMetaData + ->expects($this->once()) + ->method('addConstraint') + ->with($this->isInstanceOf('Symfony\Component\Form\Extension\Validator\Constraints\Form')); + $classMetaData + ->expects($this->once()) + ->method('addPropertyConstraint') + ->with( + $this->identicalTo('children'), + $this->isInstanceOf('Symfony\Component\Validator\Constraints\Valid') + ); + + return $classMetaData; + } +} From b9a1ddbf22ce64d85a71d1ff06c963fb3daaf877 Mon Sep 17 00:00:00 2001 From: Sebastian Blum Date: Tue, 8 Jul 2014 13:46:05 +0200 Subject: [PATCH 313/447] [2.5][Form] solved dependency to ValidatorInterface, fix #11036 --- .../EventListener/ValidationListener.php | 13 ++- .../Type/FormTypeValidatorExtension.php | 12 ++- Extension/Validator/ValidatorExtension.php | 27 +++++- .../EventListener/ValidationListenerTest.php | 26 ++++++ .../Type/FormTypeValidatorExtensionTest.php | 27 ++++++ .../Validator/ValidatorExtensionTest.php | 93 +++++++++++++++++++ 6 files changed, 189 insertions(+), 9 deletions(-) create mode 100644 Tests/Extension/Validator/ValidatorExtensionTest.php diff --git a/Extension/Validator/EventListener/ValidationListener.php b/Extension/Validator/EventListener/ValidationListener.php index 26d2bfdaa7..62c59ddc43 100644 --- a/Extension/Validator/EventListener/ValidationListener.php +++ b/Extension/Validator/EventListener/ValidationListener.php @@ -13,7 +13,8 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapperInterface; -use Symfony\Component\Validator\ValidatorInterface; +use Symfony\Component\Validator\Validator\ValidatorInterface; +use Symfony\Component\Validator\ValidatorInterface as LegacyValidatorInterface; use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Validator\Constraints\Form; @@ -35,8 +36,16 @@ public static function getSubscribedEvents() return array(FormEvents::POST_SUBMIT => 'validateForm'); } - public function __construct(ValidatorInterface $validator, ViolationMapperInterface $violationMapper) + /** + * @param ValidatorInterface|LegacyValidatorInterface $validator + * @param ViolationMapperInterface $violationMapper + */ + public function __construct($validator, ViolationMapperInterface $violationMapper) { + if (!$validator instanceof ValidatorInterface && !$validator instanceof LegacyValidatorInterface) { + throw new \InvalidArgumentException('Validator must be instance of Symfony\Component\Validator\Validator\ValidatorInterface or Symfony\Component\Validator\ValidatorInterface'); + } + $this->validator = $validator; $this->violationMapper = $violationMapper; } diff --git a/Extension/Validator/Type/FormTypeValidatorExtension.php b/Extension/Validator/Type/FormTypeValidatorExtension.php index 344bddadc1..644a46db93 100644 --- a/Extension/Validator/Type/FormTypeValidatorExtension.php +++ b/Extension/Validator/Type/FormTypeValidatorExtension.php @@ -14,7 +14,8 @@ use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\Extension\Validator\ViolationMapper\ViolationMapper; use Symfony\Component\Form\Extension\Validator\EventListener\ValidationListener; -use Symfony\Component\Validator\ValidatorInterface; +use Symfony\Component\Validator\Validator\ValidatorInterface; +use Symfony\Component\Validator\ValidatorInterface as LegacyValidatorInterface; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolverInterface; @@ -33,8 +34,15 @@ class FormTypeValidatorExtension extends BaseValidatorExtension */ private $violationMapper; - public function __construct(ValidatorInterface $validator) + /** + * @param ValidatorInterface|LegacyValidatorInterface $validator + */ + public function __construct($validator) { + if (!$validator instanceof ValidatorInterface && !$validator instanceof LegacyValidatorInterface) { + throw new \InvalidArgumentException('Validator must be instance of Symfony\Component\Validator\Validator\ValidatorInterface or Symfony\Component\Validator\ValidatorInterface'); + } + $this->validator = $validator; $this->violationMapper = new ViolationMapper(); } diff --git a/Extension/Validator/ValidatorExtension.php b/Extension/Validator/ValidatorExtension.php index 572a4ac938..88890ae651 100644 --- a/Extension/Validator/ValidatorExtension.php +++ b/Extension/Validator/ValidatorExtension.php @@ -13,8 +13,10 @@ use Symfony\Component\Form\Extension\Validator\Constraints\Form; use Symfony\Component\Form\AbstractExtension; -use Symfony\Component\Validator\ValidatorInterface; use Symfony\Component\Validator\Constraints\Valid; +use Symfony\Component\Validator\Mapping\ClassMetadata; +use Symfony\Component\Validator\Validator\ValidatorInterface; +use Symfony\Component\Validator\ValidatorInterface as LegacyValidatorInterface; /** * Extension supporting the Symfony2 Validator component in forms. @@ -25,17 +27,32 @@ class ValidatorExtension extends AbstractExtension { private $validator; - public function __construct(ValidatorInterface $validator) + /** + * @param ValidatorInterface|LegacyValidatorInterface $validator + */ + public function __construct($validator) { - $this->validator = $validator; + // since validator apiVersion 2.5 + if ($validator instanceof ValidatorInterface) { + $this->validator = $validator; + + /** @var $metadata ClassMetadata */ + $metadata = $this->validator->getMetadataFor('Symfony\Component\Form\Form'); + // until validator apiVersion 2.4 + } elseif ($validator instanceof LegacyValidatorInterface) { + $this->validator = $validator; + + /** @var $metadata ClassMetadata */ + $metadata = $this->validator->getMetadataFactory()->getMetadataFor('Symfony\Component\Form\Form'); + } else { + throw new \InvalidArgumentException('Validator must be instance of Symfony\Component\Validator\Validator\ValidatorInterface or Symfony\Component\Validator\ValidatorInterface'); + } // Register the form constraints in the validator programmatically. // This functionality is required when using the Form component without // the DIC, where the XML file is loaded automatically. Thus the following // code must be kept synchronized with validation.xml - /** @var \Symfony\Component\Validator\Mapping\ClassMetadata $metadata */ - $metadata = $this->validator->getMetadataFactory()->getMetadataFor('Symfony\Component\Form\Form'); $metadata->addConstraint(new Form()); $metadata->addPropertyConstraint('children', new Valid()); } diff --git a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php index 8d8f9235d1..d819277db0 100644 --- a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php +++ b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php @@ -158,4 +158,30 @@ public function testValidateWithEmptyViolationList() $this->listener->validateForm(new FormEvent($form, null)); } + + public function testValidatorInterfaceSinceSymfony25() + { + // Mock of ValidatorInterface since apiVersion 2.5 + $validator = $this->getMock('Symfony\Component\Validator\Validator\ValidatorInterface'); + + $listener = new ValidationListener($validator, $this->violationMapper); + $this->assertAttributeSame($validator, 'validator', $listener); + } + + public function testValidatorInterfaceUntilSymfony24() + { + // Mock of ValidatorInterface until apiVersion 2.4 + $validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface'); + + $listener = new ValidationListener($validator, $this->violationMapper); + $this->assertAttributeSame($validator, 'validator', $listener); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testInvalidValidatorInterface() + { + new ValidationListener(null, $this->violationMapper); + } } diff --git a/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php b/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php index 298306b57d..4ca10da50e 100644 --- a/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php +++ b/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\Type; +use Symfony\Component\Form\Extension\Validator\Type\FormTypeValidatorExtension; use Symfony\Component\Validator\ConstraintViolationList; class FormTypeValidatorExtensionTest extends BaseValidatorExtensionTest @@ -36,6 +37,32 @@ public function testSubmitValidatesData() $form->submit(array()); } + public function testValidatorInterfaceSinceSymfony25() + { + // Mock of ValidatorInterface since apiVersion 2.5 + $validator = $this->getMock('Symfony\Component\Validator\Validator\ValidatorInterface'); + + $formTypeValidatorExtension = new FormTypeValidatorExtension($validator); + $this->assertAttributeSame($validator, 'validator', $formTypeValidatorExtension); + } + + public function testValidatorInterfaceUntilSymfony24() + { + // Mock of ValidatorInterface until apiVersion 2.4 + $validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface'); + + $formTypeValidatorExtension = new FormTypeValidatorExtension($validator); + $this->assertAttributeSame($validator, 'validator', $formTypeValidatorExtension); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testInvalidValidatorInterface() + { + new FormTypeValidatorExtension(null); + } + protected function createForm(array $options = array()) { return $this->factory->create('form', null, $options); diff --git a/Tests/Extension/Validator/ValidatorExtensionTest.php b/Tests/Extension/Validator/ValidatorExtensionTest.php new file mode 100644 index 0000000000..bc69231fe2 --- /dev/null +++ b/Tests/Extension/Validator/ValidatorExtensionTest.php @@ -0,0 +1,93 @@ + +* +* For the full copyright and license information, please view the LICENSE +* file that was distributed with this source code. +*/ + +namespace Symfony\Component\Form\Tests\Extension\Validator; + +use Symfony\Component\Form\Extension\Validator\ValidatorExtension; + +class ValidatorExtensionTest extends \PHPUnit_Framework_TestCase +{ + public function testValidatorInterfaceSinceSymfony25() + { + $classMetaData = $this->createClassMetaDataMock(); + + // Mock of ValidatorInterface since apiVersion 2.5 + $validator = $this->getMock('Symfony\Component\Validator\Validator\ValidatorInterface'); + + $validator + ->expects($this->once()) + ->method('getMetadataFor') + ->with($this->identicalTo('Symfony\Component\Form\Form')) + ->will($this->returnValue($classMetaData)) + ; + + $validatorExtension = new ValidatorExtension($validator); + $this->assertAttributeSame($validator, 'validator', $validatorExtension); + } + + public function testValidatorInterfaceUntilSymfony24() + { + $classMetaData = $this->createClassMetaDataMock(); + + $metaDataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface'); + + $metaDataFactory + ->expects($this->once()) + ->method('getMetadataFor') + ->with($this->identicalTo('Symfony\Component\Form\Form')) + ->will($this->returnValue($classMetaData)) + ; + + // Mock of ValidatorInterface until apiVersion 2.4 + $validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface'); + + $validator + ->expects($this->once()) + ->method('getMetadataFactory') + ->will($this->returnValue($metaDataFactory)) + ; + + $validatorExtension = new ValidatorExtension($validator); + $this->assertAttributeSame($validator, 'validator', $validatorExtension); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testInvalidValidatorInterface() + { + new ValidatorExtension(null); + } + + /** + * @return mixed + */ + private function createClassMetaDataMock() + { + $classMetaData = $this->getMockBuilder('Symfony\Component\Validator\Mapping\ClassMetadata') + ->disableOriginalConstructor() + ->getMock(); + + $classMetaData + ->expects($this->once()) + ->method('addConstraint') + ->with($this->isInstanceOf('Symfony\Component\Form\Extension\Validator\Constraints\Form')); + $classMetaData + ->expects($this->once()) + ->method('addPropertyConstraint') + ->with( + $this->identicalTo('children'), + $this->isInstanceOf('Symfony\Component\Validator\Constraints\Valid') + ); + + return $classMetaData; + } +} From 46e9670d3c38d51e49c81d14c2f7792f55f842d8 Mon Sep 17 00:00:00 2001 From: Andrew Moore Date: Wed, 23 Jul 2014 22:02:17 -0400 Subject: [PATCH 314/447] [Form][Validator] All index items after children are to be considered grand-children when resolving ViolationPath (fixes #11458) --- .../Validator/ViolationMapper/ViolationPath.php | 14 +++++++++++--- .../ViolationMapper/ViolationMapperTest.php | 16 ++++++++-------- .../ViolationMapper/ViolationPathTest.php | 3 ++- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/Extension/Validator/ViolationMapper/ViolationPath.php b/Extension/Validator/ViolationMapper/ViolationPath.php index 662443ed72..1cb1baf025 100644 --- a/Extension/Validator/ViolationMapper/ViolationPath.php +++ b/Extension/Validator/ViolationMapper/ViolationPath.php @@ -70,9 +70,17 @@ public function __construct($violationPath) break; } - $this->elements[] = $elements[$i]; - $this->isIndex[] = true; - $this->mapsForm[] = true; + // All the following index items (regardless if .children is + // explicitly used) are children and grand-children + for (; $i < $l && $path->isIndex($i); ++$i) { + $this->elements[] = $elements[$i]; + $this->isIndex[] = true; + $this->mapsForm[] = true; + } + + // Rewind the pointer as the last element above didn't match + // (even if the pointer was moved forward) + --$i; } elseif ('data' === $elements[$i] && $path->isProperty($i)) { // Skip element "data" ++$i; diff --git a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php index c802ea7e80..73607bff96 100644 --- a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php +++ b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php @@ -712,14 +712,14 @@ public function provideDefaultTests() array(self::LEVEL_2, 'address', '[address]', 'street', '[office][street]', 'data[address][office][street].prop'), // Edge cases which must not occur - array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address][street]'), - array(self::LEVEL_1, 'address', 'address', 'street', 'street', 'children[address][street].prop'), - array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address][street]'), - array(self::LEVEL_1, 'address', 'address', 'street', '[street]', 'children[address][street].prop'), - array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address][street]'), - array(self::LEVEL_1, 'address', '[address]', 'street', 'street', 'children[address][street].prop'), - array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address][street]'), - array(self::LEVEL_1, 'address', '[address]', 'street', '[street]', 'children[address][street].prop'), + array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address][street]'), + array(self::LEVEL_2, 'address', 'address', 'street', 'street', 'children[address][street].prop'), + array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'children[address][street]'), + array(self::LEVEL_2, 'address', 'address', 'street', '[street]', 'children[address][street].prop'), + array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'children[address][street]'), + array(self::LEVEL_2, 'address', '[address]', 'street', 'street', 'children[address][street].prop'), + array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'children[address][street]'), + array(self::LEVEL_2, 'address', '[address]', 'street', '[street]', 'children[address][street].prop'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'children[person].children[address].children[street]'), array(self::LEVEL_0, 'address', 'person.address', 'street', 'street', 'children[person].children[address].data.street'), diff --git a/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.php b/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.php index 02df8f43eb..0b750de733 100644 --- a/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.php +++ b/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.php @@ -30,7 +30,8 @@ public function providePaths() )), array('children[address][street]', array( array('address', true, true), - ), 'children[address]'), + array('street', true, true), + ), 'children[address].children[street]'), array('children[address].data', array( array('address', true, true), ), 'children[address]'), From 9f49710280eec8da6b532a27d987d6c4bee7f54e Mon Sep 17 00:00:00 2001 From: Charles Sanquer Date: Sun, 16 Jun 2013 16:25:18 +0200 Subject: [PATCH 315/447] add allow_html5 option to date and time FormType to disable HTML5 date input when widget is set to single_text remove unnecessary test when creating datetime format data transformer --- CHANGELOG.md | 4 ++++ Extension/Core/Type/DateTimeType.php | 8 ++++++-- Extension/Core/Type/DateType.php | 4 +++- Extension/Core/Type/TimeType.php | 6 +++++- .../DateTimeToRfc3339TransformerTest.php | 2 +- Tests/Extension/Core/Type/DateTimeTypeTest.php | 11 +++++++++++ Tests/Extension/Core/Type/DateTypeTest.php | 11 +++++++++++ Tests/Extension/Core/Type/TimeTypeTest.php | 11 +++++++++++ 8 files changed, 52 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2999e1ffcf..a356bf7f92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ CHANGELOG ========= +2.6.0 +----- +* added allow_html5 option to Date, Time and DateTimeFormType to disable HTML5 input date when widget option is single_text + 2.5.0 ------ diff --git a/Extension/Core/Type/DateTimeType.php b/Extension/Core/Type/DateTimeType.php index a612b6fc9c..88dd9d94d1 100644 --- a/Extension/Core/Type/DateTimeType.php +++ b/Extension/Core/Type/DateTimeType.php @@ -117,6 +117,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'empty_value', 'required', 'translation_domain', + 'allow_html5', ))); $timeOptions = array_intersect_key($options, array_flip(array( @@ -128,6 +129,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'empty_value', 'required', 'translation_domain', + 'allow_html5', ))); if (null !== $options['date_widget']) { @@ -180,10 +182,11 @@ public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars['widget'] = $options['widget']; - // Change the input to a HTML5 date input if + // Change the input to a HTML5 datetime input if // * the widget is set to "single_text" // * the format matches the one expected by HTML5 - if ('single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) { + // * the allow_html5 is set to true + if ($options['allow_html5'] && 'single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) { $view->vars['type'] = 'datetime'; } } @@ -218,6 +221,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'time_widget' => $timeWidget, 'with_minutes' => true, 'with_seconds' => false, + 'allow_html5' => true, // Don't modify \DateTime classes by reference, we treat // them like immutable value objects 'by_reference' => false, diff --git a/Extension/Core/Type/DateType.php b/Extension/Core/Type/DateType.php index 022a414932..c9562a1632 100644 --- a/Extension/Core/Type/DateType.php +++ b/Extension/Core/Type/DateType.php @@ -130,7 +130,8 @@ public function finishView(FormView $view, FormInterface $form, array $options) // Change the input to a HTML5 date input if // * the widget is set to "single_text" // * the format matches the one expected by HTML5 - if ('single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) { + // * the allow_html5 is set to true + if ($options['allow_html5'] && 'single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) { $view->vars['type'] = 'date'; } @@ -199,6 +200,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'model_timezone' => null, 'view_timezone' => null, 'empty_value' => $emptyValue, + 'allow_html5' => true, // Don't modify \DateTime classes by reference, we treat // them like immutable value objects 'by_reference' => false, diff --git a/Extension/Core/Type/TimeType.php b/Extension/Core/Type/TimeType.php index 6bf41517ac..8e73dd096c 100644 --- a/Extension/Core/Type/TimeType.php +++ b/Extension/Core/Type/TimeType.php @@ -138,7 +138,10 @@ public function buildView(FormView $view, FormInterface $form, array $options) 'with_seconds' => $options['with_seconds'], )); - if ('single_text' === $options['widget']) { + // Change the input to a HTML5 time input if + // * the widget is set to "single_text" + // * the allow_html5 is set to true + if ($options['allow_html5'] && 'single_text' === $options['widget']) { $view->vars['type'] = 'time'; // we need to force the browser to display the seconds by @@ -192,6 +195,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'model_timezone' => null, 'view_timezone' => null, 'empty_value' => $emptyValue, + 'allow_html5' => true, // Don't modify \DateTime classes by reference, we treat // them like immutable value objects 'by_reference' => false, diff --git a/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php b/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php index c8f3806086..16a7a4ad81 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php @@ -32,7 +32,7 @@ protected function tearDown() $this->dateTimeWithoutSeconds = null; } - public static function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE) + public static function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) { if ($expected instanceof \DateTime && $actual instanceof \DateTime) { $expected = $expected->format('c'); diff --git a/Tests/Extension/Core/Type/DateTimeTypeTest.php b/Tests/Extension/Core/Type/DateTimeTypeTest.php index c76039262d..180d68716e 100644 --- a/Tests/Extension/Core/Type/DateTimeTypeTest.php +++ b/Tests/Extension/Core/Type/DateTimeTypeTest.php @@ -405,6 +405,17 @@ public function testPassHtml5TypeIfSingleTextAndHtml5Format() $this->assertSame('datetime', $view->vars['type']); } + public function testDontPassHtml5TypeIfHtml5NotAllowed() + { + $form = $this->factory->create('datetime', null, array( + 'widget' => 'single_text', + 'allow_html5' => false, + )); + + $view = $form->createView(); + $this->assertFalse(isset($view->vars['type'])); + } + public function testDontPassHtml5TypeIfNotHtml5Format() { $form = $this->factory->create('datetime', null, array( diff --git a/Tests/Extension/Core/Type/DateTypeTest.php b/Tests/Extension/Core/Type/DateTypeTest.php index e38bfe0ebb..0554362cbf 100644 --- a/Tests/Extension/Core/Type/DateTypeTest.php +++ b/Tests/Extension/Core/Type/DateTypeTest.php @@ -705,6 +705,17 @@ public function testPassHtml5TypeIfSingleTextAndHtml5Format() $this->assertSame('date', $view->vars['type']); } + public function testDontPassHtml5TypeIfHtml5NotAllowed() + { + $form = $this->factory->create('date', null, array( + 'widget' => 'single_text', + 'allow_html5' => false, + )); + + $view = $form->createView(); + $this->assertFalse(isset($view->vars['type'])); + } + public function testDontPassHtml5TypeIfNotHtml5Format() { $form = $this->factory->create('date', null, array( diff --git a/Tests/Extension/Core/Type/TimeTypeTest.php b/Tests/Extension/Core/Type/TimeTypeTest.php index bfd1b79347..f73d5caddc 100644 --- a/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/Tests/Extension/Core/Type/TimeTypeTest.php @@ -519,6 +519,17 @@ public function testSingleTextWidgetWithSecondsShouldNotOverrideStepAttribute() $this->assertEquals(30, $view->vars['attr']['step']); } + public function testDontPassHtml5TypeIfHtml5NotAllowed() + { + $form = $this->factory->create('time', null, array( + 'widget' => 'single_text', + 'allow_html5' => false, + )); + + $view = $form->createView(); + $this->assertFalse(isset($view->vars['type'])); + } + public function testPassDefaultEmptyValueToViewIfNotRequired() { $form = $this->factory->create('time', null, array( From a8cface29011434c9ad565b7cbd79a70b34b4257 Mon Sep 17 00:00:00 2001 From: WouterJ Date: Sat, 26 Jul 2014 11:54:23 +0200 Subject: [PATCH 316/447] Unify null comparisons --- Tests/Extension/Validator/ViolationMapper/ViolationPathTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.php b/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.php index 02df8f43eb..2dab4ffad7 100644 --- a/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.php +++ b/Tests/Extension/Validator/ViolationMapper/ViolationPathTest.php @@ -126,7 +126,7 @@ public function provideParents() public function testGetParent($violationPath, $parentPath) { $path = new ViolationPath($violationPath); - $parent = $parentPath === null ? null : new ViolationPath($parentPath); + $parent = null === $parentPath ? null : new ViolationPath($parentPath); $this->assertEquals($parent, $path->getParent()); } From 4d6c31dbf67ce45b0e02f49707c3a5f916cd54ce Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 26 Jul 2014 14:21:36 +0200 Subject: [PATCH 317/447] remove unused imports --- Extension/Core/Type/LocaleType.php | 1 - 1 file changed, 1 deletion(-) diff --git a/Extension/Core/Type/LocaleType.php b/Extension/Core/Type/LocaleType.php index c68c561a2d..4610c1b459 100644 --- a/Extension/Core/Type/LocaleType.php +++ b/Extension/Core/Type/LocaleType.php @@ -13,7 +13,6 @@ use Symfony\Component\Form\AbstractType; use Symfony\Component\Intl\Intl; -use Symfony\Component\Locale\Locale; use Symfony\Component\OptionsResolver\OptionsResolverInterface; class LocaleType extends AbstractType From 740a6926e99b3b143075c7e9f2517858e9ff96aa Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 27 Jul 2014 10:25:12 +0200 Subject: [PATCH 318/447] fixed CS --- .../Core/DataTransformer/DateTimeToRfc3339TransformerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php b/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php index c8f3806086..16a7a4ad81 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php @@ -32,7 +32,7 @@ protected function tearDown() $this->dateTimeWithoutSeconds = null; } - public static function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE) + public static function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false) { if ($expected instanceof \DateTime && $actual instanceof \DateTime) { $expected = $expected->format('c'); From 9791f0a0c2f80f2d1f6dffe117871a34751e4f29 Mon Sep 17 00:00:00 2001 From: g123456789l Date: Sun, 27 Jul 2014 09:53:15 -0400 Subject: [PATCH 319/447] Update validators.eu.xlf Spelling of 'CSRF' was incorrect --- Resources/translations/validators.eu.xlf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/translations/validators.eu.xlf b/Resources/translations/validators.eu.xlf index a07f786c72..ba741ab0fc 100644 --- a/Resources/translations/validators.eu.xlf +++ b/Resources/translations/validators.eu.xlf @@ -12,7 +12,7 @@ The CSRF token is invalid. - CSFR tokena ez da egokia. + CSRF tokena ez da egokia. From bca6730db0e42f1e6a43d12ed0611a6c86818041 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 26 Jul 2014 14:09:47 +0200 Subject: [PATCH 320/447] fix some docblocks --- ButtonBuilder.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ButtonBuilder.php b/ButtonBuilder.php index 9302af4190..b02f8f5fe1 100644 --- a/ButtonBuilder.php +++ b/ButtonBuilder.php @@ -503,6 +503,8 @@ public function setRequestHandler(RequestHandlerInterface $requestHandler) * * @param bool $initialize * + * @return ButtonBuilder + * * @throws BadMethodCallException */ public function setAutoInitialize($initialize) From 25c892aed20ce15e99bf84eee2f9e7263f14ed30 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Tue, 5 Aug 2014 17:39:31 +0200 Subject: [PATCH 321/447] [Form] Fixed FormValidator compatibility with the non-BC 2.5 Validation API --- .../Validator/Constraints/FormValidator.php | 35 +-- .../Constraints/LegacyFormValidator.php | 223 +++++++++++++ .../Constraints/FormValidatorTest.php | 296 +++++++----------- .../LegacyFormValidator2Dot4ApiTest.php | 32 ++ .../LegacyFormValidatorLegacyApiTest.php | 26 ++ 5 files changed, 408 insertions(+), 204 deletions(-) create mode 100644 Extension/Validator/Constraints/LegacyFormValidator.php create mode 100644 Tests/Extension/Validator/Constraints/LegacyFormValidator2Dot4ApiTest.php create mode 100644 Tests/Extension/Validator/Constraints/LegacyFormValidatorLegacyApiTest.php diff --git a/Extension/Validator/Constraints/FormValidator.php b/Extension/Validator/Constraints/FormValidator.php index ab049bf66d..3e96bc75ac 100644 --- a/Extension/Validator/Constraints/FormValidator.php +++ b/Extension/Validator/Constraints/FormValidator.php @@ -53,6 +53,7 @@ public function validate($form, Constraint $constraint) /* @var FormInterface $form */ $config = $form->getConfig(); + $validator = $this->context->getValidator()->inContext($this->context); if ($form->isSynchronized()) { // Validate the form data only if transformation succeeded @@ -61,7 +62,7 @@ public function validate($form, Constraint $constraint) // Validate the data against its own constraints if (self::allowDataWalking($form)) { foreach ($groups as $group) { - $this->context->validate($form->getData(), 'data', $group, true); + $validator->atPath('data')->validate($form->getData(), null, $group); } } @@ -71,7 +72,7 @@ public function validate($form, Constraint $constraint) foreach ($constraints as $constraint) { foreach ($groups as $group) { if (in_array($group, $constraint->groups)) { - $this->context->validateValue($form->getData(), $constraint, 'data', $group); + $validator->atPath('data')->validate($form->getData(), $constraint, $group); // Prevent duplicate validation continue 2; @@ -100,23 +101,20 @@ public function validate($form, Constraint $constraint) ? (string) $form->getViewData() : gettype($form->getViewData()); - $this->context->addViolation( - $config->getOption('invalid_message'), - array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters')), - $form->getViewData(), - null, - Form::ERR_INVALID - ); + $this->context->buildViolation($config->getOption('invalid_message')) + ->setParameters(array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters'))) + ->setInvalidValue($form->getViewData()) + ->setCode(Form::ERR_INVALID) + ->addViolation(); } } // Mark the form with an error if it contains extra fields if (count($form->getExtraData()) > 0) { - $this->context->addViolation( - $config->getOption('extra_fields_message'), - array('{{ extra_fields }}' => implode('", "', array_keys($form->getExtraData()))), - $form->getExtraData() - ); + $this->context->buildViolation($config->getOption('extra_fields_message')) + ->setParameter('{{ extra_fields }}', implode('", "', array_keys($form->getExtraData()))) + ->setInvalidValue($form->getExtraData()) + ->addViolation(); } // Mark the form with an error if the uploaded size was too large @@ -126,11 +124,10 @@ public function validate($form, Constraint $constraint) $max = $this->serverParams->getPostMaxSize(); if (!empty($max) && $length > $max) { - $this->context->addViolation( - $config->getOption('post_max_size_message'), - array('{{ max }}' => $this->serverParams->getNormalizedIniPostMaxSize()), - $length - ); + $this->context->buildViolation($config->getOption('post_max_size_message')) + ->setParameter('{{ max }}', $this->serverParams->getNormalizedIniPostMaxSize()) + ->setInvalidValue($length) + ->addViolation(); } } } diff --git a/Extension/Validator/Constraints/LegacyFormValidator.php b/Extension/Validator/Constraints/LegacyFormValidator.php new file mode 100644 index 0000000000..2ed206b59d --- /dev/null +++ b/Extension/Validator/Constraints/LegacyFormValidator.php @@ -0,0 +1,223 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Extension\Validator\Constraints; + +use Symfony\Component\Form\FormInterface; +use Symfony\Component\Form\Extension\Validator\Util\ServerParams; +use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\ConstraintValidator; +use Symfony\Component\Validator\Exception\UnexpectedTypeException; + +/** + * @author Bernhard Schussek + */ +class LegacyFormValidator extends ConstraintValidator +{ + /** + * @var ServerParams + */ + private $serverParams; + + /** + * Creates a validator with the given server parameters. + * + * @param ServerParams $params The server parameters. Default + * parameters are created if null. + */ + public function __construct(ServerParams $params = null) + { + $this->serverParams = $params ?: new ServerParams(); + } + + /** + * {@inheritdoc} + */ + public function validate($form, Constraint $constraint) + { + if (!$constraint instanceof Form) { + throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Form'); + } + + if (!$form instanceof FormInterface) { + return; + } + + /* @var FormInterface $form */ + $config = $form->getConfig(); + + if ($form->isSynchronized()) { + // Validate the form data only if transformation succeeded + $groups = self::getValidationGroups($form); + + // Validate the data against its own constraints + if (self::allowDataWalking($form)) { + foreach ($groups as $group) { + $this->context->validate($form->getData(), 'data', $group, true); + } + } + + // Validate the data against the constraints defined + // in the form + $constraints = $config->getOption('constraints'); + foreach ($constraints as $constraint) { + foreach ($groups as $group) { + if (in_array($group, $constraint->groups)) { + $this->context->validateValue($form->getData(), $constraint, 'data', $group); + + // Prevent duplicate validation + continue 2; + } + } + } + } else { + $childrenSynchronized = true; + + foreach ($form as $child) { + if (!$child->isSynchronized()) { + $childrenSynchronized = false; + break; + } + } + + // Mark the form with an error if it is not synchronized BUT all + // of its children are synchronized. If any child is not + // synchronized, an error is displayed there already and showing + // a second error in its parent form is pointless, or worse, may + // lead to duplicate errors if error bubbling is enabled on the + // child. + // See also https://github.com/symfony/symfony/issues/4359 + if ($childrenSynchronized) { + $clientDataAsString = is_scalar($form->getViewData()) + ? (string) $form->getViewData() + : gettype($form->getViewData()); + + $this->context->addViolation( + $config->getOption('invalid_message'), + array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters')), + $form->getViewData(), + null, + Form::ERR_INVALID + ); + } + } + + // Mark the form with an error if it contains extra fields + if (count($form->getExtraData()) > 0) { + $this->context->addViolation( + $config->getOption('extra_fields_message'), + array('{{ extra_fields }}' => implode('", "', array_keys($form->getExtraData()))), + $form->getExtraData() + ); + } + + // Mark the form with an error if the uploaded size was too large + $length = $this->serverParams->getContentLength(); + + if ($form->isRoot() && null !== $length) { + $max = $this->serverParams->getPostMaxSize(); + + if (!empty($max) && $length > $max) { + $this->context->addViolation( + $config->getOption('post_max_size_message'), + array('{{ max }}' => $this->serverParams->getNormalizedIniPostMaxSize()), + $length + ); + } + } + } + + /** + * Returns whether the data of a form may be walked. + * + * @param FormInterface $form The form to test. + * + * @return bool Whether the graph walker may walk the data. + */ + private static function allowDataWalking(FormInterface $form) + { + $data = $form->getData(); + + // Scalar values cannot have mapped constraints + if (!is_object($data) && !is_array($data)) { + return false; + } + + // Root forms are always validated + if ($form->isRoot()) { + return true; + } + + // Non-root forms are validated if validation cascading + // is enabled in all ancestor forms + while (null !== ($form = $form->getParent())) { + if (!$form->getConfig()->getOption('cascade_validation')) { + return false; + } + } + + return true; + } + + /** + * Returns the validation groups of the given form. + * + * @param FormInterface $form The form. + * + * @return array The validation groups. + */ + private static function getValidationGroups(FormInterface $form) + { + // Determine the clicked button of the complete form tree + $clickedButton = null; + + if (method_exists($form, 'getClickedButton')) { + $clickedButton = $form->getClickedButton(); + } + + if (null !== $clickedButton) { + $groups = $clickedButton->getConfig()->getOption('validation_groups'); + + if (null !== $groups) { + return self::resolveValidationGroups($groups, $form); + } + } + + do { + $groups = $form->getConfig()->getOption('validation_groups'); + + if (null !== $groups) { + return self::resolveValidationGroups($groups, $form); + } + + $form = $form->getParent(); + } while (null !== $form); + + return array(Constraint::DEFAULT_GROUP); + } + + /** + * Post-processes the validation groups option for a given form. + * + * @param array|callable $groups The validation groups. + * @param FormInterface $form The validated form. + * + * @return array The validation groups. + */ + private static function resolveValidationGroups($groups, FormInterface $form) + { + if (!is_string($groups) && is_callable($groups)) { + $groups = call_user_func($groups, $form); + } + + return (array) $groups; + } +} diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index 4d9c26b81c..f8bf154d6e 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -21,11 +21,13 @@ use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\NotBlank; +use Symfony\Component\Validator\Tests\Constraints\AbstractConstraintValidatorTest; +use Symfony\Component\Validator\Validation; /** * @author Bernhard Schussek */ -class FormValidatorTest extends \PHPUnit_Framework_TestCase +class FormValidatorTest extends AbstractConstraintValidatorTest { /** * @var \PHPUnit_Framework_MockObject_MockObject @@ -40,12 +42,7 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase /** * @var \PHPUnit_Framework_MockObject_MockObject */ - private $serverParams; - - /** - * @var FormValidator - */ - private $validator; + protected $serverParams; protected function setUp() { @@ -55,32 +52,38 @@ protected function setUp() 'Symfony\Component\Form\Extension\Validator\Util\ServerParams', array('getNormalizedIniPostMaxSize', 'getContentLength') ); - $this->validator = new FormValidator($this->serverParams); + + parent::setUp(); + } + + protected function getApiVersion() + { + return Validation::API_VERSION_2_5; + } + + protected function createValidator() + { + return new FormValidator($this->serverParams); } public function testValidate() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => array('group1', 'group2')); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); - $context->expects($this->at(0)) - ->method('validate') - ->with($object, 'data', 'group1', true); - $context->expects($this->at(1)) - ->method('validate') - ->with($object, 'data', 'group2', true); + $this->expectValidateAt(0, 'data', $object, 'group1'); + $this->expectValidateAt(1, 'data', $object, 'group2'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testValidateConstraints() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $constraint1 = new NotNull(array('groups' => array('group1', 'group2'))); $constraint2 = new NotBlank(array('groups' => 'group2')); @@ -94,28 +97,20 @@ public function testValidateConstraints() ->getForm(); // First default constraints - $context->expects($this->at(0)) - ->method('validate') - ->with($object, 'data', 'group1', true); - $context->expects($this->at(1)) - ->method('validate') - ->with($object, 'data', 'group2', true); + $this->expectValidateAt(0, 'data', $object, 'group1'); + $this->expectValidateAt(1, 'data', $object, 'group2'); // Then custom constraints - $context->expects($this->at(2)) - ->method('validateValue') - ->with($object, $constraint1, 'data', 'group1'); - $context->expects($this->at(3)) - ->method('validateValue') - ->with($object, $constraint2, 'data', 'group2'); - - $this->validator->initialize($context); + $this->expectValidateValueAt(2, 'data', $object, $constraint1, 'group1'); + $this->expectValidateValueAt(3, 'data', $object, $constraint2, 'group2'); + $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testDontValidateIfParentWithoutCascadeValidation() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parent = $this->getBuilder('parent', null, array('cascade_validation' => false)) @@ -128,16 +123,15 @@ public function testDontValidateIfParentWithoutCascadeValidation() $form->setData($object); - $context->expects($this->never()) - ->method('validate'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testValidateConstraintsEvenIfNoCascadeValidation() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $constraint1 = new NotNull(array('groups' => array('group1', 'group2'))); $constraint2 = new NotBlank(array('groups' => 'group2')); @@ -155,20 +149,16 @@ public function testValidateConstraintsEvenIfNoCascadeValidation() ->getForm(); $parent->add($form); - $context->expects($this->at(0)) - ->method('validateValue') - ->with($object, $constraint1, 'data', 'group1'); - $context->expects($this->at(1)) - ->method('validateValue') - ->with($object, $constraint2, 'data', 'group2'); + $this->expectValidateValueAt(0, 'data', $object, $constraint1, 'group1'); + $this->expectValidateValueAt(1, 'data', $object, $constraint2, 'group2'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testDontValidateIfNoValidationGroups() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $form = $this->getBuilder('name', '\stdClass', array( @@ -179,16 +169,15 @@ public function testDontValidateIfNoValidationGroups() $form->setData($object); - $context->expects($this->never()) - ->method('validate'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testDontValidateConstraintsIfNoValidationGroups() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $constraint1 = $this->getMock('Symfony\Component\Validator\Constraint'); $constraint2 = $this->getMock('Symfony\Component\Validator\Constraint'); @@ -204,16 +193,15 @@ public function testDontValidateConstraintsIfNoValidationGroups() // Launch transformer $form->submit(array()); - $context->expects($this->never()) - ->method('validate'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testDontValidateIfNotSynchronized() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $form = $this->getBuilder('name', '\stdClass', array( @@ -233,26 +221,18 @@ function () { throw new TransformationFailedException(); } // Launch transformer $form->submit('foo'); - $context->expects($this->never()) - ->method('validate'); - - $context->expects($this->once()) - ->method('addViolation') - ->with( - 'invalid_message_key', - array('{{ value }}' => 'foo', '{{ foo }}' => 'bar'), - 'foo' - ); - $context->expects($this->never()) - ->method('addViolationAt'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertViolation('invalid_message_key', array( + '{{ value }}' => 'foo', + '{{ foo }}' => 'bar' + ), 'property.path', 'foo', null, Form::ERR_INVALID); } public function testAddInvalidErrorEvenIfNoValidationGroups() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $form = $this->getBuilder('name', '\stdClass', array( @@ -273,31 +253,24 @@ function () { throw new TransformationFailedException(); } // Launch transformer $form->submit('foo'); - $context->expects($this->never()) - ->method('validate'); - - $context->expects($this->once()) - ->method('addViolation') - ->with( - 'invalid_message_key', - array('{{ value }}' => 'foo', '{{ foo }}' => 'bar'), - 'foo' - ); - $context->expects($this->never()) - ->method('addViolationAt'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertViolation('invalid_message_key', array( + '{{ value }}' => 'foo', + '{{ foo }}' => 'bar' + ), 'property.path', 'foo', null, Form::ERR_INVALID); } public function testDontValidateConstraintsIfNotSynchronized() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $constraint1 = $this->getMock('Symfony\Component\Validator\Constraint'); $constraint2 = $this->getMock('Symfony\Component\Validator\Constraint'); $options = array( + 'invalid_message' => 'invalid_message_key', 'validation_groups' => array('group1', 'group2'), 'constraints' => array($constraint1, $constraint2), ); @@ -310,19 +283,20 @@ function () { throw new TransformationFailedException(); } ->getForm(); // Launch transformer - $form->submit(array()); + $form->submit('foo'); - $context->expects($this->never()) - ->method('validate'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertViolation('invalid_message_key', array( + '{{ value }}' => 'foo', + ), 'property.path','foo', null, Form::ERR_INVALID); } // https://github.com/symfony/symfony/issues/4359 public function testDontMarkInvalidIfAnyChildIsNotSynchronized() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $failingTransformer = new CallbackTransformer( @@ -344,55 +318,46 @@ function () { throw new TransformationFailedException(); } // Launch transformer $form->submit(array('child' => 'foo')); - $context->expects($this->never()) - ->method('addViolation'); - $context->expects($this->never()) - ->method('addViolationAt'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testHandleCallbackValidationGroups() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => array($this, 'getValidationGroups')); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); - $context->expects($this->at(0)) - ->method('validate') - ->with($object, 'data', 'group1', true); - $context->expects($this->at(1)) - ->method('validate') - ->with($object, 'data', 'group2', true); + $this->expectValidateAt(0, 'data', $object, 'group1'); + $this->expectValidateAt(1, 'data', $object, 'group2'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testDontExecuteFunctionNames() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => 'header'); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); - $context->expects($this->once()) - ->method('validate') - ->with($object, 'data', 'header', true); + $this->expectValidateAt(0, 'data', $object, 'header'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testHandleClosureValidationGroups() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => function (FormInterface $form) { return array('group1', 'group2'); @@ -401,20 +366,16 @@ public function testHandleClosureValidationGroups() ->setData($object) ->getForm(); - $context->expects($this->at(0)) - ->method('validate') - ->with($object, 'data', 'group1', true); - $context->expects($this->at(1)) - ->method('validate') - ->with($object, 'data', 'group2', true); + $this->expectValidateAt(0, 'data', $object, 'group1'); + $this->expectValidateAt(1, 'data', $object, 'group2'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testUseValidationGroupOfClickedButton() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parent = $this->getBuilder('parent', null, array('cascade_validation' => true)) @@ -432,17 +393,15 @@ public function testUseValidationGroupOfClickedButton() $parent->submit(array('name' => $object, 'submit' => '')); - $context->expects($this->once()) - ->method('validate') - ->with($object, 'data', 'button_group', true); + $this->expectValidateAt(0, 'data', $object, 'button_group'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testDontUseValidationGroupOfUnclickedButton() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parent = $this->getBuilder('parent', null, array('cascade_validation' => true)) @@ -460,17 +419,15 @@ public function testDontUseValidationGroupOfUnclickedButton() $form->setData($object); - $context->expects($this->once()) - ->method('validate') - ->with($object, 'data', 'form_group', true); + $this->expectValidateAt(0, 'data', $object, 'form_group'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testUseInheritedValidationGroup() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parentOptions = array( @@ -486,17 +443,15 @@ public function testUseInheritedValidationGroup() $form->setData($object); - $context->expects($this->once()) - ->method('validate') - ->with($object, 'data', 'group', true); + $this->expectValidateAt(0, 'data', $object, 'group'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testUseInheritedCallbackValidationGroup() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parentOptions = array( @@ -512,20 +467,16 @@ public function testUseInheritedCallbackValidationGroup() $form->setData($object); - $context->expects($this->at(0)) - ->method('validate') - ->with($object, 'data', 'group1', true); - $context->expects($this->at(1)) - ->method('validate') - ->with($object, 'data', 'group2', true); + $this->expectValidateAt(0, 'data', $object, 'group1'); + $this->expectValidateAt(1, 'data', $object, 'group2'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testUseInheritedClosureValidationGroup() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parentOptions = array( @@ -543,52 +494,43 @@ public function testUseInheritedClosureValidationGroup() $form->setData($object); - $context->expects($this->at(0)) - ->method('validate') - ->with($object, 'data', 'group1', true); - $context->expects($this->at(1)) - ->method('validate') - ->with($object, 'data', 'group2', true); + $this->expectValidateAt(0, 'data', $object, 'group1'); + $this->expectValidateAt(1, 'data', $object, 'group2'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testAppendPropertyPath() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $form = $this->getBuilder('name', '\stdClass') ->setData($object) ->getForm(); - $context->expects($this->once()) - ->method('validate') - ->with($object, 'data', 'Default', true); + $this->expectValidateAt(0, 'data', $object, 'Default'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testDontWalkScalars() { - $context = $this->getMockExecutionContext(); - $form = $this->getBuilder() ->setData('scalar') ->getForm(); - $context->expects($this->never()) - ->method('validate'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testViolationIfExtraData() { - $context = $this->getMockExecutionContext(); - $form = $this->getBuilder('parent', null, array('extra_fields_message' => 'Extra!')) ->setCompound(true) ->setDataMapper($this->getDataMapper()) @@ -597,18 +539,13 @@ public function testViolationIfExtraData() $form->submit(array('foo' => 'bar')); - $context->expects($this->once()) - ->method('addViolation') - ->with( - 'Extra!', - array('{{ extra_fields }}' => 'foo'), - array('foo' => 'bar') - ); - $context->expects($this->never()) - ->method('addViolationAt'); - - $this->validator->initialize($context); + $this->expectNoValidate(); + $this->validator->validate($form, new Form()); + + $this->assertViolation('Extra!', array( + '{{ extra_fields }}' => 'foo' + ), 'property.path', array('foo' => 'bar')); } /** @@ -623,26 +560,18 @@ public function testPostMaxSizeViolation($contentLength, $iniMax, $nbViolation, ->method('getNormalizedIniPostMaxSize') ->will($this->returnValue($iniMax)); - $context = $this->getMockExecutionContext(); $options = array('post_max_size_message' => 'Max {{ max }}!'); $form = $this->getBuilder('name', null, $options)->getForm(); + $this->validator->validate($form, new Form()); + + $violations = array(); + for ($i = 0; $i < $nbViolation; ++$i) { - if (0 === $i && count($params) > 0) { - $context->expects($this->at($i)) - ->method('addViolation') - ->with($options['post_max_size_message'], $params); - } else { - $context->expects($this->at($i)) - ->method('addViolation'); - } + $violations[] = $this->createViolation($options['post_max_size_message'], $params, 'property.path', $contentLength); } - $context->expects($this->never()) - ->method('addViolationAt'); - - $this->validator->initialize($context); - $this->validator->validate($form, new Form()); + $this->assertViolations($violations); } public function getPostMaxSizeFixtures() @@ -668,7 +597,6 @@ public function testNoViolationIfNotRoot() $this->serverParams->expects($this->never()) ->method('getNormalizedIniPostMaxSize'); - $context = $this->getMockExecutionContext(); $parent = $this->getBuilder() ->setCompound(true) ->setDataMapper($this->getDataMapper()) @@ -676,13 +604,11 @@ public function testNoViolationIfNotRoot() $form = $this->getForm(); $parent->add($form); - $context->expects($this->never()) - ->method('addViolation'); - $context->expects($this->never()) - ->method('addViolationAt'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } /** diff --git a/Tests/Extension/Validator/Constraints/LegacyFormValidator2Dot4ApiTest.php b/Tests/Extension/Validator/Constraints/LegacyFormValidator2Dot4ApiTest.php new file mode 100644 index 0000000000..a54e10676f --- /dev/null +++ b/Tests/Extension/Validator/Constraints/LegacyFormValidator2Dot4ApiTest.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Validator\Constraints; + +use Symfony\Component\Form\Extension\Validator\Constraints\LegacyFormValidator; +use Symfony\Component\Validator\Validation; + +/** + * @since 2.5.3 + * @author Bernhard Schussek + */ +class LegacyFormValidator2Dot4ApiTest extends FormValidatorTest +{ + protected function getApiVersion() + { + return Validation::API_VERSION_2_4; + } + + protected function createValidator() + { + return new LegacyFormValidator($this->serverParams); + } +} diff --git a/Tests/Extension/Validator/Constraints/LegacyFormValidatorLegacyApiTest.php b/Tests/Extension/Validator/Constraints/LegacyFormValidatorLegacyApiTest.php new file mode 100644 index 0000000000..faa68b2518 --- /dev/null +++ b/Tests/Extension/Validator/Constraints/LegacyFormValidatorLegacyApiTest.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Validator\Constraints; + +use Symfony\Component\Validator\Validation; + +/** + * @since 2.5.3 + * @author Bernhard Schussek + */ +class LegacyFormValidatorLegacyApiTest extends FormValidatorTest +{ + protected function getApiVersion() + { + return Validation::API_VERSION_2_5_BC; + } +} From fb0765dd0317c75d1c023a654dc6d805e0d95b0d Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Wed, 6 Aug 2014 15:23:29 +0200 Subject: [PATCH 322/447] [Validator] Removed legacy validator classes --- .../Validator/Constraints/FormValidator.php | 76 ++++-- .../Constraints/LegacyFormValidator.php | 223 ------------------ .../LegacyFormValidator2Dot4ApiTest.php | 6 - 3 files changed, 60 insertions(+), 245 deletions(-) delete mode 100644 Extension/Validator/Constraints/LegacyFormValidator.php diff --git a/Extension/Validator/Constraints/FormValidator.php b/Extension/Validator/Constraints/FormValidator.php index 3e96bc75ac..1efadfd66d 100644 --- a/Extension/Validator/Constraints/FormValidator.php +++ b/Extension/Validator/Constraints/FormValidator.php @@ -15,6 +15,7 @@ use Symfony\Component\Form\Extension\Validator\Util\ServerParams; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; +use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** @@ -53,7 +54,11 @@ public function validate($form, Constraint $constraint) /* @var FormInterface $form */ $config = $form->getConfig(); - $validator = $this->context->getValidator()->inContext($this->context); + $validator = null; + + if ($this->context instanceof ExecutionContextInterface) { + $validator = $this->context->getValidator()->inContext($this->context); + } if ($form->isSynchronized()) { // Validate the form data only if transformation succeeded @@ -62,7 +67,12 @@ public function validate($form, Constraint $constraint) // Validate the data against its own constraints if (self::allowDataWalking($form)) { foreach ($groups as $group) { - $validator->atPath('data')->validate($form->getData(), null, $group); + if ($validator) { + $validator->atPath('data')->validate($form->getData(), null, $group); + } else { + // 2.4 API + $this->context->validate($form->getData(), 'data', $group, true); + } } } @@ -72,7 +82,12 @@ public function validate($form, Constraint $constraint) foreach ($constraints as $constraint) { foreach ($groups as $group) { if (in_array($group, $constraint->groups)) { - $validator->atPath('data')->validate($form->getData(), $constraint, $group); + if ($validator) { + $validator->atPath('data')->validate($form->getData(), $constraint, $group); + } else { + // 2.4 API + $this->context->validateValue($form->getData(), $constraint, 'data', $group); + } // Prevent duplicate validation continue 2; @@ -101,20 +116,40 @@ public function validate($form, Constraint $constraint) ? (string) $form->getViewData() : gettype($form->getViewData()); - $this->context->buildViolation($config->getOption('invalid_message')) - ->setParameters(array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters'))) - ->setInvalidValue($form->getViewData()) - ->setCode(Form::ERR_INVALID) - ->addViolation(); + if ($this->context instanceof ExecutionContextInterface) { + $this->context->buildViolation($config->getOption('invalid_message')) + ->setParameters(array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters'))) + ->setInvalidValue($form->getViewData()) + ->setCode(Form::ERR_INVALID) + ->addViolation(); + } else { + // 2.4 API + $this->context->addViolation( + $config->getOption('invalid_message'), + array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters')), + $form->getViewData(), + null, + Form::ERR_INVALID + ); + } } } // Mark the form with an error if it contains extra fields if (count($form->getExtraData()) > 0) { - $this->context->buildViolation($config->getOption('extra_fields_message')) - ->setParameter('{{ extra_fields }}', implode('", "', array_keys($form->getExtraData()))) - ->setInvalidValue($form->getExtraData()) - ->addViolation(); + if ($this->context instanceof ExecutionContextInterface) { + $this->context->buildViolation($config->getOption('extra_fields_message')) + ->setParameter('{{ extra_fields }}', implode('", "', array_keys($form->getExtraData()))) + ->setInvalidValue($form->getExtraData()) + ->addViolation(); + } else { + // 2.4 API + $this->context->addViolation( + $config->getOption('extra_fields_message'), + array('{{ extra_fields }}' => implode('", "', array_keys($form->getExtraData()))), + $form->getExtraData() + ); + } } // Mark the form with an error if the uploaded size was too large @@ -124,10 +159,19 @@ public function validate($form, Constraint $constraint) $max = $this->serverParams->getPostMaxSize(); if (!empty($max) && $length > $max) { - $this->context->buildViolation($config->getOption('post_max_size_message')) - ->setParameter('{{ max }}', $this->serverParams->getNormalizedIniPostMaxSize()) - ->setInvalidValue($length) - ->addViolation(); + if ($this->context instanceof ExecutionContextInterface) { + $this->context->buildViolation($config->getOption('post_max_size_message')) + ->setParameter('{{ max }}', $this->serverParams->getNormalizedIniPostMaxSize()) + ->setInvalidValue($length) + ->addViolation(); + } else { + // 2.4 API + $this->context->addViolation( + $config->getOption('post_max_size_message'), + array('{{ max }}' => $this->serverParams->getNormalizedIniPostMaxSize()), + $length + ); + } } } } diff --git a/Extension/Validator/Constraints/LegacyFormValidator.php b/Extension/Validator/Constraints/LegacyFormValidator.php deleted file mode 100644 index 2ed206b59d..0000000000 --- a/Extension/Validator/Constraints/LegacyFormValidator.php +++ /dev/null @@ -1,223 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Extension\Validator\Constraints; - -use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\Extension\Validator\Util\ServerParams; -use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\ConstraintValidator; -use Symfony\Component\Validator\Exception\UnexpectedTypeException; - -/** - * @author Bernhard Schussek - */ -class LegacyFormValidator extends ConstraintValidator -{ - /** - * @var ServerParams - */ - private $serverParams; - - /** - * Creates a validator with the given server parameters. - * - * @param ServerParams $params The server parameters. Default - * parameters are created if null. - */ - public function __construct(ServerParams $params = null) - { - $this->serverParams = $params ?: new ServerParams(); - } - - /** - * {@inheritdoc} - */ - public function validate($form, Constraint $constraint) - { - if (!$constraint instanceof Form) { - throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Form'); - } - - if (!$form instanceof FormInterface) { - return; - } - - /* @var FormInterface $form */ - $config = $form->getConfig(); - - if ($form->isSynchronized()) { - // Validate the form data only if transformation succeeded - $groups = self::getValidationGroups($form); - - // Validate the data against its own constraints - if (self::allowDataWalking($form)) { - foreach ($groups as $group) { - $this->context->validate($form->getData(), 'data', $group, true); - } - } - - // Validate the data against the constraints defined - // in the form - $constraints = $config->getOption('constraints'); - foreach ($constraints as $constraint) { - foreach ($groups as $group) { - if (in_array($group, $constraint->groups)) { - $this->context->validateValue($form->getData(), $constraint, 'data', $group); - - // Prevent duplicate validation - continue 2; - } - } - } - } else { - $childrenSynchronized = true; - - foreach ($form as $child) { - if (!$child->isSynchronized()) { - $childrenSynchronized = false; - break; - } - } - - // Mark the form with an error if it is not synchronized BUT all - // of its children are synchronized. If any child is not - // synchronized, an error is displayed there already and showing - // a second error in its parent form is pointless, or worse, may - // lead to duplicate errors if error bubbling is enabled on the - // child. - // See also https://github.com/symfony/symfony/issues/4359 - if ($childrenSynchronized) { - $clientDataAsString = is_scalar($form->getViewData()) - ? (string) $form->getViewData() - : gettype($form->getViewData()); - - $this->context->addViolation( - $config->getOption('invalid_message'), - array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters')), - $form->getViewData(), - null, - Form::ERR_INVALID - ); - } - } - - // Mark the form with an error if it contains extra fields - if (count($form->getExtraData()) > 0) { - $this->context->addViolation( - $config->getOption('extra_fields_message'), - array('{{ extra_fields }}' => implode('", "', array_keys($form->getExtraData()))), - $form->getExtraData() - ); - } - - // Mark the form with an error if the uploaded size was too large - $length = $this->serverParams->getContentLength(); - - if ($form->isRoot() && null !== $length) { - $max = $this->serverParams->getPostMaxSize(); - - if (!empty($max) && $length > $max) { - $this->context->addViolation( - $config->getOption('post_max_size_message'), - array('{{ max }}' => $this->serverParams->getNormalizedIniPostMaxSize()), - $length - ); - } - } - } - - /** - * Returns whether the data of a form may be walked. - * - * @param FormInterface $form The form to test. - * - * @return bool Whether the graph walker may walk the data. - */ - private static function allowDataWalking(FormInterface $form) - { - $data = $form->getData(); - - // Scalar values cannot have mapped constraints - if (!is_object($data) && !is_array($data)) { - return false; - } - - // Root forms are always validated - if ($form->isRoot()) { - return true; - } - - // Non-root forms are validated if validation cascading - // is enabled in all ancestor forms - while (null !== ($form = $form->getParent())) { - if (!$form->getConfig()->getOption('cascade_validation')) { - return false; - } - } - - return true; - } - - /** - * Returns the validation groups of the given form. - * - * @param FormInterface $form The form. - * - * @return array The validation groups. - */ - private static function getValidationGroups(FormInterface $form) - { - // Determine the clicked button of the complete form tree - $clickedButton = null; - - if (method_exists($form, 'getClickedButton')) { - $clickedButton = $form->getClickedButton(); - } - - if (null !== $clickedButton) { - $groups = $clickedButton->getConfig()->getOption('validation_groups'); - - if (null !== $groups) { - return self::resolveValidationGroups($groups, $form); - } - } - - do { - $groups = $form->getConfig()->getOption('validation_groups'); - - if (null !== $groups) { - return self::resolveValidationGroups($groups, $form); - } - - $form = $form->getParent(); - } while (null !== $form); - - return array(Constraint::DEFAULT_GROUP); - } - - /** - * Post-processes the validation groups option for a given form. - * - * @param array|callable $groups The validation groups. - * @param FormInterface $form The validated form. - * - * @return array The validation groups. - */ - private static function resolveValidationGroups($groups, FormInterface $form) - { - if (!is_string($groups) && is_callable($groups)) { - $groups = call_user_func($groups, $form); - } - - return (array) $groups; - } -} diff --git a/Tests/Extension/Validator/Constraints/LegacyFormValidator2Dot4ApiTest.php b/Tests/Extension/Validator/Constraints/LegacyFormValidator2Dot4ApiTest.php index a54e10676f..fb3208facd 100644 --- a/Tests/Extension/Validator/Constraints/LegacyFormValidator2Dot4ApiTest.php +++ b/Tests/Extension/Validator/Constraints/LegacyFormValidator2Dot4ApiTest.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\Constraints; -use Symfony\Component\Form\Extension\Validator\Constraints\LegacyFormValidator; use Symfony\Component\Validator\Validation; /** @@ -24,9 +23,4 @@ protected function getApiVersion() { return Validation::API_VERSION_2_4; } - - protected function createValidator() - { - return new LegacyFormValidator($this->serverParams); - } } From 9f42e24eb9d282f24859ffe27d683413669970d6 Mon Sep 17 00:00:00 2001 From: "Issei.M" Date: Wed, 6 Aug 2014 12:51:22 +0900 Subject: [PATCH 323/447] [Form] allowed CallbackTransformer to use callable --- CallbackTransformer.php | 21 +++++++++++++----- Tests/CallbackTransformerTest.php | 37 +++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 Tests/CallbackTransformerTest.php diff --git a/CallbackTransformer.php b/CallbackTransformer.php index c53c6df788..03459d4e8a 100644 --- a/CallbackTransformer.php +++ b/CallbackTransformer.php @@ -18,24 +18,33 @@ class CallbackTransformer implements DataTransformerInterface { /** * The callback used for forward transform - * @var \Closure + * @var callable */ private $transform; /** * The callback used for reverse transform - * @var \Closure + * @var callable */ private $reverseTransform; /** * Constructor. * - * @param \Closure $transform The forward transform callback - * @param \Closure $reverseTransform The reverse transform callback + * @param callable $transform The forward transform callback + * @param callable $reverseTransform The reverse transform callback + * + * @throws \InvalidArgumentException when the given callbacks is invalid */ - public function __construct(\Closure $transform, \Closure $reverseTransform) + public function __construct($transform, $reverseTransform) { + if (!is_callable($transform)) { + throw new \InvalidArgumentException('Argument 1 should be a callable'); + } + if (!is_callable($reverseTransform)) { + throw new \InvalidArgumentException('Argument 2 should be a callable'); + } + $this->transform = $transform; $this->reverseTransform = $reverseTransform; } @@ -47,7 +56,7 @@ public function __construct(\Closure $transform, \Closure $reverseTransform) * * @return mixed The value in the transformed representation * - * @throws UnexpectedTypeException when the argument is not a string + * @throws UnexpectedTypeException when the argument is not of the expected type * @throws TransformationFailedException when the transformation fails */ public function transform($data) diff --git a/Tests/CallbackTransformerTest.php b/Tests/CallbackTransformerTest.php new file mode 100644 index 0000000000..706bc076ec --- /dev/null +++ b/Tests/CallbackTransformerTest.php @@ -0,0 +1,37 @@ +assertEquals('foo has been transformed', $transformer->transform('foo')); + $this->assertEquals('bar has reversely been transformed', $transformer->reverseTransform('bar')); + } + + /** + * @dataProvider invalidCallbacksProvider + * + * @expectedException \InvalidArgumentException + */ + public function testConstructorWithInvalidCallbacks($transformCallback, $reverseTransformCallback) + { + new CallbackTransformer($transformCallback, $reverseTransformCallback); + } + + public function invalidCallbacksProvider() + { + return array( + array( null, function(){} ), + array( function(){}, null ), + ); + } +} From 775c55b8fc1b60ca5d5ff6f86e25f42078b4e359 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 8 Aug 2014 10:10:43 +0200 Subject: [PATCH 324/447] [Validator] Backported constraint validator tests from 2.5 --- .../Constraints/FormValidatorTest.php | 294 +++++++----------- 1 file changed, 105 insertions(+), 189 deletions(-) diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index dc504172a0..bfb84a15f8 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -21,11 +21,12 @@ use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\NotBlank; +use Symfony\Component\Validator\Tests\Constraints\AbstractConstraintValidatorTest; /** * @author Bernhard Schussek */ -class FormValidatorTest extends \PHPUnit_Framework_TestCase +class FormValidatorTest extends AbstractConstraintValidatorTest { /** * @var \PHPUnit_Framework_MockObject_MockObject @@ -40,51 +41,43 @@ class FormValidatorTest extends \PHPUnit_Framework_TestCase /** * @var \PHPUnit_Framework_MockObject_MockObject */ - private $serverParams; - - /** - * @var FormValidator - */ - private $validator; + protected $serverParams; protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\Event')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->serverParams = $this->getMock( 'Symfony\Component\Form\Extension\Validator\Util\ServerParams', array('getNormalizedIniPostMaxSize', 'getContentLength') ); - $this->validator = new FormValidator($this->serverParams); + + parent::setUp(); + } + + protected function createValidator() + { + return new FormValidator($this->serverParams); } public function testValidate() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => array('group1', 'group2')); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); - $context->expects($this->at(0)) - ->method('validate') - ->with($object, 'data', 'group1', true); - $context->expects($this->at(1)) - ->method('validate') - ->with($object, 'data', 'group2', true); + $this->expectValidateAt(0, 'data', $object, 'group1'); + $this->expectValidateAt(1, 'data', $object, 'group2'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testValidateConstraints() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $constraint1 = new NotNull(array('groups' => array('group1', 'group2'))); $constraint2 = new NotBlank(array('groups' => 'group2')); @@ -98,28 +91,20 @@ public function testValidateConstraints() ->getForm(); // First default constraints - $context->expects($this->at(0)) - ->method('validate') - ->with($object, 'data', 'group1', true); - $context->expects($this->at(1)) - ->method('validate') - ->with($object, 'data', 'group2', true); + $this->expectValidateAt(0, 'data', $object, 'group1'); + $this->expectValidateAt(1, 'data', $object, 'group2'); // Then custom constraints - $context->expects($this->at(2)) - ->method('validateValue') - ->with($object, $constraint1, 'data', 'group1'); - $context->expects($this->at(3)) - ->method('validateValue') - ->with($object, $constraint2, 'data', 'group2'); - - $this->validator->initialize($context); + $this->expectValidateValueAt(2, 'data', $object, $constraint1, 'group1'); + $this->expectValidateValueAt(3, 'data', $object, $constraint2, 'group2'); + $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testDontValidateIfParentWithoutCascadeValidation() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parent = $this->getBuilder('parent', null, array('cascade_validation' => false)) @@ -132,16 +117,15 @@ public function testDontValidateIfParentWithoutCascadeValidation() $form->setData($object); - $context->expects($this->never()) - ->method('validate'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testValidateConstraintsEvenIfNoCascadeValidation() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $constraint1 = new NotNull(array('groups' => array('group1', 'group2'))); $constraint2 = new NotBlank(array('groups' => 'group2')); @@ -159,20 +143,16 @@ public function testValidateConstraintsEvenIfNoCascadeValidation() ->getForm(); $parent->add($form); - $context->expects($this->at(0)) - ->method('validateValue') - ->with($object, $constraint1, 'data', 'group1'); - $context->expects($this->at(1)) - ->method('validateValue') - ->with($object, $constraint2, 'data', 'group2'); + $this->expectValidateValueAt(0, 'data', $object, $constraint1, 'group1'); + $this->expectValidateValueAt(1, 'data', $object, $constraint2, 'group2'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testDontValidateIfNoValidationGroups() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $form = $this->getBuilder('name', '\stdClass', array( @@ -183,16 +163,15 @@ public function testDontValidateIfNoValidationGroups() $form->setData($object); - $context->expects($this->never()) - ->method('validate'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testDontValidateConstraintsIfNoValidationGroups() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $constraint1 = $this->getMock('Symfony\Component\Validator\Constraint'); $constraint2 = $this->getMock('Symfony\Component\Validator\Constraint'); @@ -208,16 +187,15 @@ public function testDontValidateConstraintsIfNoValidationGroups() // Launch transformer $form->submit(array()); - $context->expects($this->never()) - ->method('validate'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testDontValidateIfNotSynchronized() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $form = $this->getBuilder('name', '\stdClass', array( @@ -237,26 +215,18 @@ function () { throw new TransformationFailedException(); } // Launch transformer $form->submit('foo'); - $context->expects($this->never()) - ->method('validate'); - - $context->expects($this->once()) - ->method('addViolation') - ->with( - 'invalid_message_key', - array('{{ value }}' => 'foo', '{{ foo }}' => 'bar'), - 'foo' - ); - $context->expects($this->never()) - ->method('addViolationAt'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertViolation('invalid_message_key', array( + '{{ value }}' => 'foo', + '{{ foo }}' => 'bar' + ), 'property.path', 'foo', null, Form::ERR_INVALID); } public function testAddInvalidErrorEvenIfNoValidationGroups() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $form = $this->getBuilder('name', '\stdClass', array( @@ -277,31 +247,24 @@ function () { throw new TransformationFailedException(); } // Launch transformer $form->submit('foo'); - $context->expects($this->never()) - ->method('validate'); - - $context->expects($this->once()) - ->method('addViolation') - ->with( - 'invalid_message_key', - array('{{ value }}' => 'foo', '{{ foo }}' => 'bar'), - 'foo' - ); - $context->expects($this->never()) - ->method('addViolationAt'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertViolation('invalid_message_key', array( + '{{ value }}' => 'foo', + '{{ foo }}' => 'bar' + ), 'property.path', 'foo', null, Form::ERR_INVALID); } public function testDontValidateConstraintsIfNotSynchronized() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $constraint1 = $this->getMock('Symfony\Component\Validator\Constraint'); $constraint2 = $this->getMock('Symfony\Component\Validator\Constraint'); $options = array( + 'invalid_message' => 'invalid_message_key', 'validation_groups' => array('group1', 'group2'), 'constraints' => array($constraint1, $constraint2), ); @@ -314,19 +277,20 @@ function () { throw new TransformationFailedException(); } ->getForm(); // Launch transformer - $form->submit(array()); + $form->submit('foo'); - $context->expects($this->never()) - ->method('validate'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertViolation('invalid_message_key', array( + '{{ value }}' => 'foo', + ), 'property.path','foo', null, Form::ERR_INVALID); } // https://github.com/symfony/symfony/issues/4359 public function testDontMarkInvalidIfAnyChildIsNotSynchronized() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $failingTransformer = new CallbackTransformer( @@ -348,55 +312,46 @@ function () { throw new TransformationFailedException(); } // Launch transformer $form->submit(array('child' => 'foo')); - $context->expects($this->never()) - ->method('addViolation'); - $context->expects($this->never()) - ->method('addViolationAt'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testHandleCallbackValidationGroups() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => array($this, 'getValidationGroups')); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); - $context->expects($this->at(0)) - ->method('validate') - ->with($object, 'data', 'group1', true); - $context->expects($this->at(1)) - ->method('validate') - ->with($object, 'data', 'group2', true); + $this->expectValidateAt(0, 'data', $object, 'group1'); + $this->expectValidateAt(1, 'data', $object, 'group2'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testDontExecuteFunctionNames() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => 'header'); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); - $context->expects($this->once()) - ->method('validate') - ->with($object, 'data', 'header', true); + $this->expectValidateAt(0, 'data', $object, 'header'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testHandleClosureValidationGroups() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $options = array('validation_groups' => function (FormInterface $form) { return array('group1', 'group2'); @@ -405,20 +360,16 @@ public function testHandleClosureValidationGroups() ->setData($object) ->getForm(); - $context->expects($this->at(0)) - ->method('validate') - ->with($object, 'data', 'group1', true); - $context->expects($this->at(1)) - ->method('validate') - ->with($object, 'data', 'group2', true); + $this->expectValidateAt(0, 'data', $object, 'group1'); + $this->expectValidateAt(1, 'data', $object, 'group2'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testUseValidationGroupOfClickedButton() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parent = $this->getBuilder('parent', null, array('cascade_validation' => true)) @@ -436,17 +387,15 @@ public function testUseValidationGroupOfClickedButton() $parent->submit(array('name' => $object, 'submit' => '')); - $context->expects($this->once()) - ->method('validate') - ->with($object, 'data', 'button_group', true); + $this->expectValidateAt(0, 'data', $object, 'button_group'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testDontUseValidationGroupOfUnclickedButton() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parent = $this->getBuilder('parent', null, array('cascade_validation' => true)) @@ -464,17 +413,15 @@ public function testDontUseValidationGroupOfUnclickedButton() $form->setData($object); - $context->expects($this->once()) - ->method('validate') - ->with($object, 'data', 'form_group', true); + $this->expectValidateAt(0, 'data', $object, 'form_group'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testUseInheritedValidationGroup() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parentOptions = array( @@ -490,17 +437,15 @@ public function testUseInheritedValidationGroup() $form->setData($object); - $context->expects($this->once()) - ->method('validate') - ->with($object, 'data', 'group', true); + $this->expectValidateAt(0, 'data', $object, 'group'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testUseInheritedCallbackValidationGroup() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parentOptions = array( @@ -516,20 +461,16 @@ public function testUseInheritedCallbackValidationGroup() $form->setData($object); - $context->expects($this->at(0)) - ->method('validate') - ->with($object, 'data', 'group1', true); - $context->expects($this->at(1)) - ->method('validate') - ->with($object, 'data', 'group2', true); + $this->expectValidateAt(0, 'data', $object, 'group1'); + $this->expectValidateAt(1, 'data', $object, 'group2'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testUseInheritedClosureValidationGroup() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $parentOptions = array( @@ -547,52 +488,43 @@ public function testUseInheritedClosureValidationGroup() $form->setData($object); - $context->expects($this->at(0)) - ->method('validate') - ->with($object, 'data', 'group1', true); - $context->expects($this->at(1)) - ->method('validate') - ->with($object, 'data', 'group2', true); + $this->expectValidateAt(0, 'data', $object, 'group1'); + $this->expectValidateAt(1, 'data', $object, 'group2'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testAppendPropertyPath() { - $context = $this->getMockExecutionContext(); $object = $this->getMock('\stdClass'); $form = $this->getBuilder('name', '\stdClass') ->setData($object) ->getForm(); - $context->expects($this->once()) - ->method('validate') - ->with($object, 'data', 'Default', true); + $this->expectValidateAt(0, 'data', $object, 'Default'); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testDontWalkScalars() { - $context = $this->getMockExecutionContext(); - $form = $this->getBuilder() ->setData('scalar') ->getForm(); - $context->expects($this->never()) - ->method('validate'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } public function testViolationIfExtraData() { - $context = $this->getMockExecutionContext(); - $form = $this->getBuilder('parent', null, array('extra_fields_message' => 'Extra!')) ->setCompound(true) ->setDataMapper($this->getDataMapper()) @@ -601,18 +533,13 @@ public function testViolationIfExtraData() $form->submit(array('foo' => 'bar')); - $context->expects($this->once()) - ->method('addViolation') - ->with( - 'Extra!', - array('{{ extra_fields }}' => 'foo'), - array('foo' => 'bar') - ); - $context->expects($this->never()) - ->method('addViolationAt'); - - $this->validator->initialize($context); + $this->expectNoValidate(); + $this->validator->validate($form, new Form()); + + $this->assertViolation('Extra!', array( + '{{ extra_fields }}' => 'foo' + ), 'property.path', array('foo' => 'bar')); } /** @@ -627,26 +554,18 @@ public function testPostMaxSizeViolation($contentLength, $iniMax, $nbViolation, ->method('getNormalizedIniPostMaxSize') ->will($this->returnValue($iniMax)); - $context = $this->getMockExecutionContext(); $options = array('post_max_size_message' => 'Max {{ max }}!'); $form = $this->getBuilder('name', null, $options)->getForm(); + $this->validator->validate($form, new Form()); + + $violations = array(); + for ($i = 0; $i < $nbViolation; ++$i) { - if (0 === $i && count($params) > 0) { - $context->expects($this->at($i)) - ->method('addViolation') - ->with($options['post_max_size_message'], $params); - } else { - $context->expects($this->at($i)) - ->method('addViolation'); - } + $violations[] = $this->createViolation($options['post_max_size_message'], $params, 'property.path', $contentLength); } - $context->expects($this->never()) - ->method('addViolationAt'); - - $this->validator->initialize($context); - $this->validator->validate($form, new Form()); + $this->assertViolations($violations); } public function getPostMaxSizeFixtures() @@ -672,7 +591,6 @@ public function testNoViolationIfNotRoot() $this->serverParams->expects($this->never()) ->method('getNormalizedIniPostMaxSize'); - $context = $this->getMockExecutionContext(); $parent = $this->getBuilder() ->setCompound(true) ->setDataMapper($this->getDataMapper()) @@ -680,13 +598,11 @@ public function testNoViolationIfNotRoot() $form = $this->getForm(); $parent->add($form); - $context->expects($this->never()) - ->method('addViolation'); - $context->expects($this->never()) - ->method('addViolationAt'); + $this->expectNoValidate(); - $this->validator->initialize($context); $this->validator->validate($form, new Form()); + + $this->assertNoViolation(); } /** From fc260bef021f99cd67e863d8e93dabe43d2de2f7 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 8 Aug 2014 08:20:54 +0200 Subject: [PATCH 325/447] [Form] Fixed ValidatorExtension to work with the 2.5 Validation API --- Extension/Validator/ValidatorExtension.php | 30 +++--- .../Validator/ValidatorExtensionTest.php | 93 +++++++++---------- 2 files changed, 60 insertions(+), 63 deletions(-) diff --git a/Extension/Validator/ValidatorExtension.php b/Extension/Validator/ValidatorExtension.php index 88890ae651..5717ffb154 100644 --- a/Extension/Validator/ValidatorExtension.php +++ b/Extension/Validator/ValidatorExtension.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Form\Extension\Validator; +use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Extension\Validator\Constraints\Form; use Symfony\Component\Form\AbstractExtension; use Symfony\Component\Validator\Constraints\Valid; @@ -29,23 +30,19 @@ class ValidatorExtension extends AbstractExtension /** * @param ValidatorInterface|LegacyValidatorInterface $validator + * + * @throws UnexpectedTypeException If $validator is invalid */ public function __construct($validator) { - // since validator apiVersion 2.5 + // 2.5 API if ($validator instanceof ValidatorInterface) { - $this->validator = $validator; - - /** @var $metadata ClassMetadata */ - $metadata = $this->validator->getMetadataFor('Symfony\Component\Form\Form'); - // until validator apiVersion 2.4 + $metadata = $validator->getMetadataFor('Symfony\Component\Form\Form'); + // 2.4 API } elseif ($validator instanceof LegacyValidatorInterface) { - $this->validator = $validator; - - /** @var $metadata ClassMetadata */ - $metadata = $this->validator->getMetadataFactory()->getMetadataFor('Symfony\Component\Form\Form'); + $metadata = $validator->getMetadataFactory()->getMetadataFor('Symfony\Component\Form\Form'); } else { - throw new \InvalidArgumentException('Validator must be instance of Symfony\Component\Validator\Validator\ValidatorInterface or Symfony\Component\Validator\ValidatorInterface'); + throw new UnexpectedTypeException($validator, 'Symfony\Component\Validator\Validator\ValidatorInterface or Symfony\Component\Validator\ValidatorInterface'); } // Register the form constraints in the validator programmatically. @@ -53,13 +50,22 @@ public function __construct($validator) // the DIC, where the XML file is loaded automatically. Thus the following // code must be kept synchronized with validation.xml + /** @var $metadata ClassMetadata */ $metadata->addConstraint(new Form()); $metadata->addPropertyConstraint('children', new Valid()); + + $this->validator = $validator; } public function loadTypeGuesser() { - return new ValidatorTypeGuesser($this->validator->getMetadataFactory()); + // 2.4 API + if ($this->validator instanceof LegacyValidatorInterface) { + return new ValidatorTypeGuesser($this->validator->getMetadataFactory()); + } + + // 2.5 API - ValidatorInterface extends MetadataFactoryInterface + return new ValidatorTypeGuesser($this->validator); } protected function loadTypeExtensions() diff --git a/Tests/Extension/Validator/ValidatorExtensionTest.php b/Tests/Extension/Validator/ValidatorExtensionTest.php index bc69231fe2..eca0873818 100644 --- a/Tests/Extension/Validator/ValidatorExtensionTest.php +++ b/Tests/Extension/Validator/ValidatorExtensionTest.php @@ -15,79 +15,70 @@ class ValidatorExtensionTest extends \PHPUnit_Framework_TestCase { - public function testValidatorInterfaceSinceSymfony25() + public function test2Dot5ValidationApi() { - $classMetaData = $this->createClassMetaDataMock(); - - // Mock of ValidatorInterface since apiVersion 2.5 $validator = $this->getMock('Symfony\Component\Validator\Validator\ValidatorInterface'); + $metadata = $this->getMockBuilder('Symfony\Component\Validator\Mapping\ClassMetadata') + ->disableOriginalConstructor() + ->getMock(); - $validator - ->expects($this->once()) + $validator->expects($this->once()) ->method('getMetadataFor') ->with($this->identicalTo('Symfony\Component\Form\Form')) - ->will($this->returnValue($classMetaData)) - ; + ->will($this->returnValue($metadata)); + + // Verify that the constraints are added + $metadata->expects($this->once()) + ->method('addConstraint') + ->with($this->isInstanceOf('Symfony\Component\Form\Extension\Validator\Constraints\Form')); + + $metadata->expects($this->once()) + ->method('addPropertyConstraint') + ->with('children', $this->isInstanceOf('Symfony\Component\Validator\Constraints\Valid')); - $validatorExtension = new ValidatorExtension($validator); - $this->assertAttributeSame($validator, 'validator', $validatorExtension); + $extension = new ValidatorExtension($validator); + $guesser = $extension->loadTypeGuesser(); + + $this->assertInstanceOf('Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser', $guesser); } - public function testValidatorInterfaceUntilSymfony24() + public function test2Dot4ValidationApi() { - $classMetaData = $this->createClassMetaDataMock(); + $factory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface'); + $validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface'); + $metadata = $this->getMockBuilder('Symfony\Component\Validator\Mapping\ClassMetadata') + ->disableOriginalConstructor() + ->getMock(); - $metaDataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface'); + $validator->expects($this->any()) + ->method('getMetadataFactory') + ->will($this->returnValue($factory)); - $metaDataFactory - ->expects($this->once()) + $factory->expects($this->once()) ->method('getMetadataFor') ->with($this->identicalTo('Symfony\Component\Form\Form')) - ->will($this->returnValue($classMetaData)) - ; + ->will($this->returnValue($metadata)); - // Mock of ValidatorInterface until apiVersion 2.4 - $validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface'); + // Verify that the constraints are added + $metadata->expects($this->once()) + ->method('addConstraint') + ->with($this->isInstanceOf('Symfony\Component\Form\Extension\Validator\Constraints\Form')); - $validator - ->expects($this->once()) - ->method('getMetadataFactory') - ->will($this->returnValue($metaDataFactory)) - ; + $metadata->expects($this->once()) + ->method('addPropertyConstraint') + ->with('children', $this->isInstanceOf('Symfony\Component\Validator\Constraints\Valid')); - $validatorExtension = new ValidatorExtension($validator); - $this->assertAttributeSame($validator, 'validator', $validatorExtension); + $extension = new ValidatorExtension($validator); + $guesser = $extension->loadTypeGuesser(); + + $this->assertInstanceOf('Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser', $guesser); } /** - * @expectedException \InvalidArgumentException + * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException */ public function testInvalidValidatorInterface() { new ValidatorExtension(null); } - - /** - * @return mixed - */ - private function createClassMetaDataMock() - { - $classMetaData = $this->getMockBuilder('Symfony\Component\Validator\Mapping\ClassMetadata') - ->disableOriginalConstructor() - ->getMock(); - - $classMetaData - ->expects($this->once()) - ->method('addConstraint') - ->with($this->isInstanceOf('Symfony\Component\Form\Extension\Validator\Constraints\Form')); - $classMetaData - ->expects($this->once()) - ->method('addPropertyConstraint') - ->with( - $this->identicalTo('children'), - $this->isInstanceOf('Symfony\Component\Validator\Constraints\Valid') - ); - - return $classMetaData; - } } From d79424b4653f54389337415d3404329f5a13e1be Mon Sep 17 00:00:00 2001 From: "Nek (Maxime Veber)" Date: Fri, 15 Aug 2014 14:15:04 +0200 Subject: [PATCH 326/447] Fixed #11675 ValueToDuplicatesTransformer accept "0" value Fixed wrong return null syntax Added transformation to null on empty arrays Removed useless statement in condition and switched to yoda condition --- .../ValueToDuplicatesTransformer.php | 2 +- .../ValueToDuplicatesTransformerTest.php | 23 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php b/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php index 618fc6b4a4..ffc9915fa4 100644 --- a/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php +++ b/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php @@ -64,7 +64,7 @@ public function reverseTransform($array) $emptyKeys = array(); foreach ($this->keys as $key) { - if (!empty($array[$key])) { + if (isset($array[$key]) && '' !== $array[$key] && false !== $array[$key] && array() !== $array[$key]) { if ($array[$key] !== $result) { throw new TransformationFailedException( 'All values in the array should be the same' diff --git a/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php b/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php index 2c5298da50..a8a088a95a 100644 --- a/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php @@ -82,6 +82,29 @@ public function testReverseTransformCompletelyNull() $this->assertNull($this->transformer->reverseTransform($input)); } + public function testReverseTransformEmptyArray() + { + $input = array( + 'a' => array(), + 'b' => array(), + 'c' => array(), + ); + + $this->assertNull($this->transformer->reverseTransform($input)); + } + + + public function testReverseTransformZeroString() + { + $input = array( + 'a' => '0', + 'b' => '0', + 'c' => '0' + ); + + $this->assertSame('0', $this->transformer->reverseTransform($input)); + } + /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ From d630648fd471c1fb03b97db56a7b82352c8fd38b Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Tue, 19 Aug 2014 16:41:47 +0200 Subject: [PATCH 327/447] [Validator] deprecate member metadata accessors in favor of existing property metadata accessors add changelog for deprecations fix test --- Extension/Validator/ValidatorTypeGuesser.php | 12 +++++++++--- composer.json | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Extension/Validator/ValidatorTypeGuesser.php b/Extension/Validator/ValidatorTypeGuesser.php index 63d06dca71..e8444ced9b 100644 --- a/Extension/Validator/ValidatorTypeGuesser.php +++ b/Extension/Validator/ValidatorTypeGuesser.php @@ -15,8 +15,10 @@ use Symfony\Component\Form\Guess\Guess; use Symfony\Component\Form\Guess\TypeGuess; use Symfony\Component\Form\Guess\ValueGuess; -use Symfony\Component\Validator\MetadataFactoryInterface; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Mapping\ClassMetadataInterface; +use Symfony\Component\Validator\Mapping\GenericMetadata; +use Symfony\Component\Validator\MetadataFactoryInterface; class ValidatorTypeGuesser implements FormTypeGuesserInterface { @@ -264,10 +266,14 @@ protected function guess($class, $property, \Closure $closure, $defaultValue = n $guesses = array(); $classMetadata = $this->metadataFactory->getMetadataFor($class); - if ($classMetadata->hasMemberMetadatas($property)) { - $memberMetadatas = $classMetadata->getMemberMetadatas($property); + if ($classMetadata instanceof ClassMetadataInterface && $classMetadata->hasPropertyMetadata($property)) { + $memberMetadatas = $classMetadata->getPropertyMetadata($property); foreach ($memberMetadatas as $memberMetadata) { + if (!$memberMetadata instanceof GenericMetadata) { + continue; + } + $constraints = $memberMetadata->getConstraints(); foreach ($constraints as $constraint) { diff --git a/composer.json b/composer.json index 14412e1f61..95aed3da95 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,7 @@ "symfony/property-access": "~2.3" }, "require-dev": { - "symfony/validator": "~2.2", + "symfony/validator": "~2.3", "symfony/http-foundation": "~2.2", "symfony/http-kernel": "~2.4", "symfony/security-csrf": "~2.4", From da14fe37f17c80f7108e2271d6326ae5f26e6c39 Mon Sep 17 00:00:00 2001 From: "Issei.M" Date: Wed, 20 Aug 2014 19:06:28 +0900 Subject: [PATCH 328/447] [Form] FormBuilder::getIterator() now deals with resolved children --- FormBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FormBuilder.php b/FormBuilder.php index 434afa861a..e73c03fd7a 100644 --- a/FormBuilder.php +++ b/FormBuilder.php @@ -242,7 +242,7 @@ public function getIterator() throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } - return new \ArrayIterator($this->children); + return new \ArrayIterator($this->all()); } /** From 9476b99d0373d4b189bd7eaf952437502b047634 Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Wed, 20 Aug 2014 16:09:22 +0200 Subject: [PATCH 329/447] [Validator] add getConstraints to MetadataInterface --- Extension/Validator/ValidatorTypeGuesser.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Extension/Validator/ValidatorTypeGuesser.php b/Extension/Validator/ValidatorTypeGuesser.php index e8444ced9b..5a97b3fd14 100644 --- a/Extension/Validator/ValidatorTypeGuesser.php +++ b/Extension/Validator/ValidatorTypeGuesser.php @@ -17,7 +17,6 @@ use Symfony\Component\Form\Guess\ValueGuess; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Mapping\ClassMetadataInterface; -use Symfony\Component\Validator\Mapping\GenericMetadata; use Symfony\Component\Validator\MetadataFactoryInterface; class ValidatorTypeGuesser implements FormTypeGuesserInterface @@ -270,10 +269,6 @@ protected function guess($class, $property, \Closure $closure, $defaultValue = n $memberMetadatas = $classMetadata->getPropertyMetadata($property); foreach ($memberMetadatas as $memberMetadata) { - if (!$memberMetadata instanceof GenericMetadata) { - continue; - } - $constraints = $memberMetadata->getConstraints(); foreach ($constraints as $constraint) { From 88c9edee076f789ec200520b2b78fb00eed94e04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Steffen=20Ro=C3=9Fkamp?= Date: Tue, 16 Sep 2014 11:11:47 +0200 Subject: [PATCH 330/447] [Form] Fix PHPDoc for builder setData methods The underlying data variable is typed as mixed whereas the methods paramers where typed as array. --- ButtonBuilder.php | 2 +- FormConfigBuilderInterface.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ButtonBuilder.php b/ButtonBuilder.php index b02f8f5fe1..bbddd9cfa2 100644 --- a/ButtonBuilder.php +++ b/ButtonBuilder.php @@ -425,7 +425,7 @@ public function setType(ResolvedFormTypeInterface $type) * * This method should not be invoked. * - * @param array $data + * @param mixed $data * * @throws BadMethodCallException */ diff --git a/FormConfigBuilderInterface.php b/FormConfigBuilderInterface.php index da2da0b668..50793a2c49 100644 --- a/FormConfigBuilderInterface.php +++ b/FormConfigBuilderInterface.php @@ -212,7 +212,7 @@ public function setType(ResolvedFormTypeInterface $type); /** * Sets the initial data of the form. * - * @param array $data The data of the form in application format. + * @param mixed $data The data of the form in application format. * * @return self The configuration object. */ From ed8fb227bc1f1c8afdea2040bbd6a510afb68cf0 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 21 Sep 2014 20:53:12 +0200 Subject: [PATCH 331/447] fixed CS --- .../Core/DataMapper/PropertyPathMapper.php | 1 - .../BooleanToStringTransformer.php | 1 - .../DateTimeToStringTransformer.php | 20 +++++++------- .../MoneyToLocalizedStringTransformer.php | 1 - Extension/Core/Type/ChoiceType.php | 2 +- Extension/Core/Type/DateType.php | 2 +- Extension/Core/Type/TimeType.php | 2 +- Extension/Templating/TemplatingExtension.php | 2 +- Extension/Validator/Util/ServerParams.php | 1 - Extension/Validator/ValidatorTypeGuesser.php | 2 +- Form.php | 16 ++++++------ FormConfigBuilder.php | 2 +- NativeRequestHandler.php | 2 +- Tests/AbstractDivLayoutTest.php | 6 ++--- Tests/AbstractLayoutTest.php | 26 +++++++++---------- Tests/AbstractTableLayoutTest.php | 6 ++--- Tests/CallbackTransformerTest.php | 8 +++--- Tests/CompoundFormTest.php | 2 +- .../Core/ChoiceList/ChoiceListTest.php | 10 +++---- .../Core/ChoiceList/ObjectChoiceListTest.php | 6 ++--- .../Core/ChoiceList/SimpleChoiceListTest.php | 4 +-- .../DateTimeToRfc3339TransformerTest.php | 2 +- ...NumberToLocalizedStringTransformerTest.php | 1 - .../ValueToDuplicatesTransformerTest.php | 3 +-- Tests/Extension/Core/Type/ChoiceTypeTest.php | 4 +-- .../Extension/Core/Type/CurrencyTypeTest.php | 1 - .../Extension/Core/Type/DateTimeTypeTest.php | 5 ++-- Tests/Extension/Core/Type/DateTypeTest.php | 6 ++--- Tests/Extension/Core/Type/FormTypeTest.php | 10 +++---- .../Extension/Core/Type/RepeatedTypeTest.php | 4 +-- Tests/Extension/Core/Type/TimeTypeTest.php | 8 +++--- .../EventListener/BindRequestListenerTest.php | 2 +- .../Constraints/FormValidatorTest.php | 8 +++--- .../Validator/ValidatorTypeGuesserTest.php | 2 +- Tests/Guess/GuessTest.php | 4 ++- Tests/NativeRequestHandlerTest.php | 2 +- Tests/SimpleFormTest.php | 2 +- Util/FormUtil.php | 4 ++- Util/OrderedHashMap.php | 2 +- 39 files changed, 94 insertions(+), 98 deletions(-) diff --git a/Extension/Core/DataMapper/PropertyPathMapper.php b/Extension/Core/DataMapper/PropertyPathMapper.php index d07f3f15e6..2208f26d1e 100644 --- a/Extension/Core/DataMapper/PropertyPathMapper.php +++ b/Extension/Core/DataMapper/PropertyPathMapper.php @@ -81,7 +81,6 @@ public function mapFormsToData($forms, &$data) // Write-back is disabled if the form is not synchronized (transformation failed), // if the form was not submitted and if the form is disabled (modification not allowed) if (null !== $propertyPath && $config->getMapped() && $form->isSubmitted() && $form->isSynchronized() && !$form->isDisabled()) { - // If the field is of type DateTime and the data is the same skip the update to // keep the original object hash if ($form->getData() instanceof \DateTime && $form->getData() == $this->propertyAccessor->getValue($data, $propertyPath)) { diff --git a/Extension/Core/DataTransformer/BooleanToStringTransformer.php b/Extension/Core/DataTransformer/BooleanToStringTransformer.php index d839427877..38c9bb273b 100644 --- a/Extension/Core/DataTransformer/BooleanToStringTransformer.php +++ b/Extension/Core/DataTransformer/BooleanToStringTransformer.php @@ -81,5 +81,4 @@ public function reverseTransform($value) return true; } - } diff --git a/Extension/Core/DataTransformer/DateTimeToStringTransformer.php b/Extension/Core/DataTransformer/DateTimeToStringTransformer.php index a9ea5e761f..11ffd3791d 100644 --- a/Extension/Core/DataTransformer/DateTimeToStringTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToStringTransformer.php @@ -161,16 +161,16 @@ public function reverseTransform($value) // Check which of the date parts are present in the pattern preg_match( - '/(' . - '(?P[djDl])|' . - '(?P[FMmn])|' . - '(?P[Yy])|' . - '(?P[ghGH])|' . - '(?Pi)|' . - '(?Ps)|' . - '(?Pz)|' . - '(?PU)|' . - '[^djDlFMmnYyghGHiszU]' . + '/('. + '(?P[djDl])|'. + '(?P[FMmn])|'. + '(?P[Yy])|'. + '(?P[ghGH])|'. + '(?Pi)|'. + '(?Ps)|'. + '(?Pz)|'. + '(?PU)|'. + '[^djDlFMmnYyghGHiszU]'. ')*/', $this->parseFormat, $matches diff --git a/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php index d746961d2d..d70c08a8aa 100644 --- a/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php @@ -85,5 +85,4 @@ public function reverseTransform($value) return $value; } - } diff --git a/Extension/Core/Type/ChoiceType.php b/Extension/Core/Type/ChoiceType.php index 712f5b6de8..08504dea2b 100644 --- a/Extension/Core/Type/ChoiceType.php +++ b/Extension/Core/Type/ChoiceType.php @@ -159,7 +159,7 @@ public function finishView(FormView $view, FormInterface $form, array $options) */ public function setDefaultOptions(OptionsResolverInterface $resolver) { - $choiceListCache =& $this->choiceListCache; + $choiceListCache = & $this->choiceListCache; $choiceList = function (Options $options) use (&$choiceListCache) { // Harden against NULL values (like in EntityType and ModelType) diff --git a/Extension/Core/Type/DateType.php b/Extension/Core/Type/DateType.php index 1748d2e31f..6d90e55714 100644 --- a/Extension/Core/Type/DateType.php +++ b/Extension/Core/Type/DateType.php @@ -187,7 +187,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) return array( 'year' => $emptyValue, 'month' => $emptyValue, - 'day' => $emptyValue + 'day' => $emptyValue, ); }; diff --git a/Extension/Core/Type/TimeType.php b/Extension/Core/Type/TimeType.php index 6bf41517ac..3585b5bd31 100644 --- a/Extension/Core/Type/TimeType.php +++ b/Extension/Core/Type/TimeType.php @@ -177,7 +177,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) return array( 'hour' => $emptyValue, 'minute' => $emptyValue, - 'second' => $emptyValue + 'second' => $emptyValue, ); }; diff --git a/Extension/Templating/TemplatingExtension.php b/Extension/Templating/TemplatingExtension.php index 573cb518d4..1e56f0c6b6 100644 --- a/Extension/Templating/TemplatingExtension.php +++ b/Extension/Templating/TemplatingExtension.php @@ -27,7 +27,7 @@ class TemplatingExtension extends AbstractExtension public function __construct(PhpEngine $engine, CsrfProviderInterface $csrfProvider = null, array $defaultThemes = array()) { $engine->addHelpers(array( - new FormHelper(new FormRenderer(new TemplatingRendererEngine($engine, $defaultThemes), $csrfProvider)) + new FormHelper(new FormRenderer(new TemplatingRendererEngine($engine, $defaultThemes), $csrfProvider)), )); } } diff --git a/Extension/Validator/Util/ServerParams.php b/Extension/Validator/Util/ServerParams.php index 93a1dd7d6f..58fdc25e22 100644 --- a/Extension/Validator/Util/ServerParams.php +++ b/Extension/Validator/Util/ServerParams.php @@ -69,5 +69,4 @@ public function getContentLength() ? (int) $_SERVER['CONTENT_LENGTH'] : null; } - } diff --git a/Extension/Validator/ValidatorTypeGuesser.php b/Extension/Validator/ValidatorTypeGuesser.php index 63d06dca71..589fc12a36 100644 --- a/Extension/Validator/ValidatorTypeGuesser.php +++ b/Extension/Validator/ValidatorTypeGuesser.php @@ -196,7 +196,7 @@ public function guessMaxLengthForConstraint(Constraint $constraint) case 'Symfony\Component\Validator\Constraints\Type': if (in_array($constraint->type, array('double', 'float', 'numeric', 'real'))) { - return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); + return new ValueGuess(null, Guess::MEDIUM_CONFIDENCE); } break; diff --git a/Form.php b/Form.php index a94a679f9d..3f3fe88241 100644 --- a/Form.php +++ b/Form.php @@ -351,20 +351,20 @@ public function setData($modelData) $expectedType = 'scalar, array or an instance of \ArrayAccess'; throw new LogicException( - 'The form\'s view data is expected to be of type '.$expectedType.', ' . - 'but is '.$actualType.'. You ' . - 'can avoid this error by setting the "data_class" option to ' . - '"'.get_class($viewData).'" or by adding a view transformer ' . + 'The form\'s view data is expected to be of type '.$expectedType.', '. + 'but is '.$actualType.'. You '. + 'can avoid this error by setting the "data_class" option to '. + '"'.get_class($viewData).'" or by adding a view transformer '. 'that transforms '.$actualType.' to '.$expectedType.'.' ); } if (null !== $dataClass && !$viewData instanceof $dataClass) { throw new LogicException( - 'The form\'s view data is expected to be an instance of class ' . - $dataClass.', but is '. $actualType.'. You can avoid this error ' . - 'by setting the "data_class" option to null or by adding a view ' . - 'transformer that transforms '.$actualType.' to an instance of ' . + 'The form\'s view data is expected to be an instance of class '. + $dataClass.', but is '.$actualType.'. You can avoid this error '. + 'by setting the "data_class" option to null or by adding a view '. + 'transformer that transforms '.$actualType.' to an instance of '. $dataClass.'.' ); } diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index 733b79dfdd..1d70a49644 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -44,7 +44,7 @@ class FormConfigBuilder implements FormConfigBuilderInterface 'PUT', 'POST', 'DELETE', - 'PATCH' + 'PATCH', ); /** diff --git a/NativeRequestHandler.php b/NativeRequestHandler.php index c76534473c..fefe546af8 100644 --- a/NativeRequestHandler.php +++ b/NativeRequestHandler.php @@ -155,7 +155,7 @@ private static function fixPhpFilesArray($data) 'name' => $data['name'][$key], 'type' => $data['type'][$key], 'tmp_name' => $data['tmp_name'][$key], - 'size' => $data['size'][$key] + 'size' => $data['size'][$key], )); } diff --git a/Tests/AbstractDivLayoutTest.php b/Tests/AbstractDivLayoutTest.php index ee9ed8f2a6..21ea55833a 100644 --- a/Tests/AbstractDivLayoutTest.php +++ b/Tests/AbstractDivLayoutTest.php @@ -525,7 +525,7 @@ public function testRepeatedWithCustomOptions() $form = $this->factory->createNamed('name', 'repeated', null, array( // the global required value cannot be overridden 'first_options' => array('label' => 'Test', 'required' => false), - 'second_options' => array('label' => 'Test2') + 'second_options' => array('label' => 'Test2'), )); $this->assertWidgetMatchesXpath($form->createView(), array(), @@ -587,7 +587,7 @@ public function testLabelHasNoId() public function testLabelIsNotRenderedWhenSetToFalse() { $form = $this->factory->createNamed('name', 'text', null, array( - 'label' => false + 'label' => false, )); $html = $this->renderRow($form->createView()); @@ -698,7 +698,7 @@ public function testFormEndWithRest() $html = $this->renderEnd($view); // Insert the start tag, the end tag should be rendered by the helper - $this->assertMatchesXpath('
' . $html, + $this->assertMatchesXpath(''.$html, '/form [ ./div diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index 9e3647a2b2..5439bd096f 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -215,7 +215,7 @@ public function testLabelDoesNotRenderFieldAttributes() $form = $this->factory->createNamed('name', 'text'); $html = $this->renderLabel($form->createView(), null, array( 'attr' => array( - 'class' => 'my&class' + 'class' => 'my&class', ), )); @@ -232,7 +232,7 @@ public function testLabelWithCustomAttributesPassedDirectly() $form = $this->factory->createNamed('name', 'text'); $html = $this->renderLabel($form->createView(), null, array( 'label_attr' => array( - 'class' => 'my&class' + 'class' => 'my&class', ), )); @@ -249,7 +249,7 @@ public function testLabelWithCustomTextAndCustomAttributesPassedDirectly() $form = $this->factory->createNamed('name', 'text'); $html = $this->renderLabel($form->createView(), 'Custom label', array( 'label_attr' => array( - 'class' => 'my&class' + 'class' => 'my&class', ), )); @@ -270,7 +270,7 @@ public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly )); $html = $this->renderLabel($form->createView(), null, array( 'label_attr' => array( - 'class' => 'my&class' + 'class' => 'my&class', ), )); @@ -555,7 +555,7 @@ public function testSingleChoiceRequiredWithEmptyValue() 'required' => true, 'multiple' => false, 'expanded' => false, - 'empty_value' => 'Test&Me' + 'empty_value' => 'Test&Me', )); // The "disabled" attribute was removed again due to a bug in the @@ -660,7 +660,7 @@ public function testMultipleChoiceSkipsEmptyValue() 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'multiple' => true, 'expanded' => false, - 'empty_value' => 'Test&Me' + 'empty_value' => 'Test&Me', )); $this->assertWidgetMatchesXpath($form->createView(), array(), @@ -726,7 +726,7 @@ public function testSingleChoiceExpandedWithEmptyValue() 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'multiple' => false, 'expanded' => true, - 'empty_value' => 'Test&Me' + 'empty_value' => 'Test&Me', )); $this->assertWidgetMatchesXpath($form->createView(), array(), @@ -1825,7 +1825,7 @@ public function testStartTag() { $form = $this->factory->create('form', null, array( 'method' => 'get', - 'action' => 'http://example.com/directory' + 'action' => 'http://example.com/directory', )); $html = $this->renderStart($form->createView()); @@ -1837,12 +1837,12 @@ public function testStartTagForPutRequest() { $form = $this->factory->create('form', null, array( 'method' => 'put', - 'action' => 'http://example.com/directory' + 'action' => 'http://example.com/directory', )); $html = $this->renderStart($form->createView()); - $this->assertMatchesXpath($html . '', + $this->assertMatchesXpath($html.'', '/form [./input[@type="hidden"][@name="_method"][@value="PUT"]] [@method="post"] @@ -1859,7 +1859,7 @@ public function testStartTagWithOverriddenVars() $html = $this->renderStart($form->createView(), array( 'method' => 'post', - 'action' => 'http://foo.com/directory' + 'action' => 'http://foo.com/directory', )); $this->assertSame('
', $html); @@ -1869,7 +1869,7 @@ public function testStartTagForMultipartForm() { $form = $this->factory->createBuilder('form', null, array( 'method' => 'get', - 'action' => 'http://example.com/directory' + 'action' => 'http://example.com/directory', )) ->add('file', 'file') ->getForm(); @@ -1883,7 +1883,7 @@ public function testStartTagWithExtraAttributes() { $form = $this->factory->create('form', null, array( 'method' => 'get', - 'action' => 'http://example.com/directory' + 'action' => 'http://example.com/directory', )); $html = $this->renderStart($form->createView(), array( diff --git a/Tests/AbstractTableLayoutTest.php b/Tests/AbstractTableLayoutTest.php index 5c91195169..25fa504a53 100644 --- a/Tests/AbstractTableLayoutTest.php +++ b/Tests/AbstractTableLayoutTest.php @@ -42,7 +42,7 @@ public function testRow() public function testLabelIsNotRenderedWhenSetToFalse() { $form = $this->factory->createNamed('name', 'text', null, array( - 'label' => false + 'label' => false, )); $html = $this->renderRow($form->createView()); @@ -401,7 +401,7 @@ public function testRepeatedWithCustomOptions() $form = $this->factory->createNamed('name', 'repeated', 'foobar', array( 'type' => 'password', 'first_options' => array('label' => 'Test', 'required' => false), - 'second_options' => array('label' => 'Test2') + 'second_options' => array('label' => 'Test2'), )); $this->assertWidgetMatchesXpath($form->createView(), array(), @@ -471,7 +471,7 @@ public function testFormEndWithRest() // tag is missing. If someone renders a form with table layout // manually, she should call form_rest() explicitly within the
// tag. - $this->assertMatchesXpath('' . $html, + $this->assertMatchesXpath(''.$html, '/form [ ./tr diff --git a/Tests/CallbackTransformerTest.php b/Tests/CallbackTransformerTest.php index 706bc076ec..7f3b074e78 100644 --- a/Tests/CallbackTransformerTest.php +++ b/Tests/CallbackTransformerTest.php @@ -9,8 +9,8 @@ class CallbackTransformerTest extends \PHPUnit_Framework_TestCase public function testTransform() { $transformer = new CallbackTransformer( - function($value) { return $value.' has been transformed'; }, - function($value) { return $value.' has reversely been transformed'; } + function ($value) { return $value.' has been transformed'; }, + function ($value) { return $value.' has reversely been transformed'; } ); $this->assertEquals('foo has been transformed', $transformer->transform('foo')); @@ -30,8 +30,8 @@ public function testConstructorWithInvalidCallbacks($transformCallback, $reverse public function invalidCallbacksProvider() { return array( - array( null, function(){} ), - array( function(){}, null ), + array( null, function () {} ), + array( function () {}, null ), ); } } diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index 565b6ce646..17c4f3b0bf 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -794,7 +794,7 @@ public function testSubmitGetRequestWithEmptyRootFormName() $values = array( 'firstName' => 'Bernhard', 'lastName' => 'Schussek', - 'extra' => 'data' + 'extra' => 'data', ); $request = new Request($values, array(), array(), array(), array(), array( diff --git a/Tests/Extension/Core/ChoiceList/ChoiceListTest.php b/Tests/Extension/Core/ChoiceList/ChoiceListTest.php index 59f002d8cc..538bbc1b3d 100644 --- a/Tests/Extension/Core/ChoiceList/ChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/ChoiceListTest.php @@ -60,7 +60,7 @@ public function testInitNestedTraversable() $this->list = new ChoiceList( new \ArrayIterator(array( 'Group' => array($this->obj1, $this->obj2), - 'Not a Group' => $traversableChoice + 'Not a Group' => $traversableChoice, )), array( 'Group' => array('A', 'B'), @@ -72,11 +72,11 @@ public function testInitNestedTraversable() $this->assertSame(array($this->obj1, $this->obj2, $traversableChoice), $this->list->getChoices()); $this->assertSame(array('0', '1', '2'), $this->list->getValues()); $this->assertEquals(array( - 'Group' => array(1 => new ChoiceView($this->obj2, '1', 'B')) + 'Group' => array(1 => new ChoiceView($this->obj2, '1', 'B')), ), $this->list->getPreferredViews()); $this->assertEquals(array( 'Group' => array(0 => new ChoiceView($this->obj1, '0', 'A')), - 2 => new ChoiceView($traversableChoice, '2', 'C') + 2 => new ChoiceView($traversableChoice, '2', 'C'), ), $this->list->getRemainingViews()); } @@ -86,11 +86,11 @@ public function testInitNestedArray() $this->assertSame(array('0', '1', '2', '3'), $this->list->getValues()); $this->assertEquals(array( 'Group 1' => array(1 => new ChoiceView($this->obj2, '1', 'B')), - 'Group 2' => array(2 => new ChoiceView($this->obj3, '2', 'C')) + 'Group 2' => array(2 => new ChoiceView($this->obj3, '2', 'C')), ), $this->list->getPreferredViews()); $this->assertEquals(array( 'Group 1' => array(0 => new ChoiceView($this->obj1, '0', 'A')), - 'Group 2' => array(3 => new ChoiceView($this->obj4, '3', 'D')) + 'Group 2' => array(3 => new ChoiceView($this->obj4, '3', 'D')), ), $this->list->getRemainingViews()); } diff --git a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php index 27effd9f5c..2040dfd9e1 100644 --- a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php @@ -69,11 +69,11 @@ public function testInitNestedArray() $this->assertSame(array('0', '1', '2', '3'), $this->list->getValues()); $this->assertEquals(array( 'Group 1' => array(1 => new ChoiceView($this->obj2, '1', 'B')), - 'Group 2' => array(2 => new ChoiceView($this->obj3, '2', 'C')) + 'Group 2' => array(2 => new ChoiceView($this->obj3, '2', 'C')), ), $this->list->getPreferredViews()); $this->assertEquals(array( 'Group 1' => array(0 => new ChoiceView($this->obj1, '0', 'A')), - 'Group 2' => array(3 => new ChoiceView($this->obj4, '3', 'D')) + 'Group 2' => array(3 => new ChoiceView($this->obj4, '3', 'D')), ), $this->list->getRemainingViews()); } @@ -102,7 +102,7 @@ public function testInitArrayWithGroupPath() $this->assertSame(array('0', '1', '2', '3', '4', '5'), $this->list->getValues()); $this->assertEquals(array( 'Group 1' => array(1 => new ChoiceView($this->obj2, '1', 'B')), - 'Group 2' => array(2 => new ChoiceView($this->obj3, '2', 'C')) + 'Group 2' => array(2 => new ChoiceView($this->obj3, '2', 'C')), ), $this->list->getPreferredViews()); $this->assertEquals(array( 'Group 1' => array(0 => new ChoiceView($this->obj1, '0', 'A')), diff --git a/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php b/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php index 838a8e0864..3a5804ef28 100644 --- a/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/SimpleChoiceListTest.php @@ -33,11 +33,11 @@ public function testInitNestedArray() $this->assertSame(array(0 => 'a', 1 => 'b', 2 => 'c', 3 => 'd'), $this->list->getValues()); $this->assertEquals(array( 'Group 1' => array(1 => new ChoiceView('b', 'b', 'B')), - 'Group 2' => array(2 => new ChoiceView('c', 'c', 'C')) + 'Group 2' => array(2 => new ChoiceView('c', 'c', 'C')), ), $this->list->getPreferredViews()); $this->assertEquals(array( 'Group 1' => array(0 => new ChoiceView('a', 'a', 'A')), - 'Group 2' => array(3 => new ChoiceView('d', 'd', 'D')) + 'Group 2' => array(3 => new ChoiceView('d', 'd', 'D')), ), $this->list->getRemainingViews()); } diff --git a/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php b/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php index 16a7a4ad81..a39f53aa70 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php @@ -65,7 +65,7 @@ public function reverseTransformProvider() // format without seconds, as appears in some browsers array('UTC', 'UTC', '2010-02-03 04:05:00 UTC', '2010-02-03T04:05Z'), array('America/New_York', 'Asia/Hong_Kong', '2010-02-03 04:05:00 America/New_York', '2010-02-03T17:05+08:00'), - array('Europe/Amsterdam', 'Europe/Amsterdam', '2013-08-21 10:30:00 Europe/Amsterdam', '2013-08-21T08:30:00Z') + array('Europe/Amsterdam', 'Europe/Amsterdam', '2013-08-21 10:30:00 Europe/Amsterdam', '2013-08-21T08:30:00Z'), )); } diff --git a/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php index 971dd0a738..88115eaaae 100644 --- a/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php @@ -89,7 +89,6 @@ public function testTransformWithRoundingMode() $transformer = new NumberToLocalizedStringTransformer(2, null, NumberToLocalizedStringTransformer::ROUND_DOWN); $this->assertEquals('1234,54', $transformer->transform(1234.547), '->transform() rounding-mode works'); - } /** diff --git a/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php b/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php index a8a088a95a..6dc9785c24 100644 --- a/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/ValueToDuplicatesTransformerTest.php @@ -93,13 +93,12 @@ public function testReverseTransformEmptyArray() $this->assertNull($this->transformer->reverseTransform($input)); } - public function testReverseTransformZeroString() { $input = array( 'a' => '0', 'b' => '0', - 'c' => '0' + 'c' => '0', ); $this->assertSame('0', $this->transformer->reverseTransform($input)); diff --git a/Tests/Extension/Core/Type/ChoiceTypeTest.php b/Tests/Extension/Core/Type/ChoiceTypeTest.php index b251da031c..0f100f24ea 100644 --- a/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -43,7 +43,7 @@ class ChoiceTypeTest extends \Symfony\Component\Form\Test\TypeTestCase 'Doctrine' => array( 'd' => 'Jon', 'e' => 'Roman', - ) + ), ); protected function setUp() @@ -868,7 +868,7 @@ public function testSubmitMultipleExpandedWithEmptyChild() '' => 'Empty', 1 => 'Not Empty', 2 => 'Not Empty 2', - ) + ), )); $form->submit(array('', '2')); diff --git a/Tests/Extension/Core/Type/CurrencyTypeTest.php b/Tests/Extension/Core/Type/CurrencyTypeTest.php index b0eb6dc01c..ec290e3019 100644 --- a/Tests/Extension/Core/Type/CurrencyTypeTest.php +++ b/Tests/Extension/Core/Type/CurrencyTypeTest.php @@ -33,5 +33,4 @@ public function testCurrenciesAreSelectable() $this->assertContains(new ChoiceView('USD', 'USD', 'US Dollar'), $choices, '', false, false); $this->assertContains(new ChoiceView('SIT', 'SIT', 'Slovenian Tolar'), $choices, '', false, false); } - } diff --git a/Tests/Extension/Core/Type/DateTimeTypeTest.php b/Tests/Extension/Core/Type/DateTimeTypeTest.php index b9c1ebad38..213bc9ce43 100644 --- a/Tests/Extension/Core/Type/DateTimeTypeTest.php +++ b/Tests/Extension/Core/Type/DateTimeTypeTest.php @@ -441,7 +441,7 @@ public function testDateTypeSingleTextErrorsBubbleUp() { $error = new FormError('Invalid!'); $form = $this->factory->create('datetime', null, array( - 'date_widget' => 'single_text' + 'date_widget' => 'single_text', )); $form['date']->addError($error); @@ -465,7 +465,7 @@ public function testTimeTypeSingleTextErrorsBubbleUp() { $error = new FormError('Invalid!'); $form = $this->factory->create('datetime', null, array( - 'time_widget' => 'single_text' + 'time_widget' => 'single_text', )); $form['time']->addError($error); @@ -473,5 +473,4 @@ public function testTimeTypeSingleTextErrorsBubbleUp() $this->assertSame(array(), $form['time']->getErrors()); $this->assertSame(array($error), $form->getErrors()); } - } diff --git a/Tests/Extension/Core/Type/DateTypeTest.php b/Tests/Extension/Core/Type/DateTypeTest.php index 508ab410b0..f095f30354 100644 --- a/Tests/Extension/Core/Type/DateTypeTest.php +++ b/Tests/Extension/Core/Type/DateTypeTest.php @@ -412,7 +412,7 @@ public function testMonthsOptionShortFormat() $this->assertEquals(array( new ChoiceView('1', '1', 'Jän'), - new ChoiceView('4', '4', 'Apr.') + new ChoiceView('4', '4', 'Apr.'), ), $view['month']->vars['choices']); } @@ -554,7 +554,7 @@ public function testPassDatePatternToViewDifferentFormat() public function testPassDatePatternToViewDifferentPattern() { $form = $this->factory->create('date', null, array( - 'format' => 'MMyyyydd' + 'format' => 'MMyyyydd', )); $view = $form->createView(); @@ -565,7 +565,7 @@ public function testPassDatePatternToViewDifferentPattern() public function testPassDatePatternToViewDifferentPatternWithSeparators() { $form = $this->factory->create('date', null, array( - 'format' => 'MM*yyyy*dd' + 'format' => 'MM*yyyy*dd', )); $view = $form->createView(); diff --git a/Tests/Extension/Core/Type/FormTypeTest.php b/Tests/Extension/Core/Type/FormTypeTest.php index e670e57389..35cc17c6aa 100644 --- a/Tests/Extension/Core/Type/FormTypeTest.php +++ b/Tests/Extension/Core/Type/FormTypeTest.php @@ -334,7 +334,7 @@ public function testSubformDoesntCallSetters() // reference has a getter, but not setter 'reference' => array( 'firstName' => 'Foo', - ) + ), )); $this->assertEquals('Foo', $author->getReference()->firstName); @@ -359,7 +359,7 @@ public function testSubformCallsSettersIfTheObjectChanged() // referenceCopy has a getter that returns a copy 'referenceCopy' => array( 'firstName' => 'Foo', - ) + ), )); $this->assertEquals('Foo', $author->getReferenceCopy()->firstName); @@ -372,7 +372,7 @@ public function testSubformCallsSettersIfByReferenceIsFalse() $builder = $this->factory->createBuilder('form', $author); $builder->add('referenceCopy', 'form', array( 'data_class' => 'Symfony\Component\Form\Tests\Fixtures\Author', - 'by_reference' => false + 'by_reference' => false, )); $builder->get('referenceCopy')->add('firstName', 'text'); $form = $builder->getForm(); @@ -381,7 +381,7 @@ public function testSubformCallsSettersIfByReferenceIsFalse() // referenceCopy has a getter that returns a copy 'referenceCopy' => array( 'firstName' => 'Foo', - ) + ), )); // firstName can only be updated if setReferenceCopy() was called @@ -576,7 +576,7 @@ public function testNormDataIsPassedToView() public function testPassZeroLabelToView() { $view = $this->factory->create('form', null, array( - 'label' => '0' + 'label' => '0', )) ->createView(); diff --git a/Tests/Extension/Core/Type/RepeatedTypeTest.php b/Tests/Extension/Core/Type/RepeatedTypeTest.php index 9e125d781b..d506f5f5a6 100644 --- a/Tests/Extension/Core/Type/RepeatedTypeTest.php +++ b/Tests/Extension/Core/Type/RepeatedTypeTest.php @@ -52,7 +52,7 @@ public function testSetOptionsPerChild() // the global required value cannot be overridden 'type' => 'text', 'first_options' => array('label' => 'Test', 'required' => false), - 'second_options' => array('label' => 'Test2') + 'second_options' => array('label' => 'Test2'), )); $this->assertEquals('Test', $form['first']->getConfig()->getOption('label')); @@ -112,7 +112,7 @@ public function testSetOptionsPerChildAndOverwrite() $form = $this->factory->create('repeated', null, array( 'type' => 'text', 'options' => array('label' => 'Label'), - 'second_options' => array('label' => 'Second label') + 'second_options' => array('label' => 'Second label'), )); $this->assertEquals('Label', $form['first']->getConfig()->getOption('label')); diff --git a/Tests/Extension/Core/Type/TimeTypeTest.php b/Tests/Extension/Core/Type/TimeTypeTest.php index ca186207ac..b4fb3b1572 100644 --- a/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/Tests/Extension/Core/Type/TimeTypeTest.php @@ -276,7 +276,7 @@ public function testSetDataDifferentTimezones() $displayedData = array( 'hour' => (int) $outputTime->format('H'), 'minute' => (int) $outputTime->format('i'), - 'second' => (int) $outputTime->format('s') + 'second' => (int) $outputTime->format('s'), ); $this->assertEquals($displayedData, $form->getViewData()); @@ -302,7 +302,7 @@ public function testSetDataDifferentTimezonesDateTime() $displayedData = array( 'hour' => (int) $outputTime->format('H'), 'minute' => (int) $outputTime->format('i'), - 'second' => (int) $outputTime->format('s') + 'second' => (int) $outputTime->format('s'), ); $this->assertDateTimeEquals($dateTime, $form->getData()); @@ -510,8 +510,8 @@ public function testSingleTextWidgetWithSecondsShouldNotOverrideStepAttribute() 'widget' => 'single_text', 'with_seconds' => true, 'attr' => array( - 'step' => 30 - ) + 'step' => 30, + ), )); $view = $form->createView(); diff --git a/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php b/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php index 2ff072b2eb..00a93aa264 100644 --- a/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php +++ b/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php @@ -51,7 +51,7 @@ protected function setUp() 'name' => 'upload.png', 'size' => 123, 'tmp_name' => $path, - 'type' => 'image/png' + 'type' => 'image/png', ), ); diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index bfb84a15f8..19d5cec9f4 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -221,7 +221,7 @@ function () { throw new TransformationFailedException(); } $this->assertViolation('invalid_message_key', array( '{{ value }}' => 'foo', - '{{ foo }}' => 'bar' + '{{ foo }}' => 'bar', ), 'property.path', 'foo', null, Form::ERR_INVALID); } @@ -253,7 +253,7 @@ function () { throw new TransformationFailedException(); } $this->assertViolation('invalid_message_key', array( '{{ value }}' => 'foo', - '{{ foo }}' => 'bar' + '{{ foo }}' => 'bar', ), 'property.path', 'foo', null, Form::ERR_INVALID); } @@ -355,7 +355,7 @@ public function testHandleClosureValidationGroups() $object = $this->getMock('\stdClass'); $options = array('validation_groups' => function (FormInterface $form) { return array('group1', 'group2'); - }); + },); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); @@ -538,7 +538,7 @@ public function testViolationIfExtraData() $this->validator->validate($form, new Form()); $this->assertViolation('Extra!', array( - '{{ extra_fields }}' => 'foo' + '{{ extra_fields }}' => 'foo', ), 'property.path', array('foo' => 'bar')); } diff --git a/Tests/Extension/Validator/ValidatorTypeGuesserTest.php b/Tests/Extension/Validator/ValidatorTypeGuesserTest.php index f42003d214..090abf4486 100644 --- a/Tests/Extension/Validator/ValidatorTypeGuesserTest.php +++ b/Tests/Extension/Validator/ValidatorTypeGuesserTest.php @@ -71,7 +71,7 @@ public static function dataProviderTestGuessMaxLengthForConstraintWithType() array('double'), array('float'), array('numeric'), - array('real') + array('real'), ); } } diff --git a/Tests/Guess/GuessTest.php b/Tests/Guess/GuessTest.php index 235eb6ed2d..2422663720 100644 --- a/Tests/Guess/GuessTest.php +++ b/Tests/Guess/GuessTest.php @@ -13,7 +13,9 @@ use Symfony\Component\Form\Guess\Guess; -class TestGuess extends Guess {} +class TestGuess extends Guess +{ +} class GuessTest extends \PHPUnit_Framework_TestCase { diff --git a/Tests/NativeRequestHandlerTest.php b/Tests/NativeRequestHandlerTest.php index 9d3a997fec..02b0a4ed74 100644 --- a/Tests/NativeRequestHandlerTest.php +++ b/Tests/NativeRequestHandlerTest.php @@ -82,7 +82,7 @@ public function testConvertEmptyUploadedFilesToNull() 'type' => '', 'tmp_name' => '', 'error' => UPLOAD_ERR_NO_FILE, - 'size' => 0 + 'size' => 0, ))); $form->expects($this->once()) diff --git a/Tests/SimpleFormTest.php b/Tests/SimpleFormTest.php index d6d3238b42..657f145c6c 100644 --- a/Tests/SimpleFormTest.php +++ b/Tests/SimpleFormTest.php @@ -518,7 +518,7 @@ public function testSubmitExecutesTransformationChain() '' => '', // direction is reversed! 'norm' => 'filteredclient', - 'filterednorm' => 'cleanedclient' + 'filterednorm' => 'cleanedclient', ))) ->addModelTransformer(new FixedDataTransformer(array( '' => '', diff --git a/Util/FormUtil.php b/Util/FormUtil.php index b3beb458be..af6ac4a643 100644 --- a/Util/FormUtil.php +++ b/Util/FormUtil.php @@ -19,7 +19,9 @@ class FormUtil /** * This class should not be instantiated */ - private function __construct() {} + private function __construct() + { + } /** * Returns whether the given data is empty. diff --git a/Util/OrderedHashMap.php b/Util/OrderedHashMap.php index bf5b08cda6..2ba53e2610 100644 --- a/Util/OrderedHashMap.php +++ b/Util/OrderedHashMap.php @@ -120,7 +120,7 @@ public function offsetExists($key) public function offsetGet($key) { if (!isset($this->elements[$key])) { - throw new \OutOfBoundsException('The offset "' . $key . '" does not exist.'); + throw new \OutOfBoundsException('The offset "'.$key.'" does not exist.'); } return $this->elements[$key]; From 6ce42efbbd9f974c0121a350634c3a9c38379d92 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Sun, 6 Jul 2014 16:36:42 +0200 Subject: [PATCH 332/447] [2.3] Add missing development dependencies --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 14f9dadce4..f55a042086 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,8 @@ "symfony/property-access": "~2.3" }, "require-dev": { - "symfony/validator": "~2.2", + "doctrine/collections": "~1.0", + "symfony/validator": "~2.3.0", "symfony/http-foundation": "~2.2" }, "suggest": { From ed2de54090b28d74aa8d84d2df2ca1700e83ba67 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 23 Sep 2014 08:31:13 +0200 Subject: [PATCH 333/447] fixed CS --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a356bf7f92..c663c960fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,9 @@ CHANGELOG 2.6.0 ----- -* added allow_html5 option to Date, Time and DateTimeFormType to disable HTML5 input date when widget option is single_text + + * added "allow_html5" option to Date, Time and DateTimeFormType to be able to + enable/disable HTML5 input date when widget option is "single_text" 2.5.0 ------ From e624116c61a317723a6b6a3c3f90d99a071bd0ff Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Tue, 23 Sep 2014 12:15:17 +0200 Subject: [PATCH 334/447] [Form] Changed "allow_html5" to "html5" --- CHANGELOG.md | 2 +- Extension/Core/Type/DateTimeType.php | 10 +++++----- Extension/Core/Type/DateType.php | 6 +++--- Extension/Core/Type/TimeType.php | 6 +++--- Tests/Extension/Core/Type/DateTimeTypeTest.php | 2 +- Tests/Extension/Core/Type/DateTypeTest.php | 2 +- Tests/Extension/Core/Type/TimeTypeTest.php | 2 +- 7 files changed, 15 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c663c960fb..4381726126 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ CHANGELOG 2.6.0 ----- - * added "allow_html5" option to Date, Time and DateTimeFormType to be able to + * added "html5" option to Date, Time and DateTimeFormType to be able to enable/disable HTML5 input date when widget option is "single_text" 2.5.0 diff --git a/Extension/Core/Type/DateTimeType.php b/Extension/Core/Type/DateTimeType.php index 88dd9d94d1..cad1c5e8d5 100644 --- a/Extension/Core/Type/DateTimeType.php +++ b/Extension/Core/Type/DateTimeType.php @@ -117,7 +117,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'empty_value', 'required', 'translation_domain', - 'allow_html5', + 'html5', ))); $timeOptions = array_intersect_key($options, array_flip(array( @@ -129,7 +129,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'empty_value', 'required', 'translation_domain', - 'allow_html5', + 'html5', ))); if (null !== $options['date_widget']) { @@ -185,8 +185,8 @@ public function buildView(FormView $view, FormInterface $form, array $options) // Change the input to a HTML5 datetime input if // * the widget is set to "single_text" // * the format matches the one expected by HTML5 - // * the allow_html5 is set to true - if ($options['allow_html5'] && 'single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) { + // * the html5 is set to true + if ($options['html5'] && 'single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) { $view->vars['type'] = 'datetime'; } } @@ -221,7 +221,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'time_widget' => $timeWidget, 'with_minutes' => true, 'with_seconds' => false, - 'allow_html5' => true, + 'html5' => true, // Don't modify \DateTime classes by reference, we treat // them like immutable value objects 'by_reference' => false, diff --git a/Extension/Core/Type/DateType.php b/Extension/Core/Type/DateType.php index 757a9904c3..35657742e5 100644 --- a/Extension/Core/Type/DateType.php +++ b/Extension/Core/Type/DateType.php @@ -136,8 +136,8 @@ public function finishView(FormView $view, FormInterface $form, array $options) // Change the input to a HTML5 date input if // * the widget is set to "single_text" // * the format matches the one expected by HTML5 - // * the allow_html5 is set to true - if ($options['allow_html5'] && 'single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) { + // * the html5 is set to true + if ($options['html5'] && 'single_text' === $options['widget'] && self::HTML5_FORMAT === $options['format']) { $view->vars['type'] = 'date'; } @@ -206,7 +206,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'model_timezone' => null, 'view_timezone' => null, 'empty_value' => $emptyValue, - 'allow_html5' => true, + 'html5' => true, // Don't modify \DateTime classes by reference, we treat // them like immutable value objects 'by_reference' => false, diff --git a/Extension/Core/Type/TimeType.php b/Extension/Core/Type/TimeType.php index eebfc35cee..223c3d9289 100644 --- a/Extension/Core/Type/TimeType.php +++ b/Extension/Core/Type/TimeType.php @@ -140,8 +140,8 @@ public function buildView(FormView $view, FormInterface $form, array $options) // Change the input to a HTML5 time input if // * the widget is set to "single_text" - // * the allow_html5 is set to true - if ($options['allow_html5'] && 'single_text' === $options['widget']) { + // * the html5 is set to true + if ($options['html5'] && 'single_text' === $options['widget']) { $view->vars['type'] = 'time'; // we need to force the browser to display the seconds by @@ -195,7 +195,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'model_timezone' => null, 'view_timezone' => null, 'empty_value' => $emptyValue, - 'allow_html5' => true, + 'html5' => true, // Don't modify \DateTime classes by reference, we treat // them like immutable value objects 'by_reference' => false, diff --git a/Tests/Extension/Core/Type/DateTimeTypeTest.php b/Tests/Extension/Core/Type/DateTimeTypeTest.php index 35b6ab45a8..e45f6134e8 100644 --- a/Tests/Extension/Core/Type/DateTimeTypeTest.php +++ b/Tests/Extension/Core/Type/DateTimeTypeTest.php @@ -409,7 +409,7 @@ public function testDontPassHtml5TypeIfHtml5NotAllowed() { $form = $this->factory->create('datetime', null, array( 'widget' => 'single_text', - 'allow_html5' => false, + 'html5' => false, )); $view = $form->createView(); diff --git a/Tests/Extension/Core/Type/DateTypeTest.php b/Tests/Extension/Core/Type/DateTypeTest.php index 8e12858421..28e681a28c 100644 --- a/Tests/Extension/Core/Type/DateTypeTest.php +++ b/Tests/Extension/Core/Type/DateTypeTest.php @@ -709,7 +709,7 @@ public function testDontPassHtml5TypeIfHtml5NotAllowed() { $form = $this->factory->create('date', null, array( 'widget' => 'single_text', - 'allow_html5' => false, + 'html5' => false, )); $view = $form->createView(); diff --git a/Tests/Extension/Core/Type/TimeTypeTest.php b/Tests/Extension/Core/Type/TimeTypeTest.php index e1129e0e15..d74dc69ace 100644 --- a/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/Tests/Extension/Core/Type/TimeTypeTest.php @@ -523,7 +523,7 @@ public function testDontPassHtml5TypeIfHtml5NotAllowed() { $form = $this->factory->create('time', null, array( 'widget' => 'single_text', - 'allow_html5' => false, + 'html5' => false, )); $view = $form->createView(); From 550f89f21853142095a308626eedbf8f437dbdb2 Mon Sep 17 00:00:00 2001 From: rpg600 Date: Mon, 8 Sep 2014 10:53:21 +0200 Subject: [PATCH 335/447] [Form] Add a form error if post_max_size has been reached. --- .../HttpFoundationRequestHandler.php | 19 +++++++++++++++++ NativeRequestHandler.php | 18 ++++++++++++++++ Tests/AbstractRequestHandlerTest.php | 21 +++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/Extension/HttpFoundation/HttpFoundationRequestHandler.php b/Extension/HttpFoundation/HttpFoundationRequestHandler.php index 2094699481..065d01aec8 100644 --- a/Extension/HttpFoundation/HttpFoundationRequestHandler.php +++ b/Extension/HttpFoundation/HttpFoundationRequestHandler.php @@ -12,6 +12,8 @@ namespace Symfony\Component\Form\Extension\HttpFoundation; use Symfony\Component\Form\Exception\UnexpectedTypeException; +use Symfony\Component\Form\Extension\Validator\Util\ServerParams; +use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\RequestHandlerInterface; use Symfony\Component\HttpFoundation\Request; @@ -24,6 +26,19 @@ */ class HttpFoundationRequestHandler implements RequestHandlerInterface { + /** + * @var ServerParams + */ + private $serverParams; + + /** + * {@inheritdoc} + */ + public function __construct(ServerParams $params = null) + { + $this->serverParams = $params ?: new ServerParams(); + } + /** * {@inheritdoc} */ @@ -61,6 +76,10 @@ public function handleRequest(FormInterface $form, $request = null) $params = $request->request->get($name, $default); $files = $request->files->get($name, $default); } else { + if ($this->serverParams->getContentLength() > $this->serverParams->getPostMaxSize()) { + $form->addError(new FormError('Max post size exceeded.')); + } + // Don't submit the form if it is not present in the request return; } diff --git a/NativeRequestHandler.php b/NativeRequestHandler.php index fefe546af8..02c90c8798 100644 --- a/NativeRequestHandler.php +++ b/NativeRequestHandler.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\UnexpectedTypeException; +use Symfony\Component\Form\Extension\Validator\Util\ServerParams; /** * A request handler using PHP's super globals $_GET, $_POST and $_SERVER. @@ -20,6 +21,19 @@ */ class NativeRequestHandler implements RequestHandlerInterface { + /** + * @var ServerParams + */ + private $serverParams; + + /** + * {@inheritdoc} + */ + public function __construct(ServerParams $params = null) + { + $this->serverParams = $params ?: new ServerParams(); + } + /** * The allowed keys of the $_FILES array. * @@ -75,6 +89,10 @@ public function handleRequest(FormInterface $form, $request = null) $params = array_key_exists($name, $_POST) ? $_POST[$name] : $default; $files = array_key_exists($name, $fixedFiles) ? $fixedFiles[$name] : $default; } else { + if ($this->serverParams->getContentLength() > $this->serverParams->getPostMaxSize()) { + $form->addError(new FormError('Max post size exceeded.')); + } + // Don't submit the form if it is not present in the request return; } diff --git a/Tests/AbstractRequestHandlerTest.php b/Tests/AbstractRequestHandlerTest.php index fbba16ba17..8eb4816d57 100644 --- a/Tests/AbstractRequestHandlerTest.php +++ b/Tests/AbstractRequestHandlerTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Form\Tests; +use Symfony\Component\Form\Forms; + /** * @author Bernhard Schussek */ @@ -21,11 +23,17 @@ abstract class AbstractRequestHandlerTest extends \PHPUnit_Framework_TestCase */ protected $requestHandler; + /** + * @var \Symfony\Component\Form\FormFactory + */ + protected $factory; + protected $request; protected function setUp() { $this->requestHandler = $this->getRequestHandler(); + $this->factory = Forms::createFormFactoryBuilder()->getFormFactory(); $this->request = null; } @@ -249,6 +257,19 @@ public function testSubmitFileIfNoParam($method) $this->requestHandler->handleRequest($form, $this->request); } + public function testAddFormErrorIfPostMaxSizeExceeded() + { + $form = $this->factory->createNamed('name', 'text'); + $this->setRequestData('POST', array(), array()); + $_SERVER['CONTENT_LENGTH'] = 1000000000; + + $this->requestHandler->handleRequest($form, $this->request); + + $this->assertEquals("ERROR: Max post size exceeded.\n", $form->getErrorsAsString()); + + unset($_SERVER['CONTENT_LENGTH']); + } + abstract protected function setRequestData($method, $data, $files = array()); abstract protected function getRequestHandler(); From e13ff44d5dd5f098197ed2e994a00d7448e49034 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Mon, 15 Sep 2014 16:48:43 +0200 Subject: [PATCH 336/447] [Form] Moved POST_MAX_SIZE validation from FormValidator to request handler --- Extension/Core/Type/FormType.php | 38 +++++----- .../HttpFoundationExtension.php | 13 +++- .../HttpFoundationRequestHandler.php | 29 ++++++-- .../Type/FormTypeHttpFoundationExtension.php | 5 +- .../Validator/Constraints/FormValidator.php | 32 --------- .../Type/FormTypeValidatorExtension.php | 1 - Extension/Validator/Util/ServerParams.php | 55 +------------- NativeRequestHandler.php | 25 +++++-- Tests/AbstractRequestHandlerTest.php | 54 ++++++++++++-- .../HttpFoundationRequestHandlerTest.php | 2 +- .../Constraints/FormValidatorTest.php | 63 ---------------- Tests/NativeRequestHandlerTest.php | 2 +- Util/ServerParams.php | 72 +++++++++++++++++++ 13 files changed, 198 insertions(+), 193 deletions(-) create mode 100644 Util/ServerParams.php diff --git a/Extension/Core/Type/FormType.php b/Extension/Core/Type/FormType.php index 6da2034731..b417afdbcb 100644 --- a/Extension/Core/Type/FormType.php +++ b/Extension/Core/Type/FormType.php @@ -56,8 +56,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) ->setDataLocked($isDataOptionSet) ->setDataMapper($options['compound'] ? new PropertyPathMapper($this->propertyAccessor) : null) ->setMethod($options['method']) - ->setAction($options['action']) - ; + ->setAction($options['action']); if ($options['trim']) { $builder->addEventSubscriber(new TrimListener()); @@ -170,25 +169,26 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) )); $resolver->setDefaults(array( - 'data_class' => $dataClass, - 'empty_data' => $emptyData, - 'trim' => true, - 'required' => true, - 'read_only' => false, - 'max_length' => null, - 'pattern' => null, - 'property_path' => null, - 'mapped' => true, - 'by_reference' => true, - 'error_bubbling' => $errorBubbling, - 'label_attr' => array(), - 'virtual' => null, - 'inherit_data' => $inheritData, - 'compound' => true, - 'method' => 'POST', + 'data_class' => $dataClass, + 'empty_data' => $emptyData, + 'trim' => true, + 'required' => true, + 'read_only' => false, + 'max_length' => null, + 'pattern' => null, + 'property_path' => null, + 'mapped' => true, + 'by_reference' => true, + 'error_bubbling' => $errorBubbling, + 'label_attr' => array(), + 'virtual' => null, + 'inherit_data' => $inheritData, + 'compound' => true, + 'method' => 'POST', // According to RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt) // section 4.2., empty URIs are considered same-document references - 'action' => '', + 'action' => '', + 'post_max_size_message' => 'The uploaded file was too large. Please try to upload a smaller file.', )); $resolver->setAllowedTypes(array( diff --git a/Extension/HttpFoundation/HttpFoundationExtension.php b/Extension/HttpFoundation/HttpFoundationExtension.php index 08bd89c9e4..33e9c1c4d4 100644 --- a/Extension/HttpFoundation/HttpFoundationExtension.php +++ b/Extension/HttpFoundation/HttpFoundationExtension.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Extension\HttpFoundation; use Symfony\Component\Form\AbstractExtension; +use Symfony\Component\Form\Util\ServerParams; /** * Integrates the HttpFoundation component with the Form library. @@ -20,10 +21,20 @@ */ class HttpFoundationExtension extends AbstractExtension { + /** + * @var ServerParams + */ + private $serverParams; + + public function __construct(ServerParams $serverParams = null) + { + $this->serverParams = $serverParams; + } + protected function loadTypeExtensions() { return array( - new Type\FormTypeHttpFoundationExtension(), + new Type\FormTypeHttpFoundationExtension($this->serverParams), ); } } diff --git a/Extension/HttpFoundation/HttpFoundationRequestHandler.php b/Extension/HttpFoundation/HttpFoundationRequestHandler.php index 065d01aec8..03805fef52 100644 --- a/Extension/HttpFoundation/HttpFoundationRequestHandler.php +++ b/Extension/HttpFoundation/HttpFoundationRequestHandler.php @@ -12,10 +12,10 @@ namespace Symfony\Component\Form\Extension\HttpFoundation; use Symfony\Component\Form\Exception\UnexpectedTypeException; -use Symfony\Component\Form\Extension\Validator\Util\ServerParams; use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\RequestHandlerInterface; +use Symfony\Component\Form\Util\ServerParams; use Symfony\Component\HttpFoundation\Request; /** @@ -34,9 +34,9 @@ class HttpFoundationRequestHandler implements RequestHandlerInterface /** * {@inheritdoc} */ - public function __construct(ServerParams $params = null) + public function __construct(ServerParams $serverParams = null) { - $this->serverParams = $params ?: new ServerParams(); + $this->serverParams = $serverParams ?: new ServerParams(); } /** @@ -68,6 +68,25 @@ public function handleRequest(FormInterface $form, $request = null) $data = $request->query->get($name); } } else { + // Mark the form with an error if the uploaded size was too large + // This is done here and not in FormValidator because $_POST is + // empty when that error occurs. Hence the form is never submitted. + $contentLength = $this->serverParams->getContentLength(); + $maxContentLength = $this->serverParams->getPostMaxSize(); + + if (!empty($maxContentLength) && $contentLength > $maxContentLength) { + // Submit the form, but don't clear the default values + $form->submit(null, false); + + $form->addError(new FormError( + $form->getConfig()->getOption('post_max_size_message'), + null, + array('{{ max }}' => $this->serverParams->getNormalizedIniPostMaxSize()) + )); + + return; + } + if ('' === $name) { $params = $request->request->all(); $files = $request->files->all(); @@ -76,10 +95,6 @@ public function handleRequest(FormInterface $form, $request = null) $params = $request->request->get($name, $default); $files = $request->files->get($name, $default); } else { - if ($this->serverParams->getContentLength() > $this->serverParams->getPostMaxSize()) { - $form->addError(new FormError('Max post size exceeded.')); - } - // Don't submit the form if it is not present in the request return; } diff --git a/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php b/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php index 9b09b05c39..4596f06b98 100644 --- a/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php +++ b/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php @@ -15,6 +15,7 @@ use Symfony\Component\Form\Extension\HttpFoundation\EventListener\BindRequestListener; use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\Form\Util\ServerParams; /** * @author Bernhard Schussek @@ -31,10 +32,10 @@ class FormTypeHttpFoundationExtension extends AbstractTypeExtension */ private $requestHandler; - public function __construct() + public function __construct(ServerParams $serverParams = null) { $this->listener = new BindRequestListener(); - $this->requestHandler = new HttpFoundationRequestHandler(); + $this->requestHandler = new HttpFoundationRequestHandler($serverParams); } /** diff --git a/Extension/Validator/Constraints/FormValidator.php b/Extension/Validator/Constraints/FormValidator.php index 154e865923..2851016f40 100644 --- a/Extension/Validator/Constraints/FormValidator.php +++ b/Extension/Validator/Constraints/FormValidator.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Form\Extension\Validator\Constraints; use Symfony\Component\Form\FormInterface; -use Symfony\Component\Form\Extension\Validator\Util\ServerParams; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; @@ -21,22 +20,6 @@ */ class FormValidator extends ConstraintValidator { - /** - * @var ServerParams - */ - private $serverParams; - - /** - * Creates a validator with the given server parameters. - * - * @param ServerParams $params The server parameters. Default - * parameters are created if null. - */ - public function __construct(ServerParams $params = null) - { - $this->serverParams = $params ?: new ServerParams(); - } - /** * {@inheritdoc} */ @@ -113,21 +96,6 @@ public function validate($form, Constraint $constraint) $form->getExtraData() ); } - - // Mark the form with an error if the uploaded size was too large - $length = $this->serverParams->getContentLength(); - - if ($form->isRoot() && null !== $length) { - $max = $this->serverParams->getPostMaxSize(); - - if (!empty($max) && $length > $max) { - $this->context->addViolation( - $config->getOption('post_max_size_message'), - array('{{ max }}' => $this->serverParams->getNormalizedIniPostMaxSize()), - $length - ); - } - } } /** diff --git a/Extension/Validator/Type/FormTypeValidatorExtension.php b/Extension/Validator/Type/FormTypeValidatorExtension.php index 344bddadc1..ae39af66fc 100644 --- a/Extension/Validator/Type/FormTypeValidatorExtension.php +++ b/Extension/Validator/Type/FormTypeValidatorExtension.php @@ -66,7 +66,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'invalid_message' => 'This value is not valid.', 'invalid_message_parameters' => array(), 'extra_fields_message' => 'This form should not contain extra fields.', - 'post_max_size_message' => 'The uploaded file was too large. Please try to upload a smaller file.', )); $resolver->setNormalizers(array( diff --git a/Extension/Validator/Util/ServerParams.php b/Extension/Validator/Util/ServerParams.php index 58fdc25e22..c058d60cae 100644 --- a/Extension/Validator/Util/ServerParams.php +++ b/Extension/Validator/Util/ServerParams.php @@ -14,59 +14,6 @@ /** * @author Bernhard Schussek */ -class ServerParams +class ServerParams extends \Symfony\Component\Form\Util\ServerParams { - /** - * Returns maximum post size in bytes. - * - * @return null|int The maximum post size in bytes - */ - public function getPostMaxSize() - { - $iniMax = strtolower($this->getNormalizedIniPostMaxSize()); - - if ('' === $iniMax) { - return; - } - - $max = ltrim($iniMax, '+'); - if (0 === strpos($max, '0x')) { - $max = intval($max, 16); - } elseif (0 === strpos($max, '0')) { - $max = intval($max, 8); - } else { - $max = intval($max); - } - - switch (substr($iniMax, -1)) { - case 't': $max *= 1024; - case 'g': $max *= 1024; - case 'm': $max *= 1024; - case 'k': $max *= 1024; - } - - return $max; - } - - /** - * Returns the normalized "post_max_size" ini setting. - * - * @return string - */ - public function getNormalizedIniPostMaxSize() - { - return strtoupper(trim(ini_get('post_max_size'))); - } - - /** - * Returns the content length of the request. - * - * @return mixed The request content length. - */ - public function getContentLength() - { - return isset($_SERVER['CONTENT_LENGTH']) - ? (int) $_SERVER['CONTENT_LENGTH'] - : null; - } } diff --git a/NativeRequestHandler.php b/NativeRequestHandler.php index 02c90c8798..9df9066886 100644 --- a/NativeRequestHandler.php +++ b/NativeRequestHandler.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\UnexpectedTypeException; -use Symfony\Component\Form\Extension\Validator\Util\ServerParams; +use Symfony\Component\Form\Util\ServerParams; /** * A request handler using PHP's super globals $_GET, $_POST and $_SERVER. @@ -76,6 +76,25 @@ public function handleRequest(FormInterface $form, $request = null) $data = $_GET[$name]; } } else { + // Mark the form with an error if the uploaded size was too large + // This is done here and not in FormValidator because $_POST is + // empty when that error occurs. Hence the form is never submitted. + $contentLength = $this->serverParams->getContentLength(); + $maxContentLength = $this->serverParams->getPostMaxSize(); + + if (!empty($maxContentLength) && $contentLength > $maxContentLength) { + // Submit the form, but don't clear the default values + $form->submit(null, false); + + $form->addError(new FormError( + $form->getConfig()->getOption('post_max_size_message'), + null, + array('{{ max }}' => $this->serverParams->getNormalizedIniPostMaxSize()) + )); + + return; + } + $fixedFiles = array(); foreach ($_FILES as $name => $file) { $fixedFiles[$name] = self::stripEmptyFiles(self::fixPhpFilesArray($file)); @@ -89,10 +108,6 @@ public function handleRequest(FormInterface $form, $request = null) $params = array_key_exists($name, $_POST) ? $_POST[$name] : $default; $files = array_key_exists($name, $fixedFiles) ? $fixedFiles[$name] : $default; } else { - if ($this->serverParams->getContentLength() > $this->serverParams->getPostMaxSize()) { - $form->addError(new FormError('Max post size exceeded.')); - } - // Don't submit the form if it is not present in the request return; } diff --git a/Tests/AbstractRequestHandlerTest.php b/Tests/AbstractRequestHandlerTest.php index 8eb4816d57..b017db90d0 100644 --- a/Tests/AbstractRequestHandlerTest.php +++ b/Tests/AbstractRequestHandlerTest.php @@ -11,7 +11,10 @@ namespace Symfony\Component\Form\Tests; +use Symfony\Component\Form\FormError; +use Symfony\Component\Form\FormFactory; use Symfony\Component\Form\Forms; +use Symfony\Component\Form\RequestHandlerInterface; /** * @author Bernhard Schussek @@ -19,19 +22,25 @@ abstract class AbstractRequestHandlerTest extends \PHPUnit_Framework_TestCase { /** - * @var \Symfony\Component\Form\RequestHandlerInterface + * @var RequestHandlerInterface */ protected $requestHandler; /** - * @var \Symfony\Component\Form\FormFactory + * @var FormFactory */ protected $factory; protected $request; + protected $serverParams; + protected function setUp() { + $this->serverParams = $this->getMock( + 'Symfony\Component\Form\Util\ServerParams', + array('getNormalizedIniPostMaxSize', 'getContentLength') + ); $this->requestHandler = $this->getRequestHandler(); $this->factory = Forms::createFormFactoryBuilder()->getFormFactory(); $this->request = null; @@ -257,17 +266,48 @@ public function testSubmitFileIfNoParam($method) $this->requestHandler->handleRequest($form, $this->request); } - public function testAddFormErrorIfPostMaxSizeExceeded() + /** + * @dataProvider getPostMaxSizeFixtures + */ + public function testAddFormErrorIfPostMaxSizeExceeded($contentLength, $iniMax, $shouldFail, array $errorParams = array()) { - $form = $this->factory->createNamed('name', 'text'); + $this->serverParams->expects($this->once()) + ->method('getContentLength') + ->will($this->returnValue($contentLength)); + $this->serverParams->expects($this->any()) + ->method('getNormalizedIniPostMaxSize') + ->will($this->returnValue($iniMax)); + + $options = array('post_max_size_message' => 'Max {{ max }}!'); + $form = $this->factory->createNamed('name', 'text', null, $options); $this->setRequestData('POST', array(), array()); - $_SERVER['CONTENT_LENGTH'] = 1000000000; $this->requestHandler->handleRequest($form, $this->request); - $this->assertEquals("ERROR: Max post size exceeded.\n", $form->getErrorsAsString()); + if ($shouldFail) { + $errors = array(new FormError($options['post_max_size_message'], null, $errorParams)); - unset($_SERVER['CONTENT_LENGTH']); + $this->assertEquals($errors, $form->getErrors()); + $this->assertTrue($form->isSubmitted()); + } else { + $this->assertCount(0, $form->getErrors()); + $this->assertFalse($form->isSubmitted()); + } + } + + public function getPostMaxSizeFixtures() + { + return array( + array(pow(1024, 3) + 1, '1G', true, array('{{ max }}' => '1G')), + array(pow(1024, 3), '1G', false), + array(pow(1024, 2) + 1, '1M', true, array('{{ max }}' => '1M')), + array(pow(1024, 2), '1M', false), + array(1024 + 1, '1K', true, array('{{ max }}' => '1K')), + array(1024, '1K', false), + array(null, '1K', false), + array(1024, '', false), + array(1024, 0, false), + ); } abstract protected function setRequestData($method, $data, $files = array()); diff --git a/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php b/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php index cf5d63d90e..dcd26891c1 100644 --- a/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php +++ b/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php @@ -43,7 +43,7 @@ protected function setRequestData($method, $data, $files = array()) protected function getRequestHandler() { - return new HttpFoundationRequestHandler(); + return new HttpFoundationRequestHandler($this->serverParams); } protected function getMockFile() diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index 19d5cec9f4..8032d6273d 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -542,69 +542,6 @@ public function testViolationIfExtraData() ), 'property.path', array('foo' => 'bar')); } - /** - * @dataProvider getPostMaxSizeFixtures - */ - public function testPostMaxSizeViolation($contentLength, $iniMax, $nbViolation, array $params = array()) - { - $this->serverParams->expects($this->once()) - ->method('getContentLength') - ->will($this->returnValue($contentLength)); - $this->serverParams->expects($this->any()) - ->method('getNormalizedIniPostMaxSize') - ->will($this->returnValue($iniMax)); - - $options = array('post_max_size_message' => 'Max {{ max }}!'); - $form = $this->getBuilder('name', null, $options)->getForm(); - - $this->validator->validate($form, new Form()); - - $violations = array(); - - for ($i = 0; $i < $nbViolation; ++$i) { - $violations[] = $this->createViolation($options['post_max_size_message'], $params, 'property.path', $contentLength); - } - - $this->assertViolations($violations); - } - - public function getPostMaxSizeFixtures() - { - return array( - array(pow(1024, 3) + 1, '1G', 1, array('{{ max }}' => '1G')), - array(pow(1024, 3), '1G', 0), - array(pow(1024, 2) + 1, '1M', 1, array('{{ max }}' => '1M')), - array(pow(1024, 2), '1M', 0), - array(1024 + 1, '1K', 1, array('{{ max }}' => '1K')), - array(1024, '1K', 0), - array(null, '1K', 0), - array(1024, '', 0), - array(1024, 0, 0), - ); - } - - public function testNoViolationIfNotRoot() - { - $this->serverParams->expects($this->once()) - ->method('getContentLength') - ->will($this->returnValue(1025)); - $this->serverParams->expects($this->never()) - ->method('getNormalizedIniPostMaxSize'); - - $parent = $this->getBuilder() - ->setCompound(true) - ->setDataMapper($this->getDataMapper()) - ->getForm(); - $form = $this->getForm(); - $parent->add($form); - - $this->expectNoValidate(); - - $this->validator->validate($form, new Form()); - - $this->assertNoViolation(); - } - /** * Access has to be public, as this method is called via callback array * in {@link testValidateFormDataCanHandleCallbackValidationGroups()} diff --git a/Tests/NativeRequestHandlerTest.php b/Tests/NativeRequestHandlerTest.php index 02b0a4ed74..eac767f8c8 100644 --- a/Tests/NativeRequestHandlerTest.php +++ b/Tests/NativeRequestHandlerTest.php @@ -203,7 +203,7 @@ protected function setRequestData($method, $data, $files = array()) protected function getRequestHandler() { - return new NativeRequestHandler(); + return new NativeRequestHandler($this->serverParams); } protected function getMockFile() diff --git a/Util/ServerParams.php b/Util/ServerParams.php new file mode 100644 index 0000000000..3b1f835182 --- /dev/null +++ b/Util/ServerParams.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Util; + +/** + * @author Bernhard Schussek + */ +class ServerParams +{ + /** + * Returns maximum post size in bytes. + * + * @return null|int The maximum post size in bytes + */ + public function getPostMaxSize() + { + $iniMax = strtolower($this->getNormalizedIniPostMaxSize()); + + if ('' === $iniMax) { + return; + } + + $max = ltrim($iniMax, '+'); + if (0 === strpos($max, '0x')) { + $max = intval($max, 16); + } elseif (0 === strpos($max, '0')) { + $max = intval($max, 8); + } else { + $max = intval($max); + } + + switch (substr($iniMax, -1)) { + case 't': $max *= 1024; + case 'g': $max *= 1024; + case 'm': $max *= 1024; + case 'k': $max *= 1024; + } + + return $max; + } + + /** + * Returns the normalized "post_max_size" ini setting. + * + * @return string + */ + public function getNormalizedIniPostMaxSize() + { + return strtoupper(trim(ini_get('post_max_size'))); + } + + /** + * Returns the content length of the request. + * + * @return mixed The request content length. + */ + public function getContentLength() + { + return isset($_SERVER['CONTENT_LENGTH']) + ? (int) $_SERVER['CONTENT_LENGTH'] + : null; + } +} From 96266d51e1e6588aacaa0cd48110ddef2430d520 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Tue, 23 Sep 2014 16:46:44 +0200 Subject: [PATCH 337/447] [Form] Renamed the option "empty_value" to "placeholder" --- Extension/Core/Type/ChoiceType.php | 35 +++--- Extension/Core/Type/DateTimeType.php | 5 +- Extension/Core/Type/DateType.php | 32 +++--- Extension/Core/Type/TimeType.php | 33 +++--- Tests/AbstractLayoutTest.php | 52 ++++----- Tests/Extension/Core/Type/ChoiceTypeTest.php | 46 +++++--- .../Extension/Core/Type/DateTimeTypeTest.php | 100 +++++++++++------- Tests/Extension/Core/Type/DateTypeTest.php | 63 ++++++----- Tests/Extension/Core/Type/TimeTypeTest.php | 64 ++++++----- 9 files changed, 265 insertions(+), 165 deletions(-) diff --git a/Extension/Core/Type/ChoiceType.php b/Extension/Core/Type/ChoiceType.php index 08504dea2b..28c991e96b 100644 --- a/Extension/Core/Type/ChoiceType.php +++ b/Extension/Core/Type/ChoiceType.php @@ -57,8 +57,8 @@ public function buildForm(FormBuilderInterface $builder, array $options) // Check if the choices already contain the empty value // Only add the empty value option if this is not the case - if (null !== $options['empty_value'] && 0 === count($options['choice_list']->getChoicesForValues(array('')))) { - $placeholderView = new ChoiceView(null, '', $options['empty_value']); + if (null !== $options['placeholder'] && 0 === count($options['choice_list']->getChoicesForValues(array('')))) { + $placeholderView = new ChoiceView(null, '', $options['placeholder']); // "placeholder" is a reserved index // see also ChoiceListInterface::getIndicesForChoices() @@ -101,7 +101,7 @@ public function buildView(FormView $view, FormInterface $form, array $options) 'preferred_choices' => $options['choice_list']->getPreferredViews(), 'choices' => $options['choice_list']->getRemainingViews(), 'separator' => '-------------------', - 'empty_value' => null, + 'placeholder' => null, )); // The decision, whether a choice is selected, is potentially done @@ -119,13 +119,17 @@ public function buildView(FormView $view, FormInterface $form, array $options) } // Check if the choices already contain the empty value - $view->vars['empty_value_in_choices'] = 0 !== count($options['choice_list']->getChoicesForValues(array(''))); + $view->vars['placeholder_in_choices'] = 0 !== count($options['choice_list']->getChoicesForValues(array(''))); // Only add the empty value option if this is not the case - if (null !== $options['empty_value'] && !$view->vars['empty_value_in_choices']) { - $view->vars['empty_value'] = $options['empty_value']; + if (null !== $options['placeholder'] && !$view->vars['placeholder_in_choices']) { + $view->vars['placeholder'] = $options['placeholder']; } + // BC + $view->vars['empty_value'] = $view->vars['placeholder']; + $view->vars['empty_value_in_choices'] = $view->vars['placeholder_in_choices']; + if ($options['multiple'] && !$options['expanded']) { // Add "[]" to the name in case a select tag with multiple options is // displayed. Otherwise only one of the selected options is sent in the @@ -187,20 +191,25 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) return $options['required'] ? null : ''; }; - $emptyValueNormalizer = function (Options $options, $emptyValue) { + // for BC with the "empty_value" option + $placeholder = function (Options $options) { + return $options['empty_value']; + }; + + $placeholderNormalizer = function (Options $options, $placeholder) { if ($options['multiple']) { // never use an empty value for this case return; - } elseif (false === $emptyValue) { + } elseif (false === $placeholder) { // an empty value should be added but the user decided otherwise return; - } elseif ($options['expanded'] && '' === $emptyValue) { + } elseif ($options['expanded'] && '' === $placeholder) { // never use an empty label for radio buttons return 'None'; } // empty value has been set explicitly - return $emptyValue; + return $placeholder; }; $compound = function (Options $options) { @@ -214,7 +223,8 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'choices' => array(), 'preferred_choices' => array(), 'empty_data' => $emptyData, - 'empty_value' => $emptyValue, + 'empty_value' => $emptyValue, // deprecated + 'placeholder' => $placeholder, 'error_bubbling' => false, 'compound' => $compound, // The view data is always a string, even if the "data" option @@ -224,7 +234,8 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) )); $resolver->setNormalizers(array( - 'empty_value' => $emptyValueNormalizer, + 'empty_value' => $placeholderNormalizer, + 'placeholder' => $placeholderNormalizer, )); $resolver->setAllowedTypes(array( diff --git a/Extension/Core/Type/DateTimeType.php b/Extension/Core/Type/DateTimeType.php index cad1c5e8d5..27f1c06a25 100644 --- a/Extension/Core/Type/DateTimeType.php +++ b/Extension/Core/Type/DateTimeType.php @@ -115,6 +115,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'months', 'days', 'empty_value', + 'placeholder', 'required', 'translation_domain', 'html5', @@ -127,6 +128,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'with_minutes', 'with_seconds', 'empty_value', + 'placeholder', 'required', 'translation_domain', 'html5', @@ -237,7 +239,8 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) // Don't add some defaults in order to preserve the defaults // set in DateType and TimeType $resolver->setOptional(array( - 'empty_value', + 'empty_value', // deprecated + 'placeholder', 'years', 'months', 'days', diff --git a/Extension/Core/Type/DateType.php b/Extension/Core/Type/DateType.php index 35657742e5..db33340539 100644 --- a/Extension/Core/Type/DateType.php +++ b/Extension/Core/Type/DateType.php @@ -88,11 +88,11 @@ public function buildForm(FormBuilderInterface $builder, array $options) if ('choice' === $options['widget']) { // Only pass a subset of the options to children $yearOptions['choices'] = $this->formatTimestamps($formatter, '/y+/', $this->listYears($options['years'])); - $yearOptions['empty_value'] = $options['empty_value']['year']; + $yearOptions['placeholder'] = $options['placeholder']['year']; $monthOptions['choices'] = $this->formatTimestamps($formatter, '/[M|L]+/', $this->listMonths($options['months'])); - $monthOptions['empty_value'] = $options['empty_value']['month']; + $monthOptions['placeholder'] = $options['placeholder']['month']; $dayOptions['choices'] = $this->formatTimestamps($formatter, '/d+/', $this->listDays($options['days'])); - $dayOptions['empty_value'] = $options['empty_value']['day']; + $dayOptions['placeholder'] = $options['placeholder']['day']; } // Append generic carry-along options @@ -171,24 +171,28 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) return $options['widget'] !== 'single_text'; }; - $emptyValue = $emptyValueDefault = function (Options $options) { + $emptyValue = $placeholderDefault = function (Options $options) { return $options['required'] ? null : ''; }; - $emptyValueNormalizer = function (Options $options, $emptyValue) use ($emptyValueDefault) { - if (is_array($emptyValue)) { - $default = $emptyValueDefault($options); + $placeholder = function (Options $options) { + return $options['empty_value']; + }; + + $placeholderNormalizer = function (Options $options, $placeholder) use ($placeholderDefault) { + if (is_array($placeholder)) { + $default = $placeholderDefault($options); return array_merge( array('year' => $default, 'month' => $default, 'day' => $default), - $emptyValue + $placeholder ); } return array( - 'year' => $emptyValue, - 'month' => $emptyValue, - 'day' => $emptyValue, + 'year' => $placeholder, + 'month' => $placeholder, + 'day' => $placeholder, ); }; @@ -205,7 +209,8 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'format' => $format, 'model_timezone' => null, 'view_timezone' => null, - 'empty_value' => $emptyValue, + 'empty_value' => $emptyValue, // deprecated + 'placeholder' => $placeholder, 'html5' => true, // Don't modify \DateTime classes by reference, we treat // them like immutable value objects @@ -220,7 +225,8 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) )); $resolver->setNormalizers(array( - 'empty_value' => $emptyValueNormalizer, + 'empty_value' => $placeholderNormalizer, + 'placeholder' => $placeholderNormalizer, )); $resolver->setAllowedValues(array( diff --git a/Extension/Core/Type/TimeType.php b/Extension/Core/Type/TimeType.php index 223c3d9289..7b38fc49ab 100644 --- a/Extension/Core/Type/TimeType.php +++ b/Extension/Core/Type/TimeType.php @@ -63,7 +63,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) // Only pass a subset of the options to children $hourOptions['choices'] = $hours; - $hourOptions['empty_value'] = $options['empty_value']['hour']; + $hourOptions['placeholder'] = $options['placeholder']['hour']; if ($options['with_minutes']) { foreach ($options['minutes'] as $minute) { @@ -71,7 +71,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) } $minuteOptions['choices'] = $minutes; - $minuteOptions['empty_value'] = $options['empty_value']['minute']; + $minuteOptions['placeholder'] = $options['placeholder']['minute']; } if ($options['with_seconds']) { @@ -82,7 +82,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) } $secondOptions['choices'] = $seconds; - $secondOptions['empty_value'] = $options['empty_value']['second']; + $secondOptions['placeholder'] = $options['placeholder']['second']; } // Append generic carry-along options @@ -163,24 +163,29 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) return $options['widget'] !== 'single_text'; }; - $emptyValue = $emptyValueDefault = function (Options $options) { + $emptyValue = $placeholderDefault = function (Options $options) { return $options['required'] ? null : ''; }; - $emptyValueNormalizer = function (Options $options, $emptyValue) use ($emptyValueDefault) { - if (is_array($emptyValue)) { - $default = $emptyValueDefault($options); + // for BC with the "empty_value" option + $placeholder = function (Options $options) { + return $options['empty_value']; + }; + + $placeholderNormalizer = function (Options $options, $placeholder) use ($placeholderDefault) { + if (is_array($placeholder)) { + $default = $placeholderDefault($options); return array_merge( array('hour' => $default, 'minute' => $default, 'second' => $default), - $emptyValue + $placeholder ); } return array( - 'hour' => $emptyValue, - 'minute' => $emptyValue, - 'second' => $emptyValue, + 'hour' => $placeholder, + 'minute' => $placeholder, + 'second' => $placeholder, ); }; @@ -194,7 +199,8 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'with_seconds' => false, 'model_timezone' => null, 'view_timezone' => null, - 'empty_value' => $emptyValue, + 'empty_value' => $emptyValue, // deprecated + 'placeholder' => $placeholder, 'html5' => true, // Don't modify \DateTime classes by reference, we treat // them like immutable value objects @@ -209,7 +215,8 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) )); $resolver->setNormalizers(array( - 'empty_value' => $emptyValueNormalizer, + 'empty_value' => $placeholderNormalizer, + 'placeholder' => $placeholderNormalizer, )); $resolver->setAllowedValues(array( diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index a46fecd7aa..4755e208e9 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -525,14 +525,14 @@ public function testSingleChoiceNonRequiredNoneSelected() ); } - public function testSingleChoiceWithNonRequiredEmptyValue() + public function testSingleChoiceNonRequiredWithPlaceholder() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'multiple' => false, 'expanded' => false, 'required' => false, - 'empty_value' => 'Select&Anything&Not&Me', + 'placeholder' => 'Select&Anything&Not&Me', )); $this->assertWidgetMatchesXpath($form->createView(), array(), @@ -549,14 +549,14 @@ public function testSingleChoiceWithNonRequiredEmptyValue() ); } - public function testSingleChoiceRequiredWithEmptyValue() + public function testSingleChoiceRequiredWithPlaceholder() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'required' => true, 'multiple' => false, 'expanded' => false, - 'empty_value' => 'Test&Me', + 'placeholder' => 'Test&Me', )); // The "disabled" attribute was removed again due to a bug in the @@ -576,7 +576,7 @@ public function testSingleChoiceRequiredWithEmptyValue() ); } - public function testSingleChoiceRequiredWithEmptyValueViaView() + public function testSingleChoiceRequiredWithPlaceholderViaView() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), @@ -588,7 +588,7 @@ public function testSingleChoiceRequiredWithEmptyValueViaView() // The "disabled" attribute was removed again due to a bug in the // BlackBerry 10 browser. // See https://github.com/symfony/symfony/pull/7678 - $this->assertWidgetMatchesXpath($form->createView(), array('empty_value' => ''), + $this->assertWidgetMatchesXpath($form->createView(), array('placeholder' => ''), '/select [@name="name"] [@required="required"] @@ -655,13 +655,13 @@ public function testMultipleChoice() ); } - public function testMultipleChoiceSkipsEmptyValue() + public function testMultipleChoiceSkipsPlaceholder() { $form = $this->factory->createNamed('name', 'choice', array('&a'), array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'multiple' => true, 'expanded' => false, - 'empty_value' => 'Test&Me', + 'placeholder' => 'Test&Me', )); $this->assertWidgetMatchesXpath($form->createView(), array(), @@ -721,13 +721,13 @@ public function testSingleChoiceExpanded() ); } - public function testSingleChoiceExpandedWithEmptyValue() + public function testSingleChoiceExpandedWithPlaceholder() { $form = $this->factory->createNamed('name', 'choice', '&a', array( 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), 'multiple' => false, 'expanded' => true, - 'empty_value' => 'Test&Me', + 'placeholder' => 'Test&Me', )); $this->assertWidgetMatchesXpath($form->createView(), array(), @@ -806,10 +806,10 @@ public function testCountry() ); } - public function testCountryWithEmptyValue() + public function testCountryWithPlaceholder() { $form = $this->factory->createNamed('name', 'country', 'AT', array( - 'empty_value' => 'Select&Country', + 'placeholder' => 'Select&Country', 'required' => false, )); @@ -862,11 +862,11 @@ public function testDateTime() ); } - public function testDateTimeWithEmptyValueGlobal() + public function testDateTimeWithPlaceholderGlobal() { $form = $this->factory->createNamed('name', 'datetime', null, array( 'input' => 'string', - 'empty_value' => 'Change&Me', + 'placeholder' => 'Change&Me', 'required' => false, )); @@ -1074,12 +1074,12 @@ public function testDateChoice() ); } - public function testDateChoiceWithEmptyValueGlobal() + public function testDateChoiceWithPlaceholderGlobal() { $form = $this->factory->createNamed('name', 'date', null, array( 'input' => 'string', 'widget' => 'choice', - 'empty_value' => 'Change&Me', + 'placeholder' => 'Change&Me', 'required' => false, )); @@ -1101,13 +1101,13 @@ public function testDateChoiceWithEmptyValueGlobal() ); } - public function testDateChoiceWithEmptyValueOnYear() + public function testDateChoiceWithPlaceholderOnYear() { $form = $this->factory->createNamed('name', 'date', null, array( 'input' => 'string', 'widget' => 'choice', 'required' => false, - 'empty_value' => array('year' => 'Change&Me'), + 'placeholder' => array('year' => 'Change&Me'), )); $this->assertWidgetMatchesXpath($form->createView(), array(), @@ -1208,11 +1208,11 @@ public function testBirthDay() ); } - public function testBirthDayWithEmptyValue() + public function testBirthDayWithPlaceholder() { $form = $this->factory->createNamed('name', 'birthday', '1950-01-01', array( 'input' => 'string', - 'empty_value' => '', + 'placeholder' => '', 'required' => false, )); @@ -1649,11 +1649,11 @@ public function testTimeSingleText() ); } - public function testTimeWithEmptyValueGlobal() + public function testTimeWithPlaceholderGlobal() { $form = $this->factory->createNamed('name', 'time', null, array( 'input' => 'string', - 'empty_value' => 'Change&Me', + 'placeholder' => 'Change&Me', 'required' => false, )); @@ -1674,12 +1674,12 @@ public function testTimeWithEmptyValueGlobal() ); } - public function testTimeWithEmptyValueOnYear() + public function testTimeWithPlaceholderOnYear() { $form = $this->factory->createNamed('name', 'time', null, array( 'input' => 'string', 'required' => false, - 'empty_value' => array('hour' => 'Change&Me'), + 'placeholder' => array('hour' => 'Change&Me'), )); $this->assertWidgetMatchesXpath($form->createView(), array(), @@ -1729,10 +1729,10 @@ public function testTimezone() ); } - public function testTimezoneWithEmptyValue() + public function testTimezoneWithPlaceholder() { $form = $this->factory->createNamed('name', 'timezone', null, array( - 'empty_value' => 'Select&Timezone', + 'placeholder' => 'Select&Timezone', 'required' => false, )); diff --git a/Tests/Extension/Core/Type/ChoiceTypeTest.php b/Tests/Extension/Core/Type/ChoiceTypeTest.php index 0f100f24ea..cf1ea2a4f0 100644 --- a/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -1011,7 +1011,7 @@ public function testPassExpandedToView() $this->assertTrue($view->vars['expanded']); } - public function testEmptyValueIsNullByDefaultIfRequired() + public function testPlaceholderIsNullByDefaultIfRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => false, @@ -1020,10 +1020,10 @@ public function testEmptyValueIsNullByDefaultIfRequired() )); $view = $form->createView(); - $this->assertNull($view->vars['empty_value']); + $this->assertNull($view->vars['placeholder']); } - public function testEmptyValueIsEmptyStringByDefaultIfNotRequired() + public function testPlaceholderIsEmptyStringByDefaultIfNotRequired() { $form = $this->factory->create('choice', null, array( 'multiple' => false, @@ -1032,46 +1032,66 @@ public function testEmptyValueIsEmptyStringByDefaultIfNotRequired() )); $view = $form->createView(); - $this->assertSame('', $view->vars['empty_value']); + $this->assertSame('', $view->vars['placeholder']); } /** - * @dataProvider getOptionsWithEmptyValue + * @dataProvider getOptionsWithPlaceholder */ - public function testPassEmptyValueToView($multiple, $expanded, $required, $emptyValue, $viewValue) + public function testPassPlaceholderToView($multiple, $expanded, $required, $placeholder, $viewValue) { $form = $this->factory->create('choice', null, array( 'multiple' => $multiple, 'expanded' => $expanded, 'required' => $required, - 'empty_value' => $emptyValue, + 'placeholder' => $placeholder, 'choices' => $this->choices, )); $view = $form->createView(); + $this->assertEquals($viewValue, $view->vars['placeholder']); + $this->assertFalse($view->vars['placeholder_in_choices']); + } + + /** + * @dataProvider getOptionsWithPlaceholder + */ + public function testPassEmptyValueBC($multiple, $expanded, $required, $placeholder, $viewValue) + { + $form = $this->factory->create('choice', null, array( + 'multiple' => $multiple, + 'expanded' => $expanded, + 'required' => $required, + 'empty_value' => $placeholder, + 'choices' => $this->choices, + )); + $view = $form->createView(); + + $this->assertEquals($viewValue, $view->vars['placeholder']); + $this->assertFalse($view->vars['placeholder_in_choices']); $this->assertEquals($viewValue, $view->vars['empty_value']); $this->assertFalse($view->vars['empty_value_in_choices']); } /** - * @dataProvider getOptionsWithEmptyValue + * @dataProvider getOptionsWithPlaceholder */ - public function testDontPassEmptyValueIfContainedInChoices($multiple, $expanded, $required, $emptyValue, $viewValue) + public function testDontPassPlaceholderIfContainedInChoices($multiple, $expanded, $required, $placeholder, $viewValue) { $form = $this->factory->create('choice', null, array( 'multiple' => $multiple, 'expanded' => $expanded, 'required' => $required, - 'empty_value' => $emptyValue, + 'placeholder' => $placeholder, 'choices' => array('a' => 'A', '' => 'Empty'), )); $view = $form->createView(); - $this->assertNull($view->vars['empty_value']); - $this->assertTrue($view->vars['empty_value_in_choices']); + $this->assertNull($view->vars['placeholder']); + $this->assertTrue($view->vars['placeholder_in_choices']); } - public function getOptionsWithEmptyValue() + public function getOptionsWithPlaceholder() { return array( // single non-expanded diff --git a/Tests/Extension/Core/Type/DateTimeTypeTest.php b/Tests/Extension/Core/Type/DateTimeTypeTest.php index e45f6134e8..933d94b035 100644 --- a/Tests/Extension/Core/Type/DateTimeTypeTest.php +++ b/Tests/Extension/Core/Type/DateTimeTypeTest.php @@ -280,7 +280,7 @@ public function testSingleTextWidgetShouldUseTheRightInputType() $this->assertEquals('datetime', $view->vars['type']); } - public function testPassDefaultEmptyValueToViewIfNotRequired() + public function testPassDefaultPlaceholderToViewIfNotRequired() { $form = $this->factory->create('datetime', null, array( 'required' => false, @@ -288,15 +288,15 @@ public function testPassDefaultEmptyValueToViewIfNotRequired() )); $view = $form->createView(); - $this->assertSame('', $view['date']['year']->vars['empty_value']); - $this->assertSame('', $view['date']['month']->vars['empty_value']); - $this->assertSame('', $view['date']['day']->vars['empty_value']); - $this->assertSame('', $view['time']['hour']->vars['empty_value']); - $this->assertSame('', $view['time']['minute']->vars['empty_value']); - $this->assertSame('', $view['time']['second']->vars['empty_value']); + $this->assertSame('', $view['date']['year']->vars['placeholder']); + $this->assertSame('', $view['date']['month']->vars['placeholder']); + $this->assertSame('', $view['date']['day']->vars['placeholder']); + $this->assertSame('', $view['time']['hour']->vars['placeholder']); + $this->assertSame('', $view['time']['minute']->vars['placeholder']); + $this->assertSame('', $view['time']['second']->vars['placeholder']); } - public function testPassNoEmptyValueToViewIfRequired() + public function testPassNoPlaceholderToViewIfRequired() { $form = $this->factory->create('datetime', null, array( 'required' => true, @@ -304,15 +304,31 @@ public function testPassNoEmptyValueToViewIfRequired() )); $view = $form->createView(); - $this->assertNull($view['date']['year']->vars['empty_value']); - $this->assertNull($view['date']['month']->vars['empty_value']); - $this->assertNull($view['date']['day']->vars['empty_value']); - $this->assertNull($view['time']['hour']->vars['empty_value']); - $this->assertNull($view['time']['minute']->vars['empty_value']); - $this->assertNull($view['time']['second']->vars['empty_value']); + $this->assertNull($view['date']['year']->vars['placeholder']); + $this->assertNull($view['date']['month']->vars['placeholder']); + $this->assertNull($view['date']['day']->vars['placeholder']); + $this->assertNull($view['time']['hour']->vars['placeholder']); + $this->assertNull($view['time']['minute']->vars['placeholder']); + $this->assertNull($view['time']['second']->vars['placeholder']); } - public function testPassEmptyValueAsString() + public function testPassPlaceholderAsString() + { + $form = $this->factory->create('datetime', null, array( + 'placeholder' => 'Empty', + 'with_seconds' => true, + )); + + $view = $form->createView(); + $this->assertSame('Empty', $view['date']['year']->vars['placeholder']); + $this->assertSame('Empty', $view['date']['month']->vars['placeholder']); + $this->assertSame('Empty', $view['date']['day']->vars['placeholder']); + $this->assertSame('Empty', $view['time']['hour']->vars['placeholder']); + $this->assertSame('Empty', $view['time']['minute']->vars['placeholder']); + $this->assertSame('Empty', $view['time']['second']->vars['placeholder']); + } + + public function testPassEmptyValueBC() { $form = $this->factory->create('datetime', null, array( 'empty_value' => 'Empty', @@ -320,6 +336,12 @@ public function testPassEmptyValueAsString() )); $view = $form->createView(); + $this->assertSame('Empty', $view['date']['year']->vars['placeholder']); + $this->assertSame('Empty', $view['date']['month']->vars['placeholder']); + $this->assertSame('Empty', $view['date']['day']->vars['placeholder']); + $this->assertSame('Empty', $view['time']['hour']->vars['placeholder']); + $this->assertSame('Empty', $view['time']['minute']->vars['placeholder']); + $this->assertSame('Empty', $view['time']['second']->vars['placeholder']); $this->assertSame('Empty', $view['date']['year']->vars['empty_value']); $this->assertSame('Empty', $view['date']['month']->vars['empty_value']); $this->assertSame('Empty', $view['date']['day']->vars['empty_value']); @@ -328,10 +350,10 @@ public function testPassEmptyValueAsString() $this->assertSame('Empty', $view['time']['second']->vars['empty_value']); } - public function testPassEmptyValueAsArray() + public function testPassPlaceholderAsArray() { $form = $this->factory->create('datetime', null, array( - 'empty_value' => array( + 'placeholder' => array( 'year' => 'Empty year', 'month' => 'Empty month', 'day' => 'Empty day', @@ -343,19 +365,19 @@ public function testPassEmptyValueAsArray() )); $view = $form->createView(); - $this->assertSame('Empty year', $view['date']['year']->vars['empty_value']); - $this->assertSame('Empty month', $view['date']['month']->vars['empty_value']); - $this->assertSame('Empty day', $view['date']['day']->vars['empty_value']); - $this->assertSame('Empty hour', $view['time']['hour']->vars['empty_value']); - $this->assertSame('Empty minute', $view['time']['minute']->vars['empty_value']); - $this->assertSame('Empty second', $view['time']['second']->vars['empty_value']); + $this->assertSame('Empty year', $view['date']['year']->vars['placeholder']); + $this->assertSame('Empty month', $view['date']['month']->vars['placeholder']); + $this->assertSame('Empty day', $view['date']['day']->vars['placeholder']); + $this->assertSame('Empty hour', $view['time']['hour']->vars['placeholder']); + $this->assertSame('Empty minute', $view['time']['minute']->vars['placeholder']); + $this->assertSame('Empty second', $view['time']['second']->vars['placeholder']); } - public function testPassEmptyValueAsPartialArrayAddEmptyIfNotRequired() + public function testPassPlaceholderAsPartialArrayAddEmptyIfNotRequired() { $form = $this->factory->create('datetime', null, array( 'required' => false, - 'empty_value' => array( + 'placeholder' => array( 'year' => 'Empty year', 'day' => 'Empty day', 'hour' => 'Empty hour', @@ -365,19 +387,19 @@ public function testPassEmptyValueAsPartialArrayAddEmptyIfNotRequired() )); $view = $form->createView(); - $this->assertSame('Empty year', $view['date']['year']->vars['empty_value']); - $this->assertSame('', $view['date']['month']->vars['empty_value']); - $this->assertSame('Empty day', $view['date']['day']->vars['empty_value']); - $this->assertSame('Empty hour', $view['time']['hour']->vars['empty_value']); - $this->assertSame('', $view['time']['minute']->vars['empty_value']); - $this->assertSame('Empty second', $view['time']['second']->vars['empty_value']); + $this->assertSame('Empty year', $view['date']['year']->vars['placeholder']); + $this->assertSame('', $view['date']['month']->vars['placeholder']); + $this->assertSame('Empty day', $view['date']['day']->vars['placeholder']); + $this->assertSame('Empty hour', $view['time']['hour']->vars['placeholder']); + $this->assertSame('', $view['time']['minute']->vars['placeholder']); + $this->assertSame('Empty second', $view['time']['second']->vars['placeholder']); } - public function testPassEmptyValueAsPartialArrayAddNullIfRequired() + public function testPassPlaceholderAsPartialArrayAddNullIfRequired() { $form = $this->factory->create('datetime', null, array( 'required' => true, - 'empty_value' => array( + 'placeholder' => array( 'year' => 'Empty year', 'day' => 'Empty day', 'hour' => 'Empty hour', @@ -387,12 +409,12 @@ public function testPassEmptyValueAsPartialArrayAddNullIfRequired() )); $view = $form->createView(); - $this->assertSame('Empty year', $view['date']['year']->vars['empty_value']); - $this->assertNull($view['date']['month']->vars['empty_value']); - $this->assertSame('Empty day', $view['date']['day']->vars['empty_value']); - $this->assertSame('Empty hour', $view['time']['hour']->vars['empty_value']); - $this->assertNull($view['time']['minute']->vars['empty_value']); - $this->assertSame('Empty second', $view['time']['second']->vars['empty_value']); + $this->assertSame('Empty year', $view['date']['year']->vars['placeholder']); + $this->assertNull($view['date']['month']->vars['placeholder']); + $this->assertSame('Empty day', $view['date']['day']->vars['placeholder']); + $this->assertSame('Empty hour', $view['time']['hour']->vars['placeholder']); + $this->assertNull($view['time']['minute']->vars['placeholder']); + $this->assertSame('Empty second', $view['time']['second']->vars['placeholder']); } public function testPassHtml5TypeIfSingleTextAndHtml5Format() diff --git a/Tests/Extension/Core/Type/DateTypeTest.php b/Tests/Extension/Core/Type/DateTypeTest.php index 28e681a28c..883b7bb45d 100644 --- a/Tests/Extension/Core/Type/DateTypeTest.php +++ b/Tests/Extension/Core/Type/DateTypeTest.php @@ -611,46 +611,61 @@ public function testSingleTextWidgetShouldUseTheRightInputType() $this->assertEquals('date', $view->vars['type']); } - public function testPassDefaultEmptyValueToViewIfNotRequired() + public function testPassDefaultPlaceholderToViewIfNotRequired() { $form = $this->factory->create('date', null, array( 'required' => false, )); $view = $form->createView(); - $this->assertSame('', $view['year']->vars['empty_value']); - $this->assertSame('', $view['month']->vars['empty_value']); - $this->assertSame('', $view['day']->vars['empty_value']); + $this->assertSame('', $view['year']->vars['placeholder']); + $this->assertSame('', $view['month']->vars['placeholder']); + $this->assertSame('', $view['day']->vars['placeholder']); } - public function testPassNoEmptyValueToViewIfRequired() + public function testPassNoPlaceholderToViewIfRequired() { $form = $this->factory->create('date', null, array( 'required' => true, )); $view = $form->createView(); - $this->assertNull($view['year']->vars['empty_value']); - $this->assertNull($view['month']->vars['empty_value']); - $this->assertNull($view['day']->vars['empty_value']); + $this->assertNull($view['year']->vars['placeholder']); + $this->assertNull($view['month']->vars['placeholder']); + $this->assertNull($view['day']->vars['placeholder']); } - public function testPassEmptyValueAsString() + public function testPassPlaceholderAsString() + { + $form = $this->factory->create('date', null, array( + 'placeholder' => 'Empty', + )); + + $view = $form->createView(); + $this->assertSame('Empty', $view['year']->vars['placeholder']); + $this->assertSame('Empty', $view['month']->vars['placeholder']); + $this->assertSame('Empty', $view['day']->vars['placeholder']); + } + + public function testPassEmptyValueBC() { $form = $this->factory->create('date', null, array( 'empty_value' => 'Empty', )); $view = $form->createView(); + $this->assertSame('Empty', $view['year']->vars['placeholder']); + $this->assertSame('Empty', $view['month']->vars['placeholder']); + $this->assertSame('Empty', $view['day']->vars['placeholder']); $this->assertSame('Empty', $view['year']->vars['empty_value']); $this->assertSame('Empty', $view['month']->vars['empty_value']); $this->assertSame('Empty', $view['day']->vars['empty_value']); } - public function testPassEmptyValueAsArray() + public function testPassPlaceholderAsArray() { $form = $this->factory->create('date', null, array( - 'empty_value' => array( + 'placeholder' => array( 'year' => 'Empty year', 'month' => 'Empty month', 'day' => 'Empty day', @@ -658,41 +673,41 @@ public function testPassEmptyValueAsArray() )); $view = $form->createView(); - $this->assertSame('Empty year', $view['year']->vars['empty_value']); - $this->assertSame('Empty month', $view['month']->vars['empty_value']); - $this->assertSame('Empty day', $view['day']->vars['empty_value']); + $this->assertSame('Empty year', $view['year']->vars['placeholder']); + $this->assertSame('Empty month', $view['month']->vars['placeholder']); + $this->assertSame('Empty day', $view['day']->vars['placeholder']); } - public function testPassEmptyValueAsPartialArrayAddEmptyIfNotRequired() + public function testPassPlaceholderAsPartialArrayAddEmptyIfNotRequired() { $form = $this->factory->create('date', null, array( 'required' => false, - 'empty_value' => array( + 'placeholder' => array( 'year' => 'Empty year', 'day' => 'Empty day', ), )); $view = $form->createView(); - $this->assertSame('Empty year', $view['year']->vars['empty_value']); - $this->assertSame('', $view['month']->vars['empty_value']); - $this->assertSame('Empty day', $view['day']->vars['empty_value']); + $this->assertSame('Empty year', $view['year']->vars['placeholder']); + $this->assertSame('', $view['month']->vars['placeholder']); + $this->assertSame('Empty day', $view['day']->vars['placeholder']); } - public function testPassEmptyValueAsPartialArrayAddNullIfRequired() + public function testPassPlaceholderAsPartialArrayAddNullIfRequired() { $form = $this->factory->create('date', null, array( 'required' => true, - 'empty_value' => array( + 'placeholder' => array( 'year' => 'Empty year', 'day' => 'Empty day', ), )); $view = $form->createView(); - $this->assertSame('Empty year', $view['year']->vars['empty_value']); - $this->assertNull($view['month']->vars['empty_value']); - $this->assertSame('Empty day', $view['day']->vars['empty_value']); + $this->assertSame('Empty year', $view['year']->vars['placeholder']); + $this->assertNull($view['month']->vars['placeholder']); + $this->assertSame('Empty day', $view['day']->vars['placeholder']); } public function testPassHtml5TypeIfSingleTextAndHtml5Format() diff --git a/Tests/Extension/Core/Type/TimeTypeTest.php b/Tests/Extension/Core/Type/TimeTypeTest.php index d74dc69ace..5d257a03c6 100644 --- a/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/Tests/Extension/Core/Type/TimeTypeTest.php @@ -530,7 +530,7 @@ public function testDontPassHtml5TypeIfHtml5NotAllowed() $this->assertFalse(isset($view->vars['type'])); } - public function testPassDefaultEmptyValueToViewIfNotRequired() + public function testPassDefaultPlaceholderToViewIfNotRequired() { $form = $this->factory->create('time', null, array( 'required' => false, @@ -538,12 +538,12 @@ public function testPassDefaultEmptyValueToViewIfNotRequired() )); $view = $form->createView(); - $this->assertSame('', $view['hour']->vars['empty_value']); - $this->assertSame('', $view['minute']->vars['empty_value']); - $this->assertSame('', $view['second']->vars['empty_value']); + $this->assertSame('', $view['hour']->vars['placeholder']); + $this->assertSame('', $view['minute']->vars['placeholder']); + $this->assertSame('', $view['second']->vars['placeholder']); } - public function testPassNoEmptyValueToViewIfRequired() + public function testPassNoPlaceholderToViewIfRequired() { $form = $this->factory->create('time', null, array( 'required' => true, @@ -551,12 +551,25 @@ public function testPassNoEmptyValueToViewIfRequired() )); $view = $form->createView(); - $this->assertNull($view['hour']->vars['empty_value']); - $this->assertNull($view['minute']->vars['empty_value']); - $this->assertNull($view['second']->vars['empty_value']); + $this->assertNull($view['hour']->vars['placeholder']); + $this->assertNull($view['minute']->vars['placeholder']); + $this->assertNull($view['second']->vars['placeholder']); } - public function testPassEmptyValueAsString() + public function testPassPlaceholderAsString() + { + $form = $this->factory->create('time', null, array( + 'placeholder' => 'Empty', + 'with_seconds' => true, + )); + + $view = $form->createView(); + $this->assertSame('Empty', $view['hour']->vars['placeholder']); + $this->assertSame('Empty', $view['minute']->vars['placeholder']); + $this->assertSame('Empty', $view['second']->vars['placeholder']); + } + + public function testPassEmptyValueBC() { $form = $this->factory->create('time', null, array( 'empty_value' => 'Empty', @@ -564,15 +577,18 @@ public function testPassEmptyValueAsString() )); $view = $form->createView(); + $this->assertSame('Empty', $view['hour']->vars['placeholder']); + $this->assertSame('Empty', $view['minute']->vars['placeholder']); + $this->assertSame('Empty', $view['second']->vars['placeholder']); $this->assertSame('Empty', $view['hour']->vars['empty_value']); $this->assertSame('Empty', $view['minute']->vars['empty_value']); $this->assertSame('Empty', $view['second']->vars['empty_value']); } - public function testPassEmptyValueAsArray() + public function testPassPlaceholderAsArray() { $form = $this->factory->create('time', null, array( - 'empty_value' => array( + 'placeholder' => array( 'hour' => 'Empty hour', 'minute' => 'Empty minute', 'second' => 'Empty second', @@ -581,16 +597,16 @@ public function testPassEmptyValueAsArray() )); $view = $form->createView(); - $this->assertSame('Empty hour', $view['hour']->vars['empty_value']); - $this->assertSame('Empty minute', $view['minute']->vars['empty_value']); - $this->assertSame('Empty second', $view['second']->vars['empty_value']); + $this->assertSame('Empty hour', $view['hour']->vars['placeholder']); + $this->assertSame('Empty minute', $view['minute']->vars['placeholder']); + $this->assertSame('Empty second', $view['second']->vars['placeholder']); } - public function testPassEmptyValueAsPartialArrayAddEmptyIfNotRequired() + public function testPassPlaceholderAsPartialArrayAddEmptyIfNotRequired() { $form = $this->factory->create('time', null, array( 'required' => false, - 'empty_value' => array( + 'placeholder' => array( 'hour' => 'Empty hour', 'second' => 'Empty second', ), @@ -598,16 +614,16 @@ public function testPassEmptyValueAsPartialArrayAddEmptyIfNotRequired() )); $view = $form->createView(); - $this->assertSame('Empty hour', $view['hour']->vars['empty_value']); - $this->assertSame('', $view['minute']->vars['empty_value']); - $this->assertSame('Empty second', $view['second']->vars['empty_value']); + $this->assertSame('Empty hour', $view['hour']->vars['placeholder']); + $this->assertSame('', $view['minute']->vars['placeholder']); + $this->assertSame('Empty second', $view['second']->vars['placeholder']); } - public function testPassEmptyValueAsPartialArrayAddNullIfRequired() + public function testPassPlaceholderAsPartialArrayAddNullIfRequired() { $form = $this->factory->create('time', null, array( 'required' => true, - 'empty_value' => array( + 'placeholder' => array( 'hour' => 'Empty hour', 'second' => 'Empty second', ), @@ -615,9 +631,9 @@ public function testPassEmptyValueAsPartialArrayAddNullIfRequired() )); $view = $form->createView(); - $this->assertSame('Empty hour', $view['hour']->vars['empty_value']); - $this->assertNull($view['minute']->vars['empty_value']); - $this->assertSame('Empty second', $view['second']->vars['empty_value']); + $this->assertSame('Empty hour', $view['hour']->vars['placeholder']); + $this->assertNull($view['minute']->vars['placeholder']); + $this->assertSame('Empty second', $view['second']->vars['placeholder']); } public function provideCompoundWidgets() From 4ba90e55a1303bcf31421f4223f272792da839f2 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Wed, 27 Feb 2013 12:10:38 +0100 Subject: [PATCH 338/447] [Form] Fixed ValidatorTypeGuesser to guess properties without constraints not to be required --- CHANGELOG.md | 3 +- Extension/Validator/ValidatorTypeGuesser.php | 6 +- .../Validator/ValidatorTypeGuesserTest.php | 106 ++++++++++++++---- 3 files changed, 89 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a696c7be9a..7d1f86281e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,8 @@ CHANGELOG ========= - 2.3.0 ------- +----- * deprecated FormPerformanceTestCase and FormIntegrationTestCase in the Symfony\Component\Form\Tests namespace and moved them to the Symfony\Component\Form\Test namespace * deprecated TypeTestCase in the Symfony\Component\Form\Tests\Extension\Core\Type namespace and moved it to the Symfony\Component\Form\Test namespace diff --git a/Extension/Validator/ValidatorTypeGuesser.php b/Extension/Validator/ValidatorTypeGuesser.php index 589fc12a36..8884629dc9 100644 --- a/Extension/Validator/ValidatorTypeGuesser.php +++ b/Extension/Validator/ValidatorTypeGuesser.php @@ -276,10 +276,10 @@ protected function guess($class, $property, \Closure $closure, $defaultValue = n } } } + } - if (null !== $defaultValue) { - $guesses[] = new ValueGuess($defaultValue, Guess::LOW_CONFIDENCE); - } + if (null !== $defaultValue) { + $guesses[] = new ValueGuess($defaultValue, Guess::LOW_CONFIDENCE); } return Guess::getBestGuess($guesses); diff --git a/Tests/Extension/Validator/ValidatorTypeGuesserTest.php b/Tests/Extension/Validator/ValidatorTypeGuesserTest.php index 090abf4486..0e3934bc9d 100644 --- a/Tests/Extension/Validator/ValidatorTypeGuesserTest.php +++ b/Tests/Extension/Validator/ValidatorTypeGuesserTest.php @@ -13,32 +13,91 @@ use Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser; use Symfony\Component\Form\Guess\Guess; +use Symfony\Component\Form\Guess\ValueGuess; +use Symfony\Component\Validator\Constraints\Email; use Symfony\Component\Validator\Constraints\Length; +use Symfony\Component\Validator\Constraints\NotBlank; +use Symfony\Component\Validator\Constraints\NotNull; +use Symfony\Component\Validator\Constraints\Range; +use Symfony\Component\Validator\Constraints\True; use Symfony\Component\Validator\Constraints\Type; +use Symfony\Component\Validator\Mapping\ClassMetadata; /** -* @author franek -*/ + * @author franek + * @author Bernhard Schussek + */ class ValidatorTypeGuesserTest extends \PHPUnit_Framework_TestCase { - private $typeGuesser; + const TEST_CLASS = 'Symfony\Component\Form\Tests\Extension\Validator\ValidatorTypeGuesserTest_TestClass'; + + const TEST_PROPERTY = 'property'; + + /** + * @var ValidatorTypeGuesser + */ + private $guesser; + + /** + * @var ClassMetadata + */ + private $metadata; + + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + private $metadataFactory; - public function setUp() + protected function setUp() { if (!class_exists('Symfony\Component\Validator\Constraint')) { $this->markTestSkipped('The "Validator" component is not available'); } - $metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface'); + $this->metadata = new ClassMetadata(self::TEST_CLASS); + $this->metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface'); + $this->metadataFactory->expects($this->any()) + ->method('getMetadataFor') + ->with(self::TEST_CLASS) + ->will($this->returnValue($this->metadata)); + $this->guesser = new ValidatorTypeGuesser($this->metadataFactory); + } + + public function guessRequiredProvider() + { + return array( + array(new NotNull(), new ValueGuess(true, Guess::HIGH_CONFIDENCE)), + array(new NotBlank(), new ValueGuess(true, Guess::HIGH_CONFIDENCE)), + array(new True(), new ValueGuess(true, Guess::HIGH_CONFIDENCE)), + array(new Length(10), new ValueGuess(false, Guess::LOW_CONFIDENCE)), + array(new Range(array('min' => 1, 'max' => 20)), new ValueGuess(false, Guess::LOW_CONFIDENCE)), + ); + } + + /** + * @dataProvider guessRequiredProvider + */ + public function testGuessRequired($constraint, $guess) + { + // add distracting constraint + $this->metadata->addPropertyConstraint(self::TEST_PROPERTY, new Email()); + + // add constraint under test + $this->metadata->addPropertyConstraint(self::TEST_PROPERTY, $constraint); - $this->typeGuesser = new ValidatorTypeGuesser($metadataFactory); + $this->assertEquals($guess, $this->guesser->guessRequired(self::TEST_CLASS, self::TEST_PROPERTY)); + } + + public function testGuessRequiredReturnsFalseForUnmappedProperties() + { + $this->assertEquals(new ValueGuess(false, Guess::LOW_CONFIDENCE), $this->guesser->guessRequired(self::TEST_CLASS, self::TEST_PROPERTY)); } public function testGuessMaxLengthForConstraintWithMaxValue() { $constraint = new Length(array('max' => '2')); - $result = $this->typeGuesser->guessMaxLengthForConstraint($constraint); + $result = $this->guesser->guessMaxLengthForConstraint($constraint); $this->assertInstanceOf('Symfony\Component\Form\Guess\ValueGuess', $result); $this->assertEquals(2, $result->getValue()); $this->assertEquals(Guess::HIGH_CONFIDENCE, $result->getConfidence()); @@ -48,30 +107,35 @@ public function testGuessMaxLengthForConstraintWithMinValue() { $constraint = new Length(array('min' => '2')); - $result = $this->typeGuesser->guessMaxLengthForConstraint($constraint); + $result = $this->guesser->guessMaxLengthForConstraint($constraint); $this->assertNull($result); } + public function maxLengthTypeProvider() + { + return array ( + array('double'), + array('float'), + array('numeric'), + array('real'), + ); + } + /** -* @dataProvider dataProviderTestGuessMaxLengthForConstraintWithType -*/ + * @dataProvider maxLengthTypeProvider + */ public function testGuessMaxLengthForConstraintWithType($type) { $constraint = new Type($type); - $result = $this->typeGuesser->guessMaxLengthForConstraint($constraint); + $result = $this->guesser->guessMaxLengthForConstraint($constraint); $this->assertInstanceOf('Symfony\Component\Form\Guess\ValueGuess', $result); - $this->assertEquals(null, $result->getValue()); + $this->assertNull($result->getValue()); $this->assertEquals(Guess::MEDIUM_CONFIDENCE, $result->getConfidence()); } +} - public static function dataProviderTestGuessMaxLengthForConstraintWithType() - { - return array ( - array('double'), - array('float'), - array('numeric'), - array('real'), - ); - } +class ValidatorTypeGuesserTest_TestClass +{ + private $property; } From 156991d92aef222c0f055c61cce0c26e43f7b407 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Wed, 24 Sep 2014 13:02:35 +0200 Subject: [PATCH 339/447] [Validator] Simplified testing of violations --- .../Constraints/FormValidatorTest.php | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index 8032d6273d..41c7439ba8 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -219,10 +219,12 @@ function () { throw new TransformationFailedException(); } $this->validator->validate($form, new Form()); - $this->assertViolation('invalid_message_key', array( - '{{ value }}' => 'foo', - '{{ foo }}' => 'bar', - ), 'property.path', 'foo', null, Form::ERR_INVALID); + $this->buildViolation('invalid_message_key') + ->setParameter('{{ value }}', 'foo') + ->setParameter('{{ foo }}', 'bar') + ->setInvalidValue('foo') + ->setCode(Form::ERR_INVALID) + ->assertRaised(); } public function testAddInvalidErrorEvenIfNoValidationGroups() @@ -251,10 +253,12 @@ function () { throw new TransformationFailedException(); } $this->validator->validate($form, new Form()); - $this->assertViolation('invalid_message_key', array( - '{{ value }}' => 'foo', - '{{ foo }}' => 'bar', - ), 'property.path', 'foo', null, Form::ERR_INVALID); + $this->buildViolation('invalid_message_key') + ->setParameter('{{ value }}', 'foo') + ->setParameter('{{ foo }}', 'bar') + ->setInvalidValue('foo') + ->setCode(Form::ERR_INVALID) + ->assertRaised(); } public function testDontValidateConstraintsIfNotSynchronized() @@ -283,9 +287,11 @@ function () { throw new TransformationFailedException(); } $this->validator->validate($form, new Form()); - $this->assertViolation('invalid_message_key', array( - '{{ value }}' => 'foo', - ), 'property.path','foo', null, Form::ERR_INVALID); + $this->buildViolation('invalid_message_key') + ->setParameter('{{ value }}', 'foo') + ->setInvalidValue('foo') + ->setCode(Form::ERR_INVALID) + ->assertRaised(); } // https://github.com/symfony/symfony/issues/4359 @@ -537,9 +543,10 @@ public function testViolationIfExtraData() $this->validator->validate($form, new Form()); - $this->assertViolation('Extra!', array( - '{{ extra_fields }}' => 'foo', - ), 'property.path', array('foo' => 'bar')); + $this->buildViolation('Extra!') + ->setParameter('{{ extra_fields }}', 'foo') + ->setInvalidValue(array('foo' => 'bar')) + ->assertRaised(); } /** From 1739ab42ae07b9798723c14c3c2e3db0495ad9d2 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 25 Sep 2014 11:23:31 +0200 Subject: [PATCH 340/447] [Form] Removed constructor argument from FormTypeHttpFoundationExtension for forward compatibility with 2.5 --- .../HttpFoundation/HttpFoundationExtension.php | 13 +------------ .../Type/FormTypeHttpFoundationExtension.php | 5 ++--- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/Extension/HttpFoundation/HttpFoundationExtension.php b/Extension/HttpFoundation/HttpFoundationExtension.php index 33e9c1c4d4..08bd89c9e4 100644 --- a/Extension/HttpFoundation/HttpFoundationExtension.php +++ b/Extension/HttpFoundation/HttpFoundationExtension.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Form\Extension\HttpFoundation; use Symfony\Component\Form\AbstractExtension; -use Symfony\Component\Form\Util\ServerParams; /** * Integrates the HttpFoundation component with the Form library. @@ -21,20 +20,10 @@ */ class HttpFoundationExtension extends AbstractExtension { - /** - * @var ServerParams - */ - private $serverParams; - - public function __construct(ServerParams $serverParams = null) - { - $this->serverParams = $serverParams; - } - protected function loadTypeExtensions() { return array( - new Type\FormTypeHttpFoundationExtension($this->serverParams), + new Type\FormTypeHttpFoundationExtension(), ); } } diff --git a/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php b/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php index 4596f06b98..9b09b05c39 100644 --- a/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php +++ b/Extension/HttpFoundation/Type/FormTypeHttpFoundationExtension.php @@ -15,7 +15,6 @@ use Symfony\Component\Form\Extension\HttpFoundation\EventListener\BindRequestListener; use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationRequestHandler; use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\Util\ServerParams; /** * @author Bernhard Schussek @@ -32,10 +31,10 @@ class FormTypeHttpFoundationExtension extends AbstractTypeExtension */ private $requestHandler; - public function __construct(ServerParams $serverParams = null) + public function __construct() { $this->listener = new BindRequestListener(); - $this->requestHandler = new HttpFoundationRequestHandler($serverParams); + $this->requestHandler = new HttpFoundationRequestHandler(); } /** From 108042fa585dafa4cca0df9d909fcbe949cf730b Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Wed, 24 Sep 2014 11:48:52 +0200 Subject: [PATCH 341/447] [Validator] Added ConstraintValidator::buildViolation() helper for BC with 2.4 API --- .../Validator/Constraints/FormValidator.php | 38 +++++-------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/Extension/Validator/Constraints/FormValidator.php b/Extension/Validator/Constraints/FormValidator.php index 2a6673cbc5..ab826f9c97 100644 --- a/Extension/Validator/Constraints/FormValidator.php +++ b/Extension/Validator/Constraints/FormValidator.php @@ -99,40 +99,20 @@ public function validate($form, Constraint $constraint) ? (string) $form->getViewData() : gettype($form->getViewData()); - if ($this->context instanceof ExecutionContextInterface) { - $this->context->buildViolation($config->getOption('invalid_message')) - ->setParameters(array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters'))) - ->setInvalidValue($form->getViewData()) - ->setCode(Form::ERR_INVALID) - ->addViolation(); - } else { - // 2.4 API - $this->context->addViolation( - $config->getOption('invalid_message'), - array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters')), - $form->getViewData(), - null, - Form::ERR_INVALID - ); - } + $this->buildViolation($config->getOption('invalid_message')) + ->setParameters(array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters'))) + ->setInvalidValue($form->getViewData()) + ->setCode(Form::ERR_INVALID) + ->addViolation(); } } // Mark the form with an error if it contains extra fields if (count($form->getExtraData()) > 0) { - if ($this->context instanceof ExecutionContextInterface) { - $this->context->buildViolation($config->getOption('extra_fields_message')) - ->setParameter('{{ extra_fields }}', implode('", "', array_keys($form->getExtraData()))) - ->setInvalidValue($form->getExtraData()) - ->addViolation(); - } else { - // 2.4 API - $this->context->addViolation( - $config->getOption('extra_fields_message'), - array('{{ extra_fields }}' => implode('", "', array_keys($form->getExtraData()))), - $form->getExtraData() - ); - } + $this->buildViolation($config->getOption('extra_fields_message')) + ->setParameter('{{ extra_fields }}', implode('", "', array_keys($form->getExtraData()))) + ->setInvalidValue($form->getExtraData()) + ->addViolation(); } } From 584a850b8c162cbc4f937739f8b195f2dd4b5483 Mon Sep 17 00:00:00 2001 From: Eric GELOEN Date: Wed, 6 Nov 2013 01:36:01 +0100 Subject: [PATCH 342/447] [Form][DateTime] Propagate invalid_message & invalid_message parameters to date & time sub widgets --- Extension/Core/Type/DateTimeType.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Extension/Core/Type/DateTimeType.php b/Extension/Core/Type/DateTimeType.php index a612b6fc9c..e8c4e748de 100644 --- a/Extension/Core/Type/DateTimeType.php +++ b/Extension/Core/Type/DateTimeType.php @@ -117,6 +117,8 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'empty_value', 'required', 'translation_domain', + 'invalid_message', + 'invalid_message_parameters', ))); $timeOptions = array_intersect_key($options, array_flip(array( @@ -128,6 +130,8 @@ public function buildForm(FormBuilderInterface $builder, array $options) 'empty_value', 'required', 'translation_domain', + 'invalid_message', + 'invalid_message_parameters', ))); if (null !== $options['date_widget']) { From 07f4556ce0398a609b14b2ee7a7d403765857709 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 26 Sep 2014 11:51:41 +0200 Subject: [PATCH 343/447] [Form] Added "label_format" option --- CHANGELOG.md | 1 + Extension/Core/Type/BaseType.php | 7 +++ Tests/AbstractLayoutTest.php | 102 +++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4381726126..8ca730cd37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ CHANGELOG * added "html5" option to Date, Time and DateTimeFormType to be able to enable/disable HTML5 input date when widget option is "single_text" + * added "label_format" option with possible placeholders "%name%" and "%id%" 2.5.0 ------ diff --git a/Extension/Core/Type/BaseType.php b/Extension/Core/Type/BaseType.php index a6f8c430e1..c227edd6f2 100644 --- a/Extension/Core/Type/BaseType.php +++ b/Extension/Core/Type/BaseType.php @@ -44,6 +44,7 @@ public function buildView(FormView $view, FormInterface $form, array $options) $name = $form->getName(); $blockName = $options['block_name'] ?: $form->getName(); $translationDomain = $options['translation_domain']; + $labelFormat = $options['label_format']; if ($view->parent) { if ('' !== ($parentFullName = $view->parent->vars['full_name'])) { @@ -59,6 +60,10 @@ public function buildView(FormView $view, FormInterface $form, array $options) if (!$translationDomain) { $translationDomain = $view->parent->vars['translation_domain']; } + + if (!$labelFormat) { + $labelFormat = $view->parent->vars['label_format']; + } } else { $id = $name; $fullName = $name; @@ -87,6 +92,7 @@ public function buildView(FormView $view, FormInterface $form, array $options) 'full_name' => $fullName, 'disabled' => $form->isDisabled(), 'label' => $options['label'], + 'label_format' => $labelFormat, 'multipart' => false, 'attr' => $options['attr'], 'block_prefixes' => $blockPrefixes, @@ -111,6 +117,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'block_name' => null, 'disabled' => false, 'label' => null, + 'label_format' => null, 'attr' => array(), 'translation_domain' => null, 'auto_initialize' => true, diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index 4755e208e9..93409636fe 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -283,6 +283,108 @@ public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly ); } + public function testLabelFormatName() + { + $form = $this->factory->createNamedBuilder('myform') + ->add('myfield', 'text') + ->getForm(); + $view = $form->get('myfield')->createView(); + $html = $this->renderLabel($view, null, array('label_format' => 'form.%name%')); + + $this->assertMatchesXpath($html, +'/label + [@for="myform_myfield"] + [.="[trans]form.myfield[/trans]"] +' + ); + } + + public function testLabelFormatId() + { + $form = $this->factory->createNamedBuilder('myform') + ->add('myfield', 'text') + ->getForm(); + $view = $form->get('myfield')->createView(); + $html = $this->renderLabel($view, null, array('label_format' => 'form.%id%')); + + $this->assertMatchesXpath($html, +'/label + [@for="myform_myfield"] + [.="[trans]form.myform_myfield[/trans]"] +' + ); + } + + public function testLabelFormatAsFormOption() + { + $options = array('label_format' => 'form.%name%'); + + $form = $this->factory->createNamedBuilder('myform', 'form', null, $options) + ->add('myfield', 'text') + ->getForm(); + $view = $form->get('myfield')->createView(); + $html = $this->renderLabel($view); + + $this->assertMatchesXpath($html, +'/label + [@for="myform_myfield"] + [.="[trans]form.myfield[/trans]"] +' + ); + } + + public function testLabelFormatOverriddenOption() + { + $options = array('label_format' => 'form.%name%'); + + $form = $this->factory->createNamedBuilder('myform', 'form', null, $options) + ->add('myfield', 'text', array('label_format' => 'field.%name%')) + ->getForm(); + $view = $form->get('myfield')->createView(); + $html = $this->renderLabel($view); + + $this->assertMatchesXpath($html, +'/label + [@for="myform_myfield"] + [.="[trans]field.myfield[/trans]"] +' + ); + } + + public function testLabelFormatOnButton() + { + $form = $this->factory->createNamedBuilder('myform') + ->add('mybutton', 'button') + ->getForm(); + $view = $form->get('mybutton')->createView(); + $html = $this->renderWidget($view, array('label_format' => 'form.%name%')); + + $this->assertMatchesXpath($html, +'/button + [@type="button"] + [@name="myform[mybutton]"] + [.="[trans]form.mybutton[/trans]"] +' + ); + } + + public function testLabelFormatOnButtonId() + { + $form = $this->factory->createNamedBuilder('myform') + ->add('mybutton', 'button') + ->getForm(); + $view = $form->get('mybutton')->createView(); + $html = $this->renderWidget($view, array('label_format' => 'form.%id%')); + + $this->assertMatchesXpath($html, +'/button + [@type="button"] + [@name="myform[mybutton]"] + [.="[trans]form.myform_mybutton[/trans]"] +' + ); + } + public function testErrors() { $form = $this->factory->createNamed('name', 'text'); From aff400c391a2dc0152b1514d040992912aad490e Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Mon, 15 Sep 2014 13:39:24 +0200 Subject: [PATCH 344/447] [Intl] Integrated ICU data into Intl component --- Tests/Extension/Core/Type/LanguageTypeTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Extension/Core/Type/LanguageTypeTest.php b/Tests/Extension/Core/Type/LanguageTypeTest.php index 24434b2148..5c54632e79 100644 --- a/Tests/Extension/Core/Type/LanguageTypeTest.php +++ b/Tests/Extension/Core/Type/LanguageTypeTest.php @@ -31,7 +31,7 @@ public function testCountriesAreSelectable() $this->assertContains(new ChoiceView('en', 'en', 'English'), $choices, '', false, false); $this->assertContains(new ChoiceView('en_GB', 'en_GB', 'British English'), $choices, '', false, false); - $this->assertContains(new ChoiceView('en_US', 'en_US', 'U.S. English'), $choices, '', false, false); + $this->assertContains(new ChoiceView('en_US', 'en_US', 'American English'), $choices, '', false, false); $this->assertContains(new ChoiceView('fr', 'fr', 'French'), $choices, '', false, false); $this->assertContains(new ChoiceView('my', 'my', 'Burmese'), $choices, '', false, false); } From 62c4147971982b7c13a951d148f5797e56f4c2fb Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 27 Sep 2014 22:16:29 +0200 Subject: [PATCH 345/447] fixed some composer.json to make standalone component tests pass --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 0993aefaf3..6e1f344196 100644 --- a/composer.json +++ b/composer.json @@ -23,7 +23,7 @@ "symfony/property-access": "~2.3" }, "require-dev": { - "symfony/validator": "~2.4", + "symfony/validator": "~2.4,<2.5.0", "symfony/http-foundation": "~2.2", "symfony/http-kernel": "~2.4", "symfony/security-csrf": "~2.4", From 916ed4f695ce52b39a4b3661a4e064d8306df941 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Fri, 26 Sep 2014 13:06:33 +0200 Subject: [PATCH 346/447] [Form] The trace of form errors is now displayed in the profiler --- Button.php | 9 +++++ CHANGELOG.md | 1 + Extension/DataCollector/FormDataExtractor.php | 37 +++++++++++++++---- .../Validator/Constraints/FormValidator.php | 1 + Form.php | 20 ++++++---- FormInterface.php | 12 ++++++ .../DataCollector/FormDataExtractorTest.php | 11 ++++-- .../Constraints/FormValidatorTest.php | 9 +++++ 8 files changed, 82 insertions(+), 18 deletions(-) diff --git a/Button.php b/Button.php index 380b20f4dd..0ba4c8138c 100644 --- a/Button.php +++ b/Button.php @@ -344,6 +344,15 @@ public function isSynchronized() return true; } + /** + * Unsupported method. + * + * @return null Always returns null + */ + public function getTransformationFailure() + { + } + /** * Unsupported method. * diff --git a/CHANGELOG.md b/CHANGELOG.md index 4381726126..dfc2e89ea7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ CHANGELOG * ObjectChoiceList now compares choices by their value, if a value path is given * you can now pass interface names in the "data_class" option + * [BC BREAK] added `FormInterface::getTransformationFailure()` 2.4.0 ----- diff --git a/Extension/DataCollector/FormDataExtractor.php b/Extension/DataCollector/FormDataExtractor.php index 80e910177a..0ae5560afe 100644 --- a/Extension/DataCollector/FormDataExtractor.php +++ b/Extension/DataCollector/FormDataExtractor.php @@ -115,18 +115,39 @@ public function extractSubmittedData(FormInterface $form) 'origin' => is_object($error->getOrigin()) ? spl_object_hash($error->getOrigin()) : null, + 'trace' => array(), ); $cause = $error->getCause(); - if ($cause instanceof ConstraintViolationInterface) { - $errorData['cause'] = array( - 'root' => $this->valueExporter->exportValue($cause->getRoot()), - 'path' => $this->valueExporter->exportValue($cause->getPropertyPath()), - 'value' => $this->valueExporter->exportValue($cause->getInvalidValue()), - ); - } else { - $errorData['cause'] = null !== $cause ? $this->valueExporter->exportValue($cause) : null; + while (null !== $cause) { + if ($cause instanceof ConstraintViolationInterface) { + $errorData['trace'][] = array( + 'class' => $this->valueExporter->exportValue(get_class($cause)), + 'root' => $this->valueExporter->exportValue($cause->getRoot()), + 'path' => $this->valueExporter->exportValue($cause->getPropertyPath()), + 'value' => $this->valueExporter->exportValue($cause->getInvalidValue()), + ); + + $cause = method_exists($cause, 'getCause') ? $cause->getCause() : null; + + continue; + } + + if ($cause instanceof \Exception) { + $errorData['trace'][] = array( + 'class' => $this->valueExporter->exportValue(get_class($cause)), + 'message' => $this->valueExporter->exportValue($cause->getMessage()), + ); + + $cause = $cause->getPrevious(); + + continue; + } + + $errorData['trace'][] = $cause; + + break; } $data['errors'][] = $errorData; diff --git a/Extension/Validator/Constraints/FormValidator.php b/Extension/Validator/Constraints/FormValidator.php index 1fe1147051..7c0dc44ab1 100644 --- a/Extension/Validator/Constraints/FormValidator.php +++ b/Extension/Validator/Constraints/FormValidator.php @@ -103,6 +103,7 @@ public function validate($form, Constraint $constraint) ->setParameters(array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters'))) ->setInvalidValue($form->getViewData()) ->setCode(Form::ERR_INVALID) + ->setCause($form->getTransformationFailure()) ->addViolation(); } } diff --git a/Form.php b/Form.php index 90048d3fb5..9b259e820b 100644 --- a/Form.php +++ b/Form.php @@ -121,12 +121,10 @@ class Form implements \IteratorAggregate, FormInterface private $extraData = array(); /** - * Whether the data in model, normalized and view format is - * synchronized. Data may not be synchronized if transformation errors - * occur. - * @var bool + * Returns the transformation failure generated during submission, if any + * @var TransformationFailedException|null */ - private $synchronized = true; + private $transformationFailure; /** * Whether the form's data has been initialized. @@ -634,7 +632,7 @@ public function submit($submittedData, $clearMissing = true) $viewData = $this->normToView($normData); } } catch (TransformationFailedException $e) { - $this->synchronized = false; + $this->transformationFailure = $e; // If $viewData was not yet set, set it to $submittedData so that // the erroneous data is accessible on the form. @@ -711,7 +709,15 @@ public function isBound() */ public function isSynchronized() { - return $this->synchronized; + return null === $this->transformationFailure; + } + + /** + * {@inheritdoc} + */ + public function getTransformationFailure() + { + return $this->transformationFailure; } /** diff --git a/FormInterface.php b/FormInterface.php index 274ce04e62..1b9e6e4777 100644 --- a/FormInterface.php +++ b/FormInterface.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Form; +use Symfony\Component\Form\Exception\TransformationFailedException; + /** * A form group bundling multiple forms in a hierarchical structure. * @@ -230,10 +232,20 @@ public function isEmpty(); /** * Returns whether the data in the different formats is synchronized. * + * If the data is not synchronized, you can get the transformation failure + * by calling {@link getTransformationFailure()}. + * * @return bool */ public function isSynchronized(); + /** + * Returns the data transformation failure, if any. + * + * @return TransformationFailedException|null The transformation failure + */ + public function getTransformationFailure(); + /** * Initializes the form tree. * diff --git a/Tests/Extension/DataCollector/FormDataExtractorTest.php b/Tests/Extension/DataCollector/FormDataExtractorTest.php index 77b2d4472a..deb6069ee2 100644 --- a/Tests/Extension/DataCollector/FormDataExtractorTest.php +++ b/Tests/Extension/DataCollector/FormDataExtractorTest.php @@ -319,7 +319,7 @@ public function testExtractSubmittedDataStoresErrors() 'norm' => "'Foobar'", ), 'errors' => array( - array('message' => 'Invalid!', 'origin' => null, 'cause' => null), + array('message' => 'Invalid!', 'origin' => null, 'trace' => array()), ), 'synchronized' => 'true', ), $this->dataExtractor->extractSubmittedData($form)); @@ -340,7 +340,7 @@ public function testExtractSubmittedDataStoresErrorOrigin() 'norm' => "'Foobar'", ), 'errors' => array( - array('message' => 'Invalid!', 'origin' => spl_object_hash($form), 'cause' => null), + array('message' => 'Invalid!', 'origin' => spl_object_hash($form), 'trace' => array()), ), 'synchronized' => 'true', ), $this->dataExtractor->extractSubmittedData($form)); @@ -360,7 +360,12 @@ public function testExtractSubmittedDataStoresErrorCause() 'norm' => "'Foobar'", ), 'errors' => array( - array('message' => 'Invalid!', 'origin' => null, 'cause' => 'object(Exception)'), + array('message' => 'Invalid!', 'origin' => null, 'trace' => array( + array( + 'class' => "'Exception'", + 'message' => "''", + ), + )), ), 'synchronized' => 'true', ), $this->dataExtractor->extractSubmittedData($form)); diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index 99c5e584c1..877797f163 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -225,11 +225,14 @@ function () { throw new TransformationFailedException(); } $this->validator->validate($form, new Form()); + $is2Dot4Api = Validation::API_VERSION_2_4 === $this->getApiVersion(); + $this->buildViolation('invalid_message_key') ->setParameter('{{ value }}', 'foo') ->setParameter('{{ foo }}', 'bar') ->setInvalidValue('foo') ->setCode(Form::ERR_INVALID) + ->setCause($is2Dot4Api ? null : $form->getTransformationFailure()) ->assertRaised(); } @@ -259,11 +262,14 @@ function () { throw new TransformationFailedException(); } $this->validator->validate($form, new Form()); + $is2Dot4Api = Validation::API_VERSION_2_4 === $this->getApiVersion(); + $this->buildViolation('invalid_message_key') ->setParameter('{{ value }}', 'foo') ->setParameter('{{ foo }}', 'bar') ->setInvalidValue('foo') ->setCode(Form::ERR_INVALID) + ->setCause($is2Dot4Api ? null : $form->getTransformationFailure()) ->assertRaised(); } @@ -293,10 +299,13 @@ function () { throw new TransformationFailedException(); } $this->validator->validate($form, new Form()); + $is2Dot4Api = Validation::API_VERSION_2_4 === $this->getApiVersion(); + $this->buildViolation('invalid_message_key') ->setParameter('{{ value }}', 'foo') ->setInvalidValue('foo') ->setCode(Form::ERR_INVALID) + ->setCause($is2Dot4Api ? null : $form->getTransformationFailure()) ->assertRaised(); } From 28708bd40da8b7ba33a47f10714755b4641d88cf Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Wed, 24 Sep 2014 12:08:18 +0200 Subject: [PATCH 347/447] [Validator] Added error codes to all constraints with multiple error causes --- Extension/Validator/Constraints/Form.php | 11 ++++++++++- Extension/Validator/Constraints/FormValidator.php | 3 ++- .../Validator/EventListener/ValidationListener.php | 2 +- .../Validator/Constraints/FormValidatorTest.php | 14 ++++++++------ .../EventListener/ValidationListenerTest.php | 4 ++-- 5 files changed, 23 insertions(+), 11 deletions(-) diff --git a/Extension/Validator/Constraints/Form.php b/Extension/Validator/Constraints/Form.php index 87e3329765..da1a92b5e4 100644 --- a/Extension/Validator/Constraints/Form.php +++ b/Extension/Validator/Constraints/Form.php @@ -18,11 +18,20 @@ */ class Form extends Constraint { + const NOT_SYNCHRONIZED_ERROR = 1; + const NO_SUCH_FIELD_ERROR = 2; + /** - * Violation code marking an invalid form. + * @deprecated Deprecated since Symfony 2.6, to be removed in 3.0. Use + * {@self NOT_SYNCHRONIZED_ERROR} instead. */ const ERR_INVALID = 1; + protected static $errorNames = array( + self::NOT_SYNCHRONIZED_ERROR => 'NOT_SYNCHRONIZED_ERROR', + self::NO_SUCH_FIELD_ERROR => 'NO_SUCH_FIELD_ERROR', + ); + /** * {@inheritdoc} */ diff --git a/Extension/Validator/Constraints/FormValidator.php b/Extension/Validator/Constraints/FormValidator.php index 7c0dc44ab1..d4e6f466fc 100644 --- a/Extension/Validator/Constraints/FormValidator.php +++ b/Extension/Validator/Constraints/FormValidator.php @@ -102,7 +102,7 @@ public function validate($form, Constraint $constraint) $this->buildViolation($config->getOption('invalid_message')) ->setParameters(array_replace(array('{{ value }}' => $clientDataAsString), $config->getOption('invalid_message_parameters'))) ->setInvalidValue($form->getViewData()) - ->setCode(Form::ERR_INVALID) + ->setCode(Form::NOT_SYNCHRONIZED_ERROR) ->setCause($form->getTransformationFailure()) ->addViolation(); } @@ -113,6 +113,7 @@ public function validate($form, Constraint $constraint) $this->buildViolation($config->getOption('extra_fields_message')) ->setParameter('{{ extra_fields }}', implode('", "', array_keys($form->getExtraData()))) ->setInvalidValue($form->getExtraData()) + ->setCode(Form::NO_SUCH_FIELD_ERROR) ->addViolation(); } } diff --git a/Extension/Validator/EventListener/ValidationListener.php b/Extension/Validator/EventListener/ValidationListener.php index 62c59ddc43..37f194380a 100644 --- a/Extension/Validator/EventListener/ValidationListener.php +++ b/Extension/Validator/EventListener/ValidationListener.php @@ -66,7 +66,7 @@ public function validateForm(FormEvent $event) foreach ($violations as $violation) { // Allow the "invalid" constraint to be put onto // non-synchronized forms - $allowNonSynchronized = Form::ERR_INVALID === $violation->getCode(); + $allowNonSynchronized = $violation->getConstraint() instanceof Form && Form::NOT_SYNCHRONIZED_ERROR === $violation->getCode(); $this->violationMapper->mapViolation($violation, $form, $allowNonSynchronized); } diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index 877797f163..5fa4f39f09 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -231,7 +231,7 @@ function () { throw new TransformationFailedException(); } ->setParameter('{{ value }}', 'foo') ->setParameter('{{ foo }}', 'bar') ->setInvalidValue('foo') - ->setCode(Form::ERR_INVALID) + ->setCode(Form::NOT_SYNCHRONIZED_ERROR) ->setCause($is2Dot4Api ? null : $form->getTransformationFailure()) ->assertRaised(); } @@ -268,7 +268,7 @@ function () { throw new TransformationFailedException(); } ->setParameter('{{ value }}', 'foo') ->setParameter('{{ foo }}', 'bar') ->setInvalidValue('foo') - ->setCode(Form::ERR_INVALID) + ->setCode(Form::NOT_SYNCHRONIZED_ERROR) ->setCause($is2Dot4Api ? null : $form->getTransformationFailure()) ->assertRaised(); } @@ -304,7 +304,7 @@ function () { throw new TransformationFailedException(); } $this->buildViolation('invalid_message_key') ->setParameter('{{ value }}', 'foo') ->setInvalidValue('foo') - ->setCode(Form::ERR_INVALID) + ->setCode(Form::NOT_SYNCHRONIZED_ERROR) ->setCause($is2Dot4Api ? null : $form->getTransformationFailure()) ->assertRaised(); } @@ -558,9 +558,11 @@ public function testViolationIfExtraData() $this->validator->validate($form, new Form()); - $this->assertViolation('Extra!', array( - '{{ extra_fields }}' => 'foo', - ), 'property.path', array('foo' => 'bar')); + $this->buildViolation('Extra!') + ->setParameter('{{ extra_fields }}', 'foo') + ->setInvalidValue(array('foo' => 'bar')) + ->setCode(Form::NO_SUCH_FIELD_ERROR) + ->assertRaised(); } public function testNoViolationIfAllowExtraData() diff --git a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php index d819277db0..845dc85025 100644 --- a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php +++ b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php @@ -66,7 +66,7 @@ protected function setUp() private function getConstraintViolation($code = null) { - return new ConstraintViolation($this->message, $this->messageTemplate, $this->params, null, 'prop.path', null, null, $code); + return new ConstraintViolation($this->message, $this->messageTemplate, $this->params, null, 'prop.path', null, null, $code, new Form()); } private function getBuilder($name = 'name', $propertyPath = null, $dataClass = null) @@ -109,7 +109,7 @@ public function testMapViolation() public function testMapViolationAllowsNonSyncIfInvalid() { - $violation = $this->getConstraintViolation(Form::ERR_INVALID); + $violation = $this->getConstraintViolation(Form::NOT_SYNCHRONIZED_ERROR); $form = $this->getForm('street'); $this->validator->expects($this->once()) From d251ab14697095cddba305613fa0d500d91422c7 Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Sun, 5 Oct 2014 05:13:10 +0200 Subject: [PATCH 348/447] [Form] remove unnecessary call --- FormBuilder.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/FormBuilder.php b/FormBuilder.php index e73c03fd7a..1c56df2a71 100644 --- a/FormBuilder.php +++ b/FormBuilder.php @@ -139,10 +139,7 @@ public function remove($name) } unset($this->unresolvedChildren[$name]); - - if (array_key_exists($name, $this->children)) { - unset($this->children[$name]); - } + unset($this->children[$name]); return $this; } From a1cefc9a6013e85f74f2a4bc94f611d6016dd06a Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Tue, 7 Oct 2014 21:02:39 +0200 Subject: [PATCH 349/447] [Form] fix form handling with unconventional request methods like OPTIONS --- .../EventListener/BindRequestListener.php | 31 +++++++------------ .../HttpFoundationRequestHandler.php | 4 ++- NativeRequestHandler.php | 4 ++- 3 files changed, 18 insertions(+), 21 deletions(-) diff --git a/Extension/HttpFoundation/EventListener/BindRequestListener.php b/Extension/HttpFoundation/EventListener/BindRequestListener.php index 2930c5b36a..6ba976a823 100644 --- a/Extension/HttpFoundation/EventListener/BindRequestListener.php +++ b/Extension/HttpFoundation/EventListener/BindRequestListener.php @@ -13,7 +13,6 @@ use Symfony\Component\Form\FormEvents; use Symfony\Component\Form\FormEvent; -use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; @@ -49,12 +48,19 @@ public function preBind(FormEvent $event) $name = $form->getConfig()->getName(); $default = $form->getConfig()->getCompound() ? array() : null; - // Store the bound data in case of a post request + // For request methods that must not have a request body we fetch data + // from the query string. Otherwise we look for data in the request body. switch ($request->getMethod()) { - case 'POST': - case 'PUT': - case 'DELETE': - case 'PATCH': + case 'GET': + case 'HEAD': + case 'TRACE': + $data = '' === $name + ? $request->query->all() + : $request->query->get($name, $default); + + break; + + default: if ('' === $name) { // Form bound without name $params = $request->request->all(); @@ -71,19 +77,6 @@ public function preBind(FormEvent $event) } break; - - case 'GET': - $data = '' === $name - ? $request->query->all() - : $request->query->get($name, $default); - - break; - - default: - throw new LogicException(sprintf( - 'The request method "%s" is not supported', - $request->getMethod() - )); } $event->setData($data); diff --git a/Extension/HttpFoundation/HttpFoundationRequestHandler.php b/Extension/HttpFoundation/HttpFoundationRequestHandler.php index 03805fef52..98bbd4b9ce 100644 --- a/Extension/HttpFoundation/HttpFoundationRequestHandler.php +++ b/Extension/HttpFoundation/HttpFoundationRequestHandler.php @@ -55,7 +55,9 @@ public function handleRequest(FormInterface $form, $request = null) return; } - if ('GET' === $method) { + // For request methods that must not have a request body we fetch data + // from the query string. Otherwise we look for data in the request body. + if ('GET' === $method || 'HEAD' === $method || 'TRACE' === $method) { if ('' === $name) { $data = $request->query->all(); } else { diff --git a/NativeRequestHandler.php b/NativeRequestHandler.php index 9df9066886..c4096ee362 100644 --- a/NativeRequestHandler.php +++ b/NativeRequestHandler.php @@ -63,7 +63,9 @@ public function handleRequest(FormInterface $form, $request = null) return; } - if ('GET' === $method) { + // For request methods that must not have a request body we fetch data + // from the query string. Otherwise we look for data in the request body. + if ('GET' === $method || 'HEAD' === $method || 'TRACE' === $method) { if ('' === $name) { $data = $_GET; } else { From fb8990760fad3deeff31847b034c2860829712ab Mon Sep 17 00:00:00 2001 From: Stepan Anchugov Date: Mon, 18 Aug 2014 22:28:21 +0600 Subject: [PATCH 350/447] [Form] Fix #11694 - Enforce options value type check in some form types --- Extension/Core/Type/BirthdayType.php | 4 +++ Extension/Core/Type/DateType.php | 3 ++ Extension/Core/Type/RepeatedType.php | 6 ++++ Extension/Core/Type/TimeType.php | 6 ++++ Extension/Core/Type/UrlType.php | 4 +++ .../Extension/Core/Type/BirthdayTypeTest.php | 33 +++++++++++++++++++ Tests/Extension/Core/Type/DateTypeTest.php | 30 +++++++++++++++++ .../Extension/Core/Type/RepeatedTypeTest.php | 33 +++++++++++++++++++ Tests/Extension/Core/Type/TimeTypeTest.php | 30 +++++++++++++++++ Tests/Extension/Core/Type/UrlTypeTest.php | 10 ++++++ 10 files changed, 159 insertions(+) create mode 100644 Tests/Extension/Core/Type/BirthdayTypeTest.php diff --git a/Extension/Core/Type/BirthdayType.php b/Extension/Core/Type/BirthdayType.php index 5314c140a1..f90f57d4b6 100644 --- a/Extension/Core/Type/BirthdayType.php +++ b/Extension/Core/Type/BirthdayType.php @@ -24,6 +24,10 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) $resolver->setDefaults(array( 'years' => range(date('Y') - 120, date('Y')), )); + + $resolver->setAllowedTypes(array( + 'years' => 'array', + )); } /** diff --git a/Extension/Core/Type/DateType.php b/Extension/Core/Type/DateType.php index 6d90e55714..bcbf42dc5d 100644 --- a/Extension/Core/Type/DateType.php +++ b/Extension/Core/Type/DateType.php @@ -237,6 +237,9 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) $resolver->setAllowedTypes(array( 'format' => array('int', 'string'), + 'years' => 'array', + 'months' => 'array', + 'days' => 'array', )); } diff --git a/Extension/Core/Type/RepeatedType.php b/Extension/Core/Type/RepeatedType.php index 9a3cd14615..67422e38f4 100644 --- a/Extension/Core/Type/RepeatedType.php +++ b/Extension/Core/Type/RepeatedType.php @@ -55,6 +55,12 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'second_name' => 'second', 'error_bubbling' => false, )); + + $resolver->setAllowedTypes(array( + 'options' => 'array', + 'first_options' => 'array', + 'second_options' => 'array', + )); } /** diff --git a/Extension/Core/Type/TimeType.php b/Extension/Core/Type/TimeType.php index 3585b5bd31..eee118a030 100644 --- a/Extension/Core/Type/TimeType.php +++ b/Extension/Core/Type/TimeType.php @@ -221,6 +221,12 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'choice', ), )); + + $resolver->setAllowedTypes(array( + 'hours' => 'array', + 'minutes' => 'array', + 'seconds' => 'array', + )); } /** diff --git a/Extension/Core/Type/UrlType.php b/Extension/Core/Type/UrlType.php index 27749b1a8c..b79809259f 100644 --- a/Extension/Core/Type/UrlType.php +++ b/Extension/Core/Type/UrlType.php @@ -34,6 +34,10 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) $resolver->setDefaults(array( 'default_protocol' => 'http', )); + + $resolver->setAllowedTypes(array( + 'default_protocol' => array('null', 'string'), + )); } /** diff --git a/Tests/Extension/Core/Type/BirthdayTypeTest.php b/Tests/Extension/Core/Type/BirthdayTypeTest.php new file mode 100644 index 0000000000..755eac9035 --- /dev/null +++ b/Tests/Extension/Core/Type/BirthdayTypeTest.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\Type; + +/** + * @author Stepan Anchugov + */ +class BirthdayTypeTest extends BaseTypeTest +{ + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + */ + public function testSetInvalidYearsOption() + { + $this->factory->create('birthday', null, array( + 'years' => 'bad value', + )); + } + + protected function getTestedType() + { + return 'birthday'; + } +} diff --git a/Tests/Extension/Core/Type/DateTypeTest.php b/Tests/Extension/Core/Type/DateTypeTest.php index f095f30354..ed583a0af4 100644 --- a/Tests/Extension/Core/Type/DateTypeTest.php +++ b/Tests/Extension/Core/Type/DateTypeTest.php @@ -340,6 +340,36 @@ public function testThrowExceptionIfFormatIsInvalid() )); } + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + */ + public function testThrowExceptionIfYearsIsInvalid() + { + $this->factory->create('date', null, array( + 'years' => 'bad value', + )); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + */ + public function testThrowExceptionIfMonthsIsInvalid() + { + $this->factory->create('date', null, array( + 'months' => 'bad value', + )); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + */ + public function testThrowExceptionIfDaysIsInvalid() + { + $this->factory->create('date', null, array( + 'days' => 'bad value', + )); + } + public function testSetDataWithDifferentTimezones() { $form = $this->factory->create('date', null, array( diff --git a/Tests/Extension/Core/Type/RepeatedTypeTest.php b/Tests/Extension/Core/Type/RepeatedTypeTest.php index d506f5f5a6..5db909ff21 100644 --- a/Tests/Extension/Core/Type/RepeatedTypeTest.php +++ b/Tests/Extension/Core/Type/RepeatedTypeTest.php @@ -72,6 +72,39 @@ public function testSetRequired() $this->assertFalse($form['second']->isRequired()); } + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + */ + public function testSetInvalidOptions() + { + $this->factory->create('repeated', null, array( + 'type' => 'text', + 'options' => 'bad value', + )); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + */ + public function testSetInvalidFirstOptions() + { + $this->factory->create('repeated', null, array( + 'type' => 'text', + 'first_options' => 'bad value', + )); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + */ + public function testSetInvalidSecondOptions() + { + $this->factory->create('repeated', null, array( + 'type' => 'text', + 'second_options' => 'bad value', + )); + } + public function testSetErrorBubblingToTrue() { $form = $this->factory->create('repeated', null, array( diff --git a/Tests/Extension/Core/Type/TimeTypeTest.php b/Tests/Extension/Core/Type/TimeTypeTest.php index b4fb3b1572..01c50abb20 100644 --- a/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/Tests/Extension/Core/Type/TimeTypeTest.php @@ -673,4 +673,34 @@ public function testInitializeWithSecondsAndWithoutMinutes() 'with_seconds' => true, )); } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + */ + public function testThrowExceptionIfHoursIsInvalid() + { + $this->factory->create('time', null, array( + 'hours' => 'bad value', + )); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + */ + public function testThrowExceptionIfMinutesIsInvalid() + { + $this->factory->create('time', null, array( + 'minutes' => 'bad value', + )); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + */ + public function testThrowExceptionIfSecondsIsInvalid() + { + $this->factory->create('time', null, array( + 'seconds' => 'bad value', + )); + } } diff --git a/Tests/Extension/Core/Type/UrlTypeTest.php b/Tests/Extension/Core/Type/UrlTypeTest.php index 718d4cd650..fa975ac86c 100644 --- a/Tests/Extension/Core/Type/UrlTypeTest.php +++ b/Tests/Extension/Core/Type/UrlTypeTest.php @@ -70,4 +70,14 @@ public function testSubmitAddsNoDefaultProtocolIfSetToNull() $this->assertSame('www.domain.com', $form->getData()); $this->assertSame('www.domain.com', $form->getViewData()); } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + */ + public function testThrowExceptionIfDefaultProtocolIsInvalid() + { + $this->factory->create('url', null, array( + 'default_protocol' => array(), + )); + } } From 2c6919c3d12b49a8518374f02d1e2d5d82417c16 Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Fri, 17 Oct 2014 01:39:03 +0200 Subject: [PATCH 351/447] [Form] no need to add the url listener when it does not do anything --- Extension/Core/EventListener/FixUrlProtocolListener.php | 5 +++++ Extension/Core/Type/UrlType.php | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Extension/Core/EventListener/FixUrlProtocolListener.php b/Extension/Core/EventListener/FixUrlProtocolListener.php index e25dacf237..4a5a1df6af 100644 --- a/Extension/Core/EventListener/FixUrlProtocolListener.php +++ b/Extension/Core/EventListener/FixUrlProtocolListener.php @@ -24,6 +24,11 @@ class FixUrlProtocolListener implements EventSubscriberInterface { private $defaultProtocol; + /** + * Constructor. + * + * @param string|null $defaultProtocol The URL scheme to add when there is none or null to not modify the data + */ public function __construct($defaultProtocol = 'http') { $this->defaultProtocol = $defaultProtocol; diff --git a/Extension/Core/Type/UrlType.php b/Extension/Core/Type/UrlType.php index b79809259f..5c414afc93 100644 --- a/Extension/Core/Type/UrlType.php +++ b/Extension/Core/Type/UrlType.php @@ -23,7 +23,9 @@ class UrlType extends AbstractType */ public function buildForm(FormBuilderInterface $builder, array $options) { - $builder->addEventSubscriber(new FixUrlProtocolListener($options['default_protocol'])); + if (null !== $options['default_protocol']) { + $builder->addEventSubscriber(new FixUrlProtocolListener($options['default_protocol'])); + } } /** From 98acb93b6b74598b340478e09872d1b64faa11c8 Mon Sep 17 00:00:00 2001 From: Disquedur Date: Wed, 22 Oct 2014 20:27:13 +0200 Subject: [PATCH 352/447] Remove aligned '=>' and '=' --- .../DateTimeToArrayTransformer.php | 24 ++++---- .../NumberToLocalizedStringTransformer.php | 10 ++-- Extension/Core/Type/BaseType.php | 34 +++++------ Extension/Core/Type/CheckboxType.php | 6 +- Extension/Core/Type/ChoiceType.php | 28 +++++----- Extension/Core/Type/CollectionType.php | 12 ++-- Extension/Core/Type/DateTimeType.php | 28 +++++----- Extension/Core/Type/DateType.php | 30 +++++----- Extension/Core/Type/FileType.php | 2 +- Extension/Core/Type/FormType.php | 56 +++++++++---------- Extension/Core/Type/HiddenType.php | 4 +- Extension/Core/Type/IntegerType.php | 6 +- Extension/Core/Type/MoneyType.php | 8 +-- Extension/Core/Type/NumberType.php | 6 +- Extension/Core/Type/PasswordType.php | 2 +- Extension/Core/Type/PercentType.php | 4 +- Extension/Core/Type/RepeatedType.php | 16 +++--- Extension/Core/Type/TimeType.php | 30 +++++----- Extension/Csrf/Type/FormTypeCsrfExtension.php | 10 ++-- .../Type/FormTypeValidatorExtension.php | 12 ++-- FormBuilder.php | 2 +- FormFactory.php | 2 +- FormView.php | 2 +- NativeRequestHandler.php | 8 +-- Tests/AbstractDivLayoutTest.php | 2 +- Tests/AbstractTableLayoutTest.php | 4 +- .../Core/EventListener/TrimListenerTest.php | 2 +- Tests/Extension/Core/Type/ChoiceTypeTest.php | 38 ++++++------- .../Core/Type/CollectionTypeTest.php | 18 +++--- .../Extension/Core/Type/RepeatedTypeTest.php | 18 +++--- 30 files changed, 212 insertions(+), 212 deletions(-) diff --git a/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php b/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php index eeeb9fafac..e36be12009 100644 --- a/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php @@ -63,12 +63,12 @@ public function transform($dateTime) { if (null === $dateTime) { return array_intersect_key(array( - 'year' => '', - 'month' => '', - 'day' => '', - 'hour' => '', - 'minute' => '', - 'second' => '', + 'year' => '', + 'month' => '', + 'day' => '', + 'hour' => '', + 'minute' => '', + 'second' => '', ), array_flip($this->fields)); } @@ -86,12 +86,12 @@ public function transform($dateTime) } $result = array_intersect_key(array( - 'year' => $dateTime->format('Y'), - 'month' => $dateTime->format('m'), - 'day' => $dateTime->format('d'), - 'hour' => $dateTime->format('H'), - 'minute' => $dateTime->format('i'), - 'second' => $dateTime->format('s'), + 'year' => $dateTime->format('Y'), + 'month' => $dateTime->format('m'), + 'day' => $dateTime->format('d'), + 'hour' => $dateTime->format('H'), + 'minute' => $dateTime->format('i'), + 'second' => $dateTime->format('s'), ), array_flip($this->fields)); if (!$this->pad) { diff --git a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php index 8b30c7f696..3bf9581cd0 100644 --- a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php @@ -23,13 +23,13 @@ */ class NumberToLocalizedStringTransformer implements DataTransformerInterface { - const ROUND_FLOOR = \NumberFormatter::ROUND_FLOOR; - const ROUND_DOWN = \NumberFormatter::ROUND_DOWN; + const ROUND_FLOOR = \NumberFormatter::ROUND_FLOOR; + const ROUND_DOWN = \NumberFormatter::ROUND_DOWN; const ROUND_HALFDOWN = \NumberFormatter::ROUND_HALFDOWN; const ROUND_HALFEVEN = \NumberFormatter::ROUND_HALFEVEN; - const ROUND_HALFUP = \NumberFormatter::ROUND_HALFUP; - const ROUND_UP = \NumberFormatter::ROUND_UP; - const ROUND_CEILING = \NumberFormatter::ROUND_CEILING; + const ROUND_HALFUP = \NumberFormatter::ROUND_HALFUP; + const ROUND_UP = \NumberFormatter::ROUND_UP; + const ROUND_CEILING = \NumberFormatter::ROUND_CEILING; protected $precision; diff --git a/Extension/Core/Type/BaseType.php b/Extension/Core/Type/BaseType.php index a6f8c430e1..66f3641f43 100644 --- a/Extension/Core/Type/BaseType.php +++ b/Extension/Core/Type/BaseType.php @@ -81,24 +81,24 @@ public function buildView(FormView $view, FormInterface $form, array $options) } $view->vars = array_replace($view->vars, array( - 'form' => $view, - 'id' => $id, - 'name' => $name, - 'full_name' => $fullName, - 'disabled' => $form->isDisabled(), - 'label' => $options['label'], - 'multipart' => false, - 'attr' => $options['attr'], - 'block_prefixes' => $blockPrefixes, + 'form' => $view, + 'id' => $id, + 'name' => $name, + 'full_name' => $fullName, + 'disabled' => $form->isDisabled(), + 'label' => $options['label'], + 'multipart' => false, + 'attr' => $options['attr'], + 'block_prefixes' => $blockPrefixes, 'unique_block_prefix' => $uniqueBlockPrefix, - 'translation_domain' => $translationDomain, + 'translation_domain' => $translationDomain, // Using the block name here speeds up performance in collection // forms, where each entry has the same full block name. // Including the type is important too, because if rows of a // collection form have different types (dynamically), they should // be rendered differently. // https://github.com/symfony/symfony/issues/5038 - 'cache_key' => $uniqueBlockPrefix.'_'.$form->getConfig()->getType()->getName(), + 'cache_key' => $uniqueBlockPrefix.'_'.$form->getConfig()->getType()->getName(), )); } @@ -108,16 +108,16 @@ public function buildView(FormView $view, FormInterface $form, array $options) public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( - 'block_name' => null, - 'disabled' => false, - 'label' => null, - 'attr' => array(), + 'block_name' => null, + 'disabled' => false, + 'label' => null, + 'attr' => array(), 'translation_domain' => null, - 'auto_initialize' => true, + 'auto_initialize' => true, )); $resolver->setAllowedTypes(array( - 'attr' => 'array', + 'attr' => 'array', )); } } diff --git a/Extension/Core/Type/CheckboxType.php b/Extension/Core/Type/CheckboxType.php index 3952bb3316..13c78041d0 100644 --- a/Extension/Core/Type/CheckboxType.php +++ b/Extension/Core/Type/CheckboxType.php @@ -41,7 +41,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars = array_replace($view->vars, array( - 'value' => $options['value'], + 'value' => $options['value'], 'checked' => null !== $form->getViewData(), )); } @@ -56,9 +56,9 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) }; $resolver->setDefaults(array( - 'value' => '1', + 'value' => '1', 'empty_data' => $emptyData, - 'compound' => false, + 'compound' => false, )); } diff --git a/Extension/Core/Type/ChoiceType.php b/Extension/Core/Type/ChoiceType.php index 08504dea2b..529903e7dc 100644 --- a/Extension/Core/Type/ChoiceType.php +++ b/Extension/Core/Type/ChoiceType.php @@ -96,12 +96,12 @@ public function buildForm(FormBuilderInterface $builder, array $options) public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars = array_replace($view->vars, array( - 'multiple' => $options['multiple'], - 'expanded' => $options['expanded'], + 'multiple' => $options['multiple'], + 'expanded' => $options['expanded'], 'preferred_choices' => $options['choice_list']->getPreferredViews(), - 'choices' => $options['choice_list']->getRemainingViews(), - 'separator' => '-------------------', - 'empty_value' => null, + 'choices' => $options['choice_list']->getRemainingViews(), + 'separator' => '-------------------', + 'empty_value' => null, )); // The decision, whether a choice is selected, is potentially done @@ -208,19 +208,19 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) }; $resolver->setDefaults(array( - 'multiple' => false, - 'expanded' => false, - 'choice_list' => $choiceList, - 'choices' => array(), + 'multiple' => false, + 'expanded' => false, + 'choice_list' => $choiceList, + 'choices' => array(), 'preferred_choices' => array(), - 'empty_data' => $emptyData, - 'empty_value' => $emptyValue, - 'error_bubbling' => false, - 'compound' => $compound, + 'empty_data' => $emptyData, + 'empty_value' => $emptyValue, + 'error_bubbling' => false, + 'compound' => $compound, // The view data is always a string, even if the "data" option // is manually set to an object. // See https://github.com/symfony/symfony/pull/5582 - 'data_class' => null, + 'data_class' => null, )); $resolver->setNormalizers(array( diff --git a/Extension/Core/Type/CollectionType.php b/Extension/Core/Type/CollectionType.php index 0cb3af1bb7..0688bb19df 100644 --- a/Extension/Core/Type/CollectionType.php +++ b/Extension/Core/Type/CollectionType.php @@ -49,7 +49,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars = array_replace($view->vars, array( - 'allow_add' => $options['allow_add'], + 'allow_add' => $options['allow_add'], 'allow_delete' => $options['allow_delete'], )); @@ -80,12 +80,12 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) }; $resolver->setDefaults(array( - 'allow_add' => false, - 'allow_delete' => false, - 'prototype' => true, + 'allow_add' => false, + 'allow_delete' => false, + 'prototype' => true, 'prototype_name' => '__name__', - 'type' => 'text', - 'options' => array(), + 'type' => 'text', + 'options' => array(), )); $resolver->setNormalizers(array( diff --git a/Extension/Core/Type/DateTimeType.php b/Extension/Core/Type/DateTimeType.php index e8c4e748de..9f2927d978 100644 --- a/Extension/Core/Type/DateTimeType.php +++ b/Extension/Core/Type/DateTimeType.php @@ -212,26 +212,26 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) }; $resolver->setDefaults(array( - 'input' => 'datetime', + 'input' => 'datetime', 'model_timezone' => null, - 'view_timezone' => null, - 'format' => self::HTML5_FORMAT, - 'date_format' => null, - 'widget' => null, - 'date_widget' => $dateWidget, - 'time_widget' => $timeWidget, - 'with_minutes' => true, - 'with_seconds' => false, + 'view_timezone' => null, + 'format' => self::HTML5_FORMAT, + 'date_format' => null, + 'widget' => null, + 'date_widget' => $dateWidget, + 'time_widget' => $timeWidget, + 'with_minutes' => true, + 'with_seconds' => false, // Don't modify \DateTime classes by reference, we treat // them like immutable value objects - 'by_reference' => false, + 'by_reference' => false, 'error_bubbling' => false, // If initialized with a \DateTime object, FormType initializes // this option to "\DateTime". Since the internal, normalized // representation is not \DateTime, but an array, we need to unset // this option. - 'data_class' => null, - 'compound' => $compound, + 'data_class' => null, + 'compound' => $compound, )); // Don't add some defaults in order to preserve the defaults @@ -247,7 +247,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) )); $resolver->setAllowedValues(array( - 'input' => array( + 'input' => array( 'datetime', 'string', 'timestamp', @@ -266,7 +266,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'choice', ), // This option will overwrite "date_widget" and "time_widget" options - 'widget' => array( + 'widget' => array( null, // default, don't overwrite options 'single_text', 'text', diff --git a/Extension/Core/Type/DateType.php b/Extension/Core/Type/DateType.php index bcbf42dc5d..a7fc6cadf5 100644 --- a/Extension/Core/Type/DateType.php +++ b/Extension/Core/Type/DateType.php @@ -196,25 +196,25 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) }; $resolver->setDefaults(array( - 'years' => range(date('Y') - 5, date('Y') + 5), - 'months' => range(1, 12), - 'days' => range(1, 31), - 'widget' => 'choice', - 'input' => 'datetime', - 'format' => $format, + 'years' => range(date('Y') - 5, date('Y') + 5), + 'months' => range(1, 12), + 'days' => range(1, 31), + 'widget' => 'choice', + 'input' => 'datetime', + 'format' => $format, 'model_timezone' => null, - 'view_timezone' => null, - 'empty_value' => $emptyValue, + 'view_timezone' => null, + 'empty_value' => $emptyValue, // Don't modify \DateTime classes by reference, we treat // them like immutable value objects - 'by_reference' => false, + 'by_reference' => false, 'error_bubbling' => false, // If initialized with a \DateTime object, FormType initializes // this option to "\DateTime". Since the internal, normalized // representation is not \DateTime, but an array, we need to unset // this option. - 'data_class' => null, - 'compound' => $compound, + 'data_class' => null, + 'compound' => $compound, )); $resolver->setNormalizers(array( @@ -222,13 +222,13 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) )); $resolver->setAllowedValues(array( - 'input' => array( + 'input' => array( 'datetime', 'string', 'timestamp', 'array', ), - 'widget' => array( + 'widget' => array( 'single_text', 'text', 'choice', @@ -237,9 +237,9 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) $resolver->setAllowedTypes(array( 'format' => array('int', 'string'), - 'years' => 'array', + 'years' => 'array', 'months' => 'array', - 'days' => 'array', + 'days' => 'array', )); } diff --git a/Extension/Core/Type/FileType.php b/Extension/Core/Type/FileType.php index 2c09da6f6b..dd5e0dfe30 100644 --- a/Extension/Core/Type/FileType.php +++ b/Extension/Core/Type/FileType.php @@ -24,7 +24,7 @@ class FileType extends AbstractType public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars = array_replace($view->vars, array( - 'type' => 'file', + 'type' => 'file', 'value' => '', )); } diff --git a/Extension/Core/Type/FormType.php b/Extension/Core/Type/FormType.php index b417afdbcb..3fb360aefb 100644 --- a/Extension/Core/Type/FormType.php +++ b/Extension/Core/Type/FormType.php @@ -85,19 +85,19 @@ public function buildView(FormView $view, FormInterface $form, array $options) } $view->vars = array_replace($view->vars, array( - 'read_only' => $readOnly, - 'errors' => $form->getErrors(), - 'valid' => $form->isSubmitted() ? $form->isValid() : true, - 'value' => $form->getViewData(), - 'data' => $form->getNormData(), - 'required' => $form->isRequired(), + 'read_only' => $readOnly, + 'errors' => $form->getErrors(), + 'valid' => $form->isSubmitted() ? $form->isValid() : true, + 'value' => $form->getViewData(), + 'data' => $form->getNormData(), + 'required' => $form->isRequired(), 'max_length' => $options['max_length'], - 'pattern' => $options['pattern'], - 'size' => null, + 'pattern' => $options['pattern'], + 'size' => null, 'label_attr' => $options['label_attr'], - 'compound' => $form->getConfig()->getCompound(), - 'method' => $form->getConfig()->getMethod(), - 'action' => $form->getConfig()->getAction(), + 'compound' => $form->getConfig()->getCompound(), + 'method' => $form->getConfig()->getMethod(), + 'action' => $form->getConfig()->getAction(), )); } @@ -169,25 +169,25 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) )); $resolver->setDefaults(array( - 'data_class' => $dataClass, - 'empty_data' => $emptyData, - 'trim' => true, - 'required' => true, - 'read_only' => false, - 'max_length' => null, - 'pattern' => null, - 'property_path' => null, - 'mapped' => true, - 'by_reference' => true, - 'error_bubbling' => $errorBubbling, - 'label_attr' => array(), - 'virtual' => null, - 'inherit_data' => $inheritData, - 'compound' => true, - 'method' => 'POST', + 'data_class' => $dataClass, + 'empty_data' => $emptyData, + 'trim' => true, + 'required' => true, + 'read_only' => false, + 'max_length' => null, + 'pattern' => null, + 'property_path' => null, + 'mapped' => true, + 'by_reference' => true, + 'error_bubbling' => $errorBubbling, + 'label_attr' => array(), + 'virtual' => null, + 'inherit_data' => $inheritData, + 'compound' => true, + 'method' => 'POST', // According to RFC 2396 (http://www.ietf.org/rfc/rfc2396.txt) // section 4.2., empty URIs are considered same-document references - 'action' => '', + 'action' => '', 'post_max_size_message' => 'The uploaded file was too large. Please try to upload a smaller file.', )); diff --git a/Extension/Core/Type/HiddenType.php b/Extension/Core/Type/HiddenType.php index bd4fa898e6..352b34620c 100644 --- a/Extension/Core/Type/HiddenType.php +++ b/Extension/Core/Type/HiddenType.php @@ -23,10 +23,10 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( // hidden fields cannot have a required attribute - 'required' => false, + 'required' => false, // Pass errors to the parent 'error_bubbling' => true, - 'compound' => false, + 'compound' => false, )); } diff --git a/Extension/Core/Type/IntegerType.php b/Extension/Core/Type/IntegerType.php index b224cac5fd..557b458838 100644 --- a/Extension/Core/Type/IntegerType.php +++ b/Extension/Core/Type/IntegerType.php @@ -38,11 +38,11 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( // default precision is locale specific (usually around 3) - 'precision' => null, - 'grouping' => false, + 'precision' => null, + 'grouping' => false, // Integer cast rounds towards 0, so do the same when displaying fractions 'rounding_mode' => \NumberFormatter::ROUND_DOWN, - 'compound' => false, + 'compound' => false, )); $resolver->setAllowedValues(array( diff --git a/Extension/Core/Type/MoneyType.php b/Extension/Core/Type/MoneyType.php index 9e36f9ce16..787557c4b9 100644 --- a/Extension/Core/Type/MoneyType.php +++ b/Extension/Core/Type/MoneyType.php @@ -52,10 +52,10 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'precision' => 2, - 'grouping' => false, - 'divisor' => 1, - 'currency' => 'EUR', - 'compound' => false, + 'grouping' => false, + 'divisor' => 1, + 'currency' => 'EUR', + 'compound' => false, )); } diff --git a/Extension/Core/Type/NumberType.php b/Extension/Core/Type/NumberType.php index beb3c89a41..2e4ba7a335 100644 --- a/Extension/Core/Type/NumberType.php +++ b/Extension/Core/Type/NumberType.php @@ -37,10 +37,10 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( // default precision is locale specific (usually around 3) - 'precision' => null, - 'grouping' => false, + 'precision' => null, + 'grouping' => false, 'rounding_mode' => \NumberFormatter::ROUND_HALFUP, - 'compound' => false, + 'compound' => false, )); $resolver->setAllowedValues(array( diff --git a/Extension/Core/Type/PasswordType.php b/Extension/Core/Type/PasswordType.php index 5a5b1635d1..8f5633c6d1 100644 --- a/Extension/Core/Type/PasswordType.php +++ b/Extension/Core/Type/PasswordType.php @@ -35,7 +35,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'always_empty' => true, - 'trim' => false, + 'trim' => false, )); } diff --git a/Extension/Core/Type/PercentType.php b/Extension/Core/Type/PercentType.php index b1df94364d..079eca0497 100644 --- a/Extension/Core/Type/PercentType.php +++ b/Extension/Core/Type/PercentType.php @@ -33,8 +33,8 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( 'precision' => 0, - 'type' => 'fractional', - 'compound' => false, + 'type' => 'fractional', + 'compound' => false, )); $resolver->setAllowedValues(array( diff --git a/Extension/Core/Type/RepeatedType.php b/Extension/Core/Type/RepeatedType.php index 67422e38f4..47a3299359 100644 --- a/Extension/Core/Type/RepeatedType.php +++ b/Extension/Core/Type/RepeatedType.php @@ -24,7 +24,7 @@ class RepeatedType extends AbstractType public function buildForm(FormBuilderInterface $builder, array $options) { // Overwrite required option for child fields - $options['first_options']['required'] = $options['required']; + $options['first_options']['required'] = $options['required']; $options['second_options']['required'] = $options['required']; if (!isset($options['options']['error_bubbling'])) { @@ -47,18 +47,18 @@ public function buildForm(FormBuilderInterface $builder, array $options) public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( - 'type' => 'text', - 'options' => array(), - 'first_options' => array(), + 'type' => 'text', + 'options' => array(), + 'first_options' => array(), 'second_options' => array(), - 'first_name' => 'first', - 'second_name' => 'second', + 'first_name' => 'first', + 'second_name' => 'second', 'error_bubbling' => false, )); $resolver->setAllowedTypes(array( - 'options' => 'array', - 'first_options' => 'array', + 'options' => 'array', + 'first_options' => 'array', 'second_options' => 'array', )); } diff --git a/Extension/Core/Type/TimeType.php b/Extension/Core/Type/TimeType.php index eee118a030..fc6362c24c 100644 --- a/Extension/Core/Type/TimeType.php +++ b/Extension/Core/Type/TimeType.php @@ -30,7 +30,7 @@ class TimeType extends AbstractType */ public function buildForm(FormBuilderInterface $builder, array $options) { - $parts = array('hour'); + $parts = array('hour'); $format = 'H'; if ($options['with_seconds'] && !$options['with_minutes']) { @@ -133,7 +133,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) public function buildView(FormView $view, FormInterface $form, array $options) { $view->vars = array_replace($view->vars, array( - 'widget' => $options['widget'], + 'widget' => $options['widget'], 'with_minutes' => $options['with_minutes'], 'with_seconds' => $options['with_seconds'], )); @@ -182,26 +182,26 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) }; $resolver->setDefaults(array( - 'hours' => range(0, 23), - 'minutes' => range(0, 59), - 'seconds' => range(0, 59), - 'widget' => 'choice', - 'input' => 'datetime', - 'with_minutes' => true, - 'with_seconds' => false, + 'hours' => range(0, 23), + 'minutes' => range(0, 59), + 'seconds' => range(0, 59), + 'widget' => 'choice', + 'input' => 'datetime', + 'with_minutes' => true, + 'with_seconds' => false, 'model_timezone' => null, - 'view_timezone' => null, - 'empty_value' => $emptyValue, + 'view_timezone' => null, + 'empty_value' => $emptyValue, // Don't modify \DateTime classes by reference, we treat // them like immutable value objects - 'by_reference' => false, + 'by_reference' => false, 'error_bubbling' => false, // If initialized with a \DateTime object, FormType initializes // this option to "\DateTime". Since the internal, normalized // representation is not \DateTime, but an array, we need to unset // this option. - 'data_class' => null, - 'compound' => $compound, + 'data_class' => null, + 'compound' => $compound, )); $resolver->setNormalizers(array( @@ -223,7 +223,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) )); $resolver->setAllowedTypes(array( - 'hours' => 'array', + 'hours' => 'array', 'minutes' => 'array', 'seconds' => 'array', )); diff --git a/Extension/Csrf/Type/FormTypeCsrfExtension.php b/Extension/Csrf/Type/FormTypeCsrfExtension.php index 845e18b2a2..e4ef174461 100644 --- a/Extension/Csrf/Type/FormTypeCsrfExtension.php +++ b/Extension/Csrf/Type/FormTypeCsrfExtension.php @@ -112,11 +112,11 @@ public function finishView(FormView $view, FormInterface $form, array $options) public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults(array( - 'csrf_protection' => $this->defaultEnabled, - 'csrf_field_name' => $this->defaultFieldName, - 'csrf_provider' => $this->defaultCsrfProvider, - 'csrf_message' => 'The CSRF token is invalid. Please try to resubmit the form.', - 'intention' => null, + 'csrf_protection' => $this->defaultEnabled, + 'csrf_field_name' => $this->defaultFieldName, + 'csrf_provider' => $this->defaultCsrfProvider, + 'csrf_message' => 'The CSRF token is invalid. Please try to resubmit the form.', + 'intention' => null, )); } diff --git a/Extension/Validator/Type/FormTypeValidatorExtension.php b/Extension/Validator/Type/FormTypeValidatorExtension.php index ae39af66fc..4f9234920c 100644 --- a/Extension/Validator/Type/FormTypeValidatorExtension.php +++ b/Extension/Validator/Type/FormTypeValidatorExtension.php @@ -60,16 +60,16 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) }; $resolver->setDefaults(array( - 'error_mapping' => array(), - 'constraints' => array(), - 'cascade_validation' => false, - 'invalid_message' => 'This value is not valid.', + 'error_mapping' => array(), + 'constraints' => array(), + 'cascade_validation' => false, + 'invalid_message' => 'This value is not valid.', 'invalid_message_parameters' => array(), - 'extra_fields_message' => 'This form should not contain extra fields.', + 'extra_fields_message' => 'This form should not contain extra fields.', )); $resolver->setNormalizers(array( - 'constraints' => $constraintsNormalizer, + 'constraints' => $constraintsNormalizer, )); } diff --git a/FormBuilder.php b/FormBuilder.php index 1c56df2a71..9511187e3b 100644 --- a/FormBuilder.php +++ b/FormBuilder.php @@ -82,7 +82,7 @@ public function add($child, $type = null, array $options = array()) // Add to "children" to maintain order $this->children[$child] = null; $this->unresolvedChildren[$child] = array( - 'type' => $type, + 'type' => $type, 'options' => $options, ); diff --git a/FormFactory.php b/FormFactory.php index a5fd9cc0c6..4a2b6d634a 100644 --- a/FormFactory.php +++ b/FormFactory.php @@ -104,7 +104,7 @@ public function createBuilderForProperty($class, $property, $data = null, array $type = $typeGuess ? $typeGuess->getType() : 'text'; $maxLength = $maxLengthGuess ? $maxLengthGuess->getValue() : null; - $pattern = $patternGuess ? $patternGuess->getValue() : null; + $pattern = $patternGuess ? $patternGuess->getValue() : null; if (null !== $pattern) { $options = array_merge(array('pattern' => $pattern), $options); diff --git a/FormView.php b/FormView.php index c2c3679f0b..f8e81ffbc2 100644 --- a/FormView.php +++ b/FormView.php @@ -24,7 +24,7 @@ class FormView implements \ArrayAccess, \IteratorAggregate, \Countable */ public $vars = array( 'value' => null, - 'attr' => array(), + 'attr' => array(), ); /** diff --git a/NativeRequestHandler.php b/NativeRequestHandler.php index 9df9066886..bc91b02756 100644 --- a/NativeRequestHandler.php +++ b/NativeRequestHandler.php @@ -184,11 +184,11 @@ private static function fixPhpFilesArray($data) foreach (array_keys($data['name']) as $key) { $files[$key] = self::fixPhpFilesArray(array( - 'error' => $data['error'][$key], - 'name' => $data['name'][$key], - 'type' => $data['type'][$key], + 'error' => $data['error'][$key], + 'name' => $data['name'][$key], + 'type' => $data['type'][$key], 'tmp_name' => $data['tmp_name'][$key], - 'size' => $data['size'][$key], + 'size' => $data['size'][$key], )); } diff --git a/Tests/AbstractDivLayoutTest.php b/Tests/AbstractDivLayoutTest.php index 21ea55833a..075d6fee15 100644 --- a/Tests/AbstractDivLayoutTest.php +++ b/Tests/AbstractDivLayoutTest.php @@ -524,7 +524,7 @@ public function testRepeatedWithCustomOptions() { $form = $this->factory->createNamed('name', 'repeated', null, array( // the global required value cannot be overridden - 'first_options' => array('label' => 'Test', 'required' => false), + 'first_options' => array('label' => 'Test', 'required' => false), 'second_options' => array('label' => 'Test2'), )); diff --git a/Tests/AbstractTableLayoutTest.php b/Tests/AbstractTableLayoutTest.php index 25fa504a53..013e13c472 100644 --- a/Tests/AbstractTableLayoutTest.php +++ b/Tests/AbstractTableLayoutTest.php @@ -399,8 +399,8 @@ public function testRepeated() public function testRepeatedWithCustomOptions() { $form = $this->factory->createNamed('name', 'repeated', 'foobar', array( - 'type' => 'password', - 'first_options' => array('label' => 'Test', 'required' => false), + 'type' => 'password', + 'first_options' => array('label' => 'Test', 'required' => false), 'second_options' => array('label' => 'Test2'), )); diff --git a/Tests/Extension/Core/EventListener/TrimListenerTest.php b/Tests/Extension/Core/EventListener/TrimListenerTest.php index 606f6a2b05..c753798432 100644 --- a/Tests/Extension/Core/EventListener/TrimListenerTest.php +++ b/Tests/Extension/Core/EventListener/TrimListenerTest.php @@ -65,7 +65,7 @@ public function testTrimUtf8Separators($hex) $symbol = mb_convert_encoding($binary, 'UTF-8', 'UCS-2BE'); $symbol = $symbol."ab\ncd".$symbol; - $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); + $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $symbol); $filter = new TrimListener(); diff --git a/Tests/Extension/Core/Type/ChoiceTypeTest.php b/Tests/Extension/Core/Type/ChoiceTypeTest.php index 0f100f24ea..895661ee4f 100644 --- a/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -94,8 +94,8 @@ public function testChoiceListAndChoicesCanBeEmpty() public function testExpandedChoicesOptionsTurnIntoChildren() { $form = $this->factory->create('choice', null, array( - 'expanded' => true, - 'choices' => $this->choices, + 'expanded' => true, + 'choices' => $this->choices, )); $this->assertCount(count($this->choices), $form, 'Each choice should become a new field'); @@ -104,10 +104,10 @@ public function testExpandedChoicesOptionsTurnIntoChildren() public function testPlaceholderPresentOnNonRequiredExpandedSingleChoice() { $form = $this->factory->create('choice', null, array( - 'multiple' => false, - 'expanded' => true, - 'required' => false, - 'choices' => $this->choices, + 'multiple' => false, + 'expanded' => true, + 'required' => false, + 'choices' => $this->choices, )); $this->assertTrue(isset($form['placeholder'])); @@ -117,10 +117,10 @@ public function testPlaceholderPresentOnNonRequiredExpandedSingleChoice() public function testPlaceholderNotPresentIfRequired() { $form = $this->factory->create('choice', null, array( - 'multiple' => false, - 'expanded' => true, - 'required' => true, - 'choices' => $this->choices, + 'multiple' => false, + 'expanded' => true, + 'required' => true, + 'choices' => $this->choices, )); $this->assertFalse(isset($form['placeholder'])); @@ -130,10 +130,10 @@ public function testPlaceholderNotPresentIfRequired() public function testPlaceholderNotPresentIfMultiple() { $form = $this->factory->create('choice', null, array( - 'multiple' => true, - 'expanded' => true, - 'required' => false, - 'choices' => $this->choices, + 'multiple' => true, + 'expanded' => true, + 'required' => false, + 'choices' => $this->choices, )); $this->assertFalse(isset($form['placeholder'])); @@ -143,9 +143,9 @@ public function testPlaceholderNotPresentIfMultiple() public function testPlaceholderNotPresentIfEmptyChoice() { $form = $this->factory->create('choice', null, array( - 'multiple' => false, - 'expanded' => true, - 'required' => false, + 'multiple' => false, + 'expanded' => true, + 'required' => false, 'choices' => array( '' => 'Empty', 1 => 'Not empty', @@ -159,8 +159,8 @@ public function testPlaceholderNotPresentIfEmptyChoice() public function testExpandedChoicesOptionsAreFlattened() { $form = $this->factory->create('choice', null, array( - 'expanded' => true, - 'choices' => $this->groupedChoices, + 'expanded' => true, + 'choices' => $this->groupedChoices, )); $flattened = array(); diff --git a/Tests/Extension/Core/Type/CollectionTypeTest.php b/Tests/Extension/Core/Type/CollectionTypeTest.php index be3ad9db5c..3dee683ddd 100644 --- a/Tests/Extension/Core/Type/CollectionTypeTest.php +++ b/Tests/Extension/Core/Type/CollectionTypeTest.php @@ -120,7 +120,7 @@ public function testResizedUpIfSubmittedWithExtraDataAndAllowAdd() public function testAllowAddButNoPrototype() { $form = $this->factory->create('collection', null, array( - 'type' => 'form', + 'type' => 'form', 'allow_add' => true, 'prototype' => false, )); @@ -132,7 +132,7 @@ public function testPrototypeMultipartPropagation() { $form = $this->factory ->create('collection', null, array( - 'type' => 'file', + 'type' => 'file', 'allow_add' => true, 'prototype' => true, )) @@ -144,7 +144,7 @@ public function testPrototypeMultipartPropagation() public function testGetDataDoesNotContainsPrototypeNameBeforeDataAreSet() { $form = $this->factory->create('collection', array(), array( - 'type' => 'file', + 'type' => 'file', 'prototype' => true, 'allow_add' => true, )); @@ -156,7 +156,7 @@ public function testGetDataDoesNotContainsPrototypeNameBeforeDataAreSet() public function testGetDataDoesNotContainsPrototypeNameAfterDataAreSet() { $form = $this->factory->create('collection', array(), array( - 'type' => 'file', + 'type' => 'file', 'allow_add' => true, 'prototype' => true, )); @@ -169,7 +169,7 @@ public function testGetDataDoesNotContainsPrototypeNameAfterDataAreSet() public function testPrototypeNameOption() { $form = $this->factory->create('collection', null, array( - 'type' => 'form', + 'type' => 'form', 'prototype' => true, 'allow_add' => true, )); @@ -177,9 +177,9 @@ public function testPrototypeNameOption() $this->assertSame('__name__', $form->getConfig()->getAttribute('prototype')->getName(), '__name__ is the default'); $form = $this->factory->create('collection', null, array( - 'type' => 'form', - 'prototype' => true, - 'allow_add' => true, + 'type' => 'form', + 'prototype' => true, + 'allow_add' => true, 'prototype_name' => '__test__', )); @@ -189,7 +189,7 @@ public function testPrototypeNameOption() public function testPrototypeDefaultLabel() { $form = $this->factory->create('collection', array(), array( - 'type' => 'file', + 'type' => 'file', 'allow_add' => true, 'prototype' => true, 'prototype_name' => '__test__', diff --git a/Tests/Extension/Core/Type/RepeatedTypeTest.php b/Tests/Extension/Core/Type/RepeatedTypeTest.php index 5db909ff21..8e56b8feb9 100644 --- a/Tests/Extension/Core/Type/RepeatedTypeTest.php +++ b/Tests/Extension/Core/Type/RepeatedTypeTest.php @@ -36,7 +36,7 @@ public function testSetData() public function testSetOptions() { $form = $this->factory->create('repeated', null, array( - 'type' => 'text', + 'type' => 'text', 'options' => array('label' => 'Global'), )); @@ -50,8 +50,8 @@ public function testSetOptionsPerChild() { $form = $this->factory->create('repeated', null, array( // the global required value cannot be overridden - 'type' => 'text', - 'first_options' => array('label' => 'Test', 'required' => false), + 'type' => 'text', + 'first_options' => array('label' => 'Test', 'required' => false), 'second_options' => array('label' => 'Test2'), )); @@ -65,7 +65,7 @@ public function testSetRequired() { $form = $this->factory->create('repeated', null, array( 'required' => false, - 'type' => 'text', + 'type' => 'text', )); $this->assertFalse($form['first']->isRequired()); @@ -78,7 +78,7 @@ public function testSetRequired() public function testSetInvalidOptions() { $this->factory->create('repeated', null, array( - 'type' => 'text', + 'type' => 'text', 'options' => 'bad value', )); } @@ -89,7 +89,7 @@ public function testSetInvalidOptions() public function testSetInvalidFirstOptions() { $this->factory->create('repeated', null, array( - 'type' => 'text', + 'type' => 'text', 'first_options' => 'bad value', )); } @@ -100,7 +100,7 @@ public function testSetInvalidFirstOptions() public function testSetInvalidSecondOptions() { $this->factory->create('repeated', null, array( - 'type' => 'text', + 'type' => 'text', 'second_options' => 'bad value', )); } @@ -143,8 +143,8 @@ public function testSetErrorBubblingIndividually() public function testSetOptionsPerChildAndOverwrite() { $form = $this->factory->create('repeated', null, array( - 'type' => 'text', - 'options' => array('label' => 'Label'), + 'type' => 'text', + 'options' => array('label' => 'Label'), 'second_options' => array('label' => 'Second label'), )); From 2d45368f9f9a9cfa369e76a000a565d41e1800be Mon Sep 17 00:00:00 2001 From: "Michael H. Arieli" Date: Mon, 10 Nov 2014 18:50:16 -0800 Subject: [PATCH 353/447] [Translations] Added missing Hebrew language trans-unit sources --- Resources/translations/validators.he.xlf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Resources/translations/validators.he.xlf b/Resources/translations/validators.he.xlf index 5198738d3f..74a71d05a3 100644 --- a/Resources/translations/validators.he.xlf +++ b/Resources/translations/validators.he.xlf @@ -11,8 +11,8 @@ הקובץ שהועלה גדול מדי. נסה להעלות קובץ קטן יותר. - The CSRF token is invalid. - אסימון CSRF אינו חוקי. + The CSRF token is invalid. Please try to resubmit the form. + אסימון CSRF אינו חוקי. אנא נסה לשלוח שוב את הטופס. From 9b180976a30c3e6f480a53b6162d9ce536667855 Mon Sep 17 00:00:00 2001 From: Daniel Wehner Date: Thu, 23 Oct 2014 14:21:59 +0200 Subject: [PATCH 354/447] Add machine readable events --- FormEvents.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/FormEvents.php b/FormEvents.php index 6c4efc5be1..2bdd585251 100644 --- a/FormEvents.php +++ b/FormEvents.php @@ -15,31 +15,52 @@ */ final class FormEvents { + /** + * @Event + */ const PRE_SUBMIT = 'form.pre_bind'; + /** + * @Event + */ const SUBMIT = 'form.bind'; + /** + * @Event + */ const POST_SUBMIT = 'form.post_bind'; + /** + * @Event + */ const PRE_SET_DATA = 'form.pre_set_data'; + /** + * @Event + */ const POST_SET_DATA = 'form.post_set_data'; /** * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link PRE_SUBMIT} instead. + * + * @Event */ const PRE_BIND = 'form.pre_bind'; /** * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link SUBMIT} instead. + * + * @Event */ const BIND = 'form.bind'; /** * @deprecated Deprecated since version 2.3, to be removed in 3.0. Use * {@link POST_SUBMIT} instead. + * + * @Event */ const POST_BIND = 'form.post_bind'; From d414d28657418896ba7a9726b2454a5f54b307cf Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Sun, 2 Nov 2014 19:53:26 +0000 Subject: [PATCH 355/447] Drop support for model_timezone and view_timezone options in TimeType and DateType. --- CHANGELOG.md | 1 + Extension/Core/Type/DateType.php | 12 ++-- Extension/Core/Type/TimeType.php | 12 ++-- Tests/Extension/Core/Type/DateTypeTest.php | 62 ++++------------- Tests/Extension/Core/Type/TimeTypeTest.php | 77 +++++----------------- 5 files changed, 39 insertions(+), 125 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 148df57314..e0fc25aa82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ CHANGELOG * added "html5" option to Date, Time and DateTimeFormType to be able to enable/disable HTML5 input date when widget option is "single_text" * added "label_format" option with possible placeholders "%name%" and "%id%" + * [BC BREAK] drop support for model_timezone and view_timezone options in TimeType and DateType 2.5.0 ------ diff --git a/Extension/Core/Type/DateType.php b/Extension/Core/Type/DateType.php index 5bc3fb157e..8a0028ce17 100644 --- a/Extension/Core/Type/DateType.php +++ b/Extension/Core/Type/DateType.php @@ -57,8 +57,8 @@ public function buildForm(FormBuilderInterface $builder, array $options) if ('single_text' === $options['widget']) { $builder->addViewTransformer(new DateTimeToLocalizedStringTransformer( - $options['model_timezone'], - $options['view_timezone'], + 'UTC', + 'UTC', $dateFormat, $timeFormat, $calendar, @@ -105,7 +105,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) ->add('month', $options['widget'], $monthOptions) ->add('day', $options['widget'], $dayOptions) ->addViewTransformer(new DateTimeToArrayTransformer( - $options['model_timezone'], $options['view_timezone'], array('year', 'month', 'day') + 'UTC', 'UTC', array('year', 'month', 'day') )) ->setAttribute('formatter', $formatter) ; @@ -113,15 +113,15 @@ public function buildForm(FormBuilderInterface $builder, array $options) if ('string' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone'], 'Y-m-d') + new DateTimeToStringTransformer('UTC', 'UTC', 'Y-m-d') )); } elseif ('timestamp' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToTimestampTransformer($options['model_timezone'], $options['model_timezone']) + new DateTimeToTimestampTransformer('UTC', 'UTC') )); } elseif ('array' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], array('year', 'month', 'day')) + new DateTimeToArrayTransformer('UTC', 'UTC', array('year', 'month', 'day')) )); } } diff --git a/Extension/Core/Type/TimeType.php b/Extension/Core/Type/TimeType.php index adff60c215..236a546dc4 100644 --- a/Extension/Core/Type/TimeType.php +++ b/Extension/Core/Type/TimeType.php @@ -48,7 +48,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) } if ('single_text' === $options['widget']) { - $builder->addViewTransformer(new DateTimeToStringTransformer($options['model_timezone'], $options['view_timezone'], $format)); + $builder->addViewTransformer(new DateTimeToStringTransformer('UTC', 'UTC', $format)); } else { $hourOptions = $minuteOptions = $secondOptions = array( 'error_bubbling' => true, @@ -109,20 +109,20 @@ public function buildForm(FormBuilderInterface $builder, array $options) $builder->add('second', $options['widget'], $secondOptions); } - $builder->addViewTransformer(new DateTimeToArrayTransformer($options['model_timezone'], $options['view_timezone'], $parts, 'text' === $options['widget'])); + $builder->addViewTransformer(new DateTimeToArrayTransformer('UTC', 'UTC', $parts, 'text' === $options['widget'])); } if ('string' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone'], 'H:i:s') + new DateTimeToStringTransformer('UTC', 'UTC', 'H:i:s') )); } elseif ('timestamp' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToTimestampTransformer($options['model_timezone'], $options['model_timezone']) + new DateTimeToTimestampTransformer('UTC', 'UTC') )); } elseif ('array' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], $parts) + new DateTimeToArrayTransformer('UTC', 'UTC', $parts) )); } } @@ -197,8 +197,6 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'input' => 'datetime', 'with_minutes' => true, 'with_seconds' => false, - 'model_timezone' => null, - 'view_timezone' => null, 'empty_value' => $emptyValue, // deprecated 'placeholder' => $placeholder, 'html5' => true, diff --git a/Tests/Extension/Core/Type/DateTypeTest.php b/Tests/Extension/Core/Type/DateTypeTest.php index 7e31afbac6..5ba37df1d0 100644 --- a/Tests/Extension/Core/Type/DateTypeTest.php +++ b/Tests/Extension/Core/Type/DateTypeTest.php @@ -17,6 +17,8 @@ class DateTypeTest extends TypeTestCase { + private $defaultTimezone; + protected function setUp() { parent::setUp(); @@ -25,6 +27,13 @@ protected function setUp() IntlTestHelper::requireFullIntl($this); \Locale::setDefault('de_AT'); + + $this->defaultTimezone = date_default_timezone_get(); + } + + protected function tearDown() + { + date_default_timezone_set($this->defaultTimezone); } /** @@ -50,8 +59,6 @@ public function testInvalidInputOption() public function testSubmitFromSingleTextDateTimeWithDefaultFormat() { $form = $this->factory->create('date', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'widget' => 'single_text', 'input' => 'datetime', )); @@ -66,8 +73,6 @@ public function testSubmitFromSingleTextDateTime() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'widget' => 'single_text', 'input' => 'datetime', )); @@ -82,8 +87,6 @@ public function testSubmitFromSingleTextString() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'widget' => 'single_text', 'input' => 'string', )); @@ -98,8 +101,6 @@ public function testSubmitFromSingleTextTimestamp() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'widget' => 'single_text', 'input' => 'timestamp', )); @@ -116,8 +117,6 @@ public function testSubmitFromSingleTextRaw() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'widget' => 'single_text', 'input' => 'array', )); @@ -137,8 +136,6 @@ public function testSubmitFromSingleTextRaw() public function testSubmitFromText() { $form = $this->factory->create('date', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'widget' => 'text', )); @@ -159,8 +156,6 @@ public function testSubmitFromText() public function testSubmitFromChoice() { $form = $this->factory->create('date', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'widget' => 'choice', )); @@ -181,8 +176,6 @@ public function testSubmitFromChoice() public function testSubmitFromChoiceEmpty() { $form = $this->factory->create('date', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'widget' => 'choice', 'required' => false, )); @@ -202,8 +195,6 @@ public function testSubmitFromChoiceEmpty() public function testSubmitFromInputDateTimeDifferentPattern() { $form = $this->factory->create('date', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'format' => 'MM*yyyy*dd', 'widget' => 'single_text', 'input' => 'datetime', @@ -218,8 +209,6 @@ public function testSubmitFromInputDateTimeDifferentPattern() public function testSubmitFromInputStringDifferentPattern() { $form = $this->factory->create('date', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'format' => 'MM*yyyy*dd', 'widget' => 'single_text', 'input' => 'string', @@ -234,8 +223,6 @@ public function testSubmitFromInputStringDifferentPattern() public function testSubmitFromInputTimestampDifferentPattern() { $form = $this->factory->create('date', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'format' => 'MM*yyyy*dd', 'widget' => 'single_text', 'input' => 'timestamp', @@ -252,8 +239,6 @@ public function testSubmitFromInputTimestampDifferentPattern() public function testSubmitFromInputRawDifferentPattern() { $form = $this->factory->create('date', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'format' => 'MM*yyyy*dd', 'widget' => 'single_text', 'input' => 'array', @@ -370,27 +355,12 @@ public function testThrowExceptionIfDaysIsInvalid() )); } - public function testSetDataWithDifferentTimezones() + public function testSetDataWithDifferentTimezoneDateTime() { - $form = $this->factory->create('date', null, array( - 'format' => \IntlDateFormatter::MEDIUM, - 'model_timezone' => 'America/New_York', - 'view_timezone' => 'Pacific/Tahiti', - 'input' => 'string', - 'widget' => 'single_text', - )); + date_default_timezone_set('Pacific/Tahiti'); - $form->setData('2010-06-02'); - - $this->assertEquals('01.06.2010', $form->getViewData()); - } - - public function testSetDataWithDifferentTimezonesDateTime() - { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, - 'model_timezone' => 'America/New_York', - 'view_timezone' => 'Pacific/Tahiti', 'input' => 'datetime', 'widget' => 'single_text', )); @@ -400,7 +370,7 @@ public function testSetDataWithDifferentTimezonesDateTime() $form->setData($dateTime); $this->assertDateTimeEquals($dateTime, $form->getData()); - $this->assertEquals('01.06.2010', $form->getViewData()); + $this->assertEquals('02.06.2010', $form->getViewData()); } public function testYearsOption() @@ -495,8 +465,6 @@ public function testIsPartiallyFilledReturnsFalseIfSingleText() $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('date', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'widget' => 'single_text', )); @@ -510,8 +478,6 @@ public function testIsPartiallyFilledReturnsFalseIfChoiceAndCompletelyEmpty() $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('date', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'widget' => 'choice', )); @@ -529,8 +495,6 @@ public function testIsPartiallyFilledReturnsFalseIfChoiceAndCompletelyFilled() $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('date', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'widget' => 'choice', )); @@ -548,8 +512,6 @@ public function testIsPartiallyFilledReturnsTrueIfChoiceAndDayEmpty() $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('date', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'widget' => 'choice', )); diff --git a/Tests/Extension/Core/Type/TimeTypeTest.php b/Tests/Extension/Core/Type/TimeTypeTest.php index 7fd145fa3e..0154c05e63 100644 --- a/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/Tests/Extension/Core/Type/TimeTypeTest.php @@ -17,18 +17,25 @@ class TimeTypeTest extends TypeTestCase { + private $defaultTimezone; + protected function setUp() { IntlTestHelper::requireIntl($this); parent::setUp(); + + $this->defaultTimezone = date_default_timezone_get(); + } + + protected function tearDown() + { + date_default_timezone_set($this->defaultTimezone); } public function testSubmitDateTime() { $form = $this->factory->create('time', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'input' => 'datetime', )); @@ -48,8 +55,6 @@ public function testSubmitDateTime() public function testSubmitString() { $form = $this->factory->create('time', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'input' => 'string', )); @@ -67,8 +72,6 @@ public function testSubmitString() public function testSubmitTimestamp() { $form = $this->factory->create('time', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'input' => 'timestamp', )); @@ -88,8 +91,6 @@ public function testSubmitTimestamp() public function testSubmitArray() { $form = $this->factory->create('time', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'input' => 'array', )); @@ -107,8 +108,6 @@ public function testSubmitArray() public function testSubmitDatetimeSingleText() { $form = $this->factory->create('time', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'input' => 'datetime', 'widget' => 'single_text', )); @@ -122,8 +121,6 @@ public function testSubmitDatetimeSingleText() public function testSubmitDatetimeSingleTextWithoutMinutes() { $form = $this->factory->create('time', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'input' => 'datetime', 'widget' => 'single_text', 'with_minutes' => false, @@ -138,8 +135,6 @@ public function testSubmitDatetimeSingleTextWithoutMinutes() public function testSubmitArraySingleText() { $form = $this->factory->create('time', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'input' => 'array', 'widget' => 'single_text', )); @@ -158,8 +153,6 @@ public function testSubmitArraySingleText() public function testSubmitArraySingleTextWithoutMinutes() { $form = $this->factory->create('time', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'input' => 'array', 'widget' => 'single_text', 'with_minutes' => false, @@ -178,8 +171,6 @@ public function testSubmitArraySingleTextWithoutMinutes() public function testSubmitArraySingleTextWithSeconds() { $form = $this->factory->create('time', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'input' => 'array', 'widget' => 'single_text', 'with_seconds' => true, @@ -200,8 +191,6 @@ public function testSubmitArraySingleTextWithSeconds() public function testSubmitStringSingleText() { $form = $this->factory->create('time', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'input' => 'string', 'widget' => 'single_text', )); @@ -215,8 +204,6 @@ public function testSubmitStringSingleText() public function testSubmitStringSingleTextWithoutMinutes() { $form = $this->factory->create('time', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'input' => 'string', 'widget' => 'single_text', 'with_minutes' => false, @@ -231,8 +218,6 @@ public function testSubmitStringSingleTextWithoutMinutes() public function testSetDataWithoutMinutes() { $form = $this->factory->create('time', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'input' => 'datetime', 'with_minutes' => false, )); @@ -245,8 +230,6 @@ public function testSetDataWithoutMinutes() public function testSetDataWithSeconds() { $form = $this->factory->create('time', null, array( - 'model_timezone' => 'UTC', - 'view_timezone' => 'UTC', 'input' => 'datetime', 'with_seconds' => true, )); @@ -256,53 +239,23 @@ public function testSetDataWithSeconds() $this->assertEquals(array('hour' => 3, 'minute' => 4, 'second' => 5), $form->getViewData()); } - public function testSetDataDifferentTimezones() + public function testSetDataWithTimezoneDateTime() { - $form = $this->factory->create('time', null, array( - 'model_timezone' => 'America/New_York', - 'view_timezone' => 'Asia/Hong_Kong', - 'input' => 'string', - 'with_seconds' => true, - )); - - $dateTime = new \DateTime('2013-01-01 12:04:05'); - $dateTime->setTimezone(new \DateTimeZone('America/New_York')); + date_default_timezone_set('Asia/Hong_Kong'); - $form->setData($dateTime->format('H:i:s')); - - $outputTime = clone $dateTime; - $outputTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); - - $displayedData = array( - 'hour' => (int) $outputTime->format('H'), - 'minute' => (int) $outputTime->format('i'), - 'second' => (int) $outputTime->format('s'), - ); - - $this->assertEquals($displayedData, $form->getViewData()); - } - - public function testSetDataDifferentTimezonesDateTime() - { $form = $this->factory->create('time', null, array( - 'model_timezone' => 'America/New_York', - 'view_timezone' => 'Asia/Hong_Kong', 'input' => 'datetime', 'with_seconds' => true, )); - $dateTime = new \DateTime('12:04:05'); - $dateTime->setTimezone(new \DateTimeZone('America/New_York')); + $dateTime = new \DateTime('12:04:05', new \DateTimeZone('America/New_York')); $form->setData($dateTime); - $outputTime = clone $dateTime; - $outputTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); - $displayedData = array( - 'hour' => (int) $outputTime->format('H'), - 'minute' => (int) $outputTime->format('i'), - 'second' => (int) $outputTime->format('s'), + 'hour' => 12, + 'minute' => 4, + 'second' => 5, ); $this->assertDateTimeEquals($dateTime, $form->getData()); From 11edd97b8aa9ca9f94abb7a9f405bfd59839f68e Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 16 Nov 2014 19:10:38 +0100 Subject: [PATCH 356/447] *_timezone changes also affect the BirthdayType --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0fc25aa82..cd5f619b25 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ CHANGELOG * added "html5" option to Date, Time and DateTimeFormType to be able to enable/disable HTML5 input date when widget option is "single_text" * added "label_format" option with possible placeholders "%name%" and "%id%" - * [BC BREAK] drop support for model_timezone and view_timezone options in TimeType and DateType + * [BC BREAK] drop support for model_timezone and view_timezone options in TimeType, DateType and BirthdayType 2.5.0 ------ From 5c8131c0f67b1a48a7038703e7c498dcbd3486cf Mon Sep 17 00:00:00 2001 From: Jerome TAMARELLE Date: Mon, 17 Nov 2014 14:53:37 +0100 Subject: [PATCH 357/447] [Form] Add doc for FormEvents --- FormEvents.php | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/FormEvents.php b/FormEvents.php index 2bdd585251..54c72271c7 100644 --- a/FormEvents.php +++ b/FormEvents.php @@ -16,26 +16,57 @@ final class FormEvents { /** + * The PRE_SUBMIT event is dispatched at the beginning of the Form::submit() method. + * + * It can be used to: + * - Change data from the request, before submitting the data to the form. + * - Add or remove form fields, before submitting the data to the form. + * The event listener method receives a Symfony\Component\Form\FormEvent instance. + * * @Event */ const PRE_SUBMIT = 'form.pre_bind'; /** + * The SUBMIT event is dispatched just before the Form::submit() method + * transforms back the normalized data to the model and view data. + * + * It can be used to change data from the normalized representation of the data. + * The event listener method receives a Symfony\Component\Form\FormEvent instance. + * * @Event */ const SUBMIT = 'form.bind'; /** + * The FormEvents::POST_SUBMIT event is dispatched after the Form::submit() + * once the model and view data have been denormalized. + * + * It can be used to fetch data after denormalization. + * The event listener method receives a Symfony\Component\Form\FormEvent instance. + * * @Event */ const POST_SUBMIT = 'form.post_bind'; /** + * The FormEvents::PRE_SET_DATA event is dispatched at the beginning of the Form::setData() method. + * + * It can be used to: + * - Modify the data given during pre-population; + * - Modify a form depending on the pre-populated data (adding or removing fields dynamically). + * The event listener method receives a Symfony\Component\Form\FormEvent instance. + * * @Event */ const PRE_SET_DATA = 'form.pre_set_data'; /** + * The FormEvents::POST_SET_DATA event is dispatched at the end of the Form::setData() method. + * + * This event is mostly here for reading data after having pre-populated the form. + * The event listener method receives a Symfony\Component\Form\FormEvent instance. + * * @Event */ const POST_SET_DATA = 'form.post_set_data'; From cfaf3be171f4378b98098d577a90af38b0bf4934 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 17 Nov 2014 15:32:09 +0100 Subject: [PATCH 358/447] compare version using PHP_VERSION_ID To let opcode caches optimize cached code, the `PHP_VERSION_ID` constant is used to detect the current PHP version instead of calling `version_compare()` with `PHP_VERSION`. --- .../Core/DataTransformer/DateTimeToStringTransformer.php | 2 +- Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php | 2 +- .../Core/DataTransformer/DateTimeToStringTransformerTest.php | 4 ++-- Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.php | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Extension/Core/DataTransformer/DateTimeToStringTransformer.php b/Extension/Core/DataTransformer/DateTimeToStringTransformer.php index 11ffd3791d..4a84e01a52 100644 --- a/Extension/Core/DataTransformer/DateTimeToStringTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToStringTransformer.php @@ -69,7 +69,7 @@ public function __construct($inputTimezone = null, $outputTimezone = null, $form // The pipe in the parser pattern only works as of PHP 5.3.7 // See http://bugs.php.net/54316 $this->parseUsingPipe = null === $parseUsingPipe - ? version_compare(phpversion(), '5.3.7', '>=') + ? PHP_VERSION_ID >= 50307 : $parseUsingPipe; // See http://php.net/manual/en/datetime.createfromformat.php diff --git a/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php b/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php index f0a74b4962..6b4ff984af 100644 --- a/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php +++ b/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php @@ -65,7 +65,7 @@ public function isCsrfTokenValid($intention, $token) */ protected function getSessionId() { - if (version_compare(PHP_VERSION, '5.4', '>=')) { + if (PHP_VERSION_ID >= 50400) { if (PHP_SESSION_NONE === session_status()) { session_start(); } diff --git a/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php index d6a6568b86..dbcdad0f96 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php @@ -60,7 +60,7 @@ public function dataProvider() ); // This test will fail < 5.3.9 - see https://bugs.php.net/51994 - if (version_compare(phpversion(), '5.3.9', '>=')) { + if (PHP_VERSION_ID >= 50309) { $data[] = array('Y-z', '2010-33', '2010-02-03 00:00:00 UTC'); } @@ -111,7 +111,7 @@ public function testTransformExpectsDateTime() */ public function testReverseTransformUsingPipe($format, $input, $output) { - if (version_compare(phpversion(), '5.3.7', '<')) { + if (PHP_VERSION_ID < 50307) { $this->markTestSkipped('Pipe usage requires PHP 5.3.7 or newer.'); } diff --git a/Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.php b/Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.php index a99b544406..3cf62f8db3 100644 --- a/Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.php +++ b/Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.php @@ -49,7 +49,7 @@ public function testGenerateCsrfTokenOnUnstartedSession() { session_id('touti'); - if (!version_compare(PHP_VERSION, '5.4', '>=')) { + if (PHP_VERSION_ID < 50400) { $this->markTestSkipped('This test requires PHP >= 5.4'); } From a4fd4f7d2649588c97ae35f751aa838ee81be610 Mon Sep 17 00:00:00 2001 From: Farhad Safarov Date: Thu, 13 Nov 2014 13:39:39 +0200 Subject: [PATCH 359/447] Azerbaijani locale --- Resources/translations/validators.az.xlf | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 Resources/translations/validators.az.xlf diff --git a/Resources/translations/validators.az.xlf b/Resources/translations/validators.az.xlf new file mode 100644 index 0000000000..69e447385a --- /dev/null +++ b/Resources/translations/validators.az.xlf @@ -0,0 +1,19 @@ + + + + + + This form should not contain extra fields. + Bu formada əlavə sahə olmamalıdır. + + + The uploaded file was too large. Please try to upload a smaller file. + Yüklənən fayl çox böyükdür. Lütfən daha kiçik fayl yükləyin. + + + The CSRF token is invalid. Please try to resubmit the form. + CSRF nişanı yanlışdır. Lütfen formanı yenidən göndərin. + + + + From 69c7062975d107ef9b3035badc8ea50661808806 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Mon, 24 Nov 2014 13:25:40 +0100 Subject: [PATCH 360/447] Rename Symfony2 to Symfony --- Extension/Csrf/CsrfProvider/SessionCsrfProvider.php | 2 +- Extension/Validator/ValidatorExtension.php | 2 +- Tests/FormConfigTest.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Extension/Csrf/CsrfProvider/SessionCsrfProvider.php b/Extension/Csrf/CsrfProvider/SessionCsrfProvider.php index ea1fa58547..52c9685ee1 100644 --- a/Extension/Csrf/CsrfProvider/SessionCsrfProvider.php +++ b/Extension/Csrf/CsrfProvider/SessionCsrfProvider.php @@ -14,7 +14,7 @@ use Symfony\Component\HttpFoundation\Session\Session; /** - * This provider uses a Symfony2 Session object to retrieve the user's + * This provider uses a Symfony Session object to retrieve the user's * session ID. * * @see DefaultCsrfProvider diff --git a/Extension/Validator/ValidatorExtension.php b/Extension/Validator/ValidatorExtension.php index 572a4ac938..9affa1a4d7 100644 --- a/Extension/Validator/ValidatorExtension.php +++ b/Extension/Validator/ValidatorExtension.php @@ -17,7 +17,7 @@ use Symfony\Component\Validator\Constraints\Valid; /** - * Extension supporting the Symfony2 Validator component in forms. + * Extension supporting the Symfony Validator component in forms. * * @author Bernhard Schussek */ diff --git a/Tests/FormConfigTest.php b/Tests/FormConfigTest.php index 961dfd3367..b77632c505 100644 --- a/Tests/FormConfigTest.php +++ b/Tests/FormConfigTest.php @@ -49,7 +49,7 @@ public function getHtml4Ids() array('9', true), // Contrary to the HTML4 spec, we allow names starting with an // underscore, since this is already a widely used practice in - // Symfony2. + // Symfony. // For root forms, leading underscores will be stripped from the // "id" attribute to produce valid HTML4. array('_', true), From f807a1b56f5c75cecaf29b2ab8662d1f7607c68b Mon Sep 17 00:00:00 2001 From: alfonso Date: Sat, 29 Nov 2014 11:49:05 +0100 Subject: [PATCH 361/447] Fix incorrect spanish translation --- Resources/translations/validators.es.xlf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/translations/validators.es.xlf b/Resources/translations/validators.es.xlf index 175096ae8a..b609e53e56 100644 --- a/Resources/translations/validators.es.xlf +++ b/Resources/translations/validators.es.xlf @@ -12,7 +12,7 @@ The CSRF token is invalid. Please try to resubmit the form. - El token CSRF no es válido. Por favor, pruebe de enviar nuevamente el formulario. + El token CSRF no es válido. Por favor, pruebe a enviar nuevamente el formulario. From 7db37bb35755f2a05b74639552fd134e119bdb90 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Sun, 30 Nov 2014 13:33:44 +0000 Subject: [PATCH 362/447] Docblock fixes --- AbstractRendererEngine.php | 4 +-- Extension/Core/ChoiceList/ChoiceList.php | 20 ++++++------ .../Core/ChoiceList/ObjectChoiceList.php | 10 +++--- .../Core/ChoiceList/SimpleChoiceList.php | 10 +++--- .../DateTimeToLocalizedStringTransformer.php | 12 +++---- .../DateTimeToStringTransformer.php | 8 ++--- .../CsrfProvider/CsrfProviderInterface.php | 2 +- .../Templating/TemplatingRendererEngine.php | 4 +-- .../Validator/Constraints/FormValidator.php | 6 ++-- .../Validator/ViolationMapper/MappingRule.php | 4 +-- .../ViolationMapper/ViolationMapper.php | 4 +-- .../ViolationMapperInterface.php | 8 ++--- .../ViolationMapper/ViolationPath.php | 4 +-- Form.php | 4 +-- FormBuilder.php | 2 +- FormConfigBuilderInterface.php | 10 +++--- FormInterface.php | 32 +++++++++---------- FormRendererEngineInterface.php | 2 +- FormView.php | 2 +- PreloadedExtension.php | 4 +-- Tests/AbstractFormTest.php | 2 +- .../DataMapper/PropertyPathMapperTest.php | 3 +- Tests/ResolvedFormTypeTest.php | 2 +- Util/FormUtil.php | 2 +- 24 files changed, 81 insertions(+), 80 deletions(-) diff --git a/AbstractRendererEngine.php b/AbstractRendererEngine.php index 764fe1de70..00bf85401c 100644 --- a/AbstractRendererEngine.php +++ b/AbstractRendererEngine.php @@ -131,7 +131,7 @@ public function getResourceHierarchyLevel(FormView $view, array $blockNameHierar * @param FormView $view The form view for finding the applying themes. * @param string $blockName The name of the block to load. * - * @return bool True if the resource could be loaded, false otherwise. + * @return bool True if the resource could be loaded, false otherwise. */ abstract protected function loadResourceForBlockName($cacheKey, FormView $view, $blockName); @@ -149,7 +149,7 @@ abstract protected function loadResourceForBlockName($cacheKey, FormView $view, * @param int $hierarchyLevel The level in the block hierarchy that * should be loaded. * - * @return bool True if the resource could be loaded, false otherwise. + * @return bool True if the resource could be loaded, false otherwise. */ private function loadResourceForBlockNameHierarchy($cacheKey, FormView $view, array $blockNameHierarchy, $hierarchyLevel) { diff --git a/Extension/Core/ChoiceList/ChoiceList.php b/Extension/Core/ChoiceList/ChoiceList.php index db21fc2c99..02b59f6822 100644 --- a/Extension/Core/ChoiceList/ChoiceList.php +++ b/Extension/Core/ChoiceList/ChoiceList.php @@ -69,16 +69,16 @@ class ChoiceList implements ChoiceListInterface /** * Creates a new choice list. * - * @param array|\Traversable $choices The array of choices. Choices may also be given - * as hierarchy of unlimited depth. Hierarchies are - * created by creating nested arrays. The title of - * the sub-hierarchy can be stored in the array - * key pointing to the nested array. The topmost - * level of the hierarchy may also be a \Traversable. - * @param array $labels The array of labels. The structure of this array - * should match the structure of $choices. - * @param array $preferredChoices A flat array of choices that should be - * presented to the user with priority. + * @param array|\Traversable $choices The array of choices. Choices may also be given + * as hierarchy of unlimited depth. Hierarchies are + * created by creating nested arrays. The title of + * the sub-hierarchy can be stored in the array + * key pointing to the nested array. The topmost + * level of the hierarchy may also be a \Traversable. + * @param array $labels The array of labels. The structure of this array + * should match the structure of $choices. + * @param array $preferredChoices A flat array of choices that should be + * presented to the user with priority. * * @throws UnexpectedTypeException If the choices are not an array or \Traversable. */ diff --git a/Extension/Core/ChoiceList/ObjectChoiceList.php b/Extension/Core/ChoiceList/ObjectChoiceList.php index 14c6f238d3..6db1e0fa50 100644 --- a/Extension/Core/ChoiceList/ObjectChoiceList.php +++ b/Extension/Core/ChoiceList/ObjectChoiceList.php @@ -64,23 +64,23 @@ class ObjectChoiceList extends ChoiceList /** * Creates a new object choice list. * - * @param array|\Traversable $choices The array of choices. Choices may also be given + * @param array|\Traversable $choices The array of choices. Choices may also be given * as hierarchy of unlimited depth by creating nested * arrays. The title of the sub-hierarchy can be * stored in the array key pointing to the nested * array. The topmost level of the hierarchy may also * be a \Traversable. - * @param string $labelPath A property path pointing to the property used + * @param string $labelPath A property path pointing to the property used * for the choice labels. The value is obtained * by calling the getter on the object. If the * path is NULL, the object's __toString() method * is used instead. - * @param array $preferredChoices A flat array of choices that should be + * @param array $preferredChoices A flat array of choices that should be * presented to the user with priority. - * @param string $groupPath A property path pointing to the property used + * @param string $groupPath A property path pointing to the property used * to group the choices. Only allowed if * the choices are given as flat array. - * @param string $valuePath A property path pointing to the property used + * @param string $valuePath A property path pointing to the property used * for the choice values. If not given, integers * are generated instead. * @param PropertyAccessorInterface $propertyAccessor The reflection graph for reading property paths. diff --git a/Extension/Core/ChoiceList/SimpleChoiceList.php b/Extension/Core/ChoiceList/SimpleChoiceList.php index 7a5fb346ce..e071bb4fd2 100644 --- a/Extension/Core/ChoiceList/SimpleChoiceList.php +++ b/Extension/Core/ChoiceList/SimpleChoiceList.php @@ -34,11 +34,11 @@ class SimpleChoiceList extends ChoiceList /** * Creates a new simple choice list. * - * @param array $choices The array of choices with the choices as keys and - * the labels as values. Choices may also be given - * as hierarchy of unlimited depth by creating nested - * arrays. The title of the sub-hierarchy is stored - * in the array key pointing to the nested array. + * @param array $choices The array of choices with the choices as keys and + * the labels as values. Choices may also be given + * as hierarchy of unlimited depth by creating nested + * arrays. The title of the sub-hierarchy is stored + * in the array key pointing to the nested array. * @param array $preferredChoices A flat array of choices that should be * presented to the user with priority. */ diff --git a/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php index e992b01fc1..edcd6746cf 100644 --- a/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php @@ -32,12 +32,12 @@ class DateTimeToLocalizedStringTransformer extends BaseDateTimeTransformer * * @see BaseDateTimeTransformer::formats for available format options * - * @param string $inputTimezone The name of the input timezone - * @param string $outputTimezone The name of the output timezone - * @param int $dateFormat The date format - * @param int $timeFormat The time format - * @param int $calendar One of the \IntlDateFormatter calendar constants - * @param string $pattern A pattern to pass to \IntlDateFormatter + * @param string $inputTimezone The name of the input timezone + * @param string $outputTimezone The name of the output timezone + * @param int $dateFormat The date format + * @param int $timeFormat The time format + * @param int $calendar One of the \IntlDateFormatter calendar constants + * @param string $pattern A pattern to pass to \IntlDateFormatter * * @throws UnexpectedTypeException If a format is not supported or if a timezone is not a string */ diff --git a/Extension/Core/DataTransformer/DateTimeToStringTransformer.php b/Extension/Core/DataTransformer/DateTimeToStringTransformer.php index 4a84e01a52..4dd3a03bbc 100644 --- a/Extension/Core/DataTransformer/DateTimeToStringTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToStringTransformer.php @@ -53,10 +53,10 @@ class DateTimeToStringTransformer extends BaseDateTimeTransformer * * @see \DateTime::format() for supported formats * - * @param string $inputTimezone The name of the input timezone - * @param string $outputTimezone The name of the output timezone - * @param string $format The date format - * @param bool $parseUsingPipe Whether to parse by appending a pipe "|" to the parse format + * @param string $inputTimezone The name of the input timezone + * @param string $outputTimezone The name of the output timezone + * @param string $format The date format + * @param bool $parseUsingPipe Whether to parse by appending a pipe "|" to the parse format * * @throws UnexpectedTypeException if a timezone is not a string */ diff --git a/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php b/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php index b1f255e35e..e7e2cc290a 100644 --- a/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php +++ b/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php @@ -43,7 +43,7 @@ public function generateCsrfToken($intention); * @param string $intention The intention used when generating the CSRF token * @param string $token The token supplied by the browser * - * @return bool Whether the token supplied by the browser is correct + * @return bool Whether the token supplied by the browser is correct */ public function isCsrfTokenValid($intention, $token); } diff --git a/Extension/Templating/TemplatingRendererEngine.php b/Extension/Templating/TemplatingRendererEngine.php index 74790ba330..a9003e0032 100644 --- a/Extension/Templating/TemplatingRendererEngine.php +++ b/Extension/Templating/TemplatingRendererEngine.php @@ -52,7 +52,7 @@ public function renderBlock(FormView $view, $resource, $blockName, array $variab * @param FormView $view The form view for finding the applying themes. * @param string $blockName The name of the block to load. * - * @return bool True if the resource could be loaded, false otherwise. + * @return bool True if the resource could be loaded, false otherwise. */ protected function loadResourceForBlockName($cacheKey, FormView $view, $blockName) { @@ -110,7 +110,7 @@ protected function loadResourceForBlockName($cacheKey, FormView $view, $blockNam * @param string $blockName The name of the block to load a resource for. * @param mixed $theme The theme to load the block from. * - * @return bool True if the resource could be loaded, false otherwise. + * @return bool True if the resource could be loaded, false otherwise. */ protected function loadResourceFromTheme($cacheKey, $blockName, $theme) { diff --git a/Extension/Validator/Constraints/FormValidator.php b/Extension/Validator/Constraints/FormValidator.php index 2851016f40..f862970a7f 100644 --- a/Extension/Validator/Constraints/FormValidator.php +++ b/Extension/Validator/Constraints/FormValidator.php @@ -101,9 +101,9 @@ public function validate($form, Constraint $constraint) /** * Returns whether the data of a form may be walked. * - * @param FormInterface $form The form to test. + * @param FormInterface $form The form to test. * - * @return bool Whether the graph walker may walk the data. + * @return bool Whether the graph walker may walk the data. */ private static function allowDataWalking(FormInterface $form) { @@ -133,7 +133,7 @@ private static function allowDataWalking(FormInterface $form) /** * Returns the validation groups of the given form. * - * @param FormInterface $form The form. + * @param FormInterface $form The form. * * @return array The validation groups. */ diff --git a/Extension/Validator/ViolationMapper/MappingRule.php b/Extension/Validator/ViolationMapper/MappingRule.php index ce48e77c24..48b5ceace6 100644 --- a/Extension/Validator/ViolationMapper/MappingRule.php +++ b/Extension/Validator/ViolationMapper/MappingRule.php @@ -55,7 +55,7 @@ public function getOrigin() * If the rule matches, the form mapped by the rule is returned. * Otherwise this method returns false. * - * @param string $propertyPath The property path to match against the rule. + * @param string $propertyPath The property path to match against the rule. * * @return null|FormInterface The mapped form or null. */ @@ -71,7 +71,7 @@ public function match($propertyPath) * * @param string $propertyPath The property path to match against the rule. * - * @return bool Whether the property path is a prefix of the rule or not. + * @return bool Whether the property path is a prefix of the rule or not. */ public function isPrefix($propertyPath) { diff --git a/Extension/Validator/ViolationMapper/ViolationMapper.php b/Extension/Validator/ViolationMapper/ViolationMapper.php index 220b3aadfc..7686809588 100644 --- a/Extension/Validator/ViolationMapper/ViolationMapper.php +++ b/Extension/Validator/ViolationMapper/ViolationMapper.php @@ -228,8 +228,8 @@ private function matchChild(FormInterface $form, PropertyPathIteratorInterface $ /** * Reconstructs a property path from a violation path and a form tree. * - * @param ViolationPath $violationPath The violation path. - * @param FormInterface $origin The root form of the tree. + * @param ViolationPath $violationPath The violation path. + * @param FormInterface $origin The root form of the tree. * * @return RelativePath The reconstructed path. */ diff --git a/Extension/Validator/ViolationMapper/ViolationMapperInterface.php b/Extension/Validator/ViolationMapper/ViolationMapperInterface.php index e53046caf5..fb56a2bad2 100644 --- a/Extension/Validator/ViolationMapper/ViolationMapperInterface.php +++ b/Extension/Validator/ViolationMapper/ViolationMapperInterface.php @@ -23,11 +23,11 @@ interface ViolationMapperInterface * Maps a constraint violation to a form in the form tree under * the given form. * - * @param ConstraintViolation $violation The violation to map. - * @param FormInterface $form The root form of the tree - * to map it to. + * @param ConstraintViolation $violation The violation to map. + * @param FormInterface $form The root form of the tree + * to map it to. * @param bool $allowNonSynchronized Whether to allow - * mapping to non-synchronized forms. + * mapping to non-synchronized forms. */ public function mapViolation(ConstraintViolation $violation, FormInterface $form, $allowNonSynchronized = false); } diff --git a/Extension/Validator/ViolationMapper/ViolationPath.php b/Extension/Validator/ViolationMapper/ViolationPath.php index 1cb1baf025..9fa318ac3d 100644 --- a/Extension/Validator/ViolationMapper/ViolationPath.php +++ b/Extension/Validator/ViolationMapper/ViolationPath.php @@ -206,9 +206,9 @@ public function isIndex($index) * In this example, "address" and "office" map to forms, while * "street does not. * - * @param int $index The element index. + * @param int $index The element index. * - * @return bool Whether the element maps to a form. + * @return bool Whether the element maps to a form. * * @throws OutOfBoundsException If the offset is invalid. */ diff --git a/Form.php b/Form.php index 3f3fe88241..868140d173 100644 --- a/Form.php +++ b/Form.php @@ -782,7 +782,7 @@ public function getErrors() * * This method should only be used to help debug a form. * - * @param int $level The indentation level (used internally) + * @param int $level The indentation level (used internally) * * @return string A string representation of all errors */ @@ -992,7 +992,7 @@ public function getIterator() /** * Returns the number of form children (implements the \Countable interface). * - * @return int The number of embedded form children + * @return int The number of embedded form children */ public function count() { diff --git a/FormBuilder.php b/FormBuilder.php index 9511187e3b..9437dad1c1 100644 --- a/FormBuilder.php +++ b/FormBuilder.php @@ -245,7 +245,7 @@ public function getIterator() /** * Converts an unresolved child into a {@link FormBuilder} instance. * - * @param string $name The name of the unresolved child. + * @param string $name The name of the unresolved child. * * @return FormBuilder The created instance. */ diff --git a/FormConfigBuilderInterface.php b/FormConfigBuilderInterface.php index 50793a2c49..ad8bf69328 100644 --- a/FormConfigBuilderInterface.php +++ b/FormConfigBuilderInterface.php @@ -50,7 +50,7 @@ public function addEventSubscriber(EventSubscriberInterface $subscriber); * view to the normalized format. * * @param DataTransformerInterface $viewTransformer - * @param bool $forcePrepend if set to true, prepend instead of appending + * @param bool $forcePrepend if set to true, prepend instead of appending * * @return self The configuration object. */ @@ -72,7 +72,7 @@ public function resetViewTransformers(); * normalized to the model format. * * @param DataTransformerInterface $modelTransformer - * @param bool $forceAppend if set to true, append instead of prepending + * @param bool $forceAppend if set to true, append instead of prepending * * @return self The configuration object. */ @@ -153,8 +153,8 @@ public function setRequired($required); * Sets the property path that the form should be mapped to. * * @param null|string|PropertyPathInterface $propertyPath - * The property path or null if the path should be set - * automatically based on the form's name. + * The property path or null if the path should be set + * automatically based on the form's name. * * @return self The configuration object. */ @@ -174,7 +174,7 @@ public function setMapped($mapped); * Sets whether the form's data should be modified by reference. * * @param bool $byReference Whether the data should be - * modified by reference. + * modified by reference. * * @return self The configuration object. */ diff --git a/FormInterface.php b/FormInterface.php index 67dbb2319b..1a353dcabc 100644 --- a/FormInterface.php +++ b/FormInterface.php @@ -21,13 +21,13 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable /** * Sets the parent form. * - * @param FormInterface|null $parent The parent form or null if it's the root. + * @param FormInterface|null $parent The parent form or null if it's the root. * * @return FormInterface The form instance * * @throws Exception\AlreadySubmittedException If the form has already been submitted. - * @throws Exception\LogicException When trying to set a parent for a form with - * an empty name. + * @throws Exception\LogicException When trying to set a parent for a form with + * an empty name. */ public function setParent(FormInterface $parent = null); @@ -41,15 +41,15 @@ public function getParent(); /** * Adds or replaces a child to the form. * - * @param FormInterface|string|int $child The FormInterface instance or the name of the child. - * @param string|null $type The child's type, if a name was passed. - * @param array $options The child's options, if a name was passed. + * @param FormInterface|string|int $child The FormInterface instance or the name of the child. + * @param string|null $type The child's type, if a name was passed. + * @param array $options The child's options, if a name was passed. * * @return FormInterface The form instance * - * @throws Exception\AlreadySubmittedException If the form has already been submitted. - * @throws Exception\LogicException When trying to add a child to a non-compound form. - * @throws Exception\UnexpectedTypeException If $child or $type has an unexpected type. + * @throws Exception\AlreadySubmittedException If the form has already been submitted. + * @throws Exception\LogicException When trying to add a child to a non-compound form. + * @throws Exception\UnexpectedTypeException If $child or $type has an unexpected type. */ public function add($child, $type = null, array $options = array()); @@ -76,7 +76,7 @@ public function has($name); /** * Removes a child from the form. * - * @param string $name The name of the child to remove + * @param string $name The name of the child to remove * * @return FormInterface The form instance * @@ -101,14 +101,14 @@ public function getErrors(); /** * Updates the form with default data. * - * @param mixed $modelData The data formatted as expected for the underlying object + * @param mixed $modelData The data formatted as expected for the underlying object * * @return FormInterface The form instance * * @throws Exception\AlreadySubmittedException If the form has already been submitted. - * @throws Exception\LogicException If listeners try to call setData in a cycle. Or if - * the view data does not match the expected type - * according to {@link FormConfigInterface::getDataClass}. + * @throws Exception\LogicException If listeners try to call setData in a cycle. Or if + * the view data does not match the expected type + * according to {@link FormConfigInterface::getDataClass}. */ public function setData($modelData); @@ -152,7 +152,7 @@ public function getConfig(); /** * Returns whether the form is submitted. * - * @return bool true if the form is submitted, false otherwise + * @return bool true if the form is submitted, false otherwise */ public function isSubmitted(); @@ -173,7 +173,7 @@ public function getPropertyPath(); /** * Adds an error to this form. * - * @param FormError $error + * @param FormError $error * * @return FormInterface The form instance */ diff --git a/FormRendererEngineInterface.php b/FormRendererEngineInterface.php index 31528e0531..b49ec9cc8a 100644 --- a/FormRendererEngineInterface.php +++ b/FormRendererEngineInterface.php @@ -120,7 +120,7 @@ public function getResourceForBlockNameHierarchy(FormView $view, array $blockNam * looking. Level 0 indicates the root block, i.e. * the first element of $blockNameHierarchy. * - * @return int|bool The hierarchy level or false, if no resource was found. + * @return int|bool The hierarchy level or false, if no resource was found. */ public function getResourceHierarchyLevel(FormView $view, array $blockNameHierarchy, $hierarchyLevel); diff --git a/FormView.php b/FormView.php index f8e81ffbc2..dc3422473a 100644 --- a/FormView.php +++ b/FormView.php @@ -58,7 +58,7 @@ public function __construct(FormView $parent = null) /** * Returns whether the view was already rendered. * - * @return bool Whether this view's widget is rendered. + * @return bool Whether this view's widget is rendered. */ public function isRendered() { diff --git a/PreloadedExtension.php b/PreloadedExtension.php index 804841e7b7..f70ca8d455 100644 --- a/PreloadedExtension.php +++ b/PreloadedExtension.php @@ -38,9 +38,9 @@ class PreloadedExtension implements FormExtensionInterface /** * Creates a new preloaded extension. * - * @param FormTypeInterface[] $types The types that the extension should support. + * @param FormTypeInterface[] $types The types that the extension should support. * @param array[FormTypeExtensionInterface[]] typeExtensions The type extensions that the extension should support. - * @param FormTypeGuesserInterface|null $typeGuesser The guesser that the extension should support. + * @param FormTypeGuesserInterface|null $typeGuesser The guesser that the extension should support. */ public function __construct(array $types, array $typeExtensions, FormTypeGuesserInterface $typeGuesser = null) { diff --git a/Tests/AbstractFormTest.php b/Tests/AbstractFormTest.php index 77b0188a03..76167b2dad 100644 --- a/Tests/AbstractFormTest.php +++ b/Tests/AbstractFormTest.php @@ -70,7 +70,7 @@ protected function getBuilder($name = 'name', EventDispatcherInterface $dispatch } /** - * @param string $name + * @param string $name * * @return \PHPUnit_Framework_MockObject_MockObject */ diff --git a/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php b/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php index 06a2cb088f..d6cd476386 100644 --- a/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php +++ b/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php @@ -61,7 +61,8 @@ private function getPropertyPath($path) /** * @param FormConfigInterface $config - * @param bool $synchronized + * @param bool $synchronized + * * @return \PHPUnit_Framework_MockObject_MockObject */ private function getForm(FormConfigInterface $config, $synchronized = true, $submitted = true) diff --git a/Tests/ResolvedFormTypeTest.php b/Tests/ResolvedFormTypeTest.php index bb32a24122..5aa0d357fd 100644 --- a/Tests/ResolvedFormTypeTest.php +++ b/Tests/ResolvedFormTypeTest.php @@ -269,7 +269,7 @@ private function getMockFormFactory() /** * @param string $name - * @param array $options + * @param array $options * * @return FormBuilder */ diff --git a/Util/FormUtil.php b/Util/FormUtil.php index af6ac4a643..afa5994047 100644 --- a/Util/FormUtil.php +++ b/Util/FormUtil.php @@ -30,7 +30,7 @@ private function __construct() * a form and needs to be consistent. PHP's keyword `empty` cannot * be used as it also considers 0 and "0" to be empty. * - * @param mixed $data + * @param mixed $data * * @return bool */ From bf85329817dd9150d386900c89a089c9992cb629 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Tue, 2 Dec 2014 19:42:47 +0000 Subject: [PATCH 363/447] PSR-2 fixes --- Extension/Core/DataTransformer/ArrayToPartsTransformer.php | 4 ++-- Tests/Extension/Validator/ValidatorTypeGuesserTest.php | 2 +- .../Validator/ViolationMapper/ViolationMapperTest.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Extension/Core/DataTransformer/ArrayToPartsTransformer.php b/Extension/Core/DataTransformer/ArrayToPartsTransformer.php index 6cc3a836e5..6929fb8867 100644 --- a/Extension/Core/DataTransformer/ArrayToPartsTransformer.php +++ b/Extension/Core/DataTransformer/ArrayToPartsTransformer.php @@ -32,7 +32,7 @@ public function transform($array) $array = array(); } - if (!is_array($array) ) { + if (!is_array($array)) { throw new TransformationFailedException('Expected an array.'); } @@ -51,7 +51,7 @@ public function transform($array) public function reverseTransform($array) { - if (!is_array($array) ) { + if (!is_array($array)) { throw new TransformationFailedException('Expected an array.'); } diff --git a/Tests/Extension/Validator/ValidatorTypeGuesserTest.php b/Tests/Extension/Validator/ValidatorTypeGuesserTest.php index 0e3934bc9d..fdaab2f2f8 100644 --- a/Tests/Extension/Validator/ValidatorTypeGuesserTest.php +++ b/Tests/Extension/Validator/ValidatorTypeGuesserTest.php @@ -113,7 +113,7 @@ public function testGuessMaxLengthForConstraintWithMinValue() public function maxLengthTypeProvider() { - return array ( + return array( array('double'), array('float'), array('numeric'), diff --git a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php index 73607bff96..75a8074105 100644 --- a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php +++ b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php @@ -168,7 +168,7 @@ public function testAbortMappingIfNotSynchronized() $child = $this->getForm('address', 'address', null, array(), false, false); // even though "street" is synchronized, it should not have any errors // due to its parent not being synchronized - $grandChild = $this->getForm('street' , 'street'); + $grandChild = $this->getForm('street', 'street'); $parent->add($child); $child->add($grandChild); From 562f74c4715cc6b4c5806f3438eaf69fc6175306 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Wed, 3 Dec 2014 20:10:26 +0000 Subject: [PATCH 364/447] CS fixes --- Extension/Core/DataTransformer/ChoicesToValuesTransformer.php | 1 - Tests/AbstractLayoutTest.php | 3 +-- .../Core/DataTransformer/ChoicesToValuesTransformerTest.php | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php b/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php index 4492865e5a..0ee0b0fefd 100644 --- a/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php +++ b/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Form\Extension\Core\DataTransformer; use Symfony\Component\Form\Exception\TransformationFailedException; - use Symfony\Component\Form\DataTransformerInterface; use Symfony\Component\Form\Extension\Core\ChoiceList\ChoiceListInterface; diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index 5439bd096f..45e18a1841 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -1783,8 +1783,7 @@ public function testEmptyRootFormName() $this->assertMatchesXpath($this->renderWidget($form->createView()), '//input[@type="hidden"][@id="_token"][@name="_token"] | - //input[@type="text"][@id="child"][@name="child"]' - , 2); + //input[@type="text"][@id="child"][@name="child"]', 2); } public function testButton() diff --git a/Tests/Extension/Core/DataTransformer/ChoicesToValuesTransformerTest.php b/Tests/Extension/Core/DataTransformer/ChoicesToValuesTransformerTest.php index 572971938d..87f5018b04 100644 --- a/Tests/Extension/Core/DataTransformer/ChoicesToValuesTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/ChoicesToValuesTransformerTest.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; use Symfony\Component\Form\Extension\Core\ChoiceList\SimpleChoiceList; - use Symfony\Component\Form\Extension\Core\DataTransformer\ChoicesToValuesTransformer; class ChoicesToValuesTransformerTest extends \PHPUnit_Framework_TestCase From c0250a387b140f0bb1f27db1f1a6fb88cabf23d7 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Wed, 3 Dec 2014 21:28:36 +0000 Subject: [PATCH 365/447] [2.3] More cs fixes --- Tests/Extension/Validator/Constraints/FormValidatorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index 41c7439ba8..4e3f3a4718 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -361,7 +361,7 @@ public function testHandleClosureValidationGroups() $object = $this->getMock('\stdClass'); $options = array('validation_groups' => function (FormInterface $form) { return array('group1', 'group2'); - },); + }); $form = $this->getBuilder('name', '\stdClass', $options) ->setData($object) ->getForm(); From a0d0699dd585de36e8835623ce6cc9ba6c83e0b4 Mon Sep 17 00:00:00 2001 From: Will Donohoe Date: Thu, 4 Dec 2014 17:20:49 +1100 Subject: [PATCH 366/447] [Form] Add further timezone tests for date type --- Tests/Extension/Core/Type/DateTypeTest.php | 56 +++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/Tests/Extension/Core/Type/DateTypeTest.php b/Tests/Extension/Core/Type/DateTypeTest.php index 5ba37df1d0..255fe3a448 100644 --- a/Tests/Extension/Core/Type/DateTypeTest.php +++ b/Tests/Extension/Core/Type/DateTypeTest.php @@ -355,7 +355,7 @@ public function testThrowExceptionIfDaysIsInvalid() )); } - public function testSetDataWithDifferentTimezoneDateTime() + public function testSetDataWithDifferentNegativeUTCTimezoneDateTime() { date_default_timezone_set('Pacific/Tahiti'); @@ -373,6 +373,60 @@ public function testSetDataWithDifferentTimezoneDateTime() $this->assertEquals('02.06.2010', $form->getViewData()); } + public function testSetDataWithDifferentPositiveUTCTimezoneDateTime() + { + date_default_timezone_set('Pacific/Tahiti'); + + $form = $this->factory->create('date', null, array( + 'format' => \IntlDateFormatter::MEDIUM, + 'input' => 'datetime', + 'widget' => 'single_text', + )); + + $dateTime = new \DateTime('2010-06-02 Australia/Melbourne'); + + $form->setData($dateTime); + + $this->assertDateTimeEquals($dateTime, $form->getData()); + $this->assertEquals('02.06.2010', $form->getViewData()); + } + + public function testSetDataWithSamePositiveUTCTimezoneDateTime() + { + date_default_timezone_set('Australia/Melbourne'); + + $form = $this->factory->create('date', null, array( + 'format' => \IntlDateFormatter::MEDIUM, + 'input' => 'datetime', + 'widget' => 'single_text', + )); + + $dateTime = new \DateTime('2010-06-02 Australia/Melbourne'); + + $form->setData($dateTime); + + $this->assertDateTimeEquals($dateTime, $form->getData()); + $this->assertEquals('02.06.2010', $form->getViewData()); + } + + public function testSetDataWithSameNegativeUTCTimezoneDateTime() + { + date_default_timezone_set('America/New_York'); + + $form = $this->factory->create('date', null, array( + 'format' => \IntlDateFormatter::MEDIUM, + 'input' => 'datetime', + 'widget' => 'single_text', + )); + + $dateTime = new \DateTime('2010-06-02 America/New_York'); + + $form->setData($dateTime); + + $this->assertDateTimeEquals($dateTime, $form->getData()); + $this->assertEquals('02.06.2010', $form->getViewData()); + } + public function testYearsOption() { $form = $this->factory->create('date', null, array( From 823900e5687d9e428fa33ee727f5b3d2f6b0c569 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Thu, 4 Dec 2014 20:26:11 +0000 Subject: [PATCH 367/447] CS fixes --- .../NumberToLocalizedStringTransformer.php | 4 ++-- Form.php | 4 ++-- FormError.php | 12 ++++++------ FormErrorIterator.php | 16 ++++++++-------- FormInterface.php | 6 +++--- .../ViolationMapper/ViolationMapperTest.php | 2 +- Util/ServerParams.php | 2 +- 7 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php index b7f7359492..92f9e63bb9 100644 --- a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php @@ -242,9 +242,9 @@ protected function getNumberFormatter() /** * Rounds a number according to the configured precision and rounding mode. * - * @param int|float $number A number. + * @param int|float $number A number. * - * @return int|float The rounded number. + * @return int|float The rounded number. */ private function round($number) { diff --git a/Form.php b/Form.php index 132f5838cb..70560e801f 100644 --- a/Form.php +++ b/Form.php @@ -1128,8 +1128,8 @@ private function viewToNorm($value) /** * Utility function for indenting multi-line strings. * - * @param string $string The string - * @param int $level The number of spaces to use for indentation + * @param string $string The string + * @param int $level The number of spaces to use for indentation * * @return string The indented string */ diff --git a/FormError.php b/FormError.php index 3379faa2ca..6ec0eadf75 100644 --- a/FormError.php +++ b/FormError.php @@ -61,12 +61,12 @@ class FormError implements \Serializable * Any array key in $messageParameters will be used as a placeholder in * $messageTemplate. * - * @param string $message The translated error message - * @param string|null $messageTemplate The template for the error message - * @param array $messageParameters The parameters that should be - * substituted in the message template - * @param int|null $messagePluralization The value for error message pluralization - * @param mixed $cause The cause of the error + * @param string $message The translated error message + * @param string|null $messageTemplate The template for the error message + * @param array $messageParameters The parameters that should be + * substituted in the message template + * @param int|null $messagePluralization The value for error message pluralization + * @param mixed $cause The cause of the error * * @see \Symfony\Component\Translation\Translator */ diff --git a/FormErrorIterator.php b/FormErrorIterator.php index 58a94f815a..76e2938904 100644 --- a/FormErrorIterator.php +++ b/FormErrorIterator.php @@ -128,7 +128,7 @@ public function next() /** * Returns the current position of the iterator. * - * @return int The 0-indexed position. + * @return int The 0-indexed position. */ public function key() { @@ -138,7 +138,7 @@ public function key() /** * Returns whether the iterator's position is valid. * - * @return bool Whether the iterator is valid. + * @return bool Whether the iterator is valid. */ public function valid() { @@ -159,9 +159,9 @@ public function rewind() /** * Returns whether a position exists in the iterator. * - * @param int $position The position + * @param int $position The position * - * @return bool Whether that position exists + * @return bool Whether that position exists */ public function offsetExists($position) { @@ -171,7 +171,7 @@ public function offsetExists($position) /** * Returns the element at a position in the iterator. * - * @param int $position The position + * @param int $position The position * * @return FormError|FormErrorIterator The element at the given position * @@ -210,7 +210,7 @@ public function offsetUnset($position) * Returns whether the current element of the iterator can be recursed * into. * - * @return bool Whether the current element is an instance of this class + * @return bool Whether the current element is an instance of this class */ public function hasChildren() { @@ -240,7 +240,7 @@ public function getChildren() * * $count = count($form->getErrors(true, true)); * - * @return int The number of iterated elements + * @return int The number of iterated elements */ public function count() { @@ -250,7 +250,7 @@ public function count() /** * Sets the position of the iterator. * - * @param int $position The new position + * @param int $position The new position * * @throws OutOfBoundsException If the position is invalid */ diff --git a/FormInterface.php b/FormInterface.php index a11b0c3720..fe94673973 100644 --- a/FormInterface.php +++ b/FormInterface.php @@ -94,9 +94,9 @@ public function all(); /** * Returns the errors of this form. * - * @param bool $deep Whether to include errors of child forms as well - * @param bool $flatten Whether to flatten the list of errors in case - * $deep is set to true + * @param bool $deep Whether to include errors of child forms as well + * @param bool $flatten Whether to flatten the list of errors in case + * $deep is set to true * * @return FormErrorIterator An iterator over the {@link FormError} * instances that where added to this form diff --git a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php index 490dcc27aa..dc25e747f9 100644 --- a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php +++ b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php @@ -213,7 +213,7 @@ public function testAbortMappingIfNotSubmitted() $violation = $this->getConstraintViolation('children[address].data.street'); $parent = $this->getForm('parent'); $child = $this->getForm('address', 'address'); - $grandChild = $this->getForm('street' , 'street'); + $grandChild = $this->getForm('street', 'street'); $parent->add($child); $child->add($grandChild); diff --git a/Util/ServerParams.php b/Util/ServerParams.php index 82f352895b..eda8f7e2ed 100644 --- a/Util/ServerParams.php +++ b/Util/ServerParams.php @@ -28,7 +28,7 @@ public function __construct(RequestStack $requestStack = null) /** * Returns maximum post size in bytes. * - * @return null|int The maximum post size in bytes + * @return null|int The maximum post size in bytes */ public function getPostMaxSize() { From 883f5bb9b2ee0ca5b4c6cb6850f5ce1cd1cb0506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dariusz=20Rumi=C5=84ski?= Date: Sun, 7 Dec 2014 19:24:30 +0100 Subject: [PATCH 368/447] fix phpdoc's alignment --- Extension/Core/ChoiceList/ChoiceList.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Extension/Core/ChoiceList/ChoiceList.php b/Extension/Core/ChoiceList/ChoiceList.php index 02b59f6822..358cc4cd17 100644 --- a/Extension/Core/ChoiceList/ChoiceList.php +++ b/Extension/Core/ChoiceList/ChoiceList.php @@ -495,14 +495,14 @@ protected function fixChoice($choice) } /** - * Fixes the data type of the given choices to avoid comparison problems. - * - * @param array $choices The choices. - * - * @return array The fixed choices. - * - * @see fixChoice - */ + * Fixes the data type of the given choices to avoid comparison problems. + * + * @param array $choices The choices. + * + * @return array The fixed choices. + * + * @see fixChoice + */ protected function fixChoices(array $choices) { return $choices; From f1ef8e02de2375081e0fbe694dfd37ab15f1cca6 Mon Sep 17 00:00:00 2001 From: Sullivan SENECHAL Date: Tue, 9 Dec 2014 10:23:15 +0100 Subject: [PATCH 369/447] Fix wrong DateTransformer timezone param for non-UTC configuration. #12808 --- Extension/Core/Type/DateType.php | 14 +++++++------- Extension/Core/Type/TimeType.php | 10 +++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Extension/Core/Type/DateType.php b/Extension/Core/Type/DateType.php index 8a0028ce17..dc553ad8dd 100644 --- a/Extension/Core/Type/DateType.php +++ b/Extension/Core/Type/DateType.php @@ -57,8 +57,8 @@ public function buildForm(FormBuilderInterface $builder, array $options) if ('single_text' === $options['widget']) { $builder->addViewTransformer(new DateTimeToLocalizedStringTransformer( - 'UTC', - 'UTC', + null, + null, $dateFormat, $timeFormat, $calendar, @@ -73,7 +73,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) \Locale::getDefault(), $dateFormat, $timeFormat, - 'UTC', + null, $calendar, $pattern ); @@ -105,7 +105,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) ->add('month', $options['widget'], $monthOptions) ->add('day', $options['widget'], $dayOptions) ->addViewTransformer(new DateTimeToArrayTransformer( - 'UTC', 'UTC', array('year', 'month', 'day') + null, null, array('year', 'month', 'day') )) ->setAttribute('formatter', $formatter) ; @@ -113,15 +113,15 @@ public function buildForm(FormBuilderInterface $builder, array $options) if ('string' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToStringTransformer('UTC', 'UTC', 'Y-m-d') + new DateTimeToStringTransformer(null, null, 'Y-m-d') )); } elseif ('timestamp' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToTimestampTransformer('UTC', 'UTC') + new DateTimeToTimestampTransformer(null, null) )); } elseif ('array' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToArrayTransformer('UTC', 'UTC', array('year', 'month', 'day')) + new DateTimeToArrayTransformer(null, null, array('year', 'month', 'day')) )); } } diff --git a/Extension/Core/Type/TimeType.php b/Extension/Core/Type/TimeType.php index 236a546dc4..63d56d6899 100644 --- a/Extension/Core/Type/TimeType.php +++ b/Extension/Core/Type/TimeType.php @@ -48,7 +48,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) } if ('single_text' === $options['widget']) { - $builder->addViewTransformer(new DateTimeToStringTransformer('UTC', 'UTC', $format)); + $builder->addViewTransformer(new DateTimeToStringTransformer(null, null, $format)); } else { $hourOptions = $minuteOptions = $secondOptions = array( 'error_bubbling' => true, @@ -109,20 +109,20 @@ public function buildForm(FormBuilderInterface $builder, array $options) $builder->add('second', $options['widget'], $secondOptions); } - $builder->addViewTransformer(new DateTimeToArrayTransformer('UTC', 'UTC', $parts, 'text' === $options['widget'])); + $builder->addViewTransformer(new DateTimeToArrayTransformer(null, null, $parts, 'text' === $options['widget'])); } if ('string' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToStringTransformer('UTC', 'UTC', 'H:i:s') + new DateTimeToStringTransformer(null, null, 'H:i:s') )); } elseif ('timestamp' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToTimestampTransformer('UTC', 'UTC') + new DateTimeToTimestampTransformer(null, null) )); } elseif ('array' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToArrayTransformer('UTC', 'UTC', $parts) + new DateTimeToArrayTransformer(null, null, $parts) )); } } From b0cc5c04c5e8b8089aec520cce67ddadd54457fa Mon Sep 17 00:00:00 2001 From: origaminal Date: Sun, 23 Nov 2014 06:56:17 +0300 Subject: [PATCH 370/447] [Form] fixed a maxlength overring on a guessing --- FormFactory.php | 4 ++-- Tests/FormFactoryTest.php | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/FormFactory.php b/FormFactory.php index 8a7b1cab05..cfca4588bd 100644 --- a/FormFactory.php +++ b/FormFactory.php @@ -113,11 +113,11 @@ public function createBuilderForProperty($class, $property, $data = null, array $pattern = $patternGuess ? $patternGuess->getValue() : null; if (null !== $pattern) { - $options = array_merge(array('attr' => array('pattern' => $pattern)), $options); + $options = array_replace_recursive(array('attr' => array('pattern' => $pattern)), $options); } if (null !== $maxLength) { - $options = array_merge(array('attr' => array('maxlength' => $maxLength)), $options); + $options = array_replace_recursive(array('attr' => array('maxlength' => $maxLength)), $options); } if ($requiredGuess) { diff --git a/Tests/FormFactoryTest.php b/Tests/FormFactoryTest.php index a06b49876e..59e9e8085c 100644 --- a/Tests/FormFactoryTest.php +++ b/Tests/FormFactoryTest.php @@ -504,6 +504,41 @@ public function testCreateBuilderUsesMaxLengthIfFound() $this->assertEquals('builderInstance', $this->builder); } + public function testCreateBuilderUsesMaxLengthAndPattern() + { + $this->guesser1->expects($this->once()) + ->method('guessMaxLength') + ->with('Application\Author', 'firstName') + ->will($this->returnValue(new ValueGuess( + 20, + Guess::HIGH_CONFIDENCE + ))); + + $this->guesser2->expects($this->once()) + ->method('guessPattern') + ->with('Application\Author', 'firstName') + ->will($this->returnValue(new ValueGuess( + '.{5,}', + Guess::HIGH_CONFIDENCE + ))); + + $factory = $this->getMockFactory(array('createNamedBuilder')); + + $factory->expects($this->once()) + ->method('createNamedBuilder') + ->with('firstName', 'text', null, array('attr' => array('maxlength' => 20, 'pattern' => '.{5,}', 'class' => 'tinymce'))) + ->will($this->returnValue('builderInstance')); + + $this->builder = $factory->createBuilderForProperty( + 'Application\Author', + 'firstName', + null, + array('attr' => array('class' => 'tinymce')) + ); + + $this->assertEquals('builderInstance', $this->builder); + } + public function testCreateBuilderUsesRequiredSettingWithHighestConfidence() { $this->guesser1->expects($this->once()) From e1c5762238c45ab210ea32274777073e8203e8fc Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 13 Dec 2014 12:05:29 +0100 Subject: [PATCH 371/447] Test components using their lowest possible deps --- composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/composer.json b/composer.json index f55a042086..e5d0f06e2b 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,8 @@ }, "require-dev": { "doctrine/collections": "~1.0", - "symfony/validator": "~2.3.0", + "symfony/validator": "~2.3.0,>=2.3.20", + "symfony/translation": "~2.0,>=2.0.5", "symfony/http-foundation": "~2.2" }, "suggest": { From fe4366f1b3d13f84a6d6b804a2b92a0b1a1721db Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 15 Dec 2014 21:25:19 +0100 Subject: [PATCH 372/447] Test lowest versions of dependencies --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 54041626b1..ecefabdcf8 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ }, "require-dev": { "doctrine/collections": "~1.0", - "symfony/validator": "~2.5", + "symfony/validator": "~2.5,>=2.5.5", "symfony/http-foundation": "~2.2", "symfony/http-kernel": "~2.4", "symfony/security-csrf": "~2.4", From f959a871c8ff913b59083df4efd64b8ccd8ec1ae Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 16 Dec 2014 17:36:57 +0100 Subject: [PATCH 373/447] [2.6] Test lowest versions of dependencies --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index d5a7f0a095..18f3abaecf 100644 --- a/composer.json +++ b/composer.json @@ -24,7 +24,7 @@ }, "require-dev": { "doctrine/collections": "~1.0", - "symfony/validator": "~2.5,>=2.5.5", + "symfony/validator": "~2.6", "symfony/http-foundation": "~2.2", "symfony/http-kernel": "~2.4", "symfony/security-csrf": "~2.4", From a3fb398ec9977dc8a9b2bbcc22fa72707c4f26c3 Mon Sep 17 00:00:00 2001 From: sarah khalil Date: Thu, 18 Dec 2014 20:00:19 +0100 Subject: [PATCH 374/447] [Tests] Silenced all deprecations in tests for 2.3 --- phpunit.xml.dist | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index bd91d7b831..7ddac030f7 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -6,6 +6,10 @@ colors="true" bootstrap="vendor/autoload.php" > + + + + ./Tests/ From c6e761abcf81d6141e8bd6bd66bbbaf8c4b9dc96 Mon Sep 17 00:00:00 2001 From: Graham Campbell Date: Sun, 21 Dec 2014 17:00:50 +0000 Subject: [PATCH 375/447] [2.3] CS And DocBlock Fixes --- AbstractExtension.php | 12 ++++--- Button.php | 8 ----- ButtonBuilder.php | 20 ------------ CallbackTransformer.php | 6 ++-- .../Core/ChoiceList/ChoiceListInterface.php | 4 +-- Extension/Core/ChoiceList/LazyChoiceList.php | 6 ++-- .../BooleanToStringTransformer.php | 3 +- .../DataTransformer/DataTransformerChain.php | 11 ++++--- .../DateTimeToLocalizedStringTransformer.php | 4 +-- .../DateTimeToStringTransformer.php | 11 ++++--- .../DateTimeToTimestampTransformer.php | 4 +-- .../NumberToLocalizedStringTransformer.php | 4 +-- .../PercentToLocalizedStringTransformer.php | 2 +- .../EventListener/MergeCollectionListener.php | 6 ++-- .../Core/EventListener/ResizeFormListener.php | 6 ++-- Extension/Core/EventListener/TrimListener.php | 2 +- Extension/Core/Type/ChoiceType.php | 1 + Extension/Core/Type/DateTimeType.php | 2 +- Extension/Core/Type/MoneyType.php | 2 +- Extension/Core/Type/TimezoneType.php | 3 +- .../CsrfProvider/CsrfProviderInterface.php | 2 +- .../Csrf/CsrfProvider/DefaultCsrfProvider.php | 5 +-- .../Csrf/CsrfProvider/SessionCsrfProvider.php | 3 +- .../EventListener/CsrfValidationListener.php | 9 ++++-- Extension/Validator/ValidatorTypeGuesser.php | 10 +++--- .../ViolationMapper/ViolationPath.php | 2 +- Form.php | 32 +++++++++++++------ FormError.php | 19 ++++++----- FormRegistry.php | 2 +- FormTypeGuesserChain.php | 2 +- FormTypeGuesserInterface.php | 9 +++--- FormView.php | 5 ++- Guess/Guess.php | 16 ++++++---- Guess/TypeGuess.php | 14 ++++---- Guess/ValueGuess.php | 9 +++--- ReversedTransformer.php | 7 ++-- Tests/CompoundFormPerformanceTest.php | 2 +- .../DataMapper/PropertyPathMapperTest.php | 1 + ...NumberToLocalizedStringTransformerTest.php | 1 + Tests/Extension/Core/Type/FormTypeTest.php | 1 + .../FormValidatorPerformanceTest.php | 2 +- .../Constraints/FormValidatorTest.php | 2 +- Tests/FormBuilderTest.php | 2 +- Tests/Util/OrderedHashMapTest.php | 2 +- Util/FormUtil.php | 2 +- 45 files changed, 150 insertions(+), 128 deletions(-) diff --git a/AbstractExtension.php b/AbstractExtension.php index d057f92e87..a2eef508f3 100644 --- a/AbstractExtension.php +++ b/AbstractExtension.php @@ -20,25 +20,29 @@ abstract class AbstractExtension implements FormExtensionInterface { /** - * The types provided by this extension + * The types provided by this extension. + * * @var FormTypeInterface[] An array of FormTypeInterface */ private $types; /** - * The type extensions provided by this extension + * The type extensions provided by this extension. + * * @var FormTypeExtensionInterface[] An array of FormTypeExtensionInterface */ private $typeExtensions; /** - * The type guesser provided by this extension + * The type guesser provided by this extension. + * * @var FormTypeGuesserInterface */ private $typeGuesser; /** - * Whether the type guesser has been loaded + * Whether the type guesser has been loaded. + * * @var bool */ private $typeGuesserLoaded = false; diff --git a/Button.php b/Button.php index b6404a97d9..e7b553edcc 100644 --- a/Button.php +++ b/Button.php @@ -206,8 +206,6 @@ public function setData($modelData) /** * Unsupported method. - * - * @return null Always returns null. */ public function getData() { @@ -215,8 +213,6 @@ public function getData() /** * Unsupported method. - * - * @return null Always returns null. */ public function getNormData() { @@ -224,8 +220,6 @@ public function getNormData() /** * Unsupported method. - * - * @return null Always returns null. */ public function getViewData() { @@ -273,8 +267,6 @@ public function getName() /** * Unsupported method. - * - * @return null Always returns null. */ public function getPropertyPath() { diff --git a/ButtonBuilder.php b/ButtonBuilder.php index bbddd9cfa2..d881acc3fe 100644 --- a/ButtonBuilder.php +++ b/ButtonBuilder.php @@ -544,8 +544,6 @@ public function getFormConfig() /** * Unsupported method. - * - * @return null Always returns null. */ public function getEventDispatcher() { @@ -561,8 +559,6 @@ public function getName() /** * Unsupported method. - * - * @return null Always returns null. */ public function getPropertyPath() { @@ -640,8 +636,6 @@ public function getModelTransformers() /** * Unsupported method. - * - * @return null Always returns null. */ public function getDataMapper() { @@ -679,8 +673,6 @@ public function getErrorBubbling() /** * Unsupported method. - * - * @return null Always returns null. */ public function getEmptyData() { @@ -723,8 +715,6 @@ public function getAttribute($name, $default = null) /** * Unsupported method. - * - * @return null Always returns null. */ public function getData() { @@ -732,8 +722,6 @@ public function getData() /** * Unsupported method. - * - * @return null Always returns null. */ public function getDataClass() { @@ -751,8 +739,6 @@ public function getDataLocked() /** * Unsupported method. - * - * @return null Always returns null. */ public function getFormFactory() { @@ -760,8 +746,6 @@ public function getFormFactory() /** * Unsupported method. - * - * @return null Always returns null. */ public function getAction() { @@ -769,8 +753,6 @@ public function getAction() /** * Unsupported method. - * - * @return null Always returns null. */ public function getMethod() { @@ -778,8 +760,6 @@ public function getMethod() /** * Unsupported method. - * - * @return null Always returns null. */ public function getRequestHandler() { diff --git a/CallbackTransformer.php b/CallbackTransformer.php index 03459d4e8a..7857ad5f59 100644 --- a/CallbackTransformer.php +++ b/CallbackTransformer.php @@ -17,13 +17,15 @@ class CallbackTransformer implements DataTransformerInterface { /** - * The callback used for forward transform + * The callback used for forward transform. + * * @var callable */ private $transform; /** - * The callback used for reverse transform + * The callback used for reverse transform. + * * @var callable */ private $reverseTransform; diff --git a/Extension/Core/ChoiceList/ChoiceListInterface.php b/Extension/Core/ChoiceList/ChoiceListInterface.php index febf80ef05..c74a666228 100644 --- a/Extension/Core/ChoiceList/ChoiceListInterface.php +++ b/Extension/Core/ChoiceList/ChoiceListInterface.php @@ -29,14 +29,14 @@ interface ChoiceListInterface { /** - * Returns the list of choices + * Returns the list of choices. * * @return array The choices with their indices as keys */ public function getChoices(); /** - * Returns the values for the choices + * Returns the values for the choices. * * @return array The values with the corresponding choice indices as keys */ diff --git a/Extension/Core/ChoiceList/LazyChoiceList.php b/Extension/Core/ChoiceList/LazyChoiceList.php index 996f900cf3..67e20b91e8 100644 --- a/Extension/Core/ChoiceList/LazyChoiceList.php +++ b/Extension/Core/ChoiceList/LazyChoiceList.php @@ -14,7 +14,7 @@ use Symfony\Component\Form\Exception\InvalidArgumentException; /** - * A choice list that is loaded lazily + * A choice list that is loaded lazily. * * This list loads itself as soon as any of the getters is accessed for the * first time. You should implement loadChoiceList() in your child classes, @@ -25,7 +25,7 @@ abstract class LazyChoiceList implements ChoiceListInterface { /** - * The loaded choice list + * The loaded choice list. * * @var ChoiceListInterface */ @@ -128,7 +128,7 @@ public function getIndicesForValues(array $values) } /** - * Loads the choice list + * Loads the choice list. * * Should be implemented by child classes. * diff --git a/Extension/Core/DataTransformer/BooleanToStringTransformer.php b/Extension/Core/DataTransformer/BooleanToStringTransformer.php index 38c9bb273b..b75b98914d 100644 --- a/Extension/Core/DataTransformer/BooleanToStringTransformer.php +++ b/Extension/Core/DataTransformer/BooleanToStringTransformer.php @@ -23,7 +23,8 @@ class BooleanToStringTransformer implements DataTransformerInterface { /** - * The value emitted upon transform if the input is true + * The value emitted upon transform if the input is true. + * * @var string */ private $trueValue; diff --git a/Extension/Core/DataTransformer/DataTransformerChain.php b/Extension/Core/DataTransformer/DataTransformerChain.php index 9cc185e1ab..2b3712c102 100644 --- a/Extension/Core/DataTransformer/DataTransformerChain.php +++ b/Extension/Core/DataTransformer/DataTransformerChain.php @@ -15,20 +15,21 @@ use Symfony\Component\Form\Exception\TransformationFailedException; /** - * Passes a value through multiple value transformers + * Passes a value through multiple value transformers. * * @author Bernhard Schussek */ class DataTransformerChain implements DataTransformerInterface { /** - * The value transformers + * The value transformers. + * * @var DataTransformerInterface[] */ protected $transformers; /** - * Uses the given value transformers to transform values + * Uses the given value transformers to transform values. * * @param array $transformers */ @@ -38,7 +39,7 @@ public function __construct(array $transformers) } /** - * Passes the value through the transform() method of all nested transformers + * Passes the value through the transform() method of all nested transformers. * * The transformers receive the value in the same order as they were passed * to the constructor. Each transformer receives the result of the previous @@ -62,7 +63,7 @@ public function transform($value) /** * Passes the value through the reverseTransform() method of all nested - * transformers + * transformers. * * The transformers receive the value in the reverse order as they were passed * to the constructor. Each transformer receives the result of the previous diff --git a/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php index edcd6746cf..e7ebcabc7a 100644 --- a/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php @@ -15,7 +15,7 @@ use Symfony\Component\Form\Exception\UnexpectedTypeException; /** - * Transforms between a normalized time and a localized time string + * Transforms between a normalized time and a localized time string. * * @author Bernhard Schussek * @author Florian Eckerstorfer @@ -149,7 +149,7 @@ public function reverseTransform($value) } /** - * Returns a preconfigured IntlDateFormatter instance + * Returns a preconfigured IntlDateFormatter instance. * * @return \IntlDateFormatter * diff --git a/Extension/Core/DataTransformer/DateTimeToStringTransformer.php b/Extension/Core/DataTransformer/DateTimeToStringTransformer.php index 4dd3a03bbc..f5ba9948d0 100644 --- a/Extension/Core/DataTransformer/DateTimeToStringTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToStringTransformer.php @@ -15,7 +15,7 @@ use Symfony\Component\Form\Exception\UnexpectedTypeException; /** - * Transforms between a date string and a DateTime object + * Transforms between a date string and a DateTime object. * * @author Bernhard Schussek * @author Florian Eckerstorfer @@ -23,13 +23,14 @@ class DateTimeToStringTransformer extends BaseDateTimeTransformer { /** - * Format used for generating strings + * Format used for generating strings. + * * @var string */ private $generateFormat; /** - * Format used for parsing strings + * Format used for parsing strings. * * Different than the {@link $generateFormat} because formats for parsing * support additional characters in PHP that are not supported for @@ -49,7 +50,7 @@ class DateTimeToStringTransformer extends BaseDateTimeTransformer private $parseUsingPipe; /** - * Transforms a \DateTime instance to a string + * Transforms a \DateTime instance to a string. * * @see \DateTime::format() for supported formats * @@ -87,7 +88,7 @@ public function __construct($inputTimezone = null, $outputTimezone = null, $form /** * Transforms a DateTime object into a date string with the configured format - * and timezone + * and timezone. * * @param \DateTime $value A DateTime object * diff --git a/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php b/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php index 38073f8291..bd51ea4195 100644 --- a/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php @@ -14,7 +14,7 @@ use Symfony\Component\Form\Exception\TransformationFailedException; /** - * Transforms between a timestamp and a DateTime object + * Transforms between a timestamp and a DateTime object. * * @author Bernhard Schussek * @author Florian Eckerstorfer @@ -53,7 +53,7 @@ public function transform($value) } /** - * Transforms a timestamp in the configured timezone into a DateTime object + * Transforms a timestamp in the configured timezone into a DateTime object. * * @param string $value A timestamp * diff --git a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php index 3bf9581cd0..79423cea3b 100644 --- a/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php @@ -86,7 +86,7 @@ public function transform($value) } /** - * Transforms a localized number into an integer or float + * Transforms a localized number into an integer or float. * * @param string $value The localized value * @@ -158,7 +158,7 @@ public function reverseTransform($value) } /** - * Returns a preconfigured \NumberFormatter instance + * Returns a preconfigured \NumberFormatter instance. * * @return \NumberFormatter */ diff --git a/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php index 2e02478e81..1db54bf43b 100644 --- a/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php @@ -134,7 +134,7 @@ public function reverseTransform($value) } /** - * Returns a preconfigured \NumberFormatter instance + * Returns a preconfigured \NumberFormatter instance. * * @return \NumberFormatter */ diff --git a/Extension/Core/EventListener/MergeCollectionListener.php b/Extension/Core/EventListener/MergeCollectionListener.php index 982a78679b..a14f99a985 100644 --- a/Extension/Core/EventListener/MergeCollectionListener.php +++ b/Extension/Core/EventListener/MergeCollectionListener.php @@ -22,13 +22,15 @@ class MergeCollectionListener implements EventSubscriberInterface { /** - * Whether elements may be added to the collection + * Whether elements may be added to the collection. + * * @var bool */ private $allowAdd; /** - * Whether elements may be removed from the collection + * Whether elements may be removed from the collection. + * * @var bool */ private $allowDelete; diff --git a/Extension/Core/EventListener/ResizeFormListener.php b/Extension/Core/EventListener/ResizeFormListener.php index 022ddc5df3..8a4919240d 100644 --- a/Extension/Core/EventListener/ResizeFormListener.php +++ b/Extension/Core/EventListener/ResizeFormListener.php @@ -34,13 +34,15 @@ class ResizeFormListener implements EventSubscriberInterface protected $options; /** - * Whether children could be added to the group + * Whether children could be added to the group. + * * @var bool */ protected $allowAdd; /** - * Whether children could be removed from the group + * Whether children could be removed from the group. + * * @var bool */ protected $allowDelete; diff --git a/Extension/Core/EventListener/TrimListener.php b/Extension/Core/EventListener/TrimListener.php index cbe6e0ab79..eaec5c163b 100644 --- a/Extension/Core/EventListener/TrimListener.php +++ b/Extension/Core/EventListener/TrimListener.php @@ -16,7 +16,7 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** - * Trims string data + * Trims string data. * * @author Bernhard Schussek */ diff --git a/Extension/Core/Type/ChoiceType.php b/Extension/Core/Type/ChoiceType.php index 529903e7dc..dc241779c9 100644 --- a/Extension/Core/Type/ChoiceType.php +++ b/Extension/Core/Type/ChoiceType.php @@ -32,6 +32,7 @@ class ChoiceType extends AbstractType { /** * Caches created choice lists. + * * @var array */ private $choiceListCache = array(); diff --git a/Extension/Core/Type/DateTimeType.php b/Extension/Core/Type/DateTimeType.php index 9f2927d978..5a653233b9 100644 --- a/Extension/Core/Type/DateTimeType.php +++ b/Extension/Core/Type/DateTimeType.php @@ -37,7 +37,7 @@ class DateTimeType extends AbstractType * This is not quite the HTML5 format yet, because ICU lacks the * capability of parsing and generating RFC 3339 dates, which * are like the below pattern but with a timezone suffix. The - * timezone suffix is + * timezone suffix is. * * * "Z" for UTC * * "(-|+)HH:mm" for other timezones (note the colon!) diff --git a/Extension/Core/Type/MoneyType.php b/Extension/Core/Type/MoneyType.php index 787557c4b9..9653d6f8ab 100644 --- a/Extension/Core/Type/MoneyType.php +++ b/Extension/Core/Type/MoneyType.php @@ -68,7 +68,7 @@ public function getName() } /** - * Returns the pattern for this locale + * Returns the pattern for this locale. * * The pattern contains the placeholder "{{ widget }}" where the HTML tag should * be inserted diff --git a/Extension/Core/Type/TimezoneType.php b/Extension/Core/Type/TimezoneType.php index cd4a2ad38b..96b1407768 100644 --- a/Extension/Core/Type/TimezoneType.php +++ b/Extension/Core/Type/TimezoneType.php @@ -17,7 +17,8 @@ class TimezoneType extends AbstractType { /** - * Stores the available timezone choices + * Stores the available timezone choices. + * * @var array */ private static $timezones; diff --git a/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php b/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php index e7e2cc290a..14b07e1a93 100644 --- a/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php +++ b/Extension/Csrf/CsrfProvider/CsrfProviderInterface.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Form\Extension\Csrf\CsrfProvider; /** - * Marks classes able to provide CSRF protection + * Marks classes able to provide CSRF protection. * * You can generate a CSRF token by using the method generateCsrfToken(). To * this method you should pass a value that is unique to the page that should diff --git a/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php b/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php index 6b4ff984af..31ea45f3d5 100644 --- a/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php +++ b/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php @@ -22,13 +22,14 @@ class DefaultCsrfProvider implements CsrfProviderInterface { /** - * A secret value used for generating the CSRF token + * A secret value used for generating the CSRF token. + * * @var string */ protected $secret; /** - * Initializes the provider with a secret value + * Initializes the provider with a secret value. * * A recommended value for the secret is a generated value with at least * 32 characters and mixed letters, digits and special characters. diff --git a/Extension/Csrf/CsrfProvider/SessionCsrfProvider.php b/Extension/Csrf/CsrfProvider/SessionCsrfProvider.php index 52c9685ee1..420de5ceed 100644 --- a/Extension/Csrf/CsrfProvider/SessionCsrfProvider.php +++ b/Extension/Csrf/CsrfProvider/SessionCsrfProvider.php @@ -24,7 +24,8 @@ class SessionCsrfProvider extends DefaultCsrfProvider { /** - * The user session from which the session ID is returned + * The user session from which the session ID is returned. + * * @var Session */ protected $session; diff --git a/Extension/Csrf/EventListener/CsrfValidationListener.php b/Extension/Csrf/EventListener/CsrfValidationListener.php index 547e9d756c..a800fc48d9 100644 --- a/Extension/Csrf/EventListener/CsrfValidationListener.php +++ b/Extension/Csrf/EventListener/CsrfValidationListener.php @@ -24,19 +24,21 @@ class CsrfValidationListener implements EventSubscriberInterface { /** - * The name of the CSRF field + * The name of the CSRF field. + * * @var string */ private $fieldName; /** - * The provider for generating and validating CSRF tokens + * The provider for generating and validating CSRF tokens. + * * @var CsrfProviderInterface */ private $csrfProvider; /** - * A text mentioning the intention of the CSRF token + * A text mentioning the intention of the CSRF token. * * Validation of the token will only succeed if it was generated in the * same session and with the same intention. @@ -47,6 +49,7 @@ class CsrfValidationListener implements EventSubscriberInterface /** * The message displayed in case of an error. + * * @var string */ private $errorMessage; diff --git a/Extension/Validator/ValidatorTypeGuesser.php b/Extension/Validator/ValidatorTypeGuesser.php index 8884629dc9..56f763b7ce 100644 --- a/Extension/Validator/ValidatorTypeGuesser.php +++ b/Extension/Validator/ValidatorTypeGuesser.php @@ -78,7 +78,7 @@ public function guessPattern($class, $property) } /** - * Guesses a field class name for a given constraint + * Guesses a field class name for a given constraint. * * @param Constraint $constraint The constraint to guess for * @@ -162,7 +162,7 @@ public function guessTypeForConstraint(Constraint $constraint) } /** - * Guesses whether a field is required based on the given constraint + * Guesses whether a field is required based on the given constraint. * * @param Constraint $constraint The constraint to guess for * @@ -179,7 +179,7 @@ public function guessRequiredForConstraint(Constraint $constraint) } /** - * Guesses a field's maximum length based on the given constraint + * Guesses a field's maximum length based on the given constraint. * * @param Constraint $constraint The constraint to guess for * @@ -209,7 +209,7 @@ public function guessMaxLengthForConstraint(Constraint $constraint) } /** - * Guesses a field's pattern based on the given constraint + * Guesses a field's pattern based on the given constraint. * * @param Constraint $constraint The constraint to guess for * @@ -248,7 +248,7 @@ public function guessPatternForConstraint(Constraint $constraint) /** * Iterates over the constraints of a property, executes a constraints on - * them and returns the best guess + * them and returns the best guess. * * @param string $class The class to read the constraints from * @param string $property The property for which to find constraints diff --git a/Extension/Validator/ViolationMapper/ViolationPath.php b/Extension/Validator/ViolationMapper/ViolationPath.php index 9fa318ac3d..8e406a9b08 100644 --- a/Extension/Validator/ViolationMapper/ViolationPath.php +++ b/Extension/Validator/ViolationMapper/ViolationPath.php @@ -222,7 +222,7 @@ public function mapsForm($index) } /** - * Returns a new iterator for this path + * Returns a new iterator for this path. * * @return ViolationPathIterator */ diff --git a/Form.php b/Form.php index 868140d173..b67700a6f3 100644 --- a/Form.php +++ b/Form.php @@ -61,61 +61,71 @@ class Form implements \IteratorAggregate, FormInterface { /** - * The form's configuration + * The form's configuration. + * * @var FormConfigInterface */ private $config; /** - * The parent of this form + * The parent of this form. + * * @var FormInterface */ private $parent; /** - * The children of this form + * The children of this form. + * * @var FormInterface[] A map of FormInterface instances */ private $children; /** - * The errors of this form + * The errors of this form. + * * @var FormError[] An array of FormError instances */ private $errors = array(); /** - * Whether this form was submitted + * Whether this form was submitted. + * * @var bool */ private $submitted = false; /** - * The button that was used to submit the form + * The button that was used to submit the form. + * * @var Button */ private $clickedButton; /** - * The form data in model format + * The form data in model format. + * * @var mixed */ private $modelData; /** - * The form data in normalized format + * The form data in normalized format. + * * @var mixed */ private $normData; /** - * The form data in view format + * The form data in view format. + * * @var mixed */ private $viewData; /** - * The submitted values that don't belong to any children + * The submitted values that don't belong to any children. + * * @var array */ private $extraData = array(); @@ -124,6 +134,7 @@ class Form implements \IteratorAggregate, FormInterface * Whether the data in model, normalized and view format is * synchronized. Data may not be synchronized if transformation errors * occur. + * * @var bool */ private $synchronized = true; @@ -144,6 +155,7 @@ class Form implements \IteratorAggregate, FormInterface /** * Whether setData() is currently being called. + * * @var bool */ private $lockSetData = false; diff --git a/FormError.php b/FormError.php index e29147be79..c6fccbbb33 100644 --- a/FormError.php +++ b/FormError.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Form; /** - * Wraps errors in forms + * Wraps errors in forms. * * @author Bernhard Schussek */ @@ -24,25 +24,28 @@ class FormError private $message; /** - * The template for the error message + * The template for the error message. + * * @var string */ protected $messageTemplate; /** - * The parameters that should be substituted in the message template + * The parameters that should be substituted in the message template. + * * @var array */ protected $messageParameters; /** - * The value for error message pluralization + * The value for error message pluralization. + * * @var int|null */ protected $messagePluralization; /** - * Constructor + * Constructor. * * Any array key in $messageParameters will be used as a placeholder in * $messageTemplate. @@ -64,7 +67,7 @@ public function __construct($message, $messageTemplate = null, array $messagePar } /** - * Returns the error message + * Returns the error message. * * @return string */ @@ -74,7 +77,7 @@ public function getMessage() } /** - * Returns the error message template + * Returns the error message template. * * @return string */ @@ -84,7 +87,7 @@ public function getMessageTemplate() } /** - * Returns the parameters to be inserted in the message template + * Returns the parameters to be inserted in the message template. * * @return array */ diff --git a/FormRegistry.php b/FormRegistry.php index b2912fb052..0dc21df2bc 100644 --- a/FormRegistry.php +++ b/FormRegistry.php @@ -23,7 +23,7 @@ class FormRegistry implements FormRegistryInterface { /** - * Extensions + * Extensions. * * @var FormExtensionInterface[] An array of FormExtensionInterface */ diff --git a/FormTypeGuesserChain.php b/FormTypeGuesserChain.php index 979a7214d8..7c4f65b435 100644 --- a/FormTypeGuesserChain.php +++ b/FormTypeGuesserChain.php @@ -82,7 +82,7 @@ public function guessPattern($class, $property) /** * Executes a closure for each guesser and returns the best guess from the - * return values + * return values. * * @param \Closure $closure The closure to execute. Accepts a guesser * as argument and should return a Guess instance diff --git a/FormTypeGuesserInterface.php b/FormTypeGuesserInterface.php index 7cd384a798..f62112493d 100644 --- a/FormTypeGuesserInterface.php +++ b/FormTypeGuesserInterface.php @@ -17,7 +17,7 @@ interface FormTypeGuesserInterface { /** - * Returns a field guess for a property name of a class + * Returns a field guess for a property name of a class. * * @param string $class The fully qualified class name * @param string $property The name of the property to guess for @@ -27,7 +27,7 @@ interface FormTypeGuesserInterface public function guessType($class, $property); /** - * Returns a guess whether a property of a class is required + * Returns a guess whether a property of a class is required. * * @param string $class The fully qualified class name * @param string $property The name of the property to guess for @@ -37,7 +37,7 @@ public function guessType($class, $property); public function guessRequired($class, $property); /** - * Returns a guess about the field's maximum length + * Returns a guess about the field's maximum length. * * @param string $class The fully qualified class name * @param string $property The name of the property to guess for @@ -47,12 +47,13 @@ public function guessRequired($class, $property); public function guessMaxLength($class, $property); /** - * Returns a guess about the field's pattern + * Returns a guess about the field's pattern. * * - When you have a min value, you guess a min length of this min (LOW_CONFIDENCE) , lines below * - If this value is a float type, this is wrong so you guess null with MEDIUM_CONFIDENCE to override the previous guess. * Example: * You want a float greater than 5, 4.512313 is not valid but length(4.512314) > length(5) + * * @link https://github.com/symfony/symfony/pull/3927 * * @param string $class The fully qualified class name diff --git a/FormView.php b/FormView.php index dc3422473a..ac50dc336f 100644 --- a/FormView.php +++ b/FormView.php @@ -20,6 +20,7 @@ class FormView implements \ArrayAccess, \IteratorAggregate, \Countable { /** * The variables assigned to this view. + * * @var array */ public $vars = array( @@ -29,12 +30,14 @@ class FormView implements \ArrayAccess, \IteratorAggregate, \Countable /** * The parent view. + * * @var FormView */ public $parent; /** * The child views. + * * @var FormView[] */ public $children = array(); @@ -138,7 +141,7 @@ public function offsetUnset($name) } /** - * Returns an iterator to iterate over children (implements \IteratorAggregate) + * Returns an iterator to iterate over children (implements \IteratorAggregate). * * @return \ArrayIterator The iterator */ diff --git a/Guess/Guess.php b/Guess/Guess.php index e999f5421a..0595e7bba3 100644 --- a/Guess/Guess.php +++ b/Guess/Guess.php @@ -14,7 +14,7 @@ use Symfony\Component\Form\Exception\InvalidArgumentException; /** - * Base class for guesses made by TypeGuesserInterface implementation + * Base class for guesses made by TypeGuesserInterface implementation. * * Each instance contains a confidence value about the correctness of the guess. * Thus an instance with confidence HIGH_CONFIDENCE is more likely to be @@ -25,31 +25,35 @@ abstract class Guess { /** - * Marks an instance with a value that is extremely likely to be correct + * Marks an instance with a value that is extremely likely to be correct. + * * @var int */ const VERY_HIGH_CONFIDENCE = 3; /** - * Marks an instance with a value that is very likely to be correct + * Marks an instance with a value that is very likely to be correct. + * * @var int */ const HIGH_CONFIDENCE = 2; /** - * Marks an instance with a value that is likely to be correct + * Marks an instance with a value that is likely to be correct. + * * @var int */ const MEDIUM_CONFIDENCE = 1; /** - * Marks an instance with a value that may be correct + * Marks an instance with a value that may be correct. + * * @var int */ const LOW_CONFIDENCE = 0; /** - * The confidence about the correctness of the value + * The confidence about the correctness of the value. * * One of VERY_HIGH_CONFIDENCE, HIGH_CONFIDENCE, MEDIUM_CONFIDENCE * and LOW_CONFIDENCE. diff --git a/Guess/TypeGuess.php b/Guess/TypeGuess.php index 50ab944d6f..87cc60a0f1 100644 --- a/Guess/TypeGuess.php +++ b/Guess/TypeGuess.php @@ -13,26 +13,28 @@ /** * Contains a guessed class name and a list of options for creating an instance - * of that class + * of that class. * * @author Bernhard Schussek */ class TypeGuess extends Guess { /** - * The guessed field type + * The guessed field type. + * * @var string */ private $type; /** - * The guessed options for creating an instance of the guessed class + * The guessed options for creating an instance of the guessed class. + * * @var array */ private $options; /** - * Constructor + * Constructor. * * @param string $type The guessed field type * @param array $options The options for creating instances of the @@ -49,7 +51,7 @@ public function __construct($type, array $options, $confidence) } /** - * Returns the guessed field type + * Returns the guessed field type. * * @return string */ @@ -59,7 +61,7 @@ public function getType() } /** - * Returns the guessed options for creating instances of the guessed type + * Returns the guessed options for creating instances of the guessed type. * * @return array */ diff --git a/Guess/ValueGuess.php b/Guess/ValueGuess.php index c101201ff8..fe40e020cc 100644 --- a/Guess/ValueGuess.php +++ b/Guess/ValueGuess.php @@ -12,20 +12,21 @@ namespace Symfony\Component\Form\Guess; /** - * Contains a guessed value + * Contains a guessed value. * * @author Bernhard Schussek */ class ValueGuess extends Guess { /** - * The guessed value + * The guessed value. + * * @var array */ private $value; /** - * Constructor + * Constructor. * * @param string $value The guessed value * @param int $confidence The confidence that the guessed class name @@ -39,7 +40,7 @@ public function __construct($value, $confidence) } /** - * Returns the guessed value + * Returns the guessed value. * * @return mixed */ diff --git a/ReversedTransformer.php b/ReversedTransformer.php index 4fd2456462..fc5cd12bc3 100644 --- a/ReversedTransformer.php +++ b/ReversedTransformer.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Form; /** - * Reverses a transformer + * Reverses a transformer. * * When the transform() method is called, the reversed transformer's * reverseTransform() method is called and vice versa. @@ -22,13 +22,14 @@ class ReversedTransformer implements DataTransformerInterface { /** - * The reversed transformer + * The reversed transformer. + * * @var DataTransformerInterface */ protected $reversedTransformer; /** - * Reverses this transformer + * Reverses this transformer. * * @param DataTransformerInterface $reversedTransformer */ diff --git a/Tests/CompoundFormPerformanceTest.php b/Tests/CompoundFormPerformanceTest.php index 73c602c554..3840cb8f95 100644 --- a/Tests/CompoundFormPerformanceTest.php +++ b/Tests/CompoundFormPerformanceTest.php @@ -17,7 +17,7 @@ class CompoundFormPerformanceTest extends \Symfony\Component\Form\Tests\FormPerformanceTestCase { /** - * Create a compound form multiple times, as happens in a collection form + * Create a compound form multiple times, as happens in a collection form. * * @group benchmark */ diff --git a/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php b/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php index d6cd476386..e8e875cc8e 100644 --- a/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php +++ b/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php @@ -49,6 +49,7 @@ protected function setUp() /** * @param $path + * * @return \PHPUnit_Framework_MockObject_MockObject */ private function getPropertyPath($path) diff --git a/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php index 88115eaaae..871c88af70 100644 --- a/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/NumberToLocalizedStringTransformerTest.php @@ -258,6 +258,7 @@ public function testReverseTransformExpectsValidNumber() /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + * * @link https://github.com/symfony/symfony/issues/3161 */ public function testReverseTransformDisallowsNaN() diff --git a/Tests/Extension/Core/Type/FormTypeTest.php b/Tests/Extension/Core/Type/FormTypeTest.php index 35cc17c6aa..43f9e706d1 100644 --- a/Tests/Extension/Core/Type/FormTypeTest.php +++ b/Tests/Extension/Core/Type/FormTypeTest.php @@ -288,6 +288,7 @@ public function provideZeros() /** * @dataProvider provideZeros + * * @see https://github.com/symfony/symfony/issues/1986 */ public function testSetDataThroughParamsWithZero($data, $dataAsString) diff --git a/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.php b/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.php index b46f993a62..65df79c857 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorPerformanceTest.php @@ -28,7 +28,7 @@ protected function getExtensions() } /** - * findClickedButton() used to have an exponential number of calls + * findClickedButton() used to have an exponential number of calls. * * @group benchmark */ diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index 4e3f3a4718..f2f4e4422e 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -552,7 +552,7 @@ public function testViolationIfExtraData() /** * Access has to be public, as this method is called via callback array * in {@link testValidateFormDataCanHandleCallbackValidationGroups()} - * and {@link testValidateFormDataUsesInheritedCallbackValidationGroup()} + * and {@link testValidateFormDataUsesInheritedCallbackValidationGroup()}. */ public function getValidationGroups(FormInterface $form) { diff --git a/Tests/FormBuilderTest.php b/Tests/FormBuilderTest.php index e076c97e78..71cd70cfbb 100644 --- a/Tests/FormBuilderTest.php +++ b/Tests/FormBuilderTest.php @@ -41,7 +41,7 @@ protected function tearDown() /** * Changing the name is not allowed, otherwise the name and property path - * are not synchronized anymore + * are not synchronized anymore. * * @see FormType::buildForm */ diff --git a/Tests/Util/OrderedHashMapTest.php b/Tests/Util/OrderedHashMapTest.php index 60703c5b3b..7adff69a3f 100644 --- a/Tests/Util/OrderedHashMapTest.php +++ b/Tests/Util/OrderedHashMapTest.php @@ -58,7 +58,7 @@ public function testInsertNullKeys() /** * Updates should not change the position of an element, otherwise we could * turn foreach loops into endless loops if they change the current - * element: + * element. * * foreach ($map as $index => $value) { * $map[$index] = $value + 1; diff --git a/Util/FormUtil.php b/Util/FormUtil.php index afa5994047..0862179f54 100644 --- a/Util/FormUtil.php +++ b/Util/FormUtil.php @@ -17,7 +17,7 @@ class FormUtil { /** - * This class should not be instantiated + * This class should not be instantiated. */ private function __construct() { From 4a18addecf75969d6f21017ab8cc05a239ee59b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Paku=C5=82a?= Date: Thu, 18 Dec 2014 13:49:55 +0100 Subject: [PATCH 376/447] fix #10054 - form data collector with dynamic fields | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #10054 | License | MIT | Doc PR | - --- Extension/DataCollector/FormDataCollector.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Extension/DataCollector/FormDataCollector.php b/Extension/DataCollector/FormDataCollector.php index cabd801af8..752a3d066f 100644 --- a/Extension/DataCollector/FormDataCollector.php +++ b/Extension/DataCollector/FormDataCollector.php @@ -139,7 +139,9 @@ public function collectSubmittedData(FormInterface $form) $hash = spl_object_hash($form); if (!isset($this->dataByForm[$hash])) { - $this->dataByForm[$hash] = array(); + // field was created by form event + $this->collectConfiguration($form); + $this->collectDefaultData($form); } $this->dataByForm[$hash] = array_replace( From 1ad9a4cd660a2ae11e14edba9de787d50fdd4888 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 29 Dec 2014 09:26:36 +0100 Subject: [PATCH 377/447] No global state for isolated tests and other fixes --- Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.php b/Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.php index 3cf62f8db3..f201f99862 100644 --- a/Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.php +++ b/Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.php @@ -15,6 +15,7 @@ /** * @runTestsInSeparateProcesses + * @preserveGlobalState disabled */ class DefaultCsrfProviderTest extends \PHPUnit_Framework_TestCase { @@ -24,6 +25,7 @@ public static function setUpBeforeClass() { ini_set('session.save_handler', 'files'); ini_set('session.save_path', sys_get_temp_dir()); + ini_set('error_reporting', -1 & ~E_USER_DEPRECATED); } protected function setUp() From 6c9027756bf78d496716153be3f5a5eb58bc24a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Paku=C5=82a?= Date: Mon, 29 Dec 2014 14:07:34 +0100 Subject: [PATCH 378/447] fix regression in form tests after pr #13027 | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - --- .../DataCollector/FormDataCollectorTest.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Tests/Extension/DataCollector/FormDataCollectorTest.php b/Tests/Extension/DataCollector/FormDataCollectorTest.php index 72e323aaa1..f4774a5cc4 100644 --- a/Tests/Extension/DataCollector/FormDataCollectorTest.php +++ b/Tests/Extension/DataCollector/FormDataCollectorTest.php @@ -497,16 +497,21 @@ public function testCollectSubmittedDataCountsErrors() $form2 = $this->createForm('form2'); $form1->add($childForm1); - - $this->dataExtractor->expects($this->at(0)) + $this->dataExtractor + ->method('extractConfiguration') + ->will($this->returnValue(array())); + $this->dataExtractor + ->method('extractDefaultData') + ->will($this->returnValue(array())); + $this->dataExtractor->expects($this->at(4)) ->method('extractSubmittedData') ->with($form1) ->will($this->returnValue(array('errors' => array('foo')))); - $this->dataExtractor->expects($this->at(1)) + $this->dataExtractor->expects($this->at(5)) ->method('extractSubmittedData') ->with($childForm1) ->will($this->returnValue(array('errors' => array('bar', 'bam')))); - $this->dataExtractor->expects($this->at(2)) + $this->dataExtractor->expects($this->at(8)) ->method('extractSubmittedData') ->with($form2) ->will($this->returnValue(array('errors' => array('baz')))); From 0942268adc00ae2194ab985f211bcef5664277aa Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Mon, 29 Dec 2014 22:18:50 +0100 Subject: [PATCH 379/447] Remove usages of deprecated constants --- .../HttpFoundation/EventListener/BindRequestListener.php | 2 +- Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php | 2 +- Tests/SimpleFormTest.php | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Extension/HttpFoundation/EventListener/BindRequestListener.php b/Extension/HttpFoundation/EventListener/BindRequestListener.php index 6ba976a823..bb144ed65a 100644 --- a/Extension/HttpFoundation/EventListener/BindRequestListener.php +++ b/Extension/HttpFoundation/EventListener/BindRequestListener.php @@ -27,7 +27,7 @@ class BindRequestListener implements EventSubscriberInterface public static function getSubscribedEvents() { // High priority in order to supersede other listeners - return array(FormEvents::PRE_BIND => array('preBind', 128)); + return array(FormEvents::PRE_SUBMIT => array('preBind', 128)); } public function preBind(FormEvent $event) diff --git a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php index 91392bc441..fdeec2aa34 100644 --- a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php +++ b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php @@ -297,7 +297,7 @@ public function testValidateTokenOnBindIfRootAndCompoundUsesTypeClassAsIntention ->add('child', 'text') ->getForm(); - $form->bind(array( + $form->submit(array( 'child' => 'foobar', 'csrf' => 'token', )); diff --git a/Tests/SimpleFormTest.php b/Tests/SimpleFormTest.php index 657f145c6c..76752b9bd2 100644 --- a/Tests/SimpleFormTest.php +++ b/Tests/SimpleFormTest.php @@ -109,10 +109,10 @@ public function testFalseIsConvertedToNull() })); $config = new FormConfigBuilder('name', null, $this->dispatcher); - $config->addEventListener(FormEvents::PRE_BIND, array($mock, 'preBind')); + $config->addEventListener(FormEvents::PRE_SUBMIT, array($mock, 'preBind')); $form = new Form($config); - $form->bind(false); + $form->submit(false); $this->assertTrue($form->isValid()); $this->assertNull($form->getData()); From 35f3bf9b0467b64816340dcc91890138c123b679 Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Mon, 29 Dec 2014 22:04:28 +0100 Subject: [PATCH 380/447] Replace usages of the deprecated TypeTestCase by the new one --- Tests/CompoundFormPerformanceTest.php | 2 +- Tests/Extension/Core/Type/CountryTypeTest.php | 3 ++- Tests/Extension/Core/Type/CurrencyTypeTest.php | 3 ++- Tests/Extension/Core/Type/DateTimeTypeTest.php | 3 ++- Tests/Extension/Core/Type/DateTypeTest.php | 3 ++- Tests/Extension/Core/Type/IntegerTypeTest.php | 3 ++- Tests/Extension/Core/Type/LanguageTypeTest.php | 3 ++- Tests/Extension/Core/Type/LocaleTypeTest.php | 3 ++- Tests/Extension/Core/Type/MoneyTypeTest.php | 3 ++- Tests/Extension/Core/Type/NumberTypeTest.php | 3 ++- Tests/Extension/Core/Type/SubmitTypeTest.php | 4 +++- Tests/Extension/Core/Type/TimeTypeTest.php | 3 ++- Tests/Extension/Core/Type/UrlTypeTest.php | 4 +++- 13 files changed, 27 insertions(+), 13 deletions(-) diff --git a/Tests/CompoundFormPerformanceTest.php b/Tests/CompoundFormPerformanceTest.php index 3840cb8f95..77873a71f9 100644 --- a/Tests/CompoundFormPerformanceTest.php +++ b/Tests/CompoundFormPerformanceTest.php @@ -14,7 +14,7 @@ /** * @author Bernhard Schussek */ -class CompoundFormPerformanceTest extends \Symfony\Component\Form\Tests\FormPerformanceTestCase +class CompoundFormPerformanceTest extends \Symfony\Component\Form\Test\FormPerformanceTestCase { /** * Create a compound form multiple times, as happens in a collection form. diff --git a/Tests/Extension/Core/Type/CountryTypeTest.php b/Tests/Extension/Core/Type/CountryTypeTest.php index 1d56e2a024..7c2cebb542 100644 --- a/Tests/Extension/Core/Type/CountryTypeTest.php +++ b/Tests/Extension/Core/Type/CountryTypeTest.php @@ -12,9 +12,10 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Extension\Core\View\ChoiceView; +use Symfony\Component\Form\Test\TypeTestCase as TestCase; use Symfony\Component\Intl\Util\IntlTestHelper; -class CountryTypeTest extends TypeTestCase +class CountryTypeTest extends TestCase { protected function setUp() { diff --git a/Tests/Extension/Core/Type/CurrencyTypeTest.php b/Tests/Extension/Core/Type/CurrencyTypeTest.php index ec290e3019..702262f580 100644 --- a/Tests/Extension/Core/Type/CurrencyTypeTest.php +++ b/Tests/Extension/Core/Type/CurrencyTypeTest.php @@ -12,9 +12,10 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Extension\Core\View\ChoiceView; +use Symfony\Component\Form\Test\TypeTestCase as TestCase; use Symfony\Component\Intl\Util\IntlTestHelper; -class CurrencyTypeTest extends TypeTestCase +class CurrencyTypeTest extends TestCase { protected function setUp() { diff --git a/Tests/Extension/Core/Type/DateTimeTypeTest.php b/Tests/Extension/Core/Type/DateTimeTypeTest.php index 213bc9ce43..8f51e2607c 100644 --- a/Tests/Extension/Core/Type/DateTimeTypeTest.php +++ b/Tests/Extension/Core/Type/DateTimeTypeTest.php @@ -12,9 +12,10 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\FormError; +use Symfony\Component\Form\Test\TypeTestCase as TestCase; use Symfony\Component\Intl\Util\IntlTestHelper; -class DateTimeTypeTest extends TypeTestCase +class DateTimeTypeTest extends TestCase { protected function setUp() { diff --git a/Tests/Extension/Core/Type/DateTypeTest.php b/Tests/Extension/Core/Type/DateTypeTest.php index ed583a0af4..e5b58a8c4a 100644 --- a/Tests/Extension/Core/Type/DateTypeTest.php +++ b/Tests/Extension/Core/Type/DateTypeTest.php @@ -13,9 +13,10 @@ use Symfony\Component\Form\Extension\Core\View\ChoiceView; use Symfony\Component\Form\FormError; +use Symfony\Component\Form\Test\TypeTestCase as TestCase; use Symfony\Component\Intl\Util\IntlTestHelper; -class DateTypeTest extends TypeTestCase +class DateTypeTest extends TestCase { protected function setUp() { diff --git a/Tests/Extension/Core/Type/IntegerTypeTest.php b/Tests/Extension/Core/Type/IntegerTypeTest.php index 998bbe0120..85f91ff181 100644 --- a/Tests/Extension/Core/Type/IntegerTypeTest.php +++ b/Tests/Extension/Core/Type/IntegerTypeTest.php @@ -11,9 +11,10 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use Symfony\Component\Form\Test\TypeTestCase as TestCase; use Symfony\Component\Intl\Util\IntlTestHelper; -class IntegerTypeTest extends TypeTestCase +class IntegerTypeTest extends TestCase { protected function setUp() { diff --git a/Tests/Extension/Core/Type/LanguageTypeTest.php b/Tests/Extension/Core/Type/LanguageTypeTest.php index 5c54632e79..e234811887 100644 --- a/Tests/Extension/Core/Type/LanguageTypeTest.php +++ b/Tests/Extension/Core/Type/LanguageTypeTest.php @@ -12,9 +12,10 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Extension\Core\View\ChoiceView; +use Symfony\Component\Form\Test\TypeTestCase as TestCase; use Symfony\Component\Intl\Util\IntlTestHelper; -class LanguageTypeTest extends TypeTestCase +class LanguageTypeTest extends TestCase { protected function setUp() { diff --git a/Tests/Extension/Core/Type/LocaleTypeTest.php b/Tests/Extension/Core/Type/LocaleTypeTest.php index e402cb4bfb..6c1951a4e9 100644 --- a/Tests/Extension/Core/Type/LocaleTypeTest.php +++ b/Tests/Extension/Core/Type/LocaleTypeTest.php @@ -12,9 +12,10 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Extension\Core\View\ChoiceView; +use Symfony\Component\Form\Test\TypeTestCase as TestCase; use Symfony\Component\Intl\Util\IntlTestHelper; -class LocaleTypeTest extends TypeTestCase +class LocaleTypeTest extends TestCase { protected function setUp() { diff --git a/Tests/Extension/Core/Type/MoneyTypeTest.php b/Tests/Extension/Core/Type/MoneyTypeTest.php index e42c89c5a8..c499908d77 100644 --- a/Tests/Extension/Core/Type/MoneyTypeTest.php +++ b/Tests/Extension/Core/Type/MoneyTypeTest.php @@ -11,9 +11,10 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use Symfony\Component\Form\Test\TypeTestCase as TestCase; use Symfony\Component\Intl\Util\IntlTestHelper; -class MoneyTypeTest extends TypeTestCase +class MoneyTypeTest extends TestCase { protected function setUp() { diff --git a/Tests/Extension/Core/Type/NumberTypeTest.php b/Tests/Extension/Core/Type/NumberTypeTest.php index e5b3dd747c..d4a88dd260 100644 --- a/Tests/Extension/Core/Type/NumberTypeTest.php +++ b/Tests/Extension/Core/Type/NumberTypeTest.php @@ -11,9 +11,10 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use Symfony\Component\Form\Test\TypeTestCase as TestCase; use Symfony\Component\Intl\Util\IntlTestHelper; -class NumberTypeTest extends TypeTestCase +class NumberTypeTest extends TestCase { protected function setUp() { diff --git a/Tests/Extension/Core/Type/SubmitTypeTest.php b/Tests/Extension/Core/Type/SubmitTypeTest.php index 2319a4fe75..212ffd4007 100644 --- a/Tests/Extension/Core/Type/SubmitTypeTest.php +++ b/Tests/Extension/Core/Type/SubmitTypeTest.php @@ -11,10 +11,12 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; +use Symfony\Component\Form\Test\TypeTestCase as TestCase; + /** * @author Bernhard Schussek */ -class SubmitTypeTest extends TypeTestCase +class SubmitTypeTest extends TestCase { public function testCreateSubmitButtonInstances() { diff --git a/Tests/Extension/Core/Type/TimeTypeTest.php b/Tests/Extension/Core/Type/TimeTypeTest.php index 01c50abb20..087d4c171e 100644 --- a/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/Tests/Extension/Core/Type/TimeTypeTest.php @@ -13,9 +13,10 @@ use Symfony\Component\Form\Extension\Core\View\ChoiceView; use Symfony\Component\Form\FormError; +use Symfony\Component\Form\Test\TypeTestCase as TestCase; use Symfony\Component\Intl\Util\IntlTestHelper; -class TimeTypeTest extends TypeTestCase +class TimeTypeTest extends TestCase { protected function setUp() { diff --git a/Tests/Extension/Core/Type/UrlTypeTest.php b/Tests/Extension/Core/Type/UrlTypeTest.php index fa975ac86c..f5c38ea752 100644 --- a/Tests/Extension/Core/Type/UrlTypeTest.php +++ b/Tests/Extension/Core/Type/UrlTypeTest.php @@ -11,7 +11,9 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; -class UrlTypeTest extends TypeTestCase +use Symfony\Component\Form\Test\TypeTestCase as TestCase; + +class UrlTypeTest extends TestCase { public function testSubmitAddsDefaultProtocolIfNoneIsIncluded() { From fea34f6a55adf35b80f12df83b6a8378939f83be Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Mon, 29 Dec 2014 23:41:34 +0100 Subject: [PATCH 381/447] Fix phpdoc and coding standards This removes the unused use statements which were not catched by PHP-CS-Fixer because of string occurences. It also fixes some invalid phpdoc (scalar is not recognized as a valid type for instance). --- .../Core/DataTransformer/BooleanToStringTransformerTest.php | 2 +- Tests/Extension/Core/Type/CollectionTypeTest.php | 2 -- Tests/Extension/Core/Type/FormTypeTest.php | 1 - Tests/Extension/Validator/Constraints/FormValidatorTest.php | 1 - Tests/Fixtures/FooSubType.php | 5 ----- Tests/Fixtures/FooSubTypeWithParentInstance.php | 5 ----- Tests/Fixtures/FooType.php | 5 ----- Tests/FormFactoryTest.php | 1 - Tests/ResolvedFormTypeTest.php | 1 - 9 files changed, 1 insertion(+), 22 deletions(-) diff --git a/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php index 4149160c9c..a1217783d1 100644 --- a/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php @@ -18,7 +18,7 @@ class BooleanToStringTransformerTest extends \PHPUnit_Framework_TestCase const TRUE_VALUE = '1'; /** - * @var boolToStringTransformer + * @var BooleanToStringTransformer */ protected $transformer; diff --git a/Tests/Extension/Core/Type/CollectionTypeTest.php b/Tests/Extension/Core/Type/CollectionTypeTest.php index 3dee683ddd..6f88a92cb9 100644 --- a/Tests/Extension/Core/Type/CollectionTypeTest.php +++ b/Tests/Extension/Core/Type/CollectionTypeTest.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; -use Symfony\Component\Form\Form; - class CollectionTypeTest extends \Symfony\Component\Form\Test\TypeTestCase { public function testContainsNoChildByDefault() diff --git a/Tests/Extension/Core/Type/FormTypeTest.php b/Tests/Extension/Core/Type/FormTypeTest.php index 43f9e706d1..43a6fa794c 100644 --- a/Tests/Extension/Core/Type/FormTypeTest.php +++ b/Tests/Extension/Core/Type/FormTypeTest.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\PropertyAccess\PropertyPath; -use Symfony\Component\Form\Form; use Symfony\Component\Form\CallbackTransformer; use Symfony\Component\Form\Tests\Fixtures\Author; use Symfony\Component\Form\Tests\Fixtures\FixedDataTransformer; diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index f2f4e4422e..c440a0470a 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -18,7 +18,6 @@ use Symfony\Component\Form\Extension\Validator\Constraints\Form; use Symfony\Component\Form\Extension\Validator\Constraints\FormValidator; use Symfony\Component\Form\SubmitButtonBuilder; -use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Tests\Constraints\AbstractConstraintValidatorTest; diff --git a/Tests/Fixtures/FooSubType.php b/Tests/Fixtures/FooSubType.php index 4f7ba6d4a7..52cefb44cf 100644 --- a/Tests/Fixtures/FooSubType.php +++ b/Tests/Fixtures/FooSubType.php @@ -12,11 +12,6 @@ namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\FormBuilder; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormFactoryInterface; -use Symfony\Component\EventDispatcher\EventDispatcher; -use Symfony\Component\OptionsResolver\OptionsResolverInterface; class FooSubType extends AbstractType { diff --git a/Tests/Fixtures/FooSubTypeWithParentInstance.php b/Tests/Fixtures/FooSubTypeWithParentInstance.php index 468b5a32a7..9416d7b4ed 100644 --- a/Tests/Fixtures/FooSubTypeWithParentInstance.php +++ b/Tests/Fixtures/FooSubTypeWithParentInstance.php @@ -12,11 +12,6 @@ namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\FormBuilder; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormFactoryInterface; -use Symfony\Component\EventDispatcher\EventDispatcher; -use Symfony\Component\OptionsResolver\OptionsResolverInterface; class FooSubTypeWithParentInstance extends AbstractType { diff --git a/Tests/Fixtures/FooType.php b/Tests/Fixtures/FooType.php index 626ccf08ed..bc19110792 100644 --- a/Tests/Fixtures/FooType.php +++ b/Tests/Fixtures/FooType.php @@ -12,11 +12,6 @@ namespace Symfony\Component\Form\Tests\Fixtures; use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\FormBuilder; -use Symfony\Component\Form\FormBuilderInterface; -use Symfony\Component\Form\FormFactoryInterface; -use Symfony\Component\EventDispatcher\EventDispatcher; -use Symfony\Component\OptionsResolver\OptionsResolverInterface; class FooType extends AbstractType { diff --git a/Tests/FormFactoryTest.php b/Tests/FormFactoryTest.php index ea872b01ed..224ef54007 100644 --- a/Tests/FormFactoryTest.php +++ b/Tests/FormFactoryTest.php @@ -16,7 +16,6 @@ use Symfony\Component\Form\Guess\Guess; use Symfony\Component\Form\Guess\ValueGuess; use Symfony\Component\Form\Guess\TypeGuess; -use Symfony\Component\Form\Tests\Fixtures\Author; use Symfony\Component\Form\Tests\Fixtures\FooType; use Symfony\Component\Form\Tests\Fixtures\FooSubType; use Symfony\Component\Form\Tests\Fixtures\FooSubTypeWithParentInstance; diff --git a/Tests/ResolvedFormTypeTest.php b/Tests/ResolvedFormTypeTest.php index 5aa0d357fd..21f151d083 100644 --- a/Tests/ResolvedFormTypeTest.php +++ b/Tests/ResolvedFormTypeTest.php @@ -14,7 +14,6 @@ use Symfony\Component\Form\ResolvedFormType; use Symfony\Component\Form\FormView; use Symfony\Component\Form\FormBuilder; -use Symfony\Component\Form\Form; use Symfony\Component\OptionsResolver\OptionsResolverInterface; /** From 34c9517a5117f2400620f3994aa0b848f401c374 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 30 Dec 2014 11:15:02 +0100 Subject: [PATCH 382/447] fixed unit tests --- Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php index 93724121fe..334872a389 100644 --- a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php +++ b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php @@ -284,15 +284,15 @@ public function testValidateTokenOnSubmitIfRootAndCompoundUsesTypeClassAsIntenti */ public function testValidateTokenOnBindIfRootAndCompoundUsesTypeClassAsIntentionIfEmptyFormName($valid) { - $this->csrfProvider->expects($this->once()) - ->method('isCsrfTokenValid') - ->with('Symfony\Component\Form\Extension\Core\Type\FormType', 'token') + $this->tokenManager->expects($this->once()) + ->method('isTokenValid') + ->with(new CsrfToken('Symfony\Component\Form\Extension\Core\Type\FormType', 'token')) ->will($this->returnValue($valid)); $form = $this->factory ->createNamedBuilder('', 'form', null, array( 'csrf_field_name' => 'csrf', - 'csrf_provider' => $this->csrfProvider, + 'csrf_token_manager' => $this->tokenManager, 'compound' => true, )) ->add('child', 'text') From 79af0f3d987495500916be0cedaa0bd19a7dcaa0 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Tue, 30 Dec 2014 11:40:10 +0000 Subject: [PATCH 383/447] [Form] Set a child type to text if added to the form without a type. This copies the behaviour of the FormBuilder::create() to the Form::add(). --- Form.php | 4 ++++ Tests/CompoundFormTest.php | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/Form.php b/Form.php index b67700a6f3..8a19f82a2d 100644 --- a/Form.php +++ b/Form.php @@ -873,6 +873,10 @@ public function add($child, $type = null, array $options = array()) // Never initialize child forms automatically $options['auto_initialize'] = false; + if (null === $type && null === $this->config->getDataClass()) { + $type = 'text'; + } + if (null === $type) { $child = $this->config->getFormFactory()->createForProperty($this->config->getDataClass(), $child, null, $options); } else { diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index 17c4f3b0bf..6e500baaa9 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -207,6 +207,22 @@ public function testAddUsingIntegerNameAndType() $this->assertSame(array(0 => $child), $this->form->all()); } + public function testAddWithoutType() + { + $child = $this->getBuilder('foo')->getForm(); + + $this->factory->expects($this->once()) + ->method('createNamed') + ->with('foo', 'text') + ->will($this->returnValue($child)); + + $this->form->add('foo'); + + $this->assertTrue($this->form->has('foo')); + $this->assertSame($this->form, $child->getParent()); + $this->assertSame(array('foo' => $child), $this->form->all()); + } + public function testAddUsingNameButNoType() { $this->form = $this->getBuilder('name', null, '\stdClass') From 5ef24565572b69cedb7ecfa69975c04d43e8cbe5 Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Tue, 30 Dec 2014 12:20:04 +0000 Subject: [PATCH 384/447] [Form] Remove a redundant test. This is exactly the same as testValidateTokenOnSubmitIfRootAndCompoundUsesTypeClassAsIntentionIfEmptyFormName(). --- .../Csrf/Type/FormTypeCsrfExtensionTest.php | 31 ------------------- 1 file changed, 31 deletions(-) diff --git a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php index fdeec2aa34..b05b1f29b1 100644 --- a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php +++ b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php @@ -278,37 +278,6 @@ public function testValidateTokenOnSubmitIfRootAndCompoundUsesTypeClassAsIntenti $this->assertSame($valid, $form->isValid()); } - /** - * @dataProvider provideBoolean - */ - public function testValidateTokenOnBindIfRootAndCompoundUsesTypeClassAsIntentionIfEmptyFormName($valid) - { - $this->csrfProvider->expects($this->once()) - ->method('isCsrfTokenValid') - ->with('Symfony\Component\Form\Extension\Core\Type\FormType', 'token') - ->will($this->returnValue($valid)); - - $form = $this->factory - ->createNamedBuilder('', 'form', null, array( - 'csrf_field_name' => 'csrf', - 'csrf_provider' => $this->csrfProvider, - 'compound' => true, - )) - ->add('child', 'text') - ->getForm(); - - $form->submit(array( - 'child' => 'foobar', - 'csrf' => 'token', - )); - - // Remove token from data - $this->assertSame(array('child' => 'foobar'), $form->getData()); - - // Validate accordingly - $this->assertSame($valid, $form->isValid()); - } - public function testFailIfRootAndCompoundAndTokenMissing() { $this->csrfProvider->expects($this->never()) From 8affd4eb81cd4c9018676f48cc07c838e874a78e Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Tue, 30 Dec 2014 15:05:42 +0000 Subject: [PATCH 385/447] Clarify a comment. The previous comment was lying since collectViewVariables() doesn't really call the buildPreliminaryFormTree() nor the buildFinalFormTree(). --- .../DataCollector/EventListener/DataCollectorListener.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Extension/DataCollector/EventListener/DataCollectorListener.php b/Extension/DataCollector/EventListener/DataCollectorListener.php index 65ed4abaae..6419af4778 100644 --- a/Extension/DataCollector/EventListener/DataCollectorListener.php +++ b/Extension/DataCollector/EventListener/DataCollectorListener.php @@ -76,8 +76,7 @@ public function postSubmit(FormEvent $event) $this->dataCollector->collectSubmittedData($event->getForm()); // Assemble a form tree - // This is done again in collectViewVariables(), but that method - // is not guaranteed to be called (i.e. when no view is created) + // This is done again after the view is built, but we need it here as the view is not always created. $this->dataCollector->buildPreliminaryFormTree($event->getForm()); } } From d1aa83341c59b5b640215d10db909bf26e35353f Mon Sep 17 00:00:00 2001 From: Saro0h Date: Thu, 1 Jan 2015 01:12:43 +0100 Subject: [PATCH 386/447] Updated copyright to 2015 --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 0b3292cf90..43028bc600 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2014 Fabien Potencier +Copyright (c) 2004-2015 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 300ecf4dd83285aecd6a2d3c0e255d382863e48f Mon Sep 17 00:00:00 2001 From: Hugo Hamon Date: Sun, 21 Dec 2014 17:36:15 +0100 Subject: [PATCH 387/447] Fixes various phpdoc and coding standards. --- Extension/Core/ChoiceList/ChoiceList.php | 2 +- Extension/Core/ChoiceList/ChoiceListInterface.php | 2 +- Tests/FormBuilderTest.php | 4 +--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Extension/Core/ChoiceList/ChoiceList.php b/Extension/Core/ChoiceList/ChoiceList.php index 358cc4cd17..d9d00ef7d1 100644 --- a/Extension/Core/ChoiceList/ChoiceList.php +++ b/Extension/Core/ChoiceList/ChoiceList.php @@ -501,7 +501,7 @@ protected function fixChoice($choice) * * @return array The fixed choices. * - * @see fixChoice + * @see fixChoice() */ protected function fixChoices(array $choices) { diff --git a/Extension/Core/ChoiceList/ChoiceListInterface.php b/Extension/Core/ChoiceList/ChoiceListInterface.php index c74a666228..d205b92d4d 100644 --- a/Extension/Core/ChoiceList/ChoiceListInterface.php +++ b/Extension/Core/ChoiceList/ChoiceListInterface.php @@ -88,7 +88,7 @@ public function getPreferredViews(); * choice indices as keys on the lowest levels and the choice * group names in the keys of the higher levels * - * @see getPreferredValues + * @see getPreferredValues() */ public function getRemainingViews(); diff --git a/Tests/FormBuilderTest.php b/Tests/FormBuilderTest.php index 71cd70cfbb..c49d393b44 100644 --- a/Tests/FormBuilderTest.php +++ b/Tests/FormBuilderTest.php @@ -16,9 +16,7 @@ class FormBuilderTest extends \PHPUnit_Framework_TestCase { private $dispatcher; - private $factory; - private $builder; protected function setUp() @@ -43,7 +41,7 @@ protected function tearDown() * Changing the name is not allowed, otherwise the name and property path * are not synchronized anymore. * - * @see FormType::buildForm + * @see FormType::buildForm() */ public function testNoSetName() { From b430298ab6ceffcd8e89ce1cad04be9a30c20173 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 2 Jan 2015 17:09:32 +0100 Subject: [PATCH 388/447] [2.3] Cleanup deprecations --- ButtonBuilder.php | 6 ++++++ Test/DeprecationErrorHandler.php | 3 +++ Tests/AbstractLayoutTest.php | 13 +++++++++--- ....php => LegacyBindRequestListenerTest.php} | 21 ++++++++++--------- 4 files changed, 30 insertions(+), 13 deletions(-) rename Tests/Extension/HttpFoundation/EventListener/{BindRequestListenerTest.php => LegacyBindRequestListenerTest.php} (93%) diff --git a/ButtonBuilder.php b/ButtonBuilder.php index d881acc3fe..24bc2f8916 100644 --- a/ButtonBuilder.php +++ b/ButtonBuilder.php @@ -386,6 +386,9 @@ public function setByReference($byReference) * @param bool $virtual * * @throws BadMethodCallException + * + * @deprecated since version 2.3, to be removed in 3.0. Use + * {@link setInheritData()} instead. */ public function setVirtual($virtual) { @@ -588,6 +591,9 @@ public function getByReference() * Unsupported method. * * @return bool Always returns false. + * + * @deprecated since version 2.3, to be removed in 3.0. Use + * {@link getInheritData()} instead. */ public function getVirtual() { diff --git a/Test/DeprecationErrorHandler.php b/Test/DeprecationErrorHandler.php index 36417f740f..9ee0523177 100644 --- a/Test/DeprecationErrorHandler.php +++ b/Test/DeprecationErrorHandler.php @@ -13,6 +13,9 @@ use Symfony\Component\Form\FormEvent; +/** + * @deprecated since version 2.3, to be removed in 3.0. + */ class DeprecationErrorHandler { public static function handle($errorNumber, $message, $file, $line, $context) diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index 45e18a1841..e05176cf43 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -101,7 +101,10 @@ protected function assertWidgetMatchesXpath(FormView $view, array $vars, $xpath) abstract protected function renderForm(FormView $view, array $vars = array()); - abstract protected function renderEnctype(FormView $view); + protected function renderEnctype(FormView $view) + { + $this->markTestSkipped(sprintf('Legacy %s::renderEnctype() is not implemented.', get_class($this))); + } abstract protected function renderLabel(FormView $view, $label = null, array $vars = array()); @@ -119,8 +122,10 @@ abstract protected function renderEnd(FormView $view, array $vars = array()); abstract protected function setTheme(FormView $view, array $themes); - public function testEnctype() + public function testLegacyEnctype() { + $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); + $form = $this->factory->createNamedBuilder('name', 'form') ->add('file', 'file') ->getForm(); @@ -128,8 +133,10 @@ public function testEnctype() $this->assertEquals('enctype="multipart/form-data"', $this->renderEnctype($form->createView())); } - public function testNoEnctype() + public function testLegacyNoEnctype() { + $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); + $form = $this->factory->createNamedBuilder('name', 'form') ->add('text', 'text') ->getForm(); diff --git a/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php b/Tests/Extension/HttpFoundation/EventListener/LegacyBindRequestListenerTest.php similarity index 93% rename from Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php rename to Tests/Extension/HttpFoundation/EventListener/LegacyBindRequestListenerTest.php index 00a93aa264..4f1027f0b1 100644 --- a/Tests/Extension/HttpFoundation/EventListener/BindRequestListenerTest.php +++ b/Tests/Extension/HttpFoundation/EventListener/LegacyBindRequestListenerTest.php @@ -15,14 +15,13 @@ use Symfony\Component\Form\Form; use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\Form\FormEvent; -use Symfony\Component\Form\Test\DeprecationErrorHandler; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\File\UploadedFile; /** * @author Bernhard Schussek */ -class BindRequestListenerTest extends \PHPUnit_Framework_TestCase +class LegacyBindRequestListenerTest extends \PHPUnit_Framework_TestCase { private $values; @@ -37,6 +36,8 @@ class BindRequestListenerTest extends \PHPUnit_Framework_TestCase protected function setUp() { + $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); + $path = tempnam(sys_get_temp_dir(), 'sf2'); touch($path); @@ -102,7 +103,7 @@ public function testSubmitRequest($method) $event = new FormEvent($form, $request); $listener = new BindRequestListener(); - DeprecationErrorHandler::preBind($listener, $event); + $listener->preBind($event); $this->assertEquals(array( 'name' => 'Bernhard', @@ -129,7 +130,7 @@ public function testSubmitRequestWithEmptyName($method) $event = new FormEvent($form, $request); $listener = new BindRequestListener(); - DeprecationErrorHandler::preBind($listener, $event); + $listener->preBind($event); $this->assertEquals(array( 'name' => 'Bernhard', @@ -158,7 +159,7 @@ public function testSubmitEmptyRequestToCompoundForm($method) $event = new FormEvent($form, $request); $listener = new BindRequestListener(); - DeprecationErrorHandler::preBind($listener, $event); + $listener->preBind($event); // Default to empty array $this->assertEquals(array(), $event->getData()); @@ -184,7 +185,7 @@ public function testSubmitEmptyRequestToSimpleForm($method) $event = new FormEvent($form, $request); $listener = new BindRequestListener(); - DeprecationErrorHandler::preBind($listener, $event); + $listener->preBind($event); // Default to null $this->assertNull($event->getData()); @@ -207,7 +208,7 @@ public function testSubmitGetRequest() $event = new FormEvent($form, $request); $listener = new BindRequestListener(); - DeprecationErrorHandler::preBind($listener, $event); + $listener->preBind($event); $this->assertEquals(array( 'name' => 'Bernhard', @@ -231,7 +232,7 @@ public function testSubmitGetRequestWithEmptyName() $event = new FormEvent($form, $request); $listener = new BindRequestListener(); - DeprecationErrorHandler::preBind($listener, $event); + $listener->preBind($event); $this->assertEquals(array( 'name' => 'Bernhard', @@ -257,7 +258,7 @@ public function testSubmitEmptyGetRequestToCompoundForm() $event = new FormEvent($form, $request); $listener = new BindRequestListener(); - DeprecationErrorHandler::preBind($listener, $event); + $listener->preBind($event); $this->assertEquals(array(), $event->getData()); } @@ -279,7 +280,7 @@ public function testSubmitEmptyGetRequestToSimpleForm() $event = new FormEvent($form, $request); $listener = new BindRequestListener(); - DeprecationErrorHandler::preBind($listener, $event); + $listener->preBind($event); $this->assertNull($event->getData()); } From 16085b7e77ace0eefbb567417bf6717710b51e69 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 3 Jan 2015 10:53:32 +0100 Subject: [PATCH 389/447] [2.3] Remove useless tests skips --- Test/FormIntegrationTestCase.php | 4 --- Tests/AbstractFormTest.php | 4 --- Tests/CompoundFormTest.php | 24 -------------- .../DataMapper/PropertyPathMapperTest.php | 8 ----- .../FixRadioInputListenerTest.php | 4 --- .../FixUrlProtocolListenerTest.php | 7 ---- .../MergeCollectionListenerTest.php | 4 --- .../EventListener/ResizeFormListenerTest.php | 4 --- .../Core/EventListener/TrimListenerTest.php | 7 ---- .../CsrfProvider/SessionCsrfProviderTest.php | 4 --- .../CsrfValidationListenerTest.php | 4 --- .../LegacyBindRequestListenerTest.php | 32 ------------------- .../EventListener/ValidationListenerTest.php | 4 --- .../Extension/Validator/Type/TypeTestCase.php | 4 --- .../Validator/ValidatorTypeGuesserTest.php | 4 --- .../ViolationMapper/ViolationMapperTest.php | 4 --- Tests/FormBuilderTest.php | 4 --- Tests/FormFactoryTest.php | 4 --- Tests/ResolvedFormTypeTest.php | 12 ------- 19 files changed, 142 deletions(-) diff --git a/Test/FormIntegrationTestCase.php b/Test/FormIntegrationTestCase.php index a5cf86c412..caab26970c 100644 --- a/Test/FormIntegrationTestCase.php +++ b/Test/FormIntegrationTestCase.php @@ -26,10 +26,6 @@ abstract class FormIntegrationTestCase extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - $this->factory = Forms::createFormFactoryBuilder() ->addExtensions($this->getExtensions()) ->getFormFactory(); diff --git a/Tests/AbstractFormTest.php b/Tests/AbstractFormTest.php index 76167b2dad..a2d171c234 100644 --- a/Tests/AbstractFormTest.php +++ b/Tests/AbstractFormTest.php @@ -34,10 +34,6 @@ abstract class AbstractFormTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - // We need an actual dispatcher to use the deprecated // bindRequest() method $this->dispatcher = new EventDispatcher(); diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index 17c4f3b0bf..b5440ccbee 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -583,10 +583,6 @@ public function requestMethodProvider() */ public function testSubmitPostOrPutRequest($method) { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $path = tempnam(sys_get_temp_dir(), 'sf2'); touch($path); @@ -635,10 +631,6 @@ public function testSubmitPostOrPutRequest($method) */ public function testSubmitPostOrPutRequestWithEmptyRootFormName($method) { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $path = tempnam(sys_get_temp_dir(), 'sf2'); touch($path); @@ -686,10 +678,6 @@ public function testSubmitPostOrPutRequestWithEmptyRootFormName($method) */ public function testSubmitPostOrPutRequestWithSingleChildForm($method) { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $path = tempnam(sys_get_temp_dir(), 'sf2'); touch($path); @@ -726,10 +714,6 @@ public function testSubmitPostOrPutRequestWithSingleChildForm($method) */ public function testSubmitPostOrPutRequestWithSingleChildFormUploadedFile($method) { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $path = tempnam(sys_get_temp_dir(), 'sf2'); touch($path); @@ -755,10 +739,6 @@ public function testSubmitPostOrPutRequestWithSingleChildFormUploadedFile($metho public function testSubmitGetRequest() { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $values = array( 'author' => array( 'firstName' => 'Bernhard', @@ -787,10 +767,6 @@ public function testSubmitGetRequest() public function testSubmitGetRequestWithEmptyRootFormName() { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $values = array( 'firstName' => 'Bernhard', 'lastName' => 'Schussek', diff --git a/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php b/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php index e8e875cc8e..05497fceaa 100644 --- a/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php +++ b/Tests/Extension/Core/DataMapper/PropertyPathMapperTest.php @@ -34,14 +34,6 @@ class PropertyPathMapperTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\Event')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - - if (!class_exists('Symfony\Component\PropertyAccess\PropertyAccess')) { - $this->markTestSkipped('The "PropertyAccess" component is not available'); - } - $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->propertyAccessor = $this->getMock('Symfony\Component\PropertyAccess\PropertyAccessorInterface'); $this->mapper = new PropertyPathMapper($this->propertyAccessor); diff --git a/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php b/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php index a5d5c78a81..426293395c 100644 --- a/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php +++ b/Tests/Extension/Core/EventListener/FixRadioInputListenerTest.php @@ -21,10 +21,6 @@ class FixRadioInputListenerTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - parent::setUp(); $this->choiceList = new SimpleChoiceList(array('' => 'Empty', 0 => 'A', 1 => 'B')); diff --git a/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php b/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php index 2b84e4fd82..475681a053 100644 --- a/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php +++ b/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php @@ -16,13 +16,6 @@ class FixUrlProtocolListenerTest extends \PHPUnit_Framework_TestCase { - protected function setUp() - { - if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - } - public function testFixHttpUrl() { $data = "www.symfony.com"; diff --git a/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php b/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php index dbd28c6b55..2d7ecfec75 100644 --- a/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php +++ b/Tests/Extension/Core/EventListener/MergeCollectionListenerTest.php @@ -22,10 +22,6 @@ abstract class MergeCollectionListenerTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->form = $this->getForm('axes'); diff --git a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php index 07620dc635..7bcc7f2d12 100644 --- a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php +++ b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php @@ -24,10 +24,6 @@ class ResizeFormListenerTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->form = $this->getBuilder() diff --git a/Tests/Extension/Core/EventListener/TrimListenerTest.php b/Tests/Extension/Core/EventListener/TrimListenerTest.php index c753798432..38b39ac11c 100644 --- a/Tests/Extension/Core/EventListener/TrimListenerTest.php +++ b/Tests/Extension/Core/EventListener/TrimListenerTest.php @@ -16,13 +16,6 @@ class TrimListenerTest extends \PHPUnit_Framework_TestCase { - protected function setUp() - { - if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - } - public function testTrim() { $data = " Foo! "; diff --git a/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.php b/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.php index 1dcc6b4c63..99e87158b5 100644 --- a/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.php +++ b/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.php @@ -20,10 +20,6 @@ class SessionCsrfProviderTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\HttpFoundation\Session\Session')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $this->session = $this->getMock( 'Symfony\Component\HttpFoundation\Session\Session', array(), diff --git a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php index 0bcfe74e99..7f2220af72 100644 --- a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php +++ b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php @@ -23,10 +23,6 @@ class CsrfValidationListenerTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->csrfProvider = $this->getMock('Symfony\Component\Form\Extension\Csrf\CsrfProvider\CsrfProviderInterface'); diff --git a/Tests/Extension/HttpFoundation/EventListener/LegacyBindRequestListenerTest.php b/Tests/Extension/HttpFoundation/EventListener/LegacyBindRequestListenerTest.php index 4f1027f0b1..183d3a7a3a 100644 --- a/Tests/Extension/HttpFoundation/EventListener/LegacyBindRequestListenerTest.php +++ b/Tests/Extension/HttpFoundation/EventListener/LegacyBindRequestListenerTest.php @@ -87,10 +87,6 @@ public function requestMethodProvider() */ public function testSubmitRequest($method) { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $values = array('author' => $this->values); $files = array('author' => $this->filesNested); $request = new Request(array(), $values, array(), array(), $files, array( @@ -116,10 +112,6 @@ public function testSubmitRequest($method) */ public function testSubmitRequestWithEmptyName($method) { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $request = new Request(array(), $this->values, array(), array(), $this->filesPlain, array( 'REQUEST_METHOD' => $method, )); @@ -143,10 +135,6 @@ public function testSubmitRequestWithEmptyName($method) */ public function testSubmitEmptyRequestToCompoundForm($method) { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $request = new Request(array(), array(), array(), array(), array(), array( 'REQUEST_METHOD' => $method, )); @@ -170,10 +158,6 @@ public function testSubmitEmptyRequestToCompoundForm($method) */ public function testSubmitEmptyRequestToSimpleForm($method) { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $request = new Request(array(), array(), array(), array(), array(), array( 'REQUEST_METHOD' => $method, )); @@ -193,10 +177,6 @@ public function testSubmitEmptyRequestToSimpleForm($method) public function testSubmitGetRequest() { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $values = array('author' => $this->values); $request = new Request($values, array(), array(), array(), array(), array( 'REQUEST_METHOD' => 'GET', @@ -218,10 +198,6 @@ public function testSubmitGetRequest() public function testSubmitGetRequestWithEmptyName() { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $request = new Request($this->values, array(), array(), array(), array(), array( 'REQUEST_METHOD' => 'GET', )); @@ -242,10 +218,6 @@ public function testSubmitGetRequestWithEmptyName() public function testSubmitEmptyGetRequestToCompoundForm() { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $request = new Request(array(), array(), array(), array(), array(), array( 'REQUEST_METHOD' => 'GET', )); @@ -265,10 +237,6 @@ public function testSubmitEmptyGetRequestToCompoundForm() public function testSubmitEmptyGetRequestToSimpleForm() { - if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - $this->markTestSkipped('The "HttpFoundation" component is not available'); - } - $request = new Request(array(), array(), array(), array(), array(), array( 'REQUEST_METHOD' => 'GET', )); diff --git a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php index 528f94633b..13cbcd2f65 100644 --- a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php +++ b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php @@ -53,10 +53,6 @@ class ValidationListenerTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\Event')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface'); diff --git a/Tests/Extension/Validator/Type/TypeTestCase.php b/Tests/Extension/Validator/Type/TypeTestCase.php index d94d896a1c..f197b19857 100644 --- a/Tests/Extension/Validator/Type/TypeTestCase.php +++ b/Tests/Extension/Validator/Type/TypeTestCase.php @@ -20,10 +20,6 @@ abstract class TypeTestCase extends BaseTypeTestCase protected function setUp() { - if (!class_exists('Symfony\Component\Validator\Constraint')) { - $this->markTestSkipped('The "Validator" component is not available'); - } - $this->validator = $this->getMock('Symfony\Component\Validator\ValidatorInterface'); $metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface'); $this->validator->expects($this->once())->method('getMetadataFactory')->will($this->returnValue($metadataFactory)); diff --git a/Tests/Extension/Validator/ValidatorTypeGuesserTest.php b/Tests/Extension/Validator/ValidatorTypeGuesserTest.php index fdaab2f2f8..61b2a917ec 100644 --- a/Tests/Extension/Validator/ValidatorTypeGuesserTest.php +++ b/Tests/Extension/Validator/ValidatorTypeGuesserTest.php @@ -50,10 +50,6 @@ class ValidatorTypeGuesserTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\Validator\Constraint')) { - $this->markTestSkipped('The "Validator" component is not available'); - } - $this->metadata = new ClassMetadata(self::TEST_CLASS); $this->metadataFactory = $this->getMock('Symfony\Component\Validator\MetadataFactoryInterface'); $this->metadataFactory->expects($this->any()) diff --git a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php index 75a8074105..e4e0f9cc48 100644 --- a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php +++ b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php @@ -60,10 +60,6 @@ class ViolationMapperTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\Event')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->mapper = new ViolationMapper(); $this->message = 'Message'; diff --git a/Tests/FormBuilderTest.php b/Tests/FormBuilderTest.php index c49d393b44..da691838c3 100644 --- a/Tests/FormBuilderTest.php +++ b/Tests/FormBuilderTest.php @@ -21,10 +21,6 @@ class FormBuilderTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->builder = new FormBuilder('name', null, $this->dispatcher, $this->factory); diff --git a/Tests/FormFactoryTest.php b/Tests/FormFactoryTest.php index 224ef54007..546f6bd6c0 100644 --- a/Tests/FormFactoryTest.php +++ b/Tests/FormFactoryTest.php @@ -52,10 +52,6 @@ class FormFactoryTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - $this->resolvedTypeFactory = $this->getMock('Symfony\Component\Form\ResolvedFormTypeFactoryInterface'); $this->guesser1 = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface'); $this->guesser2 = $this->getMock('Symfony\Component\Form\FormTypeGuesserInterface'); diff --git a/Tests/ResolvedFormTypeTest.php b/Tests/ResolvedFormTypeTest.php index 21f151d083..fe61c8b41a 100644 --- a/Tests/ResolvedFormTypeTest.php +++ b/Tests/ResolvedFormTypeTest.php @@ -38,14 +38,6 @@ class ResolvedFormTypeTest extends \PHPUnit_Framework_TestCase protected function setUp() { - if (!class_exists('Symfony\Component\OptionsResolver\OptionsResolver')) { - $this->markTestSkipped('The "OptionsResolver" component is not available'); - } - - if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) { - $this->markTestSkipped('The "EventDispatcher" component is not available'); - } - $this->dispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface'); $this->factory = $this->getMock('Symfony\Component\Form\FormFactoryInterface'); $this->dataMapper = $this->getMock('Symfony\Component\Form\DataMapperInterface'); @@ -53,10 +45,6 @@ protected function setUp() public function testCreateBuilder() { - if (version_compare(\PHPUnit_Runner_Version::id(), '3.7', '<')) { - $this->markTestSkipped('This test requires PHPUnit 3.7.'); - } - $parentType = $this->getMockFormType(); $type = $this->getMockFormType(); $extension1 = $this->getMockFormTypeExtension(); From 39fcd964035ad09fc7b6b2368faad8e530922907 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 4 Jan 2015 12:57:22 +0100 Subject: [PATCH 390/447] add back model_timezone and view_timezone options --- CHANGELOG.md | 9 ++- Extension/Core/Type/TimeType.php | 2 + Tests/Extension/Core/Type/DateTypeTest.php | 51 +++++++++++++- Tests/Extension/Core/Type/TimeTypeTest.php | 77 +++++++++++++++++----- 4 files changed, 121 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cd5f619b25..4611542054 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,20 @@ CHANGELOG ========= +2.6.2 +----- + +* Added back the `model_timezone` and `view_timezone` options for `TimeType`, `DateType` + and `BirthdayType` + 2.6.0 ----- * added "html5" option to Date, Time and DateTimeFormType to be able to enable/disable HTML5 input date when widget option is "single_text" * added "label_format" option with possible placeholders "%name%" and "%id%" - * [BC BREAK] drop support for model_timezone and view_timezone options in TimeType, DateType and BirthdayType + * [BC BREAK] drop support for model_timezone and view_timezone options in TimeType, DateType and BirthdayType, + update to 2.6.2 to get back support for these options 2.5.0 ------ diff --git a/Extension/Core/Type/TimeType.php b/Extension/Core/Type/TimeType.php index 63d56d6899..4fd2cba56c 100644 --- a/Extension/Core/Type/TimeType.php +++ b/Extension/Core/Type/TimeType.php @@ -197,6 +197,8 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'input' => 'datetime', 'with_minutes' => true, 'with_seconds' => false, + 'model_timezone' => null, + 'view_timezone' => null, 'empty_value' => $emptyValue, // deprecated 'placeholder' => $placeholder, 'html5' => true, diff --git a/Tests/Extension/Core/Type/DateTypeTest.php b/Tests/Extension/Core/Type/DateTypeTest.php index 185656ee23..d8b3312b1f 100644 --- a/Tests/Extension/Core/Type/DateTypeTest.php +++ b/Tests/Extension/Core/Type/DateTypeTest.php @@ -60,6 +60,8 @@ public function testInvalidInputOption() public function testSubmitFromSingleTextDateTimeWithDefaultFormat() { $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'widget' => 'single_text', 'input' => 'datetime', )); @@ -74,6 +76,8 @@ public function testSubmitFromSingleTextDateTime() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'widget' => 'single_text', 'input' => 'datetime', )); @@ -88,6 +92,8 @@ public function testSubmitFromSingleTextString() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'widget' => 'single_text', 'input' => 'string', )); @@ -102,6 +108,8 @@ public function testSubmitFromSingleTextTimestamp() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'widget' => 'single_text', 'input' => 'timestamp', )); @@ -118,6 +126,8 @@ public function testSubmitFromSingleTextRaw() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'widget' => 'single_text', 'input' => 'array', )); @@ -137,6 +147,8 @@ public function testSubmitFromSingleTextRaw() public function testSubmitFromText() { $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'widget' => 'text', )); @@ -157,6 +169,8 @@ public function testSubmitFromText() public function testSubmitFromChoice() { $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'widget' => 'choice', )); @@ -177,6 +191,8 @@ public function testSubmitFromChoice() public function testSubmitFromChoiceEmpty() { $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'widget' => 'choice', 'required' => false, )); @@ -196,6 +212,8 @@ public function testSubmitFromChoiceEmpty() public function testSubmitFromInputDateTimeDifferentPattern() { $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'format' => 'MM*yyyy*dd', 'widget' => 'single_text', 'input' => 'datetime', @@ -210,6 +228,8 @@ public function testSubmitFromInputDateTimeDifferentPattern() public function testSubmitFromInputStringDifferentPattern() { $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'format' => 'MM*yyyy*dd', 'widget' => 'single_text', 'input' => 'string', @@ -224,6 +244,8 @@ public function testSubmitFromInputStringDifferentPattern() public function testSubmitFromInputTimestampDifferentPattern() { $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'format' => 'MM*yyyy*dd', 'widget' => 'single_text', 'input' => 'timestamp', @@ -240,6 +262,8 @@ public function testSubmitFromInputTimestampDifferentPattern() public function testSubmitFromInputRawDifferentPattern() { $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'format' => 'MM*yyyy*dd', 'widget' => 'single_text', 'input' => 'array', @@ -358,10 +382,25 @@ public function testThrowExceptionIfDaysIsInvalid() public function testSetDataWithDifferentNegativeUTCTimezoneDateTime() { - date_default_timezone_set('Pacific/Tahiti'); + $form = $this->factory->create('date', null, array( + 'format' => \IntlDateFormatter::MEDIUM, + 'model_timezone' => 'America/New_York', + 'view_timezone' => 'Pacific/Tahiti', + 'input' => 'string', + 'widget' => 'single_text', + )); + $form->setData('2010-06-02'); + + $this->assertEquals('01.06.2010', $form->getViewData()); + } + + public function testSetDataWithDifferentTimezonesDateTime() + { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, + 'model_timezone' => 'America/New_York', + 'view_timezone' => 'Pacific/Tahiti', 'input' => 'datetime', 'widget' => 'single_text', )); @@ -371,7 +410,7 @@ public function testSetDataWithDifferentNegativeUTCTimezoneDateTime() $form->setData($dateTime); $this->assertDateTimeEquals($dateTime, $form->getData()); - $this->assertEquals('02.06.2010', $form->getViewData()); + $this->assertEquals('01.06.2010', $form->getViewData()); } public function testSetDataWithDifferentPositiveUTCTimezoneDateTime() @@ -520,6 +559,8 @@ public function testIsPartiallyFilledReturnsFalseIfSingleText() $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'widget' => 'single_text', )); @@ -533,6 +574,8 @@ public function testIsPartiallyFilledReturnsFalseIfChoiceAndCompletelyEmpty() $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'widget' => 'choice', )); @@ -550,6 +593,8 @@ public function testIsPartiallyFilledReturnsFalseIfChoiceAndCompletelyFilled() $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'widget' => 'choice', )); @@ -567,6 +612,8 @@ public function testIsPartiallyFilledReturnsTrueIfChoiceAndDayEmpty() $this->markTestIncomplete('Needs to be reimplemented using validators'); $form = $this->factory->create('date', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'widget' => 'choice', )); diff --git a/Tests/Extension/Core/Type/TimeTypeTest.php b/Tests/Extension/Core/Type/TimeTypeTest.php index 3ad3bd46f9..dfa8fbc5a1 100644 --- a/Tests/Extension/Core/Type/TimeTypeTest.php +++ b/Tests/Extension/Core/Type/TimeTypeTest.php @@ -18,25 +18,18 @@ class TimeTypeTest extends TestCase { - private $defaultTimezone; - protected function setUp() { IntlTestHelper::requireIntl($this); parent::setUp(); - - $this->defaultTimezone = date_default_timezone_get(); - } - - protected function tearDown() - { - date_default_timezone_set($this->defaultTimezone); } public function testSubmitDateTime() { $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'input' => 'datetime', )); @@ -56,6 +49,8 @@ public function testSubmitDateTime() public function testSubmitString() { $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'input' => 'string', )); @@ -73,6 +68,8 @@ public function testSubmitString() public function testSubmitTimestamp() { $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'input' => 'timestamp', )); @@ -92,6 +89,8 @@ public function testSubmitTimestamp() public function testSubmitArray() { $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'input' => 'array', )); @@ -109,6 +108,8 @@ public function testSubmitArray() public function testSubmitDatetimeSingleText() { $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'input' => 'datetime', 'widget' => 'single_text', )); @@ -122,6 +123,8 @@ public function testSubmitDatetimeSingleText() public function testSubmitDatetimeSingleTextWithoutMinutes() { $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'input' => 'datetime', 'widget' => 'single_text', 'with_minutes' => false, @@ -136,6 +139,8 @@ public function testSubmitDatetimeSingleTextWithoutMinutes() public function testSubmitArraySingleText() { $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'input' => 'array', 'widget' => 'single_text', )); @@ -154,6 +159,8 @@ public function testSubmitArraySingleText() public function testSubmitArraySingleTextWithoutMinutes() { $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'input' => 'array', 'widget' => 'single_text', 'with_minutes' => false, @@ -172,6 +179,8 @@ public function testSubmitArraySingleTextWithoutMinutes() public function testSubmitArraySingleTextWithSeconds() { $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'input' => 'array', 'widget' => 'single_text', 'with_seconds' => true, @@ -192,6 +201,8 @@ public function testSubmitArraySingleTextWithSeconds() public function testSubmitStringSingleText() { $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'input' => 'string', 'widget' => 'single_text', )); @@ -205,6 +216,8 @@ public function testSubmitStringSingleText() public function testSubmitStringSingleTextWithoutMinutes() { $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'input' => 'string', 'widget' => 'single_text', 'with_minutes' => false, @@ -219,6 +232,8 @@ public function testSubmitStringSingleTextWithoutMinutes() public function testSetDataWithoutMinutes() { $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'input' => 'datetime', 'with_minutes' => false, )); @@ -231,6 +246,8 @@ public function testSetDataWithoutMinutes() public function testSetDataWithSeconds() { $form = $this->factory->create('time', null, array( + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', 'input' => 'datetime', 'with_seconds' => true, )); @@ -240,23 +257,53 @@ public function testSetDataWithSeconds() $this->assertEquals(array('hour' => 3, 'minute' => 4, 'second' => 5), $form->getViewData()); } - public function testSetDataWithTimezoneDateTime() + public function testSetDataDifferentTimezones() { - date_default_timezone_set('Asia/Hong_Kong'); + $form = $this->factory->create('time', null, array( + 'model_timezone' => 'America/New_York', + 'view_timezone' => 'Asia/Hong_Kong', + 'input' => 'string', + 'with_seconds' => true, + )); + + $dateTime = new \DateTime('2013-01-01 12:04:05'); + $dateTime->setTimezone(new \DateTimeZone('America/New_York')); + $form->setData($dateTime->format('H:i:s')); + + $outputTime = clone $dateTime; + $outputTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); + + $displayedData = array( + 'hour' => (int) $outputTime->format('H'), + 'minute' => (int) $outputTime->format('i'), + 'second' => (int) $outputTime->format('s'), + ); + + $this->assertEquals($displayedData, $form->getViewData()); + } + + public function testSetDataDifferentTimezonesDateTime() + { $form = $this->factory->create('time', null, array( + 'model_timezone' => 'America/New_York', + 'view_timezone' => 'Asia/Hong_Kong', 'input' => 'datetime', 'with_seconds' => true, )); - $dateTime = new \DateTime('12:04:05', new \DateTimeZone('America/New_York')); + $dateTime = new \DateTime('12:04:05'); + $dateTime->setTimezone(new \DateTimeZone('America/New_York')); $form->setData($dateTime); + $outputTime = clone $dateTime; + $outputTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); + $displayedData = array( - 'hour' => 12, - 'minute' => 4, - 'second' => 5, + 'hour' => (int) $outputTime->format('H'), + 'minute' => (int) $outputTime->format('i'), + 'second' => (int) $outputTime->format('s'), ); $this->assertDateTimeEquals($dateTime, $form->getData()); From a677bc9cfa8417942b8f79cfaab18f809ed1c884 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 4 Jan 2015 15:37:21 +0100 Subject: [PATCH 391/447] [2.5] cleanup deprecated uses --- Extension/Core/Type/ChoiceType.php | 1 - Forms.php | 53 ------------------- .../ChoiceList/AbstractChoiceListTest.php | 40 ++++++++++---- .../Core/ChoiceList/LazyChoiceListTest.php | 8 ++- .../Core/ChoiceList/ObjectChoiceListTest.php | 16 ++++-- .../SimpleNumericChoiceListTest.php | 8 ++- ....php => LegacyDefaultCsrfProviderTest.php} | 0 ....php => LegacySessionCsrfProviderTest.php} | 4 +- .../Constraints/FormValidatorTest.php | 2 +- Tests/SimpleFormTest.php | 6 +-- 10 files changed, 61 insertions(+), 77 deletions(-) rename Tests/Extension/Csrf/CsrfProvider/{DefaultCsrfProviderTest.php => LegacyDefaultCsrfProviderTest.php} (100%) rename Tests/Extension/Csrf/CsrfProvider/{SessionCsrfProviderTest.php => LegacySessionCsrfProviderTest.php} (92%) diff --git a/Extension/Core/Type/ChoiceType.php b/Extension/Core/Type/ChoiceType.php index dc241779c9..fa10838f90 100644 --- a/Extension/Core/Type/ChoiceType.php +++ b/Extension/Core/Type/ChoiceType.php @@ -62,7 +62,6 @@ public function buildForm(FormBuilderInterface $builder, array $options) $placeholderView = new ChoiceView(null, '', $options['empty_value']); // "placeholder" is a reserved index - // see also ChoiceListInterface::getIndicesForChoices() $this->addSubForms($builder, array('placeholder' => $placeholderView), $options); } diff --git a/Forms.php b/Forms.php index c949c1f48a..96ac45129f 100644 --- a/Forms.php +++ b/Forms.php @@ -55,39 +55,6 @@ * ->getFormFactory(); * * - * Support for CSRF protection is provided by the CsrfExtension. - * This extension needs a CSRF provider with a strong secret - * (e.g. a 20 character long random string). The default - * implementation for this is DefaultCsrfProvider: - * - * - * use Symfony\Component\Form\Extension\Csrf\CsrfExtension; - * use Symfony\Component\Form\Extension\Csrf\CsrfProvider\DefaultCsrfProvider; - * - * $secret = 'V8a5Z97e...'; - * $formFactory = Forms::createFormFactoryBuilder() - * ->addExtension(new CsrfExtension(new DefaultCsrfProvider($secret))) - * ->getFormFactory(); - * - * - * Support for the HttpFoundation is provided by the - * HttpFoundationExtension. You are also advised to load the CSRF - * extension with the driver for HttpFoundation's Session class: - * - * - * use Symfony\Component\HttpFoundation\Session\Session; - * use Symfony\Component\Form\Extension\HttpFoundation\HttpFoundationExtension; - * use Symfony\Component\Form\Extension\Csrf\CsrfExtension; - * use Symfony\Component\Form\Extension\Csrf\CsrfProvider\SessionCsrfProvider; - * - * $session = new Session(); - * $secret = 'V8a5Z97e...'; - * $formFactory = Forms::createFormFactoryBuilder() - * ->addExtension(new HttpFoundationExtension()) - * ->addExtension(new CsrfExtension(new SessionCsrfProvider($session, $secret))) - * ->getFormFactory(); - * - * * Support for the Validator component is provided by ValidatorExtension. * This extension needs a validator object to function properly: * @@ -129,26 +96,6 @@ * ->getFormFactory(); * * - * If you also loaded the CsrfExtension, you should pass the CSRF provider - * to the extension so that you can render CSRF tokens in your templates - * more easily: - * - * - * use Symfony\Component\Form\Extension\Csrf\CsrfExtension; - * use Symfony\Component\Form\Extension\Csrf\CsrfProvider\DefaultCsrfProvider; - * use Symfony\Component\Form\Extension\Templating\TemplatingExtension; - * - * - * $secret = 'V8a5Z97e...'; - * $csrfProvider = new DefaultCsrfProvider($secret); - * $formFactory = Forms::createFormFactoryBuilder() - * ->addExtension(new CsrfExtension($csrfProvider)) - * ->addExtension(new TemplatingExtension($engine, $csrfProvider, array( - * 'FrameworkBundle:Form', - * ))) - * ->getFormFactory(); - * - * * @author Bernhard Schussek */ final class Forms diff --git a/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php b/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php index c762064e0b..f503b95622 100644 --- a/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php @@ -161,63 +161,83 @@ public function testGetValues() $this->assertSame($this->values, $this->list->getValues()); } - public function testGetIndicesForChoices() + public function testLegacyGetIndicesForChoices() { + $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $choices = array($this->choice1, $this->choice2); $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices)); } - public function testGetIndicesForChoicesPreservesKeys() + public function testLegacyGetIndicesForChoicesPreservesKeys() { + $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $choices = array(5 => $this->choice1, 8 => $this->choice2); $this->assertSame(array(5 => $this->index1, 8 => $this->index2), $this->list->getIndicesForChoices($choices)); } - public function testGetIndicesForChoicesPreservesOrder() + public function testLegacyGetIndicesForChoicesPreservesOrder() { + $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $choices = array($this->choice2, $this->choice1); $this->assertSame(array($this->index2, $this->index1), $this->list->getIndicesForChoices($choices)); } - public function testGetIndicesForChoicesIgnoresNonExistingChoices() + public function testLegacyGetIndicesForChoicesIgnoresNonExistingChoices() { + $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $choices = array($this->choice1, $this->choice2, 'foobar'); $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices)); } - public function testGetIndicesForChoicesEmpty() + public function testLegacyGetIndicesForChoicesEmpty() { + $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->assertSame(array(), $this->list->getIndicesForChoices(array())); } - public function testGetIndicesForValues() + public function testLegacyGetIndicesForValues() { + $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + // values and indices are always the same $values = array($this->value1, $this->value2); $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForValues($values)); } - public function testGetIndicesForValuesPreservesKeys() + public function testLegacyGetIndicesForValuesPreservesKeys() { + $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + // values and indices are always the same $values = array(5 => $this->value1, 8 => $this->value2); $this->assertSame(array(5 => $this->index1, 8 => $this->index2), $this->list->getIndicesForValues($values)); } - public function testGetIndicesForValuesPreservesOrder() + public function testLegacyGetIndicesForValuesPreservesOrder() { + $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $values = array($this->value2, $this->value1); $this->assertSame(array($this->index2, $this->index1), $this->list->getIndicesForValues($values)); } - public function testGetIndicesForValuesIgnoresNonExistingValues() + public function testLegacyGetIndicesForValuesIgnoresNonExistingValues() { + $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $values = array($this->value1, $this->value2, 'foobar'); $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForValues($values)); } - public function testGetIndicesForValuesEmpty() + public function testLegacyGetIndicesForValuesEmpty() { + $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->assertSame(array(), $this->list->getIndicesForValues(array())); } diff --git a/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php b/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php index bcd309e050..d4ff2124af 100644 --- a/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php @@ -57,14 +57,18 @@ public function testGetRemainingViews() $this->assertEquals(array(0 => new ChoiceView('a', 'a', 'A'), 2 => new ChoiceView('c', 'c', 'C')), $this->list->getRemainingViews()); } - public function testGetIndicesForChoices() + public function testLegacyGetIndicesForChoices() { + $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $choices = array('b', 'c'); $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); } - public function testGetIndicesForValues() + public function testLegacyGetIndicesForValues() { + $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $values = array('b', 'c'); $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); } diff --git a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php index a05fb57c2f..c20ac1ce27 100644 --- a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php @@ -185,8 +185,10 @@ public function testInitArrayThrowsExceptionIfToStringNotFound() ); } - public function testGetIndicesForChoicesWithValuePath() + public function testLegacyGetIndicesForChoicesWithValuePath() { + $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->list = new ObjectChoiceList( array($this->obj1, $this->obj2, $this->obj3, $this->obj4), 'name', @@ -200,8 +202,10 @@ public function testGetIndicesForChoicesWithValuePath() $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices)); } - public function testGetIndicesForChoicesWithValuePathPreservesKeys() + public function testLegacyGetIndicesForChoicesWithValuePathPreservesKeys() { + $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->list = new ObjectChoiceList( array($this->obj1, $this->obj2, $this->obj3, $this->obj4), 'name', @@ -214,8 +218,10 @@ public function testGetIndicesForChoicesWithValuePathPreservesKeys() $this->assertSame(array(5 => $this->index1, 8 => $this->index2), $this->list->getIndicesForChoices($choices)); } - public function testGetIndicesForChoicesWithValuePathPreservesOrder() + public function testLegacyGetIndicesForChoicesWithValuePathPreservesOrder() { + $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->list = new ObjectChoiceList( array($this->obj1, $this->obj2, $this->obj3, $this->obj4), 'name', @@ -228,8 +234,10 @@ public function testGetIndicesForChoicesWithValuePathPreservesOrder() $this->assertSame(array($this->index2, $this->index1), $this->list->getIndicesForChoices($choices)); } - public function testGetIndicesForChoicesWithValuePathIgnoresNonExistingChoices() + public function testLegacyGetIndicesForChoicesWithValuePathIgnoresNonExistingChoices() { + $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->list = new ObjectChoiceList( array($this->obj1, $this->obj2, $this->obj3, $this->obj4), 'name', diff --git a/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php b/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php index fea0dad9ea..540ae16f74 100644 --- a/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php @@ -15,15 +15,19 @@ class SimpleNumericChoiceListTest extends AbstractChoiceListTest { - public function testGetIndicesForChoicesDealsWithNumericChoices() + public function testLegacyGetIndicesForChoicesDealsWithNumericChoices() { + $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + // Pass choices as strings although they are integers $choices = array('0', '1'); $this->assertSame(array(0, 1), $this->list->getIndicesForChoices($choices)); } - public function testGetIndicesForValuesDealsWithNumericValues() + public function testLegacyGetIndicesForValuesDealsWithNumericValues() { + $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + // Pass values as strings although they are integers $values = array('0', '1'); $this->assertSame(array(0, 1), $this->list->getIndicesForValues($values)); diff --git a/Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.php b/Tests/Extension/Csrf/CsrfProvider/LegacyDefaultCsrfProviderTest.php similarity index 100% rename from Tests/Extension/Csrf/CsrfProvider/DefaultCsrfProviderTest.php rename to Tests/Extension/Csrf/CsrfProvider/LegacyDefaultCsrfProviderTest.php diff --git a/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.php b/Tests/Extension/Csrf/CsrfProvider/LegacySessionCsrfProviderTest.php similarity index 92% rename from Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.php rename to Tests/Extension/Csrf/CsrfProvider/LegacySessionCsrfProviderTest.php index 99e87158b5..018f80fa44 100644 --- a/Tests/Extension/Csrf/CsrfProvider/SessionCsrfProviderTest.php +++ b/Tests/Extension/Csrf/CsrfProvider/LegacySessionCsrfProviderTest.php @@ -13,13 +13,15 @@ use Symfony\Component\Form\Extension\Csrf\CsrfProvider\SessionCsrfProvider; -class SessionCsrfProviderTest extends \PHPUnit_Framework_TestCase +class LegacySessionCsrfProviderTest extends \PHPUnit_Framework_TestCase { protected $provider; protected $session; protected function setUp() { + $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); + $this->session = $this->getMock( 'Symfony\Component\HttpFoundation\Session\Session', array(), diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index 786de984ae..b92536fb0f 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -566,7 +566,7 @@ public function getValidationGroups(FormInterface $form) private function getMockExecutionContext() { - return $this->getMock('Symfony\Component\Validator\ExecutionContextInterface'); + return $this->getMock('Symfony\Component\Validator\Context\ExecutionContextInterface'); } /** diff --git a/Tests/SimpleFormTest.php b/Tests/SimpleFormTest.php index 4d88a5ef0f..06047cfb2a 100644 --- a/Tests/SimpleFormTest.php +++ b/Tests/SimpleFormTest.php @@ -100,16 +100,16 @@ public function testDataIsInitializedFromSubmit() public function testFalseIsConvertedToNull() { $mock = $this->getMockBuilder('\stdClass') - ->setMethods(array('preBind')) + ->setMethods(array('preSubmit')) ->getMock(); $mock->expects($this->once()) - ->method('preBind') + ->method('preSubmit') ->with($this->callback(function ($event) { return null === $event->getData(); })); $config = new FormConfigBuilder('name', null, $this->dispatcher); - $config->addEventListener(FormEvents::PRE_SUBMIT, array($mock, 'preBind')); + $config->addEventListener(FormEvents::PRE_SUBMIT, array($mock, 'preSubmit')); $form = new Form($config); $form->submit(false); From ae7ee9349676cfd1978ae33004afe706dec47d46 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 4 Jan 2015 21:27:00 +0100 Subject: [PATCH 392/447] [2.6] cleanup deprecated uses --- Extension/Core/Type/DateTimeType.php | 2 +- Extension/Core/Type/FormType.php | 2 +- composer.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Extension/Core/Type/DateTimeType.php b/Extension/Core/Type/DateTimeType.php index d8b29d2a4a..252d370080 100644 --- a/Extension/Core/Type/DateTimeType.php +++ b/Extension/Core/Type/DateTimeType.php @@ -242,7 +242,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) // Don't add some defaults in order to preserve the defaults // set in DateType and TimeType - $resolver->setOptional(array( + $resolver->setDefined(array( 'empty_value', // deprecated 'placeholder', 'years', diff --git a/Extension/Core/Type/FormType.php b/Extension/Core/Type/FormType.php index e22d90cfa8..627d1557b7 100644 --- a/Extension/Core/Type/FormType.php +++ b/Extension/Core/Type/FormType.php @@ -165,7 +165,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) // If data is given, the form is locked to that data // (independent of its value) - $resolver->setOptional(array( + $resolver->setDefined(array( 'data', )); diff --git a/composer.json b/composer.json index 18f3abaecf..75f8d43c48 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,7 @@ "php": ">=5.3.3", "symfony/event-dispatcher": "~2.1", "symfony/intl": "~2.3", - "symfony/options-resolver": "~2.1", + "symfony/options-resolver": "~2.6", "symfony/property-access": "~2.3" }, "require-dev": { From b1657d26a398f86a7b155e1cd17928da0bff82ae Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 5 Jan 2015 17:25:45 +0100 Subject: [PATCH 393/447] [Form] fix Context\ExecutionContextInterface mock --- Test/DeprecationErrorHandler.php | 4 ++-- .../ChoiceList/AbstractChoiceListTest.php | 20 +++++++++---------- .../Core/ChoiceList/LazyChoiceListTest.php | 4 ++-- .../Core/ChoiceList/ObjectChoiceListTest.php | 8 ++++---- .../SimpleNumericChoiceListTest.php | 4 ++-- .../Constraints/FormValidatorTest.php | 15 +++++++++++++- 6 files changed, 34 insertions(+), 21 deletions(-) diff --git a/Test/DeprecationErrorHandler.php b/Test/DeprecationErrorHandler.php index 9ee0523177..a88ec79214 100644 --- a/Test/DeprecationErrorHandler.php +++ b/Test/DeprecationErrorHandler.php @@ -20,7 +20,7 @@ class DeprecationErrorHandler { public static function handle($errorNumber, $message, $file, $line, $context) { - if ($errorNumber & E_USER_DEPRECATED) { + if ($errorNumber & ~E_USER_DEPRECATED) { return true; } @@ -29,7 +29,7 @@ public static function handle($errorNumber, $message, $file, $line, $context) public static function handleBC($errorNumber, $message, $file, $line, $context) { - if ($errorNumber & E_USER_DEPRECATED) { + if ($errorNumber & ~E_USER_DEPRECATED) { return true; } diff --git a/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php b/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php index f503b95622..f7615546be 100644 --- a/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php @@ -163,7 +163,7 @@ public function testGetValues() public function testLegacyGetIndicesForChoices() { - $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); $choices = array($this->choice1, $this->choice2); $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices)); @@ -171,7 +171,7 @@ public function testLegacyGetIndicesForChoices() public function testLegacyGetIndicesForChoicesPreservesKeys() { - $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); $choices = array(5 => $this->choice1, 8 => $this->choice2); $this->assertSame(array(5 => $this->index1, 8 => $this->index2), $this->list->getIndicesForChoices($choices)); @@ -179,7 +179,7 @@ public function testLegacyGetIndicesForChoicesPreservesKeys() public function testLegacyGetIndicesForChoicesPreservesOrder() { - $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); $choices = array($this->choice2, $this->choice1); $this->assertSame(array($this->index2, $this->index1), $this->list->getIndicesForChoices($choices)); @@ -187,7 +187,7 @@ public function testLegacyGetIndicesForChoicesPreservesOrder() public function testLegacyGetIndicesForChoicesIgnoresNonExistingChoices() { - $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); $choices = array($this->choice1, $this->choice2, 'foobar'); $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices)); @@ -195,14 +195,14 @@ public function testLegacyGetIndicesForChoicesIgnoresNonExistingChoices() public function testLegacyGetIndicesForChoicesEmpty() { - $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); $this->assertSame(array(), $this->list->getIndicesForChoices(array())); } public function testLegacyGetIndicesForValues() { - $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); // values and indices are always the same $values = array($this->value1, $this->value2); @@ -211,7 +211,7 @@ public function testLegacyGetIndicesForValues() public function testLegacyGetIndicesForValuesPreservesKeys() { - $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); // values and indices are always the same $values = array(5 => $this->value1, 8 => $this->value2); @@ -220,7 +220,7 @@ public function testLegacyGetIndicesForValuesPreservesKeys() public function testLegacyGetIndicesForValuesPreservesOrder() { - $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); $values = array($this->value2, $this->value1); $this->assertSame(array($this->index2, $this->index1), $this->list->getIndicesForValues($values)); @@ -228,7 +228,7 @@ public function testLegacyGetIndicesForValuesPreservesOrder() public function testLegacyGetIndicesForValuesIgnoresNonExistingValues() { - $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); $values = array($this->value1, $this->value2, 'foobar'); $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForValues($values)); @@ -236,7 +236,7 @@ public function testLegacyGetIndicesForValuesIgnoresNonExistingValues() public function testLegacyGetIndicesForValuesEmpty() { - $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); $this->assertSame(array(), $this->list->getIndicesForValues(array())); } diff --git a/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php b/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php index d4ff2124af..4b23916673 100644 --- a/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php @@ -59,7 +59,7 @@ public function testGetRemainingViews() public function testLegacyGetIndicesForChoices() { - $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); $choices = array('b', 'c'); $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); @@ -67,7 +67,7 @@ public function testLegacyGetIndicesForChoices() public function testLegacyGetIndicesForValues() { - $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); $values = array('b', 'c'); $this->assertSame(array(1, 2), $this->list->getIndicesForValues($values)); diff --git a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php index c20ac1ce27..eca3169150 100644 --- a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php @@ -187,7 +187,7 @@ public function testInitArrayThrowsExceptionIfToStringNotFound() public function testLegacyGetIndicesForChoicesWithValuePath() { - $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); $this->list = new ObjectChoiceList( array($this->obj1, $this->obj2, $this->obj3, $this->obj4), @@ -204,7 +204,7 @@ public function testLegacyGetIndicesForChoicesWithValuePath() public function testLegacyGetIndicesForChoicesWithValuePathPreservesKeys() { - $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); $this->list = new ObjectChoiceList( array($this->obj1, $this->obj2, $this->obj3, $this->obj4), @@ -220,7 +220,7 @@ public function testLegacyGetIndicesForChoicesWithValuePathPreservesKeys() public function testLegacyGetIndicesForChoicesWithValuePathPreservesOrder() { - $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); $this->list = new ObjectChoiceList( array($this->obj1, $this->obj2, $this->obj3, $this->obj4), @@ -236,7 +236,7 @@ public function testLegacyGetIndicesForChoicesWithValuePathPreservesOrder() public function testLegacyGetIndicesForChoicesWithValuePathIgnoresNonExistingChoices() { - $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); $this->list = new ObjectChoiceList( array($this->obj1, $this->obj2, $this->obj3, $this->obj4), diff --git a/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php b/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php index 540ae16f74..9bbac31a37 100644 --- a/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php @@ -17,7 +17,7 @@ class SimpleNumericChoiceListTest extends AbstractChoiceListTest { public function testLegacyGetIndicesForChoicesDealsWithNumericChoices() { - $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); // Pass choices as strings although they are integers $choices = array('0', '1'); @@ -26,7 +26,7 @@ public function testLegacyGetIndicesForChoicesDealsWithNumericChoices() public function testLegacyGetIndicesForValuesDealsWithNumericValues() { - $this->iniSet('error_reporting', -1 & E_USER_DEPRECATED); + $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); // Pass values as strings although they are integers $values = array('0', '1'); diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index b92536fb0f..cad7c25491 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -566,7 +566,20 @@ public function getValidationGroups(FormInterface $form) private function getMockExecutionContext() { - return $this->getMock('Symfony\Component\Validator\Context\ExecutionContextInterface'); + $context = $this->getMock('Symfony\Component\Validator\Context\ExecutionContextInterface'); + $validator = $this->getMock('Symfony\Component\Validator\Validator\ValidatorInterface'); + $contextualValidator = $this->getMock('Symfony\Component\Validator\Validator\ContextualValidatorInterface'); + + $validator->expects($this->any()) + ->method('inContext') + ->with($context) + ->will($this->returnValue($contextualValidator)); + + $context->expects($this->any()) + ->method('getValidator') + ->will($this->returnValue($validator)); + + return $context; } /** From 8635a65d1b10cde46ca8398f2ce9eb369e672af9 Mon Sep 17 00:00:00 2001 From: Peter Rehm Date: Wed, 7 Jan 2015 11:23:40 +0100 Subject: [PATCH 394/447] Removed unneeded version requirements --- Tests/ResolvedFormTypeTest.php | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/Tests/ResolvedFormTypeTest.php b/Tests/ResolvedFormTypeTest.php index ebb83a8333..2f3fe61020 100644 --- a/Tests/ResolvedFormTypeTest.php +++ b/Tests/ResolvedFormTypeTest.php @@ -100,10 +100,6 @@ public function testGetOptionsResolver() public function testCreateBuilder() { - if (version_compare(\PHPUnit_Runner_Version::id(), '3.7', '<')) { - $this->markTestSkipped('This test requires PHPUnit 3.7.'); - } - $givenOptions = array('a' => 'a_custom', 'c' => 'c_custom'); $resolvedOptions = array('a' => 'a_custom', 'b' => 'b_default', 'c' => 'c_custom', 'd' => 'd_default'); $optionsResolver = $this->getMock('Symfony\Component\OptionsResolver\OptionsResolverInterface'); @@ -132,10 +128,6 @@ public function testCreateBuilder() public function testCreateBuilderWithDataClassOption() { - if (version_compare(\PHPUnit_Runner_Version::id(), '3.7', '<')) { - $this->markTestSkipped('This test requires PHPUnit 3.7.'); - } - $givenOptions = array('data_class' => 'Foo'); $resolvedOptions = array('data_class' => '\stdClass'); $optionsResolver = $this->getMock('Symfony\Component\OptionsResolver\OptionsResolverInterface'); @@ -164,10 +156,6 @@ public function testCreateBuilderWithDataClassOption() public function testBuildForm() { - if (version_compare(\PHPUnit_Runner_Version::id(), '3.7', '<')) { - $this->markTestSkipped('This test requires PHPUnit 3.7.'); - } - $test = $this; $i = 0; From 7e4d6ff512ffb1269efe5f39874dbe066b35ac9a Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 8 Jan 2015 09:14:31 +0100 Subject: [PATCH 395/447] [Form] fixed the CSRF extension to allow using only the new interfaces --- Extension/Csrf/Type/FormTypeCsrfExtension.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Extension/Csrf/Type/FormTypeCsrfExtension.php b/Extension/Csrf/Type/FormTypeCsrfExtension.php index e9b005b1dc..8043cbb3fd 100644 --- a/Extension/Csrf/Type/FormTypeCsrfExtension.php +++ b/Extension/Csrf/Type/FormTypeCsrfExtension.php @@ -128,6 +128,10 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) // BC clause for the "csrf_provider" option $csrfTokenManager = function (Options $options) { + if ($options['csrf_provider'] instanceof CsrfTokenManagerInterface) { + return $options['csrf_provider']; + } + return $options['csrf_provider'] instanceof CsrfTokenManagerAdapter ? $options['csrf_provider']->getTokenManager() : new CsrfProviderAdapter($options['csrf_provider']); @@ -139,7 +143,7 @@ public function setDefaultOptions(OptionsResolverInterface $resolver) 'csrf_message' => 'The CSRF token is invalid. Please try to resubmit the form.', 'csrf_token_manager' => $csrfTokenManager, 'csrf_token_id' => $csrfTokenId, - 'csrf_provider' => new CsrfTokenManagerAdapter($this->defaultTokenManager), + 'csrf_provider' => $this->defaultTokenManager, 'intention' => null, )); } From 5fba8186ffad1bcc6e65f92fbbc9132fdec1b399 Mon Sep 17 00:00:00 2001 From: Alexander Schwenn Date: Fri, 9 Jan 2015 05:42:47 +0100 Subject: [PATCH 396/447] [Form] Fixed check of violation constraint #12792 ConstraintViolation::getConstraint() must not expect to provide a constraint as long as Symfony\Component\Validator\ExecutionContext exists (before 3.0) --- .../EventListener/ValidationListener.php | 3 +- .../EventListener/ValidationListenerTest.php | 29 ++++++++++++++++--- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/Extension/Validator/EventListener/ValidationListener.php b/Extension/Validator/EventListener/ValidationListener.php index 37f194380a..4bebce09cd 100644 --- a/Extension/Validator/EventListener/ValidationListener.php +++ b/Extension/Validator/EventListener/ValidationListener.php @@ -66,7 +66,8 @@ public function validateForm(FormEvent $event) foreach ($violations as $violation) { // Allow the "invalid" constraint to be put onto // non-synchronized forms - $allowNonSynchronized = $violation->getConstraint() instanceof Form && Form::NOT_SYNCHRONIZED_ERROR === $violation->getCode(); + // ConstraintViolation::getConstraint() must not expect to provide a constraint as long as Symfony\Component\Validator\ExecutionContext exists (before 3.0) + $allowNonSynchronized = (null === $violation->getConstraint() || $violation->getConstraint() instanceof Form) && Form::NOT_SYNCHRONIZED_ERROR === $violation->getCode(); $this->violationMapper->mapViolation($violation, $form, $allowNonSynchronized); } diff --git a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php index 845dc85025..91608aebe8 100644 --- a/Tests/Extension/Validator/EventListener/ValidationListenerTest.php +++ b/Tests/Extension/Validator/EventListener/ValidationListenerTest.php @@ -64,9 +64,9 @@ protected function setUp() $this->params = array('foo' => 'bar'); } - private function getConstraintViolation($code = null) + private function getConstraintViolation($code = null, $constraint = null) { - return new ConstraintViolation($this->message, $this->messageTemplate, $this->params, null, 'prop.path', null, null, $code, new Form()); + return new ConstraintViolation($this->message, $this->messageTemplate, $this->params, null, 'prop.path', null, null, $code, $constraint); } private function getBuilder($name = 'name', $propertyPath = null, $dataClass = null) @@ -93,7 +93,7 @@ private function getMockForm() // More specific mapping tests can be found in ViolationMapperTest public function testMapViolation() { - $violation = $this->getConstraintViolation(); + $violation = $this->getConstraintViolation(null, new Form()); $form = $this->getForm('street'); $this->validator->expects($this->once()) @@ -109,7 +109,28 @@ public function testMapViolation() public function testMapViolationAllowsNonSyncIfInvalid() { - $violation = $this->getConstraintViolation(Form::NOT_SYNCHRONIZED_ERROR); + $violation = $this->getConstraintViolation(Form::NOT_SYNCHRONIZED_ERROR, new Form()); + $form = $this->getForm('street'); + + $this->validator->expects($this->once()) + ->method('validate') + ->will($this->returnValue(array($violation))); + + $this->violationMapper->expects($this->once()) + ->method('mapViolation') + // pass true now + ->with($violation, $form, true); + + $this->listener->validateForm(new FormEvent($form, null)); + } + + public function testMapViolationAllowsNonSyncIfInvalidWithoutConstraintReference() + { + // constraint violations have no reference to the constraint if they are created by + // Symfony\Component\Validator\ExecutionContext + // which is deprecated in favor of + // Symfony\Component\Validator\Context\ExecutionContext + $violation = $this->getConstraintViolation(Form::NOT_SYNCHRONIZED_ERROR, null); $form = $this->getForm('street'); $this->validator->expects($this->once()) From 66834df9d43f8dbb0d79f5df28d01cb9fe712698 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 16 Jan 2015 16:35:16 +0100 Subject: [PATCH 397/447] [Form] Improved exception message if the data class is not found --- FormConfigBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FormConfigBuilder.php b/FormConfigBuilder.php index 1d70a49644..d8ebed7403 100644 --- a/FormConfigBuilder.php +++ b/FormConfigBuilder.php @@ -193,7 +193,7 @@ public function __construct($name, $dataClass, EventDispatcherInterface $dispatc self::validateName($name); if (null !== $dataClass && !class_exists($dataClass)) { - throw new InvalidArgumentException(sprintf('The data class "%s" is not a valid class.', $dataClass)); + throw new InvalidArgumentException(sprintf('Class "%s" not found. Is the "data_class" form option set correctly?', $dataClass)); } $this->name = (string) $name; From 67effa6592e6da7e007496e1b170cc3fc2c7a5c7 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 25 Jan 2015 04:21:54 +0100 Subject: [PATCH 398/447] [Form] fixed form tests when using 2.7 deps --- .../Validator/Constraints/FormValidatorTest.php | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/Tests/Extension/Validator/Constraints/FormValidatorTest.php index e1b941ab8e..3dd8a83a33 100644 --- a/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -18,6 +18,7 @@ use Symfony\Component\Form\Extension\Validator\Constraints\Form; use Symfony\Component\Form\Extension\Validator\Constraints\FormValidator; use Symfony\Component\Form\SubmitButtonBuilder; +use Symfony\Component\Validator\Context\ExecutionContextInterface; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Tests\Constraints\AbstractConstraintValidatorTest; @@ -224,14 +225,12 @@ function () { throw new TransformationFailedException(); } $this->validator->validate($form, new Form()); - $is2Dot4Api = Validation::API_VERSION_2_4 === $this->getApiVersion(); - $this->buildViolation('invalid_message_key') ->setParameter('{{ value }}', 'foo') ->setParameter('{{ foo }}', 'bar') ->setInvalidValue('foo') ->setCode(Form::NOT_SYNCHRONIZED_ERROR) - ->setCause($is2Dot4Api ? null : $form->getTransformationFailure()) + ->setCause($this->context instanceof ExecutionContextInterface ? $form->getTransformationFailure() : null) ->assertRaised(); } @@ -261,14 +260,12 @@ function () { throw new TransformationFailedException(); } $this->validator->validate($form, new Form()); - $is2Dot4Api = Validation::API_VERSION_2_4 === $this->getApiVersion(); - $this->buildViolation('invalid_message_key') ->setParameter('{{ value }}', 'foo') ->setParameter('{{ foo }}', 'bar') ->setInvalidValue('foo') ->setCode(Form::NOT_SYNCHRONIZED_ERROR) - ->setCause($is2Dot4Api ? null : $form->getTransformationFailure()) + ->setCause($this->context instanceof ExecutionContextInterface ? $form->getTransformationFailure() : null) ->assertRaised(); } @@ -298,13 +295,11 @@ function () { throw new TransformationFailedException(); } $this->validator->validate($form, new Form()); - $is2Dot4Api = Validation::API_VERSION_2_4 === $this->getApiVersion(); - $this->buildViolation('invalid_message_key') ->setParameter('{{ value }}', 'foo') ->setInvalidValue('foo') ->setCode(Form::NOT_SYNCHRONIZED_ERROR) - ->setCause($is2Dot4Api ? null : $form->getTransformationFailure()) + ->setCause($this->context instanceof ExecutionContextInterface ? $form->getTransformationFailure() : null) ->assertRaised(); } From 199f9942e934fa89f58f5b7d4186af3674671346 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 3 Feb 2015 20:11:13 +0100 Subject: [PATCH 399/447] [Validator] fix DOS-style line endings --- Resources/translations/validators.bg.xlf | 38 ++++++++++++------------ 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/Resources/translations/validators.bg.xlf b/Resources/translations/validators.bg.xlf index 6f00bde940..5c768c305f 100644 --- a/Resources/translations/validators.bg.xlf +++ b/Resources/translations/validators.bg.xlf @@ -1,19 +1,19 @@ - - - - - - This form should not contain extra fields. - Тази форма не трябва да съдържа допълнителни полета. - - - The uploaded file was too large. Please try to upload a smaller file. - Каченият файл е твърде голям. Моля, опитайте да качите по-малък файл. - - - The CSRF token is invalid. Please try to resubmit the form. - Невалиден CSRF токен. Моля, опитайте да изпратите формата отново. - - - - \ No newline at end of file + + + + + + This form should not contain extra fields. + Тази форма не трябва да съдържа допълнителни полета. + + + The uploaded file was too large. Please try to upload a smaller file. + Каченият файл е твърде голям. Моля, опитайте да качите по-малък файл. + + + The CSRF token is invalid. Please try to resubmit the form. + Невалиден CSRF токен. Моля, опитайте да изпратите формата отново. + + + + From 6bc617380ee6e011ca86dc32ac5e9d6897fab5a1 Mon Sep 17 00:00:00 2001 From: Javier Spagnoletti Date: Thu, 29 Jan 2015 23:30:47 -0300 Subject: [PATCH 400/447] [2.7] [Form] Replaced calls to array_search() by in_array() where is no need to get the index | Q | A | ------------- | --- | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | none | License | MIT | Doc PR | none --- Extension/Core/ChoiceList/ChoiceList.php | 2 +- Extension/Core/Type/ChoiceType.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Extension/Core/ChoiceList/ChoiceList.php b/Extension/Core/ChoiceList/ChoiceList.php index d9d00ef7d1..40e9d1a075 100644 --- a/Extension/Core/ChoiceList/ChoiceList.php +++ b/Extension/Core/ChoiceList/ChoiceList.php @@ -381,7 +381,7 @@ protected function addChoice(array &$bucketForPreferred, array &$bucketForRemain */ protected function isPreferred($choice, array $preferredChoices) { - return false !== array_search($choice, $preferredChoices, true); + return in_array($choice, $preferredChoices, true); } /** diff --git a/Extension/Core/Type/ChoiceType.php b/Extension/Core/Type/ChoiceType.php index dc241779c9..5520119fdf 100644 --- a/Extension/Core/Type/ChoiceType.php +++ b/Extension/Core/Type/ChoiceType.php @@ -111,7 +111,7 @@ public function buildView(FormView $view, FormInterface $form, array $options) // avoid making the type check inside the closure. if ($options['multiple']) { $view->vars['is_selected'] = function ($choice, array $values) { - return false !== array_search($choice, $values, true); + return in_array($choice, $values, true); }; } else { $view->vars['is_selected'] = function ($choice, $value) { From c03f1d75ac445b678fd3154bfdf2051c25646203 Mon Sep 17 00:00:00 2001 From: Andrew M Date: Sat, 29 Nov 2014 11:11:35 +0100 Subject: [PATCH 401/447] Add reference to documentation in FormEvents phpdocs --- FormEvents.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/FormEvents.php b/FormEvents.php index 54c72271c7..13fc97f494 100644 --- a/FormEvents.php +++ b/FormEvents.php @@ -11,6 +11,12 @@ namespace Symfony\Component\Form; /** + * To learn more about how form events work check the documentation + * entry at {@link http://symfony.com/doc/current/components/form/form_events.html} + * + * To learn how to dynamically modify forms using events check the cookbook + * entry at {@link http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html} + * * @author Bernhard Schussek */ final class FormEvents From b39f6928db2ca73b219d968d1eb151efe25f42e5 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 5 Feb 2015 10:28:56 +0100 Subject: [PATCH 402/447] fixed URL --- FormEvents.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FormEvents.php b/FormEvents.php index 13fc97f494..c48dff3880 100644 --- a/FormEvents.php +++ b/FormEvents.php @@ -12,10 +12,10 @@ /** * To learn more about how form events work check the documentation - * entry at {@link http://symfony.com/doc/current/components/form/form_events.html} + * entry at {@link http://symfony.com/doc/any/components/form/form_events.html} * * To learn how to dynamically modify forms using events check the cookbook - * entry at {@link http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html} + * entry at {@link http://symfony.com/doc/any/cookbook/form/dynamic_form_modification.html} * * @author Bernhard Schussek */ From ff06705a0540e9fb2236b3e49ecfb5ce62f707bd Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 8 Feb 2015 08:41:14 +0100 Subject: [PATCH 403/447] renamed composer.phar to composer to be consistent with the Symfony docs --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4396ec0155..bde6b78be6 100644 --- a/README.md +++ b/README.md @@ -22,5 +22,5 @@ Resources You can run the unit tests with the following command: $ cd path/to/Symfony/Component/Form/ - $ composer.phar install + $ composer install $ phpunit From 438e162bfb2f38a799bfb6b527713d4ab7baa5cf Mon Sep 17 00:00:00 2001 From: Jakub Zalas Date: Tue, 10 Feb 2015 17:14:04 +0000 Subject: [PATCH 404/447] [FrameworkBundle] Fix title and placeholder rendering in php form templates. --- Tests/AbstractLayoutTest.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index e05176cf43..cfc41cdf48 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -1898,4 +1898,18 @@ public function testStartTagWithExtraAttributes() $this->assertSame('', $html); } + + public function testTranslatedAttributes() + { + $view = $this->factory->createNamedBuilder('name', 'form') + ->add('firstName', 'text', array('attr' => array('title' => 'Foo'))) + ->add('lastName', 'text', array('attr' => array('placeholder' => 'Bar'))) + ->getForm() + ->createView(); + + $html = $this->renderForm($view); + + $this->assertMatchesXpath($html, '/form//input[@title="[trans]Foo[/trans]"]'); + $this->assertMatchesXpath($html, '/form//input[@placeholder="[trans]Bar[/trans]"]'); + } } From 6da08d34bac415ebe8690a3745c9f9ea49b54d93 Mon Sep 17 00:00:00 2001 From: Wouter J Date: Tue, 17 Feb 2015 14:25:32 +0100 Subject: [PATCH 405/447] Small syntax fix --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4611542054..1060f57cd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,8 @@ CHANGELOG 2.6.2 ----- -* Added back the `model_timezone` and `view_timezone` options for `TimeType`, `DateType` - and `BirthdayType` + * Added back the `model_timezone` and `view_timezone` options for `TimeType`, `DateType` + and `BirthdayType` 2.6.0 ----- From 2c5d36c258da8a0edd5a9c0c41c5bfa7d554229b Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 24 Feb 2015 09:06:17 +0100 Subject: [PATCH 406/447] [2.3] require-dev PHPUnit bridge --- composer.json | 1 + phpunit.xml.dist | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index e5d0f06e2b..d9fcb2c0cf 100644 --- a/composer.json +++ b/composer.json @@ -23,6 +23,7 @@ "symfony/property-access": "~2.3" }, "require-dev": { + "symfony/phpunit-bridge": "~2.7", "doctrine/collections": "~1.0", "symfony/validator": "~2.3.0,>=2.3.20", "symfony/translation": "~2.0,>=2.0.5", diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 7ddac030f7..104aee4b0b 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -7,8 +7,7 @@ bootstrap="vendor/autoload.php" > - - + From fe05c612a9e3cd12f3e8137a4605a2e72fd1b69a Mon Sep 17 00:00:00 2001 From: Mikael Pajunen Date: Tue, 24 Feb 2015 00:10:57 +0200 Subject: [PATCH 407/447] [Form] NativeRequestHandler file handling fix --- NativeRequestHandler.php | 4 +- Tests/AbstractRequestHandlerTest.php | 46 ++++++++++++++++++- .../HttpFoundationRequestHandlerTest.php | 4 +- Tests/Fixtures/foo2 | 0 Tests/Fixtures/foo3 | 0 Tests/NativeRequestHandlerTest.php | 6 +-- 6 files changed, 52 insertions(+), 8 deletions(-) create mode 100644 Tests/Fixtures/foo2 create mode 100644 Tests/Fixtures/foo3 diff --git a/NativeRequestHandler.php b/NativeRequestHandler.php index ea748d6161..a888967bb3 100644 --- a/NativeRequestHandler.php +++ b/NativeRequestHandler.php @@ -98,8 +98,8 @@ public function handleRequest(FormInterface $form, $request = null) } $fixedFiles = array(); - foreach ($_FILES as $name => $file) { - $fixedFiles[$name] = self::stripEmptyFiles(self::fixPhpFilesArray($file)); + foreach ($_FILES as $fileKey => $file) { + $fixedFiles[$fileKey] = self::stripEmptyFiles(self::fixPhpFilesArray($file)); } if ('' === $name) { diff --git a/Tests/AbstractRequestHandlerTest.php b/Tests/AbstractRequestHandlerTest.php index b017db90d0..e4d63c2a94 100644 --- a/Tests/AbstractRequestHandlerTest.php +++ b/Tests/AbstractRequestHandlerTest.php @@ -266,6 +266,50 @@ public function testSubmitFileIfNoParam($method) $this->requestHandler->handleRequest($form, $this->request); } + /** + * @dataProvider methodExceptGetProvider + */ + public function testSubmitMultipleFiles($method) + { + $form = $this->getMockForm('param1', $method); + $file = $this->getMockFile(); + + $this->setRequestData($method, array( + 'param1' => null, + ), array( + 'param2' => $this->getMockFile('2'), + 'param1' => $file, + 'param3' => $this->getMockFile('3'), + )); + + $form->expects($this->once()) + ->method('submit') + ->with($file, 'PATCH' !== $method); + + $this->requestHandler->handleRequest($form, $this->request); + } + + /** + * @dataProvider methodExceptGetProvider + */ + public function testSubmitFileWithNamelessForm($method) + { + $form = $this->getMockForm(null, $method); + $file = $this->getMockFile(); + + $this->setRequestData($method, array( + '' => null, + ), array( + '' => $file, + )); + + $form->expects($this->once()) + ->method('submit') + ->with($file, 'PATCH' !== $method); + + $this->requestHandler->handleRequest($form, $this->request); + } + /** * @dataProvider getPostMaxSizeFixtures */ @@ -314,7 +358,7 @@ abstract protected function setRequestData($method, $data, $files = array()); abstract protected function getRequestHandler(); - abstract protected function getMockFile(); + abstract protected function getMockFile($suffix = ''); protected function getMockForm($name, $method = null, $compound = true) { diff --git a/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php b/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php index dcd26891c1..4d4ac86fe7 100644 --- a/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php +++ b/Tests/Extension/HttpFoundation/HttpFoundationRequestHandlerTest.php @@ -46,8 +46,8 @@ protected function getRequestHandler() return new HttpFoundationRequestHandler($this->serverParams); } - protected function getMockFile() + protected function getMockFile($suffix = '') { - return new UploadedFile(__DIR__.'/../../Fixtures/foo', 'foo'); + return new UploadedFile(__DIR__.'/../../Fixtures/foo'.$suffix, 'foo'.$suffix); } } diff --git a/Tests/Fixtures/foo2 b/Tests/Fixtures/foo2 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Tests/Fixtures/foo3 b/Tests/Fixtures/foo3 new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Tests/NativeRequestHandlerTest.php b/Tests/NativeRequestHandlerTest.php index eac767f8c8..38580063e7 100644 --- a/Tests/NativeRequestHandlerTest.php +++ b/Tests/NativeRequestHandlerTest.php @@ -206,12 +206,12 @@ protected function getRequestHandler() return new NativeRequestHandler($this->serverParams); } - protected function getMockFile() + protected function getMockFile($suffix = '') { return array( - 'name' => 'upload.txt', + 'name' => 'upload'.$suffix.'.txt', 'type' => 'text/plain', - 'tmp_name' => 'owfdskjasdfsa', + 'tmp_name' => 'owfdskjasdfsa'.$suffix, 'error' => UPLOAD_ERR_OK, 'size' => 100, ); From ad149646dede5e0f74db606a7b3aec9cba5e3259 Mon Sep 17 00:00:00 2001 From: Dariusz Ruminski Date: Wed, 18 Feb 2015 08:05:44 +0100 Subject: [PATCH 408/447] CS fixes --- FormEvents.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FormEvents.php b/FormEvents.php index c48dff3880..d8c0510c28 100644 --- a/FormEvents.php +++ b/FormEvents.php @@ -12,10 +12,10 @@ /** * To learn more about how form events work check the documentation - * entry at {@link http://symfony.com/doc/any/components/form/form_events.html} + * entry at {@link http://symfony.com/doc/any/components/form/form_events.html}. * * To learn how to dynamically modify forms using events check the cookbook - * entry at {@link http://symfony.com/doc/any/cookbook/form/dynamic_form_modification.html} + * entry at {@link http://symfony.com/doc/any/cookbook/form/dynamic_form_modification.html}. * * @author Bernhard Schussek */ From 4c01bf3ca84f402e8e0c8c6f7e8ff6900844fb68 Mon Sep 17 00:00:00 2001 From: Vladimir Reznichenko Date: Fri, 6 Mar 2015 20:37:36 +0100 Subject: [PATCH 409/447] [2.3] [Config] [Console] [DependencyInjection] [DomCrawler] [Form] [HttpKernel] [PropertyAccess] [Security] [Translation] [Yaml] static code analysis, code cleanup --- AbstractRendererEngine.php | 3 +-- FormBuilder.php | 3 +-- FormRenderer.php | 3 +-- Test/FormPerformanceTestCase.php | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/AbstractRendererEngine.php b/AbstractRendererEngine.php index 00bf85401c..8202cbf97b 100644 --- a/AbstractRendererEngine.php +++ b/AbstractRendererEngine.php @@ -67,8 +67,7 @@ public function setTheme(FormView $view, $themes) // Unset instead of resetting to an empty array, in order to allow // implementations (like TwigRendererEngine) to check whether $cacheKey // is set at all. - unset($this->resources[$cacheKey]); - unset($this->resourceHierarchyLevels[$cacheKey]); + unset($this->resources[$cacheKey], $this->resourceHierarchyLevels[$cacheKey]); } /** diff --git a/FormBuilder.php b/FormBuilder.php index 9437dad1c1..8b5b919413 100644 --- a/FormBuilder.php +++ b/FormBuilder.php @@ -138,8 +138,7 @@ public function remove($name) throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } - unset($this->unresolvedChildren[$name]); - unset($this->children[$name]); + unset($this->unresolvedChildren[$name], $this->children[$name]); return $this; } diff --git a/FormRenderer.php b/FormRenderer.php index 09b010563f..2c6b1dd0be 100644 --- a/FormRenderer.php +++ b/FormRenderer.php @@ -279,8 +279,7 @@ public function searchAndRenderBlock(FormView $view, $blockNameSuffix, array $va // Clear the caches if they were filled for the first time within // this function call if ($hierarchyInit) { - unset($this->blockNameHierarchyMap[$viewAndSuffixCacheKey]); - unset($this->hierarchyLevelMap[$viewAndSuffixCacheKey]); + unset($this->blockNameHierarchyMap[$viewAndSuffixCacheKey], $this->hierarchyLevelMap[$viewAndSuffixCacheKey]); } if ($varInit) { diff --git a/Test/FormPerformanceTestCase.php b/Test/FormPerformanceTestCase.php index 3060472975..090eb8bc4f 100644 --- a/Test/FormPerformanceTestCase.php +++ b/Test/FormPerformanceTestCase.php @@ -54,7 +54,7 @@ protected function runTest() */ public function setMaxRunningTime($maxRunningTime) { - if (is_integer($maxRunningTime) && $maxRunningTime >= 0) { + if (is_int($maxRunningTime) && $maxRunningTime >= 0) { $this->maxRunningTime = $maxRunningTime; } else { throw new \InvalidArgumentException(); From ae3065f8ede1a6835df5b6a758c196821561fe30 Mon Sep 17 00:00:00 2001 From: Vladimir Reznichenko Date: Sat, 7 Mar 2015 20:12:23 +0100 Subject: [PATCH 410/447] Php Inspections (EA Extended) - static code analysis includes: Reduce couple count calls in [Yaml] Modernize type casting, fix several strict comparisons Unsets merged Elvis operator usage Short syntax for applied operations --- Extension/Core/Type/ChoiceType.php | 2 +- Util/ServerParams.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Extension/Core/Type/ChoiceType.php b/Extension/Core/Type/ChoiceType.php index 5520119fdf..418661aebe 100644 --- a/Extension/Core/Type/ChoiceType.php +++ b/Extension/Core/Type/ChoiceType.php @@ -131,7 +131,7 @@ public function buildView(FormView $view, FormInterface $form, array $options) // Add "[]" to the name in case a select tag with multiple options is // displayed. Otherwise only one of the selected options is sent in the // POST request. - $view->vars['full_name'] = $view->vars['full_name'].'[]'; + $view->vars['full_name'] .= '[]'; } } diff --git a/Util/ServerParams.php b/Util/ServerParams.php index 3b1f835182..9b9c02d393 100644 --- a/Util/ServerParams.php +++ b/Util/ServerParams.php @@ -35,7 +35,7 @@ public function getPostMaxSize() } elseif (0 === strpos($max, '0')) { $max = intval($max, 8); } else { - $max = intval($max); + $max = (int) $max; } switch (substr($iniMax, -1)) { From 8567c4b2f09412f1e4800f61aa2e96d1f425f097 Mon Sep 17 00:00:00 2001 From: sarah khalil Date: Wed, 11 Mar 2015 19:44:00 +0100 Subject: [PATCH 411/447] Changed visibility of setUp() and tearDown to protected --- Tests/Extension/DataCollector/DataCollectorExtensionTest.php | 2 +- .../DataCollector/Type/DataCollectorTypeExtensionTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/Extension/DataCollector/DataCollectorExtensionTest.php b/Tests/Extension/DataCollector/DataCollectorExtensionTest.php index 9f5991c105..ce4367cbe4 100644 --- a/Tests/Extension/DataCollector/DataCollectorExtensionTest.php +++ b/Tests/Extension/DataCollector/DataCollectorExtensionTest.php @@ -28,7 +28,7 @@ class DataCollectorExtensionTest extends \PHPUnit_Framework_TestCase */ private $dataCollector; - public function setUp() + protected function setUp() { $this->dataCollector = $this->getMock('Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface'); $this->extension = new DataCollectorExtension($this->dataCollector); diff --git a/Tests/Extension/DataCollector/Type/DataCollectorTypeExtensionTest.php b/Tests/Extension/DataCollector/Type/DataCollectorTypeExtensionTest.php index cb77456984..d881127685 100644 --- a/Tests/Extension/DataCollector/Type/DataCollectorTypeExtensionTest.php +++ b/Tests/Extension/DataCollector/Type/DataCollectorTypeExtensionTest.php @@ -24,7 +24,7 @@ class DataCollectorTypeExtensionTest extends \PHPUnit_Framework_TestCase */ private $dataCollector; - public function setUp() + protected function setUp() { $this->dataCollector = $this->getMock('Symfony\Component\Form\Extension\DataCollector\FormDataCollectorInterface'); $this->extension = new DataCollectorTypeExtension($this->dataCollector); From fb85752b84909c152ad6e5c3bd585d88d4aa5d61 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 13 Mar 2015 18:08:02 +0100 Subject: [PATCH 412/447] [2.3] add @group legacy --- Tests/AbstractLayoutTest.php | 6 ++++++ .../EventListener/LegacyBindRequestListenerTest.php | 1 + 2 files changed, 7 insertions(+) diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index cfc41cdf48..f741ce0b68 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -122,6 +122,9 @@ abstract protected function renderEnd(FormView $view, array $vars = array()); abstract protected function setTheme(FormView $view, array $themes); + /** + * @group legacy + */ public function testLegacyEnctype() { $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); @@ -133,6 +136,9 @@ public function testLegacyEnctype() $this->assertEquals('enctype="multipart/form-data"', $this->renderEnctype($form->createView())); } + /** + * @group legacy + */ public function testLegacyNoEnctype() { $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); diff --git a/Tests/Extension/HttpFoundation/EventListener/LegacyBindRequestListenerTest.php b/Tests/Extension/HttpFoundation/EventListener/LegacyBindRequestListenerTest.php index 183d3a7a3a..521f7b3c17 100644 --- a/Tests/Extension/HttpFoundation/EventListener/LegacyBindRequestListenerTest.php +++ b/Tests/Extension/HttpFoundation/EventListener/LegacyBindRequestListenerTest.php @@ -20,6 +20,7 @@ /** * @author Bernhard Schussek + * @group legacy */ class LegacyBindRequestListenerTest extends \PHPUnit_Framework_TestCase { From e222853aeb7da9735f8b2735ce6994cf7c536b54 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 13 Mar 2015 18:32:20 +0100 Subject: [PATCH 413/447] [2.6] add @group legacy --- .../ChoiceList/AbstractChoiceListTest.php | 30 +++++++++++++++++++ .../Core/ChoiceList/LazyChoiceListTest.php | 6 ++++ .../Core/ChoiceList/ObjectChoiceListTest.php | 12 ++++++++ .../SimpleNumericChoiceListTest.php | 6 ++++ .../LegacyDefaultCsrfProviderTest.php | 3 +- .../LegacySessionCsrfProviderTest.php | 3 ++ .../LegacyFormValidator2Dot4ApiTest.php | 1 + .../LegacyFormValidatorLegacyApiTest.php | 1 + 8 files changed, 61 insertions(+), 1 deletion(-) diff --git a/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php b/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php index f7615546be..68ef4dca4f 100644 --- a/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/AbstractChoiceListTest.php @@ -161,6 +161,9 @@ public function testGetValues() $this->assertSame($this->values, $this->list->getValues()); } + /** + * @group legacy + */ public function testLegacyGetIndicesForChoices() { $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); @@ -169,6 +172,9 @@ public function testLegacyGetIndicesForChoices() $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices)); } + /** + * @group legacy + */ public function testLegacyGetIndicesForChoicesPreservesKeys() { $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); @@ -177,6 +183,9 @@ public function testLegacyGetIndicesForChoicesPreservesKeys() $this->assertSame(array(5 => $this->index1, 8 => $this->index2), $this->list->getIndicesForChoices($choices)); } + /** + * @group legacy + */ public function testLegacyGetIndicesForChoicesPreservesOrder() { $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); @@ -185,6 +194,9 @@ public function testLegacyGetIndicesForChoicesPreservesOrder() $this->assertSame(array($this->index2, $this->index1), $this->list->getIndicesForChoices($choices)); } + /** + * @group legacy + */ public function testLegacyGetIndicesForChoicesIgnoresNonExistingChoices() { $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); @@ -193,6 +205,9 @@ public function testLegacyGetIndicesForChoicesIgnoresNonExistingChoices() $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices)); } + /** + * @group legacy + */ public function testLegacyGetIndicesForChoicesEmpty() { $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); @@ -200,6 +215,9 @@ public function testLegacyGetIndicesForChoicesEmpty() $this->assertSame(array(), $this->list->getIndicesForChoices(array())); } + /** + * @group legacy + */ public function testLegacyGetIndicesForValues() { $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); @@ -209,6 +227,9 @@ public function testLegacyGetIndicesForValues() $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForValues($values)); } + /** + * @group legacy + */ public function testLegacyGetIndicesForValuesPreservesKeys() { $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); @@ -218,6 +239,9 @@ public function testLegacyGetIndicesForValuesPreservesKeys() $this->assertSame(array(5 => $this->index1, 8 => $this->index2), $this->list->getIndicesForValues($values)); } + /** + * @group legacy + */ public function testLegacyGetIndicesForValuesPreservesOrder() { $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); @@ -226,6 +250,9 @@ public function testLegacyGetIndicesForValuesPreservesOrder() $this->assertSame(array($this->index2, $this->index1), $this->list->getIndicesForValues($values)); } + /** + * @group legacy + */ public function testLegacyGetIndicesForValuesIgnoresNonExistingValues() { $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); @@ -234,6 +261,9 @@ public function testLegacyGetIndicesForValuesIgnoresNonExistingValues() $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForValues($values)); } + /** + * @group legacy + */ public function testLegacyGetIndicesForValuesEmpty() { $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); diff --git a/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php b/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php index 4b23916673..0e5e2e6527 100644 --- a/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/LazyChoiceListTest.php @@ -57,6 +57,9 @@ public function testGetRemainingViews() $this->assertEquals(array(0 => new ChoiceView('a', 'a', 'A'), 2 => new ChoiceView('c', 'c', 'C')), $this->list->getRemainingViews()); } + /** + * @group legacy + */ public function testLegacyGetIndicesForChoices() { $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); @@ -65,6 +68,9 @@ public function testLegacyGetIndicesForChoices() $this->assertSame(array(1, 2), $this->list->getIndicesForChoices($choices)); } + /** + * @group legacy + */ public function testLegacyGetIndicesForValues() { $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); diff --git a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php index eca3169150..2bb06349ae 100644 --- a/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/ObjectChoiceListTest.php @@ -185,6 +185,9 @@ public function testInitArrayThrowsExceptionIfToStringNotFound() ); } + /** + * @group legacy + */ public function testLegacyGetIndicesForChoicesWithValuePath() { $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); @@ -202,6 +205,9 @@ public function testLegacyGetIndicesForChoicesWithValuePath() $this->assertSame(array($this->index1, $this->index2), $this->list->getIndicesForChoices($choices)); } + /** + * @group legacy + */ public function testLegacyGetIndicesForChoicesWithValuePathPreservesKeys() { $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); @@ -218,6 +224,9 @@ public function testLegacyGetIndicesForChoicesWithValuePathPreservesKeys() $this->assertSame(array(5 => $this->index1, 8 => $this->index2), $this->list->getIndicesForChoices($choices)); } + /** + * @group legacy + */ public function testLegacyGetIndicesForChoicesWithValuePathPreservesOrder() { $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); @@ -234,6 +243,9 @@ public function testLegacyGetIndicesForChoicesWithValuePathPreservesOrder() $this->assertSame(array($this->index2, $this->index1), $this->list->getIndicesForChoices($choices)); } + /** + * @group legacy + */ public function testLegacyGetIndicesForChoicesWithValuePathIgnoresNonExistingChoices() { $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); diff --git a/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php b/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php index 9bbac31a37..b351790c45 100644 --- a/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php +++ b/Tests/Extension/Core/ChoiceList/SimpleNumericChoiceListTest.php @@ -15,6 +15,9 @@ class SimpleNumericChoiceListTest extends AbstractChoiceListTest { + /** + * @group legacy + */ public function testLegacyGetIndicesForChoicesDealsWithNumericChoices() { $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); @@ -24,6 +27,9 @@ public function testLegacyGetIndicesForChoicesDealsWithNumericChoices() $this->assertSame(array(0, 1), $this->list->getIndicesForChoices($choices)); } + /** + * @group legacy + */ public function testLegacyGetIndicesForValuesDealsWithNumericValues() { $this->iniSet('error_reporting', -1 & ~E_USER_DEPRECATED); diff --git a/Tests/Extension/Csrf/CsrfProvider/LegacyDefaultCsrfProviderTest.php b/Tests/Extension/Csrf/CsrfProvider/LegacyDefaultCsrfProviderTest.php index f201f99862..c1cf354442 100644 --- a/Tests/Extension/Csrf/CsrfProvider/LegacyDefaultCsrfProviderTest.php +++ b/Tests/Extension/Csrf/CsrfProvider/LegacyDefaultCsrfProviderTest.php @@ -16,8 +16,9 @@ /** * @runTestsInSeparateProcesses * @preserveGlobalState disabled + * @group legacy */ -class DefaultCsrfProviderTest extends \PHPUnit_Framework_TestCase +class LegacyDefaultCsrfProviderTest extends \PHPUnit_Framework_TestCase { protected $provider; diff --git a/Tests/Extension/Csrf/CsrfProvider/LegacySessionCsrfProviderTest.php b/Tests/Extension/Csrf/CsrfProvider/LegacySessionCsrfProviderTest.php index 018f80fa44..eb4f58c8b6 100644 --- a/Tests/Extension/Csrf/CsrfProvider/LegacySessionCsrfProviderTest.php +++ b/Tests/Extension/Csrf/CsrfProvider/LegacySessionCsrfProviderTest.php @@ -13,6 +13,9 @@ use Symfony\Component\Form\Extension\Csrf\CsrfProvider\SessionCsrfProvider; +/** + * @group legacy + */ class LegacySessionCsrfProviderTest extends \PHPUnit_Framework_TestCase { protected $provider; diff --git a/Tests/Extension/Validator/Constraints/LegacyFormValidator2Dot4ApiTest.php b/Tests/Extension/Validator/Constraints/LegacyFormValidator2Dot4ApiTest.php index fb3208facd..f94df0c7e3 100644 --- a/Tests/Extension/Validator/Constraints/LegacyFormValidator2Dot4ApiTest.php +++ b/Tests/Extension/Validator/Constraints/LegacyFormValidator2Dot4ApiTest.php @@ -16,6 +16,7 @@ /** * @since 2.5.3 * @author Bernhard Schussek + * @group legacy */ class LegacyFormValidator2Dot4ApiTest extends FormValidatorTest { diff --git a/Tests/Extension/Validator/Constraints/LegacyFormValidatorLegacyApiTest.php b/Tests/Extension/Validator/Constraints/LegacyFormValidatorLegacyApiTest.php index faa68b2518..9adb364a39 100644 --- a/Tests/Extension/Validator/Constraints/LegacyFormValidatorLegacyApiTest.php +++ b/Tests/Extension/Validator/Constraints/LegacyFormValidatorLegacyApiTest.php @@ -16,6 +16,7 @@ /** * @since 2.5.3 * @author Bernhard Schussek + * @group legacy */ class LegacyFormValidatorLegacyApiTest extends FormValidatorTest { From 3c962f6bd0660dab3ef2f08882de3f224e4aa7da Mon Sep 17 00:00:00 2001 From: Dariusz Ruminski Date: Sat, 21 Mar 2015 11:51:07 +0100 Subject: [PATCH 414/447] CS: Convert double quotes to single quotes --- .../Core/EventListener/FixUrlProtocolListenerTest.php | 6 +++--- Tests/Extension/Core/EventListener/TrimListenerTest.php | 2 +- .../Csrf/EventListener/CsrfValidationListenerTest.php | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php b/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php index 475681a053..a971ea215c 100644 --- a/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php +++ b/Tests/Extension/Core/EventListener/FixUrlProtocolListenerTest.php @@ -18,7 +18,7 @@ class FixUrlProtocolListenerTest extends \PHPUnit_Framework_TestCase { public function testFixHttpUrl() { - $data = "www.symfony.com"; + $data = 'www.symfony.com'; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); @@ -30,7 +30,7 @@ public function testFixHttpUrl() public function testSkipKnownUrl() { - $data = "http://www.symfony.com"; + $data = 'http://www.symfony.com'; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); @@ -42,7 +42,7 @@ public function testSkipKnownUrl() public function testSkipOtherProtocol() { - $data = "ftp://www.symfony.com"; + $data = 'ftp://www.symfony.com'; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); diff --git a/Tests/Extension/Core/EventListener/TrimListenerTest.php b/Tests/Extension/Core/EventListener/TrimListenerTest.php index 38b39ac11c..3818c7861f 100644 --- a/Tests/Extension/Core/EventListener/TrimListenerTest.php +++ b/Tests/Extension/Core/EventListener/TrimListenerTest.php @@ -18,7 +18,7 @@ class TrimListenerTest extends \PHPUnit_Framework_TestCase { public function testTrim() { - $data = " Foo! "; + $data = ' Foo! '; $form = $this->getMock('Symfony\Component\Form\Test\FormInterface'); $event = new FormEvent($form, $data); diff --git a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php index 7f2220af72..646c385c15 100644 --- a/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php +++ b/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php @@ -62,7 +62,7 @@ protected function getMockForm() // https://github.com/symfony/symfony/pull/5838 public function testStringFormData() { - $data = "XP4HUzmHPi"; + $data = 'XP4HUzmHPi'; $event = new FormEvent($this->form, $data); $validation = new CsrfValidationListener('csrf', $this->csrfProvider, 'unknown', 'Invalid.'); From f64a18084063c2ffec7ad7dc9f93bbe1bacad997 Mon Sep 17 00:00:00 2001 From: "Issei.M" Date: Fri, 20 Mar 2015 22:26:52 +0900 Subject: [PATCH 415/447] [Form] fixed phpdoc --- Button.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Button.php b/Button.php index e7b553edcc..6055db9b7d 100644 --- a/Button.php +++ b/Button.php @@ -194,9 +194,7 @@ public function getErrors() * * This method should not be invoked. * - * @param string $modelData - * - * @throws BadMethodCallException + * @param mixed $modelData */ public function setData($modelData) { From 81d81e71b0367cf640e57b6c42878c3b3d37b609 Mon Sep 17 00:00:00 2001 From: Vladimir Reznichenko Date: Fri, 20 Mar 2015 17:17:32 +0100 Subject: [PATCH 416/447] [2.3] Static Code Analysis for Components --- NativeRequestHandler.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NativeRequestHandler.php b/NativeRequestHandler.php index a888967bb3..7c883f12eb 100644 --- a/NativeRequestHandler.php +++ b/NativeRequestHandler.php @@ -184,10 +184,10 @@ private static function fixPhpFilesArray($data) unset($files[$k]); } - foreach (array_keys($data['name']) as $key) { + foreach ($data['name'] as $key => $name) { $files[$key] = self::fixPhpFilesArray(array( 'error' => $data['error'][$key], - 'name' => $data['name'][$key], + 'name' => $name, 'type' => $data['type'][$key], 'tmp_name' => $data['tmp_name'][$key], 'size' => $data['size'][$key], From 63a4f33c8e329080f745cec16a4fd3c85374d2bf Mon Sep 17 00:00:00 2001 From: Dariusz Ruminski Date: Tue, 24 Mar 2015 17:36:00 +0100 Subject: [PATCH 417/447] CS: Ensure there is no code on the same line as the PHP open tag and it is followed by a blankline --- FormEvents.php | 1 + 1 file changed, 1 insertion(+) diff --git a/FormEvents.php b/FormEvents.php index d8c0510c28..978e716e94 100644 --- a/FormEvents.php +++ b/FormEvents.php @@ -1,4 +1,5 @@ Date: Tue, 24 Mar 2015 17:44:35 +0100 Subject: [PATCH 418/447] CS: fix some license headers --- Extension/Core/ChoiceList/ObjectChoiceList.php | 12 ++++++------ Test/TypeTestCase.php | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Extension/Core/ChoiceList/ObjectChoiceList.php b/Extension/Core/ChoiceList/ObjectChoiceList.php index 6db1e0fa50..16577e9a39 100644 --- a/Extension/Core/ChoiceList/ObjectChoiceList.php +++ b/Extension/Core/ChoiceList/ObjectChoiceList.php @@ -2,12 +2,12 @@ /* * This file is part of the Symfony package. -* -* (c) Fabien Potencier -* -* For the full copyright and license information, please view the LICENSE -* file that was distributed with this source code. -*/ + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ namespace Symfony\Component\Form\Extension\Core\ChoiceList; diff --git a/Test/TypeTestCase.php b/Test/TypeTestCase.php index 9d51a9eec1..87797757ff 100644 --- a/Test/TypeTestCase.php +++ b/Test/TypeTestCase.php @@ -3,7 +3,7 @@ /* * This file is part of the Symfony package. * - * (c) Fabien Potencier + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. From 49a33aa09e7f706349a359b1f8aab04a6641c637 Mon Sep 17 00:00:00 2001 From: Mantas Varatiejus Date: Thu, 11 Dec 2014 15:39:46 +0200 Subject: [PATCH 419/447] [Form] [TwigBridge] Bootstrap layout whitespace control --- Tests/AbstractBootstrap3LayoutTest.php | 1818 ++++++++++++++++++++++++ Tests/AbstractLayoutTest.php | 10 +- 2 files changed, 1826 insertions(+), 2 deletions(-) create mode 100644 Tests/AbstractBootstrap3LayoutTest.php diff --git a/Tests/AbstractBootstrap3LayoutTest.php b/Tests/AbstractBootstrap3LayoutTest.php new file mode 100644 index 0000000000..b5354e0bd2 --- /dev/null +++ b/Tests/AbstractBootstrap3LayoutTest.php @@ -0,0 +1,1818 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +use Symfony\Component\Form\FormError; + +abstract class AbstractBootstrap3LayoutTest extends AbstractLayoutTest +{ + public function testLabelOnForm() + { + $form = $this->factory->createNamed('name', 'date'); + $view = $form->createView(); + $this->renderWidget($view, array('label' => 'foo')); + $html = $this->renderLabel($view); + + $this->assertMatchesXpath($html, +'/label + [@class="control-label required"] + [.="[trans]Name[/trans]"] +' + ); + } + + public function testLabelDoesNotRenderFieldAttributes() + { + $form = $this->factory->createNamed('name', 'text'); + $html = $this->renderLabel($form->createView(), null, array( + 'attr' => array( + 'class' => 'my&class', + ), + )); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="control-label required"] +' + ); + } + + public function testLabelWithCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', 'text'); + $html = $this->renderLabel($form->createView(), null, array( + 'label_attr' => array( + 'class' => 'my&class', + ), + )); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="my&class control-label required"] +' + ); + } + + public function testLabelWithCustomTextAndCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', 'text'); + $html = $this->renderLabel($form->createView(), 'Custom label', array( + 'label_attr' => array( + 'class' => 'my&class', + ), + )); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="my&class control-label required"] + [.="[trans]Custom label[/trans]"] +' + ); + } + + public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', 'text', null, array( + 'label' => 'Custom label', + )); + $html = $this->renderLabel($form->createView(), null, array( + 'label_attr' => array( + 'class' => 'my&class', + ), + )); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="my&class control-label required"] + [.="[trans]Custom label[/trans]"] +' + ); + } + + public function testErrors() + { + $form = $this->factory->createNamed('name', 'text'); + $form->addError(new FormError('[trans]Error 1[/trans]')); + $form->addError(new FormError('[trans]Error 2[/trans]')); + $view = $form->createView(); + $html = $this->renderErrors($view); + + $this->assertMatchesXpath($html, +'/div + [@class="alert alert-danger"] + [ + ./ul + [@class="list-unstyled"] + [ + ./li + [.="[trans]Error 1[/trans]"] + [ + ./span[@class="glyphicon glyphicon-exclamation-sign"] + ] + /following-sibling::li + [.="[trans]Error 2[/trans]"] + [ + ./span[@class="glyphicon glyphicon-exclamation-sign"] + ] + ] + [count(./li)=2] + ] +' + ); + } + + public function testOverrideWidgetBlock() + { + // see custom_widgets.html.twig + $form = $this->factory->createNamed('text_id', 'text'); + $html = $this->renderWidget($form->createView()); + + $this->assertMatchesXpath($html, +'/div + [ + ./input + [@type="text"] + [@id="text_id"] + [@class="form-control"] + ] + [@id="container"] +' + ); + } + + public function testCheckedCheckbox() + { + $form = $this->factory->createNamed('name', 'checkbox', true); + + $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')), +'/div + [@class="checkbox"] + [ + ./label + [.="[trans]Name[/trans]"] + [ + ./input[@type="checkbox"][@name="name"][@id="my&id"][@class="my&class"][@checked="checked"][@value="1"] + ] + ] +' + ); + } + + public function testUncheckedCheckbox() + { + $form = $this->factory->createNamed('name', 'checkbox', false); + + $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')), +'/div + [@class="checkbox"] + [ + ./label + [.="[trans]Name[/trans]"] + [ + ./input[@type="checkbox"][@name="name"][@id="my&id"][@class="my&class"][not(@checked)] + ] + ] +' + ); + } + + public function testCheckboxWithValue() + { + $form = $this->factory->createNamed('name', 'checkbox', false, array( + 'value' => 'foo&bar', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')), +'/div + [@class="checkbox"] + [ + ./label + [.="[trans]Name[/trans]"] + [ + ./input[@type="checkbox"][@name="name"][@id="my&id"][@class="my&class"][@value="foo&bar"] + ] + ] +' + ); + } + + public function testSingleChoice() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'multiple' => false, + 'expanded' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/select + [@name="name"] + [@class="my&class form-control"] + [not(@required)] + [ + ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=2] +' + ); + } + + public function testSingleChoiceWithPreferred() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'preferred_choices' => array('&b'), + 'multiple' => false, + 'expanded' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('separator' => '-- sep --', 'attr' => array('class' => 'my&class')), +'/select + [@name="name"] + [@class="my&class form-control"] + [not(@required)] + [ + ./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + /following-sibling::option[@disabled="disabled"][not(@selected)][.="-- sep --"] + /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + ] + [count(./option)=3] +' + ); + } + + public function testSingleChoiceWithPreferredAndNoSeparator() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'preferred_choices' => array('&b'), + 'multiple' => false, + 'expanded' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('separator' => null, 'attr' => array('class' => 'my&class')), +'/select + [@name="name"] + [@class="my&class form-control"] + [not(@required)] + [ + ./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + ] + [count(./option)=2] +' + ); + } + + public function testSingleChoiceWithPreferredAndBlankSeparator() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'preferred_choices' => array('&b'), + 'multiple' => false, + 'expanded' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('separator' => '', 'attr' => array('class' => 'my&class')), +'/select + [@name="name"] + [@class="my&class form-control"] + [not(@required)] + [ + ./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + /following-sibling::option[@disabled="disabled"][not(@selected)][.=""] + /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + ] + [count(./option)=3] +' + ); + } + + public function testChoiceWithOnlyPreferred() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'preferred_choices' => array('&a', '&b'), + 'multiple' => false, + 'expanded' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/select + [@class="my&class form-control"] + [count(./option)=2] +' + ); + } + + public function testSingleChoiceNonRequired() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'required' => false, + 'multiple' => false, + 'expanded' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/select + [@name="name"] + [@class="my&class form-control"] + [not(@required)] + [ + ./option[@value=""][.="[trans][/trans]"] + /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=3] +' + ); + } + + public function testSingleChoiceNonRequiredNoneSelected() + { + $form = $this->factory->createNamed('name', 'choice', null, array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'required' => false, + 'multiple' => false, + 'expanded' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/select + [@name="name"] + [@class="my&class form-control"] + [not(@required)] + [ + ./option[@value=""][.="[trans][/trans]"] + /following-sibling::option[@value="&a"][not(@selected)][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=3] +' + ); + } + + public function testSingleChoiceNonRequiredWithPlaceholder() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'multiple' => false, + 'expanded' => false, + 'required' => false, + 'placeholder' => 'Select&Anything&Not&Me', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/select + [@name="name"] + [@class="my&class form-control"] + [not(@required)] + [ + ./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Anything&Not&Me[/trans]"] + /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=3] +' + ); + } + + public function testSingleChoiceRequiredWithPlaceholder() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'required' => true, + 'multiple' => false, + 'expanded' => false, + 'placeholder' => 'Test&Me', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/select + [@name="name"] + [@class="my&class form-control"] + [@required="required"] + [ + ./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Test&Me[/trans]"] + /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=3] +' + ); + } + + public function testSingleChoiceRequiredWithPlaceholderViaView() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'required' => true, + 'multiple' => false, + 'expanded' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('placeholder' => '', 'attr' => array('class' => 'my&class')), +'/select + [@name="name"] + [@class="my&class form-control"] + [@required="required"] + [ + ./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"] + /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=3] +' + ); + } + + public function testSingleChoiceGrouped() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array( + 'Group&1' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'Group&2' => array('&c' => 'Choice&C'), + ), + 'multiple' => false, + 'expanded' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/select + [@name="name"] + [@class="my&class form-control"] + [./optgroup[@label="[trans]Group&1[/trans]"] + [ + ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=2] + ] + [./optgroup[@label="[trans]Group&2[/trans]"] + [./option[@value="&c"][not(@selected)][.="[trans]Choice&C[/trans]"]] + [count(./option)=1] + ] + [count(./optgroup)=2] +' + ); + } + + public function testMultipleChoice() + { + $form = $this->factory->createNamed('name', 'choice', array('&a'), array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'required' => true, + 'multiple' => true, + 'expanded' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/select + [@name="name[]"] + [@class="my&class form-control"] + [@required="required"] + [@multiple="multiple"] + [ + ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=2] +' + ); + } + + public function testMultipleChoiceSkipsPlaceholder() + { + $form = $this->factory->createNamed('name', 'choice', array('&a'), array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'multiple' => true, + 'expanded' => false, + 'placeholder' => 'Test&Me', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/select + [@name="name[]"] + [@class="my&class form-control"] + [@multiple="multiple"] + [ + ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=2] +' + ); + } + + public function testMultipleChoiceNonRequired() + { + $form = $this->factory->createNamed('name', 'choice', array('&a'), array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'required' => false, + 'multiple' => true, + 'expanded' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/select + [@name="name[]"] + [@class="my&class form-control"] + [@multiple="multiple"] + [ + ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=2] +' + ); + } + + public function testSingleChoiceExpanded() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'multiple' => false, + 'expanded' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [@class="radio"] + [ + ./label + [.="[trans]Choice&A[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] + ] + ] + /following-sibling::div + [@class="radio"] + [ + ./label + [.="[trans]Choice&B[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"][@class="form-control"] + ] +' + ); + } + + public function testSingleChoiceExpandedWithPlaceholder() + { + $form = $this->factory->createNamed('name', 'choice', '&a', array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B'), + 'multiple' => false, + 'expanded' => true, + 'placeholder' => 'Test&Me', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [@class="radio"] + [ + ./label + [.="[trans]Test&Me[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_placeholder"][not(@checked)] + ] + ] + /following-sibling::div + [@class="radio"] + [ + ./label + [.="[trans]Choice&A[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@checked] + ] + ] + /following-sibling::div + [@class="radio"] + [ + ./label + [.="[trans]Choice&B[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"][@class="form-control"] + ] +' + ); + } + + public function testSingleChoiceExpandedWithBooleanValue() + { + $form = $this->factory->createNamed('name', 'choice', true, array( + 'choices' => array('1' => 'Choice&A', '0' => 'Choice&B'), + 'multiple' => false, + 'expanded' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [@class="radio"] + [ + ./label + [.="[trans]Choice&A[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@checked] + ] + ] + /following-sibling::div + [@class="radio"] + [ + ./label + [.="[trans]Choice&B[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"][@class="form-control"] + ] +' + ); + } + + public function testMultipleChoiceExpanded() + { + $form = $this->factory->createNamed('name', 'choice', array('&a', '&c'), array( + 'choices' => array('&a' => 'Choice&A', '&b' => 'Choice&B', '&c' => 'Choice&C'), + 'multiple' => true, + 'expanded' => true, + 'required' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [@class="checkbox"] + [ + ./label + [.="[trans]Choice&A[/trans]"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@checked][not(@required)] + ] + ] + /following-sibling::div + [@class="checkbox"] + [ + ./label + [.="[trans]Choice&B[/trans]"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_1"][not(@checked)][not(@required)] + ] + ] + /following-sibling::div + [@class="checkbox"] + [ + ./label + [.="[trans]Choice&C[/trans]"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_2"][@checked][not(@required)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"][@class="form-control"] + ] +' + ); + } + + public function testCountry() + { + $form = $this->factory->createNamed('name', 'country', 'AT'); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/select + [@name="name"] + [@class="my&class form-control"] + [./option[@value="AT"][@selected="selected"][.="[trans]Austria[/trans]"]] + [count(./option)>200] +' + ); + } + + public function testCountryWithPlaceholder() + { + $form = $this->factory->createNamed('name', 'country', 'AT', array( + 'placeholder' => 'Select&Country', + 'required' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/select + [@name="name"] + [@class="my&class form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Country[/trans]"]] + [./option[@value="AT"][@selected="selected"][.="[trans]Austria[/trans]"]] + [count(./option)>201] +' + ); + } + + public function testDateTime() + { + $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array( + 'input' => 'string', + 'with_seconds' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/div + [ + ./select + [@id="name_date_month"] + [@class="form-control"] + [./option[@value="2"][@selected="selected"]] + /following-sibling::select + [@id="name_date_day"] + [@class="form-control"] + [./option[@value="3"][@selected="selected"]] + /following-sibling::select + [@id="name_date_year"] + [@class="form-control"] + [./option[@value="2011"][@selected="selected"]] + /following-sibling::select + [@id="name_time_hour"] + [@class="form-control"] + [./option[@value="4"][@selected="selected"]] + /following-sibling::select + [@id="name_time_minute"] + [@class="form-control"] + [./option[@value="5"][@selected="selected"]] + ] + [count(.//select)=5] +' + ); + } + + public function testDateTimeWithPlaceholderGlobal() + { + $form = $this->factory->createNamed('name', 'datetime', null, array( + 'input' => 'string', + 'placeholder' => 'Change&Me', + 'required' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_date_month"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + /following-sibling::select + [@id="name_date_day"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + /following-sibling::select + [@id="name_date_year"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + /following-sibling::select + [@id="name_time_hour"] + [@class="form-control"] + [./option[@value=""][.="[trans]Change&Me[/trans]"]] + /following-sibling::select + [@id="name_time_minute"] + [@class="form-control"] + [./option[@value=""][.="[trans]Change&Me[/trans]"]] + ] + [count(.//select)=5] +' + ); + } + + public function testDateTimeWithHourAndMinute() + { + $data = array('year' => '2011', 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '5'); + + $form = $this->factory->createNamed('name', 'datetime', $data, array( + 'input' => 'array', + 'required' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_date_month"] + [@class="form-control"] + [./option[@value="2"][@selected="selected"]] + /following-sibling::select + [@id="name_date_day"] + [@class="form-control"] + [./option[@value="3"][@selected="selected"]] + /following-sibling::select + [@id="name_date_year"] + [@class="form-control"] + [./option[@value="2011"][@selected="selected"]] + /following-sibling::select + [@id="name_time_hour"] + [@class="form-control"] + [./option[@value="4"][@selected="selected"]] + /following-sibling::select + [@id="name_time_minute"] + [@class="form-control"] + [./option[@value="5"][@selected="selected"]] + ] + [count(.//select)=5] +' + ); + } + + public function testDateTimeWithSeconds() + { + $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array( + 'input' => 'string', + 'with_seconds' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_date_month"] + [@class="form-control"] + [./option[@value="2"][@selected="selected"]] + /following-sibling::select + [@id="name_date_day"] + [@class="form-control"] + [./option[@value="3"][@selected="selected"]] + /following-sibling::select + [@id="name_date_year"] + [@class="form-control"] + [./option[@value="2011"][@selected="selected"]] + /following-sibling::select + [@id="name_time_hour"] + [@class="form-control"] + [./option[@value="4"][@selected="selected"]] + /following-sibling::select + [@id="name_time_minute"] + [@class="form-control"] + [./option[@value="5"][@selected="selected"]] + /following-sibling::select + [@id="name_time_second"] + [@class="form-control"] + [./option[@value="6"][@selected="selected"]] + ] + [count(.//select)=6] +' + ); + } + + public function testDateTimeSingleText() + { + $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array( + 'input' => 'string', + 'date_widget' => 'single_text', + 'time_widget' => 'single_text', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/div + [@class="my&class form-inline"] + [ + ./input + [@type="date"] + [@id="name_date"] + [@name="name[date]"] + [@class="form-control"] + [@value="2011-02-03"] + /following-sibling::input + [@type="time"] + [@id="name_time"] + [@name="name[time]"] + [@class="form-control"] + [@value="04:05"] + ] +' + ); + } + + public function testDateTimeWithWidgetSingleText() + { + $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array( + 'input' => 'string', + 'widget' => 'single_text', + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/input + [@type="datetime"] + [@name="name"] + [@class="my&class form-control"] + [@value="2011-02-03T04:05:06Z"] +' + ); + } + + public function testDateTimeWithWidgetSingleTextIgnoreDateAndTimeWidgets() + { + $form = $this->factory->createNamed('name', 'datetime', '2011-02-03 04:05:06', array( + 'input' => 'string', + 'date_widget' => 'choice', + 'time_widget' => 'choice', + 'widget' => 'single_text', + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/input + [@type="datetime"] + [@name="name"] + [@class="my&class form-control"] + [@value="2011-02-03T04:05:06Z"] +' + ); + } + + public function testDateChoice() + { + $form = $this->factory->createNamed('name', 'date', '2011-02-03', array( + 'input' => 'string', + 'widget' => 'choice', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_month"] + [@class="form-control"] + [./option[@value="2"][@selected="selected"]] + /following-sibling::select + [@id="name_day"] + [@class="form-control"] + [./option[@value="3"][@selected="selected"]] + /following-sibling::select + [@id="name_year"] + [@class="form-control"] + [./option[@value="2011"][@selected="selected"]] + ] + [count(./select)=3] +' + ); + } + + public function testDateChoiceWithPlaceholderGlobal() + { + $form = $this->factory->createNamed('name', 'date', null, array( + 'input' => 'string', + 'widget' => 'choice', + 'placeholder' => 'Change&Me', + 'required' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_month"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + /following-sibling::select + [@id="name_day"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + /following-sibling::select + [@id="name_year"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + ] + [count(./select)=3] +' + ); + } + + public function testDateChoiceWithPlaceholderOnYear() + { + $form = $this->factory->createNamed('name', 'date', null, array( + 'input' => 'string', + 'widget' => 'choice', + 'required' => false, + 'placeholder' => array('year' => 'Change&Me'), + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_month"] + [@class="form-control"] + [./option[@value="1"]] + /following-sibling::select + [@id="name_day"] + [@class="form-control"] + [./option[@value="1"]] + /following-sibling::select + [@id="name_year"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + ] + [count(./select)=3] +' + ); + } + + public function testDateText() + { + $form = $this->factory->createNamed('name', 'date', '2011-02-03', array( + 'input' => 'string', + 'widget' => 'text', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/div + [@class="my&class form-inline"] + [ + ./input + [@id="name_month"] + [@type="text"] + [@class="form-control"] + [@value="2"] + /following-sibling::input + [@id="name_day"] + [@type="text"] + [@class="form-control"] + [@value="3"] + /following-sibling::input + [@id="name_year"] + [@type="text"] + [@class="form-control"] + [@value="2011"] + ] + [count(./input)=3] +' + ); + } + + public function testDateSingleText() + { + $form = $this->factory->createNamed('name', 'date', '2011-02-03', array( + 'input' => 'string', + 'widget' => 'single_text', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/input + [@type="date"] + [@name="name"] + [@class="my&class form-control"] + [@value="2011-02-03"] +' + ); + } + + public function testBirthDay() + { + $form = $this->factory->createNamed('name', 'birthday', '2000-02-03', array( + 'input' => 'string', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_month"] + [@class="form-control"] + [./option[@value="2"][@selected="selected"]] + /following-sibling::select + [@id="name_day"] + [@class="form-control"] + [./option[@value="3"][@selected="selected"]] + /following-sibling::select + [@id="name_year"] + [@class="form-control"] + [./option[@value="2000"][@selected="selected"]] + ] + [count(./select)=3] +' + ); + } + + public function testBirthDayWithPlaceholder() + { + $form = $this->factory->createNamed('name', 'birthday', '1950-01-01', array( + 'input' => 'string', + 'placeholder' => '', + 'required' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_month"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"]] + [./option[@value="1"][@selected="selected"]] + /following-sibling::select + [@id="name_day"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"]] + [./option[@value="1"][@selected="selected"]] + /following-sibling::select + [@id="name_year"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"]] + [./option[@value="1950"][@selected="selected"]] + ] + [count(./select)=3] +' + ); + } + + public function testEmail() + { + $form = $this->factory->createNamed('name', 'email', 'foo&bar'); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/input + [@type="email"] + [@name="name"] + [@class="my&class form-control"] + [@value="foo&bar"] + [not(@maxlength)] +' + ); + } + + public function testEmailWithMaxLength() + { + $form = $this->factory->createNamed('name', 'email', 'foo&bar', array( + 'attr' => array('maxlength' => 123), + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/input + [@type="email"] + [@name="name"] + [@class="my&class form-control"] + [@value="foo&bar"] + [@maxlength="123"] +' + ); + } + + public function testHidden() + { + $form = $this->factory->createNamed('name', 'hidden', 'foo&bar'); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/input + [@type="hidden"] + [@name="name"] + [@class="my&class form-control"] + [@value="foo&bar"] +' + ); + } + + public function testReadOnly() + { + $form = $this->factory->createNamed('name', 'text', null, array( + 'read_only' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/input + [@type="text"] + [@name="name"] + [@class="my&class form-control"] + [@readonly="readonly"] +' + ); + } + + public function testDisabled() + { + $form = $this->factory->createNamed('name', 'text', null, array( + 'disabled' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/input + [@type="text"] + [@name="name"] + [@class="my&class form-control"] + [@disabled="disabled"] +' + ); + } + + public function testInteger() + { + $form = $this->factory->createNamed('name', 'integer', 123); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/input + [@type="number"] + [@name="name"] + [@class="my&class form-control"] + [@value="123"] +' + ); + } + + public function testLanguage() + { + $form = $this->factory->createNamed('name', 'language', 'de'); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/select + [@name="name"] + [@class="my&class form-control"] + [./option[@value="de"][@selected="selected"][.="[trans]German[/trans]"]] + [count(./option)>200] +' + ); + } + + public function testLocale() + { + $form = $this->factory->createNamed('name', 'locale', 'de_AT'); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/select + [@name="name"] + [@class="my&class form-control"] + [./option[@value="de_AT"][@selected="selected"][.="[trans]German (Austria)[/trans]"]] + [count(./option)>200] +' + ); + } + + public function testMoney() + { + $form = $this->factory->createNamed('name', 'money', 1234.56, array( + 'currency' => 'EUR', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')), +'/div + [@class="input-group"] + [ + ./span + [@class="input-group-addon"] + [contains(.., "€")] + /following-sibling::input + [@id="my&id"] + [@type="text"] + [@name="name"] + [@class="my&class form-control"] + [@value="1234.56"] + ] +' + ); + } + + public function testNumber() + { + $form = $this->factory->createNamed('name', 'number', 1234.56); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/input + [@type="text"] + [@name="name"] + [@class="my&class form-control"] + [@value="1234.56"] +' + ); + } + + public function testPassword() + { + $form = $this->factory->createNamed('name', 'password', 'foo&bar'); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/input + [@type="password"] + [@name="name"] + [@class="my&class form-control"] +' + ); + } + + public function testPasswordSubmittedWithNotAlwaysEmpty() + { + $form = $this->factory->createNamed('name', 'password', null, array( + 'always_empty' => false, + )); + $form->submit('foo&bar'); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/input + [@type="password"] + [@name="name"] + [@class="my&class form-control"] + [@value="foo&bar"] +' + ); + } + + public function testPasswordWithMaxLength() + { + $form = $this->factory->createNamed('name', 'password', 'foo&bar', array( + 'attr' => array('maxlength' => 123), + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/input + [@type="password"] + [@name="name"] + [@class="my&class form-control"] + [@maxlength="123"] +' + ); + } + + public function testPercent() + { + $form = $this->factory->createNamed('name', 'percent', 0.1); + + $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')), +'/div + [@class="input-group"] + [ + ./input + [@id="my&id"] + [@type="text"] + [@name="name"] + [@class="my&class form-control"] + [@value="10"] + /following-sibling::span + [@class="input-group-addon"] + [contains(.., "%")] + ] +' + ); + } + + public function testCheckedRadio() + { + $form = $this->factory->createNamed('name', 'radio', true); + + $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')), +'/div + [@class="radio"] + [ + ./label + [@class="required"] + [ + ./input + [@id="my&id"] + [@type="radio"] + [@name="name"] + [@class="my&class"] + [@checked="checked"] + [@value="1"] + ] + ] +' + ); + } + + public function testUncheckedRadio() + { + $form = $this->factory->createNamed('name', 'radio', false); + + $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')), +'/div + [@class="radio"] + [ + ./label + [@class="required"] + [ + ./input + [@id="my&id"] + [@type="radio"] + [@name="name"] + [@class="my&class"] + [not(@checked)] + ] + ] +' + ); + } + + public function testRadioWithValue() + { + $form = $this->factory->createNamed('name', 'radio', false, array( + 'value' => 'foo&bar', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')), +'/div + [@class="radio"] + [ + ./label + [@class="required"] + [ + ./input + [@id="my&id"] + [@type="radio"] + [@name="name"] + [@class="my&class"] + [@value="foo&bar"] + ] + ] +' + ); + } + + public function testTextarea() + { + $form = $this->factory->createNamed('name', 'textarea', 'foo&bar', array( + 'attr' => array('pattern' => 'foo'), + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/textarea + [@name="name"] + [@pattern="foo"] + [@class="my&class form-control"] + [.="foo&bar"] +' + ); + } + + public function testText() + { + $form = $this->factory->createNamed('name', 'text', 'foo&bar'); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/input + [@type="text"] + [@name="name"] + [@class="my&class form-control"] + [@value="foo&bar"] + [not(@maxlength)] +' + ); + } + + public function testTextWithMaxLength() + { + $form = $this->factory->createNamed('name', 'text', 'foo&bar', array( + 'attr' => array('maxlength' => 123), + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/input + [@type="text"] + [@name="name"] + [@class="my&class form-control"] + [@value="foo&bar"] + [@maxlength="123"] +' + ); + } + + public function testSearch() + { + $form = $this->factory->createNamed('name', 'search', 'foo&bar'); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/input + [@type="search"] + [@name="name"] + [@class="my&class form-control"] + [@value="foo&bar"] + [not(@maxlength)] +' + ); + } + + public function testTime() + { + $form = $this->factory->createNamed('name', 'time', '04:05:06', array( + 'input' => 'string', + 'with_seconds' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_hour"] + [@class="form-control"] + [not(@size)] + [./option[@value="4"][@selected="selected"]] + /following-sibling::select + [@id="name_minute"] + [@class="form-control"] + [not(@size)] + [./option[@value="5"][@selected="selected"]] + ] + [count(./select)=2] +' + ); + } + + public function testTimeWithSeconds() + { + $form = $this->factory->createNamed('name', 'time', '04:05:06', array( + 'input' => 'string', + 'with_seconds' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_hour"] + [@class="form-control"] + [not(@size)] + [./option[@value="4"][@selected="selected"]] + [count(./option)>23] + /following-sibling::select + [@id="name_minute"] + [@class="form-control"] + [not(@size)] + [./option[@value="5"][@selected="selected"]] + [count(./option)>59] + /following-sibling::select + [@id="name_second"] + [@class="form-control"] + [not(@size)] + [./option[@value="6"][@selected="selected"]] + [count(./option)>59] + ] + [count(./select)=3] +' + ); + } + + public function testTimeText() + { + $form = $this->factory->createNamed('name', 'time', '04:05:06', array( + 'input' => 'string', + 'widget' => 'text', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/div + [@class="my&class form-inline"] + [ + ./input + [@type="text"] + [@id="name_hour"] + [@name="name[hour]"] + [@class="form-control"] + [@value="04"] + [@required="required"] + [not(@size)] + /following-sibling::input + [@type="text"] + [@id="name_minute"] + [@name="name[minute]"] + [@class="form-control"] + [@value="05"] + [@required="required"] + [not(@size)] + ] + [count(./input)=2] +' + ); + } + + public function testTimeSingleText() + { + $form = $this->factory->createNamed('name', 'time', '04:05:06', array( + 'input' => 'string', + 'widget' => 'single_text', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/input + [@type="time"] + [@name="name"] + [@class="my&class form-control"] + [@value="04:05"] + [not(@size)] +' + ); + } + + public function testTimeWithPlaceholderGlobal() + { + $form = $this->factory->createNamed('name', 'time', null, array( + 'input' => 'string', + 'placeholder' => 'Change&Me', + 'required' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_hour"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + [count(./option)>24] + /following-sibling::select + [@id="name_minute"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + [count(./option)>60] + ] + [count(./select)=2] +' + ); + } + + public function testTimeWithPlaceholderOnYear() + { + $form = $this->factory->createNamed('name', 'time', null, array( + 'input' => 'string', + 'required' => false, + 'placeholder' => array('hour' => 'Change&Me'), + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_hour"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + [count(./option)>24] + /following-sibling::select + [@id="name_minute"] + [./option[@value="1"]] + [count(./option)>59] + ] + [count(./select)=2] +' + ); + } + + public function testTimezone() + { + $form = $this->factory->createNamed('name', 'timezone', 'Europe/Vienna'); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/select + [@name="name"] + [@class="my&class form-control"] + [not(@required)] + [./optgroup + [@label="[trans]Europe[/trans]"] + [./option[@value="Europe/Vienna"][@selected="selected"][.="[trans]Vienna[/trans]"]] + ] + [count(./optgroup)>10] + [count(.//option)>200] +' + ); + } + + public function testTimezoneWithPlaceholder() + { + $form = $this->factory->createNamed('name', 'timezone', null, array( + 'placeholder' => 'Select&Timezone', + 'required' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/select + [@class="my&class form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Timezone[/trans]"]] + [count(./optgroup)>10] + [count(.//option)>201] +' + ); + } + + public function testUrl() + { + $url = 'http://www.google.com?foo1=bar1&foo2=bar2'; + $form = $this->factory->createNamed('name', 'url', $url); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), +'/input + [@type="url"] + [@name="name"] + [@class="my&class form-control"] + [@value="http://www.google.com?foo1=bar1&foo2=bar2"] +' + ); + } + + public function testButton() + { + $form = $this->factory->createNamed('name', 'button'); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), + '/button[@type="button"][@name="name"][.="[trans]Name[/trans]"][@class="my&class btn"]' + ); + } + + public function testSubmit() + { + $form = $this->factory->createNamed('name', 'submit'); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), + '/button[@type="submit"][@name="name"][@class="my&class btn"]' + ); + } + + public function testReset() + { + $form = $this->factory->createNamed('name', 'reset'); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), + '/button[@type="reset"][@name="name"][@class="my&class btn"]' + ); + } + + public function testWidgetAttributes() + { + $form = $this->factory->createNamed('text', 'text', 'value', array( + 'required' => true, + 'disabled' => true, + 'read_only' => true, + 'attr' => array('maxlength' => 10, 'pattern' => '\d+', 'class' => 'foobar', 'data-foo' => 'bar'), + )); + + $html = $this->renderWidget($form->createView()); + + // compare plain HTML to check the whitespace + $this->assertSame('', $html); + } + + public function testWidgetAttributeNameRepeatedIfTrue() + { + $form = $this->factory->createNamed('text', 'text', 'value', array( + 'attr' => array('foo' => true), + )); + + $html = $this->renderWidget($form->createView()); + + // foo="foo" + $this->assertSame('', $html); + } + + public function testButtonAttributes() + { + $form = $this->factory->createNamed('button', 'button', null, array( + 'disabled' => true, + 'attr' => array('class' => 'foobar', 'data-foo' => 'bar'), + )); + + $html = $this->renderWidget($form->createView()); + + // compare plain HTML to check the whitespace + $this->assertSame('', $html); + } + + public function testButtonAttributeNameRepeatedIfTrue() + { + $form = $this->factory->createNamed('button', 'button', null, array( + 'attr' => array('foo' => true), + )); + + $html = $this->renderWidget($form->createView()); + + // foo="foo" + $this->assertSame('', $html); + } +} diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index 85f66a1c3f..6375542b28 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -92,9 +92,15 @@ protected function assertWidgetMatchesXpath(FormView $view, array $vars, $xpath) 'attr' => array('class' => 'my&class'), ), $vars)); - $xpath = trim($xpath).' - [@id="my&id"] + if (!isset($vars['id'])) { + $xpath = trim($xpath).' + [@id="my&id"]'; + } + + if (!isset($vars['attr']['class'])) { + $xpath .= ' [@class="my&class"]'; + } $this->assertMatchesXpath($html, $xpath); } From d701757cb181327d2bba16b38c2c13c6a642a6a9 Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Tue, 24 Mar 2015 19:34:06 +0100 Subject: [PATCH 420/447] Translator component has default domain for null implemented no need to have default translation domain logic in 3 different places --- Extension/Core/Type/BaseType.php | 6 +----- Tests/Extension/Core/Type/BaseTypeTest.php | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Extension/Core/Type/BaseType.php b/Extension/Core/Type/BaseType.php index 66f3641f43..e22bc880e6 100644 --- a/Extension/Core/Type/BaseType.php +++ b/Extension/Core/Type/BaseType.php @@ -56,7 +56,7 @@ public function buildView(FormView $view, FormInterface $form, array $options) $uniqueBlockPrefix = '_'.$blockName; } - if (!$translationDomain) { + if (null === $translationDomain) { $translationDomain = $view->parent->vars['translation_domain']; } } else { @@ -76,10 +76,6 @@ public function buildView(FormView $view, FormInterface $form, array $options) } $blockPrefixes[] = $uniqueBlockPrefix; - if (!$translationDomain) { - $translationDomain = 'messages'; - } - $view->vars = array_replace($view->vars, array( 'form' => $view, 'id' => $id, diff --git a/Tests/Extension/Core/Type/BaseTypeTest.php b/Tests/Extension/Core/Type/BaseTypeTest.php index bfa1e21805..0048cf41c5 100644 --- a/Tests/Extension/Core/Type/BaseTypeTest.php +++ b/Tests/Extension/Core/Type/BaseTypeTest.php @@ -112,7 +112,7 @@ public function testDefaultTranslationDomain() ->getForm() ->createView(); - $this->assertEquals('messages', $view['child']->vars['translation_domain']); + $this->assertNull($view['child']->vars['translation_domain']); } public function testPassLabelToView() From dfc5e7109b93c5d3cfb9ba73a8f20b3539b0237c Mon Sep 17 00:00:00 2001 From: Dariusz Ruminski Date: Thu, 26 Mar 2015 23:32:35 +0100 Subject: [PATCH 421/447] CS: fixes --- Tests/AbstractFormTest.php | 16 ++++++++-------- Tests/CallbackTransformerTest.php | 13 +++++++++++-- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/Tests/AbstractFormTest.php b/Tests/AbstractFormTest.php index a2d171c234..2a842b29df 100644 --- a/Tests/AbstractFormTest.php +++ b/Tests/AbstractFormTest.php @@ -1,13 +1,13 @@ - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ namespace Symfony\Component\Form\Tests; diff --git a/Tests/CallbackTransformerTest.php b/Tests/CallbackTransformerTest.php index 7f3b074e78..af49e69e6c 100644 --- a/Tests/CallbackTransformerTest.php +++ b/Tests/CallbackTransformerTest.php @@ -1,5 +1,14 @@ + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Symfony\Component\Form\Tests; use Symfony\Component\Form\CallbackTransformer; @@ -30,8 +39,8 @@ public function testConstructorWithInvalidCallbacks($transformCallback, $reverse public function invalidCallbacksProvider() { return array( - array( null, function () {} ), - array( function () {}, null ), + array(null, function () {}), + array(function () {}, null), ); } } From 301d6b168c72c2f1399ce1a4629dc22861c6288e Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Fri, 27 Mar 2015 22:21:56 +0100 Subject: [PATCH 422/447] remove useless tests that fail in php 7 --- Tests/Extension/Core/Type/ChoiceTypeTest.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/Tests/Extension/Core/Type/ChoiceTypeTest.php b/Tests/Extension/Core/Type/ChoiceTypeTest.php index 895661ee4f..9e4ecd4552 100644 --- a/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -66,16 +66,6 @@ protected function tearDown() $this->objectChoices = null; } - /** - * @expectedException \PHPUnit_Framework_Error - */ - public function testChoicesOptionExpectsArray() - { - $this->factory->create('choice', null, array( - 'choices' => new \ArrayObject(), - )); - } - /** * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException */ From eb734af983cac5d632fad9af2ab75860f6ebd539 Mon Sep 17 00:00:00 2001 From: Dariusz Ruminski Date: Fri, 27 Mar 2015 23:06:33 +0100 Subject: [PATCH 423/447] CS: Unary operators should be placed adjacent to their operands --- Extension/Core/Type/ChoiceType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/Core/Type/ChoiceType.php b/Extension/Core/Type/ChoiceType.php index 418661aebe..bde4ba723f 100644 --- a/Extension/Core/Type/ChoiceType.php +++ b/Extension/Core/Type/ChoiceType.php @@ -160,7 +160,7 @@ public function finishView(FormView $view, FormInterface $form, array $options) */ public function setDefaultOptions(OptionsResolverInterface $resolver) { - $choiceListCache = & $this->choiceListCache; + $choiceListCache = &$this->choiceListCache; $choiceList = function (Options $options) use (&$choiceListCache) { // Harden against NULL values (like in EntityType and ModelType) From 73ec9a6ce1fb16a55c7284129e214b5191539501 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Tue, 7 Apr 2015 18:35:44 +0200 Subject: [PATCH 424/447] [Form] Fixed DateType/TimeType that were broken since 849fb2998485639d253e2438ecf78f62cc833a53 and 1c4a75a00a86df3e17979be86bddaafc108daf98 --- Extension/Core/Type/DateType.php | 12 ++-- Extension/Core/Type/TimeType.php | 10 +-- Tests/Extension/Core/Type/DateTypeTest.php | 72 ++++------------------ 3 files changed, 22 insertions(+), 72 deletions(-) diff --git a/Extension/Core/Type/DateType.php b/Extension/Core/Type/DateType.php index dc553ad8dd..7a6c11f2fb 100644 --- a/Extension/Core/Type/DateType.php +++ b/Extension/Core/Type/DateType.php @@ -57,8 +57,8 @@ public function buildForm(FormBuilderInterface $builder, array $options) if ('single_text' === $options['widget']) { $builder->addViewTransformer(new DateTimeToLocalizedStringTransformer( - null, - null, + $options['model_timezone'], + $options['view_timezone'], $dateFormat, $timeFormat, $calendar, @@ -105,7 +105,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) ->add('month', $options['widget'], $monthOptions) ->add('day', $options['widget'], $dayOptions) ->addViewTransformer(new DateTimeToArrayTransformer( - null, null, array('year', 'month', 'day') + $options['model_timezone'], $options['view_timezone'], array('year', 'month', 'day') )) ->setAttribute('formatter', $formatter) ; @@ -113,15 +113,15 @@ public function buildForm(FormBuilderInterface $builder, array $options) if ('string' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToStringTransformer(null, null, 'Y-m-d') + new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone'], 'Y-m-d') )); } elseif ('timestamp' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToTimestampTransformer(null, null) + new DateTimeToTimestampTransformer($options['model_timezone'], $options['model_timezone']) )); } elseif ('array' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToArrayTransformer(null, null, array('year', 'month', 'day')) + new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], array('year', 'month', 'day')) )); } } diff --git a/Extension/Core/Type/TimeType.php b/Extension/Core/Type/TimeType.php index 4fd2cba56c..adff60c215 100644 --- a/Extension/Core/Type/TimeType.php +++ b/Extension/Core/Type/TimeType.php @@ -48,7 +48,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) } if ('single_text' === $options['widget']) { - $builder->addViewTransformer(new DateTimeToStringTransformer(null, null, $format)); + $builder->addViewTransformer(new DateTimeToStringTransformer($options['model_timezone'], $options['view_timezone'], $format)); } else { $hourOptions = $minuteOptions = $secondOptions = array( 'error_bubbling' => true, @@ -109,20 +109,20 @@ public function buildForm(FormBuilderInterface $builder, array $options) $builder->add('second', $options['widget'], $secondOptions); } - $builder->addViewTransformer(new DateTimeToArrayTransformer(null, null, $parts, 'text' === $options['widget'])); + $builder->addViewTransformer(new DateTimeToArrayTransformer($options['model_timezone'], $options['view_timezone'], $parts, 'text' === $options['widget'])); } if ('string' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToStringTransformer(null, null, 'H:i:s') + new DateTimeToStringTransformer($options['model_timezone'], $options['model_timezone'], 'H:i:s') )); } elseif ('timestamp' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToTimestampTransformer(null, null) + new DateTimeToTimestampTransformer($options['model_timezone'], $options['model_timezone']) )); } elseif ('array' === $options['input']) { $builder->addModelTransformer(new ReversedTransformer( - new DateTimeToArrayTransformer(null, null, $parts) + new DateTimeToArrayTransformer($options['model_timezone'], $options['model_timezone'], $parts) )); } } diff --git a/Tests/Extension/Core/Type/DateTypeTest.php b/Tests/Extension/Core/Type/DateTypeTest.php index d8b3312b1f..172f338d56 100644 --- a/Tests/Extension/Core/Type/DateTypeTest.php +++ b/Tests/Extension/Core/Type/DateTypeTest.php @@ -380,93 +380,43 @@ public function testThrowExceptionIfDaysIsInvalid() )); } - public function testSetDataWithDifferentNegativeUTCTimezoneDateTime() + public function testSetDataWithNegativeTimezoneOffsetStringInput() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, - 'model_timezone' => 'America/New_York', - 'view_timezone' => 'Pacific/Tahiti', + 'model_timezone' => 'UTC', + 'view_timezone' => 'America/New_York', 'input' => 'string', 'widget' => 'single_text', )); $form->setData('2010-06-02'); + // 2010-06-02 00:00:00 UTC + // 2010-06-01 20:00:00 UTC-4 $this->assertEquals('01.06.2010', $form->getViewData()); } - public function testSetDataWithDifferentTimezonesDateTime() + public function testSetDataWithNegativeTimezoneOffsetDateTimeInput() { $form = $this->factory->create('date', null, array( 'format' => \IntlDateFormatter::MEDIUM, - 'model_timezone' => 'America/New_York', - 'view_timezone' => 'Pacific/Tahiti', + 'model_timezone' => 'UTC', + 'view_timezone' => 'America/New_York', 'input' => 'datetime', 'widget' => 'single_text', )); - $dateTime = new \DateTime('2010-06-02 America/New_York'); + $dateTime = new \DateTime('2010-06-02 UTC'); $form->setData($dateTime); + // 2010-06-02 00:00:00 UTC + // 2010-06-01 20:00:00 UTC-4 $this->assertDateTimeEquals($dateTime, $form->getData()); $this->assertEquals('01.06.2010', $form->getViewData()); } - public function testSetDataWithDifferentPositiveUTCTimezoneDateTime() - { - date_default_timezone_set('Pacific/Tahiti'); - - $form = $this->factory->create('date', null, array( - 'format' => \IntlDateFormatter::MEDIUM, - 'input' => 'datetime', - 'widget' => 'single_text', - )); - - $dateTime = new \DateTime('2010-06-02 Australia/Melbourne'); - - $form->setData($dateTime); - - $this->assertDateTimeEquals($dateTime, $form->getData()); - $this->assertEquals('02.06.2010', $form->getViewData()); - } - - public function testSetDataWithSamePositiveUTCTimezoneDateTime() - { - date_default_timezone_set('Australia/Melbourne'); - - $form = $this->factory->create('date', null, array( - 'format' => \IntlDateFormatter::MEDIUM, - 'input' => 'datetime', - 'widget' => 'single_text', - )); - - $dateTime = new \DateTime('2010-06-02 Australia/Melbourne'); - - $form->setData($dateTime); - - $this->assertDateTimeEquals($dateTime, $form->getData()); - $this->assertEquals('02.06.2010', $form->getViewData()); - } - - public function testSetDataWithSameNegativeUTCTimezoneDateTime() - { - date_default_timezone_set('America/New_York'); - - $form = $this->factory->create('date', null, array( - 'format' => \IntlDateFormatter::MEDIUM, - 'input' => 'datetime', - 'widget' => 'single_text', - )); - - $dateTime = new \DateTime('2010-06-02 America/New_York'); - - $form->setData($dateTime); - - $this->assertDateTimeEquals($dateTime, $form->getData()); - $this->assertEquals('02.06.2010', $form->getViewData()); - } - public function testYearsOption() { $form = $this->factory->create('date', null, array( From 50da8dcbb32541636a88d8a664569090195115b0 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 10 Apr 2015 20:22:21 +0200 Subject: [PATCH 425/447] [2.6] Fix @link annotations --- Extension/DataCollector/FormDataCollector.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Extension/DataCollector/FormDataCollector.php b/Extension/DataCollector/FormDataCollector.php index 752a3d066f..ddfb3400cb 100644 --- a/Extension/DataCollector/FormDataCollector.php +++ b/Extension/DataCollector/FormDataCollector.php @@ -18,7 +18,7 @@ use Symfony\Component\HttpKernel\DataCollector\DataCollector; /** - * Data collector for {@link \Symfony\Component\Form\FormInterface} instances. + * Data collector for {@link FormInterface} instances. * * @since 2.4 * @author Robert Schönthal From 550479e299d4e96f7ac430f077676629c3326424 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 10 Apr 2015 20:06:04 +0200 Subject: [PATCH 426/447] [2.3] Fix @link annotations --- Extension/Core/ChoiceList/ChoiceListInterface.php | 4 ++-- Extension/Core/Type/BaseType.php | 2 +- .../HttpFoundation/EventListener/BindRequestListener.php | 2 +- Extension/Validator/ViolationMapper/ViolationPath.php | 2 +- NativeRequestHandler.php | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Extension/Core/ChoiceList/ChoiceListInterface.php b/Extension/Core/ChoiceList/ChoiceListInterface.php index d205b92d4d..a1265a80dc 100644 --- a/Extension/Core/ChoiceList/ChoiceListInterface.php +++ b/Extension/Core/ChoiceList/ChoiceListInterface.php @@ -127,7 +127,7 @@ public function getValuesForChoices(array $choices); * Returns the indices corresponding to the given choices. * * The indices must be positive integers or strings accepted by - * {@link FormConfigBuilder::validateName()}. + * {@link \Symfony\Component\Form\FormConfigBuilder::validateName()}. * * The index "placeholder" is internally reserved. * @@ -145,7 +145,7 @@ public function getIndicesForChoices(array $choices); * Returns the indices corresponding to the given values. * * The indices must be positive integers or strings accepted by - * {@link FormConfigBuilder::validateName()}. + * {@link \Symfony\Component\Form\FormConfigBuilder::validateName()}. * * The index "placeholder" is internally reserved. * diff --git a/Extension/Core/Type/BaseType.php b/Extension/Core/Type/BaseType.php index e22bc880e6..43d90d9599 100644 --- a/Extension/Core/Type/BaseType.php +++ b/Extension/Core/Type/BaseType.php @@ -21,7 +21,7 @@ * Encapsulates common logic of {@link FormType} and {@link ButtonType}. * * This type does not appear in the form's type inheritance chain and as such - * cannot be extended (via {@link FormTypeExtension}s) nor themed. + * cannot be extended (via {@link \Symfony\Component\Form\FormExtensionInterface}) nor themed. * * @author Bernhard Schussek */ diff --git a/Extension/HttpFoundation/EventListener/BindRequestListener.php b/Extension/HttpFoundation/EventListener/BindRequestListener.php index bb144ed65a..2489cf371c 100644 --- a/Extension/HttpFoundation/EventListener/BindRequestListener.php +++ b/Extension/HttpFoundation/EventListener/BindRequestListener.php @@ -20,7 +20,7 @@ * @author Bernhard Schussek * * @deprecated Deprecated since version 2.3, to be removed in 3.0. Pass the - * Request instance to {@link Form::handleRequest()} instead. + * Request instance to {@link \Symfony\Component\Form\Form::handleRequest()} instead. */ class BindRequestListener implements EventSubscriberInterface { diff --git a/Extension/Validator/ViolationMapper/ViolationPath.php b/Extension/Validator/ViolationMapper/ViolationPath.php index 8e406a9b08..c84f98a200 100644 --- a/Extension/Validator/ViolationMapper/ViolationPath.php +++ b/Extension/Validator/ViolationMapper/ViolationPath.php @@ -48,7 +48,7 @@ class ViolationPath implements \IteratorAggregate, PropertyPathInterface /** * Creates a new violation path from a string. * - * @param string $violationPath The property path of a {@link ConstraintViolation} + * @param string $violationPath The property path of a {@link \Symfony\Component\Validator\ConstraintViolation} * object. */ public function __construct($violationPath) diff --git a/NativeRequestHandler.php b/NativeRequestHandler.php index 7c883f12eb..c9a76858dd 100644 --- a/NativeRequestHandler.php +++ b/NativeRequestHandler.php @@ -159,7 +159,7 @@ private static function getRequestMethod() * It's safe to pass an already converted array, in which case this method * just returns the original array unmodified. * - * This method is identical to {@link Symfony\Component\HttpFoundation\FileBag::fixPhpFilesArray} + * This method is identical to {@link \Symfony\Component\HttpFoundation\FileBag::fixPhpFilesArray} * and should be kept as such in order to port fixes quickly and easily. * * @param array $data From ad29500d59b778c583dad01edc8b6cbb5c29c414 Mon Sep 17 00:00:00 2001 From: Vladimir Reznichenko Date: Thu, 9 Apr 2015 16:55:17 +0200 Subject: [PATCH 427/447] [2.3] Static Code Analysis for Components --- Extension/Core/DataTransformer/BaseDateTimeTransformer.php | 4 ++-- Extension/Core/DataTransformer/DateTimeToArrayTransformer.php | 2 ++ Extension/Core/EventListener/MergeCollectionListener.php | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Extension/Core/DataTransformer/BaseDateTimeTransformer.php b/Extension/Core/DataTransformer/BaseDateTimeTransformer.php index 0cf9741dce..309d46074e 100644 --- a/Extension/Core/DataTransformer/BaseDateTimeTransformer.php +++ b/Extension/Core/DataTransformer/BaseDateTimeTransformer.php @@ -40,11 +40,11 @@ abstract class BaseDateTimeTransformer implements DataTransformerInterface */ public function __construct($inputTimezone = null, $outputTimezone = null) { - if (!is_string($inputTimezone) && null !== $inputTimezone) { + if (null !== $inputTimezone && !is_string($inputTimezone)) { throw new UnexpectedTypeException($inputTimezone, 'string'); } - if (!is_string($outputTimezone) && null !== $outputTimezone) { + if (null !== $outputTimezone && !is_string($outputTimezone)) { throw new UnexpectedTypeException($outputTimezone, 'string'); } diff --git a/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php b/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php index e36be12009..b3f4dbdd63 100644 --- a/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php @@ -99,6 +99,8 @@ public function transform($dateTime) // remove leading zeros $entry = (string) (int) $entry; } + // unset reference to keep scope clear + unset($entry); } return $result; diff --git a/Extension/Core/EventListener/MergeCollectionListener.php b/Extension/Core/EventListener/MergeCollectionListener.php index a14f99a985..a7d31c2e9a 100644 --- a/Extension/Core/EventListener/MergeCollectionListener.php +++ b/Extension/Core/EventListener/MergeCollectionListener.php @@ -74,7 +74,7 @@ public function onSubmit(FormEvent $event) } // If we are not allowed to change anything, return immediately - if ((!$this->allowAdd && !$this->allowDelete) || $data === $dataToMergeInto) { + if ($data === $dataToMergeInto || (!$this->allowAdd && !$this->allowDelete)) { $event->setData($dataToMergeInto); return; From 9cd323e8877a8332a36e83d3d1473838879a8939 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 1 May 2015 16:06:45 +0200 Subject: [PATCH 428/447] link to https://symfony.com where possible --- FormEvents.php | 4 ++-- README.md | 2 +- composer.json | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/FormEvents.php b/FormEvents.php index 978e716e94..e4663811ea 100644 --- a/FormEvents.php +++ b/FormEvents.php @@ -13,10 +13,10 @@ /** * To learn more about how form events work check the documentation - * entry at {@link http://symfony.com/doc/any/components/form/form_events.html}. + * entry at {@link https://symfony.com/doc/any/components/form/form_events.html}. * * To learn how to dynamically modify forms using events check the cookbook - * entry at {@link http://symfony.com/doc/any/cookbook/form/dynamic_form_modification.html}. + * entry at {@link https://symfony.com/doc/any/cookbook/form/dynamic_form_modification.html}. * * @author Bernhard Schussek */ diff --git a/README.md b/README.md index bde6b78be6..8f34c7a419 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ https://github.com/fabpot/Silex/blob/master/src/Silex/Provider/FormServiceProvid Documentation: -http://symfony.com/doc/2.3/book/forms.html +https://symfony.com/doc/2.3/book/forms.html Resources --------- diff --git a/composer.json b/composer.json index d9fcb2c0cf..f1b5a9d239 100644 --- a/composer.json +++ b/composer.json @@ -3,7 +3,7 @@ "type": "library", "description": "Symfony Form Component", "keywords": [], - "homepage": "http://symfony.com", + "homepage": "https://symfony.com", "license": "MIT", "authors": [ { @@ -12,7 +12,7 @@ }, { "name": "Symfony Community", - "homepage": "http://symfony.com/contributors" + "homepage": "https://symfony.com/contributors" } ], "require": { From aa6ac87be9d06ec3e3cd15b53b00e3e58feb1e2e Mon Sep 17 00:00:00 2001 From: Wouter J Date: Sun, 3 May 2015 16:08:06 +0200 Subject: [PATCH 429/447] Fix getOrigin --- Form.php | 8 ++-- Tests/AbstractRequestHandlerTest.php | 5 ++- .../Csrf/Type/FormTypeCsrfExtensionTest.php | 4 +- .../DataCollector/FormDataExtractorTest.php | 4 +- .../ViolationMapper/ViolationMapperTest.php | 38 ++++++++++--------- 5 files changed, 33 insertions(+), 26 deletions(-) diff --git a/Form.php b/Form.php index b0528d1d2a..5a1e802090 100644 --- a/Form.php +++ b/Form.php @@ -684,11 +684,11 @@ public function bind($submittedData) */ public function addError(FormError $error) { - if ($this->parent && $this->config->getErrorBubbling()) { - if (null === $error->getOrigin()) { - $error->setOrigin($this); - } + if (null === $error->getOrigin()) { + $error->setOrigin($this); + } + if ($this->parent && $this->config->getErrorBubbling()) { $this->parent->addError($error); } else { $this->errors[] = $error; diff --git a/Tests/AbstractRequestHandlerTest.php b/Tests/AbstractRequestHandlerTest.php index 197ae392bb..d6e0b4f671 100644 --- a/Tests/AbstractRequestHandlerTest.php +++ b/Tests/AbstractRequestHandlerTest.php @@ -329,9 +329,10 @@ public function testAddFormErrorIfPostMaxSizeExceeded($contentLength, $iniMax, $ $this->requestHandler->handleRequest($form, $this->request); if ($shouldFail) { - $errors = array(new FormError($options['post_max_size_message'], null, $errorParams)); + $error = new FormError($options['post_max_size_message'], null, $errorParams); + $error->setOrigin($form); - $this->assertEquals($errors, iterator_to_array($form->getErrors())); + $this->assertEquals(array($error), iterator_to_array($form->getErrors())); $this->assertTrue($form->isSubmitted()); } else { $this->assertCount(0, $form->getErrors()); diff --git a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php index 53e3d3a6b3..bc78a4a442 100644 --- a/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php +++ b/Tests/Extension/Csrf/Type/FormTypeCsrfExtensionTest.php @@ -393,8 +393,10 @@ public function testsTranslateCustomErrorMessage() )); $errors = $form->getErrors(); + $expected = new FormError('[trans]Foobar[/trans]'); + $expected->setOrigin($form); $this->assertGreaterThan(0, count($errors)); - $this->assertEquals(new FormError('[trans]Foobar[/trans]'), $errors[0]); + $this->assertEquals($expected, $errors[0]); } } diff --git a/Tests/Extension/DataCollector/FormDataExtractorTest.php b/Tests/Extension/DataCollector/FormDataExtractorTest.php index deb6069ee2..fc0b76fdf0 100644 --- a/Tests/Extension/DataCollector/FormDataExtractorTest.php +++ b/Tests/Extension/DataCollector/FormDataExtractorTest.php @@ -319,7 +319,7 @@ public function testExtractSubmittedDataStoresErrors() 'norm' => "'Foobar'", ), 'errors' => array( - array('message' => 'Invalid!', 'origin' => null, 'trace' => array()), + array('message' => 'Invalid!', 'origin' => spl_object_hash($form), 'trace' => array()), ), 'synchronized' => 'true', ), $this->dataExtractor->extractSubmittedData($form)); @@ -360,7 +360,7 @@ public function testExtractSubmittedDataStoresErrorCause() 'norm' => "'Foobar'", ), 'errors' => array( - array('message' => 'Invalid!', 'origin' => null, 'trace' => array( + array('message' => 'Invalid!', 'origin' => spl_object_hash($form), 'trace' => array( array( 'class' => "'Exception'", 'message' => "''", diff --git a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php index dc25e747f9..0934ef6b36 100644 --- a/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php +++ b/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php @@ -15,6 +15,7 @@ use Symfony\Component\Form\Exception\TransformationFailedException; use Symfony\Component\Form\CallbackTransformer; use Symfony\Component\Form\Form; +use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormConfigBuilder; use Symfony\Component\Form\FormError; use Symfony\Component\PropertyAccess\PropertyPath; @@ -110,9 +111,12 @@ protected function getConstraintViolation($propertyPath) /** * @return FormError */ - protected function getFormError(ConstraintViolationInterface $violation) + protected function getFormError(ConstraintViolationInterface $violation, FormInterface $form) { - return new FormError($this->message, $this->messageTemplate, $this->params, null, $violation); + $error = new FormError($this->message, $this->messageTemplate, $this->params, null, $violation); + $error->setOrigin($form); + + return $error; } public function testMapToFormInheritingParentDataIfDataDoesNotMatch() @@ -130,7 +134,7 @@ public function testMapToFormInheritingParentDataIfDataDoesNotMatch() $this->mapper->mapViolation($violation, $parent); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($child->getErrors()), $child->getName().' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation, $child)), iterator_to_array($child->getErrors()), $child->getName().' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); } @@ -159,7 +163,7 @@ public function testFollowDotRules() $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $child->getName().' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChild->getName().' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($grandGrandChild->getErrors()), $grandGrandChild->getName().' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation, $grandGrandChild)), iterator_to_array($grandGrandChild->getErrors()), $grandGrandChild->getName().' should have an error, but has none'); } public function testAbortMappingIfNotSynchronized() @@ -800,17 +804,17 @@ public function testDefaultErrorMapping($target, $childName, $childPath, $grandC $this->mapper->mapViolation($violation, $parent); if (self::LEVEL_0 === $target) { - $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($parent->getErrors()), $parent->getName().' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation, $parent)), iterator_to_array($parent->getErrors()), $parent->getName().' should have an error, but has none'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($child->getErrors()), $childName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation, $child)), iterator_to_array($child->getErrors()), $childName.' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } else { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($grandChild->getErrors()), $grandChildName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation, $grandChild)), iterator_to_array($grandChild->getErrors()), $grandChildName.' should have an error, but has none'); } } @@ -1274,17 +1278,17 @@ public function testCustomDataErrorMapping($target, $mapFrom, $mapTo, $childName } if (self::LEVEL_0 === $target) { - $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($parent->getErrors()), $parent->getName().' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation, $parent)), iterator_to_array($parent->getErrors()), $parent->getName().' should have an error, but has none'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($child->getErrors()), $childName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation, $child)), iterator_to_array($child->getErrors()), $childName.' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } else { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($grandChild->getErrors()), $grandChildName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation, $grandChild)), iterator_to_array($grandChild->getErrors()), $grandChildName.' should have an error, but has none'); } } @@ -1458,16 +1462,16 @@ public function testCustomFormErrorMapping($target, $mapFrom, $mapTo, $errorName if (self::LEVEL_0 === $target) { $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($parent->getErrors()), $parent->getName().' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation, $parent)), iterator_to_array($parent->getErrors()), $parent->getName().' should have an error, but has none'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one'); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($child->getErrors()), $childName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation, $child)), iterator_to_array($child->getErrors()), $childName.' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1B === $target) { - $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($errorChild->getErrors()), $errorName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation, $errorChild)), iterator_to_array($errorChild->getErrors()), $errorName.' should have an error, but has none'); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); @@ -1475,7 +1479,7 @@ public function testCustomFormErrorMapping($target, $mapFrom, $mapTo, $errorName $this->assertCount(0, $errorChild->getErrors(), $errorName.' should not have an error, but has one'); $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($grandChild->getErrors()), $grandChildName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation, $grandChild)), iterator_to_array($grandChild->getErrors()), $grandChildName.' should have an error, but has none'); } } @@ -1522,17 +1526,17 @@ public function testErrorMappingForFormInheritingParentData($target, $childName, $this->mapper->mapViolation($violation, $parent); if (self::LEVEL_0 === $target) { - $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($parent->getErrors()), $parent->getName().' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation, $parent)), iterator_to_array($parent->getErrors()), $parent->getName().' should have an error, but has none'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } elseif (self::LEVEL_1 === $target) { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($child->getErrors()), $childName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation, $child)), iterator_to_array($child->getErrors()), $childName.' should have an error, but has none'); $this->assertCount(0, $grandChild->getErrors(), $grandChildName.' should not have an error, but has one'); } else { $this->assertCount(0, $parent->getErrors(), $parent->getName().' should not have an error, but has one'); $this->assertCount(0, $child->getErrors(), $childName.' should not have an error, but has one'); - $this->assertEquals(array($this->getFormError($violation)), iterator_to_array($grandChild->getErrors()), $grandChildName.' should have an error, but has none'); + $this->assertEquals(array($this->getFormError($violation, $grandChild)), iterator_to_array($grandChild->getErrors()), $grandChildName.' should have an error, but has none'); } } } From 43979f775f1c6e3e22f281741830f30ae4047f15 Mon Sep 17 00:00:00 2001 From: "stefan.r" Date: Mon, 6 Apr 2015 01:30:32 +0200 Subject: [PATCH 430/447] Fixed compatibility with PHP7 and up by introducing new constraints (IsNull, IsTrue, IsFalse) and related validators (IsNullValidator, IsTrueValidator, IsFalseValidator) --- Extension/Validator/ValidatorTypeGuesser.php | 3 +++ .../Validator/ValidatorTypeGuesserTest.php | 16 ++++++++++++++-- composer.json | 2 +- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Extension/Validator/ValidatorTypeGuesser.php b/Extension/Validator/ValidatorTypeGuesser.php index 56f763b7ce..63dacfaacc 100644 --- a/Extension/Validator/ValidatorTypeGuesser.php +++ b/Extension/Validator/ValidatorTypeGuesser.php @@ -157,6 +157,8 @@ public function guessTypeForConstraint(Constraint $constraint) case 'Symfony\Component\Validator\Constraints\True': case 'Symfony\Component\Validator\Constraints\False': + case 'Symfony\Component\Validator\Constraints\IsTrue': + case 'Symfony\Component\Validator\Constraints\IsFalse': return new TypeGuess('checkbox', array(), Guess::MEDIUM_CONFIDENCE); } } @@ -174,6 +176,7 @@ public function guessRequiredForConstraint(Constraint $constraint) case 'Symfony\Component\Validator\Constraints\NotNull': case 'Symfony\Component\Validator\Constraints\NotBlank': case 'Symfony\Component\Validator\Constraints\True': + case 'Symfony\Component\Validator\Constraints\IsTrue': return new ValueGuess(true, Guess::HIGH_CONFIDENCE); } } diff --git a/Tests/Extension/Validator/ValidatorTypeGuesserTest.php b/Tests/Extension/Validator/ValidatorTypeGuesserTest.php index 61b2a917ec..654f6d5d2f 100644 --- a/Tests/Extension/Validator/ValidatorTypeGuesserTest.php +++ b/Tests/Extension/Validator/ValidatorTypeGuesserTest.php @@ -19,7 +19,7 @@ use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\Range; -use Symfony\Component\Validator\Constraints\True; +use Symfony\Component\Validator\Constraints\IsTrue; use Symfony\Component\Validator\Constraints\Type; use Symfony\Component\Validator\Mapping\ClassMetadata; @@ -64,7 +64,7 @@ public function guessRequiredProvider() return array( array(new NotNull(), new ValueGuess(true, Guess::HIGH_CONFIDENCE)), array(new NotBlank(), new ValueGuess(true, Guess::HIGH_CONFIDENCE)), - array(new True(), new ValueGuess(true, Guess::HIGH_CONFIDENCE)), + array(new IsTrue(), new ValueGuess(true, Guess::HIGH_CONFIDENCE)), array(new Length(10), new ValueGuess(false, Guess::LOW_CONFIDENCE)), array(new Range(array('min' => 1, 'max' => 20)), new ValueGuess(false, Guess::LOW_CONFIDENCE)), ); @@ -84,6 +84,18 @@ public function testGuessRequired($constraint, $guess) $this->assertEquals($guess, $this->guesser->guessRequired(self::TEST_CLASS, self::TEST_PROPERTY)); } + /** + * @group legacy + */ + public function testLegacyGuessRequired() + { + if (PHP_VERSION_ID >= 70000) { + $this->markTestSkipped('Cannot use a class called True on PHP 7 or higher.'); + } + $true = 'Symfony\Component\Validator\Constraints\True'; + $this->testGuessRequired(new $true(), new ValueGuess(true, Guess::HIGH_CONFIDENCE)); + } + public function testGuessRequiredReturnsFalseForUnmappedProperties() { $this->assertEquals(new ValueGuess(false, Guess::LOW_CONFIDENCE), $this->guesser->guessRequired(self::TEST_CLASS, self::TEST_PROPERTY)); diff --git a/composer.json b/composer.json index d9fcb2c0cf..48d217ed6e 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "require-dev": { "symfony/phpunit-bridge": "~2.7", "doctrine/collections": "~1.0", - "symfony/validator": "~2.3.0,>=2.3.20", + "symfony/validator": "~2.3.29", "symfony/translation": "~2.0,>=2.0.5", "symfony/http-foundation": "~2.2" }, From c70882bb716aea44d9e8d91c3afd77b93de95e1e Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 15 May 2015 15:29:32 +0200 Subject: [PATCH 431/447] [Form] Test for space in AbstractBootstrap3LayoutTest::testErrors --- Tests/AbstractBootstrap3LayoutTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/AbstractBootstrap3LayoutTest.php b/Tests/AbstractBootstrap3LayoutTest.php index b5354e0bd2..d927089dc2 100644 --- a/Tests/AbstractBootstrap3LayoutTest.php +++ b/Tests/AbstractBootstrap3LayoutTest.php @@ -118,12 +118,12 @@ public function testErrors() [@class="list-unstyled"] [ ./li - [.="[trans]Error 1[/trans]"] + [.=" [trans]Error 1[/trans]"] [ ./span[@class="glyphicon glyphicon-exclamation-sign"] ] /following-sibling::li - [.="[trans]Error 2[/trans]"] + [.=" [trans]Error 2[/trans]"] [ ./span[@class="glyphicon glyphicon-exclamation-sign"] ] From bb35442e2dc9eaf52408eee606c91b81b3642485 Mon Sep 17 00:00:00 2001 From: Diego Saint Esteben Date: Thu, 21 May 2015 18:12:55 -0300 Subject: [PATCH 432/447] Check instance of FormBuilderInterface instead of FormBuilder --- FormBuilder.php | 4 ++-- Tests/FormBuilderTest.php | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/FormBuilder.php b/FormBuilder.php index 8b5b919413..81c9ad5f6d 100644 --- a/FormBuilder.php +++ b/FormBuilder.php @@ -62,7 +62,7 @@ public function add($child, $type = null, array $options = array()) throw new BadMethodCallException('FormBuilder methods cannot be accessed anymore once the builder is turned into a FormConfigInterface instance.'); } - if ($child instanceof self) { + if ($child instanceof FormBuilderInterface) { $this->children[$child->getName()] = $child; // In case an unresolved child with the same name exists @@ -72,7 +72,7 @@ public function add($child, $type = null, array $options = array()) } if (!is_string($child) && !is_int($child)) { - throw new UnexpectedTypeException($child, 'string, integer or Symfony\Component\Form\FormBuilder'); + throw new UnexpectedTypeException($child, 'string, integer or Symfony\Component\Form\FormBuilderInterface'); } if (null !== $type && !is_string($type) && !$type instanceof FormTypeInterface) { diff --git a/Tests/FormBuilderTest.php b/Tests/FormBuilderTest.php index da691838c3..8c7b96587d 100644 --- a/Tests/FormBuilderTest.php +++ b/Tests/FormBuilderTest.php @@ -11,7 +11,9 @@ namespace Symfony\Component\Form\Tests; +use Symfony\Component\Form\ButtonBuilder; use Symfony\Component\Form\FormBuilder; +use Symfony\Component\Form\SubmitButtonBuilder; class FormBuilderTest extends \PHPUnit_Framework_TestCase { @@ -154,6 +156,12 @@ public function testCreateNoTypeNo() $this->builder->create('foo'); } + public function testAddButton() + { + $this->builder->add(new ButtonBuilder('reset')); + $this->builder->add(new SubmitButtonBuilder('submit')); + } + public function testGetUnknown() { $this->setExpectedException('Symfony\Component\Form\Exception\InvalidArgumentException', 'The child with the name "foo" does not exist.'); From 2a9246450fd78cf51176cfccdd5ad7c09745ab2e Mon Sep 17 00:00:00 2001 From: Vladimir Reznichenko Date: Fri, 29 May 2015 19:14:48 +0200 Subject: [PATCH 433/447] Php Inspections (EA Extended): - resolved possible PHP Fatal in \Symfony\Component\BrowserKit\Cookie::__toString -resolved implicit magic methods calls -resolved callable name case mismatches --- Extension/Core/DataTransformer/DateTimeToStringTransformer.php | 2 +- Tests/AbstractLayoutTest.php | 2 +- .../Core/DataTransformer/DateTimeToStringTransformerTest.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Extension/Core/DataTransformer/DateTimeToStringTransformer.php b/Extension/Core/DataTransformer/DateTimeToStringTransformer.php index f5ba9948d0..8fa1622a36 100644 --- a/Extension/Core/DataTransformer/DateTimeToStringTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToStringTransformer.php @@ -219,7 +219,7 @@ public function reverseTransform($value) } if ($this->inputTimezone !== $this->outputTimezone) { - $dateTime->setTimeZone(new \DateTimeZone($this->inputTimezone)); + $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone)); } } catch (TransformationFailedException $e) { throw $e; diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index f741ce0b68..8bbf9aab5d 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -60,7 +60,7 @@ protected function assertMatchesXpath($html, $expression, $count = 1) try { // Wrap in node so we can load HTML with multiple tags at // the top level - $dom->loadXml(''.$html.''); + $dom->loadXML(''.$html.''); } catch (\Exception $e) { $this->fail(sprintf( "Failed loading HTML:\n\n%s\n\nError: %s", diff --git a/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php index dbcdad0f96..a0aede7c85 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php @@ -147,7 +147,7 @@ public function testReverseTransformWithDifferentTimezones() $output = new \DateTime('2010-02-03 16:05:06 Asia/Hong_Kong'); $input = $output->format('Y-m-d H:i:s'); - $output->setTimeZone(new \DateTimeZone('America/New_York')); + $output->setTimezone(new \DateTimeZone('America/New_York')); $this->assertDateTimeEquals($output, $reverseTransformer->reverseTransform($input)); } From d460bd68a53bcff421f6990b45f470518f2b28fd Mon Sep 17 00:00:00 2001 From: Sergio Santoro Date: Sat, 6 Jun 2015 18:12:30 +0200 Subject: [PATCH 434/447] [Form] Fix call to removed method (BC broken in 2.3) ResolvedFormType#getTypeExtensions() was calling method AbstractType#getExtensions() which has been removed in commit b3081e85a062abb8fc8a22f20a2b3289db2ff501 | Q | A | ------------- | --- | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - --- ResolvedFormType.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ResolvedFormType.php b/ResolvedFormType.php index b922e32561..218d0d999f 100644 --- a/ResolvedFormType.php +++ b/ResolvedFormType.php @@ -93,11 +93,6 @@ public function getInnerType() */ public function getTypeExtensions() { - // BC - if ($this->innerType instanceof AbstractType) { - return $this->innerType->getExtensions(); - } - return $this->typeExtensions; } From 800ea00682a289d2bfac66b7b2ad7a9b8681e84e Mon Sep 17 00:00:00 2001 From: Dominik Zogg Date: Sat, 6 Jun 2015 08:40:52 +0000 Subject: [PATCH 435/447] without this change allways the legacy code get called --- Extension/Validator/ValidatorExtension.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Extension/Validator/ValidatorExtension.php b/Extension/Validator/ValidatorExtension.php index f6ef3070ca..8a9a75074f 100644 --- a/Extension/Validator/ValidatorExtension.php +++ b/Extension/Validator/ValidatorExtension.php @@ -59,13 +59,13 @@ public function __construct($validator) public function loadTypeGuesser() { - // 2.4 API - if ($this->validator instanceof LegacyValidatorInterface) { - return new ValidatorTypeGuesser($this->validator->getMetadataFactory()); + // 2.5 API + if ($this->validator instanceof ValidatorInterface) { + return new ValidatorTypeGuesser($this->validator); } - // 2.5 API - ValidatorInterface extends MetadataFactoryInterface - return new ValidatorTypeGuesser($this->validator); + // 2.4 API + return new ValidatorTypeGuesser($this->validator->getMetadataFactory()); } protected function loadTypeExtensions() From eac6996d745ac59f4d42096a25c2915567bbd08f Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 7 Jun 2015 08:50:12 +0200 Subject: [PATCH 436/447] [Form] add test to avoid regression of #14891 --- Tests/Extension/Validator/ValidatorExtensionTest.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Tests/Extension/Validator/ValidatorExtensionTest.php b/Tests/Extension/Validator/ValidatorExtensionTest.php index eca0873818..ee822316ad 100644 --- a/Tests/Extension/Validator/ValidatorExtensionTest.php +++ b/Tests/Extension/Validator/ValidatorExtensionTest.php @@ -17,7 +17,9 @@ class ValidatorExtensionTest extends \PHPUnit_Framework_TestCase { public function test2Dot5ValidationApi() { - $validator = $this->getMock('Symfony\Component\Validator\Validator\ValidatorInterface'); + $validator = $this->getMockBuilder('Symfony\Component\Validator\Validator\RecursiveValidator') + ->disableOriginalConstructor() + ->getMock(); $metadata = $this->getMockBuilder('Symfony\Component\Validator\Mapping\ClassMetadata') ->disableOriginalConstructor() ->getMock(); @@ -36,6 +38,10 @@ public function test2Dot5ValidationApi() ->method('addPropertyConstraint') ->with('children', $this->isInstanceOf('Symfony\Component\Validator\Constraints\Valid')); + $validator + ->expects($this->never()) + ->method('getMetadataFactory'); + $extension = new ValidatorExtension($validator); $guesser = $extension->loadTypeGuesser(); From 3d4f32ea7f454b9326fed9bc006dfc8e65da55b5 Mon Sep 17 00:00:00 2001 From: Christian Schmidt Date: Sat, 6 Jun 2015 17:05:57 +0200 Subject: [PATCH 437/447] [Form] Support DateTimeImmutable in transform() --- .../DateTimeToArrayTransformer.php | 13 ++++++---- .../DateTimeToLocalizedStringTransformer.php | 14 ++++------- .../DateTimeToRfc3339Transformer.php | 6 ++--- .../DateTimeToStringTransformer.php | 13 ++++++---- .../DateTimeToTimestampTransformer.php | 15 ++++-------- .../DateTimeToArrayTransformerTest.php | 24 +++++++++++++++++++ ...teTimeToLocalizedStringTransformerTest.php | 16 +++++++++++++ .../DateTimeToRfc3339TransformerTest.php | 14 +++++++++++ .../DateTimeToStringTransformerTest.php | 15 ++++++++++++ .../DateTimeToTimestampTransformerTest.php | 15 ++++++++++++ 10 files changed, 111 insertions(+), 34 deletions(-) diff --git a/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php b/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php index b3f4dbdd63..afbfc1041e 100644 --- a/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php @@ -51,7 +51,7 @@ public function __construct($inputTimezone = null, $outputTimezone = null, array /** * Transforms a normalized date into a localized date. * - * @param \DateTime $dateTime Normalized date. + * @param \DateTime|\DateTimeInterface $dateTime A DateTime object * * @return array Localized date. * @@ -72,14 +72,17 @@ public function transform($dateTime) ), array_flip($this->fields)); } - if (!$dateTime instanceof \DateTime) { - throw new TransformationFailedException('Expected a \DateTime.'); + if (!$dateTime instanceof \DateTime && !$dateTime instanceof \DateTimeInterface) { + throw new TransformationFailedException('Expected a \DateTime or \DateTimeInterface.'); } - $dateTime = clone $dateTime; if ($this->inputTimezone !== $this->outputTimezone) { + if (!$dateTime instanceof \DateTimeImmutable) { + $dateTime = clone $dateTime; + } + try { - $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone)); + $dateTime = $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone)); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } diff --git a/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php b/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php index e7ebcabc7a..b38680a1bb 100644 --- a/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php @@ -70,7 +70,7 @@ public function __construct($inputTimezone = null, $outputTimezone = null, $date /** * Transforms a normalized date into a localized date string/array. * - * @param \DateTime $dateTime Normalized date. + * @param \DateTime|\DateTimeInterface $dateTime A DateTime object * * @return string|array Localized date string/array. * @@ -84,17 +84,11 @@ public function transform($dateTime) return ''; } - if (!$dateTime instanceof \DateTime) { - throw new TransformationFailedException('Expected a \DateTime.'); + if (!$dateTime instanceof \DateTime && !$dateTime instanceof \DateTimeInterface) { + throw new TransformationFailedException('Expected a \DateTime or \DateTimeInterface.'); } - // convert time to UTC before passing it to the formatter - $dateTime = clone $dateTime; - if ('UTC' !== $this->inputTimezone) { - $dateTime->setTimezone(new \DateTimeZone('UTC')); - } - - $value = $this->getIntlDateFormatter()->format((int) $dateTime->format('U')); + $value = $this->getIntlDateFormatter()->format($dateTime->getTimestamp()); if (intl_get_error_code() != 0) { throw new TransformationFailedException(intl_get_error_message()); diff --git a/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php b/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php index e3297ffef3..c78d80401a 100644 --- a/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php +++ b/Extension/Core/DataTransformer/DateTimeToRfc3339Transformer.php @@ -27,13 +27,13 @@ public function transform($dateTime) return ''; } - if (!$dateTime instanceof \DateTime) { - throw new TransformationFailedException('Expected a \DateTime.'); + if (!$dateTime instanceof \DateTime && !$dateTime instanceof \DateTimeInterface) { + throw new TransformationFailedException('Expected a \DateTime or \DateTimeInterface.'); } if ($this->inputTimezone !== $this->outputTimezone) { $dateTime = clone $dateTime; - $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone)); + $dateTime = $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone)); } return preg_replace('/\+00:00$/', 'Z', $dateTime->format('c')); diff --git a/Extension/Core/DataTransformer/DateTimeToStringTransformer.php b/Extension/Core/DataTransformer/DateTimeToStringTransformer.php index 8fa1622a36..fdcfeee8ec 100644 --- a/Extension/Core/DataTransformer/DateTimeToStringTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToStringTransformer.php @@ -90,7 +90,7 @@ public function __construct($inputTimezone = null, $outputTimezone = null, $form * Transforms a DateTime object into a date string with the configured format * and timezone. * - * @param \DateTime $value A DateTime object + * @param \DateTime|\DateTimeInterface $dateTime A DateTime object * * @return string A value as produced by PHP's date() function * @@ -104,13 +104,16 @@ public function transform($value) return ''; } - if (!$value instanceof \DateTime) { - throw new TransformationFailedException('Expected a \DateTime.'); + if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) { + throw new TransformationFailedException('Expected a \DateTime or \DateTimeInterface.'); + } + + if (!$value instanceof \DateTimeImmutable) { + $value = clone $value; } - $value = clone $value; try { - $value->setTimezone(new \DateTimeZone($this->outputTimezone)); + $value = $value->setTimezone(new \DateTimeZone($this->outputTimezone)); } catch (\Exception $e) { throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); } diff --git a/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php b/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php index bd51ea4195..b8f5f381a5 100644 --- a/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToTimestampTransformer.php @@ -24,7 +24,7 @@ class DateTimeToTimestampTransformer extends BaseDateTimeTransformer /** * Transforms a DateTime object into a timestamp in the configured timezone. * - * @param \DateTime $value A \DateTime object + * @param \DateTime|\DateTimeInterface $dateTime A DateTime object * * @return int A timestamp * @@ -38,18 +38,11 @@ public function transform($value) return; } - if (!$value instanceof \DateTime) { - throw new TransformationFailedException('Expected a \DateTime.'); + if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) { + throw new TransformationFailedException('Expected a \DateTime or \DateTimeInterface.'); } - $value = clone $value; - try { - $value->setTimezone(new \DateTimeZone($this->outputTimezone)); - } catch (\Exception $e) { - throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); - } - - return (int) $value->format('U'); + return $value->getTimestamp(); } /** diff --git a/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.php b/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.php index db5f2b1638..3042eea5a4 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeToArrayTransformerTest.php @@ -116,6 +116,30 @@ public function testTransformDifferentTimezones() $this->assertSame($output, $transformer->transform($input)); } + public function testTransformDateTimeImmutable() + { + if (PHP_VERSION_ID < 50500) { + $this->markTestSkipped('DateTimeImmutable was introduced in PHP 5.5.0'); + } + + $transformer = new DateTimeToArrayTransformer('America/New_York', 'Asia/Hong_Kong'); + + $input = new \DateTimeImmutable('2010-02-03 04:05:06 America/New_York'); + + $dateTime = new \DateTimeImmutable('2010-02-03 04:05:06 America/New_York'); + $dateTime = $dateTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); + $output = array( + 'year' => (string) (int) $dateTime->format('Y'), + 'month' => (string) (int) $dateTime->format('m'), + 'day' => (string) (int) $dateTime->format('d'), + 'hour' => (string) (int) $dateTime->format('H'), + 'minute' => (string) (int) $dateTime->format('i'), + 'second' => (string) (int) $dateTime->format('s'), + ); + + $this->assertSame($output, $transformer->transform($input)); + } + /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ diff --git a/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php index cb50fc3669..d6964d395a 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformerTest.php @@ -141,6 +141,22 @@ public function testTransformWithDifferentPatterns() $this->assertEquals('02*2010*03 04|05|06', $transformer->transform($this->dateTime)); } + public function testTransformDateTimeImmutableTimezones() + { + if (PHP_VERSION_ID < 50500) { + $this->markTestSkipped('DateTimeImmutable was introduced in PHP 5.5.0'); + } + + $transformer = new DateTimeToLocalizedStringTransformer('America/New_York', 'Asia/Hong_Kong'); + + $input = new \DateTimeImmutable('2010-02-03 04:05:06 America/New_York'); + + $dateTime = clone $input; + $dateTime = $dateTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); + + $this->assertEquals($dateTime->format('d.m.Y H:i'), $transformer->transform($input)); + } + /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ diff --git a/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php b/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php index a39f53aa70..be3827cc74 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeToRfc3339TransformerTest.php @@ -79,6 +79,20 @@ public function testTransform($fromTz, $toTz, $from, $to) $this->assertSame($to, $transformer->transform(null !== $from ? new \DateTime($from) : null)); } + /** + * @dataProvider transformProvider + */ + public function testTransformDateTimeImmutable($fromTz, $toTz, $from, $to) + { + if (PHP_VERSION_ID < 50500) { + $this->markTestSkipped('DateTimeImmutable was introduced in PHP 5.5.0'); + } + + $transformer = new DateTimeToRfc3339Transformer($fromTz, $toTz); + + $this->assertSame($to, $transformer->transform(null !== $from ? new \DateTimeImmutable($from) : null)); + } + /** * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException */ diff --git a/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php b/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php index a0aede7c85..e1099d9b35 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeToStringTransformerTest.php @@ -97,6 +97,21 @@ public function testTransformWithDifferentTimezones() $this->assertEquals($output, $transformer->transform($input)); } + public function testTransformDateTimeImmutable() + { + if (PHP_VERSION_ID < 50500) { + $this->markTestSkipped('DateTimeImmutable was introduced in PHP 5.5.0'); + } + + $transformer = new DateTimeToStringTransformer('Asia/Hong_Kong', 'America/New_York', 'Y-m-d H:i:s'); + + $input = new \DateTimeImmutable('2010-02-03 12:05:06 America/New_York'); + $output = $input->format('Y-m-d H:i:s'); + $input = $input->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); + + $this->assertEquals($output, $transformer->transform($input)); + } + public function testTransformExpectsDateTime() { $transformer = new DateTimeToStringTransformer(); diff --git a/Tests/Extension/Core/DataTransformer/DateTimeToTimestampTransformerTest.php b/Tests/Extension/Core/DataTransformer/DateTimeToTimestampTransformerTest.php index b54f0c4c50..451451d09d 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeToTimestampTransformerTest.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeToTimestampTransformerTest.php @@ -56,6 +56,21 @@ public function testTransformFromDifferentTimezone() $this->assertEquals($output, $transformer->transform($input)); } + public function testTransformDateTimeImmutable() + { + if (PHP_VERSION_ID < 50500) { + $this->markTestSkipped('DateTimeImmutable was introduced in PHP 5.5.0'); + } + + $transformer = new DateTimeToTimestampTransformer('Asia/Hong_Kong', 'America/New_York'); + + $input = new \DateTimeImmutable('2010-02-03 04:05:06 America/New_York'); + $output = $input->format('U'); + $input = $input->setTimezone(new \DateTimeZone('Asia/Hong_Kong')); + + $this->assertEquals($output, $transformer->transform($input)); + } + public function testTransformExpectsDateTime() { $transformer = new DateTimeToTimestampTransformer(); From 63b07db4811b80034afd6c8126fc438be550f228 Mon Sep 17 00:00:00 2001 From: Vladimir Reznichenko Date: Sun, 21 Jun 2015 07:33:01 +0200 Subject: [PATCH 438/447] [2.3] Static Code Analysis for Components --- Tests/Extension/Core/Type/ChoiceTypePerformanceTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.php b/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.php index 0685946fc1..83430d935c 100644 --- a/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.php +++ b/Tests/Extension/Core/Type/ChoiceTypePerformanceTest.php @@ -30,7 +30,7 @@ public function testSameChoiceFieldCreatedMultipleTimes() $choices = range(1, 300); for ($i = 0; $i < 100; ++$i) { - $this->factory->create('choice', rand(1, 400), array( + $this->factory->create('choice', mt_rand(1, 400), array( 'choices' => $choices, )); } From a4d649743750f8109c6b8038665cb53f66a0e43c Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Mon, 22 Jun 2015 17:14:39 +0200 Subject: [PATCH 439/447] [Form] Fixed: remove quoted strings from Intl date formats (e.g. es_ES full pattern) --- Extension/Core/Type/DateType.php | 4 ++++ Tests/Extension/Core/Type/DateTypeTest.php | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/Extension/Core/Type/DateType.php b/Extension/Core/Type/DateType.php index a7fc6cadf5..3e837ccef0 100644 --- a/Extension/Core/Type/DateType.php +++ b/Extension/Core/Type/DateType.php @@ -145,6 +145,10 @@ public function finishView(FormView $view, FormInterface $form, array $options) // remove special characters unless the format was explicitly specified if (!is_string($options['format'])) { + // remove quoted strings first + $pattern = preg_replace('/\'[^\']+\'/', '', $pattern); + + // remove remaining special chars $pattern = preg_replace('/[^yMd]+/', '', $pattern); } diff --git a/Tests/Extension/Core/Type/DateTypeTest.php b/Tests/Extension/Core/Type/DateTypeTest.php index e5b58a8c4a..e5aba86efe 100644 --- a/Tests/Extension/Core/Type/DateTypeTest.php +++ b/Tests/Extension/Core/Type/DateTypeTest.php @@ -614,6 +614,20 @@ public function testDontPassDatePatternIfText() $this->assertFalse(isset($view->vars['date_pattern'])); } + public function testDatePatternFormatWithQuotedStrings() + { + \Locale::setDefault('es_ES'); + + $form = $this->factory->create('date', null, array( + // EEEE, d 'de' MMMM 'de' y + 'format' => \IntlDateFormatter::FULL, + )); + + $view = $form->createView(); + + $this->assertEquals('{{ day }}{{ month }}{{ year }}', $view->vars['date_pattern']); + } + public function testPassWidgetToView() { $form = $this->factory->create('date', null, array( From e6f15ecb0db6e77d7a0710cf60934cae2ce9eb94 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Mon, 22 Jun 2015 21:00:03 +0200 Subject: [PATCH 440/447] [Form] Fixed: Data mappers always receive forms indexed by their names --- Form.php | 2 +- Tests/CompoundFormTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Form.php b/Form.php index 8a19f82a2d..de229064d5 100644 --- a/Form.php +++ b/Form.php @@ -895,7 +895,7 @@ public function add($child, $type = null, array $options = array()) $child->setParent($this); if (!$this->lockSetData && $this->defaultDataSet && !$this->config->getInheritData()) { - $iterator = new InheritDataAwareIterator(new \ArrayIterator(array($child))); + $iterator = new InheritDataAwareIterator(new \ArrayIterator(array($child->getName() => $child))); $iterator = new \RecursiveIteratorIterator($iterator); $this->config->getDataMapper()->mapDataToForms($viewData, $iterator); } diff --git a/Tests/CompoundFormTest.php b/Tests/CompoundFormTest.php index 5ebb9906fa..1f7b78889d 100644 --- a/Tests/CompoundFormTest.php +++ b/Tests/CompoundFormTest.php @@ -352,7 +352,7 @@ public function testAddMapsViewDataToFormIfInitialized() ->with('bar', $this->isInstanceOf('\RecursiveIteratorIterator')) ->will($this->returnCallback(function ($data, \RecursiveIteratorIterator $iterator) use ($child, $test) { $test->assertInstanceOf('Symfony\Component\Form\Util\InheritDataAwareIterator', $iterator->getInnerIterator()); - $test->assertSame(array($child), iterator_to_array($iterator)); + $test->assertSame(array($child->getName() => $child), iterator_to_array($iterator)); })); $form->initialize(); From 261138b7c61fc5ff84722527b2cd837ce9230e21 Mon Sep 17 00:00:00 2001 From: BruceWouaigne Date: Thu, 5 Mar 2015 18:38:17 +0100 Subject: [PATCH 441/447] [Form] [EventListener] fixed sending non array data on submit to ResizeListener --- Extension/Core/EventListener/ResizeFormListener.php | 2 +- .../Core/EventListener/ResizeFormListenerTest.php | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Extension/Core/EventListener/ResizeFormListener.php b/Extension/Core/EventListener/ResizeFormListener.php index 8a4919240d..01c3c1b0b2 100644 --- a/Extension/Core/EventListener/ResizeFormListener.php +++ b/Extension/Core/EventListener/ResizeFormListener.php @@ -101,7 +101,7 @@ public function preSubmit(FormEvent $event) } if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { - throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)'); + $data = array(); } // Remove all empty rows diff --git a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php index 7bcc7f2d12..7197666392 100644 --- a/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php +++ b/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php @@ -167,15 +167,14 @@ public function testPreSubmitDoesNothingIfNotAllowAddNorAllowDelete() $this->assertFalse($this->form->has('2')); } - /** - * @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException - */ - public function testPreSubmitRequiresArrayOrTraversable() + public function testPreSubmitDealsWithNoArrayOrTraversable() { $data = 'no array or traversable'; $event = new FormEvent($this->form, $data); $listener = new ResizeFormListener('text', array(), false, false); $listener->preSubmit($event); + + $this->assertFalse($this->form->has('1')); } public function testPreSubmitDealsWithNullData() From 4a72cca01cfc4f6968b39cf3e2255404c4b5df92 Mon Sep 17 00:00:00 2001 From: Restless-ET Date: Tue, 16 Jun 2015 10:52:18 +0100 Subject: [PATCH 442/447] [Translation][Form][choice] empty_value shouldn't be translated when it has an empty value --- Tests/AbstractLayoutTest.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Tests/AbstractLayoutTest.php b/Tests/AbstractLayoutTest.php index 8bbf9aab5d..c5529d8aa5 100644 --- a/Tests/AbstractLayoutTest.php +++ b/Tests/AbstractLayoutTest.php @@ -505,7 +505,7 @@ public function testSingleChoiceNonRequired() [@name="name"] [not(@required)] [ - ./option[@value=""][.="[trans][/trans]"] + ./option[@value=""][.=""] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] @@ -528,7 +528,7 @@ public function testSingleChoiceNonRequiredNoneSelected() [@name="name"] [not(@required)] [ - ./option[@value=""][.="[trans][/trans]"] + ./option[@value=""][.=""] /following-sibling::option[@value="&a"][not(@selected)][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] @@ -605,7 +605,7 @@ public function testSingleChoiceRequiredWithEmptyValueViaView() [@name="name"] [@required="required"] [ - ./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"] + ./option[@value=""][not(@selected)][not(@disabled)][.=""] /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] ] @@ -1233,15 +1233,15 @@ public function testBirthDayWithEmptyValue() [ ./select [@id="name_month"] - [./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"]] + [./option[@value=""][not(@selected)][not(@disabled)][.=""]] [./option[@value="1"][@selected="selected"]] /following-sibling::select [@id="name_day"] - [./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"]] + [./option[@value=""][not(@selected)][not(@disabled)][.=""]] [./option[@value="1"][@selected="selected"]] /following-sibling::select [@id="name_year"] - [./option[@value=""][not(@selected)][not(@disabled)][.="[trans][/trans]"]] + [./option[@value=""][not(@selected)][not(@disabled)][.=""]] [./option[@value="1950"][@selected="selected"]] ] [count(./select)=3] From 4b3dcca98ad83aba6480702c93df0091ed600f3e Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 30 Jun 2015 08:51:58 +0200 Subject: [PATCH 443/447] Towards 100% HHVM compat --- Tests/Extension/Core/DataTransformer/DateTimeTestCase.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/Extension/Core/DataTransformer/DateTimeTestCase.php b/Tests/Extension/Core/DataTransformer/DateTimeTestCase.php index f7722c496e..200cbc3282 100644 --- a/Tests/Extension/Core/DataTransformer/DateTimeTestCase.php +++ b/Tests/Extension/Core/DataTransformer/DateTimeTestCase.php @@ -15,6 +15,6 @@ abstract class DateTimeTestCase extends \PHPUnit_Framework_TestCase { public static function assertDateTimeEquals(\DateTime $expected, \DateTime $actual) { - self::assertEquals($expected->format('c'), $actual->format('c')); + self::assertEquals($expected->format('U'), $actual->format('U')); } } From 4050d4b4028117ee0c4c4225bfe2c86260eef461 Mon Sep 17 00:00:00 2001 From: zhil Date: Wed, 1 Jul 2015 15:52:14 +0300 Subject: [PATCH 444/447] Update DateTimeToArrayTransformer.php --- .../Core/DataTransformer/DateTimeToArrayTransformer.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php b/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php index afbfc1041e..07070952f5 100644 --- a/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php +++ b/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php @@ -179,15 +179,16 @@ public function reverseTransform($value) try { $dateTime = new \DateTime(sprintf( - '%s-%s-%s %s:%s:%s %s', + '%s-%s-%s %s:%s:%s', empty($value['year']) ? '1970' : $value['year'], empty($value['month']) ? '1' : $value['month'], empty($value['day']) ? '1' : $value['day'], empty($value['hour']) ? '0' : $value['hour'], empty($value['minute']) ? '0' : $value['minute'], - empty($value['second']) ? '0' : $value['second'], - $this->outputTimezone - )); + empty($value['second']) ? '0' : $value['second'] + ), + new \DateTimeZone($this->outputTimezone) + ); if ($this->inputTimezone !== $this->outputTimezone) { $dateTime->setTimezone(new \DateTimeZone($this->inputTimezone)); From fd290b6441437e3de0aba8aad4800529b4851f49 Mon Sep 17 00:00:00 2001 From: Dariusz Ruminski Date: Sun, 5 Jul 2015 16:01:47 +0200 Subject: [PATCH 445/447] fix CS --- PreloadedExtension.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/PreloadedExtension.php b/PreloadedExtension.php index f70ca8d455..6b4f9ef6a1 100644 --- a/PreloadedExtension.php +++ b/PreloadedExtension.php @@ -38,9 +38,9 @@ class PreloadedExtension implements FormExtensionInterface /** * Creates a new preloaded extension. * - * @param FormTypeInterface[] $types The types that the extension should support. - * @param array[FormTypeExtensionInterface[]] typeExtensions The type extensions that the extension should support. - * @param FormTypeGuesserInterface|null $typeGuesser The guesser that the extension should support. + * @param FormTypeInterface[] $types The types that the extension should support. + * @param array[FormTypeExtensionInterface[]] $typeExtensions The type extensions that the extension should support. + * @param FormTypeGuesserInterface|null $typeGuesser The guesser that the extension should support. */ public function __construct(array $types, array $typeExtensions, FormTypeGuesserInterface $typeGuesser = null) { From 8adfffa3410ab5f2ccac3e358de589105a5d6faf Mon Sep 17 00:00:00 2001 From: Ilya Antipenko Date: Thu, 9 Jul 2015 21:38:49 +0300 Subject: [PATCH 446/447] Remove excess whitespace --- Form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Form.php b/Form.php index de229064d5..7a18dcb800 100644 --- a/Form.php +++ b/Form.php @@ -357,7 +357,7 @@ public function setData($modelData) if (!FormUtil::isEmpty($viewData)) { $dataClass = $this->config->getDataClass(); - $actualType = is_object($viewData) ? 'an instance of class '.get_class($viewData) : ' a(n) '.gettype($viewData); + $actualType = is_object($viewData) ? 'an instance of class '.get_class($viewData) : 'a(n) '.gettype($viewData); if (null === $dataClass && is_object($viewData) && !$viewData instanceof \ArrayAccess) { $expectedType = 'scalar, array or an instance of \ArrayAccess'; From b691114e317c529991eb9520af7be9a808af5a5e Mon Sep 17 00:00:00 2001 From: "Issei.M" Date: Wed, 22 Jul 2015 01:25:33 +0900 Subject: [PATCH 447/447] [Form] updated exception message of ButtonBuilder::setRequestHandler() --- ButtonBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ButtonBuilder.php b/ButtonBuilder.php index 24bc2f8916..e8f7805561 100644 --- a/ButtonBuilder.php +++ b/ButtonBuilder.php @@ -498,7 +498,7 @@ public function setMethod($method) */ public function setRequestHandler(RequestHandlerInterface $requestHandler) { - throw new BadMethodCallException('Buttons do not support form processors.'); + throw new BadMethodCallException('Buttons do not support request handlers.'); } /**