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

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