Auf dieser Seite... (ausblenden)
In diesem Tutorial werden eine Reihe von kleinen Plugins vorgestellt, die anhand verschiedener Beispiele einige der Möglichkeiten der Plugin-Schnittstelle von Stud.IP zeigen.
Der erste Schritt sollte sein, ein Grundgerüst für ein Plugin anzulegen, das nichts weiter macht als sich im System zu registrieren.
Ein Stud.IP-Plugin besteht immer aus mindestens zwei Dateien: Der Plugin-Klasse mit dem PHP-Code und einer Textdatei mit Informationen über das Plugin (Name, Version, Autor usw.). Im einfachsten Fall kann das so aussehen:
MyPlugin.php
Wichtig ist hierbei:
MyPlugin") benannt und hat die Endung ".php".
StudipPlugin abgeleitet werden.
SystemPlugin, das sagt, daß dieses Plugin auf jeder Seite aktiv sein soll (mehr dazu später).
Das Plugin selbst tut nichts und tritt damit auch (außerhalb der Plugin-Verwaltung) nicht in Erscheinung.
plugin.manifest
Die Datei mit den Informationen über das Plugin wird von Stud.IP (unter anderem) verwendet, um dem Administrator weitere Informationen anzeigen zu können. Sie hat immer den Namen "plugin.manifest". Es sollte mindestens folgende Einträge geben:
Der erste Schritt ist, aus den Plugin-Dateien ein Installationsarchiv zu erstellen. Dazu packt man alle Plugin-Dateien in ein ZIP-Archiv ein, und schon ist das Plugin-Paket fertig. Vorsicht: Der Ordner, in dem das Plugin liegt, darf dabei nicht mit eingepackt werden, nur der Inhalt. Die Struktur des Archivs sollte also hinterher so aussehen:
Anschließend kann man das Plugin über die Plugin-Verwaltung in Stud.IP installieren:

Dort sollte man das Plugin noch aktivieren, damit es auch tatsächlich geladen wird. Außerdem kann man in der Spalte "Aktionen" die Rechteverwaltung für das Plugin vornehmen. In der Voreinstellung kann es von allen angemeldeten Nutzern im System verwendet werden.
Jetzt soll das Plugin auch wirklich etwas tun. Angenommen, wir wollen, daß hinter dem Namen der Stud.IP-Installation in der Kopfzeile immer die Anmeldekennung des gerade angemeldeten Nutzers angezeigt wird. Wie funktioniert so etwas?
Der Punkt 1 ist zum Glück bereits erledigt: Da unser Plugin das Interface SystemPlugin implementiert, ist es automatisch auf jeder Seite aktiv.
Punkt 2 führt uns direkt in die Untiefen der Stud.IP-API. Zum Glück gibt es hier aber eine sehr einfach zu bedienende Funktion, die uns die aktuelle Nutzerkennung liefert: get_username().
Für Punkt 3 kann man sich etwas CSS bedienen, um Inhalte auf einer Seite zu verändern:
Dieses Stück CSS sorgt dafür, daß hinter dem Element mit der ID "id" im HTML der Text "some text" angezeigt wird. In unserem Fall hat das gesuchte Element in der Kopfzeile die ID "barTopFont". Soweit, so gut. Aber wie bekommen wir das CSS auf die Stud.IP-Seite?
Dazu gibt es eine API in Stud.IP, die es Plugins ermöglicht, Eingriffe in den Seitenaufbau vorzunehmen: PageLayout. Unter anderem kann man damit auch eigenes CSS in die erzeugte Seite einbauen. Zusammen sieht das ganze dann etwa so aus:
Da ein System-Plugin keinen speziellen Einsprungpunkt für Stud.IP hat, wird der Code direkt in den Konstruktor integriert. Natürlich sollte man hier nicht vergessen, den Konstruktor der Basisklasse aufzurufen... Das fertige Plugin sieht dann so aus:

