bug #25185 [Serializer] Do not cache attributes if attributes in context (sroze)

This PR was merged into the 3.3 branch.

Discussion
----------

[Serializer] Do not cache attributes if `attributes` in context

| Q             | A
| ------------- | ---
| Branch?       | 3.3
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #25108
| License       | MIT
| Doc PR        | ø

Caching attributes based on the class works only when these attributes are not overwritten. This disables the cache when they are.

To me, this `extractAttributes` method should actually be a `AttributeResolver` dependency that can be decorated using different caching strategies I'd say but... that's a much bigger refactoring that needs more reflection with @dunglas.

Commits
-------

6e87382bfa Do not cache cache attributes if `attributes` is in the context
This commit is contained in:
Fabien Potencier 2017-11-28 18:30:17 -08:00
commit 020d78a65b
2 changed files with 35 additions and 0 deletions

View File

@ -126,6 +126,10 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer
return $allowedAttributes;
}
if (isset($context['attributes'])) {
return $this->extractAttributes($object, $format, $context);
}
if (isset($this->attributesCache[$class])) {
return $this->attributesCache[$class];
}

View File

@ -713,6 +713,37 @@ class ObjectNormalizerTest extends TestCase
'inner' => array('foo' => 'foo', 'bar' => 'bar'),
), DummyWithConstructorObjectAndDefaultValue::class, null, $context));
}
public function testNormalizeSameObjectWithDifferentAttributes()
{
$classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()));
$this->normalizer = new ObjectNormalizer($classMetadataFactory);
$serializer = new Serializer(array($this->normalizer));
$this->normalizer->setSerializer($serializer);
$dummy = new ObjectOuter();
$dummy->foo = new ObjectInner();
$dummy->foo->foo = 'foo.foo';
$dummy->foo->bar = 'foo.bar';
$dummy->bar = new ObjectInner();
$dummy->bar->foo = 'bar.foo';
$dummy->bar->bar = 'bar.bar';
$this->assertEquals(array(
'foo' => array(
'bar' => 'foo.bar',
),
'bar' => array(
'foo' => 'bar.foo',
),
), $this->normalizer->normalize($dummy, 'json', array(
'attributes' => array(
'foo' => array('bar'),
'bar' => array('foo'),
),
)));
}
}
class ObjectDummy