Skip to content

Commit ae3a47b

Browse files
committed
Min, max, and between rules are able to validate uploaded file value
1 parent 9e1f8e6 commit ae3a47b

File tree

10 files changed

+190
-78
lines changed

10 files changed

+190
-78
lines changed

src/Rules/Between.php

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
class Between extends Rule
88
{
9+
use Traits\SizeTrait;
910

1011
/** @var string */
1112
protected $message = "The :attribute must be between :min and :max";
@@ -23,17 +24,15 @@ public function check($value): bool
2324
{
2425
$this->requireParameters($this->fillableParams);
2526

26-
$min = (int) $this->parameter('min');
27-
$max = (int) $this->parameter('max');
27+
$min = $this->getBytesSize($this->parameter('min'));
28+
$max = $this->getBytesSize($this->parameter('max'));
2829

29-
if (is_int($value) || is_float($value)) {
30-
return $value >= $min and $value <= $max;
31-
} elseif (is_string($value)) {
32-
return mb_strlen($value, 'UTF-8') >= $min and mb_strlen($value, 'UTF-8') <= $max;
33-
} elseif (is_array($value)) {
34-
return count($value) >= $min and count($value) <= $max;
35-
} else {
30+
$valueSize = $this->getValueSize($value);
31+
32+
if (!is_numeric($valueSize)) {
3633
return false;
3734
}
35+
36+
return ($valueSize >= $min && $valueSize <= $max);
3837
}
3938
}

src/Rules/Max.php

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
class Max extends Rule
88
{
9+
use Traits\SizeTrait;
910

1011
/** @var string */
1112
protected $message = "The :attribute maximum is :max";
@@ -23,15 +24,13 @@ public function check($value): bool
2324
{
2425
$this->requireParameters($this->fillableParams);
2526

26-
$max = (int) $this->parameter('max');
27-
if (is_int($value)) {
28-
return $value <= $max;
29-
} elseif (is_string($value)) {
30-
return mb_strlen($value, 'UTF-8') <= $max;
31-
} elseif (is_array($value)) {
32-
return count($value) <= $max;
33-
} else {
27+
$max = $this->getBytesSize($this->parameter('max'));
28+
$valueSize = $this->getValueSize($value);
29+
30+
if (!is_numeric($valueSize)) {
3431
return false;
3532
}
33+
34+
return $valueSize <= $max;
3635
}
3736
}

src/Rules/Min.php

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
class Min extends Rule
88
{
9+
use Traits\SizeTrait;
910

1011
/** @var string */
1112
protected $message = "The :attribute minimum is :min";
@@ -23,15 +24,13 @@ public function check($value): bool
2324
{
2425
$this->requireParameters($this->fillableParams);
2526

26-
$min = (int) $this->parameter('min');
27-
if (is_int($value)) {
28-
return $value >= $min;
29-
} elseif (is_string($value)) {
30-
return mb_strlen($value, 'UTF-8') >= $min;
31-
} elseif (is_array($value)) {
32-
return count($value) >= $min;
33-
} else {
27+
$min = $this->getBytesSize($this->parameter('min'));
28+
$valueSize = $this->getValueSize($value);
29+
30+
if (!is_numeric($valueSize)) {
3431
return false;
3532
}
33+
34+
return $valueSize >= $min;
3635
}
3736
}

src/Rules/Traits/FileTrait.php

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -39,53 +39,4 @@ public function isUploadedFile($value): bool
3939
{
4040
return $this->isValueFromUploadedFiles($value) && is_uploaded_file($value['tmp_name']);
4141
}
42-
43-
/**
44-
* Given $size and get the bytes
45-
*
46-
* @param string|int $size
47-
* @return int
48-
*/
49-
protected function getBytes($size): int
50-
{
51-
if (is_int($size)) {
52-
return $size;
53-
}
54-
55-
if (!is_string($size)) {
56-
throw new InvalidArgumentException("Size must be string or integer Bytes", 1);
57-
}
58-
59-
if (!preg_match("/^(?<number>((\d+)?\.)?\d+)(?<format>(B|K|M|G|T|P)B?)?$/i", $size, $match)) {
60-
throw new InvalidArgumentException("Size is not valid format", 1);
61-
}
62-
63-
$number = (float)$match['number'];
64-
$format = isset($match['format']) ? $match['format'] : '';
65-
66-
switch (strtoupper($format)) {
67-
case "KB":
68-
case "K":
69-
return $number * 1024;
70-
71-
case "MB":
72-
case "M":
73-
return $number * pow(1024, 2);
74-
75-
case "GB":
76-
case "G":
77-
return $number * pow(1024, 3);
78-
79-
case "TB":
80-
case "T":
81-
return $number * pow(1024, 4);
82-
83-
case "PB":
84-
case "P":
85-
return $number * pow(1024, 5);
86-
87-
default:
88-
return $number;
89-
}
90-
}
9142
}

src/Rules/Traits/SizeTrait.php

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<?php
2+
3+
namespace Rakit\Validation\Rules\Traits;
4+
5+
use InvalidArgumentException;
6+
7+
trait SizeTrait
8+
{
9+
10+
/**
11+
* Get size (int) value from given $value
12+
*
13+
* @param int|string $value
14+
* @return float|false
15+
*/
16+
protected function getValueSize($value)
17+
{
18+
if (is_int($value) || is_float($value)) {
19+
return (float) $value;
20+
} elseif (is_string($value)) {
21+
return (float) mb_strlen($value, 'UTF-8');
22+
} elseif ($this->isUploadedFileValue($value)) {
23+
return (float) $value['size'];
24+
} elseif (is_array($value)) {
25+
return (float) count($value);
26+
} else {
27+
return false;
28+
}
29+
}
30+
31+
/**
32+
* Given $size and get the bytes
33+
*
34+
* @param string|int $size
35+
* @return float
36+
* @throws InvalidArgumentException
37+
*/
38+
protected function getBytesSize($size)
39+
{
40+
if (is_numeric($size)) {
41+
return (float) $size;
42+
}
43+
44+
if (!is_string($size)) {
45+
throw new InvalidArgumentException("Size must be string or numeric Bytes", 1);
46+
}
47+
48+
if (!preg_match("/^(?<number>((\d+)?\.)?\d+)(?<format>(B|K|M|G|T|P)B?)?$/i", $size, $match)) {
49+
throw new InvalidArgumentException("Size is not valid format", 1);
50+
}
51+
52+
$number = (float) $match['number'];
53+
$format = isset($match['format']) ? $match['format'] : '';
54+
55+
switch (strtoupper($format)) {
56+
case "KB":
57+
case "K":
58+
return $number * 1024;
59+
60+
case "MB":
61+
case "M":
62+
return $number * pow(1024, 2);
63+
64+
case "GB":
65+
case "G":
66+
return $number * pow(1024, 3);
67+
68+
case "TB":
69+
case "T":
70+
return $number * pow(1024, 4);
71+
72+
case "PB":
73+
case "P":
74+
return $number * pow(1024, 5);
75+
76+
default:
77+
return $number;
78+
}
79+
}
80+
81+
/**
82+
* Check whether value is from $_FILES
83+
*
84+
* @param mixed $value
85+
* @return bool
86+
*/
87+
public function isUploadedFileValue($value): bool
88+
{
89+
if (!is_array($value)) {
90+
return false;
91+
}
92+
93+
$keys = ['name', 'type', 'tmp_name', 'size', 'error'];
94+
foreach ($keys as $key) {
95+
if (!array_key_exists($key, $value)) {
96+
return false;
97+
}
98+
}
99+
100+
return true;
101+
}
102+
}

src/Rules/UploadedFile.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
class UploadedFile extends Rule
99
{
10-
use Traits\FileTrait;
10+
use Traits\FileTrait, Traits\SizeTrait;
1111

1212
/** @var string */
1313
protected $message = "The :attribute is not valid";
@@ -119,14 +119,14 @@ public function check($value): bool
119119
}
120120

121121
if ($minSize) {
122-
$bytesMinSize = $this->getBytes($minSize);
122+
$bytesMinSize = $this->getBytesSize($minSize);
123123
if ($value['size'] < $bytesMinSize) {
124124
return false;
125125
}
126126
}
127127

128128
if ($maxSize) {
129-
$bytesMaxSize = $this->getBytes($maxSize);
129+
$bytesMaxSize = $this->getBytesSize($maxSize);
130130
if ($value['size'] > $bytesMaxSize) {
131131
return false;
132132
}

tests/Rules/BetweenTest.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,29 @@ public function testInvalids()
3030
$this->assertFalse($this->rule->fillParameters([50, 100])->check(123));
3131
$this->assertFalse($this->rule->fillParameters([50, 100])->check(123.4));
3232
}
33+
34+
public function testUploadedFileValue()
35+
{
36+
$mb = function ($n) {
37+
return $n * 1024 * 1024;
38+
};
39+
40+
$sampleFile = [
41+
'name' => pathinfo(__FILE__, PATHINFO_BASENAME),
42+
'type' => 'text/plain',
43+
'size' => $mb(2),
44+
'tmp_name' => __FILE__,
45+
'error' => 0
46+
];
47+
48+
$this->assertTrue($this->rule->fillParameters([$mb(2), $mb(5)])->check($sampleFile));
49+
$this->assertTrue($this->rule->fillParameters(['2M', '5M'])->check($sampleFile));
50+
$this->assertTrue($this->rule->fillParameters([$mb(1), $mb(2)])->check($sampleFile));
51+
$this->assertTrue($this->rule->fillParameters(['1M', '2M'])->check($sampleFile));
52+
53+
$this->assertFalse($this->rule->fillParameters([$mb(2.1), $mb(5)])->check($sampleFile));
54+
$this->assertFalse($this->rule->fillParameters(['2.1M', '5M'])->check($sampleFile));
55+
$this->assertFalse($this->rule->fillParameters([$mb(1), $mb(1.9)])->check($sampleFile));
56+
$this->assertFalse($this->rule->fillParameters(['1M', '1.9M'])->check($sampleFile));
57+
}
3358
}

tests/Rules/MaxTest.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,22 @@ public function testInvalids()
3131
$this->assertFalse($this->rule->fillParameters([2])->check([1,2,3]));
3232
$this->assertFalse($this->rule->fillParameters([100])->check(123));
3333
}
34+
35+
public function testUploadedFileValue()
36+
{
37+
$twoMega = 1024 * 1024 * 2;
38+
$sampleFile = [
39+
'name' => pathinfo(__FILE__, PATHINFO_BASENAME),
40+
'type' => 'text/plain',
41+
'size' => $twoMega,
42+
'tmp_name' => __FILE__,
43+
'error' => 0
44+
];
45+
46+
$this->assertTrue($this->rule->fillParameters([$twoMega])->check($sampleFile));
47+
$this->assertTrue($this->rule->fillParameters(['2M'])->check($sampleFile));
48+
49+
$this->assertFalse($this->rule->fillParameters([$twoMega - 1])->check($sampleFile));
50+
$this->assertFalse($this->rule->fillParameters(['1.9M'])->check($sampleFile));
51+
}
3452
}