Kommen wir nun zu einem weiteren Beispiel, das zeigt, wie ein Plugin eigene Inhalte auf der Startseite anzeigen kann. Als Beispiel wollen wir bei jedem Aufruf der Seite ein zufälliges Zitat aus einer bekannten Fernsehserie einblenden. Und das sowohl für angemeldete als auch für nicht angemeldetet Nutzer. Wie funktioniert so etwas?
PortalPluginHierzu gibt es ein spezielles Plugin-Interface, das jedem Plugin die Möglichkeit bietet, einen eigenen Kasten auf der Startseite zu plazieren, ganz analog zu den vorhandenen Kästen für die Termine, systemweiten Ankündigungen oder Umfragen:
Offensichtlich benötigt man ein Template-Objekt für die Ausgabe, und man kann noch gewisse Eigenschaften des erzeugten Kastens vorgeben (Icon, Titel usw.).
Text- oder HTML-Ausgabe sollte in Stud.IP immer über Templates passieren, das sind (in PHP geschriebene) Vorlagen für die Ausgabe, die mit Platzhaltern bestückt sein können, um Werte aus dem Programmcode an bestimmte Stellen in der Ausgabe zu bringen. Eine komplette Beschreibung mit vielen Beispielen befindet sich hier im Wiki unter dem Punkt FlexiTemplates.
In unserem Fall brauchen wir nur einen kleinen Bereich, in dem ein vorformatierter Text angezeigt werden kann. Das Template dafür steht in einer eigenen PHP-Datei und kann etwa so aussehen:
templates/fortune.php
Das "<pre>" sollte nicht überraschend sein, aber wieso steht da htmlReady()? Nun, damit spezielle Zeichen in dem auszugebenden Text nicht versehentlich vom Browser als HTML-Markup ausgewertet werden (man stelle sich vor, die Variable $fortune enthielte selbst Dinge wie "<b>"), müssen diese vor der Ausgabe entsprechend kodiert werden. Aus "<b>" würde dann "<b>", was vom Browser wieder als "<b>" angezeigt würde.
Daher ist es wichtig, bei jeder Ausgabe eines Werts in einem Template an die Verwendung von htmlReady() (oder formatReady(), wenn man mit der Stud.IP-Formatierung arbeitet) zu denken. Die einzige Ausnahme sind Werte, die bereits fertige HTML-Fragmente für die Anzeige enthalten. Ein Beispiel dafür sehen wir später.
Das Plugin wird wie im ersten Beispiel von der Klasse StudipPlugin abgeleitet, implementiert jetzt aber - wie oben besprochen - das Interface PortalPlugin. Zusätzlich benötigen wir nun noch eine eigene TemplateFactoy für unser Plugin, damit das Template aus dem Ordner des Plugins geladen werden kann. Es ist üblich, alle Templates für ein Plugin in einem Ordner mit dem Namen "templatess" abzulegen. Der Code zum Laden des Templates sieht dann so aus:
Die Methode getPluginPath() eines Plugins liefert einen Dateisystempfad zum Installationsordner des Plugins, relativ zu diesem Ort kann man dann z.B. Template-Dateien laden. Dieser Pfad ist aber nur serverseitig gültig, er kann nicht zum erzeugen von URLs verwendet werden.
Schließlich soll unser Plugin noch ein Icon und einen Titel für die Anzeige bekommen. Dazu muß man die entsprechenden Attribute "icon_url" und "title" in dem Template setzen. Als Titel setzen wir einfach den Namen des Plugins ein. Für die URL des Icons benötigen wir eine URL zu einer Ressource im Plugin, dazu gibt es - analog zu getPluginPath() für serverseitge Pfade - auch eine Methode getPluginURL(), die eine für den Nutzer gültige URL auf den Installationsort des Plugins liefert. Diese URL kann dann als Basis für die Icon-URL verwendet werden:
Schließlich muß noch die Template-Varianble $fortune aus der Template-Datei mit einem Zitattext gefüllt werden. Eine einfache Möglichkeit ist, einfach das (hoffentlich auf dem Rechner installierte) fortune Kommando aufzurufen, das gleiche eine entsprechende Zitat-Datenbank mitbringt. Die komplette Plugin-Klasse sieht dann am Ende so aus:
Wollen wir, daß unser Plugin auch für nicht angemeldete Nutzer sichtbar ist, so muß man der Installation noch bei den Rechteeinstellungen auswählen, daß neben den voreingestellten Standardrollen auch die Rolle "nobody" (diese Rolle ist speziell für nicht angemeldete Nutzer) das Plugin verwenden kann:

Das installierte Plugin sieht dann beim Aufruf im System so aus:

