Routing-Framework
=================

"Framework" ist eigentlich ein übertriebener Begriff für die eine, kleine
Klasse, die für AddOns eine API anbietet, um eigene URLs zu erzeugen.

Betrachten wir ein Beispiel: Wir haben einen Shop auf der Website. Dieser Shop
verwaltet seine Produkte und Kategorien in seinen eigenen Datenbank-Tabellen.
Alle im CMS nötigen Artikel liegen in der Kategorie "Shop" (Warenkorb,
Kategorieliste, Detailseite, ...).

Zwar kann realURL2 für diese Seiten einen direkten Link
erzeugen (``example.com/shop/detailseite.html``), aber Dinge wie die Produkt-
oder Kategorie-ID aus dem Shop muss man dann weiterhin über GET-Parameter
anfügen (``example.com/shop/detailseite.html?product_id=12``).

Zu diesem Zweck kann über die API dafür gesorgt werden, dass auch für
Nicht-Sally-Inhalte schöne URLs erzeugt werden. Dazu legt man im Code einen
UrlGenerator an und bindet an diesen dann einzelne Parameter. Diese steuern, wie
die URL nachher aussehen wird und auf welche Daten das Script später zugreifen
kann.

In diesem Beispiel wollen wir einen Link zu einer Produkt-Detailseite erzeugen.
Das dazu zuständige Modul erwartet das anzuzeigende Produkt als GET-Parameter
namens ``product_id``.

.. sourcecode:: php

  <?
  // Generator anlegen
  $generator = new WV24_Generator('produkte/:name.html');

  // Nun können an diese Route einzelne Parameter gebunden werden.
  $generator->bind('name', 'Mein tolles Produkt!');

  // Routen werden in Namespaces gruppiert. Namespaces sollten dem Namensschema
  // "addon.namespace" folgen, daher verwenden wir...
  $generator->setNamespace('shop.products');

  // Innerhalb eines Namespaces muss jede URL einen eindeutigen Identifier
  // haben. Hier können IDs wie die Produkt-ID aus dem Shop kodiert werden.
  $generator->setIdent($productID.'_'.$clang);

  // Welcher Artikel soll beim Aufruf dieser URL angezeigt werden?
  $generator->setArticle(10);

  // ... und welche Sprache?
  $generator->setClang($clang);

  // Jetzt kann die URL erzeugt werden. Ergebnis ist ein _WV24_URL-Objekt.
  // Die URL wird dabei sofort in der Datenbank hinterlegt und ist damit "live".
  $url = $generator->generate();

Die erzeugte URL lautet nun **/shop/produkte/mein-tolles-produkt.html**. Wird
diese URL aufgerufen, wird realURL2 den Artikel mit der ID 10 initialisieren und
ihm dann die Kontrolle übergeben. Nur haben wir noch ein Problem: Die Produkt-ID
fehlt, denn die wollten wir ja gerade aus den URLs entfernen. Dafür kann man bei
``bind()`` beliebig viele weitere Parameter angeben, die alle in der Route
ersetzt werden und auf Wunsch beim Request der erzeugten URL wiederhergestellt
werden.

Das korrigierte Beispiel sieht dann wie folgt aus:

.. sourcecode:: php

  <?
  // Generator anlegen
  $generator = new WV24_Generator('produkte/:name.html');

  // Nun können an diese Route einzelne Parameter gebunden werden.
  $generator->bind('name', 'Mein tolles Produkt!');
  $generator->bind('product_id', $productID, true); // true = stelle diesen Wert bitte später wieder her

  $generator->setNamespace('shop.products');
  $generator->setIdent($productID.'_'.$clang);
  $generator->setArticle(10);
  $generator->setClang($clang);

  $url = $generator->generate();

In diesem Fall wird die exakt gleiche URL erzeugt, aber beim Request neben
``article_id`` und ``clang`` (den beiden Standard-Parametern von SallyCMS) auch
noch ``product_id`` wiederhergestellt.

Es ist auch möglich, Routen zu erstellen, die nicht von einem bestimmten
Ziel-Artikel abhängen. Dazu macht man sie im Konstruktor von WV24_Route einfach
absolut:

.. sourcecode:: php

  <?
  // Generator anlegen
  $generator = new WV24_Generator('/produkte/:name.html');

Nun wird eine URL wie **/produkte/mein-tolles-produkt.html** erzeugt.

Soll eine vollständige URL als Basis verwendet werden, so kann auch das
Hinzufügen der Standard-Domain komplett abgeschaltet werden.

.. sourcecode:: php

  <?
  // Generator anlegen
  $generator = new WV24_Generator(':mybase/:name.html');
  $generator->setIsFullUrl();

  // 4. Parameter = raw => Wert 1:1 in die URL übernehmen anstatt Sonderzeichen
  // zu entfernen.
  $generator->bind('mybase', 'http://example.com', false, true);
  $generator->bind('name', 'foo');

  $url = $generator->generate();
  print $url->getRawURL(); // http://example.com/foo.html

.. warning::

  Alle Parameter, die wiederhergestellt werden sollen, werden
  JSON-kodiert in der Datenbank zu jeder URL abgespeichert. Damit ist es nicht
  möglich, Objekte oder Ressourcen (DB-Verbindungen, File-Handles) abzuspeichern.
  Es wäre gut, wenn man sich an dieser Stelle auf skalare Werte und höchstens
  Arrays beschränkt. Das entsprechende Feld in der DB-Tabelle kann **maximal 4096
  Zeichen** aufnehmen (inkl. JSON-Overhead).

Updates
-------

Generell ist jede Komponente selber dafür verantwortlich, die URLs aktuell zu
halten. realURL2 wird niemals dazu "auffordern", URLs neu zu erzeugen. Werden
also beispielsweise Artikelinformationen in einer URL abgelegt, so müsste der
Erzeuger auch auf die entsprechenden Artikel-Events von Sally lauschen, um die
URL bei Bedarf neu zu erzeugen.
