Skip to content

Commit e337ce9

Browse files
author
Romaric Drigon
committed
Added a "html5" option to PercentType, to render an input[type="number"]. Added tests over PercentType.
1 parent 8535579 commit e337ce9

File tree

4 files changed

+164
-3
lines changed

4 files changed

+164
-3
lines changed

src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,18 @@ class PercentToLocalizedStringTransformer implements DataTransformerInterface
3333

3434
private $type;
3535
private $scale;
36+
private $html5Format;
3637

3738
/**
3839
* @see self::$types for a list of supported types
3940
*
4041
* @param int $scale The scale
4142
* @param string $type One of the supported types
43+
* @param bool $html5Format Use a HTML5 specific format, as per https://www.w3.org/TR/html51/sec-forms.html#date-time-and-number-formats
4244
*
4345
* @throws UnexpectedTypeException if the given value of type is unknown
4446
*/
45-
public function __construct(int $scale = null, string $type = null)
47+
public function __construct(int $scale = null, string $type = null, bool $html5Format = false)
4648
{
4749
if (null === $scale) {
4850
$scale = 0;
@@ -58,6 +60,7 @@ public function __construct(int $scale = null, string $type = null)
5860

5961
$this->type = $type;
6062
$this->scale = $scale;
63+
$this->html5Format = $html5Format;
6164
}
6265

6366
/**
@@ -176,7 +179,13 @@ public function reverseTransform($value)
176179
*/
177180
protected function getNumberFormatter()
178181
{
179-
$formatter = new \NumberFormatter(\Locale::getDefault(), \NumberFormatter::DECIMAL);
182+
// Values used in HTML5 number inputs should be formatted as in "1234.5", ie. 'en' format without grouping,
183+
// according to https://www.w3.org/TR/html51/sec-forms.html#date-time-and-number-formats
184+
$formatter = new \NumberFormatter($this->html5Format ? 'en' : \Locale::getDefault(), \NumberFormatter::DECIMAL);
185+
186+
if ($this->html5Format) {
187+
$formatter->setAttribute(\NumberFormatter::GROUPING_USED, 0);
188+
}
180189

181190
$formatter->setAttribute(\NumberFormatter::FRACTION_DIGITS, $this->scale);
182191

src/Symfony/Component/Form/Extension/Core/Type/PercentType.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class PercentType extends AbstractType
2525
*/
2626
public function buildForm(FormBuilderInterface $builder, array $options)
2727
{
28-
$builder->addViewTransformer(new PercentToLocalizedStringTransformer($options['scale'], $options['type']));
28+
$builder->addViewTransformer(new PercentToLocalizedStringTransformer($options['scale'], $options['type'], $options['html5']));
2929
}
3030

3131
/**
@@ -34,6 +34,10 @@ public function buildForm(FormBuilderInterface $builder, array $options)
3434
public function buildView(FormView $view, FormInterface $form, array $options)
3535
{
3636
$view->vars['symbol'] = $options['symbol'];
37+
38+
if ($options['html5']) {
39+
$view->vars['type'] = 'number';
40+
}
3741
}
3842

3943
/**
@@ -46,6 +50,7 @@ public function configureOptions(OptionsResolver $resolver)
4650
'symbol' => '%',
4751
'type' => 'fractional',
4852
'compound' => false,
53+
'html5' => false,
4954
]);
5055

5156
$resolver->setAllowedValues('type', [
@@ -55,6 +60,7 @@ public function configureOptions(OptionsResolver $resolver)
5560

5661
$resolver->setAllowedTypes('scale', 'int');
5762
$resolver->setAllowedTypes('symbol', ['bool', 'string']);
63+
$resolver->setAllowedTypes('html5', 'bool');
5864
}
5965

6066
/**

src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,4 +294,83 @@ public function testReverseTransformDisallowsTrailingExtraCharactersMultibyte()
294294

295295
$transformer->reverseTransform("12\xc2\xa0345,678foo");
296296
}
297+
298+
public function testTransformForHtml5Format()
299+
{
300+
$transformer = new PercentToLocalizedStringTransformer(null, null, true);
301+
302+
// Since we test against "de_CH", we need the full implementation
303+
IntlTestHelper::requireFullIntl($this, false);
304+
305+
\Locale::setDefault('de_CH');
306+
307+
$this->assertEquals('10', $transformer->transform(0.105));
308+
$this->assertEquals('200000', $transformer->transform(2000));
309+
}
310+
311+
public function testTransformForHtml5FormatWithInteger()
312+
{
313+
$transformer = new PercentToLocalizedStringTransformer(null, 'integer', true);
314+
315+
// Since we test against "de_CH", we need the full implementation
316+
IntlTestHelper::requireFullIntl($this, false);
317+
318+
\Locale::setDefault('de_CH');
319+
320+
$this->assertEquals('0', $transformer->transform(0.1));
321+
$this->assertEquals('1234', $transformer->transform(1234));
322+
}
323+
324+
public function testTransformForHtml5FormatWithScale()
325+
{
326+
// Since we test against "de_CH", we need the full implementation
327+
IntlTestHelper::requireFullIntl($this, false);
328+
329+
\Locale::setDefault('de_CH');
330+
331+
$transformer = new PercentToLocalizedStringTransformer(2, null, true);
332+
333+
$this->assertEquals('12.34', $transformer->transform(0.1234));
334+
}
335+
336+
public function testReverseTransformForHtml5Format()
337+
{
338+
// Since we test against "de_CH", we need the full implementation
339+
IntlTestHelper::requireFullIntl($this, false);
340+
341+
\Locale::setDefault('de_CH');
342+
343+
$transformer = new PercentToLocalizedStringTransformer(null, null, true);
344+
345+
$this->assertEquals(0.015, $transformer->reverseTransform('1.5'));
346+
$this->assertEquals(0.15, $transformer->reverseTransform('15'));
347+
$this->assertEquals(2000, $transformer->reverseTransform('200000'));
348+
}
349+
350+
public function testReverseTransformForHtml5FormatWithInteger()
351+
{
352+
// Since we test against "de_CH", we need the full implementation
353+
IntlTestHelper::requireFullIntl($this, false);
354+
355+
\Locale::setDefault('de_CH');
356+
357+
$transformer = new PercentToLocalizedStringTransformer(null, 'integer', true);
358+
359+
$this->assertEquals(10, $transformer->reverseTransform('10'));
360+
$this->assertEquals(15, $transformer->reverseTransform('15'));
361+
$this->assertEquals(12, $transformer->reverseTransform('12'));
362+
$this->assertEquals(200, $transformer->reverseTransform('200'));
363+
}
364+
365+
public function testReverseTransformForHtml5FormatWithScale()
366+
{
367+
// Since we test against "de_CH", we need the full implementation
368+
IntlTestHelper::requireFullIntl($this, false);
369+
370+
\Locale::setDefault('de_CH');
371+
372+
$transformer = new PercentToLocalizedStringTransformer(2, null, true);
373+
374+
$this->assertEquals(0.1234, $transformer->reverseTransform('12.34'));
375+
}
297376
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Form\Tests\Extension\Core\Type;
13+
14+
use Symfony\Component\Intl\Util\IntlTestHelper;
15+
16+
class PercentTypeTest extends BaseTypeTest
17+
{
18+
const TESTED_TYPE = 'Symfony\Component\Form\Extension\Core\Type\PercentType';
19+
20+
private $defaultLocale;
21+
22+
protected function setUp(): void
23+
{
24+
// we test against different locales, so we need the full
25+
// implementation
26+
IntlTestHelper::requireFullIntl($this, false);
27+
28+
parent::setUp();
29+
30+
$this->defaultLocale = \Locale::getDefault();
31+
}
32+
33+
protected function tearDown(): void
34+
{
35+
parent::tearDown();
36+
37+
\Locale::setDefault($this->defaultLocale);
38+
}
39+
40+
public function testSubmitNull($expected = null, $norm = null, $view = null)
41+
{
42+
parent::testSubmitNull($expected, $norm, '');
43+
}
44+
45+
public function testSubmitNullUsesDefaultEmptyData($emptyData = '10', $expectedData = 0.1)
46+
{
47+
$form = $this->factory->create(static::TESTED_TYPE, null, [
48+
'empty_data' => $emptyData,
49+
]);
50+
$form->submit(null);
51+
52+
$this->assertSame($emptyData, $form->getViewData());
53+
$this->assertSame($expectedData, $form->getNormData());
54+
$this->assertSame($expectedData, $form->getData());
55+
}
56+
57+
public function testHtml5EnablesSpecificFormatting()
58+
{
59+
\Locale::setDefault('de_CH');
60+
61+
$form = $this->factory->create(static::TESTED_TYPE, null, ['html5' => true, 'scale' => 2, 'type' => 'integer']);
62+
$form->setData('1234.56');
63+
64+
$this->assertSame('1234.56', $form->createView()->vars['value']);
65+
$this->assertSame('number', $form->createView()->vars['type']);
66+
}
67+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy