diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 1ba15d3..fa9db15 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -47,6 +47,7 @@ Yii Framework 2 Change Log - Bug #15440: Fixed `yii\behaviors\AttributeTypecastBehavior::$attributeTypes` auto-detection fails for rule, which specify attribute with '!' prefix (klimov-paul) - Bug #15462: Fixed `accessChecker` configuration error (developeruz) - Bug #15494: Fixed missing `WWW-Authenticate` header (developeruz) +- Bug #15553: Fixed `yii\validators\NumberValidator` incorrectly validate resource (developeruz) - Enh #3087: Added `yii\helpers\BaseHtml::error()` "errorSource" option to be able to customize errors display (yanggs07, developeruz, silverfire) - Enh #3250: Added support for events partial wildcard matching (klimov-paul) - Enh #5515: Added default value for `yii\behaviors\BlameableBehavior` for cases when the user is guest (dmirogin) diff --git a/framework/validators/NumberValidator.php b/framework/validators/NumberValidator.php index 9bf9cde..88b0d41 100644 --- a/framework/validators/NumberValidator.php +++ b/framework/validators/NumberValidator.php @@ -81,7 +81,7 @@ class NumberValidator extends Validator public function validateAttribute($model, $attribute) { $value = $model->$attribute; - if (is_array($value) || (is_object($value) && !method_exists($value, '__toString'))) { + if ($this->isNotNumber($value)) { $this->addError($model, $attribute, $this->message); return; } @@ -103,7 +103,7 @@ class NumberValidator extends Validator */ protected function validateValue($value) { - if (is_array($value) || is_object($value)) { + if ($this->isNotNumber($value)) { return [Yii::t('yii', '{attribute} is invalid.'), []]; } $pattern = $this->integerOnly ? $this->integerPattern : $this->numberPattern; @@ -118,6 +118,16 @@ class NumberValidator extends Validator return null; } + /* + * @param mixed $value the data value to be checked. + */ + private function isNotNumber($value) + { + return is_array($value) + || (is_object($value) && !method_exists($value, '__toString')) + || (!is_object($value) && !is_scalar($value) && !is_null($value)); + } + /** * {@inheritdoc} */ diff --git a/tests/framework/validators/NumberValidatorTest.php b/tests/framework/validators/NumberValidatorTest.php index e794eeb..fa3edfa 100644 --- a/tests/framework/validators/NumberValidatorTest.php +++ b/tests/framework/validators/NumberValidatorTest.php @@ -298,4 +298,45 @@ class NumberValidatorTest extends TestCase $value = new \stdClass(); $this->assertFalse($val->validate($value)); } + + public function testValidateResource() + { + $val = new NumberValidator(); + $fp = fopen('php://stdin', 'r'); + $this->assertFalse($val->validate($fp)); + + $model = new FakedValidationModel(); + $model->attr_number = $fp; + $val->validateAttribute($model, 'attr_number'); + $this->assertTrue($model->hasErrors('attr_number')); + + fclose($fp); + } + + public function testValidateToString() + { + $val = new NumberValidator(); + $object = new TestClass('10'); + $this->assertTrue($val->validate($object)); + + $model = new FakedValidationModel(); + $model->attr_number = $object; + $val->validateAttribute($model, 'attr_number'); + $this->assertFalse($model->hasErrors('attr_number')); + } +} + +class TestClass +{ + public $foo; + + public function __construct($foo) + { + $this->foo = $foo; + } + + public function __toString() + { + return $this->foo; + } }