Skip to content

Commit 74bf9b8

Browse files
committed
Move required into validation interface.
This provides better handling of dependent validators.
1 parent 6bb3d70 commit 74bf9b8

21 files changed

+386
-359
lines changed

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ A common scenario would be to decode received input for a resource object and th
1919
attributes within a controller. For example:
2020

2121
``` php
22+
<?php
23+
2224
class ArticleController
2325
{
2426

@@ -46,6 +48,7 @@ The above example can be refactored to use validators to parse the provided cont
4648
controller:
4749

4850
``` php
51+
<?php
4952

5053
use CloudCreativity\JsonApi\Validator\Resource\ResourceObjectValidator;
5154
use CloudCreativity\JsonApi\Validator\Document\DocumentValidator;
@@ -61,8 +64,9 @@ class ArticleController
6164
$validator->type('article')
6265
->attr('title', 'string')
6366
->attr('content', 'string')
64-
->belongsTo('author', 'person')
65-
->required(['author']);
67+
->belongsTo('author', 'person', [
68+
'required' => true,
69+
]);
6670

6771
return $validator;
6872
}
@@ -88,6 +92,10 @@ In this refactored controller, `$data` can be used knowing that it has passed va
8892
been cast to an instance of `CloudCreativity\JsonApi\Object\Document\Document`, providing a fluid interface for
8993
handling the input within the controller.
9094

95+
If the provided input did not pass validation, then the decoder throws a
96+
`CloudCreativity\JsonApi\Error\MultiErrorException` which contains the JSON API error messages indicating what is
97+
invalid, including JSON pointers to the source of the validation error.
98+
9199
## Status
92100

93101
This repository is under active development and is currently in a pre-release state.

src/Contracts/Validator/KeyedValidatorInterface.php

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
* Interface KeyedValidatorInterface
2323
* @package CloudCreativity\JsonApi
2424
*/
25-
interface KeyedValidatorInterface extends ValidatorInterface
25+
interface KeyedValidatorInterface extends ValidatorInterface, \IteratorAggregate
2626
{
2727

2828
/**
@@ -32,18 +32,6 @@ interface KeyedValidatorInterface extends ValidatorInterface
3232
*/
3333
public function setValidator($key, ValidatorInterface $validator);
3434

35-
/**
36-
* @param $keyOrKeys
37-
* @return $this
38-
*/
39-
public function setRequiredKeys($keyOrKeys);
40-
41-
/**
42-
* @param $keyOrKeys
43-
* @return $this
44-
*/
45-
public function addRequiredKeys($keyOrKeys);
46-
4735
/**
4836
* @param $key
4937
* @return ValidatorInterface
@@ -63,17 +51,6 @@ public function hasValidator($key);
6351
*/
6452
public function keys();
6553

66-
/**
67-
* @param $key
68-
* @return bool
69-
*/
70-
public function isRequiredKey($key);
71-
72-
/**
73-
* @return bool
74-
*/
75-
public function hasRequiredKeys();
76-
7754
/**
7855
* @param $keyOrKeys
7956
* @return $this
@@ -90,4 +67,4 @@ public function addAllowedKeys($keyOrKeys);
9067
* @return bool
9168
*/
9269
public function isAllowedKey($key);
93-
}
70+
}

