Magnolia CMS: Advanced Templating

Über das offensichtliche Templating hinaus geht zum Beispiel das Beerben von Dialogen oder das Verschachteln von Komponenten:

Vererbung von Dialogen

Vererbung ist recht simpel, wenn man ein paar Dinge weiß (wie immer bei Magnolia). So beerbt man zum Beispiel keine Komponenten. Komponenten haben immer einen “dialog”, einen “renderType”, ein “templateScript” und einen “title”, aber kein “extends” – anders als Pages! Man kann allerdings Dialoge beerben, und einer Komponente einen solchen Dialog zuweisen. Im Template-Script dieser Komponente kann man dann auf die Werte “beider” Dialoge zugreifen.

Desweiteren muss man wissen, und das ist der eigentliche Clou, dass das “extends”-Property eines Dialoges relativ verlinkt – also anders als bei der Verlinkung von bsplw. Pages mit ihren Komponenten. Das sieht korrekterweise dann so aus:

Im Beispiel oben übernimmt “largeTeaser” die “actions” und alles aus “form” von “teaser”.

 

Verschachteln von Komponenten

Was ich gerne haben möchte, ist Folgendes: Eine “smallTeaser”-Komponente, die aus genau zwei kleinen Teasern besteht. Nicht mehr (sollte das nötig sein, könnte man der Seite eine weitere “smallTeaser”-Komponente hinzufügen), aber auch nicht weniger (denn dann entsteht ein “Loch” im Layout, es müssen immer genau zwei kleine Teaser nebeneinander sitzen).

Vorweg: Das geht nicht.

Was man nur machen kann, ist folgendes: Eine “smallTeasers”-Komponente definieren, die in Form einer Liste maximal zwei kleine Teaser enthält. Das funktioniert analog zu Areas mittels “availableComponents”:

Die erwähnten “Löcher” im Layout bleiben damit explizit möglich; man kann auch nur einen kleinen Teaser einsetzen. Außerdem denke man an komplexere Komponenten, die aus einem Teaser, einem einleitenden Text+Headline, einem wasweißich bestehen. Es ist (offenbar) nicht möglich, das mittels verschachtelten Komponenten abzubilden. Man hätte immer eine Liste von bis zu (nicht genau) drei Elementen, die eine beliebige Kombination der genannten wären. Auch drei mal Teaser ohne Einleitung wären möglich. So nützen einem verschachtelte Komponenten nichts 🙁

Achso, das obligatorische “muss man wissen”: Unter den “availableComponents” darf nicht mehr als eine Komponente mit derselben ID liegen! Dann stürzt alles mit der äußerst hilfreichen Fehlermeldung “An error occurred while executing action [addComponent]” ab 🙂 Das muss man immer mittels Listen lösen.

HTH

Magnolia CMS: Templating

Voraussetzung: Entsprechende Templates in der Struktur Seite (“Page”) -> Bereich (bsplw. für Teaser, “Area”) -> Komponenten (die Teaser in diesem Beispiel, “Components”) -> Eingabemaske (für die Daten des Teasers, “Dialog”). Details zum Aufsetzen und Verknüpfen dieser Templates im letzten Post. Jedem Template außer dem Dialog wird mit dem Attribut “TemplateScript” ein Skript im Dateisystem zugeordnet (Dateiendung .ftl).

Nun sollen diese Skripte gefüllt werden. Wieder glänzt die “Dokumentation” nicht mit Details. Im Gegenteil: Ganze Bereiche werden verschwiegen, wichtige Details sind irreführend bis falsch, der Rest ist fragmentiert. Aber der Reihe nach. Im Folgenden benutze ich übrigens Freemarker, nicht JSP.

Das Page-Skript enthält eine komplette HTML-Seite. Ich hätte das gerne anders gemacht, zum Beispiel würde ich den <head> gerne auslagern, aber das ist eine extra Baustelle, die auch nicht offensichtlich dokumentiert ist. Deshalb: In diesem Beispiel ist die Page eine HTML-Seite, mit <body>, <head> und allem drum und dran. In das Skript muss im <head> ein Tag eingefügt werden, um das “Edit”-Panel zu aktivieren:

Im Body markiere ich den Teaser-Bereich mit

wobei “teasers” der Name des zugehörigen Content Knotens der Areas ist, siehe hier. Die Seite kann nun editiert werden; als editierbare Elemente wird der Teaser-Bereich angeboten. Dorthinein können die im Bereich erlaubten Komponenten (“availableComponents”) gesetzt werden. Per default, d.h. ohne jedes Skript, zeigt eine Area diese Komponenten dann an. Will man manuell eingreifen, etwa für umschliessendes HTML, dann kann man das Area-Skript wie folgt nachbauen:

Die Komponenten schließlich sind stark mit ihrem “Dialog” (ihrer Eingabemaske) verknüpft, und hier beginnt die Magie. Es gibt tatsächlich kein funktionierendes Beispiel, wie man bsplw. ein Bild aus der Asset-Verwaltung im Dialog auswählen, und im Skript verlinken kann. Der Didaktik wegen erst der Dialog (Klick für große Ansicht):

