platform/src/Core/Checkout/Shipping/Validator/ShippingMethodValidator.php line 37

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Checkout\Shipping\Validator;
  3. use Doctrine\DBAL\Connection;
  4. use Shopware\Core\Checkout\Shipping\ShippingMethodDefinition;
  5. use Shopware\Core\Checkout\Shipping\ShippingMethodEntity;
  6. use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\InsertCommand;
  7. use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\UpdateCommand;
  8. use Shopware\Core\Framework\DataAbstractionLayer\Write\Validation\PreWriteValidationEvent;
  9. use Shopware\Core\Framework\Validation\WriteConstraintViolationException;
  10. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  11. use Symfony\Component\Validator\ConstraintViolation;
  12. use Symfony\Component\Validator\ConstraintViolationInterface;
  13. use Symfony\Component\Validator\ConstraintViolationList;
  14. class ShippingMethodValidator implements EventSubscriberInterface
  15. {
  16.     public const VIOLATION_TAX_TYPE_INVALID 'tax_type_invalid';
  17.     public const VIOLATION_TAX_ID_REQUIRED 'c1051bb4-d103-4f74-8988-acbcafc7fdc3';
  18.     private Connection $connection;
  19.     public function __construct(Connection $connection)
  20.     {
  21.         $this->connection $connection;
  22.     }
  23.     public static function getSubscribedEvents()
  24.     {
  25.         return [
  26.             PreWriteValidationEvent::class => 'preValidate',
  27.         ];
  28.     }
  29.     public function preValidate(PreWriteValidationEvent $event): void
  30.     {
  31.         $allowTypes = [
  32.             ShippingMethodEntity::TAX_TYPE_FIXED,
  33.             ShippingMethodEntity::TAX_TYPE_AUTO,
  34.             ShippingMethodEntity::TAX_TYPE_HIGHEST,
  35.         ];
  36.         $writeCommands $event->getCommands();
  37.         foreach ($writeCommands as $command) {
  38.             $violations = new ConstraintViolationList();
  39.             if (!$command instanceof InsertCommand && !$command instanceof UpdateCommand) {
  40.                 continue;
  41.             }
  42.             if ($command->getDefinition()->getClass() !== ShippingMethodDefinition::class) {
  43.                 continue;
  44.             }
  45.             $shippingMethod $this->findShippingMethod($command->getPrimaryKey()['id']);
  46.             $payload $command->getPayload();
  47.             /** @var string|null $taxType */
  48.             $taxType $this->getValue($payload'tax_type'$shippingMethod);
  49.             /** @var string|null $taxId */
  50.             $taxId $this->getValue($payload'tax_id'$shippingMethod);
  51.             if ($taxType && !\in_array($taxType$allowTypestrue)) {
  52.                 $violations->add(
  53.                     $this->buildViolation(
  54.                         'The selected tax type {{ type }} is invalid.',
  55.                         ['{{ type }}' => $taxType],
  56.                         '/taxType',
  57.                         $taxType,
  58.                         self::VIOLATION_TAX_TYPE_INVALID
  59.                     )
  60.                 );
  61.             }
  62.             if ($taxType === ShippingMethodEntity::TAX_TYPE_FIXED && !$taxId) {
  63.                 $violations->add(
  64.                     $this->buildViolation(
  65.                         'The defined tax rate is required when fixed tax present',
  66.                         ['{{ taxId }}' => null],
  67.                         '/taxId',
  68.                         $taxType,
  69.                         self::VIOLATION_TAX_ID_REQUIRED
  70.                     )
  71.                 );
  72.             }
  73.             if ($violations->count() > 0) {
  74.                 $event->getExceptions()->add(new WriteConstraintViolationException($violations$command->getPath()));
  75.             }
  76.         }
  77.     }
  78.     private function findShippingMethod(string $shippingMethodId): array
  79.     {
  80.         $shippingMethod $this->connection->executeQuery(
  81.             'SELECT `tax_type`, `tax_id` FROM `shipping_method` WHERE `id` = :id',
  82.             ['id' => $shippingMethodId]
  83.         );
  84.         return $shippingMethod->fetchAll();
  85.     }
  86.     private function buildViolation(
  87.         string $messageTemplate,
  88.         array $parameters,
  89.         string $propertyPath,
  90.         string $invalidValue,
  91.         string $code
  92.     ): ConstraintViolationInterface {
  93.         return new ConstraintViolation(
  94.             str_replace(array_keys($parameters), array_values($parameters), $messageTemplate),
  95.             $messageTemplate,
  96.             $parameters,
  97.             null,
  98.             $propertyPath,
  99.             $invalidValue,
  100.             null,
  101.             $code
  102.         );
  103.     }
  104.     /**
  105.      * Gets a value from an array. It also does clean checks if
  106.      * the key is set, and also provides the option for default values.
  107.      *
  108.      * @param array  $data  the data array
  109.      * @param string $key   the requested key in the array
  110.      * @param array  $dbRow the db row of from the database
  111.      *
  112.      * @return mixed the object found in the key, or the default value
  113.      */
  114.     private function getValue(array $datastring $key, array $dbRow)
  115.     {
  116.         // try in our actual data set
  117.         if (isset($data[$key])) {
  118.             return $data[$key];
  119.         }
  120.         // try in our db row fallback
  121.         if (isset($dbRow[$key])) {
  122.             return $dbRow[$key];
  123.         }
  124.         // use default
  125.         return null;
  126.     }
  127. }