Voraussetzungen für das Erstellen einen Kontaktformulars in GRAV

Informationen zum Erstellen findet man auch im GRAV-Tutorial.

Das Form-Plugin von gravity muss installiert und aktiviert sein.

Das Mail-Plugin von gravity muss installiert und konfiguriert sein. Hier müssen die E-Mail-Adressen eingetragen werden, an die das Formular seine Daten schickt und wer als Absender übergeben werden soll. Bisher war es ausreichend den PHP-Mailer zu verwenden.

Das Formular wurde als Inhalt auf der Home-Page platziert. Dazu muss zuerst für die Site der Template-Type Form ausgewählt werden. Infolge dessen wird die default.md im Verzeichnis user/pages/01.home ersetzt durch eine Datei form.md.

Register Options:

  • Folder Numeric Prefix: enabled (das setzt eine Nummer vor den Ordner und ermöglicht zum einen die Sortierung zum anderen wird diese Seite dann sofort auch als Menüeintrag im Hauptmenü erscheinen.)
  • Folder Name: kontaktformular
  • Parent: -Root-
  • Display Template: Form

Danach muss im Feld Frontmatter im Expert-Modus für die Page nachfolgender Inhalt eingesetzt (s.u.). Über das Template-Layout wird der Page Content eingeblendet im Mainbar.

 Register Content im Feld Formmatter:

title: Home
form:
    name: contact
    fields:
        -
            name: name
            label: 'Vor- und Nachname'
            placeholder: 'Geben Sie hier Ihren Namen ein.'
            autofocus: 'off'
            autocomplete: 'on'
            type: text
            validate:
                required: true
        -
            name: telefonnummer
            label: Telefonnummer
            placeholder: 'Wie kann ich Sie telefonisch erreichen?'
            autocomplete: 'on'
            type: text
            validate:
                required: true
        -
            name: email
            label: E-Mail
            placeholder: 'Geben Sie hier Ihren E-Mail-Adresse ein ein'
            type: email
            validate:
                required: true
        -
            name: message
            label: Nachricht/Frage
            placeholder: 'Ihr Nachricht oder Frage an mich'
            type: textarea
            validate:
                required: false
        -
            name: erstkontakt
            label: Erstkontakt
            placeholder: 'Wie haben Sie von mir erfahren?'
            type: textarea
            validate:
                required: flase
        -
            name: g-recaptcha-response
            label: Captcha
            type: captcha
            recaptcha_not_validated: 'Captcha ist nicht korrekt!'
            validate:
                required: true
    buttons:
        -
            type: submit
            value: Absenden
    process:
        -
            captcha: null
        -
            email:
                subject: '[Site Contact Form] {{ form.value.name|e }}'
                body: '{% include ''forms/data.html.twig'' %}'
        -
            save:
                fileprefix: contact-
                dateformat: Ymd-His-u
                extension: txt
                body: '{% include ''forms/data.txt.twig'' %}'
        -
            message: 'Vielen Dank für Ihrer Nachricht.'
        -
            display: thankyou

Im Register Content im Inhalt Editorfeld kann weiterer Seiteninhalt stehen:

# Mein Kontaktformular separate Seite über Menü
Regular **markdown** content goes here...

Das was hinter title: steht wird als Menüeintragtext verwendet und gleichzeitig als SiteName im Browser-Tab angezeigt. Hier sollte eine aussagekräftiger SEF-tauglicher Title stehen. Wenn dieser aber zu lang ist, um auch als Menüeintrag zu funktionieren, muss das in der Gantry5-Menü-Konfiguration für diesen Menüeintrag im Titlefeld ganz oben geändert werde.

Das was hinter form: name: steht wird, als Formular-Name im HTML-Output verwendet.

Alternativ kann die Seite und ihr Formular auch per phpStorm bearbeitet werden durch Scripten von user/pages/01.Home/form.md.

 

Einbinden reCaptcha

Das Fomular-Plugin von GRAV kennt schon sehr viele verschiedene Feldtypen, u.a. ist auch der Typ Captcha vorhanden und kann einfach eingebunden werden. Um ein reCaptcha in ein Formular einzubinden, gibt es zwei Möglichkeiten um die reCaptcha-Keys zu hinterlegen. Entweder global im Form-Plugin oder im Seiten-Formular.

