Skip to content

Commit 15f382c

Browse files
authored
Merge pull request #13 from adelowo/rules
Updated the uploaded rule to make use of a built in function
2 parents 7a4d718 + 80af0ea commit 15f382c

File tree

5 files changed

+216
-84
lines changed

5 files changed

+216
-84
lines changed

src/Rules/FileTrait.php

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
namespace Rakit\Validation\Rules;
4+
5+
use InvalidArgumentException;
6+
7+
trait FileTrait
8+
{
9+
10+
/**
11+
* Check whether value is from $_FILES
12+
*
13+
* @param mixed $value
14+
*/
15+
public function isValueFromUploadedFiles($value)
16+
{
17+
if (!is_array($value)) return false;
18+
19+
$keys = ['name', 'type', 'tmp_name', 'size', 'error'];
20+
foreach($keys as $key) {
21+
if (!array_key_exists($key, $value)) return false;
22+
}
23+
24+
return true;
25+
}
26+
27+
public function isUploadedFile($value)
28+
{
29+
return $this->isValueFromUploadedFiles($value) AND is_uploaded_file($value['tmp_name']);
30+
}
31+
32+
protected function getBytes($size)
33+
{
34+
if (is_int($size)) {
35+
return $size;
36+
}
37+
38+
if (!is_string($size)) {
39+
throw new InvalidArgumentException("Size must be string or integer Bytes", 1);
40+
}
41+
42+
if (!preg_match("/^(?<number>((\d+)?\.)?\d+)(?<format>(B|K|M|G|T|P)B?)?$/i", $size, $match)) {
43+
throw new InvalidArgumentException("Size is not valid format", 1);
44+
}
45+
46+
$number = (float)$match['number'];
47+
$format = isset($match['format']) ? $match['format'] : '';
48+
49+
switch (strtoupper($format)) {
50+
case "KB":
51+
case "K":
52+
return $number * 1024;
53+
54+
case "MB":
55+
case "M":
56+
return $number * pow(1024, 2);
57+
58+
case "GB":
59+
case "G":
60+
return $number * pow(1024, 3);
61+
62+
case "TB":
63+
case "T":
64+
return $number * pow(1024, 4);
65+
66+
case "PB":
67+
case "P":
68+
return $number * pow(1024, 5);
69+
70+
default:
71+
return $number;
72+
}
73+
}
74+
}

src/Rules/Required.php

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

