WordPress-Plugin entwickeln und veröffentlichen: unser Workflow bei onOffice
Im Jahr 2015 wurde entschieden, unsere CMS um WordPress zu erweitern und Jakob Jungmann bekam die Aufgabe, das Plugin für WordPress zu erstellen. In diesem Artikel wird der Entwicklungsprozess unseres WordPress-Plugins beschrieben.
Das Plugin onOffice for WP-Websites wird klassenbasiert entwickelt, mit PHPUnit getestet und vor jedem Release manuell durch die QA geprüft. Nach erfolgreichen Tests startet ein Git-Tag den Build und die Veröffentlichung im WordPress.org-SVN. Der Artikel beschreibt diesen Entwicklungsprozess und die wichtigsten Erfahrungen aus Review, Release und Übersetzung.

Inhaltsverzeichnis
- Vom ersten Prototyp zur Backend-GUI
- Workflow in unserem Plugin
- Die Veröffentlichung
- Die Übersetzung
- Hinweise zur Plugin-Veröffentlichung
Key Takeaways
- Das onOffice WordPress-Plugin verbindet eine klassenbasierte Architektur mit PHP-DI und PHPUnit, um die eigene Logik möglichst isoliert testbar zu machen.
- Jeder Feature- oder Bugfix-Branch wird vor dem Merge zusätzlich durch die QA in der Release-Konfiguration geprüft.
- Ein Git-Tag stößt den automatisierten Build und die Veröffentlichung des fertigen Plugin-Pakets im WordPress.org-SVN an.
- Für WordPress.org muss das Release-Paket vollständig und direkt installierbar sein; nicht benötigte Entwicklungsdateien werden daraus entfernt.
- Plugin-Slug und Text-Domain müssen übereinstimmen, während Eingaben validiert beziehungsweise bereinigt und Ausgaben kontextgerecht escaped werden.
Vom ersten Prototyp zur Backend-GUI
Im Jahr 2015 wurde entschieden, unsere CMS um WordPress zu erweitern und ich bekam die Aufgabe, das Plugin für WordPress zu erstellen. Die Entwicklung wurde anfangs stark vorangetrieben, funktional orientiert, jedoch ohne Backend-GUI. Alle Einstellungen waren in Konfigurationsdateien untergebracht, was oft hart, frustrierend und sehr unhandlich für die Webdesigner war.
Die Entwicklung des Backend-GUI wurde im Oktober 2017 gestartet. Im Commit-Graph sieht man ab dem Zeitpunkt deutlich mehr Commits.
Mein erster Eindruck vom WordPress-Basissystem war negativ:
- WordPress enthält viel prozedurales PHP, gekoppelt an ein Event-System.
- Es gibt Hürden wie globale Variablen oder Zustände.
- Logik und Daten sind nicht gut getrennt, und der Quellcode steht teilweise in Dateien, die viele Funktionen, Klassen oder Darstellungslogik enthalten und per include geladen werden.
Man findet zwar viele anfängerfreundliche Tutorials, die den Einstieg erleichtern. Für erweiterte Themen muss allerdings viel Quellcode studiert werden, weil die Dokumentationen hier nicht weiterhelfen.
Workflow in unserem Plugin
onOffice arbeitet bei anderen PHP-Softwareprodukten mit einem DI-Framework. Auch beim WordPress-Plugin wurde dieser Ansatz aufgenommen. Zum Einsatz kommt dabei nicht das hauseigene DI, sondern PHP-DI.
In Klassen soll möglichst viel Logik liegen, und alle Klassen sollen testbar sein. Um dieses Ziel zu erreichen, müssen große Teile des WordPress-Codes in Klassen gewrappt werden, da eine gute Testbarkeit sonst kaum zu erreichen ist. Die Unit-Tests erstellen wir mit PHPUnit.
Features und Bugfixes werden in einem neuen Branch erstellt, der von der QA-Abteilung vor dem Merge in den master manuell getestet wird. Das QA-Team testet dabei die Release-Konfiguration.
Ein Push eines neuen Git-Tags triggert automatisch eine Veröffentlichung ins WP-SVN. Ein Tag wird erstellt, sobald Unit-Tests und manuelle Tests erfolgreich waren und der Feature- oder Bugfix-Branch in den master gemerged worden ist.
Die Veröffentlichung
Bei der Veröffentlichung sind wir auf einige Dinge hingewiesen worden, die wahrscheinlich viele Plugin-Entwickler betreffen. Folgende Punkte wurden erwähnt:
1. WordPress-Core-Dateien nicht direkt inkludieren
Das betrifft unter anderem wp-config.php, wp-blog-header.php und wp-load.php, da die Dateisystemstruktur je nach Installation und deren Einstellungen variieren kann.
Falls also neue Einstiegspunkte gebraucht werden, sollten dafür die vorgesehenen WordPress-Schnittstellen verwendet werden, zum Beispiel Hooks, Rewrite-Regeln, REST-Routen oder WordPress-AJAX. PHP-Dateien des Plugins sollten nicht von außen als eigene Einstiegspunkte aufgerufen werden.
2. Eingaben validieren und Ausgaben escapen
WordPress stellt viele Funktionen für Validierung, Sanitizing und Escaping bereit. Zugriffe auf Superglobale wie $_POST, $_GET oder $_REQUEST sollten auf die tatsächlich benötigten Werte beschränkt werden. Eingaben werden möglichst früh entschärft beziehungsweise validiert; Ausgaben werden passend zu ihrem Kontext möglichst spät escaped. Auch Berechtigungsprüfungen und Nonces müssen je nach Anwendungsfall berücksichtigt werden.
Dokumentation:
- https://developer.wordpress.org/plugins/security/securing-input/
- https://developer.wordpress.org/plugins/security/securing-output/
Optimierung des Plugins
Ende September 2019 haben wir dann unsere verbesserte Version eingereicht. Wir hatten den Code als Link zum GitHub-Repository angegeben und erklärt, wie man ihn lauffähig macht: Das Repository musste rekursiv geklont und die Composer-Abhängigkeiten mussten installiert werden. Wir wurden darauf hingewiesen, dass für die Einreichung ein vollständiges, direkt installierbares Plugin-Paket erforderlich ist. Nicht für den Betrieb benötigte Entwicklungsverzeichnisse wie tests/ sollten aus diesem Release-Paket entfernt werden.
Daraufhin haben wir ein Release-Script erstellt, das den Composer-Schritt, den Eintrag der Versionsnummer und der stabilen Version in der readme.txt für uns übernimmt, damit uns dort Fehler durch händische Arbeit erspart bleiben. Das Script entfernt darüber hinaus das tests/-Verzeichnis mit den Unit-Tests vor der Veröffentlichung.
Nachdem wir unsere letzten Nachbesserungen eingereicht haben, wurde 12 Stunden später unser Plugin akzeptiert und ist seitdem im WordPress.org Plugin Directory verfügbar. Die zwölf Stunden beschreiben unseren damaligen Einzelfall und sind keine allgemeine Bearbeitungszeit für Plugin-Reviews.


