Skip to content

Commit

Permalink
[Feature] Scope Folder to selected users & return folders/media to API
Browse files Browse the repository at this point in the history
  • Loading branch information
3x1io committed Jul 24, 2024
1 parent c882c97 commit 9545408
Show file tree
Hide file tree
Showing 27 changed files with 680 additions and 212 deletions.
34 changes: 34 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,40 @@ you can allow create and manage subfolders on your media manager on `/app/Provid
)
```

## Allow User Access

now you can allow user to access selected folder and restract user to access each other folders if the folder is not public on `/app/Providers/Filament/AdminPanelProvider.php`

```php
->plugin(
\TomatoPHP\FilamentMediaManager\FilamentMediaManagerPlugin::make()
->allowUserAccess()
)
```

**NOTE** don't forget to migrate after update the plugin

## Folders API

now you can access your media and folders using API you have 2 endpoints

- `/api/folders` to get all folders
- `/api/folders/{id}` to get folder by id with sub folders and media files

to allow this feature you need to publish the config file by use this command

```bash
php artisan vendor:publish --tag="filament-media-manager-config"
```

then you can set `api.active` to `true` on the config file

```php
'api' => [
"active" => true,
],
```

## Publish Assets

you can publish config file by use this command
Expand Down
14 changes: 14 additions & 0 deletions config/filament-media-manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,19 @@
"model" => [
"folder" => \TomatoPHP\FilamentMediaManager\Models\Folder::class,
"media" => \TomatoPHP\FilamentMediaManager\Models\Media::class,
],

"api" => [
"active" => false,
"middlewares" => [
"api",
"auth:sanctum"
],
"prefix" => "api/media-manager",
"resources" => [
"folders" => \TomatoPHP\FilamentMediaManager\Http\Resources\FoldersResource::class,
"folder" => \TomatoPHP\FilamentMediaManager\Http\Resources\FolderResource::class,
"media" => \TomatoPHP\FilamentMediaManager\Http\Resources\MediaResource::class
]
]
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('folder_has_models', function (Blueprint $table) {
$table->id();

//Morph
$table->string('model_type');
$table->unsignedBigInteger('model_id');

//Folder
$table->foreignId('folder_id')->constrained('folders')->onDelete('cascade');

$table->timestamps();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('media_has_models');
}
};
38 changes: 38 additions & 0 deletions database/migrations/2024_10_03_171810_update_folders_table.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('folders', function (Blueprint $table) {
$table->boolean('is_public')->default(true)->nullable();
$table->boolean('has_user_access')->default(false)->nullable();
$table->unsignedBigInteger('user_id')->nullable();
$table->string('user_type')->nullable();
});
}

/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('folders', function (Blueprint $table) {
$table->dropColumn('is_public');
$table->dropColumn('has_user_access');
$table->dropColumn('user_id');
$table->dropColumn('user_type');
});
}
};
3 changes: 0 additions & 3 deletions resources/lang/ar.json

This file was deleted.

3 changes: 0 additions & 3 deletions resources/lang/en.json

This file was deleted.

