Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3183aed

Browse files
committed
[Validator] Improved performance of cache key generation
1 parent 029a716 commit 3183aed

12 files changed

+198
-306
lines changed

src/Symfony/Component/Validator/Context/ExecutionContext.php

Lines changed: 11 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ class ExecutionContext implements ExecutionContextInterface
104104
*
105105
* @var array
106106
*/
107-
private $validatedClassConstraints = array();
107+
private $validatedConstraints = array();
108108

109109
/**
110110
* Stores which property constraint has been validated for which property.
@@ -319,64 +319,36 @@ public function getMetadataFactory()
319319
/**
320320
* {@inheritdoc}
321321
*/
322-
public function markObjectAsValidatedForGroup($objectHash, $groupHash)
322+
public function markGroupAsValidated($cacheKey, $groupHash)
323323
{
324-
if (!isset($this->validatedObjects[$objectHash])) {
325-
$this->validatedObjects[$objectHash] = array();
324+
if (!isset($this->validatedObjects[$cacheKey])) {
325+
$this->validatedObjects[$cacheKey] = array();
326326
}
327327

328-
$this->validatedObjects[$objectHash][$groupHash] = true;
328+
$this->validatedObjects[$cacheKey][$groupHash] = true;
329329
}
330330

331331
/**
332332
* {@inheritdoc}
333333
*/
334-
public function isObjectValidatedForGroup($objectHash, $groupHash)
334+
public function isGroupValidated($cacheKey, $groupHash)
335335
{
336-
return isset($this->validatedObjects[$objectHash][$groupHash]);
336+
return isset($this->validatedObjects[$cacheKey][$groupHash]);
337337
}
338338

339339
/**
340340
* {@inheritdoc}
341341
*/
342-
public function markClassConstraintAsValidated($objectHash, $constraintHash)
342+
public function markConstraintAsValidated($cacheKey, $constraintHash)
343343
{
344-
if (!isset($this->validatedClassConstraints[$objectHash])) {
345-
$this->validatedClassConstraints[$objectHash] = array();
346-
}
347-
348-
$this->validatedClassConstraints[$objectHash][$constraintHash] = true;
349-
}
350-
351-
/**
352-
* {@inheritdoc}
353-
*/
354-
public function isClassConstraintValidated($objectHash, $constraintHash)
355-
{
356-
return isset($this->validatedClassConstraints[$objectHash][$constraintHash]);
357-
}
358-
359-
/**
360-
* {@inheritdoc}
361-
*/
362-
public function markPropertyConstraintAsValidated($objectHash, $propertyName, $constraintHash)
363-
{
364-
if (!isset($this->validatedPropertyConstraints[$objectHash])) {
365-
$this->validatedPropertyConstraints[$objectHash] = array();
366-
}
367-
368-
if (!isset($this->validatedPropertyConstraints[$objectHash][$propertyName])) {
369-
$this->validatedPropertyConstraints[$objectHash][$propertyName] = array();
370-
}
371-
372-
$this->validatedPropertyConstraints[$objectHash][$propertyName][$constraintHash] = true;
344+
$this->validatedConstraints[$cacheKey.':'.$constraintHash] = true;
373345
}
374346

375347
/**
376348
* {@inheritdoc}
377349
*/
378-
public function isPropertyConstraintValidated($objectHash, $propertyName, $constraintHash)
350+
public function isConstraintValidated($cacheKey, $constraintHash)
379351
{
380-
return isset($this->validatedPropertyConstraints[$objectHash][$propertyName][$constraintHash]);
352+
return isset($this->validatedConstraints[$cacheKey.':'.$constraintHash]);
381353
}
382354
}

src/Symfony/Component/Validator/Context/ExecutionContextInterface.php

Lines changed: 8 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -124,19 +124,19 @@ public function setGroup($group);
124124
/**
125125
* Marks an object as validated in a specific validation group.
126126
*
127-
* @param string $objectHash The hash of the object
127+
* @param string $cacheKey The hash of the object
128128
* @param string $groupHash The group's name or hash, if it is group
129129
* sequence
130130
*
131131
* @internal Used by the validator engine. Should not be called by user
132132
* code.
133133
*/
134-
public function markObjectAsValidatedForGroup($objectHash, $groupHash);
134+
public function markGroupAsValidated($cacheKey, $groupHash);
135135

