Questions & Answers

SOLVED
udo_woitek
I'm new here

Generierungsparameter aus Dateinamen ermitteln?

Jump to solution

Hallo,

in einem der Generierung nachgelagerten Modul mรถchte ich aus den generierten Dateinamen (zu findem im Staging-Verzeichnis) eventuell mit Hilfe des im Context gespeicherten UrlCreators die Generierungsparameter (Sprache und Vorlage) ermitteln. Fรผr "normale" Seiten und Medien ist das noch durch ein Iterieren รผber die Projekt-Sprachen und -Vorlagen mรถglich, mit denen ich dann den UrlCreator fรผr ein ContentProducer- oder Media-Objekt den Dateinamen nochmals erstellen lasse.

Vielleicht gibt es dafรผr schon einen einfacheren Weg (weiterhin unabhรคngig vom Typ des UrlCreator, also ohne gespeicherte URLs)?

Bei Inhaltsprojektionen scheitert dieser Weg jedoch, da ich Dateinamen mit angehรคngten Nummern vorliegen habe. Im Prinzip wรผrde ich nun die Dateinamensermittlung wie oben fรผr beliebig viele contentId-Werte vornehmen und den vorliegenden mit dem erneut generierten Dateinamen vergleichen. Das ist keine sinnvolle Option, daher meine zweite Frage: Kann ich aus einem durch Inhaltsprojektion erstellten Dateinamen auf die Generierungssprache und das Generierungstemplate schlieรŸen? Und vor allem wie?

Danke und schรถne GrรผรŸe,

Udo Woitek.

1 Solution

Accepted Solutions

Hallo Udo,

vorweg: beschrieben mag sich das Ganze recht aufwรคndig anhรถren, ist aber in 30 Minuten gebaut.

1. Fรผge im Ausgabekanal des Projekteinstellungs-Templates folgendes hinzu:

