From d404ff5a1941fcf05a8193a14f3b3bb865e7e6d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20L=C3=A9pine?= Date: Sun, 2 Feb 2025 08:10:18 +0100 Subject: [PATCH] Commands install component and its dependencies --- .../src/Command/UxToolkitInstallCommand.php | 4 +- .../src/Compiler/TwigComponentCompiler.php | 17 +++++- .../src/Registry/DependenciesResolver.php | 6 +- src/Toolkit/src/Registry/RegistryItem.php | 10 ++++ src/Toolkit/src/UxToolkitBundle.php | 2 + .../Compiler/TwigComponentCompilerTest.php | 60 ++++++++++++++++--- 6 files changed, 84 insertions(+), 15 deletions(-) diff --git a/src/Toolkit/src/Command/UxToolkitInstallCommand.php b/src/Toolkit/src/Command/UxToolkitInstallCommand.php index d2685b7c7b..cb19fcd308 100644 --- a/src/Toolkit/src/Command/UxToolkitInstallCommand.php +++ b/src/Toolkit/src/Command/UxToolkitInstallCommand.php @@ -82,7 +82,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $destination = $input->getOption('destination'); try { $io->info(\sprintf('Installing component "%s"...', $component->name)); - $this->compiler->compile($component, $destination); + $this->compiler->compile($registry, $component, $destination); } catch (TwigComponentAlreadyExist $e) { if (!$input->isInteractive()) { $io->error(\sprintf('The component "%s" already exists.', $component->name)); @@ -97,7 +97,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } // again - $this->compiler->compile($component, $destination); + $this->compiler->compile($registry, $component, $destination); } $io->success(\sprintf('The component "%s" has been installed.', $component->name)); diff --git a/src/Toolkit/src/Compiler/TwigComponentCompiler.php b/src/Toolkit/src/Compiler/TwigComponentCompiler.php index 74f5f3ad56..cf7cd11609 100644 --- a/src/Toolkit/src/Compiler/TwigComponentCompiler.php +++ b/src/Toolkit/src/Compiler/TwigComponentCompiler.php @@ -13,6 +13,8 @@ use Symfony\Component\Filesystem\Filesystem; use Symfony\UX\Toolkit\Compiler\Exception\TwigComponentAlreadyExist; +use Symfony\UX\Toolkit\Registry\DependenciesResolver; +use Symfony\UX\Toolkit\Registry\Registry; use Symfony\UX\Toolkit\Registry\RegistryItem; /** @@ -20,23 +22,36 @@ * * @internal */ -class TwigComponentCompiler +final class TwigComponentCompiler { public function __construct( private readonly ?string $prefix, + private readonly DependenciesResolver $dependenciesResolver, ) { } public function compile( + Registry $registry, RegistryItem $item, string $directory, ): void { + // resolve dependencies (avoid circular dependencies) + $this->dependenciesResolver->resolve($registry); $filesystem = new Filesystem(); if (!$filesystem->exists($directory)) { $filesystem->mkdir($directory); } + $componentsToInstall = array_merge([$item->name], $item->getDependencies()); + + foreach ($componentsToInstall as $componentName) { + $this->installComponent($registry->get($componentName), $directory, $filesystem); + } + } + + private function installComponent(RegistryItem $item, string $directory, Filesystem $filesystem) + { $filename = implode(\DIRECTORY_SEPARATOR, [ $directory, $this->prefix, diff --git a/src/Toolkit/src/Registry/DependenciesResolver.php b/src/Toolkit/src/Registry/DependenciesResolver.php index 4e7b639881..dcde4771cf 100644 --- a/src/Toolkit/src/Registry/DependenciesResolver.php +++ b/src/Toolkit/src/Registry/DependenciesResolver.php @@ -37,12 +37,8 @@ public function resolve(Registry $registry): array private function resolveDependency(Registry $registry, string $itemName, array $resolved, array $unresolved) { $unresolved[] = $itemName; - $dependencies = []; - if (null !== $registry->get($itemName)->parentName) { - $dependencies[] = $registry->get($itemName)->parentName; - } - foreach ($dependencies as $dep) { + foreach ($registry->get($itemName)->getDependencies() as $dep) { if (!\in_array($dep, $resolved)) { if (!\in_array($dep, $unresolved)) { $unresolved[] = $dep; diff --git a/src/Toolkit/src/Registry/RegistryItem.php b/src/Toolkit/src/Registry/RegistryItem.php index 84f8ea5aa7..25fe8c5fef 100644 --- a/src/Toolkit/src/Registry/RegistryItem.php +++ b/src/Toolkit/src/Registry/RegistryItem.php @@ -71,4 +71,14 @@ public static function fromFile(SplFileInfo $file): self // $file->getContents(), // ); } + + public function getDependencies(): array + { + $dependencies = []; + if (null !== $this->parentName) { + $dependencies[] = $this->parentName; + } + + return $dependencies; + } } diff --git a/src/Toolkit/src/UxToolkitBundle.php b/src/Toolkit/src/UxToolkitBundle.php index 7ba24735c6..0a3978cb20 100644 --- a/src/Toolkit/src/UxToolkitBundle.php +++ b/src/Toolkit/src/UxToolkitBundle.php @@ -23,6 +23,7 @@ use Symfony\UX\Toolkit\ComponentRepository\RepositoryFactory; use Symfony\UX\Toolkit\ComponentRepository\RepositoryIdentifier; use Symfony\UX\Toolkit\DependencyInjection\ToolkitExtension; +use Symfony\UX\Toolkit\Registry\DependenciesResolver; use Symfony\UX\Toolkit\Registry\RegistryFactory; /** @@ -45,6 +46,7 @@ public function build(ContainerBuilder $container): void $container->autowire(RepositoryFactory::class); $container->autowire(RepositoryIdentifier::class); $container->autowire(RegistryFactory::class); + $container->autowire(DependenciesResolver::class); $container->autowire(TwigComponentCompiler::class); $container->getDefinition(TwigComponentCompiler::class) diff --git a/src/Toolkit/tests/Compiler/TwigComponentCompilerTest.php b/src/Toolkit/tests/Compiler/TwigComponentCompilerTest.php index 4fc750805a..0b649070fc 100644 --- a/src/Toolkit/tests/Compiler/TwigComponentCompilerTest.php +++ b/src/Toolkit/tests/Compiler/TwigComponentCompilerTest.php @@ -14,8 +14,8 @@ use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; use Symfony\UX\Toolkit\Compiler\Exception\TwigComponentAlreadyExist; use Symfony\UX\Toolkit\Compiler\TwigComponentCompiler; -use Symfony\UX\Toolkit\ComponentRepository\OfficialRepository; -use Symfony\UX\Toolkit\ComponentRepository\RepositoryIdentity; +use Symfony\UX\Toolkit\Registry\DependenciesResolver; +use Symfony\UX\Toolkit\Registry\Registry; use Symfony\UX\Toolkit\Registry\RegistryItem; use Symfony\UX\Toolkit\Registry\RegistryItemType; @@ -26,9 +26,10 @@ class TwigComponentCompilerTest extends KernelTestCase { public function testItShouldCompileComponentToFile(): void { - $compiler = new TwigComponentCompiler('Acme'); + $compiler = new TwigComponentCompiler('Acme', new DependenciesResolver()); $destination = sys_get_temp_dir().\DIRECTORY_SEPARATOR.uniqid('component_'); + $registry = new Registry(); $item = new RegistryItem( 'Badge', RegistryItemType::Component, @@ -36,8 +37,9 @@ public function testItShouldCompileComponentToFile(): void null, '' ); + $registry->add($item); - $compiler->compile($item, $destination); + $compiler->compile($registry, $item, $destination); $this->assertFileExists($destination); $this->assertFileExists($destination.'/Acme/Badge.html.twig'); @@ -48,9 +50,10 @@ public function testItShouldCompileComponentToFile(): void public function testShouldThrowExceptionIfFileAlreadyExist(): void { - $compiler = new TwigComponentCompiler('Acme'); + $compiler = new TwigComponentCompiler('Acme', new DependenciesResolver()); $destination = sys_get_temp_dir().\DIRECTORY_SEPARATOR.uniqid('component_'); + $registry = new Registry(); $item = new RegistryItem( 'Badge', RegistryItemType::Component, @@ -58,10 +61,53 @@ public function testShouldThrowExceptionIfFileAlreadyExist(): void null, '' ); + $registry->add($item); - $compiler->compile($item, $destination); + $compiler->compile($registry, $item, $destination); $this->expectException(TwigComponentAlreadyExist::class); - $compiler->compile($item, $destination); + $compiler->compile($registry, $item, $destination); + } + + public function testDependenciesAreAlsoCompiled(): void + { + $compiler = new TwigComponentCompiler('Acme', new DependenciesResolver()); + $destination = sys_get_temp_dir().\DIRECTORY_SEPARATOR.uniqid('component_'); + + $registry = new Registry(); + $registry->add( + new RegistryItem( + 'Badge', + RegistryItemType::Component, + 'default', + null, + '' + ) + ); + $registry->add( + new RegistryItem( + 'Table', + RegistryItemType::Component, + 'default', + null, + 'foo
' + ) + ); + $registry->add( + new RegistryItem( + 'Row', + RegistryItemType::Component, + 'default', + 'Table', + 'foo' + ) + ); + + $compiler->compile($registry, $registry->get('Row'), $destination); + + $this->assertFileExists($destination); + $this->assertFileExists($destination.'/Acme/Table.html.twig'); + $this->assertFileExists($destination.'/Acme/Row.html.twig'); + $this->assertFileDoesNotExist($destination.'/Acme/Badge.html.twig'); } }