C3: Tutorial Extension Entwicklung 2.Teil: Selective DCA Paletten und Subpaletten

Aus Contao Community Documentation

Einleitung

Dieses Tutorial ist der zweite Teil einer Tutorial-Reihe:
http://de.contaowiki.org/C3:_Tutorial_Extension_Entwicklung_1.Teil:_Grundlagen

...es basiert auf der großartigen Screencast-Reihe von Tristan Lins. Unbedingt ansehen!
Videolink : DCA Paletten und Subpaletten, MetaPalettes

An wen richtet sich dieses Tutorial?

Dieses Tutorial ist für all diejenigen gedacht, die ein Step-by-Step Tutorial zum Einstieg in die Extension-Entwicklung mit Contao 3 suchen.

Lernziel

Das Screencast-Modul aus dem ersten Teil wird um zusätzliche Funktionen erweitert: Der BE-User kann nun unter verschiedenen Screencast-Quellen auswählen. In Abhängigkeit der Quellen ändern sich die nachfolgenden Eingabe- bzw. Auswahlfelder. Diese kontextsensitiven Felder bezeichnet man in Conato als selektive Paletten.

So sieht eine Ansicht unserer fertigen Erweiterung aus:
T2 youtube.png

Was man wissen sollte

Grundlagen in PHP, objektorientierter Programmierung und SQL sind nötig. Ferner sollte man Grundlagen der Extension-Entwicklung in Contao verstanden haben (Verzeichnisstruktur, DCA, Templates).

Wer damit noch Schwierigkeiten hat, der sollte hier:
http://de.contaowiki.org/C3:_Tutorial_Extension_Entwicklung_1.Teil:_Grundlagen
nochmal die Grundlagen nachlesen.

Vorbereitung

Der fertige Quellcode aus dem ersten Teil muss vorhanden sein.

Source-Code

Den Quellcode könnt ihr hier: https://github.com/bit3/contao-screencast3 herunterladen.

Hinweis.png Hinweis: Es kann sein, dass der Quellcode auf github bereits einer fortgeschritteneren Version entspricht. Passt die Dateien daher ggf. dem Code der beiden Tutorials an oder (am besten) programmiert alles selber!


Definition der Anwendungsfälle

Unsere Anwendung soll folgendes leisten:

  1. Zunächst hat der BE-User nur die Auswahl, welche Screencast-Quelle er eingeben möchte und welchen Titel er dieser Quelle gibt. Zur Auswahl stehen hier: Keine Quelle (default), Remote-Quelle oder Lokale-Quelle.
  2. Hat er die Wahl getroffen, werden zusätzliche Optionen sichtbar.

1. Fall: Keine Quelle

Es werden keine zusätzlichen Optionen angezeigt.

2. Fall: Lokal

Es wird die Möglichkeit gegeben, direkt auf eine Datei aus der Dateiverwaltung zu verlinken.

3. Fall: Remote

Es wird die Möglichkeit gegeben, zwischen zwei Remote-Plattformen zu wählen (Youtube und Vimeo).

Entscheidet sich der User für "Youtube", erhält er die Optionen die Video-URL einzutragen, nach Ende des Videos vorgeschlagene Videos einzublenden, über HTTPS zu streamen, erweiterten Datenschutz zu aktivieren und die Größe anzugeben. Bei der Größe kann er zusätzlich zwischen zwei Optionen wählen: Vordefinierte Größe und individuelle Größe.

Bei "Vimeo" erhält er die Optionen die Video-URL einzutragen und eine Größe anzuwählen. Auch hier hat er bei der Größe zusätzlich die Wahl zwischen zwei Optionen: Vordefinierte Größe und individuelle Größe.

Die DCA-Paletten

Was sind Paletten und Subpaletten?

Bei Paletten handelt es sich um eine Gruppe von Eingabe und Auswahlfeldern, die zu einem Modul oder Element gehören. Paletten sind logischerweise immer an den Anwendungsfall angepasst.

Hier zwei Beispiele für wohlbekannte Paletten: Die der Inhaltselemente "Überschrift" und "Hyperlink". Unterschiedliche C3 Paletten

Paletten können sich aber nicht nur grundsätzlich (Überschrift, Hyperlink, News,...) sondern auch dynamisch innerhalb eines Moduls bzw. Elements unterscheiden:
Hier ein Beispiel für unterschiedliche Paletten unserer Extension "Screencast":
T2 mcPaletten.png

