- <?php declare(strict_types=1);
- namespace Shopware\Core\Framework\Adapter\Cache;
- use Doctrine\DBAL\Connection;
- use Shopware\Core\Checkout\Cart\CachedRuleLoader;
- use Shopware\Core\Checkout\Customer\Aggregate\CustomerGroup\CustomerGroupDefinition;
- use Shopware\Core\Checkout\Payment\PaymentMethodDefinition;
- use Shopware\Core\Checkout\Payment\SalesChannel\CachedPaymentMethodRoute;
- use Shopware\Core\Checkout\Shipping\SalesChannel\CachedShippingMethodRoute;
- use Shopware\Core\Checkout\Shipping\ShippingMethodDefinition;
- use Shopware\Core\Content\Category\CategoryDefinition;
- use Shopware\Core\Content\Category\Event\CategoryIndexerEvent;
- use Shopware\Core\Content\Category\SalesChannel\CachedCategoryRoute;
- use Shopware\Core\Content\Category\SalesChannel\CachedNavigationRoute;
- use Shopware\Core\Content\Cms\CmsPageDefinition;
- use Shopware\Core\Content\LandingPage\Event\LandingPageIndexerEvent;
- use Shopware\Core\Content\LandingPage\SalesChannel\CachedLandingPageRoute;
- use Shopware\Core\Content\Product\Aggregate\ProductCategory\ProductCategoryDefinition;
- use Shopware\Core\Content\Product\Aggregate\ProductCrossSelling\ProductCrossSellingDefinition;
- use Shopware\Core\Content\Product\Aggregate\ProductManufacturer\ProductManufacturerDefinition;
- use Shopware\Core\Content\Product\Aggregate\ProductProperty\ProductPropertyDefinition;
- use Shopware\Core\Content\Product\Events\ProductChangedEventInterface;
- use Shopware\Core\Content\Product\Events\ProductIndexerEvent;
- use Shopware\Core\Content\Product\Events\ProductNoLongerAvailableEvent;
- use Shopware\Core\Content\Product\ProductDefinition;
- use Shopware\Core\Content\Product\SalesChannel\CrossSelling\CachedProductCrossSellingRoute;
- 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\Content\ProductStream\ProductStreamDefinition;
- use Shopware\Core\Content\Property\Aggregate\PropertyGroupOption\PropertyGroupOptionDefinition;
- use Shopware\Core\Content\Property\Aggregate\PropertyGroupOptionTranslation\PropertyGroupOptionTranslationDefinition;
- use Shopware\Core\Content\Property\Aggregate\PropertyGroupTranslation\PropertyGroupTranslationDefinition;
- use Shopware\Core\Content\Property\PropertyGroupDefinition;
- use Shopware\Core\Content\Rule\Event\RuleIndexerEvent;
- use Shopware\Core\Content\Seo\CachedSeoResolver;
- use Shopware\Core\Content\Seo\Event\SeoUrlUpdateEvent;
- use Shopware\Core\Content\Sitemap\Event\SitemapGeneratedEvent;
- use Shopware\Core\Content\Sitemap\SalesChannel\CachedSitemapRoute;
- use Shopware\Core\Defaults;
- use Shopware\Core\Framework\Adapter\Translation\Translator;
- use Shopware\Core\Framework\DataAbstractionLayer\Cache\EntityCacheKeyGenerator;
- use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenContainerEvent;
- use Shopware\Core\Framework\Log\Package;
- use Shopware\Core\Framework\Plugin\Event\PluginPostActivateEvent;
- use Shopware\Core\Framework\Plugin\Event\PluginPostDeactivateEvent;
- use Shopware\Core\Framework\Plugin\Event\PluginPostInstallEvent;
- use Shopware\Core\Framework\Plugin\Event\PluginPostUninstallEvent;
- use Shopware\Core\Framework\Plugin\Event\PluginPostUpdateEvent;
- use Shopware\Core\Framework\Uuid\Uuid;
- use Shopware\Core\System\Country\Aggregate\CountryState\CountryStateDefinition;
- use Shopware\Core\System\Country\CountryDefinition;
- use Shopware\Core\System\Country\SalesChannel\CachedCountryRoute;
- use Shopware\Core\System\Country\SalesChannel\CachedCountryStateRoute;
- use Shopware\Core\System\Currency\CurrencyDefinition;
- use Shopware\Core\System\Currency\SalesChannel\CachedCurrencyRoute;
- use Shopware\Core\System\Language\LanguageDefinition;
- use Shopware\Core\System\Language\SalesChannel\CachedLanguageRoute;
- use Shopware\Core\System\SalesChannel\Aggregate\SalesChannelCountry\SalesChannelCountryDefinition;
- use Shopware\Core\System\SalesChannel\Aggregate\SalesChannelCurrency\SalesChannelCurrencyDefinition;
- use Shopware\Core\System\SalesChannel\Aggregate\SalesChannelLanguage\SalesChannelLanguageDefinition;
- use Shopware\Core\System\SalesChannel\Aggregate\SalesChannelPaymentMethod\SalesChannelPaymentMethodDefinition;
- use Shopware\Core\System\SalesChannel\Aggregate\SalesChannelShippingMethod\SalesChannelShippingMethodDefinition;
- use Shopware\Core\System\SalesChannel\Context\CachedBaseContextFactory;
- use Shopware\Core\System\SalesChannel\Context\CachedSalesChannelContextFactory;
- use Shopware\Core\System\SalesChannel\SalesChannelDefinition;
- use Shopware\Core\System\Salutation\SalesChannel\CachedSalutationRoute;
- use Shopware\Core\System\Salutation\SalutationDefinition;
- use Shopware\Core\System\Snippet\SnippetDefinition;
- use Shopware\Core\System\StateMachine\Loader\InitialStateIdLoader;
- use Shopware\Core\System\StateMachine\StateMachineDefinition;
- use Shopware\Core\System\SystemConfig\CachedSystemConfigLoader;
- use Shopware\Core\System\SystemConfig\Event\SystemConfigChangedEvent;
- use Shopware\Core\System\SystemConfig\SystemConfigService;
- use Shopware\Core\System\Tax\TaxDefinition;
- use Symfony\Component\EventDispatcher\EventSubscriberInterface;
- /**
-  * @internal - The functions inside this class are no public-api and can be changed without previous deprecation
-  */
- #[Package('core')]
- class CacheInvalidationSubscriber implements EventSubscriberInterface
- {
-     private Connection $connection;
-     private CacheInvalidator $cacheInvalidator;
-     public function __construct(
-         CacheInvalidator $cacheInvalidator,
-         Connection $connection
-     ) {
-         $this->cacheInvalidator = $cacheInvalidator;
-         $this->connection = $connection;
-     }
-     /**
-      * @return array<string, string|array{0: string, 1: int}|list<array{0: string, 1?: int}>>
-      */
-     public static function getSubscribedEvents()
-     {
-         return [
-             CategoryIndexerEvent::class => [
-                 ['invalidateCategoryRouteByCategoryIds', 2000],
-                 ['invalidateListingRouteByCategoryIds', 2001],
-             ],
-             LandingPageIndexerEvent::class => [
-                 ['invalidateIndexedLandingPages', 2000],
-             ],
-             ProductIndexerEvent::class => [
-                 ['invalidateSearch', 2000],
-                 ['invalidateListings', 2001],
-                 ['invalidateProductIds', 2002],
-                 ['invalidateDetailRoute', 2004],
-                 ['invalidateStreamsAfterIndexing', 2005],
-                 ['invalidateReviewRoute', 2006],
-             ],
-             ProductNoLongerAvailableEvent::class => [
-                 ['invalidateSearch', 2000],
-                 ['invalidateListings', 2001],
-                 ['invalidateProductIds', 2002],
-                 ['invalidateDetailRoute', 2004],
-                 ['invalidateStreamsAfterIndexing', 2005],
-                 ['invalidateReviewRoute', 2006],
-             ],
-             EntityWrittenContainerEvent::class => [
-                 ['invalidateCmsPageIds', 2001],
-                 ['invalidateCurrencyRoute', 2002],
-                 ['invalidateLanguageRoute', 2003],
-                 ['invalidateNavigationRoute', 2004],
-                 ['invalidatePaymentMethodRoute', 2005],
-                 ['invalidateProductAssignment', 2006],
-                 ['invalidateManufacturerFilters', 2007],
-                 ['invalidatePropertyFilters', 2008],
-                 ['invalidateCrossSellingRoute', 2009],
-                 ['invalidateContext', 2010],
-                 ['invalidateShippingMethodRoute', 2011],
-                 ['invalidateSnippets', 2012],
-                 ['invalidateStreamsBeforeIndexing', 2013],
-                 ['invalidateStreamIds', 2014],
-                 ['invalidateCountryRoute', 2015],
-                 ['invalidateSalutationRoute', 2016],
-                 ['invalidateInitialStateIdLoader', 2017],
-                 ['invalidateCountryStateRoute', 2018],
-             ],
-             SeoUrlUpdateEvent::class => [
-                 ['invalidateSeoUrls', 2000],
-             ],
-             RuleIndexerEvent::class => [
-                 ['invalidateRules', 2000],
-             ],
-             PluginPostInstallEvent::class => [
-                 ['invalidateRules', 2000],
-                 ['invalidateConfig', 2001],
-             ],
-             PluginPostActivateEvent::class => [
-                 ['invalidateRules', 2000],
-                 ['invalidateConfig', 2001],
-             ],
-             PluginPostUpdateEvent::class => [
-                 ['invalidateRules', 2000],
-                 ['invalidateConfig', 2001],
-             ],
-             PluginPostDeactivateEvent::class => [
-                 ['invalidateRules', 2000],
-                 ['invalidateConfig', 2001],
-             ],
-             PluginPostUninstallEvent::class => [
-                 ['invalidateRules', 2000],
-                 ['invalidateConfig', 2001],
-             ],
-             SystemConfigChangedEvent::class => [
-                 ['invalidateConfigKey', 2000],
-             ],
-             SitemapGeneratedEvent::class => [
-                 ['invalidateSitemap', 2000],
-             ],
-         ];
-     }
-     public function invalidateInitialStateIdLoader(EntityWrittenContainerEvent $event): void
-     {
-         if (!$event->getPrimaryKeys(StateMachineDefinition::ENTITY_NAME)) {
-             return;
-         }
-         $this->cacheInvalidator->invalidate([InitialStateIdLoader::CACHE_KEY]);
-     }
-     public function invalidateSitemap(SitemapGeneratedEvent $event): void
-     {
-         $this->cacheInvalidator->invalidate([
-             CachedSitemapRoute::buildName($event->getSalesChannelContext()->getSalesChannelId()),
-         ]);
-     }
-     public function invalidateConfig(): void
-     {
-         // invalidates the complete cached config
-         $this->cacheInvalidator->invalidate([
-             CachedSystemConfigLoader::CACHE_TAG,
-         ]);
-     }
-     public function invalidateConfigKey(SystemConfigChangedEvent $event): void
-     {
-         // invalidates the complete cached config and routes which access a specific key
-         $this->cacheInvalidator->invalidate([
-             SystemConfigService::buildName($event->getKey()),
-             CachedSystemConfigLoader::CACHE_TAG,
-         ]);
-     }
-     public function invalidateSnippets(EntityWrittenContainerEvent $event): void
-     {
-         // invalidates all http cache items where the snippets used
-         $snippets = $event->getEventByEntityName(SnippetDefinition::ENTITY_NAME);
-         if (!$snippets) {
-             return;
-         }
-         $tags = [];
-         foreach ($snippets->getPayloads() as $payload) {
-             if (isset($payload['translationKey'])) {
-                 $tags[] = Translator::buildName($payload['translationKey']);
-             }
-         }
-         $this->cacheInvalidator->invalidate($tags);
-     }
-     public function invalidateShippingMethodRoute(EntityWrittenContainerEvent $event): void
-     {
-         // checks if a shipping method changed or the assignment between shipping method and sales channel
-         $logs = array_merge(
-             $this->getChangedShippingMethods($event),
-             $this->getChangedShippingAssignments($event)
-         );
-         $this->cacheInvalidator->invalidate($logs);
-     }
-     public function invalidateSeoUrls(SeoUrlUpdateEvent $event): void
-     {
-         // invalidates the cache for the seo url resolver based on the path infos which used for the new seo urls
-         $urls = $event->getSeoUrls();
-         $pathInfo = array_column($urls, 'pathInfo');
-         $this->cacheInvalidator->invalidate(array_map([CachedSeoResolver::class, 'buildName'], $pathInfo));
-     }
-     public function invalidateRules(): void
-     {
-         // invalidates the rule loader each time a rule changed or a plugin install state changed
-         $this->cacheInvalidator->invalidate([CachedRuleLoader::CACHE_KEY]);
-     }
-     public function invalidateCmsPageIds(EntityWrittenContainerEvent $event): void
-     {
-         // invalidates all routes and http cache pages where a cms page was loaded, the id is assigned as tag
-         $this->cacheInvalidator->invalidate(
-             array_map([EntityCacheKeyGenerator::class, 'buildCmsTag'], $event->getPrimaryKeys(CmsPageDefinition::ENTITY_NAME))
-         );
-     }
-     public function invalidateProductIds(ProductChangedEventInterface $event): void
-     {
-         // invalidates all routes which loads products in nested unknown objects, like cms listing elements or cross selling elements
-         $this->cacheInvalidator->invalidate(
-             array_map([EntityCacheKeyGenerator::class, 'buildProductTag'], $event->getIds())
-         );
-     }
-     public function invalidateStreamIds(EntityWrittenContainerEvent $event): void
-     {
-         // invalidates all routes which are loaded based on a stream (e.G. category listing and cross selling)
-         $this->cacheInvalidator->invalidate(
-             array_map([EntityCacheKeyGenerator::class, 'buildStreamTag'], $event->getPrimaryKeys(ProductStreamDefinition::ENTITY_NAME))
-         );
-     }
-     public function invalidateCategoryRouteByCategoryIds(CategoryIndexerEvent $event): void
-     {
-         // invalidates the category route cache when a category changed
-         $this->cacheInvalidator->invalidate(
-             array_map([CachedCategoryRoute::class, 'buildName'], $event->getIds())
-         );
-     }
-     public function invalidateListingRouteByCategoryIds(CategoryIndexerEvent $event): void
-     {
-         // invalidates the product listing route each time a category changed
-         $this->cacheInvalidator->invalidate(
-             array_map([CachedProductListingRoute::class, 'buildName'], $event->getIds())
-         );
-     }
-     public function invalidateIndexedLandingPages(LandingPageIndexerEvent $event): void
-     {
-         // invalidates the landing page route, if the corresponding landing page changed
-         $this->cacheInvalidator->invalidate(
-             array_map([CachedLandingPageRoute::class, 'buildName'], $event->getIds())
-         );
-     }
-     public function invalidateCurrencyRoute(EntityWrittenContainerEvent $event): void
-     {
-         // invalidates the currency route when a currency changed or an assignment between the sales channel and currency changed
-         $this->cacheInvalidator->invalidate(array_merge(
-             $this->getChangedCurrencyAssignments($event),
-             $this->getChangedCurrencies($event)
-         ));
-     }
-     public function invalidateLanguageRoute(EntityWrittenContainerEvent $event): void
-     {
-         // invalidates the language route when a language changed or an assignment between the sales channel and language changed
-         $this->cacheInvalidator->invalidate(array_merge(
-             $this->getChangedLanguageAssignments($event),
-             $this->getChangedLanguages($event)
-         ));
-     }
-     public function invalidateCountryRoute(EntityWrittenContainerEvent $event): void
-     {
-         // invalidates the country route when a country changed or an assignment between the sales channel and country changed
-         $this->cacheInvalidator->invalidate(array_merge(
-             $this->getChangedCountryAssignments($event),
-             $this->getChangedCountries($event),
-         ));
-     }
-     public function invalidateCountryStateRoute(EntityWrittenContainerEvent $event): void
-     {
-         $tags = [];
-         if (
-             $event->getDeletedPrimaryKeys(CountryStateDefinition::ENTITY_NAME)
-             || $event->getPrimaryKeysWithPropertyChange(CountryStateDefinition::ENTITY_NAME, ['countryId'])
-         ) {
-             $tags[] = CachedCountryStateRoute::ALL_TAG;
-         }
-         if (empty($tags)) {
-             // invalidates the country-state route when a state changed or an assignment between the state and country changed
-             $tags = array_map(
-                 [CachedCountryStateRoute::class, 'buildName'],
-                 $event->getPrimaryKeys(CountryDefinition::ENTITY_NAME)
-             );
-         }
-         $this->cacheInvalidator->invalidate($tags);
-     }
-     public function invalidateSalutationRoute(EntityWrittenContainerEvent $event): void
-     {
-         // invalidates the salutation route when a salutation changed
-         $this->cacheInvalidator->invalidate(array_merge(
-             $this->getChangedSalutations($event),
-         ));
-     }
-     public function invalidateNavigationRoute(EntityWrittenContainerEvent $event): void
-     {
-         // invalidates the navigation route when a category changed or the entry point configuration of an sales channel changed
-         $logs = array_merge(
-             $this->getChangedCategories($event),
-             $this->getChangedEntryPoints($event)
-         );
-         $this->cacheInvalidator->invalidate($logs);
-     }
-     public function invalidatePaymentMethodRoute(EntityWrittenContainerEvent $event): void
-     {
-         // invalidates the payment method route when a payment method changed or an assignment between the sales channel and payment method changed
-         $logs = array_merge(
-             $this->getChangedPaymentMethods($event),
-             $this->getChangedPaymentAssignments($event)
-         );
-         $this->cacheInvalidator->invalidate($logs);
-     }
-     public function invalidateSearch(): void
-     {
-         // invalidates the search and suggest route each time a product changed
-         $this->cacheInvalidator->invalidate([
-             'product-suggest-route',
-             'product-search-route',
-         ]);
-     }
-     public function invalidateDetailRoute(ProductChangedEventInterface $event): void
-     {
-         //invalidates the product detail route each time a product changed or if the product is no longer available (because out of stock)
-         $this->cacheInvalidator->invalidate(
-             array_map([CachedProductDetailRoute::class, 'buildName'], $event->getIds())
-         );
-     }
-     public function invalidateProductAssignment(EntityWrittenContainerEvent $event): void
-     {
-         //invalidates the product listing route, each time a product - category assignment changed
-         $ids = $event->getPrimaryKeys(ProductCategoryDefinition::ENTITY_NAME);
-         $ids = array_column($ids, 'categoryId');
-         $this->cacheInvalidator->invalidate(
-             array_map([CachedProductListingRoute::class, 'buildName'], $ids)
-         );
-     }
-     public function invalidateContext(EntityWrittenContainerEvent $event): void
-     {
-         //invalidates the context cache - each time one of the entities which are considered inside the context factory changed
-         $ids = $event->getPrimaryKeys(SalesChannelDefinition::ENTITY_NAME);
-         $keys = array_map([CachedSalesChannelContextFactory::class, 'buildName'], $ids);
-         $keys = array_merge($keys, array_map([CachedBaseContextFactory::class, 'buildName'], $ids));
-         if ($event->getEventByEntityName(CurrencyDefinition::ENTITY_NAME)) {
-             $keys[] = CachedSalesChannelContextFactory::ALL_TAG;
-         }
-         if ($event->getEventByEntityName(PaymentMethodDefinition::ENTITY_NAME)) {
-             $keys[] = CachedSalesChannelContextFactory::ALL_TAG;
-         }
-         if ($event->getEventByEntityName(ShippingMethodDefinition::ENTITY_NAME)) {
-             $keys[] = CachedSalesChannelContextFactory::ALL_TAG;
-         }
-         if ($event->getEventByEntityName(TaxDefinition::ENTITY_NAME)) {
-             $keys[] = CachedSalesChannelContextFactory::ALL_TAG;
-         }
-         if ($event->getEventByEntityName(CountryDefinition::ENTITY_NAME)) {
-             $keys[] = CachedSalesChannelContextFactory::ALL_TAG;
-         }
-         if ($event->getEventByEntityName(CustomerGroupDefinition::ENTITY_NAME)) {
-             $keys[] = CachedSalesChannelContextFactory::ALL_TAG;
-         }
-         if ($event->getEventByEntityName(LanguageDefinition::ENTITY_NAME)) {
-             $keys[] = CachedSalesChannelContextFactory::ALL_TAG;
-         }
-         $keys = array_filter(array_unique($keys));
-         if (empty($keys)) {
-             return;
-         }
-         $this->cacheInvalidator->invalidate($keys);
-     }
-     public function invalidateManufacturerFilters(EntityWrittenContainerEvent $event): void
-     {
-         // invalidates the product listing route, each time a manufacturer changed
-         $ids = $event->getPrimaryKeys(ProductManufacturerDefinition::ENTITY_NAME);
-         if (empty($ids)) {
-             return;
-         }
-         $ids = $this->connection->fetchFirstColumn(
-             'SELECT DISTINCT LOWER(HEX(category_id)) as category_id
-              FROM product_category_tree
-                 INNER JOIN product ON product.id = product_category_tree.product_id AND product_category_tree.product_version_id = product.version_id
-              WHERE product.product_manufacturer_id IN (:ids)
-              AND product.version_id = :version',
-             ['ids' => Uuid::fromHexToBytesList($ids), 'version' => Uuid::fromHexToBytes(Defaults::LIVE_VERSION)],
-             ['ids' => Connection::PARAM_STR_ARRAY]
-         );
-         $this->cacheInvalidator->invalidate(
-             array_map([CachedProductListingRoute::class, 'buildName'], $ids)
-         );
-     }
-     public function invalidatePropertyFilters(EntityWrittenContainerEvent $event): void
-     {
-         $this->cacheInvalidator->invalidate(array_merge(
-             $this->getChangedPropertyFilterTags($event),
-             $this->getDeletedPropertyFilterTags($event)
-         ));
-     }
-     public function invalidateReviewRoute(ProductChangedEventInterface $event): void
-     {
-         $this->cacheInvalidator->invalidate(
-             array_map([CachedProductReviewRoute::class, 'buildName'], $event->getIds())
-         );
-     }
-     public function invalidateListings(ProductChangedEventInterface $event): void
-     {
-         // invalidates product listings which are based on the product category assignment
-         $this->cacheInvalidator->invalidate(
-             array_map([CachedProductListingRoute::class, 'buildName'], $this->getProductCategoryIds($event->getIds()))
-         );
-     }
-     public function invalidateStreamsBeforeIndexing(EntityWrittenContainerEvent $event): void
-     {
-         // invalidates all stream based pages and routes before the product indexer changes product_stream_mapping
-         $ids = $event->getPrimaryKeys(ProductDefinition::ENTITY_NAME);
-         if (empty($ids)) {
-             return;
-         }
-         // invalidates product listings which are based on a product stream
-         $ids = $this->connection->fetchFirstColumn(
-             'SELECT DISTINCT LOWER(HEX(product_stream_id))
-              FROM product_stream_mapping
-              WHERE product_stream_mapping.product_id IN (:ids)
-              AND product_stream_mapping.product_version_id = :version',
-             ['ids' => Uuid::fromHexToBytesList($ids), 'version' => Uuid::fromHexToBytes(Defaults::LIVE_VERSION)],
-             ['ids' => Connection::PARAM_STR_ARRAY]
-         );
-         $this->cacheInvalidator->invalidate(
-             array_map([EntityCacheKeyGenerator::class, 'buildStreamTag'], $ids)
-         );
-     }
-     public function invalidateStreamsAfterIndexing(ProductChangedEventInterface $event): void
-     {
-         // invalidates all stream based pages and routes after the product indexer changes product_stream_mapping
-         $ids = $this->connection->fetchFirstColumn(
-             'SELECT DISTINCT LOWER(HEX(product_stream_id))
-              FROM product_stream_mapping
-              WHERE product_stream_mapping.product_id IN (:ids)
-              AND product_stream_mapping.product_version_id = :version',
-             ['ids' => Uuid::fromHexToBytesList($event->getIds()), 'version' => Uuid::fromHexToBytes(Defaults::LIVE_VERSION)],
-             ['ids' => Connection::PARAM_STR_ARRAY]
-         );
-         $this->cacheInvalidator->invalidate(
-             array_map([EntityCacheKeyGenerator::class, 'buildStreamTag'], $ids)
-         );
-     }
-     public function invalidateCrossSellingRoute(EntityWrittenContainerEvent $event): void
-     {
-         // invalidates the product detail route for the changed cross selling definitions
-         $ids = $event->getPrimaryKeys(ProductCrossSellingDefinition::ENTITY_NAME);
-         if (empty($ids)) {
-             return;
-         }
-         $ids = $this->connection->fetchFirstColumn(
-             'SELECT DISTINCT LOWER(HEX(product_id)) FROM product_cross_selling WHERE id IN (:ids)',
-             ['ids' => Uuid::fromHexToBytesList($ids)],
-             ['ids' => Connection::PARAM_STR_ARRAY]
-         );
-         $this->cacheInvalidator->invalidate(
-             array_map([CachedProductCrossSellingRoute::class, 'buildName'], $ids)
-         );
-     }
-     /**
-      * @return list<string>
-      */
-     private function getDeletedPropertyFilterTags(EntityWrittenContainerEvent $event): array
-     {
-         // invalidates the product listing route, each time a property changed
-         $ids = $event->getDeletedPrimaryKeys(ProductPropertyDefinition::ENTITY_NAME);
-         if (empty($ids)) {
-             return [];
-         }
-         $productIds = array_column($ids, 'productId');
-         return array_merge(
-             array_map([CachedProductDetailRoute::class, 'buildName'], array_unique($productIds)),
-             array_map([CachedProductListingRoute::class, 'buildName'], $this->getProductCategoryIds($productIds))
-         );
-     }
-     /**
-      * @return list<string>
-      */
-     private function getChangedPropertyFilterTags(EntityWrittenContainerEvent $event): array
-     {
-         // invalidates the product listing route and detail rule, each time a property group changed
-         $propertyGroupIds = array_unique(array_merge(
-             $event->getPrimaryKeysWithPayloadIgnoringFields(PropertyGroupDefinition::ENTITY_NAME, ['id', 'updatedAt']),
-             array_column($event->getPrimaryKeysWithPayloadIgnoringFields(PropertyGroupTranslationDefinition::ENTITY_NAME, ['propertyGroupId', 'languageId', 'updatedAt']), 'propertyGroupId')
-         ));
-         // invalidates the product listing route and detail rule, each time a property option changed
-         $propertyOptionIds = array_unique(array_merge(
-             $event->getPrimaryKeysWithPayloadIgnoringFields(PropertyGroupOptionDefinition::ENTITY_NAME, ['id', 'updatedAt']),
-             array_column($event->getPrimaryKeysWithPayloadIgnoringFields(PropertyGroupOptionTranslationDefinition::ENTITY_NAME, ['propertyGroupOptionId', 'languageId', 'updatedAt']), 'propertyGroupOptionId')
-         ));
-         if (empty($propertyGroupIds) && empty($propertyOptionIds)) {
-             return [];
-         }
-         $productIds = $this->connection->fetchFirstColumn(
-             'SELECT product_property.product_id
-              FROM product_property
-                 LEFT JOIN property_group_option productProperties ON productProperties.id = product_property.property_group_option_id
-              WHERE productProperties.property_group_id IN (:ids) OR productProperties.id IN (:optionIds)
-              AND product_property.product_version_id = :version',
-             ['ids' => Uuid::fromHexToBytesList($propertyGroupIds), 'optionIds' => Uuid::fromHexToBytesList($propertyOptionIds), 'version' => Uuid::fromHexToBytes(Defaults::LIVE_VERSION)],
-             ['ids' => Connection::PARAM_STR_ARRAY, 'optionIds' => Connection::PARAM_STR_ARRAY]
-         );
-         $productIds = array_unique(array_merge(
-             $productIds,
-             $this->connection->fetchFirstColumn(
-                 'SELECT product_option.product_id
-                  FROM product_option
-                     LEFT JOIN property_group_option productOptions ON productOptions.id = product_option.property_group_option_id
-                  WHERE productOptions.property_group_id IN (:ids) OR productOptions.id IN (:optionIds)
-                  AND product_option.product_version_id = :version',
-                 ['ids' => Uuid::fromHexToBytesList($propertyGroupIds), 'optionIds' => Uuid::fromHexToBytesList($propertyOptionIds), 'version' => Uuid::fromHexToBytes(Defaults::LIVE_VERSION)],
-                 ['ids' => Connection::PARAM_STR_ARRAY, 'optionIds' => Connection::PARAM_STR_ARRAY]
-             )
-         ));
-         if (empty($productIds)) {
-             return [];
-         }
-         $parentIds = $this->connection->fetchFirstColumn(
-             'SELECT DISTINCT LOWER(HEX(COALESCE(parent_id, id)))
-             FROM product
-             WHERE id in (:productIds) AND version_id = :version',
-             ['productIds' => $productIds, 'version' => Uuid::fromHexToBytes(Defaults::LIVE_VERSION)],
-             ['productIds' => Connection::PARAM_STR_ARRAY]
-         );
-         $categoryIds = $this->connection->fetchFirstColumn(
-             'SELECT DISTINCT LOWER(HEX(category_id))
-             FROM product_category_tree
-             WHERE product_id in (:productIds) AND product_version_id = :version',
-             ['productIds' => $productIds, 'version' => Uuid::fromHexToBytes(Defaults::LIVE_VERSION)],
-             ['productIds' => Connection::PARAM_STR_ARRAY]
-         );
-         return array_merge(
-             array_map([CachedProductDetailRoute::class, 'buildName'], array_filter($parentIds)),
-             array_map([CachedProductListingRoute::class, 'buildName'], array_filter($categoryIds)),
-         );
-     }
-     /**
-      * @param list<string> $ids
-      *
-      * @return list<string>
-      */
-     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]
-         );
-     }
-     /**
-      * @return list<string>
-      */
-     private function getChangedShippingMethods(EntityWrittenContainerEvent $event): array
-     {
-         $ids = $event->getPrimaryKeys(ShippingMethodDefinition::ENTITY_NAME);
-         if (empty($ids)) {
-             return [];
-         }
-         $ids = $this->connection->fetchFirstColumn(
-             'SELECT DISTINCT LOWER(HEX(sales_channel_id)) as id FROM sales_channel_shipping_method WHERE shipping_method_id IN (:ids)',
-             ['ids' => Uuid::fromHexToBytesList($ids)],
-             ['ids' => Connection::PARAM_STR_ARRAY]
-         );
-         $tags = [];
-         if ($event->getDeletedPrimaryKeys(ShippingMethodDefinition::ENTITY_NAME)) {
-             $tags[] = CachedShippingMethodRoute::ALL_TAG;
-         }
-         return array_merge($tags, array_map([CachedShippingMethodRoute::class, 'buildName'], $ids));
-     }
-     /**
-      * @return list<string>
-      */
-     private function getChangedShippingAssignments(EntityWrittenContainerEvent $event): array
-     {
-         //Used to detect changes to the shipping assignment of a sales channel
-         $ids = $event->getPrimaryKeys(SalesChannelShippingMethodDefinition::ENTITY_NAME);
-         $ids = array_column($ids, 'salesChannelId');
-         return array_map([CachedShippingMethodRoute::class, 'buildName'], $ids);
-     }
-     /**
-      * @return list<string>
-      */
-     private function getChangedPaymentMethods(EntityWrittenContainerEvent $event): array
-     {
-         $ids = $event->getPrimaryKeys(PaymentMethodDefinition::ENTITY_NAME);
-         if (empty($ids)) {
-             return [];
-         }
-         $ids = $this->connection->fetchFirstColumn(
-             'SELECT DISTINCT LOWER(HEX(sales_channel_id)) as id FROM sales_channel_payment_method WHERE payment_method_id IN (:ids)',
-             ['ids' => Uuid::fromHexToBytesList($ids)],
-             ['ids' => Connection::PARAM_STR_ARRAY]
-         );
-         $tags = [];
-         if ($event->getDeletedPrimaryKeys(PaymentMethodDefinition::ENTITY_NAME)) {
-             $tags[] = CachedPaymentMethodRoute::ALL_TAG;
-         }
-         return array_merge($tags, array_map([CachedPaymentMethodRoute::class, 'buildName'], $ids));
-     }
-     /**
-      * @return list<string>
-      */
-     private function getChangedPaymentAssignments(EntityWrittenContainerEvent $event): array
-     {
-         //Used to detect changes to the language assignment of a sales channel
-         $ids = $event->getPrimaryKeys(SalesChannelPaymentMethodDefinition::ENTITY_NAME);
-         $ids = array_column($ids, 'salesChannelId');
-         return array_map([CachedPaymentMethodRoute::class, 'buildName'], $ids);
-     }
-     /**
-      * @return list<string>
-      */
-     private function getChangedCategories(EntityWrittenContainerEvent $event): array
-     {
-         $ids = $event->getPrimaryKeysWithPayload(CategoryDefinition::ENTITY_NAME);
-         if (empty($ids)) {
-             return [];
-         }
-         $ids = array_map([CachedNavigationRoute::class, 'buildName'], $ids);
-         $ids[] = CachedNavigationRoute::BASE_NAVIGATION_TAG;
-         return $ids;
-     }
-     /**
-      * @return list<string>
-      */
-     private function getChangedEntryPoints(EntityWrittenContainerEvent $event): array
-     {
-         $ids = $event->getPrimaryKeysWithPropertyChange(
-             SalesChannelDefinition::ENTITY_NAME,
-             ['navigationCategoryId', 'navigationCategoryDepth', 'serviceCategoryId', 'footerCategoryId']
-         );
-         if (empty($ids)) {
-             return [];
-         }
-         return [CachedNavigationRoute::ALL_TAG];
-     }
-     /**
-      * @return list<string>
-      */
-     private function getChangedCountries(EntityWrittenContainerEvent $event): array
-     {
-         $ids = $event->getPrimaryKeys(CountryDefinition::ENTITY_NAME);
-         if (empty($ids)) {
-             return [];
-         }
-         //Used to detect changes to the country itself and invalidate the route for all sales channels in which the country is assigned.
-         $ids = $this->connection->fetchFirstColumn(
-             'SELECT DISTINCT LOWER(HEX(sales_channel_id)) as id FROM sales_channel_country WHERE country_id IN (:ids)',
-             ['ids' => Uuid::fromHexToBytesList($ids)],
-             ['ids' => Connection::PARAM_STR_ARRAY]
-         );
-         $tags = [];
-         if ($event->getDeletedPrimaryKeys(CountryDefinition::ENTITY_NAME)) {
-             $tags[] = CachedCountryRoute::ALL_TAG;
-         }
-         return array_merge($tags, array_map([CachedCountryRoute::class, 'buildName'], $ids));
-     }
-     /**
-      * @return list<string>
-      */
-     private function getChangedCountryAssignments(EntityWrittenContainerEvent $event): array
-     {
-         //Used to detect changes to the country assignment of a sales channel
-         $ids = $event->getPrimaryKeys(SalesChannelCountryDefinition::ENTITY_NAME);
-         $ids = array_column($ids, 'salesChannelId');
-         return array_map([CachedCountryRoute::class, 'buildName'], $ids);
-     }
-     /**
-      * @return list<string>
-      */
-     private function getChangedSalutations(EntityWrittenContainerEvent $event): array
-     {
-         $ids = $event->getPrimaryKeys(SalutationDefinition::ENTITY_NAME);
-         if (empty($ids)) {
-             return [];
-         }
-         return [CachedSalutationRoute::ALL_TAG];
-     }
-     /**
-      * @return list<string>
-      */
-     private function getChangedLanguages(EntityWrittenContainerEvent $event): array
-     {
-         $ids = $event->getPrimaryKeys(LanguageDefinition::ENTITY_NAME);
-         if (empty($ids)) {
-             return [];
-         }
-         //Used to detect changes to the language itself and invalidate the route for all sales channels in which the language is assigned.
-         $ids = $this->connection->fetchFirstColumn(
-             'SELECT DISTINCT LOWER(HEX(sales_channel_id)) as id FROM sales_channel_language WHERE language_id IN (:ids)',
-             ['ids' => Uuid::fromHexToBytesList($ids)],
-             ['ids' => Connection::PARAM_STR_ARRAY]
-         );
-         $tags = [];
-         if ($event->getDeletedPrimaryKeys(LanguageDefinition::ENTITY_NAME)) {
-             $tags[] = CachedLanguageRoute::ALL_TAG;
-         }
-         return array_merge($tags, array_map([CachedLanguageRoute::class, 'buildName'], $ids));
-     }
-     /**
-      * @return list<string>
-      */
-     private function getChangedLanguageAssignments(EntityWrittenContainerEvent $event): array
-     {
-         //Used to detect changes to the language assignment of a sales channel
-         $ids = $event->getPrimaryKeys(SalesChannelLanguageDefinition::ENTITY_NAME);
-         $ids = array_column($ids, 'salesChannelId');
-         return array_map([CachedLanguageRoute::class, 'buildName'], $ids);
-     }
-     /**
-      * @return list<string>
-      */
-     private function getChangedCurrencies(EntityWrittenContainerEvent $event): array
-     {
-         $ids = $event->getPrimaryKeys(CurrencyDefinition::ENTITY_NAME);
-         if (empty($ids)) {
-             return [];
-         }
-         //Used to detect changes to the currency itself and invalidate the route for all sales channels in which the currency is assigned.
-         $ids = $this->connection->fetchFirstColumn(
-             'SELECT DISTINCT LOWER(HEX(sales_channel_id)) as id FROM sales_channel_currency WHERE currency_id IN (:ids)',
-             ['ids' => Uuid::fromHexToBytesList($ids)],
-             ['ids' => Connection::PARAM_STR_ARRAY]
-         );
-         $tags = [];
-         if ($event->getDeletedPrimaryKeys(CurrencyDefinition::ENTITY_NAME)) {
-             $tags[] = CachedCurrencyRoute::ALL_TAG;
-         }
-         return array_merge($tags, array_map([CachedCurrencyRoute::class, 'buildName'], $ids));
-     }
-     /**
-      * @return list<string>
-      */
-     private function getChangedCurrencyAssignments(EntityWrittenContainerEvent $event): array
-     {
-         //Used to detect changes to the currency assignment of a sales channel
-         $ids = $event->getPrimaryKeys(SalesChannelCurrencyDefinition::ENTITY_NAME);
-         $ids = array_column($ids, 'salesChannelId');
-         return array_map([CachedCurrencyRoute::class, 'buildName'], $ids);
-     }
- }
-