Skip to content

Commit 86a6980

Browse files
committed
Merge branch '2.x' into 3.x
* 2.x: Allow using directory name as component name for anonymous components
2 parents 30064ea + c756147 commit 86a6980

File tree

9 files changed

+71
-0
lines changed

9 files changed

+71
-0
lines changed

src/TwigComponent/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
- Add option `profiler.collect_components` to control component data collection
1919
in the profiler (enabled in debug mode by default)
20+
- Add support for using directory name as component name for anonymous components
2021

2122
## 2.30
2223

src/TwigComponent/doc/index.rst

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,43 @@ the subdirectory:
676676
{# renders as: #}
677677
<button class="primary">Click Me!</button>
678678

679+
If your anonymous component lives in a directory with the same name, you can
680+
name the component file ``index.html.twig`` to avoid repetition:
681+
682+
.. code-block:: html+twig
683+
684+
{# templates/components/Menu/index.html.twig #}
685+
<nav {{ attributes.defaults({class: 'menu'}) }}>
686+
<ul>
687+
{% block content %}{% endblock %}
688+
</ul>
689+
</nav>
690+
691+
.. code-block:: html+twig
692+
693+
{# templates/components/Menu/Item.html.twig #}
694+
{% props href, label %}
695+
<li {{ attributes.defaults({class: 'menu__item'}) }}>
696+
<a href="{{ href }}">{% block content %}{{ label }}{% endblock %}</a>
697+
</li>
698+
699+
.. code-block:: html+twig
700+
701+
{# index.html.twig #}
702+
...
703+
<twig:Menu>
704+
<twig:Menu:Item href="/">Home</twig:Menu:Item>
705+
<twig:Menu:Item href="/about">About</twig:Menu:Item>
706+
</twig:Menu>
707+
708+
{# renders as: #}
709+
<nav class="menu">
710+
<ul>
711+
<li class="menu__item"><a href="/">Home</a></li>
712+
<li class="menu__item"><a href="/about">About</a></li>
713+
</ul>
714+
</nav>
715+
679716
Like normal, you can pass extra attributes that will be rendered on the element:
680717

681718
.. code-block:: html+twig

src/TwigComponent/src/ComponentTemplateFinder.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ public function findAnonymousComponentTemplate(string $name): ?string
3333
return $template;
3434
}
3535

36+
$template = rtrim($this->directory, '/').'/'.$componentPath.'/index.html.twig';
37+
if ($loader->exists($template)) {
38+
return $template;
39+
}
40+
3641
$parts = explode('/', $componentPath, 2);
3742
if (\count($parts) < 2) {
3843
return null;

src/TwigComponent/tests/Fixtures/templates/anonymous/Bar.html.twig

Whitespace-only changes.

src/TwigComponent/tests/Fixtures/templates/anonymous/Bar/index.html.twig

Whitespace-only changes.

src/TwigComponent/tests/Fixtures/templates/anonymous/Menu/Item.html.twig

Whitespace-only changes.

src/TwigComponent/tests/Fixtures/templates/anonymous/Menu/index.html.twig

Whitespace-only changes.

src/TwigComponent/tests/Integration/ComponentFactoryTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,29 @@ public function testLoadingAnonymousComponentFromBundle()
149149
$this->assertNull($metadata->get('class'));
150150
}
151151

152+
public function testLoadingAnonymousComponentWithFallback()
153+
{
154+
self::bootKernel(['environment' => 'anonymous_directory']);
155+
156+
$metadata = $this->factory()->metadataFor('Menu');
157+
158+
$this->assertSame('anonymous/Menu/index.html.twig', $metadata->getTemplate());
159+
$this->assertSame('Menu', $metadata->getName());
160+
$this->assertNull($metadata->get('class'));
161+
162+
$metadata = $this->factory()->metadataFor('Menu:Item');
163+
164+
$this->assertSame('anonymous/Menu/Item.html.twig', $metadata->getTemplate());
165+
$this->assertSame('Menu:Item', $metadata->getName());
166+
$this->assertNull($metadata->get('class'));
167+
168+
// Ensure anonymous/Bar.html.twig takes precedence over anonymous/Bar/index.html.twig
169+
$metadata = $this->factory()->metadataFor('Bar');
170+
$this->assertSame('anonymous/Bar.html.twig', $metadata->getTemplate());
171+
$this->assertSame('Bar', $metadata->getName());
172+
$this->assertNull($metadata->get('class'));
173+
}
174+
152175
public function testAutoNamingInSubDirectory()
153176
{
154177
$metadata = $this->factory()->metadataFor('SubDirectory:ComponentInSubDirectory');

src/TwigComponent/tests/Unit/ComponentTemplateFinderTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,18 @@ public function testFindTemplateWithinDirectory()
5353
'foo/bar.html.twig',
5454
'bar/foo/bar.html.twig',
5555
'foo/foo/bar.html.twig',
56+
'foo/qux/index.html.twig',
57+
'foo/foo/baz/index.html.twig',
5658
];
5759
$loader = $this->createLoader($templates);
5860
$finder = new ComponentTemplateFinder($loader, 'foo');
5961

6062
$this->assertEquals('foo/bar.html.twig', $finder->findAnonymousComponentTemplate('bar'));
6163
$this->assertEquals('foo/foo/bar.html.twig', $finder->findAnonymousComponentTemplate('foo:bar'));
6264
$this->assertEquals('foo/foo/bar.html.twig', $finder->findAnonymousComponentTemplate('foo:bar'));
65+
66+
$this->assertEquals('foo/qux/index.html.twig', $finder->findAnonymousComponentTemplate('qux'));
67+
$this->assertEquals('foo/foo/baz/index.html.twig', $finder->findAnonymousComponentTemplate('foo:baz'));
6368
}
6469

6570
private function createLoader(array $templates): LoaderInterface

0 commit comments

Comments
 (0)