Compare commits
6 Commits
79cb5a8f58
...
8bf17784cc
Author | SHA1 | Date |
---|---|---|
|
8bf17784cc | |
|
c00ee87082 | |
|
1b2b148af5 | |
|
14ca7d312f | |
|
17afb48028 | |
|
22d7841d5a |
|
@ -5,10 +5,16 @@
|
|||
"license": "MIT",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Zoomyboy\\MedialibraryHelper\\Tests\\": "tests/",
|
||||
"Zoomyboy\\MedialibraryHelper\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Zoomyboy\\MedialibraryHelper\\Tests\\": "tests/",
|
||||
"Workbench\\App\\": "tests/workbench/app/",
|
||||
"Database\\Factories\\": "tests/workbench/database/factories/"
|
||||
}
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"name": "Philipp Lang",
|
||||
|
@ -28,7 +34,20 @@
|
|||
},
|
||||
"scripts": {
|
||||
"post-autoload-dump": [
|
||||
"@clear",
|
||||
"@prepare",
|
||||
"@php vendor/bin/testbench package:discover --ansi"
|
||||
],
|
||||
"clear": "@php vendor/bin/testbench package:purge-skeleton --ansi",
|
||||
"prepare": "@php vendor/bin/testbench package:discover --ansi",
|
||||
"build": "@php vendor/bin/testbench workbench:build --ansi",
|
||||
"serve": [
|
||||
"Composer\\Config::disableProcessTimeout",
|
||||
"@build",
|
||||
"@php vendor/bin/testbench serve"
|
||||
],
|
||||
"test": [
|
||||
"@php vendor/bin/pest"
|
||||
]
|
||||
},
|
||||
"config": {
|
||||
|
|
|
@ -8682,16 +8682,16 @@
|
|||
"packages-dev": [
|
||||
{
|
||||
"name": "fakerphp/faker",
|
||||
"version": "v1.23.0",
|
||||
"version": "v1.23.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/FakerPHP/Faker.git",
|
||||
"reference": "e3daa170d00fde61ea7719ef47bb09bb8f1d9b01"
|
||||
"reference": "bfb4fe148adbf78eff521199619b93a52ae3554b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/FakerPHP/Faker/zipball/e3daa170d00fde61ea7719ef47bb09bb8f1d9b01",
|
||||
"reference": "e3daa170d00fde61ea7719ef47bb09bb8f1d9b01",
|
||||
"url": "https://api.github.com/repos/FakerPHP/Faker/zipball/bfb4fe148adbf78eff521199619b93a52ae3554b",
|
||||
"reference": "bfb4fe148adbf78eff521199619b93a52ae3554b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -8717,11 +8717,6 @@
|
|||
"ext-mbstring": "Required for multibyte Unicode string functionality."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "v1.21-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Faker\\": "src/Faker/"
|
||||
|
@ -8744,9 +8739,9 @@
|
|||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/FakerPHP/Faker/issues",
|
||||
"source": "https://github.com/FakerPHP/Faker/tree/v1.23.0"
|
||||
"source": "https://github.com/FakerPHP/Faker/tree/v1.23.1"
|
||||
},
|
||||
"time": "2023-06-12T08:44:38+00:00"
|
||||
"time": "2024-01-02T13:46:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "hamcrest/hamcrest-php",
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'temp_disk' => 'temp',
|
||||
'middleware' => ['web', 'auth:web'],
|
||||
];
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace Zoomyboy\MedialibraryHelper;
|
||||
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use Spatie\LaravelData\Attributes\MapInputName;
|
||||
use Spatie\LaravelData\Attributes\MapOutputName;
|
||||
use Spatie\LaravelData\Data;
|
||||
use Spatie\LaravelData\Mappers\SnakeCaseMapper;
|
||||
use Spatie\MediaLibrary\HasMedia;
|
||||
use Spatie\MediaLibrary\MediaCollections\MediaCollection;
|
||||
use Spatie\MediaLibrary\MediaCollections\Models\Media;
|
||||
|
||||
#[MapInputName(SnakeCaseMapper::class)]
|
||||
#[MapOutputName(SnakeCaseMapper::class)]
|
||||
class DeferredMediaData extends Data
|
||||
{
|
||||
public ?int $id;
|
||||
|
||||
public string $originalUrl;
|
||||
|
||||
public int $size;
|
||||
|
||||
public string $name;
|
||||
|
||||
public string $collectionName;
|
||||
|
||||
public string $fileName;
|
||||
|
||||
public string $mimeType;
|
||||
|
||||
public bool $fallback = false;
|
||||
|
||||
public bool $isDeferred = true;
|
||||
|
||||
public static function fromPath(string $path, MediaCollection $collection): self
|
||||
{
|
||||
$file = new MediaFile(Storage::disk(config('media-library.temp_disk'))->path($path));
|
||||
return static::withoutMagicalCreationFrom([
|
||||
'collection_name' => $collection->name,
|
||||
'original_url' => Storage::disk(config('media-library.temp_disk'))->url($path),
|
||||
'size' => $file->getSize(),
|
||||
'name' => $file->getBasename(),
|
||||
'file_name' => $file->getFilename(),
|
||||
'mime_type' => Storage::disk(config('media-library.temp_disk'))->mimeType($path),
|
||||
'path' => $path,
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -5,16 +5,14 @@ namespace Zoomyboy\MedialibraryHelper;
|
|||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Spatie\Image\Image;
|
||||
use Spatie\LaravelData\DataCollection;
|
||||
use Spatie\MediaLibrary\HasMedia;
|
||||
use Spatie\MediaLibrary\MediaCollections\Exceptions\InvalidBase64Data;
|
||||
use Spatie\MediaLibrary\MediaCollections\FileAdder;
|
||||
use Spatie\MediaLibrary\MediaCollections\MediaCollection;
|
||||
use Spatie\MediaLibrary\MediaCollections\Models\Media;
|
||||
use Symfony\Component\HttpFoundation\File\File;
|
||||
use Zoomyboy\MedialibraryHelper\Rules\ModelRule;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class MediaController
|
||||
{
|
||||
|
@ -23,12 +21,15 @@ class MediaController
|
|||
public function store(Request $request)
|
||||
{
|
||||
$request->validate([
|
||||
'model' => ['required', 'string', Rule::in(app('media-library-helpers')->keys())],
|
||||
'id' => 'required',
|
||||
'parent' => ['required', new ModelRule()],
|
||||
]);
|
||||
|
||||
$model = $this->validateModel($request);
|
||||
$collection = $model->getMediaCollection($request->input('collection'));
|
||||
if (is_null($request->input('parent.id'))) {
|
||||
return $this->storeDeferred($request);
|
||||
}
|
||||
|
||||
$model = ModelRule::getModel($request->input('parent'));
|
||||
$collection = ModelRule::getCollection($request->input('parent'));
|
||||
$isSingle = 1 === $collection->collectionSizeLimit;
|
||||
$this->authorize('storeMedia', [$model, $collection->name]);
|
||||
|
||||
|
@ -65,6 +66,37 @@ class MediaController
|
|||
return $isSingle ? MediaData::from($medias->first()) : MediaData::collection($medias);
|
||||
}
|
||||
|
||||
protected function storeDeferred(Request $request)
|
||||
{
|
||||
$modelName = ModelRule::getModelClassName($request->input('parent'));
|
||||
$collection = ModelRule::getCollection($request->input('parent'));
|
||||
$isSingle = 1 === $collection->collectionSizeLimit;
|
||||
|
||||
$request->validate($isSingle ? [
|
||||
'payload' => 'array',
|
||||
'payload.name' => 'required|string|regex:/\..*$/|max:255',
|
||||
'payload.content' => 'required|string',
|
||||
] : [
|
||||
'payload' => 'required|array|min:1',
|
||||
'payload.*' => 'array',
|
||||
'payload.*.name' => 'required|string|regex:/\..*$/|max:255',
|
||||
'payload.*.content' => 'required|string',
|
||||
]);
|
||||
|
||||
$content = $isSingle ? [$request->input('payload')] : $request->input('payload');
|
||||
|
||||
$tempPaths = collect($content)->map(function ($c) use ($collection, $modelName) {
|
||||
$file = new MediaFile($c['name']);
|
||||
|
||||
$tmpFile = $this->storeTemporaryFile($c['content'], $collection);
|
||||
Storage::disk(config('media-library.temp_disk'))->move($tmpFile, 'media-library/' . $file->getFilename());
|
||||
return 'media-library/' . $file->getFilename();
|
||||
});
|
||||
|
||||
$this->authorize('storeMedia', [$modelName, null, $collection->name]);
|
||||
return $isSingle ? DeferredMediaData::fromPath($tempPaths->first(), $collection) : DeferredMediaData::collectionFromPaths($tempPaths, $collection);
|
||||
}
|
||||
|
||||
public function update(Request $request, Media $media): MediaData
|
||||
{
|
||||
$this->authorize('updateMedia', [$media->model, $media->collection_name]);
|
||||
|
@ -116,27 +148,7 @@ class MediaController
|
|||
return property_exists($collection, $callback);
|
||||
}
|
||||
|
||||
protected 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;
|
||||
}
|
||||
|
||||
protected function fileAdderFromData($model, $data, $collection): FileAdder
|
||||
private function storeTemporaryFile(string $data, MediaCollection $collection): string
|
||||
{
|
||||
$maxWidth = $collection->runCallback('maxWidth', 9);
|
||||
if (str_contains($data, ';base64')) {
|
||||
|
@ -156,13 +168,20 @@ class MediaController
|
|||
throw InvalidBase64Data::create();
|
||||
}
|
||||
|
||||
$tmpFile = tempnam(sys_get_temp_dir(), 'media-library');
|
||||
file_put_contents($tmpFile, $binaryData);
|
||||
$tmpFile = 'media-library/' . str()->uuid()->toString();
|
||||
Storage::disk(config('media-library.temp_disk'))->put($tmpFile, $binaryData);
|
||||
|
||||
if (null !== $maxWidth && 'image/jpeg' === mime_content_type($tmpFile)) {
|
||||
Image::load($tmpFile)->width($maxWidth)->save();
|
||||
if (null !== $maxWidth && 'image/jpeg' === Storage::disk(config('media-library.temp_disk'))->mimeType($tmpFile)) {
|
||||
Image::load(Storage::disk(config('media-library.temp_disk'))->path($tmpFile))->width($maxWidth)->save();
|
||||
}
|
||||
|
||||
return $model->addMedia($tmpFile);
|
||||
return $tmpFile;
|
||||
}
|
||||
|
||||
protected function fileAdderFromData($model, $data, $collection): FileAdder
|
||||
{
|
||||
$tmpFile = $this->storeTemporaryFile($data, $collection);
|
||||
|
||||
return $model->addMediaFromDisk($tmpFile, config('media-library.temp_disk'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,9 +37,12 @@ class MediaData extends Data
|
|||
|
||||
public bool $fallback = false;
|
||||
|
||||
public bool $isDeferred = false;
|
||||
|
||||
public static function fromMedia(Media $media): self
|
||||
{
|
||||
$conversions = collect($media->getMediaConversionNames())->flip()->map(fn ($integer, $conversion) => $media->hasGeneratedConversion($conversion)
|
||||
$conversions = collect($media->getMediaConversionNames())->flip()->map(
|
||||
fn ($integer, $conversion) => $media->hasGeneratedConversion($conversion)
|
||||
? ['original_url' => $media->getFullUrl($conversion)]
|
||||
: null,
|
||||
);
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
|
||||
namespace Zoomyboy\MedialibraryHelper\Rules;
|
||||
|
||||
use Illuminate\Contracts\Validation\InvokableRule;
|
||||
use Spatie\MediaLibrary\HasMedia;
|
||||
use Illuminate\Validation\Factory;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Spatie\MediaLibrary\MediaCollections\MediaCollection;
|
||||
|
||||
class ModelRule implements InvokableRule
|
||||
{
|
||||
|
||||
public ?string $collection;
|
||||
public ?int $id;
|
||||
public ?string $model;
|
||||
|
||||
/**
|
||||
* @param array{?id: int, ?collection: string, ?model: string} $attribute
|
||||
*/
|
||||
public function __invoke($attribute, $value, $fail)
|
||||
{
|
||||
app(Factory::class)->make([$attribute => $value], [
|
||||
"{$attribute}.id" => 'nullable|integer|gt:0',
|
||||
"{$attribute}.model" => ['required', 'string', Rule::in(app('media-library-helpers')->keys())],
|
||||
"{$attribute}.collection" => 'required|string',
|
||||
])->validate();
|
||||
|
||||
|
||||
$this->model = data_get($value, 'model');
|
||||
$this->id = data_get($value, 'id');
|
||||
$this->collection = data_get($value, 'collection');
|
||||
|
||||
if (is_null($this->id)) {
|
||||
$this->validateDeferred($attribute, $value);
|
||||
return;
|
||||
}
|
||||
|
||||
$model = app('media-library-helpers')->get($this->model);
|
||||
app(Factory::class)->make([$attribute => $value], [
|
||||
"{$attribute}.collection" => ['required', Rule::in((new $model())->getRegisteredMediaCollections()->pluck('name'))],
|
||||
"{$attribute}.id" => ['required', 'exists:' . (new $model)->getTable() . ',id'],
|
||||
])->validate();
|
||||
}
|
||||
|
||||
public function validateDeferred($attribute, $value): void
|
||||
{
|
||||
app(Factory::class)->make([$attribute => $value], [
|
||||
"{$attribute}.model" => ['required', 'string', Rule::in(app('media-library-helpers')->keys())],
|
||||
"{$attribute}.collection" => 'required|string',
|
||||
])->validate();
|
||||
|
||||
$model = app('media-library-helpers')->get($this->model);
|
||||
|
||||
app(Factory::class)->make([$attribute => $value], [
|
||||
"{$attribute}.collection" => ['required', Rule::in((new $model())->getRegisteredMediaCollections()->pluck('name'))],
|
||||
])->validate();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array{?id: int, ?collection: string, ?model: string} $modelParam
|
||||
*/
|
||||
public static function getModel($modelParam): HasMedia
|
||||
{
|
||||
$model = static::getModelClassName($modelParam);
|
||||
|
||||
return $model::find($modelParam['id']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{?id: int, ?collection: string, ?model: string} $modelParam
|
||||
* @return class-string<HasMedia>
|
||||
*/
|
||||
public static function getModelClassName($modelParam): string
|
||||
{
|
||||
return app('media-library-helpers')->get($modelParam['model']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array{?id: int, ?collection: string, ?model: string} $modelParam
|
||||
*/
|
||||
public static function getCollection($modelParam): MediaCollection
|
||||
{
|
||||
$className = static::getModelClassName($modelParam);
|
||||
|
||||
return (new $className)->getMediaCollection($modelParam['collection']);
|
||||
}
|
||||
}
|
|
@ -12,6 +12,8 @@ class ServiceProvider extends BaseServiceProvider
|
|||
{
|
||||
app()->bind('media-library-helpers', fn () => collect([]));
|
||||
app()->singleton(CollectionExtension::class, fn () => new CollectionExtension());
|
||||
|
||||
$this->mergeConfigFrom(__DIR__ . '/../config/media-library.php', 'media-library');
|
||||
}
|
||||
|
||||
public function boot(): void
|
||||
|
@ -24,8 +26,8 @@ class ServiceProvider extends BaseServiceProvider
|
|||
$router->patch('mediaupload/{media}', [MediaController::class, 'update'])->name('media.update');
|
||||
});
|
||||
|
||||
|
||||
MediaCollection::mixin(app(CollectionExtension::class));
|
||||
// app(CollectionExtension::class)->boot();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
providers:
|
||||
- Spatie\MediaLibrary\MediaLibraryServiceProvider
|
||||
- Spatie\LaravelData\LaravelDataServiceProvider
|
||||
- Zoomyboy\MedialibraryHelper\ServiceProvider
|
||||
|
||||
migrations:
|
||||
- tests/workbench/database/migrations
|
||||
|
||||
workbench:
|
||||
start: '/'
|
||||
install: false
|
||||
discovers:
|
||||
web: false
|
||||
api: false
|
||||
commands: false
|
||||
components: false
|
||||
views: false
|
||||
build: []
|
||||
assets: []
|
||||
sync: []
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
namespace Zoomyboy\MedialibraryHelper\Tests\Feature;
|
||||
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
test('it uploads a deferred file to a collection', function () {
|
||||
$this->auth()->registerModel()->withoutExceptionHandling();
|
||||
$content = base64_encode($this->pdfFile()->getContent());
|
||||
|
||||
$payload = [
|
||||
'parent' => ['model' => 'post', 'collection' => 'defaultSingleFile', 'id' => null],
|
||||
'payload' => [
|
||||
'content' => $content,
|
||||
'name' => 'beispiel bild.jpg',
|
||||
],
|
||||
];
|
||||
|
||||
$this->postJson('/mediaupload', $payload)
|
||||
->assertStatus(201)
|
||||
->assertJson([
|
||||
'is_deferred' => true,
|
||||
'original_url' => Storage::disk('temp')->url('media-library/beispiel bild.jpg'),
|
||||
'name' => 'beispiel bild',
|
||||
'collection_name' => 'defaultSingleFile',
|
||||
'size' => 3028,
|
||||
'file_name' => 'beispiel bild.jpg',
|
||||
'mime_type' => 'application/pdf',
|
||||
]);
|
||||
Storage::disk('temp')->assertExists('media-library/beispiel bild.jpg');
|
||||
});
|
||||
|
||||
test('it handles authorization with collection', function () {
|
||||
$this->auth(['storeMedia' => ['collection' => 'rtrt']])->registerModel();
|
||||
$content = base64_encode($this->pdfFile()->getContent());
|
||||
|
||||
$this->postJson('/mediaupload', [
|
||||
'parent' => ['model' => 'post', 'collection' => 'defaultSingleFile', 'id' => null],
|
||||
'payload' => [
|
||||
'content' => $content,
|
||||
'name' => 'beispiel bild.jpg',
|
||||
],
|
||||
])->assertStatus(403);
|
||||
});
|
||||
|
||||
test('it handles authorization with collection correctly', function () {
|
||||
$this->auth(['storeMedia' => ['collection' => 'defaultSingleFile']])->registerModel();
|
||||
$content = base64_encode($this->pdfFile()->getContent());
|
||||
|
||||
$this->postJson('/mediaupload', [
|
||||
'parent' => ['model' => 'post', 'collection' => 'defaultSingleFile', 'id' => null],
|
||||
'payload' => [
|
||||
'content' => $content,
|
||||
'name' => 'beispiel bild.jpg',
|
||||
],
|
||||
])->assertStatus(201);
|
||||
});
|
||||
|
||||
test('it needs a collection', function ($key, $value) {
|
||||
$this->auth()->registerModel();
|
||||
$content = base64_encode($this->pdfFile()->getContent());
|
||||
|
||||
$payload = [
|
||||
'parent' => ['model' => 'post', 'collection' => '', 'id' => null],
|
||||
'payload' => [
|
||||
'content' => $content,
|
||||
'name' => 'beispiel bild.jpg',
|
||||
],
|
||||
];
|
||||
|
||||
data_set($payload, $key, $value);
|
||||
|
||||
$this->postJson('/mediaupload', $payload)->assertJsonValidationErrors($key);
|
||||
})->with(function () {
|
||||
yield ['parent.collection', ''];
|
||||
yield ['parent.collection', -1];
|
||||
yield ['parent.collection', 'missingcollection'];
|
||||
yield ['parent.model', 'lalala'];
|
||||
yield ['parent.model', -1];
|
||||
yield ['parent.model', ''];
|
||||
});
|
|
@ -3,8 +3,8 @@
|
|||
namespace Zoomyboy\MedialibraryHelper\Tests\Feature;
|
||||
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Zoomyboy\MedialibraryHelper\Tests\Events\MediaChange;
|
||||
use Zoomyboy\MedialibraryHelper\Tests\Events\MediaDestroyed;
|
||||
use Workbench\App\Events\MediaChange;
|
||||
use Workbench\App\Events\MediaDestroyed;
|
||||
|
||||
test('it deletes multiple media', function () {
|
||||
$this->auth()->registerModel()->withoutExceptionHandling();
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Zoomyboy\MedialibraryHelper\Tests\Feature;
|
||||
|
||||
use Illuminate\Foundation\Console\VendorPublishCommand;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Spatie\MediaLibrary\MediaLibraryServiceProvider;
|
||||
|
||||
afterEach(function () {
|
||||
@unlink(config_path('media-library.php'));
|
||||
});
|
||||
|
||||
test('modifies config file', function () {
|
||||
Artisan::call(VendorPublishCommand::class, ['--provider' => MediaLibraryServiceProvider::class, '--tag' => 'config']);
|
||||
$configContents = file_get_contents(config_path('media-library.php'));
|
||||
$configContents = preg_replace('/\'image_driver\' => env.*/', '\'image_driver\' => "lala",', $configContents);
|
||||
file_put_contents(config_path('media-library.php'), $configContents);
|
||||
|
||||
$this->tearDownTheTestEnvironment();
|
||||
$this->setUpTheTestEnvironment();
|
||||
|
||||
$this->assertEquals('lala', config('media-library.image_driver'));
|
||||
$this->assertEquals('temp', config('media-library.temp_disk'));
|
||||
});
|
|
@ -3,7 +3,7 @@
|
|||
namespace Zoomyboy\MedialibraryHelper\Tests\Feature;
|
||||
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Zoomyboy\MedialibraryHelper\Tests\Events\MediaChange;
|
||||
use Workbench\App\Events\MediaChange;
|
||||
|
||||
test('it can reorder media', function () {
|
||||
Event::fake();
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
namespace Zoomyboy\MedialibraryHelper\Tests\Feature;
|
||||
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Zoomyboy\MedialibraryHelper\Tests\Events\MediaChange;
|
||||
use Workbench\App\Events\MediaChange;
|
||||
|
||||
test('it updates a single files properties', function () {
|
||||
Event::fake();
|
||||
|
|
|
@ -4,8 +4,8 @@ namespace Zoomyboy\MedialibraryHelper\Tests\Feature;
|
|||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Zoomyboy\MedialibraryHelper\Tests\Events\MediaChange;
|
||||
use Zoomyboy\MedialibraryHelper\Tests\Events\MediaStored;
|
||||
use Workbench\App\Events\MediaChange;
|
||||
use Workbench\App\Events\MediaStored;
|
||||
|
||||
test('it uploads a single file to a single file collection', function () {
|
||||
$this->auth()->registerModel();
|
||||
|
@ -13,9 +13,7 @@ test('it uploads a single file to a single file collection', function () {
|
|||
$content = base64_encode($this->pdfFile()->getContent());
|
||||
|
||||
$response = $this->postJson('/mediaupload', [
|
||||
'model' => 'post',
|
||||
'id' => $post->id,
|
||||
'collection' => 'defaultSingleFile',
|
||||
'parent' => ['model' => 'post', 'collection' => 'defaultSingleFile', 'id' => $post->id],
|
||||
'payload' => [
|
||||
'content' => $content,
|
||||
'name' => 'beispiel bild.jpg',
|
||||
|
@ -31,92 +29,18 @@ test('it uploads a single file to a single file collection', function () {
|
|||
$response->assertJsonPath('name', 'beispiel bild');
|
||||
$response->assertJsonPath('collection_name', 'defaultSingleFile');
|
||||
$response->assertJsonPath('file_name', 'beispiel-bild.jpg');
|
||||
$response->assertJsonPath('is_deferred', false);
|
||||
$response->assertJsonMissingPath('model_type');
|
||||
$response->assertJsonMissingPath('model_id');
|
||||
});
|
||||
|
||||
test('test validation', function (array $attributes, string $messages) {
|
||||
$this->auth()->registerModel();
|
||||
$post = $this->newPost();
|
||||
$content = base64_encode($this->pdfFile()->getContent());
|
||||
|
||||
$this->postJson('/mediaupload', [
|
||||
'model' => 'post',
|
||||
'id' => $post->id,
|
||||
'collection' => 'defaultSingleFile',
|
||||
'payload' => [
|
||||
'content' => $content,
|
||||
'name' => 'beispiel bild.jpg',
|
||||
],
|
||||
...$attributes
|
||||
])->assertJsonValidationErrors($messages);
|
||||
})->with([
|
||||
'missing collection' => [
|
||||
['collection' => ''],
|
||||
'collection'
|
||||
],
|
||||
'missing id' => [
|
||||
['id' => ''],
|
||||
'id'
|
||||
],
|
||||
]);
|
||||
|
||||
test('test validation for payload', function () {
|
||||
$this->auth()->registerModel();
|
||||
$post = $this->newPost();
|
||||
|
||||
$this->postJson('/mediaupload', [
|
||||
'model' => 'post',
|
||||
'id' => $post->id,
|
||||
'collection' => 'defaultSingleFile',
|
||||
'payload' => [
|
||||
'content' => '',
|
||||
'name' => 'beispiel bild.jpg',
|
||||
],
|
||||
])->assertJsonValidationErrors('payload.content');
|
||||
});
|
||||
|
||||
test('test validation for name', function () {
|
||||
$this->auth()->registerModel();
|
||||
$post = $this->newPost();
|
||||
$content = base64_encode($this->pdfFile()->getContent());
|
||||
|
||||
$this->postJson('/mediaupload', [
|
||||
'model' => 'post',
|
||||
'id' => $post->id,
|
||||
'collection' => 'defaultSingleFile',
|
||||
'payload' => [
|
||||
'content' => $content,
|
||||
'name' => '',
|
||||
],
|
||||
])->assertJsonValidationErrors('payload.name');
|
||||
});
|
||||
|
||||
test('test validation for extension', function () {
|
||||
$this->auth()->registerModel();
|
||||
$post = $this->newPost();
|
||||
$content = base64_encode($this->pdfFile()->getContent());
|
||||
|
||||
$this->postJson('/mediaupload', [
|
||||
'model' => 'post',
|
||||
'id' => $post->id,
|
||||
'collection' => 'defaultSingleFile',
|
||||
'payload' => [
|
||||
'content' => $content,
|
||||
'name' => 'aaa',
|
||||
],
|
||||
])->assertJsonValidationErrors('payload.name');
|
||||
});
|
||||
|
||||
test('it uploads a single image to a single file collection', function () {
|
||||
$this->auth()->registerModel();
|
||||
$this->auth()->registerModel()->withoutExceptionHandling();
|
||||
$post = $this->newPost();
|
||||
$content = base64_encode($this->jpgFile()->getContent());
|
||||
|
||||
$response = $this->postJson('/mediaupload', [
|
||||
'model' => 'post',
|
||||
'id' => $post->id,
|
||||
'collection' => 'defaultSingleFile',
|
||||
'parent' => ['model' => 'post', 'collection' => 'defaultSingleFile', 'id' => $post->id],
|
||||
'payload' => [
|
||||
'content' => $content,
|
||||
'name' => 'beispiel bild.jpg',
|
||||
|
@ -134,9 +58,7 @@ test('it forces a filename for a single collection', function () {
|
|||
$content = base64_encode($this->pdfFile()->getContent());
|
||||
|
||||
$response = $this->postJson('/mediaupload', [
|
||||
'model' => 'post',
|
||||
'id' => $post->id,
|
||||
'collection' => 'singleForced',
|
||||
'parent' => ['model' => 'post', 'collection' => 'singleForced', 'id' => $post->id],
|
||||
'payload' => [
|
||||
'content' => $content,
|
||||
'name' => 'beispiel bild.jpg',
|
||||
|
@ -155,9 +77,7 @@ test('it sets custom title when storing', function () {
|
|||
$content = base64_encode($this->pdfFile()->getContent());
|
||||
|
||||
$response = $this->postJson('/mediaupload', [
|
||||
'model' => 'post',
|
||||
'id' => $post->id,
|
||||
'collection' => 'singleStoringHook',
|
||||
'parent' => ['model' => 'post', 'collection' => 'singleStoringHook', 'id' => $post->id],
|
||||
'payload' => [
|
||||
'content' => $content,
|
||||
'name' => 'beispiel bild.jpg',
|
||||
|
@ -177,9 +97,7 @@ test('it sets custom properties from properties method', function () {
|
|||
$content = base64_encode($this->pdfFile()->getContent());
|
||||
|
||||
$response = $this->postJson('/mediaupload', [
|
||||
'model' => 'post',
|
||||
'id' => $post->id,
|
||||
'collection' => 'multipleProperties',
|
||||
'parent' => ['model' => 'post', 'collection' => 'multipleProperties', 'id' => $post->id],
|
||||
'payload' => [
|
||||
'content' => $content,
|
||||
'name' => 'beispiel bild.jpg',
|
||||
|
@ -199,9 +117,7 @@ test('it forces a filename for multiple collections', function () {
|
|||
$content = base64_encode($this->pdfFile()->getContent());
|
||||
|
||||
$response = $this->postJson('/mediaupload', [
|
||||
'model' => 'post',
|
||||
'id' => $post->id,
|
||||
'collection' => 'multipleForced',
|
||||
'parent' => ['model' => 'post', 'collection' => 'multipleForced', 'id' => $post->id],
|
||||
'payload' => [
|
||||
[
|
||||
'content' => $content,
|
||||
|
@ -222,9 +138,7 @@ test('it throws event when file has been uploaded', function () {
|
|||
$content = base64_encode($this->pdfFile()->getContent());
|
||||
|
||||
$response = $this->postJson('/mediaupload', [
|
||||
'model' => 'post',
|
||||
'id' => $post->id,
|
||||
'collection' => 'singleWithEvent',
|
||||
'parent' => ['model' => 'post', 'collection' => 'singleWithEvent', 'id' => $post->id],
|
||||
'payload' => [
|
||||
'content' => $content,
|
||||
'name' => 'beispiel bild.jpg',
|
||||
|
@ -244,9 +158,7 @@ test('it throws event when multiple files uploaded', function () {
|
|||
$content = base64_encode($this->pdfFile()->getContent());
|
||||
|
||||
$response = $this->postJson('/mediaupload', [
|
||||
'model' => 'post',
|
||||
'id' => $post->id,
|
||||
'collection' => 'multipleFilesWithEvent',
|
||||
'parent' => ['model' => 'post', 'collection' => 'multipleFilesWithEvent', 'id' => $post->id],
|
||||
'payload' => [
|
||||
[
|
||||
'content' => $content,
|
||||
|
@ -271,9 +183,7 @@ test('it uploads multiple files', function () {
|
|||
$post->addMedia($file->getPathname())->preservingOriginal()->toMediaCollection('images');
|
||||
|
||||
$response = $this->postJson('/mediaupload', [
|
||||
'model' => 'post',
|
||||
'id' => $post->id,
|
||||
'collection' => 'images',
|
||||
'parent' => ['model' => 'post', 'collection' => 'images', 'id' => $post->id],
|
||||
'payload' => [
|
||||
[
|
||||
'content' => base64_encode($file->getContent()),
|
||||
|
@ -305,80 +215,125 @@ test('it returns 403 when not authorized', function () {
|
|||
$this->auth(['storeMedia' => false])->registerModel();
|
||||
$post = $this->newPost();
|
||||
|
||||
$response = $this->postJson('/mediaupload', [
|
||||
'model' => 'post',
|
||||
'id' => $post->id,
|
||||
'collection' => 'defaultSingleFile',
|
||||
$this->postJson('/mediaupload', [
|
||||
'parent' => ['model' => 'post', 'collection' => 'defaultSingleFile', 'id' => $post->id],
|
||||
'payload' => [
|
||||
'content' => base64_encode($this->pdfFile()->getContent()),
|
||||
'name' => 'beispiel bild.jpg',
|
||||
],
|
||||
]);
|
||||
|
||||
$response->assertStatus(403);
|
||||
])->assertStatus(403);
|
||||
});
|
||||
|
||||
test('it needs validation for single files', function (array $payload, string $invalidFieldName) {
|
||||
test('it checks for model when running authorization', function () {
|
||||
$otherPost = $this->newPost();
|
||||
$post = $this->newPost();
|
||||
$this->auth(['storeMedia' => ['id' => $post->id, 'collection' => 'defaultSingleFile']])->registerModel();
|
||||
|
||||
$this->postJson('/mediaupload', [
|
||||
'parent' => ['model' => 'post', 'collection' => 'defaultSingleFile', 'id' => $post->id],
|
||||
'payload' => [
|
||||
'content' => base64_encode($this->pdfFile()->getContent()),
|
||||
'name' => 'beispiel bild.jpg',
|
||||
],
|
||||
])->assertStatus(201);
|
||||
|
||||
$this->postJson('/mediaupload', [
|
||||
'parent' => ['model' => 'post', 'collection' => 'defaultSingleFile', 'id' => $otherPost->id],
|
||||
'payload' => [
|
||||
'content' => base64_encode($this->pdfFile()->getContent()),
|
||||
'name' => 'beispiel bild.jpg',
|
||||
],
|
||||
])->assertStatus(403);
|
||||
});
|
||||
|
||||
test('it checks for collection when running authorization', function () {
|
||||
$post = $this->newPost();
|
||||
$this->auth(['storeMedia' => ['id' => $post->id, 'collection' => 'defaultSingleFile']])->registerModel();
|
||||
|
||||
$this->postJson('/mediaupload', [
|
||||
'parent' => ['model' => 'post', 'collection' => 'defaultSingleFile', 'id' => $post->id],
|
||||
'payload' => [
|
||||
'content' => base64_encode($this->pdfFile()->getContent()),
|
||||
'name' => 'beispiel bild.jpg',
|
||||
],
|
||||
])->assertStatus(201);
|
||||
|
||||
$this->postJson('/mediaupload', [
|
||||
'parent' => ['model' => 'post', 'collection' => 'singleWithEvent', 'id' => $post->id],
|
||||
'payload' => [
|
||||
'content' => base64_encode($this->pdfFile()->getContent()),
|
||||
'name' => 'beispiel bild.jpg',
|
||||
],
|
||||
])->assertStatus(403);
|
||||
});
|
||||
|
||||
test('it needs validation for single files', function (array $payloadOverwrites, string $invalidFieldName) {
|
||||
$this->auth()->registerModel();
|
||||
$post = $this->newPost();
|
||||
|
||||
$response = $this->postJson('/mediaupload', [
|
||||
'model' => 'post',
|
||||
'id' => $post->id,
|
||||
'collection' => 'defaultSingleFile',
|
||||
$payload = [
|
||||
'parent' => ['model' => 'post', 'collection' => 'defaultSingleFile', 'id' => $post->id],
|
||||
'payload' => [
|
||||
'content' => base64_encode($this->pdfFile()->getContent()),
|
||||
'name' => 'beispiel bild.jpg',
|
||||
],
|
||||
...$payload,
|
||||
]);
|
||||
];
|
||||
|
||||
foreach ($payloadOverwrites as $key => $value) {
|
||||
data_set($payload, $key, $value);
|
||||
}
|
||||
|
||||
$response = $this->postJson('/mediaupload', $payload);
|
||||
|
||||
$response->assertStatus(422);
|
||||
$response->assertJsonValidationErrors($invalidFieldName);
|
||||
})->with(function () {
|
||||
yield [['model' => 'missingmodel'], 'model'];
|
||||
yield [['id' => -1], 'model'];
|
||||
yield [['collection' => 'missingcollection'], 'collection'];
|
||||
yield [['payload' => ['name' => 'AAA', 'content' => []]], 'payload.content'];
|
||||
yield [['payload' => ['name' => 'AAA', 'content' => ['UU']]], 'payload.content'];
|
||||
yield [['payload' => ['name' => 'AAA', 'content' => null]], 'payload.content'];
|
||||
yield [['payload' => ['name' => 'AAA', 'content' => '']], 'payload.content'];
|
||||
yield [['payload' => ['name' => 'AAA', 'content' => 1]], 'payload.content'];
|
||||
yield [['payload' => ['name' => '', 'content' => 'aaadfdf']], 'payload.name'];
|
||||
yield [['payload' => ['name' => ['U'], 'content' => 'aaadfdf']], 'payload.name'];
|
||||
yield [['payload' => ['name' => 1, 'content' => 'aaadfdf']], 'payload.name'];
|
||||
yield [['payload' => ['name' => null, 'content' => 'aaadfdf']], 'payload.name'];
|
||||
yield [['parent.model' => 'missingmodel'], 'parent.model'];
|
||||
yield [['parent.id' => -1], 'parent.id'];
|
||||
yield [['parent.collection' => 'missingcollection'], 'parent.collection'];
|
||||
yield [['payload.content' => []], 'payload.content'];
|
||||
yield [['payload.content' => ['UU']], 'payload.content'];
|
||||
yield [['payload.content' => null], 'payload.content'];
|
||||
yield [['payload.content' => ''], 'payload.content'];
|
||||
yield [['payload.content' => 1], 'payload.content'];
|
||||
yield [['payload.name' => ''], 'payload.name'];
|
||||
yield [['payload.name' => ['U']], 'payload.name'];
|
||||
yield [['payload.name' => 1], 'payload.name'];
|
||||
yield [['payload.name' => null], 'payload.name'];
|
||||
yield [['payload' => 'lalal'], 'payload'];
|
||||
yield [['payload' => 55], 'payload'];
|
||||
});
|
||||
|
||||
test('it needs validation for multiple files', function (array $payload, string $invalidFieldName) {
|
||||
test('it needs validation for multiple files', function (array $payloadOverwrites, string $invalidFieldName) {
|
||||
$this->auth()->registerModel();
|
||||
$post = $this->newPost();
|
||||
|
||||
$response = $this->postJson('/mediaupload', [
|
||||
'model' => 'post',
|
||||
'id' => $post->id,
|
||||
'collection' => 'images',
|
||||
$payload = [
|
||||
'parent' => ['model' => 'post', 'collection' => 'images', 'id' => $post->id],
|
||||
'payload' => [
|
||||
[
|
||||
'content' => base64_encode($this->pdfFile()->getContent()),
|
||||
'name' => 'beispiel bild.jpg',
|
||||
],
|
||||
],
|
||||
...$payload,
|
||||
]);
|
||||
];
|
||||
|
||||
foreach ($payloadOverwrites as $key => $value) {
|
||||
data_set($payload, $key, $value);
|
||||
}
|
||||
|
||||
$response = $this->postJson('/mediaupload', $payload);
|
||||
|
||||
|
||||
$response->assertStatus(422);
|
||||
$response->assertJsonValidationErrors($invalidFieldName);
|
||||
})->with(function () {
|
||||
yield [['model' => 'missingmodel'], 'model'];
|
||||
yield [['id' => -1], 'model'];
|
||||
yield [['collection' => 'missingcollection'], 'collection'];
|
||||
yield [['parent.model' => 'missingmodel'], 'parent.model'];
|
||||
yield [['parent.model' => 'post.missingcollection'], 'parent.model'];
|
||||
yield [['parent.id' => -1], 'parent.id'];
|
||||
yield [['payload' => 'lalal'], 'payload'];
|
||||
yield [['payload' => []], 'payload'];
|
||||
yield [['payload' => 1], 'payload'];
|
||||
|
||||
yield [['payload' => [['name' => 'AAA', 'content' => []]]], 'payload.0.content'];
|
||||
yield [['payload' => [['name' => 'AAA', 'content' => ['UU']]]], 'payload.0.content'];
|
||||
yield [['payload' => [['name' => 'AAA', 'content' => null]]], 'payload.0.content'];
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Auth\Access\Gate;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Workbench\App\Models\Post;
|
||||
use Workbench\App\Policies\PostPolicy;
|
||||
|
||||
uses(Zoomyboy\MedialibraryHelper\Tests\TestCase::class)->in('Feature');
|
||||
uses(Illuminate\Foundation\Testing\RefreshDatabase::class)->in('Feature');
|
||||
uses()->beforeEach(fn () => Storage::fake('media'))->in('Feature');
|
||||
uses()->beforeEach(fn () => Storage::fake('media') && Storage::fake('temp'))->in('Feature');
|
||||
uses()->beforeEach(fn () => Gate::policy(Post::class, PostPolicy::class))->in('Feature');
|
||||
|
|
|
@ -4,30 +4,15 @@ namespace Zoomyboy\MedialibraryHelper\Tests;
|
|||
|
||||
use Illuminate\Http\File;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Orchestra\Testbench\Concerns\WithWorkbench;
|
||||
use Orchestra\Testbench\TestCase as BaseTestCase;
|
||||
use Spatie\LaravelData\LaravelDataServiceProvider;
|
||||
use Spatie\MediaLibrary\MediaLibraryServiceProvider;
|
||||
use Zoomyboy\MedialibraryHelper\ServiceProvider;
|
||||
use Zoomyboy\MedialibraryHelper\Tests\Models\Post;
|
||||
use Workbench\App\Models\Post;
|
||||
use Workbench\App\Models\User;
|
||||
|
||||
class TestCase extends BaseTestCase
|
||||
{
|
||||
/**
|
||||
* Define database migrations.
|
||||
*/
|
||||
protected function defineDatabaseMigrations(): void
|
||||
{
|
||||
$this->loadMigrationsFrom(__DIR__ . '/migrations');
|
||||
}
|
||||
|
||||
protected function getPackageProviders($app): array
|
||||
{
|
||||
return [
|
||||
ServiceProvider::class,
|
||||
MediaLibraryServiceProvider::class,
|
||||
LaravelDataServiceProvider::class,
|
||||
];
|
||||
}
|
||||
use WithWorkbench;
|
||||
|
||||
/**
|
||||
* Generate a pdf file with a filename and get path.
|
||||
|
@ -65,23 +50,8 @@ class TestCase extends BaseTestCase
|
|||
|
||||
protected function auth(array $policies = []): self
|
||||
{
|
||||
$policies = [
|
||||
'storeMedia' => true,
|
||||
'updateMedia' => true,
|
||||
'destroyMedia' => true,
|
||||
'listMedia' => true,
|
||||
...$policies,
|
||||
];
|
||||
|
||||
foreach ($policies as $ability => $result) {
|
||||
Gate::define($ability, fn (?string $user, string $collectionName) => $result);
|
||||
}
|
||||
$this->be(User::factory()->policies($policies)->create());
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function defineEnvironment($app)
|
||||
{
|
||||
$app['config']->set('media-library.middleware', ['web']);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Zoomyboy\MedialibraryHelper\Tests\Events;
|
||||
namespace Workbench\App\Events;
|
||||
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Queue\SerializesModels;
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Zoomyboy\MedialibraryHelper\Tests\Events;
|
||||
namespace Workbench\App\Events;
|
||||
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Queue\SerializesModels;
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Zoomyboy\MedialibraryHelper\Tests\Events;
|
||||
namespace Workbench\App\Events;
|
||||
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Queue\SerializesModels;
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Zoomyboy\MedialibraryHelper\Tests\Models;
|
||||
namespace Workbench\App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
|
@ -8,9 +8,9 @@ use Illuminate\Support\Str;
|
|||
use Spatie\MediaLibrary\HasMedia;
|
||||
use Spatie\MediaLibrary\InteractsWithMedia;
|
||||
use Spatie\MediaLibrary\MediaCollections\Models\Media;
|
||||
use Zoomyboy\MedialibraryHelper\Tests\Events\MediaChange;
|
||||
use Zoomyboy\MedialibraryHelper\Tests\Events\MediaDestroyed;
|
||||
use Zoomyboy\MedialibraryHelper\Tests\Events\MediaStored;
|
||||
use Workbench\App\Events\MediaChange;
|
||||
use Workbench\App\Events\MediaDestroyed;
|
||||
use Workbench\App\Events\MediaStored;
|
||||
|
||||
class Post extends Model implements HasMedia
|
||||
{
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
namespace Workbench\App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
|
||||
class User extends Authenticatable
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
public $guarded = [];
|
||||
|
||||
public $casts = [
|
||||
'policies' => 'json',
|
||||
];
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
namespace Workbench\App\Policies;
|
||||
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
use Spatie\MediaLibrary\HasMedia;
|
||||
use Workbench\App\Models\User;
|
||||
|
||||
class PostPolicy
|
||||
{
|
||||
use HandlesAuthorization;
|
||||
|
||||
public function listMedia(User $user, HasMedia $model): bool
|
||||
{
|
||||
if (is_bool($user->policies['listMedia'])) {
|
||||
return $user->policies['listMedia'] === true;
|
||||
}
|
||||
|
||||
return data_get($user->policies, 'listMedia.id') === $model->id
|
||||
&& data_get($user->policies, 'listMedia.collection') === $collection;
|
||||
}
|
||||
|
||||
public function storeMedia(User $user, ?HasMedia $model, ?string $collection = null): bool
|
||||
{
|
||||
if (is_bool($user->policies['storeMedia'])) {
|
||||
return $user->policies['storeMedia'] === true;
|
||||
}
|
||||
|
||||
if (is_null($model)) {
|
||||
return data_get($user->policies, 'storeMedia.collection') === $collection;
|
||||
}
|
||||
|
||||
return data_get($user->policies, 'storeMedia.id') === $model->id
|
||||
&& data_get($user->policies, 'storeMedia.collection') === $collection;
|
||||
}
|
||||
|
||||
public function updateMedia(User $user, HasMedia $model, string $collection): bool
|
||||
{
|
||||
if (is_bool($user->policies['updateMedia'])) {
|
||||
return $user->policies['updateMedia'] === true;
|
||||
}
|
||||
|
||||
return data_get($user->policies, 'updateMedia.id') === $model->id
|
||||
&& data_get($user->policies, 'updateMedia.collection') === $collection;
|
||||
}
|
||||
|
||||
public function destroyMedia(User $user, HasMedia $model, string $collection): bool
|
||||
{
|
||||
if (is_bool($user->policies['destroyMedia'])) {
|
||||
return $user->policies['destroyMedia'] === true;
|
||||
}
|
||||
|
||||
return data_get($user->policies, 'destroyMedia.id') === $model->id
|
||||
&& data_get($user->policies, 'destroyMedia.collection') === $collection;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
namespace Database\Factories\Models;
|
||||
|
||||
use Workbench\App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
/**
|
||||
* @extends Factory<User>
|
||||
*/
|
||||
class UserFactory extends Factory
|
||||
{
|
||||
protected $model = User::class;
|
||||
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition()
|
||||
{
|
||||
return [
|
||||
'email' => $this->faker->safeEmail,
|
||||
'password' => Hash::make('password'),
|
||||
'name' => $this->faker->firstName,
|
||||
'policies' => [],
|
||||
];
|
||||
}
|
||||
|
||||
public function policies(array $policies): self
|
||||
{
|
||||
return $this->state(['policies' => [
|
||||
'storeMedia' => true,
|
||||
'updateMedia' => true,
|
||||
'destroyMedia' => true,
|
||||
'listMedia' => true,
|
||||
...$policies,
|
||||
]]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('users', function (Blueprint $table) {
|
||||
$table->id();
|
||||
$table->string('email');
|
||||
$table->string('name');
|
||||
$table->string('password');
|
||||
$table->json('policies');
|
||||
$table->timestamps();
|
||||
});
|
||||
}
|
||||
};
|
Loading…
Reference in New Issue