<?php declare(strict_types=1);
namespace Dvdw\Cache\Framework\Adapter\Cache;
use Dvdw\Cache\System\SalesChannel\AbstractStoreApiResponseTagBuilder;
use Psr\Cache\CacheException;
use Psr\Cache\InvalidArgumentException;
use Shopware\Core\Framework\Adapter\Cache\AbstractCacheTracer;
use Shopware\Core\Framework\Adapter\Cache\CacheValueCompressor;
use Shopware\Core\Framework\DataAbstractionLayer\Cache\EntityCacheKeyGenerator;
use Shopware\Core\Framework\DataAbstractionLayer\FieldSerializer\JsonFieldSerializer;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Core\System\SalesChannel\StoreApiResponse;
use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Contracts\Cache\ItemInterface;
class CacheHelper
{
private CacheInterface $cache;
private EntityCacheKeyGenerator $generator;
private AbstractCacheTracer $tracer;
private AbstractStoreApiResponseTagBuilder $tagBuilder;
public function __construct(
CacheInterface $cache,
EntityCacheKeyGenerator $generator,
AbstractCacheTracer $tracer,
AbstractStoreApiResponseTagBuilder $tagBuilder
)
{
$this->cache = $cache;
$this->generator = $generator;
$this->tracer = $tracer;
$this->tagBuilder = $tagBuilder;
}
/**
* @throws CacheException
* @throws InvalidArgumentException
*/
public function get(CacheItemInfo $itemInfo): StoreApiResponse
{
$key = $itemInfo->getKey();
if ($key === null) {
$key = $this->generateKey($itemInfo->buildName(), $itemInfo->getCriteria(), $itemInfo->getContext());
}
$value = $this->cache->get($key, function (ItemInterface $item) use ($itemInfo) {
$name = $itemInfo->buildName();
$response = $this->tracer->trace($name, function () use ($itemInfo) {
return $itemInfo->getRoute()->load($itemInfo->getRequest(), $itemInfo->getCriteria(), $itemInfo->getContext());
});
$tags = $itemInfo->getTags();
if ($tags === null) {
$tags = [];
}
$tags = array_unique(array_filter(array_merge($tags, $this->generateTags($response, $itemInfo))));
$item->tag($tags);
return CacheValueCompressor::compress($response);
});
return CacheValueCompressor::uncompress($value);
}
private function generateKey(string $name, Criteria $criteria, SalesChannelContext $context): string
{
$parts = [
$this->generator->getCriteriaHash($criteria),
$this->generator->getSalesChannelContextHash($context)
];
return $name . '-' . md5(JsonFieldSerializer::encodeJson($parts));
}
private function generateTags(StoreApiResponse $response, CacheItemInfo $itemInfo): array
{
$name = $itemInfo->buildName();
$tags = array_merge(
$this->tracer->get($name),
[$name, $itemInfo->getAllTag()],
$this->tagBuilder->build($response, $itemInfo)
);
return array_unique(array_filter($tags));
}
}