8000 [Validator] New NodeTraverser implementation by webmozart · Pull Request #10287 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Validator] New NodeTraverser implementation #10287

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 86 commits into from
Mar 31, 2014
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
25cdc68
[Validator] Refactored ValidatorTest and ValidationVisitorTest into a…
webmozart Feb 12, 2014
a6ed4ca
[Validator] Prototype of the traverser implementation
webmozart Feb 17, 2014
a40189c 8000
[Validator] Decoupled the new classes a bit
webmozart Feb 17, 2014
7e3a41d
[Validator] Moved visitors to NodeVisitor namespace
webmozart Feb 17, 2014
b1a9477
[Validator] Added ObjectInitializer visitor
webmozart Feb 17, 2014
1156bde
[Validator] Extracted code for group sequence resolving into GroupSeq…
webmozart Feb 17, 2014
321d5bb
[Validator] Throw exception if ObjectInitializer is constructed witho…
webmozart Feb 17, 2014
680f1ee
[Validator] Renamed $params to $parameters
webmozart Feb 17, 2014
8ae68c9
[Validator] Made tests green (yay!)
webmozart Feb 18, 2014
c1b1e03
[Validator] Added TODO reminder
webmozart Feb 18, 2014
5fbf848
[Validator] Added note about Callback constraint to CHANGELOG
webmozart Feb 18, 2014
8318286
[Validator] Completed GroupSequence implementation
webmozart Feb 18, 2014
f6b7288
[Validator] Removed unused use statement
webmozart Feb 18, 2014
4ea3ff6
[Validator] Finished inline documentation of ExecutionContext[Interface]
webmozart Feb 18, 2014
adc1437
[Validator] Fixed failing tests
webmozart Feb 18, 2014
499b2bb
[Validator] Completed test coverage of ExecutionContext
webmozart Feb 18, 2014
405a03b
[Validator] Updated deprecation notes in GroupSequence
webmozart Feb 18, 2014
9b07b0c
[Validator] Implemented BC validation of arrays through validate()
webmozart Feb 18, 2014
297ba4f
[Validator] Added a note why scalars are passed to cascadeObject() in…
webmozart Feb 18, 2014
09f744b
[Validator] Implemented BC traversal of traversables through validate()
webmozart Feb 18, 2014
ee1adad
[Validator] Implemented handling of arrays and Traversables in Legacy…
webmozart Feb 19, 2014
718601c
[Validator] Changed validateValue() to validate() in the new API
webmozart Feb 19, 2014
feb3d6f
[Validator] Tested the validation in a separate context
webmozart Feb 19, 2014
1e81f3b
[Validator] Finished test coverage and documentation of ExecutionCont…
webmozart Feb 19, 2014
9c9e715
[Validator] Completed documentation of GroupManagerInterface
webmozart Feb 19, 2014
2c65a28
[Validator] Completed test coverage and documentation of the Node cla…
webmozart Feb 19, 2014
a3555fb
[Validator] Fixed: Objects are not traversed unless they are instance…
webmozart Feb 19, 2014
bc29591
[Validator] Clearly separated classes supporting the API <2.5/2.5+
webmozart Feb 19, 2014
26eafa4
[Validator] Removed unused use statements
webmozart Feb 19, 2014
df41974
[Validator] Changed context manager to context factory
webmozart Feb 19, 2014
e440690
[Validator] Renamed validateCollection() to validateObjects()
webmozart Feb 19, 2014
e057b19
[Validator] Decoupled ContextRefresher from ExecutionContext
webmozart Feb 19, 2014
230f2a7
[Validator] Fixed exception message
webmozart Feb 19, 2014
cf1281f
[Validator] Added "Visitor" suffix to all node visitors
webmozart Feb 20, 2014
94583a9
[Validator] Changed NodeTraverser to traverse nodes iteratively, not …
webmozart Feb 20, 2014
117b1b9
[Validator] Wrapped collections into CollectionNode instances
webmozart Feb 20, 2014
51197f6
[Validator] Made traversal of Traversables consistent
webmozart Feb 20, 2014
08172bf
[Validator] Merged validate(), validateObject() and validateObjects()…
webmozart Feb 20, 2014
aeb6822
[Validator] Improved visitor names
webmozart Feb 20, 2014
4161371
[Validator] Removed unused use statements
webmozart Feb 20, 2014
76d8c9a
[Validator] Fixed typos
webmozart Feb 20, 2014
778ec24
[Validator] Removed helper class Traversal
webmozart Feb 20, 2014
6fc6ecd
[Validator] Fixed tests under PHP<5.3.9
webmozart Feb 20, 2014
2936d10
[Validator] Removed unused use statement
webmozart Feb 20, 2014
e8fa15b
[Validator] Fixed the new validator API under PHP < 5.3.9
webmozart Feb 20, 2014
8558377
[Validator] Added deprecation notes
webmozart Feb 20, 2014
dbce5a2
[Validator] Updated outdated doc blocks
webmozart Feb 20, 2014
822fe47
[Validator] Completed inline documentation of the Node classes and th…
webmozart Feb 21, 2014
186c115
[Validator] Improved test coverage of NonRecursiveNodeTraverser
webmozart Feb 21, 2014
299c2dc
[Validator] Improved test coverage and prevented duplicate validation…
webmozart Feb 21, 2014
be7f055
[Validator] Visitors may now abort the traversal by returning false f…
webmozart Feb 21, 2014
9986f03
[Validator] Added inline documentation for the PropertyPath utility c…
webmozart Feb 21, 2014
524a953
[Validator] Improved inline documentation of the validators
webmozart Feb 21, 2014
9ca61df
[Validator] Improved inline documentation of CascadingStrategy and Tr…
webmozart Feb 21, 2014
01ceeda
[Validator] Improved test coverage of the Traverse constraint
webmozart Feb 21, 2014
79387a7
[Validator] Improved inline documentation of the metadata classes
webmozart Feb 21, 2014
987313d
[Validator] Improved inline documentation of the violation builder
webmozart Feb 21, 2014
93fdff7
[Validator] The supported API versions can now be passed to the Valid…
webmozart Feb 21, 2014
886e05e
[Validator] Removed unused use statement
webmozart Feb 21, 2014
f61d31e
[Validator] Fixed grammar
webmozart Feb 21, 2014
23534ca
[Validator] Added a recursive clone of the new implementation for spe…
webmozart Feb 22, 2014
38e26fb
[Validator] Decoupled RecursiveContextualValidator from Node
webmozart Feb 22, 2014
274d4e6
[Validator] Changed ValidatorBuilder to always use LegacyExecutionCon…
webmozart Mar 11, 2014
eeed509
[Validator] Improved phpdoc of RecursiveValidator
webmozart Mar 11, 2014
5c479d8
[Validator] Simplified validateNodeForGroup
webmozart Mar 11, 2014
eed29d8
[Validator] Improved performance of *ContextualValidator::validate()
webmozart Mar 11, 2014
50bb84d
[Validator] Optimized RecursiveContextualValidator
webmozart Mar 11, 2014
be508e0
[Validator] Merged DefaultGroupReplacingVisitor and ContextUpdateVisi…
webmozart Mar 11, 2014
1622eb3
[Validator] Fixed reference to removed class in ValidatorBuilder
webmozart Mar 11, 2014
94ef21e
[Validator] Optimized use statements
webmozart Mar 17, 2014
73c9cc5
[Validator] Optimized performance by calling spl_object_hash() only o…
webmozart Mar 17, 2014
2f23d97
[Validator] Reduced number of method calls on the execution context
webmozart Mar 17, 2014
029a716
[Validator] Moved logic of replaceDefaultGroup() to validateNode()
webmozart Mar 17, 2014
3183aed
[Validator] Improved performance of cache key generation
webmozart Mar 17, 2014
90c27bb
[Validator] Removed traverser implementation
webmozart Mar 18, 2014
166d71a
[Validator] Removed unused property
webmozart Mar 18, 2014
7bc952d
[Validator] Improved inline documentation of RecursiveContextualValid…
webmozart Mar 18, 2014
1b111d0
[Validator] Fixed typos pointed out by @cordoval
webmozart Mar 18, 2014
0946dbe
[Validator] Adapted CHANGELOG
webmozart Mar 18, 2014
9b204c9
[FrameworkBundle] Implemented configuration to select the desired Val…
webmozart Mar 18, 2014
c5629bb
[Validator] Added getObject() to ExecutionContextInterface
webmozart Mar 18, 2014
3dc2b4d
[Validator] Made "symfony/property-access" an optional dependency
webmozart Mar 18, 2014
0bfde4a
[Validator] Fixed misnamed method calls in FrameworkExtension
webmozart Mar 18, 2014
b1badea
[Validator] Fixed failing CsrfFormLoginTest
webmozart Mar 30, 2014
68d8018
[Validator] Documented changes in the UPGRADE files
webmozart Mar 30, 2014
ca6a722
[Validator] Converted `@deprecate` doc comment into regular doc comment
webmozart Mar 30, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[Validator] Improved performance of cache key generation
  • Loading branch information
