diff --git a/config/services.php b/config/services.php index 4b95bf7..91137a4 100644 --- a/config/services.php +++ b/config/services.php @@ -6,6 +6,7 @@ use Malio\EdnotifBundle\Auth\TokenProvider; use Malio\EdnotifBundle\Bovin\Api\BovinApi; use Malio\EdnotifBundle\Bovin\Api\BovinApiInterface; use Malio\EdnotifBundle\Bovin\Mapper\AnimalFileMapper; +use Malio\EdnotifBundle\Shared\Mapper\StandardResponseMapper; use Malio\EdnotifBundle\Shared\Soap\SoapClientFactory; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; @@ -22,6 +23,8 @@ return static function (ContainerConfigurator $container): void { ->arg('$soapOptions', '%ednotif.soap_options%') ; + $services->set(StandardResponseMapper::class); + $services->set('ednotif.soap.guichet', SoapClient::class) ->factory([service(SoapClientFactory::class), 'create']) ->args(['%ednotif.guichet_wsdl%']) @@ -32,7 +35,7 @@ return static function (ContainerConfigurator $container): void { ->args(['%ednotif.metier_wsdl%']) ; - $services->set(AnimalFileMapper::class); + $services->set(AnimalFileMapper::class)->args([service(StandardResponseMapper::class)]); $services->set(TokenProvider::class) ->args([ diff --git a/src/Bovin/Dto/InventoryDto.php b/src/Bovin/Dto/InventoryDto.php index 0874ff6..a2296a9 100644 --- a/src/Bovin/Dto/InventoryDto.php +++ b/src/Bovin/Dto/InventoryDto.php @@ -18,7 +18,7 @@ final readonly class InventoryDto public int $nbBovins, public ?DateTimeImmutable $startDate, public ?DateTimeImmutable $endDate, - public bool $includesEarTagStock, + public ?bool $includesEarTagStock, public array $animals, public array $earTagSeries, public ?object $rawSoapResponse, diff --git a/src/Bovin/Mapper/AnimalFileMapper.php b/src/Bovin/Mapper/AnimalFileMapper.php index 0b932d5..c0c6646 100644 --- a/src/Bovin/Mapper/AnimalFileMapper.php +++ b/src/Bovin/Mapper/AnimalFileMapper.php @@ -5,16 +5,19 @@ declare(strict_types=1); namespace Malio\EdnotifBundle\Bovin\Mapper; use Malio\EdnotifBundle\Bovin\Dto\AnimalFileDto; -use Malio\EdnotifBundle\Shared\Dto\AnomalyDto; -use Malio\EdnotifBundle\Shared\Dto\StandardResponseDto; +use Malio\EdnotifBundle\Shared\Mapper\StandardResponseMapper; final class AnimalFileMapper { use BovinNodeMappingTrait; + public function __construct( + private readonly StandardResponseMapper $standardResponseMapper, + ) {} + public function map(object $soapResponse): AnimalFileDto { - $standardResponse = $this->mapStandardResponse($soapResponse->ReponseStandard ?? null); + $standardResponse = $this->standardResponseMapper->map($soapResponse->ReponseStandard ?? null); $specificResponseNode = $soapResponse->ReponseSpecifique ?? null; $bovinNode = is_object($specificResponseNode) ? ($specificResponseNode->Bovin ?? null) : null; @@ -44,22 +47,4 @@ final class AnimalFileMapper rawSoapResponse: $soapResponse ); } - - private function mapStandardResponse(mixed $standardResponseNode): StandardResponseDto - { - $result = (bool) ($standardResponseNode->Resultat ?? false); - - $anomalyNode = $standardResponseNode->Anomalie ?? null; - $anomaly = null; - - if (is_object($anomalyNode)) { - $anomaly = new AnomalyDto( - code: $this->toNullableString($anomalyNode->Code ?? null), - severity: $this->toNullableInt($anomalyNode->Severite ?? null), - message: $this->toNullableString($anomalyNode->Message ?? null), - ); - } - - return new StandardResponseDto($result, $anomaly); - } } diff --git a/src/Bovin/Mapper/InventoryMapper.php b/src/Bovin/Mapper/InventoryMapper.php index 9ec5884..3787ec1 100644 --- a/src/Bovin/Mapper/InventoryMapper.php +++ b/src/Bovin/Mapper/InventoryMapper.php @@ -6,8 +6,7 @@ namespace Malio\EdnotifBundle\Bovin\Mapper; use Malio\EdnotifBundle\Bovin\Dto\EarTagSeriesDto; use Malio\EdnotifBundle\Bovin\Dto\InventoryDto; -use Malio\EdnotifBundle\Shared\Dto\AnomalyDto; -use Malio\EdnotifBundle\Shared\Dto\StandardResponseDto; +use Malio\EdnotifBundle\Shared\Mapper\StandardResponseMapper; final class InventoryMapper { @@ -15,17 +14,18 @@ final class InventoryMapper public function __construct( private readonly AnimalSummaryMapper $animalSummaryMapper, + private readonly StandardResponseMapper $standardResponseMapper, ) {} public function map(object $soapResponse, ?object $unzippedMessage): InventoryDto { - $standardResponse = $this->mapStandardResponse($soapResponse->ReponseStandard ?? null); + $standardResponse = $this->standardResponseMapper->map($soapResponse->ReponseStandard ?? null); $nbBovins = $this->toNullableInt($soapResponse->ReponseSpecifique->NbBovins ?? null) ?? 0; $startDate = null; $endDate = null; - $includesEarTagStock = false; + $includesEarTagStock = null; $animals = []; $earTagSeries = []; @@ -34,7 +34,7 @@ final class InventoryMapper if (is_object($infoNode)) { $startDate = $this->toNullableDate($infoNode->DateDebut ?? null); $endDate = $this->toNullableDate($infoNode->DateFin ?? null); - $includesEarTagStock = (bool) $this->toNullableBool($infoNode->StockBoucles ?? null); + $includesEarTagStock = $this->toNullableBool($infoNode->StockBoucles ?? null); } $bovinsNode = $unzippedMessage->Bovins->Bovin ?? null; @@ -65,21 +65,4 @@ final class InventoryMapper rawSoapResponse: $soapResponse, ); } - - private function mapStandardResponse(mixed $standardResponseNode): StandardResponseDto - { - $result = (bool) ($standardResponseNode->Resultat ?? false); - $anomalyNode = $standardResponseNode->Anomalie ?? null; - $anomaly = null; - - if (is_object($anomalyNode)) { - $anomaly = new AnomalyDto( - code: $this->toNullableString($anomalyNode->Code ?? null), - severity: $this->toNullableInt($anomalyNode->Severite ?? null), - message: $this->toNullableString($anomalyNode->Message ?? null), - ); - } - - return new StandardResponseDto($result, $anomaly); - } } diff --git a/src/Shared/Mapper/StandardResponseMapper.php b/src/Shared/Mapper/StandardResponseMapper.php new file mode 100644 index 0000000..6c1b3f5 --- /dev/null +++ b/src/Shared/Mapper/StandardResponseMapper.php @@ -0,0 +1,53 @@ +Resultat ?? false); + $anomalyNode = is_object($standardResponseNode) ? ($standardResponseNode->Anomalie ?? null) : null; + + $anomaly = null; + if (is_object($anomalyNode)) { + $anomaly = new AnomalyDto( + code: $this->toNullableString($anomalyNode->Code ?? null), + severity: $this->toNullableInt($anomalyNode->Severite ?? null), + message: $this->toNullableString($anomalyNode->Message ?? null), + ); + } + + return new StandardResponseDto($result, $anomaly); + } + + private function toNullableString(mixed $value): ?string + { + if (null === $value) { + return null; + } + $stringValue = trim((string) $value); + + return '' === $stringValue ? null : $stringValue; + } + + private function toNullableInt(mixed $value): ?int + { + if (null === $value) { + return null; + } + if (is_int($value)) { + return $value; + } + if (is_numeric($value)) { + return (int) $value; + } + + return null; + } +} diff --git a/tests/Unit/Bovin/Mapper/InventoryMapperTest.php b/tests/Unit/Bovin/Mapper/InventoryMapperTest.php index 899accf..76dac82 100644 --- a/tests/Unit/Bovin/Mapper/InventoryMapperTest.php +++ b/tests/Unit/Bovin/Mapper/InventoryMapperTest.php @@ -8,6 +8,7 @@ use DateTimeImmutable; use Malio\EdnotifBundle\Bovin\Dto\InventoryDto; use Malio\EdnotifBundle\Bovin\Mapper\AnimalSummaryMapper; use Malio\EdnotifBundle\Bovin\Mapper\InventoryMapper; +use Malio\EdnotifBundle\Shared\Mapper\StandardResponseMapper; use PHPUnit\Framework\Attributes\CoversClass; use PHPUnit\Framework\TestCase; use stdClass; @@ -20,7 +21,7 @@ final class InventoryMapperTest extends TestCase { public function testMapFullInventory(): void { - $mapper = new InventoryMapper(new AnimalSummaryMapper()); + $mapper = new InventoryMapper(new AnimalSummaryMapper(), new StandardResponseMapper()); $inventory = $mapper->map($this->makeSoapResponse(), $this->makeUnzippedMessage()); @@ -37,7 +38,7 @@ final class InventoryMapperTest extends TestCase public function testMapInventoryWithoutMessageZipReturnsEmptyLists(): void { - $mapper = new InventoryMapper(new AnimalSummaryMapper()); + $mapper = new InventoryMapper(new AnimalSummaryMapper(), new StandardResponseMapper()); $soapResponse = new stdClass(); $soapResponse->ReponseStandard = new stdClass();