@@ -41,48 +41,99 @@ class TypeConstraint extends Constraint
41
41
public function check ($ value = null , $ schema = null , $ path = null , $ i = null )
42
42
{
43
43
$ type = isset ($ schema ->type ) ? $ schema ->type : null ;
44
- $ isValid = true ;
44
+ $ isValid = false ;
45
+ $ wording = array ();
45
46
46
47
if (is_array ($ type )) {
47
- // @TODO refactor
48
- $ validatedOneType = false ;
49
- $ errors = array ();
50
- foreach ($ type as $ tp ) {
51
- $ validator = new static ($ this ->checkMode );
52
- $ subSchema = new \stdClass ();
53
- $ subSchema ->type = $ tp ;
54
- $ validator ->check ($ value , $ subSchema , $ path , null );
55
- $ error = $ validator ->getErrors ();
56
-
57
- if (!count ($ error )) {
58
- $ validatedOneType = true ;
59
- break ;
60
- }
61
-
62
- $ errors = $ error ;
63
- }
64
-
65
- if (!$ validatedOneType ) {
66
- $ this ->addErrors ($ errors );
67
-
68
- return ;
69
- }
48
+ $ this ->validateTypesArray ($ value , $ type , $ wording , $ isValid , $ path );
70
49
} elseif (is_object ($ type )) {
71
50
$ this ->checkUndefined ($ value , $ type , $ path );
51
+ return ;
72
52
} else {
73
53
$ isValid = $ this ->validateType ($ value , $ type );
74
54
}
75
55
76
56
if ($ isValid === false ) {
77
- if (!isset (self ::$ wording [$ type ])) {
78
- throw new StandardUnexpectedValueException (
79
- sprintf (
80
- "No wording for %s available, expected wordings are: [%s] " ,
81
- var_export ($ type , true ),
82
- implode (', ' , array_filter (self ::$ wording )))
83
- );
57
+ if (!is_array ($ type )) {
58
+ $ this ->validateTypeNameWording ($ type );
59
+ $ wording [] = self ::$ wording [$ type ];
60
+ }
61
+ $ this ->addError ($ path , ucwords (gettype ($ value )) . " value found, but " .
62
+ $ this ->implodeWith ($ wording , ', ' , 'or ' ) . " is required " , 'type ' );
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Validates the given $value against the array of types in $type. Sets the value
68
+ * of $isValid to true, if at least one $type mateches the type of $value or the value
69
+ * passed as $isValid is already true.
70
+ *
71
+ * @param mixed $value Value to validate
72
+ * @param array $type TypeConstraints to check agains
73
+ * @param array $wording An array of wordings of the valid types of the array $type
74
+ * @param boolean $isValid The current validation value
75
+ */
76
+ protected function validateTypesArray ($ value , array $ type , &$ validTypesWording , &$ isValid ,
77
+ $ path ) {
78
+ foreach ($ type as $ tp ) {
79
+ // $tp can be an object, if it's a schema instead of a simple type, validate it
80
+ // with a new type constraint
81
+ if (is_object ($ tp )) {
82
+ if (!$ isValid ) {
83
+ $ validator = new static ($ this ->checkMode );
84
+ $ subSchema = new \stdClass ();
85
+ $ subSchema ->type = $ tp ;
86
+ $ validator ->check ($ value , $ subSchema , $ path , null );
87
+ $ error = $ validator ->getErrors ();
88
+ $ isValid = !(bool )$ error ;
89
+ $ validTypesWording [] = self ::$ wording ['object ' ];
90
+ }
91
+ } else {
92
+ $ this ->validateTypeNameWording ( $ tp );
93
+ $ validTypesWording [] = self ::$ wording [$ tp ];
94
+ if (!$ isValid ) {
95
+ $ isValid = $ this ->validateType ( $ value , $ tp );
96
+ }
84
97
}
85
- $ this ->addError ($ path , ucwords (gettype ($ value )) . " value found, but " . self ::$ wording [$ type ] . " is required " , 'type ' );
98
+ }
99
+ }
100
+
101
+ /**
102
+ * Implodes the given array like implode() with turned around parameters and with the
103
+ * difference, that, if $listEnd isn't false, the last element delimiter is $listEnd instead of
104
+ * $delimiter.
105
+ *
106
+ * @param array $elements The elements to implode
107
+ * @param string $delimiter The delimiter to use
108
+ * @param bool $listEnd The last delimiter to use (defaults to $delimiter)
109
+ * @return string
110
+ */
111
+ protected function implodeWith (array $ elements , $ delimiter = ', ' , $ listEnd = false ) {
112
+ if ($ listEnd === false || !isset ($ elements [1 ])) {
113
+ return implode (', ' , $ elements );
114
+ }
115
+ $ lastElement = array_slice ($ elements , -1 );
116
+ $ firsElements = join (', ' , array_slice ($ elements , 0 , -1 ));
117
+ $ implodedElements = array_merge (array ($ firsElements ), $ lastElement );
118
+ return join (" $ listEnd " , $ implodedElements );
119
+ }
120
+
121
+ /**
122
+ * Validates the given $type, if there's an associated self::$wording. If not, throws an
123
+ * exception.
124
+ *
125
+ * @param string $type The type to validate
126
+ *
127
+ * @throws StandardUnexpectedValueException
128
+ */
129
+ protected function validateTypeNameWording ( $ type ) {
130
+ if (!isset (self ::$ wording [$ type ])) {
131
+ throw new StandardUnexpectedValueException (
132
+ sprintf (
133
+ "No wording for %s available, expected wordings are: [%s] " ,
134
+ var_export ($ type , true ),
135
+ implode (', ' , array_filter (self ::$ wording )))
136
+ );
86
137
}
87
138
}
88
139
@@ -126,7 +177,7 @@ protected function validateType($value, $type)
126
177
if ('string ' === $ type ) {
127
178
return is_string ($ value );
128
179
}
129
-
180
+
130
181
if ('email ' === $ type ) {
131
182
return is_string ($ value );
132
183
}
0 commit comments