Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit170b631

Browse files
minor#60415 [TwigBundle] Improve error when autoconfiguring a class with bothExtensionInterface and Twig callable attribute (GromNaN)
This PR was merged into the 7.3 branch.Discussion----------[TwigBundle] Improve error when autoconfiguring a class with both `ExtensionInterface` and Twig callable attribute| Q | A| ------------- | ---| Branch? | 7.3| Bug fix? | no| New feature? | no| Deprecations? | no| Issues | -| License | MITReported by Javier:> I'm updating Twig extensions to use the `#[AsTwig...]` attributes. I removed the `getFunctions()` method and had this:> ```> class FooExtension extends AbstractExtension> {> #[AsTwigFunction('name_of_function')]> public function foo(): string> {> // ...> }> }> ```> Then I saw this exception: `Unable to register extension "App\Twig\FooExtension" as it is already registered.`> My error is that I forgot to remove extends `AbstractExtension`But I think that Symfony's error exception should be more helpful. A quick example of something that could've helped me: *"When using the AsTwigFunction attribute, your Twig extension cannot extend AbstractExtension"*The ExtensionSet exception is thrown because the same an extension is registered twice:1. It has the `twig.extension` tag autoconfigured because it implements `Twig\Extension\ExtensionInterface`2. An `AttributeExtension` is registered for this class because it as one of the extension attributes (since#52748)Previous exception when `twig` service is instanciated:> LogicException : Unable to register extension "Symfony\Bundle\TwigBundle\Tests\Functional\InvalidExtensionWithAttributes" as it is already registered.New exception during container compilation:> Symfony\Component\DependencyInjection\Exception\LogicException : The class "Symfony\Bundle\TwigBundle\Tests\Functional\InvalidExtensionWithAttributes" cannot both extend "Twig\Extension\AbstractExtension" and use the "#[Twig\Attribute\AsTwigFilter]" attribute on method "funFilter()", choose one or the other.Checking `AbstractExtension` makes the error message more specific to the code, as most extensions extend this class and doesn't implement the interface directly.Commits-------752b41d [TwigBundle] Improve error when autoconfiguring a class with both ExtensionInterface and Twig callable attribute
2 parentse67b362 +752b41d commit170b631

File tree

2 files changed

+72
-15
lines changed

2 files changed

+72
-15
lines changed

‎src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/AttributeExtensionPass.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,13 @@
1414
useSymfony\Component\DependencyInjection\ChildDefinition;
1515
useSymfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
1616
useSymfony\Component\DependencyInjection\ContainerBuilder;
17+
useSymfony\Component\DependencyInjection\Exception\LogicException;
1718
useTwig\Attribute\AsTwigFilter;
1819
useTwig\Attribute\AsTwigFunction;
1920
useTwig\Attribute\AsTwigTest;
21+
useTwig\Extension\AbstractExtension;
2022
useTwig\Extension\AttributeExtension;
23+
useTwig\Extension\ExtensionInterface;
2124

2225
/**
2326
* Register an instance of AttributeExtension for each service using the
@@ -33,6 +36,14 @@ final class AttributeExtensionPass implements CompilerPassInterface
3336

3437
publicstaticfunctionautoconfigureFromAttribute(ChildDefinition$definition,AsTwigFilter|AsTwigFunction|AsTwigTest$attribute,\ReflectionMethod$reflector):void
3538
{
39+
$class =$reflector->getDeclaringClass();
40+
if ($class->implementsInterface(ExtensionInterface::class)) {
41+
if ($class->isSubclassOf(AbstractExtension::class)) {
42+
thrownewLogicException(\sprintf('The class "%s" cannot extend "%s" and use the "#[%s]" attribute on method "%s()", choose one or the other.',$class->name, AbstractExtension::class,$attribute::class,$reflector->name));
43+
}
44+
thrownewLogicException(\sprintf('The class "%s" cannot implement "%s" and use the "#[%s]" attribute on method "%s()", choose one or the other.',$class->name, ExtensionInterface::class,$attribute::class,$reflector->name));
45+
}
46+
3647
$definition->addTag(self::TAG);
3748

3849
// The service must be tagged as a runtime to call non-static methods

‎src/Symfony/Bundle/TwigBundle/Tests/Functional/AttributeExtensionTest.php

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,35 +11,39 @@
1111

1212
namespaceSymfony\Bundle\TwigBundle\Tests\Functional;
1313

14+
usePHPUnit\Framework\Attributes\After;
15+
usePHPUnit\Framework\Attributes\Before;
16+
usePHPUnit\Framework\Attributes\BeforeClass;
1417
useSymfony\Bundle\FrameworkBundle\FrameworkBundle;
1518
useSymfony\Bundle\TwigBundle\Tests\TestCase;
1619
useSymfony\Bundle\TwigBundle\TwigBundle;
1720
useSymfony\Component\Config\Loader\LoaderInterface;
1821
useSymfony\Component\DependencyInjection\ContainerBuilder;
22+
useSymfony\Component\DependencyInjection\Exception\LogicException;
1923
useSymfony\Component\Filesystem\Filesystem;
2024
useSymfony\Component\HttpKernel\Kernel;
2125
useTwig\Attribute\AsTwigFilter;
2226
useTwig\Attribute\AsTwigFunction;
2327
useTwig\Attribute\AsTwigTest;
2428
useTwig\Environment;
2529
useTwig\Error\RuntimeError;
30+
useTwig\Extension\AbstractExtension;
2631
useTwig\Extension\AttributeExtension;
2732

2833
class AttributeExtensionTestextends TestCase
2934
{
30-
publicfunctiontestExtensionWithAttributes()
35+
/** @beforeClass */
36+
#[BeforeClass]
37+
publicstaticfunctionassertTwigVersion():void
3138
{
3239
if (!class_exists(AttributeExtension::class)) {
3340
self::markTestSkipped('Twig 3.21 is required.');
3441
}
42+
}
3543

