<?php declare(strict_types=1);
namespace ShopStudio\Blog\Core\Framework\Adapter\Cache;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Exception;
use ShopStudio\Blog\Content\BlogPost\Aggregate\BlogPostComment\Events\BlogPostCommentChangedEventInterface;
use ShopStudio\Blog\Content\BlogPost\Aggregate\BlogPostComment\Events\BlogPostCommentIndexerEvent;
use ShopStudio\Blog\Content\BlogPost\Events\BlogPostChangedEventInterface;
use ShopStudio\Blog\Content\BlogPost\Events\BlogPostIndexerEvent;
use ShopStudio\Blog\Content\BlogPost\SalesChannel\Comment\CachedBlogPostCommentRoute;
use ShopStudio\Blog\Content\BlogPost\SalesChannel\Detail\CachedBlogPostDetailRoute;
use ShopStudio\Blog\Content\BlogPost\SalesChannel\Listing\CachedBlogPostListingRoute;
use ShopStudio\Blog\Content\BlogPost\SalesChannel\Search\CachedBlogPostSearchRoute;
use ShopStudio\Blog\Content\BlogPost\SalesChannel\Suggest\CachedBlogPostSuggestRoute;
use ShopStudio\Blog\Core\Framework\DataAbstractionLayer\Cache\EntityCacheKeyGenerator;
use Shopware\Core\Defaults;
use Shopware\Core\Framework\Adapter\Cache\CacheInvalidator;
use Shopware\Core\Framework\Uuid\Uuid;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* @since 2.0.0
*/
class CacheInvalidationSubscriber implements EventSubscriberInterface
{
/**
* @since 2.0.0
*/
private CacheInvalidator $cacheInvalidator;
/**
* @since 2.0.0
*/
private Connection $connection;
/**
* @since 2.0.0
*/
public function __construct(
CacheInvalidator $cacheInvalidator,
Connection $connection
) {
$this->cacheInvalidator = $cacheInvalidator;
$this->connection = $connection;
}
/**
* @since 2.0.0
*/
public static function getSubscribedEvents(): array
{
return [
BlogPostIndexerEvent::class => [
['invalidateBlogPostSearch', 2000],
['invalidateBlogPostListings', 2001],
['invalidateBlogPostIds', 2002],
['invalidateBlogPostDetails', 2004],
],
BlogPostCommentIndexerEvent::class => [
['invalidateBlogPostComments', 2000],
['invalidateBlogPostCommentIds', 2002],
['invalidateBlogPostDetailsByComment', 2004],
],
];
}
/**
* Invalidates the search and suggest route each time a blog post changed.
*
* @since 2.0.0
*/
public function invalidateBlogPostSearch(): void
{
$this->cacheInvalidator->invalidate([
CachedBlogPostSuggestRoute::NAME,
CachedBlogPostSearchRoute::NAME,
]);
}
/**
* @since 2.0.0
*/
public function invalidateBlogPostIds(BlogPostChangedEventInterface $event): void
{
$this->cacheInvalidator->invalidate(
array_map([EntityCacheKeyGenerator::class, 'buildBlogPostTag'], $event->getIds())
);
}
/**
* Invalidates blog post listings which are based on the blog post category assignment.
*
* @since 2.0.0
*
* @throws Exception
*/
public function invalidateBlogPostListings(BlogPostChangedEventInterface $event): void
{
$ids = $this->connection->fetchFirstColumn(
'SELECT DISTINCT LOWER(HEX(category_id)) as category_id
FROM shopstudio_blog_blog_post_category_tree
WHERE shopstudio_blog_blog_post_id IN (:ids)
AND category_version_id = :version',
['ids' => Uuid::fromHexToBytesList($event->getIds()), 'version' => Uuid::fromHexToBytes(Defaults::LIVE_VERSION)],
['ids' => Connection::PARAM_STR_ARRAY]
);
$this->cacheInvalidator->invalidate(
array_map([CachedBlogPostListingRoute::class, 'buildName'], $ids)
);
}
/**
* Invalidates the blog post detail route each time a blog post changed.
*
* @since 2.0.0
*/
public function invalidateBlogPostDetails(BlogPostChangedEventInterface $event): void
{
$this->cacheInvalidator->invalidate(
array_map([CachedBlogPostDetailRoute::class, 'buildName'], $event->getIds())
);
}
/**
* @since 2.0.0
*/
public function invalidateBlogPostCommentIds(BlogPostCommentChangedEventInterface $event): void
{
$this->cacheInvalidator->invalidate(
array_map([EntityCacheKeyGenerator::class, 'buildBlogPostCommentTag'], $event->getIds())
);
}
/**
* Invalidates blog post listings which are based on the blog post category assignment.
*
* @since 2.0.0
*
* @throws Exception
*/
public function invalidateBlogPostComments(BlogPostCommentChangedEventInterface $event): void
{
$ids = $this->findBlogPostIdsByCommentIds($event->getIds());
$this->cacheInvalidator->invalidate(
array_map([CachedBlogPostCommentRoute::class, 'buildName'], $ids)
);
}
/**
* @since 2.0.0
*
* @throws Exception
*/
public function invalidateBlogPostDetailsByComment(BlogPostCommentChangedEventInterface $event): void
{
$ids = $this->findBlogPostIdsByCommentIds($event->getIds());
$this->cacheInvalidator->invalidate(
array_map([CachedBlogPostDetailRoute::class, 'buildName'], $ids)
);
}
/**
* @since 2.0.0
*
* @param string[] $blogPostCommentIds
*
* @throws Exception
*
* @return string[]
*/
private function findBlogPostIdsByCommentIds(array $blogPostCommentIds): array
{
return $this->connection->fetchFirstColumn(
'SELECT DISTINCT LOWER(HEX(shopstudio_blog_blog_post_id)) as blog_post_id
FROM shopstudio_blog_blog_post_comment
WHERE id IN (:ids)',
['ids' => Uuid::fromHexToBytesList($blogPostCommentIds)],
['ids' => Connection::PARAM_STR_ARRAY]
);
}
}