Dokumentation
=============
Installation
---------------
Dateistruktur:
./ Anwendung (z.B. art-course, art-ksk)
../art-framework/ 

Dann:
composer install
cp vendor/cbikt/art-framework/make.sh-example make.sh
chmod +x make.sh
gedit make.sh
=> OUTDIR="/home/cb/Desktop/git/build-ksk" setzen
./make.sh

apt install python3 python3-lxml gettext python3-sqlparse python3-networkx python3-phply python3-polib

Template in der Page ändern
---------------
`<rad:page xmlns="http://www.w3.org/1999/xhtml"   xmlns:rad="http://cbikt.de/rad-framework/page"   title="Reisedetails" template="print">`

Lokalisierung von ENUMs
---------------
Lokalisierung von Enums erfolgt nun automatisch über die pages-po ("cd po && ./make.sh" nicht vergessen).

Zusätzlich gibt es jetzt die Möglichkeit, im Schema zu einem ENUM-Wert ein "Label" zu setzen. Dieses Label wird dann im EnumWidget anstelle des eigentlichen Enum-Wertes angezeigt (und lokalisiert). Dazu das Enum wie folgt im Schema definieren:
spaltenname (...) ENUM('Wert 1' : 'Label', 'Wert 2 (ohne Label, ist optional)', ...)

Weitere Informationen zu Lokalisierung
---------------
Beachte, dass die Strings aus dem Framework anders übersetzt werden als
die aus den Pages:

- innerhalb des Frameworks muss gettext explizit mit der Domain als
Argument aufgerufen werden. (Die Domain des Framewoks ist "rad", die der
Pages ist "rad-pages".) Dies geschieht, indem man eine der d*-Funktionen
von gettext benutzt, also z.B.: dgettext("rad", "Cancel"). Während der
Laufzeit ist die Default-Domain "rad-pages", d.h. _("abc") ist
äquivalent zu dgettext("rad-pages", "abc"). Um Tipparbeit zu sparen, ist
die Funktion function _r($msgid) { return dgettext("rad", $msgid); }
definiert.
Beispiel: 9e39050840 im Framework-Repo

- Die gettext-Dateien des Frameworks liegen in art-framework/po. Dort
gibt es auch eine Makefile, die ausgeführt werden muss, wenn sich
Strings in der Domain "rad" geändert haben.

- Ob gettext von Deutsch nach Englisch oder umgekehrt oder eine Mischung
davon übersetzt, ist gettext egal. Es funktionieren alle Kombinationen.

- PHP hat Schwierigkeiten, wenn sich während der Laufzeit des
PHP-Prozesses die gettext-Datenbanken  (die .mo-Dateien) ändern. Solange
der php-Prozess nach einer Änderung neu gestartet wird, ist das kein
Problem. Geschieht je nach Webserver-Konfiguration evtl. bereits
automatisch.

rad:date
----------------
rad:date unterstützt jetzt das Attribute "format". Die alten Attribute
with-seconds und with-time sind entfernt.

"format" ist ein Format-String entsprechend der date()-Funktion von PHP.
Einige Platzhalter funktionieren nicht (wie z.B. Wochentag), siehe
art-framework/art/helper/Cbikt/DateFormatter.php für eine komplette Liste.

Neben einem gültigen Format-String kann das Attribut auch einen der
folgende Werte haben:
- date_short
- date_long
- datetime_short
- datetime_long
Wird als Format einer dieser Werte benutzt, wird ein passendes Format in
Abhängigkeit der aktuellen Locale verwendet. Die Formate sind in
art-framework/art/helper/Cbikt/LanguageSystem.php ab Zeile 34 definiert.
Guck bitte über diese Formate mal drüber. Das englische Format ist
momentan MONAT/TAG/JAHR, das könnte evtl. verwirrend für die Benutzer sein.