Im Seitenformular wie erfolgt das wie oben im Beispieltext von Frontmatter zu erkennen durch die beiden Parameter recaptcha_site_key und recaptcha_secret_key

        -
            name: g-recaptcha-response
            label: Captcha
            type: captcha
            recaptcha_site_key: 6Lcf1hQUAAAAAL4hWp0pwbBHGny2Sznn2ucLoFOt
            recaptcha_not_validated: 'Captcha ist nicht korrekt!'
            validate:
                required: true

 

Das kann auch wie oben beschrieben in der form.md editiert werden.

Besser jedoch ist es den Site-Key hier einfach wegzulassen und statt dessen nur im Form-Plugin als globale Einstellung zu hinterlegen. Wenn das über das Form-Plugin erfolgt, dann muss über den Menüpkt Plugins > Form in der Gruppe ReCaptcha die Schlüssen reinkopiert werden.

Verantwortlich für die Ausgabe ist das html-Template user/plugins/form/templates/forms/fields/captcha/captcha.html.twig. In diesem werden die Key eingebunden entweder aus dem Page-form.md per

{{ field.recaptcha_site_key }}
{{ config.plugins.form.recaptcha.site_key }}

oder als Pluginparameter:

{{ field.recaptcha_secret_key }}
{{ config.plugins.form.recaptcha.secret_key }}

Das verantwortliche Prozess-Script für die Formularanzeige und Verarbeitung ist user/plugins/form/form.php. Achtung, hier gab es einen Schreibfehler bei Variablenbezeichnern (statt recaptcha stand recatpcha). Der Fehler ist zwar bekannt und angeblich auch behoben, tauchte aber trotzdem wieder auf.



 

Fehler im Script: user/plugins/form/form.php

Achtung! Ich hatte tagelang gesucht, warum das Formular bei jedem Sendeversuch immer den Fehler liefert, dass der Schlüssel nicht übereinstimmt. Google-reCaptcha sendet hier ein JSON-Array zurück mit diesem Inhalt:

{ [“success”]=> bool(false) [“error-codes”]=> array(1) { [0]=> string(22) “missing-input-response” } }

Als Ursache für die Ablehnung konnte ich dann endlich feststellen, dass der Request (query) an Google nicht korrekt kodiert war. Im o.g. Script wird zum Zusammenbauen des query http_build_query() verwendet. Auf manchen Servern verhält sich http_build_query($foo) aber anders (so z.B. ohne Probleme auf meinem Hetzer-Server und mit Problemen auf meinem HostEurope-Server), nämlich das & wird zur Verknüpfung der GET-Parameter für den Ajax-Request durch & ersetzt. Das akzeptiert Google-reCaptcha nicht! Nach Studium der Joomla-ReCaptcha, konnte ich feststellen, dass Joomla stattdessen das Konstrukt: urlencode(stripslashes($foo)) verwendet und damit saubere „&“.

Wie nachfolgend zu sehen habe ich das Script umgeschrieben. Ob die beiden neuen Array-Elemente remoteip und v wirklich notwendig sind, ist zu bezweifeln. So jedenfalls in Google-Dokumentationen gesehen.

                $query = "";
                
                // modif. generat array for later use in foreach
                 $queryArr = array(
                    'secret'   => $recaptchaSecret,
                    'response' => $form->value('g-recaptcha-response', true),
                    'remoteip' => $_SERVER['REMOTE_ADDR'],
                    'v'        => 'php_1.0',
                );
                // bad solution:
                $query = http_build_query($queryArr);
                
                // replacing better solution:
                foreach ($queryArr as $key => $value) {
                    $query .= $key.'='. urlencode(stripslashes($value)).'&';
                }
                // echo '<br />$query new/solved:'.
                $query = substr($query, 0, strlen($query) - 1);
                // echo '<br />$url: '.
                    $url = 'https://www.1d5920f4b44b27a802bd77c4f0536f5a-gdprlock/recaptcha/api/siteverify?' . $query;

                $responseStrg = file_get_contents($url);

Den Fehler hatte ich hier im GRAV-Forum gepostet. https://discourse.getgrav.org/t/error-validating-the-captcha/2886/3 wird aber leider ignoriert.