Im nächsten Beispiel geht es nun um ein Plugin auf der Profilseite. Als Aufgabe nehmen wir uns vor, eine einfache Version der "Eigenen Kategorien" des Profils in einem Plugin nachzubauen: Es soll in einem Kasten im Nutzerprofil ein (ggf. formatierter) Text angezeigt werden, der dort vom Nutzer selbst auch bearbeitet werden kann. Im Gegensatz zu den "Eigenen Kategorien" gibt es aber immer nur einen Kasten und es können weder Titel noch die Sichtbarkeit eingestellt werden. Dazu müssen wir uns mit folgenden neuen Fragen beschäftigen:
HomepagePluginGanz analog zur Anzeige von eigenen Inhalten auf der Startseite gibt es auch ein entsprechendes Interface zur Anzeige von Inhalten auf der Profilseite: HomepagePlugin. Es bietet die gleichen Möglichkeiten und wird auch exakt genauso benutzt:
Auch hier benötigt man natürlich wieder ein Template-Objekt und entsprechende Template-Dateien für die Ausgabe.
Das Template für die Anzeige kann wieder sehr einfach gehalten werden:

templates/fortune.php
Anders als bei dem vorhergehenden Beispiel wird hier die Funktion formatReady() aufgerufen, um den auszugebenden Text für die Anzeige aufzubereiten. Während htmlReady() sich nur um die Kodierung von Sonderzeichen kümmert, wertet formatReady() zusätzlich auch die Stud.IP-Formatierungssyntax aus, d.h. bestimmte Markierungen im Text führen zu speziellen Hervorhebungen bei der Anzeige. Zusätzlich können auch Listen, Tabellen, Links, Bilder und anderes angezeigt werden. Die "id" auf dem umschließenden DIV wird später verwendet, um diesen Punkt auf der Profilseite gezielt anspringen zu können.
Für die Erstellung des Templates kann man im wesentlichen den Code aus dem letzten Beispiel wiederverwenden (auf ein Icon verzichten wir hier). Der anzuzeigende Inhalt kommt von einer eigenen Methode getContents(), die später den Text aus der Datenbank lesen wird:
Das oben gezeigte Template erlaubt noch keine Bearbeitung des angezeigen Inhaltes. Darum soll es in nun diesem Abschnitt gehen: Wir brauchen dazu noch ein entsprechendes Template für die Eingabe - also ein HTML-Formular - sowie etwas Logik in unserem Plugin zur Auswertung dieser Eingabe. Falls der Stud.IP-Nutzer seine eigene Profilseite aufruft, sollte er einen speziellen Editiermodus des Plugins aktivieren können (dazu gleich mehr), der dann ein entsprechedes Formular anzeigt:

