Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions config/filament-library.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
<?php

use Tapp\FilamentLibrary\Models\LibraryItem;
use Tapp\FilamentLibrary\Models\LibraryItemPermission;
use Tapp\FilamentLibrary\Models\LibraryItemTag;
use Tapp\FilamentLibrary\Resources\LibraryItemResource;

return [
/*
|--------------------------------------------------------------------------
Expand All @@ -13,6 +18,62 @@
*/
'user_model' => env('FILAMENT_LIBRARY_USER_MODEL', 'App\\Models\\User'),

/*
|--------------------------------------------------------------------------
| Model class overrides
|--------------------------------------------------------------------------
|
| Extend package models in your application and register the classes here
| when you need custom behavior. Each class must extend the corresponding
| Tapp\FilamentLibrary\Models\* model.
|
| Example (in your app's config/filament-library.php):
|
| 'models' => [
| 'LibraryItem' => \App\Models\LibraryItem::class,
| 'LibraryItemPermission' => \App\Models\LibraryItemPermission::class,
| 'LibraryItemTag' => \App\Models\LibraryItemTag::class,
| ],
|
*/
'models' => [
'LibraryItem' => LibraryItem::class,
'LibraryItemPermission' => LibraryItemPermission::class,
'LibraryItemTag' => LibraryItemTag::class,
],

/*
|--------------------------------------------------------------------------
| Filament resource class overrides
|--------------------------------------------------------------------------
|
| Use this option to custom Filament Resource classes
|
| Example (in your app's config/filament-library.php):
|
| 'resources' => [
| 'LibraryItemResource' => \App\Filament\Resources\Library\LibraryItemResource::class,
| ],
|
*/
'resources' => [
'LibraryItemResource' => LibraryItemResource::class,
],

/*
|--------------------------------------------------------------------------
| Personal folder provisioning
|--------------------------------------------------------------------------
|
| When enabled, the plugin registers a listener that creates a personal
| library folder when a user is created. Disable this when your app
| provisions personal folders itself (for example with tenant checks).
|
*/
'personal_folder' => [
'auto_create_on_user_created' => env('FILAMENT_LIBRARY_AUTO_CREATE_PERSONAL_FOLDER', true),
],

/*
|--------------------------------------------------------------------------
| Video Link Support
Expand Down
16 changes: 16 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,22 @@ parameters:
count: 1
path: database/seeders/LibrarySeeder.php

# FilamentLibraryPlugin - App\Models\User is application-specific (default user model)
-
message: "#^Class App\\\\Models\\\\User not found\\.$#"
count: 1
path: src/FilamentLibraryPlugin.php

-
message: "#^PHPDoc tag @var for variable \\$userModel contains unknown class App\\\\Models\\\\User\\.$#"
count: 1
path: src/FilamentLibraryPlugin.php

-
message: "#^Call to an undefined static method App\\\\Models\\\\User\\:\\:created\\(\\)\\.$#"
count: 1
path: src/FilamentLibraryPlugin.php

# Config file - env() is allowed in config files
-
message: "#^Called 'env' outside of the config directory which returns null when the config is cached, use 'config'\\.$#"
Expand Down
116 changes: 104 additions & 12 deletions src/FilamentLibraryPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,25 @@
use Filament\Panel;
use Illuminate\Contracts\Auth\Authenticatable;
use Tapp\FilamentLibrary\Models\LibraryItem;
use Tapp\FilamentLibrary\Models\LibraryItemPermission;
use Tapp\FilamentLibrary\Models\LibraryItemTag;
use Tapp\FilamentLibrary\Resources\LibraryItemResource;

class FilamentLibraryPlugin implements Plugin
{
protected static $libraryAdminCallback = null;

protected static bool $personalFolderListenerRegistered = false;

/**
* @var array<string, class-string>
*/
protected static array $defaultModels = [
'LibraryItem' => LibraryItem::class,
'LibraryItemPermission' => LibraryItemPermission::class,
'LibraryItemTag' => LibraryItemTag::class,
];

public function getId(): string
{
return 'filament-library';
Expand Down Expand Up @@ -60,47 +73,111 @@ public static function isLibraryAdmin($user): bool
return false;
}

/**
* @return class-string<LibraryItemResource>
*/
public static function libraryItemResourceClass(): string
{
/** @var class-string<LibraryItemResource> $resourceClass */
$resourceClass = config(
'filament-library.resources.LibraryItemResource',
LibraryItemResource::class,
);

return $resourceClass;
}

/**
* @return class-string
*/
public static function modelClass(string $model): string
{
/** @var class-string $modelClass */
$modelClass = config(
"filament-library.models.{$model}",
static::$defaultModels[$model] ?? throw new \InvalidArgumentException("Unknown filament-library model [{$model}]."),
);

return $modelClass;
}

/**
* @return class-string<LibraryItem>
*/
public static function libraryItemModelClass(): string
{
/** @var class-string<LibraryItem> $modelClass */
$modelClass = static::modelClass('LibraryItem');

return $modelClass;
}

/**
* @return class-string<LibraryItemPermission>
*/
public static function libraryItemPermissionModelClass(): string
{
/** @var class-string<LibraryItemPermission> $modelClass */
$modelClass = static::modelClass('LibraryItemPermission');

return $modelClass;
}

/**
* @return class-string<LibraryItemTag>
*/
public static function libraryItemTagModelClass(): string
{
/** @var class-string<LibraryItemTag> $modelClass */
$modelClass = static::modelClass('LibraryItemTag');

return $modelClass;
}

public function register(Panel $panel): void
{
$panelId = $panel->getId();
$libraryItemResourceClass = static::libraryItemResourceClass();

$panel
->resources([
LibraryItemResource::class,
])
->resources(
array_values(config('filament-library.resources', [
LibraryItemResource::class,
])),
)
->navigationItems([
NavigationItem::make('Library')
->url(fn () => LibraryItemResource::getUrl('index'))
->url(fn () => $libraryItemResourceClass::getUrl('index'))
->icon('heroicon-o-building-library')
->group('Resource Library')
->sort(1)
->isActiveWhen(fn () => request()->routeIs("filament.{$panelId}.resources.library.index")),
NavigationItem::make('Search All')
->url(fn () => LibraryItemResource::getUrl('search-all'))
->url(fn () => $libraryItemResourceClass::getUrl('search-all'))
->icon('heroicon-o-magnifying-glass')
->group('Resource Library')
->sort(2)
->isActiveWhen(fn () => request()->routeIs("filament.{$panelId}.resources.library.search-all")),
NavigationItem::make('My Documents')
->url(fn () => LibraryItemResource::getUrl('my-documents'))
->url(fn () => $libraryItemResourceClass::getUrl('my-documents'))
->icon('heroicon-o-folder')
->group('Resource Library')
->sort(3)
->isActiveWhen(fn () => request()->routeIs("filament.{$panelId}.resources.library.my-documents")),
NavigationItem::make('Shared with Me')
->url(fn () => LibraryItemResource::getUrl('shared-with-me'))
->url(fn () => $libraryItemResourceClass::getUrl('shared-with-me'))
->icon('heroicon-o-share')
->group('Resource Library')
->sort(4)
->isActiveWhen(fn () => request()->routeIs("filament.{$panelId}.resources.library.shared-with-me")),
NavigationItem::make('Created by Me')
->url(fn () => LibraryItemResource::getUrl('created-by-me'))
->url(fn () => $libraryItemResourceClass::getUrl('created-by-me'))
->icon('heroicon-o-user')
->group('Resource Library')
->sort(5)
->isActiveWhen(fn () => request()->routeIs("filament.{$panelId}.resources.library.created-by-me")),
NavigationItem::make('Favorites')
->url(fn () => LibraryItemResource::getUrl('favorites'))
->url(fn () => $libraryItemResourceClass::getUrl('favorites'))
->icon('heroicon-o-star')
->group('Resource Library')
->sort(6)
Expand All @@ -110,9 +187,24 @@ public function register(Panel $panel): void

public function boot(Panel $panel): void
{
// Ensure users have personal folders when they access the library
User::created(function ($user) {
LibraryItem::ensurePersonalFolder($user);
if (! config('filament-library.personal_folder.auto_create_on_user_created', true)) {
return;
}

if (static::$personalFolderListenerRegistered) {
return;
}

static::$personalFolderListenerRegistered = true;

/** @var class-string<User> $userModel */
$userModel = config('filament-library.user_model', User::class);

$libraryItemModel = static::libraryItemModelClass();

// Optionally provision a personal folder when a user is created
$userModel::created(function ($user) use ($libraryItemModel): void {
$libraryItemModel::ensurePersonalFolder($user);
});
}

Expand Down
12 changes: 9 additions & 3 deletions src/FilamentLibraryServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,11 @@ public function packageBooted(): void
// Register middleware
$this->app['router']->pushMiddlewareToGroup('web', RedirectToCorrectEditPage::class);

// Register the policy
$this->app['Illuminate\Contracts\Auth\Access\Gate']->policy(LibraryItem::class, LibraryItemPolicy::class);
// Register the policy for the default package model only; host apps
// provide their own policy when overriding models.LibraryItem.
if (FilamentLibraryPlugin::libraryItemModelClass() === LibraryItem::class) {
$this->app['Illuminate\Contracts\Auth\Access\Gate']->policy(LibraryItem::class, LibraryItemPolicy::class);
}

// Handle Stubs
if (app()->runningInConsole()) {
Expand Down Expand Up @@ -180,10 +183,13 @@ protected function registerLibraryFileStoredEvent(): void

Media::created(function (Media $media): void {
$model = $media->model;
if (! $model instanceof LibraryItem) {
$libraryItemModel = FilamentLibraryPlugin::libraryItemModelClass();

if (! is_object($model) || ! is_a($model, $libraryItemModel)) {
return;
}

/** @var LibraryItem $item */
$item = $model;

if ($item->type !== 'file') {
Expand Down
4 changes: 2 additions & 2 deletions src/Middleware/RedirectToCorrectEditPage.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use Closure;
use Filament\Facades\Filament;
use Illuminate\Http\Request;
use Tapp\FilamentLibrary\Models\LibraryItem;
use Tapp\FilamentLibrary\FilamentLibraryPlugin;

class RedirectToCorrectEditPage
{
Expand All @@ -27,7 +27,7 @@ public function handle(Request $request, Closure $next)
$recordId = $request->route('record');

if ($recordId) {
$libraryItem = LibraryItem::find($recordId);
$libraryItem = FilamentLibraryPlugin::libraryItemModelClass()::find($recordId);

if ($libraryItem) {
// Redirect to the correct edit page based on type
Expand Down
12 changes: 8 additions & 4 deletions src/Models/LibraryItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,19 @@ protected static function boot(): void
*/
public function parent(): BelongsTo
{
return $this->belongsTo(LibraryItem::class, 'parent_id');
$libraryItemModel = config('filament-library.models.LibraryItem', static::class);

return $this->belongsTo($libraryItemModel, 'parent_id');
}

/**
* Get the child items.
*/
public function children(): HasMany
{
return $this->hasMany(LibraryItem::class, 'parent_id');
$libraryItemModel = config('filament-library.models.LibraryItem', static::class);

return $this->hasMany($libraryItemModel, 'parent_id');
}

/**
Expand Down Expand Up @@ -163,7 +167,7 @@ public function updater(): BelongsTo
*/
public function permissions(): HasMany
{
return $this->hasMany(LibraryItemPermission::class);
return $this->hasMany(config('filament-library.models.LibraryItemPermission', LibraryItemPermission::class));
}

/**
Expand Down Expand Up @@ -637,7 +641,7 @@ public static function getGeneralAccessOptions(): array
*/
public function tags(): BelongsToMany
{
return $this->belongsToMany(LibraryItemTag::class, 'library_item_tag_pivot')
return $this->belongsToMany(config('filament-library.models.LibraryItemTag', LibraryItemTag::class), 'library_item_tag_pivot')
->withTimestamps();
}

Expand Down
2 changes: 1 addition & 1 deletion src/Models/LibraryItemPermission.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class LibraryItemPermission extends Model
*/
public function libraryItem(): BelongsTo
{
return $this->belongsTo(LibraryItem::class);
return $this->belongsTo(config('filament-library.models.LibraryItem', LibraryItem::class));
}

/**
Expand Down
Loading