1
|
|
|
<?php |
2
|
|
|
namespace Comfort\Validator\Helper; |
3
|
|
|
|
4
|
|
|
use Comfort\ValidationError; |
5
|
|
|
use Comfort\Validator\AbstractValidator; |
6
|
|
|
|
7
|
|
|
trait AlternativesTrait |
8
|
|
|
{ |
9
|
|
|
/** |
10
|
|
|
* Provide conditional validation in two structures: |
11
|
|
|
* - alternatives(validator, validator, validator) |
12
|
|
|
* Atleast ONE of the supplied validators MUST be valid |
13
|
|
|
* - alternatives([['if' => validator, 'then' => <validator|value>']]) |
14
|
|
|
* |
15
|
|
|
* @param $conditions |
16
|
|
|
* @return $this |
17
|
|
|
*/ |
18
|
|
|
public function alternatives() |
19
|
|
|
{ |
20
|
|
|
$args = func_get_args(); |
21
|
|
|
$numArgs = func_num_args(); |
22
|
|
|
|
23
|
|
|
if ($numArgs == 1) { |
24
|
|
|
return $this->ifThenElse($args[0]); |
25
|
|
|
} else { |
26
|
|
|
return $this->orMethod($args); |
27
|
|
|
} |
28
|
|
|
} |
29
|
|
|
|
30
|
|
|
/** |
31
|
|
|
* Assess a list of validators |
32
|
|
|
* @param \Comfort\Validator\AbstractValidator[] $conditions |
33
|
|
|
*/ |
34
|
|
|
private function orMethod($conditions) |
35
|
|
|
{ |
36
|
|
|
return $this->add(function ($value, $nameKey) use ($conditions) { |
|
|
|
|
37
|
|
|
$errors = []; |
38
|
|
|
foreach ($conditions as $condition) { |
39
|
|
|
if (!$condition instanceof AbstractValidator) { |
40
|
|
|
return $this->createError('alternatives.malformed_condition', $value, $nameKey); |
|
|
|
|
41
|
|
|
} |
42
|
|
|
|
43
|
|
|
$result = $condition($value); |
44
|
|
|
if ($result instanceof ValidationError) { |
45
|
|
|
$errors[] = $result; |
46
|
|
|
} |
47
|
|
|
} |
48
|
|
|
|
49
|
|
|
if (count($errors) === count($conditions)) { |
50
|
|
|
return $this->createError('alternatives.failed_or', $value, $nameKey); |
|
|
|
|
51
|
|
|
} |
52
|
|
|
}); |
53
|
|
|
} |
54
|
|
|
|
55
|
|
|
/** |
56
|
|
|
* @param $conditions |
57
|
|
|
* @return mixed |
58
|
|
|
*/ |
59
|
|
|
private function ifThenElse($conditions) |
60
|
|
|
{ |
61
|
|
|
return $this->add(function ($value, $nameKey) use ($conditions) { |
|
|
|
|
62
|
|
|
|
63
|
|
|
foreach ($conditions as $condition) { |
64
|
|
|
if (!isset($condition['is'])) { |
65
|
|
|
return $this->createError('alternatives.missing_is', $value, $nameKey); |
|
|
|
|
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
if (!$condition['is'] instanceof AbstractValidator) { |
69
|
|
|
return $this->createError('alternatives.invalid_is', $value, $nameKey); |
|
|
|
|
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
/** @var AbstractValidator $is */ |
73
|
|
|
$is = $condition['is']; |
74
|
|
|
$is->toBool(true); |
75
|
|
|
|
76
|
|
|
if (!isset($condition['then'])) { |
77
|
|
|
return $this->createError('alternatives.missing_then', $value, $nameKey); |
|
|
|
|
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
if ($is($value)) { |
81
|
|
View Code Duplication |
if ($condition['then'] instanceof AbstractValidator) { |
|
|
|
|
82
|
|
|
$validationStack = $condition['then']->validationStack; |
83
|
|
|
foreach ($validationStack as $validator) { |
84
|
|
|
$this->validationStack[] = $validator; |
|
|
|
|
85
|
|
|
} |
86
|
|
|
} elseif (!is_null($condition['then'])) { |
87
|
|
|
return $condition['then']; |
88
|
|
|
} |
89
|
|
View Code Duplication |
} elseif (isset($condition['else'])) { |
|
|
|
|
90
|
|
|
if ($condition['else'] instanceof AbstractValidator) { |
91
|
|
|
$validationStack = $condition['else']->validationStack; |
92
|
|
|
foreach ($validationStack as $validator) { |
93
|
|
|
$this->validationStack[] = $validator; |
94
|
|
|
} |
95
|
|
|
} elseif (!is_null($condition['else'])) { |
96
|
|
|
return $condition['else']; |
97
|
|
|
} |
98
|
|
|
} |
99
|
|
|
} |
100
|
|
|
}); |
101
|
|
|
} |
102
|
|
|
} |
This check looks for methods that are used by a trait but not required by it.
To illustrate, let’s look at the following code example
The trait
Idable
provides a methodequalsId
that in turn relies on the methodgetId()
. If this method does not exist on a class mixing in this trait, the method will fail.Adding the
getId()
as an abstract method to the trait will make sure it is available.