src/Core/Checkout/Customer/Subscriber/CustomerGroupSubscriber.php line 63

  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Checkout\Customer\Subscriber;
  3. use Cocur\Slugify\SlugifyInterface;
  4. use Shopware\Core\Checkout\Customer\Aggregate\CustomerGroup\CustomerGroupCollection;
  5. use Shopware\Core\Checkout\Customer\Aggregate\CustomerGroupTranslation\CustomerGroupTranslationCollection;
  6. use Shopware\Core\Content\Seo\SeoUrlPersister;
  7. use Shopware\Core\Defaults;
  8. use Shopware\Core\Framework\Context;
  9. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityDeletedEvent;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
  15. use Shopware\Core\Framework\Log\Package;
  16. use Shopware\Core\System\Language\LanguageCollection;
  17. use Shopware\Core\System\Language\LanguageEntity;
  18. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  19. /**
  20.  * @internal
  21.  */
  22. #[Package('customer-order')]
  23. class CustomerGroupSubscriber implements EventSubscriberInterface
  24. {
  25.     private const ROUTE_NAME 'frontend.account.customer-group-registration.page';
  26.     /**
  27.      * @internal
  28.      */
  29.     public function __construct(private readonly EntityRepository $customerGroupRepository, private readonly EntityRepository $seoUrlRepository, private readonly EntityRepository $languageRepository, private readonly SeoUrlPersister $persister, private readonly SlugifyInterface $slugify)
  30.     {
  31.     }
  32.     public static function getSubscribedEvents(): array
  33.     {
  34.         return [
  35.             'customer_group_translation.written' => 'updatedCustomerGroup',
  36.             'customer_group_registration_sales_channels.written' => 'newSalesChannelAddedToCustomerGroup',
  37.             'customer_group_translation.deleted' => 'deleteCustomerGroup',
  38.         ];
  39.     }
  40.     public function newSalesChannelAddedToCustomerGroup(EntityWrittenEvent $event): void
  41.     {
  42.         $ids = [];
  43.         foreach ($event->getWriteResults() as $writeResult) {
  44.             /** @var array<string, string> $pk */
  45.             $pk $writeResult->getPrimaryKey();
  46.             $ids[] = $pk['customerGroupId'];
  47.         }
  48.         if (\count($ids) === 0) {
  49.             return;
  50.         }
  51.         $this->createUrls($ids$event->getContext());
  52.     }
  53.     public function updatedCustomerGroup(EntityWrittenEvent $event): void
  54.     {
  55.         $ids = [];
  56.         foreach ($event->getWriteResults() as $writeResult) {
  57.             if ($writeResult->hasPayload('registrationTitle')) {
  58.                 /** @var array<string, string> $pk */
  59.                 $pk $writeResult->getPrimaryKey();
  60.                 $ids[] = $pk['customerGroupId'];
  61.             }
  62.         }
  63.         if (\count($ids) === 0) {
  64.             return;
  65.         }
  66.         $this->createUrls($ids$event->getContext());
  67.     }
  68.     public function deleteCustomerGroup(EntityDeletedEvent $event): void
  69.     {
  70.         $ids = [];
  71.         foreach ($event->getWriteResults() as $writeResult) {
  72.             /** @var array<string, string> $pk */
  73.             $pk $writeResult->getPrimaryKey();
  74.             $ids[] = $pk['customerGroupId'];
  75.         }
  76.         if (\count($ids) === 0) {
  77.             return;
  78.         }
  79.         $criteria = new Criteria();
  80.         $criteria->addFilter(new EqualsAnyFilter('foreignKey'$ids));
  81.         $criteria->addFilter(new EqualsFilter('routeName'self::ROUTE_NAME));
  82.         /** @var array<string> $ids */
  83.         $ids array_values($this->seoUrlRepository->searchIds($criteria$event->getContext())->getIds());
  84.         if (\count($ids) === 0) {
  85.             return;
  86.         }
  87.         $this->seoUrlRepository->delete(array_map(fn (string $id) => ['id' => $id], $ids), $event->getContext());
  88.     }
  89.     /**
  90.      * @param list<string> $ids
  91.      */
  92.     private function createUrls(array $idsContext $context): void
  93.     {
  94.         $criteria = new Criteria($ids);
  95.         $criteria->addFilter(new EqualsFilter('registrationActive'true));
  96.         $criteria->addAssociation('registrationSalesChannels.languages');
  97.         $criteria->addAssociation('translations');
  98.         /** @var CustomerGroupCollection $groups */
  99.         $groups $this->customerGroupRepository->search($criteria$context)->getEntities();
  100.         $buildUrls = [];
  101.         foreach ($groups as $group) {
  102.             if ($group->getRegistrationSalesChannels() === null) {
  103.                 continue;
  104.             }
  105.             foreach ($group->getRegistrationSalesChannels() as $registrationSalesChannel) {
  106.                 if ($registrationSalesChannel->getLanguages() === null) {
  107.                     continue;
  108.                 }
  109.                 /** @var array<string> $languageIds */
  110.                 $languageIds $registrationSalesChannel->getLanguages()->getIds();
  111.                 $criteria = new Criteria($languageIds);
  112.                 /** @var LanguageCollection $languageCollection */
  113.                 $languageCollection $this->languageRepository->search($criteria$context)->getEntities();
  114.                 foreach ($languageIds as $languageId) {
  115.                     /** @var LanguageEntity $language */
  116.                     $language $languageCollection->get($languageId);
  117.                     $title $this->getTranslatedTitle($group->getTranslations(), $language);
  118.                     if (!isset($buildUrls[$languageId])) {
  119.                         $buildUrls[$languageId] = [
  120.                             'urls' => [],
  121.                             'salesChannel' => $registrationSalesChannel,
  122.                         ];
  123.                     }
  124.                     $buildUrls[$languageId]['urls'][] = [
  125.                         'salesChannelId' => $registrationSalesChannel->getId(),
  126.                         'foreignKey' => $group->getId(),
  127.                         'routeName' => self::ROUTE_NAME,
  128.                         'pathInfo' => '/customer-group-registration/' $group->getId(),
  129.                         'isCanonical' => true,
  130.                         'seoPathInfo' => '/' $this->slugify->slugify($title),
  131.                     ];
  132.                 }
  133.             }
  134.         }
  135.         foreach ($buildUrls as $languageId => $config) {
  136.             $context = new Context(
  137.                 $context->getSource(),
  138.                 $context->getRuleIds(),
  139.                 $context->getCurrencyId(),
  140.                 [$languageId]
  141.             );
  142.             $this->persister->updateSeoUrls(
  143.                 $context,
  144.                 self::ROUTE_NAME,
  145.                 array_column($config['urls'], 'foreignKey'),
  146.                 $config['urls'],
  147.                 $config['salesChannel']
  148.             );
  149.         }
  150.     }
  151.     private function getTranslatedTitle(?CustomerGroupTranslationCollection $translationsLanguageEntity $language): string
  152.     {
  153.         if ($translations === null) {
  154.             return '';
  155.         }
  156.         // Requested translation
  157.         foreach ($translations as $translation) {
  158.             if ($translation->getLanguageId() === $language->getId() && $translation->getRegistrationTitle() !== null) {
  159.                 return $translation->getRegistrationTitle();
  160.             }
  161.         }
  162.         // Inherited translation
  163.         foreach ($translations as $translation) {
  164.             if ($translation->getLanguageId() === $language->getParentId() && $translation->getRegistrationTitle() !== null) {
  165.                 return $translation->getRegistrationTitle();
  166.             }
  167.         }
  168.         // System Language
  169.         foreach ($translations as $translation) {
  170.             if ($translation->getLanguageId() === Defaults::LANGUAGE_SYSTEM && $translation->getRegistrationTitle() !== null) {
  171.                 return $translation->getRegistrationTitle();
  172.             }
  173.         }
  174.         return '';
  175.     }
  176. }