Subpaletten ergänzen Paletten um einzelne Felder. Subpaletten werden innerhalb eines Moduls oder Elements meist von mehreren Paletten gemeinsam verwendet.
Hier ein Beispiel für Anzeigeoptionen der Videos. Diese wird gemeinsam von der Palette Youtube und Vimeo verwendet:
T2 subPaletten.png

Für die unterschiedlichen Ansichten müssen daher die jeweiligen Paletten definiert werden.

Definition der Paletten

  • Öffnet die Datei dca/tl_screencast.php und modifiziert den Code im Bereich palettes wie folgt:
	// Palettes
	'palettes' => array
	(
		'__selector__'  => array('type', 'platform', 'defineSize'),
		'default'       => '{title_legend},type,title',
		'remote'        => '{title_legend},type,title;{screencast_legend},platform',
		'remote_youtube' => '{title_legend},type,title;{screencast_legend},platform,url,youtubeShowSuggestions,youtubeHttps,youtubeExtendedDataSecurity;{display_legend:hide},defineSize',
		'remote_vimeo'   => '{title_legend},type,title;{screencast_legend},platform,url;{display_legend:hide},defineSize',
		'local'         => '{title_legend},type,title;{screencast_legend},path',
	),
		// Subpalettes
	'subpalettes' => array
	(
		'defineSize_predefined' => 'sizePredefined',
		'defineSize_custom'	=> 'sizeCustom'
	),

Was passiert hier?
Im ersten Teil dieser Reihe gab es nur eine Palette (default). In unserem erweiterten Modul Screencast werden nun für die verschiedenen Anwendungsfälle unterschiedliche Eingabe- und Auswahlfelder nötig. Diese werden in den unterschiedlichen Paletten definiert.

Gehen wir die Paletten in der Reihenfolge durch, wie sie auch in der Extension auftauchen. Achtet dabei auf die Parallelen in der folgenden Beschreibung (type, local, remote) und in der Palettendefinition:

Die default Palette

Die default-Palette wird immer zuerst angezeigt. In unserem Beispiel hat der BE-User also zuächst nur die Möglichkeit, einen bestimmten Screencast-Typ (type) auszuwählen und einen Titel (title) einzugeben.

T2 pdefault.png

Die local Palette

Die local Palette zeigt sich dem User, wenn er im Bereich type die Auswahl local trifft.

T2 plocal.png

Die remote Palette

Die remote Palette zeigt sich dem User, wenn er im Bereich type die Auswahl remote trifft.

T2 premote.png

Die remote_youtube Palette

Die remote_youtube Palette zeigt sich dem User, wenn er im Bereich type die Auswahl remote trifft und anschließend im Feld Plattform youtube wählt.

T2 pyoutube.png

Die remote_vimeo Palette

Die remote_vimeo Palette zeigt sich dem User, wenn er im Bereich type die Auswahl remote trifft und anschließend im Feld Plattform vimeo wählt.

T2 pvimeo.png

Die Subpalette defineSize

Die defineSize Subpalette ist eine Zusatzpalette, die angezeigt wird, wenn der User im Bereich type die Auswahl remote trifft, sich daraufhin im Feld Plattform für vimeo oder youtube entscheidet und dann noch eine Option zur Einstellung der Videogröße wählt. T2 subPaletten.png

Wozu dient dann __selector__?

Im Bereich palettes wird auch definiert, welche Felder überhaupt zu einem Wechsel der Paletten führen können.
In unserem Beispiel wechseln die Paletten also, wenn der User einen bestimmten type, eine platform oder eine bestimmte Größe (defineSize) ausgewählt hat.
Dies sagt jedoch noch nichts darüber aus, welche Werte die Felder haben müssen, um z.B. die Palette remote_youtube aufzurufen.
Dies geschieht in der Definition der Felder:

Die Eingabe- und Auswahlfelder anlegen

  • Ergänzt euren Code im Bereich fields um folgende Zeilen. Der Ordnung halber am besten unter dem Feld tstamp:
	'type'  => array
		(
			'label'     => &$GLOBALS['TL_LANG']['tl_screencast']['type'],
			'inputType' => 'select',
			'exclude'   => true,
			'sorting'   => true,
			'flag'      => 1,
			'options'   => array('remote', 'local'),
			'reference' => &$GLOBALS['TL_LANG']['tl_screencast'],
			'eval'      => array(
				'includeBlankOption' => true,
				'submitOnChange'     => true,
				'mandatory'          => true,
				'tl_class'           => 'w50',
			),
			'sql'       => "varchar(10) NOT NULL default ''"
		),

