Navigazione Docs

Sistema Plugin

Come funziona il sistema plugin di Fatturino e come crearne uno.

Architettura

Come Funziona

  1. Plugin Registry — Traccia quali plugin sono registrati e attivi
  2. Service Providers — Ogni plugin ha un provider che registra contratti
  3. Capability System — Plugin dichiarano cosa possono fare via enum
  4. Activation DB — Tabella plugins traccia lo stato (attivo/disattivo/locked)

File Structure

fatturino/
├── app/
│   ├── Enums/Capability.php           # Azioni plugin-realizzabili
│   ├── Contracts/                      # Contratti per plugin
│   │   ├── LoginCustomizer.php
│   │   └── ...
│   └── Services/PluginRegistry.php    # Gestisce attivazione
├── packages/
│   ├── plugin-demo-mode/              # Plugin di esempio
│   │   ├── src/
│   │   │   └── DemoModeServiceProvider.php
│   │   └── config/
│   │       └── demo-mode.php
│   └── plugin-hello/                  # Template per plugin custom

Creare un Plugin

Step 1: Struttura Base

mkdir -p packages/plugin-my-feature/src

cd packages/plugin-my-feature
cat > composer.json << 'EOF'
{
  "name": "fatturino/plugin-my-feature",
  "description": "My awesome feature",
  "type": "library",
  "require": { "php": "^8.3" },
  "autoload": {
    "psr-4": {
      "FatturoiNoPlugins\\MyFeature\\": "src/"
    }
  }
}
EOF

Step 2: Service Provider

namespace FatturoiNoPlugins\MyFeature;

use Illuminate\Support\ServiceProvider;

class MyFeatureServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        // Registra route, view, asset, etc
        $this->loadRoutesFrom(__DIR__.'/routes/web.php');
    }

    public function register(): void
    {
        // Registra binding nel container
        $this->app->bind('my-feature', function () {
            return new MyFeatureService();
        });
    }

    public static function capabilities(): array
    {
        return [\FatturoiNo\Enums\Capability::CustomInvoiceFields];
    }
}

Step 3: Registra nel Core

In app/Providers/AppServiceProvider.php:

use App\Services\PluginRegistry;

public function boot(): void
{
    $registry = $this->app->make(PluginRegistry::class);
    $registry->register('my-feature',
        \FatturoiNoPlugins\MyFeature\MyFeatureServiceProvider::class
    );
}

Step 4: Accedi dal Dashboard

Il plugin apparirà in Settings → Plugins e si attiva/disattiva da lì.

Plugin Builtin

Demo Mode Plugin

  • Ubicazione: packages/plugin-demo-mode/
  • Features: Credenziali demo, fixtures dati, banners UI
  • Locked: Utenti non possono disattivare

Hello Plugin

  • Ubicazione: packages/plugin-hello/
  • Uso: Starting point per creare il tuo primo plugin

Contratti Plugin

LoginCustomizer

Implementa la customizzazione della pagina di login:

namespace App\Contracts;

interface LoginCustomizer
{
    public function customizeLogin(): string;  // HTML customizzato
    public function customizeTitle(): string;  // Titolo page
}

Best Practices

Isolamento

Evita di toccare il core. Usa contratti e binding:

// ✓ Buono
$this->app->bind(MyContract::class, MyImplementation::class);

// ✗ Male
DB::table('invoices')->update(...);

Configurazione

Ogni plugin ha una cartella config/:

// packages/my-plugin/config/my-plugin.php
return [
    'enabled' => env('MY_PLUGIN_ENABLED', true),
    'api_key' => env('MY_PLUGIN_API_KEY'),
];

// Accedi nel plugin
$enabled = config('my-plugin.enabled');

Testing

test('plugin can be activated', function () {
    $registry = app(PluginRegistry::class);
    $registry->activate('my-feature');
    assertTrue($registry->isActive('my-feature'));
});

Prossimi Passi