Markus Michalski FAQ

Subticket Manager: Technische Details

Technische Details des osTicket-Plugins Subticket Manager: Startablauf, Auto-Verknüpfung, Dateistruktur, Datenbank-Änderungen, Deployment nach scp/, Schutzmechanismen und Einschränkungen.

English Version

Zurück zur Übersicht

Subticket Manager: Technische Details

Plugin-Metadaten

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)

Startablauf

Bei jedem Seitenaufruf, bei dem osTicket das aktive Plugin lädt, läuft bootstrap() in dieser Reihenfolge:

graph TD
    A["bootstrap()"] --> B["Services anlegen"]
    B --> C["Konfiguration in Zwischenspeicher"]
    C --> D["subticket_parent aus URL in Session"]
    D --> E["scp-Dateien neu kopieren, wenn Version abweicht"]
    E --> F["Tabellen, Spalte und Indizes anlegen"]
    F --> G["Staff-App Subtickets registrieren"]
    G --> H["Signal object.view nur im Staff-Bereich"]
    H --> I["Signale model.updated und model.created"]
    I --> J["Queue-Indikator-Skript auf Queue-Seiten"]

Auto-Verknüpfung beim Anlegen

sequenceDiagram
    participant A as Agent
    participant P as Panel
    participant O as osTicket
    participant H as TicketEventHandler
    A->>P: Create Subticket
    P->>O: Formular Neues Ticket mit Parent-ID
    O->>H: bootstrap speichert ID in der Session
    A->>O: Ticket anlegen
    O->>H: Signal model.created
    H->>O: UPDATE ost_ticket SET ticket_pid

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.

Dateistruktur

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

Datenbank-Änderungen

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 version werden vom Plugin angelegt, aber nirgends gelesen oder beschrieben. Die Funktionen des Plugins kommen allein mit ticket_pid aus.

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).

Deployment nach scp/

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.

Regeln und Schutzmechanismen

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

Kompatibilitätsprüfung

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.

Einschränkungen