Librería satélite para manipulación de documentos ODF (Open Document Format).
- Sistema avanzado de plantillas ODF con soporte para:
- Variables simples y anidadas
- Bucles
- Condiciones IF
- Imágenes y SVG dinámicos
- Operaciones aritméticas
- Funciones personalizables
- Múltiples formatos de exportación:
- ODF nativo
- PDF (requiere LibreOffice)
- Opciones de salida flexibles:
- Guardar a disco
- Enviar por correo (Symfony Mailer/Nette)
- Imprimir (CUPS)
- PHP 8.4+
- Extensión ZIP de PHP
- LibreOffice (opcional, para conversión a PDF)
- Composer
composer require xvii/satelles-odf-relatioEl proceso de creación y procesamiento de un documento ODF es sencillo. A continuación se muestra un ejemplo básico de cómo utilizar la biblioteca para generar un documento a partir de una plantilla ODF.
use Tabula17\Satelles\Odf\OdfProcessor;
use Tabula17\Satelles\Odf\File\OdfContainer;
use Tabula17\Satelles\Odf\Renderer\DataRenderer;
use Tabula17\Satelles\Odf\Functions\Advanced;
use Tabula17\Satelles\Odf\Exporter\ExportToFile;
// Configuración básica
$zipHandler = new ZipArchive();
$fileContainer = new OdfContainer($zipHandler);
$functions = new Advanced('/tmp');
$data = [
'title' => 'Mi Documento',
'items' => [ 'name' => 'item1', 'name' => 'item2', 'name' => 'item3']
];
// Crear el procesador
$renderer = new DataRenderer($data, $functions);
$processor = new OdfProcessor(
'template.odt',
'/tmp',
$fileContainer,
$renderer
);
// Procesar y exportar
$processor->loadFile()
->process($data)
->compile()
->exportTo(new ExportToFile('/output', 'result.odf'))
->cleanUpWorkingDir();El método process aplica los datos a la plantilla, compile genera el documento ODF.
El método exportTo puede ser utilizado para exportar a diferentes formatos, como ODF nativo o PDF, dependiendo de la implementación del exportador.
Hasta ese momento, el documento ODF generado se encuentra en el directorio de trabajo temporal especificado.
Este método se puede encadenar y volver a ejecutar con otros exportadores para realizar operaciones adicionales, como enviar por correo o imprimir.
La clase ExportToFile utilizada en los ejemplos utiliza el método saveToDisk para guardar el archivo generado en el disco.
Los "exportadores" pueden incluir una instancia de una clase que implemente ConverterInterface para la conversión del formato final.
En este caso ExportToFile usa ConvertToPdf para convertir el archivo ODF a PDF, si es que encuentra instalado LibreOffice en el sistema.
Esta clase se encarga de ejecutar el comando soffice para realizar la conversión, por lo cual no es recomendada para entornos de alto rendimiento o producción, ya que puede ser lenta y bloquear el proceso.
Para estos casos se recomienda utilizar un servidor Unoserver, que permite realizar la conversión de manera asíncrona y con mejor rendimiento (ver 🪐 orbitalis-odf-exemplar.)
Al finalizar, se limpia el directorio de trabajo temporal con cleanUpWorkingDir.
Las plantillas pueden editarse directamente en openoffice o libreoffice. Para utilizar las variables y estructuras de control, debes agregar etiquetas específicas en el documento ODF. Estas etiquetas se utilizan para identificar dónde se deben insertar los datos dinámicos. Es necesario conocer la estructura XML del ODF para agregar las etiquetas correctamente.
Para agregar estos valores desde la inetrfaz de usuario, utiliza el menú "Insertar" -> "Campo" -> "Otro campo" -> "Funciones".
Agregar en la referencia la etiqueta correspondiente (ej. odf-tpl-text) , posar el puntero en donde quiere agregar la etiqueta, accionar el botón "Insertar" y en el agregar el valor de la variable (ej. ${variable}).
El nombre de la variable (${variable}) debe corresponder al nombre del miembro en el set de datos que se está utilizando.
En el caso de que la variable necesite tener un valor por defecto, se puede utilizar la sintaxis ${variable?defaultValue}.
<text:text-input text:description="odf-tpl-text">${variable}</text:text-input>Los bucles se utilizan para iterar sobre colecciones de datos. Se definen con la etiqueta odf-tpl-loop y se pueden utilizar dentro de tablas o listas.
<text:text-input text:description="odf-tpl-loop">items#up@table:table-row as item</text:text-input>
<text:text-input text:description="odf-tpl-text">${item.name}</text:text-input>La variable está conformada por el miembro en el set de datos que define el bucle (items en este caso) seguido del descriptor del elemento que va a repetirse en la iteración.
En este ejemplo#up@table:table-row repite en la iteración una fila de tabla ubicada como padre del nodo <text:text-input /> que contiene la variable.
El miembro anterior al @ indíca el nivel de iteración, mientras que el miembro posterior define al elemento XML que se está iterando.
Por ejemplo si se necesita iterar un elemento en el mismo nivel, se utiliza #left@text:p si está posicionado antes o #right@text:span si está después.
Si es un elemento hijo del contenedor, se utiliza #down@text:p.
En as item se define el alias de la variable que se utilizará para denominar a las variables hijas dentro del bucle.
Las condiciones se definen con la etiqueta odf-tpl-if y permiten mostrar u ocultar contenido basado en condiciones lógicas.
La sintaxis es similar a la de las variables, pero se utiliza para evaluar expresiones. Ver el método evaluateExpression en la clase XmlProcessor para más detalles sobre cómo se evalúan las condiciones.
<text:text-input text:description="odf-tpl-if">${total} > 1000#up@table:table-row</text:text-input>Para insertar imágenes dinámicas se debe agregar una imágen como 'placeholder' en donde irá la generada en el proceso y mediante las propiedades de la misma se agregan las etiquetas (nombre) y las variables (texto alternativo) utilizando la siguiente sintaxis:
<draw:frame draw:name="odf-tpl-image">
<svg:desc>${image_path}</svg:desc>
<draw:image xlink:href=""/>
</draw:frame>Si la imágen está dentro de un buclé y se genera de manera diferente en cada iteración, utiliza:
<draw:frame draw:name="odf-tpl-image-loop">
<svg:desc>${image_path}</svg:desc>
<draw:image xlink:href=""/>
</draw:frame>Si la imagen es un SVG, utiliza:
<draw:frame draw:name="odf-tpl-svg">
<svg:desc>${svg_content}</svg:desc>
<draw:image xlink:href=""/>
</draw:frame>Al igual que las imágenes, si el SVG está dentro de un bucle, utiliza:
<draw:frame draw:name="odf-tpl-svg-loop">
<svg:desc>${svg_content}</svg:desc>
<draw:image xlink:href=""/>
</draw:frame>Para realizar operaciones aritméticas básicas dentro de las plantillas, puedes utilizar la sintaxis ${value1 + value2}.
<text:text-input text:description="odf-tpl-text">${value1}+${value2}</text:text-input>Estas operaciones son evaluadas mediante la clase Tabula17\Satelles\Securitas\Evaluator\SafeMathEvaluator de la librería xvii/satelles-securitas.
La clase DataRenderer permite definir funciones personalizadas que pueden ser utilizadas en las plantillas como "transformadores" de los datos pasados a las variables.
Estas se definen en la clase de funciones que se pasa al DataRenderer. La clase Base proporciona un método mágico que llama a funciones PHP lo cual permite utilizar funciones nativas de PHP directamente en las plantillas.
En la sintaxis de la plantilla, se utiliza el símbolo # seguido del nombre de la función y sus parámetros separados por |.
El primer parámetro pasado automáticamente a la función es el valor de la variable, por lo cual no hay que incluirlo.
Los siguientes son los parámetros adicionales que la función pueda requerir.
Si la función requiere que el parámetro con el valor de la variable NO sea el primero se debe ubicar el término __VALUE__ en la posición requerida.
Por ejemplo, para utilizar la función strtoupper de PHP, puedes hacer lo siguiente:
<text:text-input text:description="odf-tpl-text">${variable#strtoupper}</text:text-input>O para formatear un número con dos decimales:
<text:text-input text:description="odf-tpl-text">${variable#number_format|2|,}</text:text-input>Para crear funciones personalizadas, extiende la clase Tabula17\Satelles\Odf\Functions\Base o crea una nueva clase que implemente Tabula17\Satelles\Odf\FunctionsInterface y define tus métodos.
Luego, pasa tu clase de funciones al DataRenderer.
Como ejemplo está la clase Advanced que incluye funciones para generar códigos QR y de barras (utilizados en los ejemplos).
use Tabula17\Satelles\Odf\Functions\Base;
class MyFunctions extends Base { /*o implements FunctionsInterface */
public function customFormat($value, $param) {
// Implementación personalizada
return $formatted;
}
}
$renderer = new DataRenderer($data, new MyFunctions());<text:text-input text:description="odf-tpl-text">${variable#customFormat|paramValue}</text:text-input>El directorio examples/ contiene ejemplos completos:
saveToDiskComplex.php: Procesamiento complejo con guardado a discosendMail.php: Envío por correo electrónicomultipleActions.php: Múltiples acciones de exportaciónprintFile.php: Impresión de documentossaveToDisk.php: Guardado básico a disco
Puede ver dentro de examples/templates/ las plantillas utilizadas en los ejemplos, y dentro de examples/media/ los datos y recursos necesarios para generar los reportes.
Adaptación para uso asincrónico mediante Swoole: 🪐 orbitalis-odf-exemplar.
MIT License
Para reportar problemas o solicitar nuevas características:
- Revisa los issues existentes
- Abre un nuevo issue con los detalles del problema o sugerencia