1<?php 2declare(strict_types = 1); 3namespace TYPO3\CMS\Core\ExpressionLanguage\FunctionsProvider; 4 5/* 6 * This file is part of the TYPO3 CMS project. 7 * 8 * It is free software; you can redistribute it and/or modify it under 9 * the terms of the GNU General Public License, either version 2 10 * of the License, or any later version. 11 * 12 * For the full copyright and license information, please read the 13 * LICENSE.txt file that was distributed with this source code. 14 * 15 * The TYPO3 project - inspiring people to share! 16 */ 17 18use Symfony\Component\ExpressionLanguage\ExpressionFunction; 19use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; 20use TYPO3\CMS\Core\Configuration\Features; 21use TYPO3\CMS\Core\Context\Context; 22use TYPO3\CMS\Core\Utility\ArrayUtility; 23use TYPO3\CMS\Core\Utility\Exception\MissingArrayPathException; 24use TYPO3\CMS\Core\Utility\GeneralUtility; 25use TYPO3\CMS\Core\Utility\StringUtility; 26use TYPO3\CMS\Core\Utility\VersionNumberUtility; 27 28/** 29 * Class DefaultFunctionsProvider 30 * @internal 31 */ 32class DefaultFunctionsProvider implements ExpressionFunctionProviderInterface 33{ 34 /** 35 * @return ExpressionFunction[] An array of Function instances 36 */ 37 public function getFunctions() 38 { 39 return [ 40 $this->getIpFunction(), 41 $this->getCompatVersionFunction(), 42 $this->getLikeFunction(), 43 $this->getEnvFunction(), 44 $this->getDateFunction(), 45 $this->getFeatureToggleFunction(), 46 $this->getTraverseArrayFunction(), 47 ]; 48 } 49 50 protected function getIpFunction(): ExpressionFunction 51 { 52 return new ExpressionFunction( 53 'ip', 54 function () { 55 // Not implemented, we only use the evaluator 56 }, 57 function ($arguments, $str) { 58 if ($str === 'devIP') { 59 $str = trim($GLOBALS['TYPO3_CONF_VARS']['SYS']['devIPmask'] ?? ''); 60 } 61 return (bool)GeneralUtility::cmpIP(GeneralUtility::getIndpEnv('REMOTE_ADDR'), $str); 62 } 63 ); 64 } 65 66 protected function getCompatVersionFunction(): ExpressionFunction 67 { 68 return new ExpressionFunction( 69 'compatVersion', 70 function () { 71 // Not implemented, we only use the evaluator 72 }, 73 function ($arguments, $str) { 74 return VersionNumberUtility::convertVersionNumberToInteger(TYPO3_branch) >= 75 VersionNumberUtility::convertVersionNumberToInteger($str); 76 } 77 ); 78 } 79 80 protected function getLikeFunction(): ExpressionFunction 81 { 82 return new ExpressionFunction('like', function () { 83 // Not implemented, we only use the evaluator 84 }, function ($arguments, $haystack, $needle) { 85 $result = StringUtility::searchStringWildcard((string)$haystack, (string)$needle); 86 return $result; 87 }); 88 } 89 90 protected function getEnvFunction(): ExpressionFunction 91 { 92 return ExpressionFunction::fromPhp('getenv'); 93 } 94 95 protected function getDateFunction(): ExpressionFunction 96 { 97 return new ExpressionFunction('date', function () { 98 // Not implemented, we only use the evaluator 99 }, function ($arguments, $format) { 100 return GeneralUtility::makeInstance(Context::class) 101 ->getAspect('date')->getDateTime()->format($format); 102 }); 103 } 104 105 protected function getFeatureToggleFunction(): ExpressionFunction 106 { 107 return new ExpressionFunction('feature', function () { 108 // Not implemented, we only use the evaluator 109 }, function ($arguments, $featureName) { 110 return GeneralUtility::makeInstance(Features::class) 111 ->isFeatureEnabled($featureName); 112 }); 113 } 114 115 public function getTraverseArrayFunction(): ExpressionFunction 116 { 117 return new ExpressionFunction('traverse', function () { 118 // Not implemented, we only use the evaluator 119 }, function ($arguments, $array, $path) { 120 if (!is_array($array) || !is_string($path) || $path === '') { 121 return ''; 122 } 123 try { 124 return ArrayUtility::getValueByPath($array, $path); 125 } catch (MissingArrayPathException $e) { 126 return ''; 127 } 128 }); 129 } 130} 131