| Eigenschaft | Wert |
|---|---|
| Plugin-ID | subticket-manager |
| Name | Subticket Manager |
| Plugin-Klasse | SubticketPlugin in class.SubticketPlugin.php |
| Konfigurationsklasse | SubticketPluginConfig in config.php |
| Instanzen | Singleton, enable() legt die Instanz automatisch an |
| Lizenz | GNU GPL v2 (Datei LICENSE) |
Bei jedem Seitenaufruf, bei dem osTicket das aktive Plugin lädt, läuft bootstrap() in dieser Reihenfolge:
Der Handler nimmt die ID nur an, wenn sie numerisch und größer als 0 ist. Beim Anlegen setzt er ticket_pid per direktem UPDATE, ohne Existenz-, Schleifen- oder Abteilungsprüfung, und löscht die ID danach aus der Session.
subticket-manager/
├── plugin.php # Metadaten
├── class.SubticketPlugin.php # Plugin-Klasse, Lebenszyklus, Signal-Anbindung
├── config.php # Konfigurationsformular
├── queue-decoration.php # ParentTicketDecoration
├── ajax/
│ ├── SubticketController.php # Logik hinter ajax-subticket.php
│ └── PluginPathResolver.php # Hilfsfunktion für Tests
├── scp-files/ # werden nach scp/ kopiert
│ ├── subtickets.php # Übersichtsseite
│ ├── ajax-subticket.php # AJAX-Einstiegspunkt
│ └── apps.php # Anwendungs-Übersicht
├── js/
│ ├── subticket-panel.js # Panel-Interaktionen
│ └── queue-indicator.js # Icons in der Warteschlange
└── src/ # PSR-4, Namespace SubticketManager
├── Asset/AssetDeployer.php # Kopieren und Entfernen der scp-Dateien
├── Config/ConfigCache.php # Zwischenspeicher für Konfigurationswerte
├── Database/DatabaseService.php # Tabellen, Spalte, Indizes, Fremdschlüssel
├── Hierarchy/HierarchyService.php # Verknüpfen, Trennen, Schleifenprüfung
├── Signal/TicketEventHandler.php # Signal-Handler
└── UI/PanelRenderer.php # HTML, CSS und Skript-Loader des Panels
Die Beziehungen selbst stehen in der osTicket-Spalte ost_ticket.ticket_pid. Das Plugin ergänzt beim Start, falls noch nicht vorhanden:
| Objekt | Definition |
|---|---|
Tabelle ost_ticket_hierarchy_metadata |
ticket_id (Primärschlüssel), auto_close_enabled, inherit_settings, dependency_type, max_children, created, updated |
Tabelle ost_ticket_progress |
parent_id (Primärschlüssel), total_children, completed_children, in_progress_children, pending_children, last_calculated |
Spalte ost_ticket.version |
int(11) DEFAULT 0 |
Index idx_ticket_pid |
auf ost_ticket(ticket_pid) |
Index idx_ticket_hierarchy |
auf ost_ticket(ticket_id, ticket_pid, status_id) |
Fremdschlüssel fk_hierarchy_ticket, fk_progress_ticket |
auf ost_ticket(ticket_id) mit ON DELETE CASCADE, nur wenn für die Tabelle noch kein Fremdschlüssel besteht |
Die beiden Tabellen und die Spalte
versionwerden vom Plugin angelegt, aber nirgends gelesen oder beschrieben. Die Funktionen des Plugins kommen allein mitticket_pidaus.
Die Prüfungen laufen bei jedem Start des Plugins (also bei jedem osTicket-Seitenaufruf): als SHOW-Abfragen für Tabellen, Spalte und Indizes und je Tabelle als SELECT auf information_schema.TABLE_CONSTRAINTS für den Fremdschlüssel. Beim Deinstallieren entfernt das Plugin die Objekte nur, wenn Remove Data on Uninstall aktiv ist (siehe Konfiguration).
Der AssetDeployer kopiert scp-files/subtickets.php, scp-files/ajax-subticket.php und scp-files/apps.php nach scp/. Er läuft bei enable() und bei jedem Start, wenn die Datei scp/.subticket-deployed-version fehlt oder eine andere Version als plugin.php enthält. Die Zielverzeichnis- und Schreibrechte-Prüfung liefert die Fehlermeldungen aus Installation.
| Bereich | Verhalten |
|---|---|
| Verknüpfen | ID größer 0, kein Selbstbezug, beide Tickets müssen existieren, keine Schleife |
| Schleifenprüfung | isDescendant() folgt der Kette ticket_pid höchstens zehn Ebenen. Bei tieferen Ketten endet die Prüfung ohne Treffer. Eine Begrenzung der Hierarchietiefe gibt es nicht |
| Mehrere Parents | Nicht möglich, ein Ticket hat genau eine Spalte ticket_pid |
| Eingaben | Ticket-IDs werden als positive Zahlen validiert, SQL-Werte laufen durch db_input() |
| CSRF | link, unlink und create verlangen ein gültiges osTicket-CSRF-Token |
| Abteilungszugriff | Prüfung über canAccessDept(), Administratoren sind ausgenommen |
| Rate-Limit | 100 Anfragen pro 60 Sekunden und Session für children, link, unlink, create |
| Panel-Ausgabe | Nummer, Betreff und Status werden mit htmlspecialchars ausgegeben |
Die Plugin-Klasse enthält isCompatible(). Die Methode meldet false, wenn die osTicket-Version unter 1.18.0 liegt, PHP unter 7.4 läuft oder die Spalte ticket_pid in ost_ticket fehlt.
ost_ ist in allen SQL-Abfragen fest eingetragen.children und die Übersichtsseite prüfen keine Abteilungsrechte.