vendor/shopware/core/Content/Cms/Subscriber/CmsPageDefaultChangeSubscriber.php line 50

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Content\Cms\Subscriber;
  3. use Doctrine\DBAL\Connection;
  4. use Shopware\Core\Content\Category\CategoryDefinition;
  5. use Shopware\Core\Content\Cms\CmsException;
  6. use Shopware\Core\Content\Cms\CmsPageDefinition;
  7. use Shopware\Core\Content\Cms\Exception\PageNotFoundException;
  8. use Shopware\Core\Content\Product\ProductDefinition;
  9. use Shopware\Core\Defaults;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Event\BeforeDeleteEvent;
  11. use Shopware\Core\Framework\Uuid\Uuid;
  12. use Shopware\Core\System\SystemConfig\Event\BeforeSystemConfigChangedEvent;
  13. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  14. class CmsPageDefaultChangeSubscriber implements EventSubscriberInterface
  15. {
  16.     /**
  17.      * @var array<string>
  18.      */
  19.     public static array $defaultCmsPageConfigKeys = [
  20.         ProductDefinition::CONFIG_KEY_DEFAULT_CMS_PAGE_PRODUCT,
  21.         CategoryDefinition::CONFIG_KEY_DEFAULT_CMS_PAGE_CATEGORY,
  22.     ];
  23.     private Connection $connection;
  24.     /**
  25.      * @internal
  26.      */
  27.     public function __construct(
  28.         Connection $connection
  29.     ) {
  30.         $this->connection $connection;
  31.     }
  32.     public static function getSubscribedEvents(): array
  33.     {
  34.         return [
  35.             BeforeSystemConfigChangedEvent::class => 'validateChangeOfDefaultCmsPage',
  36.             BeforeDeleteEvent::class => 'beforeDeletion',
  37.         ];
  38.     }
  39.     /**
  40.      * @throws CmsException
  41.      * @throws \JsonException
  42.      */
  43.     public function beforeDeletion(BeforeDeleteEvent $event): void
  44.     {
  45.         $cmsPageIds $event->getIds(CmsPageDefinition::ENTITY_NAME);
  46.         // no cms page is affected by this deletion event
  47.         if (empty($cmsPageIds)) {
  48.             return;
  49.         }
  50.         $defaultPages $this->cmsPageIsDefault($cmsPageIds);
  51.         // count !== 0 indicates that there are some cms pages which would be deleted but are currently a default
  52.         if (\count($defaultPages) !== 0) {
  53.             throw CmsException::deletionOfDefault($defaultPages);
  54.         }
  55.     }
  56.     /**
  57.      * @throws CmsException
  58.      * @throws PageNotFoundException
  59.      */
  60.     public function validateChangeOfDefaultCmsPage(BeforeSystemConfigChangedEvent $event): void
  61.     {
  62.         $newDefaultCmsPageId $event->getValue();
  63.         $systemConfigKey $event->getKey();
  64.         $salesChannelId $event->getSalesChannelId();
  65.         if (!\in_array($systemConfigKeyself::$defaultCmsPageConfigKeystrue)) {
  66.             return;
  67.         }
  68.         // prevent deleting the overall default (salesChannelId === null)
  69.         // a sales channel specific default can still be deleted (salesChannelId !== null)
  70.         if ($newDefaultCmsPageId === null && $salesChannelId === null) {
  71.             $oldCmsPageId $this->getCurrentOverallDefaultCmsPageId($systemConfigKey);
  72.             throw CmsException::overallDefaultSystemConfigDeletion($oldCmsPageId);
  73.         }
  74.         if (!\is_string($newDefaultCmsPageId) && $newDefaultCmsPageId !== null) {
  75.             throw new PageNotFoundException('invalid page');
  76.         }
  77.         // prevent changing the default to an invalid cms page id
  78.         if (\is_string($newDefaultCmsPageId) && !$this->cmsPageExists($newDefaultCmsPageId)) {
  79.             throw new PageNotFoundException($newDefaultCmsPageId);
  80.         }
  81.     }
  82.     private function getCurrentOverallDefaultCmsPageId(string $systemConfigKey): string
  83.     {
  84.         $result $this->connection->fetchOne(
  85.             'SELECT configuration_value FROM system_config WHERE configuration_key = :configKey AND sales_channel_id is NULL;',
  86.             [
  87.                 'configKey' => $systemConfigKey,
  88.             ]
  89.         );
  90.         $config json_decode($resulttrue);
  91.         return $config['_value'];
  92.     }
  93.     /**
  94.      * @param array<string> $cmsPageIds
  95.      *
  96.      * @return array<string>
  97.      */
  98.     private function cmsPageIsDefault(array $cmsPageIds): array
  99.     {
  100.         $configurations $this->connection->fetchAllAssociative(
  101.             'SELECT DISTINCT configuration_value FROM system_config WHERE configuration_key IN (:configKeys);',
  102.             [
  103.                 'configKeys' => self::$defaultCmsPageConfigKeys,
  104.             ],
  105.             [
  106.                 'configKeys' => Connection::PARAM_STR_ARRAY,
  107.             ]
  108.         );
  109.         $defaultIds = [];
  110.         foreach ($configurations as $configuration) {
  111.             $configValue $configuration['configuration_value'];
  112.             $config json_decode($configValuetrue);
  113.             $defaultIds[] = $config['_value'];
  114.         }
  115.         // returns from all provided cms pages the ones which are default
  116.         return array_intersect($cmsPageIds$defaultIds);
  117.     }
  118.     private function cmsPageExists(string $cmsPageId): bool
  119.     {
  120.         $count $this->connection->fetchOne(
  121.             'SELECT count(*) FROM cms_page WHERE id = :cmsPageId AND version_id = :versionId LIMIT 1;',
  122.             [
  123.                 'cmsPageId' => Uuid::fromHexToBytes($cmsPageId),
  124.                 'versionId' => Uuid::fromHexToBytes(Defaults::LIVE_VERSION),
  125.             ]
  126.         );
  127.         return $count === '1';
  128.     }
  129. }