$CMS_IF(!#global.preview && #global.scheduleContext.getProperty("gv_urlMap")==null)$  

    $CMS_SET(void,#global.scheduleContext.setProperty("gv_urlMap",{:}))$

$CMS_END_IF$

Hintergrund: Der Ausgabekanal der Projekteinstellungen wird zwar nicht "ausgegeben", aber zu Beginn jeder Generierung ausgewertet - und zwar pro Sprache und Ausgabekanal. Dieser Code legt eine leere Map in die Property "gv_urlMap" des Generierungskontextes. Diese Properties "leben" im Auftrag. Vor allem รผber mehrere Tasks im Auftrag. Nach Ausfรผhrung des Auftrages werden sie entsorgt.

2. Rendertemplate

Erstelle ein Rendertemplate (=Formatvorlage, z.B. "save_url_map") mit folgendem Inhalt:

$CMS_IF(!#global.preview && #global.scheduleContext.getProperty("gv_urlMap")!=null)$

    $CMS_SET(set_infoMap,{

        "nodeUid":#global.node.uid,

        "lang":#global.language.abbreviation,

        "templateSet":#global.templateSet.uid,

        "datasetTable":#global.dataset.entity.entityType.name,

        "datasetId":#global.dataset.entity.id

    })$

    $CMS_SET(set_url)$$CMS_REF(#global.ref, abs:2)$$CMS_END_SET$

    $CMS_SET(void,#global.scheduleContext

        .getProperty("gv_urlMap")

        .put(set_url.toString,set_infoMap)

    )$

$CMS_END_IF$

Die infoMap kannst Du nach Deinen Bedรผrfnissen anpassen, im Beispiel landen darin die UID der Seitenreferenz, die Sprache usw. Es muss nicht unbedingt eine Map sein. Du kannst auch das gv_urlMap bei Bedarf als Liste statt Map nutzen - je nachdem was am praktikabelsten ist. Da ich es aber so verstanden habe, dass Du zu den einzelnen Dateien diese Infos brauchst, macht eine Map mit den absoluten URLs als Keys hier wahrscheinlich am meisten Sinn.

Dieses Rendertemplate bindest Du in alle Seitenvorlagen ein (die Stelle ist relativ egal):

$CMS_RENDER(template:"save_url_map")$

Bis hierher hast Du also nach der Generierung eine Map mit den absoluten Pfaden als Key und einigen Infos als "Sub-Map". Diese Map "lebt" als Property im ScheduleContext.

Die Frage ist: Wie kommt man da jetzt sinnvoll ran? ๐Ÿ˜‰

Man kรถnnte hier jetzt einen Script-Task bauen, der das irgendwohin schreibt, am einfachsten ist das aber รผber ein spezielles Seitentemplate:

3. Seitentemplate zum Erzeugen der Map

Erstelle ein neues Seitentemplate, z.B. "url_map" mit der Dateiendung ".json" und folgender Ausgabe:

$CMS_IF(!#global.preview && #global.scheduleContext.getProperty("gv_urlMap")!=null)$

    $CMS_VALUE(#global.scheduleContext.getProperty("gv_urlMap").toJSON())$  

$CMS_END_IF$

Erstelle dazu - am besten jeweils "auรŸerhalb" der Website-Ordner - eine Inhaltsseite basierend auf diesem Template und eine Seitenreferenz und gib beides frei.

4. Map im Auftrag erzeugen

Fรผge dem Generierungsauftrag einen weiteren Generierungstask NACH allen anderen hinzu:

Typ: Teilgenerierung, einziger Startknoten ist die in (4.) angelegt Seitenreferenz.

Wichtig: Nur in EINER Sprache (egal welche) und nur fรผr EINEN (egal welcher) Ausgabekanal erzeugen. Zum Generierungszeitpunkt liegen ja schon alle Infos in der Map.

5. Generieren

Nach dem Generieren (im Auftrag) hast Du dann eine weitere Datei im JSON-Format, die diese Map mit den ganzen Infos enthรคlt. Wenn Du nicht willst, dass sie deployt wird, kannst Du den entsprechenden Generierungstask einfach hinter den Deployment-Task packen.

Viele GrรผรŸe

Michael

View solution in original post

8 Replies
mbergmann
Crownpeak employee

Hallo Udo,

ich wรผrde hier grundsรคtzlich einen anderen Ansatz versuchen: Wรคhrend der Generierung kann jede Seite ihre eigene URL (=Dateiname) in eine "passende" Datenstruktur - wohl eine (ggf. verschachtelte) Map - legen. Diese Map "lebt" im ScheduleContext (als Property). Nach der Generierung kann man dann im selben Auftrag mit einem weiteren Task diese Map auswerten / ausgeben / whatever.

Dein Ansatz funktioniert wahrscheinlich nicht im Fall von URL-Konflikten und hรถrt sich auรŸerdem irgendwie kompliziert an...

Viele GrรผรŸe

Michael

Hallo Michael,

vielen Dank fรผr deine Antwort. Ich gebe dir Recht, dass mein gewรคhlter, hier geschilderter Weg ziemlich umstรคndlich ist. Es war aber aus meinem Verstรคndnis heraus die praktikabelste Lรถsung um *nach* der Generierung herauszufinden, mit welcher Kombination von Eigenschaften (Sprache, Ausgabetemplate) eine im Generierungsverzeichnis vorgefundene Datei erstellt worden ist.

Die von dir angesprochene Mรถglichkeit hat unter anderem den Vorteil, dass ich die Dateinamensgenerierung per UrlCreator nur einmal durchfรผhren mรผsste. Allerdings ist mir nicht ganz klar, wie "jede Seite" ihre eigene URL zum einen wรคhrend der Generierung unabhรคngig vom verwendeten UrlCreator herausfinden und speichern kann und wie das insbesondere bei Projektionen und Dokumentengruppen funktioniert.

Vielleicht kannst du mir mit ein paar gezielten Hinweisen hier auf die Sprรผnge helfen. Das wรคre groรŸartig!

Viel GrรผรŸe,

Udo.

0 Kudos

Hallo Udo,

vorweg: beschrieben mag sich das Ganze recht aufwรคndig anhรถren, ist aber in 30 Minuten gebaut.

1. Fรผge im Ausgabekanal des Projekteinstellungs-Templates folgendes hinzu:

$CMS_IF(!#global.preview && #global.scheduleContext.getProperty("gv_urlMap")==null)$  

    $CMS_SET(void,#global.scheduleContext.setProperty("gv_urlMap",{:}))$

$CMS_END_IF$

Hintergrund: Der Ausgabekanal der Projekteinstellungen wird zwar nicht "ausgegeben", aber zu Beginn jeder Generierung ausgewertet - und zwar pro Sprache und Ausgabekanal. Dieser Code legt eine leere Map in die Property "gv_urlMap" des Generierungskontextes. Diese Properties "leben" im Auftrag. Vor allem รผber mehrere Tasks im Auftrag. Nach Ausfรผhrung des Auftrages werden sie entsorgt.

2. Rendertemplate

Erstelle ein Rendertemplate (=Formatvorlage, z.B. "save_url_map") mit folgendem Inhalt:

$CMS_IF(!#global.preview && #global.scheduleContext.getProperty("gv_urlMap")!=null)$

    $CMS_SET(set_infoMap,{

        "nodeUid":#global.node.uid,

        "lang":#global.language.abbreviation,

        "templateSet":#global.templateSet.uid,

        "datasetTable":#global.dataset.entity.entityType.name,

        "datasetId":#global.dataset.entity.id

    })$

    $CMS_SET(set_url)$$CMS_REF(#global.ref, abs:2)$$CMS_END_SET$

    $CMS_SET(void,#global.scheduleContext

        .getProperty("gv_urlMap")

        .put(set_url.toString,set_infoMap)

    )$

$CMS_END_IF$

Die infoMap kannst Du nach Deinen Bedรผrfnissen anpassen, im Beispiel landen darin die UID der Seitenreferenz, die Sprache usw. Es muss nicht unbedingt eine Map sein. Du kannst auch das gv_urlMap bei Bedarf als Liste statt Map nutzen - je nachdem was am praktikabelsten ist. Da ich es aber so verstanden habe, dass Du zu den einzelnen Dateien diese Infos brauchst, macht eine Map mit den absoluten URLs als Keys hier wahrscheinlich am meisten Sinn.

Dieses Rendertemplate bindest Du in alle Seitenvorlagen ein (die Stelle ist relativ egal):

$CMS_RENDER(template:"save_url_map")$

Bis hierher hast Du also nach der Generierung eine Map mit den absoluten Pfaden als Key und einigen Infos als "Sub-Map". Diese Map "lebt" als Property im ScheduleContext.

Die Frage ist: Wie kommt man da jetzt sinnvoll ran? ๐Ÿ˜‰

Man kรถnnte hier jetzt einen Script-Task bauen, der das irgendwohin schreibt, am einfachsten ist das aber รผber ein spezielles Seitentemplate:

3. Seitentemplate zum Erzeugen der Map

Erstelle ein neues Seitentemplate, z.B. "url_map" mit der Dateiendung ".json" und folgender Ausgabe:

$CMS_IF(!#global.preview && #global.scheduleContext.getProperty("gv_urlMap")!=null)$

    $CMS_VALUE(#global.scheduleContext.getProperty("gv_urlMap").toJSON())$  

$CMS_END_IF$

Erstelle dazu - am besten jeweils "auรŸerhalb" der Website-Ordner - eine Inhaltsseite basierend auf diesem Template und eine Seitenreferenz und gib beides frei.

4. Map im Auftrag erzeugen

Fรผge dem Generierungsauftrag einen weiteren Generierungstask NACH allen anderen hinzu:

Typ: Teilgenerierung, einziger Startknoten ist die in (4.) angelegt Seitenreferenz.

Wichtig: Nur in EINER Sprache (egal welche) und nur fรผr EINEN (egal welcher) Ausgabekanal erzeugen. Zum Generierungszeitpunkt liegen ja schon alle Infos in der Map.

5. Generieren

Nach dem Generieren (im Auftrag) hast Du dann eine weitere Datei im JSON-Format, die diese Map mit den ganzen Infos enthรคlt. Wenn Du nicht willst, dass sie deployt wird, kannst Du den entsprechenden Generierungstask einfach hinter den Deployment-Task packen.

Viele GrรผรŸe

Michael

GroรŸartig! Vielen Dank.

Ich werde die Ideen so schnell wie mรถglich mit meinem Projekt verkรผpfen und melde mich dann wieder!

Danke nochmals und herzliche GrรผรŸe,

Udo Woitek.

0 Kudos

Hallo Michael,

ich habe deine Vorschlรคge jetzt mal eingebaut und bin begeistert. Diese Vorgehensweise erspart mir eine Menge Aufwand. Ich hoffe nur, dass der Speicherbedarf nicht exorbitant anwรคchst, so dass ich diese Methode auch bei grรถรŸeren FirstSpirit-Projekten anwenden kann. Zur Not werde ich wohl ein paar von den Angaben in der Map reduzieren mรผssen.

Ich bedanke mich vielmals fรผr die tatkrรคftige Untersรผtzung.

Schรถne GrรผรŸe,

Udo Woitek.

0 Kudos

Hallo Udo,

klar, dadurch dass die Map im Speicher gehalten wird ist das natรผrlich theoretisch mรถglich. Wรผrde ich jetzt aber aus dem Bauch heraus erstmal einfach probieren - man kann sich den Speicherbedarf ja auch grob ausrechnen. Wieviele Dateien generiert ihr denn so pro Lauf? Falls es damit tatsรคchlich Probleme gibt, kann man das Ganze auch etwas anders lรถsen, indem man sich eine eigene Klasse hierfรผr baut und die aus dem Template-Kanal heraus anspricht. Das wรคre aber dann wieder aufwรคndiger.

Wenn man mal so 200 Bytes pro Eintrag rechnet kรคme man bei 10.000 Seiten auf schlappe 2MB.

Viele GrรผรŸe

Michael

0 Kudos

Hallo Michael,

da wir fรผr externe FirstSpirit-Anwender entwickeln, ist der gesamte Datenbestand nicht sicher. Es kรถnnten aber schon groรŸe Webauftritte werden. Aber du hast Recht, es lรคsst sich ganz gut ausrechnen, was an Datenaufkommen zu erwarten ist. Ich werde mit dieser Lรถsung erstmal weiter arbeiten und mir die kompliziertere vorbehalten. Nochmals vielen Dank!

Viele GrรผรŸe,

Udo.

0 Kudos

Hallo Michael,

die Lรถsung funktioniert sehr gut. Gibt es denn ein รคhnliches Vorgehen fรผr Mediendateien, welche ja sprachunabhรคngig oder in verschiedenen Generierungssprachen vorliegen kรถnnen und nicht รผber Vorlagen fรผr die Ausgabe verfรผgen?

Danke und viele GrรผรŸe,

Udo.

0 Kudos

Type a product name