custom/plugins/SwagCmsExtensions/src/Form/Validation/TechnicalNameValidator.php line 40

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 Swag\CmsExtensions\Form\Validation;
  8. use Doctrine\DBAL\Connection;
  9. use Doctrine\DBAL\Driver\ResultStatement;
  10. use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\DeleteCommand;
  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\PreWriteValidationEvent;
  15. use Shopware\Core\Framework\Validation\WriteConstraintViolationException;
  16. use Swag\CmsExtensions\Form\FormDefinition;
  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 TechnicalNameValidator implements EventSubscriberInterface
  22. {
  23.     private Connection $connection;
  24.     public function __construct(Connection $connection)
  25.     {
  26.         $this->connection $connection;
  27.     }
  28.     public static function getSubscribedEvents(): array
  29.     {
  30.         return [
  31.             PreWriteValidationEvent::class => 'preValidate',
  32.         ];
  33.     }
  34.     public function preValidate(PreWriteValidationEvent $event): void
  35.     {
  36.         $violationList = new ConstraintViolationList();
  37.         foreach ($event->getCommands() as $command) {
  38.             if (!($command instanceof InsertCommand || $command instanceof UpdateCommand)) {
  39.                 continue;
  40.             }
  41.             if ($command->getDefinition()->getClass() !== FormDefinition::class) {
  42.                 continue;
  43.             }
  44.             $violationList->addAll($this->validateTechnicalName($command$event));
  45.         }
  46.         if ($violationList->count() > 0) {
  47.             $event->getExceptions()->add(new WriteConstraintViolationException($violationList));
  48.             return;
  49.         }
  50.     }
  51.     private function validateTechnicalName(WriteCommand $commandPreWriteValidationEvent $event): ConstraintViolationListInterface
  52.     {
  53.         $violationList = new ConstraintViolationList();
  54.         $payload $command->getPayload();
  55.         if (!isset($payload['technical_name'])) {
  56.             return $violationList;
  57.         }
  58.         if ($this->isTechnicalNameUnique($command->getPrimaryKey()['id'], $payload['technical_name'], $event)) {
  59.             return $violationList;
  60.         }
  61.         $messageTemplate 'The technical name (%value%) of this form is not unique or a form template with this name already exists.';
  62.         $parameters = ['%value%' => $payload['technical_name'] ?? 'NULL'];
  63.         $violationList->add(new ConstraintViolation(
  64.             \str_replace(\array_keys($parameters), $parameters$messageTemplate),
  65.             $messageTemplate,
  66.             $parameters,
  67.             null,
  68.             \sprintf('%s/technicalName'$command->getPath()),
  69.             null
  70.         ));
  71.         return $violationList;
  72.     }
  73.     private function isTechnicalNameUnique(string $formIdstring $technicalNamePreWriteValidationEvent $event): bool
  74.     {
  75.         $ignoredIds = [$formId];
  76.         foreach ($event->getCommands() as $formCommand) {
  77.             if ($formCommand->getDefinition()->getClass() !== FormDefinition::class) {
  78.                 continue;
  79.             }
  80.             $otherId $formCommand->getPrimaryKey()['id'];
  81.             if ($formId === $otherId) {
  82.                 continue;
  83.             }
  84.             if ($formCommand instanceof DeleteCommand) {
  85.                 $ignoredIds[] = $formCommand->getPrimaryKey()['id'];
  86.                 continue;
  87.             }
  88.             $payload $formCommand->getPayload();
  89.             if (isset($payload['technical_name']) && $payload['technical_name'] === $technicalName) {
  90.                 return false;
  91.             }
  92.         }
  93.         $query $this->connection->createQueryBuilder()
  94.             ->select('technical_name')
  95.             ->from(FormDefinition::ENTITY_NAME)
  96.             ->where('technical_name = :technical_name')
  97.             ->andWhere('id NOT IN (:ids)')
  98.             ->setParameter('technical_name'$technicalName)
  99.             ->setParameter('ids'$ignoredIdsConnection::PARAM_STR_ARRAY)
  100.             ->setMaxResults(1)
  101.             ->execute();
  102.         if (!($query instanceof ResultStatement)) {
  103.             return true;
  104.         }
  105.         return !(bool) $query->fetchColumn();
  106.     }
  107. }