Skip to content

Commit 57e3a0f

Browse files
committed
fix: move isCacheKeySafe from GraphQL to AbstractItemNormalizer
1 parent 35577f7 commit 57e3a0f

File tree

2 files changed

+37
-38
lines changed

2 files changed

+37
-38
lines changed

src/GraphQl/Serializer/ItemNormalizer.php

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
use ApiPlatform\Metadata\ResourceAccessCheckerInterface;
2525
use ApiPlatform\Metadata\ResourceClassResolverInterface;
2626
use ApiPlatform\Metadata\Util\ClassInfoTrait;
27-
use ApiPlatform\Serializer\CacheKeyTrait;
2827
use ApiPlatform\Serializer\ItemNormalizer as BaseItemNormalizer;
2928
use Psr\Log\LoggerInterface;
3029
use Psr\Log\NullLogger;
@@ -40,15 +39,12 @@
4039
*/
4140
final class ItemNormalizer extends BaseItemNormalizer
4241
{
43-
use CacheKeyTrait;
4442
use ClassInfoTrait;
4543

4644
public const FORMAT = 'graphql';
4745
public const ITEM_RESOURCE_CLASS_KEY = '#itemResourceClass';
4846
public const ITEM_IDENTIFIERS_KEY = '#itemIdentifiers';
4947

50-
private array $safeCacheKeysCache = [];
51-
5248
public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, IriConverterInterface $iriConverter, private readonly IdentifiersExtractorInterface $identifiersExtractor, ResourceClassResolverInterface $resourceClassResolver, ?PropertyAccessorInterface $propertyAccessor = null, ?NameConverterInterface $nameConverter = null, ?ClassMetadataFactoryInterface $classMetadataFactory = null, ?LoggerInterface $logger = null, ?ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, ?ResourceAccessCheckerInterface $resourceAccessChecker = null)
5349
{
5450
parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $iriConverter, $resourceClassResolver, $propertyAccessor, $nameConverter, $classMetadataFactory, $logger ?: new NullLogger(), $resourceMetadataCollectionFactory, $resourceAccessChecker);
@@ -90,12 +86,6 @@ public function normalize(mixed $data, ?string $format = null, array $context =
9086
return parent::normalize($data, $format, $context);
9187
}
9288

93-
if ($this->isCacheKeySafe($context)) {
94-
$context['cache_key'] = $this->getCacheKey($format, $context);
95-
} else {
96-
$context['cache_key'] = false;
97-
}
98-
9989
unset($context['operation_name'], $context['operation']); // Remove operation and operation_name only when cache key has been created
10090
$normalizedData = parent::normalize($data, $format, $context);
10191
if (!\is_array($normalizedData)) {
@@ -161,32 +151,4 @@ protected function setAttributeValue(object $object, string $attribute, mixed $v
161151

162152
parent::setAttributeValue($object, $attribute, $value, $format, $context);
163153
}
164-
165-
/**
166-
* Check if any property contains a security grants, which makes the cache key not safe,
167-
* as allowed_properties can differ for 2 instances of the same object.
168-
*/
169-
private function isCacheKeySafe(array $context): bool
170-
{
171-
if (!isset($context['resource_class']) || !$this->resourceClassResolver->isResourceClass($context['resource_class'])) {
172-
return false;
173-
}
174-
$resourceClass = $this->resourceClassResolver->getResourceClass(null, $context['resource_class']);
175-
if (isset($this->safeCacheKeysCache[$resourceClass])) {
176-
return $this->safeCacheKeysCache[$resourceClass];
177-
}
178-
$options = $this->getFactoryOptions($context);
179-
$propertyNames = $this->propertyNameCollectionFactory->create($resourceClass, $options);
180-
181-
$this->safeCacheKeysCache[$resourceClass] = true;
182-
foreach ($propertyNames as $propertyName) {
183-
$propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $propertyName, $options);
184-
if (null !== $propertyMetadata->getSecurity()) {
185-
$this->safeCacheKeysCache[$resourceClass] = false;
186-
break;
187-
}
188-
}
189-
190-
return $this->safeCacheKeysCache[$resourceClass];
191-
}
192154
}

src/Serializer/AbstractItemNormalizer.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
*/
6161
abstract class AbstractItemNormalizer extends AbstractObjectNormalizer
6262
{
63+
use CacheKeyTrait;
6364
use ClassInfoTrait;
6465
use CloneTrait;
6566
use ContextTrait;
@@ -76,6 +77,8 @@ abstract class AbstractItemNormalizer extends AbstractObjectNormalizer
7677
protected array $localFactoryOptionsCache = [];
7778
protected ?ResourceAccessCheckerInterface $resourceAccessChecker;
7879

80+
private array $safeCacheKeysCache = [];
81+
7982
public function __construct(protected PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, protected PropertyMetadataFactoryInterface $propertyMetadataFactory, protected IriConverterInterface $iriConverter, protected ResourceClassResolverInterface $resourceClassResolver, ?PropertyAccessorInterface $propertyAccessor = null, ?NameConverterInterface $nameConverter = null, ?ClassMetadataFactoryInterface $classMetadataFactory = null, array $defaultContext = [], ?ResourceMetadataCollectionFactoryInterface $resourceMetadataCollectionFactory = null, ?ResourceAccessCheckerInterface $resourceAccessChecker = null, protected ?TagCollectorInterface $tagCollector = null, protected ?OperationResourceClassResolverInterface $operationResourceResolver = null)
8083
{
8184
if (!isset($defaultContext['circular_reference_handler'])) {
@@ -188,6 +191,12 @@ public function normalize(mixed $data, ?string $format = null, array $context =
188191
$context['resources'][$iri] = $iri;
189192
}
190193

194+
if ($this->isCacheKeySafe($context)) {
195+
$context['cache_key'] = $this->getCacheKey($format, $context);
196+
} else {
197+
$context['cache_key'] = false;
198+
}
199+
191200
$context['object'] = $data;
192201
$context['format'] = $format;
193202

@@ -536,6 +545,34 @@ protected function canAccessAttributePostDenormalize(?object $object, ?object $p
536545
return true;
537546
}
538547

548+
/**
549+
* Check if any property contains a security grants, which makes the cache key not safe,
550+
* as allowed_properties can differ for 2 instances of the same object.
551+
*/
552+
private function isCacheKeySafe(array $context): bool
553+
{
554+
if (!isset($context['resource_class']) || !$this->resourceClassResolver->isResourceClass($context['resource_class'])) {
555+
return false;
556+
}
557+
$resourceClass = $this->resourceClassResolver->getResourceClass(null, $context['resource_class']);
558+
if (isset($this->safeCacheKeysCache[$resourceClass])) {
559+
return $this->safeCacheKeysCache[$resourceClass];
560+
}
561+
$options = $this->getFactoryOptions($context);
562+
$propertyNames = $this->propertyNameCollectionFactory->create($resourceClass, $options);
563+
564+
$this->safeCacheKeysCache[$resourceClass] = true;
565+
foreach ($propertyNames as $propertyName) {
566+
$propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $propertyName, $options);
567+
if (null !== $propertyMetadata->getSecurity()) {
568+
$this->safeCacheKeysCache[$resourceClass] = false;
569+
break;
570+
}
571+
}
572+
573+
return $this->safeCacheKeysCache[$resourceClass];
574+
}
575+
539576
/**
540577
* {@inheritdoc}
541578
*/

0 commit comments

Comments
 (0)