Skip to content

Commit f4ef898

Browse files
authored
Merge pull request #12 from TappNetwork/option_to_add_forum_by_user
Ability to add forum
2 parents 1aa4181 + cf89335 commit f4ef898

10 files changed

Lines changed: 182 additions & 3 deletions

File tree

README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ The `ForumUser` trait provides:
9999
- `getMentionableUsers()` method - Customize which users are mentionable (see "Custom Mentionables" below)
100100
- `hasCustomForumSearch()`, `getForumSearchResults()`, `getForumOptionLabel()` methods - Custom search functionality (see "Custom User Model, Attribute, and Search Functionality" below)
101101
- `isForumAdmin()` method - Override to grant admin access to hidden forums (defaults to `false`)
102+
- `canCreateForum()` method - Controls forum creation permissions (see "Forum Creation Permissions" below)
102103

103104
6. Add to your custom theme (usually`theme.css`) file:
104105

@@ -370,6 +371,49 @@ public static function getMentionableUsers()
370371

371372
Forums can be set as public (visible to all logged-in users) or hidden (only visible to assigned users). Forum admins can see all hidden forums regardless of assignment.
372373

374+
### Forum Creation Permissions
375+
376+
By default, forum creation is **disabled** for security. To enable forum creation, you must add the `ForumUser` trait to your User model and override the `canCreateForum()` method:
377+
378+
```php
379+
// In your User model
380+
use Tapp\FilamentForum\Traits\ForumUser;
381+
382+
class User extends Authenticatable
383+
{
384+
use ForumUser;
385+
386+
/**
387+
* Determine if the user can create forums.
388+
* Override this method to enable forum creation with custom logic.
389+
*/
390+
public function canCreateForum(): bool
391+
{
392+
// Example: Using Spatie Laravel Permission
393+
return $this->hasPermissionTo('create forum');
394+
395+
// Example: Using roles
396+
// return $this->hasRole(['Admin', 'Moderator']);
397+
398+
// Example: Allow all authenticated users
399+
// return true;
400+
401+
// Example: Custom logic
402+
// return $this->is_verified && $this->reputation_points >= 100;
403+
}
404+
}
405+
```
406+
407+
**Important**:
408+
- Make sure to add the `ForumUser` trait to your User model (see step 5 in Installation)
409+
- The trait provides a default implementation that returns `false` for security
410+
- You must explicitly override `canCreateForum()` to enable forum creation
411+
412+
The `canCreateForum()` method is:
413+
- **Checked automatically** when displaying the "Create" button on the forums list page
414+
- **Enforced** when accessing the forum creation page
415+
- **Secure by default** - forum creation is disabled unless explicitly enabled
416+
373417
### Setting Forum Access
374418

375419
In the admin panel, you can set a forum as hidden by checking the "Hidden Forum" checkbox. Hidden forums will only be visible to:

database/migrations/create_forum_user_table.php.stub

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ return new class extends Migration
1313
{
1414
Schema::create('forum_user', function (Blueprint $table) {
1515
$table->id();
16-
$table->foreignId('user_id')->constrained()->onDelete('cascade');
17-
$table->foreignId('forum_id')->constrained('forums')->onDelete('cascade');
16+
$table->foreignId('user_id')->constrained()->cascadeOnDelete();
17+
$table->foreignId('forum_id')->constrained('forums')->cascadeOnDelete();
1818
$table->timestamps();
1919
$table->unique(['user_id', 'forum_id']);
2020
});

database/migrations/create_forums_table.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ public function up(): void
2222
->cascadeOnDelete();
2323
}
2424

25-
$table->foreignId('owner_id')->nullable()->constrained('users')->onDelete('set null');
25+
$table->foreignId('owner_id')->nullable()->constrained('users')->nullOnDelete();
2626
$table->string('name');
2727
$table->text('description')->nullable();
2828
$table->timestamps();

