Self-registration
Other modules can advertise their scheduled jobs so they show up in the admin UI without manual registry editing. Two ways (a module may use both); both are discovered automatically on each tick, only for enabled modules:
Marker method
getCronJobs(): array on the module’s module.php
class, returning the same shape. Equivalent: getModuleEvents(): array, getModuleCommands(): array.
Manifest file (recommended)
modules_v4/<module>/cron-jobs.php that returns an array of job specs:
<?php
// modules_v4/linkenhancer/cron-jobs.php
declare(strict_types=1);
return [
[
'name' => 'link-index',
'title' => 'Update the link index',
'triggers' => [
['type' => 'time', 'cron' => '*/30 * * * *'],
],
'command_type' => 'module',
'command' => 'modules_v4/linkenhancer/cli/build-link-index.php',
'args' => '--limit=5000',
],
];Translatable title / description literals in a manifest should be wrapped in
MoreI18N::translate() (identity marker)
so xgettext picks them up - translation happens at render time, never at manifest
load.
Job spec fields
| Key | Required | Meaning |
|---|---|---|
name | yes | slug a-z 0-9 _ -, max 64; stored as <module>:<name> |
title | no | human name (defaults to name) |
triggers | yes | list of trigger entries, at least one |
command_type | yes | module or core |
command | yes | the command |
args | no | plain option/value tokens |
enabled | no | default false — discovered jobs are created disabled |
timeout_sec | no | default 300, range 30 - 3600 |
Once a discovered job is inserted it is admin-owned: later ticks never overwrite it.
Announcing events
The same manifest can also announce events your module emits (so they show up in
the event catalog and the job form’s suggestions). Instead of a plain job list, the
manifest may return an associative array with optional jobs and events lists (a
plain list still means “jobs only”):
<?php
// modules_v4/linkenhancer/cron-jobs.php
declare(strict_types=1);
return [
'jobs' => [
[
'name' => 'link-index',
'triggers' => [
['type' => 'time', 'cron' => '*/30 * * * *'],
// A job may combine several triggers:
// ['type' => 'event', 'event' => 'linkenhancer:index-dirty'],
],
'command_type' => 'module',
'command' => 'modules_v4/linkenhancer/cli/build-link-index.php',
],
],
'events' => [
['name' => 'index-dirty', 'description' => 'The link index is out of date.', 'payload' => ['tree']],
],
];- An announced event is namespaced
<module>:<name>(like the offered job keys). - An event trigger’s
eventvalue that carries no colon is auto-namespaced<module>:<event>; a name that already has a colon (e.g.cronjob:log-edit-update) is kept as-is. - Equivalent marker method:
getModuleEvents(): array(same event-spec shape).
Event spec fields
| Key | Required | Meaning |
|---|---|---|
name | yes | slug a-z 0-9 _ - (stored as <module>:<name>) |
description | no | shown in the event catalog (translation key, max 255) |
payload | no | list of payload parameter names (max 8), shown in the catalog |
Announcing commands
The same manifest can also announce commands a job may run, with their available
parameters. A plain manifest list is still “jobs only”; to announce commands the
manifest returns the associative form with a commands list:
// modules_v4/linkenhancer/cron-jobs.php
declare(strict_types=1);
return [
'jobs' => [ /* … */ ],
'commands' => [
[
'command' => 'modules_v4/linkenhancer/cli/build-link-index.php',
// 'command_type' => 'module', // optional - derived from the command value
'description' => 'Rebuild the link index incrementally.',
'params' => [
['name' => '--limit', 'optional' => true, 'default' => '5000', 'description' => 'max records per run'],
['name' => '--since', 'optional' => true, 'description' => 'only changes since this timestamp'],
],
],
],
];Command spec fields
| Key | Required | Meaning |
|---|---|---|
command | yes | a modules_v4/…/cli/*.php path or an allowlisted core command, max 255 |
command_type | no | module or core (derived from command when omitted) |
description | no | shown in the command catalog (translation key, max 255) |
params | no | list of parameter descriptors (max 8) |
Each parameter descriptor has name (the option token, e.g. --limit), optional
(bool, default true — set false for a required option), default (an optional
value) and description (optional). Equivalent marker method:
getModuleCommands(): array (same command-spec shape).
Curation rule: a module that announces commands curates its own command list — the glob-based discovery no longer lists its scripts, so internal scripts (
tick.php,watch.php,wrap.php,smoke-job.php) are not offered as job commands. A module that announces nothing falls back to glob discovery of itscli/scripts (backward compatible).