platform/src/Core/System/Language/TranslationValidator.php line 29

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