webmozart committed Mar 30, 2014
commit 3183aed7cdd669ee6ad6fc4715e820dad1ae46c6
50 changes: 11 additions & 39 deletions src/Symfony/Component/Validator/Context/ExecutionContext.php
8000
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class ExecutionContext implements ExecutionContextInterface
< 8000 span class='blob-code-inner blob-code-marker ' data-code-marker=" "> *
* @var array
*/
private $validatedClassConstraints = array();
private $validatedConstraints = array();

/**
* Stores which property constraint has been validated for which property.
Expand Down Expand Up @@ -319,64 +319,36 @@ public function getMetadataFactory()
/**
* {@inheritdoc}
*/
public function markObjectAsValidatedForGroup($objectHash, $groupHash)
public function markGroupAsValidated($cacheKey, $groupHash)
{
if (!isset($this->validatedObjects[$objectHash])) {
$this->validatedObjects[$objectHash] = array();
if (!isset($this->validatedObjects[$cacheKey])) {
$this->validatedObjects[$cacheKey] = array();
}

$this->validatedObjects[$objectHash][$groupHash] = true;
$this->validatedObjects[$cacheKey][$groupHash] = true;
}

/**
* {@inheritdoc}
*/
public function isObjectValidatedForGroup($objectHash, $groupHash)
public function isGroupValidated($cacheKey, $groupHash)
{
return isset($this->validatedObjects[$objectHash][$groupHash]);
return isset($this->validatedObjects[$cacheKey][$groupHash]);
}

/**
* {@inheritdoc}
*/
public function markClassConstraintAsValidated($objectHash, $constraintHash)
public function markConstraintAsValidated($cacheKey, $constraintHash)
{
if (!isset($this->validatedClassConstraints[$objectHash])) {
$this->validatedClassConstraints[$objectHash] = array();
}

$this->validatedClassConstraints[$objectHash][$constraintHash] = true;
}

/**
* {@inheritdoc}
*/
public function isClassConstraintValidated($objectHash, $constraintHash)
{
return isset($this->validatedClassConstraints[$objectHash][$constraintHash]);
}

/**
* {@inheritdoc}
*/
public function markPropertyConstraintAsValidated($objectHash, $propertyName, $constraintHash)
{
if (!isset($this->validatedPropertyConstraints[$objectHash])) {
$this->validatedPropertyConstraints[$objectHash] = array();
}

if (!isset($this->validatedPropertyConstraints[$objectHash][$propertyName])) {
$this->validatedPropertyConstraints[$objectHash][$propertyName] = array();
}

$this->validatedPropertyConstraints[$objectHash][$propertyName][$constraintHash] = true;
$this->validatedConstraints[$cacheKey.':'.$constraintHash] = true;
}

/**
* {@inheritdoc}
*/
public function isPropertyConstraintValidated($objectHash, $propertyName, $constraintHash)
public function isConstraintValidated($cacheKey, $constraintHash)
{
return isset($this->validatedPropertyConstraints[$objectHash][$propertyName][$constraintHash]);
return isset($this->validatedConstraints[$cacheKey.':'.$constraintHash]);
}
}
< A3E2 td class="blob-code blob-code-deletion js-file-line"> * @param string $objectHash The hash of the object
Original file line number Diff line number Diff line change
Expand Up @@ -124,19 +124,19 @@ public function setGroup($group);
/**
* Marks an object as validated in a specific validation group.
*
* @param string $objectHash The hash of the object
* @param string $cacheKey The hash of the object
* @param string $groupHash The group's name or hash, if it is group
* sequence
*
* @internal Used by the validator engine. Should not be called by user
* code.
*/
public function markObjectAsValidatedForGroup($objectHash, $groupHash);
public function markGroupAsValidated($cacheKey, $groupHash);

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

