feat : décodeur ZIP+XML partagé pour les réponses Get* bovin
This commit is contained in:
82
src/Shared/Soap/ZipMessageDecoder.php
Normal file
82
src/Shared/Soap/ZipMessageDecoder.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Malio\EdnotifBundle\Shared\Soap;
|
||||
|
||||
use RuntimeException;
|
||||
use ZipArchive;
|
||||
|
||||
final class ZipMessageDecoder
|
||||
{
|
||||
/**
|
||||
* Décode le binaire `MessageZip` retourné par les opérations EDNOTIF de type
|
||||
* `Get*` (Inventaire / RetourDossiers / SortiesPresumees) : le contenu est déjà
|
||||
* décodé par ext-soap depuis base64, il reste à dézipper et parser le XML.
|
||||
*/
|
||||
public function decode(string $zipBinary): object
|
||||
{
|
||||
if ('' === $zipBinary) {
|
||||
throw new RuntimeException('ZipMessageDecoder: binaire ZIP vide.');
|
||||
}
|
||||
|
||||
$tempFile = tempnam(sys_get_temp_dir(), 'ednotif_zip_');
|
||||
if (false === $tempFile) {
|
||||
throw new RuntimeException('ZipMessageDecoder: impossible de créer un fichier temporaire.');
|
||||
}
|
||||
|
||||
try {
|
||||
if (false === file_put_contents($tempFile, $zipBinary)) {
|
||||
throw new RuntimeException('ZipMessageDecoder: impossible d\'écrire le fichier temporaire.');
|
||||
}
|
||||
|
||||
$xml = $this->readFirstEntry($tempFile);
|
||||
} finally {
|
||||
@unlink($tempFile);
|
||||
}
|
||||
|
||||
$previous = libxml_use_internal_errors(true);
|
||||
$simpleXml = simplexml_load_string($xml);
|
||||
libxml_use_internal_errors($previous);
|
||||
|
||||
if (false === $simpleXml) {
|
||||
throw new RuntimeException('ZipMessageDecoder: XML invalide dans l\'archive ZIP.');
|
||||
}
|
||||
|
||||
$json = json_encode($simpleXml);
|
||||
if (false === $json) {
|
||||
throw new RuntimeException('ZipMessageDecoder: échec de l\'encodage JSON intermédiaire.');
|
||||
}
|
||||
|
||||
$decoded = json_decode($json, false);
|
||||
if (!is_object($decoded)) {
|
||||
throw new RuntimeException('ZipMessageDecoder: décodage JSON non objet.');
|
||||
}
|
||||
|
||||
return $decoded;
|
||||
}
|
||||
|
||||
private function readFirstEntry(string $filePath): string
|
||||
{
|
||||
$zip = new ZipArchive();
|
||||
$openResult = $zip->open($filePath, ZipArchive::RDONLY);
|
||||
if (true !== $openResult) {
|
||||
throw new RuntimeException(sprintf('ZipMessageDecoder: ouverture ZIP impossible (code %s).', (string) $openResult));
|
||||
}
|
||||
|
||||
try {
|
||||
if (0 === $zip->numFiles) {
|
||||
throw new RuntimeException('ZipMessageDecoder: archive ZIP vide.');
|
||||
}
|
||||
|
||||
$xml = $zip->getFromIndex(0);
|
||||
if (false === $xml) {
|
||||
throw new RuntimeException('ZipMessageDecoder: lecture de l\'entrée ZIP impossible.');
|
||||
}
|
||||
} finally {
|
||||
$zip->close();
|
||||
}
|
||||
|
||||
return $xml;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user