Formular-Finisher zum TYPO3 Backend-Editor hinzufügen

veröf­fent­licht am 05 August 2017

Der umständ­liche und undoku­men­tierte Weg eigene Finisher in den neuen Typo3 8.7 Formu­lar-E­ditor hinzu­zu­fü­gen.

Es gibt viele Gründe weshalb man einen weiteren Finisher brauchen würde. Mein Grund war eine Clever­reach integra­tion. Leider ist die TYPO3 Api etwas unnötig kompli­ziert gestall­tet. Ein einfa­ches ValidatorInterface kombi­niert mit einer ext_lo­cal­con­f.php methode FormUtility::addValidator war wohl zu einfach.

Das Ergebnis im TYPO3-Ba­ckend soll dann am Ende ungefähr so aussehen:

Die Finisher Klasse

Als erstes würde ich den Finisher anlegen. Wenn man sich die mitge­lie­ferten Finisher als Beispiel nimmt, gehören unsere in Classes\Model\Finishers. Wenn du ein relativ gutes Beispiel suchst, wie ein funktio­nie­render Finisher aussieht, würde ich mich an den EmailFinisher und den RedirectFinisher halten.

namespace Vendor\VendorExtension\Domain\Finishers;

use TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher;

class CleverreachSubscribeFinisher extends AbstractFinisher
{
    /**
     * Dies sind die Optionen die wir später haben wollen.
     * 
     * @var array
     */
    protected $defaultOptions = [
        'apiKey' => '',
        'email' => ''
    ];

    /**
     * Hier kommt unsere schöne Logik hin.
     */
    protected function executeInternal()
    {
        // liefert alle formular werte
        $this->finisherContext->getFormValues();
        // holt die Option apikey, die wir später definieren
        $this->parseOption('apiKey');
        
        // die exakte implementierung zeige ich hier nicht
        // die wird ehh je nach anforderung unterschiedlich sein 
    }
}

Form Framework Konfiguration

Wir brauchen 3 Yaml Dateien um den Finisher zu regis­trie­ren. Die Form Exten­sion packt diese in Configuration/Yaml. Ich persöhn­lich würde den Ordner aller­dings Form nennen um ein wenig klarheit zu schaffen für was die Confi­gu­ra­tion ist.

Ich zeig hier einfach beispiel­haft yaml Datein. Ich definiere hier nur 2 Felder um die Dateien kurz zu halten, es ist so schon lang genug.

# BaseSetup.yaml
TYPO3:
  CMS:
    Form:
      prototypes:
        standard:
          finishersDefinition:
            CleverreachSubscribe:
              implementationClassName: 'Vendor\VendorExtension\Domain\Finishers\CleverreachSubscribeFinisher'
# FormEditor.yaml
TYPO3:
  CMS:
    Form:
      prototypes:
        standard:
          formElementsDefinition:
            Form:
              formEditor:
                editors:
                  900:
                    # Diese Definition erweitert das Dropdown der Finisher im menü
                    selectOptions:
                      35:
                        value: 'CleverreachSubscribe'
                        label: 'Cleverreach Subscribe'
                propertyCollections:
                  finishers:
                    # Hier wird definiert, welche Felder der Finisher später haben soll
                    25:
                      identifier: 'CleverreachSubscribe'
                      editors:
                        __inheritances:
                          10: 'TYPO3.CMS.Form.mixins.formElementMixins.BaseCollectionEditorsMixin'
                        100:
                          label: "Cleverreach Subscribe"
                        # Das ist die Definition für die darstellung von apiKey im Backend
                        110:
                          identifier: 'apiKey'
                          templateName: 'Inspector-TextEditor'
                          label: 'apiKey'
                          propertyPath: 'options.apiKey'
                          propertyValidators:
                            10: 'NotEmpty'
                        # Und das hier ist die definition für das email feld.
                        # Es hat die Besonderheit, dass ein Feld aus dem Formular ausgewählt werden kann
                        # Es wird dann sowas wie {input-1} gespeichert.
                        # ->parseOption('email') im Finisher löst die Referenz dann auf
                        # und gibt den Wert von input-1 zurück.
                        140:
                          identifier: 'email'
                          templateName: 'Inspector-TextEditor'
                          label: 'Subscribers email'
                          propertyPath: 'options.email'
                          enableFormelementSelectionButton: true
                          propertyValidators:
                            10: 'NotEmpty'
                            20: 'FormElementIdentifierWithinCurlyBracesInclusive'
                            
          # Hier ist definiert welche optionen das javascript im backend beim hinzufügen lädt.
          # Am besten sollten es die selben sein wie in finisher. 
          finishersDefinition:
            CleverreachSubscribe:
              formEditor:
                iconIdentifier: 't3-form-icon-finisher'
                label: 'A Label that seems to be never used...'
                predefinedDefaults:
                  options:
                    apiKey: ''
                    email: ''
# FormEngineSetup.yaml
TYPO3:
  CMS:
    Form:
      prototypes:
        standard:
          finishersDefinition:
            CleverreachSubscribe:
              FormEngine:
                label: "When is this label used? And for what?"
                elements:
                  # hier nochmal alle Felder
                  # ich habe keine Ahnung wofür diese sind aber ohne geht es nicht
                  # spontan würde ich behaupten das es tca configuration ist
                  # aber ich definiere keine Datenbank Felder ~ vielleicht ist das aber eine Option
                  apiKey: {label: apiKey, config: {type: input}}
                  email:  {label: email , config: {type: input}}

Und das war so ziemlich der nervigste Teil. Jetzt müssen wir nur noch unsere yaml Dateien regis­trie­ren. Dafür brauchen wir wieder gutes altes TypoScript.

# frontend configuration
plugin.tx_form.settings.yamlConfigurations {
    1499086547 = EXT:extension/Configuration/Form/BaseSetup.yml
    1499088215 = EXT:extension/Configuration/Form/FormEngineSetup.yml
}
# backend configuration
module.tx_form.settings.yamlConfigurations {
    1499086547 = EXT:extension/Configuration/Form/BaseSetup.yml
    1499086867 = EXT:extension/Configuration/Form/FormEditorSetup.yml
    1499088215 = EXT:extension/Configuration/Form/FormEngineSetup.yml
}

Zusammenfassung

Im Endef­fekt ist es nicht sehr kompli­ziert wenn man weiß was man tun muss. Das nervigste ist, dass alles mehrfach definiert werden muss. Das hinzu­fügen einer Option muss an 4 Stellen über 3 Dateien einge­tragen werden. Auch die pfade zu den Werten lassen sich nicht sonder­lich gut merken. Ich vermute einfach, das nie daran gedacht wurde das jemand diese Api nutzt. Das würde auch das Fehlen der Dokumen­ta­tion erklären ~ bei TYPO3 ist man sich da nie sicher.