# Für Entwickler: Ereignisse

Fileshelf lässt sich mit eigenen Plugins erweitern – genau so, wie es die Pro-Version tut. Alle Plugins der Gruppe `fileshelf` lädt Fileshelf, bevor es seine Ereignisse feuert. Die Klassen liegen in `Graup\Component\Fileshelf\Administrator\Event`.

<div class="callout info" id="bkmrk-die-ereignisse-sind-">Die Ereignisse sind die öffentliche Schnittstelle von Fileshelf. Name, Argumente und öffentliche Methoden ändern sich nur mit einer neuen Hauptversion.

</div>## Die Ereignisse

<table class="table" id="bkmrk-ereignisklassewannwa"> <thead> <tr><th scope="col">Ereignis</th><th scope="col">Klasse</th><th scope="col">Wann</th><th scope="col">Was ein Plugin tun kann</th></tr> </thead> <tbody> <tr><td><code>onFileshelfResolveToken</code></td><td><code>ResolveTokenEvent</code></td><td>Die Anfrage trägt einen Token (<code>t</code>).</td><td><code>grant&#40;&#41;</code> überspringt Zugriffsebene und Passwort, <code>reject&#40;&#41;</code> sperrt mit Grund <code>token</code>.</td></tr> <tr><td><code>onFileshelfAccess</code></td><td><code>AccessEvent</code></td><td>Nach Status, Token, Zugriffsebene und Passwort; auch in Listen (Kontext <code>list</code>).</td><td><code>deny&#40;&#36;reason&#44; &#36;message&#44; &#36;redirect&#41;</code> sperrt. In Listen nichts zählen oder schreiben.</td></tr> <tr><td><code>onFileshelfBeforeSend</code></td><td><code>BeforeSendEvent</code></td><td>Zugriff erteilt, vor dem Zähler.</td><td><code>setFile&#40;&#41;</code> tauscht die Datei; Fileshelf prüft sie danach erneut gegen die Ablage.</td></tr> <tr><td><code>onFileshelfAfterCount</code></td><td><code>AfterCountEvent</code></td><td>Nach dem Hochzählen, vor dem ersten Byte.</td><td>Nur Meldung; <code>getRequestId&#40;&#41;</code> verbindet mit dem nächsten Ereignis.</td></tr> <tr><td><code>onFileshelfAfterSend</code></td><td><code>AfterSendEvent</code></td><td>Nach dem Senden, auch bei Abbruch.</td><td><code>isCompleted&#40;&#41;</code>, <code>getBytesSent&#40;&#41;</code>, <code>getMethod&#40;&#41;</code>.</td></tr> <tr><td><code>onFileshelfDownloadDisplay</code></td><td><code>DownloadDisplayEvent</code></td><td>Detailseite, je Position.</td><td><code>addHtml&#40;&#41;</code> mit fertig maskiertem HTML.</td></tr> <tr><td><code>onFileshelfDashboard</code></td><td><code>DashboardEvent</code></td><td>Dashboard im Backend.</td><td><code>addTile&#40;&#36;id&#44; &#36;title&#44; &#36;html&#44; &#36;order&#44; &#36;area&#41;</code> (<code>&#36;area</code>: <code>status</code>, <code>content</code>, <code>insight</code> oder <code>setup</code>); ab 1.8.0 <code>addAttention&#40;&#36;id&#44; &#36;text&#44; &#36;link&#44; &#36;count&#44; &#36;label&#41;</code> für „Braucht Ihre Aufmerksamkeit“, nur bei Handlungsbedarf mit Ausweg; eigenes Recht vorher prüfen.</td></tr> <tr><td><code>onFileshelfAdminPages</code></td><td><code>AdminPagesEvent</code></td><td>Dashboard und jede Plugin-Seite.</td><td><code>addPage&#40;&#36;name&#44; &#36;title&#44; &#36;right&#44; &#36;icon&#41;</code> meldet eine Seite <code>view&#61;page&#38;page&#61;…</code> an; Fileshelf prüft das Recht.</td></tr> <tr><td><code>onFileshelfAdminPage</code></td><td><code>AdminPageEvent</code></td><td>Die Plugin-Seite wird angezeigt.</td><td><code>addHtml&#40;&#41;</code>, <code>addAction&#40;&#36;action&#44; &#36;label&#44; &#36;icon&#44; &#36;confirm&#41;</code>.</td></tr> <tr><td><code>onFileshelfAdminAction</code></td><td><code>AdminActionEvent</code></td><td>Eine Aktion der Seite läuft; Token, Recht und Bestätigung sind geprüft.</td><td><code>handled&#40;&#36;message&#44; &#36;type&#41;</code>.</td></tr> <tr><td><code>onFileshelfFilesInUse</code></td><td><code>FilesInUseEvent</code></td><td>Werkzeuge, Download-Formular und Medienmanager fragen, welche Dateien der Ablage Plugins gehören.</td><td><code>claim&#40;&#36;path&#41;</code> für eigene Dateien (z. B. ältere Versionen); sie gelten nie als verwaist.</td></tr> <tr><td><code>onFileshelfSitePages</code></td><td><code>SitePagesEvent</code></td><td>Menüpunkt „Erweiterungsseite“ und jeder Aufruf einer solchen Seite.</td><td><code>addPage&#40;&#36;name&#44; &#36;title&#44; &#36;login&#41;</code> meldet eine Seite der Website an; mit <code>&#36;login</code> leitet Fileshelf Gäste zur Anmeldung.</td></tr> <tr><td><code>onFileshelfSitePage</code></td><td><code>SitePageEvent</code></td><td>Die Seite wird angezeigt.</td><td><code>addHtml&#40;&#41;</code> mit fertig maskiertem HTML, <code>setTitle&#40;&#41;</code>, <code>getOptions&#40;&#41;</code> (Menüpunkt).</td></tr> <tr><td><code>onFileshelfSiteAction</code></td><td><code>SiteActionEvent</code></td><td>Ein Formular der Seite wurde abgeschickt; Token, Seite und Anmeldung sind geprüft.</td><td><code>handled&#40;&#36;message&#44; &#36;type&#44; &#36;redirect&#41;</code>; Fileshelf maskiert die Meldung.</td></tr> <tr><td><code>onFileshelfCategoryDisplay</code></td><td><code>CategoryDisplayEvent</code></td><td>Kategorieseite, Positionen <code>beforeList</code> und <code>afterList</code>.</td><td><code>addHtml&#40;&#41;</code> mit fertig maskiertem HTML; <code>getTotal&#40;&#41;</code> nennt die Zahl der gelisteten Downloads.</td></tr> <tr><td><code>onFileshelfActionLog</code></td><td><code>ActionLogEvent</code></td><td>Seit 1.3.0: Fileshelf oder ein Plugin meldet eine Aktion fürs Aktionsprotokoll (Passwort, Freigabe, Import).</td><td>Reine Meldung: <code>getAction&#40;&#41;</code>, <code>getKind&#40;&#41;</code> (<code>download</code>, <code>category</code>, <code>import</code>), <code>getItemId&#40;&#41;</code>, <code>getTitle&#40;&#41;</code>, <code>getDetails&#40;&#41;</code>. Das Plugin „Aktionsprotokoll - Fileshelf“ schreibt sie.</td></tr> <tr><td><code>onFileshelfImportSources</code></td><td><code>ImportSourcesEvent</code> (Pro)</td><td>Seit 1.3.0: Die Seite „Import“ sammelt ihre Quellen.</td><td><code>addSource&#40;&#41;</code> mit einer Klasse, die <code>SourceInterface</code> des Import-Plugins erfüllt (Kategorien, Downloads, Prüfung der Tabellen).</td></tr> <tr><td><code>onFileshelfResolveScopes</code></td><td><code>ResolveScopesEvent</code></td><td>Von der Pro-Version (Limits) gefeuert, sobald ein Limit einen Scope-Typ eines anderen Plugins nutzt; die Free-Version feuert es nicht.</td><td><code>addScope&#40;&#36;type&#44; &#36;id&#41;</code>.</td></tr> </tbody></table>

