vendor/shopware/core/Framework/DataAbstractionLayer/Write/Validation/LockValidator.php line 43

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Framework\DataAbstractionLayer\Write\Validation;
  3. use Doctrine\DBAL\Connection;
  4. use Shopware\Core\Framework\DataAbstractionLayer\Dbal\EntityDefinitionQueryHelper;
  5. use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\InsertCommand;
  6. use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\WriteCommand;
  7. use Shopware\Core\Framework\Log\Package;
  8. use Shopware\Core\Framework\Validation\WriteConstraintViolationException;
  9. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  10. use Symfony\Component\Validator\ConstraintViolation;
  11. use Symfony\Component\Validator\ConstraintViolationList;
  12. /**
  13. * @deprecated tag:v6.5.0 - reason:becomes-internal - EventSubscribers will become internal in v6.5.0
  14. */
  15. #[Package('core')]
  16. class LockValidator implements EventSubscriberInterface
  17. {
  18. public const VIOLATION_LOCKED = 'FRAMEWORK__ENTITY_IS_LOCKED';
  19. private Connection $connection;
  20. /**
  21. * @internal
  22. */
  23. public function __construct(Connection $connection)
  24. {
  25. $this->connection = $connection;
  26. }
  27. public static function getSubscribedEvents(): array
  28. {
  29. return [
  30. PreWriteValidationEvent::class => 'preValidate',
  31. ];
  32. }
  33. /**
  34. * @throws WriteConstraintViolationException
  35. */
  36. public function preValidate(PreWriteValidationEvent $event): void
  37. {
  38. $violations = new ConstraintViolationList();
  39. $writeCommands = $event->getCommands();
  40. $lockedEntities = $this->containsLockedEntities($writeCommands);
  41. if (empty($lockedEntities)) {
  42. return;
  43. }
  44. $message = 'The %s entity is locked and can neither be modified nor deleted.';
  45. foreach ($lockedEntities as $entity => $_isLocked) {
  46. $violations->add(new ConstraintViolation(
  47. sprintf($message, $entity),
  48. sprintf($message, '{{ entity }}'),
  49. ['{{ entity }}' => $entity],
  50. null,
  51. '/',
  52. null,
  53. null,
  54. self::VIOLATION_LOCKED
  55. ));
  56. }
  57. $event->getExceptions()->add(new WriteConstraintViolationException($violations));
  58. }
  59. /**
  60. * @param WriteCommand[] $writeCommands
  61. *
  62. * @return array<string, bool>
  63. */
  64. private function containsLockedEntities(array $writeCommands): array
  65. {
  66. $ids = [];
  67. $locked = [];
  68. foreach ($writeCommands as $command) {
  69. if ($command instanceof InsertCommand) {
  70. continue;
  71. }
  72. if (!$command->getDefinition()->isLockAware()) {
  73. continue;
  74. }
  75. $ids[$command->getDefinition()->getEntityName()][] = $command->getPrimaryKey()['id'];
  76. }
  77. /** @var string $entityName */
  78. foreach ($ids as $entityName => $primaryKeys) {
  79. $locked[$entityName] = $this->connection->createQueryBuilder()
  80. ->select('1')
  81. ->from(EntityDefinitionQueryHelper::escape($entityName))
  82. ->where('`id` IN (:ids) AND `locked` = 1')
  83. ->setParameter('ids', $primaryKeys, Connection::PARAM_STR_ARRAY)
  84. ->execute()
  85. ->rowCount() > 0;
  86. }
  87. return array_filter($locked);
  88. }
  89. }