Skip to content

Commit

Permalink
Min, max, and between rules are able to validate uploaded file value
Browse files Browse the repository at this point in the history
  • Loading branch information
emsifa committed Nov 24, 2018
1 parent 9e1f8e6 commit ae3a47b
Show file tree
Hide file tree
Showing 10 changed files with 190 additions and 78 deletions.
17 changes: 8 additions & 9 deletions src/Rules/Between.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

class Between extends Rule
{
use Traits\SizeTrait;

/** @var string */
protected $message = "The :attribute must be between :min and :max";
Expand All @@ -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);
}
}
15 changes: 7 additions & 8 deletions src/Rules/Max.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

class Max extends Rule
{
use Traits\SizeTrait;

/** @var string */
protected $message = "The :attribute maximum is :max";
Expand All @@ -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;
}
}
15 changes: 7 additions & 8 deletions src/Rules/Min.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

class Min extends Rule
{
use Traits\SizeTrait;

/** @var string */
protected $message = "The :attribute minimum is :min";
Expand All @@ -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;
}
}
49 changes: 0 additions & 49 deletions src/Rules/Traits/FileTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -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("/^(?<number>((\d+)?\.)?\d+)(?<format>(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;
}
}
}
102 changes: 102 additions & 0 deletions src/Rules/Traits/SizeTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php

namespace Rakit\Validation\Rules\Traits;

use InvalidArgumentException;

trait SizeTrait
{

/**
* Get size (int) value from given $value
*
* @param int|string $value
* @return float|false
*/
protected function getValueSize($value)
{
if (is_int($value) || is_float($value)) {
return (float) $value;
} elseif (is_string($value)) {
return (float) mb_strlen($value, 'UTF-8');
} elseif ($this->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("/^(?<number>((\d+)?\.)?\d+)(?<format>(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;
}
}
6 changes: 3 additions & 3 deletions src/Rules/UploadedFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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;
}
Expand Down
25 changes: 25 additions & 0 deletions tests/Rules/BetweenTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
}
18 changes: 18 additions & 0 deletions tests/Rules/MaxTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
}
18 changes: 18 additions & 0 deletions tests/Rules/MinTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
}
3 changes: 2 additions & 1 deletion tests/ValidatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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])];

Expand Down

0 comments on commit ae3a47b

Please sign in to comment.