<?php
namespace ApplifactionGuidedShopping\Service;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Exception;
use Shopware\Core\Defaults;
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\Field\Flag\RuleAreas;
use Shopware\Core\Framework\DataAbstractionLayer\FieldSerializer\JsonFieldSerializer;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Contracts\Cache\ItemInterface;
class CacheService
{
/**
* @var CacheInterface
*/
private $cache;
/**
* @var EntityCacheKeyGenerator
*/
private $generator;
/**
* @var AbstractCacheTracer
*/
private $tracer;
/**
* @var Connection
*/
private $connection;
public function __construct(
CacheInterface $cache,
EntityCacheKeyGenerator $generator,
AbstractCacheTracer $tracer,
Connection $connection
)
{
$this->cache = $cache;
$this->generator = $generator;
$this->tracer = $tracer;
$this->connection = $connection;
}
public function getCacheValueOrRecalculate(
string $cacheKeyPrefix,
array $cacheKeyData,
\DateInterval $cacheExpiresAfter,
\Closure $recalculateCallback,
?SalesChannelContext $context = null,
?Criteria $criteria = null): mixed
{
$cacheKey = $this->generateKey($cacheKeyPrefix, $cacheKeyData, $context, $criteria);
$cacheResult = $this->cache->get($cacheKey, function (ItemInterface $item) use ($cacheKey, $cacheExpiresAfter, $recalculateCallback) {
$traceResult = $this->tracer->trace($cacheKey, function () use ($recalculateCallback, $cacheExpiresAfter) {
return $recalculateCallback();
});
$item->expiresAfter($cacheExpiresAfter);
return CacheValueCompressor::compress($traceResult);
});
return CacheValueCompressor::uncompress($cacheResult);
}
private function generateKey(string $prefix, array $data = [], ?SalesChannelContext $context = null, ?Criteria $criteria = null): string
{
$parts = [];
if (!empty($data)) {
$parts[] = md5(JsonFieldSerializer::encodeJson($data));
}
if (!!$criteria) {
$parts[] = $this->generator->getCriteriaHash($criteria);
}
if (!!$context) {
$parts[] = $this->generator->getSalesChannelContextHash($context, [RuleAreas::PRODUCT_AREA]);
}
return $prefix . '-' . md5(JsonFieldSerializer::encodeJson($parts));
}
public function fetchUpdatedAtByProductIds(array $productIds): string
{
$updatedAtSql = <<<SQL
SELECT created_at, updated_at
FROM product
WHERE LOWER(HEX(id)) IN (:productIds)
SQL;
try {
$updatedAtResults = $this->connection->fetchAllAssociative(
$updatedAtSql,
['productIds' => $productIds],
['productIds' => Connection::PARAM_STR_ARRAY]
);
} catch (\Exception $e) {
return "";
}
$updatedAtResults = array_map(fn($updatedAtResult) => ($updatedAtResult['updated_at'] ?? $updatedAtResult['created_at']), $updatedAtResults);
return join(';', $updatedAtResults);
}
public function fetchUpdatedAtByRuleIds(array $ruleIds): string
{
$updatedAtSql = <<<SQL
SELECT created_at, updated_at
FROM ags_accessory_rule
WHERE LOWER(HEX(id)) IN (:ruleIds)
SQL;
try {
$updatedAtResults = $this->connection->fetchAllAssociative(
$updatedAtSql,
['ruleIds' => $ruleIds],
['ruleIds' => Connection::PARAM_STR_ARRAY]
);
} catch (\Exception $e) {
return "";
}
$updatedAtResults = array_map(fn($updatedAtResult) => ($updatedAtResult['updated_at'] ?? $updatedAtResult['created_at']), $updatedAtResults);
return join(';', $updatedAtResults);
}
public function fetchUpdatedAtByProductFinderIds(array $productFinderIds): string
{
$updatedAtSql = <<<SQL
SELECT created_at, updated_at
FROM ags_product_finder
WHERE LOWER(HEX(id)) IN (:productFinderIds)
SQL;
try {
$updatedAtResults = $this->connection->fetchAllAssociative(
$updatedAtSql,
['productFinderIds' => $productFinderIds],
['productFinderIds' => Connection::PARAM_STR_ARRAY]
);
} catch (\Exception $e) {
return "";
}
$updatedAtResults = array_map(fn($updatedAtResult) => ($updatedAtResult['updated_at'] ?? $updatedAtResult['created_at']), $updatedAtResults);
return join(';', $updatedAtResults);
}
}