Dokumentation der StringParser_BBCode-Klasse

4. Callback-Funktionen

4.1 Behandlungsarten, die Callback-Funktionen benötigen

Wie bei der Erläuterung zur Einbindung von BBCode bereits beschrieben ist, gibt es diverse Behandlungsarten, die Callback-Funktionen benötigen, um den BBCode zu verarbeiten. Diese sind:

Bei all diesen Behandlungsarten muss man der Methode addCode als dritten Parameter den Namen einer Funktion mitgeben, die diesen Code behandeln soll.

4.2 Aufbau der Callback-Funktionen

Alle Callback-Funktionen müssen wie folgt aufgebaut sein:

function name_der_funktion ($action, $attributes, $content, $params, &$node_object) {
  // tue etwas
}

Im Folgenden wird der Ablauf gezeigt, wann genau die Callback-Funktion bei einem BBCode aufgerufen wird:

  1. Es wird ein öffnender BBCode-Tag gefunden. Von diesem werden der Name und die Attribute extrahiert.
  2. Es wird geprüft, ob der BBCode überhaupt im aktuellen Kontext erlaubt ist. Wenn nicht, wird er ignoriert.
  3. Die Callback-Funktion für diesen BBCode wird mit dem Wert 'validate' für $action aufgerufen.
  4. Falls die Callback-Funktion false zurückgegeben hat, wird der BBCode ignoriert. Falls die Callback-Funktion true zurückgegeben hat, wird der BBCode in die Baumstruktur aufgenommen.
  5. Der Text wird weiterverarbeitet.

  6. Falls Revalidierung aktiviert ist wird bei auftreten des schließenden BBCode-Tags die Callback-Funktion mit dem Wert 'validate_again' für $action aufgerufen. Falls die Callback-Funktion false zurückgibt, gilt der Code als ungültig und alles ab dem öffnenden BBCode-Tag wird noch einmal verarbeitet.
  7. Nachdem der komplette Text verarbeitet wurde, wird die Baumstruktur in eine Zeichenkette zurückverwandelt.
  8. Im Verlauf dieses Prozesses wird die Callback-Funktion mit dem Wert 'output' für $action aufgerufen.
  9. Die Callback-Funktion muss nun eine Zeichenkette zurückgeben, die dann als Ersetzung für das komplette Element (inklusive Inhalt!) genutzt wird. Falls die Funktion in diesem Fall etwas anderes, als eine Zeichenkette zurückgibt, bricht der Parservorgang komplett ab, der BBCode konnte dann überhaupt nicht korrekt verarbeitet werden.

Die Parameter, die die Funktion erwarten muss, sind folgende:

$action
Entweder 'validate', 'validate_again' oder 'output'. 'validate' wird immer dann gesetzt, wenn der Code validiert werden soll, 'output' immer dann, wenn die Ausgabe erfolgen soll.
$attributes
Die Attribute, die in dem Start-Tag enthalten waren als assoziatives Array. $attributes['quelle'] enthält also den Inhalt des Attributes quelle.
$content
Der gesamte Inhalt des Elements zwischen dem Starttag und dem Endtag. Dieser Wert ist nur in zwei Fällen gesetzt: Bei $action == 'output', bei dem schon alle Parserfunktionen angewendet worden und bei einem Code der Behandlungsart usecontent oder usecontent?, bei der der Inhalt schon bei validate zur Verfügung steht. Allerdings ist bei diesen Behandlungsarten zu beachten, dass bei $action == 'validate' Parserfunktionen noch nicht auf den Inhalt angewendet wurden, bei $action == 'output' dagegen schon.
$params
Die Parameter, die beim addCode-Aufruf an die Klasse übergeben wurden, stehen der Funktion auch wieder zur Verfügung. Wofür diese Parameter genutzt werden, steht frei.
$node_object
Das Objekt vom Typ StringParser_BBCode_Node_Element, das alle Informationen über den aktuellen Knoten in der Baumstruktur enthält. Damit kann man beispielsweise auf Eltern- oder Kindknoten zugreifen. Warnung: Das Objekt dürfte nur für sehr seltsame Sonderfälle interessant sein. Eine Manipulation des Objekts kann zu unerwarteten Ergebnissen bis hin zu Endlosschleifen oder ähnlichem führen. Hinweis: Bei $action == 'validate' befindet sich der Baum noch im Aufbau und das Objekt besitzt noch keine Kindknoten.

4.3 Beispiel einer Callback-Funktion zum Ersetzen von Links

function do_bbcode_url ($action, $attributes, $content, $params, &$node_object) {
    // 1) der code wird validiert
    if ($action == 'validate') {
        // der Code wurde so angegeben: [url]http://.../[/url]
        if (!isset ($attributes['default'])) {
            // ist dies ein gültiger URL?
            return is_valid_url ($content);
        }
        // der Code wurde so angegeben: [url=http://.../]Text[/url]
        // ist dies ein gültiger URL
        return is_valid_url ($attributes['default']);
    }
    // 2) der code wird ausgegeben
    else {
        // der Code wurde so angegeben: [url]http://.../[/url]
        if (!isset ($attributes['default'])) {
            return '<a href="'.htmlspecialchars ($content).'">'.htmlspecialchars ($content).'</a>';
        }
        // der Code wurde so angegeben: [url=http://.../]Text[/url]
        return '<a href="'.htmlspecialchars ($attributes['default']).'">'.$content.'</a>';
    }
}

// ...

$bbcode->addCode ('url', 'usecontent?', 'do_bbcode_url', array ('usecontent_param' => 'default'),
                  'link', array ('block', 'inline'), array ('link'));

Das obige Beispiel setzt voraus, dass es eine Funktion is_valid_url gibt, die übeprüft, ob ein URL gültig ist, oder nicht, und dann entsprechend true oder false zurückgibt. Man könnte die Überprüfung auch bleiben lassen und $action == 'validate' immer mit return true; quittieren, allerdings ist dies nicht zu empfehlen, da sonst ja auch [url]dies://ist alles andere / als ein gültiger url[/url] ersetzt würde, was dann in alle Browsern zu Fehlermeldungen führt, wenn man diesem Link dann folgt.

Desweiteren wird im obigen Beispiel [url] als usecontent? definiert, damit man innerhalb des BBCodes noch normalen Text (als Link-Titel) haben kann, wenn der Code in der Form [url=http://.../] angegeben wurde, oder dass der Text innerhalb des BBCodes die URL darstellt ([url]http://.../[/url]). Je nachdem, ob das Attribut default gesetzt ist, unterscheidet die Funktion, ob es sich um die eine oder andere Form handelt.

4.4 Revalidierung beim Auftreten von schließenden Tags

Im Normalfall wird nur beim Auftreten des öffnenden Tags die Callback-Funktion mit $action == 'validate' aufgerufen. Man kann der Klasse jedoch mitteilen, dass sie beim Auftreten des schließenden Tags die Callback-Funktion noch einmal aufrufen soll - diesmal mit $action == 'validate_again'. Dazu ruft man die Methode setValidateAgain auf:

$bbcode->setValidateAgain(true);

Da bei usecontent (und im Falle, dass usecontent? oder callback_replace? sich wie usecontent verhalten sollen) die Callback-Funktion sowieso erst beim Auftreten des schließenden Tags aufgerufen wird, gilt dies in diesem Fall nicht.