Dca-rules: Unterschied zwischen den Versionen

Aus Contao Community Documentation

 
(4 dazwischenliegende Versionen von einem Benutzer werden nicht angezeigt)
Zeile 1: Zeile 1:
[[Category:Dca-rules]]
+
[[Category:Dcarules]]
 
[[Kategorie:Extensions]]
 
[[Kategorie:Extensions]]
 
{{ExtInfo
 
{{ExtInfo
 
| Dev=David Molineus http://www.netzmacht.de
 
| Dev=David Molineus http://www.netzmacht.de
| ExtVersion=1.0.0-rc2
+
| ExtVersion=1.0.0-rc3
 
| Version=2.11.0 - 3.0.1
 
| Version=2.11.0 - 3.0.1
 
| ERLink=https://contao.org/de/extension-list/view/dca-rules.html
 
| ERLink=https://contao.org/de/extension-list/view/dca-rules.html
Zeile 9: Zeile 9:
 
}}
 
}}
  
=Permission Regeln verwenden=
+
=Allgemeines=
  
Auf dieser Seite werden die Permission Regeln von [[dca-rules]] dokumentiert. Bei dca-rules handelt es sich um eine Erweiterung, mit deren hilfe wiederkehrende Bedingungen für DataContainer innerhalb von DCA-Dateien angegeben werden können ohne extra Callbacks zu definieren.  
+
Die Erweiterung '''dca-rules''' ist als Hilfswerkzeug für die Entwicklung von DataContainern konzipiert. Es stellt allgemeine Callbacks für die Generierung von Operationen, Global Operationen, für die Rechteüberprüfung sowie der Ausgabe der Labeln in der Listenansicht. Diese können mit Regeln konfiguriert werden, sodass diese über die DCA-Dateien erstellt werden können ohne neue Callbacks zu definieren. Damit wird die Erzeugung redundanter Callbacks bei der Entwicklung von DataContainern reduziert.
  
=Regel generic=
+
=Vorgehensweise ohne dca-rules=
  
Diese Regel dient als Basis aller weiteren Permission-Regeln. Ihr Hauptaufgabe ist den Zugriff der Aktionen zu beschränken. Dabei sind die angegebenen Aktionen als Whitelist zu verstehen. Sie kann daher auch als eigenständige Regel verwendet werden. Außerdem besteht die Möglichkeit bei einer fehlgeschlagenen Überprüfung eine angepasste Fehlermeldung zu erstellen, die im Systemlog erscheint.
+
Um den Einsatz von den DCA-Regeln zu verdeutlichen, soll hier ein Beispiel erläutert werden. Es ist eine Erweiterung geplant, die es angemeldeten Benutzern im Frontend ermöglicht, Artikel mit Rückmeldungen zu versehen, z.B. dass sie eine Überarbeitung benötigen. Diese sollen dem Nutzer zugeordnet werden und von Redakteuren im Backend bearbeitet werden können. Backend-Redakteure ohne Bearbeitungsrechte sollen, die Feedbacks einsehen können. Hat der Benutzer Zugriff aus das Member Modul, soll außerdem ein Button zum entsprechenden Benutzer angezeigt werden. Gelöscht werden sollen die Feedbacks hingegen nur vom Administrator.
  
==Mögliche Parameter==
+
==Aufbau der tl_feedback==
* '''act''' ''array/string'', optional<br />definiert die angegebenen Aktionen des DataContainers, auf die die Regel angewendet wird
+
* '''error''' ''string'', optional<br />die Fehlermeldung für die Logdatei
+
* '''params''' ''string'', optional<br />Werte die in der Fehlermeldung ersetzt werden sollen
+
  
==Beispiele==
+
Man erstellt also einen DataContainer ''tl_feedback.php'', der die entsprechenden Felder ''id, pid, tstamp, created, memberid, userid, status, type, message'' beinhaltet. Pid ist hierbei die ID der Artikel, memberid die ID des Nutzers, der das Feedback abgegeben hat, userid die ID des bearbeiteten Benutzers. Außerdem wird in created die Timestamp gespeichert, als das Feedback abgegeben wurde, während tstamp bei jeder Änderung aktualisiert wird.
 +
 
 +
==Benötigte Operationen==
 +
 
 +
Nach den Anforderungen, müssen folgende Operationen erstellt werden:
 +
 
 +
* Feedback bearbeiten (wenn Rechte vorhanden)
 +
* Benutzer anzeigen (wenn Zugriff aus Modul member)
 +
* Feedback löschen (nur Admin)
 +
* Feedback anzeigen (alle Benutzer mit Zugriff auf Modul)
 +
 
 +
Dies bedeutet außerdem, dass die Zugriffsrechte überprüft werden müssen:
 +
 
 +
* Bearbeiten nur Redakteure mit Lösch-Rechten
 +
* Löschen Aktion nur Administrator
 +
 
 +
==DataContainer Klasse==
 +
 
 +
Nach dem gewöhnlichen Weg, würde man jetzt für die Buttons edit, member, delete Callbacks definieren, sowie einen onload_callback checkPermission, welches die Zugriffsrechte überprüft. Im unten dargestellten Code-Beispiel ist dies kurz verdeutlicht. Das Problem hierbei ist, dass man immer wieder die gleichen Callbacks definiert, sobald die Zugriffsrechte mal eingeschränkt sind.
  
 
<source lang="php">
 
