Skip to content

Commit

Permalink
feat: support for spatie/laravel-medialibrary v11 has been added
Browse files Browse the repository at this point in the history
  • Loading branch information
everzel committed Jan 26, 2024
1 parent d872ec5 commit 15aea91
Show file tree
Hide file tree
Showing 61 changed files with 1,263 additions and 804 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/.idea
/vendor
/vendor_old
/node_modules
package-lock.json
composer.phar
Expand Down
9 changes: 5 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,15 @@
}
],
"require": {
"php": "^7.4|^8.0|^8.1",
"spatie/laravel-medialibrary": "^8.0|^9.0|^10.0|^11.0"
"php": "^8.2",
"spatie/laravel-medialibrary": "^11.0",
"spatie/laravel-data": "^3.0"
},
"require-dev": {
"laravel/nova": "^4.0",
"orchestra/testbench": "^5.0|^6.0|^7.0",
"orchestra/testbench": "^6.0|^7.0|^8.0",
"nunomaduro/collision": "^4.0|^5.0|^6.0",
"phpunit/phpunit": "^8.5|^9.0"
"phpunit/phpunit": "^9.0"
},
"autoload": {
"psr-4": {
Expand Down
2 changes: 1 addition & 1 deletion dist/js/field.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/mix-manifest.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"/js/field.js": "/js/field.js?id=09ae783f2f976065e1658d283605d203",
"/js/field.js": "/js/field.js?id=ce95629eb5176683a8275b0d4eaaaacf",
"/css/field.css": "/css/field.css?id=d95e4549d8e45d413398a7fc8bfb5628"
}
5 changes: 4 additions & 1 deletion phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true"
printerClass="NunoMaduro\Collision\Adapters\Phpunit\Printer"
Expand All @@ -15,4 +15,7 @@
<directory suffix=".php">./tests/</directory>
</testsuite>
</testsuites>
<php>
<env name="APP_DEBUG" value="true"/>
</php>
</phpunit>
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
</ModalHeader>

<ModalContent>
<IndexSearchInput @update:keyword="applyFilter" />
<IndexSearchInput
class="mb-2"
@update:keyword="applyFilter"
/>

<LoadingView :loading="loading">
<slot>
Expand All @@ -22,7 +25,7 @@
</LoadingView>
<PaginationSimple v-bind="pagination" @page="selectPage"
><span class="text-xs"
>{{ pagination.from }}-{{ pagination.to }} of {{ pagination.allMatchingResourceCount }}</span
>{{ (pagination.from || 0) }}-{{ (pagination.to || 0) }} of {{ pagination.allMatchingResourceCount }}</span
></PaginationSimple
>
</ModalContent>
Expand Down Expand Up @@ -140,7 +143,6 @@ export default {
},
applyFilter(keyword) {
console.log(keyword)
this.params.name = keyword
this.selectPage(1)
},
Expand Down
4 changes: 2 additions & 2 deletions resources/js/components/Medialibrary/Modals/Cropper.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
<button
v-if="rotatable"
type="button"
class="ml-2 flex h-8 w-8 items-center justify-center rounded hover:opacity-50 focus:outline-none focus:ring"
class="hidden ml-2 flex h-8 w-8 items-center justify-center rounded hover:opacity-50 focus:outline-none focus:ring"
@click="rotate(-90)"
>
<icon-cropper-rotate width="24" height="24" />
Expand All @@ -40,7 +40,7 @@
<button
v-if="rotatable"
type="button"
class="ml-2 flex h-8 w-8 items-center justify-center rounded hover:opacity-50 focus:outline-none focus:ring"
class="hidden ml-2 flex h-8 w-8 items-center justify-center rounded hover:opacity-50 focus:outline-none focus:ring"
@click="rotate(90)"
>
<icon-cropper-rotate width="24" height="24" style="transform: rotateY(180deg)" />
Expand Down
16 changes: 16 additions & 0 deletions routes/api.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

use DmitryBubyakin\NovaMedialibraryField\Http\Controllers\MediaAttachController;
use DmitryBubyakin\NovaMedialibraryField\Http\Controllers\MediaAttachmentListController;
use DmitryBubyakin\NovaMedialibraryField\Http\Controllers\MediaCropController;
use DmitryBubyakin\NovaMedialibraryField\Http\Controllers\MediaListController;
use DmitryBubyakin\NovaMedialibraryField\Http\Controllers\MediaRegenerateController;
use DmitryBubyakin\NovaMedialibraryField\Http\Controllers\MediaSortController;
use Illuminate\Support\Facades\Route;

Route::post('sort', MediaSortController::class);
Route::post('{media}/crop', MediaCropController::class);
Route::post('{media}/regenerate', MediaRegenerateController::class);
Route::get('{resource}/{resourceId}/media/{field}', MediaListController::class);
Route::get('{resource}/{resourceId}/media/{field}/attachable', MediaAttachmentListController::class);
Route::post('{resource}/{resourceId}/media/{field}', MediaAttachController::class);
63 changes: 63 additions & 0 deletions src/Actions/MediaAttachAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

namespace DmitryBubyakin\NovaMedialibraryField\Actions;

use DmitryBubyakin\NovaMedialibraryField\Data\MediaAttachData;
use DmitryBubyakin\NovaMedialibraryField\Models\TransientModel;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\MediaCollections\Models\Media;

class MediaAttachAction
{
public function handle(MediaAttachData $data): void
{
$resourceModel = $this->getResourceModel($data);
$uuid = $this->getUuid($data);

$this->rememberTargetModel($data, $resourceModel);

call_user_func_array($data->field->attachCallback, [
$resourceModel,
$data->file,
$data->field->collectionName,
$data->field->diskName,
$uuid,
]);
}

private function getResourceModel(MediaAttachData $data): ?HasMedia
{
return $data->resourceExists ? $data->resourceModel : TransientModel::make();
}

private function getUuid(MediaAttachData $data): ?string
{
return $data->resourceExists ? '' : $data->fieldUuid;
}

private function rememberTargetModel(MediaAttachData $data, HasMedia $resourceModel): void
{
if (! $resourceModel instanceof TransientModel) {
return;
}

/** @var Media $media */
$media = config('media-library.media_model');

$callback = function (Media $media) use ($data, $resourceModel): void {
if ($media->collection_name !== $data->fieldUuid) {
return;
}

TransientModel::setCustomPropertyValue(
$media,
$data->resource::$model,
$data->field->collectionName,
);

$resourceModel->registerAllMediaConversions($media);
};

$media::creating($callback);
}
}
89 changes: 89 additions & 0 deletions src/Actions/MediaAttachmentListAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

namespace DmitryBubyakin\NovaMedialibraryField\Actions;

use DmitryBubyakin\NovaMedialibraryField\Data\MediaAttachmentListData;
use DmitryBubyakin\NovaMedialibraryField\Fields\Support\AttachableMediaPresenter;
use DmitryBubyakin\NovaMedialibraryField\Models\TransientModel;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Pagination\LengthAwarePaginator;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
use function DmitryBubyakin\NovaMedialibraryField\call_or_default;

class MediaAttachmentListAction
{
public function handle(MediaAttachmentListData $data): LengthAwarePaginator
{
$resourceModel = $this->getResourceModel($data);

$queryBuilder = $this->getBaseQueryBuilder();

$queryBuilder = $this->applyNameFilter($queryBuilder, $data->name);
$queryBuilder = $this->applyMaxSizeFilter($queryBuilder, $data->maxSize);
$queryBuilder = $this->applyMimeTypeFilter($queryBuilder, $data->mimeType);

$queryBuilder = call_or_default(
$data->field->attachExistingCallback,
[$queryBuilder, $data->request, $resourceModel],
) ?: $queryBuilder;

return $queryBuilder
->paginate($data->perPage)
->through(fn (Media $media): AttachableMediaPresenter => new AttachableMediaPresenter($media));
}

private function getResourceModel(MediaAttachmentListData $data): HasMedia
{
return $data->resourceExists
? $data->resourceModel
: TransientModel::make();
}

private function getBaseQueryBuilder(): Builder
{
/** @var Media $media */
$media = config('media-library.media_model');

return $media::query();
}

private function applyNameFilter(Builder $builder, ?string $name): Builder
{
$callback = function (Builder $builder) use ($name): Builder {
return $builder->where(function (Builder $builder) use ($name): Builder {
return $builder
->where('name', 'like', '%' . $name . '%')
->orWhere('file_name', 'like', '%' . $name . '%');
});
};

return $builder->when(!empty($name), $callback);
}

private function applyMaxSizeFilter(Builder $builder, ?int $maxSize): Builder
{
$callback = function (Builder $builder) use ($maxSize): Builder {
return $builder->where('size', '<=', $maxSize);
};

return $builder->when(!empty($maxSize), $callback);
}

private function applyMimeTypeFilter(Builder $builder, ?string $mimeType): Builder
{
$callback = function (Builder $builder) use ($mimeType): Builder {
if (str_contains($mimeType, ',')) {
$mimeTypes = explode(',', $mimeType);

return $builder->whereIn('mime_type', $mimeTypes);
}

$mimeType = str_replace('*', '%', $mimeType);

return $builder->where('mime_type', 'like', $mimeType);
};

return $builder->when(!empty($mimeType), $callback);
}
}
60 changes: 60 additions & 0 deletions src/Actions/MediaCropAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

namespace DmitryBubyakin\NovaMedialibraryField\Actions;

use DmitryBubyakin\NovaMedialibraryField\Data\MediaCropData;
use Spatie\Image\Enums\Orientation;
use Spatie\MediaLibrary\MediaCollections\Models\Media;

class MediaCropAction
{
public function handle(MediaCropData $data): void
{
$media = $this->findMedia($data->mediaId);

$this->setManipulations($media, $data);
}

private function findMedia(int $mediaId): Media
{
/** @var Media $media */
$media = config('media-library.media_model');

/** @var Media $media */
$media = $media::query()->findOrFail($mediaId);

return $media;
}

private function setManipulations(Media $media, MediaCropData $data): void
{
$media->manipulations = [
$data->conversion => [
'manualCrop' => $this->getManualCrop($data),
//'orientation' => $this->getOrientation($data),
],
];

$media->save();
}

private function getManualCrop(MediaCropData $data): array
{
return [
$data->cropWidth,
$data->cropHeight,
$data->cropX,
$data->cropY,
];
}

private function getOrientation(MediaCropData $data): Orientation
{
return match ($data->rotate) {
90 => Orientation::Rotate90,
180 => Orientation::Rotate180,
270 => Orientation::Rotate270,
default => Orientation::Rotate0,
};
}
}
54 changes: 54 additions & 0 deletions src/Actions/MediaListAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

namespace DmitryBubyakin\NovaMedialibraryField\Actions;

use DmitryBubyakin\NovaMedialibraryField\Data\MediaListData;
use DmitryBubyakin\NovaMedialibraryField\Fields\Medialibrary;
use DmitryBubyakin\NovaMedialibraryField\Fields\Support\MediaPresenter;
use DmitryBubyakin\NovaMedialibraryField\Models\TransientModel;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\MediaCollections\Models\Collections\MediaCollection;
use Spatie\MediaLibrary\MediaCollections\Models\Media;

class MediaListAction
{
public function handle(MediaListData $data): array
{
$resourceModel = $this->getResourceModel($data);
$collectionName = $this->getCollectionName($data);

$media = $this->getMedia($data->field, $resourceModel, $collectionName);

return $this->transformMedia($media, $data->field);
}

private function getResourceModel(MediaListData $data): HasMedia
{
return $data->resourceExists ? $data->resourceModel : TransientModel::make();
}

private function getCollectionName(MediaListData $data): ?string
{
return $data->resourceExists ? $data->field->collectionName : $data->fieldUuid;
}

private function getMedia(
Medialibrary $field,
HasMedia $resourceModel,
string $collectionName,
): MediaCollection
{
return call_user_func(
$field->resolveMediaUsingCallback,
$resourceModel,
$collectionName,
);
}

private function transformMedia(MediaCollection $media, Medialibrary $field): array
{
return $media
->map(fn (Media $media): MediaPresenter => new MediaPresenter($media, $field))
->toArray();
}
}
Loading

0 comments on commit 15aea91

Please sign in to comment.