YForm-Tabellen und Formulare im eigenen Addon einbinden
- 1. Zielsetzung
- 2. Zwei Schritte zum Glück
- 2.1 Die einfache Lösung
- 2.2 Die perfekte(?) Lösung
- 3. Anmerkungen
- 4. Testumgebung
1. Zielsetzung
YForm bietet sich an, Tabellen zu verwalten. Damit stehen auch jede Menge Feldtypen und Validierungen zur Verfügung. Man findet dort auch so schöne Feldtypen wie google_geomap bzw. osm_geomap zur Karteneinbindung. Und es gib eine Suchfunktion, und die Massenänderung, …
Viele Addon basieren auf eigenen Tabellen und bauen sie z.B. mit rex_form und rex_list zusammen. Nichts spricht gegen diese Vorgehensweise. Aber muss man immer auf selbstgebaute Tabellen und Formulare aufsetzen? Oder lässt sich YForm elegant nutzen? So z.B.
Hier soll gezeigt werden, wie einfach es möglich ist, per YForm verwaltete Tabellen in einem Addon so zu nutzen, als seien es originäre Listen- und Formular-Seiten des Addons.
2. Zwei Schritte zum Glück
Die Lösung besteht aus zwei Teilen
- Addon-Menü konfigurieren
- Helper-Funktion (page) für das Addon-Menü schreiben
Im ersten Schritt wird die Tabelle als Seitenaufruf im Menü des eigenen Addons eingebaut. Über den Menüpunkt
wird eine Seite aufgerufen, die von einer dafür vorgesehenen PHP-Datei (zweiter Schritt) im Verzeichnis myaddon/pages
erzeugt wird.
Nachfolgend werden zwei Varianten beschrieben. Die einfache basiert auf einer je YForm-Tabelle individuell
konfigurierten PHP-Page, die zweite zeigt eine universelle Version, die über package.yml
konfiguriert wird.
Die eigentlich ausführende Funktion in YForm - das Original - findet sich in der Datei
yform/plugins/manager/pages/data_edit.php
.
Sie kann mit geringem Aufwand als Blaupause für eine eigene Aufrufseite dienen:
<?php
$table_name = rex_request('table_name', 'string');
$table = rex_yform_manager_table::get($table_name);
if ($table && rex::getUser() && (rex::getUser()->isAdmin() || rex::getUser()->getComplexPerm('yform_manager_table')->hasPerm($table->getTableName()))) {
try {
$page = new rex_yform_manager();
$page->setTable($table);
$page->setLinkVars(['page' => 'yform/manager/data_edit', 'table_name' => $table->getTableName()]);
echo $page->getDataPage();
} catch (Exception $e) {
$message = nl2br($e->getMessage()."\n".$e->getTraceAsString());
echo rex_view::warning($message);
}
} else {
if (!$table) {
echo rex_view::warning(rex_i18n::msg('yform_table_not_found'));
}
}
2.1 Die einfache Lösung
Konkret sind zwei Schritte notwendig:
2.1.1 Addon-Menü konfigurieren
In der package.yml
des Addons wird das Menü um Einträge erweitert, die jeweils eine
Tabelle anzeigen und die Bearbeitung ermöglichen:
page:
title: 'Addon-Titel'
subpages:
orte:
title: 'Orte'
icon: rex-icon fa-map-marker
termine:
title: 'Termine'
icon: rex-icon fa-calendar
Das führt dazu, dass für orte
eine Datei myaddon/pages/orte.php
und für termine
eine Datei
myaddon/pages/orte.php
aufgerufen werden. Beide müssen existieren.
2.1.2 Helper-Funktion für das Addon-Menü schreiben
Die beiden Dateien myaddon/pages/orte.php
bzw. myaddon/pages/orte.php
werden Varianten der
data_edit.php
. Zwei Änderungen sind zwingend notwendig.
-
$table_name fest vorgeben
Im Originalcode wird der Tabellenname aus den Request-Parametern abgelesen (
$table_name = rex_request('table_name', 'string');
). Das funktioniert beim ersten Aufruf aus dem Menü noch nicht; daher wird der Name der zu bearbeitenden Tabelle (im Beispiel “rex_myaddon_orte” bzw. “rex_myaddon_termine” ) fest eingegeben. -
YForm mitteilen, dass die Tabellen/Formulare im Addon angezeigt werden
Für alle Folgeaufrufe ist im Original die Zielseite mit
yform/manager/data_edit
fest angegeben. Dort muss entweder der eigene Seitenname fest eingetragen werden (im Beispiel: ‘myaddon/orte’ bzw. ‘myaddon/termine’) oder noch besser ganz allgemein der Seitenpfad, über den die Datei eh grade aufgerufen wurde (alsorex_request('page', 'string')
).
Die einfachste Lösung besteht also darin, je zu bearbeitender Tabelle eine eigene Variante der
data_edit.php
im pages-Verzeichnis des Addons abzulegen.
<?php
$table_name = 'rex_myaddon_orte';
$table = rex_yform_manager_table::get($table_name);
if ($table && rex::getUser() && (rex::getUser()->isAdmin() || rex::getUser()->getComplexPerm('yform_manager_table')->hasPerm($table->getTableName()))) {
try {
$page = new rex_yform_manager();
$page->setTable($table);
$page->setLinkVars(['page' => rex_request('page', 'string'), 'table_name' => $table->getTableName()]);
echo $page->getDataPage();
} catch (Exception $e) {
$message = nl2br($e->getMessage()."\n".$e->getTraceAsString());
echo rex_view::warning($message);
}
} else {
if (!$table) {
echo rex_view::warning(rex_i18n::msg('yform_table_not_found'));
}
}
Das Verfahren ist einfach, hat jedoch noch einen Schönheitsfehler. Die YForm-Seiten werden immer mit der Seiten-Titelzeile angezeigt. Sie kann auch nicht wirksam über Parameter oder Extension-Points unterdrückt werden. Wie man sie trotzdem loswerden kann, wird in einem späteren Kapitel beschrieben.
2.2 Die perfekte(?) Lösung
Nachfolgend wird beschrieben, wie man statt mit separaten Dateien pro Tabelle mit einer universellen Page-Datei die Tabellen einbinden kann. Wieder sind es zwei Schritte:
Im Unterschied zur einfachen Version erfolgt die komplette Konfiguration der Aufrufe über package.yml
.
2.1 Addon-Menü konfigurieren
In der package.yml
des Addons wird das Menü um Einträge erweitert, die jeweils eine Tabelle anzeigen und die Bearbeitung ermöglichen:
page:
title: 'Addon-Titel'
subpages:
orte:
title: 'Orte'
icon: rex-icon fa-map-marker
subPath: pages/data_edit.php
yformTable: rex_myaddon_orte
yformClass: myaddon-yform
termine:
title: 'Termine'
icon: rex-icon fa-calendar
subPath: pages/data_edit.php
yformTable: rex_myaddon_termine
yformClass: myaddon-yform
yformTitle: true
“Normale” Menüpunkte würden zur Bearbeitung die Datei myaddon/pages/orte.php
bzw.
myaddon/pages/termine.php
heranziehen.
Aber subPath: pages/data_edit.php
leitet den Aufruf auf die Datei
myaddon/pages/data_edit.php
um.
Es kann auch ein anderes Verzeichnis als myaddon/pages
sein (z.B. project/pages
), das ist nur ein Beispiel.
Damit myaddon/pages/data_edit.php
unterscheiden kann, was eigentlich zu tun ist, wird mit zusätzlichen
Parametern die Anforderung spezifiziert:
Property | Beschreibung |
---|---|
yformTable | Der Name der Tabelle, die bearbeitet werden soll (notwendig). |
yformClass | CSS-Klassename für einen <div> -Tag, der um die generierte Seite gelegt wird. Das erleichtert die Suche in Output-Filtern und ermöglicht individuelle CSS-Konfigurationen (default: keine <div> -Klammer). |
yformTitle | Wenn angegeben und auf true gesetzt wird die (eigentlich im Addon überflüssige) Titelzeile doch eingeblendet (default: false). |
Eine Lösung für die in einem späteren Kapitel beschriebene Kopfzeilenproblematik ist hier schon mal vorweggenommen.
2.2 Helper-Funktion für das Addon-Menü schreiben
-
$table_name aus der package.yml nehmen
Im Originalcode wird der Tabellenname aus den Request-Parametern abgelesen (
$table_name = rex_request('table_name', 'string');
). Das funktioniert beim ersten Aufruf aus dem Menü noch nicht; statt dessen soll die PropertyyformTable
herangezogen werden. -
YForm mitteilen, dass die Tabellen/Formulare im Addon angezeigt werden
Dazu reicht es aus, in
setLinkVars
den Url-Parameter “page” auf den Wert aus der URL zu setzen.
Die neue, eigene myaddon/pages/data_edit.php
könnte in der Basisversion so aussehen:
<?php
if( isset( $this->getProperty('page')['subpages'][rex_be_controller::getCurrentPagePart(2)] ) )
{
$properties = $this->getProperty('page')['subpages'][rex_be_controller::getCurrentPagePart(2)];
if( $sub=rex_be_controller::getCurrentPagePart(3) ) $properties = $properties['subpages'][$sub];
$table_name = isset( $properties['yformTable'] ) ? $properties['yformTable'] : '';
$target_page = rex_request('page', 'string');
}
else
{
$table_name = '';
}
$table = rex_yform_manager_table::get($table_name);
if ($table && rex::getUser() && (rex::getUser()->isAdmin() || rex::getUser()->getComplexPerm('yform_manager_table')->hasPerm($table->getTableName()))) {
try {
$page = new rex_yform_manager();
$page->setTable($table);
$page->setLinkVars([ 'page' => $target_page, 'table_name' => $table->getTableName()]);
echo $page->getDataPage();
} catch (Exception $e) {
$message = nl2br($e->getMessage()."\n".$e->getTraceAsString());
echo rex_view::warning($message);
}
} else {
if (!$table) {
echo rex_view::warning(rex_i18n::msg('yform_table_not_found'));
}
}
Die Version ist der allgemeinere Ansatz ggü. der einfachen Lösung, hat aber noch nicht alle angestrebten Features.
Um die beiden Parameter yformTitle
und yformClass
zu berücksichtigen, ist etwas mehr Code erforderlich:
Hier ist der vollständige Code der perfekten(?) Lösung:
<?php
$target_page = rex_request( 'page', 'string' );
if( $target_page == 'yform/manager/data_edit' )
{
$table_name = rex_request( 'table_name', 'string' );
$wrapper = '';
$show_title = true;
}
elseif( isset( $this->getProperty('page')['subpages'][rex_be_controller::getCurrentPagePart(2)] ) )
{
# page-Properties allgemein abrufen
$properties = $this->getProperty('page')['subpages'][rex_be_controller::getCurrentPagePart(2)];
if( $sub=rex_be_controller::getCurrentPagePart(3) ) $properties = $properties['subpages'][$sub];
# yform-properties
$table_name = isset( $properties['yformTable'] ) ? $properties['yformTable'] : '';
$wrapper = isset( $properties['yformClass'] ) ? $properties['yformClass'] : '';
$show_title = isset( $properties['yformTitle'] ) && $properties['yformTitle'] == true;
}
else
{
$table_name = '';
}
$table = rex_yform_manager_table::get($table_name);
if ($table && rex::getUser() && (rex::getUser()->isAdmin() || rex::getUser()->getComplexPerm('yform_manager_table')->hasPerm($table->getTableName())))
{
try {
$page = new rex_yform_manager();
$page->setTable( $table );
$page->setLinkVars( ['page' => $target_page, 'table_name' => $table->getTableName()] );
if( $wrapper ) echo "<div class=\"$wrapper\">";
if( $show_title )
{
echo $page->getDataPage();
}
else
{
# Seite erzeugen und abfangen
ob_start();
echo $page->getDataPage();
$page = ob_get_clean();
# Such den Header - Fall 1: mit Suchspalte?
$p = strpos( $page,'</header>'.PHP_EOL.'<div class="row">' );
# Such den Header - Fall 2: ohne Suchspalte
if( $p === false ) $p = strpos( $page,'</header>'.PHP_EOL.'<section class="rex-page-section">' );
# Header rauswerfen
if( $p !== false ) $page = substr( $page, $p );
# ausgabe
echo $page;
}
if( $wrapper ) echo '</div>';
} catch (Exception $e) {
$message = nl2br($e->getMessage()."\n".$e->getTraceAsString());
echo rex_view::warning($message);
}
} elseif ( !$table ) {
echo rex_view::warning(rex_i18n::msg('yform_table_not_found'));
}
3. Anmerkungen
3.1 Titelzeile
Die Titelzeile kann via EP “PAGE_TITLE” auf “leer” gesetzt werden. Der entsprechende <header>
-Tag wird trotzdem eingebaut. Er wäre zwar nicht sichtbar, aber in Installationen mit dem Addon quick_navigation hilft das
nicht weiter, da die Quick-Navigation in den <header>
-Tag gehängt wird.
Andere vorgegebene Möglichkeiten, die Headerzeile zu beeinflussen oder auszublenden, bestehen nicht.
Somit bleibt nur, die Titelzeile entweder per CSS auszublenden oder wie oben beschrieben herauszulöschen. Schöner wäre es, wenn sie gar nicht erst erzeugt werden würde.
Dazu bedarf es aber Änderungen in der Klasse rex_yform_manager
z.B. in Form einer Methode, die ein Flag showTitle=false
setzen würde.
3.2 Idee: Integration in YForm
Die oben beschriebene data_edit.php
ist geeeignet, die originale yform/plugins/manager/pages/data_edit.php
zu ersetzen.
Der Aufruf in der package.yml des Addons wäre dann
subPath: ../yform/plugins/manager/pages/data_edit.php
Zudem würde der Code etwas entlastet, wenn der Klasse rex_yform_manager
ein Mechanismus spendiert wird, der die Ausgabe der Titelzeile unterdrückt. Dies kann z.B. durch eine Methode, die ein Flag showTitle=false
setzt, realisiert werden.
4. Testumgebung
- REDAXO 5.5.1
- YFORM 2.3