Skip to content

Commit

Permalink
Added option to set a limit for MediaCollections (#1533)
Browse files Browse the repository at this point in the history
* Added option to set a limit for MediaCollections with BC for singleFile() method

* Stylefix

* Changed type declaration for

* Changed type declaration for

* Small change to the docs to improve a sentence

* Updated docs: now has a seperate example for onlyKeepLatest

* Assert that the first file no longer is in the collection after adding the Nth+1 file

* Stylefix
  • Loading branch information
joshuadegier authored and freekmurze committed Aug 21, 2019
1 parent 7e5b22f commit dcdb910
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 5 deletions.
29 changes: 29 additions & 0 deletions docs/working-with-media-collections/defining-media-collections.md
Expand Up @@ -127,6 +127,35 @@ $yourModel->getMedia('avatar')->count(); // returns 1
$yourModel->getFirstMediaUrl('avatar'); // will return an url to the `$anotherPathToImage` file
```

## Limited file collections

Whenever you want to limit the amount of files inside a collection you can use the `onlyKeepLatests(n)` method. Whenever you add a file to a collection and exceed the given limit, Medialibrary will delete the oldest file(s) and keep the collection size at `n`.

```php
// in your model

public function registerMediaCollections()
{
$this
->addMediaCollection('limited-collection')
->onlyKeepLatests(3);
}
```

For the first 3 files, nothing strange happens. The files get added to the collection and the collection now holds all 3 files. Whenever you decide to add a 4th file, Medialibrary deletes the first file and keeps the latest 3.

```php
$yourModel->addMedia($firstFile)->toMediaCollection('limited-collection');
$yourModel->getMedia('avatar')->count(); // returns 1
$yourModel->addMedia($secondFile)->toMediaCollection('limited-collection');
$yourModel->getMedia('avatar')->count(); // returns 2
$yourModel->addMedia($thirdFile)->toMediaCollection('limited-collection');
$yourModel->getMedia('avatar')->count(); // returns 3
$yourModel->addMedia($fourthFile)->toMediaCollection('limited-collection');
$yourModel->getMedia('avatar')->count(); // returns 3
$yourModel->getFirstMediaUrl('avatar'); // will return an url to the `$secondFile` file
```

## Registering media conversions

It's recommended that your first read the section on [converting images](/laravel-medialibrary/v7/converting-images/defining-conversions) before reading the following paragraphs.
Expand Down
8 changes: 6 additions & 2 deletions src/FileAdder/FileAdder.php
Expand Up @@ -325,8 +325,12 @@ protected function processMediaItem(HasMedia $model, Media $media, self $fileAdd
dispatch($job);
}

if (optional($this->getMediaCollection($media->collection_name))->singleFile) {
$model->clearMediaCollectionExcept($media->collection_name, $media);
if ($collectionSizeLimit = optional($this->getMediaCollection($media->collection_name))->collectionSizeLimit) {
$collectionMedia = $this->subject->fresh()->getMedia($media->collection_name);

if ($collectionMedia->count() > $collectionSizeLimit) {
$model->clearMediaCollectionExcept($media->collection_name, $collectionMedia->reverse()->take($collectionSizeLimit));
}
}
}

Expand Down
11 changes: 8 additions & 3 deletions src/MediaCollection/MediaCollection.php
Expand Up @@ -20,8 +20,8 @@ class MediaCollection
/** @var callable */
public $acceptsFile;

/** @var bool */
public $singleFile = false;
/** @var int */
public $collectionSizeLimit = false;

/** @var string */
public $fallbackUrl = '';
Expand Down Expand Up @@ -62,7 +62,12 @@ public function acceptsFile(callable $acceptsFile): self

public function singleFile(): self
{
$this->singleFile = true;
return $this->onlyKeepLatest(1);
}

public function onlyKeepLatest(int $int): self
{
$this->collectionSizeLimit = $int;

return $this;
}
Expand Down
26 changes: 26 additions & 0 deletions tests/Feature/FileAdder/MediaConversions/MediaCollectionTest.php
Expand Up @@ -170,9 +170,35 @@ public function registerMediaCollections()

$model = $testModel::create(['name' => 'testmodel']);

$model->addMedia($this->getTestJpg())->preservingOriginal()->toMediaCollection('images');
$model->addMedia($this->getTestJpg())->preservingOriginal()->toMediaCollection('images');
$model->addMedia($this->getTestJpg())->preservingOriginal()->toMediaCollection('images');

$this->assertCount(1, $model->getMedia('images'));
}

/** @test */
public function if_the_only_keeps_latest_method_is_specified_it_will_delete_all_other_media_and_will_only_keep_the_latest_n_ones()
{
$testModel = new class extends TestModelWithConversion {
public function registerMediaCollections()
{
$this
->addMediaCollection('images')
->onlyKeepLatest(3);
}
};

$model = $testModel::create(['name' => 'testmodel']);

$firstFile = $model->addMedia($this->getTestJpg())->preservingOriginal()->toMediaCollection('images');
$model->addMedia($this->getTestJpg())->preservingOriginal()->toMediaCollection('images');
$model->addMedia($this->getTestJpg())->preservingOriginal()->toMediaCollection('images');
$model->addMedia($this->getTestJpg())->preservingOriginal()->toMediaCollection('images');

$this->assertFalse($model->getMedia('images')->contains(function ($model) use ($firstFile) {
return $model->is($firstFile);
}));
$this->assertCount(3, $model->getMedia('images'));
}
}

1 comment on commit dcdb910

@francoism90
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been well tested? It does sound pretty dangerous and I don't want to lose files in my collection.

Thanks.

Please sign in to comment.