Monday, January 6, 2014

TYPO3 - In-Place migration from TemplaVoila to Fluidtemplate and Grid Elements

In the past few years I have made several websites with TYPO3 4.5 LTS and TemplaVoila. The new LTS of TYPO3 is going to be released march 25th, 2014 and there will surely also be a version of TemplaVoila, which is compatible with TYPO3 6.2 LTS, but is TemplaVoila a future-proof solution that will be supported by the community?

When Tolleiv wrote in his blogpost, that TemplaVoila won’t be actively distributed and supported any more by him, I stopped using it for new website projects and switched to Fluidtemplate and Grid Elements which both work great.

I asked myself what to do with the TYPO3 websites I have made with TemplaVoila? Is it maybe possible to migrate a TemplaVoila website to Fluidtemplate and Grid Elements? Or should a website based on TemplaVoila be built up completely new from scatch if you want to switch the template engine?

Starting to test a migration

I started to test a migration from TemplaVoila to Fluidtemplate and Grid Elements on some of my websites. Doing so, I quickly came to a point where I was frustrated and about to drop the migration process, because I had to do a lot of work manually. After I created all Fluidtemplates and Grid Elements, I had to reassign the content elements from TemplaVoila content columns to the backend layout Fluidtemplate content columns, since not all TemplaVoila columns could be automatically migrated to the corresponding content column in the backend layout. Also I had to manually migrate content and FlexForm content for all Grid Elements I created. At this point, I started to create the TYPO3 extension sf_tv2fluidge, which helped me to automate some tasks in the migration process.

Removing unreferenced content elements

The first thing I stumbled across in the migration process were unreferenced content elements. I have seen several websites, were the "Non-used elements" tab in the TemplaVoila page view contained many, many records (sometimes more than 50 elements), because users thought, that those elements have been deleted. Well, actually they are just unlinked and not visible, but still present on the page. So the first thing I had to do during the migration process to Fluidtemplate was to remove all unreferenced elements, because Fluidtemplate does not know anything abount unreferenced content. Since it is not very efficient to remove all unreferenced elements manually, I created an action for sf_tv2fluidge, which recursively for all pages marked all unreferenced elements as deleted.

Migrating TemplaVoila mapped content to Fluidtemplate

I used to create several page templates with different amount of content columns with TemplaVoila. While migrating to Fluidtemplate, I found out, that TemplaVoila mapped content elements could not always just be migrated to the corresponding content column of a Fluidtemplate backend layout. For smaller websites with just one TemplaVoila content column, the migration of all content elements was easy and I did not have to reassign the column position of the content elements, but for more complex templates with multiple content columns the result was mixed up and content did'nt show up in the corresponding content column of the backend layout. Also the sorting of the content elements was not the same as in TemplaVoila.

Content migration from TemplaVoila to backend layouts with Fluidtemplate

I therefore created a content migration helper in sf_tv2fluidge which allows to assign TemplaVoila content columns to backend layout content columns and finally migrate all affected content elements to the target content columns and keep the sorting of the content elements. Also the helper sets the corresponding backend layout for the matching pages.

TemplaVoila references

One nice feature of TemplaVoila is the ability to create references to content elements. Sadly, my newly created content migration helper did not migrate referenced content, so I digged deeper into the functionality of that feature in TemplaVoila.

When TemplaVoila creates a reference to a content object, it just saves the uid of the referenced content element in an XML node. In this XML node, also all other uids from content elements on the corresponding content column are saved. The sorting of records is just as the uids are ordered in the XML node. So the original content element remains on source the page and the reference is just evaluated by TemplaVoila when rendering content in frontend or displaying content elements in the backend page module.

The traditional way of referencing content in TYPO3 is to create a shortcut to an content element by using the "Insert record" content element. This actually creates a new record in the tt_content table which holds the uids to the referenced content objects. Also it contains the column position and the sorting.

So doing the content migration I had to create a new shortcut for each TemplaVoila reference and also respect the sorting of all content elements in the TemplaVoila content column.

Migrating TemplaVoila Flexible Content Elements to Grid Elements

The last big task was releated to TemplaVoila Flexible Content Elements. I normally used Flexible Content Elements when I wanted to enable the site editor to add dynamic content structures to a page. Examples for Flexible Content Elements are elements with muliple columns, sliders or accordions.

As Flexible Content Elements are part of TemplaVoila, they also need to be migrated when you want to use Fluidtemplate as your templateengine. The best approach to do this, is to use Grid Elements, which supports the same XML structure for flexforms as TemplaVoila does. So it should at least be possible to migrate the content from Flexible Content Elements to Grid Elements.

Now you could just copy the flexform structure of a Flexible Content Elements to a new Grid Element and try to get things working, but this approach is really not recommended. Grid Elements integrates directly into the TYPO3 page module and the user can for example use drag and drop with content elements directly on Grid Elements. By just copying the flexform XML structure of your Flexible Content Element to a new Grid Element, you will loose some advantages of Grid Elements. So you have to look at each Flexible Content Element individually and choose the best matching approach (e.g. recreate, migrate flexform or mixed recreation/flexform migration).

When all Grid Elements have been created, content must be migrated. Here I faced a different situation as for normal page content. On one side, a Grid Element can have content columns, where content elements from Flexible Content Elements should be remapped. On the other side, a Grid Element can have a flexform XML structure, which is used to allow the user to input content. And finally, a Grid Element can also be a combination of both content columns and flexform.

Migration from Flexible Content Elements to Grid Elements

I added a Flexible Content Element to Grid Elements migration helper to sf_tv2fluidge, which tries to respect all 3 scenarios described above, keeps care of referenced content, migrates all content and user input made through flexform and finally converts the Flexible Content Element in the tt_content table to a Grid Element.

Screencast of a in-place migration

Well, by now this article was very theoretical and I think it is hard to show a complete site migration by screenshots, so I created a screencast which shows a complete migration process of a demosite, which I created for this article.


As you could see in the screencast, it is possible to migrate an existing TYPO3 website made with TemplaVoila to Fluidtemplate with Grid Elements. You will of course have to do some work by creating Fluidtemplates and Grid Elements, but can benefit from sf_tv2fluidge which helps you to automate several migration steps.

I'm pretty sure, that not all websites can be migrated as smooth as shown in the screencast, since I did not test the migration of a multilingual website and also I did not test Flexible Content Elements with containers for elements.


1. Extension on GitHub:
2. Extension on TER: