Eigene TypoScript Conditions erstellen mit Expression Language

Ich zeige dir wie du eigene Bedingungen in TypoScript mittels der Symfony Expression Language in TYPO3 erstellen kannst.

In TYPO3 kommt man als Integrator oder Entwickler irgendwann an die Situation, dass die TYPO3 eigenen TypoScript Conditions nicht mehr ausreichen. Das ist der Zeitpunkt an dem man gerne eigene Conditions erstellen möchte. Glücklicherweise ist dass in TYPO3 sehr einfach möglich.

Was sind TypoScript Conditions?

Für einen PHP Entwickler ist die Frage schnell beantwortet. TypoScript Conditions sind IF - Anweisungen in TypoScript. 

Für nicht Nicht - Entwickler kann ich eine TypoScript Condition an diesem Beispiel erklären:

[page["uid"] == 2]
// do something
[END]

Die Condition steht in Zeile eins und ist eingerahmt in eckigen Klammern [...]. Die Klammern teilen TypoScript mit, dass jetzt eine Bedingung kommt. Die Bedingung nutzt das globale TypoScript - Objekt: page, welches Informationen über die aktuelle Seite hält.

In diesem Fall fragen wir die uid, also die ID der Seite ab. Wenn die ID den Wert 2 hat, dann werden die folgenen TypoScript Zeilen bis zum nächsten: [END] oder [GLOBAL] ausgeführt. Für Seiten deren ID nicht 2 sind, werden diese Zeilen nicht ausgeführt.

Was ist die Expression Language?

Die Expression Language kommt von Symfony. Symfony ist ein beliebtes PHP Framework, welches die modernsten Softwaretechniken einsetzt. TYPO3 hat die Expression Language ab der Version 9 in seinen Core integriert. Der TypoScript Code oben ist ebenfalls Expression Language. Der Vorteil von Expression Language ist die einfache Syntax und die Flexibilität.

Eigene TypoScript Condition erstellen

Um eigene TypoScript Conditions zu erstellen muss man programmatisch eingreifen. Wir müssen folgende Schritte vornehmen:

  1. Registrierung eines neuen Condition Provider
  2. Neuen Provider implementieren
  3. TypoScript Variablen konfigurieren
  4. TypoScript Funktionen konfigurieren

Um diese Schritte vornehmen zu können, sollte man eine eigene Extension schreiben. Wie du eine eigene Extension erstellen kannst, dass lernst du in dem Lernpfad für TYPO3 Entwickler.

Registrierung des Condition Provider

Erstelle einen neuen Ordner: Configuration innerhalb deines Extensionordners. Dort erstellt du eine PHP Datei mit den Namen: ExpressionLanguage.php. 

typo3conf/ext/deine_extension/Configuration/ExpressionLanguage.php

Diese Datei wird von TYPO3 automatisch gesucht und falls vorhanden ausgeführt.

Implementierung des Condition Providers

<?php
namespace Slavlee\DeineExtension\ExpressionLanguage;
use TYPO3\CMS\Core\ExpressionLanguage\AbstractProvider;

class ExampleTypoScriptConditionProvider extends AbstractProvider
{
    public function __construct()
    {
    }
}

TYPO3 bildet automatisch eine Instanz von dieser Klasse. Die Basisklasse: AbstractProvider liefert alle Funktionen die automatisch von TYPO3 ausgeführt werden. Du kannst dich also allein auf die Implementierung deiner Funktionen konzentrieren.

TypoScript Variablen konfigurieren

Die Registrierung der TypoScript Variable erfolgt im Konstruktor. Der Konstruktor ist eine spezielle Funktione die automatisch von PHP aufgerufen wird, wenn eine neue Instanz dieser Klasse gebildet wird.

class ExampleTypoScriptConditionProvider extends AbstractProvider
{
    public function __construct()
    {
        $this->expressionLanguageVariables = [
            'param1' => 'exampleValue',
        ];
    }
}

Mit diesen einfachen Zeilen hast du bereits eine TypoScript Variable erstellt, die du sofort einsetzen kannst. 

[param1 === 'exampleValue']
// do something
[GLOBAL]

Sobald nun unsere neue TypoScript Variabel einen bestimmten Wert hat, wird der entsprechende TypoScript Code ausgeführt. So kannst du zum Beispiel Plugins einblenden, sobald im TypoScript eine Einstellung geändert wird. 

TypoScript Funktionen konfigurieren

Während man bei einer Variablen nur einen Vergleich gegen einen Wert vornehmen kann, lässt sich mit einer TypoScript Funktion komplexere Vergleiche vornehmen. Die Registrierung erfolgt ebenfalls im Konstruktor.

class SlavleeTypoScriptConditionProvider extends AbstractProvider
{
    public function __construct()
    {
        $this->expressionLanguageProviders = [
            SlavleeConditionFunctionsProvider::class,
        ];
    }
}

Eine Funktion ist in der Implementierung nichts anderes wie eine weitere PHP Klasse.

<?php
namespace Slavlee\DeineExtension\TypoScript;
use Symfony\Component\ExpressionLanguage\ExpressionFunction;
use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;

class SlavleeConditionFunctionsProvider implements ExpressionFunctionProviderInterface
{
    public function getFunctions()
    {
        return [
            $this->getExampleFunction(),
        ];
    }

    protected function getExampleFunction(): ExpressionFunction
    {
        // TODO: Implement
    }
}

Diese Klasse erbt von einer Basisklasse die Funktionen besitzt die TYPO3 kennt und ausführt. Die Implementierung und somit Funktionalität der Funktion programmierst du. So können wie beispielsweise eine TypoScript Funktion schreiben die prüft, ob eine Extension geladen wurde:

protected function getExampleFunction(): ExpressionFunction {
  return new ExpressionFunction('isLoaded', function () {
        // Not implemented, we only use the evaluator
    }, function ($existingVariables, $extensionName) {
        return \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded($extensionName);
    });
}

Du kannst hier beliebig viele Parameter angeben und im TypoScript nutzen. Selbstverständlich lassen sich hier auf mehr als nur eine TypoScript Funktion definieren. Die obige Funktion kann man in TypoScript wie folgt nutzen:

[isLoaded('slavlee_package')]
// do something
[GLOBAL]

Du siehst - es ist super einfach neue TypoScript Variablen und Funktionen zu erstellen, die du dann auch in Bedingungen nutzen kannst.