@@ -102,6 +102,8 @@ public function validate($value, $constraints = null, $groups = null)
102
102
103
103
$ this ->traverseGenericNode (
104
104
$ value ,
105
+ is_object ($ value ) ? spl_object_hash ($ value ) : null ,
106
+ null ,
105
107
null ,
106
108
$ metadata ,
107
109
$ this ->defaultPropertyPath ,
@@ -116,23 +118,24 @@ public function validate($value, $constraints = null, $groups = null)
116
118
117
119
if (is_object ($ value )) {
118
120
$ this ->cascadeObject (
119
- $ value ,
120
- $ this ->defaultPropertyPath ,
121
- $ groups ,
122
- TraversalStrategy::IMPLICIT ,
123
- $ this ->context
121
+ $ value ,
122
+ spl_object_hash ($ value ),
123
+ $ this ->defaultPropertyPath ,
124
+ $ groups ,
125
+ TraversalStrategy::IMPLICIT ,
126
+ $ this ->context
124
127
);
125
128
126
129
return $ this ;
127
130
}
128
131
129
132
if (is_array ($ value )) {
130
133
$ this ->cascadeCollection (
131
- $ value ,
132
- $ this ->defaultPropertyPath ,
133
- $ groups ,
134
- TraversalStrategy::IMPLICIT ,
135
- $ this ->context
134
+ $ value ,
135
+ $ this ->defaultPropertyPath ,
136
+ $ groups ,
137
+ TraversalStrategy::IMPLICIT ,
138
+ $ this ->context
136
139
);
137
140
138
141
return $ this ;
@@ -148,9 +151,9 @@ public function validate($value, $constraints = null, $groups = null)
148
151
/**
149
152
* {@inheritdoc}
150
153
*/
151
- public function validateProperty ($ object , $ propertyName , $ groups = null )
154
+ public function validateProperty ($ container , $ propertyName , $ groups = null )
152
155
{
153
- $ classMetadata = $ this ->metadataFactory ->getMetadataFor ($ object );
156
+ $ classMetadata = $ this ->metadataFactory ->getMetadataFor ($ container );
154
157
155
158
if (!$ classMetadata instanceof ClassMetadataInterface) {
156
159
// Cannot be UnsupportedMetadataException because of BC with
@@ -165,13 +168,16 @@ public function validateProperty($object, $propertyName, $groups = null)
165
168
166
169
$ propertyMetadatas = $ classMetadata ->getPropertyMetadata ($ propertyName );
167
170
$ groups = $ groups ? $ this ->normalizeGroups ($ groups ) : $ this ->defaultGroups ;
171
+ $ containerHash = spl_object_hash ($ container );
168
172
169
173
foreach ($ propertyMetadatas as $ propertyMetadata ) {
170
- $ propertyValue = $ propertyMetadata ->getPropertyValue ($ object );
174
+ $ propertyValue = $ propertyMetadata ->getPropertyValue ($ container );
171
175
172
176
$ this ->traverseGenericNode (
173
177
$ propertyValue ,
174
- $ object ,
178
+ is_object ($ propertyValue ) ? spl_object_hash ($ propertyValue ) : null ,
179
+ $ container ,
180
+ $ containerHash ,
175
181
$ propertyMetadata ,
176
182
PropertyPath::append ($ this ->defaultPropertyPath , $ propertyName ),
177
183
$ groups ,
@@ -187,9 +193,9 @@ public function validateProperty($object, $propertyName, $groups = null)
187
193
/**
188
194
* {@inheritdoc}
189
195
*/
190
- public function validatePropertyValue ($ object , $ propertyName , $ value , $ groups = null )
196
+ public function validatePropertyValue ($ container , $ propertyName , $ value , $ groups = null )
191
197
{
192
- $ classMetadata = $ this ->metadataFactory ->getMetadataFor ($ object );
198
+ $ classMetadata = $ this ->metadataFactory ->getMetadataFor ($ container );
193
199
194
200
if (!$ classMetadata instanceof ClassMetadataInterface) {
195
201
// Cannot be UnsupportedMetadataException because of BC with
@@ -204,11 +210,14 @@ public function validatePropertyValue($object, $propertyName, $value, $groups =
204
210
205
211
$ propertyMetadatas = $ classMetadata ->getPropertyMetadata ($ propertyName );
206
212
$ groups = $ groups ? $ this ->normalizeGroups ($ groups ) : $ this ->defaultGroups ;
213
+ $ containerHash = spl_object_hash ($ container );
207
214
208
215
foreach ($ propertyMetadatas as $ propertyMetadata ) {
209
216
$ this ->traverseGenericNode (
210
217
$ value ,
211
- $ object ,
218
+ is_object ($ value ) ? spl_object_hash ($ value ) : null ,
219
+ $ container ,
220
+ $ containerHash ,
212
221
$ propertyMetadata ,
213
222
PropertyPath::append ($ this ->defaultPropertyPath , $ propertyName ),
214
223
$ groups ,
@@ -266,12 +275,12 @@ protected function normalizeGroups($groups)
266
275
* @see CollectionNode
267
276
* @see TraversalStrategy
268
277
*/
269
- private function traverseClassNode ($ value , ClassMetadataInterface $ metadata = null , $ propertyPath , array $ groups , $ cascadedGroups , $ traversalStrategy , ExecutionContextInterface $ context )
278
+ private function traverseClassNode ($ value , $ valueHash , ClassMetadataInterface $ metadata = null , $ propertyPath , array $ groups , $ cascadedGroups , $ traversalStrategy , ExecutionContextInterface $ context )
270
279
{
271
280
// Replace "Default" group by group sequence, if appropriate
272
281
$ groups = $ this ->replaceDefaultGroup ($ value , $ metadata , $ groups );
273
282
274
- $ groups = $ this ->validateNode ($ value , $ value , $ metadata , $ propertyPath , $ groups , $ traversalStrategy , $ context );
283
+ $ groups = $ this ->validateNode ($ value , $ valueHash , null , null , $ metadata , $ propertyPath , $ groups , $ traversalStrategy , $ context );
275
284
276
285
if (0 === count ($ groups )) {
277
286
return ;
@@ -288,9 +297,13 @@ private function traverseClassNode($value, ClassMetadataInterface $metadata = nu
288
297
));
289
298
}
290
299
300
+ $ propertyValue = $ propertyMetadata ->getPropertyValue ($ value );
301
+
291
302
$ this ->traverseGenericNode (
292
- $ propertyMetadata ->getPropertyValue ($ value ),
303
+ $ propertyValue ,
304
+ is_object ($ propertyValue ) ? spl_object_hash ($ propertyValue ) : null ,
293
305
$ value ,
306
+ $ valueHash ,
294
307
$ propertyMetadata ,
295
308
$ propertyPath
296
309
? $ propertyPath .'. ' .$ propertyName
@@ -392,6 +405,7 @@ private function cascadeCollection($collection, $propertyPath, array $groups, $t
392
405
if (is_object ($ value )) {
393
406
$ this ->cascadeObject (
394
407
$ value ,
408
+ spl_object_hash ($ value ),
395
409
$ propertyPath .'[ ' .$ key .'] ' ,
396
410
$ groups ,
397
411
$ traversalStrategy ,
@@ -418,9 +432,9 @@ private function cascadeCollection($collection, $propertyPath, array $groups, $t
418
432
* @param Node $node The node
419
433
* @param ExecutionContextInterface $context The current execution context
420
434
*/
421
- private function traverseGenericNode ($ value , $ object , MetadataInterface $ metadata = null , $ propertyPath , array $ groups , $ cascadedGroups , $ traversalStrategy , ExecutionContextInterface $ context )
435
+ private function traverseGenericNode ($ value , $ valueHash , $ container , $ containerHash , MetadataInterface $ metadata = null , $ propertyPath , array $ groups , $ cascadedGroups , $ traversalStrategy , ExecutionContextInterface $ context )
422
436
{
423
- $ groups = $ this ->validateNode ($ value , $ object , $ metadata , $ propertyPath , $ groups , $ traversalStrategy , $ context );
437
+ $ groups = $ this ->validateNode ($ value , $ valueHash , $ container , $ containerHash , $ metadata , $ propertyPath , $ groups , $ traversalStrategy , $ context );
424
438
425
439
if (0 === count ($ groups )) {
426
440
return ;
@@ -467,6 +481,7 @@ private function traverseGenericNode($value, $object, MetadataInterface $metadat
467
481
// (BC with Symfony < 2.5)
468
482
$ this ->cascadeObject (
469
483
$ value ,
484
+ $ valueHash ,
470
485
$ propertyPath ,
471
486
$ cascadedGroups ,
472
487
$ traversalStrategy ,
@@ -492,7 +507,7 @@ private function traverseGenericNode($value, $object, MetadataInterface $metadat
492
507
* traversal of the object, a new collection node is put on the stack.
493
508
* Otherwise, an exception is thrown.
494
509
*
495
- * @param object $object The object to cascade
510
+ * @param object $container The object to cascade
496
511
* @param string $propertyPath The current property path
497
512
* @param string[] $groups The validated groups
498
513
* @param integer $traversalStrategy The strategy for traversing the
@@ -507,10 +522,10 @@ private function traverseGenericNode($value, $object, MetadataInterface $metadat
507
522
* metadata factory does not implement
508
523
* {@link ClassMetadataInterface}
509
524
*/
510
- private function cascadeObject ($ object , $ propertyPath , array $ groups , $ traversalStrategy , ExecutionContextInterface $ context )
525
+ private function cascadeObject ($ container , $ containerHash , $ propertyPath , array $ groups , $ traversalStrategy , ExecutionContextInterface $ context )
511
526
{
512
527
try {
513
- $ classMetadata = $ this ->metadataFactory ->getMetadataFor ($ object );
528
+ $ classMetadata = $ this ->metadataFactory ->getMetadataFor ($ container );
514
529
515
530
if (!$ classMetadata instanceof ClassMetadataInterface) {
516
531
throw new UnsupportedMetadataException (sprintf (
@@ -522,7 +537,8 @@ private function cascadeObject($object, $propertyPath, array $groups, $traversal
522
537
}
523
538
524
539
$ this ->traverseClassNode (
525
- $ object ,
540
+ $ container ,
541
+ $ containerHash ,
526
542
$ classMetadata ,
527
543
$ propertyPath ,
528
544
$ groups ,
@@ -532,7 +548,7 @@ private function cascadeObject($object, $propertyPath, array $groups, $traversal
532
548
);
533
549
} catch (NoSuchMetadataException $ e ) {
534
550
// Rethrow if not Traversable
535
- if (!$ object instanceof \Traversable) {
551
+ if (!$ container instanceof \Traversable) {
536
552
throw $ e ;
537
553
}
538
554
@@ -542,7 +558,7 @@ private function cascadeObject($object, $propertyPath, array $groups, $traversal
542
558
}
543
559
544
560
$ this ->cascadeCollection (
545
- $ object ,
561
+ $ container ,
546
562
$ propertyPath ,
547
563
$ groups ,
548
564
$ traversalStrategy ,
@@ -563,14 +579,12 @@ private function cascadeObject($object, $propertyPath, array $groups, $traversal
563
579
*
564
580
* @return array The groups in which the successor nodes should be validated
565
581
*/
566
- public function validateNode ($ value , $ object , MetadataInterface $ metadata = null , $ propertyPath , array $ groups , $ traversalStrategy , ExecutionContextInterface $ context )
582
+ public function validateNode ($ value , $ valueHash , $ container , $ containerHash , MetadataInterface $ metadata = null , $ propertyPath , array $ groups , $ traversalStrategy , ExecutionContextInterface $ context )
567
583
{
568
584
$ context ->setValue ($ value );
569
585
$ context ->setMetadata ($ metadata );
570
586
$ context ->setPropertyPath ($ propertyPath );
571
587
572
- $ objectHash = is_object ($ object ) ? spl_object_hash ($ object ) : null ;
573
-
574
588
// if group (=[<G1,G2>,G3,G4]) contains group sequence (=<G1,G2>)
575
589
// then call traverse() with each entry of the group sequence and abort
576
590
// if necessary (G1, G2)
@@ -587,20 +601,20 @@ public function validateNode($value, $object, MetadataInterface $metadata = null
587
601
// Use the object hash for group sequences
588
602
$ groupHash = is_object ($ group ) ? spl_object_hash ($ group ) : $ group ;
589
603
590
- if ($ context ->isObjectValidatedForGroup ($ objectHash , $ groupHash )) {
604
+ if ($ context ->isObjectValidatedForGroup ($ valueHash , $ groupHash )) {
591
605
// Skip this group when validating the successor nodes
592
606
// (property and/or collection nodes)
593
607
unset($ groups [$ key ]);
594
608
595
609
continue ;
596
610
}
597
611
598
- $ context ->markObjectAsValidatedForGroup ($ objectHash , $ groupHash );
612
+ $ context ->markObjectAsValidatedForGroup ($ valueHash , $ groupHash );
599
613
}
600
614
601
615
if ($ group instanceof GroupSequence) {
602
616
// Traverse group sequence until a violation is generated
603
- $ this ->stepThroughGroupSequence ($ value , $ object , $ metadata , $ propertyPath , $ traversalStrategy , $ group , $ context );
617
+ $ this ->stepThroughGroupSequence ($ value , $ valueHash , $ container , $ containerHash , $ metadata , $ propertyPath , $ traversalStrategy , $ group , $ context );
604
618
605
619
// Skip the group sequence when validating successor nodes
606
620
unset($ groups [$ key ]);
@@ -609,7 +623,7 @@ public function validateNode($value, $object, MetadataInterface $metadata = null
609
623
}
610
624
611
625
// Validate normal group
612
- $ this ->validateNodeForGroup ($ value , $ objectHash , $ metadata , $ group , $ context );
626
+ $ this ->validateNodeForGroup ($ value , $ valueHash , $ containerHash , $ metadata , $ group , $ context );
613
627
}
614
628
615
629
return $ groups ;
@@ -625,7 +639,7 @@ public function validateNode($value, $object, MetadataInterface $metadata = null
625
639
* @param GroupSequence $groupSequence The group sequence
626
640
* @param ExecutionContextInterface $context The execution context
627
641
*/
628
- private function stepThroughGroupSequence ($ value , $ object , MetadataInterface $ metadata = null , $ propertyPath , $ traversalStrategy , GroupSequence $ groupSequence , ExecutionContextInterface $ context )
642
+ private function stepThroughGroupSequence ($ value , $ valueHash , $ container , $ containerHash , MetadataInterface $ metadata = null , $ propertyPath , $ traversalStrategy , GroupSequence $ groupSequence , ExecutionContextInterface $ context )
629
643
{
630
644
$ violationCount = count ($ context ->getViolations ());
631
645
@@ -640,6 +654,7 @@ private function stepThroughGroupSequence($value, $object, MetadataInterface $me
640
654
if ($ metadata instanceof ClassMetadataInterface) {
641
655
$ this ->traverseClassNode (
642
656
$ value ,
657
+ $ valueHash ,
643
658
$ metadata ,
644
659
$ propertyPath ,
645
660
$ groups ,
@@ -650,7 +665,9 @@ private function stepThroughGroupSequence($value, $object, MetadataInterface $me
650
665
} else {
651
666
$ this ->traverseGenericNode (
652
667
$ value ,
653
- $ object ,
668
+ $ valueHash ,
669
+ $ container ,
670
+ $ containerHash ,
654
671
$ metadata ,
655
672
$ propertyPath ,
656
673
$ groups ,
@@ -673,36 +690,38 @@ private function stepThroughGroupSequence($value, $object, MetadataInterface $me
673
690
* @param Node $node The validated node
674
691
* @param string $group The group to validate
675
692
* @param ExecutionContextInterface $context The execution context
676
- * @param string $objectHash The hash of the node's
693
+ * @param string $containerHash The hash of the node's
677
694
* object (if any)
678
695
*
679
696
* @throws \Exception
680
697
*/
681
- private function validateNodeForGroup ($ value , $ objectHash , MetadataInterface $ metadata = null , $ group , ExecutionContextInterface $ context )
698
+ private function validateNodeForGroup ($ value , $ valueHash , $ containerHash , MetadataInterface $ metadata = null , $ group , ExecutionContextInterface $ context )
682
699
{
683
700
$ context ->setGroup ($ group );
684
701
702
+ $ propertyName = $ metadata instanceof PropertyMetadataInterface
703
+ ? $ metadata ->getPropertyName ()
704
+ : null ;
705
+
685
706
foreach ($ metadata ->findConstraints ($ group ) as $ constraint ) {
686
707
// Prevent duplicate validation of constraints, in the case
687
708
// that constraints belong to multiple validated groups
688
- if (null !== $ objectHash ) {
709
+ if (null !== $ propertyName ) {
689
710
$ constraintHash = spl_object_hash ($ constraint );
690
711
691
- if ($ metadata instanceof ClassMetadataInterface) {
692
- if ($ context ->isClassConstraintValidated ($ objectHash , $ constraintHash )) {
693
- continue ;
694
- }
695
-
696
- $ context ->markClassConstraintAsValidated ($ objectHash , $ constraintHash );
697
- } elseif ($ metadata instanceof PropertyMetadataInterface) {
698
- $ propertyName = $ metadata ->getPropertyName ();
712
+ if ($ context ->isPropertyConstraintValidated ($ containerHash , $ propertyName , $ constraintHash )) {
713
+ continue ;
714
+ }
699
715
700
- if ( $ context ->isPropertyConstraintValidated ( $ objectHash , $ propertyName , $ constraintHash )) {
701
- continue ;
702
- }
716
+ $ context ->markPropertyConstraintAsValidated ( $ containerHash , $ propertyName , $ constraintHash );
717
+ } elseif ( null !== $ valueHash ) {
718
+ $ constraintHash = spl_object_hash ( $ constraint );
703
719
704
- $ context ->markPropertyConstraintAsValidated ($ objectHash , $ propertyName , $ constraintHash );
720
+ if ($ context ->isClassConstraintValidated ($ valueHash , $ constraintHash )) {
721
+ continue ;
705
722
}
723
+
724
+ $ context ->markClassConstraintAsValidated ($ valueHash , $ constraintHash );
706
725
}
707
726
708
727
$ validator = $ this ->validatorFactory ->getInstance ($ constraint );
0 commit comments