Was passiert hier?

Die meisten Einträge sollten aus dem 1. Tutorial bekannt sein. Interessant sind folgende Elemente:
*inputType: Hier soll nun ein Select-Feld angezeigt werden.
*options: Hier werden die Optionen des Select-Feldes definiert. Beachtet, dass hier die Werte für die entsprechenden neuen Paletten definiert werden.
*includeBlankOption: In den Optionen der Select-Felder erscheint auch ein leerer Eintrag (nichts gewählt).
*submitOnChange: Die Formularfelder werden immer abgesendet, wenn ihr eine neue Option im Selectfeld wählt. Das ist praktisch, da der User sonst immer erst auf "Speichern" klicken müsste, um die geänderte Palette zu sehen.

  • Speichert die Datei und aktualisiert eure Datenbank.
  • In eurer Erweiterung solltet ihr nun eine Typ-Auswahlmöglichkeit haben.

Da jedoch jede Menge Felder, die bereits in den Paletten definiert wurden fehlen, hält sich der Spaß noch in Grenzen.

  • Tauscht euren Code im fields-Bereich mit folgendem Code aus bzw. modifiziert ihn entsprechend:
	// Fields
	'fields'   => array
	(
		'id'     => array
		(
			'sql' => "int(10) unsigned NOT NULL auto_increment"
		),
		'tstamp' => array
		(
			'sql' => "int(10) unsigned NOT NULL default '0'"
		),
		'type'  => array
		(
			'label'     => &$GLOBALS['TL_LANG']['tl_screencast']['type'],
			'inputType' => 'select',
			'exclude'   => true,
			'sorting'   => true,
			'flag'      => 1,
			'options'   => array('remote', 'local'),
			'reference' => &$GLOBALS['TL_LANG']['tl_screencast'],
			'eval'      => array(
				'includeBlankOption' => true,
				'submitOnChange'     => true,
				'mandatory'          => true,
				'tl_class'           => 'w50',
			),
			'sql'       => "varchar(10) NOT NULL default ''"
		),
		'title'  => array
		(
			'label'     => &$GLOBALS['TL_LANG']['tl_screencast']['title'],
			'inputType' => 'text',
			'exclude'   => true,
			'sorting'   => true,
			'flag'      => 1,
			'search'    => true,
			'eval'      => array(
				'mandatory' => true,
				'unique'    => true,
				'maxlength' => 255,
				'tl_class'  => 'w50'
			),
			'sql'       => "varchar(255) NOT NULL default ''"
		),
		'platform'  => array
		(
			'label'     => &$GLOBALS['TL_LANG']['tl_screencast']['platform'],
			'inputType' => 'select',
			'exclude'   => true,
			'sorting'   => true,
			'flag'      => 1,
			'options'   => array('remote_youtube', 'remote_vimeo'),
			'reference' => &$GLOBALS['TL_LANG']['tl_screencast'],
			'eval'      => array(
				'includeBlankOption' => true,
				'submitOnChange'     => true,
				'mandatory'          => true,
				'tl_class'           => 'w50',
			),
			'sql'       => "varchar(20) NOT NULL default ''"
		),
		'url'    => array
		(
			'label'     => &$GLOBALS['TL_LANG']['tl_screencast']['url'],
			'inputType' => 'text',
			'exclude'   => true,
			'eval'      => array(
				'tl_class' => 'w50'
			),
			'sql'       => "text NULL"
		),
		'path'    => array
		(
			'label'     => &$GLOBALS['TL_LANG']['tl_screencast']['path'],
			'inputType' => 'fileTree',
			'exclude'   => true,
			'sql'       => "text NULL"
		),
		'youtubeShowSuggestions'    => array
		(
			'label'     => &$GLOBALS['TL_LANG']['tl_screencast']['youtubeShowSuggestions'],
			'inputType' => 'checkbox',
			'exclude'   => true,
			'eval'      => array(
				'tl_class' => 'w50 m12'
			),
			'sql'       => "char(1) NOT NULL default ''"
		),
		'youtubeHttps'    => array
		(
			'label'     => &$GLOBALS['TL_LANG']['tl_screencast']['youtubeHttps'],
			'inputType' => 'checkbox',
			'exclude'   => true,
			'eval'      => array(
				'tl_class' => 'w50 m12'
			),
			'sql'       => "char(1) NOT NULL default ''"
		),
		'youtubeExtendedDataSecurity'    => array
		(
			'label'     => &$GLOBALS['TL_LANG']['tl_screencast']['youtubeExtendedDataSecurity'],
			'inputType' => 'checkbox',
			'exclude'   => true,
			'eval'      => array(
				'tl_class' => 'w50 m12'
			),
			'sql'       => "char(1) NOT NULL default ''"
		),
		'defineSize'    => array
		(
			'label'     => &$GLOBALS['TL_LANG']['tl_screencast']['defineSize'],
			'default'   => 'predefined',
			'inputType' => 'select',
			'exclude'   => true,
			'options'   => array('predefined', 'custom'),
			'reference' => &$GLOBALS['TL_LANG']['tl_screencast'],
			'eval'      => array(
				'submitOnChange' => true,
				'tl_class'       => 'clr w50 m12'
			),
			'sql'       => "varchar(12) NOT NULL default ''"
		),
		'sizeCustom'    => array
		(
			'label'     => &$GLOBALS['TL_LANG']['tl_screencast']['sizeCustom'],
			'inputType' => 'text',
			'exclude'   => true,
			'eval'      => array(
				'multiple' => true,
				'size'     => 2,
				'tl_class' => 'clr w50'
			),
			'sql'       => "varchar(255) NOT NULL default ''"
		),
			'sizePredefined'    => array
		(
			'label'     => &$GLOBALS['TL_LANG']['tl_screencast']['sizePredefined'],
			'inputType' => 'radio',
			'exclude'   => true,
			'options' 	=> array('640x480', '854x480'),
			'eval'      => array(
				'multiple' => true,
				'size'     => 2,
				'tl_class' => 'clr w50'
			),
			'sql'       => "varchar(12) NOT NULL default ''"
		),
	)
);

