refactor : extraire les helpers de mapping bovin dans un trait partagé

This commit is contained in:
2026-04-21 08:28:10 +02:00
parent dd87ea9216
commit b4d763dc0e
2 changed files with 170 additions and 172 deletions

View File

@@ -4,21 +4,14 @@ declare(strict_types=1);
namespace Malio\EdnotifBundle\Bovin\Mapper;
use DateTimeImmutable;
use Malio\EdnotifBundle\Bovin\Dto\AnimalFileDto;
use Malio\EdnotifBundle\Bovin\Dto\BovinIdentificationDto;
use Malio\EdnotifBundle\Bovin\Dto\BovinRef;
use Malio\EdnotifBundle\Bovin\Dto\DateValueDto;
use Malio\EdnotifBundle\Bovin\Dto\ExploitationRef;
use Malio\EdnotifBundle\Bovin\Dto\MovementDto;
use Malio\EdnotifBundle\Bovin\Dto\ParentInfoDto;
use Malio\EdnotifBundle\Bovin\Dto\PresencePeriodDto;
use Malio\EdnotifBundle\Shared\Dto\AnomalyDto;
use Malio\EdnotifBundle\Shared\Dto\StandardResponseDto;
use Throwable;
final class AnimalFileMapper
{
use BovinNodeMappingTrait;
public function map(object $soapResponse): AnimalFileDto
{
$standardResponse = $this->mapStandardResponse($soapResponse->ReponseStandard ?? null);
@@ -69,167 +62,4 @@ final class AnimalFileMapper
return new StandardResponseDto($result, $anomaly);
}
private function mapIdentification(object $identificationNode): BovinIdentificationDto
{
$bovinRef = $this->mapBovinRef($identificationNode->Bovin ?? null);
$birthDate = null;
$birthDateNode = $identificationNode->DateNaissance ?? null;
if (is_object($birthDateNode)) {
$birthDate = new DateValueDto(
date: $this->toNullableDate($birthDateNode->Date ?? null),
completenessFlag: $this->toNullableString($birthDateNode->TemoinCompletude ?? null),
);
}
$motherCarrier = $this->mapParentInfo($identificationNode->MerePorteuse ?? null);
$fatherIpg = $this->mapParentInfo($identificationNode->PereIPG ?? null);
$birthExploitation = $this->mapExploitationRef($identificationNode->ExploitationNaissance ?? null);
return new BovinIdentificationDto(
bovin: $bovinRef,
sex: $this->toNullableString($identificationNode->Sexe ?? null),
breedType: $this->toNullableString($identificationNode->TypeRacial ?? null),
birthDate: $birthDate,
workNumber: $this->toNullableString($identificationNode->NumeroTravail ?? null),
isFilie: $this->toNullableBool($identificationNode->StatutFilie ?? null),
motherCarrier: $motherCarrier,
fatherIpg: $fatherIpg,
birthExploitation: $birthExploitation,
);
}
private function mapPresencePeriod(object $presencePeriodNode): PresencePeriodDto
{
$entryNode = $presencePeriodNode->Entree ?? null;
$exitNode = $presencePeriodNode->Sortie ?? null;
$entryMovement = is_object($entryNode) ? $this->mapMovement($entryNode, 'entry') : null;
$exitMovement = is_object($exitNode) ? $this->mapMovement($exitNode, 'exit') : null;
return new PresencePeriodDto(
entry: $entryMovement,
exit: $exitMovement,
);
}
private function mapMovement(object $movementNode, string $direction): MovementDto
{
$dateValue = null;
$causeValue = null;
if ('entry' === $direction) {
// SOAP: DateEntree / CauseEntree
$dateValue = $movementNode->DateEntree ?? ($movementNode->Date ?? ($movementNode->DateMouvement ?? null));
$causeValue = $movementNode->CauseEntree ?? null;
} else {
// SOAP (souvent): DateSortie / CauseSortie
$dateValue = $movementNode->DateSortie ?? ($movementNode->Date ?? ($movementNode->DateMouvement ?? null));
$causeValue = $movementNode->CauseSortie ?? null;
}
$exploitationRef = $this->mapExploitationRef($movementNode->Exploitation ?? null);
return new MovementDto(
date: $this->toNullableDate($dateValue),
cause: $this->toNullableString($causeValue),
exploitation: $exploitationRef,
);
}
private function mapParentInfo(mixed $parentNode): ?ParentInfoDto
{
if (!is_object($parentNode)) {
return null;
}
$bovinRef = $this->mapBovinRef($parentNode->Bovin ?? null);
return new ParentInfoDto(
bovin: $bovinRef,
breedType: $this->toNullableString($parentNode->TypeRacial ?? null),
);
}
private function mapBovinRef(mixed $bovinNode): ?BovinRef
{
if (!is_object($bovinNode)) {
return null;
}
return new BovinRef(
countryCode: $this->toNullableString($bovinNode->CodePays ?? null),
nationalNumber: $this->toNullableString($bovinNode->NumeroNational ?? null),
);
}
private function mapExploitationRef(mixed $exploitationNode): ?ExploitationRef
{
if (!is_object($exploitationNode)) {
return null;
}
return new ExploitationRef(
countryCode: $this->toNullableString($exploitationNode->CodePays ?? null),
exploitationNumber: $this->toNullableString($exploitationNode->NumeroExploitation ?? null),
);
}
/** @return list<mixed> */
private function normalizeToList(mixed $value): array
{
if (null === $value) {
return [];
}
return is_array($value) ? $value : [$value];
}
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;
}
private function toNullableBool(mixed $value): ?bool
{
if (null === $value) {
return null;
}
return (bool) $value;
}
private function toNullableDate(mixed $value): ?DateTimeImmutable
{
if (!is_string($value) || '' === trim($value)) {
return null;
}
try {
return new DateTimeImmutable($value);
} catch (Throwable) {
return null;
}
}
}