src/Contracts/Validator/ValidatorInterface.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,14 @@ interface ValidatorInterface extends ErrorsAwareInterface
3232
* @return bool
3333
*/
3434
public function isValid($value);
35-
}
35+
36+
/**
37+
* Whether a value must be provided for validation.
38+
*
39+
* If the validator is being used as a dependent validator, then the parent validator can use this method to detect
40+
* if there must be a provided value to pass to the dependent validator.
41+
*
42+
* @return bool
43+
*/
44+
public function isRequired();
45+
}
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
<?php
2+
3+
/**
4+
* Copyright 2015 Cloud Creativity Limited
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
namespace CloudCreativity\JsonApi\Validator;
20+
21+
use CloudCreativity\JsonApi\Contracts\Validator\KeyedValidatorInterface;
22+
use CloudCreativity\JsonApi\Contracts\Validator\ValidatorInterface;
23+
use CloudCreativity\JsonApi\Validator\Helper\AllowedKeysTrait;
24+
25+
/**
26+
* Class AbstractKeyedValidator
27+
* @package CloudCreativity\JsonApi
28+
*/
29+
abstract class AbstractKeyedValidator extends AbstractValidator implements KeyedValidatorInterface
30+
{
31+
32+
use AllowedKeysTrait;
33+
34+
const ERROR_REQUIRED = 'required';
35+
36+
/**
37+
* Validators for use with keys within the attributes.
38+
*
39+
* @var array
40+
*/
41+
protected $_validators = [];
42+
43+
/**
44+
* @param $key
45+
* @param ValidatorInterface $validator
46+
* @return $this
47+
*/
48+
public function setValidator($key, ValidatorInterface $validator)
49+
{
50+
$this->_validators[$key] = $validator;
51+
52+
return $this;
53+
}
54+
55+
/**
56+
* @param ValidatorInterface[] $validators
57+
* @return $this
58+
*/
59+
public function setValidators(array $validators)
60+
{
61+
foreach ($validators as $key => $validator) {
62+
63+
if (!$validator instanceof ValidatorInterface) {
64+
throw new \InvalidArgumentException('Expecting only ValidatorInterface instances.');
65+
}
66+
67+
$this->setValidator($key, $validator);
68+
}
69+
70+
return $this;
71+
}
72+
73+
/**
74+
* @param $key
75+
* @return ValidatorInterface
76+
*/
77+
public function getValidator($key)
78+
{
79+
if (!isset($this->_validators[$key])) {
80+
throw new \RuntimeException(sprintf('No validator for key "%s".', $key));
81+
}
82+
83+
return $this->_validators[$key];
84+
}
85+
86+
/**
87+
* @return ValidatorInterface[]
88+
*/
89+
public function getValidators()
90+
{
91+
return $this->_validators;
92+
}
93+
94+
/**
95+
* @param $key
96+
* @return bool
97+
*/
98+
public function hasValidator($key)
99+
{
100+
return isset($this->_validators[$key]);
101+
}
102+
103+
/**
104+
* @return array
105+
*/
106+
public function keys()
107+
{
108+
return array_keys($this->_validators);
109+
}
110+
111+
/**
112+
* @return bool
113+
*/
114+
public function isRequired()
115+
{
116+
/** @var ValidatorInterface $validator */
117+
foreach ($this as $validator) {
118+
119+
if ($validator->isRequired()) {
120+
return true;
121+
}
122+
}
123+
124+
return false;
125+
}
126+
127+
/**
128+
* @param $key
129+
* @return bool
130+
*/
131+
public function isRequiredKey($key)
132+
{
133+
if (!$this->hasValidator($key)) {
134+
return false;
135+
}
136+
137+
return $this
138+
->getValidator($key)
139+
->isRequired();
140+
}
141+
142+
/**
143+
* @return \ArrayIterator
144+
*/
145+
public function getIterator()
146+
{
147+
return new \ArrayIterator($this->_validators);
148+
}
149+
150+
/**
151+
* @param object $value
152+
*/
153+
protected function checkRequired($value)
154+
{
155+
if (!is_object($value)) {
156+
throw new \RuntimeException('Expecting an object to check required keys.');
157+
}
158+
159+
/** @var ValidatorInterface $validator */
160+
foreach ($this as $key => $validator) {
161+
162+
if (!$validator->isRequired()) {
163+
continue;
164+
}
165+
166+
if (!isset($value->{$key})) {
167+
$this->error(static::ERROR_REQUIRED, '/' . $key);
168+
}
169+
}
170+
}
171+
}

0 commit comments

Comments
 (0)