Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6d68740

Browse files
committed
Merge pull request #8634 from bschussek/issue8473
[Form] Changed (Number|Integer)ToLocalizedStringTransformer::reverseTransform() to do rounding
2 parents 45465e4 + 0869720 commit 6d68740

File tree

6 files changed

+474
-36
lines changed

6 files changed

+474
-36
lines changed

UPGRADE-2.4.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
UPGRADE FROM 2.3 to 2.4
2+
=======================
3+
4+
Form
5+
----
6+
7+
* The constructor parameter `$precision` in `IntegerToLocalizedStringTransformer`
8+
is now ignored completely, because a precision does not make sense for
9+
integers.

UPGRADE-3.0.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ UPGRADE FROM 2.x to 3.0
158158

159159
* The `FormItegrationTestCase` and `FormPerformanceTestCase` classes were moved form the `Symfony\Component\Form\Tests` namespace to the `Symfony\Component\Form\Test` namespace.
160160

161+
* The constants `ROUND_HALFEVEN`, `ROUND_HALFUP` and `ROUND_HALFDOWN` in class
162+
`NumberToLocalizedStringTransformer` were renamed to `ROUND_HALF_EVEN`,
163+
`ROUND_HALF_UP` and `ROUND_HALF_DOWN`.
164+
161165

162166
### FrameworkBundle
163167

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

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111

1212
namespace Symfony\Component\Form\Extension\Core\DataTransformer;
1313

14-
use Symfony\Component\Form\Exception\TransformationFailedException;
15-
1614
/**
1715
* Transforms between an integer and a localized number with grouping
1816
* (each thousand) and comma separators.
@@ -22,32 +20,28 @@
2220
class IntegerToLocalizedStringTransformer extends NumberToLocalizedStringTransformer
2321
{
2422
/**
25-
* {@inheritDoc}
23+
* Constructs a transformer.
24+
*
25+
* @param integer $precision Unused.
26+
* @param Boolean $grouping Whether thousands should be grouped.
27+
* @param integer $roundingMode One of the ROUND_ constants in this class.
2628
*/
27-
public function reverseTransform($value)
29+
public function __construct($precision = null, $grouping = null, $roundingMode = self::ROUND_DOWN)
2830
{
29-
if (!is_string($value)) {
30-
throw new TransformationFailedException('Expected a string.');
31-
}
32-
33-
if ('' === $value) {
34-
return null;
35-
}
36-
37-
if ('NaN' === $value) {
38-
throw new TransformationFailedException('"NaN" is not a valid integer');
31+
if (null === $roundingMode) {
32+
$roundingMode = self::ROUND_DOWN;
3933
}
4034

41-
$formatter = $this->getNumberFormatter();
42-
$value = $formatter->parse(
43-
$value,
44-
PHP_INT_SIZE == 8 ? $formatter::TYPE_INT64 : $formatter::TYPE_INT32
45-
);
35+
parent::__construct(0, $grouping, $roundingMode);
36+
}
4637

47-
if (intl_is_failure($formatter->getErrorCode())) {
48-
throw new TransformationFailedException($formatter->getErrorMessage());
49-
}
38+
/**
39+
* {@inheritDoc}
40+
*/
41+
public function reverseTransform($value)
42+
{
43+
$result = parent::reverseTransform($value);
5044

51-
return $value;
45+
return null !== $result ? (int) $result : null;
5246
}
5347
}

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

