Crear Plugins para FacturaScripts

Guía completa para desarrollar plugins desde cero

Introducción al Desarrollo de Plugins

Los plugins permiten extender la funcionalidad de FacturaScripts sin modificar el código base. En esta guía aprenderás a crear un plugin completo desde cero.

🎯 Lo que aprenderás

  • Estructura básica de un plugin
  • Creación de controladores
  • Definición de modelos de datos
  • Implementación de vistas
  • Configuración del archivo INI

📦 Plugin de Ejemplo

  • Nombre: MiPrimerPlugin
  • Función: Gestión de tareas simples
  • Características: CRUD completo
  • Base de datos: Una tabla nueva

Estructura del Plugin

Todo plugin en FacturaScripts sigue una estructura específica. Vamos a crear el directorio base:

Plugins/
└── MiPrimerPlugin/
    ├── Controller/
    │   └── ListTarea.php
    ├── Model/
    │   └── Tarea.php
    ├── View/
    │   └── ListTarea.html.twig
    ├── Translation/
    │   └── es_ES.json
    └── facturascripts.ini

Paso 1: Configuración del Plugin (facturascripts.ini)

Este archivo define la información básica del plugin:

[plugin]
name = MiPrimerPlugin
description = "Mi primer plugin para FacturaScripts - Gestión de tareas"
version = 1.0
author = Tu Nombre
email = tu@email.com
min_version = 2024

[models]
MiPrimerPlugin/Model/Tarea = Tarea

[controllers]
MiPrimerPlugin/Controller/ListTarea = ListTarea

Paso 2: Crear el Modelo de Datos

El modelo define la estructura de datos y la tabla en la base de datos:

<?php
namespace FacturaScripts\Plugins\MiPrimerPlugin\Model;

use FacturaScripts\Core\Model\Base\ModelClass;
use FacturaScripts\Core\Model\Base\ModelTrait;

class Tarea extends ModelClass
{
    use ModelTrait;

    /**
     * Primary key (autoincrement)
     * @var int
     */
    public $id;

    /**
     * Task title
     * @var string
     */
    public $titulo;

    /**
     * Task description
     * @var string
     */
    public $descripcion;

    /**
     * Creation date
     * @var string
     */
    public $fechacreacion;

    /**
     * Due date
     * @var string
     */
    public $fechavencimiento;

    /**
     * Completed flag
     * @var bool
     */
    public $completada;

    /**
     * Returns the name of the table in the database
     * @return string
     */
    public static function tableName(): string
    {
        return 'tareas';
    }

    /**
     * Returns the name of the primary column
     * @return string
     */
    public static function primaryColumn(): string
    {
        return 'id';
    }

    /**
     * Returns the mapping of fields in the table
     * @return array
     */
    public function getFields(): array
    {
        return [
            'id' => ['type' => 'INT', 'auto_increment' => true],
            'titulo' => ['type' => 'VARCHAR', 'length' => 100],
            'descripcion' => ['type' => 'TEXT'],
            'fechacreacion' => ['type' => 'DATETIME'],
            'fechavencimiento' => ['type' => 'DATETIME'],
            'completada' => ['type' => 'BOOLEAN']
        ];
    }

    /**
     * Executed before saving the model
     * @return bool
     */
    protected function beforeSave(): bool
    {
        if ($this->isInsert()) {
            $this->fechacreacion = date('Y-m-d H:i:s');
        }
        return parent::beforeSave();
    }
}

Paso 3: Crear el Controlador

El controlador maneja la lógica de la aplicación y las interacciones del usuario:

<?php
namespace FacturaScripts\Plugins\MiPrimerPlugin\Controller;

use FacturaScripts\Core\Lib\ExtendedController\ListController;
use FacturaScripts\Plugins\MiPrimerPlugin\Model\Tarea;

class ListTarea extends ListController
{
    /**
     * Returns the class name of the model
     * @return string
     */
    public function getModelClassName(): string
    {
        return 'Tarea';
    }

    /**
     * Returns the page title
     * @return string
     */
    public function getPageData(): array
    {
        $pageData = parent::getPageData();
        $pageData['title'] = 'Tareas';
        $pageData['menu'] = 'admin';
        $pageData['icon'] = 'fas fa-tasks';
        return $pageData;
    }

    /**
     * Create the views to display
     */
    protected function createViews()
    {
        $this->addListView('ListTarea', 'Tarea', 'tareas', 'fas fa-tasks');
        $this->setSettings('ListTarea', 'btnNew', true);
    }

    /**
     * Load view data procedure
     * @param string $viewName
     * @param BaseView $view
     */
    protected function loadData($viewName, $view)
    {
        switch ($viewName) {
            case 'ListTarea':
                $view->loadData();
                break;
        }
    }
}

Paso 4: Crear la Vista (Template)

La vista define la interfaz de usuario. Usamos el sistema de plantillas de FacturaScripts:

{% extends "Master/MenuTemplate.html.twig" %}