In der Version 2.10 des Form-Plugins wurden diverse Änderungen in diesem Script von den Core-Entwicklern vorgenommen. Beim Update stellte sich heraus, dass oben beschriebener Fehler nach wie vor auftritt. Deshalb wurden auch in dieser Version von mir die Änderungen nachgepflegt:

Diese Zeile:

                $query = http_build_query([
                    'secret'   => $recaptchaSecret,
                    'response' => $form->value('g-recaptcha-response', true)
                ]);

wurden ersetzt durch folgende:

                $query = '';
                $queryArr = array(
                    'secret'   => $recaptchaSecret,
                    'response' => $form->value('g-recaptcha-response', true),
                    'remoteip' => $_SERVER['REMOTE_ADDR'],
                    'v'        => 'php_1.0',
                );
                foreach ($queryArr as $key => $value) {
                    $query .= $key . '=' . urlencode(stripslashes($value)) . '&';
                }
                $query = substr($query, 0, strlen($query) - 1);

 

Das Speichern der Formulardaten:

Wenn die Formulardaten gespeichert werden sollen, muss dafür das Verzeichnis user/data/kontaktformular_homepage angelegt werden. Der Pfadname ist abhängig vom Parameter form: > name: in der user/pages/01.home/form.md und muss hiermit identisch übereinstimmen. Es entstehen dann dort mit jedem sendeten Formular eine Text-Datei feedback-datum-zeit.txt.

 

Rückmeldeseite

Wenn das Formular gesendet wurde, kann man eine Seite ausliefern, die Ein Feedback liefert – eine sogenannte – Danke-Seite. Welche Seite das ist kann ebenfalls in der user/pages/01.home/form.md festgelegt werden unter form: > process: > display: Hier kann dann z.B. thankyou stehen (ist auch üblicher Standard). Diese Angabe ist als Pfadangabe zu verstehen. Wenn hier nur thankyou steht, dann muss es einen Pfad user/pages/thankyou in dem dann die Scripte liegen, entweder eine formdata.md oder eine formdata.html.twig. Andere Strukturen entstehen, wenn z.B. /thankyou im form.md als Zielseite steht (s. Tutorial).

Leider funktioniert hier nicht alles korrekt. Es wird z.T. immer englischer Text ausgegeben, obwohl in den Sprachdateien deutsche Übersetzungen vorhanden (user/plugins/form/languages.yaml). Auch soll eigentlich eine overriding funktionieren, aber scheinbar wird o.g. formdata.html.twig nicht so verwendet wie aus den Tutorials zu erkennen.

In der Dokumentation steht, dass man als Rückmeldeseite unter dem eigentlichen Formular-Ordner eine Unterseite anlegen soll – also somit auch eine Unterordner. Das funktionierte auch gut, wenn die Formularseite selbst nicht die Startseite ist, sondern über einen Menüpunkt als Unterseite erreichbar ist (Beispiel: user/pages/02.kontaktformular-separte-seite/dank-kontaktanfrage/default.md) Hier wird also noch dem Senden die default.md verwendet als Dankeseite.

 

Feedback-DankeSeite mit Ausgabe der Formular-Daten:

Wenn einfach nur eine default.md abgelegt wird, dann werden vermutlich keine Daten gefetched. Demgegenüber wird im Fall einer formdata.md auch die Formulardaten in der Dankeseite mit ausgegeben.

 

Die Mail-Templates

Auch die rausgehenden Mails beim Absenden des Formulars können indiv. gescriptet werden. Damit habe ich wg. fehlender Aufgabenstellung jedoch noch nicht beschäftigt.

 

Einbetten eines Formulars auf eine bestehende Seite als Custom-HTML-Particle - Alternative.

Um das Formular einzubinden, kann man einfach im Layout des der Seite zugewiesenen Templates ein Custom-HTML-Particle platzieren. In diesem kommt dann im Feld Custom HTML folgender Inhalt:

{% include "forms/form.html.twig" with { form: forms('Kontaktformular') } %}

Das Optionsfeld Process Twig muss aktiviert werden damit der obige Inhalt verarbeitet wird statt als Inhalt anzuzeigen.