Lines changed: 115 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,75 @@
2323
*/
2424
class NumberToLocalizedStringTransformer implements DataTransformerInterface
2525
{
26-
const ROUND_FLOOR = \NumberFormatter::ROUND_FLOOR;
27-
const ROUND_DOWN = \NumberFormatter::ROUND_DOWN;
28-
const ROUND_HALFDOWN = \NumberFormatter::ROUND_HALFDOWN;
29-
const ROUND_HALFEVEN = \NumberFormatter::ROUND_HALFEVEN;
30-
const ROUND_HALFUP = \NumberFormatter::ROUND_HALFUP;
31-
const ROUND_UP = \NumberFormatter::ROUND_UP;
32-
const ROUND_CEILING = \NumberFormatter::ROUND_CEILING;
26+
/**
27+
* Rounds a number towards positive infinity.
28+
*
29+
* Rounds 1.4 to 2 and -1.4 to -1.
30+
*/
31+
const ROUND_CEILING = \NumberFormatter::ROUND_CEILING;
32+
33+
/**
34+
* Rounds a number towards negative infinity.
35+
*
36+
* Rounds 1.4 to 1 and -1.4 to -2.
37+
*/
38+
const ROUND_FLOOR = \NumberFormatter::ROUND_FLOOR;
39+
40+
/**
41+
* Rounds a number away from zero.
42+
*
43+
* Rounds 1.4 to 2 and -1.4 to -2.
44+
*/
45+
const ROUND_UP = \NumberFormatter::ROUND_UP;
46+
47+
/**
48+
* Rounds a number towards zero.
49+
*
50+
* Rounds 1.4 to 1 and -1.4 to -1.
51+
*/
52+
const ROUND_DOWN = \NumberFormatter::ROUND_DOWN;
53+
54+
/**
55+
* Rounds to the nearest number and halves to the next even number.
56+
*
57+
* Rounds 2.5, 1.6 and 1.5 to 2 and 1.4 to 1.
58+
*/
59+
const ROUND_HALF_EVEN = \NumberFormatter::ROUND_HALFEVEN;
60+
61+
/**
62+
* Rounds to the nearest number and halves away from zero.
63+
*
64+
* Rounds 2.5 to 3, 1.6 and 1.5 to 2 and 1.4 to 1.
65+
*/
66+
const ROUND_HALF_UP = \NumberFormatter::ROUND_HALFUP;
67+
68+
/**
69+
* Rounds to the nearest number and halves towards zero.
70+
*
71+
* Rounds 2.5 and 1.6 to 2, 1.5 and 1.4 to 1.
72+
*/
73+
const ROUND_HALF_DOWN = \NumberFormatter::ROUND_HALFDOWN;
74+
75+
/**
76+
* Alias for {@link self::ROUND_HALF_EVEN}.
77+
*
78+
* @deprecated Deprecated as of Symfony 2.4, to be removed in Symfony 3.0.
79+
*/
80+
const ROUND_HALFEVEN = self::ROUND_HALF_EVEN;
81+
82+
/**
83+
* Alias for {@link self::ROUND_HALF_UP}.
84+
*
85+
* @deprecated Deprecated as of Symfony 2.4, to be removed in Symfony 3.0.
86+
*/
87+
const ROUND_HALFUP = self::ROUND_HALF_UP;
88+
89+
/**
90+
* Alias for {@link self::ROUND_HALF_DOWN}.
91+
*
92+
* @deprecated Deprecated as of Symfony 2.4, to be removed in Symfony 3.0.
93+
*/
94+
const ROUND_HALFDOWN = self::ROUND_HALF_DOWN;
3395

3496
protected $precision;
3597

@@ -160,7 +222,8 @@ public function reverseTransform($value)
160222
}
161223
}
162224

163-
return $result;
225+
// NumberFormatter::parse() does not round
226+
return $this->round($result);
164227
}
165228

166229
/**
@@ -181,4 +244,48 @@ protected function getNumberFormatter()
181244

182245
return $formatter;
183246
}
247+
248+
/**
249+
* Rounds a number according to the configured precision and rounding mode.
250+
*
251+
* @param integer|float $number A number.
252+
*
253+
* @return integer|float The rounded number.
254+
*/
255+
private function round($number)
256+
{
257+
if (null !== $this->precision && null !== $this->roundingMode) {
258+
// shift number to maintain the correct precision during rounding
259+
$roundingCoef = pow(10, $this->precision);
260+
$number *= $roundingCoef;
261+
262+
switch ($this->roundingMode) {
263+
case self::ROUND_CEILING:
264+
$number = ceil($number);
265+
break;
266+
case self::ROUND_FLOOR:
267+
$number = floor($number);
268+
break;
269+
case self::ROUND_UP:
270+
$number = $number > 0 ? ceil($number) : floor($number);
271+
break;
272+
case self::ROUND_DOWN:
273+
$number = $number > 0 ? floor($number) : ceil($number);
274+
break;
275+
case self::ROUND_HALF_EVEN:
276+
$number = round($number, 0, PHP_ROUND_HALF_EVEN);
277+
break;
278+
case self::ROUND_HALF_UP:
279+
$number = round($number, 0, PHP_ROUND_HALF_UP);
280+
break;
281+
case self::ROUND_HALF_DOWN:
282+
$number = round($number, 0, PHP_ROUND_HALF_DOWN);
283+
break;
284+
}
285+
286+
$number /= $roundingCoef;
287+
}
288+
289+
return $number;
290+
}
184291
}

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

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,67 @@ protected function setUp()
2626
\Locale::setDefault('de_AT');
2727
}
2828

