Tag Archives: TYPO3

TypoScript-Konfiguration in Extbase Command Controller

Für die Umsetzung einer komfortablen Import-Funktion griff ich bei einem aktuellen Projekt auf das Command-Framework von Extbase zurück. Damit zu arbeiten ist eine wahre Freude; so wird z.B. der DocComment-Block von Kommando-Methoden automatisch ausgewertet und als Hilfetext im CLI-Dispatcher angezeigt. Selbst die Methoden-Argumente werden automatisch von $propertyName CLI-typisch als --property-name zur Verfügung gestellt. Ganz nebenbei wird hiermit auch gleich noch ein Scheduler-Task ohne jegliche weitere Konfiguration angelegt. Achja, die Einrichtung beschränkt sich übrigens auf eine einzige Zeile in der ext_localconf.php. In TYPO3 Flow genügt sogar allein die Existenz des Command-Controllers.

Neben allen Lobeshymnen stieß ich jedoch auf ein großes Problem: Im CLI-Kontext wurde meine TypoScript-Konfiguration nicht geladen.

Continue reading

Let’s bring the magic to Extbase

Beim Durchstöbern der Meldungen des Extension-Builder bin ich eher zufällig auf etwas gestoßen, was die Entwicklung von TYPO3-Erweiterungen mit Extbase revolutionieren könnte:

Workpaper: Magic for Domain Models
– A Plan for the Future of Models in Extbase

Um die Idee hinter dem Vorhaben zu verstehen, hier einmal eine kurze Auflistung der zum Hinzufügen eines einzelnen Felds zu einer einzigen Tabelle typischerweise notwendigen Schritte:

  1. Definition des Datenbank-Feldes (plus einer weiteren Tabelle bei MM-Beziehungen) in der ext_tables.sql,
  2. Hinzufügen der Eigenschaft nebst Getter und Setter zum betreffenden Model (plus ggf. Methoden zum Hinzufügen oder Entfernen von Elementen bei MM-Beziehungen),
  3. Hinzufügen des Felds zum TYPO3-Backend durch Anpassung der TCA-Definition der Tabelle,
  4. Ergänzen der notwendigen Übersetzungen (locallang_db.xml) und ggf. Beschreibungen/Hilfetexte (locallang_csh_*.xml)

Weitere Schritte ergeben sich, wenn z.B. MM-Beziehungen auch auf der Gegenseite bearbeitet/abgerufen werden können sollen. Insgesamt also eine Menge Schritte für eine eigentlich lapidare Erweiterung. Zudem verteilen sich die Schritte über mehrere Dateien deren Zusammenhang nicht unbedingt direkt ersichtlich ist. All dies zentral und mit minimalen Anpassungen vornehmen zu können würde Zeit und Aufwand sparen sowie mögliche Fehlerquellen reduzieren. Genau dies stellt das Projekt „Magic for Domain Models“ in Aussicht:

The core purpose is to make extension development, particularly modelling, more centralized and less prone to errors – and as a side bonus making it dynamic if so requested.

Erreicht werden soll dies um stark erweiterte Kennzeichnungen in den Kommentaren für Domain-Model und dessen Eigenschaften, was sich stark an die Möglichkeiten in FLOW3 anlehnt. Eine Beispiel-Konfiguration von der Projekt-Seite:

/**
 * Refrigerator Model
 *
 * (description and model annotiations ... )
 */
class Tx_Fedexample_Domain_Model_Refrigerator extends Tx_Extbase_DomainObject_AbstractEntity {
 
 // Other properties ...
 