Alle Formate funktionieren unabhängig davon, ob die Quell-Spalte im
Schema ein DATE oder DATETIME ist. Nicht im Format spezifizierte Werte
(z.B. Sekunden bei date_long) werden auf einen undefinierten Wert gesetzt.


Neues Locale anlegen
---------------
Da man Sprachen beliebig mischen kann, kannst du dafür auch eine
deutsche Übersetzung anlegen.

msginit -l de -i pages-po/rad-pages.pot -o pages-po/de_DE.UTF-8.po

Dann kannst du den englischen Teil (hier also die Enums) in dieser Datei
auf Deutsch übersetzen. Der Rest (Kompilieren der PO-Dateien) geschieht
dann automatisch bei make).

module-event bevor gespeichert wird
---------------
Es gibt nun ein neues Event für rad:single-form namens "onvalidate".

Wird mit den gleichen Argumenten wie onsubmit aufgerufen (d.h. erstes
Argument ist die Referenz auf das Record). Mit W\Page::error($msg,
$fields=array()) kannst du eigene Validierungs-Fehlermeldungen erzeugen.
Dieses Event wird erzeugt NACHDEM die normale Validierung gegen das
Schema erfolgreich war und BEVOR das Record gespeichert wird.

Um zu verhindern, dass das Record gespeichert wird, ruft man im
Event-Handler von onvalidate die Methode $e->cancel() auf (es reicht
also nicht, Page::error() allein aufzurufen).


rad:single-form: Redirect nach 'save'
---------------
Der automatische Redirect nach einem Klick auf "save" in einem rad:single-form
funktioniert nicht korrekt, wenn ein neues Record angelegt wurde. Als
Workaround muss Code in den onsubmit-Handler des single-forms gesetzt werden,
der entweder 1) auf eine Übersichtsseite weiterleitet oder 2) manuell die URL
zum Bearbeiten des soeben erzeugten Records zusammensetzt und darauf
weiterleitet.

Spaltennamen der Tabellen
---------------
Die Spaltennamen in den Fehlermeldungen werden nun wie folgt übersetzt:

In die .pot-Datei der Anwendung wird nun für jede Tabelle aus dem Schema
ein Eintrag "table:<name>" und für jede Spalte ein Eintrag
"column:<table>.<column>" erstellt. Diese Strings können in den
.po-Dateien übersetzt werden und die Übersetzung wird dann automatisch
bei Fehlermeldungen benutzt.

Die Präfixe table: und column: sind in der Übersetzung (nicht aber in
der msgid) optional und werden vom Framework beim Übersetzen automatisch
wieder entfernt. D.h. die Einträge

msgid "column:course_cycle.id"
msgstr "column:Zyklus-ID"

und

msgid "column:course_cycle.id"
msgstr "Zyklus-ID"

sind komplett äquivalent.

Die .pot-Dateien können mit ./make.sh aus dem po-Verzeichnis heraus
aktualisiert werden. Ggf. vorher touch ../db/schema.sql ausführen.

Um die Spaltennamen auch auf Englisch angeben zu können, reicht es, eine
englische .po zu erstellen. Die enthält dann für alle msgids leere
Übersetzungen bis auf die für die Tabellen- und Spaltennamen. Das geht mit:
msginit -l en -i rad.pot -o en_US.UTF-8.po

Was mit dieser Methode natürlich nicht übersetzt wird, sind die
Spaltennamen, die in MySQL-Fehlermeldungen auftauchen. Damit muss man leben.


MySQL Views
---------------
Views werden insofern unterstützt, als es bei einem CREATE TABLE
x-Eintrag in der schema.sql zur Laufzeit egal ist, ob x nun eine Tabelle
oder eine View mit dem Namen x ist. In deinem Fall wird auf dem
MySQL-Server die Anweisung
CREATE VIEW x AS SELECT a, b, c, IF(...) AS d FROM ...
ausgeführt und in die schema.sql kommt die Anweisung
CREATE TABLE x (
  a ...,
  b ...,
  c ...,
  d ...
)