3 changes: 3 additions & 0 deletions resources/lang/en/messages.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
'name' => 'Name',
'collection' => 'Collection',
'description' => 'Description',
'is_public' => 'Is Public',
'has_user_access' => 'Has User Access',
'users' => 'Users',
'icon' => 'Icon',
'color' => 'Color',
'is_protected' => 'Is Protected',
Expand Down
38 changes: 25 additions & 13 deletions resources/views/pages/media.blade.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@php
$currentFolder = \TomatoPHP\FilamentMediaManager\Models\Folder::find($this->folder_id);
if(filament('filament-media-manager')->allowSubFolders){
$folders = \TomatoPHP\FilamentMediaManager\Models\Folder::query()
->where('model_type', \TomatoPHP\FilamentMediaManager\Models\Folder::class)
Expand Down Expand Up @@ -50,10 +51,10 @@
<div>
<div class="flex flex-col justify-between border-t dark:border-gray-700 p-4">
<div>
<h1 class="font-bold break-words">{{ $item->hasCustomProperty('title') ? $item->getCustomProperty('title') : $item->name }}</h1>
<h1 class="font-bold break-words">{{ $item->hasCustomProperty('title') ? (!empty($item->getCustomProperty('title')) ? $item->getCustomProperty('title') : $item->name) : $item->name }}</h1>
</div>

@if($item->hasCustomProperty('description'))
@if($item->hasCustomProperty('description') && !empty($item->getCustomProperty('description')))
<div>
<div>
<h1 class="font-bold">Description</h1>
Expand Down Expand Up @@ -186,25 +187,36 @@
</div>
@if($item->custom_properties)
@foreach($item->custom_properties as $key=>$value)
<div>
@if($value)
<div>
<h1 class="font-bold">{{str($key)->title()}}</h1>
</div>
<div class="flex justify-start">
<p class="text-sm">
{{ $value }}
</p>
<div>
<h1 class="font-bold">{{str($key)->title()}}</h1>
</div>
<div class="flex justify-start">
<p class="text-sm">
{{ $value }}
</p>
</div>
</div>
</div>
@endif
@endforeach
@endif
</div>
</div>
</div>

<x-slot name="footer">
{{ ($this->deleteMedia)(['record' => $item]) }}
</x-slot>
@if(filament('filament-media-manager')->allowUserAccess && (!empty($currentFolder->user_id)))
@if($currentFolder->user_id === auth()->user()->id && $currentFolder->user_type === get_class(auth()->user()))
<x-slot name="footer">
{{ ($this->deleteMedia)(['record' => $item]) }}
</x-slot>
@endif
@else
<x-slot name="footer">
{{ ($this->deleteMedia)(['record' => $item]) }}
</x-slot>
@endif

</x-filament::modal>
@endif
@endforeach
Expand Down
8 changes: 8 additions & 0 deletions routes/api.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

use Illuminate\Support\Facades\Route;

Route::middleware(config('filament-media-manager.api.middlewares'))->prefix(config('filament-media-manager.api.prefix'))->name('media-manager.')->group(function (){
Route::get('/folders', [\TomatoPHP\FilamentMediaManager\Http\Controllers\FolderController::class, 'index'])->name('folders.index');
Route::get('/folders/{id}', [\TomatoPHP\FilamentMediaManager\Http\Controllers\FolderController::class, 'show'])->name('folders.show');
});
3 changes: 0 additions & 3 deletions routes/web.php

This file was deleted.

7 changes: 7 additions & 0 deletions src/FilamentMediaManagerPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
class FilamentMediaManagerPlugin implements Plugin
{
public ?bool $allowSubFolders = false;
public ?bool $allowUserAccess = false;

public function getId(): string
{
Expand All @@ -25,6 +26,12 @@ public function allowSubFolders(bool $condation = true): static
return $this;
}

public function allowUserAccess(bool $condation = true): static
{
$this->allowUserAccess = $condation;
return $this;
}

public function register(Panel $panel): void
{
$panel->resources([
Expand Down
6 changes: 4 additions & 2 deletions src/FilamentMediaManagerServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,10 @@ public function register(): void
__DIR__.'/../resources/lang' => base_path('lang/vendor/filament-media-manager'),
], 'filament-media-manager-lang');

//Register Routes
$this->loadRoutesFrom(__DIR__.'/../routes/web.php');
if(config('filament-media-manager.api.active')){
//Register Routes
$this->loadRoutesFrom(__DIR__.'/../routes/api.php');
}

$this->app->bind('filament-media-manager', function () {
return new FilamentMediaManagerServices();
Expand Down
29 changes: 23 additions & 6 deletions src/Form/MediaManagerInput.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,23 +95,33 @@ protected function setUp(): void
->where('collection', null)
->first();
if(!$homeFolder){
$homeFolder = config('filament-media-manager.model.folder')::create([
$data = [
'model_type' => get_class($record),
'model_id' => null,
'name' => Str::of(get_class($record))->afterLast('\\')->title()->toString()
]);
];
if(filament('filament-media-manager')->allowUserAccess){
$data['user_id'] = auth()->user()->id;
$data['user_type'] = get_class(auth()->user());
}
$homeFolder = config('filament-media-manager.model.folder')::create($data);
}

$collectionFolder = config('filament-media-manager.model.folder')::where('model_type', get_class($record))
->where('model_id', null)
->where('collection', $component->name)
->first();
if(!$collectionFolder){
$collectionFolder = config('filament-media-manager.model.folder')::create([
$data = [
'collection' => $component->name,
'model_type' => get_class($record),
'name' => Str::of($component->name)->title()->toString()
]);
];
if(filament('filament-media-manager')->allowUserAccess){
$data['user_id'] = auth()->user()->id;
$data['user_type'] = get_class(auth()->user());
}
$collectionFolder = config('filament-media-manager.model.folder')::create($data);
}

$folder = config('filament-media-manager.model.folder')::where('collection', $component->name)
Expand All @@ -120,12 +130,19 @@ protected function setUp(): void
->first();

if(!$folder){
$folder = config('filament-media-manager.model.folder')::create([
$data = [
'collection' => $component->name,
'model_type' => get_class($record),
'model_id' => $record->id,
'name' => $component->folderTitleFieldName ? $record->{$component->folderTitleFieldName} : Str::of( get_class($record))->afterLast('\\')->title()->toString() . '['.$record->id.']',
]);
];

if(filament('filament-media-manager')->allowUserAccess){
$data['user_id'] = auth()->user()->id;
$data['user_type'] = get_class(auth()->user());
}

$folder = config('filament-media-manager.model.folder')::create($data);
}

$callback = $media->getAttributeValue('uuid');
Expand Down
36 changes: 36 additions & 0 deletions src/Http/Controllers/FolderController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace TomatoPHP\FilamentMediaManager\Http\Controllers;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
use TomatoPHP\FilamentMediaManager\Http\Resources\FolderResource;
use TomatoPHP\FilamentMediaManager\Http\Resources\FoldersResource;
use TomatoPHP\FilamentMediaManager\Http\Resources\MediaResource;
use TomatoPHP\FilamentMediaManager\Models\Folder;

class FolderController extends Controller
{
public function index(Request $request)
{
$folders = config('filament-media-manager.model.folder')::query();

if ($request->has('search')) {
$folders->where('name', 'like', '%'.$request->search.'%');
}

return response()->json([
'data' => config('filament-media-manager.api.resources.folders')::collection($folders->paginate(10))
], 200);
}

public function show(int $id)
{
$folder = Folder::query()->findOrFail($id);

return response()->json([
'data' => config('filament-media-manager.api.resources.folder')::make($folder)
], 200);
}
}
Empty file removed src/Http/Middleware/.gitkeep
Empty file.
Empty file removed src/Http/Requests/.gitkeep
Empty file.
Loading

0 comments on commit 9545408

Please sign in to comment.