 /**
 * Food content
 *
 * The parameters given to the "OneToMany" annotation are the default values which
 * will be used if not overridden - so they are shown for illustration only. You
 * can leave them out (just use @Magic\OneToMany) to use the table name in the relation
 * (tx_fedexample_domain_model_fooditem because Tx_FedExample_Domain_Model_FoodItem
 * is the type of relation. And the target field name from this Model (refrigerator).
 *
 * Note that a @Magic\Database annotations is not required here, it is automatically
 * applied based on the relation type. Although we use @Magic\Inline here there are
 * other options - like @Magic\Select and @Magic\Group, each with their own options.
 *
 * @var Tx_Extbase_Persistence_ObjectStorage<Tx_Fedexample_Domain_Model_FoodItem>
 * @Magic\Field(type="relation")
 * @Magic\OneToMany(foreignTable="tx_fedexample_domain_model_fooditem", foreignField="refrigerator")
 * @Magic\Inline(maxItems="1000")
 * @Magic\Column(provider="Tx_Magic_Provider_Column_InlineProvider", dynamic="TRUE")
 */
 protected $food;
 
}

Aus diesen Angaben kann automatisch geschlussfolgert werden, dass für die Datenbank-Tabelle tx_fedexample_domain_model_refrigerator ein Feld namens food definiert, als MM-Beziehung gekennzeichnet und im TYPO3-Backend via IRRE bearbeitet werden soll.

Darüber hinaus soll es aber auch möglich sein, das Bearbeiten von Feldern im TYPO3-Backend durch neue und benutzerdefinierte Widgets zu verbessern. Im Endeffekt sollen Datenbank-Definition, TCA-Konfiguration und Backend-Bearbeitungsmöglichkeiten an einer einzigen zentralen Stelle zusammengeführt werden: dem Model. Alle dafür von TYPO3 benötigten Angaben sollen automatisch und dynamisch generiert werden. All dies soll gänzlich optional sein, wobei nach einer gewissen Reifephase sicher nichts dagegen spricht, dies zum Standardverhalten zu machen. Wer spart sich nicht gerne Arbeit und Zeit.

Um das ganze performant zu halten, soll das Ergebnis der automatischen Code-Generierung natürlich Cache-fähig sein, was eingeplant, aber momentan noch ein offener Punkt ist. Der aktuelle Entwicklungsverlauf kann im TYPO3-Git-Repository der Magic-Erweiterung verfolgt werden. Initiiert und voran getrieben wird die Entwicklung von keinem geringeren als Claus Due, dem Kopf hinter den unschätzbar hilfreichen fed– und flux-Erweiterungen. Die Wahrscheinlichkeit, dass dieses Projekt also Realität wird ist sehr hoch. Hilfe in jeder Form ist allerdings sehr willkommen.

So muss Magie der Neuzeit aussehen.

Extbase: Model-Zugriff in Validatoren

Für den Fall, dass die Standard-Validatoren von Extbase oder benutzerdefinierte Validatoren für einzelne Eigenschaften eines Models nicht genügen, gibt es noch die Option eines benutzerdefinierten Validators mit vollem Zugriff auf die neue Instanz eines Models.

Dafür kann man sich eine gänzlich undokumentierte Feinheit des Extbase-Frameworks zunutze machen: standardmäßig wird in einem Standardpfad versucht, einen passenden Validator passend zu einem Model zu finden. Wieder ein Beispiel für „Konvention über Konfiguration“, worauf in Extbase und FLOW3 Wert gelegt wird.

Der besagte Validator wird standardmäßig unter Classes/Domain/Validator/ModelNameValidator.php gesucht. Wie bei allen Extbase-Validatoren üblich ist zur Erfüllung der Schnittstelle Tx_Extbase_Validation_Validator_ValidatorInterface (OOP-Konvention wäre hier eigentlich IValidator) eine Ableitung von Tx_Extbase_Validation_Validator_AbstractValidator empfehlenswert. Dessen isValid-Methode erhält als einziges Argument die betreffende Instanz des Models, womit dann beliebige Überprüfungen vorgenommen werden können. Da hier ein uneingeschränkter Zugriff auf alle Eigenschaften des Models gegeben ist, können so auch komplexe Validierungen mit Abhängigkeiten zwischen Eigenschaften und dergleichen vorgenommen werden.

