Search code examples
phptypo3typoscripttypo3-9.x

TYPO3: how to migrate userFunc TypoScript condition to Symfony Expression Language?


How can I migrate this TypoScript condition to be fully compatible with the Symfony Expression Language for conditions in TYPO3 9.5?

[userFunc = TYPO3\CMS\Core\Utility\ExtensionManagementUtility::isLoaded('fluid_styled_content')]


Solution

  • You'd have to provide your own functions at the moment.

    There is a tutorial here: https://usetypo3.com/symfony-expression-language-in-typo3.html

    But basically you'd have the file yourext/Configuration/ExpressionLanguage.php with content like:

    <?php
    
    return [
        'typoscript' => [
            \Vendor\Yourext\ExpressionLanguage\ConditionProvider::class
        ]
    ];
    

    This registers a condition provider for the typoscript context.

    For adding simple functions you need to set function provider classes to the expressionLanguageProviders of that class.

    Which might look like this:

    <?php
    
    namespace Vendor\Yourext\ExpressionLanguage;
    
    use TYPO3\CMS\Core\ExpressionLanguage\AbstractProvider;
    
    class ConditionProvider extends AbstractProvider
    {
        public function __construct()
        {
            $this->expressionLanguageProviders = [
                UtilitiesConditionFunctionsProvider::class,
                SomeOtherConditionFunctionsProvider::class,
                AThirdConditionFunctionsProvider::class,
            ];
        }
    }
    

    (Maybe even set it on the property directly, instead of using the constructor, but that's what I did).

    Those function providers need to implement the \Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface interface, which is basically just a getFunctions method that needs to return an array of \Symfony\Component\ExpressionLanguage\ExpressionFunction instances.

    My UtilitiesConditionFunctionsProvider looks like this:

    <?php
    
    namespace Vendor\Yourext\ExpressionLanguage;
    
    use Symfony\Component\ExpressionLanguage\ExpressionFunction;
    use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
    use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
    
    class UtilitiesConditionFunctionsProvider implements ExpressionFunctionProviderInterface
    {
    
        /**
         * @return ExpressionFunction[] An array of Function instances
         */
        public function getFunctions()
        {
            return [
                $this->getIntersectsFunction(),
                $this->getExtensionLoadedFunction(),
            ];
        }
    
        /**
         * @return ExpressionFunction
         */
        protected function getIntersectsFunction()
        {
            return new ExpressionFunction('intersects', function () {
                // Not implemented, we only use the evaluator
            }, function ($arguments, $left, $right) {
                return count(array_intersect($left, $right)) > 0;
            });
        }
    
        protected function getExtensionLoadedFunction()
        {
            return new ExpressionFunction('loaded', function () {
                // Not implemented, we only use the evaluator
            }, function ($arguments, $extKey) {
                return ExtensionManagementUtility::isLoaded($extKey);
            });
        }
    }
    

    With that it's now possible to use intersects( ... ) and loaded( ... ) in my conditions.