diff --git a/src/Rules/Between.php b/src/Rules/Between.php index ac055e7..fa7de36 100644 --- a/src/Rules/Between.php +++ b/src/Rules/Between.php @@ -6,6 +6,7 @@ class Between extends Rule { + use Traits\SizeTrait; /** @var string */ protected $message = "The :attribute must be between :min and :max"; @@ -23,17 +24,15 @@ public function check($value): bool { $this->requireParameters($this->fillableParams); - $min = (int) $this->parameter('min'); - $max = (int) $this->parameter('max'); + $min = $this->getBytesSize($this->parameter('min')); + $max = $this->getBytesSize($this->parameter('max')); - if (is_int($value) || is_float($value)) { - return $value >= $min and $value <= $max; - } elseif (is_string($value)) { - return mb_strlen($value, 'UTF-8') >= $min and mb_strlen($value, 'UTF-8') <= $max; - } elseif (is_array($value)) { - return count($value) >= $min and count($value) <= $max; - } else { + $valueSize = $this->getValueSize($value); + + if (!is_numeric($valueSize)) { return false; } + + return ($valueSize >= $min && $valueSize <= $max); } } diff --git a/src/Rules/Max.php b/src/Rules/Max.php index 7de011f..709d28b 100644 --- a/src/Rules/Max.php +++ b/src/Rules/Max.php @@ -6,6 +6,7 @@ class Max extends Rule { + use Traits\SizeTrait; /** @var string */ protected $message = "The :attribute maximum is :max"; @@ -23,15 +24,13 @@ public function check($value): bool { $this->requireParameters($this->fillableParams); - $max = (int) $this->parameter('max'); - if (is_int($value)) { - return $value <= $max; - } elseif (is_string($value)) { - return mb_strlen($value, 'UTF-8') <= $max; - } elseif (is_array($value)) { - return count($value) <= $max; - } else { + $max = $this->getBytesSize($this->parameter('max')); + $valueSize = $this->getValueSize($value); + + if (!is_numeric($valueSize)) { return false; } + + return $valueSize <= $max; } } diff --git a/src/Rules/Min.php b/src/Rules/Min.php index f407c27..555f8d9 100644 --- a/src/Rules/Min.php +++ b/src/Rules/Min.php @@ -6,6 +6,7 @@ class Min extends Rule { + use Traits\SizeTrait; /** @var string */ protected $message = "The :attribute minimum is :min"; @@ -23,15 +24,13 @@ public function check($value): bool { $this->requireParameters($this->fillableParams); - $min = (int) $this->parameter('min'); - if (is_int($value)) { - return $value >= $min; - } elseif (is_string($value)) { - return mb_strlen($value, 'UTF-8') >= $min; - } elseif (is_array($value)) { - return count($value) >= $min; - } else { + $min = $this->getBytesSize($this->parameter('min')); + $valueSize = $this->getValueSize($value); + + if (!is_numeric($valueSize)) { return false; } + + return $valueSize >= $min; } } diff --git a/src/Rules/Traits/FileTrait.php b/src/Rules/Traits/FileTrait.php index 8388f90..82740d3 100644 --- a/src/Rules/Traits/FileTrait.php +++ b/src/Rules/Traits/FileTrait.php @@ -39,53 +39,4 @@ public function isUploadedFile($value): bool { return $this->isValueFromUploadedFiles($value) && is_uploaded_file($value['tmp_name']); } - - /** - * Given $size and get the bytes - * - * @param string|int $size - * @return int - */ - protected function getBytes($size): int - { - if (is_int($size)) { - return $size; - } - - if (!is_string($size)) { - throw new InvalidArgumentException("Size must be string or integer Bytes", 1); - } - - if (!preg_match("/^(?((\d+)?\.)?\d+)(?(B|K|M|G|T|P)B?)?$/i", $size, $match)) { - throw new InvalidArgumentException("Size is not valid format", 1); - } - - $number = (float)$match['number']; - $format = isset($match['format']) ? $match['format'] : ''; - - switch (strtoupper($format)) { - case "KB": - case "K": - return $number * 1024; - - case "MB": - case "M": - return $number * pow(1024, 2); - - case "GB": - case "G": - return $number * pow(1024, 3); - - case "TB": - case "T": - return $number * pow(1024, 4); - - case "PB": - case "P": - return $number * pow(1024, 5); - - default: - return $number; - } - } } diff --git a/src/Rules/Traits/SizeTrait.php b/src/Rules/Traits/SizeTrait.php new file mode 100644 index 0000000..8d4fab9 --- /dev/null +++ b/src/Rules/Traits/SizeTrait.php @@ -0,0 +1,102 @@ +isUploadedFileValue($value)) { + return (float) $value['size']; + } elseif (is_array($value)) { + return (float) count($value); + } else { + return false; + } + } + + /** + * Given $size and get the bytes + * + * @param string|int $size + * @return float + * @throws InvalidArgumentException + */ + protected function getBytesSize($size) + { + if (is_numeric($size)) { + return (float) $size; + } + + if (!is_string($size)) { + throw new InvalidArgumentException("Size must be string or numeric Bytes", 1); + } + + if (!preg_match("/^(?((\d+)?\.)?\d+)(?(B|K|M|G|T|P)B?)?$/i", $size, $match)) { + throw new InvalidArgumentException("Size is not valid format", 1); + } + + $number = (float) $match['number']; + $format = isset($match['format']) ? $match['format'] : ''; + + switch (strtoupper($format)) { + case "KB": + case "K": + return $number * 1024; + + case "MB": + case "M": + return $number * pow(1024, 2); + + case "GB": + case "G": + return $number * pow(1024, 3); + + case "TB": + case "T": + return $number * pow(1024, 4); + + case "PB": + case "P": + return $number * pow(1024, 5); + + default: + return $number; + } + } + + /** + * Check whether value is from $_FILES + * + * @param mixed $value + * @return bool + */ + public function isUploadedFileValue($value): bool + { + if (!is_array($value)) { + return false; + } + + $keys = ['name', 'type', 'tmp_name', 'size', 'error']; + foreach ($keys as $key) { + if (!array_key_exists($key, $value)) { + return false; + } + } + + return true; + } +} diff --git a/src/Rules/UploadedFile.php b/src/Rules/UploadedFile.php index 2494154..dc2478c 100644 --- a/src/Rules/UploadedFile.php +++ b/src/Rules/UploadedFile.php @@ -7,7 +7,7 @@ class UploadedFile extends Rule { - use Traits\FileTrait; + use Traits\FileTrait, Traits\SizeTrait; /** @var string */ protected $message = "The :attribute is not valid"; @@ -119,14 +119,14 @@ public function check($value): bool } if ($minSize) { - $bytesMinSize = $this->getBytes($minSize); + $bytesMinSize = $this->getBytesSize($minSize); if ($value['size'] < $bytesMinSize) { return false; } } if ($maxSize) { - $bytesMaxSize = $this->getBytes($maxSize); + $bytesMaxSize = $this->getBytesSize($maxSize); if ($value['size'] > $bytesMaxSize) { return false; } diff --git a/tests/Rules/BetweenTest.php b/tests/Rules/BetweenTest.php index cbe2d1a..7bcf5f0 100644 --- a/tests/Rules/BetweenTest.php +++ b/tests/Rules/BetweenTest.php @@ -30,4 +30,29 @@ public function testInvalids() $this->assertFalse($this->rule->fillParameters([50, 100])->check(123)); $this->assertFalse($this->rule->fillParameters([50, 100])->check(123.4)); } + + public function testUploadedFileValue() + { + $mb = function ($n) { + return $n * 1024 * 1024; + }; + + $sampleFile = [ + 'name' => pathinfo(__FILE__, PATHINFO_BASENAME), + 'type' => 'text/plain', + 'size' => $mb(2), + 'tmp_name' => __FILE__, + 'error' => 0 + ]; + + $this->assertTrue($this->rule->fillParameters([$mb(2), $mb(5)])->check($sampleFile)); + $this->assertTrue($this->rule->fillParameters(['2M', '5M'])->check($sampleFile)); + $this->assertTrue($this->rule->fillParameters([$mb(1), $mb(2)])->check($sampleFile)); + $this->assertTrue($this->rule->fillParameters(['1M', '2M'])->check($sampleFile)); + + $this->assertFalse($this->rule->fillParameters([$mb(2.1), $mb(5)])->check($sampleFile)); + $this->assertFalse($this->rule->fillParameters(['2.1M', '5M'])->check($sampleFile)); + $this->assertFalse($this->rule->fillParameters([$mb(1), $mb(1.9)])->check($sampleFile)); + $this->assertFalse($this->rule->fillParameters(['1M', '1.9M'])->check($sampleFile)); + } } diff --git a/tests/Rules/MaxTest.php b/tests/Rules/MaxTest.php index 0ce0a2f..8c9087b 100644 --- a/tests/Rules/MaxTest.php +++ b/tests/Rules/MaxTest.php @@ -31,4 +31,22 @@ public function testInvalids() $this->assertFalse($this->rule->fillParameters([2])->check([1,2,3])); $this->assertFalse($this->rule->fillParameters([100])->check(123)); } + + public function testUploadedFileValue() + { + $twoMega = 1024 * 1024 * 2; + $sampleFile = [ + 'name' => pathinfo(__FILE__, PATHINFO_BASENAME), + 'type' => 'text/plain', + 'size' => $twoMega, + 'tmp_name' => __FILE__, + 'error' => 0 + ]; + + $this->assertTrue($this->rule->fillParameters([$twoMega])->check($sampleFile)); + $this->assertTrue($this->rule->fillParameters(['2M'])->check($sampleFile)); + + $this->assertFalse($this->rule->fillParameters([$twoMega - 1])->check($sampleFile)); + $this->assertFalse($this->rule->fillParameters(['1.9M'])->check($sampleFile)); + } } diff --git a/tests/Rules/MinTest.php b/tests/Rules/MinTest.php index e946261..98b8b99 100644 --- a/tests/Rules/MinTest.php +++ b/tests/Rules/MinTest.php @@ -31,4 +31,22 @@ public function testInvalids() $this->assertFalse($this->rule->fillParameters([4])->check('ワード')); $this->assertFalse($this->rule->fillParameters([2])->check('字')); } + + public function testUploadedFileValue() + { + $twoMega = 1024 * 1024 * 2; + $sampleFile = [ + 'name' => pathinfo(__FILE__, PATHINFO_BASENAME), + 'type' => 'text/plain', + 'size' => $twoMega, + 'tmp_name' => __FILE__, + 'error' => 0 + ]; + + $this->assertTrue($this->rule->fillParameters([$twoMega])->check($sampleFile)); + $this->assertTrue($this->rule->fillParameters(['2M'])->check($sampleFile)); + + $this->assertFalse($this->rule->fillParameters([$twoMega + 1])->check($sampleFile)); + $this->assertFalse($this->rule->fillParameters(['2.1M'])->check($sampleFile)); + } } diff --git a/tests/ValidatorTest.php b/tests/ValidatorTest.php index 9289bbb..5e1dff0 100644 --- a/tests/ValidatorTest.php +++ b/tests/ValidatorTest.php @@ -370,7 +370,8 @@ public function testInternalValidationRuleCanBeOverridden() { $this->validator->allowRuleOverride(true); - $this->validator->addValidator('required', new Required()); //This is a custom rule defined in the fixtures directory + //This is a custom rule defined in the fixtures directory + $this->validator->addValidator('required', new Required()); $data = ['s' => json_encode(['name' => 'space x', 'human' => false])];