View File

@@ -0,0 +1,168 @@
<?php
declare(strict_types=1);
namespace Malio\EdnotifBundle\Bovin\Mapper;
use DateTimeImmutable;
use Malio\EdnotifBundle\Bovin\Dto\BovinIdentificationDto;
use Malio\EdnotifBundle\Bovin\Dto\BovinRef;
use Malio\EdnotifBundle\Bovin\Dto\DateValueDto;
use Malio\EdnotifBundle\Bovin\Dto\ExploitationRef;
use Malio\EdnotifBundle\Bovin\Dto\MovementDto;
use Malio\EdnotifBundle\Bovin\Dto\ParentInfoDto;
use Malio\EdnotifBundle\Bovin\Dto\PresencePeriodDto;
use Throwable;
/**
* Helpers partagés par les mappers travaillant sur des noeuds `Bovin` issus
* d'EDNOTIF, que la source soit une réponse SOAP directe (stdClass via ext-soap)
* ou un message XML zippé (stdClass via ZipMessageDecoder).
*/
trait BovinNodeMappingTrait
{
protected function mapIdentification(object $identificationNode): BovinIdentificationDto
{
$birthDate = null;
$birthDateNode = $identificationNode->DateNaissance ?? null;
if (is_object($birthDateNode)) {
$birthDate = new DateValueDto(
date: $this->toNullableDate($birthDateNode->Date ?? null),
completenessFlag: $this->toNullableString($birthDateNode->TemoinCompletude ?? null),
);
}
return new BovinIdentificationDto(
bovin: $this->mapBovinRef($identificationNode->Bovin ?? null),
sex: $this->toNullableString($identificationNode->Sexe ?? null),
breedType: $this->toNullableString($identificationNode->TypeRacial ?? null),
birthDate: $birthDate,
workNumber: $this->toNullableString($identificationNode->NumeroTravail ?? null),
isFilie: $this->toNullableBool($identificationNode->StatutFilie ?? null),
motherCarrier: $this->mapParentInfo($identificationNode->MerePorteuse ?? null),
fatherIpg: $this->mapParentInfo($identificationNode->PereIPG ?? null),
birthExploitation: $this->mapExploitationRef($identificationNode->ExploitationNaissance ?? null),
);
}
protected function mapPresencePeriod(object $presencePeriodNode): PresencePeriodDto
{
$entryNode = $presencePeriodNode->Entree ?? null;
$exitNode = $presencePeriodNode->Sortie ?? null;
return new PresencePeriodDto(
entry: is_object($entryNode) ? $this->mapMovement($entryNode, 'entry') : null,
exit: is_object($exitNode) ? $this->mapMovement($exitNode, 'exit') : null,
);
}
protected function mapMovement(object $movementNode, string $direction): MovementDto
{
if ('entry' === $direction) {
$dateValue = $movementNode->DateEntree ?? ($movementNode->Date ?? ($movementNode->DateMouvement ?? null));
$causeValue = $movementNode->CauseEntree ?? null;
} else {
$dateValue = $movementNode->DateSortie ?? ($movementNode->Date ?? ($movementNode->DateMouvement ?? null));
$causeValue = $movementNode->CauseSortie ?? null;
}
return new MovementDto(
date: $this->toNullableDate($dateValue),
cause: $this->toNullableString($causeValue),
exploitation: $this->mapExploitationRef($movementNode->Exploitation ?? null),
);
}
protected function mapParentInfo(mixed $parentNode): ?ParentInfoDto
{
if (!is_object($parentNode)) {
return null;
}
return new ParentInfoDto(
bovin: $this->mapBovinRef($parentNode->Bovin ?? null),
breedType: $this->toNullableString($parentNode->TypeRacial ?? null),
);
}
protected function mapBovinRef(mixed $bovinNode): ?BovinRef
{
if (!is_object($bovinNode)) {
return null;
}
return new BovinRef(
countryCode: $this->toNullableString($bovinNode->CodePays ?? null),
nationalNumber: $this->toNullableString($bovinNode->NumeroNational ?? null),
);
}
protected function mapExploitationRef(mixed $exploitationNode): ?ExploitationRef
{
if (!is_object($exploitationNode)) {
return null;
}
return new ExploitationRef(
countryCode: $this->toNullableString($exploitationNode->CodePays ?? null),
exploitationNumber: $this->toNullableString($exploitationNode->NumeroExploitation ?? null),
);
}
/** @return list<mixed> */
protected function normalizeToList(mixed $value): array
{
if (null === $value) {
return [];
}
return is_array($value) ? array_values($value) : [$value];
}
protected function toNullableString(mixed $value): ?string
{
if (null === $value) {
return null;
}
$stringValue = trim((string) $value);
return '' === $stringValue ? null : $stringValue;
}
protected 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;
}
protected function toNullableBool(mixed $value): ?bool
{
if (null === $value) {
return null;
}
return (bool) $value;
}
protected function toNullableDate(mixed $value): ?DateTimeImmutable
{
if (!is_string($value) || '' === trim($value)) {
return null;
}
try {
return new DateTimeImmutable($value);
} catch (Throwable) {
return null;
}
}
}