Extensions

Capabilities

Latch extensions are capable of providing any or all of the following behaviors:

  1. Loading stylesheets. Latch autoloads css/style.css for each active extension when the file exists.
  2. Overriding core scripts and templates. Most files are loaded through Latch\File\ext_part(), which checks active extensions before core files. Files in app contain CMS initialization logic and are not extension override targets.
  3. Event handlers. Extensions can run PHP code for any Latch event and can define custom event names for their own code.
  4. Custom admin forms that write data to the latch_extensions table.
  5. Custom shortcodes from extensions/my_extension/lib/shortcodes.
  6. Custom post templates, page templates, form templates, datatype handlers, cachers, and other files resolved through ext_part().

Metadata

Every extension must have a package.json file in the root of the extension directory, for example extensions/my_extension/package.json.

Here is an example with the common supported keys:

{
    "name": "Backups",
    "description": "Schedule backups of your Latch files and database.",
    "author": "Sparknight",
    "url": "https://sparknight.io",
    "version": "0.0.1",
    "icon": "fa-solid fa-hard-drive"
}

A few points to keep in mind:

  • name is the friendly value shown in the dashboard. The extension directory is the unique identifier used by the filesystem.
  • If icon is provided, the extension can appear as a sidebar link in the Admin Dashboard.
  • version should follow Semantic Versioning.

Priority

Extensions are loaded in the order they appear in the active extension list.

For file overrides, the first active extension with a matching file takes precedence. Other matches further down the extension list are ignored.

For events, multiple extensions can hook into the same event. The earlier extension in the active extension list runs first.

Events

Event files live at:

extensions/my_extension/lib/events/event_name.php

The event class must use this namespace and class pattern:

<?php

namespace Latch\Ext\MyExtension\Events;

class EventName
{
    public static function event($args)
    {
        // Your processing here.
    }
}

For example, to add content to the bottom of a Latch form, create extensions/my_extension/lib/events/form_after.php:

<?php

namespace Latch\Ext\MyExtension\Events;

class FormAfter
{
    public static function event($args)
    {
        return <<<HTML
            <button type="button">My Custom Button</button>
        HTML;
    }
}

The $args variable is a named array provided by $_SESSION["latch"]->events->trigger().

Initialization Event

The init event is triggered immediately after extension event files are loaded. It is a good place to include extension libraries, run installation routines, or initialize namespaced services.

Example init.php:

<?php

namespace Latch\Ext\MyExtension\Events;

class Init
{
    public static function event($args)
    {
        include_once __DIR__ . "/../my-extension.php";
    }
}

If your extension exposes reusable code, put it in a namespaced file outside the event handler, such as extensions/my_extension/lib/my-extension.php:

<?php

namespace Latch\Ext\MyExtension;

function get_log()
{
    return \Latch\Util\new_log("ext.my_extension");
}

Cron Event

A cron job is a task that runs automatically at a specific time or interval. Latch relies on a single cron job that fires every minute. It calls lib/hooks/cron.php, which triggers the cron event.

An extension can add scheduled behavior by creating:

extensions/my_extension/lib/events/cron.php

The handler should decide for itself whether work is due. For example, the Backups extension checks configured backup jobs and only runs a job when its schedule has elapsed.