Skip to content
This repository
Browse code

Make Validation::decimal accept integers

Fix #2800
Force locale of ValidationTests with en_US to ensure decimal dot separator
  • Loading branch information...
commit 28bd6880df2f4a6bd182bcb0f3a04dd5a1b64fad 1 parent afbd582
Cauan Cabral authored April 17, 2012 markstory committed April 17, 2012
12  lib/Cake/Test/Case/Utility/ValidationTest.php
@@ -103,6 +103,8 @@ class ValidationTest extends CakeTestCase {
103 103
 	public function setUp() {
104 104
 		parent::setUp();
105 105
 		$this->_appEncoding = Configure::read('App.encoding');
  106
+		$this->_appLocale = setlocale(LC_ALL, "0");
  107
+		setlocale(LC_ALL, 'en_US');
106 108
 	}
107 109
 
108 110
 /**
@@ -113,6 +115,7 @@ public function setUp() {
113 115
 	public function tearDown() {
114 116
 		parent::tearDown();
115 117
 		Configure::write('App.encoding', $this->_appEncoding);
  118
+		setlocale(LC_ALL, $this->_appLocale);
116 119
 	}
117 120
 
118 121
 /**
@@ -1490,10 +1493,13 @@ public function testDecimal() {
1490 1493
 		$this->assertTrue(Validation::decimal('+0123.45e6'));
1491 1494
 		$this->assertTrue(Validation::decimal('-0123.45e6'));
1492 1495
 		$this->assertTrue(Validation::decimal('0123.45e6'));
  1496
+		$this->assertTrue(Validation::decimal('1234'));
  1497
+		$this->assertTrue(Validation::decimal('-1234'));
  1498
+		$this->assertTrue(Validation::decimal('+1234'));
  1499
+		$this->assertTrue(Validation::decimal(1234.56));
  1500
+		$this->assertTrue(Validation::decimal(1234.00));
  1501
+
1493 1502
 		$this->assertFalse(Validation::decimal('string'));
1494  
-		$this->assertFalse(Validation::decimal('1234'));
1495  
-		$this->assertFalse(Validation::decimal('-1234'));
1496  
-		$this->assertFalse(Validation::decimal('+1234'));
1497 1503
 	}
1498 1504
 
1499 1505
 /**
4  lib/Cake/Utility/Validation.php
@@ -382,9 +382,9 @@ public static function boolean($check) {
382 382
 	public static function decimal($check, $places = null, $regex = null) {
383 383
 		if (is_null($regex)) {
384 384
 			if (is_null($places)) {
385  
-				$regex = '/^[-+]?[0-9]*\\.{1}[0-9]+(?:[eE][-+]?[0-9]+)?$/';
  385
+				$regex = '/^[-+]?[0-9]*(\\.{1}[0-9]+(?:[eE][-+]?[0-9]+)?)?$/';
386 386
 			} else {
387  
-				$regex = '/^[-+]?[0-9]*\\.{1}[0-9]{' . $places . '}$/';
  387
+				$regex = '/^[-+]?[0-9]*(\\.{1}[0-9]{' . $places . '})?$/';
388 388
 			}
389 389
 		}
390 390
 		return self::_check($check, $regex);

11 notes on commit 28bd688

Ber Clausen
bar commented on 28bd688 August 24, 2012

Why is Validator::decimal() nos validation decimal point anymore?¿
Even the docs says it should:

Checks that a value is a valid decimal. If $places is null, the $check is allowed to be a scientific float
If no decimal point is found a false will be returned. Both the sign and exponent are optional.

From:

$this->assertFalse(Validation::decimal('1234'));

to

$this->assertTrue(Validation::decimal('1234'));
Mark Story
Owner

Well 1234 is a valid decimal value, as it has implicit 00's

Ber Clausen
bar commented on 28bd688 August 24, 2012

I know, but the whoie point of testing against decimal(), and not numeric() or naturalNumber() is to detect a decimal point (again, as the documentation says). It can't be right that (int)1234 passes the test...

Mark Story
Owner

The original issue that created this change was http://cakephp.lighthouseapp.com/projects/42648-cakephp/tickets/2800 The wikipedia article on decimal values says

Trailing zeros after the decimal point are not necessary

Which seems reasonable considering decimal values generally come from user input, and requiring trailing zero's seems a bit excessive. Both '10' and '10.000' have the same representation in both PHP and Javascript. Additionally databases like MySQL and SQLite treat these values as interchangeable as does Postgres from what I remember.

Ber Clausen
bar commented on 28bd688 August 24, 2012

Yes, because of PHP type juggling feature and being loosely typed, it removes trailing zeroes and automatically types the value to float, so when you type 13.00 ends being (float) 13, but when you type '13.00', it does not change but correctly passes the tests.

The solution to that can be undoing what PHP does when a float number is detected, a working proof of concept with old tests and new ones should be:

bar@70deff6

Ber Clausen
bar commented on 28bd688 August 24, 2012

Updating the commit with a clearly invalid test wich fails here because of the ()? regex grouping

$this->assertFalse(Validation::decimal(''));

bar@a59548a

Miles Johnson

I agree with bar. I would only use the decimal validation rule if I wanted to validate a number with a decimal place: 10.23, 45323.33 and even 4343.00. Numbers without a decimal shouldn't pass IMO.

Mark Story
Owner

@bar a59548a seems like a reasonable change as '' passing as a decimal is wrong like you said.

Ber Clausen
bar commented on 28bd688 August 24, 2012

@markstory yes, it seemed odd...

Mark Story
Owner

Thanks for the change @bar, merged in b75a6b4

Ber Clausen
bar commented on 28bd688 August 24, 2012

Sure, being able to contribute to the core is always a pleasure!

Please sign in to comment.
Something went wrong with that request. Please try again.