xform kann mehr – Anwendungen für das Formularaddon von Redaxo

xform ist das Addon für die Erstellung von Formularen in Redaxo. Das Addon wird von Jan Kristinus entwickelt und gepflegt. Es gilt aber als schlecht – oder darf man sagen nicht? – dokumentiert, was aber eigentlich auch gar nicht wirklich stört. Vor einiger Zeit hatte ich einen Spamschutz als Honeypot entwickelt, der sich schon auf vielen Websites bewährt.

Eigene Inhaltselemente für xform

Zunächst einmal erweitern wir xform um eigene Inhaltselemente. Das ist einfacher, als es zunächst aussieht. Wir wollen ein Textfeld aus einer Get-Variablen vorbelegen. Zunächst einmal müssen wir uns überlegen, wo wir das neue Inhaltselement unterbringen wollen. Es liegt natürlich nahe, dies direkt bei den anderen Inhaltselementen unter addons/xform/classes/values abzulegen. Das hat allerdings den Nachteil, dass es eventuell bei einer kompletten Neuinstallation von xform verloren geht. Daher können wir es auch einfach in einem eigenen Addon unterbringen. Hierzu schreiben wir in die config.php des eigenen Addons diese zwei Zeilen:

// Hier werden Inhaltsklassen gesucht
$REX['ADDON']['xform']['classpaths']['value']['eigenes_addon'] = $REX["INCLUDE_PATH"]."/addons/eigenes_addon/xform/value/";

// Hier werden Templates gesucht
$REX['ADDON']['xform']['templatepaths']['eigenes_addon'] = $REX["INCLUDE_PATH"]."/addons/eigenes_addon/xform/templates/";

Damit findet xform Inhaltselemente von nun an auch in den angegebenen Verzeichnissen. Die erste Zeile gibt an, wo Inhaltsklassen gesucht werden, die zweite Zeile gibt an, wo Templates gesucht werden.

Nun nehmen wir ein bereits vorhandenes Inhaltselement, welches unseren Wünschen weitestgehend entspricht, kopieren es und benennen es um. Hierzu verwenden wir die Datei addons/xform/classes/values/class.xform.text.inc.php, kopieren sie in das eigene xform/value Verzeichnis und benennen sie in class.xform.text_request.inc.php um. Die Klasse wird umbenannt und wir benennen auch gleich alle Bezeichnungen in den Funktionen getDescription und getDefinitions um. Nun müssen wir nur noch den Defaultwert aus der Get-Variablen holen und einsetzen. Der fertige Code sieht so aus:

<?php
class rex_xform_text_request extends rex_xform_abstract
{
function enterObject()
{
$this->setValue((string) $this->getValue());

if ($this->getValue() == '' && !$this->params['send']) {
if ($this->getElement(7) == 'get') {
$this->setValue(rex_get($this->getElement(6)));
} elseif ($this->getElement(7) == 'post') {
$this->setValue(rex_post($this->getElement(6)));
} else {
$this->setValue(rex_request($this->getElement(6)));
}
}

$this->params['form_output'][$this->getId()] = $this->parse('value.text.tpl.php');
$this->params['value_pool']['email'][$this->getName()] = stripslashes($this->getValue());
if ($this->getElement(4) != 'no_db') {
$this->params['value_pool']['sql'][$this->getName()] = $this->getValue();
}
}

function getDescription()
{
return 'text_request -> Beispiel: text_request|name|label||[no_db]|cssclassname|request_value|[post,get,request]';
}

function getDefinitions()
{
return array(
'type' => 'value',
'name' => 'text_request',
'values' => array(
'name' => array( 'type' => 'name', 'label' => 'Feld' ),
'label' => array( 'type' => 'text', 'label' => 'Bezeichnung'),
'default' => array( 'type' => 'text', 'label' => '-leer-'),
'no_db' => array( 'type' => 'no_db', 'label' => 'Datenbank', 'default' => 0),
'css_class' => array( 'type' => 'text', 'label' => 'cssclassname'),
'request_value' => array( 'type' => 'text', 'label' => 'cssclassname'),
),
'description' => 'Ein einfaches Textfeld als Eingabe',
'dbtype' => 'text',
'famous' => true
);

}
}

