Skip to content

Commit

Permalink
Add fallback path/url support for conversions (#3062)
Browse files Browse the repository at this point in the history
* change the types of fallback properties

* pass the conversion names to the fallback methods

* update tests

* formatting

* formatting

* formatting

* update docs

* update docs

* formatting [docs]
  • Loading branch information
mertasan authored Oct 21, 2022
1 parent b12dc4b commit 2f7db87
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 21 deletions.
43 changes: 43 additions & 0 deletions docs/working-with-media-collections/defining-media-collections.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,49 @@ public function registerMediaCollections(): void
}
```

When you use a fallback URL/path, [conversions](https://spatie.be/docs/laravel-medialibrary/v10/converting-images/defining-conversions) will use the default fallback URL/path if the media do not exist. You can pass a conversion name to the second parameter to use fallbacks per conversion.

```php
use Spatie\MediaLibrary\MediaCollections\Models\Media;

// ...

public function registerMediaCollections(): void
{
$this
->addMediaCollection('avatar')
->useFallbackUrl('/default_avatar.jpg')
->useFallbackUrl('/default_avatar_thumb.jpg', 'thumb')
->useFallbackPath(public_path('/default_avatar.jpg'))
->useFallbackPath(public_path('/default_avatar_thumb.jpg'), 'thumb')
->registerMediaConversions(function (Media $media) {
$this
->addMediaConversion('thumb')
->width(50)
->height(50);

$this
->addMediaConversion('thumb_2')
->width(100)
->height(100);
});
}
```

In this way, the image sizes are always as expected:

```php
$yourModel->getFirstMediaUrl('avatar'); // default_avatar.jpg
$yourModel->getFirstMediaUrl('avatar', 'thumb'); // default_avatar_thumb.jpg
$yourModel->getFirstMediaUrl('avatar', 'thumb_2'); // default_avatar.jpg

// ...

