|
27 | 27 |
|
28 | 28 | /**
|
29 | 29 | * @see https://supabase.com/docs/guides/storage/s3/compatibility
|
| 30 | + * @see https://github.com/supabase/storage-js/blob/main/src/lib/types.ts |
30 | 31 | *
|
31 | 32 | * Image Transformations:
|
32 | 33 | * @see https://supabase.com/docs/guides/storage/serving/image-transformations#transformation-options
|
33 |
| - * @psalm-type ImageTransformationOptions = array{ |
| 34 | + * @psalm-type TransformOptions = array{ |
34 | 35 | * width?: positive-int,
|
35 | 36 | * height?: positive-int,
|
36 | 37 | * resize?: 'contain'|'cover'|'fill',
|
37 |
| - * format?: 'origin'|'avif', |
38 | 38 | * quality?: int<20, 100>,
|
| 39 | + * format?: 'origin'|'avif', |
| 40 | + * } |
| 41 | + * @psalm-type UrlParameters = array{ |
| 42 | + * download?: string|bool, |
| 43 | + * transform?: TransformOptions, |
| 44 | + * expiresIn?: int, |
39 | 45 | * }
|
40 | 46 | */
|
41 | 47 | final class SupabaseAdapter implements FilesystemAdapter
|
@@ -110,7 +116,7 @@ public function write(string $path, string $contents, Config $config): void
|
110 | 116 | throw UnableToWriteFile::atLocation($path, $res->body());
|
111 | 117 | }
|
112 | 118 |
|
113 |
| - // Delete empty placeholder file if not specified directly |
| 119 | + // Delete an empty placeholder file if not specified directly |
114 | 120 | $filename = pathinfo($path, PATHINFO_BASENAME);
|
115 | 121 | if ($filename !== self::EMPTY_FOLDER_PLACEHOLDER_NAME) {
|
116 | 122 | $dirname = pathinfo($path, PATHINFO_DIRNAME);
|
@@ -431,46 +437,41 @@ public function getUrl(string $path): string
|
431 | 437 |
|
432 | 438 | /**
|
433 | 439 | * @internal
|
434 |
| - * @param array{expiresIn?: int, transform?: ImageTransformationOptions, download?: bool|string, ...} $options |
| 440 | + * @see https://supabase.com/docs/guides/storage/serving/image-transformations?queryGroups=language&language=js#signing-urls-with-transformation-options |
| 441 | + * @psalm-param UrlParameters $options |
435 | 442 | * @throws UnableToGenerateTemporaryUrl
|
436 | 443 | */
|
437 | 444 | public function getSignedUrl(string $path, array $options = []): string
|
438 | 445 | {
|
439 |
| - $options['expiresIn'] ??= $this->config->get('signed_url_ttl,', 3_600); |
440 |
| - $_queryString = ''; |
| 446 | + $url = $this->config->get('url', $this->endpoint); |
441 | 447 |
|
442 |
| - $transformOptions = []; |
443 |
| - if (isset($options['transform'])) { |
444 |
| - $transformOptions = array_merge($transformOptions, $options['transform']); |
445 |
| - unset($options['transform']); |
446 |
| - } |
| 448 | + $apiBody = [ |
| 449 | + 'expiresIn' => $options['expiresIn'] ?? $this->config->get('signed_url_ttl,', 3_600), |
| 450 | + ]; |
447 | 451 |
|
448 |
| - if (Arr::get($options, 'download')) { |
449 |
| - $_queryString = '&download'; |
450 |
| - unset($options['download']); |
| 452 | + if (isset($options['transform'])) { |
| 453 | + $apiBody['transform'] = $options['transform']; |
451 | 454 | }
|
452 | 455 |
|
453 |
| - $response = $this->httpClient->post(sprintf('/object/sign/%s/%s', $this->bucket, $path), $options); |
| 456 | + /** @see https://supabase.github.io/storage/#/object/post_object_sign__bucketName___wildcard_ */ |
| 457 | + $response = $this->httpClient->post(sprintf('/object/sign/%s/%s', $this->bucket, $path), $apiBody); |
454 | 458 | if (!$response->successful() || $response->json('signedURL') === null) {
|
455 | 459 | throw new UnableToGenerateTemporaryUrl($response->body(), $path);
|
456 | 460 | }
|
457 | 461 |
|
458 |
| - $url = $this->config->get('url', $this->endpoint); |
459 | 462 | $signedUrl = $this->joinPaths($url, $response->json('signedURL'));
|
460 | 463 |
|
461 |
| - $transformJson = json_encode($transformOptions); |
462 |
| - if ($transformJson === false) { |
463 |
| - throw new UnableToGenerateTemporaryUrl('Failed to encode transform options', $path); |
| 464 | + if ($download = Arr::get($options, 'download')) { |
| 465 | + $signedUrl .= (str_contains($signedUrl, '?') ? '&' : '?').'download'.(is_string($download) ? "=$download" : ''); |
464 | 466 | }
|
465 | 467 |
|
466 |
| - $signedUrl .= (str_contains($signedUrl, '?') ? '&' : '?').'transform='.$transformJson; |
467 |
| - |
468 |
| - return urldecode($signedUrl.$_queryString); |
| 468 | + return urldecode($signedUrl); |
469 | 469 | }
|
470 | 470 |
|
471 | 471 | /**
|
472 | 472 | * @internal
|
473 |
| - * @param array{transform?: ImageTransformationOptions, download?: bool|string, ...} $options |
| 473 | + * @see https://supabase.com/docs/guides/storage/serving/image-transformations?queryGroups=language&language=js#get-a-public-url-for-a-transformed-image |
| 474 | + * @pslam-param UrlParameters $options |
474 | 475 | * @throws \RuntimeException
|
475 | 476 | */
|
476 | 477 | public function getPublicUrl(string $path, array $options = []): string
|
@@ -506,7 +507,7 @@ public function getPublicUrl(string $path, array $options = []): string
|
506 | 507 | /**
|
507 | 508 | * Laravel's magic method.
|
508 | 509 | * Used by {@see \Illuminate\Filesystem\FilesystemAdapter::temporaryUrl}
|
509 |
| - * @param array<mixed> $options |
| 510 | + * @param UrlParameters $options |
510 | 511 | * @api
|
511 | 512 | */
|
512 | 513 | public function getTemporaryUrl(string $path, \DateTimeInterface $expiration, array $options): string
|
|
0 commit comments