Module Installation Hooks

1 views Markdown

The nine hooks over installing, switching on, deleting and queueing modules.

Overview

A module travels four steps: it is uploaded, switched on, switched off and deleted. Each step has a gate you can stop at in front of it and an event that reports it behind.

Two shapes differ. The switching hooks take a list, because the panel allows a multiple selection; the deletion hooks work with one module.

Reference

Stopping a module being switched on

gatemodule.activate
AdminModules a list arrives

Runs before one or more modules are switched on. The panel allows a multiple selection, so what arrives is a list.

Parameters 2
$groupstringThe module type: mail, text message, payment or product.
$modulesarrayThe keys being switched on in this request. It is an array even for one module; walk all of them.
Return 1
mixedA filled return blocks it: either a text or an array carrying a message, both accepted, and the message is shown to the user. An empty return lets it carry on.
Listener
Hook::add('gate:module.activate', 10, function ($group, $modules) {
    // It is an array even when one module was picked.
    foreach ($modules as $key)
        if (!Acme::licensed($group, $key)) return 'You hold no licence for this module: ' . $key;

    return null;
});

Following modules being switched on

actionmodule.activated
AdminModules a list arrives

Runs after the modules are switched on.

Parameters 2
$groupstringThe module type.
$modulesarrayThe keys that were switched on.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:module.activated', 10, function ($group, $modules) {
    foreach ($modules as $key) Acme::onModuleOn($group, $key);
});

Following modules being switched off

actionmodule.deactivated
AdminModules a list arrives

Runs after modules are switched off. A payment or server module taken out of service can leave live services behind it.

Parameters 2
$groupstringThe module type.
$modulesarrayThe keys that were switched off.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:module.deactivated', 10, function ($group, $modules) {
    // Live services may still sit behind a module now switched off.
    foreach ($modules as $key) Acme::warnOrphans($group, $key);
});

Stopping a module being deleted

gatemodule.delete
AdminModules one module

Runs before a module is deleted along with its files. Unlike switching on, here there is one module.

Parameters 2
$typestringThe module type.
$keystringThe module key.
Return 1
string|nullA non-empty text blocks the operation and is shown as the error. An empty return lets it carry on.
Listener
Hook::add('gate:module.delete', 10, function ($type, $key) {
    // Do not let a module go while services still sit on it.
    if (Acme::hasLiveServices($type, $key)) return 'Live services still run on this module.';

    return null;
});

Following a module being deleted

actionmodule.deleted
AdminModules after deletion

Runs after a module is deleted. Its files are no longer on disk.

Parameters 2
$typestringThe type of the deleted module.
$keystringThe key of the deleted module.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:module.deleted', 10, function ($type, $key) {
    Acme::forgetModule($type, $key);
});

Stopping an add-on upload

gatemodule.addon_install
AdminModules the uploaded file

Runs before an uploaded add-on package is opened. What you hold is the raw file, still in the temporary folder.

Parameters 2
$filearrayThe uploaded file: its name, temporary path and size. The file name comes from the user: do not trust it as it stands.
$activatedboolWhether it will be switched on right after the install.
Return 1
string|nullA non-empty text blocks the operation and is shown as the error. An empty return lets it carry on.
Listener
Hook::add('gate:module.addon_install', 10, function ($file, $activated) {
    // The name comes from the user: look at the content, not the name.
    if (!Acme::signatureValid($file['tmp_name'] ?? '')) return 'The package signature did not verify.';

    return null;
});

Stopping an add-on deletion

gatemodule.addon_delete
AdminModules before the write

Runs before an add-on is removed.

Parameters 1
$keystringThe key of the add-on to be removed.
Return 1
string|nullA non-empty text blocks the operation and is shown as the error. An empty return lets it carry on.
Listener
Hook::add('gate:module.addon_delete', 10, function ($key) {
    if (Acme::isRequired($key)) return 'The installation needs this add-on to run.';

    return null;
});

Changing the add-on list

filtermodule.addons_list
AdminModules passed by link

Runs once the list on the add-on page is prepared.

Parameters 1
$moduleListarrayby linkThe list in three groups: enabled, disabled and available to buy. Change it without breaking the shape: the template expects all three groups.
Return 1
voidThe return is ignored; you write over the list.
Listener
Hook::add('filter:module.addons_list', 10, function (&$moduleList) {
    // Keep the shape of the three groups.
    $moduleList['premium'] = Acme::filterOffers($moduleList['premium'] ?? []);
});

Stopping an intervention in the queue

gatemodule.queue_intervene
AdminModules zero on a bulk action

Runs before an administrator steps into the module queue by hand: retrying, deleting, clearing and running now.

Parameters 2
$actionstringWhat kind of intervention it is.
$idintThe id of the target record. On a bulk action it arrives as zero: a rule written to inspect one record then inspects nothing.
Return 1
string|nullA non-empty text blocks the operation and is shown as the error. An empty return lets it carry on.
Listener
Hook::add('gate:module.queue_intervene', 10, function ($action, $id) {
    // On a bulk action the id is ZERO: build no single-record assumption.
    if ($id === 0 && $action === 'delete') return 'Bulk deletion is closed.';

    return null;
});

Pitfalls

The switching hooks receive a list

Even for a single module the parameter is an array. A check that compares it directly catches nothing; walk the list.

A bulk queue action carries a zero

When several records are handled at once the record id arrives as zero. A rule written to inspect one record then quietly inspects nothing.

Was this helpful?

Thanks for your feedback!

Still Need Help?

Our support team is here around the clock for anything you can't find above.