Der Validator sollte zu guter Letzt wie immer true oder false zurückgeben um über das Ergebnis der Validierung zu informieren und im Fehlerfall zuvor noch eine aussagekräftige Fehlermeldung vermerken. Dies kann entweder über die addError-Methode oder direkt per Manipulation der errors-Eigenschaft geschehen:

// 1) addError()
$this->addError('Descriptive error message', 0000000000); // Hier sollte 0000000000 eine eindeutige Nummer sein
 
// 2) errors
$this->errors[] = new Tx_Extbase_Validation_Error('Descriptive error message', 0000000000); // Siehe oben

Letztere Variante bietet die Möglichkeit, manuell Instanzen von Tx_Extbase_Validation_PropertyError einzufügen. Dadurch können bestehende, auf Model-Eigenschaften optimierte, Partials für die Ausgabe von Validierungsfehlern ohne Anpassung verwendet werden. Dazu hängt man die eigentlichen Fehlermeldungen an eine Fake-Eigenschaft:

// Container für gruppierte Fehlermeldungen über eine Fake-Eigenschaft anlegen
if (!isset($this->errors['fakeProperty']) {
 
  $this->errors['fakeProperty'] = new Tx_Extbase_Validation_PropertyError('fakeProperty');
}
 
// Eigentliche Fehlermeldungen an den Container anhängen
$this->errors['fakeProperty']->addErrors(array(
  new Tx_Extbase_Validation_Error('Descriptive error message', 0000000000); // See above
));

Da dieser Validator allgemein für das Model gilt, wird er immer dann zur Rate gezogen, wenn eine neue Instanz des Models im Zuge einer Aktion angelegt werden soll. Wahlweise kann man dies allerdings auch manuell für die gewünschten Aktionen eines Controllers über die  @validate …Validator.php DocComment-Notation erfolgen. Allerdings sollte man dann darauf achten, dass der Validator nicht der oben beschriebenen Pfad-Konvention folgt. Andernfalls wird der Validator wie gehabt immer aufgerufen, @dontvalidate einmal ausgenommen. Auf diese Weise können der Zielaktion auch beliebige weitere Validatoren hinzugefügt werden, welche jeweils den gleichen Zugriff auf das Model haben.

Drag and Drop im Seitenbaum

Heute bin ich durch Zufall auf ein in der Dokumentation von TYPO3 nirgends erwähntes Feature gestoßen: Drag and Drop von Elementen des Seitenbaumes im Backend.

Ein schlichtes Anpacken und über dem Zielort ablegen lässt ein kleines Menü erscheinen, welches die Möglichkeit bietet, die verschobene Seite in bzw. nach dem Zielort abzulegen oder nach Wunsch stattdessen dorthin zu kopieren.

Einziges Manko: man sieht keinen wirklichen Indikator, wohin die Seite verschoben würde. Abgesehen davon aber äußerst nützlich, da man sich so den Umweg über das List-Module spart.

News LIST- und SINGLE-Ansicht auf einer Seite

In der Dokumentation zu tt_news wird ein Weg beschrieben, um die LIST- und SINGLE-Ansicht für News-Einträge in einer einzigen Plugininstanz nutzen zu können.

Unglücklicherweise ist dieses Vorgehen auf das althergebrachte Templating-System zugeschnitten und damit z. B. für TemplaVoilà nicht anwendbar.

Es gibt jedoch eine weitere Möglichkeit, die praktisch mit jedem Templating-System funktionieren sollte und nur wenige Zeilen TypoScript im Template der jeweiligen Seite erfordert:

plugin.tt_news {
 
  // Unset reference to Flexform field
  code >
  // Set default view, e. g. LIST
  code = LIST
}
 
[globalVar= GP:tx_ttnews|tt_news>0]
// Change code to SINGLE if there's a news record to display
plugin.tt_news.code = SINGLE
[global]

Damit dies jedoch funktioniert, darf in der Konfiguration für das News-Plugin nichts bei den Anzeigetypen (SINGLE, LIST, LATEST, …) ausgewählt werden. Andernfalls wird jegliche Einstellung im TypoScript ignoriert. Die Meldung, dass das Plugin hierdurch nicht konfiguriert ist, kann man getrost ignorieren.

Hinweis für die Version 3.0.0 der News-Erweiterung: das Formular für die Pluginkonfiguration wurde hier drastisch umgestaltet, wodurch es nunmehr unmöglich ist, keinen Wert für den Anzeigetyp festzulegen. Eine mögliche Lösung hierfür ist eine Modifikation des Flexforms der News-Erweiterung, was ich in diesem Zuge auch im Bugtracker von TYPO3 vorgeschlagen habe.

Das Resultat des ganzen Vorhabens sind kürzere Adressen durch die Einspaarung einer Seite.

Filemounts für normale Backendnutzer

Ziemlich häufig hat man als Administrator die Aufgabe, bestimmten Nutzern das Editieren von Inhalten im Backend von Typo3 zu erlauben. Diese Nutzer als Administratoren zu kennzeichnen ist die schnellste und einfachste, aber auch die riskanteste Möglichkeit. Denn dann haben diese natürlich freie Hand. Besser ist die Nutzung der Access Control Lists, was aber nicht Thema dieses Eintrags ist.

Vielmehr sollte ein kleiner aber feiner Fakt erwähnt werden, der mich heute schon wieder verdutzt dreinblicken hat lassen: man kann beliebig viele Filemounts für Backendnutzer und Backendnutzergruppen anlegen, aber vom Start weg funktioniert kein einziger davon. Im Rich Text Editor herrscht in Bezug auf Dateien beim Einfügen von Links oder Bildern gähnende Leere.

Die Lösung: das TEMP-Verzeichnis (standardmäßig fileadmin/_temp_) muss ebenfalls als Filemount zur Verfügung gestellt werden. Andernfalls sind alle anderen Filemounts unwirksam. Auf dieses Problem bin ich früher beits einmal gestoßen und konnte es nur nach langem Trial-und-Error lösen. Heute ist mir dies wieder passiert, jedoch konnte ich glücklicherweise bei einem alten Projekt nachschauen.

Antworten auf Kommentare

Es gibt eine Eigenschaft, die mir beim Commenting system im Vergleich zu meinem alten handgeschriebenen Gästebuch gefehlt hat: Antworten auf Kommentare. Hiermit meine ich, dass mir die Möglichkeit geboten wird, zu Kommentaren Anmerkungen oder dergleichen hinzuzufügen.

Aus diesem Grund habe ich mich entschlossen, eine Erweiterung hierfür zu erstellen. Mit Hilfe des Extension Kickstarters lassen sich recht komfortabel und schnell die Grundlagen schaffen. Für die Programmierung habe ich mich dann am Code der Erweiterung Comments: individual closing, dem Code des Commenting system selbst sowie natürlich an der Dokumentation letzterer Erweiterung orientiert. Mit ein wenig Trial und Error sowie Blicken in die API-Dokumentation Typo3s bin ich auch schnell voran gekommen.

Dadurch habe ich wieder einiges mehr über die Internas Typo3s wie z. B. das Templating-System erfahren. Der Weg ist also wie üblich das Ziel.

Und da diese Erweiterung im Gegensatz zu meinen ersten Gehversuchen einen in meinen Augen angemessenen Umfang hat, habe ich sie auch zum TER hochgeladen, von wo aus sie nun auch verfügbar ist.

Ich wünsche viel Vergnügen damit und nehme Verbesserungsvorschläge und Fehlerberichte natürlich gerne entgegen.

Weitreichender Umbau

Nach langer Zeit der Stille habe ich mich im Zuge meiner kürzlich erworbenen Fähigkeiten im Umgang mit dem CMS TYPO3 entschlossen, meine relativ verstummte Site wieder einmal auf den neuesten Stand zu bringen.

Im Zuge des Umbaus habe ich nun endlich umgesetzt, was sich früher in Form der Sektion „Artikel“ schon angedeutet hat: einen Blog. Darin werde ich von nun an mehr oder weniger große Gedanken festhalten und biete die Möglichkeit, diese zu kommentieren. Ansonsten habe ich die Sektionen deutlich abgespeckt und mich auf die vier beschränkt, die nun verblieben sind. Für alle anderen habe ich keinen Einsatzzweck mehr gesehen.

Die inneren Werte zählen

Unter der Haube hat sich praktisch alles geändert. Während früher handgeschriebener (und zugegeben stetig unübersichtlicher werdender) PHP-Code die Maschinerie am Laufen hielt, kommt nun das bereits erwähnte TYPO3 zum Einsatz. Damit kann ich nun relativ mühelos und in einer viel höheren Abstraktionsebene die Site verwalten und erweitern. Bei den unzähligen Erweiterungen, die für TYPO3 im Extension Repository zu finden sind, findet sich fast immer eine Lösung für die gewünschte Funktionalität.

Als Templating-System kommt TemplaVoilà zum Einsatz, was das Haupttemplate der Site recht übersichtlich hält, da hierdurch viel TypoScript eingespart oder ausgelagert werden kann. Für das Blogsystem kommt fürs erste News in Kombination mit dem Commenting System zum Einsatz. Der seit kurzer Zeit verfügbare T3Blog habe ich nicht wirklich zum Laufen bringen können; zudem missfällt mir hier, dass ich mir das gesamte Subsystem rund um DAM aufhalsen muss.

In den sauren Apfel habe ich nun mittlerweile beißen müssen, da ich nur mit DAM zufrieden stellend Metadaten speichern kann. Die Galerie läuft nun also DAM-basiert, die momentan genutzte DAM Liteshow ist jedoch noch nicht optimal und musste von mir – mangels Templating-Unterstützung im PHP-Code – noch stark angepasst werden.

Für menschenlesbare URIs sorgt CoolURI, was mit der XML-basierten Konfigurationsdatei recht angenehm zu handhaben ist. Damit und mit Hilfe von SQL lassen sich sehr gute Transformationen von URIs durchführen.

Kleider machen Leute

Da ein Umbau nur unter der Haube doch relativ langweilig ist, habe ich mich auch daran gemacht, ein neues Thema zu entwerfen. Dieses Mal habe ich noch mehr Wert auf Leichtgewichtigkeit gelegt, womit der Umfang der zu 羽, dem neuen Standardthema, gehörenden Stylesheet-Dateien deutlich geringer ausgefallen ist. Auch habe ich versucht, endlich einmal die Styles modular aufzubauen und entsprechend auszulagern. Das grundsätzliche Farbschema ist relativ gleich geblieben und wurde entsprechend adaptiert oder modifiziert. Zur optischen Verstärkung informativer Hinweise nutze ich das durch den Modern Skin lieb gewonnene Silk-Iconthema.

Auch das Favicon habe ich geändert. Während hier früher das „o“ des alten stylisierten Logo-Schriftzuges zu sehen war, findet sich hier nun ein schlichtes の. Hierbei handelt es sich – wie könnte es anders sein – um ein japanisches Schriftzeichen; konkret um ein Bindewort. Einfaches Beispiel hierzu: „Marks Brille“  heißt auf japanisch 「マークのめがね」. Warum gerade dieses Zeichen? Nun, es symbolisiert die ersten beiden Buchstaben des Seitentitels und ist zufällig das allererste japanische Zeichen, was ich lesen und schreiben konnte.

Ich hoffe durch die Summe dieser Änderungen meine Site viel einfacher verwalten zu können und nehme mir vor, öfter mal ein oder zwei Worte fallen zu lassen. Ich freue mich natürlich wie immer über Kommentare aller Art (gerne fleischarm).