Die Schnittstelle eines Plugins wird als Datei mit der Endung "*.config" gespeichert. Sie finden diese Dateien im Verzeichnis "plugins/".
/* in der Schnittstellenbeschreibung plugins/foo.config */
<INTERFACE>
<name der aktion>
<TYPE>primary|default|write|read|security|config</TYPE>
/* Type:
- "primary" für Kernprozesse eines Hauptprogramms
- "security" für sicherheitsrelevante Funktionen, wie das Prüfen von Passwörtern
- "config" für Funktionen zum Editieren von Konfigurationsdateien
- "write" für Schreibzugriffe auf dem Dateisystem oder einer Datenbank
- "read" für Lesezugriffe auf dem Dateisystem oder einer Datenbank
- "default" ist gedacht für Entwickler, die sich unschlüssig sind, wo die Aktion einzuordnen ist
*/
<MODE>0|1</MODE>
/* Mode:
- 0 (default) normaler Betriebsmodus
- 1 Aktion im Default-Konfiguration ("abgesicherter Modus") starten
(für sicherheitskritische Aufgaben)
*/
<TEMPLATE>Id des Templates (z.Bsp. INDEX)</TEMPLATE>
<INSERT>Id des Templates (z.Bsp. MY_TEMPLATE)</INSERT>
/* Templates:
Namen von Templates für die Ausgabe
- das unter "INSERT" angegebene Datei wird in die "TEMPLATE"-Datei eingebettet
- "TEMPLATE" bildet also einen statischen "Rahmen" um den Inhalt, Defaultwert ist "INDEX"
- Der Name des Templates entspricht dem Namen, der in der Skindatei festgelegt wurde.
Zum Vergleich öffnen Sie bspw. die Datei skins/default/default.config .
- Das spezielle Template "NULL" unterbindet dass eine Ausgabe erzeugt wird
(sehr praktisch wenn die Ausgabe keine HTML-Datei sondern bspw. eine PNG-Grafik werden soll)
- Das spezielle Template "MESSAGE" erzeugt eine Textmeldung.
*/
<PERMISSION>1</PERMISSION>
/* Permission:
Gibt an, welche Zugriffsrechte für einen Nutzer mindestens erforderlich sind,
um die Aktion aufrufen zu können. Der Wert liegt zwischen 0 und 100, wobei
der Wert 0 = "keine Beschränkung" bedeutet. Sie können eine Funktion temporär
deaktivieren, indem Sie die Permission auf -1 setzen. In diesem Fall kann niemand
die Aktion aufrufen.
*/
<ONSUCCESS>
<TEXT>Name der Textmeldung</TEXT>
<GOTO>Name der Aktion</GOTO>
</ONSUCCESS>
<ONERROR>
<TEXT>Name der Textmeldung</TEXT>
<GOTO>Name der Aktion</GOTO>
</ONERROR>
/* OnSuccess / OnError:
Sie können eine Aktion angeben, auf welche automatisch weitergeleitet werden soll,
wenn die Aktion erfolgreich war beziehungsweise, wenn ein Fehler aufgetreten ist.
Zusätzlich können Sie eine Textmeldung angeben, welche angezeigt werden soll.
Eine Liste der Textmeldungen finden Sie in der Datei "languages/de/message.config".
*/
</name der aktion>
/* ein Beispiel */
<foo>
<TYPE>write</TYPE>
<MODE>0</MODE>
<TEMPLATE>MESSAGE</TEMPLATE>
<PERMISSION>75</PERMISSION>
<ONSUCCESS>
<GOTO>foo_read</GOTO>
</ONSUCCESS>
<ONERROR>
<GOTO>foo_edit</GOTO>
</ONERROR>
<foo>
</INTERFACE>
in der Plugin-Klasse plugins/foo/plugin.php:
<?php
class plugin_foo extends plugin
{
/* ... */
function foo($ARGS)
{
/* Quelltext der Aktion "foo" */
if ($test) {
return true; /* true = SUCCESS -> gehe zu Aktion "foo_read" */
} else {
return false; /* false = ERROR -> gehe zu Aktion "foo_edit" */
}
}
function foo_edit($ARGS)
{
/* Quelltext der Aktion "foo_edit" */
}
function foo_read($ARGS)
{
/* Quelltext der Aktion "foo_read" */
}
}
?>
Zuerst sollten Sie mit Hilfe des SDK ein Grundgerüst für Ihr neues Plugin generieren lassen. Dies macht das Anpassen des Quellcodes deutlich einfacher.
Für das Erstellen einer neuen Aktion sind zwei Dinge erforderlich. Einerseits das Schreiben des Quellcodes und andererseits die Registrierung dieser neuen Aktion im Framework selbst durch Publizieren der Schnittstelle. Dadurch wird es überhaupt erst möglich, die Aktion aufzufinden und zu benutzen.
Im Folgenden ein Beispiel: Alle öffentlichen Funktionen der Klasse stellen eine Funktion bereit, die ebenso heißt, wie die Funktion selbst. Also: um eine Aktion "foo" zu erzeugen, erstellen Sie eine Funktion "foo()". Diese rufen Sie in der URL auf über: "index.php?action=foo".
Achten Sie im Folgenden Beispiel auf die "Hot-Spots". Diese markieren Stellen im Skelett der Anwendung, welche mit eigenem Code befüllt werden können.
<?php
class plugin_beispiel extends plugin
{
function plugin_beispiel($plugin_name)
{
settype($plugin_name,"string");
global $YANA;
$this->plugin_name = $plugin_name;
}
/**
* Default event handler
*
* @param string $event name of the called event in lower-case
* @param array $ARGS array of params passed to the function
* @return boolean
*/
function _default($event, $ARGS)
{
settype($event, "string");
settype($ARGS, "array");
# HOT-SPOT << hier können Sie Aktionen definieren
# zum Beispiel mit einer Switch-Anweisung:
switch ($event)
{
case 'my_action1':
# HOT-SPOT << Code für Aktion 'my_action1'
break;
case 'my_action2':
# HOT-SPOT << Code für Aktion 'my_action2'
break;
}
return true;
}
/**
* Type: read
* Permission: 0
* Templates: index entries
*
* @param array $ARGS array of params passed to the function
* @return boolean
*/
function guestbook_read_entries ($ARGS)
{
# HOT-SPOT << Code für Aktion 'guestbook_read_entries'
}
/* { ... } */
/**
* Type: write
* Permission: 100
* Templates: MESSAGE
*
* @param array $ARGS array of params passed to the function
* @return boolean
*/
function guestbook_write_write ($ARGS)
{
# HOT-SPOT << Code für Aktion 'guestbook_write_write'
$YANA->message("OK", "200");
}
function my_action ($ARGS)
{
# HOT-SPOT << Code für Aktion 'my_action'
}
}
?>
Die "Hot-Spots", an welchen der Entwickler eigenen Quellcode schreiben oder ergänzen kann, sind in diesem kurzen Beispiel entsprechend hervorgehoben. Die Funktion "my_action" soll demonstrieren, wie man nachträglich eigene Aktionen zur Schnittstelle der Klasse und damit zum Plugin hinzufügen kann. Beachten Sie die Funktion "_default". Diese wird von der Basisklasse "plugin" geerbt und fungiert als "Default event handler", welcher alle Ereignisse abfängt, die an das Plugin gesendet werden, aber über die Schnittstelle der Klasse nicht implementiert sind. Außerdem fängt diese Funktion Exoten ab, wie beispielsweise Ereignisse welche ungünstigerweise ebenso benannt sind wie der Konstruktor der Klasse selbst, oder solche, welche von der Basisklasse "plugin" geerbt wurden und somit nicht zur vom Nutzer definierten Schnittstelle der Klasse gehören können. Dies betrifft aus Sicherheitsgründen auch solche, welche in der abgeleiteten Klasse reimplementiert werden. Der Grund hierfür ist, dass diese Methoden öffentlich sind. Sie sind somit Teil einer gemeinsamen Schnittstelle aller von der Klasse "plugin" abgeleiteten Klassen. Ihre Funktionalität wird folglich gewissermaßen durch die Implementierung der Basisklasse vorgegeben und zugesichert. Sie sollte auch in den abgeleiteten Klassen erhalten bleiben.
Um eine Funktion zu erzeugen, die nicht in der öffentlichen Schnittstelle auftauchen soll, kennzeichnen sie diese Funktion als "private".
Bitte beachten: damit die neuen Funktionen verfügbar werden, müssen Sie den Plugin-Cache erneuern. Dazu loggen Sie sich als Administrator ein und klicken im Administrationsmenü auf "Liste neu laden".
Die "Setup-Menüs" finden Sie im Administrationsmenü in der Spalte "Optionen" (links), wie in folgender Abbildung.
Um den Menüeintrag und das dazu passende Setup zu erzeugen, genügt ein Eintrag in der Konfigurationsdatei des Plugins und ein HTML-Template. Es ist dazu nicht erforderlich PHP-Code zu schreiben. Betrachte Sie folgendes Beispiel der Konfigurationsdatei eines Plugins:
Datei "plugins/beispiel.config" <INFO> /* Zuerst die obligatorischen Angaben - diese haben mit dem * Setup-Menü noch nichts zu tun. */ <ID>foo</ID> <NAME>Foo plugin</NAME> <AUTHOR>Thomas Meyer</AUTHOR> <DESCRIPTION>mein Beispiel-Plugin</DESCRIPTION> <LOGO>%PLUGINDIR%foo/preview.jpg</LOGO> <IMAGE>%PLUGINDIR%foo/icon.png</IMAGE> <TYPE>primary</TYPE> /* Hier folgen die Einträge für das Setup-Menü */ <SETUP> /* Der folgende Code erzeugt einen Eintrag mit * der Beschriftung "Foo Options" und dem Icon * "plugins/foo/setup1.gif". Bei Klick auf die * Schaltfläche "Setup" wird die Aktion * "foo_setup_1" ausgelöst. */ <0> <ACTION>foo_setup_1</ACTION> <TITLE>Foo Options</TITLE> </0> /* Ein zweites Beispiel: */ <1> <ACTION>foo_setup_2</ACTION> <TITLE>Bar Options</TITLE> </1> </SETUP> </INFO> <INTERFACE> /* Den Aktionen "foo_setup_1" und "foo_setup_2" * wird nun noch ein Template zugeordnet */ <foo_setup_1> /* TYPE=config definiert, dass es ein Setup-Menü ist */ <TYPE>config</TYPE> /* PERMISSION=100 beschränkt den Zugriff auf Nutzer * mit der Sicherheitsstufe 100 - das sind Administratoren. */ <PERMISSION>100</PERMISSION> /* foo_template_1 ist der Name des Templates */ <INSERT>foo_template_1</INSERT> </foo_setup_1> <foo_setup_2> <TYPE>config</TYPE> <PERMISSION>75</PERMISSION> <INSERT>foo_template_2</INSERT> </foo_setup_2> /* ... hier folgen noch eventuell andere Aktionen ... */ </INTERFACE>
Nun benötigen Sie noch eine HTML-Seite mit einem Formular, wie in folgendem Beispiel:
Datei "skins/default/beispiel.html"
<!-- Den Kopf der Datei sollten Sie einfach übernehmen. Hier gibt es nichts
zu editieren. Copy'n'Paste reicht völlig aus. -->
<!-- BEGINN: Kopf -->
<form method="POST" enctype="multipart/form-data" action="[%$PHP_SELF%]">
[%if !$ID%][%if $PERMISSION==100%]
<input type="hidden" name="action" value="set_config_profile">
[%/if%][%else%]
<input type="hidden" name="action" value="set_config_profile">
[%/if%]
<input type="hidden" name="[%$SESSION_NAME%]" value="[%$SESSION_ID%]">
<input type="hidden" name="id" value="[%$ID%]">
<!-- ENDE: Kopf -->
<!-- Nun folgt der variable Teil, den Sie selbst ausfüllen können -->
<!-- eine Überschrift macht sich gut: -->
<h1>Setup</h1>
<!-- eine Liste mit Optionen -->
<label>Option 1
<!-- $PROFILE.OPT1 ist der gespeicherte Wert für dieses Feld -
sofern bereits einmal ein Wert gespeichert wurde.
Der Modifier |entities sorgt dafür, Tag-Klammern und
Anführungszeichen in HTML-Entitäten umgewandelt werden, damit
keine HTML-Syntaxfehler entstehen können.
-->
<input type="text" name="opt1" value="[%$PROFILE.OPT1|entities]">
</label><br>
<label>Option 2
<input type="text" name="path.opt2" value="[%$PROFILE.PATH.OPT2|entities]">
</label><br>
<label>Option 3
<input type="text" name="opt3" value="[%$PROFILE.OPT3|entities]">
</label><br>
<!-- die Schaltfläche zu Abschicken nicht vergessen -->
<input type="submit" value="[%$LANGUAGE.SPEICHERN%]">
</form>
Diese HTML-Seite bewirkt, dass nach dem Abschicken des Formulars folgendes Array gespeichert wird:
<?php
$PROFILE = array(
'opt1' => "foo",
'path' => array(
'opt2' => "bar"
),
'opt3' => "foobar"
);
?>
Sie können in Ihrem Plugin wie folgt auf die gespeicherten Optionen zugreifen:
<?php
global $YANA;
$opt1 = $YANA->getVar('PROFILE.OPT1');
$path_opt2 = $YANA->getVar('PROFILE.PATH.OPT2');
$opt3 = $YANA->getVar('PROFILE.OPT3');
?>
Damit das Formular "beispiel.html" bei Klick auf die Schaltfläche "Setup" auch angezeigt wird, muss es mit der Aktion "foo_setup_1" verknüpft werden. Dies geht wie folgt:
Datei "skins/default/beispiel.config"
<!-- Hier wird zunächst das Template unter dem Namen "foo_template_1" definiert ... -->
<foo_template_1>
<FILE>beispiel.html</FILE>
</foo_template_1>
Datei "plugins/beispiel.config"
...
<INTERFACE>
<foo_setup_1>
<TYPE>config</TYPE>
<PERMISSION>100</PERMISSION>
<!-- ... und hier wird das Template "foo_template_1" der Aktion "foo_setup_1" zugeordnet. -->
<INSERT>foo_template_1</INSERT>
</foo_setup_1>
...
</INTERFACE>
Thomas Meyer, www.yanaframework.net