diff --git a/config/services/drivers/google_cloud_storage.yaml b/config/services/drivers/google_cloud_storage.yaml index a43ac44..0f4b3bf 100644 --- a/config/services/drivers/google_cloud_storage.yaml +++ b/config/services/drivers/google_cloud_storage.yaml @@ -6,6 +6,7 @@ services: bind: $storageClient: '@sfs_media.storage.google_cloud.storage_client' $bucket: '%sfs_media.storage.google_cloud_storage.bucket%' + $publicBaseUrl: '%sfs_media.storage.google_cloud_storage.public_base_url%' sfs_media.storage.google_cloud.storage_client: class: Google\Cloud\Storage\StorageClient diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 710af65..ad42397 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -13,7 +13,7 @@ class Configuration implements ConfigurationInterface { private const HELP_AVIF = <<arrayNode('google_cloud_storage') ->children() ->scalarNode('bucket')->end() + ->scalarNode('public_base_url')->defaultNull()->end() ->end() ->end() diff --git a/src/DependencyInjection/SfsMediaExtension.php b/src/DependencyInjection/SfsMediaExtension.php index 4a38fcf..a42644b 100644 --- a/src/DependencyInjection/SfsMediaExtension.php +++ b/src/DependencyInjection/SfsMediaExtension.php @@ -44,6 +44,7 @@ public function load(array $configs, ContainerBuilder $container): void if ('google_cloud_storage' === $config['driver']) { $container->setParameter('sfs_media.storage.google_cloud_storage.bucket', $config['google_cloud_storage']['bucket']); + $container->setParameter('sfs_media.storage.google_cloud_storage.public_base_url', $config['google_cloud_storage']['public_base_url']); $loader->load('drivers/google_cloud_storage.yaml'); } diff --git a/src/Model/MediaVersion.php b/src/Model/MediaVersion.php index e8e951f..db74ba2 100644 --- a/src/Model/MediaVersion.php +++ b/src/Model/MediaVersion.php @@ -101,21 +101,7 @@ public function setUrl(?string $url): void public function getPublicUrl(): ?string { - $url = $this->getUrl(); - - if (!$url) { - return null; - } - - if (str_starts_with($url, 'gs://')) { - return 'https://storage.googleapis.com/'.substr($url, 5); - } - - if (str_starts_with($url, 'sfs-media-filesystem://')) { - return '/media/'.substr($url, 23); - } - - return $url; + return null; // todo if value in database render it (add new field) } public function getWidth(): ?int diff --git a/src/Storage/GoogleCloudStorageDriver.php b/src/Storage/GoogleCloudStorageDriver.php index 5219c4a..471a657 100644 --- a/src/Storage/GoogleCloudStorageDriver.php +++ b/src/Storage/GoogleCloudStorageDriver.php @@ -7,14 +7,8 @@ class GoogleCloudStorageDriver implements StorageDriverInterface { - protected StorageClient $storageClient; - - protected string $bucket; - - public function __construct(StorageClient $storageClient, string $bucket) + public function __construct(protected StorageClient $storageClient, protected string $bucket, protected ?string $publicBaseUrl = null) { - $this->storageClient = $storageClient; - $this->bucket = $bucket; } public function store(File $file, string $destName): string @@ -29,7 +23,7 @@ public function store(File $file, string $destName): string public function remove(string $fileName): void { - if ('gs://' !== substr($fileName, 0, 5)) { + if (!str_starts_with($fileName, 'gs://')) { return; } @@ -45,7 +39,7 @@ public function remove(string $fileName): void public function download(string $fileName, string $destPath): void { - if ('gs://' !== substr($fileName, 0, 5)) { + if (!str_starts_with($fileName, 'gs://')) { return; } @@ -61,10 +55,26 @@ public function download(string $fileName, string $destPath): void public function url(string $fileName): string { - if (str_starts_with($fileName, 'gs://')) { - return 'https://storage.googleapis.com/'.substr($fileName, 5); + if (!str_starts_with($fileName, 'gs://')) { + return $fileName; + } + + $fileName = substr($fileName, 5); + $parts = explode('/', $fileName, 2); + + $bucket = $parts[0]; + $filePath = $parts[1] ?? null; + + $publicBaseUrl = null !== $this->publicBaseUrl ? trim($this->publicBaseUrl) : null; + if ($filePath && '' === $publicBaseUrl) { + return "/$filePath"; + } + + if ($filePath && null !== $publicBaseUrl && 'null' !== strtolower($publicBaseUrl)) { + $publicBaseUrl = rtrim($publicBaseUrl, '/'); + return "$publicBaseUrl/$filePath"; } - return $fileName; + return "https://storage.googleapis.com/$bucket".($filePath ? "/$filePath" : ''); } } diff --git a/tests/Unit/DependencyInjection/ConfigurationTest.php b/tests/Unit/DependencyInjection/ConfigurationTest.php index 66e892f..9251f17 100644 --- a/tests/Unit/DependencyInjection/ConfigurationTest.php +++ b/tests/Unit/DependencyInjection/ConfigurationTest.php @@ -149,4 +149,23 @@ public function testAdvancedConfig() $config['types'] = Configuration::fixConfigTypes($config['types'] ?? null); $this->assertEquals($expected, $config); } + + public function testGoogleCloudStorageConfigWithoutPublicBaseUrl() + { + $configs = [ + 'sfs_media' => [ + 'google_cloud_storage' => [ + 'bucket' => 'media-bucket', + ], + ], + ]; + + $processor = new Processor(); + $configuration = new Configuration(); + $config = $processor->processConfiguration($configuration, $configs); + + $this->assertSame('google_cloud_storage', $config['driver']); + $this->assertSame('media-bucket', $config['google_cloud_storage']['bucket']); + $this->assertNull($config['google_cloud_storage']['public_base_url']); + } } diff --git a/tests/Unit/Storage/GoogleCloudStorageDriverTest.php b/tests/Unit/Storage/GoogleCloudStorageDriverTest.php new file mode 100644 index 0000000..2ab6227 --- /dev/null +++ b/tests/Unit/Storage/GoogleCloudStorageDriverTest.php @@ -0,0 +1,65 @@ +createMock(StorageClient::class), 'media-bucket', $publicBaseUrl); + + $this->assertSame($expectedUrl, $driver->url($storedUrl)); + } + + public function urlProvider(): iterable + { + yield 'non gcs url' => [ + 'https://example.com/image.jpg', + 'https://cdn.example.com/media', + 'https://example.com/image.jpg', + ]; + + yield 'gcs url without public base url' => [ + 'gs://media-bucket/path/to/image.jpg', + null, + 'https://storage.googleapis.com/media-bucket/path/to/image.jpg', + ]; + + yield 'gcs url with public base url' => [ + 'gs://media-bucket/path/to/image.jpg', + 'https://cdn.example.com/media', + 'https://cdn.example.com/media/path/to/image.jpg', + ]; + + yield 'gcs url with trailing slash in public base url' => [ + 'gs://media-bucket/path/to/image.jpg', + 'https://cdn.example.com/media/', + 'https://cdn.example.com/media/path/to/image.jpg', + ]; + + yield 'gcs url with string null public base url' => [ + 'gs://media-bucket/path/to/image.jpg', + 'null', + 'https://storage.googleapis.com/media-bucket/path/to/image.jpg', + ]; + + yield 'gcs url with empty public base url' => [ + 'gs://media-bucket/path/to/image.jpg', + '', + '/path/to/image.jpg', + ]; + + yield 'gcs bucket url without path' => [ + 'gs://media-bucket', + 'https://cdn.example.com/media', + 'https://storage.googleapis.com/media-bucket', + ]; + } +}