Skip to content

Commit 963bc37

Browse files
committed
Add directory options
1 parent dd1121f commit 963bc37

File tree

4 files changed

+122
-39
lines changed

4 files changed

+122
-39
lines changed

src/TwigComponent/src/Command/ComponentDebugCommand.php

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,19 @@
1616
use Symfony\Component\Console\Helper\Table;
1717
use Symfony\Component\Console\Input\InputArgument;
1818
use Symfony\Component\Console\Input\InputInterface;
19+
use Symfony\Component\Console\Input\InputOption;
1920
use Symfony\Component\Console\Output\OutputInterface;
2021
use Symfony\Component\Console\Style\SymfonyStyle;
2122
use Symfony\Component\Finder\Finder;
22-
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
2323
use Symfony\UX\LiveComponent\Attribute\LiveAction;
2424
use Symfony\UX\LiveComponent\Attribute\LiveProp;
25-
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
2625
use Symfony\UX\TwigComponent\Attribute\PostMount;
2726
use Symfony\UX\TwigComponent\Attribute\PreMount;
2827
use Symfony\UX\TwigComponent\ComponentFactory;
2928
use Symfony\UX\TwigComponent\Twig\PropsNode;
3029
use Twig\Environment;
3130

32-
#[AsCommand(name: 'debug:component', description: 'Display current components and them usages for an application')]
31+
#[AsCommand(name: 'debug:twig-component', description: 'Display current components and them usages for an application')]
3332
class ComponentDebugCommand extends Command
3433
{
3534
public function __construct(private string $twigTemplatesPath, private ComponentFactory $componentFactory, private Environment $twigEnvironment, private iterable $components)
@@ -42,11 +41,16 @@ protected function configure(): void
4241
$this
4342
->setDefinition([
4443
new InputArgument('name', InputArgument::OPTIONAL, 'A component name'),
44+
new InputOption('dir', null, InputOption::VALUE_REQUIRED, 'Show all components with a specific directory in templates', 'components'),
4545
])
4646
->setHelp(<<<'EOF'
4747
The <info>%command.name%</info> display current components and them usages for an application:
4848
49-
<info>php %command.full_name%</info>
49+
<info>php %command.full_name%</info>
50+
51+
Find all components with a specific directory in templates by specifying the directory name with the <info>--dir</info> option:
52+
53+
<info>php %command.full_name% --dir=bar/foo</info>
5054

5155
EOF
5256
)
@@ -57,6 +61,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
5761
{
5862
$io = new SymfonyStyle($input, $output);
5963
$name = $input->getArgument('name');
64+
$componentsDir = $input->getOption('dir');
6065

6166
if (null !== $name) {
6267
try {
@@ -199,38 +204,34 @@ protected function execute(InputInterface $input, OutputInterface $output): int
199204
$attributes = $reflectionClass->getAttributes();
200205

201206
foreach ($attributes as $attribute) {
202-
$attributeName = $attribute->getName();
203-
204-
if (\in_array($attributeName, [AsTwigComponent::class, AsLiveComponent::class])) {
205-
$arguments = $attribute->getArguments();
206-
207-
$name = $arguments['name'] ?? $arguments[0] ?? null;
208-
$template = $arguments['template'] ?? $arguments[1] ?? null;
209-
210-
if (null !== $template || null !== $name) {
211-
if (null !== $template && null !== $name) {
212-
$templateFile = str_replace('components/', '', $template);
213-
$metadata = $this->componentFactory->metadataFor($name);
214-
} elseif (null !== $name) {
215-
$templateFile = str_replace(':', '/', "{$name}.html.twig");
216-
$metadata = $this->componentFactory->metadataFor($name);
217-
} else {
218-
$templateFile = str_replace('components/', '', $template);
219-
$metadata = $this->componentFactory->metadataFor(str_replace('.html.twig', '', $templateFile));
220-
}
207+
$arguments = $attribute->getArguments();
208+
209+
$name = $arguments['name'] ?? $arguments[0] ?? null;
210+
$template = $arguments['template'] ?? $arguments[1] ?? null;
211+
212+
if (null !== $template || null !== $name) {
213+
if (null !== $template && null !== $name) {
214+
$templateFile = str_replace('components/', '', $template);
215+
$metadata = $this->componentFactory->metadataFor($name);
216+
} elseif (null !== $name) {
217+
$templateFile = str_replace(':', '/', "{$name}.html.twig");
218+
$metadata = $this->componentFactory->metadataFor($name);
221219
} else {
222-
$templateFile = "{$reflectionClass->getShortName()}.html.twig";
223-
$metadata = $this->componentFactory->metadataFor($reflectionClass->getShortName());
220+
$templateFile = str_replace('components/', '', $template);
221+
$metadata = $this->componentFactory->metadataFor(str_replace('.html.twig', '', $templateFile));
224222
}
223+
} else {
224+
$templateFile = "{$reflectionClass->getShortName()}.html.twig";
225+
$metadata = $this->componentFactory->metadataFor($reflectionClass->getShortName());
226+
}
225227

226-
$componentsWithClass[] = [
227-
'name' => $metadata->getName(),
228-
'type' => substr($attributeName, strrpos($attributeName, '\\') + 1),
229-
];
228+
$componentsWithClass[] = [
229+
'name' => $metadata->getName(),
230+
'type' => null !== $metadata->get('live') ? 'AsLiveComponent' : 'AsTwigComponent',
231+
];
230232

231-
if (($key = array_search($templateFile, $anonymousTemplatesComponents)) !== false) {
232-
unset($anonymousTemplatesComponents[$key]);
233-
}
233+
if (($key = array_search($templateFile, $anonymousTemplatesComponents)) !== false) {
234+
unset($anonymousTemplatesComponents[$key]);
234235
}
235236
}
236237
}
@@ -245,12 +246,14 @@ protected function execute(InputInterface $input, OutputInterface $output): int
245246
foreach ($allComponents as $component) {
246247
$metadata = $this->componentFactory->metadataFor($component['name']);
247248

248-
$dataToRender[] = [
249-
$metadata->getName(),
250-
$metadata->get('class') ?? 'Anonymous component',
251-
$metadata->getTemplate(),
252-
$component['type'],
253-
];
249+
if (str_contains($metadata->getTemplate(), $componentsDir)) {
250+
$dataToRender[] = [
251+
$metadata->getName(),
252+
$metadata->get('class') ?? 'Anonymous component',
253+
$metadata->getTemplate(),
254+
$component['type'],
255+
];
256+
}
254257
}
255258

256259
$table = new Table($output);
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\UX\TwigComponent\Tests\Fixtures\Component;
13+
14+
use Symfony\Component\OptionsResolver\OptionsResolver;
15+
use Symfony\UX\TwigComponent\Attribute\AsTwigComponent;
16+
use Symfony\UX\TwigComponent\Attribute\PreMount;
17+
18+
#[AsTwigComponent(name: 'OtherDirectory', template: 'bar/OtherDirectory.html.twig')]
19+
class OtherDirectory
20+
{
21+
public string $type = 'success';
22+
public string $message;
23+
24+
public function mount(bool $isSuccess = true)
25+
{
26+
$this->type = $isSuccess ? 'success' : 'danger';
27+
}
28+
29+
#[PreMount]
30+
public function preMount(array $data): array
31+
{
32+
// validate data
33+
$resolver = new OptionsResolver();
34+
$resolver->setDefaults(['type' => 'success']);
35+
$resolver->setAllowedValues('type', ['success', 'danger']);
36+
$resolver->setRequired('message');
37+
$resolver->setAllowedTypes('message', 'string');
38+
39+
return $resolver->resolve($data);
40+
}
41+
42+
public function getIconClass(): string
43+
{
44+
return match ($this->type) {
45+
'success' => 'fa fa-circle-check',
46+
'danger' => 'fa fa-circle-exclamation',
47+
};
48+
}
49+
50+
public function getPackageCount(): int
51+
{
52+
return 10;
53+
}
54+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<div class="alert alert-{{ type }} alert-dismissible" role="alert">
2+
<span class="me-2 {{ this.iconClass }}"></span>
3+
{{ message }}
4+
{% if type == 'success' %}
5+
<a href="#" class="alert-right-message">
6+
(browse all {{ this.packageCount }} packages)
7+
</a>
8+
{% endif %}
9+
</div>

src/TwigComponent/tests/Unit/Command/ComponentDebugCommandTest.php

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ public function testComponentWithClassPropertiesAndCustomName(): void
7171
$this->assertStringContainsString('$propA', $display);
7272
$this->assertStringContainsString('$propB', $display);
7373
$this->assertStringContainsString('$propC', $display);
74+
$this->assertStringContainsString('Mount', $display);
7475
}
7576

7677
public function testComponentWithClassPropertiesCustomNameAndCustomTemplate(): void
@@ -107,17 +108,33 @@ public function testWithAnonymousComponent(): void
107108
$this->assertStringContainsString('primary = true', $display);
108109
}
109110

111+
public function testWithDirectoryOption()
112+
{
113+
$commandTester = $this->createCommandTester();
114+
$commandTester->execute(['--dir' => 'bar']);
115+
116+
$commandTester->assertCommandIsSuccessful();
117+
118+
$display = $commandTester->getDisplay();
119+
120+
$this->assertStringContainsString('foo:bar:baz', $display);
121+
$this->assertStringContainsString('OtherDirectory', $display);
122+
$this->assertStringContainsString('components/foo/bar/baz.html.twig', $display);
123+
$this->assertStringContainsString('bar/OtherDirectory.html.twig', $display);
124+
}
125+
110126
private function createCommandTester(): CommandTester
111127
{
112128
$kernel = self::bootKernel();
113129
$application = new Application($kernel);
114130

115-
return new CommandTester($application->find('debug:component'));
131+
return new CommandTester($application->find('debug:twig-component'));
116132
}
117133

118134
private function tableDisplayCheck(string $display): void
119135
{
120136
$this->assertStringContainsString('Component', $display);
137+
$this->assertStringContainsString('Type', $display);
121138
$this->assertStringContainsString('Class', $display);
122139
$this->assertStringContainsString('Template', $display);
123140
$this->assertStringContainsString('Properties', $display);

0 commit comments

Comments
 (0)