Wenn man des Öfteren an verschiedenen TYPO3 Projekten arbeitet – bspw. als TYPO3 Integrator in einer Agentur – bietet es sich an, eine Extension zu entwickeln, die als zentrale TypoScript Bibliothek dient. Darüber hinaus können mit der Extension bestimmte Backend Einstellungen für den Redakteur (User TSconfig) und global für die Installation (Page TSconfig) eingebunden werden. Ziel dieses Beitrags ist es, eine solche Extension zu erstellen und Potentiale zur Effizienzsteigerung aufzuzeigen. Vorausgesetzt werden fortgeschrittene TYPO3 Kenntnisse und erste Erfahrungen im Umgang mit dem Extension Kickstarter sowie eine frische TYPO3 Installation.
Schritt 1: Extension anlegen
Mit Hilfe des Extension Kickstarters erstellt man eine neue Extension. Als Extension Key wählt man bspw. generic_lib und füllt alle notwendigen Felder im Bereich „General info“. Hierzu gehören ein Titel (z.B. Generic Library) und eine kurze Beschreibung. Außerdem kann man eine Kategorie angeben (z.B. Miscellaneous), einen Status wählen (z.B. Beta) sowie seinen Namen und eine E-Mail Adresse angeben. Nachdem alle Daten eingetragen und der Button „Update“ geklickt wurde, wechselt man zum Bereich „Static TypoScript code“.
Hier vergibt man für das statische Extension Template bspw. den Titel „Generic Lib“ und fügt den ersten TypoScript Code in die vorgesehen Textfelder einfügen.
Constants
In den Constants werden Pfade definiert, die uid der Root Seite festgelegt und ein Standard Logo sowie der Titel der TYPO3 Website vergeben.
generic_lib { pathRoot = fileadmin/templates/ #relative to pathRoot pathImages = images/ pathCss = css/ websiteRootUid = 1 websiteLogo = logo.png websiteTitle = Hello World Website } |
Setup
Im Setup erzeugt man eine Bibliothek, die das Logo der Website ausgibt. Das Logo ist verlinkt zur Startseite. Der Link ist absolut, um valides HTML auch bei Verwendung von RealURL zu erzeugen. Ohne die Angabe wäre das href Attribut leer.
#get website logo and wrap it with link to homepage lib.getLogo = IMAGE lib.getLogo { file = {$generic_lib.pathRoot}{$generic_lib.pathImages}{$generic_lib.websiteLogo} altText = Go to homepage of {$generic_lib.websiteTitle} altText.lang.de = Zur Startseite von {$generic_lib.websiteTitle} stdWrap.typolink.parameter = {$generic_lib.websiteRootUid} stdWrap.typolink.forceAbsoluteUrl = 1 } |
Nun klickt man auf den Button „View result“ und prüft, welche Dateien erzeugt werden. Die aktuellen Einstellungen sollen genügen und so klickt man auf den Button „Write“, um die Extension im Verzeichnis /typo3conf/ext zu generieren.
Nachdem die Extension erzeugt wurde, kann man sie installieren und den Cache leeren. Um zu prüfen, ob alles geklappt hat, erzeugt man das TypoScript Root Template. Danach wechselt man auf den Reiter „Enthält“. Dort sollte man im Select „Verfügbare Objekte“ einen neuen Eintrag „Generic Lib (generic_lib)“ sehen können. Falls dies so ist, hat man alles richtig gemacht. Man fügt als erstes CSS Styled Content und danach die Generic Lib ein.
Schritt 2: Erster Einsatz
Für einen ersten Test soll die Bibliothek „lib.getLogo“ eingebunden werden. Im Setup des TypoScript Root Templates setzt man folgende Konfiguration.
page = PAGE page { typeNum = 0 10 < lib.getLogo } |
Sobald das Logo im Pfad /fileadmin/templates/images/logo.png vorliegt, wird es auf der Website angezeigt.
Schritt 3: Optimierung und Erweiterung der Bibliothek
IMHO hat der Kickstarter eine überflüssige Verzeichnisebene “generic_lib“ im Verzeichnis „static“ angelegt. Als erstes verschiebt man die beiden Dateien constants.txt und setup.txt von /static/generic_lib/ nach /static. Danach generiert man folgende zusätzliche Verzeichnisse und Dateien.
/static/language/language.ts /static/navigation/navigation.ts /static/libs/libs.ts |
Die Datei /ext_tables.php ist anzupassen, um die geänderte Verzeichnisstruktur TYPO3 bekannt zu geben. Durch die Änderung ist leider auch das statische Template erneut dem TypoScript Root Template im Backend zuzuordnen.
t3lib_extMgm::addStaticFile($_EXTKEY,'static/', 'Generic Lib'); |
Es bietet sich an, in die setup.txt allgemein gültige Konfigurationen vorzunehmen. So definiere ich in dieser Datei bereits das Template und das Page Objekt und setze einige stets wiederkehrende config Einstellungen. Der folgende Code zeigt ein Auszug meiner setup.txt Definition.
#set page object page = PAGE page { typeNum = 0 #set new page title config.noPageTitle = 2 stylesheet = {$pathRoot}{$pathCss}screen.css shortcutIcon = {$pathRoot}{$pathImages}favicon.ico headerData { 10 = TEXT 10 { field = title wrap = <title>| | {$websiteTitle}</title> htmlSpecialChars = 1 } } } #general config config { #global variables linkVars = L disablePrefixComment = 1 doctype = xhtml_trans xmlprologue = none xhtml_cleaning = all #change title to "Seitentitel - Allgemeiner Titel" pageTitleFirst = 1 } |
Außerdem inkludiert man am Ende der setup.txt die oben erzeugten zusätzlichen Dateien.
#include language TS <INCLUDE_TYPOSCRIPT: source="FILE:EXT:generic_lib/static/language/language.ts"> #include navigation TS <INCLUDE_TYPOSCRIPT: source="FILE:EXT:generic_lib/static/navigation/navigation.ts"> #include additional libs <INCLUDE_TYPOSCRIPT: source="FILE:EXT:generic_lib/static/libs/libs.ts"> |
In der language.ts wird eine grundlegende Sprachkonfiguration vorgenommen.
config { sys_language_uid = 0 language = de locale_all = de_DE.UTF8 htmlTag_langKey = de_DE } |
In der navigation.ts speichert man öfters verwendete Navigationsobjekte. In meinem Fall habe ich ein TMENU lib.navigation angelegt mit bis zu 4 Ebenen. Ein weiteres TMENU lib.navigation_open basiert auf der lib.navigation, hat aber die Eingeschaft expAll = 1. So kann ich bspw. ein per CSS gesteuertes ausklappendes Menü abbilden. Weiterhin habe ich einige libs angelegt, die vom Typ „special“ sind. Hier lassen sich hervorragend Menüs einzelner Seiten ausgeben (special = list), Menüs von Unterseiten (special = directory), Sprachmenüs (special = language) oder der Brotkrumenpfad (special = rootline). Flexibilität entsteht durch die Verwendung von Constants, wie das folgende Beispiel zeigt.
#draw navigation with one layer lib.navigation = HMENU lib.navigation { entryLevel = {$generic_lib.navigationEntryLevel} 1 = TMENU 1 { wrap = <ul class="lvl1">|</ul> NO.linkWrap = <li class="first">|</li> |*| <li>|</li> |*| <li class="last">|</li> } 2 < .1 2.wrap = <ul class="lvl2">|</ul></li> } #draw special navigation based on special menu - list lib.navigation_special = HMENU lib.navigation_special { special = list special.value = {$generic_lib.navigationSpecialPidList} includeNotInMenu = 1 1 < lib.navigation.1 } #draw special navigation based on special menu - directory lib.navigation_special_dir < lib.navigation_special lib.navigation_special_dir { special = directory special.value = {$generic_lib.navigationSpecialPidDir} } |
In der libs.ts finden alle sonstigen Bibliotheken Platz. Hier wäre auch das weiter oben erstellte lib.getLogo unterzubringen. Neben dieser Standard Funktion habe ich bspw. eine lib angelegt, die das Feld „media“ einer Seiten ausliest.
#get page media resource lib.getMainImage = IMAGE lib.getMainImage { file.import = uploads/media/ file.import.data = levelmedia:-1, slide file.import.listNum = 0 } |
Das im Schritt 2 erstellte PAGE Objekt könnte man nun wie folgt ändern und erweitern. Dabei ist zu beachten, dass die generic_lib schon das PAGE Objekt erstellt und wir uns dadurch einige Zeilen Konfiguration sparen. Damit die Navigation funktioniert, ist in den Constants noch generic_lib.navigationEntryLevel = 0 zu setzen.
page { 10 < lib.getLogo 20 < lib.getMainImage 30 < lib.navigation 40 < styles.content.get } |
Noch ein Hinweis. Die automatisch per Kickstarter erzeugte Datei „ChangeLog“ sollte man verwenden, um Änderungen an der Extension zu dokumentieren. Dabei bietet es sich an, in der Datei „ext_emconf.php“ den Wert für die Eigenschaft „version“ zu erhöhen. Weiterhin können in der Datei über den Wert $EM_CONF[$_EXTKEY] [constraints][depends] Abhängigkeiten von anderen Extensions und bspw. der TYPO3 und PHP Version gepflegt werden.
Ich verwende auf unseren TYPO3 Servern globale TYPO3 Sourcen (via symlinks). Dort habe ich die generic_lib im Verzeichnis /typo3/ext abgelegt. Die generic_lib wird als globale Extension in der jeweiligen TYPO3 Instanz installiert. So ist nur eine Version der generic_lib zu pflegen. Sicherlich gibt es hier auch andere Möglichkeiten. Wichtig ist nur, dass man lediglich eine generic_lib pflegen muss 🙂
Ausblick und Potential
Die generic_lib stellt erst den Anfang dar. Man könnte nun eine weitere Extension pro Website „theme_PROJEKT“ erstellen und dort projektspezifische TypoScript Konfigurationen einfügen. Im Theme liegen alle benötigten CSS, HTML (sowohl Layout als auch Extension HTML Templates), Images und JavaScript Dateien. Diese Vorgehensweise bringt mehrere Vorteile:
- Es wird kein TypoScript mehr in der Datenbank gespeichert und über das Backend editiert. Man benötigt nur noch zwei Zeilen TypoScript, um das TypoScript des Themes zu inkludieren. Für die Constants <INCLUDE_TYPOSCRIPT: source=“FILE:EXT:theme_PROJEKT/files/ts/constants.ts“> und für das Setup <INCLUDE_TYPOSCRIPT: source=“FILE:EXT:theme_PROJEKT/files/ts/setup.ts“>.
- Dadurch kann man mit seinem Lieblingseditor das TypoScript extern bearbeiten. Ich verwende Notepad++ mit TypoScript Syntax Highlighting. Sehr komfortabel 😉
- Man kann eine Versionskontrolle wie SVN oder git verwenden.
In den TypoScript Dateien verwendet man dann unproblematisch die Konfiguration und Bibliotheken der generic_lib. Durch diese Vorgehensweise ist es möglich, TYPO3 Projekte immer schneller umsetzen zu können.
Dies ist ein Gastbeitrag von Björn Jacob (TRITUM GmbH) für die “Alles muss raus” Aktion.