Repository: symfony/ux
Pull request #2800 (2025-05-31 05:58:28)

[Toolkit] Remove `FileType`
| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | no <!-- please update src/**/CHANGELOG.md files -->
| Docs?         | no <!-- required for new features -->
| Issues        | Fix #... <!-- prefix each issue number with "Fix #", no need to create an issue if none exist, explain below instead -->
| License       | MIT

<!--
Replace this notice by a description of your feature/bugfix.
This will help reviewers and should be a good start for the documentation.

Additionally (see https://symfony.com/releases):
 - Always add tests and ensure they pass.
 - For new features, provide some code snippets to help understand usage.
 - Features and deprecations must be submitted against branch main.
 - Update/add documentation as required (we can help!)
 - Changelog entry should follow https://symfony.com/doc/current/contributing/code/conventions.html#writing-a-changelog-entry
 - Never break backward compatibility (see https://symfony.com/bc).
-->

Looks like it wasn't super useful 


Patch:
diff --git a/src/Toolkit/src/File/File.php b/src/Toolkit/src/File/File.php
index df43a7c7..dec39e05 100644
--- a/src/Toolkit/src/File/File.php
+++ b/src/Toolkit/src/File/File.php
@@ -27,7 +27,6 @@ final class File implements \Stringable
      * @throws \InvalidArgumentException
      */
     public function __construct(
-        public readonly FileType $type,
         public readonly string $relativePathNameToKit,
         public readonly string $relativePathName,
     ) {
@@ -46,6 +45,6 @@ final class File implements \Stringable
 
     public function __toString(): string
     {
-        return \sprintf('%s (%s)', $this->relativePathNameToKit, $this->type->getLabel());
+        return $this->relativePathNameToKit;
     }
 }
diff --git a/src/Toolkit/src/File/FileType.php b/src/Toolkit/src/File/FileType.php
deleted file mode 100644
index 26506f3a..00000000
--- a/src/Toolkit/src/File/FileType.php
+++ /dev/null
@@ -1,31 +0,0 @@
-<?php
-
-/*
- * This file is part of the Symfony package.
- *
- * (c) Fabien Potencier <fabien@symfony.com>
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\UX\Toolkit\File;
-
-/**
- * @internal
- *
- * @author Hugo Alliaume <hugo@alliau.me>
- */
-enum FileType: string
-{
-    case Twig = 'twig';
-    case StimulusController = 'stimulus_controller';
-
-    public function getLabel(): string
-    {
-        return match ($this) {
-            self::Twig => 'Twig',
-            self::StimulusController => 'Stimulus Controller',
-        };
-    }
-}
diff --git a/src/Toolkit/src/Kit/KitContextRunner.php b/src/Toolkit/src/Kit/KitContextRunner.php
index f2cd0e42..43171b01 100644
--- a/src/Toolkit/src/Kit/KitContextRunner.php
+++ b/src/Toolkit/src/Kit/KitContextRunner.php
@@ -95,9 +95,7 @@ final class KitContextRunner
                 }
 
                 foreach ($component->files as $file) {
-                    if (FileType::Twig === $file->type) {
-                        return $file->relativePathName;
-                    }
+                    return $file->relativePathName;
                 }
 
                 throw new \LogicException(\sprintf('No Twig files found for component "%s" in kit "%s", it should not happens.', $name, $this->kit->name));
diff --git a/src/Toolkit/src/Kit/KitSynchronizer.php b/src/Toolkit/src/Kit/KitSynchronizer.php
index 9160b3a1..80fbf393 100644
--- a/src/Toolkit/src/Kit/KitSynchronizer.php
+++ b/src/Toolkit/src/Kit/KitSynchronizer.php
@@ -87,7 +87,6 @@ final class KitSynchronizer
             $component = new Component(
                 name: $componentName,
                 files: [new File(
-                    type: FileType::Twig,
                     relativePathNameToKit: $relativePathNameToKit,
                     relativePathName: $relativePathName,
                 )],
@@ -124,30 +123,28 @@ final class KitSynchronizer
 
             $fileContent = file_get_contents($filePath);
 
-            if (FileType::Twig === $file->type) {
-                if (str_contains($fileContent, '<twig:') && preg_match_all(self::RE_TWIG_COMPONENT_REFERENCES, $fileContent, $matches)) {
-                    foreach ($matches[1] as $componentReferenceName) {
-                        if ($componentReferenceName === $component->name) {
-                            continue;
-                        }
+            if (str_contains($fileContent, '<twig:') && preg_match_all(self::RE_TWIG_COMPONENT_REFERENCES, $fileContent, $matches)) {
+                foreach ($matches[1] as $componentReferenceName) {
+                    if ($componentReferenceName === $component->name) {
+                        continue;
+                    }
 
-                        if (null !== $package = self::UX_COMPONENTS_PACKAGES[strtolower($componentReferenceName)] ?? null) {
-                            if (!$component->hasDependency(new PhpPackageDependency($package))) {
-                                throw new \RuntimeException(\sprintf('Component "%s" uses "%s" UX Twig component, but the composer package "%s" is not listed as a dependency in meta file.', $component->name, $componentReferenceName, $package));
-                            }
-                        } else if (null === $componentReference = $kit->getComponent($componentReferenceName)) {
-                            throw new \RuntimeException(\sprintf('Component "%s" not found in component "%s" (file "%s")', $componentReferenceName, $component->name, $file->relativePathNameToKit));
-                        } else {
-                            $component->addDependency(new ComponentDependency($componentReference->name));
+                    if (null !== $package = self::UX_COMPONENTS_PACKAGES[strtolower($componentReferenceName)] ?? null) {
+                        if (!$component->hasDependency(new PhpPackageDependency($package))) {
+                            throw new \RuntimeException(\sprintf('Component "%s" uses "%s" UX Twig component, but the composer package "%s" is not listed as a dependency in meta file.', $component->name, $componentReferenceName, $package));
                         }
+                    } else if (null === $componentReference = $kit->getComponent($componentReferenceName)) {
+                        throw new \RuntimeException(\sprintf('Component "%s" not found in component "%s" (file "%s")', $componentReferenceName, $component->name, $file->relativePathNameToKit));
+                    } else {
+                        $component->addDependency(new ComponentDependency($componentReference->name));
                     }
                 }
+            }
 
-                if (str_contains($fileContent, 'data-controller=') && preg_match_all(self::RE_STIMULUS_CONTROLLER_REFERENCES, $fileContent, $matches)) {
-                    $controllersName = array_filter(array_map(fn (string $name) => trim($name), explode(' ', $matches['controllersName'][0])));
-                    foreach ($controllersName as $controllerReferenceName) {
-                        $component->addDependency(new StimulusControllerDependency($controllerReferenceName));
-                    }
+            if (str_contains($fileContent, 'data-controller=') && preg_match_all(self::RE_STIMULUS_CONTROLLER_REFERENCES, $fileContent, $matches)) {
+                $controllersName = array_filter(array_map(fn (string $name) => trim($name), explode(' ', $matches['controllersName'][0])));
+                foreach ($controllersName as $controllerReferenceName) {
+                    $component->addDependency(new StimulusControllerDependency($controllerReferenceName));
                 }
             }
         }
@@ -171,7 +168,6 @@ final class KitSynchronizer
             $controller = new StimulusController(
                 name: $controllerName,
                 files: [new File(
-                    type: FileType::StimulusController,
                     relativePathNameToKit: $relativePathNameToKit,
                     relativePathName: $relativePathName,
                 )],


Test patch:
diff --git a/src/Toolkit/tests/Asset/ComponentTest.php b/src/Toolkit/tests/Asset/ComponentTest.php
index a1babf6b..8a8886c6 100644
--- a/src/Toolkit/tests/Asset/ComponentTest.php
+++ b/src/Toolkit/tests/Asset/ComponentTest.php
@@ -24,7 +24,7 @@ final class ComponentTest extends TestCase
     public function testCanBeInstantiated(): void
     {
         $component = new Component('Button', [
-            new File(FileType::Twig, 'templates/components/Button/Button.html.twig', 'Button.html.twig'),
+            new File('templates/components/Button/Button.html.twig', 'Button.html.twig'),
         ]);
 
         $this->assertSame('Button', $component->name);
@@ -40,7 +40,7 @@ final class ComponentTest extends TestCase
         $this->expectExceptionMessage('Invalid component name "foobar".');
 
         new Component('foobar', [
-            new File(FileType::Twig, 'templates/components/Button/Button.html.twig', 'Button.html.twig'),
+            new File('templates/components/Button/Button.html.twig', 'Button.html.twig'),
         ]);
     }
 
@@ -55,7 +55,7 @@ final class ComponentTest extends TestCase
     public function testCanAddAndGetDependencies(): void
     {
         $component = new Component('Button', [
-            new File(FileType::Twig, 'templates/components/Button/Button.html.twig', 'Button.html.twig'),
+            new File('templates/components/Button/Button.html.twig', 'Button.html.twig'),
         ]);
 
         $component->addDependency($dependency1 = new ComponentDependency('Icon'));
@@ -69,7 +69,7 @@ final class ComponentTest extends TestCase
     public function testShouldNotAddDuplicateComponentDependencies(): void
     {
         $component = new Component('Button', [
-            new File(FileType::Twig, 'templates/components/Button/Button.html.twig', 'Button.html.twig'),
+            new File('templates/components/Button/Button.html.twig', 'Button.html.twig'),
         ]);
 
         $component->addDependency($dependency1 = new ComponentDependency('Icon'));
@@ -84,7 +84,7 @@ final class ComponentTest extends TestCase
     public function testShouldReplacePhpPackageDependencyIfVersionIsHigher(): void
     {
         $component = new Component('Button', [
-            new File(FileType::Twig, 'templates/components/Button/Button.html.twig', 'Button.html.twig'),
+            new File('templates/components/Button/Button.html.twig', 'Button.html.twig'),
         ]);
 
         $component->addDependency($dependency1 = new ComponentDependency('Icon'));
@@ -103,7 +103,7 @@ final class ComponentTest extends TestCase
     public function testShouldNotReplacePhpPackageDependencyIfVersionIsLower(): void
     {
         $component = new Component('Button', [
-            new File(FileType::Twig, 'templates/components/Button/Button.html.twig', 'Button.html.twig'),
+            new File('templates/components/Button/Button.html.twig', 'Button.html.twig'),
         ]);
 
         $component->addDependency($dependency1 = new ComponentDependency('Icon'));
diff --git a/src/Toolkit/tests/Asset/StimulusControllerTest.php b/src/Toolkit/tests/Asset/StimulusControllerTest.php
index ee759ae1..092755e0 100644
--- a/src/Toolkit/tests/Asset/StimulusControllerTest.php
+++ b/src/Toolkit/tests/Asset/StimulusControllerTest.php
@@ -23,7 +23,7 @@ final class StimulusControllerTest extends TestCase
     public function testCanBeInstantiated(): void
     {
         $stimulusController = new StimulusController('clipboard', [
-            new File(FileType::StimulusController, 'assets/controllers/clipboard_controller.js', 'clipboard_controller.js'),
+            new File('assets/controllers/clipboard_controller.js', 'clipboard_controller.js'),
         ]);
 
         $this->assertSame('clipboard', $stimulusController->name);
@@ -34,7 +34,7 @@ final class StimulusControllerTest extends TestCase
         $this->expectException(\InvalidArgumentException::class);
         $this->expectExceptionMessage('Invalid Stimulus controller name "invalid_controller".');
 
-        new StimulusController('invalid_controller', [new File(FileType::StimulusController, 'assets/controllers/invalid_controller.js', 'invalid_controller.js')]);
+        new StimulusController('invalid_controller', [new File('assets/controllers/invalid_controller.js', 'invalid_controller.js')]);
     }
 
     public function testShouldFailIfStimulusControllerHasNoFiles(): void
diff --git a/src/Toolkit/tests/Command/DebugKitCommandTest.php b/src/Toolkit/tests/Command/DebugKitCommandTest.php
index 1774009f..406d237d 100644
--- a/src/Toolkit/tests/Command/DebugKitCommandTest.php
+++ b/src/Toolkit/tests/Command/DebugKitCommandTest.php
@@ -28,14 +28,28 @@ class DebugKitCommandTest extends KernelTestCase
             ->assertOutputContains('Name       Shadcn')
             ->assertOutputContains('Homepage   https://ux.symfony.com/components')
             ->assertOutputContains('License    MIT')
-            // A component details
+            // Components details
             ->assertOutputContains(<<<'EOF'
 +--------------+----------------------- Component: "Avatar" --------------------------------------+
-| File(s)      | templates/components/Avatar.html.twig (Twig)                                     |
+| File(s)      | templates/components/Avatar.html.twig                                            |
 | Dependencies | tales-from-a-dev/twig-tailwind-extra                                             |
 |              | Avatar:Image                                                                     |
 |              | Avatar:Text                                                                      |
 +--------------+----------------------------------------------------------------------------------+
+EOF
+            )
+            ->assertOutputContains(<<<'EOF'
++--------------+----------------------- Component: "Table" ---------------------------------------+
+| File(s)      | templates/components/Table.html.twig                                             |
+| Dependencies | tales-from-a-dev/twig-tailwind-extra                                             |
+|              | Table:Body                                                                       |
+|              | Table:Caption                                                                    |
+|              | Table:Cell                                                                       |
+|              | Table:Footer                                                                     |
+|              | Table:Head                                                                       |
+|              | Table:Header                                                                     |
+|              | Table:Row                                                                        |
++--------------+----------------------------------------------------------------------------------+
 EOF
             );
     }
diff --git a/src/Toolkit/tests/File/FileTest.php b/src/Toolkit/tests/File/FileTest.php
index 8ee8a6cc..b0568475 100644
--- a/src/Toolkit/tests/File/FileTest.php
+++ b/src/Toolkit/tests/File/FileTest.php
@@ -22,7 +22,7 @@ final class FileTest extends TestCase
         $this->expectException(\InvalidArgumentException::class);
         $this->expectExceptionMessage(\sprintf('The path to the kit "%s" must be relative.', __FILE__.'/templates/components/Button.html.twig'));
 
-        new File(FileType::Twig, __FILE__.'/templates/components/Button.html.twig', __FILE__.'Button.html.twig');
+        new File(__FILE__.'/templates/components/Button.html.twig', __FILE__.'Button.html.twig');
     }
 
     public function testShouldFailIfPathNameIsNotRelative(): void
@@ -30,7 +30,7 @@ final class FileTest extends TestCase
         $this->expectException(\InvalidArgumentException::class);
         $this->expectExceptionMessage(\sprintf('The path name "%s" must be relative.', __FILE__.'Button.html.twig'));
 
-        new File(FileType::Twig, 'templates/components/Button.html.twig', __FILE__.'Button.html.twig');
+        new File('templates/components/Button.html.twig', __FILE__.'Button.html.twig');
     }
 
     public function testShouldFailIfPathNameIsNotASubpathOfPathToKit(): void
@@ -38,26 +38,24 @@ final class FileTest extends TestCase
         $this->expectException(\InvalidArgumentException::class);
         $this->expectExceptionMessage(\sprintf('The relative path name "%s" must be a subpath of the relative path to the kit "%s".', 'foo/bar/Button.html.twig', 'templates/components/Button.html.twig'));
 
-        new File(FileType::Twig, 'templates/components/Button.html.twig', 'foo/bar/Button.html.twig');
+        new File('templates/components/Button.html.twig', 'foo/bar/Button.html.twig');
     }
 
     public function testCanInstantiateFile(): void
     {
-        $file = new File(FileType::Twig, 'templates/components/Button.html.twig', 'Button.html.twig');
+        $file = new File('templates/components/Button.html.twig', 'Button.html.twig');
 
-        $this->assertSame(FileType::Twig, $file->type);
         $this->assertSame('templates/components/Button.html.twig', $file->relativePathNameToKit);
         $this->assertSame('Button.html.twig', $file->relativePathName);
-        $this->assertSame('templates/components/Button.html.twig (Twig)', (string) $file);
+        $this->assertSame('templates/components/Button.html.twig', (string) $file);
     }
 
     public function testCanInstantiateFileWithSubComponent(): void
     {
-        $file = new File(FileType::Twig, 'templates/components/Table/Body.html.twig', 'Table/Body.html.twig');
+        $file = new File('templates/components/Table/Body.html.twig', 'Table/Body.html.twig');
 
-        $this->assertSame(FileType::Twig, $file->type);
         $this->assertSame('templates/components/Table/Body.html.twig', $file->relativePathNameToKit);
         $this->assertSame('Table/Body.html.twig', $file->relativePathName);
-        $this->assertSame('templates/components/Table/Body.html.twig (Twig)', (string) $file);
+        $this->assertSame('templates/components/Table/Body.html.twig', (string) $file);
     }
 }
diff --git a/src/Toolkit/tests/Installer/PoolTest.php b/src/Toolkit/tests/Installer/PoolTest.php
index 027f2433..61e76763 100644
--- a/src/Toolkit/tests/Installer/PoolTest.php
+++ b/src/Toolkit/tests/Installer/PoolTest.php
@@ -28,8 +28,8 @@ final class PoolTest extends TestCase
 
         $this->assertCount(0, $pool->getFiles());
 
-        $pool->addFile(new File(FileType::Twig, 'path/to/file.html.twig', 'file.html.twig'));
-        $pool->addFile(new File(FileType::Twig, 'path/to/another-file.html.twig', 'another-file.html.twig'));
+        $pool->addFile(new File('path/to/file.html.twig', 'file.html.twig'));
+        $pool->addFile(new File('path/to/another-file.html.twig', 'another-file.html.twig'));
 
         $this->assertCount(2, $pool->getFiles());
     }
@@ -38,8 +38,8 @@ final class PoolTest extends TestCase
     {
         $pool = new Pool();
 
-        $pool->addFile(new File(FileType::Twig, 'path/to/file.html.twig', 'file.html.twig'));
-        $pool->addFile(new File(FileType::Twig, 'path/to/file.html.twig', 'file.html.twig'));
+        $pool->addFile(new File('path/to/file.html.twig', 'file.html.twig'));
+        $pool->addFile(new File('path/to/file.html.twig', 'file.html.twig'));
 
         $this->assertCount(1, $pool->getFiles());
     }
diff --git a/src/Toolkit/tests/Kit/KitFactoryTest.php b/src/Toolkit/tests/Kit/KitFactoryTest.php
index 937e7221..5fb29c1f 100644
--- a/src/Toolkit/tests/Kit/KitFactoryTest.php
+++ b/src/Toolkit/tests/Kit/KitFactoryTest.php
@@ -85,10 +85,10 @@ EOF
         // Assert Stimulus Controllers are registered in the Kit
         $this->assertNotEmpty($kit->getStimulusControllers());
         $this->assertEquals([
-            $clipboard = new StimulusController('clipboard', [new File(FileType::StimulusController, 'assets/controllers/clipboard_controller.js', 'clipboard_controller.js')]),
-            $datePicker = new StimulusController('date-picker', [new File(FileType::StimulusController, 'assets/controllers/date_picker_controller.js', 'date_picker_controller.js')]),
-            $localTime = new StimulusController('local-time', [new File(FileType::StimulusController, 'assets/controllers/local-time-controller.js', 'local-time-controller.js')]),
-            $usersListItem = new StimulusController('users--list-item', [new File(FileType::StimulusController, 'assets/controllers/users/list_item_controller.js', 'users/list_item_controller.js')]),
+            $clipboard = new StimulusController('clipboard', [new File('assets/controllers/clipboard_controller.js', 'clipboard_controller.js')]),
+            $datePicker = new StimulusController('date-picker', [new File('assets/controllers/date_picker_controller.js', 'date_picker_controller.js')]),
+            $localTime = new StimulusController('local-time', [new File('assets/controllers/local-time-controller.js', 'local-time-controller.js')]),
+            $usersListItem = new StimulusController('users--list-item', [new File('assets/controllers/users/list_item_controller.js', 'users/list_item_controller.js')]),
         ], $kit->getStimulusControllers());
         $this->assertEquals($clipboard, $kit->getStimulusController('clipboard'));
         $this->assertEquals($datePicker, $kit->getStimulusController('date-picker'));
diff --git a/src/Toolkit/tests/Kit/KitTest.php b/src/Toolkit/tests/Kit/KitTest.php
index 1696ba39..8dda2fcf 100644
--- a/src/Toolkit/tests/Kit/KitTest.php
+++ b/src/Toolkit/tests/Kit/KitTest.php
@@ -38,8 +38,8 @@ final class KitTest extends TestCase
     public function testCanAddComponentsToTheKit(): void
     {
         $kit = new Kit(__DIR__, 'foo', 'https://example.com', 'MIT');
-        $kit->addComponent(new Component('Table', [new File(FileType::Twig, 'Table.html.twig', 'Table.html.twig')], null));
-        $kit->addComponent(new Component('Table:Row', [new File(FileType::Twig, 'Table/Row.html.twig', 'Table/Row.html.twig')], null));
+        $kit->addComponent(new Component('Table', [new File('Table.html.twig', 'Table.html.twig')], null));
+        $kit->addComponent(new Component('Table:Row', [new File('Table/Row.html.twig', 'Table/Row.html.twig')], null));
 
         $this->assertCount(2, $kit->getComponents());
     }
@@ -50,15 +50,15 @@ final class KitTest extends TestCase
         $this->expectExceptionMessage('Component "Table" is already registered in the kit.');
 
         $kit = new Kit(__DIR__, 'foo', 'https://example.com', 'MIT');
-        $kit->addComponent(new Component('Table', [new File(FileType::Twig, 'Table.html.twig', 'Table.html.twig')], null));
-        $kit->addComponent(new Component('Table', [new File(FileType::Twig, 'Table.html.twig', 'Table.html.twig')], null));
+        $kit->addComponent(new Component('Table', [new File('Table.html.twig', 'Table.html.twig')], null));
+        $kit->addComponent(new Component('Table', [new File('Table.html.twig', 'Table.html.twig')], null));
     }
 
     public function testCanGetComponentByName(): void
     {
         $kit = new Kit(__DIR__, 'foo', 'https://example.com', 'MIT');
-        $kit->addComponent(new Component('Table', [new File(FileType::Twig, 'Table.html.twig', 'Table.html.twig')], null));
-        $kit->addComponent(new Component('Table:Row', [new File(FileType::Twig, 'Table/Row.html.twig', 'Table/Row.html.twig')], null));
+        $kit->addComponent(new Component('Table', [new File('Table.html.twig', 'Table.html.twig')], null));
+        $kit->addComponent(new Component('Table:Row', [new File('Table/Row.html.twig', 'Table/Row.html.twig')], null));
 
         $this->assertSame('Table', $kit->getComponent('Table')->name);
         $this->assertSame('Table:Row', $kit->getComponent('Table:Row')->name);