diff --git a/.gitignore b/.gitignore index 1cd35e33..dff5a357 100644 --- a/.gitignore +++ b/.gitignore @@ -42,4 +42,6 @@ api/ # Ignore test artifact app/tests/Integration/Session/data/* !app/tests/Integration/Session/data/.gitkeep +app/tests/Integration/Filesystem/storage/* +!app/tests/Integration/Filesystem/storage/.gitkeep app/tests/Integration/Bakery/data/env/.env diff --git a/app/config/default.php b/app/config/default.php index a68287e6..fd077d1e 100755 --- a/app/config/default.php +++ b/app/config/default.php @@ -230,7 +230,7 @@ */ 'local' => [ 'driver' => 'local', - 'root' => 'storage', //TODO: Replace with locator; \UserFrosting\STORAGE_DIR, + 'root' => 'storage://', ], /* * Public files are directly accessible through the webserver for @@ -238,10 +238,9 @@ * Direct access from http://{url}/files/, physically located in `/public/files` * Great storage disk for assets (images, avatar, etc). */ - // TODO : Link back to public using locator 'public' => [ 'driver' => 'local', - 'root' => 'storage://', //\UserFrosting\STORAGE_PUBLIC_DIR, + 'root' => 'public://files', 'url' => 'files/', ], /* diff --git a/app/config/testing.php b/app/config/testing.php index e774f0ce..6e82a828 100755 --- a/app/config/testing.php +++ b/app/config/testing.php @@ -51,23 +51,6 @@ 'exception' => false, ], - /* - * Use testing filesystem for tests - */ - 'filesystems' => [ - 'disks' => [ - 'testing' => [ - 'driver' => 'local', - 'root' => 'storage/testing', //TODO : Replace with locator; \UserFrosting\STORAGE_DIR . \UserFrosting\DS . 'testing', - 'url' => 'files/testing/', - ], - 'testingDriver' => [ - 'driver' => 'localTest', - 'root' => 'storage/testingDriver', //TODO : Replace with locator; \UserFrosting\STORAGE_DIR . \UserFrosting\DS . 'testingDriver', - ], - ], - ], - /* * Disable native sessions in tests */ diff --git a/app/src/Filesystem/FilesystemManager.php b/app/src/Filesystem/FilesystemManager.php index 19e5417a..c675937b 100644 --- a/app/src/Filesystem/FilesystemManager.php +++ b/app/src/Filesystem/FilesystemManager.php @@ -16,6 +16,7 @@ use Illuminate\Filesystem\FilesystemManager as LaravelFilesystemManager; use League\Flysystem\FilesystemInterface; use UserFrosting\Config\Config; +use UserFrosting\UniformResourceLocator\ResourceLocatorInterface; /** * Filesystem disk manager service. @@ -25,10 +26,13 @@ class FilesystemManager extends LaravelFilesystemManager /** * Create a new filesystem manager instance. * - * @param Config $config + * @param Config $config + * @param ResourceLocatorInterface $locator */ - public function __construct(protected Config $config) - { + public function __construct( + protected Config $config, + protected ResourceLocatorInterface $locator, + ) { } /** @@ -80,4 +84,17 @@ public function getDefaultCloudDriver(): string { return $this->config->get('filesystems.cloud'); } + + /** + * Overwrite the local driver creation to replace root by locator. + * + * @param array $config + * @return \Illuminate\Contracts\Filesystem\Filesystem + */ + public function createLocalDriver(array $config) + { + $config['root'] = $this->locator->findResource($config['root'], all: true); + + return parent::createLocalDriver($config); + } } diff --git a/app/tests/Integration/Filesystem/FilesystemTest.php b/app/tests/Integration/Filesystem/FilesystemTest.php index 8d8a64c3..61d85b2c 100644 --- a/app/tests/Integration/Filesystem/FilesystemTest.php +++ b/app/tests/Integration/Filesystem/FilesystemTest.php @@ -17,36 +17,33 @@ use League\Flysystem\Filesystem; use Symfony\Component\HttpFoundation\StreamedResponse; use UserFrosting\Config\Config; -use UserFrosting\Sprinkle\Core\Facades\Storage; use UserFrosting\Sprinkle\Core\Filesystem\FilesystemManager; use UserFrosting\Sprinkle\Core\Tests\CoreTestCase as TestCase; +use UserFrosting\UniformResourceLocator\ResourceLocatorInterface; +use UserFrosting\UniformResourceLocator\ResourceStream; -/** - * FilesystemTest class. - * Tests a basic filesystem. - */ -// TODO : Most could be moved to a Unit Test. class FilesystemTest extends TestCase { - /** @var string Testing storage path */ - private string $testDir; - - /** @var string Test disk name */ - private string $testDisk = 'testing'; - - protected Config $config; - - /** - * Setup TestDatabase - */ public function setUp(): void { - // Boot parent TestCase, which will set up the database and connections for us. parent::setUp(); - $this->config = $this->ci->get(Config::class); - - $this->testDir = $this->config->get("filesystems.disks.{$this->testDisk}.root"); + // Setup test config + $config = $this->ci->get(Config::class); + $config->set('filesystems.disks.testing', [ + 'driver' => 'local', + 'root' => 'testing://', + 'url' => 'files/testing/', + ]); + $config->set('filesystems.disks.testingDriver', [ + 'driver' => 'localTest', + 'root' => 'testing://testingDriver', + ]); + + // Set up the locator stream in the testing directory + /** @var ResourceLocatorInterface */ + $locator = $this->ci->get(ResourceLocatorInterface::class); + $locator->addStream(new ResourceStream('testing', __DIR__ . '/storage/testing', true)); } /** @@ -54,8 +51,9 @@ public function setUp(): void */ public function testService(): FilesystemAdapter { - // Force this test to use the testing disk - $this->config->set('filesystems.default', $this->testDisk); + // Set the default filesystem to the testing disk + $config = $this->ci->get(Config::class); + $config->set('filesystems.default', 'testing'); // Filesystem service will return an instance of FilesystemManger $filesystem = $this->ci->get(FilesystemManager::class); @@ -63,23 +61,23 @@ public function testService(): FilesystemAdapter // Main aspect of our FilesystemManager is to adapt our config structure // to Laravel class we'll make sure here the forced config actually works - $this->assertEquals($this->testDisk, $filesystem->getDefaultDriver()); + $this->assertEquals('testing', $filesystem->getDefaultDriver()); // The disk won't return a Manager, but an Adapter. - $disk = $filesystem->disk($this->testDisk); + $disk = $filesystem->disk('testing'); $this->assertInstanceOf(FilesystemAdapter::class, $disk); return $disk; } - /** - * @depends testService - */ - // TODO : Requires reimplementation of Facade - /*public function testFacade(): void + public function testDefaultCloud(): void { - $this->assertInstanceOf(FilesystemAdapter::class, Storage::disk($this->testDisk)); - }*/ + // Set the default cloud to the testing disk + $config = $this->ci->get(Config::class); + $config->set('filesystems.cloud', 'testingDriver'); + $filesystem = $this->ci->get(FilesystemManager::class); + $this->assertEquals('testingDriver', $filesystem->getDefaultCloudDriver()); + } /** * @param FilesystemAdapter $files @@ -87,9 +85,12 @@ public function testService(): FilesystemAdapter */ public function testAdapter(FilesystemAdapter $files): void { + // Test "path", make sure the path is translated correctly via locator + $this->assertEquals(__DIR__ . '/storage/testing/', $files->path('')); + // Test basic "put" $this->assertTrue($files->put('file.txt', 'Something inside')); - $this->assertStringEqualsFile($this->testDir . '/file.txt', 'Something inside'); + $this->assertStringEqualsFile('testing://file.txt', 'Something inside'); // Test "exist" & "get" // We'll assume Laravel test covers the rest ;) @@ -98,7 +99,7 @@ public function testAdapter(FilesystemAdapter $files): void // We'll delete the test file now $this->assertTrue($files->delete('file.txt')); - $this->assertFileDoesNotExist($this->testDir . '/file.txt'); + $this->assertFileDoesNotExist('testing://file.txt'); } /** @@ -127,7 +128,7 @@ public function testUrl(FilesystemAdapter $files): void $url = $files->url('file.txt'); $this->assertEquals('files/testing/file.txt', $url); $this->assertTrue($files->delete('file.txt')); - $this->assertFileDoesNotExist($this->testDir . '/file.txt'); + $this->assertFileDoesNotExist('testing://file.txt'); } /** @@ -149,8 +150,9 @@ public function testNonExistingAdapter(): void public function testAddingAdapter(): void { $filesystemManager = $this->ci->get(FilesystemManager::class); - $filesystemManager->extend('localTest', function ($configService, $config) { + $locator = $this->ci->get(ResourceLocatorInterface::class); + $config['root'] = $locator->findResource($config['root'], all: true); $adapter = new LocalAdapter($config['root']); return new Filesystem($adapter); @@ -160,7 +162,25 @@ public function testAddingAdapter(): void $this->assertInstanceOf(FilesystemAdapter::class, $disk); // Make sure the path was set correctly - $path = $disk->path(''); - $this->assertEquals('storage/testingDriver' . DIRECTORY_SEPARATOR, $path); // N.B.: DIRECTORY_SEPARATOR is required for windows. + $this->assertEquals(__DIR__ . '/storage/testing/testingDriver/', $disk->path('')); + } + + public function testAddingDriver(): void + { + $filesystemManager = $this->ci->get(FilesystemManager::class); + + $adapter = new LocalAdapter(__DIR__ . '/storage/testing/testingDriver'); + $filesystem = new Filesystem($adapter); + $driver = new FilesystemAdapter($filesystem); + + $filesystemManager->extend('localTest', function ($configService, $config) use ($driver) { + return $driver; + }); + + $disk = $filesystemManager->disk('testingDriver'); + $this->assertInstanceOf(FilesystemAdapter::class, $disk); + + // Make sure the path was set correctly + $this->assertEquals(__DIR__ . '/storage/testing/testingDriver/', $disk->path('')); } } diff --git a/app/tests/Integration/Filesystem/storage/.gitkeep b/app/tests/Integration/Filesystem/storage/.gitkeep new file mode 100644 index 00000000..e69de29b