{% block body %}
    <div class="container-fluid">
        <div class="row">
            <div class="col-12">
                <div class="card shadow mb-4">
                    <div class="card-header py-3">
                        <h6 class="m-0 font-weight-bold text-primary">
                            <i class="fas fa-tasks mr-2"></i>
                            Gestión de Tareas
                        </h6>
                    </div>
                    <div class="card-body">
                        {% set grid = fsc.getView('ListTarea') %}
                        {{ grid.render() | raw }}
                    </div>
                </div>
            </div>
        </div>
    </div>
{% endblock %}

{% block javascripts %}
    {{ parent() }}
    <script>
        document.addEventListener('DOMContentLoaded', function() {
            // JavaScript personalizado para la vista de tareas
            console.log('Vista de tareas cargada');
        });
    </script>
{% endblock %}

Paso 5: Traducciones

Crea el archivo de traducciones para internacionalización:

{
    "tarea": "Tarea",
    "tareas": "Tareas",
    "nueva-tarea": "Nueva Tarea",
    "titulo": "Título",
    "descripcion": "Descripción",
    "fechacreacion": "Fecha de Creación",
    "fechavencimiento": "Fecha de Vencimiento",
    "completada": "Completada",
    "pendiente": "Pendiente",
    "mi-primer-plugin": "Mi Primer Plugin"
}

Paso 6: Instalar y Probar el Plugin

1. Copiar los archivos

Copia la carpeta MiPrimerPlugin completa al directorio Plugins/ de tu instalación de FacturaScripts.

2. Activar el plugin

  1. Ve al panel de administración
  2. Navega a "Administración → Plugins"
  3. Busca "MiPrimerPlugin" en la lista
  4. Haz clic en "Activar"

3. Verificar la instalación

  • Revisa que aparezca el nuevo menú "Tareas"
  • Verifica que se haya creado la tabla tareas en la base de datos
  • Prueba crear, editar y eliminar tareas

Ejemplo Completo: Plugin de Notas Rápidas

Vamos a crear un plugin más completo para gestionar notas rápidas:

Modelo: Model/Nota.php

<?php
namespace FacturaScripts\Plugins\MiPrimerPlugin\Model;

use FacturaScripts\Core\Model\Base\ModelClass;

class Nota extends ModelClass
{
    public $id;
    public $titulo;
    public $contenido;
    public $fechacreacion;
    public $importante;

    public static function tableName(): string
    {
        return 'notas';
    }

    public static function primaryColumn(): string
    {
        return 'id';
    }

    public function getFields(): array
    {
        return [
            'id' => ['type' => 'INT', 'auto_increment' => true],
            'titulo' => ['type' => 'VARCHAR', 'length' => 200],
            'contenido' => ['type' => 'TEXT'],
            'fechacreacion' => ['type' => 'DATETIME'],
            'importante' => ['type' => 'BOOLEAN']
        ];
    }

    protected function beforeSave(): bool
    {
        if ($this->isInsert()) {
            $this->fechacreacion = date('Y-m-d H:i:s');
        }
        return parent::beforeSave();
    }
}

Controlador: Controller/ListNota.php

<?php
namespace FacturaScripts\Plugins\MiPrimerPlugin\Controller;

use FacturaScripts\Core\Lib\ExtendedController\ListController;

class ListNota extends ListController
{
    public function getModelClassName(): string
    {
        return 'Nota';
    }

    public function getPageData(): array
    {
        $pageData = parent::getPageData();
        $pageData['title'] = 'Notas Rápidas';
        $pageData['menu'] = 'admin';
        $pageData['icon'] = 'fas fa-sticky-note';
        return $pageData;
    }

    protected function createViews()
    {
        $this->addListView('ListNota', 'Nota', 'notas', 'fas fa-sticky-note');
        $this->setSettings('ListNota', 'btnNew', true);
    }

    protected function loadData($viewName, $view)
    {
        switch ($viewName) {
            case 'ListNota':
                $view->loadData();
                break;
        }
    }
}

Solución de Problemas Comunes

Plugin no aparece

  • Verifica que facturascripts.ini esté bien formado
  • Comprueba los permisos de los directorios
  • Revisa los logs en MyFiles/Logs/

Errores de base de datos

  • Verifica que el modelo herede de ModelClass
  • Comprueba los nombres de tablas y columnas
  • Revisa que los tipos de datos sean correctos

Errores en vistas

  • Verifica la sintaxis Twig
  • Comprueba que las vistas existan
  • Revisa los nombres de las clases en los controladores

Mejores Prácticas

📁 Estructura de código

  • Usa namespaces correctamente
  • Sigue las convenciones de nombres
  • Documenta tu código
  • Mantén la separación MVC

🔒 Seguridad

  • Valida siempre los datos de entrada
  • Usa consultas preparadas
  • Respetar los permisos de usuarios
  • Sanitiza las salidas HTML

🎯 UX/UI

  • Usa el sistema de plantillas de FacturaScripts
  • Mantén la consistencia visual
  • Haz tus vistas responsive
  • Provee traducciones

Próximos Pasos

🚀 Funcionalidades Avanzadas

  • Crear APIs REST personalizadas
  • Implementar hooks y eventos
  • Desarrollar widgets para el dashboard
  • Crear informes personalizados

🛠️ Herramientas

  • PHPStan para análisis estático
  • Composer para dependencias
  • Git para control de versiones
  • VS Code con extensión PHP