136136
/**
137137
* Returns whether an object was validated in a specific validation group.
138138
*
139-
* @param string $objectHash The hash of the object
139+
* @param string $cacheKey The hash of the object
140140
* @param string $groupHash The group's name or hash, if it is group
141141
* sequence
142142
*
@@ -146,56 +146,29 @@ public function markObjectAsValidatedForGroup($objectHash, $groupHash);
146146
* @internal Used by the validator engine. Should not be called by user
147147
* code.
148148
*/
149-
public function isObjectValidatedForGroup($objectHash, $groupHash);
149+
public function isGroupValidated($cacheKey, $groupHash);
150150

151151
/**
152152
* Marks a constraint as validated for an object.
153153
*
154-
* @param string $objectHash The hash of the object
154+
* @param string $cacheKey The hash of the object
155155
* @param string $constraintHash The hash of the constraint
156156
*
157157
* @internal Used by the validator engine. Should not be called by user
158158
* code.
159159
*/
160-
public function markClassConstraintAsValidated($objectHash, $constraintHash);
160+
public function markConstraintAsValidated($cacheKey, $constraintHash);
161161

162162
/**
163163
* Returns whether a constraint was validated for an object.
164164
*
165-
* @param string $objectHash The hash of the object
165+
* @param string $cacheKey The hash of the object
166166
* @param string $constraintHash The hash of the constraint
167167
*
168168
* @return Boolean Whether the constraint was already validated
169169
*
170170
* @internal Used by the validator engine. Should not be called by user
171171
* code.
172172
*/
173-
public function isClassConstraintValidated($objectHash, $constraintHash);
174-
175-
/**
176-
* Marks a constraint as validated for an object and a property name.
177-
*
178-
* @param string $objectHash The hash of the object
179-
* @param string $propertyName The property name
180-
* @param string $constraintHash The hash of the constraint
181-
*
182-
* @internal Used by the validator engine. Should not be called by user
183-
* code.
184-
*/
185-
public function markPropertyConstraintAsValidated($objectHash, $propertyName, $constraintHash);
186-
187-
/**
188-
* Returns whether a constraint was validated for an object and a property
189-
* name.
190-
*
191-
* @param string $objectHash The hash of the object
192-
* @param string $propertyName The property name
193-
* @param string $constraintHash The hash of the constraint
194-
*
195-
* @return Boolean Whether the constraint was already validated
196-
*
197-
* @internal Used by the validator engine. Should not be called by user
198-
* code.
199-
*/
200-
public function isPropertyConstraintValidated($objectHash, $propertyName, $constraintHash);
173+
public function isConstraintValidated($cacheKey, $constraintHash);
201174
}

src/Symfony/Component/Validator/Node/ClassNode.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,20 +55,20 @@ class ClassNode extends Node
5555
*
5656
* @see \Symfony\Component\Validator\Mapping\TraversalStrategy
5757
*/
58-
public function __construct($object, ClassMetadataInterface $metadata, $propertyPath, array $groups, $cascadedGroups = null, $traversalStrategy = TraversalStrategy::IMPLICIT)
58+
public function __construct($object, $cacheKey, ClassMetadataInterface $metadata, $propertyPath, array $groups, $cascadedGroups = null, $traversalStrategy = TraversalStrategy::IMPLICIT)
5959
{
6060
if (!is_object($object)) {
6161
throw new UnexpectedTypeException($object, 'object');
6262
}
6363

6464
parent::__construct(
6565
$object,
66+
$cacheKey,
6667
$metadata,
6768
$propertyPath,
6869
$groups,
69-
$cascadedGroups
70+
$cascadedGroups,
71+
$traversalStrategy
7072
);
71-
72-
$this->traversalStrategy = $traversalStrategy;
7373
}
7474
}

