vendor/shopware/core/Content/Product/SalesChannel/Search/CachedProductSearchRoute.php line 79

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Content\Product\SalesChannel\Search;
  3. use Shopware\Core\Content\Product\Events\ProductSearchRouteCacheKeyEvent;
  4. use Shopware\Core\Content\Product\Events\ProductSearchRouteCacheTagsEvent;
  5. use Shopware\Core\Framework\Adapter\Cache\AbstractCacheTracer;
  6. use Shopware\Core\Framework\Adapter\Cache\CacheValueCompressor;
  7. use Shopware\Core\Framework\DataAbstractionLayer\Cache\EntityCacheKeyGenerator;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\RuleAreas;
  9. use Shopware\Core\Framework\DataAbstractionLayer\FieldSerializer\JsonFieldSerializer;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  11. use Shopware\Core\Framework\Log\Package;
  12. use Shopware\Core\Framework\Routing\Annotation\Entity;
  13. use Shopware\Core\Framework\Routing\Annotation\Since;
  14. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  15. use Shopware\Core\System\SalesChannel\StoreApiResponse;
  16. use Symfony\Component\HttpFoundation\Request;
  17. use Symfony\Component\Routing\Annotation\Route;
  18. use Symfony\Contracts\Cache\CacheInterface;
  19. use Symfony\Contracts\Cache\ItemInterface;
  20. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  21. #[Package('system-settings')]
  22. class CachedProductSearchRoute extends AbstractProductSearchRoute
  23. {
  24.     private const NAME 'product-search-route';
  25.     private AbstractProductSearchRoute $decorated;
  26.     private CacheInterface $cache;
  27.     private EntityCacheKeyGenerator $generator;
  28.     /**
  29.      * @var AbstractCacheTracer<ProductSearchRouteResponse>
  30.      */
  31.     private AbstractCacheTracer $tracer;
  32.     /**
  33.      * @var array<string>
  34.      */
  35.     private array $states;
  36.     private EventDispatcherInterface $dispatcher;
  37.     /**
  38.      * @internal
  39.      *
  40.      * @param AbstractCacheTracer<ProductSearchRouteResponse> $tracer
  41.      * @param array<string> $states
  42.      */
  43.     public function __construct(
  44.         AbstractProductSearchRoute $decorated,
  45.         CacheInterface $cache,
  46.         EntityCacheKeyGenerator $generator,
  47.         AbstractCacheTracer $tracer,
  48.         EventDispatcherInterface $dispatcher,
  49.         array $states
  50.     ) {
  51.         $this->decorated $decorated;
  52.         $this->cache $cache;
  53.         $this->generator $generator;
  54.         $this->tracer $tracer;
  55.         $this->states $states;
  56.         $this->dispatcher $dispatcher;
  57.     }
  58.     public function getDecorated(): AbstractProductSearchRoute
  59.     {
  60.         return $this->decorated;
  61.     }
  62.     /**
  63.      * @Since("6.2.0.0")
  64.      * @Entity("product")
  65.      * @Route("/store-api/search", name="store-api.search", methods={"POST"})
  66.      */
  67.     public function load(Request $requestSalesChannelContext $contextCriteria $criteria): ProductSearchRouteResponse
  68.     {
  69.         if ($context->hasState(...$this->states)) {
  70.             return $this->getDecorated()->load($request$context$criteria);
  71.         }
  72.         $key $this->generateKey($request$context$criteria);
  73.         if ($key === null) {
  74.             return $this->getDecorated()->load($request$context$criteria);
  75.         }
  76.         $value $this->cache->get($key, function (ItemInterface $item) use ($request$context$criteria) {
  77.             $response $this->tracer->trace(self::NAME, function () use ($request$context$criteria) {
  78.                 return $this->getDecorated()->load($request$context$criteria);
  79.             });
  80.             $item->tag($this->generateTags($request$response$context$criteria));
  81.             return CacheValueCompressor::compress($response);
  82.         });
  83.         return CacheValueCompressor::uncompress($value);
  84.     }
  85.     private function generateKey(Request $requestSalesChannelContext $contextCriteria $criteria): ?string
  86.     {
  87.         $parts = [
  88.             $this->generator->getCriteriaHash($criteria),
  89.             $this->generator->getSalesChannelContextHash($context, [RuleAreas::PRODUCT_AREA]),
  90.             $request->get('search'),
  91.         ];
  92.         $event = new ProductSearchRouteCacheKeyEvent($parts$request$context$criteria);
  93.         $this->dispatcher->dispatch($event);
  94.         if (!$event->shouldCache()) {
  95.             return null;
  96.         }
  97.         return self::NAME '-' md5(JsonFieldSerializer::encodeJson($event->getParts()));
  98.     }
  99.     /**
  100.      * @return array<string>
  101.      */
  102.     private function generateTags(Request $requestStoreApiResponse $responseSalesChannelContext $contextCriteria $criteria): array
  103.     {
  104.         $tags array_merge(
  105.             $this->tracer->get(self::NAME),
  106.             [self::NAME]
  107.         );
  108.         $event = new ProductSearchRouteCacheTagsEvent($tags$request$response$context$criteria);
  109.         $this->dispatcher->dispatch($event);
  110.         return array_unique(array_filter($event->getTags()));
  111.     }
  112. }