eZ Publish 5 Templating – Teil 3: Ein eigenes Layout

Avatar von Andreas Haberberger

Nachdem Teil eins und zwei dieses Tutorials die Grundlagen gelegt haben, soll es in diesem Teil darum gehen, die speziellen Eigenheiten von eZ Publish, namentlich die ehemals in der ezflow-Extension, neuerdings im Page-FieldType untergebrachten Mittel zur Organisation und Strukturierung einer Seite zu nutzen.

ezflow-to-Page (stage_4)

Die Organisation des Contents auf einer Seite ist im Legacy-Stack von eZ Publish in der Regel über die Extension „ezflow“ realisiert. In der Symfony2-Welt wurden deren Strukturen in den „Page“ FieldType übernommen. Im Wesentlichen handelt es sich dabei um die Gruppierung von ContentObjekten einer Seite in „Zones“, die die Grobgliederung der Seite erlaubt. „Zones“ enthalten ihrerseits „Blocks“, in denen wiederum einzelne ContentObjekte untergebracht werden. In einem „Block“ werden also zum Beispiel Listen aktueller Beiträge oder Ähnliches realisiert.

Der neue „Page“ FieldType ist – aktuell – allerdings nur in der Lage, eine ezflow-konforme Seitenstruktur zu lesen und für Symfony2-Twig-Templates verfügbar zu machen. Möchten wir nun ein eigenes „Page“-basiertes Seitenlayout entwickeln, müssen wir – beim aktuellen Entwicklungsstand – erst einmal ein herkömmliches ezflow-Layout definieren.

Zuerst erstellen wir eine Legacy-Extension um das Layout für den Content-Editor, der sich ja nach wie vor im Lagacy-Stack aufhält, „greifbar“ zu machen. Im Grunde genügt hier ein einfacher Rahmen aus Konfigurationsdateien und einem Preview-Icon, der das neue Layout im Content-Editor sichtbar macht. Das Ausgestalten dieses Layouts mit Legacy – „.tpl“ Templates können wir uns sparen, da sich unsere Templates ja nur in der Symfony2-Schicht befinden. Die gesamte Extension findet sich hier zum Download.

Die Definition des Layouts erfolgt in einer eZ Publish-Lagacy-typischen „zone.ini.append.php“. Wir definieren hier das „MFZoneLayout“ mit drei Zones („top“, „middle“ und „bottom“), geben ihm ein Previewbild zur Darstellung im Content-Editor mit und bestimmen, dass dieses Layout für die Content Klasse mit dem Identifier „landing_page“ gültig ist.

<?php /* #?ini charset="utf-8"?

[General]
AllowedTypes[]=MFZoneLayout

[MFZoneLayout]
ZoneTypeName=Mayflower Zone Layout
Zones[]=top
Zones[]=middle
Zones[]=bottom
ZoneName[top]=Top
ZoneName[middle]=Middle
ZoneName[bottom]=Bottom
ZoneThumbnail=mf_layout.gif
AvailableForClasses[]=landing_page
*/
?>

Die dazugehörigen Blöcke, wir beschränken uns auf einen Standardtyp namens „MFBlock“, werden  in der „block.ini.append.php“ definiert:

<?php /* #?ini charset="utf-8"?

[General]
AllowedTypes[]=MFBlock

[MFBlock]
Name=MF Block
ManualAddingOfItems=enabled
*/
?>

Die Einträge in der „site.ini.append.php“ sowie der „design.ini.append.php“ dienen nur dazu, die Extension zu aktivieren und als DesignExtension zu definieren und sind an dieser Stelle nicht weiter bemerkenswert.

Und im Frontend…

Über diese einfache Definition haben wir das Layout bereits im (Legacy-) Content-Editor verfügbar gemacht, können es für die „Landing Page“ – Seiten auswählen und Blöcke vom definierten Typ „MFBlock“ hinzufügen. Nun wollen wir aber auch unser Seitenlayout ausgeben und definieren, welche Templates zur Darstellung unserer Inhalte verwendet werden sollen.

Die Zuordnung des definierten Layouts zu einem Template in der Symfony2-Schicht erfolgt wie bereits gewohnt in unserer überschriebenen „ezpublish.yml“ in der Sektion „ezpage“:

system:
    ezdemo_site_user:
        ezpage:
            layouts:
                MFZoneLayout:
                    name: "Mayflower Zone Layout"
                    template: MayflowerTemplateTutorialBundle:page/zonelayout:mfzonelayout.html.twig
            enabledLayouts: [MFZoneLayout]
            blocks:
                MFBlock:
                    name: "Mayflower Block"
            enabledBlocks: [MFBlock]
...

In dem angegebenen Template „mfzonelayout.html.twig“ nutzen wir recht intensiv eZ Publish-eigene Strukturen:

