Pimcore Formbuilder Brick

Lukas [Pimcore, php, Datenbanken, Tricks und Tools]

Um Formulare für Pimcore zu erstellen, gibt es das Form builder plugin. Das integriert sich gut in das Pimcore Webinterface und ist somit in der Handhabung schnell zu erlernen. So können die Kunden selbst neue Formulare anlegen und bestehende bearbeiten. Was sie aber nicht einfach so von Haus aus selbst können ist neue Formulare auf beliebigen Seiten zu integrieren.

Damit das doch geht haben wir ein Brick entwickelt, dass es den Kunden erlaubt an beliebiger Stelle an welcher ein areablock zum Zuge kommt ein Formular in die Seite einzufügen.

Das area.xml

Dazu gibt es nichts zu erklären, da das xml mit dem Minimum auskommt.

<?xml version="1.0"?>
<zend-config xmlns:zf="http://framework.zend.com/xml/zend-config-xml/1.0/">
    <id>form</id>
    <name>Formular</name>
    <description></description>
    <version>1.0</version>
</zend-config>

Die view.php

Die view ist derweil etwas komplexer. Als erstes kommt ein Schnipsel für die Darstellung, da ich den Standard Zend_Form Decorator, der auf dd und dt Tags aufbaut, nicht mag. Das ist Geschmacksache und als optional zu betrachten. Unser Decorator erstellt eine Tabelle rund um das Formular. Folgende Variabeln werden später im Code referenziert.

$buttonDecorators = array(
    'ViewHelper',
    array(array('data' => 'HtmlTag'), array('tag' => 'td', 'class' => 'element')),
    array(array('label' => 'HtmlTag'), array('tag' => 'td', 'placement' => 'prepend')),
    array(array('row' => 'HtmlTag'), array('tag' => 'tr')),
);

$elementDecorators = array(
    'ViewHelper',
    'Errors',
    array(array('data' => 'HtmlTag'), array('tag' => 'td', 'class' => 'element')),
    array('Label', array('tag' => 'td', 'tagClass' => 'lbl')),
    array(array('row' => 'HtmlTag'), array('tag' => 'tr')),
);

$formDecorators = array(
    'FormElements',
    array('HtmlTag', array('tag' => 'table', 'class' => 'form')),
    'Form',
);

Als nächstes gilt es das Formular zu wählen und einige Einstellungen dem Bearbeiter der Seite zu präsentieren. So kann man wählen, an welche E-Mailadresse das Formular geschickt wird. Zudem noch die Betreffzeile sowie der Text, der nach dem abschicken des Formulares zur Bestätigung angezeigt werden wird.

$formName = $this->select("formName", array("store" => $formStore));
$reciever = $this->input("reciever");
$subject = $this->input("subject");
$thankYouText = $this->wysiwyg("thankYouText");

if ($formName instanceof Document_Tag_Select);
if ($reciever instanceof Document_Tag_Input);
if ($subject instanceof Document_Tag_Input);
if ($thankYouText instanceof Document_Tag_Wysiwyg);

if ($this->editmode) {
    echo '<h2>Formularname</h2>';
    echo $formName;
    echo '<hr/>';
    echo '<h2>E-Mailadresse des Empfängers des Formulars</h2>';
    echo $reciever;
    echo '<hr/>';
    echo '<h2>Betreff des Benachrichtigungs E-Mail</h2>';
    echo $subject;
    echo '<hr/>';
    echo '<h2>Text nach dem Absenden des Formulars</h2>';
    echo $thankYouText;
} else {
    [...]
}

Gleich zu Beginn hat sich eine Variable $formStore eingeschlichen. Die wird zuvor mit den vorhandenen Formularen des Form builder Plugins befüllt, so dass der CMS User eine einfache Auswahl erhält. Doch dazwischen noch eine Erklärung: Der gewiefte Leser wird sich vielleicht Fragen, was Zeile 6-9 soll. Eine if-Abfrage ohne jegliche Aktion. Diese besteht einzig und allein, damit die Eclipse beim versuch der Autovervollständigung weiss, was für eine Klasse das Objekt in der Variable haben soll. Anhand derer präsentiert sich automatisch die Auswahl an möglichen Methoden. So lässt es sich einfacher programmieren. Dies ist nötig, weil innerhalb einer Pimcore view gegen $this programmiert wird. Ohne Kontext kann eine IDE an der Stelle nicht wissen was $this->input zurückgeben soll.

