Das fünfte und letzte Vorstellungsthema zu WoltLab Suite 5.2 präsentiert zwei große Updates für Entwickler: Form Builder und mehrere Verbesserungen und neue Funktionen in den Entwickler-Werkzeugen.
Form Builder
Vor WoltLab Suite Core 5.2 musste bei der Erstellung von Formularen ähnlicher Code immer wieder geschrieben werden: die Eigenschaften des PHP-Controllers deklarieren, in die die Eingabewerte eingelesen werden, die entsprechenden Werte aus den Request-Daten auslesen, diese Werte validieren, sie einer `IDatabaseObjectAction`-Instanz übergeben, um das relevante Objekt zu erstellen oder zu bearbeiten, und die Eingabewerte abschließend Template-Variablen zuweisen. Im Template benötigte jedes Eingabefeld ein eigenes Form-Element, das im Allgemeinen bis auf das Label und die Beschreibung sehr viel Code mit ähnlichen Feldern gemeinsam hat.
Mit der neuen Version von WoltLab Suite Core haben wir eine neue Komponente hinzugefügt, die die Erstellung von Formularen deutlich vereinfacht: Form Builder. Mit Form Builder muss im Wesentlichen nur ein PHP-Objekt pro Eingabefeld erstellt werden und lediglich eine Zeile Template-Code für das gesamte Formular geschrieben werden.
Der folgende PHP-Code erstellt ein Formular mit zwei Eingabefeldern, einem einfachen Text-Feld, das ausgefüllt werden muss und dessen Wert nicht foo sein darf, und eine Ja/Nein-Auswahl (was einem boolschen Wert entspricht). Diese beiden Felder befinden sich in einem Abschnitt des Formulars, der mit wcf.global.form.data überschrieben ist.
protected function createForm() {
parent::createForm();
$this->form->appendChild(
FormContainer::create('data')
->label('wcf.global.form.data')
->appendChildren([
TextFormField::create('name')
->label('wcf.foo.name')
->description('wcf.foo.name.description')
->required()
->maximumLength(255)
->addValidator(new FormFieldValidator('notFoo', function(TextFormField $formField) {
if ($formField->getValue() === 'foo') {
$formField->addValidationError(
new FormFieldValidationError(
'isFoo',
'wcf.foo.name.error.isFoo'
)
);
}
})),
BooleanFormField::create('isCool')
->label('wcf.foo.isCool')
->value(true)
])
);
}
Display More
Formular-Controller, die Form Builder verwenden, müssen von der Klasse AbstractFormBuilderForm erben und sie müssen sowohl die Werte von $objectActionClass und $formAction setzen, als auch createForm() wie oben gezeigt überschreiben. Die save()-Methode wird automatisch aufgerufen und führt die relevante Aktion, create oder update, mit einem $objectActionClass-Objekt aus.
Im Template ist es ausreichend die getHtml()-Methode des Formulars aufzurufen:
Das Ergebnis ist das folgende Formular:
WoltLab Suite 5.2 wird bereits viele fertige Eingabefeld-Klasse mitliefern, die für die meisten Formulare ausreichend sein werden. Für spezielle Felder können Sie natürlich eigene Felder implementieren, die Sie dann auch direkt in Ihrem Paket wiederverwenden können.
Abschließend möchten wir noch kurz vorstellen, wie Sie innerhalb Ihres Formulars Abhängigkeiten zwischen Feldern definieren. In komplexeren Formularen kann es vorkommen, dass bestimmte Teile des Formulars nur dann verfügbar sein sollen, wenn ein bestimmtes Feld einen bestimmten Wert hat. Mit Form Builder lässt sich eine solche Abhängigkeit mit nur wenigen Zeilen PHP-Code realisieren:
In diesem Fall ist das $foo-Feld nur dann verfügbar, also im Formular sichtbar, wenn der aktuelle Wert des $bar-Feldes baz ist.
Form Builder kann selbstverständlich nicht nur in Controllern verwendet werden. Beispielsweise ist es auch in Dialogen möglich Formulare mit Form Builder zu erstellen. In diesen Fällen muss jedoch das IFormDocument-Objekt manuell erstellt werden (AbstractFormBuilderForm erledigt dies automatisch):
class FooAction extends AbstractDatabaseObjectAction {
/**
* @var DialogFormDocument
*/
protected $form;
/**
* @return DialogFormDocument
*/
protected function getForm() {
if ($this->form === null) {
$this->form = DialogFormDocument::create('fooDialogForm')
->appendChildren([
// append relevant containers and fields
]);
$this->form->build();
}
return $this->form;
}
public function validateGetFooForm() {
// access validation etc.
}
public function getFooForm() {
return [
// `dialog` and `formId` are required
'dialog' => $this->getForm()->getHtml(),
'formId' => $this->getForm()->getId()
];
}
public function validateSubmitFooForm() {
// access validation etc.
$this->getForm()->requestData($this->parameters['data'] ?? []);
$this->getForm()->readValues();
$this->getForm()->validate();
}
public function submitFooForm() {
// show form again in case of validation errors
if ($this->getForm()->hasValidationErrors()) {
return [
// `dialog` and `formId` are required
'dialog' => $this->getForm()->getHtml(),
'formId' => $this->getForm()->getId()
];
}
// actions based in valid form data
return [
// custom return values without any restrictions
];
}
}
Display More
<a href="#" class="button" id="openFooFormButton">{lang}wcf.foo.button.openFooForm{/lang}</a>
<script data-relocate="true">
require(['WoltLabSuite/Core/Form/Builder/Dialog'], function(FormBuilderDialog) {
var dialog = new FormBuilderDialog(
'fooDialog',
'wcf\\data\\foo\\FooAction',
'getFooForm',
{
destroyOnClose: true,
dialog: {
title: '{lang}wcf.foo.fooForm.title{/lang}'
},
submitActionName: 'submitFooForm',
successCallback: function(data) {
console.log(data);
}
}
);
elById('openFooFormButton').addEventListener('click', function() {
dialog.open();
});
});
</script>
Display More
Im obigen Code-Beispiel wird das von FooAction::getFooForm() generierte Formular nach einem Klick auf den openFooFormButton-Button in einem Dialog angezeigt. Die eingegebenen Daten werden nach dem Absenden des Formulars von FooAction::submitFooForm() verarbeitet. Bei einer fehlerhaften Validierung der Daten wird das Formular mit der entsprechenden Fehlermeldung wieder angezeigt wird. Bei einer erfolgreichen Validierung werden die Rückgabewerte der FooAction::submitFooForm() an successCallback übergeben.
Die Interfaces und Klassen von Form Builder sind umfangreich dokumentiert und wir werden unsere Entwickler-Dokumentation mit allgemeinen Informationen zu Form Builder und zur Migration alter Formulare zu neuen Form-Builder-Formularen aktualisieren.
Neue Entwickler-Werkzeuge
In der neuen Version haben wir außerdem viele neue Funktionen zu den Entwickler-Werkzeugen, die in der Administrationsoberfläche verfügbar sind, hinzugefügt.
So ist es nun möglich, Pakete direkt von der Projektliste aus zu installieren, ohne vorher ein Archiv erstellen und dann das Paket manuell in der Paketverwaltung hochladen zu müssen. Stattdessen verwenden die Entwickler-Werkzeuge direkt die Originaldateien aus dem Projekt-Verzeichnis.
Wenn ein neues Projekt angelegt wird, kann zusätzlich zum Import eines vorhandenen Pakets auch ein neues Paket erstellt werden. Dafür werden zusätzliche Formularfelder angezeigt, die alle Informationen aus der package.xml-Datei des Pakets abfragen. Beruhend auf diesen Daten wird dann auch eine package.xml-Datei für das neue Projekt erstellt. Analog zu dieser neuen Funktion beim Erstellen von neuen Projekten ist es nun auch möglich die `package.xml`-Datei vorhandener Projekte mit einer grafischen Benutzeroberfläche zu bearbeiten, die die Eingaben vor der Speicherung überprüft und so sicherstellt, dass die package.xml-Datei gültig ist.
Eine weitere neue und ziemlich umfrangreiche neue Funktion in den Entwickler-Werkzeuge ist die Möglichkeit Package Installation Plugin-Einträge mit einer grafischen Benutzeroberfläche hinzuzufügen, zu bearbeiten und zu löschen.
Die folgende animierte Grafik zeigt das Formular zum Hinzufügen eines neues Objekttypen zu einem Paket und demonstriert die Stärken der grafischen Benutzeroberfläche, da sich das Formular an die ausgewählten Objekttyp-Definition anpasst und alle zusätzlichen Felder anzeigt, die für die ausgewählte Objekttyp-Definition relevant sind.
Wenn ein Eintrag gelöscht wird, wird er aus der Datenbank entfernt und die Import-Anweisung wird gelöscht. Falls das Package Installation Plugin die Löschung von Einträgen unterstützt, ist es auch möglich, eine explizite Lösch-Anweisung ergänzen zu lassen.
Bitte beachten Sie, dass nur Package Installation Plugins, die das IGuiPackageInstallationPlugin-Interface implementieren, von der grafischen Benutzeroberfläche unterstützt werden.
Sowohl das Formular zum Hinzufügen neuer Projekte, als auch die Formulare zum Hinzufügen und Bearbeiten von Package Installation Plugin-Einträgen wurden mit Form Builder erstellt.
Damit ist unsere Vorstellungsreihe zu WoltLab Suite 5.2 zu Ende und wir hoffen, dass die vorgestellten Änderungen Ihr Interesse geweckt haben. Vor der Veröffentlichung der finialen Version werden wir noch eine Übersicht mit vielen der weiteren Änderungen in Version 5.2 bereitstellen.