Der Download kommt als schreibgeschütztes `DownloadRecord` (ohne Passwort-Hash), nie als Table-Objekt. Eigene Sperrgründe beginnen mit `x-<plugin>-`; die Website zeigt dann nur die Nachricht.

## Beispiel

```
final class Example extends CMSPlugin implements SubscriberInterface
{
    public static function getSubscribedEvents(): array
    {
        return ['onFileshelfAccess' => 'onAccess'];
    }

    public function onAccess(AccessEvent $event): void
    {
        if ($event->getContext() !== 'list' && !$this->allowed($event->getUser())) {
            $event->deny('x-example-hours', 'Downloads sind nur werktags möglich.');
        }
    }
}
```

Formular-Reiter am Download fügen Plugins wie bei Beiträgen mit `onContentPrepareForm` (Formular `com_fileshelf.download`) ein und speichern sie in `onContentAfterSave` (Kontext `com_fileshelf.download`).

## Seiten auf der Website

Mit dem Menüpunkttyp **Fileshelf → Erweiterungsseite** bekommt ein Plugin eine eigene Seite auf der Website, ohne eigene Komponente. Formulare dieser Seite schicken `task=extension.action`, `page`, `action` und das Formular-Token an `Route::_('index.php?option=com_fileshelf')` – die Adresse immer über `Route::_()` bauen, eine relative Adresse stimmt unter suchmaschinenfreundlichen URLs nicht. Reiter am Kategorieformular hängen Plugins mit `onContentPrepareForm` an das Formular `com_categories.categorycom_fileshelf`; Fileshelf lädt die Gruppe `fileshelf` dafür.

[English version](https://docs.graup-it.de/link/441)