Datentypen-API
==============

Ein Datentyp ist eine Klasse, die ``WV_IDatatype`` implementiert und eine Reihe
von Methoden anbietet, um sich selbst zu rendern. Dabei muss jeder Datentyp eine
systemweit eindeutig Key haben und in über die Konfiguration angemeldet werden,
um allen AddOns zur Verfügung zu stehen.

Im Prinzip stellen Datentypen eine Möglichkeit dar, Formularelemente
konfigurierbar zu machen. In der Regel rendert ein Datentyp genau ein Element
im Formular.

Die Developer Utils liefern einige Datentypen bereits mit:

* ``StringLine`` (einzeiliger Text)
* ``StringText`` (mehrzeiliger Text)
* ``Select`` (Auswahlweld / Checkbox-Gruppe / Radio-Gruppe)
* ``Boolean`` (Checkbox)
* ``Link``
* ``LinkList``
* ``Media``
* ``MediaList``
* ``DateTime``

Datentypen rendern sich seit v2.0 immer als Teile eines ``sly_Form``-Objekts und
integrieren sich so schnell und einfach in andere Formulare.

Datentyp anmelden
-----------------

Alle Datentypen stehen in der Konfiguration im Key ``developer_utils/datatypes``.
Die mitgelieferten Datentypen stehen in der :file:`globals.yml` der Developer
Utils.

Andere AddOns (oder das Frontend, in :file:`develop/config`) können ihre
Datentypen einfach hinzufügen:

.. sourcecode:: yaml

  developer_utils:
    datatypes:
      mydatatype: MyDatatypeClass

Formulare erzeugen
------------------

Jeder Datentyp kann sich in Form eines Fomrularelements darstellen. Damit gibt
es zwei wichtige Methoden: Formular anzeigen und Formular auswerten.

``renderForm(sly_Form $form, WV_IProperty $property, $value)``
  Diese Methode rendert das Formular, das der Benutzer später zur Eingabe der
  Daten sehen soll. Das Formularelement wird in das ``$form``-Objekt eingefügt.
  Aus dem ``$property`` können alle notwendigen Infos zur Anzeige des aktuellen
  Wertes ``$value`` (noch der serialisierte Roh-Wert aus der Datenbank)
  extrahiert werden.

``serializeForm(WV_IProperty $property)``
  Diese Methode ermittelt den Wert des Properties nach dem Abschicken des
  Formulars und gibt ihn als String (serialisiert) zurück.

Code-Beispiele
--------------

Da die Ansteuerung der Datentypen recht komplex werden kann, hier ein paar
einfache Beispiele:

.. sourcecode:: php

  <?
  // array(key: Class, key: Class, ...)
  $datatypes = WV_Datatype::getDatatypes();

  // Gibt den Klassennamen zurück
  $className = WV_Datatype::getClass('stringline');

  // Prüft, ob ein Datentyp existiert
  WV_Datatype::exists('datetime');

  // Eine Methode eines Datentyps ausführen
  WV_Datatype::call('datetime', 'myMethod', array('param1', 'param2'));

Für Properties (die primären Use-Cases für Datentypen) sind einige dieser
Methoden bereits gewrappt, sodass statt einem Call über ``WV_Datatype`` auch
direkt eine Proxy-Methode einer Property aufgerufen werden.

.. sourcecode:: php

  <?
  WV_Datatype::call('mydatatype', 'renderForm', array());

  // entspricht

  $property->renderForm(array());

  // Allgemein gilt
  WV_Datatype::call($property->getDatatype(), 'method') === $property->datatypeCall('method')

Schauen wir uns nun an, wie man die Formulare erzeugt:

Formular erzeugen
^^^^^^^^^^^^^^^^^

Hier können wir eine Sache beobachten, die bisher noch nicht angesprochen wurde:
Mehrsprachigkeit. Der Wert, der an ``renderForm()`` übergeben wird, wird extra
nochmal in ein Array verpackt. Warum? Nun, die Datentypen sind darauf
ausgerichtet, Mehrsprachigkeit nativ zu unterstützen. Daher erwarten sie den
Wert der Property als Array ``(sprachID => Wert, sprachID => Wert)``.
Theoretisch könnten die Datentypen natürlich selber das array() erzeugen, wenn
sie ein einzelnes Literal als Wert erhalten. Leider würde das zu
Mehrdeutigkeiten im Select-Datentyp führen, weswegen wir uns für diese Variante
entschieden haben.

.. note::

  *Merksatz:* ``renderForm()`` immer mit einer Werteliste aufrufen.

.. sourcecode:: php

  <?
  $form     = new sly_Form('index.php', 'POST', 'Daten bearbeiten');
  $property = getPropertyObjectToDisplay(); // Do whatever you like to get your data.
  $value    = getValueForThisObject();      // dito

  $property->renderForm($form, array(1 => $value)));

  $form->render();

Formular abspeichern
^^^^^^^^^^^^^^^^^^^^

Das Serialisieren des Frontends kann kompliziert werden: Wurde Mehrsprachigkeit
genutzt? Wenn ja, wurden auch mehrere Werte angegeben? Wie heißen die ganzen
automatisch generierten Felder in den einzelnen Sprachen?

Um den Entwickler von diesen Fragen zu befreien, gibt es ``serializeForm()``:

.. sourcecode:: php

  <?
  $property = getPropertyObjectToDisplay(); // Do whatever you like to get your data.
  $values   = $property->serializeForm();

Der Inhalt von ``$values`` hängt nun von der Mehrsprachigkeit der Property ab:
Einsprachige Properties geben direkt den einzelnen Wert (serialisiert) zurück.
Mehrsprachige Properties werden ein assoziatives Array zurückgeben, wobei jeder
Wert der serialisierte Wert aus der jeweiligen Sprache ist. Wenn der Benutzer im
Frontend nur einen einzelnen Wert für alle Sprachen angibt, wird dieser einzelne
Wert in jedes Array-Element kopiert (sodass das Script davon nichts mitbekommt).
``sly_Form`` kümmert sich darum, zu erkennen, dass es sich um x gleiche Werte
handelt, und wird dann automatisch das richtige Formularelement anzeigen.