<source lang="php">
// Zugriff aus show erlauben
+
class Feedback extends Backend
$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array('generic:act=show');
+
{
 +
    public function __construct()
 +
    {
 +
        parent::__construct();
 +
        $this->import('BackendUser', 'User');
 +
    }
 +
       
 +
    public function checkPermission()
 +
    {
 +
        $act = \Input::get('act');
 +
        if(($act == 'delete' || $act == 'deletAll') && !$this->user->isAdmin)
 +
        {
 +
            $this->log('Hacking attempt');
 +
            $this->redirect('contao/main.php?act=error');
 +
        }
 +
 
 +
        // check user permission ...
 +
    }
  
// Zugriff aus Löschen sowie show und edit erlauben
+
    public function generateDeleteButton($arrRow, $strHref, $strLabel, $strTitle, $strIcon, $strAttributes)
$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array('generic:act=[show,edit]');
+
    {
 +
        if(!$this->User->isAdmin)
 +
        {
 +
            return '';
 +
        }
  
// benutzerdefinierte Fehlermeldung
+
        return '<a href="">....</a>';
$GLOBALS['TL_LANG']['tl_feedback']['errors'][4] = 'Hacking attempt on tl_feedback. Only action "%s" allowed';
+
    }
$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array('generic:act=[show]:error=&.errors.4:params=['show']');
+
}
 
</source>
 
</source>
  
=Permission Regeln verwenden=
+
=Vorgehensweise mit dca-rules=
  
Auf dieser Seite werden die Permission Regeln von [[dca-rules]] dokumentiert. Bei dca-rules handelt es sich um eine Erweiterung, mit deren hilfe wiederkehrende Bedingungen für DataContainer innerhalb von DCA-Dateien angegeben werden können ohne extra Callbacks zu definieren.  
+
An dieser Stelle setzt '''dca-rules''' an und bietet eine leicht zu konfigurierbare Schnittstelle, die solche Aufgaben löst. Außerdem ist sie leicht erweiterbar, sodass selbst bei komplexeren Beispielen immer noch auf die Regeln zurückgegriffen werden kann.
  
=Regel hasAccess=
+
==Verwendung der vordefinierten Callbacks==
 +
Daher bietet die Erweiterung vordefinierte Callbacks, die anstelle der neu entwickelten aufgerufen werden. Zusätzlich werden diese noch mit Regeln definiert. Zur Zeit stehen folgende Callbacks zur Verfügung. Bei den Button Callbacks handelt es sich um magische Callbacks, die um den Buttonnamen ergänzt werden müssen. Dies ist erforderlich, damit der allgemeine Callback nur bei dem entsprechenden Button ausgeführt wird.
  
Diese Regel dient dazu Zugriffsbeschränkungen über die BackendUser::hasAccess zu überprüfen. Sie besitzt neben den hier aufgelisteten Parameter die der Regel ''generic''. Allerdings dient hierbei der Parameter als Begrenzung der Regel. Sie wird also nur dann ausgeführt, wenn die Aktion auch aufgerufen wurde.
+
* checkPermission
 +
* generateButton*
 +
* generateGlobalButton*
 +
* generateLabel
  
==Mögliche Parameter==
+
Damit diese verwendet werden können, muss die DataContainer Klasse die mitgelieferte Klasse Netzmacht\Utils\DataContainer erweitern. Diese basiert selbst auf der Backend Klasse. Außerdem benötigt sie den Namen der Tabelle. Dieser kann automatisch generiert werden, wenn die erstellte Klassen der Namenskonvention folgt. Aus der Tabelle tl_feedback wird der DataContainer Feedback. Entscheidet man sich für einen anderen Namen, muss lediglich die Variable $strTable definiert werden:
* '''module''' ''array/string'', optional<br />Überprüft den Zugriff auf Module
+
* '''permission''' ''string'', optional<br />Definiert eine beliebige Zugriffsart für BackendUser::hasAccess(action, permission)
+
* '''action''' ''array/string'', optional<br />Definiert eine beliebige Aktion für BackendUser::hasAccess(action, permission)
+
* '''alexf''' ''string'', optional<br />Kurzform um Zugriff auf Feld zu überprüfen BackendUser::hasAccess(alexf, 'alexf')
+
* '''table''' ''string'', optional<br />in Verbindung mit alexf oder action möglich die Tabelle zu bestimmen
+
* '''fop''' ''string'', optional<br />Kurzform zur Überprüfung für BackendUser::hasAccess(fop, 'fop')
+
  
==Beispiele==
+
<source lang="php">
 +
class Feedback extends Netzmacht\Utils\DataContainer
 +
{
 +
    // protected $strTable = 'tl_feedback';
 +
}
 +
</source>
 +
 
 +
Wird nun der DataContainer verwendet, können die mitgelieferten Callbacks wie gewohnt in der DCA-Datei definiert:
  
 
<source lang="php">
 
<source lang="php">
// Modulzugriff überprüfen
+
$GLOBALS['TL_DCA']['tl_feedback']['config']['onload_callback'][] = array('Feedback', 'checkPermission');
$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array('hasAccess:module=tl_article');
+
</source>
$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array('hasAccess:module=[tl_article,tl_news]');
+
  
// Zugriffsüberprüfung per permission und action
+
==Verwendung von Regeln==
$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array('hasAccess:permission=newp:action=create');
+
  
// Zugriff auf Feld der DCA-Tabelle
+
Neben den Callbacks werden nun die Regeln definiert. Diese werden in folgenden Variablen gespeichert:
$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array('hasAccess:permission=alefx:action=status');
+
$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array('hasAccess:alexf=status');
+
  