Die Übersetzung
WordPress stellt eigene Internationalisierungsfunktionen bereit, die auf gettext-Konzepten basieren. Nach der Veröffentlichung werden die Übersetzungen auf der WordPress Translations-Plattform verwaltet. Committer haben nach dem Einreichen in den Plugin-Store zunächst keinen Einfluss auf die Übersetzung. Unsere wurde angepasst, ohne dass wir eingreifen konnten. Wenn man diese wieder Übersetzen möchte, muss man sich per Chat auf der translate.wordpress.org-Plattform melden. Wer Interesse hat, Übersetzer für die deutsche Sprache zu werden, findet alle Infos hier.
Positiv ist, dass Übersetzungen nach klaren Regeln erfolgen und potenzielle Übersetzer zunächst gefragt werden, ob sie die Sprache, für die sie sich bewerben, auch tatsächlich fließend sprechen.
Man kann sich für verschiedene Übersetzerrollen bewerben. PTE ist ein projektspezifischer Übersetzer für eine Sprache, während ein GTE ein globaler Übersetzer für eine Sprache ist, ein CLPTE ist hingehen ein Cross-Locale Project Translation Editor.
Wichtig: Wenn die Übersetzungen auf translate.wordpress.org verwaltet werden, ändert sich gegebenenfalls auch die Translation Domain! Sie ist dann der Plugin Slug.
Hinweise zur Plugin-Veröffentlichung
WordPress ist ein historisch gewachsenes, abwärts-kompatibel gehaltenes System. Dafür ein neues Plugin mit modernen Programmiertechniken (DI/UnitTests) zu erstellen ist gar nicht so einfach. Dennoch ist es möglich und zahlt sich bei der Wartung aus. In der anfangs anstehenden Review kommen immer wieder neue Punkte hinzu, auf die man sich einstellen sollte. Man hat aber so viel Zeit, wie man möchte, um die Punkte zu bearbeiten. Man sollte allerdings nicht länger als sechs Monate mit der Antwort auf eine Mail warten, da der Antrag ansonsten verworfen wird.
Wenn das Plugin akzeptiert wurde, muss sich der Entwickler sofort um eine Position als PTE bemühen, um die Übersetzungen bearbeiten zu können. Achtet aber bitte vorher darauf, die richtige Text-Domain zu wählen.
Es ist eine gute Idee ein Build– und Commit-Script zu erstellen, das das Changelog auf einen Eintrag für die neue Version prüft, Composer-Abhängigkeiten installiert, den aktuellen git-Tag ins Version-Feld der Plugin-Datei einträgt und in der readme.txt die aktuelle Version als stable markiert. Darüber hinaus entfernt es das tests-Verzeichnis, commitet das Plugin mit allen Composer-Abhängigkeiten ins WP-SVN und erstellt einen stable-Tag im SVN. So erspart sich der Entwickler Fehler, die sich beim Verpacken des Releases einschleichen können.
Kurz zusammengefasst
- WordPress-Abhängigkeiten zu kapseln verbessert die isolierte Testbarkeit der eigenen Logik.
- Unit-Tests und eine manuelle Prüfung der Release-Konfiguration ergänzen sich.
- WordPress.org erwartet ein vollständiges, direkt installierbares Plugin-Paket.
- Eingaben müssen validiert beziehungsweise bereinigt und Ausgaben kontextgerecht escaped werden.
- Die Text-Domain eines WordPress.org-Plugins muss seinem Plugin-Slug entsprechen.
- Ein automatisierter Build hält Version, readme.txt, Abhängigkeiten und SVN-Tag konsistent.
Lerne unsere Softwareentwicklung kennen
Neugierig geworden, was unsere Entwickler:innen täglich alles so erarbeiten? Dann schau dich doch gerne auf unserer Team-Seite um und schau, ob du zu uns passt!


