Skip to content

Commit

Permalink
auto delete media with model
Browse files Browse the repository at this point in the history
  • Loading branch information
QuentinGab committed Mar 27, 2024
1 parent c57880a commit a0fced0
Show file tree
Hide file tree
Showing 6 changed files with 298 additions and 27 deletions.
88 changes: 62 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
[![Total Downloads](https://img.shields.io/packagist/dt/finller/laravel-media.svg?style=flat-square)](https://packagist.org/packages/finller/laravel-media)

This package provide an extremly flexible media library, allowing you to store any files with their conversions (nested conversions are supported).
It is designed to be usable with local upload/conversions and with cloud upload/conversions solutions like Bunny.net, AWS MediaConvert, Transloadit, ...
It is designed to be usable with local upload/conversions and with cloud upload/conversions solutions like Bunny.net, AWS S3/MediaConvert, Transloadit, ...

It takes its inspiration from the wonderful `spatie/laravel-media-library` package (check spatie packages, they are really great),but it's not a fork.
The migration from `spatie/laravel-media-library` is possible but not that easy if you want to keep your conversions files.
Expand All @@ -19,7 +19,7 @@ You can install the package via composer:
composer require finller/laravel-media
```

You can publish and run the migrations with:
You have to publish and run the migrations with:

```bash
php artisan vendor:publish --tag="laravel-media-migrations"
Expand All @@ -35,6 +35,9 @@ php artisan vendor:publish --tag="laravel-media-config"
This is the contents of the published config file:

```php
// config for Finller/Media

use Finller\Media\Jobs\DeleteModelMediaJob;
use Finller\Media\Models\Media;

return [
Expand All @@ -48,6 +51,26 @@ return [
*/
'disk' => env('MEDIA_DISK', env('FILESYSTEM_DISK', 'local')),

/**
* Control if media should be deleted with the model
* when using the HasMedia Trait
*/
'delete_media_with_model' => true,

/**
* Control if media should be deleted with the model
* when soft deleted
*/
'delete_media_with_trashed_model' => false,

/**
* Deleting a lot of media related to a model can take some time
* or even fail (cloud api error, permissions, ...)
* For performance and monitoring, when a model with HasMedia trait is deleted,
* each media is individually deleted inside a job.
*/
'delete_media_with_model_job' => DeleteModelMediaJob::class,

/**
* The default collection name
*/
Expand Down Expand Up @@ -105,15 +128,27 @@ There are 2 important concepts to understand, both are tied to the Model associa
For exemple: avatar, thumbnail, upload, ... are media collections.
- Media Conversion: Define a file conversion of a media.
For exemple: A 720p version of a larger 1440p video, a webp conversion or a png image, ... Are media conversion.
A Media conversion can have media conversion too!
A Media conversion can have media conversions too!

## Preparing your models

This package is designed to associate media to a model.
This package is designed to associate media to a model but can also be used without model association.

### Registering your media collections

First you need to add the `HasMedia` trait to your Model.
First you need to add the `HasMedia` trait to your Model:

```php
namespace App\Models;

use Finller\Media\Traits\HasMedia;
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
use HasMedia;
}
```

Then you can define your Media collection and Media conversion like in this exemple:

Expand All @@ -125,7 +160,7 @@ use Finller\Media\MediaCollection;
use Finller\Media\Enums\MediaType;
use Finller\Media\Support\ResponsiveImagesConversionsPreset;
use Finller\Media\Support\VideoPosterConversionPreset;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;

class Post extends Model
Expand Down Expand Up @@ -155,11 +190,6 @@ class Post extends Model

return $collections;
}

public function registerMediaConversions(Media $media): Collection
{
return collect();
}
}
```

Expand All @@ -171,12 +201,20 @@ Media conversions are run through Laravel Jobs, you can do anything in the job a
- Your job define a `run` method.
- Your job call '$this->media->storeConversion(...)`.

Let's take a look at a common Media conversion: Optimizing an image.
Let's take a look at a common media conversion task: Optimizing an image.

The following job is already provided by this package, but it's a great introduction to the concept:
> [!NOTE]
> The following job is already provided by this package, but it's a great introduction to the concept
```php
namespace Finller\Media\Jobs;
namespace App\Jobs\Media;

use Finller\Media\Jobs\ConversionJob;
use Finller\Media\Models\Media;
use Illuminate\Support\Facades\File;
use Spatie\Image\Enums\Fit;
use Spatie\Image\Image;
use Spatie\ImageOptimizer\OptimizerChain;

class OptimizedImageConversionJob extends ConversionJob
{
Expand Down Expand Up @@ -229,13 +267,14 @@ This media conversion Job can now be registered in you Model like that:
namespace App\Models;

use Finller\Media\Traits\HasMedia;
use Finller\Media\MediaCollection;
use Finller\Media\MediaConversion;
use Finller\Media\Jobs\OptimizedImageConversionJob;
use Finller\Media\Enums\MediaType;

use Spatie\Image\Enums\Fit;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Spatie\Image\Enums\Fit;
use \App\Jobs\Media\OptimizedImageConversionJob;
use Finller\Media\Models\Media;

class Post extends Model
{
Expand Down Expand Up @@ -269,16 +308,13 @@ class Post extends Model
}
```

#### Media Conversion presets

This package provide common presets for your conversions to make your life easy when converting files:
#### Common media conversions

-
This package provide common jobs for your conversions to make your life easier:

```php
$Media = new Finller\Media();
echo $Media->echoPhrase('Hello, Finller!');
```
- `VideoPosterConversionJob` will extract a poster using ffmpeg.
- `OptimizedVideoConversionJob` will optimize, resize or convert any video using ffmpeg.
- `OptimizedImageConversionJob` will optimize, resize or convert any image using spatie/image.

## Testing

Expand Down
21 changes: 21 additions & 0 deletions config/media.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

// config for Finller/Media

use Finller\Media\Jobs\DeleteModelMediaJob;
use Finller\Media\Models\Media;

return [
Expand All @@ -15,6 +16,26 @@
*/
'disk' => env('MEDIA_DISK', env('FILESYSTEM_DISK', 'local')),

/**
* Control if media should be deleted with the model
* when using the HasMedia Trait
*/
'delete_media_with_model' => true,

/**
* Control if media should be deleted with the model
* when soft deleted
*/
'delete_media_with_trashed_model' => false,

/**
* Deleting a lot of media related to a model can take some time
* or even fail (cloud api error, permissions, ...)
* For performance and monitoring, when a model with HasMedia trait is deleted,
* each media is individually deleted inside a job.
*/
'delete_media_with_model_job' => DeleteModelMediaJob::class,

/**
* The default collection name
*/
Expand Down
51 changes: 51 additions & 0 deletions src/Jobs/DeleteModelMediaJob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace Finller\Media\Jobs;

use Finller\Media\Models\Media;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

/**
* Deleting a lot of media can take some time
* In might even fail
*/
class DeleteModelMediaJob implements ShouldBeUnique, ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

public function __construct(public Media $media)
{
$this->media = $media->withoutRelations();

$this->onConnection(config('media.queue_connection'));
$this->onQueue(config('media.queue'));
}

public function uniqueId()
{
return (string) $this->media->id;
}

public function handle()
{
$this->media->delete();
}

/**
* Get the tags that should be assigned to the job.
*
* @return array
*/
public function tags()
{
return [
'media',
get_class($this),
];
}
}
26 changes: 25 additions & 1 deletion src/Traits/HasMedia.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Finller\Media\Models\Media;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphMany;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Collection;
Expand All @@ -20,6 +21,30 @@
*/
trait HasMedia
{
public static function bootHasMedia()
{
static::deleting(function (Model $model) {

if (! config('media.delete_media_with_model')) {
return true;
}

$isSoftDeleting = method_exists($model, 'isForceDeleting') && ! $model->isForceDeleting();

if (
$isSoftDeleting && ! config('media.delete_media_with_trashed_model')
) {
return true;
}

$job = config('media.delete_media_with_model_job');

foreach ($model->media as $media) {
dispatch(new $job($media));
}
});
}

public function media(): MorphMany
{
return $this->morphMany(config('media.model'), 'model')
Expand Down Expand Up @@ -65,7 +90,6 @@ public function getFirstMediaUrl(
$collection = $this->getMediaCollection($collection_name);

return value($collection?->fallback);

}

/**
Expand Down
Loading

0 comments on commit a0fced0

Please sign in to comment.