custom/plugins/SasBlogModule/src/Subscriber/BlogCacheInvalidSubscriber.php line 150

  1. <?php declare(strict_types=1);
  2. namespace Sas\BlogModule\Subscriber;
  3. use Sas\BlogModule\Content\Blog\BlogSeoUrlRoute;
  4. use Sas\BlogModule\Controller\CachedBlogController;
  5. use Sas\BlogModule\Controller\CachedBlogRssController;
  6. use Sas\BlogModule\Controller\CachedBlogSearchController;
  7. use Sas\BlogModule\Core\Content\Cms\BlogAssignment\CacheProductBlogAssignmentRoute;
  8. use Shopware\Core\Content\Category\SalesChannel\CachedCategoryRoute;
  9. use Shopware\Core\Content\Cms\CmsPageEvents;
  10. use Shopware\Core\Content\Seo\Event\SeoEvents;
  11. use Shopware\Core\Content\Seo\SeoUrlUpdater;
  12. use Shopware\Core\Framework\Adapter\Cache\CacheInvalidator;
  13. use Shopware\Core\Framework\Context;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Cache\EntityCacheKeyGenerator;
  15. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  16. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityDeletedEvent;
  17. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
  18. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  19. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
  20. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  21. use Shopware\Core\System\SystemConfig\SystemConfigService;
  22. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  23. /**
  24.  * After you change the SEO Template within the SEO settings, we need to re-generate all existing URLs.
  25.  * All old URL's should match the new saved SEO Template pattern.
  26.  */
  27. class BlogCacheInvalidSubscriber implements EventSubscriberInterface
  28. {
  29.     private SeoUrlUpdater $seoUrlUpdater;
  30.     private EntityRepository $categoryRepository;
  31.     private EntityRepository $blogRepository;
  32.     private EntityRepository $productRepository;
  33.     private CacheInvalidator $cacheInvalidator;
  34.     private SystemConfigService $systemConfigService;
  35.     public function __construct(
  36.         SeoUrlUpdater $seoUrlUpdater,
  37.         EntityRepository $categoryRepository,
  38.         EntityRepository $blogRepository,
  39.         CacheInvalidator $cacheInvalidator,
  40.         SystemConfigService $systemConfigService,
  41.         EntityRepository $productRepository
  42.     ) {
  43.         $this->seoUrlUpdater $seoUrlUpdater;
  44.         $this->categoryRepository $categoryRepository;
  45.         $this->blogRepository $blogRepository;
  46.         $this->cacheInvalidator $cacheInvalidator;
  47.         $this->systemConfigService $systemConfigService;
  48.         $this->productRepository $productRepository;
  49.     }
  50.     public static function getSubscribedEvents(): array
  51.     {
  52.         return [
  53.             CmsPageEvents::PAGE_WRITTEN_EVENT => [
  54.                 ['onUpdateSeoUrlCmsPage'10],
  55.                 ['onUpdateInvalidateCacheCmsPage'11],
  56.                 ['invalidBlogDetailCmsPage'12],
  57.             ],
  58.             'sas_blog_entries.written' => [
  59.                 ['onUpdateSeoUrl'10],
  60.                 ['onUpdateInvalidateCache'11],
  61.             ],
  62.             'sas_blog_entries.deleted' => [
  63.                 ['onDeleteSeoUrl'10],
  64.                 ['onDeleteInvalidateCache'11],
  65.             ],
  66.             SeoEvents::SEO_URL_TEMPLATE_WRITTEN_EVENT => [
  67.                 ['updateSeoUrlForAllArticles'10],
  68.             ],
  69.         ];
  70.     }
  71.     public function invalidBlogDetailCmsPage(EntityWrittenEvent $event): void
  72.     {
  73.         $cmsPageIds $event->getIds();
  74.         $cmsBlogDetailPageId $this->systemConfigService->get('SasBlogModule.config.cmsBlogDetailPage');
  75.         if (!\is_string($cmsBlogDetailPageId) || !\in_array($cmsBlogDetailPageId$cmsPageIdstrue)) {
  76.             return;
  77.         }
  78.         $this->cacheInvalidator->invalidate(
  79.             array_map([EntityCacheKeyGenerator::class, 'buildCmsTag'], [$cmsBlogDetailPageId])
  80.         );
  81.     }
  82.     public function onUpdateSeoUrlCmsPage(EntityWrittenEvent $event): void
  83.     {
  84.         $blogIds $this->getBlogIds($event);
  85.         if (empty($blogIds)) {
  86.             return;
  87.         }
  88.         $this->seoUrlUpdater->update(BlogSeoUrlRoute::ROUTE_NAME$blogIds);
  89.     }
  90.     public function onUpdateInvalidateCacheCmsPage(EntityWrittenEvent $event): void
  91.     {
  92.         $blogIds $this->getBlogIds($event);
  93.         if (empty($blogIds)) {
  94.             return;
  95.         }
  96.         $this->invalidateCache($blogIds);
  97.         $this->invalidateCacheCategory($event->getContext());
  98.         $this->invalidateCacheProductBlogAssignment($blogIds$event->getContext());
  99.     }
  100.     /**
  101.      * When a blog article created or updated we will generate the SeoUrl for it
  102.      */
  103.     public function onUpdateSeoUrl(EntityWrittenEvent $event): void
  104.     {
  105.         $this->seoUrlUpdater->update(BlogSeoUrlRoute::ROUTE_NAME$event->getIds());
  106.     }
  107.     /**
  108.      * When a blog article deleted we will mark as deleted the SeoUrl
  109.      */
  110.     public function onDeleteSeoUrl(EntityDeletedEvent $event): void
  111.     {
  112.         $this->seoUrlUpdater->update(BlogSeoUrlRoute::ROUTE_NAME$event->getIds());
  113.     }
  114.     /**
  115.      * Invalidate blog cms cache when create or update
  116.      */
  117.     public function onUpdateInvalidateCache(EntityWrittenEvent $event): void
  118.     {
  119.         $this->invalidateCache($event->getIds());
  120.         $this->invalidateCacheCategory($event->getContext());
  121.         $this->invalidateCacheProductBlogAssignment($event->getIds(), $event->getContext());
  122.     }
  123.     /**
  124.      * Invalidate blog cms cache when delete article
  125.      */
  126.     public function onDeleteInvalidateCache(EntityDeletedEvent $event): void
  127.     {
  128.         $this->invalidateCache($event->getIds());
  129.         $this->invalidateCacheCategory($event->getContext());
  130.         $this->invalidateCacheProductBlogAssignment($event->getIds(), $event->getContext());
  131.     }
  132.     /**
  133.      * When update SEO template in the settings, we will update all SEO URLs for the blog articles
  134.      */
  135.     public function updateSeoUrlForAllArticles(): void
  136.     {
  137.         $this->seoUrlUpdater->update(BlogSeoUrlRoute::ROUTE_NAME, []);
  138.     }
  139.     private function invalidateCacheProductBlogAssignment(array $blogIdsContext $context): void
  140.     {
  141.         $productIds $this->getBlogProductIds($blogIds$context);
  142.         $this->cacheInvalidator->invalidate(
  143.             array_map([CacheProductBlogAssignmentRoute::class, 'buildName'], $productIds)
  144.         );
  145.     }
  146.     private function getBlogProductIds(array $blogIdsContext $context): array
  147.     {
  148.         $criteria = new Criteria();
  149.         $criteria->addFilter(new EqualsAnyFilter('assignedBlogs.id'$blogIds));
  150.         return $this->productRepository->searchIds($criteria$context)->getIds();
  151.     }
  152.     /**
  153.      * Invalidate blog category cache
  154.      */
  155.     private function invalidateCacheCategory(Context $context): void
  156.     {
  157.         $catIds $this->getBlogCategoryIds($context);
  158.         // invalidates the category route cache when a category changed
  159.         $this->cacheInvalidator->invalidate(
  160.             array_map([CachedCategoryRoute::class, 'buildName'], $catIds)
  161.         );
  162.     }
  163.     private function getBlogCategoryIds(Context $context): array
  164.     {
  165.         $criteria = new Criteria();
  166.         $criteria->addFilter(new EqualsFilter('active'true));
  167.         $criteria->addFilter(new EqualsFilter('cmsPage.sections.blocks.type''blog-listing'));
  168.         $criteria->addAssociation('cmsPage.sections.blocks');
  169.         return $this->categoryRepository->search($criteria$context)->getIds();
  170.     }
  171.     /**
  172.      * Invalidate cache
  173.      */
  174.     private function invalidateCache(array $articleIds): void
  175.     {
  176.         $this->cacheInvalidator->invalidate(
  177.             array_map([CachedBlogController::class, 'buildName'], $articleIds)
  178.         );
  179.         $this->cacheInvalidator->invalidate([
  180.             'product-suggest-route',
  181.             'product-search-route',
  182.             CachedBlogSearchController::SEARCH_TAG,
  183.             CachedBlogRssController::RSS_TAG,
  184.         ]);
  185.         $cmsBlogDetailPageId $this->systemConfigService->get('SasBlogModule.config.cmsBlogDetailPage');
  186.         if (!\is_string($cmsBlogDetailPageId)) {
  187.             return;
  188.         }
  189.         $this->cacheInvalidator->invalidate(
  190.             array_map([EntityCacheKeyGenerator::class, 'buildCmsTag'], [$cmsBlogDetailPageId])
  191.         );
  192.     }
  193.     private function getBlogIds(EntityWrittenEvent $event): array
  194.     {
  195.         return $this->blogRepository->searchIds(
  196.             (new Criteria())->addFilter(new EqualsAnyFilter('cmsPageId'$event->getIds())),
  197.             $event->getContext()
  198.         )->getIds();
  199.     }
  200. }