resources/lang/en/filament-forum.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
'forum.navigation-label' => 'Forums',
1414
'forum.view-posts' => 'View Posts',
1515
'forum.active' => 'Active',
16+
'forum.delete.tooltip' => 'Delete',
17+
'forum.delete.modal.heading' => 'Delete Forum',
18+
'forum.delete.modal.description' => 'Are you sure you want to delete this forum? This action cannot be undone.',
19+
'forum.delete.notification' => 'Forum deleted successfully',
1620

1721
/*
1822
|--------------------------------------------------------------------------

resources/views/filament/tables/components/forum-card-column.blade.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
@php
22
use Tapp\FilamentForum\Filament\Resources\Forums\ForumResource;
33
$record = $getRecord();
4+
$livewire = $getLivewire();
5+
$canDelete = auth()->user() && auth()->id() === $record->owner_id && $record->forumPosts()->count() === 0;
46
@endphp
57

68
<div class="w-full h-full flex flex-col">
@@ -13,6 +15,12 @@
1315
class="w-full h-full object-cover"
1416
>
1517
@endif
18+
19+
@if($canDelete)
20+
<div class="absolute top-2 right-2">
21+
{{ ($livewire->deleteAction)(['record' => $record->id]) }}
22+
</div>
23+
@endif
1624
</div>
1725

1826
{{-- Content --}}

src/Filament/Resources/Forums/ForumResource.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@
77
use Filament\Resources\Resource;
88
use Filament\Schemas\Components\Fieldset;
99
use Filament\Schemas\Components\Section;
10+
use Filament\Schemas\Schema;
1011
use Filament\Support\Enums\Alignment;
1112
use Filament\Tables\Columns\Layout\Stack;
1213
use Filament\Tables\Table;
1314
use Illuminate\Database\Eloquent\Model;
15+
use Tapp\FilamentForum\Filament\Resources\Forums\Pages\CreateForum;
1416
use Tapp\FilamentForum\Filament\Resources\Forums\Pages\ListForums;
1517
use Tapp\FilamentForum\Filament\Resources\Forums\Pages\ManageForumPosts;
1618
use Tapp\FilamentForum\Filament\Resources\Forums\Pages\ViewForum;
19+
use Tapp\FilamentForum\Filament\Resources\Forums\Schemas\ForumForm;
1720
use Tapp\FilamentForum\Filament\Tables\Components\ForumCardColumn;
1821
use Tapp\FilamentForum\Models\Forum;
1922

@@ -56,6 +59,11 @@ public static function getNavigationLabel(): string
5659
return __('filament-forum::filament-forum.forum.navigation-label');
5760
}
5861

62+
public static function form(Schema $schema): Schema
63+
{
64+
return ForumForm::configure($schema);
65+
}
66+
5967
public static function table(Table $table): Table
6068
{
6169
return $table
@@ -104,6 +112,7 @@ public static function getPages(): array
104112

105113
return [
106114
'index' => ListForums::route('/'),
115+
'create' => CreateForum::route('/create'),
107116
// 'view' => ViewForum::route('/{record}'),
108117
'forum-posts' => ManageForumPosts::route("/{record}/{$forumPostSlug}"),
109118
];
@@ -116,6 +125,19 @@ public static function getSlug(?\Filament\Panel $panel = null): string
116125

117126
public static function canCreate(): bool
118127
{
128+
$user = auth()->user();
129+
130+
if (! $user) {
131+
return false;
132+
}
133+
134+
// Check if the user model has the canCreateForum method
135+
if (method_exists($user, 'canCreateForum')) {
136+
return $user->canCreateForum();
137+
}
138+
139+
// Backward compatibility: return false if method doesn't exist
140+
// This ensures existing installations don't suddenly allow forum creation
119141
return false;
120142
}
121143

src/Filament/Resources/Forums/Pages/CreateForum.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,12 @@
88
class CreateForum extends CreateRecord
99
{
1010
protected static string $resource = ForumResource::class;
11+
12+
protected function mutateFormDataBeforeCreate(array $data): array
13+
{
14+
// Automatically set the owner to the currently logged-in user
15+
$data['owner_id'] = auth()->id();
16+
17+
return $data;
18+
}
1119
}

src/Filament/Resources/Forums/Pages/ListForums.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace Tapp\FilamentForum\Filament\Resources\Forums\Pages;
44

5+
use Filament\Actions\CreateAction;
6+
use Filament\Actions\DeleteAction;
57
use Filament\Resources\Pages\ListRecords;
68
use Illuminate\Contracts\Support\Htmlable;
79
use Illuminate\Support\Facades\Auth;
@@ -17,6 +19,35 @@ public function getTitle(): string|Htmlable
1719
return __('filament-forum::filament-forum.forum.title');
1820
}
1921

22+
public function deleteAction(): DeleteAction
23+
{
24+
return DeleteAction::make()
25+
->requiresConfirmation()
26+
->modalHeading(__('filament-forum::filament-forum.forum.delete.modal.heading'))
27+
->modalDescription(__('filament-forum::filament-forum.forum.delete.modal.description'))
28+
->successNotificationTitle(__('filament-forum::filament-forum.forum.delete.notification'))
29+
->iconButton()
30+
->icon('heroicon-o-trash')
31+
->color('danger')
32+
->tooltip(__('filament-forum::filament-forum.forum.delete.tooltip'))
33+
->size('sm')
34+
->extraAttributes(['class' => 'p-1'])
35+
->record(fn (array $arguments) => Forum::find($arguments['record']))
36+
->visible(
37+
fn (array $arguments) => auth()->check() &&
38+
Forum::find($arguments['record'])?->owner_id === auth()->id() &&
39+
Forum::find($arguments['record'])?->forumPosts()->count() === 0
40+
);
41+
}
42+
43+
protected function getHeaderActions(): array
44+
{
45+
return [
46+
CreateAction::make()
47+
->visible(fn (): bool => static::getResource()::canCreate()),
48+
];
49+
}
50+
2051
protected function getTableQuery(): \Illuminate\Database\Eloquent\Builder
2152
{
2253
$user = Auth::user();
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace Tapp\FilamentForum\Filament\Resources\Forums\Schemas;
4+
5+
use Filament\Forms\Components\Checkbox;
6+
use Filament\Forms\Components\SpatieMediaLibraryFileUpload;
7+
use Filament\Forms\Components\Textarea;
8+
use Filament\Forms\Components\TextInput;
9+
use Filament\Schemas\Components\Section;
10+
use Filament\Schemas\Schema;
11+
12+
class ForumForm
13+
{
14+
public static function configure(Schema $schema): Schema
15+
{
16+
return $schema
17+
->components([
18+
Section::make()
19+
->id('forumForm')
20+
->columnSpanFull()
21+
->columns(2)
22+
->schema([
23+
TextInput::make('name')
24+
->label(__('filament-forum::filament-forum.forum.form.label.name'))
25+
->required()
26+
->maxLength(255)
27+
->columnSpanFull(),
28+
Textarea::make('description')
29+
->label(__('filament-forum::filament-forum.forum.form.label.description'))
30+
->required()
31+
->columnSpanFull(),
32+
SpatieMediaLibraryFileUpload::make('image')
33+
->label(__('filament-forum::filament-forum.forum.form.label.image'))
34+
->collection('images')
35+
->columnSpanFull(),
36+
Checkbox::make('is_hidden')
37+
->label('Hidden Forum')
38+
->helperText('If checked, only assigned users can view this forum. If unchecked, all logged in users can view it.')
39+
->live(),
40+
]),
41+
]);
42+
}
43+
}

src/Traits/ForumUser.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,23 @@ public function isForumAdmin(): bool
9191
// Override this in your User model to implement admin logic
9292
return false;
9393
}
94+
95+
/**
96+
* Determine if the user can create forums.
97+
*
98+
* By default, this returns false for security. Override this method in your
99+
* User model to enable forum creation with custom logic.
100+
*
101+
* Example:
102+
* ```
103+
* public function canCreateForum(): bool
104+
* {
105+
* return $this->hasPermissionTo('create forum');
106+
* }
107+
* ```
108+
*/
109+
public function canCreateForum(): bool
110+
{
111+
return false;
112+
}
94113
}

0 commit comments

Comments
 (0)