tests/Rules/MinTest.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,22 @@ public function testInvalids()
3131
$this->assertFalse($this->rule->fillParameters([4])->check('ワード'));
3232
$this->assertFalse($this->rule->fillParameters([2])->check(''));
3333
}
34+
35+
public function testUploadedFileValue()
36+
{
37+
$twoMega = 1024 * 1024 * 2;
38+
$sampleFile = [
39+
'name' => pathinfo(__FILE__, PATHINFO_BASENAME),
40+
'type' => 'text/plain',
41+
'size' => $twoMega,
42+
'tmp_name' => __FILE__,
43+
'error' => 0
44+
];
45+
46+
$this->assertTrue($this->rule->fillParameters([$twoMega])->check($sampleFile));
47+
$this->assertTrue($this->rule->fillParameters(['2M'])->check($sampleFile));
48+
49+
$this->assertFalse($this->rule->fillParameters([$twoMega + 1])->check($sampleFile));
50+
$this->assertFalse($this->rule->fillParameters(['2.1M'])->check($sampleFile));
51+
}
3452
}

tests/ValidatorTest.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,8 @@ public function testInternalValidationRuleCanBeOverridden()
370370
{
371371
$this->validator->allowRuleOverride(true);
372372

373-
$this->validator->addValidator('required', new Required()); //This is a custom rule defined in the fixtures directory
373+
//This is a custom rule defined in the fixtures directory
374+
$this->validator->addValidator('required', new Required());
374375

375376
$data = ['s' => json_encode(['name' => 'space x', 'human' => false])];
376377

0 commit comments

Comments
 (0)