diff --git a/src/Helper.php b/src/Helper.php index 06e0ada..8a7da25 100644 --- a/src/Helper.php +++ b/src/Helper.php @@ -84,6 +84,31 @@ public static function arrayGet(array $array, $key, $default = null) return $array; } + /** + * + * @param array $array + * @param string|null $key + * @return mixed + */ + public static function arrayIsset(array $array, $key) + { + if (is_null($key)) { + return false; + } + + if (array_key_exists($key, $array)) { + return true; + } + + foreach (explode('.', $key) as $segment) { + if (is_array($array) && array_key_exists($segment, $array)) { + return true; + } + } + + return false; + } + /** * Flatten a multi-dimensional associative array with dots. * Adapted from: https://github.com/illuminate/support/blob/v5.3.23/Arr.php#L81 diff --git a/src/Rules/Same.php b/src/Rules/Same.php index b127b55..eda613c 100644 --- a/src/Rules/Same.php +++ b/src/Rules/Same.php @@ -8,7 +8,7 @@ class Same extends Rule { /** @var string */ - protected $message = "The :attribute must be same with :field"; + protected $message = "The :attribute must be same as :field"; /** @var array */ protected $fillableParams = ['field']; diff --git a/src/Validation.php b/src/Validation.php index d74786a..386737b 100644 --- a/src/Validation.php +++ b/src/Validation.php @@ -138,6 +138,8 @@ protected function validateAttribute(Attribute $attribute) $attributeKey = $attribute->getKey(); $rules = $attribute->getRules(); + $inputIsset = $this->inputIsset($attributeKey); + $value = $this->getValue($attributeKey); $isEmptyValue = $this->isEmptyValue($value); @@ -169,9 +171,9 @@ protected function validateAttribute(Attribute $attribute) } } - if ($isValid) { + if ($isValid && ($value!==null || $inputIsset)) { $this->setValidData($attribute, $value); - } else { + } else if (!$isValid) { $this->setInvalidData($attribute, $value); } } @@ -592,6 +594,17 @@ public function getValue(string $key) return Helper::arrayGet($this->inputs, $key); } + /** + * Given $key and get value + * + * @param string $key + * @return mixed + */ + public function inputIsset(string $key):bool + { + return Helper::arrayIsset($this->inputs, $key); + } + /** * Set input value * @@ -686,6 +699,21 @@ public function getValidData(): array return $this->validData; } + + /** + * Get valid data or throw exepction + * + * @throws \Rakit\Validation\ValidationException + * @return array + */ + public function validated(): array + { + if ($this->fails()) { + throw new ValidationException($this); + } + return $this->getValidData(); + } + /** * Set invalid data * diff --git a/src/ValidationException.php b/src/ValidationException.php new file mode 100644 index 0000000..1b7e272 --- /dev/null +++ b/src/ValidationException.php @@ -0,0 +1,84 @@ +validation = $validation; + } + + /** + * Create an error message summary from the validation errors. + * + * @param Validation $validation + * @return string + */ + protected static function summarize($validation) + { + $messages = $validation->errors()->all(); + + if (! count($messages) || ! is_string($messages[0])) { + return 'The given data was invalid.'; + } + + $message = array_shift($messages); + + if ($count = $validation->errors()->count()) { + $pluralized = $count === 1 ? 'error' : 'errors'; + + $message .= ' '."and $count more $pluralized"; + } + + return $message; + } + + /** + * Get all the validation error messages. + * + * @return array + */ + public function getErrors():array + { + return $this->validation->errors()->toArray(); + } + + /** + * Set the HTTP status code to be used for the response. + * + * @param int $status + * @return $this + */ + public function status($status) + { + $this->status = $status; + + return $this; + } + +} diff --git a/tests/ValidatorTest.php b/tests/ValidatorTest.php index a17a123..8ac314e 100644 --- a/tests/ValidatorTest.php +++ b/tests/ValidatorTest.php @@ -6,6 +6,7 @@ use PHPUnit\Framework\TestCase; use Rakit\Validation\Rule; use Rakit\Validation\Rules\UploadedFile; +use Rakit\Validation\ValidationException; use Rakit\Validation\Validator; class ValidatorTest extends TestCase @@ -1282,6 +1283,7 @@ public function testGetValidData() 'thing' => 'exists', ], [ 'thing' => 'required', + 'name' => 'alpha', 'items.*.product_id' => 'required|numeric', 'emails.*' => 'required|email', 'items.*.qty' => 'required|numeric', @@ -1370,6 +1372,85 @@ public function testGetInvalidData() $this->assertFalse(isset($stuffs['two'])); } + public function testValidated() + { + $validation = $this->validator->validate([ + 'emails' => [ + 'foo@bar.com', + 'foo@blah.com' + ], + 'thing' => 'exists', + ], [ + 'thing' => 'required', + 'emails.*' => 'required|email', + ]); + + $validData = $validation->validated(); + + $this->assertEquals([ + 'emails' => [ + 0 => 'foo@bar.com', + 1 => 'foo@blah.com' + ], + 'thing' => 'exists', + ], $validData); + } + + public function testValidatedException() + { + $this->expectException(ValidationException::class); + $validation = $this->validator->validate([ + 'items' => [ + [ + 'product_id' => 1, + 'qty' => 'invalid' + ] + ], + 'emails' => [ + 'foo@bar.com', + 'something', + 'foo@blah.com' + ], + 'stuffs' => [ + 'one' => '1', + 'two' => '2', + 'three' => 'three', + ], + 'thing' => 'exists', + ], [ + 'thing' => 'required', + 'items.*.product_id' => 'required|numeric', + 'emails.*' => 'required|email', + 'items.*.qty' => 'required|numeric', + 'something' => 'required|in:on,off', + 'stuffs' => 'required|array', + 'stuffs.one' => 'numeric', + 'stuffs.two' => 'numeric', + 'stuffs.three' => 'numeric', + ]); + $validation->validated(); + } + + public function testValidatedExceptionData() + { + try { + $validation = $this->validator->validate([ + ], [ + 'thing' => 'required' + ]); + $validation->validated(); + } catch (ValidationException $e) { + $this->assertSame( + [ + 'thing' => [ + 'required'=> 'The Thing is required' + ] + ], + $e->getErrors() + ); + } + } + public function testRuleInInvalidMessages() { $validation = $this->validator->validate([