$fb = new Formbuilder_Formbuilder();
$rows = $fb->read();
$formStore = array();
if ($rows instanceof Zend_Db_Table_Rowset) {
    foreach ($rows->toArray() as $row) {
        $formStore[] = $row['name'];
    }
}

Via Formbuilder_Formbuilder Objekt werden die Formular-Einträge in der Datenbank geladen und können so dem User zur Auswahl im editmode präsentiert werden.

Der else-Teil: zeige und verarbeite das Formular

Als erstes erstellen wir ein Session-Objekt. Auf dem Objekt speichern wir ganz am Ende die aktuelle Zeit. Wozu wir das machen später mehr.

[...]
} else {
    $mySession = new Zend_Session_Namespace('formareatimer',true);
    [...]
    $mySession->time = time();
}

Es folgt das Laden des Formulars sowie der optionale Teil mit dem Wechseln der Decoraters.

$formbuilder = new Formbuilder_Frontend();
$form = $formbuilder->getForm($formName, "de");

$form->setDecorators($formDecorators);
$form->setElementDecorators($elementDecorators);
$element = $form->getElement('submit');
$element->setDecorators($buttonDecorators);

Sobald der Request mitgeschickte POST Daten enthält werden eine einige Tests gemacht. Zuerst mal, ob die eingegebenen Daten überhaupt gemäss den im Plugin erstellen Regeln überhaupt gültig sind. Als nächstes klärt sich das Mysterium der Session Variable mit der Zeit. Es gibt Bots die nach dem Erkennen eines Formulares direkt POST Requests an die Ziel-URL senden ohne die Formularseite ein weiteres mal auf zu rufen. Dann gibt es einige klügere die das machen, aber viel zu schnell sind.

Da ein Formular in der Regel etwas sinnvolles enthält, benötigt ein Mensch mit grosser Wahrscheinlichkeit mehr als 10 Sekunden um es aus zu füllen und ab zu schicken. Mit diesem einfachen Trick bremst man Spam-Bots einfach aus. Zumindest unserer Erfahrung nach haben wir weder Spam über so geschützte Formular noch Beschwerden, dass das Formular nicht funktionieren würde.

if ($this->getRequest()->isPost()) {
    if (!$form->isValid($this->getRequest()->getPost())) {
        // Failed validation; redisplay form
    } elseif ($mySession->time == 0) {
        $formErrors[] = "Sie haben die Formularseite noch gar nicht angesehen und sind vermutlich ein Roboter! Bitte warten Sie 10 Sekunden und drücken Sie nochmals auf senden.";
    } elseif (time() - $mySession->time < 10) {
        $formErrors = array("Sie haben das Formular zu schnell abgeschickt und sind vermutlich ein Roboter! Bitte warten Sie 10 Sekunden und drücken Sie nochmals auf senden.");
   
    [...]
       
} else {
    echo $form;
}

Weiter gehts. Alles ist ok, deshalb kann nun ein E-Mail an den Konfigurierten Empfänger gehen. Dies wird ganz einfach über die Pimocore_Tool Klasse erledigt. Falls erfolgreich
kann nun der Dankestext angezeigt werden. Falls nicht wird das Formular erneut angezeigt.

} else {
    //send email
    $values = $form->getValues();
    $txt = array();
    foreach ($values as $key => $value) {
        if (is_array($value)) $value = "n- ".join("n- ", $value);
        $txt[] = $key.': '.$value;
    }
    $mail = Pimcore_Tool::getMail($reciever->getValue(), $subject->getValue());
    $mail->setBodyText(join("n", $txt));
    $mail->send();
   
    $mailSent = true;
   
    echo $thankYouText;
}

if (!$mailSent) {
    echo $form;
}

Fertig ist der Form-Brick. Damit kann nun jemand, der selbständig Seiten mit Pimcore anlegen kann, auch einfache Formulare erstellen und in die
Seite integrieren.

zurück