iteo/src/Validator/ValidOrderValidator.php
2024-04-14 22:42:40 +02:00

81 lines
2.4 KiB
PHP

<?php
namespace App\Validator;
use App\Aggregate\AcceptOrderCommand;
use App\Contract\Order;
use App\Entity\Client;
use App\Service\ClientService;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\UnexpectedValueException;
class ValidOrderValidator extends ConstraintValidator
{
public function __construct(private readonly ClientService $clientService)
{
}
public function validate($value, Constraint $constraint)
{
if (!$value instanceof Order) {
throw new UnexpectedValueException($value, Order::class);
}
if (!$constraint instanceof ValidOrder) {
throw new UnexpectedValueException($constraint, ValidOrder::class);
}
$client = $this->getClient($value);
$this->checkClientBalance($client);
$this->checkMinimumProductCount($value, $constraint);
$this->checkMaximumWeight($value, $constraint);
}
private function checkMinimumProductCount(Order $value, ValidOrder $constraint): void
{
if (count($value->getProducts()) < $constraint->minProductCount) {
$this->context
->buildViolation('The number of products in order should be no less than {{ min }}')
->setParameter('{{ min }}', $constraint->minProductCount)
->atPath('products')
->addViolation();
}
}
private function checkMaximumWeight(Order $value, ValidOrder $constraint): void
{
if ($value->getTotalWeight() > $constraint->maxWeight) {
$this->context
->buildViolation('Total weight of products in order must not exceed {{ max }}kg')
->setParameter('{{ max }}', $constraint->maxWeight)
->atPath('products')
->addViolation();
}
}
private function getClient(Order $value)
{
$root = $this->context->getRoot();
if ($root instanceof AcceptOrderCommand) {
return $root->client;
}
return $this->clientService->getClient($value->getClientId());
}
private function checkClientBalance(Client $client): void
{
if ($client->getBalance() < 0) {
$this->context
->buildViolation('Total balance of the client is negative')
->atPath('clientId')
->addViolation();
}
}
}