vendor/shopware/core/Content/Category/Validation/EntryPointValidator.php line 53

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. /*
  3.  * (c) shopware AG <info@shopware.com>
  4.  * For the full copyright and license information, please view the LICENSE
  5.  * file that was distributed with this source code.
  6.  */
  7. namespace Shopware\Core\Content\Category\Validation;
  8. use Doctrine\DBAL\Connection;
  9. use Doctrine\DBAL\Driver\ResultStatement;
  10. use Shopware\Core\Content\Category\CategoryDefinition;
  11. use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\InsertCommand;
  12. use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\UpdateCommand;
  13. use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\WriteCommand;
  14. use Shopware\Core\Framework\DataAbstractionLayer\Write\Validation\PostWriteValidationEvent;
  15. use Shopware\Core\Framework\Validation\WriteConstraintViolationException;
  16. use Shopware\Core\System\SalesChannel\SalesChannelDefinition;
  17. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  18. use Symfony\Component\Validator\ConstraintViolation;
  19. use Symfony\Component\Validator\ConstraintViolationList;
  20. use Symfony\Component\Validator\ConstraintViolationListInterface;
  21. class EntryPointValidator implements EventSubscriberInterface
  22. {
  23.     private const ERROR_CODE 'CONTENT__INVALID_CATEGORY_TYPE_AS_ENTRY_POINT';
  24.     private const ALLOWED_TYPE_CHANGE = [
  25.         CategoryDefinition::TYPE_PAGE,
  26.         CategoryDefinition::TYPE_FOLDER,
  27.     ];
  28.     /**
  29.      * @var Connection
  30.      */
  31.     private $connection;
  32.     /**
  33.      * @internal
  34.      */
  35.     public function __construct(Connection $connection)
  36.     {
  37.         $this->connection $connection;
  38.     }
  39.     public static function getSubscribedEvents(): array
  40.     {
  41.         return [
  42.             PostWriteValidationEvent::class => 'postValidate',
  43.         ];
  44.     }
  45.     public function postValidate(PostWriteValidationEvent $event): void
  46.     {
  47.         $violationList = new ConstraintViolationList();
  48.         foreach ($event->getCommands() as $command) {
  49.             if (!($command instanceof InsertCommand || $command instanceof UpdateCommand)) {
  50.                 continue;
  51.             }
  52.             if ($command->getDefinition()->getClass() !== CategoryDefinition::class) {
  53.                 continue;
  54.             }
  55.             if (!isset($command->getPayload()['type'])) {
  56.                 continue;
  57.             }
  58.             $violationList->addAll($this->checkTypeChange($command$event));
  59.         }
  60.         if ($violationList->count() > 0) {
  61.             $event->getExceptions()->add(new WriteConstraintViolationException($violationList));
  62.             return;
  63.         }
  64.     }
  65.     private function checkTypeChange(WriteCommand $commandPostWriteValidationEvent $event): ConstraintViolationListInterface
  66.     {
  67.         $violationList = new ConstraintViolationList();
  68.         $payload $command->getPayload();
  69.         if (\in_array($payload['type'], self::ALLOWED_TYPE_CHANGEtrue)) {
  70.             return $violationList;
  71.         }
  72.         if ($this->isCategoryEntryPoint($command->getPrimaryKey()['id'], $event)) {
  73.             return $violationList;
  74.         }
  75.         $messageTemplate 'The type can not be assigned while category is entry point.';
  76.         $parameters = ['{{ value }}' => $payload['type']];
  77.         $violationList->add(new ConstraintViolation(
  78.             str_replace(array_keys($parameters), $parameters$messageTemplate),
  79.             $messageTemplate,
  80.             $parameters,
  81.             null,
  82.             sprintf('%s/type'$command->getPath()),
  83.             $payload['type'],
  84.             null,
  85.             self::ERROR_CODE
  86.         ));
  87.         return $violationList;
  88.     }
  89.     private function isCategoryEntryPoint(string $categoryIdPostWriteValidationEvent $event): bool
  90.     {
  91.         foreach ($event->getCommands() as $salesChannelCommand) {
  92.             if ($salesChannelCommand->getDefinition()->getClass() !== SalesChannelDefinition::class) {
  93.                 continue;
  94.             }
  95.             $payload $salesChannelCommand->getPayload();
  96.             if ((isset($payload['navigation_category_id']) && $payload['navigation_category_id'] === $categoryId)
  97.                 || (isset($payload['footer_category_id']) && $payload['footer_category_id'] === $categoryId)
  98.                 || (isset($payload['service_category_id']) && $payload['service_category_id'] === $categoryId)
  99.             ) {
  100.                 return false;
  101.             }
  102.         }
  103.         $query $this->connection->createQueryBuilder()
  104.             ->select('id')
  105.             ->from(SalesChannelDefinition::ENTITY_NAME)
  106.             ->where('navigation_category_id = :navigation_id')
  107.             ->orWhere('footer_category_id = :footer_id')
  108.             ->orWhere('service_category_id = :service_id')
  109.             ->setParameter('navigation_id'$categoryId)
  110.             ->setParameter('footer_id'$categoryId)
  111.             ->setParameter('service_id'$categoryId)
  112.             ->setMaxResults(1)
  113.             ->execute();
  114.         if (!($query instanceof ResultStatement)) {
  115.             return true;
  116.         }
  117.         return !(bool) $query->fetchColumn();
  118.     }
  119. }