Add storing events
This commit is contained in:
parent
502bb41e97
commit
58867e87e4
|
@ -0,0 +1,61 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Zoomyboy\MedialibraryHelper;
|
||||||
|
|
||||||
|
use Spatie\MediaLibrary\MediaCollections\MediaCollection;
|
||||||
|
|
||||||
|
class CollectionExtension
|
||||||
|
{
|
||||||
|
public function boot(): void
|
||||||
|
{
|
||||||
|
MediaCollection::mixin(new class() {
|
||||||
|
public function forceFileName()
|
||||||
|
{
|
||||||
|
return fn ($callback) => $this->registerCustomCallback('forceFileName', $callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function storing()
|
||||||
|
{
|
||||||
|
return fn ($callback) => $this->registerCustomCallback('storing', $callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stored()
|
||||||
|
{
|
||||||
|
return fn ($callback) => $this->registerCustomCallback('stored', $callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function runCallback()
|
||||||
|
{
|
||||||
|
return function (string $callback, ...$parameters) {
|
||||||
|
$this->setDefaultCustomCallbacks();
|
||||||
|
|
||||||
|
return call_user_func($this->customCallbacks->get($callback), ...$parameters);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public function registerCustomCallback()
|
||||||
|
{
|
||||||
|
return function (string $name, callable $callback) {
|
||||||
|
$this->setDefaultCustomCallbacks();
|
||||||
|
$this->customCallbacks->put($name, $callback);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setDefaultCustomCallbacks()
|
||||||
|
{
|
||||||
|
return function () {
|
||||||
|
if (property_exists($this, 'customCallbacks')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$this->customCallbacks = collect([
|
||||||
|
'forceFileName' => fn ($name) => $name,
|
||||||
|
'stored' => fn ($event) => true,
|
||||||
|
'storing' => fn ($adder, $name) => $adder,
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,16 +6,36 @@ use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||||
use Illuminate\Http\JsonResponse;
|
use Illuminate\Http\JsonResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
use Illuminate\Support\Str;
|
|
||||||
use Illuminate\Validation\Rule;
|
use Illuminate\Validation\Rule;
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
use Spatie\MediaLibrary\HasMedia;
|
use Spatie\MediaLibrary\HasMedia;
|
||||||
|
use Spatie\MediaLibrary\MediaCollections\MediaCollection;
|
||||||
use Spatie\MediaLibrary\MediaCollections\Models\Media;
|
use Spatie\MediaLibrary\MediaCollections\Models\Media;
|
||||||
|
|
||||||
class MediaController
|
class MediaController
|
||||||
{
|
{
|
||||||
use AuthorizesRequests;
|
use AuthorizesRequests;
|
||||||
|
|
||||||
|
private function validateModel(Request $request): HasMedia
|
||||||
|
{
|
||||||
|
$model = app('media-library-helpers')->get($request->input('model'));
|
||||||
|
|
||||||
|
$request->validate([
|
||||||
|
'collection' => [
|
||||||
|
'required',
|
||||||
|
'string',
|
||||||
|
Rule::in((new $model())->getRegisteredMediaCollections()->pluck('name'))
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$model = $model::find($request->input('id'));
|
||||||
|
if (!$model) {
|
||||||
|
throw ValidationException::withMessages(['model' => 'nicht gefunden']);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $model;
|
||||||
|
}
|
||||||
|
|
||||||
public function store(Request $request)
|
public function store(Request $request)
|
||||||
{
|
{
|
||||||
$request->validate([
|
$request->validate([
|
||||||
|
@ -30,8 +50,9 @@ class MediaController
|
||||||
|
|
||||||
$request->validate($isSingle ? [
|
$request->validate($isSingle ? [
|
||||||
'payload' => 'array',
|
'payload' => 'array',
|
||||||
'payload.name' => 'string|max:255',
|
'payload.*' => '',
|
||||||
'payload.content' => 'string',
|
'payload.name' => 'required|string|max:255',
|
||||||
|
'payload.content' => 'required|string',
|
||||||
] : [
|
] : [
|
||||||
'payload' => 'required|array|min:1',
|
'payload' => 'required|array|min:1',
|
||||||
'payload.*' => 'array',
|
'payload.*' => 'array',
|
||||||
|
@ -41,30 +62,19 @@ class MediaController
|
||||||
|
|
||||||
$content = $isSingle ? [$request->input('payload')] : $request->input('payload');
|
$content = $isSingle ? [$request->input('payload')] : $request->input('payload');
|
||||||
|
|
||||||
$medias = collect([]);
|
$medias = collect($content)->map(function($c) use ($collection, $model) {
|
||||||
foreach ($content as $c) {
|
$pathinfo = pathinfo($c['name']);
|
||||||
if (property_exists($collection, 'forceFileRenamer')) {
|
$path = $collection->runCallback('forceFileName', $pathinfo['filename']).'.'.$pathinfo['extension'];
|
||||||
$fileRenamer = $collection->forceFileRenamer;
|
|
||||||
$path = $fileRenamer($model, pathinfo($c['name'], PATHINFO_FILENAME)).'.'.pathinfo($c['name'], PATHINFO_EXTENSION);
|
|
||||||
} else {
|
|
||||||
$path = $c['name'];
|
|
||||||
}
|
|
||||||
Storage::disk('public')->put($path, base64_decode($c['content']));
|
Storage::disk('public')->put($path, base64_decode($c['content']));
|
||||||
|
|
||||||
$adder = $model->addMedia(Storage::disk('public')->path($path));
|
$adder = $model->addMedia(Storage::disk('public')->path($path));
|
||||||
if (property_exists($collection, 'storingCallback')) {
|
|
||||||
$callback = $collection->storingCallback;
|
|
||||||
$adder = $callback($adder, $path);
|
|
||||||
}
|
|
||||||
$media = $adder->toMediaCollection($collection->name);
|
|
||||||
$medias->push($media);
|
|
||||||
|
|
||||||
if ($isSingle) {
|
return tap(
|
||||||
return MediaData::fromMedia($media);
|
$collection->runCallback('storing', $adder, $path)->toMediaCollection($collection->name),
|
||||||
}
|
fn ($media) => $collection->runCallback('stored', $media)
|
||||||
}
|
);
|
||||||
|
});
|
||||||
|
|
||||||
return MediaData::collection($medias);
|
return $isSingle ? MediaData::from($medias->first()) : MediaData::collection($medias);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function index(Request $request, $parentModel, int $parentId, string $collection): JsonResponse
|
public function index(Request $request, $parentModel, int $parentId, string $collection): JsonResponse
|
||||||
|
@ -86,18 +96,9 @@ class MediaController
|
||||||
return response()->json([]);
|
return response()->json([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function validateModel(Request $request): HasMedia
|
protected function hasCallback(MediaCollection $collection, string $callback): bool
|
||||||
{
|
{
|
||||||
$model = app('media-library-helpers')->get($request->input('model'));
|
return property_exists($collection, $callback);
|
||||||
|
|
||||||
$request->validate([
|
|
||||||
'collection' => ['required', 'string', Rule::in((new $model())->getRegisteredMediaCollections()->map(fn ($collection) => $collection->name)->toArray())],
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (!$model::find($request->input('id'))) {
|
|
||||||
throw ValidationException::withMessages(['model' => 'nicht gefunden']);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $model::find($request->input('id'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ class ServiceProvider extends BaseServiceProvider
|
||||||
public function register(): void
|
public function register(): void
|
||||||
{
|
{
|
||||||
app()->bind('media-library-helpers', fn () => collect([]));
|
app()->bind('media-library-helpers', fn () => collect([]));
|
||||||
|
app()->singleton(CollectionExtension::class, fn () => new CollectionExtension());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function boot(): void
|
public function boot(): void
|
||||||
|
@ -21,17 +22,8 @@ class ServiceProvider extends BaseServiceProvider
|
||||||
$router->get('mediaupload/{parent_model}/{parent_id}/{collection}', [MediaController::class, 'index'])->name('media.index');
|
$router->get('mediaupload/{parent_model}/{parent_id}/{collection}', [MediaController::class, 'index'])->name('media.index');
|
||||||
});
|
});
|
||||||
|
|
||||||
MediaCollection::macro('forceFileName', function ($callback) {
|
app(CollectionExtension::class)->boot();
|
||||||
$this->forceFileRenamer = $callback;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
});
|
|
||||||
|
|
||||||
MediaCollection::macro('storing', function ($callback) {
|
|
||||||
$this->storingCallback = $callback;
|
|
||||||
|
|
||||||
return $this;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Zoomyboy\MedialibraryHelper\Tests\Events;
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Events\Dispatchable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Spatie\MediaLibrary\MediaCollections\Models\Media;
|
||||||
|
|
||||||
|
class MediaStored
|
||||||
|
{
|
||||||
|
use Dispatchable;
|
||||||
|
use SerializesModels;
|
||||||
|
|
||||||
|
public function __construct(public Media $media)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function broadcastOn()
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,8 @@
|
||||||
namespace Zoomyboy\MedialibraryHelper\Tests\Feature;
|
namespace Zoomyboy\MedialibraryHelper\Tests\Feature;
|
||||||
|
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Support\Facades\Event;
|
||||||
|
use Zoomyboy\MedialibraryHelper\Tests\Events\MediaStored;
|
||||||
|
|
||||||
test('it uploads a single file to a single file collection', function() {
|
test('it uploads a single file to a single file collection', function() {
|
||||||
$this->auth()->registerModel();
|
$this->auth()->registerModel();
|
||||||
|
@ -98,6 +100,55 @@ test('it forces a filename for multiple collections', function() {
|
||||||
$this->assertEquals('beispiel-bild-2023-04-04.jpg', $post->getFirstMedia('multipleForced')->file_name);
|
$this->assertEquals('beispiel-bild-2023-04-04.jpg', $post->getFirstMedia('multipleForced')->file_name);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('it throws event when file has been uploaded', function() {
|
||||||
|
Event::fake();
|
||||||
|
Carbon::setTestNow(Carbon::parse('2023-04-04 00:00:00'));
|
||||||
|
$this->auth()->registerModel()->withoutExceptionHandling();
|
||||||
|
$post = $this->newPost();
|
||||||
|
$content = base64_encode($this->pdfFile()->getContent());
|
||||||
|
|
||||||
|
$response = $this->postJson('/mediaupload', [
|
||||||
|
'model' => 'post',
|
||||||
|
'id' => $post->id,
|
||||||
|
'collection' => 'singleWithEvent',
|
||||||
|
'payload' => [
|
||||||
|
'content' => $content,
|
||||||
|
'name' => 'beispiel bild.jpg',
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
$response->assertStatus(201);
|
||||||
|
Event::assertDispatched(MediaStored::class, fn($event) => $event->media->id === $response->json('id'));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it throws event when multiple files uploaded', function() {
|
||||||
|
Event::fake();
|
||||||
|
Carbon::setTestNow(Carbon::parse('2023-04-04 00:00:00'));
|
||||||
|
$this->auth()->registerModel()->withoutExceptionHandling();
|
||||||
|
$post = $this->newPost();
|
||||||
|
$content = base64_encode($this->pdfFile()->getContent());
|
||||||
|
|
||||||
|
$response = $this->postJson('/mediaupload', [
|
||||||
|
'model' => 'post',
|
||||||
|
'id' => $post->id,
|
||||||
|
'collection' => 'multipleFilesWithEvent',
|
||||||
|
'payload' => [
|
||||||
|
[
|
||||||
|
'content' => $content,
|
||||||
|
'name' => 'beispiel bild.jpg',
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'content' => $content,
|
||||||
|
'name' => 'beispiel bild 1.jpg',
|
||||||
|
],
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
|
||||||
|
$response->assertStatus(201);
|
||||||
|
Event::assertDispatched(MediaStored::class, fn($event) => $event->media->id === $response->json('0.id'));
|
||||||
|
Event::assertDispatched(MediaStored::class, fn($event) => $event->media->id === $response->json('1.id'));
|
||||||
|
});
|
||||||
|
|
||||||
test('it uploads multiple files', function() {
|
test('it uploads multiple files', function() {
|
||||||
$this->auth()->registerModel();
|
$this->auth()->registerModel();
|
||||||
$post = $this->newPost();
|
$post = $this->newPost();
|
||||||
|
|
|
@ -3,8 +3,11 @@
|
||||||
namespace Zoomyboy\MedialibraryHelper\Tests\Models;
|
namespace Zoomyboy\MedialibraryHelper\Tests\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Support\Facades\Event;
|
||||||
use Spatie\MediaLibrary\HasMedia;
|
use Spatie\MediaLibrary\HasMedia;
|
||||||
use Spatie\MediaLibrary\InteractsWithMedia;
|
use Spatie\MediaLibrary\InteractsWithMedia;
|
||||||
|
use Spatie\MediaLibrary\MediaCollections\Models\Media;
|
||||||
|
use Zoomyboy\MedialibraryHelper\Tests\Events\MediaStored;
|
||||||
|
|
||||||
class Post extends Model implements HasMedia
|
class Post extends Model implements HasMedia
|
||||||
{
|
{
|
||||||
|
@ -19,11 +22,11 @@ class Post extends Model implements HasMedia
|
||||||
|
|
||||||
$this->addMediaCollection('images');
|
$this->addMediaCollection('images');
|
||||||
|
|
||||||
$this->addMediaCollection('singleForced')->singleFile()->forceFileName(function($adder, $name) {
|
$this->addMediaCollection('singleForced')->singleFile()->forceFileName(function($name) {
|
||||||
return $name.' '.now()->format('Y-m-d');
|
return $name.' '.now()->format('Y-m-d');
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->addMediaCollection('multipleForced')->forceFileName(function($adder, $name) {
|
$this->addMediaCollection('multipleForced')->forceFileName(function($name) {
|
||||||
return $name.' '.now()->format('Y-m-d');
|
return $name.' '.now()->format('Y-m-d');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -33,6 +36,14 @@ class Post extends Model implements HasMedia
|
||||||
'ttt' => pathinfo($fileName, PATHINFO_FILENAME),
|
'ttt' => pathinfo($fileName, PATHINFO_FILENAME),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$this->addMediaCollection('singleWithEvent')->singleFile()->stored(function(Media $media) {
|
||||||
|
Event::dispatch(new MediaStored($media));
|
||||||
|
});
|
||||||
|
|
||||||
|
$this->addMediaCollection('multipleFilesWithEvent')->stored(function(Media $media) {
|
||||||
|
Event::dispatch(new MediaStored($media));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue