# Selbst-Registrierung

> Wie andere Module ihre Jobs dem Cronjob-Modul anbieten

---

Andere Module können ihre [geplanten Jobs](../cli-scripts) *anbieten*, damit sie in der Admin-UI erscheinen, ohne dass jemand die Registry manuell editiert. Dazu können zwei Wege beschritten werden (ein Modul kann beide verwenden) - beide werden automatisch bei jedem [Tick](../tick) entdeckt, wobei dies nur für **aktivierte** Module gilt:

## Marker-Methode

`getCronJobs(): array` in der Modul-<a href="https://github.com/bschwede/wt-cronjob/tree/main/module.php" target="_blank" rel="noopener"><code>module.php</code></a>
-Klasse, die dasselbe Format zurückgibt. Entsprechend: `getModuleEvents(): array`, `getModuleCommands(): array`.

## Manifest-Datei (empfohlen)

Bereitstellung einer Datei im Modulverzeichnis (`modules_v4/<module>/cron-jobs.php`), die ein Array von Job-Spezifikationen zurückgibt:

<div class="highlight"><pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#91d7e3;font-weight:bold">&lt;?</span>php
</span></span><span style="display:flex;"><span><span style="color:#6e738d;font-style:italic">// modules_v4/linkenhancer/cron-jobs.php
</span></span></span><span style="display:flex;"><span><span style="color:#c6a0f6">declare</span>(strict_types<span style="color:#91d7e3;font-weight:bold">=</span><span style="color:#f5a97f">1</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#c6a0f6">return</span> [
</span></span><span style="display:flex;"><span>    [
</span></span><span style="display:flex;"><span>        <span style="color:#a6da95">&#39;name&#39;</span>         <span style="color:#91d7e3;font-weight:bold">=&gt;</span> <span style="color:#a6da95">&#39;link-index&#39;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#a6da95">&#39;title&#39;</span>        <span style="color:#91d7e3;font-weight:bold">=&gt;</span> <span style="color:#a6da95">&#39;Update the link index&#39;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#a6da95">&#39;triggers&#39;</span>     <span style="color:#91d7e3;font-weight:bold">=&gt;</span> [
</span></span><span style="display:flex;"><span>            [<span style="color:#a6da95">&#39;type&#39;</span> <span style="color:#91d7e3;font-weight:bold">=&gt;</span> <span style="color:#a6da95">&#39;time&#39;</span>, <span style="color:#a6da95">&#39;cron&#39;</span> <span style="color:#91d7e3;font-weight:bold">=&gt;</span> <span style="color:#a6da95">&#39;*/30 * * * *&#39;</span>],
</span></span><span style="display:flex;"><span>        ],
</span></span><span style="display:flex;"><span>        <span style="color:#a6da95">&#39;command_type&#39;</span> <span style="color:#91d7e3;font-weight:bold">=&gt;</span> <span style="color:#a6da95">&#39;module&#39;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#a6da95">&#39;command&#39;</span>      <span style="color:#91d7e3;font-weight:bold">=&gt;</span> <span style="color:#a6da95">&#39;modules_v4/linkenhancer/cli/build-link-index.php&#39;</span>,
</span></span><span style="display:flex;"><span>        <span style="color:#a6da95">&#39;args&#39;</span>         <span style="color:#91d7e3;font-weight:bold">=&gt;</span> <span style="color:#a6da95">&#39;--limit=5000&#39;</span>,
</span></span><span style="display:flex;"><span>    ],
</span></span><span style="display:flex;"><span>];</span></span></code></pre></div>

Übersetzbare `title` / `description`-Texte in einem Manifest sollten in `MoreI18N::translate()` (Identitäts-Markierung) gesetzt werden,
damit `xgettext` sie aufnimmt — die Übersetzung erfolgt zur Render-Zeit, nie beim laden des Manifests.

### Job-Spezifikations-Felder

