Skip to content

Commit 39e4036

Browse files
authored
Merge pull request #12 from TappNetwork/update_links_and_policy
Update navigation items and permissions check
2 parents 546ef98 + 9ca1d45 commit 39e4036

File tree

10 files changed

+187
-383
lines changed

10 files changed

+187
-383
lines changed

phpstan-baseline.neon

Lines changed: 52 additions & 318 deletions
Large diffs are not rendered by default.

src/FilamentLibraryPlugin.php

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Filament\Contracts\Plugin;
66
use Filament\Navigation\NavigationItem;
77
use Filament\Panel;
8+
use Tapp\FilamentLibrary\Resources\LibraryItemResource;
89

910
class FilamentLibraryPlugin implements Plugin
1011
{
@@ -58,47 +59,49 @@ public static function isLibraryAdmin($user): bool
5859

5960
public function register(Panel $panel): void
6061
{
62+
$panelId = $panel->getId();
63+
6164
$panel
6265
->resources([
63-
\Tapp\FilamentLibrary\Resources\LibraryItemResource::class,
66+
LibraryItemResource::class,
6467
])
6568
->navigationItems([
6669
NavigationItem::make('Library')
67-
->url('/library')
70+
->url(fn () => LibraryItemResource::getUrl('index'))
6871
->icon('heroicon-o-building-library')
6972
->group('Resource Library')
7073
->sort(1)
71-
->isActiveWhen(fn () => request()->is('library')),
74+
->isActiveWhen(fn () => request()->routeIs("filament.{$panelId}.resources.library.index")),
7275
NavigationItem::make('Search All')
73-
->url('/library/search-all')
76+
->url(fn () => LibraryItemResource::getUrl('search-all'))
7477
->icon('heroicon-o-magnifying-glass')
7578
->group('Resource Library')
7679
->sort(2)
77-
->isActiveWhen(fn () => request()->is('library/search-all')),
80+
->isActiveWhen(fn () => request()->routeIs("filament.{$panelId}.resources.library.search-all")),
7881
NavigationItem::make('My Documents')
79-
->url('/library/my-documents')
82+
->url(fn () => LibraryItemResource::getUrl('my-documents'))
8083
->icon('heroicon-o-folder')
8184
->group('Resource Library')
8285
->sort(3)
83-
->isActiveWhen(fn () => request()->is('library/my-documents')),
86+
->isActiveWhen(fn () => request()->routeIs("filament.{$panelId}.resources.library.my-documents")),
8487
NavigationItem::make('Shared with Me')
85-
->url('/library/shared-with-me')
88+
->url(fn () => LibraryItemResource::getUrl('shared-with-me'))
8689
->icon('heroicon-o-share')
8790
->group('Resource Library')
8891
->sort(4)
89-
->isActiveWhen(fn () => request()->is('library/shared-with-me')),
92+
->isActiveWhen(fn () => request()->routeIs("filament.{$panelId}.resources.library.shared-with-me")),
9093
NavigationItem::make('Created by Me')
91-
->url('/library/created-by-me')
94+
->url(fn () => LibraryItemResource::getUrl('created-by-me'))
9295
->icon('heroicon-o-user')
9396
->group('Resource Library')
9497
->sort(5)
95-
->isActiveWhen(fn () => request()->is('library/created-by-me')),
98+
->isActiveWhen(fn () => request()->routeIs("filament.{$panelId}.resources.library.created-by-me")),
9699
NavigationItem::make('Favorites')
97-
->url('/library/favorites')
100+
->url(fn () => LibraryItemResource::getUrl('favorites'))
98101
->icon('heroicon-o-star')
99102
->group('Resource Library')
100103
->sort(6)
101-
->isActiveWhen(fn () => request()->is('library/favorites')),
104+
->isActiveWhen(fn () => request()->routeIs("filament.{$panelId}.resources.library.favorites")),
102105
]);
103106
}
104107

src/Middleware/RedirectToCorrectEditPage.php

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Tapp\FilamentLibrary\Middleware;
44

55
use Closure;
6+
use Filament\Facades\Filament;
67
use Illuminate\Http\Request;
78
use Tapp\FilamentLibrary\Models\LibraryItem;
89

@@ -13,20 +14,29 @@ class RedirectToCorrectEditPage
1314
*/
1415
public function handle(Request $request, Closure $next)
1516
{
16-
// Check if this is an edit route for library items
17-
if ($request->routeIs('filament.admin.resources.library.edit')) {
17+
$panel = Filament::getCurrentPanel();
18+
19+
if (! $panel) {
20+
return $next($request);
21+
}
22+
23+
$panelId = $panel->getId();
24+
25+
// Check if this is an edit route for library items in any panel
26+
if ($request->routeIs("filament.{$panelId}.resources.library.edit")) {
1827
$recordId = $request->route('record');
1928

2029
if ($recordId) {
2130
$libraryItem = LibraryItem::find($recordId);
2231

2332
if ($libraryItem) {
2433
// Redirect to the correct edit page based on type
25-
$editUrl = match ($libraryItem->type) {
26-
'folder' => route('filament.admin.resources.library.edit-folder', ['record' => $recordId]),
27-
'file' => route('filament.admin.resources.library.edit-file', ['record' => $recordId]),
28-
'link' => route('filament.admin.resources.library.edit-link', ['record' => $recordId]),
29-
default => route('filament.admin.resources.library.edit-folder', ['record' => $recordId]),
34+
$type = $libraryItem->type ?? 'folder';
35+
$editUrl = match ($type) {
36+
'folder' => route("filament.{$panelId}.resources.library.edit-folder", ['record' => $recordId]),
37+
'file' => route("filament.{$panelId}.resources.library.edit-file", ['record' => $recordId]),
38+
'link' => route("filament.{$panelId}.resources.library.edit-link", ['record' => $recordId]),
39+
default => route("filament.{$panelId}.resources.library.edit-folder", ['record' => $recordId]),
3040
};
3141

3242
return redirect($editUrl);

src/Models/LibraryItem.php

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,27 @@
1313
use Spatie\MediaLibrary\InteractsWithMedia;
1414
use Spatie\MediaLibrary\MediaCollections\Models\Media;
1515

16+
/**
17+
* @property int $id
18+
* @property string $name
19+
* @property string $slug
20+
* @property string $type
21+
* @property int|null $parent_id
22+
* @property int $created_by
23+
* @property int|null $updated_by
24+
* @property string|null $external_url
25+
* @property string|null $link_description
26+
* @property string|null $general_access
27+
* @property \Illuminate\Support\Carbon|null $created_at
28+
* @property \Illuminate\Support\Carbon|null $updated_at
29+
* @property \Illuminate\Support\Carbon|null $deleted_at
30+
* @property-read LibraryItem|null $parent
31+
* @property-read \Illuminate\Database\Eloquent\Collection<int, LibraryItem> $children
32+
* @property-read \Illuminate\Database\Eloquent\Model $creator
33+
* @property-read \Illuminate\Database\Eloquent\Model|null $updater
34+
* @property-read \Illuminate\Database\Eloquent\Collection<int, LibraryItemPermission> $permissions
35+
* @property-read \Illuminate\Database\Eloquent\Collection<int, LibraryItemTag> $tags
36+
*/
1637
class LibraryItem extends Model implements HasMedia
1738
{
1839
use HasFactory;
@@ -58,14 +79,16 @@ protected static function boot(): void
5879

5980
static::created(function (self $item) {
6081
// Copy parent folder permissions to the new item
61-
if ($item->parent_id) {
82+
if ($item->parent_id && $item->parent) {
6283
$parentPermissions = $item->parent->permissions()->get();
6384

6485
foreach ($parentPermissions as $permission) {
65-
$item->permissions()->create([
66-
'user_id' => $permission->user_id,
67-
'role' => $permission->role,
68-
]);
86+
if (isset($permission->user_id) && isset($permission->role)) {
87+
$item->permissions()->create([
88+
'user_id' => $permission->user_id,
89+
'role' => $permission->role,
90+
]);
91+
}
6992
}
7093
}
7194
});
@@ -103,7 +126,9 @@ public function children(): HasMany
103126
*/
104127
public function creator(): BelongsTo
105128
{
106-
return $this->belongsTo(\App\Models\User::class, 'created_by')->withDefault(function () {
129+
$userModel = config('filament-library.user_model', config('auth.providers.users.model', 'App\\Models\\User'));
130+
131+
return $this->belongsTo($userModel, 'created_by')->withDefault(function () {
107132
// Check if 'name' field exists
108133
if (\Illuminate\Support\Facades\Schema::hasColumn('users', 'name')) {
109134
return [
@@ -126,7 +151,9 @@ public function creator(): BelongsTo
126151
*/
127152
public function updater(): BelongsTo
128153
{
129-
return $this->belongsTo(\App\Models\User::class, 'updated_by');
154+
$userModel = config('filament-library.user_model', config('auth.providers.users.model', 'App\\Models\\User'));
155+
156+
return $this->belongsTo($userModel, 'updated_by');
130157
}
131158

132159
/**
@@ -199,7 +226,7 @@ public function getEffectiveRole($user): ?string
199226
->where('user_id', $user->id)
200227
->first();
201228

202-
if ($directPermission) {
229+
if ($directPermission && isset($directPermission->role)) {
203230
return $directPermission->role;
204231
}
205232

@@ -221,13 +248,13 @@ public function getEffectiveRole($user): ?string
221248
/**
222249
* Get the current owner of this item.
223250
*/
224-
public function getCurrentOwner(): ?\App\Models\User
251+
public function getCurrentOwner(): ?\Illuminate\Database\Eloquent\Model
225252
{
226253
$ownerPermission = $this->permissions()
227254
->where('role', 'owner')
228255
->first();
229256

230-
if ($ownerPermission) {
257+
if ($ownerPermission && $ownerPermission->user) {
231258
return $ownerPermission->user;
232259
}
233260

@@ -248,7 +275,7 @@ public function isCreatorOwner(): bool
248275
/**
249276
* Transfer ownership to another user.
250277
*/
251-
public function transferOwnership(\App\Models\User $newOwner): void
278+
public function transferOwnership(\Illuminate\Database\Eloquent\Model $newOwner): void
252279
{
253280
// Remove existing owner permissions
254281
$this->permissions()->where('role', 'owner')->delete();
@@ -271,7 +298,7 @@ public function transferOwnership(\App\Models\User $newOwner): void
271298
/**
272299
* Ensure a user has a personal folder (like Google Drive's "My Drive").
273300
*/
274-
public static function ensurePersonalFolder(\App\Models\User $user): self
301+
public static function ensurePersonalFolder(\Illuminate\Database\Eloquent\Model $user): self
275302
{
276303
// Check if user already has a personal folder via the relationship
277304
if ($user->personal_folder_id) {
@@ -306,7 +333,7 @@ public static function ensurePersonalFolder(\App\Models\User $user): self
306333
/**
307334
* Get a user's personal folder.
308335
*/
309-
public static function getPersonalFolder(\App\Models\User $user): ?self
336+
public static function getPersonalFolder(\Illuminate\Database\Eloquent\Model $user): ?self
310337
{
311338
if (! $user->personal_folder_id) {
312339
return null;
@@ -318,7 +345,7 @@ public static function getPersonalFolder(\App\Models\User $user): ?self
318345
/**
319346
* Generate the personal folder name for a user.
320347
*/
321-
public static function getPersonalFolderName(\App\Models\User $user): string
348+
public static function getPersonalFolderName(\Illuminate\Database\Eloquent\Model $user): string
322349
{
323350
// Try to get a display name from various user fields
324351
$name = $user->first_name ?? $user->name ?? $user->email ?? 'User';

src/Models/LibraryItemPermission.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@
66
use Illuminate\Database\Eloquent\Model;
77
use Illuminate\Database\Eloquent\Relations\BelongsTo;
88

9+
/**
10+
* @property int $id
11+
* @property int $library_item_id
12+
* @property int $user_id
13+
* @property string $role
14+
* @property \Illuminate\Support\Carbon|null $created_at
15+
* @property \Illuminate\Support\Carbon|null $updated_at
16+
* @property-read LibraryItem $libraryItem
17+
* @property-read \Illuminate\Database\Eloquent\Model $user
18+
*/
919
class LibraryItemPermission extends Model
1020
{
1121
use HasFactory;

src/Resources/LibraryItemResource.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -293,17 +293,17 @@ public static function table(Table $table): Table
293293
->toolbarActions([
294294
BulkActionGroup::make([
295295
DeleteBulkAction::make()
296-
->visible(fn (): bool => auth()->user() && auth()->user()->can('delete', LibraryItem::class))
296+
->visible(fn (): bool => auth()->user() && auth()->user()->can('deleteAny', LibraryItem::class))
297297
->successRedirectUrl(function () {
298298
// For bulk actions, redirect to current folder (maintain current location)
299299
$currentParent = request()->get('parent');
300300

301301
return static::getUrl('index', $currentParent ? ['parent' => $currentParent] : []);
302302
}),
303303
RestoreBulkAction::make()
304-
->visible(fn (): bool => auth()->user() && auth()->user()->can('delete', LibraryItem::class)),
304+
->visible(fn (): bool => auth()->user() && auth()->user()->can('restoreAny', LibraryItem::class)),
305305
ForceDeleteBulkAction::make()
306-
->visible(fn (): bool => auth()->user() && auth()->user()->can('delete', LibraryItem::class))
306+
->visible(fn (): bool => auth()->user() && auth()->user()->can('forceDeleteAny', LibraryItem::class))
307307
->successRedirectUrl(function () {
308308
// For bulk actions, redirect to current folder (maintain current location)
309309
$currentParent = request()->get('parent');

src/Resources/Pages/ListLibraryItems.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ protected function getTableQuery(): \Illuminate\Database\Eloquent\Builder
254254

255255
public function getTitle(): string
256256
{
257-
if ($this->parentFolder) {
257+
if ($this->parentFolder && isset($this->parentFolder->name)) {
258258
return $this->parentFolder->name;
259259
}
260260

@@ -263,7 +263,7 @@ public function getTitle(): string
263263

264264
public function getSubheading(): ?string
265265
{
266-
if ($this->parentFolder && $this->parentFolder->link_description) {
266+
if ($this->parentFolder && isset($this->parentFolder->link_description) && $this->parentFolder->link_description) {
267267
return $this->parentFolder->link_description;
268268
}
269269

@@ -298,7 +298,9 @@ public function getBreadcrumbs(): array
298298
// Generate URLs more efficiently
299299
$baseUrl = static::getResource()::getUrl('index');
300300
foreach ($path as $folder) {
301-
$breadcrumbs[$baseUrl . '?parent=' . $folder->id] = $folder->name;
301+
if (isset($folder->id) && isset($folder->name)) {
302+
$breadcrumbs[$baseUrl . '?parent=' . $folder->id] = $folder->name;
303+
}
302304
}
303305
}
304306

src/Resources/RelationManagers/LibraryItemPermissionsRelationManager.php

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Filament\Tables\Table;
1616
use Illuminate\Database\Eloquent\Model;
1717
use Illuminate\Support\Facades\Schema as SchemaFacade;
18+
use Tapp\FilamentLibrary\Models\LibraryItem;
1819
use Tapp\FilamentLibrary\Models\LibraryItemPermission;
1920

2021
class LibraryItemPermissionsRelationManager extends RelationManager
@@ -41,7 +42,7 @@ public static function canAccess(): bool
4142

4243
// For non-admins, check if they have share permission on the current record
4344
$record = static::getOwnerRecord();
44-
if ($record && $record->hasPermission($user, 'share')) {
45+
if ($record instanceof LibraryItem && $record->hasPermission($user, 'share')) {
4546
return true;
4647
}
4748

@@ -50,7 +51,7 @@ public static function canAccess(): bool
5051

5152
public static function canViewForRecord(Model $ownerRecord, string $pageClass): bool
5253
{
53-
return $ownerRecord->hasPermission(auth()->user(), 'share');
54+
return $ownerRecord instanceof LibraryItem && $ownerRecord->hasPermission(auth()->user(), 'share');
5455
}
5556

5657
/**
@@ -173,28 +174,28 @@ public function table(Table $table): Table
173174
])
174175
->headerActions([
175176
CreateAction::make()
176-
->visible(fn () => $this->ownerRecord->hasPermission(auth()->user(), 'share')),
177+
->visible(fn () => $this->ownerRecord instanceof LibraryItem && $this->ownerRecord->hasPermission(auth()->user(), 'share')),
177178
])
178179
->heading('User Permissions')
179180
->description('Owner: Share and edit. Editor/Viewer: Standard permissions.')
180-
->actions([
181+
->recordActions([
181182
EditAction::make()
182-
->visible(fn () => $this->ownerRecord->hasPermission(auth()->user(), 'share')),
183+
->visible(fn () => $this->ownerRecord instanceof LibraryItem && $this->ownerRecord->hasPermission(auth()->user(), 'share')),
183184
DeleteAction::make()
184-
->visible(fn () => $this->ownerRecord->hasPermission(auth()->user(), 'share')),
185+
->visible(fn () => $this->ownerRecord instanceof LibraryItem && $this->ownerRecord->hasPermission(auth()->user(), 'share')),
185186
])
186-
->bulkActions([
187+
->toolbarActions([
187188
BulkActionGroup::make([
188189
DeleteBulkAction::make()
189-
->visible(fn () => $this->ownerRecord->hasPermission(auth()->user(), 'share')),
190+
->visible(fn () => $this->ownerRecord instanceof LibraryItem && $this->ownerRecord->hasPermission(auth()->user(), 'share')),
190191
]),
191192
])
192193
->emptyStateHeading('No permissions assigned')
193194
->emptyStateDescription('Add users to grant them specific permissions on this item.')
194195
->emptyStateActions([
195196
CreateAction::make()
196197
->label('Add Permission')
197-
->visible(fn () => $this->ownerRecord->hasPermission(auth()->user(), 'share')),
198+
->visible(fn () => $this->ownerRecord instanceof LibraryItem && $this->ownerRecord->hasPermission(auth()->user(), 'share')),
198199
]);
199200
}
200201
}

0 commit comments

Comments
 (0)