Skip to content

Commit

Permalink
Name is optional
Browse files Browse the repository at this point in the history
  • Loading branch information
GromNaN committed Mar 3, 2025
1 parent e24d6f9 commit 633ccfc
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 29 deletions.
32 changes: 22 additions & 10 deletions doc/advanced.rst
Original file line number Diff line number Diff line change
Expand Up @@ -832,20 +832,20 @@ Create a class using this attributes::

class ProjectExtension
{
#[AsTwigFilter('rot13')]
#[AsTwigFilter]
public static function rot13(string $string): string
{
// ...
}

#[AsTwigFunction('lipsum')]
#[AsTwigFunction]
public static function lipsum(int $count): string
{
// ...
}

#[AsTwigTest('even')]
public static function isEven(int $number): bool
#[AsTwigTest]
public static function even(int $number): bool
{
// ...
}
Expand All @@ -870,7 +870,7 @@ a runtime extension using one of the runtime loaders::
// Inject hypothetical dependencies
public function __construct(private LipsumProvider $lipsumProvider) {}

#[AsTwigFunction('lipsum')]
#[AsTwigFunction]
public function lipsum(int $count): string
{
return $this->lipsumProvider->lipsum($count);
Expand All @@ -885,12 +885,24 @@ a runtime extension using one of the runtime loaders::
},
]));

The name can be customized to prevent conflict with other Twig callables and follow
the :doc:`Coding Standards<../coding_standards>`::

class ProjectExtension
{
#[AsTwigFunction(name: 'name_in_snake_case')]
public function nameInCamelCase(int $count): string
{
// ...
}
}

If you want to access the current environment instance in your filter or function,
add the ``Twig\Environment`` type to the first argument of the method::