| Schlüssel | Erforderlich | Bedeutung |
| :--- | :--- | :--- |
| `name` | ja | Slug `a-z 0-9 _ -`, max. 64; gespeichert als `<module>:<name>` |
| `title` | nein | menschlicher Name (Default = `name`) |
| `triggers` | ja | Liste von Trigger-Einträgen, mindestens einer |
| `command_type` | ja | `module` oder `core` |
| `command` | ja | der Befehl |
| `args` | nein | einfache Option/Wert-Tokens |
| `enabled` | nein | Default `false` — entdeckte Jobs werden deaktiviert erstellt |
| `timeout_sec` | nein | Default `300`, Bereich 30 - 3600 |

Sobald ein entdeckter Job eingefügt ist, ist er unter **Admin-Kontrolle**: spätere Ticks überschreiben ihn nie.

## Ereignisse ankündigen

Dasselbe Manifest kann auch [**Ereignisse**](../events) ankündigen, die das Modul auslöst (damit sie im
Ereignis-Katalog und in den Vorschlägen des Job-Formulars erscheinen). Anstelle einer
einfachen Job-Liste kann das Manifest ein assoziatives Array mit optionalen `jobs`- und
`events`-Listen zurückgeben (eine einfache Liste bedeutet weiterhin „nur Jobs"):

<div class="highlight"><pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#91d7e3;font-weight:bold">&lt;?</span>php
</span></span><span style="display:flex;"><span><span style="color:#6e738d;font-style:italic">// modules_v4/linkenhancer/cron-jobs.php
</span></span></span><span style="display:flex;"><span><span style="color:#c6a0f6">declare</span>(strict_types<span style="color:#91d7e3;font-weight:bold">=</span><span style="color:#f5a97f">1</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#c6a0f6">return</span> [
</span></span><span style="display:flex;"><span>    <span style="color:#a6da95">&#39;jobs&#39;</span> <span style="color:#91d7e3;font-weight:bold">=&gt;</span> [
</span></span><span style="display:flex;"><span>        [
</span></span><span style="display:flex;"><span>            <span style="color:#a6da95">&#39;name&#39;</span>     <span style="color:#91d7e3;font-weight:bold">=&gt;</span> <span style="color:#a6da95">&#39;link-index&#39;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#a6da95">&#39;triggers&#39;</span> <span style="color:#91d7e3;font-weight:bold">=&gt;</span> [
</span></span><span style="display:flex;"><span>                [<span style="color:#a6da95">&#39;type&#39;</span> <span style="color:#91d7e3;font-weight:bold">=&gt;</span> <span style="color:#a6da95">&#39;time&#39;</span>, <span style="color:#a6da95">&#39;cron&#39;</span> <span style="color:#91d7e3;font-weight:bold">=&gt;</span> <span style="color:#a6da95">&#39;*/30 * * * *&#39;</span>],
</span></span><span style="display:flex;"><span>                <span style="color:#6e738d;font-style:italic">// A job may combine several triggers:
</span></span></span><span style="display:flex;"><span>                <span style="color:#6e738d;font-style:italic">// [&#39;type&#39; =&gt; &#39;event&#39;, &#39;event&#39; =&gt; &#39;linkenhancer:index-dirty&#39;],
</span></span></span><span style="display:flex;"><span>            ],
</span></span><span style="display:flex;"><span>            <span style="color:#a6da95">&#39;command_type&#39;</span> <span style="color:#91d7e3;font-weight:bold">=&gt;</span> <span style="color:#a6da95">&#39;module&#39;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#a6da95">&#39;command&#39;</span>      <span style="color:#91d7e3;font-weight:bold">=&gt;</span> <span style="color:#a6da95">&#39;modules_v4/linkenhancer/cli/build-link-index.php&#39;</span>,
</span></span><span style="display:flex;"><span>        ],
</span></span><span style="display:flex;"><span>    ],
</span></span><span style="display:flex;"><span>    <span style="color:#a6da95">&#39;events&#39;</span> <span style="color:#91d7e3;font-weight:bold">=&gt;</span> [
</span></span><span style="display:flex;"><span>        [<span style="color:#a6da95">&#39;name&#39;</span> <span style="color:#91d7e3;font-weight:bold">=&gt;</span> <span style="color:#a6da95">&#39;index-dirty&#39;</span>, <span style="color:#a6da95">&#39;description&#39;</span> <span style="color:#91d7e3;font-weight:bold">=&gt;</span> <span style="color:#a6da95">&#39;The link index is out of date.&#39;</span>, <span style="color:#a6da95">&#39;payload&#39;</span> <span style="color:#91d7e3;font-weight:bold">=&gt;</span> [<span style="color:#a6da95">&#39;tree&#39;</span>]],
</span></span><span style="display:flex;"><span>    ],
</span></span><span style="display:flex;"><span>];</span></span></code></pre></div>

