ldc-arcadia-api/src/Domain/Services/BrandResolver.php

76 lines
2.2 KiB
PHP

<?php
declare(strict_types=1);
namespace Domain\Services;
use Domain\Exceptions\BrandNotFoundException;
use Domain\Models\Entities\Brand;
use Domain\Models\ValueObjects\Brand\ArcadiaId;
use Domain\Ports\Directories\ArcadiaBrandDirectory;
use Domain\Ports\Repositories\BrandRepository;
use Psr\Log\LoggerInterface;
use Psr\Log\NullLogger;
final readonly class BrandResolver
{
private LoggerInterface $logger;
public function __construct(
private ArcadiaBrandDirectory $arcadiaBrandDirectory,
private BrandRepository $brandRepository,
private BrandCodeGenerator $brandCodeGenerator,
?LoggerInterface $logger = null,
) {
$this->logger = $logger ?? new NullLogger();
}
/**
* Resolve or generate/persist a Brand entity given an Arcadia brand code (ArcadiaId).
*
* @throws BrandNotFoundException
*/
public function resolve(ArcadiaId $arcadiaBrandCode): Brand
{
$existingBrand = $this->brandRepository->findByArcadiaId($arcadiaBrandCode);
if ($existingBrand !== null) {
return $existingBrand;
}
$arcadiaBrand = $this->arcadiaBrandDirectory->find($arcadiaBrandCode);
if ($arcadiaBrand === null) {
throw BrandNotFoundException::forArcadiaId($arcadiaBrandCode);
}
do {
$code = $this->brandCodeGenerator->generate($arcadiaBrand->name);
} while ($this->brandRepository->findByCode($code) !== null);
$brand = Brand::create(
name: $arcadiaBrand->name,
code: $code,
arcadiaId: $arcadiaBrand->id,
);
$this->brandRepository->persist($brand);
$this->logger->info(
sprintf(
'Created new brand code "%s" for brand "%s" (Arcadia ID %d)',
$code->value,
$arcadiaBrand->name->value,
$arcadiaBrand->id->value
),
[
'brand_id' => $brand->id()->value,
'code' => $code->value,
'name' => $arcadiaBrand->name->value,
'arcadia_id' => $arcadiaBrand->id->value,
]
);
return $brand;
}
}