Mask

The popular Mask extension is one of the most used extensions in TER. With over one million downloads on packagist it served their users well. Content Blocks is heavily inspired by Mask's architecture. In fact, it could be called the successor of Mask. The combination of Mask and the concept of a Content Block is the result of this extension. Due to this, the migration is quite simple and doesn't even require database migrations.

Manual migration

As of now, there is no automatic migration from Mask to Content Blocks. This might come in the future. For now, let's see how to do the migration manually. The advantage is that you might better understand how the extension works. Install Content Blocks in parallel to Mask and follow the steps below.

Recreation of a Mask Element

Example Mask slider element

Example Mask slider element

First, let's create a new Content Block for the Mask Element you want to migrate. For this, run the command make:content-block and create a Content Element with a vendor and name of your choice. The name can be the same as the Mask name, but doesn't have to.

Next, you need to override the typeName and disable prefixing. In this example our Mask element has the name slider, so typeName must be set to mask_slider. This is the CType, which Mask generates in the background. If you don't set this option, Content Blocks would create a unique identifier from vendor and name, which you don't want in this case. We disable prefixing, so we can adopt the existing Mask fields.

EXT:site_package/ContentBlocks/ContentElements/slider/EditorInterface.yaml
name: tx-mask/slider
typeName: mask_slider
prefixFields: false
Copied!

Our Mask element has a repeating slides field. This is a Collection in terms of Content Blocks. To adopt this field, we have to set the identifier prefixed with tx_mask. Also, foreign_field has to be set explicitly to parentid, as this is the column name, which Mask uses for its parent reference field.

All other fields can be re-defined in Content Blocks as usual. Don't forget to prefix all fields with tx_mask, even inside Collections.

EXT:site_package/ContentBlocks/ContentElements/slider/EditorInterface.yaml
name: tx-mask/slider
typeName: mask_slider
prefixFields: false
fields:
  - identifier: tx_mask_slides
    type: Collection
    foreign_field: parentid
    fields:
      - identifier: tx_mask_header
        type: Textarea
      - identifier: tx_mask_text
        type: Textarea
        enableRichtext: true
      - identifier: tx_mask_image
        type: File
Copied!

Templates

This is the easy part. Simply copy the Mask template into Frontend.html and you are done. That said, if you didn't use any partials or layouts. If so, move these to the according Source/Partials and Source/Layouts folder in your Content Block.

Icon

In case you've used a custom SVG icon for the Mask Element, you can rename it to Icon.svg and move it to the Assets folder. For FontAwesome icons you can download the SVG version from the official website.

Labels

Mask doesn't have a translation feature. Labels can be copied from the backend module view, and pasted directly into the Labels.xlf file.

Finish

That's mostly it. Now you can purge your Mask element in the backend module view and everything should work as before. Repeat the migration for every Mask Element and you can uninstall the Mask extension in the end and say farewell.

Limitations

There are some very special Mask features, which didn't make the cut to Content Blocks (for good reason).

Page templates fields

Mask has this quirky feature of assigning additional page fields based on TYPO3 backend layouts. Historically, frontend page templates are bound to backend layouts. This is a conceptual mistake, which still persists. Anyway, there is no such feature in Content Blocks. Use custom page types instead and migrate pages with special backend layouts to the new doktype.

Nested Content

Technically, nested content means the table tt_content has a relation to itself. This can be achieved with Content Blocks as well with the help of Collections. However, the approach is slightly different. Mask sets the fixed value 999 for the colPos field of child elements. All elements with this colPos value are simply hidden from the backend with a hook. Naturally, they won't appear in the frontend, as this colPos is usually not rendered. In contrast, Content Blocks uses the existing parent reference field to systematically determine the status of a child field. This method is far more superior as it doesn't force a random colPos value.

You do the migration as described with Collections above. In addition, you have to add some more config.

EXT:site_package/ContentBlocks/ContentElements/nested-content/EditorInterface.yaml
name: tx-mask/nested-content
typeName: mask_nested_content
prefixFields: false
fields:
  - identifier: tx_mask_content
    type: Collection
    foreign_table: tt_content
    foreign_field: tx_mask_content_parent_uid
    foreign_table_field: tx_mask_content_tablenames
    foreign_match_fields:
      tx_mask_content_role: tx_mask_content
Copied!

The limitation is, that you can't add constraints to the available CTypes in the child field. However, you can set a default value.

EXT:site_package/ContentBlocks/ContentElements/nested-content/EditorInterface.yaml
name: tx-mask/nested-content
typeName: mask_nested_content
prefixFields: false
fields:
  - identifier: tx_mask_content
    type: Collection
    foreign_table: tt_content
    foreign_field: tx_mask_content_parent_uid
    foreign_table_field: tx_mask_content_tablenames
    foreign_match_fields:
      tx_mask_content_role: tx_mask_content
    overrideChildTca:
      columns:
        CType:
          config:
            default: text
Copied!

Disable Content Elements

With Mask, you could disable certain Mask Elements so they won't appear in the Content Element Wizard. This is not possible with Content Blocks. All defined Content Blocks are always available. The migration is to delete those unused elements, or restrict the usage through backend user permissions.