minor #20529 [Serializer] Optimize max depth checking (dunglas)

This PR was merged into the 3.1 branch.

Discussion
----------

[Serializer] Optimize max depth checking

| Q             | A
| ------------- | ---
| Branch?       | 3.1
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes/no
| Fixed tickets | n/a
| License       | MIT
| Doc PR        | n/a

Avoid to call the metadata factory for each attribute when max depth checking is enabled.
Prepare the code for the "serialized name" feature (that also requires metadata) in Symfony 3.3.

Commits
-------

bb3ee76 [Serializer] Optimize max depth checking
This commit is contained in:
Fabien Potencier 2016-12-13 10:15:55 +01:00
commit e55f79b5c6

View File

@ -17,6 +17,7 @@ use Symfony\Component\Serializer\Exception\LogicException;
use Symfony\Component\Serializer\Exception\UnexpectedValueException;
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
use Symfony\Component\PropertyInfo\Type;
use Symfony\Component\Serializer\Mapping\AttributeMetadataInterface;
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
@ -67,9 +68,10 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
$stack = array();
$attributes = $this->getAttributes($object, $format, $context);
$class = get_class($object);
$attributesMetadata = $this->classMetadataFactory ? $this->classMetadataFactory->getMetadataFor($class)->getAttributesMetadata() : null;
foreach ($attributes as $attribute) {
if ($this->isMaxDepthReached($class, $attribute, $context)) {
if (null !== $attributesMetadata && $this->isMaxDepthReached($attributesMetadata, $class, $attribute, $context)) {
continue;
}
@ -289,42 +291,35 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
/**
* Is the max depth reached for the given attribute?
*
* @param string $class
* @param string $attribute
* @param array $context
* @param AttributeMetadataInterface[] $attributesMetadata
* @param string $class
* @param string $attribute
* @param array $context
*
* @return bool
*/
private function isMaxDepthReached($class, $attribute, array &$context)
private function isMaxDepthReached(array $attributesMetadata, $class, $attribute, array &$context)
{
if (!$this->classMetadataFactory || !isset($context[static::ENABLE_MAX_DEPTH])) {
return false;
}
$classMetadata = $this->classMetadataFactory->getMetadataFor($class);
$attributesMetadata = $classMetadata->getAttributesMetadata();
if (!isset($attributesMetadata[$attribute])) {
return false;
}
$maxDepth = $attributesMetadata[$attribute]->getMaxDepth();
if (null === $maxDepth) {
if (
!isset($context[static::ENABLE_MAX_DEPTH]) ||
!isset($attributesMetadata[$attribute]) ||
null === $maxDepth = $attributesMetadata[$attribute]->getMaxDepth()
) {
return false;
}
$key = sprintf(static::DEPTH_KEY_PATTERN, $class, $attribute);
$keyExist = isset($context[$key]);
if (!isset($context[$key])) {
$context[$key] = 1;
if ($keyExist && $context[$key] === $maxDepth) {
return false;
}
if ($context[$key] === $maxDepth) {
return true;
}
if ($keyExist) {
++$context[$key];
} else {
$context[$key] = 1;
}
++$context[$key];
return false;
}