vendor/shopware/core/System/Language/TranslationValidator.php line 33

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\System\Language;
  3. use Shopware\Core\Defaults;
  4. use Shopware\Core\Framework\DataAbstractionLayer\EntityTranslationDefinition;
  5. use Shopware\Core\Framework\DataAbstractionLayer\Field\FkField;
  6. use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\CascadeDeleteCommand;
  7. use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\DeleteCommand;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\WriteCommand;
  9. use Shopware\Core\Framework\DataAbstractionLayer\Write\Validation\PreWriteValidationEvent;
  10. use Shopware\Core\Framework\Uuid\Uuid;
  11. use Shopware\Core\Framework\Validation\WriteConstraintViolationException;
  12. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  13. use Symfony\Component\Validator\ConstraintViolation;
  14. use Symfony\Component\Validator\ConstraintViolationInterface;
  15. use Symfony\Component\Validator\ConstraintViolationList;
  16. /**
  17.  * @deprecated tag:v6.5.0 - reason:becomes-internal - EventSubscribers will become internal in v6.5.0
  18.  */
  19. class TranslationValidator implements EventSubscriberInterface
  20. {
  21.     public const VIOLATION_DELETE_SYSTEM_TRANSLATION 'delete-system-translation-violation';
  22.     public static function getSubscribedEvents(): array
  23.     {
  24.         return [
  25.             PreWriteValidationEvent::class => 'preValidate',
  26.         ];
  27.     }
  28.     public function preValidate(PreWriteValidationEvent $event): void
  29.     {
  30.         if ($event->getContext()->getVersionId() !== Defaults::LIVE_VERSION) {
  31.             return;
  32.         }
  33.         $violations = new ConstraintViolationList();
  34.         $violations->addAll($this->getDeletedSystemTranslationViolations($event->getCommands()));
  35.         if ($violations->count()) {
  36.             $event->getExceptions()->add(new WriteConstraintViolationException($violations));
  37.         }
  38.     }
  39.     /**
  40.      * @param list<WriteCommand> $writeCommands
  41.      */
  42.     private function getDeletedSystemTranslationViolations(array $writeCommands): ConstraintViolationList
  43.     {
  44.         $violations = new ConstraintViolationList();
  45.         foreach ($writeCommands as $writeCommand) {
  46.             if (!$writeCommand instanceof DeleteCommand || $writeCommand instanceof CascadeDeleteCommand) {
  47.                 continue;
  48.             }
  49.             $pk $writeCommand->getPrimaryKey();
  50.             if (!isset($pk['language_id'])) {
  51.                 continue;
  52.             }
  53.             $def $writeCommand->getDefinition();
  54.             if (!$def instanceof EntityTranslationDefinition) {
  55.                 continue;
  56.             }
  57.             if (Uuid::fromBytesToHex($pk['language_id']) !== Defaults::LANGUAGE_SYSTEM) {
  58.                 continue;
  59.             }
  60.             $fks $this->getFkFields($def);
  61.             $id Uuid::fromBytesToHex($pk[$fks['id']->getStorageName()]);
  62.             $violations->add(
  63.                 $this->buildViolation(
  64.                     'Cannot delete system translation',
  65.                     ['{{ id }}' => $id],
  66.                     '/' $id '/translations/' Defaults::LANGUAGE_SYSTEM,
  67.                     [$idDefaults::LANGUAGE_SYSTEM],
  68.                     self::VIOLATION_DELETE_SYSTEM_TRANSLATION
  69.                 )
  70.             );
  71.         }
  72.         return $violations;
  73.     }
  74.     /**
  75.      * @return FkField[]
  76.      */
  77.     private function getFkFields(EntityTranslationDefinition $definition): array
  78.     {
  79.         $rootEntity $definition->getParentDefinition();
  80.         $idStorageName $rootEntity->getEntityName() . '_id';
  81.         $versionIdStorageName $rootEntity->getEntityName() . '_version_id';
  82.         $pks $definition->getPrimaryKeys();
  83.         $idField $pks->getByStorageName($idStorageName);
  84.         if (!$idField || !$idField instanceof FkField) {
  85.             throw new \RuntimeException(sprintf('`%s` primary key should have column `%s`'$definition->getEntityName(), $idStorageName));
  86.         }
  87.         $fields = [
  88.             'id' => $idField,
  89.         ];
  90.         $versionIdField $pks->getByStorageName($versionIdStorageName);
  91.         if ($versionIdField && $versionIdField instanceof FkField) {
  92.             $fields['version'] = $versionIdField;
  93.         }
  94.         return $fields;
  95.     }
  96.     /**
  97.      * @param array<string, string> $parameters
  98.      * @param array<mixed>|null $invalidValue
  99.      */
  100.     private function buildViolation(
  101.         string $messageTemplate,
  102.         array $parameters,
  103.         ?string $propertyPath null,
  104.         ?array $invalidValue null,
  105.         ?string $code null
  106.     ): ConstraintViolationInterface {
  107.         return new ConstraintViolation(
  108.             str_replace(array_keys($parameters), array_values($parameters), $messageTemplate),
  109.             $messageTemplate,
  110.             $parameters,
  111.             null,
  112.             $propertyPath,
  113.             $invalidValue,
  114.             null,
  115.             $code
  116.         );
  117.     }
  118. }