SIGNALS Documentation
API Reference

Plugin Document Template Seeder Registry

Contract for collecting plugin callbacks that seed warehouse-scoped document templates.

Overview

App\Services\Plugins\PluginDocumentTemplateSeederRegistry collects plugin callbacks that should run when document templates are seeded for a warehouse.

The current runtime consumer is Database\Seeders\DocumentTemplateSeeder. Its seedForWarehouse() method first seeds the core SystemDocumentTemplates, then invokes this registry, and then calls DocumentSequenceDefaults::seedForWarehouse($warehouse).

As a factual note about the current integration, PluginRegistrar::seedDocumentTemplates() forwards callbacks into this registry; this is not SDK usage guidance.

Public surface

Method Purpose
register() Append one plugin seeder callback
seedForWarehouse() Invoke every registered callback for one warehouse
all() Return the accumulated callback list for inspection

Accepted contract

Each registration is a callable(Warehouse): void.

The registry does not wrap the callback in an adapter object. It stores the callable exactly as given and invokes it later with the concrete App\Models\Warehouse instance being seeded.

Current core state

Core ships no built-in plugin template seeders. The singleton starts empty and only changes if a plugin registers one or more callbacks.

Accumulation and registration order

register() appends to an internal list:

$this->seeders[] = $seeder;

That means callbacks accumulate. Re-registering the same closure or logically equivalent callback creates another entry; the registry does not deduplicate or replace earlier registrations.

seedForWarehouse() runs the callbacks in registration order:

foreach ($this->seeders as $seeder) {
    $seeder($warehouse);
}

all() returns the same ordered list, which is why tests can inspect the current registry contents directly.

Warehouse invocation and idempotence expectations

The registry itself does not create templates. It only executes callbacks.

The current caller is:

foreach (SystemDocumentTemplates::definitions() as $definition) {
    DocumentTemplate::query()->firstOrCreate(...);
}

$this->pluginSeeders->seedForWarehouse($warehouse);
DocumentSequenceDefaults::seedForWarehouse($warehouse);

Because DocumentTemplateSeeder::seedForWarehouse() may run more than once for the same warehouse, plugin callbacks should be idempotent if they create or update templates. The existing test seam uses firstOrCreate(...) for exactly that reason.

Failure behaviour

The registry does not catch exceptions, open its own transaction, or continue past failures.

If one callback throws:

  • the exception bubbles to DocumentTemplateSeeder
  • later plugin callbacks are not executed
  • DocumentSequenceDefaults::seedForWarehouse($warehouse) is not reached in that call path

This is the current framework behaviour, so plugin seeders should fail only when they genuinely want the warehouse-seeding flow to stop.

Worked example

This framework-level registration is executable against the current document_templates schema. The firstOrCreate() lookup supplies the warehouse-scoped unique identity, while the creation values include every required persisted template attribute, including the non-null body_html value:

app(PluginDocumentTemplateSeederRegistry::class)->register(function (Warehouse $warehouse): void {
    DocumentTemplate::query()->firstOrCreate(
        [
            'warehouse_id' => $warehouse->id,
            'slug' => 'plugin-equipment-cert',
        ],
        [
            'created_by_account_id' => null,
            'name' => 'Plugin Equipment Certificate',
            'description' => 'Equipment certificate supplied by the plugin.',
            'document_type' => 'equipment_certificate',
            'model_type' => Rental::class,
            'body_html' => '<p>Plugin template</p>',
            'header_html' => null,
            'footer_html' => null,
            'styles_css' => null,
            'page_config' => null,
            'branding_config' => null,
            'is_default' => false,
            'is_system' => false,
            'is_active' => true,
            'version' => 1,
            'last_edited_at' => now(),
        ],
    );
});

When DocumentTemplateSeeder::seedForWarehouse($warehouse) later runs, this callback receives that warehouse and idempotently creates the template after the core templates and before the warehouse's document sequence defaults.