Anatomie eines Plugins
Verstehe die grundlegenden Elemente eines Plugins, von den obligatorischen Headern bis hin zu den Aktivierungs-, Deaktivierungs- und Deinstallations-Hooks für einen sauberen Lebenszyklus.
Jedes robuste WordPress-Plugin benötigt ein solides Fundament. In diesem Kapitel werden wir die interne Struktur einer professionellen Entwicklung entschlüsseln und uns von Amateur-Code verabschieden, um eine modulare und skalierbare Architektur zu etablieren.
Du wirst die obligatorischen Direktiven in den Headern, die sichere Verteilung von Dateien und die absolute Beherrschung des Hooks-Systems (Actions und Filters) kennenlernen – dem Herzstück der Erweiterbarkeit des Cores. Schließlich lernst du, den gesamten Lebenszyklus der Software zu verwalten (Aktivierung, Deaktivierung und die Bereinigung nach dem Prinzip Tabula Rasa bei der Deinstallation), während du deinen Code mit den strengen offiziellen WordPress-Coding-Standards (WPCS) absicherst.
2.1 Header- und Dateistruktur
Der Ausgangspunkt für jede Plugin-Entwicklung in WordPress ist das Design der Dateistruktur und die korrekte Deklaration der Metadaten. WordPress verlässt sich auf einen speziell formatierten Kommentarblock in der Hauptdatei des Plugins, um dessen Existenz zu erkennen, es im Admin-Bereich zu registrieren und grundlegende Abhängigkeiten zu verwalten.
Der Header-Block des Plugins
Damit die WordPress-Engine eine PHP-Datei als gültiges aktives oder aktivierbares Plugin erkennt, muss diese Datei einen einleitenden Blockkommentar enthalten. WordPress nutzt die interne Funktion get_plugin_data(), um diese Direktiven mithilfe von regulären Ausdrücken zu scannen und zu parsen und diese Informationen für das Dashboard des Administrators aufzubereiten.
Es folgt eine standardisierte Vorlage mit allen Header-Direktiven, die für eine professionelle und unternehmenseigene Entwicklung benötigt werden:
PHP
Anatomie und Semantik der Header-Direktiven
- Plugin Name (Erforderlich): Definiert den kommerziellen oder operativen Namen, der in der Plugin-Liste des Administrationsbereichs angezeigt wird. Er muss einzigartig sein, um Identitätskonflikte beim Kunden zu vermeiden.
- Plugin URI: Die URL der Informationsseite, Dokumentation oder des Repositories des Plugins. Sie sollte auf eine produktspezifische Webressource verweisen.
- Description: Eine prägnante technische Zusammenfassung (empfohlen werden weniger als 140 Zeichen), die die genaue Funktionalität der Komponente beschreibt.
- Version: Die aktuelle Version des Plugins. Es ist zwingend erforderlich, dem Paradigma der semantischen Versionierung (MAJOR.MINOR.PATCH) zu folgen, damit Update-Systeme Versions-Strings korrekt vergleichen können.
- Requires at least: Die minimale WordPress-Core-Version, die die Existenz der im Code verwendeten nativen Funktionen und APIs garantiert.
- Requires PHP: Die erforderliche PHP-Mindestversion. Wenn der Server des Benutzers eine niedrigere Version ausführt, bricht WordPress die Aktivierung sicher ab und verhindert so schwerwiegende Syntaxfehler (Fatal Errors).
- Author / Author URI: Identifikation des Entwicklers oder der verantwortlichen Organisation sowie deren kontaktlink.
- License / License URI: Der rechtliche Rahmen der Software. Für ein reibungsloses Zusammenspiel im WordPress-Ökosystem wird die GPLv2-Lizenz oder neuer gewählt.
- Text Domain: Der eindeutige Bezeichner (Slug), der von der Internationalisierungs-Engine (
i18n) verwendet wird, um Übersetzungsfunktionen (__(),_e()) mit den lokalen Sprachdateien zu verknüpfen. - Domain Path: Gibt den physischen Pfad an, in dem sich die kompilierten Übersetzungsdateien (
.mound.po) befinden. Standardmäßig wird dies in/languagesabgelegt. - Update URI: Überschreibt den Standard-Update-Server des offiziellen WordPress-Verzeichnisses. Dies ist entscheidend für intern oder privat vertriebene Plugins, um den Core anzuweisen, Update-Metadaten auf eigenen Endpunkten abzurufen.
Strukturelle Architektur des Dateisystems
Obwohl WordPress die Ausführung eines Plugins erlaubt, das in einer einzigen PHP-Datei direkt im Root von wp-content/plugins/ liegt, beeinträchtigt dieser Ansatz die Wartbarkeit, das Unit-Testing und die Skalierbarkeit des Codes erheblich. Ein professionelles Umfeld erfordert eine strikte Trennung der Belange durch eine modulare Architektur.
Schadensbegrenzung bei direkten Zugriffsangriffen
Die Kontrollanweisung direkt nach den Headern entspricht einer kritischen Sicherheitsrichtlinie:
PHP
Durch die Überprüfung, ob die globale Konstante ABSPATH nicht definiert ist, wird die Ausführung des Scripts gestoppt, falls ein Angreifer versucht, die Datei direkt über die physische URL aufzurufen (z. B. https://sitio.com/wp-content/plugins/plugin/archivo.php). Dies stellt sicher, dass der Code nur ausgeführt wird, wenn WordPress seinen Sicherheits-Stack initialisiert, die Konfigurationsoptionen geladen und die Umgebung authentifiziert hat.
Professionelle Verzeichnisaufteilung
Um die Entkopplung zwischen den Geschäftsregeln, der Präsentationslogik des Backends (Administrationsbereich) und der öffentlichen Ansicht (Frontend) zu gewährleisten, wird folgende Verzeichnisstruktur implementiert:
TEXT
Initialisierungsfluss durch die Bootstrap-Datei
Die Root-Datei enterprise-order-router.php darf keine Geschäftslogik oder direkte Datenmanipulation enthalten. Ihre einzige Aufgabe besteht darin, als initialer Orchestrierungspunkt oder Bootstrap zu fungieren.
Ein robustes und objektorientiertes technisches Initialisierungsmuster strukturiert sich wie folgt:
PHP
Dieses strukturelle Design gewährleistet eine vollständige Isolierung der Komponenten, sodass mehrere Entwickler an verschiedenen Sektionen des Plugins arbeiten können, ohne Versionskonflikte zu erzeugen. Zudem garantiert es einen vorhersehbaren und sauberen Ausführungspfad für die WordPress-Engine.
2.2 Hooks: Actions und Filters
Der WordPress-Core und sein Erweiterungssystem basieren auf einer ereignisgesteuerten Architektur (Event-Driven Architecture). Dieses System, allgemein bekannt als das Hooks-System, implementiert eine Variante des Observer- oder Mediator-Entwurfsmusters. Es ermöglicht Entwicklern, benutzerdefinierte Logik einzuschleusen oder das Standardverhalten des Cores, von Themes oder anderen Plugins zu ändern, ohne die Originaldateien des Quellcodes modifizieren zu müssen.
Das Verständnis des anatomischen und funktionalen Unterschieds zwischen den beiden verfügbaren Hook-Typen — Actions (Aktionen) und Filters (Filter) — ist der Grundpfeiler der Plugin-Entwicklung.
Der Interzeptionsfluss
In Textform lässt sich der Lebenszyklus eines Hooks wie folgt visualisieren:
TEXT
WordPress pflegt ein globales Register (instanziiert in der Klasse WP_Hook) aller Funktionen, die sich für ein bestimmtes Event „registriert“ haben. Wenn der Ausführungsfluss einen definierten Punkt erreicht, stoppt WordPress seinen nativen Prozess vorübergehend und führt nacheinander alle registrierten Callbacks unter Berücksichtigung ihrer Priorität aus.
Actions (Aktionen): Verhalten einbinden
Actions sind Ereignisse im Lebenszyklus von WordPress, bei denen du benutzerdefinierten Code ausführen kannst. Eine Action muss keinen Wert zurückgeben; ihr Zweck ist es, Nebeneffekte zu erzeugen (Daten in die Datenbank schreiben, eine E-Mail senden, HTML-Code ausgeben, ein Script einreihen usw.).
Der Core ruft eine Action mit der Funktion do_action( 'hook_name', $args ) auf.
Um diese Action in deinem Plugin abzufangen, nutzt du die Funktion add_action(). In einer objektorientierten Architektur (wie in der vorherigen Sektion gezeigt) strukturieren sich die Registrierung und der Callback wie folgt:
PHP
Filters (Filter): Daten mutieren
Im Gegensatz zu Actions fangen Filter Daten ab, bevor sie in der Datenbank gespeichert oder auf dem Bildschirm gerendert werden. Die unumstößliche Regel für einen Filter lautet: Er muss immer einen Wert zurückgeben, und zwar vom gleichen Datentyp, den er empfangen hat, nachdem (oder auch nicht) die notwendigen Transformationen angewendet wurden.
Der Core stellt eine Variable mit apply_filters( 'filter_name', $value_to_filter, $extra_args ) zur Filterung bereit.
Dein Plugin fängt diese Variable über add_filter() ab und modifiziert sie:
PHP
Prioritätenverwaltung und mehrere Parameter
Die Flexibilität des Hooks-Systems beruht auf zwei kritischen Parametern der Funktionen add_action und add_filter:
-
Priorität (Priority): Ein ganzzahliger Wert, der die Ausführungsreihenfolge bestimmt. Der Standardwert ist
10. Niedrigere Zahlen (z. B.1,5) werden zuerst ausgeführt, während höhere Zahlen (z. B.20,99) danach ausgeführt werden. Wenn zwei Callbacks dieselbe Priorität haben, werden sie in der Reihenfolge ausgeführt, in der sie während des PHP-Ladevorgangs registriert wurden.- Anwendungsfall: Wenn du die Änderung eines Drittanbieter-Plugins überschreiben musst, das seinen Filter bei Priorität 10 ausführt, solltest du deinen bei einer späteren Priorität einhängen, z. B. 20 oder 99.
-
Akzeptierte Argumente (Accepted Args): Standardmäßig erhält ein Callback nur den ersten Parameter, den
do_actionoderapply_filterssendet. Wenn der ursprüngliche Hook drei Variablen übergibt und du alle drei in deiner Methode benötigst, musst du explizit3als vierten Parameter bei deiner Registrierung angeben.
Entfernen und Aufheben von Hooks
Fortgeschrittene Entwicklung umfasst auch das Deaktivieren von Verhaltensweisen, die vom Core oder anderen Plugins eingeführt wurden. Dafür gibt es remove_action() und remove_filter().
Damit das Entfernen erfolgreich ist, muss die Löschfunktion ausgeführt werden, nachdem der Ziel-Hook registriert wurde, und die Signatur (Hook-Name, exakter Callback und Priorität) muss milimetergenau übereinstimmen.
PHP
Da anonyme Hooks (PHP-Closures oder Arrow-Functions) nicht gezielt entfernt werden können, raten die WordPress-Coding-Standards dringend davon ab, sie als Callbacks bei der Entwicklung von Plugins zu verwenden, die erweiterbar sein sollen.
2.3 Aktivierungsroutinen
Der Aktivierungsprozess eines Plugins ist ein kritischer Punkt in dessen Lebenszyklus. Er wird einzig und allein in dem Moment ausgeführt, in dem ein Administrator im Admin-Bereich auf den Link „Aktivieren“ klickt oder wenn der entsprechende Befehl über die Kommandozeile wp-cli (wp plugin activate) ausgeführt wird.
Der Hauptzweck dieser Phase besteht darin, die WordPress-Umgebung so vorzubereiten, dass das Plugin ab diesem Moment einwandfrei arbeiten kann. Sie sollte nicht für wiederkehrende Geschäftslogik genutzt werden, sondern ausschließlich für Bereitstellung, strukturelle Validierung und initiale Konfigurationen.
Ausführungsmechanik und der Aktivierungs-Hook
Um eine Aktivierungsfunktion zu registrieren, stellt WordPress die native funktion register_activation_hook() bereit. Ein häufiger Fehler in der Amateur-Entwicklung besteht darin, diese Funktion innerhalb eines Hooks wie init oder plugins_loaded aufzurufen. Aufgrund der Art und Weise, wie WordPress Dateien lädt, muss register_activation_hook() direkt im Hauptteil der Root-Datei (Bootstrap) des Plugins aufgerufen werden oder in einer Klasse, die sofort von dieser geladen wird.
TEXT
Implementierung eines strukturierten Aktivierers
Entsprechend der in den vorherigen Sektionen definierten objektorientierten Architektur delegieren wir die Verantwortung für die Aktivierung an eine spezialisierte Klasse (Enterprise_Order_Router_Activator), die von der täglichen Ausführungslogik isoliert ist.
In der Hauptdatei des Plugins (enterprise-order-router.php) verweist die Registrierung auf die statische Methode dieser Klasse:
PHP
Nachfolgend wird die Implementierung der Klasse beschrieben, die die Bereitstellung sicher und unter PHP 8.1+ verwaltet:
PHP
Die Gefahr von wahllosen Rewrite-Rules-Flushes
Wenn ein Plugin Custom Post Types (CPTs) oder benutzerdefinierte Routing-Strukturen einführt (wie in Teil 2 zu sehen), müssen die URL-Umschreibungsregeln von WordPress (rewrite rules) aktualisiert werden, damit der Webserver (Apache oder Nginx) die neuen Endpunkte erkennt und keinen 404-Fehler zurückgibt.
Die für diese Aktualisierung zuständige Funktion lautet flush_rewrite_rules(). Dieser Aufruf ist jedoch eine rechentechnisch sehr teure Operation: Sie erfordert den Neuaufbau des gesamten Routen-Arrays, die Auswertung von Permalink-Strukturen und das physische Schreiben in die Datei .htaccess bzw. das Aktualisieren von Optionen in der Datenbank.
Goldene Performance-Regel: Führe flush_rewrite_rules() niemals direkt im normalen Ladevorgang des Plugins (wie beim Hook init) aus. Dies darf ausschließlich verzögert bzw. bedingt geschehen.
Sicheres Muster für Permalink-Aktualisierungen (Deferred Flush)
Da CPTs formal während des Hooks init registriert werden (der nach Beendigung des Aktivierungsscripts ausgeführt wird), wird WordPress die Regeln zwar bereinigen, wenn du flush_rewrite_rules() direkt in der Methode activate() aufrufst, aber deinen neuen CPT noch nicht im Speicher haben und ihn daher ignorieren.
Um diesen zeitlichen Versatz elegant zu lösen, nutzen wir das in der vorherigen Klasse implementierte Muster mit Transients:
PHP
Dieser Ansatz stellt sicher, dass die Umgebung nur einmal aktualisiert wird, was die Performance des Servers schont und sicherstellt, dass die neuen URL-Strukturen des Plugins sofort vom WordPress-Core erkannt werden, ohne Ausnahmen auszulösen.
2.4 Deaktivierungs- und Bereinigungsroutinen
Eine verantwortungsvolle Softwarearchitektur verlangt, dass ein Plugin das WordPress-Ökosystem beim Entfernen in demselben Zustand hinterlässt, in dem es vorgefunden wurde. Bei der Plugin-Entwicklung gibt es eine kritische und oft missverstandene Unterscheidung zwischen dem Deaktivieren eines Plugins und dessen Deinstallieren (oder Löschen).
Um diese Aufteilung der Verantwortlichkeiten zu veranschaulichen, stellt sich der abschließende Lebenszyklus eines Plugins wie folgt dar:
TEXT
Die Deaktivierungsroutine: Temporäre Pause
Die Deaktivierung erfolgt, wenn der Administrator das Plugin suspendiert, die Dateien jedoch auf dem Server belässt. Die grundlegende Prämisse lautet hier: Keine Daten zerstören. Wenn der Benutzer das Plugin Stunden später reaktiviert, müssen seine Einstellungen, Protokolle und Bestellungen noch intakt sein.
Um diese Routine zu registrieren, wird register_deactivation_hook() in der Hauptdatei (enterprise-order-router.php) verwendet und verweist auf eine spezialisierte Klasse:
PHP
Ziel der Klasse Deactivator ist es, Hintergrundprozesse anzuhalten und temporäre Strukturen zu bereinigen.
PHP
Die Deinstallationsroutine: Tabula Rasa
Die Deinstallation erfolgt, wenn der Benutzer im Plugin-Menü auf „Löschen“ klickt. Dies ist the Moment, um das Prinzip der Tabula Rasa anzuwenden: Das Plugin muss absolut jede Spur seiner Existenz in der Datenbank löschen. Geschieht dies nicht, entsteht die gefürchtete „Datenbank-Vermüllung“ (database bloat), die die Performance der Website langfristig beeinträchtigt und den Datenschutz (wie die DSGVO) gefährden kann.
Warum uninstall.php statt eines Hooks verwendet werden sollte
Obwohl WordPress die Funktion register_uninstall_hook() anbietet, empfiehlt der Industriestandard und die offizielle Konvention dringend die Verwendung einer Datei namens uninstall.php im Root-Verzeichnis des Plugins.
Der Grund? uninstall.php wird in einem isolierten Prozess ausgeführt und verhindert das Laden deines gesamten Plugin-Codes. Zudem beugt sie Problemen mit Objektreferenzen oder Abhängigkeiten vor, die beim Löschen fehlschlagen könnten.
Sichere Implementierung der uninstall.php
Die Datei uninstall.php muss geschützt werden. Wenn es einem Angreifer gelingt, diese Datei direkt aufzurufen, könnte er ein massives Löschen der Datenbank auslösen. Der Schutz wird durch die Überprüfung der Konstante WP_UNINSTALL_PLUGIN realisiert, die WordPress nur intern während des legitimen Löschvorgangs definiert.
Nachfolgend ist die Struktur einer vollständigen Deinstallationsdatei dargestellt:
PHP
Die Integration gründlicher Deinstallationsroutinen ist nicht nur Best Practice im Software Engineering, sondern eine explizite Anforderung, wenn du deinen Code im offiziellen WordPress-Verzeichnis veröffentlichen möchtest (wie in Kapitel 16 behandelt) oder für Unternehmenskunden mit strengen Code-Audits entwickelst.
2.5 WordPress-Coding-Standards
Das WordPress-Ökosystem ist eines der größten Open-Source-Projekte der Welt, mit Tausenden von Mitwirkenden und einem riesigen Plugin-Markt. Um Konsistenz, Lesbarkeit und Wartbarkeit in diesem Maßstab zu gewährleisten, hat die Community die WordPress Coding Standards (WPCS) etabliert.
Wenn du von anderen PHP-Frameworks oder modernen PHP-Umgebungen kommst, wirst du feststellen, dass WordPress erheblich von den PSR-Standards (wie PSR-12 oder dem PHP Standard Recommendation Style) abweicht. In der professionellen Plugin-Entwicklung ist das Ignorieren dieser Konventionen ein Zeichen von Amateur-Code und führt garantiert zur Ablehnung, falls du im offiziellen Verzeichnis veröffentlichen willst oder ein Code-Audit ansteht.
Hauptunterschiede zu modernen Standards (PSR)
Während die PHP-Welt Spaces und die CamelCase-Formatierung standardisiert hat, behält WordPress sein eigenes stilistisches Erbe bei. Dies sind die unumstößlichen Regeln des WPCS:
1. Einrückung und Abstände (Tabs, keine Spaces)
WordPress verwendet echte Tabulatoren für die Einrückung von Codeblöcken, keine Leerzeichen. Leerzeichen werden nur für die horizontale Ausrichtung innerhalb einer Zeile (mid-line alignment) verwendet. Darüber hinaus verlangt WPCS einen „großzügigen“ Abstand innerhalb von Klammern, eckigen Klammern und Array-Definitionen.
PHP
2. Namenskonventionen (Snake Case)
Variablen, Funktionen und Methodennamen müssen vollständig in Kleinbuchstaben geschrieben und Wörter mit Unterstrichen (snake_case) getrennt werden. Klassen müssen großgeschriebene Wörter verwenden, die ebenfalls durch Unterstriche getrennt sind (Upper_Snake_Case).
PHP
3. Yoda-Bedingungen (Yoda Conditions)
Eine der umstrittensten, aber obligatorischen Regeln im WordPress-Core. Bei logischen Vergleichen muss die Konstante, das Literal oder die unveränderliche Variable immer auf der linken Seite des Vergleichs stehen.
Der Zweck besteht darin, stumme, fatale Fehler durch eine versehentliche Zuweisung (Schreiben von = statt ==) zu verhindern. Wenn du versuchst, einer Zahl oder einem Boolean einen Wert zuzuweisen, wirft PHP sofort einen Syntaxfehler und rettet dich in der Entwicklungszeit.
PHP
Dokumentation und Kommentarblöcke (PHPDoc)
Der Code ist erst vollständig, wenn er nach den WordPress-Richtlinien dokumentiert ist. Jeder Klasse, Eigenschaft, Funktion und Methode muss ein formatierter Kommentarblock (DocBlock) vorangestellt werden.
Dies hilft nicht nur anderen Entwicklern, sondern ist auch entscheidend für die automatische Generierung der Dokumentation und damit moderne IDEs intelligentes Autovervollständigen anbieten können.
PHP
Beachte die Verwendung von standardisierten Tags wie @since (um anzugeben, in welcher Version die Funktion eingeführt wurde), @param (Typ, Name und Beschreibung horizontal ausgerichtet) und @return.
Automatisierung: PHP_CodeSniffer
Es ist ineffizient, alle Regeln des WPCS auswendig zu lernen. Der Industriestandard besteht darin, diese Validierung zu automatisieren, indem du PHP_CodeSniffer (PHPCS) in deine lokale Entwicklungsumgebung und CI-Prozesse integrierst.
Um dies über Composer in deinem Projekt zu implementieren, installierst du das offizielle Regelpaket:
Bash
Eine Konfigurationsdatei phpcs.xml.dist im Root-Verzeichnis deines Plugins teilt dem Linter mit, welche Regeln anzuwenden sind. Die gängigsten Konfigurationen umfassen:
WordPress-Core: Überprüft Formatierung, Abstände und Struktur.WordPress-Docs: Fordert und validiert das Format von DocBlocks.WordPress-Extra: Schlägt Best Practices und Codierungsmuster vor.
Wenn du vendor/bin/phpcs in deinem Terminal ausführst, erhältst du einen detaillierten Bericht über Formatierungsfehler. Viele davon (wie Abstände oder Ausrichtung) können durch Ausführen von vendor/bin/phpcbf (PHP Code Beautifier and Fixer) automatisch behoben werden.
Harmonisierung von WPCS mit modernem PHP (8.1+)
Da dieses Buch von einer modernen Entwicklung (PHP 8.1+) ausgeht, gibt es leichte Reibungen zwischen dem Legacy-Code, den WordPress unterstützt, und den modernen Features von PHP. Der aktuelle Standard in der Enterprise-Plugin-Entwicklung besteht darin, das WPCS-Format (snake_case, Tabs, Yoda) zu respektieren, aber die strikte Typisierung von PHP zu nutzen.
PHP
Diese Kombination sorgt für Code, der sich wie nativer WordPress-Code liest und anfühlt, sich jedoch mit der Sicherheit und Robustheit der strikten Typisierung moderner Softwareentwicklung ausführen lässt.
Zusammenfassung des Kapitels
- Header und Struktur: Der Einstiegspunkt eines Plugins ist ein standardisierter Kommentarblock. Eine professionelle Architektur erfordert die Aufteilung des Codes in logische Verzeichnisse (
admin,public,includes) und das Blockieren von Direktzugriffen durch Prüfen der KonstanteABSPATH. - Hooks (Actions und Filters): Sie sind das Rückgrat der Erweiterbarkeit in WordPress. Actions (
add_action) ermöglichen das Einhängen von sekundärer Logik ohne Rückgabewerte. Filter (add_filter) erlauben das Abfangen und Mutieren von Variablen und erfordern stets die Rückgabe der modifizierten Daten. - Aktivierung: Die Funktion
register_activation_hooksollte verwendet werden, um die Umgebung vorzubereiten (Abhängigkeiten validieren, initiale Optionen setzen, Datenbankstrukturen erstellen). Permalinks (flush_rewrite_rules) sollten verzögert und nicht direkt bereinigt werden. - Deaktivierung und Bereinigung: Die Deaktivierung pausiert Prozesse (wie WP-Cron), behält die Daten jedoch bei. Die Deinstallation, die über eine stumme
uninstall.phpausgeführt wird, muss eine strikte Tabula Rasa-Politik anwenden und Tabellen, Optionen, Netzwerkoptionen und Metadaten löschen, um Datenbank-Vermüllung zu vermeiden. - Coding-Standards: WordPress verwendet eigene Regeln (WPCS), die von PSR-Standards abweichen. Es ist obligatorisch, snake_case, echte Tabs zur Einrückung und Yoda-Bedingungen für sichere Vergleiche zu verwenden. Der gesamte Prozess sollte automatisch mit PHP_CodeSniffer auditiert werden.
© 2026 Esdocu. Inhalte unter MIT-Lizenz.
Diese Seite bearbeiten