Im Detail:

  • Der Dialog wird in Magnolia 5 nicht mehr direkt in Tabs unterteilt, wie die Doku hier nahelegt. Stattdessen werden “actions” (Speichern, Abbrechen, etc.) und die eigentliche Eingabemaske (“form”) unterschieden (Quelle). Das hatte ich hier schon bemängelt 🙂
  • Die “actions” sind ziemlich Copy&Paste
  • Das Formular wird dann in Tabs unterteilt, es muss immer mindestens einen Tab geben.
  • “headline”, “copy” und “button” (im Sinne von Buttontext) sind bei mir vom Typ TextFieldDefinition. Gut zu wissen: “rows” beschränkt die Zeilenanzahl nicht, es erweitert nur das Eingabefeld in der Maske. Es sind trotzdem mehr als “rows” Zeilen möglich!
  • “bgImage” schließlich ist vom Typ LinkFieldDefinition:
    • “contentPreviewDefinition” sorgt für die Vorschau des ausgewählten Bildes; dazu wird die “contentPreviewClass” auf info.magnolia.dam.asset.field.DamFilePreviewComponent gesetzt.
    • “appName” ist analog zur Doku “assets”, “class” ist ebenfalls analog zur Doku, “label” ist Freitext
    • “targetWorkspace” hat sich in Magnolia 5 ebenfalls geändert; statt “dms” muss es “dam” sein! Andererseits hatte es bei mir auch keine Auswirkungen, wenn ich das einfach weglasse^^
    • “identifierToPathConverter” hatte bei mir keine sinnvollen Auswirkungen, so wurde zum Beispiel nie der Pfad zur Datei ausgegeben, vgl. unten

So, nun hat man Texte und ein Bild im Dialog der Komponente – wie spricht man diese im Skript der Komponente an? Die Texte sind einfach:

Das Bild dagegen würde mit

nur den Pfad des Objekts in der Asset-Verwaltung ausgeben, etwa /myTeasers/teaser_1. Das wäre nicht mal eine URL zu der Grafik dahinter, wenn hier ein “.jpg” dranhinge. Stattdessen muss man den “Content” zu diesem Pfad erst auslesen, und dann in einen “Link” konvertieren:

Hier ist interessant, dass “cmsfn” vom Typ TemplatingFunctions im Template-Skript zur Verfügung steht. Muss man wissen 🙂 Was jetzt vielleicht noch so verfügbar ist, weiß ich nicht, aber für Hinweise bin ich dankbar!

HTH

Magnolia CMS: Templates mit custom Komponenten und Dialogen

Magnolia ist ein CMS, und vor nicht allzu langer Zeit in Version 5 erschienen. Wesentliche Neuerung: Das Backend ist jetzt touch-optimiert. Denn, seien wir ehrlich: Wer pflegt seine Inhalte nicht über das iPhone… das war Sarkasmus.

Wie auch immer, mit dem Umbau des Backends hat sich offenbar auch einiges an der Erstellung und Verknüpfung von Templates und deren Bestandteile geändert – was zum Teil auch (noch) nicht korrekt in der “Doku” erklärt wird. Die Anführungszeichen um “Doku” deshalb, weil es sich um ein Freitext-Wiki handelt, was das Nachschlagen mühsam macht. Hier deshalb die gebündelte Kurzform:

Anlegen von Seiten-Templates funktioniert tatsächlich nach Doku:

Verwendete Komponenten werden in der Seite im Knoten “areas” der Page referenziert, allerdings nicht (genau) wie in der Doku angegeben mittels “<module name>:<relative path to component>“: “module name” ist, wie auf dem ersten Screenshot von oben zu vermuten, tatsächlich “templating”, allerdings muss man in dem “relative path to component” das “templates” weglassen! Der relative Pfad lautet also nur “components/largeTeaser“:

Die Komponente selbst ist korrekt in der Doku beschrieben. Hier die Attribute; das templateScript liegt parallel zum Script der Page, siehe oben:

Den zugehörigen Dialog zu verlinken (Attribut “dialog“), weicht dann am stärksten von der Doku ab. Obwohl es in der Doku zu Magnolia 5 “Templating in Magnolia 5.0 works the same way as it did in 4.5” heißt (Stand: Anfang Juli 2013), muss man den Dialog in “actions” und “form” aufteilen, wie hier im Wiki beschrieben. Die Beschreibung in der (4.5er?) Doku funktioniert nicht mehr. Ein weiteres Manko der “Doku” von Magnolia: Es ist nicht offensichtlich, wann man Wiki und wann Doku verwendet 🙁

Außerdem muss man die Dialoge direkt im Modul ablegen, nicht unter “templates”. Verknüpfung dann über “templating:largeTeaser“, hier lässt man also auch das “dialogs” im Pfad weg:

Rein statische Klassen in Velocity

Eine solche Java-Klasse:

möchte man vielleicht auch in Velocity verfügbar haben. Nun funktioniert

schon mal nicht – $MyValues ist kein konkretes Objekt (und ohne eine Art Import wäre die Klasse eh nicht verfügbar). Eine Instanz möchte man aber auch nicht erzeugen:

, denn damit wäre MyValues.myString immer “Hello, you world!” (da neu initialisiert), und wer weiß, vielleicht wurde das ja mal überschrieben? Im Java-Code würde man hier ja auch nicht auf Instanzen arbeiten, sondern auf der Klasse.

Und tatsächlich kann man Velocity auch nur die Klasse übergeben, und zwar genau so, wie man es erwartet:

Im Grunde ist das nicht mal überraschend, aber ich finde das grad gut 🙂 In Velocity sieht das dann so aus:

, und das gibt immer den aktuellen Wert aus! Mit statischen Methoden funktioniert das übrigens auch – und: Ja, man könnte auch einen Singleton verwenden. Ich find’ das trotzdem gut.