// Zugriff auf Feld einer anderen Tabelle
+
<source lang="php">
$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array('hasAccess:permission=alefx:action=status:table=tl_news');
+
$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array(); // Regeln für checkPermission
$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array('hasAccess:alexf=status:table=tl:news');
+
$GLOBALS['TL_DCA']['tl_feedback']['list']['operation']['button']['button_rules'] = array(); // Regeln für generateButton
 +
$GLOBALS['TL_DCA']['tl_feedback']['list']['gobal_operation']['button']['button_rules'] = array(); // Regeln für generateGlobalButton
 +
$GLOBALS['TL_DCA']['tl_feedback']['list']['label']['label_rules'] = array(); // Regeln für generateLabel
 +
</source>
  
// Zugriff auf Dateioperation
+
Anhand des oben genannten Beispiels definieren wir zwei Regeln zur Rechteüberprüfung. Zum einem verwenden wir hasAccess um den Zugriffsrechte für die Bearbeiten Funktion zu überprüfen, sowie isAdmin um die LöschFunktionen einzugrenzen.
$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array('hasAccess:fop=5');
+
  
// Zugriff nur bei Bearbeiten überprüfen
+
<source lang="php">
$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array('hasAccess:act=[edit,editAll]:alexf=status');
+
$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array('isAdmin', 'hasAccess');
 
</source>
 
</source>
  
=Regel isAllowed=
+
Dies würde allerdings dazu führen, dass die isAdmin Regel auf alle Aktionen angewandt wird. Sprich das Modul wäre nur für Administratoren nutzbar. Daher bietet dca-rules eine Möglichkeit Attribute zu definieren. Dabei wird folgende Syntax verwendet:
  
Diese Regel dient dazu Zugriffsbeschränkungen über die BackendUser::isAllowed zu überprüfen. Damit kann der Zugriff auf eine Seite überprüft werden. Sie besitzt neben den hier aufgelisteten Parameter die der Regel ''generic''. Allerdings dient hierbei der Parameter als Begrenzung der Regel. Sie wird also nur dann ausgeführt, wenn die Aktion auch aufgerufen wurde.
+
<source lang="php">
 +
$rule = array('rule:attribute'); // setzt attribute=true
 +
$rule = array('rule:attribute=2'); // setzt attribute=2. Boolean und Numeric werden entsprechend konvertiert
 +
$rule = array('rule:attribute=$value'); // Zugriff auf eine in der Feedback definierte Variable $this->value
 +
$rule = array('rule:attribute=[one,two,three]'); // Ein Array array('one', 'two', 'three')
 +
$rule = array('rule:attribute=[true,2,false,$value,2.3, 'hallo']'); // Werte des Array werden ebenso konvertiert: array(true, 2, false, $this->value, 2.3, 'hallo');
 +
$rule = array('rule:a=2:b=3:c:4');  // Mehrere Attribute können durch einen Doppelpunkt getrennt werden
 +
$rule = array('rule:error=&.errors.1'); // accessing language vars of current table
 +
$rule = array('rule:error=&MSC.yes'); // accessing language var $GLOBALS['TL_LANG']['MSC']['yes']
 +
</source>
  
Diese Erweiterung erlaubt es neben der Überprüfung der aktuellen Datenreihe auch eine beliebige andere Tabelle als Grundlage der Überprüfung zu nehmen. Beispielsweise, wenn man auf der Ebene der tl_content die Rechte überprüfen will.
+
==Permission Regeln==
  
==Mögliche Parameter==
+
Die Permission Rules bieten alle die Möglichkeit über das act Attribute die Regel nur auf die definierten Aktionen anzuwenden. Dabei können diese als Arrray definiert werden. Demzufolge erweitert man das obige Beispiel. Außerdem soll überorpft werden, ob der Benutzer Zugriff aus das Modul hat. Daher übergeben wir den Modulnamen:
* '''operation''' ''int'', erforderlich<br />prüft ob die Aktion auf die aktuelle Seite auszuführen ist
+
* '''ptable''' ''bool/string'', optional<br />wahr, wenn die Elterntabelle als Grundlage genommen werden soll. alternativ einen Tabellenname
+
* '''pid''' ''string'', optional<br />Die Spalte der aktuellen Zeile, die zum Laden der ptable als ID genommen soll, standard ist pid
+
* '''value''' ''int'', optional<br />Alternativ einen Wert zur Überprüfung auf id=value, nur im Zusammenhang mit ptable
+
  
==Beispiele==
+
<source lang="php">
 +
$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array('isAdmin:act=[delete,deleteAll]', 'hasAccess:module=feedback');
 +
</source>
 +
 
 +
Dadurch sind die Einschränkungen schon recht weit umgesetzt. Allerdings bekämen jetzt alle Redakteure Zugriff die Beabeiten-Funktion. Um diese einzuschränken, wendet man nochmals die Regel hasAccess die mit den Attributen permission und action beliebige BackendUser::hasAccess(action, permission)
 +
Überprüfungen machen kann. Diese nuss natürlich vorher auch in der tl_user(_group) und über TL_PERMISSION definiert werden. Das soll an dieser Stelle nicht näher behandelt werden. Es wird davon ausgegangen, dass der Zugriff feedback mit dem Wert edit definiert ist. Die Regel hasAccess wird nun nur auf die Aktionen edit und editAll angewandt:
  
 
<source lang="php">
 
