~/CodeBlog.at

Ein halbkreativer Entwickler über alles zwischen C# und TYPO3.

Migration von Gridelements zu Container

Hinweis: Gemacht hab ich das Ganze bei einem Upgrade von TYPO3 10.4.21 auf die aktuellste TYPO3 11.5 LTS Version. Gridelements war Version 9.5.0 und die aktuelle Version der Container Extension ist 1.4.2.

Bei meinem Projekt waren die Grids als Datensätze in der Datenbank angelegt. Die Config dazu sieht so aus:

mod.web_layout.BackendLayouts {
  exampleKey {
    title = Zweispaltig (Teaser-Texte lang)
    icon = EXT:example_extension/Resources/Public/Images/BackendLayouts/default.gif
    config {
      backend_layout {
        colCount = 2
        rowCount = 1
        rows {
          1 {
            columns {
              1 {
                name = Links
                colPos = 10
                allowed {
                  CType = header,text,textpic,image,textmedia,bullets,form_formframework
                }
              }
              2 {
                name = Rechts
                colPos = 20
                allowed {
                  CType = header,text,textpic,image,textmedia,bullets,form_formframework
                }
              }
            }
          }
        }
      }
    }
  }
}

Für die Container Configuration brauche ich nur den Titel, die Beschreibung und die Configuration.

Die Config für den Container sieht dann so aus:

$containerRegistry->configureContainer(
    (
    new \B13\Container\Tca\ContainerConfiguration(
        'container-5',
        'Zweispaltig (Teaser-Texte lang)',
        '',
        [
            [
                [
                    'name' => 'Links',
                    'colPos' => 10,
                    'allowed' => [
                        'CType' => 'header,text,textpic,image,textmedia,bullets,form_formframework'
                    ]
                ],
                [
                    'name' => 'Rechts',
                    'colPos' => 20,
                    'allowed' => [
                        'CType' => 'header,text,textpic,image,textmedia,bullets,form_formframework'
                    ]
                ],
            ]
        ]
    )
    )
);

Als CType nehme ich einfach container-{id} und hänge die ID des Grids aus der Datenbank daran.
Die colPos übernehme ich aus den Grids.

Achtung!
Die Extensions Gridelements verwendet für die Spalten (Columns) ein eigenes Feld in der Datenbank (tx_gridelements_columns) und Container verwendet die Spalte colPos aus dem Core. Daher kann es bei der Verwendung von Backend Layouts mit den gleichen colPos zu Problemen bei der Ausgabe im FE kommen (Content Elemente werden dann zB doppelt angezeigt!). Ich empfehle die ColPos für Container mit 10 zu präfixen. Also aus z.B. 1 wird 101 usw.

Tipp am Rande: Für die allowed CTypes braucht es ohne Gridelements die Extension content_defender.

Nun folgt der aufwendigere Teil, in der Datenbank:

Um die Grids (selbst) in einen Container zu verwandeln bauen wir eigentlich nur den Ctype um:

UPDATE `tt_content` SET `CType`=CONCAT('container-', `tx_gridelements_backend_layout`) WHERE `CType`='gridelements_pi1';

Schwieriger wird es für den Content der Grids:

UPDATE `tt_content` SET `colPos`= `tx_gridelements_columns`,`tx_container_parent`=`tx_gridelements_container` WHERE `colPos`=-1;

Note: Sollte auch mit verschachtelten Grids funktionieren, hatte ich bei dem Projekt aber nicht und daher auch nicht getestet.

Funktioniert natürlich auch mit verschachtelten Grids.

Nun fehlt nur noch das Template. Dieses ist entweder beim Gridelement schon als Datei angelegt oder wird mit TypoScript gebaut. In meinem Fall via TS:

tt_content {
    gridelements_pi1.20.10.setup {
        5 < lib.gridelements.defaultGridSetup
        5 {
            columns {
                10 < .default
                10 {
                    wrap = <div class="longfacts-spalte-1">|</div>
                }

                20 < .10
                20 {
                    wrap = <div class="longfacts-spalte-2">|</div>
                }
            }

            wrap = <section id="longfacts" class="wrapper style2"><div class="inner"><div class="posts"><section class="facts-gesamt">|</section></div></div></section>
        }
    }
}

Daraus baue ich nun ein richtiges Fluidtemplate:

<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
<f:layout name="Default"/>
<f:section name="Main">
    <section id="longfacts" class="wrapper style2">
        <div class="inner">
            <div class="posts">
                <section class="facts-gesamt">
                    <div class="longfacts-spalte-1">
                        <f:if condition="{children_10}">
                            <f:for each="{children_10}" as="child">
                                <f:format.raw>{child.renderedContent}</f:format.raw>
                            </f:for>
                        </f:if>
                    </div>
                    <div class="longfacts-spalte-2">
                        <f:if condition="{children_20}">
                            <f:for each="{children_20}" as="child">
                                <f:format.raw>{child.renderedContent}</f:format.raw>
                            </f:for>
                        </f:if>
                    </div>
                </section>
            </div>
        </div>
    </section>
</f:section>
</html>

Und dann fehlt noch die TypoScript Config.

Zuerst die Standard Config für die Container Extensions (um die Templates von FSC – Fluid Styled Content – auch zu verwenden)

lib.containerElement =< lib.contentElement
lib.containerElement {
    layoutRootPaths {
        100 = EXT:fluid_styled_content/Resources/Private/Layouts
        110 = EXT:theme/Resources/Private/Layouts/Container
    }

    templateRootPaths {
        100 = EXT:fluid_styled_content/Resources/Private/Templates
        110 = EXT:theme/Resources/Private/Templates/Container
    }

    partialRootPaths {
        100 = EXT:fluid_styled_content/Resources/Private/Partials
        110 = EXT:theme/Resources/Private/Partials/Container
    }

    dataProcessing {
        10 = B13\Container\DataProcessing\ContainerProcessor
    }
}

und dann die Config für den Container selbst:

tt_content.container-5 < lib.containerElement
tt_content.container-5 {
    templateName = Container-5
}

Und schon sind alle ehemaligen Gridelements Container Elemente.