templates/edit_mode.php
Das Formular ist sehr einfach aufgebaut: Es gibt eine TEXTAREA zum Bearbeiten des Inhalts sowie zwei Schaltflächen zum Speichern bzw. Verwerfen der Änderungen. Auch hier darf das htmlReady() natürlich nicht fehlen. Ein formatReady() wäre an dieser Stelle übrigens falsch, da wir ja nicht die bereits formatierte Ansicht bearbeiten wollen. Zur Anzeige von Formularschaltflächen gibt es eine Hilfsfunktion makeButton() in Stud.IP, die wir auch hier verwenden. Dies ist ein Beispiel für eine Funktion, die bereits fertige HTML-Fragmente liefert, das Resultat von makeButton() darf also nicht mehr mit htmlReady() behandelt werden. Das von makeButton() erzeugte HTML wird hinterher etwa so aussehen:
Beim Absenden des Formulars soll unser Plugin die eingegebenen Daten verarbeiten können, wir müssen also dafür sorgen, daß wieder die Profilseite (dort lebt ja das Plugin) angezeigt wird, zusätzlich soll der Kasten des Plugins direkt angesprungen werden. Als URL für das Formular müssen wir also eine passende URL zur Profilseite generieren, inklusive Ansprungpunkt auf der Seite. URLs auf Seiten in Stud.IP werden immer - bis auf wenige, spezielle Ausnahmen - über die Klasse URLHelper erzeugt. Im einfachsten Fall gibt man nur den Namen des ensprechenden PHP-Skriptes für die Seite im Aufruf von URLHelper::getURL() an und bekommt die entsprechende URL zurück. Hier ist es sogar noch einfacher: Wir befinden uns ja schon auf der Profilseite, müssen also nur den Ansprungpunkt auf der aktuellen Seite angeben: "#edit_box".
Auch hier gilt: Beim Einsetzen von Werten in HTML muß man sich immer überlegen, ob noch ein htmlReady() erforderlich ist. Normalerweise wäre das der Fall, da das Erzeugen von Links aber recht häufig vorkommt, gibt es hierzu eine Hilfsfunktion im URLHelper, die das Kodieren gleich mit erledigt: URLHelper::getLink(). Das Resultat dieser Funktion kann also (wie makeButton()) immer direkt in die Ausgabe eingesetzt werden.
Unser Plugin kennt zwei Arten von Nutzerinteraktion: Aktivieren des Editiermodus und Abspeichern bzw. Verwerfen der Formulareingaben. Beides ist nur für den Besitzer des angezeigten Profils erlaubt. Um darauf reagieren zu können, müssen wir unsere Plugin-Methode um einige Code-Zeilen erweitern:
In der globalen Variablen $user ist der gerade in Stud.IP angemeldete Nutzer hinterlegt. Wir können also leicht überprüfen, ob der aktuelle Nutzer auch der Besitzer des angezeigten Profils ist. Falls ja, kann der Editiermodus über ein spezielles Icon in der Titelzeile des Kastens für das Plugin angewählt werden (ganz rechts, analog zu dem Icon für eigene Ankündigungen und Umfragen). Über das Template kann der Link, ggf. mit weiteren URL-Parametern, und ein Tooltip für das Icon vorgegeben werden. Ist der Editiermodus aktiviert worden, wird das entsprechende Template geladen.
Zur Abfrage von URL- und Formular-Parametern in Stud.IP sollte man immer die Klasse Request verwenden, die unter anderem auch typsicheren Zugriff auf die Parameterwerte erlaubt. Die Namen der Parameter entsprechen denen aus dem Template, d.h. "Request::submitted('save')" ermittelt, ob die Schaltfläche mit dem Namen "save" im Formular angeklickt wurde.
In diesem Plugin ist es zum ersten Mal notwendig, eigene Daten in der Stud.IP-Datenbank zu hinterlegen bzw. diese bei der Anzeige wieder aus der Datenbank auszulesen. Wie funktioniert so etwas?
Stud.IP verwendet zum Datenbankzugriff die PDO-API, die seit PHP 5.1 als Abstraktionsschicht für den Datenbankoperationen in PHP vorhanden ist. Zum Zugriff auf die (immer vorhandene) Verbindung zur Stud.IP-Datenbank gibt es die Klasse DBManager?, die ein entsprechendes PDO-Objekt verwaltet. Das Auslesen eines Wertes aus der Datenbank ist damit relativ einfach:
In diesem Fall nehmen wir an, wir hätten eine eigene Tabelle "edit_box" für unser Plugin mit zwei Spalten: "user_id" (Nutzer) und "content" (Inhalt des Plugins). Woher die kommt, sehen wir gleich. Das Abfragen von Werten erfolgt dann über SQL-Anweisungen mit entsprechenden Platzhaltern ("prepared statements") wie in der PDO-Dokumentation beschrieben.
Das Speichern von Änderungen sieht sehr ähnlich aus, muß aber nichts zurückliefern:
Aber woher kommt nun die Datenbanktabelle für unser Plugin?
Es kommt relativ häufig vor, daß ein Plugin bei der Installation eigene Tabellen in der Stud.IP-Datenbank anlegen möchte. Für diesen Fall kann man im Manifest des Plugins den Dateinamen eines SQL-Skripts hinterlegen, das bei Installation des Plugins ausgeführt wird. Ebenso kann man beim Deinstallieren ein SQL-Skript ablaufen lassen. In unserem Fall sieht das Manifest so aus:
plugin.manifest
Die beiden dort aufgeführten SQL-Skripte müssen dann nur noch die entsprechende Datenbanktabelle anlegen bzw. wieder entfernen:
sql/install.sql
sql/uninstall.sql
Noch ein Hinweis: Man sollte beim Erstellen von neuen Tabellen möglichst immer die Standardeinstellungen der Datenbank übernehmen, d.h. keine Zeichenkodierung oder Storage-Engine vorgeben.
Die bisher gezeigten Beispiele für Plugins haben sich alle in vorhandene Seiten integriert, ein Plugin kann aber auch komplett eigene Seiten in Stud.IP anbieten oder sogar Inhalte ausliefern, die gar nicht auf das Stud.IP-Design zurückgreifen wie Web-Services oder Datei-Downloads. Wie das funktioniert wird im diesem Abschitt beschrieben. Auch hier fangen wie wieder mit einem kleinen Beispiel an, diesmal soll die Aufgabe so aussehen:

[to be continued...]
Letzte Änderung am 02.05.2011 17:47 Uhr von eludwig.
Hier finden Sie Entwickler-Dokumentation für Stud.IP.
Hilfe zur Bedienung und Administration von Stud.IP finden Sie im Dokumentations-Portal.