Ich habe hier jetzt das komplette Ende der DCA-Datei aufgeführt, damit evtl. Tipp-, Klammerfehler o.ä. vermieden werden.

Die Beziehung zwischen den Paletten und den Feldern

Wer sein Augenmerk auf die Eigenschaft options der Felder type und platform richtet, wird feststellen, dass an dieser Stelle die Werte für den Aufruf der entsprechenden Paletten definiert werden.

Achtung.png Achtung: Hier besteht eine Abweichung vom Source Code auf github. Ich finde es nachvollziehbarer, wenn die options-Werte genauso lauten, wie die Paletten.


Die Beziehung zwischen den Subpaletten und den Feldern

Bei den Subpaletten ist das ein klein wenig anders (wenigsten bei select-Feldern und radio-Buttons).

Das Feld defineSize ist ein Select-Feld, welches als options die Werte predefined und custom erhält.

Um je nach Auswahl die Subpaletten wechseln zu lassen, müssen diese Werte in der Definition der Subpalettes als Suffix an den aufrufenden Feldnamen angehängt werden. Bei checkboxen reicht der direkte Verweis auf das neue Feld. Schaut da z.B. mal in die DCA tl_news.php. Dort sieht man das ganz schön.


Achtung.png Achtung: Hier besteht eine Abweichung vom Source Code auf github. Bitte ändert den Code entsprechend.


Die Übersetzung

  • Tauscht den Code in der Datei languages/de/tl_screencast.php gegen diesen hier aus:
<?php
$GLOBALS['TL_LANG']['tl_screencast']['title_legend'] = 'Titel';
$GLOBALS['TL_LANG']['tl_screencast']['path'][0] = 'Dateipfad';
$GLOBALS['TL_LANG']['tl_screencast']['path'][1] = 'Pfad zum lokalen Video';
 
$GLOBALS['TL_LANG']['tl_screencast']['type'][0] = 'Typ';
$GLOBALS['TL_LANG']['tl_screencast']['type'][1] = 'Wählen Sie hier aus, ob es sich um ein externes oder lokales Video handelt.';
 
$GLOBALS['TL_LANG']['tl_screencast']['title'][0] = 'Titel';
$GLOBALS['TL_LANG']['tl_screencast']['title'][1] = 'Geben Sie hier den Screencast Titel ein.';
 
$GLOBALS['TL_LANG']['tl_screencast']['screencast_legend'] = 'Screencast';
 
$GLOBALS['TL_LANG']['tl_screencast']['platform'][0] = 'Platform';
$GLOBALS['TL_LANG']['tl_screencast']['platform'][1] = 'Wählen Sie hier die Videoplatform aus.';
 
$GLOBALS['TL_LANG']['tl_screencast']['url'][0] = 'Video URL';
$GLOBALS['TL_LANG']['tl_screencast']['url'][1] = 'Geben Sie hier die Video URL ein.';
 
