Implementierung

Implementierung eines Plugins

Vor der Implementierung eines Plugins sollte zunächst bekannt sein, an welchen Stellen im System ein solches Plugin verlinkt sein soll und wer hierauf Zugriff besitzt. Hieraus sollte dann eine Wahl auf einen der fünf Typen bzw. Basisklassen? resultieren.

Ein neues Plugin wird dann von der so gewählten Basisklasse abgeleitet.

class UserAdministrationPlugin extends AbstractStudIPAdministrationPlugin {
    function __construct(){
        parent::__construct();
        [...]
    }
}

Im obigen Beispiel wird von der Klasse AbstractStudIPAdministrationPlugin abgeleitet. Das Plugin erhält dadurch automatisch einige Attribute und Methoden und wird so von der Plugin-Schnittstelle automatisch in den Administrationsbereich von Stud.IP eingebunden. Dies geschieht allerdings erst, wenn dem Plugin auch ein entsprechendes Navigationsobjekt zugewiesen wurde. Die abstrakte Oberklasse verfügt nämlich über kein solches Navigationsobjekt. Dies ist auch bei den übrigen Basisklassen der Fall.

1.  Die Navigation

Für die Implementierung eines Plugins bedeutet dies, dass der erste Schritt immer das Erzeugen eines Navigationsobjektes ist, welches dem Plugin zugewiesen wird. Dies lässt sich üblicherweise im Rahmen der Initialisierung des Objektes im Konstruktor durchführen, kann aber später zur Laufzeit immer wieder geändert werden.

$nav = new PluginNavigation();
$nav->setDisplayname(_("Verwaltung von Benutzern"));
$this->setNavigation($nav);
$this->setTopNavigation($nav);

Im Beispiel wird dem Plugin ein Menü mit dem Namen Verwaltung von Benutzern hinzugefügt und zusätzlich eine Top-Level-Navigation mit demselben Namen eingefügt.

  • Administrationsplugins weisen zusätzlich die Besonderheit auf, dass sie über eine TopNavigation verfügen können, die dazu führt, dass das Plugin auch auf der Startseite des Administrators angezeigt wird.
  • Systemplugins weisen die Besonderheit auf, dass sie alternativ über überhaupt keine Navigation verfügen können. In diesem Fall sollte dann aber ein BackgroundTask vorhanden sein. D.h. Systemplugins können alternativ ohne Navigation als Hintergrund-Job laufen. Sie werden dann bei jeder Aktualisierung der Seite ausgeführt. Dies eignet sich bspw. um ein Benutzertracking durchzuführen.
  • Bei Standardplugins kann es zusätzlich eine Subnavigation geben. Dies sind die in Veranstaltungen und Einrichtungen innerhalb von Stud.IP üblichen Bottomkats bzw. Links unterhalb eines Karteireiters.

2.  Icons

Neben der Navigation sollte als nächstes das Icon des Plugins definiert werden. Dieses befindet sich in der Regel innerhalb des Pluginpaketes und wird durch die PluginEngine automatisch in den entsprechenden Menüs bzw. der Titelzeile des Plugins verwendet.

$this->setPluginiconname("img/nutzer.gif");

3.  Grunddaten

Als nächstes sollte die Methode getPluginname() überschrieben werden, die den Namen des Plugins zurückliefert. Alternativ kann auch direkt der Name des Plugins gesetzt werden. Dieser Name wird bisher nur in der Pluginadministration angezeigt und dient der Verwaltung der Plugins. Eine zukünftige anderweitige Verwendung ist aber möglich. Daher sollte dieser Name immer gesetzt werden.

4.  Aufruf des Plugins durch die PluginEngine

Bevor man nun mit der Implementierung der Logik beginnen kann, sollte man sich einen Überblick davon verschaffen, welche Attribute und Methoden das jeweilige Plugin bereits durch die Plugin-Schnittstelle vorgegeben hat und wie diese durch die Plugin-Engine genutzt werden.

Zunächst einmal benutzt die Plugin-Engine die Informationen aus der Datenbank, um Plugins ins System zu laden. Anschließend wird jedes Plugin nach der Navigation gefragt und dann entsprechend im System verlinkt. Wird nun ein entsprechender Link durch den Nutzer angeklickt, so lädt die Plugin-Engine das angeforderte Plugin und fügt je nach Ausprägung (Standard, System, Administration) des Plugins einen entsprechenden Kopf über dem Plugin-Ausgabebereich ein und ruft dann die actionShow-Methode des Plugins auf. Danach wird die Seite über einen entsprechenden Abschluss beendet.

