vendor/shopware/core/Checkout/Shipping/SalesChannel/CachedShippingMethodRoute.php line 70

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