<source lang="php">
// Zugriff auf der Basis der aktuellen Datenzeile
+
$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array
$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array('isAllowed:operation=5');
+
(
 +
    'isAdmin:act=[delete,deleteAll]', 'hasAccess:module=feedback', 'hasAccess:act=[edit,editAll]:permission=feedback:action=edit'
 +
);
 +
</source>
  
// Zugriff auf der Basis der Elterntabelle
+
Das ist alles! Damit hat man in einer Zeile in der DCA-Datei die Rechteüberprüfung vorgenommen.
$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array('isAllowed:operation=5:ptable');
+
 
 +
==Button Regeln==
 +
 
 +
Das gleiche Prinzip wird bei den Button-Regeln angewandt. Diese folgen der gleichen Syntax und dem gleichen Prinzip wie die Permission Regeln. Allerdings benötigen sie noch die Regel generate, die zur Ausgabe dient. Diese muss mit angegeben werden, was den Vorteil hat, das man auch nach der Ausgabe noch Manipulationen vornehmen kann. Doch weiter an dem genannten Beispiel mit den Buttons edit,member,delete,show.
 +
 
 +
Wie bei der Rechteübergabe, werden die Regeln nun definiert. Wichtigste Helfer, sind hierbei auch wieder die Regeln isAdmin sowie hasAccess. Die Konfigurationen de Buttons sind unten aufgeführt. den show Button muss man nicht definieren, da ja die Zugriffsbeschränkung mit dem Zugriff des Modules bereits erreicht ist.
 +
 
 +
<source lang="php">
 +
$GLOBALS['TL_DCA']['tl_feedback']['list']['operations']['edit'] = array
 +
(
 +
    // normale button konfiguration, zusätzlich
 +
    'button_callback' => array('Feedback', 'generateButtonEdit'),
 +
    'button_rules'  => array('hasAccess:permission=feedback:action=edit', 'generate'),
 +
);
  
// Zugriff auf der Basis einer beliebigen Elterntabelle mit einer beliebigen ID Spalte
+
$GLOBALS['TL_DCA']['tl_feedback']['list']['operations']['member'] = array
$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array('isAllowed:operation=5:ptable=tl_subcontent:pid=pageid');
+
(
 +
    // normale button konfiguration, zusätzlich
 +
    'button_callback' => array('Feedback', 'generateButtonMember'),
 +
    'button_rules' => array('hasAccess:module=member', 'generate'),
 +
);
  
// Zugriff auf eine bestimmte Zeile der ID 3
+
$GLOBALS['TL_DCA']['tl_feedback']['list']['operations']['delete'] = array
$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array('isAllowed:operation=5:ptable:value=3');
+
(
 +
    // normale button konfiguration, zusätzlich
 +
    'button_callback' => array('Feedback', 'generateButtonDelete'),
 +
    'button_rules' => array('isAdmin', 'generate'),
 +
);
 
</source>
 
</source>
  
=Regeln isAdmin und forbidden=
+
==Label Regeln==
  
Die Regel isAdmin dient dazu Zugriff auf den Administrator zu beschränken. Sie besitzt keine weiteren Parameter als die von der Regel generic. Die Regel forbidden verbietet den Zugriff auf die angebenen Aktionen:
+
Die Label Regeln dienen dazu die Aufgabe der einzelnen Felder zu bestimmen. Sie dienen dazu einzelne Werte der Ausgabe anders zu formatieren. An dem oben genannten Beispiel gibt es die Spalte created. Die Übersicht soll im mode=1 erfolgen. Dabei wird der Timestamp nicht konvertiert. Dies erledigt Contao nur bei der tstamp Spalte automatisch. Außerdem soll ausgegeben werden, ob das Feedback bereits einem bearbeitenden Nutzer zugewiesen wurde. Hierbei soll lediglich ja/nein und nicht der Beutzername ausgegeben werden. Für beide Fälle bringt dca-rules wieder Regeln mit. Während alle anderen Regeln immer einen Abbruch der Überprüfung erreichen können, werden die LabelRegeln immer durchgeführt.
 +
 
 +
Diese werden folgendermaßen konfiguriert:
  
 
<source lang="php">
 
<source lang="php">
// Bearbeiten nur für Admin, Löschen verbieten
+
$GLOBALS['TL_DCA']['tl_feedback']['list']['label'] = array
$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array('isAdmin:act=[edit,editAll]', 'forbidden:act=[delete,deleteAll]');
+
(
 +
    'fields' => array('id', 'created', 'userid'),
 +
    'showColumns' => true,
 +
    'label_callback' => array('Feedback', 'generateLabel'),
 +
    'label_rules' => array(),
 +
);
 +
</source>
 +
 
 +
Wir erzeugen also eine Listenansicht, die tabellarisch ausgegeben wird mit den Spalten id, created und userid. Statt der Userid werden wir eine ja/nein ausgabe machen. Auch hier wird der bereits vorhandene Callback aufgerufen.
 +
 
 +
Was man bei den Regeln für Label beachten muss, dass die Werte von Contao in einem Array $values nach dem Index der oben aufgelisteten Felder überliefert bekommt. in $vlaues[0] steht also die ID, nd $values[1] der Timestamp usw. Dazu gibt es auch ein Array mit den unbearbeiten Werten $row['id']. Manchmal konvertiert Contao den Wert bereits in eine Ausgabe. Beispielsweise bei einen Boolean Wert. So wird hier entweder ein - für eine leere Angabe, oder die Spaltenbezeichnung angegeben. Aus diesem Grund verwenden die Label Regeln sowohl ein Attribute index wie auch field, um zwischen den beiden Werten wählen zu können. Der Index ist immer erforderlich, da er die Position der Ausgabe entscheidet.
 +
 
 +
