feature #4571 Add support for registered undefined element callbacks in tests (stof)

This PR was merged into the 3.x branch.

Discussion
----------

Add support for registered undefined element callbacks in tests

This also defines the proper type for the callable arguments in those methods, allowing to know the expected signature (and allowing static analysis tools to check it) instead of having to inspect the implementation to see how those callables are used.

Commits
-------

198fc1a9f9 Add support for registered undefined element callbacks in tests
This commit is contained in:
Fabien Potencier
2025-02-04 12:35:15 +01:00
4 changed files with 60 additions and 1 deletions
+2 -1
View File
@@ -2,6 +2,7 @@
* Fix wrong array index
* Bump minimum PHP version to 8.1
* Add support for registering callbacks for undefined functions, filters or token parsers in the IntegrationTestCase
# 3.19.0 (2025-01-28)
@@ -44,7 +45,7 @@
* Deprecate returning `null` from `TwigFilter::getSafe()` and `TwigFunction::getSafe()`, return `[]` instead
# 3.15.0 (2024-11-17)
* [BC BREAK] Add support for accessing class constants with the dot operator;
this can be a BC break if you don't use UPPERCASE constant names
* Add Spanish inflector support for the `plural` and `singular` filters in the String extension
+9
View File
@@ -736,6 +736,9 @@ class Environment
return $this->extensionSet->getTokenParser($name);
}
/**
* @param callable(string): (TokenParserInterface|false) $callable
*/
public function registerUndefinedTokenParserCallback(callable $callable): void
{
$this->extensionSet->registerUndefinedTokenParserCallback($callable);
@@ -775,6 +778,9 @@ class Environment
return $this->extensionSet->getFilter($name);
}
/**
* @param callable(string): (TwigFilter|false) $callable
*/
public function registerUndefinedFilterCallback(callable $callable): void
{
$this->extensionSet->registerUndefinedFilterCallback($callable);
@@ -838,6 +844,9 @@ class Environment
return $this->extensionSet->getFunction($name);
}
/**
* @param callable(string): (TwigFunction|false) $callable
*/
public function registerUndefinedFunctionCallback(callable $callable): void
{
$this->extensionSet->registerUndefinedFunctionCallback($callable);
+12
View File
@@ -52,8 +52,11 @@ final class ExtensionSet
private $binaryOperators;
/** @var array<string, mixed>|null */
private $globals;
/** @var array<callable(string): (TwigFunction|false)> */
private $functionCallbacks = [];
/** @var array<callable(string): (TwigFilter|false)> */
private $filterCallbacks = [];
/** @var array<callable(string): (TokenParserInterface|false)> */
private $parserCallbacks = [];
private $lastModified = 0;
@@ -198,6 +201,9 @@ final class ExtensionSet
return null;
}
/**
* @param callable(string): (TwigFunction|false) $callable
*/
public function registerUndefinedFunctionCallback(callable $callable): void
{
$this->functionCallbacks[] = $callable;
@@ -251,6 +257,9 @@ final class ExtensionSet
return null;
}
/**
* @param callable(string): (TwigFilter|false) $callable
*/
public function registerUndefinedFilterCallback(callable $callable): void
{
$this->filterCallbacks[] = $callable;
@@ -317,6 +326,9 @@ final class ExtensionSet
return null;
}
/**
* @param callable(string): (TokenParserInterface|false) $callable
*/
public function registerUndefinedTokenParserCallback(callable $callable): void
{
$this->parserCallbacks[] = $callable;
+37
View File
@@ -17,6 +17,7 @@ use Twig\Error\Error;
use Twig\Extension\ExtensionInterface;
use Twig\Loader\ArrayLoader;
use Twig\RuntimeLoader\RuntimeLoaderInterface;
use Twig\TokenParser\TokenParserInterface;
use Twig\TwigFilter;
use Twig\TwigFunction;
use Twig\TwigTest;
@@ -84,6 +85,30 @@ abstract class IntegrationTestCase extends TestCase
return [];
}
/**
* @return array<callable(string): (TwigFilter|false)>
*/
protected function getUndefinedFilterCallbacks(): array
{
return [];
}
/**
* @return array<callable(string): (TwigFunction|false)>
*/
protected function getUndefinedFunctionCallbacks(): array
{
return [];
}
/**
* @return array<callable(string): (TokenParserInterface|false)>
*/
protected function getUndefinedTokenParserCallbacks(): array
{
return [];
}
/**
* @dataProvider getTests
*
@@ -222,6 +247,18 @@ abstract class IntegrationTestCase extends TestCase
$twig->addFunction($function);
}
foreach ($this->getUndefinedFilterCallbacks() as $callback) {
$twig->registerUndefinedFilterCallback($callback);
}
foreach ($this->getUndefinedFunctionCallbacks() as $callback) {
$twig->registerUndefinedFunctionCallback($callback);
}
foreach ($this->getUndefinedTokenParserCallbacks() as $callback) {
$twig->registerUndefinedTokenParserCallback($callback);
}
$deprecations = [];
try {
$prevHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$deprecations, &$prevHandler) {