$GLOBALS['TL_LANG']['tl_screencast']['youtubeShowSuggestions'][0] = 'Vorgeschlagene Videos anzeigen';
$GLOBALS['TL_LANG']['tl_screencast']['youtubeShowSuggestions'][1] = 'Nach Ende des Videos vorgeschlagene Videos anzeigen.';
 
$GLOBALS['TL_LANG']['tl_screencast']['youtubeHttps'][0] = 'HTTPS verwenden';
$GLOBALS['TL_LANG']['tl_screencast']['youtubeHttps'][1] = 'Streamt das Video via HTTPS.';
 
$GLOBALS['TL_LANG']['tl_screencast']['youtubeExtendedDataSecurity'][0] = 'Erweiterter Datenschutz';
$GLOBALS['TL_LANG']['tl_screencast']['youtubeExtendedDataSecurity'][1] = 'Aktiviert den erweiterten Datenschutz Modus.';
 
$GLOBALS['TL_LANG']['tl_screencast']['display_legend'] = 'Anzeige';
 
$GLOBALS['TL_LANG']['tl_screencast']['defineSize'][0] = 'Größenoptionen wählen';
$GLOBALS['TL_LANG']['tl_screencast']['defineSize'][1] = 'Wählen Sie, ob Sie eine festgelegte Größe oder eine individuelle Größe festelegen möchten.';
 
$GLOBALS['TL_LANG']['tl_screencast']['sizePredefined'][0] = 'Größe festlegen';
$GLOBALS['TL_LANG']['tl_screencast']['sizePredefined'][1] = 'Legt die Ausgabegröße fest.';
 
$GLOBALS['TL_LANG']['tl_screencast']['sizeCustom'][0] = 'Größe';
$GLOBALS['TL_LANG']['tl_screencast']['sizeCustom'][1] = 'Geben Sie hier die Größe an.';
 
$GLOBALS['TL_LANG']['tl_screencast']['new'][0] = 'Neuer Screencast';
$GLOBALS['TL_LANG']['tl_screencast']['new'][1] = 'Einen neuen Screencast anlegen';
 
$GLOBALS['TL_LANG']['tl_screencast']['edit'][0] = 'Screencast bearbeiten';
$GLOBALS['TL_LANG']['tl_screencast']['edit'][1] = 'Screencast ID %s bearbeiten';
 
$GLOBALS['TL_LANG']['tl_screencast']['delete'][0] = 'Screencast löschen';
$GLOBALS['TL_LANG']['tl_screencast']['delete'][1] = 'Screencast ID %s löschen';
 
$GLOBALS['TL_LANG']['tl_screencast']['show'][0] = 'Screencastdetails';
$GLOBALS['TL_LANG']['tl_screencast']['show'][1] = 'Details des Screencast ID %s anzeigen';
 
$GLOBALS['TL_LANG']['tl_screencast']['remote'] = 'Externes Video';
$GLOBALS['TL_LANG']['tl_screencast']['local']  = 'Lokales Video';
 
$GLOBALS['TL_LANG']['tl_screencast']['remote_youtube'] = 'YouTube';
$GLOBALS['TL_LANG']['tl_screencast']['remote_vimeo']   = 'Vimeo';
 
$GLOBALS['TL_LANG']['tl_screencast']['predefined'] = 'Vordefinierte Größe';
$GLOBALS['TL_LANG']['tl_screencast']['custom']   = 'Individuelle Größe';

Was passiert hier? Die Übersetzungen werden analog zum 1. Tutorial für die entsprechenden Felder eingepflegt.

Geschafft!

Wenn ich mich nicht verschrieben habe und ihr alles richtig gemacht habt, könnt ihr eure erweitertes Screencast-Modul nun einsetzen.

Was fehlt?

Die Erweiterung der Klasse ModuleScreencastList.php, die Ausgabe im Template und die Übersetzung. Das überlasse ich erstmal euch;-)

Ausblick

Sobald Tristan einen neuen Screencast zum Thema bringt, haue ich wieder in die Tasten. Grüße von kobajashi

Weiterführende Links

Die Erweiterung Metapalletes http://de.contaowiki.org/MetaPalettes

Ansichten
Meine Werkzeuge

Contao Community Documentation

Meiner Meinung nach, sollten zu kleine Webspacepakete entweder Webspaß-Pakete (man beachte die Ironie) oder Horsting-Pakete heißen!

Sascha Müller
Navigation
Verstehen
Verwenden
Entwickeln
Verschiedenes
Werkzeuge