{% if zones[0].blocks %}
<div id="top">
    {% for block in zones[0].blocks %}
        {{ render( controller( "ez_page:viewBlock", {'block': block} ) ) }}
    {% endfor %}
    <hr />
</div>
{% endif %}
{% if zones[1].blocks %}
<div id="middle">
    {% for block in zones[1].blocks %}
        {{ render( controller( "ez_page:viewBlock", {'block': block} ) ) }}
    {% endfor %}
    <hr />
</div>
{% endif %}
{% if zones[2].blocks %}
<div id="bottom">
    {% for block in zones[2].blocks %}
        {{ render( controller( "ez_page:viewBlock", {'block': block} ) ) }}
    {% endfor %}
    <hr />
</div>
{% endif %}

Zum einen erhält unser Template automatisch ein Array der darin verfügbaren „Zones“, über das wir entweder iterieren oder auf das wir – wie in unserem Beispiel – selektiv zugreifen können. Über ein etwas differenzierteres HTML-Gerüst lassen sich so beliebige Bereiche in unserem Rahmentemplate definieren. In jeder „Zone“ durchlaufen wir die darin verfügbaren „Blocks“ und übergeben sie fürs erste der Standardverarbeitung durch eZ Publish. Zuständig ist an dieser Stelle ein Kollege unseres bekannten ViewControllers, der PageController, dessen Methode „viewBlock()“ hier über sein alias „ez_page“ aufgerufen wird.

Verwenden wollen wir unser Page-Template anstelle der dynamischen Artikelliste aus den ersten zwei Teilen dieses Tutorials auf den Landingpages. Dazu ändern wir „landing.html.twig“ entsprechend ab:

{% extends "MayflowerTemplateTutorialBundle::pagelayout.html.twig" %}
{% block content %}
    {{ ez_render_field( content, 'page' ) }}
{% endblock %}

Der „ez_render_field“ Template Helper ist uns ja bereits aus Teil 1 bekannt, als wir die Inhalte unserer Einzelartikel ausgegeben haben. Die Verbindung zwischen dem „ezpage“-Datentypen und unserem „mfzonelayout“-Template haben wir bereits oben durch den Eintrag in „ezpublish.yml“ vorgenommen.

Ähnlich wie beim „ViewController“ lassen sich auch hier die für die einzelnen Blöcke verwendeten Templates in der ezpublish.yml festlegen. Da wir zwecks der Vereinfachung nur einen Blocktyp („MFBlock“) definiert haben, genügt hier natürlich auch nur eine Zuweisung:

system:
    ezdemo_site_user:
...
        block_view:
            rulez:
                template: MayflowerTemplateTutorialBundle:block:mfblock.html.twig
                match:
                    Type: MFBlock
...

Über den bereits bekannten Matcher erklären wir das Template „mfblock.html.twig“ für zuständig für unseren „MFBlock“.

In dem Template beziehen wir zuerst die gültigen „Items“ unseres „Blocks“, also die ContentObjekte, die wir im ContentEditor darin abgelegt haben. In jedem Fall lohnt sich ein Blick in den Code des PageService, da dieser noch eine Reihe von hilfreichen Methoden zur Ausgestaltung der „ezpage-Blocks“ bereit hält. Der Rest des Templates ist nicht neu, der Controlleraufruf über „render()“ ist der gleiche, den wir bereits in unserer Artikelliste benutzt haben. Da wir hier nur eine Liste der eingetragenen ContentObjekte ausgeben wollen, greifen wir auf den in Teil 2 definierten viewType „listitem“ zurück, dessen Template uns wieder die passende Listenzeile liefert.

{% set validItems = pageService.getValidBlockItems( block ) %}
<div class="block-mfblock">
    <ul class="items">
        {% for item in validItems %}
            {{ render(
                controller(
                    'ez_content:viewLocation',
                    {
                        'locationId': item.locationId,
                        'viewType': 'listitem'
                    }
                )
            ) }}
        {% endfor %}
    </ul>
</div>

Damit hätten wir einmal die Runde um das grundlegende Templating in eZ Publish 5 mittels Twig gemacht. Nach wie vor bleibt es spannend, die Verwandlung des CMS von der Legacy-Anwendung hin zur vollen Symfony2-Applikation zu beobachten, aber das bereits jetzt verfügbare hochflexible Templating in Verbindung mit der „erwachsenen“ Template-Engine Twig lässt ebenso wie das mächtige REST-API eZ Publish in der Oberliga mitspielen.

In diesem Sinne: Happy Templating!

Avatar von Andreas Haberberger

Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert


Für das Handling unseres Newsletters nutzen wir den Dienst HubSpot. Mehr Informationen, insbesondere auch zu Deinem Widerrufsrecht, kannst Du jederzeit unserer Datenschutzerklärung entnehmen.