User Tools

Site Tools


projects:bbcode:start

BBcode-System

Motivation

Das Clansphere CMS hatte ein einfaches BBcode System, das lange Zeit erfolgreich seine Dienste geleistet hat. Doch inzwischen sind sowohl dem Team als auch der Community Mängel aufgefallen, die es zu beheben galt:

  • Die Erweiterung des BBcode Systems war nicht ohne Weiteres möglich und konnte nur über einen Eingriff in den Kern des Systems erfolgen
  • Das gleichzeitige Verwenden mehrerer BBcode Erweiterungen ließ sich nur durch Zusammenfriemeln verschiedener Bruchteile erreichen
  • Das Aktualisieren des Kerns hatte Probleme mit den Erweiterungen zur Folge

Diese Probleme haben Laszlo im Namen des Clansphere Teams dazu veranlasst, das BBcode System neu zu entwickeln. Objektorientiert und leicht erweiterbar sollte es sein.

Das erste Konzept hat er noch alleine entworfen und sehr einfach gehalten, doch nachdem Steffen und ich noch einige Ideen mit eingebracht haben, haben Laszlo und ich uns dazu entschlossen, zusammen noch mal neu anzufangen.

Insgesamt haben wir fast vier Mal komplett neu begonnen und dabei immer wieder neue Einfälle gehabt und Erfahrungen gesammelt. Diesen Entwicklungsprozess durch die vier verschiedenen Versionen möchten wir euch hier vorstellen. Wen nur das fertige BBcode System interessiert, kann gleich zu dem fertigen Quellcode oder zu der Anwendung gehen. Alle anderen starten bei…

Entwurf I

Laszlo schwebte vor, eine zentrale statische Klasse zum Verwalten der BBcodes und der BBcode Patterns (ein Pattern ist ein einzelnes Suchmuster, das ersetzt werden soll) zu erstellen. Die Patterns werden dabei bei dieser zentralen Klasse registriert, so dass auch Patterns von ausserhalb des Kerns eingefügt werden konnten.

Nett dabei war die Möglichkeit, verschiedene Replace-Typen angeben zu können. Neben simplen Funktionsaufrufen standen auch ausführbarer Code und im Besonderen auch anonyme Funktionen zur Auswahl.

Quellcode von Entwurf I

Entwurf II

Aus einer Diskussion von Steffen und mir kam hervor, dass bei diesem Entwurf der objektorientierte Ansatz überhaupt nicht ausgereizt wurde, da die Klasse nur als Namespace diente, statt Objekte zu instanzieren.

Also hat Laszlo die register_pattern()-Methode in einen Konstruktor umgebaut. Dadurch wurden auch die Array-Konstruktionen um einiges vereinfacht. Nun gab es für jedes Suchmuster eine eigene Instanz. Die verschiedenen Instanzen wurden in einem statischen Array gesammelt, in dem man sie nun auch gewisser Maßen sortieren konnte, indem man beim Instanzieren einen zusätzlichen Parameter übergab, um zu bestimmen, ob das Suchmuster am Anfang oder Ende angewendet werden sollte.

Ein zusätzliches Feature, was durch diesen neuen Ansatz ermöglicht wurde, war die clear()-Methode, mit der es möglich war, sämtliche BBcode-Syntax aus einer Zeichenkette zu entfernen, um einen unformatierten Text zu erhalten.

Quellcode von Entwurf II

Der Ansatz, für jedes Suchmuster eine Instanz zu erstellen, hat gut funktioniert. Allerdings waren wir nicht damit zufrieden, dass die Patterns automatisch in ein klasseninternes Array abgelegt werden, da die Situation eintreten kann, dass man ein Suchmuster anlegen und auf eine Zeichenkette anwenden möchte, ohne es global für den BBcode zu registrieren. Es folgte..

Entwurf III

Also wollten wir die statischen Methoden von den Instanz-Methoden trennen. Zuerst haben wir die vorherige BBcode-Klasse in “Pattern” umbenannt und alle statischen Methoden und Eigenschaften entfernt. Als nächstes brauchten wir eine neue Klasse für die statischen Methoden.

Wir hielten es für am Sinnvollsten, wenn jedes BBcode-Addon eine eigene Klasse hat, die die statischen Methoden und Eigenschaften von einer BBcode-Klasse erbt. So könnte man verschiedene Addons getrennt voneinander benutzen und erweitern. Die von Clansphere mitgebrachten Suchmuster wären damit auch in einer Klasse gruppiert. Da PHP aber erst ab Version 5.3 statische Vererbung genügend unterstützt, mussten wir auf die Vererbung verzichten und haben vorerst jede Addon-Klasse die statischen Funktionen selbst (und damit mehrfach) definieren lassen.

