<?php
declare(strict_types=1);
namespace NetInventors\NetiNextEasyCouponDesigns\Subscriber;
use Doctrine\DBAL\Connection;
use Shopware\Core\Content\Product\SalesChannel\Detail\CachedProductDetailRoute;
use Shopware\Core\Content\Product\SalesChannel\Listing\CachedProductListingRoute;
use Shopware\Core\Content\Product\SalesChannel\Review\CachedProductReviewRoute;
use Shopware\Core\Defaults;
use Shopware\Core\Framework\Adapter\Cache\CacheInvalidator;
use Shopware\Core\Framework\DataAbstractionLayer\Cache\EntityCacheKeyGenerator;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
use Shopware\Core\Framework\Uuid\Uuid;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class CacheInvalidationSubscriber implements EventSubscriberInterface
{
private Connection $connection;
private CacheInvalidator $cacheInvalidator;
public function __construct(
Connection $connection,
CacheInvalidator $cacheInvalidator
) {
$this->connection = $connection;
$this->cacheInvalidator = $cacheInvalidator;
}
public static function getSubscribedEvents(): array
{
return [
'neti_ec_design.written' => 'onInvalidateProductCache',
];
}
public function onInvalidateProductCache(EntityWrittenEvent $event): void
{
$sql = '
SELECT LOWER(HEX(ecp.product_id))
FROM neti_ec_design ecd
LEFT JOIN neti_ec_design_product ecdp ON ecdp.design_id = ecd.id
LEFT JOIN neti_easy_coupon_product ecp ON ecp.id = ecdp.product_id
WHERE ecd.id IN (?)
AND ecp.product_id IS NOT NULL
';
/** @var string[] $productIds */
$productIds = $this->connection->fetchFirstColumn(
$sql,
[
Uuid::fromHexToBytesList($event->getIds()),
],
[
Connection::PARAM_STR_ARRAY,
]
);
if ($productIds !== []) {
$this->cacheInvalidator->invalidate([
'product-suggest-route',
'product-search-route',
], true);
/**
* @psalm-suppress MixedArgumentTypeCoercion The first parameter is of type string[]
*/
$this->cacheInvalidator->invalidate(
array_map(
[ CachedProductListingRoute::class, 'buildName' ],
$this->getProductCategoryIds($productIds)
),
true
);
/**
* @psalm-suppress MixedArgumentTypeCoercion The first parameter is of type string[]
*/
$this->cacheInvalidator->invalidate(
array_map([ EntityCacheKeyGenerator::class, 'buildProductTag' ], $productIds),
true
);
/**
* @psalm-suppress MixedArgumentTypeCoercion The first parameter is of type string[]
*/
$this->cacheInvalidator->invalidate(
array_map([ CachedProductDetailRoute::class, 'buildName' ], $productIds),
true
);
/**
* @psalm-suppress MixedArgumentTypeCoercion The first parameter is of type string[]
*/
$this->cacheInvalidator->invalidate(
array_map([ CachedProductReviewRoute::class, 'buildName' ], $productIds),
true
);
}
}
private function getProductCategoryIds(array $ids): array
{
return $this->connection->fetchFirstColumn(
'SELECT DISTINCT LOWER(HEX(category_id)) as category_id
FROM product_category_tree
WHERE product_id IN (:ids)
AND product_version_id = :version
AND category_version_id = :version',
[ 'ids' => Uuid::fromHexToBytesList($ids), 'version' => Uuid::fromHexToBytes(Defaults::LIVE_VERSION) ],
[ 'ids' => Connection::PARAM_STR_ARRAY ]
);
}
}