From a1bb5a2c000348ae3001c78e41359c78b8135c10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Andr=C3=A9?= Date: Wed, 31 Jul 2024 06:15:23 +0200 Subject: [PATCH] [AssetMapper] Leverage Filesystem --- .../CompiledAssetMapperConfigReader.php | 5 ++--- .../ImportMap/ImportMapConfigReader.php | 5 ++++- .../ImportMap/RemotePackageDownloader.php | 9 ++++++++- .../ImportMap/RemotePackageStorage.php | 19 +++++++++++++------ .../Tests/ImportMap/ImportMapManagerTest.php | 6 +----- .../ImportMap/RemotePackageDownloaderTest.php | 14 +++++--------- .../ImportMap/RemotePackageStorageTest.php | 14 +++++++++++--- 7 files changed, 44 insertions(+), 28 deletions(-) diff --git a/src/Symfony/Component/AssetMapper/CompiledAssetMapperConfigReader.php b/src/Symfony/Component/AssetMapper/CompiledAssetMapperConfigReader.php index c0e1b44dd4f27..b203ac8bb17a2 100644 --- a/src/Symfony/Component/AssetMapper/CompiledAssetMapperConfigReader.php +++ b/src/Symfony/Component/AssetMapper/CompiledAssetMapperConfigReader.php @@ -40,8 +40,7 @@ public function loadConfig(string $filename): array public function saveConfig(string $filename, array $data): string { $path = Path::join($this->directory, $filename); - @mkdir(\dirname($path), 0777, true); - file_put_contents($path, json_encode($data, \JSON_PRETTY_PRINT | \JSON_THROW_ON_ERROR)); + $this->filesystem->dumpFile($path, json_encode($data, \JSON_PRETTY_PRINT | \JSON_THROW_ON_ERROR)); return $path; } @@ -51,7 +50,7 @@ public function removeConfig(string $filename): void $path = Path::join($this->directory, $filename); if (is_file($path)) { - unlink($path); + $this->filesystem->remove($path); } } } diff --git a/src/Symfony/Component/AssetMapper/ImportMap/ImportMapConfigReader.php b/src/Symfony/Component/AssetMapper/ImportMap/ImportMapConfigReader.php index 7ed39eabb068a..4dc98fe394245 100644 --- a/src/Symfony/Component/AssetMapper/ImportMap/ImportMapConfigReader.php +++ b/src/Symfony/Component/AssetMapper/ImportMap/ImportMapConfigReader.php @@ -12,6 +12,7 @@ namespace Symfony\Component\AssetMapper\ImportMap; use Symfony\Component\AssetMapper\Exception\RuntimeException; +use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Filesystem\Path; use Symfony\Component\VarExporter\VarExporter; @@ -23,11 +24,13 @@ class ImportMapConfigReader { private ImportMapEntries $rootImportMapEntries; + private readonly Filesystem $filesystem; public function __construct( private readonly string $importMapConfigPath, private readonly RemotePackageStorage $remotePackageStorage, ) { + $this->filesystem = new Filesystem(); } public function getEntries(): ImportMapEntries @@ -101,7 +104,7 @@ public function writeEntries(ImportMapEntries $entries): void } $map = class_exists(VarExporter::class) ? VarExporter::export($importMapConfig) : var_export($importMapConfig, true); - file_put_contents($this->importMapConfigPath, <<filesystem->dumpFile($this->importMapConfigPath, <<filesystem = new Filesystem(); } /** @@ -146,7 +150,10 @@ private function loadInstalled(): array private function saveInstalled(array $installed): void { $this->installed = $installed; - file_put_contents($this->remotePackageStorage->getStorageDir().'/installed.php', \sprintf('filesystem->dumpFile( + $this->remotePackageStorage->getStorageDir().'/installed.php', + 'filesystem = new Filesystem(); } public function getStorageDir(): string @@ -53,9 +58,10 @@ public function save(ImportMapEntry $entry, string $contents): void $vendorPath = $this->getDownloadPath($entry->packageModuleSpecifier, $entry->type); - @mkdir(\dirname($vendorPath), 0777, true); - if (false === @file_put_contents($vendorPath, $contents)) { - throw new RuntimeException(error_get_last()['message'] ?? \sprintf('Failed to write file "%s".', $vendorPath)); + try { + $this->filesystem->dumpFile($vendorPath, $contents); + } catch (IOException $e) { + throw new RuntimeException(\sprintf('Failed to write file "%s".', $vendorPath), 0, $e); } } @@ -67,9 +73,10 @@ public function saveExtraFile(ImportMapEntry $entry, string $extraFilename, stri $vendorPath = $this->getExtraFileDownloadPath($entry, $extraFilename); - @mkdir(\dirname($vendorPath), 0777, true); - if (false === @file_put_contents($vendorPath, $contents)) { - throw new RuntimeException(error_get_last()['message'] ?? \sprintf('Failed to write file "%s".', $vendorPath)); + try { + $this->filesystem->dumpFile($vendorPath, $contents); + } catch (IOException $e) { + throw new RuntimeException(\sprintf('Failed to write file "%s".', $vendorPath), 0, $e); } } diff --git a/src/Symfony/Component/AssetMapper/Tests/ImportMap/ImportMapManagerTest.php b/src/Symfony/Component/AssetMapper/Tests/ImportMap/ImportMapManagerTest.php index 65de2a2efbe1d..c2805f937de8b 100644 --- a/src/Symfony/Component/AssetMapper/Tests/ImportMap/ImportMapManagerTest.php +++ b/src/Symfony/Component/AssetMapper/Tests/ImportMap/ImportMapManagerTest.php @@ -409,11 +409,7 @@ private function mockImportMap(array $importMapEntries): void private function writeFile(string $filename, string $content): void { - $path = \dirname(self::$writableRoot.'/'.$filename); - if (!is_dir($path)) { - mkdir($path, 0777, true); - } - file_put_contents(self::$writableRoot.'/'.$filename, $content); + $this->filesystem->dumpFile(self::$writableRoot.'/'.$filename, $content); } private static function createLocalEntry(string $importName, string $path, ImportMapType $type = ImportMapType::JS, bool $isEntrypoint = false): ImportMapEntry diff --git a/src/Symfony/Component/AssetMapper/Tests/ImportMap/RemotePackageDownloaderTest.php b/src/Symfony/Component/AssetMapper/Tests/ImportMap/RemotePackageDownloaderTest.php index 115981a16eb5c..6326036fc2ffd 100644 --- a/src/Symfony/Component/AssetMapper/Tests/ImportMap/RemotePackageDownloaderTest.php +++ b/src/Symfony/Component/AssetMapper/Tests/ImportMap/RemotePackageDownloaderTest.php @@ -29,9 +29,7 @@ class RemotePackageDownloaderTest extends TestCase protected function setUp(): void { $this->filesystem = new Filesystem(); - if (!file_exists(self::$writableRoot)) { - $this->filesystem->mkdir(self::$writableRoot); - } + $this->filesystem->mkdir(self::$writableRoot); } protected function tearDown(): void @@ -106,9 +104,9 @@ public function testPackagesWithCorrectInstalledVersionSkipped() 'bar.js/file' => ['version' => '1.0.0', 'dependencies' => [], 'extraFiles' => []], 'baz' => ['version' => '1.0.0', 'dependencies' => [], 'extraFiles' => []], ]; - file_put_contents( + $this->filesystem->dumpFile( self::$writableRoot.'/assets/vendor/installed.php', - 'createMock(ImportMapConfigReader::class); @@ -116,14 +114,12 @@ public function testPackagesWithCorrectInstalledVersionSkipped() // matches installed version and file exists $entry1 = ImportMapEntry::createRemote('foo', ImportMapType::JS, path: '/any', version: '1.0.0', packageModuleSpecifier: 'foo', isEntrypoint: false); - @mkdir(self::$writableRoot.'/assets/vendor/foo', 0777, true); - file_put_contents(self::$writableRoot.'/assets/vendor/foo/foo.index.js', 'original foo content'); + $this->filesystem->dumpFile(self::$writableRoot.'/assets/vendor/foo/foo.index.js', 'original foo content'); // matches installed version but file does not exist $entry2 = ImportMapEntry::createRemote('bar.js/file', ImportMapType::JS, path: '/any', version: '1.0.0', packageModuleSpecifier: 'bar.js/file', isEntrypoint: false); // does not match installed version $entry3 = ImportMapEntry::createRemote('baz', ImportMapType::CSS, path: '/any', version: '1.1.0', packageModuleSpecifier: 'baz', isEntrypoint: false); - @mkdir(self::$writableRoot.'/assets/vendor/baz', 0777, true); - file_put_contents(self::$writableRoot.'/assets/vendor/baz/baz.index.css', 'original baz content'); + $this->filesystem->dumpFile(self::$writableRoot.'/assets/vendor/baz/baz.index.css', 'original baz content'); // matches installed & file exists, but has missing extra file $entry4 = ImportMapEntry::createRemote('has-missing-extra', ImportMapType::JS, path: '/any', version: '1.0.0', packageModuleSpecifier: 'has-missing-extra', isEntrypoint: false); $importMapEntries = new ImportMapEntries([$entry1, $entry2, $entry3, $entry4]); diff --git a/src/Symfony/Component/AssetMapper/Tests/ImportMap/RemotePackageStorageTest.php b/src/Symfony/Component/AssetMapper/Tests/ImportMap/RemotePackageStorageTest.php index f28759e030761..7c0f1541a85ed 100644 --- a/src/Symfony/Component/AssetMapper/Tests/ImportMap/RemotePackageStorageTest.php +++ b/src/Symfony/Component/AssetMapper/Tests/ImportMap/RemotePackageStorageTest.php @@ -46,18 +46,26 @@ public function testSaveThrowsWhenFailing() $vendorDir = self::$writableRoot.'/assets/acme/vendor'; $this->filesystem->mkdir($vendorDir.'/module_specifier'); $this->filesystem->touch($vendorDir.'/module_specifier/module_specifier.index.js'); - $this->filesystem->chmod($vendorDir.'/module_specifier/module_specifier.index.js', 0555); + if ('\\' === \DIRECTORY_SEPARATOR) { + $this->filesystem->chmod($vendorDir.'/module_specifier/module_specifier.index.js', 0555); + } else { + $this->filesystem->chmod($vendorDir.'/module_specifier/', 0555); + } $storage = new RemotePackageStorage($vendorDir); $entry = ImportMapEntry::createRemote('foo', ImportMapType::JS, '/does/not/matter', '1.0.0', 'module_specifier', false); $this->expectException(\RuntimeException::class); - $this->expectExceptionMessage('file_put_contents('.$vendorDir.'/module_specifier/module_specifier.index.js): Failed to open stream: Permission denied'); + $this->expectExceptionMessage('Failed to write file "'.$vendorDir.'/module_specifier/module_specifier.index.js".'); try { $storage->save($entry, 'any content'); } finally { - $this->filesystem->chmod($vendorDir.'/module_specifier/module_specifier.index.js', 0777); + if ('\\' === \DIRECTORY_SEPARATOR) { + $this->filesystem->chmod($vendorDir.'/module_specifier/module_specifier.index.js', 0777); + } else { + $this->filesystem->chmod($vendorDir.'/module_specifier/', 0777); + } } }