src/Core/System/Salutation/SalesChannel/CachedSalutationRoute.php line 60

  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\System\Salutation\SalesChannel;
  3. use Shopware\Core\Framework\Adapter\Cache\AbstractCacheTracer;
  4. use Shopware\Core\Framework\Adapter\Cache\CacheValueCompressor;
  5. use Shopware\Core\Framework\DataAbstractionLayer\Cache\EntityCacheKeyGenerator;
  6. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  7. use Shopware\Core\Framework\Log\Package;
  8. use Shopware\Core\Framework\Util\Json;
  9. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  10. use Shopware\Core\System\SalesChannel\StoreApiResponse;
  11. use Shopware\Core\System\Salutation\Event\SalutationRouteCacheKeyEvent;
  12. use Shopware\Core\System\Salutation\Event\SalutationRouteCacheTagsEvent;
  13. use Symfony\Component\HttpFoundation\Request;
  14. use Symfony\Component\Routing\Annotation\Route;
  15. use Symfony\Contracts\Cache\CacheInterface;
  16. use Symfony\Contracts\Cache\ItemInterface;
  17. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  18. #[Route(defaults: ['_routeScope' => ['store-api']])]
  19. #[Package('customer-order')]
  20. class CachedSalutationRoute extends AbstractSalutationRoute
  21. {
  22.     final public const ALL_TAG 'salutation-route';
  23.     /**
  24.      * @internal
  25.      *
  26.      * @param AbstractCacheTracer<SalutationRouteResponse> $tracer
  27.      * @param array<string> $states
  28.      */
  29.     public function __construct(private readonly AbstractSalutationRoute $decorated, private readonly CacheInterface $cache, private readonly EntityCacheKeyGenerator $generator, private readonly AbstractCacheTracer $tracer, private readonly EventDispatcherInterface $dispatcher, private readonly array $states)
  30.     {
  31.     }
  32.     public static function buildName(): string
  33.     {
  34.         return 'salutation-route';
  35.     }
  36.     public function getDecorated(): AbstractSalutationRoute
  37.     {
  38.         return $this->decorated;
  39.     }
  40.     #[Route(path'/store-api/salutation'name'store-api.salutation'methods: ['GET''POST'], defaults: ['_entity' => 'salutation'])]
  41.     public function load(Request $requestSalesChannelContext $contextCriteria $criteria): SalutationRouteResponse
  42.     {
  43.         if ($context->hasState(...$this->states)) {
  44.             return $this->getDecorated()->load($request$context$criteria);
  45.         }
  46.         $key $this->generateKey($request$context$criteria);
  47.         if ($key === null) {
  48.             return $this->getDecorated()->load($request$context$criteria);
  49.         }
  50.         $value $this->cache->get($key, function (ItemInterface $item) use ($request$context$criteria) {
  51.             $name self::buildName();
  52.             $response $this->tracer->trace($name, fn () => $this->getDecorated()->load($request$context$criteria));
  53.             $item->tag($this->generateTags($request$response$context$criteria));
  54.             return CacheValueCompressor::compress($response);
  55.         });
  56.         return CacheValueCompressor::uncompress($value);
  57.     }
  58.     private function generateKey(Request $requestSalesChannelContext $contextCriteria $criteria): ?string
  59.     {
  60.         $parts = [
  61.             $this->generator->getCriteriaHash($criteria),
  62.             $this->generator->getSalesChannelContextHash($context),
  63.         ];
  64.         $event = new SalutationRouteCacheKeyEvent($parts$request$context$criteria);
  65.         $this->dispatcher->dispatch($event);
  66.         if (!$event->shouldCache()) {
  67.             return null;
  68.         }
  69.         return self::buildName() . '-' md5((string) Json::encode($event->getParts()));
  70.     }
  71.     /**
  72.      * @return array<string>
  73.      */
  74.     private function generateTags(Request $requestStoreApiResponse $responseSalesChannelContext $contextCriteria $criteria): array
  75.     {
  76.         $tags array_merge(
  77.             $this->tracer->get(self::buildName()),
  78.             [self::ALL_TAG]
  79.         );
  80.         $event = new SalutationRouteCacheTagsEvent($tags$request$response$context$criteria);
  81.         $this->dispatcher->dispatch($event);
  82.         return array_unique(array_filter($event->getTags()));
  83.     }
  84. }