Formulare in andere Artikel einbinden

Es kommt schon öfter vor, dass man ein Kontaktformular an zentraler Stelle definieren möchte und in beliebigen anderen Artikeln einbinden möchte. Das geht auch einfach. Man braucht nur ein Modul, welches einen Artikel einbindet. Die Moduleingabe ist ein Einzeiler: REX_LINK_BUTTON[1]

Die Ausgabe ist ebenso einfach:

<?php
$art = new rex_article();
$art->setArticleId("REX_LINK_ID[1]");
echo $art->getArticle;
?>

Wenn man nun das Formular definiert, einbindet, ausfüllt und abschickt, so funktioniert der Mechanismus zwar, man landet aber auf der Seite, auf der das Formular definiert wurde. Das kann unerwünscht sein. Beispielsweise, wenn es um ein Anmeldeformular zu einem Kurs geht, dann sollten die Kursdaten noch sichtbar sein.

Der einfachste Weg dies zu bewerkstelligen führt über das XForm Ausgabemodul. Die Eingabeseite erweitern wir um ein zusätzliches Feld. Entweder um einen REX_LINK_BUTTON oder um ein Textfeld.

Nun ändern wir noch die Modulausgabe. Die Zielseite des Formulars wird in dieser Zeile festgelegt:

$xform->setRedaxoVars(REX_ARTICLE_ ID,REX_CLANG_ ID);

Wenn wir den Wert REX_ARTICLE _ID mit einem eigenen Wert versorgen, übernimmt den Rest xform.

Noch bequemer geht es, wenn man im Template die Artikel Id in $REX ablegt. z.B. $REX['my_article_id'] = $REX['ARTICLE_ID']

Dann kann man die Ausgabeseite des XForm Moduls so anpassen (vereinfacht):

if ($REX['my_article_id']) {
$xform->setRedaxoVars($REX['my_article_id'],REX_ CLANG_ID);
} else {
$xform->setRedaxoVars(REX_ ARTICLE_ID,REX_ CLANG_ID);
}

xform steckt weiterhin voller Geheimnisse. Vielleicht nicht ganz so intuitiv ist es – daher hier eine explizite Erwähnung, wie man an die Values in einer Funktion oder Methode kommt, die über einen Extensionpoint aufgerufen wird.

In der Config des Addons steht dann beispielsweise:

rex_register_extension('XFORM_DATA_UPDATED', 'meine_klasse::meine_methode');

Die Parameter werden übergeben. Der Valuepool ist dann unter

$params['subject']->objparams['value_pool']

zu finden.

Werden die vom Formular übertragenen Werte in einer eigenen action|callback|…. Funktion benötigt, so bekommt man diese beispielsweise mit

$params->params['value_pool']

Eigene Spalte in XForm List definieren

Ich lege zunächst im Tablemanager eine “blinde” Spalte an, eine Spalte also, die nicht in der Datenbank gespeichert wird. Dann in der Config des Addons die Liste erweitern.

rex_register_extension('XFORM_DATA_LIST', 'meineklasse::meinestatischefunktion');

In meiner Klasse steht dann:

   public static function meinesatischefunktion ($params) {
$list = $params['subject'];
$list->setColumnFormat('meinfeldname','custom','meineklasse::meinelinkfunktion');
}

public static function meinelinkfunktion ($params) {
return '<a class="cssklasse" href="index.php?function=meinefunktion&id=###id###">Beschreibung</a>';
}

XForm ersetzt dann den Platzhalter ###id### durch den Wert.

Nach so einem flexiblen Tool muss man übrigens in anderen Systemen lange suchen.

Danke Jan, für dieses coole Addon!