Events
Latch allows extensions to execute code when named events are triggered. Events can return snippets of output, modify a passthrough array, or replace one passthrough value depending on how the event is triggered.
For more information on extension structure, see extensions.md.
Event Handler Structure
Create event files in your extension's lib/events directory. The filename is the event name:
extensions/my_extension/lib/events/form_after.php
The class name must be the PascalCase form of the event filename, inside this namespace:
Latch\Ext\<ExtensionDirectoryPascalCase>\Events
For an extension directory named my_extension, the form_after handler looks like this:
<?php
namespace Latch\Ext\MyExtension\Events;
class FormAfter
{
public static function event($args)
{
return "<button type=\"button\">My Custom Button</button>";
}
}
Latch loads handlers for active extensions in extension order. If multiple extensions listen to the same event, the earlier extension in the active extension list runs first.
The event registry is cached, but core versions and active extension manifests form a deployment fingerprint. A changed fingerprint or missing cached handler rebuilds the registry, so versioned extension deployments can add, remove, or rename handlers without a manual cache clear. Run php tests/benchmarks/events_restore.php after changing this restore path.
Return Behavior
Events are triggered in one of three modes:
- Normal collection: each handler return value is collected into an array.
- Array passthrough: handlers receive
$argsand may return an array merged into the running$argsvalue. - Named passthrough: handlers may return a replacement for one named
$argskey.
When using passthrough events, return the full modified $args array unless the event specifically expects a single named value.
Core Events
cron
Triggered by lib/hooks/cron.php, normally once per minute.
Arguments: none by default.
Use this for scheduled extension tasks.
form_before
Triggered before form fields are rendered.
Arguments:
form: Form name.form_id: Form parent ID.form_fields: Array of field rows.
Return a modified $args array to add, remove, or alter fields before rendering.
form_after
Triggered after form fields and the submit button are rendered.
Arguments:
form: Form name.form_id: Form parent ID.errors: Present on login/register form renders that have validation errors.
Return an HTML string to append to the form.
form_post_validate
Triggered during form submission before Latch writes the post data.
Arguments:
form_id: Form parent ID._post: Submitted POST data.errors: Optional array of validation errors.
Return a modified $args array. To fail validation, add at least one value to $args["errors"].
file_deleted
Triggered immediately after Latch deletes a managed upload. The file itself no longer exists when handlers run.
Arguments:
absolute_path: Former absolute filesystem path.relative_path: Path relative to the Latch root.context: Upload context such asadmin,form, orprofile.- Context-specific values such as
field_id,field_name,post_id, oruser_idmay also be present.
Use this event to remove derivatives or external indexes associated with a managed file. Handlers must not assume the deleted source can still be read.
file_replaced
Triggered after Latch successfully replaces a managed upload at the same path and before file_uploaded is triggered for the replacement.
Arguments match file_uploaded and describe the new file at the retained path. Use this event to remove stale derivatives or indexes before rebuilding them from the subsequent file_uploaded event.
file_uploaded
Triggered after Latch has successfully moved a managed upload into its final location.
Arguments:
absolute_path: Absolute filesystem path.relative_path: Path relative to the Latch root.mime_type: MIME type detected from file contents.size: File size in bytes.widthandheight: Image dimensions, or zero for non-image files.context: Upload context such asadmin,form,profile, orsuneditor.- Context-specific values such as
field_id,field_name,field_type,form_name,post_id,user_id, ororiginal_namemay also be present.
Use this event for asynchronous or queued media work. Avoid performing expensive conversions inside the upload request.
image_variants
Triggered when the shared Media renderer looks for alternate files for an image.
Arguments:
image: Description containing the source URL, local paths when available, MIME type, dimensions, and caller context.context: Renderer-specific context such aspost-contentorfeatured-media.variants: Alternate sources accumulated from earlier handlers.
Return the full $args array with each variant represented by type, srcset, and an optional sizes value. Preserve existing variants and order additions by preference. Providers should return only distinct public URLs; the renderer escapes attributes and retains the original image as the fallback.
media_forms
Triggered when Latch resolves which post forms participate in the shared Media Library and SunEditor image gallery.
Arguments:
forms: Form names, initially containing the stockMediaform.
Return the full $args array. Append form names to retain the stock library, or replace forms to substitute another media housing form. Participating forms should use database-action value create-post and tag their canonical upload field is_media.
extensions_update
Triggered while the Extensions form is being saved, after extension rows are updated but before the active-extension cache and event registry are reloaded.
Arguments:
active_extensions: Extension directory identifiers that will be active.previous_active_extensions: Extension directory identifiers that were active before the submission.
This event is delivered through the previous event registry so an extension being disabled can remove runtime configuration that would otherwise remain behind. A newly enabled extension should perform setup from its init handler after the registry reloads.
html_attributes
Triggered before the <html> element is printed.
Arguments are an associative array of HTML attributes.
Return the modified attribute array.
init
Triggered immediately after extension event files are loaded.
Arguments: none by default.
Use this to include extension libraries, run one-time installation routines, or initialize namespaced extension services.
login_validate_before
Triggered before built-in login or registration validation.
Arguments:
_POST: Submitted POST data.errors: Current errors array.form_name: The active form name.
Return a modified $args array.
login_validate_after
Triggered after built-in login validation locates a user.
Arguments:
_POST: Submitted POST data.errors: Current errors array.form_name: The active form name.id: User ID.
Return a modified $args array.
meta_tags
Triggered before meta tags are printed in the page <head>.
Arguments include page context plus meta_tags, an associative array where each key is the tag name or property and each value is the content.
Return the modified meta_tags array.
page_load
Triggered during early page loading. This is used by extensions that need request-level checks before normal page output.
Return behavior depends on the caller.
post_metadata_validate
Triggered while submitted post metadata is being validated.
Arguments:
field_idform_idform_namesetting_namesetting_valvalid
Return a modified $args array.
register_init
Triggered before registration form handling completes its setup.
Return a modified registration argument array.
register
Triggered after a user registration is created.
Arguments:
param_usernameparam_passwordemail_safetoken
reset_password
Triggered when a password reset token is issued.
Arguments:
id: User ID.token: Reset token.email: User email.name: User display name.
save_post
Triggered after a form submission is saved.
Arguments:
post_id: Post ID forCreate postforms. Non-post database actions may leave this as-1.form_id: Form parent ID.metadata_json: Saved metadata JSON string.type: Form name.
title_tag
Triggered before the document title is printed.
Return the title string or a modified argument value, depending on the caller.
