diff --git a/src/Sii/Dte/Documento/Parser/DocumentoParser.php b/src/Sii/Dte/Documento/Parser/DocumentoParser.php new file mode 100644 index 0000000..19cbf25 --- /dev/null +++ b/src/Sii/Dte/Documento/Parser/DocumentoParser.php @@ -0,0 +1,136 @@ + + * + * Este programa es software libre: usted puede redistribuirlo y/o modificarlo + * bajo los términos de la Licencia Pública General Affero de GNU publicada + * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia, + * o (a su elección) cualquier versión posterior de la misma. + * + * Este programa se distribuye con la esperanza de que sea útil, pero SIN + * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD + * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la Licencia Pública + * General Affero de GNU para obtener una información más detallada. + * + * Debería haber recibido una copia de la Licencia Pública General Affero de + * GNU junto a este programa. + * + * En caso contrario, consulte . + */ + +namespace libredte\lib\Core\Sii\Dte\Documento\Parser; + +/** + * Clase que maneja el análisis sintáctico de los datos de un documento. + * + * Se encarga de tomar los datos en cierto formato y transformarlos a un formato + * estándarizado para ser usado en LibreDTE como un arreglo PHP con los datos en + * la estructura oficial del SII. + */ +class DocumentoParser +{ + /** + * Parser por defecto que se debe utilizar al analizar los datos si no se + * ha especificado uno al llamar al método DocumentoParser::parse(). + * + * @var string + */ + protected string $defaultParser = 'sii.json'; + + /** + * Alias de parsers. + * + * Esto es por compatibilidad hacia atrás y simplificación en el uso de los + * parsers estándares de LibreDTE que usan el formato oficial del SII. + * + * @var array + */ + protected array $parsersAlias = [ + 'json' => 'sii.json', + 'yaml' => 'sii.yaml', + 'xml' => 'sii.xml', + ]; + + /** + * Listado de parsers instanciados para ser reutilizados. + * + * @var array + */ + protected array $parsers = []; + + /** + * Ejecuta el análisis sintáctico (parseo) de los datos. + * + * @param string|array $data Datos del documento a transformar. + * @return array Arreglo con los datos transformados. + * @throws DocumentoParserException Si existe un error al parsear los datos. + */ + public function parse(string|array $data, string $parser = null): array + { + // Si no se indicó parser se usa el por defecto. + if ($parser === null) { + $parser = $this->defaultParser; + } + + // Si el parser es un alias se ajusta el nombre del parser al real. + if (isset($this->parsersAlias[$parser])) { + $parser = $this->parsersAlias[$parser]; + } + + // Obtener la instancia del parser real. + $parser = $this->getParserInstance($parser); + + // Llamar al parser para transformar los datos. + $parsedData = $parser->parse($data); + + // Entregar los datos transformados. + return $parsedData; + } + + /** + * Obtiene la instancia de un parser. + * + * @param string $parser Nombre del parser que se desea obtener. + * @return DocumentoParserInterface Instancia del parser. + */ + private function getParserInstance(string $parser): DocumentoParserInterface + { + // Si el parser no está previamente cargado se carga. + if (!isset($this->parsers[$parser])) { + // Determinar la clase del parser solicitado. + $class = $this->getParserClass($parser); + + // Si la clase del parser no existe error. + if (!class_exists($class)) { + throw new DocumentoParserException(sprintf( + 'El analizador sintáctico (parser) con el formato %s no existe.', + $parser + )); + } + + // Instanciar el parser. + $this->parsers[$parser] = new $class; + } + + // Entregar la instancia del parser. + return $this->parsers[$parser]; + } + + /** + * Determina la clase del parser que se está solicitando. + * + * @param string $parser Nombre del parser solicitado. + * @return string FQCN de la clase del parser solicitado. + */ + private function getParserClass(string $parser): string + { + // TODO: Determinar la clase del parser. + $class = ''; + + return $class; + } +} diff --git a/src/Sii/Dte/Documento/Parser/DocumentoParserException.php b/src/Sii/Dte/Documento/Parser/DocumentoParserException.php new file mode 100644 index 0000000..6a8e077 --- /dev/null +++ b/src/Sii/Dte/Documento/Parser/DocumentoParserException.php @@ -0,0 +1,35 @@ + + * + * Este programa es software libre: usted puede redistribuirlo y/o modificarlo + * bajo los términos de la Licencia Pública General Affero de GNU publicada + * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia, + * o (a su elección) cualquier versión posterior de la misma. + * + * Este programa se distribuye con la esperanza de que sea útil, pero SIN + * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD + * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la Licencia Pública + * General Affero de GNU para obtener una información más detallada. + * + * Debería haber recibido una copia de la Licencia Pública General Affero de + * GNU junto a este programa. + * + * En caso contrario, consulte . + */ + +namespace libredte\lib\Core\Sii\Dte\Documento\Parser; + +use Exception; + +/** + * Excepción personalizada para errores asociados al análisis sintáctico de los + * datos de entrada de un documento tributario electrónico. + */ +class DocumentoParserException extends Exception +{ +} diff --git a/src/Sii/Dte/Documento/Parser/DocumentoParserInterface.php b/src/Sii/Dte/Documento/Parser/DocumentoParserInterface.php new file mode 100644 index 0000000..6b7efee --- /dev/null +++ b/src/Sii/Dte/Documento/Parser/DocumentoParserInterface.php @@ -0,0 +1,39 @@ + + * + * Este programa es software libre: usted puede redistribuirlo y/o modificarlo + * bajo los términos de la Licencia Pública General Affero de GNU publicada + * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia, + * o (a su elección) cualquier versión posterior de la misma. + * + * Este programa se distribuye con la esperanza de que sea útil, pero SIN + * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD + * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la Licencia Pública + * General Affero de GNU para obtener una información más detallada. + * + * Debería haber recibido una copia de la Licencia Pública General Affero de + * GNU junto a este programa. + * + * En caso contrario, consulte . + */ + +namespace libredte\lib\Core\Sii\Dte\Documento\Parser; + +/** + * Interfaz para los parsers de datos de entrada de los documentos tributarios. + */ +interface DocumentoParserInterface +{ + /** + * Realiza la transformación de los datos del documento. + * + * @param string $data Datos de entrada del formato original. + * @return array Arreglo transformado a la estructura oficial del SII. + */ + public function parse(string $data): array; +} diff --git a/src/Sii/Dte/Documento/Parser/Sii/Json.php b/src/Sii/Dte/Documento/Parser/Sii/Json.php new file mode 100644 index 0000000..a1ed1a3 --- /dev/null +++ b/src/Sii/Dte/Documento/Parser/Sii/Json.php @@ -0,0 +1,47 @@ + + * + * Este programa es software libre: usted puede redistribuirlo y/o modificarlo + * bajo los términos de la Licencia Pública General Affero de GNU publicada + * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia, + * o (a su elección) cualquier versión posterior de la misma. + * + * Este programa se distribuye con la esperanza de que sea útil, pero SIN + * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD + * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la Licencia Pública + * General Affero de GNU para obtener una información más detallada. + * + * Debería haber recibido una copia de la Licencia Pública General Affero de + * GNU junto a este programa. + * + * En caso contrario, consulte . + */ + +namespace libredte\lib\Core\Sii\Dte\Documento\Parser\Sii; + +use libredte\lib\Core\Sii\Dte\Documento\Parser\DocumentoParserInterface; + +/** + * Transforma los datos en formato JSON con la estructura oficial del SII a un + * arreglo PHP con la estructura oficial del SII. + */ +class JsonParser implements DocumentoParserInterface +{ + /** + * Realiza la transformación de los datos del documento. + * + * @param string $data JSON con los datos de entrada. + * @return array Arreglo transformado a la estructura oficial del SII. + */ + public function parse(string $data): array + { + $array = json_decode($data, true); + + return $array; + } +} diff --git a/src/Sii/Dte/Documento/Parser/Sii/Xml.php b/src/Sii/Dte/Documento/Parser/Sii/Xml.php new file mode 100644 index 0000000..feeaca4 --- /dev/null +++ b/src/Sii/Dte/Documento/Parser/Sii/Xml.php @@ -0,0 +1,71 @@ + + * + * Este programa es software libre: usted puede redistribuirlo y/o modificarlo + * bajo los términos de la Licencia Pública General Affero de GNU publicada + * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia, + * o (a su elección) cualquier versión posterior de la misma. + * + * Este programa se distribuye con la esperanza de que sea útil, pero SIN + * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD + * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la Licencia Pública + * General Affero de GNU para obtener una información más detallada. + * + * Debería haber recibido una copia de la Licencia Pública General Affero de + * GNU junto a este programa. + * + * En caso contrario, consulte . + */ + +namespace libredte\lib\Core\Sii\Dte\Documento\Parser\Sii; + +use libredte\lib\Core\Sii\Dte\Documento\Parser\DocumentoParserException; +use libredte\lib\Core\Sii\Dte\Documento\Parser\DocumentoParserInterface; +use libredte\lib\Core\Xml\XmlConverter; +use libredte\lib\Core\Xml\XmlDocument; + +/** + * Transforma los datos en formato XML con la estructura oficial del SII a un + * arreglo PHP con la estructura oficial del SII. + */ +class XmlParser implements DocumentoParserInterface +{ + /** + * Realiza la transformación de los datos del documento. + * + * @param string $data XML con los datos de entrada. + * @return array Arreglo transformado a la estructura oficial del SII. + */ + public function parse(string $data): array + { + // Cargar los datos del XML a un arreglo. + $xmlDocument = new XmlDocument(); + $xmlDocument->loadXML($data); + $array = XmlConverter::xmlToArray($xmlDocument); + + // Obtener los datos del documento a generar. + $documentoData = $array['DTE']['Documento'] + ?? $array['DTE']['Exportaciones'] + ?? $array['DTE']['Liquidacion'] + ?? null + ; + + // Si el XML no tiene los tags válidos se lanza una excepción. + if ($documentoData === null) { + throw new DocumentoParserException( + 'El nodo raíz del XML del documento debe ser el tag "DTE". Dentro de este nodo raíz debe existir un tag "Documento", "Exportaciones" o "Liquidacion". Este segundo nodo es el que debe contener los datos del documento.' + ); + } + + // Quitar los atributos que tenga el tag encontrado. + unset($documentoData['@attributes']); + + // Entregar los datos parseados. + return $documentoData; + } +} diff --git a/src/Sii/Dte/Documento/Parser/Sii/Yaml.php b/src/Sii/Dte/Documento/Parser/Sii/Yaml.php new file mode 100644 index 0000000..9bc90ac --- /dev/null +++ b/src/Sii/Dte/Documento/Parser/Sii/Yaml.php @@ -0,0 +1,48 @@ + + * + * Este programa es software libre: usted puede redistribuirlo y/o modificarlo + * bajo los términos de la Licencia Pública General Affero de GNU publicada + * por la Fundación para el Software Libre, ya sea la versión 3 de la Licencia, + * o (a su elección) cualquier versión posterior de la misma. + * + * Este programa se distribuye con la esperanza de que sea útil, pero SIN + * GARANTÍA ALGUNA; ni siquiera la garantía implícita MERCANTIL o de APTITUD + * PARA UN PROPÓSITO DETERMINADO. Consulte los detalles de la Licencia Pública + * General Affero de GNU para obtener una información más detallada. + * + * Debería haber recibido una copia de la Licencia Pública General Affero de + * GNU junto a este programa. + * + * En caso contrario, consulte . + */ + +namespace libredte\lib\Core\Sii\Dte\Documento\Parser\Sii; + +use libredte\lib\Core\Sii\Dte\Documento\Parser\DocumentoParserInterface; +use Symfony\Component\Yaml\Yaml; + +/** + * Transforma los datos en formato YAML con la estructura oficial del SII a un + * arreglo PHP con la estructura oficial del SII. + */ +class YamlParser implements DocumentoParserInterface +{ + /** + * Realiza la transformación de los datos del documento. + * + * @param string $data YAML con los datos de entrada. + * @return array Arreglo transformado a la estructura oficial del SII. + */ + public function parse(string $data): array + { + $array = Yaml::parse($data); + + return $array; + } +}