vendor/api-platform/core/src/Api/CachedIdentifiersExtractor.php line 60

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the API Platform project.
  4.  *
  5.  * (c) Kévin Dunglas <dunglas@gmail.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. declare(strict_types=1);
  11. namespace ApiPlatform\Core\Api;
  12. use ApiPlatform\Core\Util\ResourceClassInfoTrait;
  13. use Psr\Cache\CacheException;
  14. use Psr\Cache\CacheItemPoolInterface;
  15. use Symfony\Component\PropertyAccess\PropertyAccess;
  16. use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
  17. /**
  18.  * {@inheritdoc}
  19.  *
  20.  * @author Antoine Bluchet <soyuka@gmail.com>
  21.  */
  22. final class CachedIdentifiersExtractor implements IdentifiersExtractorInterface
  23. {
  24.     use ResourceClassInfoTrait;
  25.     public const CACHE_KEY_PREFIX 'iri_identifiers';
  26.     private $cacheItemPool;
  27.     private $propertyAccessor;
  28.     private $decorated;
  29.     private $localCache = [];
  30.     private $localResourceCache = [];
  31.     public function __construct(CacheItemPoolInterface $cacheItemPoolIdentifiersExtractorInterface $decoratedPropertyAccessorInterface $propertyAccessor nullResourceClassResolverInterface $resourceClassResolver null)
  32.     {
  33.         $this->cacheItemPool $cacheItemPool;
  34.         $this->propertyAccessor $propertyAccessor ?? PropertyAccess::createPropertyAccessor();
  35.         $this->decorated $decorated;
  36.         $this->resourceClassResolver $resourceClassResolver;
  37.         if (null === $this->resourceClassResolver) {
  38.             @trigger_error(sprintf('Not injecting %s in the CachedIdentifiersExtractor might introduce cache issues with object identifiers.'ResourceClassResolverInterface::class), \E_USER_DEPRECATED);
  39.         }
  40.     }
  41.     /**
  42.      * {@inheritdoc}
  43.      */
  44.     public function getIdentifiersFromResourceClass(string $resourceClass): array
  45.     {
  46.         if (isset($this->localResourceCache[$resourceClass])) {
  47.             return $this->localResourceCache[$resourceClass];
  48.         }
  49.         return $this->localResourceCache[$resourceClass] = $this->decorated->getIdentifiersFromResourceClass($resourceClass);
  50.     }
  51.     /**
  52.      * {@inheritdoc}
  53.      */
  54.     public function getIdentifiersFromItem($item): array
  55.     {
  56.         $keys $this->getKeys($item, function ($item) use (&$identifiers) {
  57.             return $identifiers $this->decorated->getIdentifiersFromItem($item);
  58.         });
  59.         if (null !== $identifiers) {
  60.             return $identifiers;
  61.         }
  62.         $identifiers = [];
  63.         foreach ($keys as $propertyName) {
  64.             $identifiers[$propertyName] = $this->propertyAccessor->getValue($item$propertyName);
  65.             if (!\is_object($identifiers[$propertyName])) {
  66.                 continue;
  67.             }
  68.             if (null === $relatedResourceClass $this->getResourceClass($identifiers[$propertyName])) {
  69.                 continue;
  70.             }
  71.             if (!$relatedIdentifiers $this->localCache[$relatedResourceClass] ?? false) {
  72.                 $relatedCacheKey self::CACHE_KEY_PREFIX.md5($relatedResourceClass);
  73.                 try {
  74.                     $relatedCacheItem $this->cacheItemPool->getItem($relatedCacheKey);
  75.                     if (!$relatedCacheItem->isHit()) {
  76.                         return $this->decorated->getIdentifiersFromItem($item);
  77.                     }
  78.                 } catch (CacheException $e) {
  79.                     return $this->decorated->getIdentifiersFromItem($item);
  80.                 }
  81.                 $relatedIdentifiers $relatedCacheItem->get();
  82.             }
  83.             $identifiers[$propertyName] = $this->propertyAccessor->getValue($identifiers[$propertyName], $relatedIdentifiers[0]);
  84.         }
  85.         return $identifiers;
  86.     }
  87.     private function getKeys($item, callable $retriever): array
  88.     {
  89.         $resourceClass $this->getObjectClass($item);
  90.         if (isset($this->localCache[$resourceClass])) {
  91.             return $this->localCache[$resourceClass];
  92.         }
  93.         try {
  94.             $cacheItem $this->cacheItemPool->getItem(self::CACHE_KEY_PREFIX.md5($resourceClass));
  95.         } catch (CacheException $e) {
  96.             return $this->localCache[$resourceClass] = array_keys($retriever($item));
  97.         }
  98.         if ($cacheItem->isHit()) {
  99.             return $this->localCache[$resourceClass] = $cacheItem->get();
  100.         }
  101.         $keys array_keys($retriever($item));
  102.         $cacheItem->set($keys);
  103.         $this->cacheItemPool->save($cacheItem);
  104.         return $this->localCache[$resourceClass] = $keys;
  105.     }
  106. }