/**
* Marks a constraint as validated for an object.
*
* @param string $cacheKey The hash of the object
* @param string $constraintHash The hash of the constraint
*
* @internal Used by the validator engine. Should not be called by user
* code.
*/
public function markClassConstraintAsValidated($objectHash, $constraintHash);
public function markConstraintAsValidated($cacheKey, $constraintHash);

/**
* Returns whether a constraint was validated for an object.
*
* @param string $objectHash The hash of the object
* @param string $cacheKey The hash of the object
* @param string $constraintHash The hash of the constraint
*
* @return Boolean Whether the constraint was already validated
*
* @internal Used by the validator engine. Should not be called by user
* code.
*/
public function isClassConstraintValidated($objectHash, $constraintHash);

/**
* Marks a constraint as validated for an object and a property name.
*
* @param string $objectHash The hash of the object
* @param string $propertyName The property name
* @param string $constraintHash The hash of the constraint
*
* @internal Used by the validator engine. Should not be called by user
* code.
*/
public function markPropertyConstraintAsValidated($objectHash, $propertyName, $constraintHash);

/**
* Returns whether a constraint was validated for an object and a property
* name.
*
* @param string $objectHash The hash of the object
* @param string $propertyName The property name
* @param string $constraintHash The hash of the constraint
*
* @return Boolean Whether the constraint was already validated
*
* @internal Used by the validator engine. Should not be called by user
* code.
*/
public function isPropertyConstraintValidated($objectHash, $propertyName, $constraintHash);
public function isConstraintValidated($cacheKey, $constraintHash);
}
8 changes: 4 additions & 4 deletions src/Symfony/Component/Validator/Node/ClassNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,20 +55,20 @@ class ClassNode extends Node
*
* @see \Symfony\Component\Validator\Mapping\TraversalStrategy
*/
public function __construct($object, ClassMetadataInterface $metadata, $propertyPath, array $groups, $cascadedGroups = null, $traversalStrategy = TraversalStrategy::IMPLICIT)
public function __construct($object, $cacheKey, ClassMetadataInterface $metadata, $propertyPath, array $groups, $cascadedGroups = null, $traversalStrategy = TraversalStrategy::IMPLICIT)
{
if (!is_object($object)) {
throw new UnexpectedTypeException($object, 'object');
}

parent::__construct(
$object,
$cacheKey,
$metadata,
$propertyPath,
$groups,
$cascadedGroups
$cascadedGroups,
$traversalStrategy
);

$this->traversalStrategy = $traversalStrategy;
}
}
1 change: 1 addition & 0 deletions src/Symfony/Component/Validator/Node/CollectionNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public function __construct($collection, $propertyPath, array $groups, $cascaded
parent::__construct(
$collection,
null,
null,
$propertyPath,
$groups,
$cascadedGroups,
Expand Down
5 changes: 4 additions & 1 deletion src/Symfony/Component/Validator/Node/Node.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ abstract class Node
*/
public $value;

public $cacheKey;

/**
* The metadata specifying how the value should be validated.
*
Expand Down Expand Up @@ -82,13 +84,14 @@ abstract class Node
*
* @throws UnexpectedTypeException If $cascadedGroups is invalid
*/
public function __construct($value, MetadataInterface $metadata = null, $propertyPath, array $groups, $cascadedGroups = null, $traversalStrategy = TraversalStrategy::IMPLICIT)
public function __construct($value, $cacheKey, MetadataInterface $metadata = null, $propertyPath, array $groups, $cascadedGroups = null, $traversalStrategy = TraversalStrategy::IMPLICIT)
{
if (null !== $cascadedGroups && !is_array($cascadedGroups)) {
throw new UnexpectedTypeException($cascadedGroups, 'null or array');
}

$this->value = $value;
$this->cacheKey = $cacheKey;
$this->metadata = $metadata;
$this->propertyPath = $propertyPath;
$this->groups = $groups;
Expand Down
14 changes: 2 additions & 12 deletions src/Symfony/Component/Validator/Node/PropertyNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,6 @@
*/
class PropertyNode extends Node
{
/**
* @var object
*/
public $object;

/**
* @var PropertyMetadataInterface
*/
Expand All @@ -71,22 +66,17 @@ class PropertyNode extends Node
*
* @see \Symfony\Component\Validator\Mapping\TraversalStrategy
*/
public function __construct($object, $value, PropertyMetadataInterface $metadata, $propertyPath, array $groups, $cascadedGroups = null, $traversalStrategy = TraversalStrategy::IMPLICIT)
public function __construct($value, $cacheKey, PropertyMetadataInterface $metadata, $propertyPath, array $groups, $cascadedGroups = null, $traversalStrategy = TraversalStrategy::IMPLICIT)
{
if (!is_object($object)) {
throw new UnexpectedTypeException($object, 'object');
}

parent::__construct(
$value,
$cacheKey,
$metadata,
$propertyPath,
$groups,
$cascadedGroups,
$traversalStrategy
);

$this->object = $object;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<--

}
Original file line number Diff line number Diff line change
Expand Up @@ -274,8 +274,8 @@ private function traverseClassNode(ClassNode $node, ExecutionContextInterface $c
}

$nodeStack->push(new PropertyNode(
$node->value,
$propertyMetadata->getPropertyValue($node->value),
$node->cacheKey.':'.$propertyName,
$propertyMetadata,
$node->propertyPath
? $node->propertyPath.'.'.$propertyName
Expand Down Expand Up @@ -530,6 +530,7 @@ private function cascadeObject($object, $propertyPath, array $groups, $traversal

$nodeStack->push(new ClassNode(
$object,
spl_object_hash($object),
$classMetadata,
$propertyPath,
$groups,
Expand Down
< 179B td class="blob-code blob-code-addition js-file-line"> if ($context->isGroupValidated($node->cacheKey, $groupHash)) {
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,6 @@ public function visit(Node $node, ExecutionContextInterface $context)

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

if ($node instanceof ClassNode) {
$objectHash = spl_object_hash($node->value);
} elseif ($node instanceof PropertyNode) {
$objectHash = spl_object_hash($node->object);
} else {
$objectHash = null;
}

// if group (=[<G1,G2>,G3,G4]) contains group sequence (=<G1,G2>)
// then call traverse() with each entry of the group sequence and abort
// if necessary (G1, G2)
Expand All @@ -97,15 +89,15 @@ public function visit(Node $node, ExecutionContextInterface $context)
// Use the object hash for group sequences
$groupHash = is_object($group) ? spl_object_hash($group) : $group;

if ($context->isObjectValidatedForGroup($objectHash, $groupHash)) {
// Skip this group when validating the successor nodes
// (property and/or collection nodes)
unset($node->groups[$key]);

continue;
}

$context->markObjectAsValidatedForGroup($objectHash, $groupHash);
$context->markGroupAsValidated($node->cacheKey, $groupHash);

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

// Validate normal group
$this->validateNodeForGroup($node, $group, $context, $objectHash);
$this->validateInGroup($node, $group, $context);
}

return true;
Expand Down Expand Up @@ -190,31 +182,21 @@ private function traverseGroupSequence(Node $node, GroupSequence $groupSequence,
*
* @throws \Exception
*/
private function validateNodeForGroup(Node $node, $group, ExecutionContextInterface $context, $objectHash)
private function validateInGroup(Node $node, $group, ExecutionContextInterface $context)
{
$context->setGroup($group);

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

if ($node instanceof ClassNode) {
if ($context->isClassConstraintValidated($objectHash, $constraintHash)) {
continue;
}

$context->markClassConstraintAsValidated($objectHash, $constraintHash);
} elseif ($node instanceof PropertyNode) {
$propertyName = $node->metadata->getPropertyName();

if ($context->isPropertyConstraintValidated($objectHash, $propertyName, $constraintHash)) {
continue;
}

$context->markPropertyConstraintAsValidated($objectHash, $propertyName, $constraintHash);
if ($context->isConstraintValidated($node->cacheKey, $constraintHash)) {
continue;
}

$context->markConstraintAsValidated($node->cacheKey, $constraintHash);
}

$validator = $this->validatorFactory->getInstance($constraint);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ public function testConstructorExpectsObject()
{
$metadata = $this->getMock('Symfony\Component\Validator\Mapping\ClassMetadataInterface');

new ClassNode('foobar', $metadata, '', array(), array());
new ClassNode('foobar', null, $metadata, '', array(), array());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ protected function setUp()

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

$visitor1 = $this->getMock('Symfony\Component\Validator\NodeVisitor\NodeVisitorInterface');
Expand Down
Loading
0