- Ein angekündigtes Ereignis ist namespaced **`<module>:<name>`** (wie die angebotenen Job-Schlüssel).
- Der `event`-Wert eines Ereignis-Triggers, der keinen Doppelpunkt trägt, wird automatisch
  namespaced `<module>:<event>`; ein Name, der bereits einen Doppelpunkt hat (z.B.
  `cronjob:log-edit-update`), bleibt unverändert.
- Entsprechende Marker-Methode: `getModuleEvents(): array` (dasselbe Event-Spec-Format).

### Event-Spezifikations-Felder

| Schlüssel | Erforderlich | Bedeutung |
| :--- | :--- | :--- |
| `name` | ja | Slug `a-z 0-9 _ -` (gespeichert als `<module>:<name>`) |
| `description` | nein | wird im Ereignis-Katalog angezeigt (Übersetzungsschlüssel, max. 255) |
| `payload` | nein | Liste von Payload-Parameter-Namen (max. 8), wird im Katalog angezeigt |

## Befehle ankündigen

Dasselbe Manifest kann auch **Befehle** ankündigen, die ein Job ausführen kann, mit ihren
verfügbaren Parametern. Eine einfache Manifest-Liste bedeutet weiterhin „nur Jobs"; um
Befehle anzukündigen, gibt das Manifest die assoziative Form mit einer `commands`-Liste zurück:

