vendor/shopware/core/Content/Sitemap/SalesChannel/CachedSitemapRoute.php line 89

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Content\Sitemap\SalesChannel;
  3. use Shopware\Core\Content\Sitemap\Event\SitemapRouteCacheKeyEvent;
  4. use Shopware\Core\Content\Sitemap\Event\SitemapRouteCacheTagsEvent;
  5. use Shopware\Core\Content\Sitemap\Service\SitemapExporterInterface;
  6. use Shopware\Core\Framework\Adapter\Cache\AbstractCacheTracer;
  7. use Shopware\Core\Framework\Adapter\Cache\CacheValueCompressor;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Cache\EntityCacheKeyGenerator;
  9. use Shopware\Core\Framework\DataAbstractionLayer\FieldSerializer\JsonFieldSerializer;
  10. use Shopware\Core\Framework\Log\Package;
  11. use Shopware\Core\Framework\Routing\Annotation\RouteScope;
  12. use Shopware\Core\Framework\Routing\Annotation\Since;
  13. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  14. use Shopware\Core\System\SystemConfig\SystemConfigService;
  15. use Symfony\Component\HttpFoundation\Request;
  16. use Symfony\Component\Routing\Annotation\Route;
  17. use Symfony\Contracts\Cache\CacheInterface;
  18. use Symfony\Contracts\Cache\ItemInterface;
  19. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  20. /**
  21.  * @Route(defaults={"_routeScope"={"store-api"}})
  22.  */
  23. #[Package('sales-channel')]
  24. class CachedSitemapRoute extends AbstractSitemapRoute
  25. {
  26.     public const ALL_TAG 'sitemap-route';
  27.     private AbstractSitemapRoute $decorated;
  28.     private CacheInterface $cache;
  29.     private EntityCacheKeyGenerator $generator;
  30.     /**
  31.      * @var AbstractCacheTracer<SitemapRouteResponse>
  32.      */
  33.     private AbstractCacheTracer $tracer;
  34.     /**
  35.      * @var array<string>
  36.      */
  37.     private array $states;
  38.     private EventDispatcherInterface $dispatcher;
  39.     private SystemConfigService $config;
  40.     /**
  41.      * @internal
  42.      *
  43.      *  @param AbstractCacheTracer<SitemapRouteResponse> $tracer
  44.      *  @param array<string> $states
  45.      */
  46.     public function __construct(
  47.         AbstractSitemapRoute $decorated,
  48.         CacheInterface $cache,
  49.         EntityCacheKeyGenerator $generator,
  50.         AbstractCacheTracer $tracer,
  51.         EventDispatcherInterface $dispatcher,
  52.         array $states,
  53.         SystemConfigService $config
  54.     ) {
  55.         $this->decorated $decorated;
  56.         $this->cache $cache;
  57.         $this->generator $generator;
  58.         $this->tracer $tracer;
  59.         $this->states $states;
  60.         $this->dispatcher $dispatcher;
  61.         $this->config $config;
  62.     }
  63.     public static function buildName(string $id): string
  64.     {
  65.         return 'sitemap-route-' $id;
  66.     }
  67.     public function getDecorated(): AbstractSitemapRoute
  68.     {
  69.         return $this->decorated;
  70.     }
  71.     /**
  72.      * @Since("6.3.2.0")
  73.      * @Route(path="/store-api/sitemap", name="store-api.sitemap", methods={"GET", "POST"})
  74.      */
  75.     public function load(Request $requestSalesChannelContext $context): SitemapRouteResponse
  76.     {
  77.         if ($context->hasState(...$this->states)) {
  78.             return $this->getDecorated()->load($request$context);
  79.         }
  80.         $strategy $this->config->getInt('core.sitemap.sitemapRefreshStrategy');
  81.         if ($strategy === SitemapExporterInterface::STRATEGY_LIVE) {
  82.             return $this->getDecorated()->load($request$context);
  83.         }
  84.         $key $this->generateKey($request$context);
  85.         if ($key === null) {
  86.             return $this->getDecorated()->load($request$context);
  87.         }
  88.         $value $this->cache->get($key, function (ItemInterface $item) use ($request$context) {
  89.             $name self::buildName($context->getSalesChannelId());
  90.             $response $this->tracer->trace($name, function () use ($request$context) {
  91.                 return $this->getDecorated()->load($request$context);
  92.             });
  93.             $item->tag($this->generateTags($response$request$context));
  94.             return CacheValueCompressor::compress($response);
  95.         });
  96.         return CacheValueCompressor::uncompress($value);
  97.     }
  98.     private function generateKey(Request $requestSalesChannelContext $context): ?string
  99.     {
  100.         $parts = [$this->generator->getSalesChannelContextHash($context)];
  101.         $event = new SitemapRouteCacheKeyEvent($parts$request$contextnull);
  102.         $this->dispatcher->dispatch($event);
  103.         if (!$event->shouldCache()) {
  104.             return null;
  105.         }
  106.         return self::buildName($context->getSalesChannelId()) . '-' md5(JsonFieldSerializer::encodeJson($event->getParts()));
  107.     }
  108.     /**
  109.      * @return array<string>
  110.      */
  111.     private function generateTags(SitemapRouteResponse $responseRequest $requestSalesChannelContext $context): array
  112.     {
  113.         $tags array_merge(
  114.             $this->tracer->get(self::buildName($context->getSalesChannelId())),
  115.             [self::buildName($context->getSalesChannelId()), self::ALL_TAG]
  116.         );
  117.         $event = new SitemapRouteCacheTagsEvent($tags$request$response$contextnull);
  118.         $this->dispatcher->dispatch($event);
  119.         return array_unique(array_filter($event->getTags()));
  120.     }
  121. }