diff --git a/app/Exceptions/InvalidXmlException.php b/app/Exceptions/InvalidXmlException.php new file mode 100644 index 0000000..4db050d --- /dev/null +++ b/app/Exceptions/InvalidXmlException.php @@ -0,0 +1,9 @@ +log(sprintf(' traitement %d sur %s ', $progress++, $total)); - /** @var string $data */ - $data = $disk->get($filename); - try { - if ($this->encapsulate) { - $data = sprintf('%s', $data); - /** @var SimpleXMLElement|false */ - $xmlContent = simplexml_load_string($data); - } else { - /** @var SimpleXMLElement|false */ - $xmlContent = simplexml_load_string($data, null, LIBXML_NOCDATA | LIBXML_PARSEHUGE); - } + /** @var string $data */ + $data = $disk->get($filename); + try { + if ($this->encapsulate) { + $data = sprintf('%s', $data); + /** @var SimpleXMLElement|false */ + $xmlContent = simplexml_load_string($data); + } else { + /** @var SimpleXMLElement|false */ + $xmlContent = simplexml_load_string($data, null, LIBXML_NOCDATA | LIBXML_PARSEHUGE); + } - if ($xmlContent === false) { - $this->log( - sprintf('File %s could not be parsed (simplexml_load_string)', $filename), - LogType::critical() - ); - continue; // ignore the file + if ($xmlContent === false) { + throw new InvalidXmlException('XML is Invalid (simplexml_load_string returned false)'); + // $this->log( + // sprintf('File %s could not be parsed (simplexml_load_string)', $filename), + // LogType::critical() + // ); + // continue; // ignore the file + } + } catch (ErrorException $e) { + throw new InvalidXmlException('XML is Invalid', 0, $e); } $data = $this->extract($xmlContent); - $lines = []; foreach ($data[$entityName] as $traca) { $line = $this->processFields($traca); @@ -102,6 +116,7 @@ abstract class XmlJobs extends XArcadiaFlux } $lines[] = $line; } + // Mise en base des données foreach ($lines as $line) { /** @var array Unique Key columns */ @@ -116,7 +131,7 @@ abstract class XmlJobs extends XArcadiaFlux // @todo : should we put that method in a interface ? $savedData->updateLocalProductInfo(); } - } catch (ErrorException | TypeError | QueryException $e) { + } catch (InvalidXmlException $e) { $message = $e->getMessage(); if (get_class($e) === QueryException::class) { $message = implode(' ', $e->errorInfo); @@ -130,17 +145,49 @@ abstract class XmlJobs extends XArcadiaFlux ), LogType::critical() ); + $this->sendInvalidXmlEmail($filename, $e); + $this->moveToInvalid($filename); + continue; + } catch (ErrorException | TypeError $e) { + $this->log( + sprintf( + 'CRITICAL: File %s could not be parsed => %s on line %d', + $filename, + $e->getMessage(), + $e->getLine() + ), + LogType::critical() + ); + $this->sendErrorParseEmailToServiceWeb($e); continue; // ignore the file } catch (AbortXmlImportException $e) { $this->log( sprintf( - 'File %s could not be parsed => %s on line %d', + 'ERROR: File %s could not be parsed => %s on line %d', $filename, $e->getMessage(), $e->getLine() ), LogType::error() ); + $this->sendErrorParseEmailToServiceWeb($e); + $this->moveToInvalid($filename); + continue; // ignore the file + } catch (FileNotFoundException | QueryException $e) { + // This happens because of concurent xml jobs read + $message = $e->getMessage(); + if (get_class($e) === QueryException::class) { + $message = implode(' ', $e->errorInfo); + } + $this->log( + sprintf( + 'ERROR: File %s could not be read (not found) => %s on line %d', + $filename, + $message, + $e->getLine() + ), + LogType::debug() + ); continue; // ignore the file } $this->moveToArchives($filename); @@ -276,4 +323,57 @@ abstract class XmlJobs extends XArcadiaFlux } return $isXml; } + + protected function sendErrorParseEmailToServiceWeb(Throwable $e) + { + Mail::send('emails.exception', [ + 'exception' => $e, + 'appName' => config('app.name'), + ], function ($m) { + $m->to( + config('mail.contactsList.serviceweb'), + sprintf('%s Exception Handler', config('app.name')) + )->subject('Could not eat INCO, because of its toxicity !'); + }); + } + + protected function sendInvalidXmlEmail(string $filename, Throwable $e) + { + $message = $e->getPrevious()->getMessage(); + Mail::send('emails.invalidxml', [ + 'strError' => sprintf( + 'File %s could not be parsed => %s on line %d', + $filename, + $message, + $e->getLine() + ), + 'appName' => config('app.name'), + 'filename' => $filename, + 'exception' => $e->getPrevious() + ], function ($m) { + $m->to( + config('mail.contactsList.invalidInco'), + sprintf('%s Exception Handler', config('app.name')) + )->subject('You sent me an invalid XML file, please check its validity before resend ASAP.'); + }); + } + + /** + * Move the file to invalid folder + * + * @param string $filename + * @return void + */ + protected function moveToInvalid(string $filename): void + { + if (!$this->getDisk()->move($filename, sprintf('%s/%s', $this->invalidFolderName, $filename))) { + $this->log( + sprintf( + 'File %s could not be moved to invalid folder name', + $filename + ), + LogType::warning() + ); + } + } } diff --git a/config/mail.php b/config/mail.php index dd5c28d..bda467e 100644 --- a/config/mail.php +++ b/config/mail.php @@ -89,7 +89,8 @@ return [ ], 'contactsList' => [ - 'serviceweb' => env('MAIL_LIST_SERVICEWEB', 'informatique.internet@ldc.fr') + 'serviceweb' => explode(",", env('MAIL_LIST_SERVICEWEB', 'informatique.internet@ldc.fr')), + 'invalidInco' => explode(",", env('MAIL_LIST_INVALIDINCO', 'informatique.internet@ldc.fr,vincent.pierre@ldc.fr,christelle.manceau@ldc.fr')), ], /* diff --git a/resources/views/emails/invalidxml.blade.php b/resources/views/emails/invalidxml.blade.php new file mode 100644 index 0000000..e212653 --- /dev/null +++ b/resources/views/emails/invalidxml.blade.php @@ -0,0 +1,28 @@ + + + + {{ $appName }} Exception Handler: Unvalid XML + + + +

{{ $appName }} à reçu un fichier xml non valide !!

+

{{ $strError }}

+

FICHIER: `{{ $filename }}`

+

{{ $exception->getMessage() }}

+

+ date : {{ date('Y-m-d H:i:s') }}
+ code : {{$exception->getCode() }}
+ file : {{$exception->getFile() }}
+ line : {{$exception->getLine() }}
+

+ Merci de corriger le flux, puis de renvoyer le fichier en provoquant un mouvement EAI.

+ Pour rappel : Il est recommandé de valider un fichier XML à l'aide d'un DTD
+ https://www.w3schools.com/xml/xml_dtd.asp
+ ou bien XSD https://www.w3schools.com/xml/schema_intro.asp

+ Pourquoi ?
+ Pour que les concepteurs puissent identifier les types de données qui transitent (les champs et leurs caratéristiques)
+ Mais aussi valider les fichiers reçus. +

+

En l'absence de données valides, cette fiche va être mise de coté.

+ + diff --git a/storage/inco/invalid/.gitkeep b/storage/inco/invalid/.gitkeep new file mode 100644 index 0000000..e69de29