327 lines
12 KiB
ReStructuredText
327 lines
12 KiB
ReStructuredText
.. include:: /Includes.rst.txt
|
|
|
|
.. _breaking-97816-1656350406:
|
|
|
|
============================================
|
|
Breaking: #97816 - TypoScript syntax changes
|
|
============================================
|
|
|
|
See :issue:`97816`
|
|
|
|
Description
|
|
===========
|
|
|
|
TYPO3 v12 comes with a new TypoScript syntax parser that is more performant,
|
|
more robust and allows better tooling in the Backend.
|
|
|
|
The new parser is more forgiving in many places, but some seldom used syntax
|
|
details have been removed, too. This documentation explains details that may
|
|
be breaking for existing instances.
|
|
|
|
Also see :ref:`the feature documentation <feature-97816-1656350667>`
|
|
for an overview of syntax improvements.
|
|
|
|
Impact
|
|
======
|
|
|
|
Using one of the constructs below stops working in v12 and needs
|
|
TypoScript adaptions.
|
|
|
|
Affected installations
|
|
======================
|
|
|
|
Instances using TypoScript as outlined below.
|
|
|
|
Migration
|
|
=========
|
|
|
|
Streamlined constants usage
|
|
---------------------------
|
|
|
|
It has never been fully documented in which context "constants" :typoscript:`{$foo}`
|
|
shall be used and which exact capabilities they have. The main TypoScript constants
|
|
documentation within the :ref:`TypoScript Reference <t3tsref:typoscript-syntax-constants>` was partially
|
|
outdated, and the :ref:`TSconfig documentation <t3tsref:Syntax>` claimed TSconfig
|
|
is not constants aware at all, which isn't fully the case anymore. Let's sort out
|
|
some details:
|
|
|
|
* Nesting constants is **not** possible and never has been. A construct like
|
|
this is invalid syntax and is treated as string literal: :typoscript:`{$foo{$bar}}`
|
|
|
|
* Recursive constants were possible with the old parser but are not supported with the new
|
|
parser anymore. This was never documented, the Backend Template module never showed them as
|
|
resolved, only the Frontend parsed recursive constants. The simple rule is now: Never
|
|
access a constant within another constant. Instances using a construct like the below one
|
|
need to untie constants.
|
|
|
|
.. code-block:: typoscript
|
|
|
|
constants:
|
|
foo = fooValue
|
|
# This does not resolve to "fooValue" but is kept as string literal "{$foo}"
|
|
bar = {$foo}
|
|
|
|
setup:
|
|
# This does NOT resolve to "fooValue", but to the string literal "{$foo}"
|
|
myValue = {$bar}
|
|
|
|
* Similar to the above restriction, constants can be used in Frontend TypoScript *setup* conditions,
|
|
but not in Frontend TypoScript *constants* conditions. As example, a :sql:`sys_template` record with
|
|
the below content set in the :sql:`constants` field always evaluates the condition to false:
|
|
|
|
.. code-block:: typoscript
|
|
|
|
my.constant = myValue
|
|
['{$my.constant}' == 'myValue']
|
|
# Never executed since the above constant usage is NOT substituted to 'myValue'
|
|
other.constant = otherValue
|
|
[global]
|
|
|
|
If something like this is really needed, integrators can potentially work around by accessing
|
|
a :ref:`site setting <t3coreapi:sitehandling-settings>` directly in a constants condition:
|
|
|
|
.. code-block:: typoscript
|
|
|
|
The sites settings.yaml:
|
|
some:
|
|
setting: someValue
|
|
|
|
A sys_template record constants field within this site:
|
|
my.constant = myValue
|
|
[traverse(site('configuration'), 'settings/some/setting') == 'someValue']
|
|
# This works but is rather ugly to rely on
|
|
other.constant = otherValue
|
|
[global]
|
|
|
|
* Constants are now restricted to "assignments" and "conditions". Using a constant to
|
|
substitute an "identifier" / "object path" is no longer allowed. This has never been
|
|
clarified in the docs before and instances abusing constants to specify object paths
|
|
should be seldom and need to resolve the situation with the new parser now:
|
|
|
|
This is supported:
|
|
|
|
.. code-block:: typoscript
|
|
|
|
# Simple constant usage as assignment value:
|
|
foo = {$bar}
|
|
# Compiling a value with string literals and constants:
|
|
foo = I am {$bar}
|
|
# Using a constant in a condition:
|
|
[ myValue = {$bar} ]
|
|
# Using constant(s) in multiline assignments:
|
|
foo (
|
|
I am {$bar} and {$baz}
|
|
)
|
|
|
|
These constructs are *not* supported:
|
|
|
|
.. code-block:: typoscript
|
|
|
|
# Using a constant as object path specification
|
|
{$bar} = myValue
|
|
# This is an object path specification, too, and not supported:
|
|
foo < {$bar}
|
|
|
|
* PageTsConfig *does* support constant substitution: Site constants can be used
|
|
in PageTsconfig. This has been introduced with TYPO3 v10, see
|
|
:ref:`feature-91080-1657827157` for details.
|
|
|
|
File includes are always top level
|
|
----------------------------------
|
|
|
|
File includes with :typoscript:`@import` and :typoscript:`<INCLUDE_TYPOSCRIPT:` within
|
|
curly braces are not relative anymore. A construct like this is invalid:
|
|
|
|
.. code-block:: typoscript
|
|
|
|
page = PAGE
|
|
page {
|
|
@import 'EXT:my_extension/Configuration/TypoScript/bar.typoscript'
|
|
20 = TEXT
|
|
20.value = bar
|
|
}
|
|
|
|
With :file:`EXT:my_extension/Configuration/TypoScript/bar.typoscript` having this content:
|
|
|
|
.. code-block:: typoscript
|
|
|
|
10 = TEXT
|
|
10.value = foo
|
|
|
|
This *no longer* leads to this TypoScript:
|
|
|
|
.. code-block:: typoscript
|
|
|
|
page = PAGE
|
|
page.10 = TEXT
|
|
page.10.value = foo
|
|
page.20 = TEXT
|
|
page.20.value = bar
|
|
|
|
Instead, the following TypoScript will be calculated:
|
|
|
|
.. code-block:: typoscript
|
|
|
|
page = PAGE
|
|
10 = TEXT
|
|
10.value = foo
|
|
20 = TEXT
|
|
20.value = bar
|
|
|
|
This means :typoscript:`@import` and :typoscript:`<INCLUDE_TYPOSCRIPT:` basically break
|
|
any curly braces level, resetting current scope to top level. While inclusion of files has
|
|
never been documented to be valid within braces assignments, it still worked until TYPO3 v11.
|
|
This is now disallowed and must not be used anymore.
|
|
|
|
:typoscript:`<INCLUDE_TYPOSCRIPT:` with :typoscript:`DIR:` and relative paths
|
|
always assumes the :file:`public/` directory as base directory now.
|
|
(Formerly it was relative to the file holding the include statement.)
|
|
|
|
@import is more restrictive with wildcards
|
|
------------------------------------------
|
|
|
|
The previous implementation of :typoscript:`@import` relied on Symfony Finder. This turned out
|
|
to be a performance bottleneck, the new implementation is based on "native" PHP file and directory
|
|
lookup logic. For performance, security and best practice considerations, :typoscript:`@import`
|
|
is now a bit more restrictive than before, especially with wildcard :typoscript:`*` handling.
|
|
|
|
Integrators are encouraged to switch from :typoscript:`<INCLUDE_TYPOSCRIPT:` to
|
|
:typoscript:`@import` in TYPO3 v12 projects: The :typoscript:`<INCLUDE_TYPOSCRIPT:`
|
|
is more complex and harder to handle, but a bit more permissive. Note :typoscript:`@import`
|
|
can be placed within conditions bodies now: :typoscript:`@import` lines are only considered
|
|
if the condition matches. This did not work with TYPO3 v11. It is likely that
|
|
:typoscript:`<INCLUDE_TYPOSCRIPT:` will be deprecated with TYPO3 v13, integrators
|
|
should adapt to :typoscript:`@import` when upgrading to TYPO3 v12 already.
|
|
|
|
The following rules apply to :typoscript:`@import`:
|
|
|
|
* Files *must* reside in extensions, the lookup pattern *must* start with :typoscript:`EXT`
|
|
if absolute. Including TypoScript snippets, for instance, from :file:`fileadmin` is *not* allowed
|
|
and never has been for :typoscript:`@import`.
|
|
|
|
* File includes *may* be relative to the current file, and *must* be prefixed with :file:`./`
|
|
in this case. Subdirectories are allowed, path traversal using :file:`../` is not allowed.
|
|
|
|
* Files *must* end with :file:`.typoscript` in frontend TypoScript. With TSconfig, both
|
|
:file:`.tsconfig` and :file:`.typoscript` are allowed, but :file:`.tsconfig` should be
|
|
preferred.
|
|
|
|
* Directory includes are *not* recursive.
|
|
|
|
* Directory traversal using :file:`../` is *not* allowed.
|
|
|
|
* Wildcards for directories are *not* allowed. This has never been documented as working, and
|
|
is considered an unplanned side-effect of Symfony Finder. Few people used this undocumented
|
|
feature, it should be possible to restructure existing uses relatively easily.
|
|
|
|
* Only a single wildcard :typoscript:`*` is allowed for filename patterns.
|
|
|
|
Valid examples:
|
|
|
|
.. code-block:: typoscript
|
|
|
|
@import 'EXT:my_extension/Configuration/TypoScript/bar.typoscript'
|
|
|
|
# Import all files in directory, ending with :file:`.typoscript`, or additionally
|
|
# :file:`.tsconfig` in TSconfig scope, in native operating system ascending order.
|
|
@import 'EXT:my_extension/Configuration/TypoScript/'
|
|
|
|
@import 'EXT:my_extension/Configuration/TypoScript/*.typoscript'
|
|
@import 'EXT:my_extension/Configuration/TypoScript/*.setup.typoscript'
|
|
|
|
# Import setupFoo.typoscript, setup.foo.typoscript and similar
|
|
@import 'EXT:my_extension/Configuration/TypoScript/setup*.typoscript'
|
|
@import 'EXT:my_extension/Configuration/TypoScript/setup*'
|
|
|
|
# If this is in file 'EXT:my_extension/Configuration/TypoScript/foo.typoscript',
|
|
# file 'EXT:my_extension/Configuration/TypoScript/bar.typoscript is included
|
|
@import './bar.typoscript`
|
|
# Relative sub directories includes are supported
|
|
@import './SubDirectory/bar.typoscript`
|
|
# Relative sub directories with wildcards are supported,
|
|
# this will include ./SubDirectory/foo.typoscript
|
|
@import './SubDirectory/*'
|
|
|
|
Invalid examples:
|
|
|
|
.. code-block:: typoscript
|
|
|
|
# fileadmin and friends not allowed
|
|
@import 'fileadmin/foo.typoscript'
|
|
|
|
# Tries to include foo.txt.typoscript, *not* foo.txt
|
|
@import 'EXT:my_extension/Configuration/TypoScript/foo.txt'
|
|
|
|
# Directory traversal is not allowed
|
|
@import 'EXT:my_extension/Configuration/TypoScript/Foo/../Bar/bar.typoscript'
|
|
|
|
# Directory wildcards are not allowed
|
|
@import 'EXT:my_extension/Configuration/TypoScript/*/foo.typoscript'
|
|
|
|
# Multiple wildcards in filename pattern are not allowed
|
|
@import 'EXT:my_extension/Configuration/TypoScript/foo.*.*.typoscript'
|
|
|
|
|
|
UTF-8 BOM in TypoScript files
|
|
-----------------------------
|
|
|
|
The new TypoScript parser no longer ignores `UTF-8 BOM <https://en.wikipedia.org/wiki/Byte_order_mark>`_
|
|
in included files: Having a Byte-order-mark in TypoScript files may create undesired
|
|
results. They should be removed. UTF-8 BOM is disallowed in various other languages,
|
|
for instance JSON and PHP. The new parser follows here. Modern editors typically don't
|
|
add an UTF-8 BOM anymore.
|
|
|
|
Instances can check if they use UTF-8 BOM with a Unix shell command:
|
|
|
|
.. code-block:: bash
|
|
|
|
# find affected files
|
|
find . -type f -print0 | xargs -0 -n1 file {} | grep 'UTF-8 Unicode (with BOM)'
|
|
# remove UTF-8 BOM from a single file
|
|
sed -i '1s/^\xEF\xBB\xBF//' affectedFile.typoscript
|
|
|
|
Support for \\n and \\r\\n linebreaks only
|
|
------------------------------------------
|
|
|
|
TypoScript sources must terminate single lines with either "\\n" (Unix ending: LineFeed),
|
|
or "\\r\\n" (Windows ending: Carriage return, LineFeed). Ancient Mac, prior to Mac OS X
|
|
used "\\r" as single linebreak character. This old linebreak type is no longer detected
|
|
when parsing TypoScript and may lead to funny results, but chances are very low any
|
|
instance is affected by this.
|
|
|
|
Operator matching has higher precedence
|
|
---------------------------------------
|
|
|
|
The new parser looks for valid operators first, then parses things behind it.
|
|
Consider this example:
|
|
|
|
.. code-block:: typoscript
|
|
|
|
lib.nav.wrap =<ul id="nav">|</ul>
|
|
|
|
This is ambiguous: The above :typoscript:`=<ul` could be interpreted both as an
|
|
assignment :typoscript:`=` of the value :typoscript:`<ul`, or as a reference
|
|
:typoscript:`=<` to the identifier :typoscript:`ul`.
|
|
|
|
While the old parser interpreted this as an assignment, the new parser treats it
|
|
as a reference.
|
|
|
|
The above example aims for an assignment, though, which can be achieved by adding
|
|
a whitespace between :typoscript:`=` and :typoscript:`<`:
|
|
|
|
.. code-block:: typoscript
|
|
|
|
lib.nav.wrap = <ul id="nav">|</ul>
|
|
|
|
Frontend TypoScript `temp.` top level object
|
|
--------------------------------------------
|
|
|
|
The Frontend TypoScript related top level object :typoscript:`temp` had special
|
|
functionality until v12: Any TypoScript defined within was "temporary" at parse time
|
|
and unset afterwards. It was not cached and could not be used as reference
|
|
(:typoscript:`=<` operator). This special meaning has been removed, the key
|
|
:typoscript:`temp` now works just like any other top level key.
|
|
|
|
|
|
.. index:: Backend, Frontend, TSConfig, TypoScript, NotScanned, ext:core
|