$yourModel->getFirstMediaPath('avatar'); // .../default_avatar.jpg
$yourModel->getFirstMediaPath('avatar', 'thumb'); // .../default_avatar_thumb.jpg
$yourModel->getFirstMediaPath('avatar', 'thumb_2'); // .../default_avatar.jpg
```

## Only allow certain files in a collection

You can pass a callback to `acceptsFile` that will check if a file is allowed into the collection. In this example we only accept `jpeg` files.
Expand Down
26 changes: 19 additions & 7 deletions src/InteractsWithMedia.php
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ public function getFirstMediaUrl(string $collectionName = 'default', string $con
$media = $this->getFirstMedia($collectionName);

if (! $media) {
return $this->getFallbackMediaUrl($collectionName) ?: '';
return $this->getFallbackMediaUrl($collectionName, $conversionName) ?: '';
}

if ($conversionName !== '' && ! $media->hasGeneratedConversion($conversionName)) {
Expand All @@ -317,7 +317,7 @@ public function getFirstTemporaryUrl(
$media = $this->getFirstMedia($collectionName);

if (! $media) {
return $this->getFallbackMediaUrl($collectionName) ?: '';
return $this->getFallbackMediaUrl($collectionName, $conversionName) ?: '';
}

if ($conversionName !== '' && ! $media->hasGeneratedConversion($conversionName)) {
Expand All @@ -342,14 +342,26 @@ public function getMediaCollection(string $collectionName = 'default'): ?MediaCo
->first(fn (MediaCollection $collection) => $collection->name === $collectionName);
}

public function getFallbackMediaUrl(string $collectionName = 'default'): string
public function getFallbackMediaUrl(string $collectionName = 'default', string $conversionName = ''): string
{
return optional($this->getMediaCollection($collectionName))->fallbackUrl ?? '';
$fallbackUrls = optional($this->getMediaCollection($collectionName))->fallbackUrls;

if (in_array($conversionName, ['', 'default'], true)) {
return $fallbackUrls['default'] ?? '';
}

return $fallbackUrls[$conversionName] ?? $fallbackUrls['default'] ?? '';
}

public function getFallbackMediaPath(string $collectionName = 'default'): string
public function getFallbackMediaPath(string $collectionName = 'default', string $conversionName = ''): string
{
return optional($this->getMediaCollection($collectionName))->fallbackPath ?? '';
$fallbackPaths = optional($this->getMediaCollection($collectionName))->fallbackPaths;

if (in_array($conversionName, ['', 'default'], true)) {
return $fallbackPaths['default'] ?? '';
}

return $fallbackPaths[$conversionName] ?? $fallbackPaths['default'] ?? '';
}

/*
Expand All @@ -362,7 +374,7 @@ public function getFirstMediaPath(string $collectionName = 'default', string $co
$media = $this->getFirstMedia($collectionName);

if (! $media) {
return $this->getFallbackMediaPath($collectionName) ?: '';
return $this->getFallbackMediaPath($collectionName, $conversionName) ?: '';
}

if ($conversionName !== '' && ! $media->hasGeneratedConversion($conversionName)) {
Expand Down
22 changes: 16 additions & 6 deletions src/MediaCollections/MediaCollection.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@ class MediaCollection

public bool $singleFile = false;

public string $fallbackUrl = '';
/** @var array<string, string> */
public array $fallbackUrls = [];

public string $fallbackPath = '';
/** @var array<string, string> */
public array $fallbackPaths = [];

public function __construct(
public string $name
Expand Down Expand Up @@ -97,16 +99,24 @@ public function registerMediaConversions(callable $mediaConversionRegistrations)
$this->mediaConversionRegistrations = $mediaConversionRegistrations;
}

public function useFallbackUrl(string $url): self
public function useFallbackUrl(string $url, string $conversionName = ''): self
{
$this->fallbackUrl = $url;
if ($conversionName === '') {
$conversionName = 'default';
}

$this->fallbackUrls[$conversionName] = $url;

return $this;
}

public function useFallbackPath(string $path): self
public function useFallbackPath(string $path, string $conversionName = ''): self
{
$this->fallbackPath = $path;
if ($conversionName === '') {
$conversionName = 'default';
}

$this->fallbackPaths[$conversionName] = $path;

return $this;
}
Expand Down
24 changes: 17 additions & 7 deletions tests/Feature/InteractsWithMedia/GetMediaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -203,13 +203,23 @@
expect($this->testModel->getFirstMediaPath('images'))->toEqual($firstMedia->getPath());
});

it('can get the default path to the first media in a collection', function () {
expect($this->testModel->getFirstMediaPath('avatar'))->toEqual('/default-path.jpg');
});

it('can get the default url to the first media in a collection', function () {
expect($this->testModel->getFirstMediaUrl('avatar'))->toEqual('/default-url.jpg');
});
it('can get the default path to the first media in a collection', function ($conversionName, $expectedPath) {
expect($this->testModel->getFirstMediaPath('avatar', $conversionName))->toEqual($expectedPath);
})->with([
['', '/default-path.jpg'],
['default', '/default-path.jpg'],
['foo', '/default-path.jpg'],
['avatar_thumb', '/default-avatar-thumb-path.jpg'],
]);

it('can get the default url to the first media in a collection', function ($conversionName, $expectedUrl) {
expect($this->testModel->getFirstMediaUrl('avatar', $conversionName))->toEqual($expectedUrl);
})->with([
['', '/default-url.jpg'],
['default', '/default-url.jpg'],
['foo', '/default-url.jpg'],
['avatar_thumb', '/default-avatar-thumb-url.jpg'],
]);

it('can get the default path to the first media in a collection if conversion not marked as generated yet', function () {
$media = $this
Expand Down
4 changes: 3 additions & 1 deletion tests/TestSupport/TestModels/TestModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ public function registerMediaCollections(): void
$this
->addMediaCollection('avatar')
->useFallbackUrl('/default-url.jpg')
->useFallbackPath('/default-path.jpg');
->useFallbackUrl('/default-avatar-thumb-url.jpg', 'avatar_thumb')
->useFallbackPath('/default-path.jpg')
->useFallbackPath('/default-avatar-thumb-path.jpg', 'avatar_thumb');
}
}

0 comments on commit 2f7db87

Please sign in to comment.