77
class Required extends Rule
88
{
9+
use FileTrait;
10+
911
protected $implicit = true;
1012

1113
protected $message = "The :attribute is required";
@@ -14,9 +16,10 @@ public function check($value)
1416
{
1517
$this->setAttributeAsRequired();
1618

17-
if (UploadedFile::isUploadedFile($value)) {
18-
return $value['error'] != UPLOAD_ERR_NO_FILE;
19+
if ($this->attribute AND $this->attribute->hasRule('uploaded_file')) {
20+
return $this->isValueFromUploadedFiles($value) AND $value['error'] != UPLOAD_ERR_NO_FILE;
1921
}
22+
2023
if (is_string($value)) return strlen(trim($value)) > 0;
2124
if (is_array($value)) return count($value) > 0;
2225
return !is_null($value);

src/Rules/UploadedFile.php

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

88
class UploadedFile extends Rule
99
{
10+
use FileTrait;
1011

1112
protected $message = "The :attribute is not valid";
1213

@@ -60,19 +61,16 @@ public function check($value)
6061
$maxSize = $this->parameter('max_size');
6162
$allowedTypes = $this->parameter('allowed_types');
6263

63-
if (is_null($value)) {
64+
// below is Required rule job
65+
if (!$this->isValueFromUploadedFiles($value) OR $value['error'] == UPLOAD_ERR_NO_FILE) {
6466
return true;
6567
}
6668

67-
if (!static::isUploadedFile($value)) {
69+
if (!$this->isUploadedFile($value)) {
6870
return false;
6971
}
7072

71-
// we validate this in Required rule
72-
if ($value['error'] == UPLOAD_ERR_NO_FILE) {
73-
return true;
74-
}
75-
73+
// just make sure there is no error
7674
if ($value['error']) return false;
7775

7876
if ($minSize) {
@@ -101,52 +99,4 @@ public function check($value)
10199

102100
return true;
103101
}
104-
105-
public static function isUploadedFile($value)
106-
{
107-
if(!is_array($value)) return false;
108-
109-
$requiredKeys = ['name', 'type', 'tmp_name', 'size', 'error'];
110-
foreach($requiredKeys as $key) {
111-
if(!isset($value[$key])) return false;
112-
}
113-
114-
return $value;
115-
}
116-
117-
protected function getBytes($size)
118-
{
119-
if (is_int($size)) return $size;
120-
if (!is_string($size)) {
121-
throw new \InvalidArgumentException("Size must be string or integer Bytes", 1);
122-
}
123-
124-
if(!preg_match("/^(?<number>((\d+)?\.)?\d+)(?<format>(B|K|M|G|T|P)B?)?$/i", $size, $match)) {
125-
throw new \InvalidArgumentException("Size is not valid format", 1);
126-
}
127-
128-
$number = (float) $match['number'];
129-
$format = isset($match['format'])? $match['format'] : '';
130-
131-
switch (strtoupper($format)) {
132-
case "KB":
133-
case "K":
134-
return $number*1024;
135-
case "MB":
136-
case "M":
137-
return $number*pow(1024,2);
138-
case "GB":
139-
case "G":
140-
return $number*pow(1024,3);
141-
case "TB":
142-
case "T":
143-
return $number*pow(1024,4);
144-
case "PB":
145-
case "P":
146-
return $number*pow(1024,5);
147-
default:
148-
return $number;
149-
}
150-
}
151-
152102
}

tests/Rules/UploadedFileTest.php

Lines changed: 74 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,48 @@ class UploadedFileTest extends PHPUnit_Framework_TestCase
77

88
public function setUp()
99
{
10-
$this->rule = new UploadedFile;
10+
$this->rule = new UploadedFile();
1111
}
1212

1313
public function testValidUploadedFile()
1414
{
15-
$this->assertTrue($this->rule->check([
15+
$file = [
1616
'name' => pathinfo(__FILE__, PATHINFO_BASENAME),
1717
'type' => 'text/plain',
1818
'size' => filesize(__FILE__),
1919
'tmp_name' => __FILE__,
20-
'error' => 0
20+
'error' => UPLOAD_ERR_OK
21+
];
22+
23+
$uploadedFileRule = $this->getMockBuilder(UploadedFile::class)
24+
->setMethods(['isUploadedFile'])
25+
->getMock();
26+
27+
$uploadedFileRule->expects($this->once())
28+
->method('isUploadedFile')
29+
->willReturn(true);
30+
31+
$this->assertTrue($uploadedFileRule->check($file));
32+
}
33+
34+
/**
35+
* Make sure we can't just passing array like valid $_FILES['key']
36+
*/
37+
public function testValidateWithoutMockShouldBeInvalid()
38+
{
39+
$this->assertFalse($this->rule->check([
40+
'name' => pathinfo(__FILE__, PATHINFO_BASENAME),
41+
'type' => 'text/plain',
42+
'size' => filesize(__FILE__),
43+
'tmp_name' => __FILE__,
44+
'error' => UPLOAD_ERR_OK
2145
]));
2246
}
2347

24-
public function testNoUploadedFile()
48+
/**
49+
* Missing UPLOAD_ERR_NO_FILE should be valid because it is job for required rule
50+
*/
51+
public function testEmptyUploadedFileShouldBeValid()
2552
{
2653
$this->assertTrue($this->rule->check([
2754
'name' => '',
@@ -45,13 +72,20 @@ public function testUploadError()
4572

4673
public function testMaxSize()
4774
{
48-
$rule = new UploadedFile;
49-
$rule->maxSize('1M');
75+
$rule = $this->getMockBuilder(UploadedFile::class)
76+
->setMethods(['isUploadedFile'])
77+
->getMock();
78+
79+
$rule->expects($this->exactly(2))
80+
->method('isUploadedFile')
81+
->willReturn(true);
82+
83+
$rule->maxSize("1MB");
5084

5185
$this->assertFalse($rule->check([
5286
'name' => pathinfo(__FILE__, PATHINFO_BASENAME),
5387
'type' => 'text/plain',
54-
'size' => 1024*1024*1.1,
88+
'size' => 1024 * 1024 * 1.1,
5589
'tmp_name' => __FILE__,
5690
'error' => 0
5791
]));
@@ -67,7 +101,14 @@ public function testMaxSize()
67101

68102
public function testMinSize()
69103
{
70-
$rule = new UploadedFile;
104+
$rule = $this->getMockBuilder(UploadedFile::class)
105+
->setMethods(['isUploadedFile'])
106+
->getMock();
107+
108+
$rule->expects($this->exactly(2))
109+
->method('isUploadedFile')
110+
->willReturn(true);
111+
71112
$rule->minSize('10K');
72113

73114
$this->assertFalse($rule->check([
@@ -81,16 +122,23 @@ public function testMinSize()
81122
$this->assertTrue($rule->check([
82123
'name' => pathinfo(__FILE__, PATHINFO_BASENAME),
83124
'type' => 'text/plain',
84-
'size' => 10*1024,
125+
'size' => 10 * 1024,
85126
'tmp_name' => __FILE__,
86127
'error' => 0
87128
]));
88129
}
89130

90-
91131
public function testFileTypes()
92132
{
93-
$rule = new UploadedFile;
133+
134+
$rule = $this->getMockBuilder(UploadedFile::class)
135+
->setMethods(['isUploadedFile'])
136+
->getMock();
137+
138+
$rule->expects($this->exactly(3))
139+
->method('isUploadedFile')
140+
->willReturn(true);
141+
94142
$rule->fileTypes('png|jpeg');
95143

96144
$this->assertFalse($rule->check([
@@ -104,48 +152,55 @@ public function testFileTypes()
104152
$this->assertTrue($rule->check([
105153
'name' => pathinfo(__FILE__, PATHINFO_BASENAME),
106154
'type' => 'image/png',
107-
'size' => 10*1024,
155+
'size' => 10 * 1024,
108156
'tmp_name' => __FILE__,
109157
'error' => 0
110158
]));
111159

112160
$this->assertTrue($rule->check([
113161
'name' => pathinfo(__FILE__, PATHINFO_BASENAME),
114162
'type' => 'image/jpeg',
115-
'size' => 10*1024,
163+
'size' => 10 * 1024,
116164
'tmp_name' => __FILE__,
117165
'error' => 0
118166
]));
119167
}
120168

121-
public function testInvalids()
169+
/**
170+
* Missing array key(s) should be valid because it is job for required rule
171+
*/
172+
public function testMissingAKeyShouldBeValid()
122173
{
123-
$this->assertFalse($this->rule->check([
174+
// missing name
175+
$this->assertTrue($this->rule->check([
124176
'type' => 'text/plain',
125177
'size' => filesize(__FILE__),
126178
'tmp_name' => __FILE__,
127179
'error' => 0
128180
]));
129181

130-
$this->assertFalse($this->rule->check([
182+
// missing type
183+
$this->assertTrue($this->rule->check([
131184
'name' => pathinfo(__FILE__, PATHINFO_BASENAME),
132185
'size' => filesize(__FILE__),
133186
'tmp_name' => __FILE__,
134187
'error' => 0
135188
]));
136189

137-
$this->assertFalse($this->rule->check([
190+
// missing size
191+
$this->assertTrue($this->rule->check([
138192
'name' => pathinfo(__FILE__, PATHINFO_BASENAME),
139193
'type' => 'text/plain',
140194
'tmp_name' => __FILE__,
141195
'error' => 0
142196
]));
143197

144-
$this->assertFalse($this->rule->check([
198+
// missing tmp_name
199+
$this->assertTrue($this->rule->check([
145200
'name' => pathinfo(__FILE__, PATHINFO_BASENAME),
146201
'type' => 'text/plain',
147202
'size' => filesize(__FILE__),
203+
'error' => 0
148204
]));
149205
}
150-
151206
}

0 commit comments

Comments
 (0)