vendor/shopware/core/Checkout/Shipping/Validator/ShippingMethodValidator.php line 45
<?php declare(strict_types=1);namespace Shopware\Core\Checkout\Shipping\Validator;use Doctrine\DBAL\Connection;use Shopware\Core\Checkout\Shipping\ShippingMethodDefinition;use Shopware\Core\Checkout\Shipping\ShippingMethodEntity;use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\InsertCommand;use Shopware\Core\Framework\DataAbstractionLayer\Write\Command\UpdateCommand;use Shopware\Core\Framework\DataAbstractionLayer\Write\Validation\PreWriteValidationEvent;use Shopware\Core\Framework\Log\Package;use Shopware\Core\Framework\Validation\WriteConstraintViolationException;use Symfony\Component\EventDispatcher\EventSubscriberInterface;use Symfony\Component\Validator\ConstraintViolation;use Symfony\Component\Validator\ConstraintViolationInterface;use Symfony\Component\Validator\ConstraintViolationList;/*** @internal*/#[Package('checkout')]class ShippingMethodValidator implements EventSubscriberInterface{final public const VIOLATION_TAX_TYPE_INVALID = 'tax_type_invalid';final public const VIOLATION_TAX_ID_REQUIRED = 'c1051bb4-d103-4f74-8988-acbcafc7fdc3';/*** @internal*/public function __construct(private readonly Connection $connection){}/*** @return array<string, string|array{0: string, 1: int}|list<array{0: string, 1?: int}>>*/public static function getSubscribedEvents(): array{return [PreWriteValidationEvent::class => 'preValidate',];}public function preValidate(PreWriteValidationEvent $event): void{$allowTypes = [ShippingMethodEntity::TAX_TYPE_FIXED,ShippingMethodEntity::TAX_TYPE_AUTO,ShippingMethodEntity::TAX_TYPE_HIGHEST,];$writeCommands = $event->getCommands();foreach ($writeCommands as $command) {$violations = new ConstraintViolationList();if (!$command instanceof InsertCommand && !$command instanceof UpdateCommand) {continue;}if ($command->getDefinition()->getClass() !== ShippingMethodDefinition::class) {continue;}$shippingMethod = $this->findShippingMethod($command->getPrimaryKey()['id']);$payload = $command->getPayload();/** @var string|null $taxType */$taxType = $this->getValue($payload, 'tax_type', $shippingMethod);/** @var string|null $taxId */$taxId = $this->getValue($payload, 'tax_id', $shippingMethod);if ($taxType && !\in_array($taxType, $allowTypes, true)) {$violations->add($this->buildViolation('The selected tax type {{ type }} is invalid.',['{{ type }}' => $taxType],'/taxType',$taxType,self::VIOLATION_TAX_TYPE_INVALID));}if ($taxType === ShippingMethodEntity::TAX_TYPE_FIXED && !$taxId) {$violations->add($this->buildViolation('The defined tax rate is required when fixed tax present',['{{ taxId }}' => null],'/taxId',$taxType,self::VIOLATION_TAX_ID_REQUIRED));}if ($violations->count() > 0) {$event->getExceptions()->add(new WriteConstraintViolationException($violations, $command->getPath()));}}}/*** @return array<string, mixed>*/private function findShippingMethod(string $shippingMethodId): array{$shippingMethod = $this->connection->executeQuery('SELECT `tax_type`, `tax_id` FROM `shipping_method` WHERE `id` = :id',['id' => $shippingMethodId]);return $shippingMethod->fetchAssociative() ?: [];}/*** @param array<string, mixed> $parameters*/private function buildViolation(string $messageTemplate,array $parameters,string $propertyPath,string $invalidValue,string $code): ConstraintViolationInterface {return new ConstraintViolation(str_replace(array_keys($parameters), array_values($parameters), $messageTemplate),$messageTemplate,$parameters,null,$propertyPath,$invalidValue,null,$code);}/*** Gets a value from an array. It also does clean checks if* the key is set, and also provides the option for default values.** @param array<string, mixed> $data the data array* @param string $key the requested key in the array* @param array<string, mixed> $dbRow the db row of from the database** @return mixed the object found in the key, or the default value*/private function getValue(array $data, string $key, array $dbRow){// try in our actual data setif (isset($data[$key])) {return $data[$key];}// try in our db row fallbackif (isset($dbRow[$key])) {return $dbRow[$key];}// use defaultreturn null;}}