Der Aufruf des Plugins kann auch über eine andere Methode erfolgen, wenn dies durch das Plugin angefordert wird. Wie dies genau funktioniert, wird an anderer Stelle beschrieben.

Das Plugin sollte also in jedem Fall über eine actionShow-Methode verfügen, da diese der Haupteinstiegspunkt für die Plugin-Engine ist. Innerhalb dieser actionShow-Methode sollte das Plugin den Request verarbeiten und eine Ausgabe liefern. Sinnvoll ist hier auch die Unterscheidung in mehrere Schichten nach dem Model-View-Controller-Modell (MVC). Das hier als Beispiel verwendete Plugin und auch das PluginAdministrationPlugin benutzen dazu jeweils mindestens drei Klassen:

  • UserAdministrationPlugin (Controller)
  • UserAdministration (Model)
  • UserAdministrationVisualization (View)

Das Beispielplugin führt in seiner actionShow-Funktion keinerlei Unterscheidung aufgrund des eingehenden Requests durch. Statt dessen wird zunächst eine Session-Variable gelöscht und dann nur der View instanziiert und dort die Anzeige eines Suchformulars aufgerufen.

Die Visualisierungsklasse ist von einer abstrakten Oberklasse aus der Plugin-Schnittstelle abgeleitet und benötigt zur Instanziierung eine Referenz auf das aufrufende Plugin. Dies ist für eine spätere Verlinkung zwingend notwendig.

function actionShow(){ 
        $vis = new UserAdministrationVisualization($this);
        // Standard-Ansicht zeigen
        $vis->showLDAPSearchForm();          
}
function actionImportUserFromLDAP(){
    // ....
}

function actionSearchLDAP(){
    // ....
}

Weitere Funktionalität des Controllers steckt in den weiteren angedeuteten Methoden. Die Aufteilung in verschiedene Methoden verbessert hier die Übersichtlichkeit und Wartbarkeit des Codes. Statt der Aufteilung in verschiedene Methoden könnte sich auch der gesamte Code zur Kontrolle innerhalb der actionShow-Methode verbergen. Dies wäre jedoch nicht sehr übersichtlicht. Trotzdem kann dies bei einigen Fallunterscheidungen sinnvoll sein.

Wie aber kann nun aus der Visualisierung heraus auf eine der enstprechenden Methoden innerhalb des Plugins zugegriffen werden.

function actionShowLDAPSearchForm($nachname="",$email="",$name="",$fuzzy=false){
        echo '<form method="POST" action="'.PluginEngine::getLink($this->pluginref,array(),"searchLDAP").'">';
        [...]
}

Zur Erzeugung des Action-Links eines Formulars sehen wir den Aufruf der statischen Methode getLink innerhalb der PluginEngine-Klasse.

5.  Zugriff auf weitere Ressourcen im Plugin

Gelegentlich kann es notwendig sein, auf weitere Dateien im Plugin-Verzeichnis zuzugreifen, z.B. bei Verwendung von Templates oder Konfigurationsdateien im Plugin oder falls das Plugin eigene Bilder oder Stylesheets mitbringt. Hierfür gibt es zwei Hilfsmethoden in der Plugin-Klasse:

  • getPluginPath():
    liefert einen Dateisystempfad zum Verzeichnis des Plugins, den man serverseitig verwenden kann, um Ressourcen zu erreichen
  • getPluginURL():
    liefert eine absolute URL zum Verzeichnis des Plugins, falls man URLs zum Zugriff auf eigene Bilder, CSS-Dateien o.ä. konstruieren möchte

6.  Ausgangspunkt für eigene Entwicklungen

Als Ausgangspunkt für eigene Entwicklungen können die bereitgestellten Beispiel-Plugins dienen. Diese erzeugen nur einen Menüeintrag und ansonsten einen leeren Content-Bereich. Zudem sollten folgende Klassen genauer angesehen werden:

  • plugins/engine/PluginEngine.class.php
  • plugins/core/AbstractStudIPPlugin.class.php
  • plugins/core/AbstractStudIPStandardPlugin.class.php
  • plugins/core/AbstractStudIPAdministrationPlugin.class.php
  • plugins/core/AbstractStudIPSystemPlugin.class.php

Letzte Änderung am September 13, 2009, at 10:55 PM von eludwig.