Als nächstes haben wir in diesem Entwurf der Pattern-Klasse zwei neue Eingeschaften geschenkt: Regex und Level. Mit dem Setzen der Regex-Eigenschaft konnte man nun festlegen, ob das Suchmuster als regulärer Ausdruck oder als einfacher String behandelt werden sollte. Die Level-Eigenschaft war nötig um steuern zu können, wann ein Suchmuster angewendet werden soll. Beim Anwenden des BBcodes auf eine Zeichenkette wurden nur die Suchmuster benutzt, die höchstens das Level hatten, das beim Aufruf der convert-Methode festgelegt wurde.

Die dritte Neuerung bei diesem Entwurf war die Abtrennung des Secure-Systems, welches HTML-Syntax maskiert, vom Rest des BBcodes.

Quellcode von Entwurf III

Somit haben wir es geschafft, das BBcode System leicht erweiterbar zu machen und haben den OOP-Ansatz bei den Patterns gut umgesetzt. Der Kern ist sauber von den eigentlichen Funktionen getrennt und BBcode Addons lassen sich auch parallel zu den Clansphere BBcodes verwenden, so dass Addons auch Patterns hinzufügen können, ohne dass diese gleich überall eingesetzt werden und dennoch über das Addon ansteuerbar sind. Zudem sind die Funktionen gut in den jeweiligen Klassen gekapselt.

Allerdings ist das System noch nicht sehr flexibel. Unterschiedliche BBcodes können nur durch Aufrufen verschiedener statischer Klassen erreicht werden. Einzelne Muster lassen sich noch nicht ansteuern. Diese überlegungen führten uns zur…

Lösung

Wir fanden es viel logischer, einzelne BBcode-Systeme als Objekte zu instanzieren, als statische Klassen zu verwenden. Dadurch kann der jeweilige BBcode überall genau spezifiziert werden.

Deshalb haben wir beschlossen, dass sowohl Clansphere als auch die Addons ihre Patterns nur dem BBcode-System zur Verfügung stellen, ohne deren Nutzung regulieren zu können. An den Stellen, an denen der BBcode verwendet wird, kann man somit die einzelnen Patterns auswählen, die an genau dieser Stelle verwendet werden. Dadurch hat man die maximale Flexibilität erreicht.

Allerdings ist auch klar, dass es so jedes Mal ein Akt wäre, das BBcode-System zu verwenden, weil erst alle Patterns aufgelistet werden müssten, die unterstützt werden sollen.

Ein weiteres Problem ist die Dynamik. Zwar können so die Patterns überall manuell ausgewählt werden, allerdings möchte man das oft gar nicht so genau, da sonst nachträglich hinzugefügte Patterns (zum Beispiel durch Addons) nirgends verwendet werden würden, wenn man das Pattern nicht manuell an allen Stellen hinzufügt.

Aus diesen Gründen haben wir uns dazu entschlossen, Pattern-Gruppen zu erstellen.

Die Patterns werden bei der Anmeldung nun also verschiedenen (auch mehreren) Gruppen zugeordnet. Beim Instanzieren eines BBcodes gibt man die Gruppe an, dessen Patterns verwendet werden sollen. Dabei gibt man aber keineswegs die Flexibilität auf. Man entscheidet sich nicht für eine fixe Gruppe, sondern die Gruppe bestimmt nur, welche Patterns anfänglich verwendet werden. Der BBcode kann genauso wie ohne Gruppen die Patterns einzeln hinzufügen und entfernen.

Der fertige Quellcode

Ergebnis

Wir haben es geschafft, ein BBcode System zu entwickeln, das

  • durch den zentralen Zugriffspunkt Bbcode::register von überall aus leicht erweiterbar ist
  • bei jeder Verwendung bis ins Detail konfigurierbar ist
  • es ermöglicht, jedes Pattern einzeln und komfortabel (mit Namen) anzusprechen
  • trotz der Konfigurierbarkeit auch nachträgliches Erweitern gut unterstützt
  • sich trotz der Komplexität auch mal schnell und unkompliziert verwenden lässt, weil es auf die Gruppen zugreift

Anwendung

projects/bbcode/start.txt · Last modified: 14:39 02.02.2012 (external edit)