Für den hier beschriebenen Fall stehen zwei Regeln zur Verfügung: parseDate und yesNo. Dabei wird der yesNo Regel sowohl der Index als auch das Feld übergeben. Das Feld wird dann anhand des Attributes condition überprüft. Da "ja" ausgeben werden soll, wenn der Wert > 0 ist, muss die Überprüfung noch auf false gesetzt werden:
 +
 
 +
<source lang="php">
 +
$GLOBALS['TL_DCA']['tl_feedback']['list']['label'] = array
 +
(
 +
    'label_rules' => array('parseDate:index=1', 'yesNo:index=2:field=created:condition=0:is=false'),
 +
);
 +
</source>
 +
 
 +
Dadurch könenn wir so gut wie alle Aktionen der Tabelle lösen '''ohne''' einen einzigen Callback geschrieben zu haben!
 +
 
 +
=Vorhandene Regeln=
 +
Nachdem anhand des Beispiels die Funktionsweise erläutert wurde, gibt es hier eine Übersicht der vordefinierten Regeln. Auf den jeweiligen Unterseiten ist die Verwendungsweise der Regeln näher erläutert:
 +
 
 +
'''[[Permission Regeln]]'''
 +
* generic
 +
* hasAccess
 +
* isAllowed
 +
* isAdmin
 +
* forbidden
 +
 
 +
'''[[Button Regeln]]'''
 +
* disableIcon
 +
* toggleIcon
 +
* referer
 +
* hasAccess
 +
* isAllowed
 +
* isAdmin
 +
 
 +
'''[[Label Regeln]]'''
 +
