Skip to content

Commit d3d95b0

Browse files
committed
Adding an exception in case of a conflict
1 parent 84ac827 commit d3d95b0

File tree

4 files changed

+33
-1
lines changed

4 files changed

+33
-1
lines changed

src/TwigComponent/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
- `true` attribute values now render just the attribute name, `false` excludes it entirely.
66

7+
- The first argument to ``AsTwigComponent`` is now optional and defaults to the class name.
8+
79
## 2.7.0
810

911
- `PreMount` and `PostMount` hooks can now return nothing.

src/TwigComponent/src/DependencyInjection/Compiler/TwigComponentPass.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
1515
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
1616
use Symfony\Component\DependencyInjection\ContainerBuilder;
17+
use Symfony\Component\DependencyInjection\Exception\LogicException;
1718
use Symfony\Component\DependencyInjection\Reference;
1819

1920
/**
@@ -28,6 +29,7 @@ public function process(ContainerBuilder $container): void
2829
$componentConfig = [];
2930

3031
$componentReferences = [];
32+
$componentNames = [];
3133
foreach ($container->findTaggedServiceIds('twig.component') as $id => $tags) {
3234
$definition = $container->findDefinition($id);
3335

@@ -37,14 +39,19 @@ public function process(ContainerBuilder $container): void
3739
foreach ($tags as $tag) {
3840
if (!\array_key_exists('key', $tag)) {
3941
$fqcn = $definition->getClass();
40-
$tag['key'] = substr($fqcn, strrpos($fqcn, '\\') + 1);
42+
$name = substr($fqcn, strrpos($fqcn, '\\') + 1);
43+
if (\in_array($name, $componentNames, true)) {
44+
throw new LogicException(sprintf('Failed creating the "%s" component with the automatic name "%s": another component already has this name. To fix this, give the component an explicit name (hint: using "%s" will override the existing component).', $fqcn, $name, $name));
45+
}
46+
$tag['key'] = $name;
4147
}
4248

4349
$tag['service_id'] = $id;
4450
$tag['class'] = $definition->getClass();
4551
$tag['template'] = $tag['template'] ?? sprintf('components/%s.html.twig', str_replace(':', '/', $tag['key']));
4652
$componentConfig[$tag['key']] = $tag;
4753
$componentReferences[$tag['key']] = new Reference($id);
54+
$componentNames[] = $tag['key'];
4855
}
4956
}
5057

src/TwigComponent/tests/Fixtures/Kernel.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,17 @@ protected function configureContainer(ContainerConfigurator $c): void
6363
->tag('twig.component')
6464
;
6565
}
66+
67+
if ('missing_key_with_collision' === $this->environment) {
68+
$services->set('component_b_1', ComponentB::class)
69+
->tag('twig.component', [
70+
'key' => 'ComponentB',
71+
])
72+
;
73+
// this will try to reuse the same ComponentB name
74+
$services->set('component_b_2', ComponentB::class)
75+
->tag('twig.component')
76+
;
77+
}
6678
}
6779
}

src/TwigComponent/tests/Integration/ComponentFactoryTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\UX\TwigComponent\Tests\Integration;
1313

1414
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
15+
use Symfony\Component\DependencyInjection\Exception\LogicException;
1516
use Symfony\UX\TwigComponent\ComponentFactory;
1617
use Symfony\UX\TwigComponent\Tests\Fixtures\Component\ComponentA;
1718
use Symfony\UX\TwigComponent\Tests\Fixtures\Component\ComponentB;
@@ -117,6 +118,16 @@ public function testTwigComponentServiceTagWithoutKeyUsesShortClassName(): void
117118
self::assertInstanceOf(ComponentB::class, $component);
118119
}
119120

121+
public function testTwigComponentServiceTagWithoutKeyButCollissionCausesAnException(): void
122+
{
123+
$this->expectException(LogicException::class);
124+
$this->expectExceptionMessage('Failed creating the "Symfony\UX\TwigComponent\Tests\Fixtures\Component\ComponentB" component with the automatic name "ComponentB": another component already has this name. To fix this, give the component an explicit name (hint: using "ComponentB" will override the existing component).');
125+
126+
self::bootKernel(['environment' => 'missing_key_with_collision']);
127+
$component = $this->createComponent('ComponentB');
128+
self::assertInstanceOf(ComponentB::class, $component);
129+
}
130+
120131
public function testCanGetMetadataForComponentByName(): void
121132
{
122133
$metadata = $this->factory()->metadataFor('component_a');

0 commit comments

Comments
 (0)