src/Symfony/Component/Validator/Node/CollectionNode.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public function __construct($collection, $propertyPath, array $groups, $cascaded
5656
parent::__construct(
5757
$collection,
5858
null,
59+
null,
5960
$propertyPath,
6061
$groups,
6162
$cascadedGroups,

src/Symfony/Component/Validator/Node/Node.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ abstract class Node
3030
*/
3131
public $value;
3232

33+
public $cacheKey;
34+
3335
/**
3436
* The metadata specifying how the value should be validated.
3537
*
@@ -82,13 +84,14 @@ abstract class Node
8284
*
8385
* @throws UnexpectedTypeException If $cascadedGroups is invalid
8486
*/
85-
public function __construct($value, MetadataInterface $metadata = null, $propertyPath, array $groups, $cascadedGroups = null, $traversalStrategy = TraversalStrategy::IMPLICIT)
87+
public function __construct($value, $cacheKey, MetadataInterface $metadata = null, $propertyPath, array $groups, $cascadedGroups = null, $traversalStrategy = TraversalStrategy::IMPLICIT)
8688
{
8789
if (null !== $cascadedGroups && !is_array($cascadedGroups)) {
8890
throw new UnexpectedTypeException($cascadedGroups, 'null or array');
8991
}
9092

9193
$this->value = $value;
94+
$this->cacheKey = $cacheKey;
9295
$this->metadata = $metadata;
9396
$this->propertyPath = $propertyPath;
9497
$this->groups = $groups;

src/Symfony/Component/Validator/Node/PropertyNode.php

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,6 @@
4141
*/
4242
class PropertyNode extends Node
4343
{
44-
/**
45-
* @var object
46-
*/
47-
public $object;
48-
4944
/**
5045
* @var PropertyMetadataInterface
5146
*/
@@ -71,22 +66,17 @@ class PropertyNode extends Node
7166
*
7267
* @see \Symfony\Component\Validator\Mapping\TraversalStrategy
7368
*/
74-
public function __construct($object, $value, PropertyMetadataInterface $metadata, $propertyPath, array $groups, $cascadedGroups = null, $traversalStrategy = TraversalStrategy::IMPLICIT)
69+
public function __construct($value, $cacheKey, PropertyMetadataInterface $metadata, $propertyPath, array $groups, $cascadedGroups = null, $traversalStrategy = TraversalStrategy::IMPLICIT)
7570
{
76-
if (!is_object($object)) {
77-
throw new UnexpectedTypeException($object, 'object');
78-
}
79-
8071
parent::__construct(
8172
$value,
73+
$cacheKey,
8274
$metadata,
8375
$propertyPath,
8476
$groups,
8577
$cascadedGroups,
8678
$traversalStrategy
8779
);
88-
89-
$this->object = $object;
9080
}
9181

9282
}

src/Symfony/Component/Validator/NodeTraverser/NonRecursiveNodeTraverser.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,8 +274,8 @@ private function traverseClassNode(ClassNode $node, ExecutionContextInterface $c
274274
}
275275

276276
$nodeStack->push(new PropertyNode(
277-
$node->value,
278277
$propertyMetadata->getPropertyValue($node->value),
278+
$node->cacheKey.':'.$propertyName,
279279
$propertyMetadata,
280280
$node->propertyPath
281281
? $node->propertyPath.'.'.$propertyName
@@ -530,6 +530,7 @@ private function cascadeObject($object, $propertyPath, array $groups, $traversal
530530

531531
$nodeStack->push(new ClassNode(
532532
$object,
533+
spl_object_hash($object),
533534
$classMetadata,
534535
$propertyPath,
535536
$groups,

src/Symfony/Component/Validator/NodeVisitor/NodeValidationVisitor.php

Lines changed: 9 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,6 @@ public function visit(Node $node, ExecutionContextInterface $context)
7171

7272
$context->setNode($node->value, $node->metadata, $node->propertyPath);
7373

74-
if ($node instanceof ClassNode) {
75-
$objectHash = spl_object_hash($node->value);
76-
} elseif ($node instanceof PropertyNode) {
77-
$objectHash = spl_object_hash($node->object);
78-
} else {
79-
$objectHash = null;
80-
}
81-
8274
// if group (=[<G1,G2>,G3,G4]) contains group sequence (=<G1,G2>)
8375
// then call traverse() with each entry of the group sequence and abort
8476
// if necessary (G1, G2)
@@ -97,15 +89,15 @@ public function visit(Node $node, ExecutionContextInterface $context)
9789
// Use the object hash for group sequences
9890
$groupHash = is_object($group) ? spl_object_hash($group) : $group;
9991

100-
if ($context->isObjectValidatedForGroup($objectHash, $groupHash)) {
92+
if ($context->isGroupValidated($node->cacheKey, $groupHash)) {
10193
// Skip this group when validating the successor nodes
10294
// (property and/or collection nodes)
10395
unset($node->groups[$key]);
10496

10597
continue;
10698
}
10799

108-
$context->markObjectAsValidatedForGroup($objectHash, $groupHash);
100+
$context->markGroupAsValidated($node->cacheKey, $groupHash);
109101

110102
// Replace the "Default" group by the group sequence defined
111103
// for the class, if applicable
@@ -144,7 +136,7 @@ public function visit(Node $node, ExecutionContextInterface $context)
144136
}
145137

146138
// Validate normal group
147-
$this->validateNodeForGroup($node, $group, $context, $objectHash);
139+
$this->validateInGroup($node, $group, $context);
148140
}
149141

150142
return true;
@@ -190,31 +182,21 @@ private function traverseGroupSequence(Node $node, GroupSequence $groupSequence,
190182
*
191183
* @throws \Exception
192184
*/
193-
private function validateNodeForGroup(Node $node, $group, ExecutionContextInterface $context, $objectHash)
185+
private function validateInGroup(Node $node, $group, ExecutionContextInterface $context)
194186
{
195187
$context->setGroup($group);
196188

197189
foreach ($node->metadata->findConstraints($group) as $constraint) {
198190
// Prevent duplicate validation of constraints, in the case
199191
// that constraints belong to multiple validated groups
200-
if (null !== $objectHash) {
192+
if (null !== $node->cacheKey) {
201193
$constraintHash = spl_object_hash($constraint);
202194

203-
if ($node instanceof ClassNode) {
204-
if ($context->isClassConstraintValidated($objectHash, $constraintHash)) {
205-
continue;
206-
}
207-
208-
$context->markClassConstraintAsValidated($objectHash, $constraintHash);
209-
} elseif ($node instanceof PropertyNode) {
210-
$propertyName = $node->metadata->getPropertyName();
211-
212-
if ($context->isPropertyConstraintValidated($objectHash, $propertyName, $constraintHash)) {
213-
continue;
214-
}
215-
216-
$context->markPropertyConstraintAsValidated($objectHash, $propertyName, $constraintHash);
195+
if ($context->isConstraintValidated($node->cacheKey, $constraintHash)) {
196+
continue;
217197
}
198+
199+
$context->markConstraintAsValidated($node->cacheKey, $constraintHash);
218200
}
219201

220202
$validator = $this->validatorFactory->getInstance($constraint);

src/Symfony/Component/Validator/Tests/Node/ClassNodeTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@ public function testConstructorExpectsObject()
2626
{
2727
$metadata = $this->getMock('Symfony\Component\Validator\Mapping\ClassMetadataInterface');
2828

29-
new ClassNode('foobar', $metadata, '', array(), array());
29+
new ClassNode('foobar', null, $metadata, '', array(), array());
3030
}
3131
}

src/Symfony/Component/Validator/Tests/NodeTraverser/NonRecursiveNodeTraverserTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ protected function setUp()
4040

4141
public function testVisitorsMayPreventTraversal()
4242
{
43-
$nodes = array(new GenericNode('value', new GenericMetadata(), '', array('Default')));
43+
$nodes = array(new GenericNode('value', null, new GenericMetadata(), '', array('Default')));
4444
$context = $this->getMock('Symfony\Component\Validator\Context\ExecutionContextInterface');
4545

4646
$visitor1 = $this->getMock('Symfony\Component\Validator\NodeVisitor\NodeVisitorInterface');

0 commit comments

Comments
 (0)