====== Hello World-Tutorial ====== //AddOn-Programmierung für das FS2// Ziel dieses Tutorials soll es sein dir die Eigenheiten bei der AddOn-Programmierung für das Frogsystem 2 näher zu bringen. Dabei geht es vor allem um die **Integration** in das System. Es kann nicht die Aufgabe dieses Tutorials sein dir PHP, SQL oder sogar HTML beizubringen, dazu gibt es bereits genügend andere wirkliche gute Tutorials im Internet. Deswegen ist die eigentliche Programmierung, des mit diesem Tutotrial erstellten AddOns, nur rudimentär und wird sich ausschließlich um Varianten des bekannten "Hello World" drehen. Voraussetzung für dieses Tutorial ist lediglich eine **funktionierende Frogsystem 2 Installation** der aktuellen Version. Und natürlich musst du auch direkten Zugriff auf das Datei-System und den MySQL-Server haben. **Auf geht's!** ===== Der Anfang ===== Wie üblich wollen wir auch hier damit beginnen, eine einfache Datei zu erstellen, die uns die Nachricht "Hello World" ausgibt. Für Ausgaben bietet sich in einem CMS natürlich der öffentliche Bereich einer Seite an. **Über Adressen** Im Frogsystem 2 sind das die Seiten, die über die URL mit ?go= aufgerufen werden. Die entsprechenden Dateien dazu befinden sich im Data-Ordner =>[FS2]/data/. Nachdem evtl. Alias-Weiterleitungen durchgeführt wurden, sucht das System nach einer Datei in diesem Ordner, die genauso heißt, wie das, was hinter dem ?go= steht. Der Übersicht halber lassen wir aber die Dateiendung ".php" weg. Das Frogsystem 2 fügt diese dann automatisch hinzu. Andere Datei-Typen können theoretisch genauso eingebunden werden, bei ihnen muss die Dateiendung aber immer zwingend mit angegeben werden. Eine Sonderstellung besitzt hier natürlich die Artikel-Funktion, für die unabhängig davon, ob eine Datei im Data-Ordner liegt, ?go=-Adressen angelegt werden. Die Reihenfolge, nach der ?go=-Adressen überprüft werden, ist also: - Aliasse - Dateien im Data-Ordner - Artikel-Adressen Findet sich keine Datei und kein Artikel, wird die 404-Fehlerseite ausgegeben (die aber wie andere Dateien auch im Data-Ordner liegt). **Das erste Script** Jetzt erstellen wir aber erstmal unser erstes Script. Also einfach mal im Data-Ordner die Datei "helloworld.php" anlegen und diesen Inhalt einfügen: {{:hello_echo.jpg?150 |Ungewollte Ausgabe}}Wenn wir die Datei jetzt über //?go=helloworld// aufrufen, erhalten wir eine Ausgabe, die so ähnlich wie auf dem Bild aussehen sollte (roter Rahmen). Das führt uns zu einem ersten wichtigen Prinzip der FS2-Programmierung. Um Inhalte an den vorgesehenen Stelle auszugeben, kann im Frogsystem 2 nicht einfach der PHP-Befehl [[http://php.net/manual/en/function.echo.php|echo]] verwendet werden. Am richtigen Platz ausgeben werden nur die Inhalte, die am Ende des Scripts in der Variable **$template** gespeichert sind. Daher gibt es zwei Möglichkeiten um unseren Fehler zu korrigieren. Wir könnten //echo// weiter nutzen und die Ausgabe mit dem [[http://de2.php.net/manual/en/ref.outcontrol.php|PHP-Ausgabepuffer]] regeln, oder einfach //echo// durch **$template** ersetzen. In diesem Tutotial werden wir der Einfachheit halber die zweite Möglichkeit einsetzen. Dennoch sind beide Varianten prinzipiell gleichwertig. Für Seiten im Admin-CP gilt die Regkung mit **$template nicht**. Hier muss i.d.R. mit **echo** gearbeitet werden. (Dazu kommt später noch mehr.) {{ :hello_correct.jpg?150|Korrekte Ausgabe}}Versuchen wir es also einmal mit diesem Code: $template = "Hello World"; Wenn wir uns jetzt die Seite anschauen, sieht das Ganze doch schon viel besser aus (oder sollte es zumindest). ===== Datenbank & Name ===== Nun wollen wir ja eigentlich mehr machen, als nur einen einfachen Text ausgeben und damit die Welt zu begrüßen. Eigentlich würden wir gerne alles mögliche begrüßen, und über das AdminCP einstellen können, wer gerade an der Reihe ist. **Die Datenbank** Das FS2 setzt im Hintergrund auf eine MySQL-Datenbank. Am einfachsten lässt sich diese über das Tool [[http://www.phpmyadmin.net|phpmyadmin]] verwalten, aber jeder andere Zugang ist natürlich genauso möglich. Grundsätzlich verwendet das FS2 mehrere Tabellen, die dann die dann die entsprechenden Daten enthalten. Jede Tabelle beginnt dabei mit einem **Präfix**, dass während der Installation festgelegt wurde (Standard: fs2_, wird hier synonym für alle Präfixe verwendet). Es folgt dann der Name des Unter-Systems oder AddOns, für welche die Tabelle die **größte Relevanz** besitzt. Mit weiteren Unterstrichen können dann noch **Spezialisierungen** der Tabellen angegeben werden. So gibt es z.B. eine Tabelle //fs2_news//, die den Hauptinhalt von News speichert, aber auch eine Tabelle //fs2_news_config//, in der die Einstellungen für das News-System zu finden sind. Mit Relevanz ist einfach die **Zuordnung** zu einem Unter-System oder AddOn gemeint. Denn natürlich wird die Tabelle //fs2_news// auch benötigt um die Anzahl der geschrieben News zu ermitteln, sie deshalb dem Statistik-System zuzuordnen wäre aber nicht zielführend. Wir wollen nun also konfigurieren können, wenn wir mit unserem AddOn begrüßen. Deswegen erstellen wir uns jetzt eine **neue Tabelle** //fs2_hello_config// mit den Feldern //id// (Typ: TINYINT( 1 ), Standard: 1) und //hello_name// (Typ: VARCHAR( 100 ), Standard: "World"). Außerdem erstellen wir uns gleich einen Datensatz dazu. Wir können beides einfach mit Hilfe von **phpmyadmin** machen oder diesen Befehl verwenden: CREATE TABLE `fs2_hello_config` ( `id` TINYINT( 1 ) NOT NULL DEFAULT '1', `hello_name` VARCHAR( 100 ) NULL DEFAULT 'World' ); INSERT INTO `fs2_hello_config` (`id`,`hello_name`) VALUES ('1', 'World'); **Ein Name muss her** Bei der Erklärung, wie Tabellen Namen aufgebaut sind, ist dir vielleicht aufgefallen, dass dort von einem **Addon-Namen** die Rede ist. Diese Namen sind wichtig, damit sich sich verschiedenen Addons nicht in die Quere kommen. Wenn wir unser Addon auf der offiziellen Seite einstellen möchten, wird unter anderem auch darauf geachtet, dass wir einen eindeutigen Addon-Namen gewählt haben. Festlegen müssen wir einen **Titel**, der Groß-/Kleinschreibung oder Sonderzeichen enthalten darf und einen **Tag**, der als **Präfix** z.B. bei Tabellen dient, klein geschrieben werden muss und keine Sonderzeichen enthalten darf, aber immer noch mit dem Titel in Verbindung stehen sollte. Der Tag zu einem Namen sollte zwar möglichst kurz und einfach sein, muss aber auch trotzdem noch den **Bezug zum Titel** behalten. //Kai's tollem Sudoku-Addon// den Tag //sudoku// zuzuordnen wäre also nicht erlaubt, //kai-sudoku// hingegen schon. Für unser kleines Addon haben wir aber noch keine richtigen Namen gefunden. Da wir ja irgendwelche Sachen begrüßen wollen, nennen wir es einfach **"Hello!"**. (Das Ausrufezeichen macht den Titel erst so richtig cool!) Den zugehörigen Tag **"hello"**, haben im SQL-Teil schon mit eingebaut. ===== Verwaltung & Rechte ===== Im nächsten Schritt erstellen wir eine einfache Konfigurationsseite um den Namen des zu Begrüßenden komfortabel ändern zu können und erstellen dazu die entsprechenden Rechte für Mitarbeiter. **AdminCP-Seiten** Alle Seiten, die im AdminCP verwendet werden, sind unter "[FS2]/admin/" abgelegt. Sie beginnen mit dem Namen der Gruppe oder des Addons, gefolgt von einer genaueren Bezeichnung der Funktion der Seite. Die fest integrierten Seiten verwenden zusätzlich noch das Präfix "admin_". Warum das so ist, weiß aber leider niemand so genau. Wir legen uns also eine Datei mit dem Namen "hello_config.php" an und füllen sie mit folgendem Inhalt: /////////////////////// //// Update Config //// /////////////////////// if ( $_POST['hello_name'] && $_POST['hello_name'] != "" ) { // security functions $_POST['hello_name'] = savesql ( $_POST['hello_name'] ); // MySQL-Queries mysql_query ( " UPDATE `".$global_config_arr['pref']."hello_config` SET `hello_name` = '".$_POST['hello_name']."' WHERE `id` = '1' ", $db ); // system messages systext ( $TEXT["admin"]->get("changes_saved"), $TEXT["admin"]->get("info"), FALSE, $TEXT["admin"]->get("icon_save_ok") ); // Unset Vars unset ( $_POST ); } ///////////////////// //// Config Form //// ///////////////////// if ( TRUE ) { // Display Error Messages if ( isset ( $_POST['sended'] ) ) { systext ( $TEXT["admin"]->get("changes_not_saved")."
".$TEXT["admin"]->get("form_not_filled"), $TEXT["admin"]->get("error"), TRUE, $TEXT["admin"]->get("icon_save_error") ); // Load Data from DB into Post } else { $index = mysql_query ( " SELECT * FROM ".$global_config_arr['pref']."hello_config WHERE `id` = '1' ", $db); $config_arr = mysql_fetch_assoc($index); putintopost ( $config_arr ); } // security functions $_POST['hello_name'] = killhtml ( $_POST['hello_name'] ); // Display Form echo'
Allgemeine Einstellungen
Ziel der Begrüßung:
Person oder Sache, die begrüßt werden soll.
'; }
//siehe auch: [[example-admin-config|Beispiel & Erklärung einer Konfigurationsseite im AdminCP]]// **Zugriffsrechte & Links anlegen** Im AdminCP des Frogsystem 2 werden die Navigations-Menüs entsprechend der Zugriffsrechte eines eingeloggten Users gesetzt. Dazu muss jeder Seite ein entsprechendes Recht zugeordnet werden. Prinzipiell muss man für jede Seite ein Recht anlegen. Es kann nicht ein und dasselbe Recht für zwei Seiten genutzt werden. Es ist allerdings möglich Sub-Rechte zu definieren, die zusätzlich innerhalb einer Seite verwendet werden sollen. Schauen wir uns dazu einmal die Tabelle **fs2_admin_cp** an: * **page_id** Der Name des Rechts, i.d.R. Dateiname ohne Endung * **group_id** ID der Linkgruppe, der die Seite zugeordnet ist * **page_title** Der rechte Teil des Seitentitels * **page_link** Link-Name, wie er im Menü erscheint * **page_file** Name einer im Ordner "[FS2]/admin/" liegenden Datei (bei Sub-Rechten //page_link// des übergeordneten Rechts) * **page_pos** Position innerhalb der Linkgruppe * **page_int_sub_perm** Setze "1" für ein Sub-Recht {{ :hello_table_admincp.jpg |Tabelle fs2_admin_cp}} Bis auf die Linkgruppe sollte alles klar sein. Linkgruppen fassen die einzelnen Links innerhalb des Menüs optisch zu einer Gruppe zusammen. Diese Gruppen werden in der Tabelle **fs2_admin_groups** festgelegt: * **group_id** ID der Linkgruppe, wird in //fs2_admin_cp// verwendet * **group_title** Gruppenüberschrift * **menu_id** ID eines Bereichs des oberen Menüs * **group_pos** Position innerhalb eines Bereichs {{ :hello_table_admingroup.jpg |Tabelle fs2_admin_group}} Auch diese Tabelle sollte größtenteils selbsterklärend sein. **group_id** nutzt einfach einen fortlaufenden Index. **menu_id** bezieht sich auf das obere Menü, das selbst in der Tabelle //fs2_admin_cp// durch die Startseiten erzeugt wird, welche "-1" als //group_id// nutzen (und somit als Bereich inkl. zugehöriger Startseite definiert werden). Addons sollten sich entweder in einen der bestehende Bereiche oder den Sonderbereich "AddOns" einbinden. Ein eigener Bereich muss bei der Überprüfung gesonderte Auflagen erfüllen. Da es sich bei unserem AddOn um Inhalt handelt, wollen wir es auch entsprechend in den content-Bereich eingliedern, wir erstellen also folgende Gruppe: INSERT INTO `fs2_admin_groups` (`group_title`, `menu_id`, `group_pos`) VALUES ('Hello!', 'content', '99'); Die 99 als Position innherhalb des Bereichs soll lediglich dafür sorgen, dass unser AddOn immer ganz unten angezeigt wird. Mit der soeben erzeugten Gruppe können wir jetzt auch unserer eigentliches Recht bzw. den Link anlegen. INSERT INTO `fs2_admin_cp` (`page_id`, `group_id`, `page_title`, `page_link`, `page_file`, `page_pos`, `page_int_sub_perm`) VALUES ('hello_config', '27', 'Konfiguration', 'Konfiguration', 'hello_config.php', '1', '0'); //group_id// variiert natürlich und muss später nur intern vom Installationsscript ermittelt werden. Einmal aus- und einloggen und wir finden unsere brandneue Konfigurationsseite im AdminCP. (Gilt nur für Admins, bei allen anderen Benutzern muss vorher natürlich noch über die Benutzerverwaltung das neue Recht gesetzt werden.) {{ :hello_admin_config.jpg?400 |Hello! Konfigurationsseite}} **Ausgabe anpassen** Zu guter Letzt bauen wir in unsere Ausgabeseite helloworld.php noch die Abfrage des Config-Wertes aus der Datenbank ein: ////////////////////// //// Config Array //// ////////////////////// $index = mysql_query ( " SELECT * FROM `".$global_config_arr['pref']."hello_config` WHERE `id` = '1' ", $db ); $config_arr = mysql_fetch_assoc ( $index ); $template = "Hello " . stripslashes ( $config_arr['hello_name'] ) . "!"; //siehe auch: [[example-frontend|Beispiel & Erklärung einer Frontend-Seite]]// {{ :hello_db.jpg?250 |Ausgabe mit Wert aus Datenbank}} Da wir uns dazu entschieden haben das Programm "Hello!" zu nennen, sollten wir eigentlich die Datei auch in "hello.php" umbenennen. Da uns das aber zu viel Arbeit ist und da wir das Alias-System kennen lernen sollen, beleiben wir bei dem alten Namen und legen einen Alias an. Das geht ganz einfach unter System->Aliasse, die Maske ist selbsterklärend. {{ :hello_admin_aliasse.jpg?400 |Alias hinzufügen}} ===== Templates ===== Nach dem wir schon den Inhalt der Begrüßung variabel gestaltet haben, wollen wir zum Schluss auch noch das Design über ein Template gestalten. Dazu müssen wir eine spezielle Template-Seite für das Admin-CP anlegen und abschließend die Ausgabe-Datei auf dieses neue Template zugreifen lassen. **Template bearbeiten** Die Template Bearbeitung findet im Admin-CP statt. Dazu wird ein normales PHP-Skript mit dem Namen **hello_template.php** angelegt, das aber intern auf eine besondere API zugreift. Wir speichern das Skript mit folgendem Inhalt: // Set $go-Value if ( $go == "tpl_hello" ) { $TEMPLATE_GO = "tpl_hello"; } else { $TEMPLATE_GO = "hello_template"; } $TEMPLATE_FILE = "hello.tpl"; $TEMPLATE_EDIT = array(); $TEMPLATE_EDIT[] = array ( name => "HELLO", title => "Hello!-Design", description => "Darstellung der Hello!-Begrüßungsseite", rows => 20, cols => 66, help => array ( array ( tag => "hello_name", text => "Name der Person oder Sache, die begrüßt werden soll." ), ) ); // Intialise Editor echo templatepage_init ( $TEMPLATE_EDIT, $TEMPLATE_GO, $TEMPLATE_FILE ); //siehe auch: [[example-admin-template|Beispiel & Erklärung einer Template-Seite im AdminCP]]// Die im Skript angegebene Template-Datei **hello.tpl** wird vom System beim ersten Speichern automatisch erzeugt. Die Einbindung der Seite funktioniert wie gehabt über das Rechte-System. Da wir wollen, dass die Template-Bearbeitung sowohl in der AddOn-Gruppe "Hello!", als auch unter **Styles->Templates** angezeigt wird, legen wir zwei Einträge an: INSERT INTO `fs2_admin_cp` (`page_id`, `group_id`, `page_title`, `page_link`, `page_file`, `page_pos`, `page_int_sub_perm`) VALUES ('hello_template', '27', 'Template bearbeiten', 'Template', 'hello_template.php', '2', '0'), ('tpl_hello', '22', '„Hello!“ bearbeiten', 'Hello!', 'hello_template.php', '99', '0') {{ :hello_template_navi.jpg?250 |Eintrag in zwei Menü-Gruppen}} Diese doppelte Eintragung ist nur möglich, da durch die erste if-Abfrage im Skript beide Rechte überprüft werden! **Template verwenden** Beim ersten Bearbeiten erhalten wir den Hinweis, dass die Template-Datei wie gewünscht vom System erstellt wurde. {{ :hello_tpl_file_created.jpg?400 |Fehlende Template-Datei wird neu erstellt}} Für unsere Zwecke reicht es vorerst aus, wenn wir ein einfaches Template einfügen und speichern:
Hello {..hello_name..}!
Das Ausgabe-Skript wird nun noch wie folgt angepasst: ////////////////////// //// Config Array //// ////////////////////// $index = mysql_query ( " SELECT * FROM `".$global_config_arr['pref']."hello_config` WHERE `id` = '1' ", $db ); $config_arr = mysql_fetch_assoc ( $index ); ////////////////////// //// Get Template //// ////////////////////// $template = new template(); $template->setFile("hello.tpl"); $template->load("HELLO"); $template->tag("hello_name", stripslashes ( $config_arr['hello_name'] ) ); $template = $template->display(); //siehe auch: [[example-frontend|Beispiel & Erklärung einer Frontend-Seite]]// Wenn wir uns jetzt die Ausgabe anschauen, können wir feststellen, dass unser AddOn endlich fertig ist: {{ :hello_frontend_tpl_output.jpg?400 |Ausgabe einer Frontend-Seite in Abhängigkeit von einem Template}} ===== Installation & Deinstallation ===== Jedes AddOn muss ein eigenes Installations und Deinstallations-Skript mitbringen. Da für die aktuelle Version (Alix 5) keine allgemeine Form dieser Skritpe vorgesehen ist, sind wir beim Erstellen mehr oder weniger frei. Dennoch gibt es einige Hinweise die wir beachten müssen: **Allgemein** * AddOns sollten möglichst keine bestehenden Systeme (d.h. Dateien und Tabellen) verändern * Alles was eingefügt wurde, muss auch wieder entfernt werden können **Installation** * Installations-Skripte sollten keine Dateien verschieben * Dateien sollten bereits über die Ordnerstruktur eingefügt werden * Es sollte ein Original-Template im Ordner "[FS2]/styles/default" abgelegt werden * Installations-Skripte könnten erkennen ob evtl. vorhandene Dateninhalte aus einer vorherigen Installation des AddOns existieren und diese auf Wunsch übernehmen oder löschen **Deinstallation** * Prinzipiell müssen alle in die Datenbank eingefügten Daten entfernt werden * Es könnte aber eine Option angeboten werden, inhaltliche Daten zu behalten * Dateien sollten nur auf Nachfrage mit genauer Auflistung gelöscht werden //siehe auch: [[example-de-install-script|Beispiel & Erklärung eines De- bzw. Installations-Skripts]]//