Module Installation Hooks
The ten hooks over installing, switching on, updating, deleting and queueing modules.
Overview
A module travels five steps: it is uploaded, switched on, updated, switched off and deleted. Each step has a gate you can stop at in front of it and an event that reports it behind; the update has only the event.
Two shapes differ. The switching hooks take a list, because the panel allows a multiple selection; the update and deletion hooks work with one module.
Reference
Stopping a module being switched on
Runs before one or more modules are switched on. The panel allows a multiple selection, so what arrives is a list.
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
Runs after the modules are switched on.
Hook::add('action:module.activated', 10, function ($group, $modules) {
foreach ($modules as $key) Acme::onModuleOn($group, $key);
});Following a module being updated
Runs when a module bought from the store or the marketplace finishes its panel update: the new files are in place and the version has moved on. It is the moment to run your own migration. The hook fires for every updated module, so filter on type and key. Available from 5.0-beta.4.
source (wstore or marketplace), type (the module type directory), key (the module directory), from (the version before the update), version (the version installed) and dir (the module directory path). from is the only place the previous version survives.Hook::add('action:module.updated', 10, function (array $update) {
if ($update['type'] !== 'Addons' || $update['key'] !== 'Acme') return;
// Key the migration to the version the update came from.
if (version_compare($update['from'], '2.0.0', '<')) Acme::migrateTo200();
});Following modules being switched off
Runs after modules are switched off. A payment or server module taken out of service can leave live services behind it.
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
Runs before a module is deleted along with its files. Unlike switching on, here there is one module.
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
Runs after a module is deleted. Its files are no longer on disk.
Hook::add('action:module.deleted', 10, function ($type, $key) {
Acme::forgetModule($type, $key);
});Stopping an add-on upload
Runs before an uploaded add-on package is opened. What you hold is the raw file, still in the temporary folder.
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
Runs before an add-on is removed.
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
Runs once the list on the add-on page is prepared.
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
Runs before an administrator steps into the module queue by hand: retrying, deleting, clearing and running now.
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
Even for a single module the parameter is an array. A check that compares it directly catches nothing; walk the list.
When several records are handled at once the record id arrives as zero. A rule written to inspect one record then quietly inspects nothing.
A panel update moves meta.version in the module's config.php on to the installed release. A migration that compares that number with the version in your code never sees the gap; key it to from instead.
The exception is caught and written to the error log as Hook execution error: action:module.updated; the update still completes and the wizard reports success. Write the migration so it can run again.
Related Articles
- Shipping Module Updates
- Module Hooks
- System Event Hooks
- How Hooks Work
Vielen Dank für Ihre Rückmeldung!
Unser Support-Team ist rund um die Uhr für Sie da, wenn Sie oben nicht fündig werden.