platform/src/Core/Content/Category/Validation/EntryPointValidator.php line 50

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.     public function __construct(Connection $connection)
  33.     {
  34.         $this->connection $connection;
  35.     }
  36.     public static function getSubscribedEvents(): array
  37.     {
  38.         return [
  39.             PostWriteValidationEvent::class => 'postValidate',
  40.         ];
  41.     }
  42.     public function postValidate(PostWriteValidationEvent $event): void
  43.     {
  44.         $violationList = new ConstraintViolationList();
  45.         foreach ($event->getCommands() as $command) {
  46.             if (!($command instanceof InsertCommand || $command instanceof UpdateCommand)) {
  47.                 continue;
  48.             }
  49.             if ($command->getDefinition()->getClass() !== CategoryDefinition::class) {
  50.                 continue;
  51.             }
  52.             if (!isset($command->getPayload()['type'])) {
  53.                 continue;
  54.             }
  55.             $violationList->addAll($this->checkTypeChange($command$event));
  56.         }
  57.         if ($violationList->count() > 0) {
  58.             $event->getExceptions()->add(new WriteConstraintViolationException($violationList));
  59.             return;
  60.         }
  61.     }
  62.     private function checkTypeChange(WriteCommand $commandPostWriteValidationEvent $event): ConstraintViolationListInterface
  63.     {
  64.         $violationList = new ConstraintViolationList();
  65.         $payload $command->getPayload();
  66.         if (\in_array($payload['type'], self::ALLOWED_TYPE_CHANGEtrue)) {
  67.             return $violationList;
  68.         }
  69.         if ($this->isCategoryEntryPoint($command->getPrimaryKey()['id'], $event)) {
  70.             return $violationList;
  71.         }
  72.         $messageTemplate 'The type can not be assigned while category is entry point.';
  73.         $parameters = ['{{ value }}' => $payload['type']];
  74.         $violationList->add(new ConstraintViolation(
  75.             str_replace(array_keys($parameters), $parameters$messageTemplate),
  76.             $messageTemplate,
  77.             $parameters,
  78.             null,
  79.             sprintf('%s/type'$command->getPath()),
  80.             $payload['type'],
  81.             null,
  82.             self::ERROR_CODE
  83.         ));
  84.         return $violationList;
  85.     }
  86.     private function isCategoryEntryPoint(string $categoryIdPostWriteValidationEvent $event): bool
  87.     {
  88.         foreach ($event->getCommands() as $salesChannelCommand) {
  89.             if ($salesChannelCommand->getDefinition()->getClass() !== SalesChannelDefinition::class) {
  90.                 continue;
  91.             }
  92.             $payload $salesChannelCommand->getPayload();
  93.             if ((isset($payload['navigation_category_id']) && $payload['navigation_category_id'] === $categoryId)
  94.                 || (isset($payload['footer_category_id']) && $payload['footer_category_id'] === $categoryId)
  95.                 || (isset($payload['service_category_id']) && $payload['service_category_id'] === $categoryId)
  96.             ) {
  97.                 return false;
  98.             }
  99.         }
  100.         $query $this->connection->createQueryBuilder()
  101.             ->select('id')
  102.             ->from(SalesChannelDefinition::ENTITY_NAME)
  103.             ->where('navigation_category_id = :navigation_id')
  104.             ->orWhere('footer_category_id = :footer_id')
  105.             ->orWhere('service_category_id = :service_id')
  106.             ->setParameter('navigation_id'$categoryId)
  107.             ->setParameter('footer_id'$categoryId)
  108.             ->setParameter('service_id'$categoryId)
  109.             ->setMaxResults(1)
  110.             ->execute();
  111.         if (!($query instanceof ResultStatement)) {
  112.             return true;
  113.         }
  114.         return !(bool) $query->fetchColumn();
  115.     }
  116. }