36-
$kernel =newclass('test',true)extends Kernel
37-
{
38-
publicfunctionregisterBundles():iterable
39-
{
40-
return [newFrameworkBundle(),newTwigBundle()];
41-
}
42-
44+
publicfunctiontestExtensionWithAttributes()
45+
{
46+
$kernel =newclassextends AttributeExtensionKernel {
4347
publicfunctionregisterContainerConfiguration(LoaderInterface$loader):void
4448
{
4549
$loader->load(staticfunction (ContainerBuilder$container) {
@@ -53,11 +57,6 @@ public function registerContainerConfiguration(LoaderInterface $loader): void
5357
$container->setAlias('twig_test','twig')->setPublic(true);
5458
});
5559
}
56-
57-
publicfunctiongetProjectDir():string
58-
{
59-
returnsys_get_temp_dir().'/'.Kernel::VERSION.'/AttributeExtension';
60-
}
6160
};
6261

6362
$kernel->boot();
@@ -73,10 +72,30 @@ public function getProjectDir(): string
7372
$twig->getRuntime(StaticExtensionWithAttributes::class);
7473
}
7574

75+
publicfunctiontestInvalidExtensionClass()
76+
{
77+
$kernel =newclassextends AttributeExtensionKernel {
78+
publicfunctionregisterContainerConfiguration(LoaderInterface$loader):void
79+
{
80+
$loader->load(staticfunction (ContainerBuilder$container) {
81+
$container->register(InvalidExtensionWithAttributes::class, InvalidExtensionWithAttributes::class)
82+
->setAutoconfigured(true);
83+
});
84+
}
85+
};
86+
87+
$this->expectException(LogicException::class);
88+
$this->expectExceptionMessage('The class "Symfony\Bundle\TwigBundle\Tests\Functional\InvalidExtensionWithAttributes" cannot extend "Twig\Extension\AbstractExtension" and use the "#[Twig\Attribute\AsTwigFilter]" attribute on method "funFilter()", choose one or the other.');
89+
90+
$kernel->boot();
91+
}
92+
93+
7694
/**
7795
* @before
7896
* @after
7997
*/
98+
#[Before, After]
8099
protectedfunctiondeleteTempDir()
81100
{
82101
if (file_exists($dir =sys_get_temp_dir().'/'.Kernel::VERSION.'/AttributeExtension')) {
@@ -85,6 +104,24 @@ protected function deleteTempDir()
85104
}
86105
}
87106

107+
abstractclass AttributeExtensionKernelextends Kernel
108+
{
109+
publicfunction__construct()
110+
{
111+
parent::__construct('test',true);
112+
}
113+
114+
publicfunctionregisterBundles():iterable
115+
{
116+
return [newFrameworkBundle(),newTwigBundle()];
117+
}
118+
119+
publicfunctiongetProjectDir():string
120+
{
121+
returnsys_get_temp_dir().'/'.Kernel::VERSION.'/AttributeExtension';
122+
}
123+
}
124+
88125
class StaticExtensionWithAttributes
89126
{
90127
#[AsTwigFilter('foo')]
@@ -112,10 +149,19 @@ public function __construct(private bool $prefix)
112149
{
113150
}
114151

115-
#[AsTwigFilter('foo')]
116-
#[AsTwigFunction('foo')]
152+
#[AsTwigFilter('prefix_foo')]
153+
#[AsTwigFunction('prefix_foo')]
117154
publicfunctionprefix(string$value):string
118155
{
119156
return$this->prefix.$value;
120157
}
121158
}
159+
160+
class InvalidExtensionWithAttributesextends AbstractExtension
161+
{
162+
#[AsTwigFilter('fun')]
163+
publicfunctionfunFilter():string
164+
{
165+
return'fun';
166+
}
167+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp