1616use Symfony \Component \Validator \Exception \NoSuchMetadataException ;
1717use Symfony \Component \Validator \Mapping \CascadingStrategy ;
1818use Symfony \Component \Validator \Mapping \ClassMetadataInterface ;
19+ use Symfony \Component \Validator \Mapping \CollectionMetadata ;
1920use Symfony \Component \Validator \Mapping \TraversalStrategy ;
2021use Symfony \Component \Validator \MetadataFactoryInterface ;
2122use Symfony \Component \Validator \Node \ClassNode ;
23+ use Symfony \Component \Validator \Node \CollectionNode ;
2224use Symfony \Component \Validator \Node \Node ;
2325use Symfony \Component \Validator \Node \PropertyNode ;
2426use Symfony \Component \Validator \NodeVisitor \NodeVisitorInterface ;
@@ -84,6 +86,8 @@ public function traverse(array $nodes, ExecutionContextInterface $context)
8486
8587 if ($ node instanceof ClassNode) {
8688 $ this ->traverseClassNode ($ node , $ traversal );
89+ } elseif ($ node instanceof CollectionNode) {
90+ $ this ->traverseCollectionNode ($ node , $ traversal );
8791 } else {
8892 $ this ->traverseNode ($ node , $ traversal );
8993 }
@@ -145,13 +149,12 @@ private function traverseNode(Node $node, Traversal $traversal)
145149 // Arrays are always traversed, independent of the specified
146150 // traversal strategy
147151 // (BC with Symfony < 2.5)
148- $ this -> cascadeEachObjectIn (
152+ $ traversal -> nodeQueue -> enqueue ( new CollectionNode (
149153 $ node ->value ,
154+ new CollectionMetadata ($ traversalStrategy ),
150155 $ node ->propertyPath ,
151- $ cascadedGroups ,
152- $ traversalStrategy ,
153- $ traversal
154- );
156+ $ cascadedGroups
157+ ));
155158
156159 return ;
157160 }
@@ -188,13 +191,13 @@ private function traverseNode(Node $node, Traversal $traversal)
188191 ));
189192 }
190193
191- $ this -> cascadeEachObjectIn (
194+ $ traversal -> nodeQueue -> enqueue ( new CollectionNode (
192195 $ node ->value ,
196+ new CollectionMetadata ($ traversalStrategy ),
193197 $ node ->propertyPath ,
194- $ cascadedGroups ,
195- $ traversalStrategy ,
196- $ traversal
197- );
198+ $ node ->groups ,
199+ $ node ->cascadedGroups
200+ ));
198201 }
199202
200203 private function traverseClassNode (ClassNode $ node , Traversal $ traversal , $ traversalStrategy = TraversalStrategy::IMPLICIT )
@@ -252,54 +255,23 @@ private function traverseClassNode(ClassNode $node, Traversal $traversal, $trave
252255 ));
253256 }
254257
255- $ this -> cascadeEachObjectIn (
258+ $ traversal -> nodeQueue -> enqueue ( new CollectionNode (
256259 $ node ->value ,
260+ new CollectionMetadata ($ traversalStrategy ),
257261 $ node ->propertyPath ,
258262 $ node ->groups ,
259- $ traversalStrategy ,
260- $ traversal
261- );
263+ $ node ->cascadedGroups
264+ ));
262265 }
263266
264- private function cascadeObject ( $ object , $ propertyPath , array $ groups , $ traversalStrategy , Traversal $ traversal )
267+ private function traverseCollectionNode ( CollectionNode $ node , Traversal $ traversal )
265268 {
266- try {
267- $ classMetadata = $ this ->metadataFactory ->getMetadataFor ($ object );
268-
269- if (!$ classMetadata instanceof ClassMetadataInterface) {
270- // error
271- }
272-
273- $ traversal ->nodeQueue ->enqueue (new ClassNode (
274- $ object ,
275- $ classMetadata ,
276- $ propertyPath ,
277- $ groups
278- ));
279- } catch (NoSuchMetadataException $ e ) {
280- // Rethrow if the TRAVERSE bit is not set
281- if (!($ traversalStrategy & TraversalStrategy::TRAVERSE )) {
282- throw $ e ;
283- }
284-
285- // Rethrow if the object does not implement Traversable
286- if (!$ object instanceof \Traversable) {
287- throw $ e ;
288- }
289-
290- // In that case, iterate the object and cascade each entry
291- $ this ->cascadeEachObjectIn (
292- $ object ,
293- $ propertyPath ,
294- $ groups ,
295- $ traversalStrategy ,
296- $ traversal
297- );
269+ if (false === $ this ->visit ($ node , $ traversal ->context )) {
270+ return ;
298271 }
299- }
300272
301- private function cascadeEachObjectIn ( $ collection , $ propertyPath , array $ groups , $ traversalStrategy, Traversal $ traversal )
302- {
273+ $ traversalStrategy = $ node -> metadata -> getTraversalStrategy ();
274+
303275 if ($ traversalStrategy & TraversalStrategy::RECURSIVE ) {
304276 // Try to traverse nested objects, but ignore if they do not
305277 // implement Traversable
@@ -311,18 +283,17 @@ private function cascadeEachObjectIn($collection, $propertyPath, array $groups,
311283 $ traversalStrategy = TraversalStrategy::IMPLICIT ;
312284 }
313285
314- foreach ($ collection as $ key => $ value ) {
286+ foreach ($ node -> value as $ key => $ value ) {
315287 if (is_array ($ value )) {
316288 // Arrays are always cascaded, independent of the specified
317289 // traversal strategy
318290 // (BC with Symfony < 2.5)
319- $ this -> cascadeEachObjectIn (
291+ $ traversal -> nodeQueue -> enqueue ( new CollectionNode (
320292 $ value ,
321- $ propertyPath .'[ ' .$ key .'] ' ,
322- $ groups ,
323- $ traversalStrategy ,
324- $ traversal
325- );
293+ new CollectionMetadata ($ traversalStrategy ),
294+ $ node ->propertyPath .'[ ' .$ key .'] ' ,
295+ $ node ->groups
296+ ));
326297
327298 continue ;
328299 }
@@ -332,12 +303,47 @@ private function cascadeEachObjectIn($collection, $propertyPath, array $groups,
332303 if (is_object ($ value )) {
333304 $ this ->cascadeObject (
334305 $ value ,
335- $ propertyPath .'[ ' .$ key .'] ' ,
336- $ groups ,
306+ $ node -> propertyPath .'[ ' .$ key .'] ' ,
307+ $ node -> groups ,
337308 $ traversalStrategy ,
338309 $ traversal
339310 );
340311 }
341312 }
342313 }
314+
315+ private function cascadeObject ($ object , $ propertyPath , array $ groups , $ traversalStrategy , Traversal $ traversal )
316+ {
317+ try {
318+ $ classMetadata = $ this ->metadataFactory ->getMetadataFor ($ object );
319+
320+ if (!$ classMetadata instanceof ClassMetadataInterface) {
321+ // error
322+ }
323+
324+ $ traversal ->nodeQueue ->enqueue (new ClassNode (
325+ $ object ,
326+ $ classMetadata ,
327+ $ propertyPath ,
328+ $ groups
329+ ));
330+ } catch (NoSuchMetadataException $ e ) {
331+ // Rethrow if the TRAVERSE bit is not set
332+ if (!($ traversalStrategy & TraversalStrategy::TRAVERSE )) {
333+ throw $ e ;
334+ }
335+
336+ // Rethrow if the object does not implement Traversable
337+ if (!$ object instanceof \Traversable) {
338+ throw $ e ;
339+ }
340+
341+ $ traversal ->nodeQueue ->enqueue (new CollectionNode (
342+ $ object ,
343+ new CollectionMetadata ($ traversalStrategy ),
344+ $ propertyPath ,
345+ $ groups
346+ ));
347+ }
348+ }
343349}
0 commit comments