29+
public function transformWithRoundingProvider()
30+
{
31+
return array(
32+
// towards positive infinity (1.6 -> 2, -1.6 -> -1)
33+
array(1234.5, '1235', IntegerToLocalizedStringTransformer::ROUND_CEILING),
34+
array(1234.4, '1235', IntegerToLocalizedStringTransformer::ROUND_CEILING),
35+
array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_CEILING),
36+
array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_CEILING),
37+
// towards negative infinity (1.6 -> 1, -1.6 -> -2)
38+
array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_FLOOR),
39+
array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_FLOOR),
40+
array(-1234.5, '-1235', IntegerToLocalizedStringTransformer::ROUND_FLOOR),
41+
array(-1234.4, '-1235', IntegerToLocalizedStringTransformer::ROUND_FLOOR),
42+
// away from zero (1.6 -> 2, -1.6 -> 2)
43+
array(1234.5, '1235', IntegerToLocalizedStringTransformer::ROUND_UP),
44+
array(1234.4, '1235', IntegerToLocalizedStringTransformer::ROUND_UP),
45+
array(-1234.5, '-1235', IntegerToLocalizedStringTransformer::ROUND_UP),
46+
array(-1234.4, '-1235', IntegerToLocalizedStringTransformer::ROUND_UP),
47+
// towards zero (1.6 -> 1, -1.6 -> -1)
48+
array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_DOWN),
49+
array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_DOWN),
50+
array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_DOWN),
51+
array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_DOWN),
52+
// round halves (.5) to the next even number
53+
array(1234.6, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
54+
array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
55+
array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
56+
array(1233.5, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
57+
array(1232.5, '1232', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
58+
array(-1234.6, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
59+
array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
60+
array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
61+
array(-1233.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
62+
array(-1232.5, '-1232', IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
63+
// round halves (.5) away from zero
64+
array(1234.6, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
65+
array(1234.5, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
66+
array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
67+
array(-1234.6, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
68+
array(-1234.5, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
69+
array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
70+
// round halves (.5) towards zero
71+
array(1234.6, '1235', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
72+
array(1234.5, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
73+
array(1234.4, '1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
74+
array(-1234.6, '-1235', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
75+
array(-1234.5, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
76+
array(-1234.4, '-1234', IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
77+
);
78+
}
79+
80+
/**
81+
* @dataProvider transformWithRoundingProvider
82+
*/
83+
public function testTransformWithRounding($input, $output, $roundingMode)
84+
{
85+
$transformer = new IntegerToLocalizedStringTransformer(null, null, $roundingMode);
86+
87+
$this->assertEquals($output, $transformer->transform($input));
88+
}
89+
2990
public function testReverseTransform()
3091
{
3192
$transformer = new IntegerToLocalizedStringTransformer();
@@ -53,6 +114,67 @@ public function testReverseTransformWithGrouping()
53114
$this->assertEquals(12345, $transformer->reverseTransform('12345,912'));
54115
}
55116

117+
public function reverseTransformWithRoundingProvider()
118+
{
119+
return array(
120+
// towards positive infinity (1.6 -> 2, -1.6 -> -1)
121+
array('1234,5', 1235, IntegerToLocalizedStringTransformer::ROUND_CEILING),
122+
array('1234,4', 1235, IntegerToLocalizedStringTransformer::ROUND_CEILING),
123+
array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_CEILING),
124+
array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_CEILING),
125+
// towards negative infinity (1.6 -> 1, -1.6 -> -2)
126+
array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_FLOOR),
127+
array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_FLOOR),
128+
array('-1234,5', -1235, IntegerToLocalizedStringTransformer::ROUND_FLOOR),
129+
array('-1234,4', -1235, IntegerToLocalizedStringTransformer::ROUND_FLOOR),
130+
// away from zero (1.6 -> 2, -1.6 -> 2)
131+
array('1234,5', 1235, IntegerToLocalizedStringTransformer::ROUND_UP),
132+
array('1234,4', 1235, IntegerToLocalizedStringTransformer::ROUND_UP),
133+
array('-1234,5', -1235, IntegerToLocalizedStringTransformer::ROUND_UP),
134+
array('-1234,4', -1235, IntegerToLocalizedStringTransformer::ROUND_UP),
135+
// towards zero (1.6 -> 1, -1.6 -> -1)
136+
array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_DOWN),
137+
array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_DOWN),
138+
array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_DOWN),
139+
array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_DOWN),
140+
// round halves (.5) to the next even number
141+
array('1234,6', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
142+
array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
143+
array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
144+
array('1233,5', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
145+
array('1232,5', 1232, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
146+
array('-1234,6', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
147+
array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
148+
array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
149+
array('-1233,5', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
150+
array('-1232,5', -1232, IntegerToLocalizedStringTransformer::ROUND_HALF_EVEN),
151+
// round halves (.5) away from zero
152+
array('1234,6', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
153+
array('1234,5', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
154+
array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
155+
array('-1234,6', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
156+
array('-1234,5', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
157+
array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_UP),
158+
// round halves (.5) towards zero
159+
array('1234,6', 1235, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
160+
array('1234,5', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
161+
array('1234,4', 1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
162+
array('-1234,6', -1235, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
163+
array('-1234,5', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
164+
array('-1234,4', -1234, IntegerToLocalizedStringTransformer::ROUND_HALF_DOWN),
165+
);
166+
}
167+
168+
/**
169+
* @dataProvider reverseTransformWithRoundingProvider
170+
*/
171+
public function testReverseTransformWithRounding($input, $output, $roundingMode)
172+
{
173+
$transformer = new IntegerToLocalizedStringTransformer(null, null, $roundingMode);
174+
175+
$this->assertEquals($output, $transformer->reverseTransform($input));
176+
}
177+
56178
/**
57179
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
58180
*/

0 commit comments

Comments
 (0)