diff --git a/src/Illuminate/Filesystem/AwsS3V3Adapter.php b/src/Illuminate/Filesystem/AwsS3V3Adapter.php index 99aad445f45d..0d776115a2b2 100644 --- a/src/Illuminate/Filesystem/AwsS3V3Adapter.php +++ b/src/Illuminate/Filesystem/AwsS3V3Adapter.php @@ -3,6 +3,7 @@ namespace Illuminate\Filesystem; use Aws\S3\S3Client; +use Illuminate\Support\Facades\Storage; use Illuminate\Support\Traits\Conditionable; use League\Flysystem\FilesystemAdapter as FlysystemAdapter; use League\Flysystem\FilesystemOperator; @@ -20,11 +21,6 @@ class AwsS3V3Adapter extends FilesystemAdapter /** * Create a new AwsS3V3FilesystemAdapter instance. - * - * @param \League\Flysystem\FilesystemOperator $driver - * @param \League\Flysystem\FilesystemAdapter $adapter - * @param array $config - * @param \Aws\S3\S3Client $client */ public function __construct(FilesystemOperator $driver, FlysystemAdapter $adapter, array $config, S3Client $client) { @@ -57,6 +53,62 @@ public function url($path) ); } + /** + * If a ZIP File is requested from S3 Storage, + * copy it first to local storage + * and then return the local. + * + * @return string|null + */ + public function get($path) + { + if (str_ends_with($path, '.zip')) { + $localDisk = new Filesystem; + $localDisk->put( + $path, + $this->readStream($path) + ); + + return $localDisk->get($path); + } + + return parent::get($path); + } + + public function path($path) + { + if (str_ends_with($path, '.zip')) { + $localDisk = new Filesystem; + $localDisk->put( + $path, + $this->readStream($path) + ); + + return $path; + } + + return parent::path($path); + } + + public function processFileUsing($path, $closure, ?string $disk = null) + { + $isZip = str_ends_with($path, '.zip'); + if ($isZip) { + $localDisk = new Filesystem; + $localDisk->put( + $path, + $this->readStream($path) + ); + } + try { + return $closure($path); + } finally { + if ($isZip) { + $localDisk->delete($path); + } + } + } + /** * Determine if temporary URLs can be generated. * @@ -72,7 +124,6 @@ public function providesTemporaryUrls() * * @param string $path * @param \DateTimeInterface $expiration - * @param array $options * @return string */ public function temporaryUrl($path, $expiration, array $options = []) @@ -101,7 +152,6 @@ public function temporaryUrl($path, $expiration, array $options = []) * * @param string $path * @param \DateTimeInterface $expiration - * @param array $options * @return array */ public function temporaryUploadUrl($path, $expiration, array $options = []) diff --git a/src/Illuminate/Filesystem/FilesystemAdapter.php b/src/Illuminate/Filesystem/FilesystemAdapter.php index 588f8c66f973..90779c79495b 100644 --- a/src/Illuminate/Filesystem/FilesystemAdapter.php +++ b/src/Illuminate/Filesystem/FilesystemAdapter.php @@ -11,6 +11,7 @@ use Illuminate\Http\Request; use Illuminate\Http\UploadedFile; use Illuminate\Support\Arr; +use Illuminate\Support\Facades\Storage; use Illuminate\Support\Str; use Illuminate\Support\Traits\Conditionable; use Illuminate\Support\Traits\Macroable; @@ -93,10 +94,6 @@ class FilesystemAdapter implements CloudFilesystemContract /** * Create a new filesystem adapter instance. - * - * @param \League\Flysystem\FilesystemOperator $driver - * @param \League\Flysystem\FilesystemAdapter $adapter - * @param array $config */ public function __construct(FilesystemOperator $driver, FlysystemAdapter $adapter, array $config = []) { @@ -314,7 +311,6 @@ public function json($path, $flags = 0) * * @param string $path * @param string|null $name - * @param array $headers * @param string|null $disposition * @return \Symfony\Component\HttpFoundation\StreamedResponse */ @@ -349,10 +345,8 @@ public function response($path, $name = null, array $headers = [], $disposition /** * Create a streamed download response for a given file. * - * @param \Illuminate\Http\Request $request * @param string $path * @param string|null $name - * @param array $headers * @return \Symfony\Component\HttpFoundation\StreamedResponse */ public function serve(Request $request, $path, $name = null, array $headers = []) @@ -367,7 +361,6 @@ public function serve(Request $request, $path, $name = null, array $headers = [] * * @param string $path * @param string|null $name - * @param array $headers * @return \Symfony\Component\HttpFoundation\StreamedResponse */ public function download($path, $name = null, array $headers = []) @@ -798,7 +791,6 @@ public function providesTemporaryUrls() * * @param string $path * @param \DateTimeInterface $expiration - * @param array $options * @return string * * @throws \RuntimeException @@ -823,7 +815,6 @@ public function temporaryUrl($path, $expiration, array $options = []) * * @param string $path * @param \DateTimeInterface $expiration - * @param array $options * @return array * * @throws \RuntimeException @@ -1023,7 +1014,6 @@ protected function parseVisibility($visibility) /** * Define a custom callback that generates file download responses. * - * @param \Closure $callback * @return void */ public function serveUsing(Closure $callback) @@ -1034,7 +1024,6 @@ public function serveUsing(Closure $callback) /** * Define a custom temporary URL builder callback. * - * @param \Closure $callback * @return void */ public function buildTemporaryUrlsUsing(Closure $callback) @@ -1043,9 +1032,21 @@ public function buildTemporaryUrlsUsing(Closure $callback) } /** - * Determine if Flysystem exceptions should be thrown. + * This method accepts a closure to process the given Path. * - * @return bool + * @return mixed + */ + public function processFileUsing(string $path, Closure $closure, ?string $disk = null) + { + if ($disk) { + return Storage::disk($disk)->processFileUsing($path, $closure); + } + + return $closure($this->path($path)); + } + + /** + * Determine if Flysystem exceptions should be thrown. */ protected function throwsExceptions(): bool { @@ -1067,8 +1068,6 @@ protected function report($exception) /** * Determine if Flysystem exceptions should be reported. - * - * @return bool */ protected function shouldReport(): bool { diff --git a/tests/Filesystem/AwsS3V3AdapterTest.php b/tests/Filesystem/AwsS3V3AdapterTest.php new file mode 100644 index 000000000000..74fa623ccd0b --- /dev/null +++ b/tests/Filesystem/AwsS3V3AdapterTest.php @@ -0,0 +1,134 @@ +tempDir = __DIR__.'/tmp'; + $this->filesystem = new Filesystem( + $this->adapter = new LocalFilesystemAdapter($this->tempDir) + ); + } + + protected function tearDown(): void + { + $filesystem = new Filesystem( + $this->adapter = new LocalFilesystemAdapter(dirname($this->tempDir)) + ); + $filesystem->deleteDirectory(basename($this->tempDir)); + m::close(); + + unset($this->tempDir, $this->filesystem, $this->adapter); + } + + public function test_process_file_using_callback_returns_expected_values_for_s3_adapter_with_zip_file() + { + $filesystem = new FilesystemManager(new Application); + + $filesystemAdapter = $filesystem->createS3Driver([ + 'region' => 'us-west-1', + 'bucket' => 'laravel', + ]); + + $receivedPath = null; + + $result = $filesystemAdapter->processFileUsing('archive.zip', function ($path) use (&$receivedPath) { + $receivedPath = $path; + + return 'processed-zip'; + }); + + $this->assertSame('processed-zip', $result); + + $this->assertNotNull($receivedPath); + $this->assertStringEndsWith('archive.zip', $receivedPath); + } + + public function test_get_copies_zip_file_from_s3_to_local_and_returns_contents() + { + /** @var AwsS3V3Adapter|m\MockInterface $adapter */ + $adapter = m::mock(AwsS3V3Adapter::class)->makePartial(); + + $stream = fopen('php://temp', 'r+'); + fwrite($stream, 'zip-contents'); + rewind($stream); + + $adapter->shouldReceive('readStream') + ->once() + ->with('archive.zip') + ->andReturn($stream); + + $adapter->shouldReceive('get')->passthru()->byDefault(); + + $result = $adapter->get('archive.zip'); + + $this->assertSame('zip-contents', $result); + } + + public function test_get_falls_back_to_parent_get_for_non_zip_files() + { + /** @var AwsS3V3Adapter|m\MockInterface $adapter */ + $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter); + $adapter = $this->createConfiguredMock(AwsS3V3Adapter::class, [ + 'get' => $filesystemAdapter->get('file.txt'), + ]); + + $this->assertNull($adapter->get('file.txt')); + } + + public function test_path_copies_zip_file_from_s3_to_local_and_returns_original_path() + { + /** @var AwsS3V3Adapter|m\MockInterface $adapter */ + $adapter = m::mock(AwsS3V3Adapter::class)->makePartial(); + + $stream = fopen('php://temp', 'r+'); + fwrite($stream, 'zip-contents'); + rewind($stream); + + $adapter->shouldReceive('readStream') + ->once() + ->with('archive.zip') + ->andReturn($stream); + + $adapter->shouldReceive('path')->passthru()->byDefault(); + + $result = $adapter->path('archive.zip'); + + $this->assertSame('archive.zip', $result); + } + + public function test_path_falls_back_to_parent_path_for_non_zip_files() + { + $filesystem = new Filesystem( + $this->adapter = new LocalFilesystemAdapter($this->tempDir) + ); + + $filesystemAdapter = new FilesystemAdapter($filesystem, $this->adapter, [ + 'root' => $this->tempDir.DIRECTORY_SEPARATOR, + ]); + + $this->filesystem->write('file.txt', 'Hello World'); + + $this->assertEquals( + $this->tempDir.DIRECTORY_SEPARATOR.'file.txt', + $filesystemAdapter->path('file.txt') + ); + } +} diff --git a/tests/Filesystem/FilesystemAdapterTest.php b/tests/Filesystem/FilesystemAdapterTest.php index 284cc7fdbcbf..01104f27e687 100644 --- a/tests/Filesystem/FilesystemAdapterTest.php +++ b/tests/Filesystem/FilesystemAdapterTest.php @@ -26,7 +26,9 @@ class FilesystemAdapterTest extends TestCase { private $tempDir; + private $filesystem; + private $adapter; protected function setUp(): void @@ -48,7 +50,7 @@ protected function tearDown(): void unset($this->tempDir, $this->filesystem, $this->adapter); } - public function testResponse() + public function test_response() { $this->filesystem->write('file.txt', 'Hello World'); $files = new FilesystemAdapter($this->filesystem, $this->adapter); @@ -63,7 +65,7 @@ public function testResponse() $this->assertSame('inline; filename=file.txt', $response->headers->get('content-disposition')); } - public function testMimeTypeIsNotCalledAlreadyProvidedToResponse() + public function test_mime_type_is_not_called_already_provided_to_response() { $this->filesystem->write('file.txt', 'Hello World'); @@ -75,7 +77,7 @@ public function testMimeTypeIsNotCalledAlreadyProvidedToResponse() ]); } - public function testSizeIsNotCalledAlreadyProvidedToResponse() + public function test_size_is_not_called_already_provided_to_response() { $this->filesystem->write('file.txt', 'Hello World'); @@ -87,7 +89,7 @@ public function testSizeIsNotCalledAlreadyProvidedToResponse() ]); } - public function testFallbackNameCalledAlreadyProvidedToResponse() + public function test_fallback_name_called_already_provided_to_response() { $this->filesystem->write('file.txt', 'Hello World'); @@ -101,7 +103,7 @@ public function testFallbackNameCalledAlreadyProvidedToResponse() ]); } - public function testDownload() + public function test_download() { $this->filesystem->write('file.txt', 'Hello World'); $files = new FilesystemAdapter($this->filesystem, $this->adapter); @@ -110,7 +112,7 @@ public function testDownload() $this->assertSame('attachment; filename=hello.txt', $response->headers->get('content-disposition')); } - public function testDownloadNonAsciiFilename() + public function test_download_non_ascii_filename() { $this->filesystem->write('file.txt', 'Hello World'); $files = new FilesystemAdapter($this->filesystem, $this->adapter); @@ -119,7 +121,7 @@ public function testDownloadNonAsciiFilename() $this->assertSame("attachment; filename=privet.txt; filename*=utf-8''%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82.txt", $response->headers->get('content-disposition')); } - public function testDownloadNonAsciiEmptyFilename() + public function test_download_non_ascii_empty_filename() { $this->filesystem->write('привет.txt', 'Hello World'); $files = new FilesystemAdapter($this->filesystem, $this->adapter); @@ -128,7 +130,7 @@ public function testDownloadNonAsciiEmptyFilename() $this->assertSame('attachment; filename=privet.txt; filename*=utf-8\'\'%D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82.txt', $response->headers->get('content-disposition')); } - public function testDownloadPercentInFilename() + public function test_download_percent_in_filename() { $this->filesystem->write('Hello%World.txt', 'Hello World'); $files = new FilesystemAdapter($this->filesystem, $this->adapter); @@ -137,7 +139,7 @@ public function testDownloadPercentInFilename() $this->assertSame('attachment; filename=HelloWorld.txt; filename*=utf-8\'\'Hello%25World.txt', $response->headers->get('content-disposition')); } - public function testExists() + public function test_exists() { $this->filesystem->write('file.txt', 'Hello World'); $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter); @@ -145,27 +147,27 @@ public function testExists() $this->assertTrue($filesystemAdapter->fileExists('file.txt')); } - public function testMissing() + public function test_missing() { $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter); $this->assertTrue($filesystemAdapter->missing('file.txt')); $this->assertTrue($filesystemAdapter->fileMissing('file.txt')); } - public function testDirectoryExists() + public function test_directory_exists() { $this->filesystem->write('/foo/bar/file.txt', 'Hello World'); $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter); $this->assertTrue($filesystemAdapter->directoryExists('/foo/bar')); } - public function testDirectoryMissing() + public function test_directory_missing() { $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter); $this->assertTrue($filesystemAdapter->directoryMissing('/foo/bar')); } - public function testPath() + public function test_path() { $this->filesystem->write('file.txt', 'Hello World'); $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter, [ @@ -174,48 +176,48 @@ public function testPath() $this->assertEquals($this->tempDir.DIRECTORY_SEPARATOR.'file.txt', $filesystemAdapter->path('file.txt')); } - public function testGet() + public function test_get() { $this->filesystem->write('file.txt', 'Hello World'); $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter); $this->assertSame('Hello World', $filesystemAdapter->get('file.txt')); } - public function testGetFileNotFound() + public function test_get_file_not_found() { $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter); $this->assertNull($filesystemAdapter->get('file.txt')); } - public function testJsonReturnsDecodedJsonData() + public function test_json_returns_decoded_json_data() { $this->filesystem->write('file.json', '{"foo": "bar"}'); $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter); $this->assertSame(['foo' => 'bar'], $filesystemAdapter->json('file.json')); } - public function testJsonReturnsNullIfJsonDataIsInvalid() + public function test_json_returns_null_if_json_data_is_invalid() { $this->filesystem->write('file.json', '{"foo":'); $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter); $this->assertNull($filesystemAdapter->json('file.json')); } - public function testMimeTypeNotDetected() + public function test_mime_type_not_detected() { $this->filesystem->write('unknown.mime-type', ''); $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter); $this->assertFalse($filesystemAdapter->mimeType('unknown.mime-type')); } - public function testPut() + public function test_put() { $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter); $filesystemAdapter->put('file.txt', 'Something inside'); $this->assertStringEqualsFile($this->tempDir.'/file.txt', 'Something inside'); } - public function testPrepend() + public function test_prepend() { file_put_contents($this->tempDir.'/file.txt', 'World'); $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter); @@ -223,7 +225,7 @@ public function testPrepend() $this->assertStringEqualsFile($this->tempDir.'/file.txt', 'Hello '.PHP_EOL.'World'); } - public function testAppend() + public function test_append() { file_put_contents($this->tempDir.'/file.txt', 'Hello '); $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter); @@ -231,7 +233,7 @@ public function testAppend() $this->assertStringEqualsFile($this->tempDir.'/file.txt', 'Hello '.PHP_EOL.'Moon'); } - public function testDelete() + public function test_delete() { file_put_contents($this->tempDir.'/file.txt', 'Hello World'); $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter); @@ -239,13 +241,13 @@ public function testDelete() Assert::assertFileDoesNotExist($this->tempDir.'/file.txt'); } - public function testDeleteReturnsTrueWhenFileNotFound() + public function test_delete_returns_true_when_file_not_found() { $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter); $this->assertTrue($filesystemAdapter->delete('file.txt')); } - public function testCopy() + public function test_copy() { $data = '33232'; mkdir($this->tempDir.'/foo'); @@ -261,7 +263,7 @@ public function testCopy() $this->assertEquals($data, file_get_contents($this->tempDir.'/foo/foo2.txt')); } - public function testMove() + public function test_move() { $data = '33232'; mkdir($this->tempDir.'/foo'); @@ -276,7 +278,7 @@ public function testMove() $this->assertEquals($data, file_get_contents($this->tempDir.'/foo/foo2.txt')); } - public function testStream() + public function test_stream() { $this->filesystem->write('file.txt', $original_content = 'Hello World'); $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter); @@ -285,7 +287,7 @@ public function testStream() $this->assertEquals($original_content, $filesystemAdapter->get('copy.txt')); } - public function testStreamBetweenFilesystems() + public function test_stream_between_filesystems() { $secondFilesystem = new Filesystem(new LocalFilesystemAdapter($this->tempDir.'/second')); $this->filesystem->write('file.txt', $original_content = 'Hello World'); @@ -296,7 +298,7 @@ public function testStreamBetweenFilesystems() $this->assertEquals($original_content, $secondFilesystemAdapter->get('copy.txt')); } - public function testStreamToExistingFileOverwrites() + public function test_stream_to_existing_file_overwrites() { $this->filesystem->write('file.txt', 'Hello World'); $this->filesystem->write('existing.txt', 'Dear Kate'); @@ -306,20 +308,20 @@ public function testStreamToExistingFileOverwrites() $this->assertSame('Hello World', $filesystemAdapter->read('existing.txt')); } - public function testReadStreamNonExistentFileReturnsNull() + public function test_read_stream_non_existent_file_returns_null() { $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter); $this->assertNull($filesystemAdapter->readStream('nonexistent.txt')); } - public function testStreamInvalidResourceThrows() + public function test_stream_invalid_resource_throws() { $this->expectException(InvalidArgumentException::class); $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter); $filesystemAdapter->writeStream('file.txt', 'foo bar'); } - public function testPutWithStreamInterface() + public function test_put_with_stream_interface() { file_put_contents($this->tempDir.'/foo.txt', 'some-data'); @@ -332,7 +334,7 @@ public function testPutWithStreamInterface() $this->assertSame('some-data', $filesystemAdapter->get('bar.txt')); } - public function testPutFileAs() + public function test_put_file_as() { file_put_contents($filePath = $this->tempDir.'/foo.txt', 'uploaded file content'); @@ -356,7 +358,7 @@ public function testPutFileAs() ); } - public function testPutFileAsWithAbsoluteFilePath() + public function test_put_file_as_with_absolute_file_path() { file_put_contents($filePath = $this->tempDir.'/foo.txt', 'normal file content'); @@ -367,7 +369,7 @@ public function testPutFileAsWithAbsoluteFilePath() $this->assertSame('normal file content', $filesystemAdapter->read($storagePath)); } - public function testPutFileAsWithoutPath() + public function test_put_file_as_without_path() { file_put_contents($filePath = $this->tempDir.'/foo.txt', 'normal file content'); @@ -378,7 +380,7 @@ public function testPutFileAsWithoutPath() $this->assertSame('normal file content', $filesystemAdapter->read($storagePath)); } - public function testPutFile() + public function test_put_file() { file_put_contents($filePath = $this->tempDir.'/foo.txt', 'uploaded file content'); @@ -400,7 +402,7 @@ public function testPutFile() ); } - public function testPutFileWithAbsoluteFilePath() + public function test_put_file_with_absolute_file_path() { file_put_contents($filePath = $this->tempDir.'/foo.txt', 'uploaded file content'); @@ -418,7 +420,7 @@ public function testPutFileWithAbsoluteFilePath() ); } - public function testPutFileWithoutPath() + public function test_put_file_without_path() { file_put_contents($filePath = $this->tempDir.'/foo.txt', 'normal file content'); @@ -430,7 +432,7 @@ public function testPutFileWithoutPath() } #[RequiresPhpExtension('ftp')] - public function testCreateFtpDriver() + public function test_create_ftp_driver() { $filesystem = new FilesystemManager(new Application); @@ -449,7 +451,7 @@ public function testCreateFtpDriver() $this->assertSame('admin', $config['username']); } - public function testMacroable() + public function test_macroable() { $this->filesystem->write('foo.txt', 'Hello World'); @@ -461,7 +463,7 @@ public function testMacroable() $this->assertSame('Hello World', $filesystemAdapter->getFoo()); } - public function testTemporaryUrlWithCustomCallback() + public function test_temporary_url_with_custom_callback() { $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter); @@ -479,7 +481,7 @@ public function testTemporaryUrlWithCustomCallback() ); } - public function testThrowExceptionsForGet() + public function test_throw_exceptions_for_get() { $adapter = new FilesystemAdapter($this->filesystem, $this->adapter, ['throw' => true]); @@ -494,7 +496,7 @@ public function testThrowExceptionsForGet() $this->fail('Exception was not thrown.'); } - public function testThrowExceptionsForReadStream() + public function test_throw_exceptions_for_read_stream() { $adapter = new FilesystemAdapter($this->filesystem, $this->adapter, ['throw' => true]); @@ -509,7 +511,7 @@ public function testThrowExceptionsForReadStream() $this->fail('Exception was not thrown.'); } - public function testThrowExceptionsForPut() + public function test_throw_exceptions_for_put() { $this->filesystem->write('foo.txt', 'Hello World'); @@ -530,7 +532,7 @@ public function testThrowExceptionsForPut() $this->fail('Exception was not thrown.'); } - public function testThrowExceptionsForMimeType() + public function test_throw_exceptions_for_mime_type() { $this->filesystem->write('unknown.mime-type', ''); @@ -547,7 +549,7 @@ public function testThrowExceptionsForMimeType() $this->fail('Exception was not thrown.'); } - public function testReportExceptionsForGet() + public function test_report_exceptions_for_get() { $container = Container::getInstance(); @@ -575,7 +577,7 @@ public function testReportExceptionsForGet() } } - public function testReportExceptionsForReadStream() + public function test_report_exceptions_for_read_stream() { $container = Container::getInstance(); @@ -603,7 +605,7 @@ public function testReportExceptionsForReadStream() } } - public function testReportExceptionsForPut() + public function test_report_exceptions_for_put() { $container = Container::getInstance(); @@ -637,7 +639,7 @@ public function testReportExceptionsForPut() } } - public function testReportExceptionsForMimeType() + public function test_report_exceptions_for_mime_type() { $container = Container::getInstance(); @@ -667,7 +669,7 @@ public function testReportExceptionsForMimeType() } } - public function testGetAllFiles() + public function test_get_all_files() { $this->filesystem->write('body.txt', 'Hello World'); $this->filesystem->write('file1.txt', 'Hello World'); @@ -679,7 +681,7 @@ public function testGetAllFiles() $this->assertSame($filesystemAdapter->files(), ['body.txt', 'existing.txt', 'file.txt', 'file1.txt']); } - public function testProvidesTemporaryUrls() + public function test_provides_temporary_urls() { $localAdapter = new class($this->tempDir) extends LocalFilesystemAdapter { @@ -693,7 +695,7 @@ public function getTemporaryUrl($path, Carbon $expiration, $options): string $this->assertTrue($filesystemAdapter->providesTemporaryUrls()); } - public function testProvidesTemporaryUrlsWithCustomCallback() + public function test_provides_temporary_urls_with_custom_callback() { $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter); @@ -704,7 +706,7 @@ public function testProvidesTemporaryUrlsWithCustomCallback() $this->assertTrue($filesystemAdapter->providesTemporaryUrls()); } - public function testProvidesTemporaryUrlsForS3Adapter() + public function test_provides_temporary_urls_for_s3_adapter() { $filesystem = new FilesystemManager(new Application); $filesystemAdapter = $filesystem->createS3Driver([ @@ -715,7 +717,7 @@ public function testProvidesTemporaryUrlsForS3Adapter() $this->assertTrue($filesystemAdapter->providesTemporaryUrls()); } - public function testUsesRightSeperatorForS3Adapter() + public function test_uses_right_seperator_for_s3_adapter() { $filesystem = new FilesystemManager(new Application); $filesystemAdapter = $filesystem->createS3Driver([ @@ -730,21 +732,21 @@ public function testUsesRightSeperatorForS3Adapter() $this->assertStringNotContainsString('\\', $path); } - public function testProvidesTemporaryUrlsForAdapterWithoutTemporaryUrlSupport() + public function test_provides_temporary_urls_for_adapter_without_temporary_url_support() { $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter); $this->assertFalse($filesystemAdapter->providesTemporaryUrls()); } - public function testPrefixesUrls() + public function test_prefixes_urls() { $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter, ['url' => 'https://example.org/', 'prefix' => 'images']); $this->assertEquals('https://example.org/images/picture.jpeg', $filesystemAdapter->url('picture.jpeg')); } - public function testGetChecksum() + public function test_get_checksum() { $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter); $filesystemAdapter->write('path.txt', 'contents of file'); @@ -753,7 +755,7 @@ public function testGetChecksum() $this->assertEquals('a5c3556d', $filesystemAdapter->checksum('path.txt', ['checksum_algo' => 'crc32'])); } - public function testUsesRightSeperatorForS3AdapterWithoutDoublePrefixing() + public function test_uses_right_seperator_for_s3_adapter_without_double_prefixing() { $filesystem = new FilesystemManager(new Application); $filesystemAdapter = $filesystem->createS3Driver([ @@ -767,4 +769,41 @@ public function testUsesRightSeperatorForS3AdapterWithoutDoublePrefixing() $path = $filesystemAdapter->path('different'); $this->assertEquals('my-root/someprefix/different', $path); } + + public function test_process_file_using_callback_receives_path_and_returns_value() + { + $filesystemAdapter = new FilesystemAdapter($this->filesystem, $this->adapter); + + $receivedPath = null; + + $result = $filesystemAdapter->processFileUsing('mypath', function ($path) use (&$receivedPath) { + $receivedPath = $path; + + return 'myotherpath'; + }); + + $this->assertSame('myotherpath', $result); + $this->assertSame('mypath', $receivedPath); + } + + public function test_process_file_using_callback_returns_expected_values_for_s3_adapter() + { + $filesystem = new FilesystemManager(new Application); + + $filesystemAdapter = $filesystem->createS3Driver([ + 'region' => 'us-west-1', + 'bucket' => 'laravel', + ]); + + $receivedPath = null; + + $result = $filesystemAdapter->processFileUsing('mypath', function ($path) use (&$receivedPath) { + $receivedPath = $path; + + return 'myotherpath'; + }); + + $this->assertSame('myotherpath', $result); + $this->assertSame('mypath', $receivedPath); + } }