Skip to content

Commit 97779a4

Browse files
committed
Change implementation 'default' rule, and support multiple file upload
1 parent aa1712c commit 97779a4

File tree

8 files changed

+420
-11
lines changed

8 files changed

+420
-11
lines changed

src/Rules/Defaults.php

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
namespace Rakit\Validation\Rules;
44

55
use Rakit\Validation\Rule;
6+
use Rakit\Validation\Rules\Interfaces\ModifyValue;
67

7-
class Defaults extends Rule
8+
class Defaults extends Rule implements ModifyValue
89
{
910

1011
/** @var string */
@@ -26,4 +27,24 @@ public function check($value): bool
2627
$default = $this->parameter('default');
2728
return true;
2829
}
30+
31+
/**
32+
* {@inheritDoc}
33+
*/
34+
public function modifyValue($value)
35+
{
36+
return $this->isEmptyValue($value) ? $this->parameter('default') : $value;
37+
}
38+
39+
/**
40+
* Check $value is empty value
41+
*
42+
* @param mixed $value
43+
* @return boolean
44+
*/
45+
protected function isEmptyValue($value): bool
46+
{
47+
$requiredValidator = new Required;
48+
return false === $requiredValidator->check($value, []);
49+
}
2950
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Rakit\Validation\Rules\Interfaces;
4+
5+
interface BeforeValidate
6+
{
7+
/**
8+
* Before validate hook
9+
*
10+
* @return void
11+
*/
12+
public function beforeValidate();
13+
}

src/Rules/Interfaces/ModifyValue.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace Rakit\Validation\Rules\Interfaces;
4+
5+
interface ModifyValue
6+
{
7+
/**
8+
* Modify given value
9+
* so in current and next rules returned value will be used
10+
*
11+
* @param mixed $value
12+
* @return mixed
13+
*/
14+
public function modifyValue($value);
15+
}

src/Rules/Traits/FileTrait.php

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Rakit\Validation\Rules\Traits;
44

55
use InvalidArgumentException;
6+
use Rakit\Validation\Helper;
67

78
trait FileTrait
89
{
@@ -39,4 +40,47 @@ public function isUploadedFile($value): bool
3940
{
4041
return $this->isValueFromUploadedFiles($value) && is_uploaded_file($value['tmp_name']);
4142
}
43+
44+
/**
45+
* Resolve uploaded file value
46+
*
47+
* @param mixed $value
48+
* @return array|null
49+
*/
50+
public function resolveUploadedFileValue($value)
51+
{
52+
if (!$this->isValueFromUploadedFiles($value)) {
53+
return null;
54+
}
55+
56+
// Here $value should be an array:
57+
// [
58+
// 'name' => string|array,
59+
// 'type' => string|array,
60+
// 'size' => int|array,
61+
// 'tmp_name' => string|array,
62+
// 'error' => string|array,
63+
// ]
64+
65+
// Flatten $value to it's array dot format,
66+
// so our array must be something like:
67+
// ['name' => string, 'type' => string, 'size' => int, ...]
68+
// or for multiple values:
69+
// ['name.0' => string, 'name.1' => string, 'type.0' => string, 'type.1' => string, ...]
70+
// or for nested array:
71+
// ['name.foo.bar' => string, 'name.foo.baz' => string, 'type.foo.bar' => string, 'type.foo.baz' => string, ...]
72+
$arrayDots = Helper::arrayDot($value);
73+
74+
$results = [];
75+
foreach ($arrayDots as $key => $val) {
76+
// Move first key to last key
77+
// name.foo.bar -> foo.bar.name
78+
$splits = explode(".", $key);
79+
$firstKey = array_shift($splits);
80+
$key = count($splits) ? implode(".", $splits) . ".{$firstKey}" : $firstKey;
81+
82+
Helper::arraySet($results, $key, $val);
83+
}
84+
return $results;
85+
}
4286
}

src/Rules/UploadedFile.php

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22

33
namespace Rakit\Validation\Rules;
44