* parseDate ''(index,field,format='' einen Timestamp parsen
 +
* yesNo ''(index,field,codition,is)'' ja/nein ausgeben
 +
 
 +
=Eigene Regeln definieren=
 +
 
 +
Neben den vordefinierten Regeln können auch eigene Regeln definiert werden. Diese werden als Methoden in dem DataContainer definiert und folgen folgenden Konventionen. Die Button Regeln werden sowohl für die globale als auch lokale Buttons verwendet. Bei globalen ist $arrRow=null.
 +
 
 +
<source lang="php">
 +
protected function permissionRule*($objDc, &$arrAttributes, &$strError);
 +
protected function buttonRule*(&$strButton, &$strHref, &$strLabel, &$strTitle, &$strIcon, &$strAttributes, &$arrAttributes, $arrRow=null);
 +
protected function labelRule*(&$arrRow, &$strLabel, &$objDc, &$arrValues, &$arrAttributes);
 +
</source>
 +
 
 +
Da die Variablen per Referenz übergeben werden, können sie so von einer Regel zur nächsten weitergereicht werden. Möchte eine Regel beispielsweise das Icon ersetzen, so muss lediglich die icon Variable neu gesetzt werden.
 +
 
 +
<source lang="php">
 +
protected function buttonRuleChangeIcon(&$strButton, &$strHref, &$strLabel, &$strTitle, &$strIcon, &$strAttributes, &$arrAttributes, $arrRow=null)
 +
{
 +
    $strIcon = (isset($arrAttribute['icon']) ? $arrAttribute['icon'] : 'change.gif';
 +
}
 +
</source>
 +
 
 +
Sollen Attribute weitergereicht werden, so ist es erforderlich, diese als solche zu kennzeichnen. Damit wird verhindert, dass sich die einzelnen Regeln ungewollt gegenseitig beinflussen, aber dennoch Anweisungen an nächste Regeln gesetzt werden können. Dazu muss unter $arrAttributes['__set__'] das entsprechende Feld hinzugefügt werden. Sinnvoll ist dies beispielsweise, wenn eine Regel die Ausgabe beeinflussen möchte:
 +
 
 +
<source lang="php">
 +
protected function buttonRuleReferer(&$strButton, &$strHref, &$strLabel, &$strTitle, &$strIcon, &$strAttributes, &$arrAttributes, $arrRow=null)
 +
{
 +
    $strHref = $this->getReferer(true);
 +
 
 +
    // do not use addToUrl() instead use plain href
 +
    $arrAttributes['plain'] = true;
 +
    $arrAttributes['__set__'][] = 'plain';
 +
 
 +
    return true;
 +
}
 
</source>
 
</source>

Aktuelle Version vom 20. Dezember 2012, 11:15 Uhr


Erweiterungs-Übersicht
Name des Entwicklers David Molineus http://www.netzmacht.de
Version der Erweiterung 1.0.0-rc3
Kompatibilität mit Contao Version 2.11.0 - 3.0.1
Link zum Extension Repository https://contao.org/de/extension-list/view/dca-rules.html
Link zum Tracker https://github.com/dmolineus/dca-rules/


Allgemeines

Die Erweiterung dca-rules ist als Hilfswerkzeug für die Entwicklung von DataContainern konzipiert. Es stellt allgemeine Callbacks für die Generierung von Operationen, Global Operationen, für die Rechteüberprüfung sowie der Ausgabe der Labeln in der Listenansicht. Diese können mit Regeln konfiguriert werden, sodass diese über die DCA-Dateien erstellt werden können ohne neue Callbacks zu definieren. Damit wird die Erzeugung redundanter Callbacks bei der Entwicklung von DataContainern reduziert.

Vorgehensweise ohne dca-rules

Um den Einsatz von den DCA-Regeln zu verdeutlichen, soll hier ein Beispiel erläutert werden. Es ist eine Erweiterung geplant, die es angemeldeten Benutzern im Frontend ermöglicht, Artikel mit Rückmeldungen zu versehen, z.B. dass sie eine Überarbeitung benötigen. Diese sollen dem Nutzer zugeordnet werden und von Redakteuren im Backend bearbeitet werden können. Backend-Redakteure ohne Bearbeitungsrechte sollen, die Feedbacks einsehen können. Hat der Benutzer Zugriff aus das Member Modul, soll außerdem ein Button zum entsprechenden Benutzer angezeigt werden. Gelöscht werden sollen die Feedbacks hingegen nur vom Administrator.

Aufbau der tl_feedback

Man erstellt also einen DataContainer tl_feedback.php, der die entsprechenden Felder id, pid, tstamp, created, memberid, userid, status, type, message beinhaltet. Pid ist hierbei die ID der Artikel, memberid die ID des Nutzers, der das Feedback abgegeben hat, userid die ID des bearbeiteten Benutzers. Außerdem wird in created die Timestamp gespeichert, als das Feedback abgegeben wurde, während tstamp bei jeder Änderung aktualisiert wird.

Benötigte Operationen

Nach den Anforderungen, müssen folgende Operationen erstellt werden:

  • Feedback bearbeiten (wenn Rechte vorhanden)
  • Benutzer anzeigen (wenn Zugriff aus Modul member)
  • Feedback löschen (nur Admin)
  • Feedback anzeigen (alle Benutzer mit Zugriff auf Modul)

Dies bedeutet außerdem, dass die Zugriffsrechte überprüft werden müssen:

  • Bearbeiten nur Redakteure mit Lösch-Rechten
  • Löschen Aktion nur Administrator

DataContainer Klasse

Nach dem gewöhnlichen Weg, würde man jetzt für die Buttons edit, member, delete Callbacks definieren, sowie einen onload_callback checkPermission, welches die Zugriffsrechte überprüft. Im unten dargestellten Code-Beispiel ist dies kurz verdeutlicht. Das Problem hierbei ist, dass man immer wieder die gleichen Callbacks definiert, sobald die Zugriffsrechte mal eingeschränkt sind.

class Feedback extends Backend
{
    public function __construct()
    {
        parent::__construct();
        $this->import('BackendUser', 'User');
    }
 
    public function checkPermission()
    {
        $act = \Input::get('act');
        if(($act == 'delete' || $act == 'deletAll') && !$this->user->isAdmin)
        {
            $this->log('Hacking attempt');
            $this->redirect('contao/main.php?act=error');
        }
 
        // check user permission ...
    }
 
    public function generateDeleteButton($arrRow, $strHref, $strLabel, $strTitle, $strIcon, $strAttributes)
    {
        if(!$this->User->isAdmin)
        {
            return '';
        }
 
        return '<a href="">....</a>';
    }
}

Vorgehensweise mit dca-rules

An dieser Stelle setzt dca-rules an und bietet eine leicht zu konfigurierbare Schnittstelle, die solche Aufgaben löst. Außerdem ist sie leicht erweiterbar, sodass selbst bei komplexeren Beispielen immer noch auf die Regeln zurückgegriffen werden kann.

Verwendung der vordefinierten Callbacks

Daher bietet die Erweiterung vordefinierte Callbacks, die anstelle der neu entwickelten aufgerufen werden. Zusätzlich werden diese noch mit Regeln definiert. Zur Zeit stehen folgende Callbacks zur Verfügung. Bei den Button Callbacks handelt es sich um magische Callbacks, die um den Buttonnamen ergänzt werden müssen. Dies ist erforderlich, damit der allgemeine Callback nur bei dem entsprechenden Button ausgeführt wird.

  • checkPermission
  • generateButton*
  • generateGlobalButton*
  • generateLabel

Damit diese verwendet werden können, muss die DataContainer Klasse die mitgelieferte Klasse Netzmacht\Utils\DataContainer erweitern. Diese basiert selbst auf der Backend Klasse. Außerdem benötigt sie den Namen der Tabelle. Dieser kann automatisch generiert werden, wenn die erstellte Klassen der Namenskonvention folgt. Aus der Tabelle tl_feedback wird der DataContainer Feedback. Entscheidet man sich für einen anderen Namen, muss lediglich die Variable $strTable definiert werden:

class Feedback extends Netzmacht\Utils\DataContainer
{
    // protected $strTable = 'tl_feedback';
}

Wird nun der DataContainer verwendet, können die mitgelieferten Callbacks wie gewohnt in der DCA-Datei definiert:

$GLOBALS['TL_DCA']['tl_feedback']['config']['onload_callback'][] = array('Feedback', 'checkPermission');

Verwendung von Regeln

Neben den Callbacks werden nun die Regeln definiert. Diese werden in folgenden Variablen gespeichert:

$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array(); // Regeln für checkPermission
$GLOBALS['TL_DCA']['tl_feedback']['list']['operation']['button']['button_rules'] = array(); // Regeln für generateButton
$GLOBALS['TL_DCA']['tl_feedback']['list']['gobal_operation']['button']['button_rules'] = array(); // Regeln für generateGlobalButton
$GLOBALS['TL_DCA']['tl_feedback']['list']['label']['label_rules'] = array(); // Regeln für generateLabel

Anhand des oben genannten Beispiels definieren wir zwei Regeln zur Rechteüberprüfung. Zum einem verwenden wir hasAccess um den Zugriffsrechte für die Bearbeiten Funktion zu überprüfen, sowie isAdmin um die LöschFunktionen einzugrenzen.

$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array('isAdmin', 'hasAccess');

Dies würde allerdings dazu führen, dass die isAdmin Regel auf alle Aktionen angewandt wird. Sprich das Modul wäre nur für Administratoren nutzbar. Daher bietet dca-rules eine Möglichkeit Attribute zu definieren. Dabei wird folgende Syntax verwendet:

$rule = array('rule:attribute'); // setzt attribute=true
$rule = array('rule:attribute=2'); // setzt attribute=2. Boolean und Numeric werden entsprechend konvertiert
$rule = array('rule:attribute=$value'); // Zugriff auf eine in der Feedback definierte Variable $this->value
$rule = array('rule:attribute=[one,two,three]'); // Ein Array array('one', 'two', 'three')
$rule = array('rule:attribute=[true,2,false,$value,2.3, 'hallo']'); // Werte des Array werden ebenso konvertiert: array(true, 2, false, $this->value, 2.3, 'hallo');
$rule = array('rule:a=2:b=3:c:4');  // Mehrere Attribute können durch einen Doppelpunkt getrennt werden
$rule = array('rule:error=&.errors.1'); // accessing language vars of current table
$rule = array('rule:error=&MSC.yes'); // accessing language var $GLOBALS['TL_LANG']['MSC']['yes']

Permission Regeln

Die Permission Rules bieten alle die Möglichkeit über das act Attribute die Regel nur auf die definierten Aktionen anzuwenden. Dabei können diese als Arrray definiert werden. Demzufolge erweitert man das obige Beispiel. Außerdem soll überorpft werden, ob der Benutzer Zugriff aus das Modul hat. Daher übergeben wir den Modulnamen:

$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array('isAdmin:act=[delete,deleteAll]', 'hasAccess:module=feedback');

Dadurch sind die Einschränkungen schon recht weit umgesetzt. Allerdings bekämen jetzt alle Redakteure Zugriff die Beabeiten-Funktion. Um diese einzuschränken, wendet man nochmals die Regel hasAccess die mit den Attributen permission und action beliebige BackendUser::hasAccess(action, permission) Überprüfungen machen kann. Diese nuss natürlich vorher auch in der tl_user(_group) und über TL_PERMISSION definiert werden. Das soll an dieser Stelle nicht näher behandelt werden. Es wird davon ausgegangen, dass der Zugriff feedback mit dem Wert edit definiert ist. Die Regel hasAccess wird nun nur auf die Aktionen edit und editAll angewandt:

$GLOBALS['TL_DCA']['tl_feedback']['config']['permission_rules'] = array
(
    'isAdmin:act=[delete,deleteAll]', 'hasAccess:module=feedback', 'hasAccess:act=[edit,editAll]:permission=feedback:action=edit'
);

Das ist alles! Damit hat man in einer Zeile in der DCA-Datei die Rechteüberprüfung vorgenommen.

Button Regeln

Das gleiche Prinzip wird bei den Button-Regeln angewandt. Diese folgen der gleichen Syntax und dem gleichen Prinzip wie die Permission Regeln. Allerdings benötigen sie noch die Regel generate, die zur Ausgabe dient. Diese muss mit angegeben werden, was den Vorteil hat, das man auch nach der Ausgabe noch Manipulationen vornehmen kann. Doch weiter an dem genannten Beispiel mit den Buttons edit,member,delete,show.

Wie bei der Rechteübergabe, werden die Regeln nun definiert. Wichtigste Helfer, sind hierbei auch wieder die Regeln isAdmin sowie hasAccess. Die Konfigurationen de Buttons sind unten aufgeführt. den show Button muss man nicht definieren, da ja die Zugriffsbeschränkung mit dem Zugriff des Modules bereits erreicht ist.

$GLOBALS['TL_DCA']['tl_feedback']['list']['operations']['edit'] = array
(
    // normale button konfiguration, zusätzlich
    'button_callback' 		=> array('Feedback', 'generateButtonEdit'),
    'button_rules'  		=> array('hasAccess:permission=feedback:action=edit', 'generate'),
);
 
$GLOBALS['TL_DCA']['tl_feedback']['list']['operations']['member'] = array
(
    // normale button konfiguration, zusätzlich
    'button_callback' 		=> array('Feedback', 'generateButtonMember'),
    'button_rules' 		=> array('hasAccess:module=member', 'generate'),
);
 
$GLOBALS['TL_DCA']['tl_feedback']['list']['operations']['delete'] = array
(
    // normale button konfiguration, zusätzlich
    'button_callback' 		=> array('Feedback', 'generateButtonDelete'),
    'button_rules' 		=> array('isAdmin', 'generate'),
);

Label Regeln

Die Label Regeln dienen dazu die Aufgabe der einzelnen Felder zu bestimmen. Sie dienen dazu einzelne Werte der Ausgabe anders zu formatieren. An dem oben genannten Beispiel gibt es die Spalte created. Die Übersicht soll im mode=1 erfolgen. Dabei wird der Timestamp nicht konvertiert. Dies erledigt Contao nur bei der tstamp Spalte automatisch. Außerdem soll ausgegeben werden, ob das Feedback bereits einem bearbeitenden Nutzer zugewiesen wurde. Hierbei soll lediglich ja/nein und nicht der Beutzername ausgegeben werden. Für beide Fälle bringt dca-rules wieder Regeln mit. Während alle anderen Regeln immer einen Abbruch der Überprüfung erreichen können, werden die LabelRegeln immer durchgeführt.

Diese werden folgendermaßen konfiguriert:

$GLOBALS['TL_DCA']['tl_feedback']['list']['label'] = array
(
    'fields' 				=> array('id', 'created', 'userid'),
    'showColumns' 			=> true,
    'label_callback' 			=> array('Feedback', 'generateLabel'),
    'label_rules' 			=> array(),			
);

Wir erzeugen also eine Listenansicht, die tabellarisch ausgegeben wird mit den Spalten id, created und userid. Statt der Userid werden wir eine ja/nein ausgabe machen. Auch hier wird der bereits vorhandene Callback aufgerufen.

Was man bei den Regeln für Label beachten muss, dass die Werte von Contao in einem Array $values nach dem Index der oben aufgelisteten Felder überliefert bekommt. in $vlaues[0] steht also die ID, nd $values[1] der Timestamp usw. Dazu gibt es auch ein Array mit den unbearbeiten Werten $row['id']. Manchmal konvertiert Contao den Wert bereits in eine Ausgabe. Beispielsweise bei einen Boolean Wert. So wird hier entweder ein - für eine leere Angabe, oder die Spaltenbezeichnung angegeben. Aus diesem Grund verwenden die Label Regeln sowohl ein Attribute index wie auch field, um zwischen den beiden Werten wählen zu können. Der Index ist immer erforderlich, da er die Position der Ausgabe entscheidet.

Für den hier beschriebenen Fall stehen zwei Regeln zur Verfügung: parseDate und yesNo. Dabei wird der yesNo Regel sowohl der Index als auch das Feld übergeben. Das Feld wird dann anhand des Attributes condition überprüft. Da "ja" ausgeben werden soll, wenn der Wert > 0 ist, muss die Überprüfung noch auf false gesetzt werden:

$GLOBALS['TL_DCA']['tl_feedback']['list']['label'] = array
(
    'label_rules' 			=> array('parseDate:index=1', 'yesNo:index=2:field=created:condition=0:is=false'),			
);

Dadurch könenn wir so gut wie alle Aktionen der Tabelle lösen ohne einen einzigen Callback geschrieben zu haben!

Vorhandene Regeln

Nachdem anhand des Beispiels die Funktionsweise erläutert wurde, gibt es hier eine Übersicht der vordefinierten Regeln. Auf den jeweiligen Unterseiten ist die Verwendungsweise der Regeln näher erläutert:

Permission Regeln

  • generic
  • hasAccess
  • isAllowed
  • isAdmin
  • forbidden

Button Regeln

  • disableIcon
  • toggleIcon
  • referer
  • hasAccess
  • isAllowed
  • isAdmin

Label Regeln

  • parseDate (index,field,format= einen Timestamp parsen
  • yesNo (index,field,codition,is) ja/nein ausgeben

Eigene Regeln definieren

Neben den vordefinierten Regeln können auch eigene Regeln definiert werden. Diese werden als Methoden in dem DataContainer definiert und folgen folgenden Konventionen. Die Button Regeln werden sowohl für die globale als auch lokale Buttons verwendet. Bei globalen ist $arrRow=null.

protected function permissionRule*($objDc, &$arrAttributes, &$strError);
protected function buttonRule*(&$strButton, &$strHref, &$strLabel, &$strTitle, &$strIcon, &$strAttributes, &$arrAttributes, $arrRow=null);
protected function labelRule*(&$arrRow, &$strLabel, &$objDc, &$arrValues, &$arrAttributes);

Da die Variablen per Referenz übergeben werden, können sie so von einer Regel zur nächsten weitergereicht werden. Möchte eine Regel beispielsweise das Icon ersetzen, so muss lediglich die icon Variable neu gesetzt werden.

protected function buttonRuleChangeIcon(&$strButton, &$strHref, &$strLabel, &$strTitle, &$strIcon, &$strAttributes, &$arrAttributes, $arrRow=null)
{
    $strIcon = (isset($arrAttribute['icon']) ? $arrAttribute['icon'] : 'change.gif';
}

Sollen Attribute weitergereicht werden, so ist es erforderlich, diese als solche zu kennzeichnen. Damit wird verhindert, dass sich die einzelnen Regeln ungewollt gegenseitig beinflussen, aber dennoch Anweisungen an nächste Regeln gesetzt werden können. Dazu muss unter $arrAttributes['__set__'] das entsprechende Feld hinzugefügt werden. Sinnvoll ist dies beispielsweise, wenn eine Regel die Ausgabe beeinflussen möchte:

protected function buttonRuleReferer(&$strButton, &$strHref, &$strLabel, &$strTitle, &$strIcon, &$strAttributes, &$arrAttributes, $arrRow=null)
{
    $strHref = $this->getReferer(true);
 
    // do not use addToUrl() instead use plain href
    $arrAttributes['plain'] = true;
    $arrAttributes['__set__'][] = 'plain';
 
    return true;
}
Ansichten
Meine Werkzeuge

Contao Community Documentation

Ich brauch nen Bier, es ist zwar noch nicht nach 4, aber es ist nach Oli.

Yanick Witschi
Navigation
Verstehen
Verwenden
Entwickeln
Verschiedenes
Werkzeuge