FAQ zum Entwicklungs- und Veröffentlichungsprozess
Das onOffice WordPress-Plugin wird klassenbasiert entwickelt. WordPress-Abhängigkeiten werden möglichst gekapselt, damit sich die eigene Logik mit PHPUnit testen lässt. Vor dem Merge prüft die QA jeden Feature- oder Bugfix-Branch zusätzlich manuell in der Release-Konfiguration.
Nach erfolgreichen Unit-Tests und manuellen Tests wird der Entwicklungs-Branch in den master gemerged und ein Git-Tag erstellt. Dieser Tag stößt den automatisierten Build an. Das fertige Plugin-Paket wird anschließend in das WordPress.org-SVN übertragen und dort als Release getaggt.
Ja. Das bei WordPress.org eingereichte beziehungsweise veröffentlichte Plugin-Paket muss jedoch vollständig und direkt installierbar sein. Deshalb installiert das onOffice Release-Script die für den Betrieb benötigten Composer-Abhängigkeiten bereits beim Erstellen des Pakets.
Nicht für den Betrieb benötigte Entwicklungsdateien und Unit-Tests sollten aus dem Distributionspaket entfernt werden. Beim onOffice Plugin übernimmt das Release-Script diesen Schritt automatisch, während Tests und Entwicklungsdateien weiterhin im öffentlichen GitHub-Repository verfügbar bleiben.
Ein Plugin sollte nur die tatsächlich benötigten Eingabewerte verarbeiten. Diese werden möglichst früh validiert beziehungsweise bereinigt; Ausgaben werden passend zum jeweiligen Kontext möglichst spät escaped. Abhängig von der Aktion sind außerdem Berechtigungsprüfungen und Nonces erforderlich.
Die Text-Domain muss dem Plugin-Slug entsprechen. Bei onOffice for WP-Websites ist daher eine von Beginn an konsistente Benennung in Plugin-Code, Plugin-Header und Übersetzungsplattform wichtig.
Git wird für die laufende Entwicklung, Branches, Tests und Versions-Tags verwendet. Das WordPress.org-SVN dient dagegen als Release-Repository für die Versionen, die über das offizielle Plugin Directory verteilt werden.