<div class="highlight"><pre tabindex="0" style="color:#cad3f5;background-color:#24273a;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-php" data-lang="php"><span style="display:flex;"><span><span style="color:#6e738d;font-style:italic">// modules_v4/linkenhancer/cron-jobs.php
</span></span></span><span style="display:flex;"><span><span style="color:#c6a0f6">declare</span>(strict_types<span style="color:#91d7e3;font-weight:bold">=</span><span style="color:#f5a97f">1</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#c6a0f6">return</span> [
</span></span><span style="display:flex;"><span>    <span style="color:#a6da95">&#39;jobs&#39;</span> <span style="color:#91d7e3;font-weight:bold">=&gt;</span> [ <span style="color:#6e738d;font-style:italic">/* … */</span> ],
</span></span><span style="display:flex;"><span>    <span style="color:#a6da95">&#39;commands&#39;</span> <span style="color:#91d7e3;font-weight:bold">=&gt;</span> [
</span></span><span style="display:flex;"><span>        [
</span></span><span style="display:flex;"><span>            <span style="color:#a6da95">&#39;command&#39;</span>      <span style="color:#91d7e3;font-weight:bold">=&gt;</span> <span style="color:#a6da95">&#39;modules_v4/linkenhancer/cli/build-link-index.php&#39;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#6e738d;font-style:italic">// &#39;command_type&#39; =&gt; &#39;module&#39;,  // optional - derived from the command value
</span></span></span><span style="display:flex;"><span>            <span style="color:#a6da95">&#39;description&#39;</span>  <span style="color:#91d7e3;font-weight:bold">=&gt;</span> <span style="color:#a6da95">&#39;Rebuild the link index incrementally.&#39;</span>,
</span></span><span style="display:flex;"><span>            <span style="color:#a6da95">&#39;params&#39;</span> <span style="color:#91d7e3;font-weight:bold">=&gt;</span> [
</span></span><span style="display:flex;"><span>                [<span style="color:#a6da95">&#39;name&#39;</span> <span style="color:#91d7e3;font-weight:bold">=&gt;</span> <span style="color:#a6da95">&#39;--limit&#39;</span>, <span style="color:#a6da95">&#39;optional&#39;</span> <span style="color:#91d7e3;font-weight:bold">=&gt;</span> <span style="color:#c6a0f6">true</span>, <span style="color:#a6da95">&#39;default&#39;</span> <span style="color:#91d7e3;font-weight:bold">=&gt;</span> <span style="color:#a6da95">&#39;5000&#39;</span>, <span style="color:#a6da95">&#39;description&#39;</span> <span style="color:#91d7e3;font-weight:bold">=&gt;</span> <span style="color:#a6da95">&#39;max records per run&#39;</span>],
</span></span><span style="display:flex;"><span>                [<span style="color:#a6da95">&#39;name&#39;</span> <span style="color:#91d7e3;font-weight:bold">=&gt;</span> <span style="color:#a6da95">&#39;--since&#39;</span>, <span style="color:#a6da95">&#39;optional&#39;</span> <span style="color:#91d7e3;font-weight:bold">=&gt;</span> <span style="color:#c6a0f6">true</span>, <span style="color:#a6da95">&#39;description&#39;</span> <span style="color:#91d7e3;font-weight:bold">=&gt;</span> <span style="color:#a6da95">&#39;only changes since this timestamp&#39;</span>],
</span></span><span style="display:flex;"><span>            ],
</span></span><span style="display:flex;"><span>        ],
</span></span><span style="display:flex;"><span>    ],
</span></span><span style="display:flex;"><span>];</span></span></code></pre></div>

### Command-Spezifikations-Felder

| Schlüssel | Erforderlich | Bedeutung |
| :--- | :--- | :--- |
| `command` | ja | ein `modules_v4/…/cli/*.php`-Pfad oder ein erlaubter Core-Befehl, max. 255 |
| `command_type` | nein | `module` oder `core` (wird bei weggelassenem Wert aus `command` abgeleitet) |
| `description` | nein | wird im Befehl-Katalog angezeigt (Übersetzungsschlüssel, max. 255) |
| `params` | nein | Liste von Parameter-Deskriptoren (max. 8) |

Jeder Parameter-Deskriptor hat `name` (das Option-Token, z.B. `--limit`), `optional`
(Bool, Default `true` — auf `false` setzen für eine erforderliche Option), `default`
(ein optionaler Wert) und `description` (optional). Entsprechende Marker-Methode:
`getModuleCommands(): array` (dasselbe Command-Spec-Format).

> **Kurations-Regel:** Ein Modul, das Befehle ankündigt, **kuratiert seine eigene Befehlsliste** —
> die glob-basierte Entdeckung listet *seine* Skripte nicht mehr auf, sodass interne Skripte
> (<a href="https://github.com/bschwede/wt-cronjob/tree/main/cli/tick.php" target="_blank" rel="noopener"><code>tick.php</code></a>
, <a href="https://github.com/bschwede/wt-cronjob/tree/main/cli/watch.php" target="_blank" rel="noopener"><code>watch.php</code></a>
, <a href="https://github.com/bschwede/wt-cronjob/tree/main/cli/wrap.php" target="_blank" rel="noopener"><code>wrap.php</code></a>
, <a href="https://github.com/bschwede/wt-cronjob/tree/main/cli/smoke-job.php" target="_blank" rel="noopener"><code>smoke-job.php</code></a>
) nicht als Job-Befehle angeboten
> werden. Ein Modul, das nichts ankündigt, fällt auf die glob-Entdeckung seiner
> `cli/`-Skripte zurück (abwärtskompatibel).