class ProjectExtension
{
#[AsTwigFunction('lipsum')]
#[AsTwigFunction]
public function lipsum(\Twig\Environment $env, int $count): string
{
// ...
Expand All @@ -902,7 +914,7 @@ automatically when applied to variadic methods::

class ProjectExtension
{
#[AsTwigFilter('thumbnail')]
#[AsTwigFilter]
public function thumbnail(string $file, mixed ...$options): string
{
// ...
Expand All @@ -911,9 +923,9 @@ automatically when applied to variadic methods::

The attributes support other options used to configure the Twig Callables:

* ``AsTwigFilter``: ``needsCharset``, ``needsEnvironment``, ``needsContext``, ``isSafe``, ``isSafeCallback``, ``preEscape``, ``preservesSafety``, ``deprecationInfo``
* ``AsTwigFunction``: ``needsCharset``, ``needsEnvironment``, ``needsContext``, ``isSafe``, ``isSafeCallback``, ``deprecationInfo``
* ``AsTwigTest``: ``needsCharset``, ``needsEnvironment``, ``needsContext``, ``deprecationInfo``
* ``AsTwigFilter``: ``name``, ``needsCharset``, ``needsEnvironment``, ``needsContext``, ``isSafe``, ``isSafeCallback``, ``preEscape``, ``preservesSafety``, ``deprecationInfo``
* ``AsTwigFunction``: ``name``, ``needsCharset``, ``needsEnvironment``, ``needsContext``, ``isSafe``, ``isSafeCallback``, ``deprecationInfo``
* ``AsTwigTest``: ``name``, ``needsCharset``, ``needsEnvironment``, ``needsContext``, ``deprecationInfo``

Definition vs Runtime
~~~~~~~~~~~~~~~~~~~~~
Expand Down
4 changes: 2 additions & 2 deletions src/Attribute/AsTwigFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
final class AsTwigFilter
{
/**
* @param non-empty-string $name The name of the filter in Twig.
* @param non-empty-string|null $name The name of the filter in Twig. By default, the name of the PHP function is used.
* @param bool|null $needsCharset Whether the filter needs the charset passed as the first argument.
* @param bool|null $needsEnvironment Whether the filter needs the environment passed as the first argument, or after the charset.
* @param bool|null $needsContext Whether the filter needs the context array passed as the first argument, or after the charset and the environment.
Expand All @@ -43,7 +43,7 @@ final class AsTwigFilter
* @param DeprecatedCallableInfo|null $deprecationInfo Information about the deprecation
*/
public function __construct(
public string $name,
public ?string $name = null,
public ?bool $needsCharset = null,
public ?bool $needsEnvironment = null,
public ?bool $needsContext = null,
Expand Down
4 changes: 2 additions & 2 deletions src/Attribute/AsTwigFunction.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
final class AsTwigFunction
{
/**
* @param non-empty-string $name The name of the function in Twig.
* @param non-empty-string|null $name The name of the function in Twig. By default, the name of the PHP function is used.
* @param bool|null $needsCharset Whether the function needs the charset passed as the first argument.
* @param bool|null $needsEnvironment Whether the function needs the environment passed as the first argument, or after the charset.
* @param bool|null $needsContext Whether the function needs the context array passed as the first argument, or after the charset and the environment.
Expand All @@ -41,7 +41,7 @@ final class AsTwigFunction
* @param DeprecatedCallableInfo|null $deprecationInfo Information about the deprecation
*/
public function __construct(
public string $name,
public ?string $name = null,
public ?bool $needsCharset = null,
public ?bool $needsEnvironment = null,
public ?bool $needsContext = null,
Expand Down
4 changes: 2 additions & 2 deletions src/Attribute/AsTwigTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@
final class AsTwigTest
{
/**
* @param non-empty-string $name The name of the test in Twig.
* @param non-empty-string|null $name The name of the test in Twig. By default, the name of the PHP function is used.
* @param bool|null $needsCharset Whether the test needs the charset passed as the first argument.
* @param bool|null $needsEnvironment Whether the test needs the environment passed as the first argument, or after the charset.
* @param bool|null $needsContext Whether the test needs the context array passed as the first argument, or after the charset and the environment.
* @param DeprecatedCallableInfo|null $deprecationInfo Information about the deprecation
*/
public function __construct(
public string $name,
public ?string $name = null,
public ?bool $needsCharset = null,
public ?bool $needsEnvironment = null,
public ?bool $needsContext = null,
Expand Down
15 changes: 9 additions & 6 deletions src/Extension/AttributeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,9 @@ private function initFromAttributes(): void
foreach ($method->getAttributes(AsTwigFilter::class) as $reflectionAttribute) {
/** @var AsTwigFilter $attribute */
$attribute = $reflectionAttribute->newInstance();
$name = $attribute->name ?? $method->getName();

$callable = new TwigFilter($attribute->name, [$this->class, $method->getName()], [
$callable = new TwigFilter($name, [$this->class, $method->getName()], [
'needs_context' => $attribute->needsContext ?? false,
'needs_environment' => $attribute->needsEnvironment ?? $this->needsEnvironment($method),
'needs_charset' => $attribute->needsCharset ?? false,
Expand All @@ -107,14 +108,15 @@ private function initFromAttributes(): void
throw new \LogicException(sprintf('"%s::%s()" needs at least %d arguments to be used AsTwigFilter, but only %d defined.', $reflectionClass->getName(), $method->getName(), $callable->getMinimalNumberOfRequiredArguments(), $method->getNumberOfParameters()));
}

$filters[$attribute->name] = $callable;
$filters[$name] = $callable;
}

foreach ($method->getAttributes(AsTwigFunction::class) as $reflectionAttribute) {
/** @var AsTwigFunction $attribute */
$attribute = $reflectionAttribute->newInstance();
$name = $attribute->name ?? $method->getName();

$callable = new TwigFunction($attribute->name, [$this->class, $method->getName()], [
$callable = new TwigFunction($name, [$this->class, $method->getName()], [
'needs_context' => $attribute->needsContext ?? false,
'needs_environment' => $attribute->needsEnvironment ?? $this->needsEnvironment($method),
'needs_charset' => $attribute->needsCharset ?? false,
Expand All @@ -128,15 +130,16 @@ private function initFromAttributes(): void
throw new \LogicException(sprintf('"%s::%s()" needs at least %d arguments to be used AsTwigFunction, but only %d defined.', $reflectionClass->getName(), $method->getName(), $callable->getMinimalNumberOfRequiredArguments(), $method->getNumberOfParameters()));
}

$functions[$attribute->name] = $callable;
$functions[$name] = $callable;
}

foreach ($method->getAttributes(AsTwigTest::class) as $reflectionAttribute) {

/** @var AsTwigTest $attribute */
$attribute = $reflectionAttribute->newInstance();
$name = $attribute->name ?? $method->getName();

$callable = new TwigTest($attribute->name, [$this->class, $method->getName()], [
$callable = new TwigTest($name, [$this->class, $method->getName()], [
'needs_context' => $attribute->needsContext ?? false,
'needs_environment' => $attribute->needsEnvironment ?? $this->needsEnvironment($method),
'needs_charset' => $attribute->needsCharset ?? false,
Expand All @@ -148,7 +151,7 @@ private function initFromAttributes(): void
throw new \LogicException(sprintf('"%s::%s()" needs at least %d arguments to be used AsTwigTest, but only %d defined.', $reflectionClass->getName(), $method->getName(), $callable->getMinimalNumberOfRequiredArguments(), $method->getNumberOfParameters()));
}

$tests[$attribute->name] = $callable;
$tests[$name] = $callable;
}
}

Expand Down
8 changes: 4 additions & 4 deletions tests/Extension/AttributeExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public function testFilter(string $name, string $method, array $options)

public static function provideFilters()
{
yield 'with name' => ['foo', 'fooFilter', ['is_safe' => ['html']]];
yield 'default name' => ['fooFilter', 'fooFilter', ['is_safe' => ['html']]];
yield 'with env' => ['with_env_filter', 'withEnvFilter', ['needs_environment' => true]];
yield 'with context' => ['with_context_filter', 'withContextFilter', ['needs_context' => true]];
yield 'with env and context' => ['with_env_and_context_filter', 'withEnvAndContextFilter', ['needs_environment' => true, 'needs_context' => true]];
Expand Down Expand Up @@ -63,7 +63,7 @@ public function testFunction(string $name, string $method, array $options)

public static function provideFunctions()
{
yield 'with name' => ['foo', 'fooFunction', ['is_safe' => ['html']]];
yield 'default name' => ['fooFunction', 'fooFunction', ['is_safe' => ['html']]];
yield 'with env' => ['with_env_function', 'withEnvFunction', ['needs_environment' => true]];
yield 'with context' => ['with_context_function', 'withContextFunction', ['needs_context' => true]];
yield 'with env and context' => ['with_env_and_context_function', 'withEnvAndContextFunction', ['needs_environment' => true, 'needs_context' => true]];
Expand Down Expand Up @@ -91,7 +91,7 @@ public function testTest(string $name, string $method, array $options)

public static function provideTests()
{
yield 'with name' => ['foo', 'fooTest', []];
yield 'default name' => ['fooTest', 'fooTest', []];
yield 'with env' => ['with_env_test', 'withEnvTest', ['needs_environment' => true]];
yield 'with context' => ['with_context_test', 'withContextTest', ['needs_context' => true]];
yield 'with env and context' => ['with_env_and_context_test', 'withEnvAndContextTest', ['needs_environment' => true, 'needs_context' => true]];
Expand Down Expand Up @@ -148,7 +148,7 @@ public function testMultipleRegistrations()
$extensionSet->addExtension($extension2 = new AttributeExtension(\stdClass::class));

$this->assertCount(2, $extensionSet->getExtensions());
$this->assertNotNull($extensionSet->getFilter('foo'));
$this->assertNotNull($extensionSet->getFilter('fooFilter'));

$this->assertSame($extension1, $extensionSet->getExtension(ExtensionWithAttributes::class));
$this->assertSame($extension2, $extensionSet->getExtension(\stdClass::class));
Expand Down
6 changes: 3 additions & 3 deletions tests/Extension/Fixtures/ExtensionWithAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

class ExtensionWithAttributes
{
#[AsTwigFilter(name: 'foo', isSafe: ['html'])]
#[AsTwigFilter(isSafe: ['html'])]
public function fooFilter(string|int $string)
{
}
Expand Down Expand Up @@ -45,7 +45,7 @@ public function patternFilter(string $string)
{
}

#[AsTwigFunction(name: 'foo', isSafe: ['html'])]
#[AsTwigFunction(isSafe: ['html'])]
public function fooFunction(string|int $string)
{
}
Expand Down Expand Up @@ -80,7 +80,7 @@ public function deprecatedFunction(string $string)
{
}

#[AsTwigTest(name: 'foo')]
#[AsTwigTest]
public function fooTest(string|int $value)
{
}
Expand Down

0 comments on commit 633ccfc

Please sign in to comment.