5-
use Rakit\Validation\Rule;
5+
use Rakit\Validation\Helper;
66
use Rakit\Validation\MimeTypeGuesser;
7+
use Rakit\Validation\Rule;
8+
use Rakit\Validation\Rules\Interfaces\BeforeValidate;
79

8-
class UploadedFile extends Rule
10+
class UploadedFile extends Rule implements BeforeValidate
911
{
1012
use Traits\FileTrait, Traits\SizeTrait;
1113

@@ -92,6 +94,33 @@ public function fileTypes($types): Rule
9294
return $this;
9395
}
9496

97+
/**
98+
* {@inheritDoc}
99+
*/
100+
public function beforeValidate()
101+
{
102+
$attribute = $this->getAttribute();
103+
104+
// We only resolve uploaded file value
105+
// from complex attribute such as 'files.photo', 'images.*', 'images.foo.bar', etc.
106+
if (!$attribute->isUsingDotNotation()) {
107+
return;
108+
}
109+
110+
$keys = explode(".", $attribute->getKey());
111+
$firstKey = array_shift($keys);
112+
$firstKeyValue = $this->validation->getValue($firstKey);
113+
114+
$resolvedValue = $this->resolveUploadedFileValue($firstKeyValue);
115+
116+
// Return original value if $value can't be resolved as uploaded file value
117+
if (!$resolvedValue) {
118+
return;
119+
}
120+
121+
$this->validation->setValue($firstKey, $resolvedValue);
122+
}
123+
95124
/**
96125
* Check the $value is valid
97126
*

src/Validation.php

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
namespace Rakit\Validation;
44

5-
use Rakit\Validation\Rules\Required;
65
use Closure;
7-
use Rakit\Validation\Rules\Defaults;
6+
use Rakit\Validation\Rules\Interfaces\BeforeValidate;
7+
use Rakit\Validation\Rules\Interfaces\ModifyValue;
8+
use Rakit\Validation\Rules\Required;
89

910
class Validation
1011
{
@@ -92,6 +93,16 @@ public function validate(array $inputs = [])
9293
{
9394
$this->errors = new ErrorBag; // reset error bag
9495
$this->inputs = array_merge($this->inputs, $this->resolveInputAttributes($inputs));
96+
97+
// Before validation hooks
98+
foreach ($this->attributes as $attributeKey => $attribute) {
99+
foreach ($attribute->getRules() as $rule) {
100+
if ($rule instanceof BeforeValidate) {
101+
$rule->beforeValidate();
102+
}
103+
}
104+
}
105+
95106
foreach ($this->attributes as $attributeKey => $attribute) {
96107
$this->validateAttribute($attribute);
97108
}
@@ -133,10 +144,9 @@ protected function validateAttribute(Attribute $attribute)
133144
foreach ($rules as $ruleValidator) {
134145
$ruleValidator->setAttribute($attribute);
135146

136-
if ($isEmptyValue && $ruleValidator instanceof Defaults) {
137-
$value = $ruleValidator->parameter('default');
147+
if ($ruleValidator instanceof ModifyValue) {
148+
$value = $ruleValidator->modifyValue($value);
138149
$isEmptyValue = $this->isEmptyValue($value);
139-
continue;
140150
}
141151

142152
$valid = $ruleValidator->check($value);
@@ -600,6 +610,18 @@ public function getValue(string $key)
600610
return Helper::arrayGet($this->inputs, $key);
601611
}
602612

613+
/**
614+
* Set input value
615+
*
616+
* @param string $key
617+
* @param mixed $value
618+
* @return void
619+
*/
620+
public function setValue(string $key, $value)
621+
{
622+
Helper::arraySet($this->inputs, $key, $value);
623+
}
624+
603625
/**
604626
* Given $key and check value is exsited
605627
*

tests/Rules/UploadedFileTest.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,6 @@ public function testMinSize()
133133

134134
public function testFileTypes()
135135
{
136-
137136
$rule = $this->getMockBuilder(UploadedFile::class)
138137
->setMethods(['isUploadedFile'])
139138
->getMock();

0 commit comments

Comments
 (0)