From 411fc1d0ebd18ad0fcf79e4fbc648b408b8a33e7 Mon Sep 17 00:00:00 2001 From: Alymosul Date: Thu, 3 May 2018 13:56:36 +0300 Subject: [PATCH 1/2] Add new validation rules (greaterThan, lessThan, greaterThanOrEqual, lessThanOrEqual --- .../Concerns/ValidatesAttributes.php | 108 ++++++++++++++++++ src/Illuminate/Validation/Validator.php | 4 +- tests/Validation/ValidationValidatorTest.php | 92 +++++++++++++++ 3 files changed, 202 insertions(+), 2 deletions(-) diff --git a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php index e528ebc22d43..34d36bc7a2c2 100644 --- a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php +++ b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php @@ -444,6 +444,98 @@ public function validateDifferent($attribute, $value, $parameters) return true; } + /** + * Validate that an attribute is greater than another attribute. + * + * @param string $attribute + * @param mixed $value + * @param array $parameters + * @return bool + */ + public function validateGt($attribute, $value, $parameters) + { + $this->requireParameterCount(1, $parameters, 'gt'); + + $comparedToValue = $this->getValue($parameters[0]); + + if (is_null($comparedToValue) && is_numeric($parameters[0])) { + return $this->getSize($attribute, $value) > $parameters[0]; + } + + $this->requireSameTypeValues($value, $comparedToValue); + + return $this->getSize($attribute, $value) > $this->getSize($attribute, $comparedToValue); + } + + /** + * Validate that an attribute is less than another attribute. + * + * @param string $attribute + * @param mixed $value + * @param array $parameters + * @return bool + */ + public function validateLt($attribute, $value, $parameters) + { + $this->requireParameterCount(1, $parameters, 'lt'); + + $comparedToValue = $this->getValue($parameters[0]); + + if (is_null($comparedToValue) && is_numeric($parameters[0])) { + return $this->getSize($attribute, $value) < $parameters[0]; + } + + $this->requireSameTypeValues($value, $comparedToValue); + + return $this->getSize($attribute, $value) < $this->getSize($attribute, $comparedToValue); + } + + /** + * Validate that an attribute is greater than or equal another attribute. + * + * @param string $attribute + * @param mixed $value + * @param array $parameters + * @return bool + */ + public function validateGte($attribute, $value, $parameters) + { + $this->requireParameterCount(1, $parameters, 'gte'); + + $comparedToValue = $this->getValue($parameters[0]); + + if (is_null($comparedToValue) && is_numeric($parameters[0])) { + return $this->getSize($attribute, $value) >= $parameters[0]; + } + + $this->requireSameTypeValues($value, $comparedToValue); + + return $this->getSize($attribute, $value) >= $this->getSize($attribute, $comparedToValue); + } + + /** + * Validate that an attribute is less than or equal another attribute. + * + * @param string $attribute + * @param mixed $value + * @param array $parameters + * @return bool + */ + public function validateLte($attribute, $value, $parameters) + { + $this->requireParameterCount(1, $parameters, 'lte'); + + $comparedToValue = $this->getValue($parameters[0]); + + if (is_null($comparedToValue) && is_numeric($parameters[0])) { + return $this->getSize($attribute, $value) <= $parameters[0]; + } + + $this->requireSameTypeValues($value, $comparedToValue); + + return $this->getSize($attribute, $value) <= $this->getSize($attribute, $comparedToValue); + } + /** * Validate that an attribute has a given number of digits. * @@ -1539,4 +1631,20 @@ protected function requireParameterCount($count, $parameters, $rule) throw new InvalidArgumentException("Validation rule $rule requires at least $count parameters."); } } + + /** + * Require comparison values to be of the same type. + * + * @param mixed $first + * @param mixed $second + * @return void + * + * @throws \InvalidArgumentException + */ + protected function requireSameTypeValues($first, $second) + { + if (gettype($first) != gettype($second)) { + throw new InvalidArgumentException('The values under comparison must be of the same type'); + } + } } diff --git a/src/Illuminate/Validation/Validator.php b/src/Illuminate/Validation/Validator.php index 095269bda74d..a938c7e10df8 100755 --- a/src/Illuminate/Validation/Validator.php +++ b/src/Illuminate/Validation/Validator.php @@ -167,7 +167,7 @@ class Validator implements ValidatorContract protected $dependentRules = [ 'RequiredWith', 'RequiredWithAll', 'RequiredWithout', 'RequiredWithoutAll', 'RequiredIf', 'RequiredUnless', 'Confirmed', 'Same', 'Different', 'Unique', - 'Before', 'After', 'BeforeOrEqual', 'AfterOrEqual', + 'Before', 'After', 'BeforeOrEqual', 'AfterOrEqual', 'Gt', 'Lt', 'Gte', 'Lte', ]; /** @@ -182,7 +182,7 @@ class Validator implements ValidatorContract * * @var array */ - protected $numericRules = ['Numeric', 'Integer']; + protected $numericRules = ['Numeric', 'Integer', 'Gt', 'Lt', 'Gte', 'Lte']; /** * Create a new Validator instance. diff --git a/tests/Validation/ValidationValidatorTest.php b/tests/Validation/ValidationValidatorTest.php index c04c4290a916..81d30deb7b58 100755 --- a/tests/Validation/ValidationValidatorTest.php +++ b/tests/Validation/ValidationValidatorTest.php @@ -1060,6 +1060,98 @@ public function testValidateDifferent() $this->assertFalse($v->passes()); } + public function testGreaterThan() + { + $trans = $this->getIlluminateArrayTranslator(); + $v = new Validator($trans, ['lhs' => 15, 'rhs' => 10], ['lhs' => 'gt:rhs']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['lhs' => 'longer string', 'rhs' => 'string'], ['lhs' => 'gt:rhs']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['lhs' => ['string'], 'rhs' => [1, 'string']], ['lhs' => 'gt:rhs']); + $this->assertTrue($v->fails()); + + $fileOne = $this->getMockBuilder('Symfony\Component\HttpFoundation\File\File')->setMethods(['getSize'])->setConstructorArgs([__FILE__, false])->getMock(); + $fileOne->expects($this->any())->method('getSize')->will($this->returnValue(5472)); + $fileTwo = $this->getMockBuilder('Symfony\Component\HttpFoundation\File\File')->setMethods(['getSize'])->setConstructorArgs([__FILE__, false])->getMock(); + $fileTwo->expects($this->any())->method('getSize')->will($this->returnValue(3151)); + $v = new Validator($trans, ['lhs' => $fileOne, 'rhs' => $fileTwo], ['lhs' => 'gt:rhs']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['lhs' => 15], ['lhs' => 'gt:10']); + $this->assertTrue($v->passes()); + } + + public function testLessThan() + { + $trans = $this->getIlluminateArrayTranslator(); + $v = new Validator($trans, ['lhs' => 15, 'rhs' => 10], ['lhs' => 'lt:rhs']); + $this->assertTrue($v->fails()); + + $v = new Validator($trans, ['lhs' => 'longer string', 'rhs' => 'string'], ['lhs' => 'lt:rhs']); + $this->assertTrue($v->fails()); + + $v = new Validator($trans, ['lhs' => ['string'], 'rhs' => [1, 'string']], ['lhs' => 'lt:rhs']); + $this->assertTrue($v->passes()); + + $fileOne = $this->getMockBuilder('Symfony\Component\HttpFoundation\File\File')->setMethods(['getSize'])->setConstructorArgs([__FILE__, false])->getMock(); + $fileOne->expects($this->any())->method('getSize')->will($this->returnValue(5472)); + $fileTwo = $this->getMockBuilder('Symfony\Component\HttpFoundation\File\File')->setMethods(['getSize'])->setConstructorArgs([__FILE__, false])->getMock(); + $fileTwo->expects($this->any())->method('getSize')->will($this->returnValue(3151)); + $v = new Validator($trans, ['lhs' => $fileOne, 'rhs' => $fileTwo], ['lhs' => 'lt:rhs']); + $this->assertTrue($v->fails()); + + $v = new Validator($trans, ['lhs' => 15], ['lhs' => 'lt:10']); + $this->assertTrue($v->fails()); + } + + public function testGreaterThanOrEqual() + { + $trans = $this->getIlluminateArrayTranslator(); + $v = new Validator($trans, ['lhs' => 15, 'rhs' => 15], ['lhs' => 'gte:rhs']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['lhs' => 'longer string', 'rhs' => 'string'], ['lhs' => 'gte:rhs']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['lhs' => ['string'], 'rhs' => [1, 'string']], ['lhs' => 'gte:rhs']); + $this->assertTrue($v->fails()); + + $fileOne = $this->getMockBuilder('Symfony\Component\HttpFoundation\File\File')->setMethods(['getSize'])->setConstructorArgs([__FILE__, false])->getMock(); + $fileOne->expects($this->any())->method('getSize')->will($this->returnValue(5472)); + $fileTwo = $this->getMockBuilder('Symfony\Component\HttpFoundation\File\File')->setMethods(['getSize'])->setConstructorArgs([__FILE__, false])->getMock(); + $fileTwo->expects($this->any())->method('getSize')->will($this->returnValue(5472)); + $v = new Validator($trans, ['lhs' => $fileOne, 'rhs' => $fileTwo], ['lhs' => 'gte:rhs']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['lhs' => 15], ['lhs' => 'gte:15']); + $this->assertTrue($v->passes()); + } + + public function testLessThanOrEqual() + { + $trans = $this->getIlluminateArrayTranslator(); + $v = new Validator($trans, ['lhs' => 15, 'rhs' => 15], ['lhs' => 'lte:rhs']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['lhs' => 'longer string', 'rhs' => 'string'], ['lhs' => 'lte:rhs']); + $this->assertTrue($v->fails()); + + $v = new Validator($trans, ['lhs' => ['string'], 'rhs' => [1, 'string']], ['lhs' => 'lte:rhs']); + $this->assertTrue($v->passes()); + + $fileOne = $this->getMockBuilder('Symfony\Component\HttpFoundation\File\File')->setMethods(['getSize'])->setConstructorArgs([__FILE__, false])->getMock(); + $fileOne->expects($this->any())->method('getSize')->will($this->returnValue(5472)); + $fileTwo = $this->getMockBuilder('Symfony\Component\HttpFoundation\File\File')->setMethods(['getSize'])->setConstructorArgs([__FILE__, false])->getMock(); + $fileTwo->expects($this->any())->method('getSize')->will($this->returnValue(5472)); + $v = new Validator($trans, ['lhs' => $fileOne, 'rhs' => $fileTwo], ['lhs' => 'lte:rhs']); + $this->assertTrue($v->passes()); + + $v = new Validator($trans, ['lhs' => 15], ['lhs' => 'lte:10']); + $this->assertTrue($v->fails()); + } + public function testValidateAccepted() { $trans = $this->getIlluminateArrayTranslator(); From 47580bff887078d514bc45ce20c8c1677820cf27 Mon Sep 17 00:00:00 2001 From: Alymosul Date: Thu, 3 May 2018 14:06:10 +0300 Subject: [PATCH 2/2] Restrict comparison against hardcoded integers --- .../Validation/Concerns/ValidatesAttributes.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php index 34d36bc7a2c2..7f33765666ec 100644 --- a/src/Illuminate/Validation/Concerns/ValidatesAttributes.php +++ b/src/Illuminate/Validation/Concerns/ValidatesAttributes.php @@ -458,7 +458,7 @@ public function validateGt($attribute, $value, $parameters) $comparedToValue = $this->getValue($parameters[0]); - if (is_null($comparedToValue) && is_numeric($parameters[0])) { + if (is_null($comparedToValue) && (is_numeric($value) && is_numeric($parameters[0]))) { return $this->getSize($attribute, $value) > $parameters[0]; } @@ -481,7 +481,7 @@ public function validateLt($attribute, $value, $parameters) $comparedToValue = $this->getValue($parameters[0]); - if (is_null($comparedToValue) && is_numeric($parameters[0])) { + if (is_null($comparedToValue) && (is_numeric($value) && is_numeric($parameters[0]))) { return $this->getSize($attribute, $value) < $parameters[0]; } @@ -504,7 +504,7 @@ public function validateGte($attribute, $value, $parameters) $comparedToValue = $this->getValue($parameters[0]); - if (is_null($comparedToValue) && is_numeric($parameters[0])) { + if (is_null($comparedToValue) && (is_numeric($value) && is_numeric($parameters[0]))) { return $this->getSize($attribute, $value) >= $parameters[0]; } @@ -527,7 +527,7 @@ public function validateLte($attribute, $value, $parameters) $comparedToValue = $this->getValue($parameters[0]); - if (is_null($comparedToValue) && is_numeric($parameters[0])) { + if (is_null($comparedToValue) && (is_numeric($value) && is_numeric($parameters[0]))) { return $this->getSize($attribute, $value) <= $parameters[0]; }