Self-registration

How other modules can advertise their jobs to cronjob

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.

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

KeyRequiredMeaning
nameyesslug a-z 0-9 _ -, max 64; stored as <module>:<name>
titlenohuman name (defaults to name)
triggersyeslist of trigger entries, at least one
command_typeyesmodule or core
commandyesthe command
argsnoplain option/value tokens
enablednodefault false — discovered jobs are created disabled
timeout_secnodefault 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 event value 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

KeyRequiredMeaning
nameyesslug a-z 0-9 _ - (stored as <module>:<name>)
descriptionnoshown in the event catalog (translation key, max 255)
payloadnolist 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

KeyRequiredMeaning
commandyesa modules_v4/…/cli/*.php path or an allowlisted core command, max 255
command_typenomodule or core (derived from command when omitted)
descriptionnoshown in the command catalog (translation key, max 255)
paramsnolist 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 its cli/ scripts (backward compatible).

Last modified November 4, 2026: cross-references (60f426f)