vendor/shopware/core/System/Salutation/SalesChannel/CachedSalutationRoute.php line 74

  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(
  30.         private readonly AbstractSalutationRoute $decorated,
  31.         private readonly CacheInterface $cache,
  32.         private readonly EntityCacheKeyGenerator $generator,
  33.         private readonly AbstractCacheTracer $tracer,
  34.         private readonly EventDispatcherInterface $dispatcher,
  35.         private readonly array $states
  36.     ) {
  37.     }
  38.     public static function buildName(): string
  39.     {
  40.         return 'salutation-route';
  41.     }
  42.     public function getDecorated(): AbstractSalutationRoute
  43.     {
  44.         return $this->decorated;
  45.     }
  46.     #[Route(path'/store-api/salutation'name'store-api.salutation'methods: ['GET''POST'], defaults: ['_entity' => 'salutation'])]
  47.     public function load(Request $requestSalesChannelContext $contextCriteria $criteria): SalutationRouteResponse
  48.     {
  49.         if ($context->hasState(...$this->states)) {
  50.             return $this->getDecorated()->load($request$context$criteria);
  51.         }
  52.         $key $this->generateKey($request$context$criteria);
  53.         if ($key === null) {
  54.             return $this->getDecorated()->load($request$context$criteria);
  55.         }
  56.         $value $this->cache->get($key, function (ItemInterface $item) use ($request$context$criteria) {
  57.             $name self::buildName();
  58.             $response $this->tracer->trace($name, fn () => $this->getDecorated()->load($request$context$criteria));
  59.             $item->tag($this->generateTags($request$response$context$criteria));
  60.             return CacheValueCompressor::compress($response);
  61.         });
  62.         return CacheValueCompressor::uncompress($value);
  63.     }
  64.     private function generateKey(Request $requestSalesChannelContext $contextCriteria $criteria): ?string
  65.     {
  66.         $parts = [
  67.             $this->generator->getCriteriaHash($criteria),
  68.             $this->generator->getSalesChannelContextHash($context),
  69.         ];
  70.         $event = new SalutationRouteCacheKeyEvent($parts$request$context$criteria);
  71.         $this->dispatcher->dispatch($event);
  72.         if (!$event->shouldCache()) {
  73.             return null;
  74.         }
  75.         return self::buildName() . '-' md5((string) Json::encode($event->getParts()));
  76.     }
  77.     /**
  78.      * @return array<string>
  79.      */
  80.     private function generateTags(Request $requestStoreApiResponse $responseSalesChannelContext $contextCriteria $criteria): array
  81.     {
  82.         $tags array_merge(
  83.             $this->tracer->get(self::buildName()),
  84.             [self::ALL_TAG]
  85.         );
  86.         $event = new SalutationRouteCacheTagsEvent($tags$request$response$context$criteria);
  87.         $this->dispatcher->dispatch($event);
  88.         return array_unique(array_filter($event->getTags()));
  89.     }
  90. }