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
20 changes: 9 additions & 11 deletions database/factories/HelpArticleFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@

use Illuminate\Database\Eloquent\Factories\Factory;
use Tapp\FilamentHelp\Models\HelpArticle;
use Tapp\FilamentHelp\Support\Tenancy;

/**
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\Tapp\FilamentHelp\Models\HelpArticle>
* @extends Factory<HelpArticle>
*/
class HelpArticleFactory extends Factory
{
Expand All @@ -19,13 +20,12 @@ public function definition(): array
'is_public' => $this->faker->boolean(70), // 70% chance of being public
'content' => $this->faker->paragraphs(3, true),
];

// Add tenant column if tenancy is enabled
if (config('filament-help.tenancy.enabled', false)) {
$tenantColumn = config('filament-help.tenancy.column') ?? 'team_id';
$definition[$tenantColumn] = null; // Will be set explicitly or by model boot logic
if (Tenancy::hasTenantColumn()) {
$definition[Tenancy::column()] = null; // Will be set explicitly or by model boot logic
}

return $definition;
}

Expand All @@ -52,14 +52,12 @@ public function hidden(): static

public function forTeam($team): static
{
if (! config('filament-help.tenancy.enabled', false)) {
if (! Tenancy::hasTenantColumn()) {
return $this;
}

$tenantColumn = config('filament-help.tenancy.column') ?? 'team_id';


return $this->state(fn (array $attributes) => [
$tenantColumn => is_object($team) ? $team->id : $team,
Tenancy::column() => is_object($team) ? $team->id : $team,
]);
}
}
36 changes: 17 additions & 19 deletions src/Models/HelpArticle.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

namespace Tapp\FilamentHelp\Models;

use Filament\Facades\Filament;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Tapp\FilamentHelp\Support\Tenancy;

class HelpArticle extends Model
{
Expand All @@ -21,11 +23,10 @@ class HelpArticle extends Model
public function __construct(array $attributes = [])
{
parent::__construct($attributes);

// Dynamically add tenant column to fillable if tenancy is enabled
if (config('filament-help.tenancy.enabled', false)) {
$tenantColumn = config('filament-help.tenancy.column') ?? 'team_id';
$this->fillable[] = $tenantColumn;
if (Tenancy::isEnabled()) {
$this->fillable[] = Tenancy::column();
}
}

Expand All @@ -49,33 +50,30 @@ public function scopeVisible($query)
*/
public function scopeForTenant($query, $tenant)
{
if (! config('filament-help.tenancy.enabled', false)) {
if (! Tenancy::hasTenantColumn(static::class)) {
return $query;
}

$tenantColumn = config('filament-help.tenancy.column') ?? 'team_id';

return $query->where($tenantColumn, $tenant->id);

return $query->where(Tenancy::column(), $tenant->id);
}

/**
* Define your tenant relationship here.
*
*
* Example for Team:
*
*
* public function team(): BelongsTo
* {
* return $this->belongsTo(\App\Models\Team::class);
* }
*
*
* Or for Organization:
*
*
* public function organization(): BelongsTo
* {
* return $this->belongsTo(\App\Models\Organization::class);
* }
*/

protected static function boot()
{
parent::boot();
Expand All @@ -86,11 +84,11 @@ protected static function boot()
}

// Auto-assign team_id from current Filament tenant if available and enabled
if (config('filament-help.tenancy.enabled', false) && config('filament-help.tenancy.auto_assign', true)) {
$tenantColumn = config('filament-help.tenancy.column') ?? 'team_id';
if (empty($article->{$tenantColumn}) && class_exists(\Filament\Facades\Filament::class)) {
$tenant = \Filament\Facades\Filament::getTenant();
if (Tenancy::hasTenantColumn(static::class) && config('filament-help.tenancy.auto_assign', true)) {
$tenantColumn = Tenancy::column();

if (empty($article->{$tenantColumn}) && class_exists(Filament::class)) {
$tenant = Filament::getTenant();
if ($tenant) {
$article->{$tenantColumn} = $tenant->id;
}
Expand Down
12 changes: 7 additions & 5 deletions src/Resources/Frontend/HelpArticleResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@
use Filament\Support\Enums\Alignment;
use Filament\Tables\Columns\Layout\Stack;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Tapp\FilamentHelp\Models\HelpArticle;
use Tapp\FilamentHelp\Resources\Frontend\Pages\ListHelpArticles;
use Tapp\FilamentHelp\Resources\Frontend\Pages\ViewHelpArticle;
use Tapp\FilamentHelp\Support\Tenancy;
use Tapp\FilamentHelp\Tables\Components\HelpArticleCardColumn;

class HelpArticleResource extends Resource
Expand All @@ -18,7 +21,7 @@ class HelpArticleResource extends Resource

public static function getModel(): string
{
return static::$model ?? config('filament-help.model', \Tapp\FilamentHelp\Models\HelpArticle::class);
return static::$model ?? config('filament-help.model', HelpArticle::class);
}

protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-question-mark-circle';
Expand Down Expand Up @@ -97,18 +100,17 @@ public static function canDelete($record): bool
return false;
}

public static function getEloquentQuery(): \Illuminate\Database\Eloquent\Builder
public static function getEloquentQuery(): Builder
{
$query = parent::getEloquentQuery()
->public()
->visible();

// Apply tenant scoping if enabled
if (config('filament-help.tenancy.enabled', false) && config('filament-help.tenancy.scoping.frontend', true)) {
if (Tenancy::hasTenantColumn(static::getModel()) && config('filament-help.tenancy.scoping.frontend', true)) {
$tenant = Filament::getTenant();
if ($tenant) {
$tenantColumn = config('filament-help.tenancy.column') ?? 'team_id';
$query->where($tenantColumn, $tenant->id);
$query->where(Tenancy::column(), $tenant->id);
}
}

Expand Down
18 changes: 11 additions & 7 deletions src/Resources/Guest/HelpArticleResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@
namespace Tapp\FilamentHelp\Resources\Guest;

use Filament\Actions\ViewAction;
use Filament\Facades\Filament;
use Filament\Panel;
use Filament\Resources\Resource;
use Filament\Support\Enums\Alignment;
use Filament\Tables\Columns\Layout\Stack;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Tapp\FilamentHelp\Models\HelpArticle;
use Tapp\FilamentHelp\Resources\Guest\Pages\ListHelpArticles;
use Tapp\FilamentHelp\Resources\Guest\Pages\ViewHelpArticle;
use Tapp\FilamentHelp\Support\Tenancy;
use Tapp\FilamentHelp\Tables\Components\HelpArticleCardColumn;

class HelpArticleResource extends Resource
Expand All @@ -17,7 +22,7 @@ class HelpArticleResource extends Resource

public static function getModel(): string
{
return static::$model ?? config('filament-help.model', \Tapp\FilamentHelp\Models\HelpArticle::class);
return static::$model ?? config('filament-help.model', HelpArticle::class);
}

protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-question-mark-circle';
Expand All @@ -41,7 +46,7 @@ public static function setSlug(string $slug): void
static::$slug = $slug;
}

public static function getSlug(?\Filament\Panel $panel = null): string
public static function getSlug(?Panel $panel = null): string
{
return static::$slug;
}
Expand Down Expand Up @@ -94,18 +99,17 @@ public static function canDelete($record): bool
return false;
}

public static function getEloquentQuery(): \Illuminate\Database\Eloquent\Builder
public static function getEloquentQuery(): Builder
{
$query = parent::getEloquentQuery()
->public()
->visible();

// Apply tenant scoping if enabled
if (config('filament-help.tenancy.enabled', false) && config('filament-help.tenancy.scoping.guest', false)) {
$tenant = \Filament\Facades\Filament::getTenant();
if (Tenancy::hasTenantColumn(static::getModel()) && config('filament-help.tenancy.scoping.guest', false)) {
$tenant = Filament::getTenant();
if ($tenant) {
$tenantColumn = config('filament-help.tenancy.column') ?? 'team_id';
$query->where($tenantColumn, $tenant->id);
$query->where(Tenancy::column(), $tenant->id);
}
}

Expand Down
33 changes: 17 additions & 16 deletions src/Resources/HelpArticleResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Filament\Actions\ActionGroup;
use Filament\Actions\EditAction;
use Filament\Actions\ViewAction;
use Filament\Facades\Filament;
use Filament\Forms;
use Filament\Resources\Resource;
use Filament\Schemas\Components\Utilities\Get;
Expand All @@ -13,28 +14,29 @@
use Filament\Tables;
use Filament\Tables\Enums\RecordActionsPosition;
use Filament\Tables\Table;
use Filament\Tables\Actions\BulkActionGroup;
use Filament\Tables\Actions\DeleteBulkAction;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Str;
use Tapp\FilamentHelp\Models\HelpArticle;
use Tapp\FilamentHelp\Resources\HelpArticleResource\Pages;
use Tapp\FilamentHelp\Support\Tenancy;

class HelpArticleResource extends Resource
{
protected static ?string $model = null;

public static function getModel(): string
{
return static::$model ?? config('filament-help.model', \Tapp\FilamentHelp\Models\HelpArticle::class);
return static::$model ?? config('filament-help.model', HelpArticle::class);
}

protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-question-mark-circle';

public static function getTenantOwnershipRelationshipName(): string
{
if (config('filament-help.tenancy.enabled', false)) {
if (Tenancy::isEnabled()) {
return config('filament-help.tenancy.relationship') ?? 'team';
}

return parent::getTenantOwnershipRelationshipName();
}

Expand Down Expand Up @@ -81,11 +83,11 @@ public static function form(Schema $schema): Schema
->label('Hidden (Draft/Archived)')
->helperText('When enabled, this article will be hidden from everyone except admins. Hidden articles are not accessible via public URL, even if public access is enabled. Use this for draft or archived articles.')
->default(false),
Forms\Components\Textarea::make('embed')
->label('Embed (HTML)')
->rows(4)
->helperText('Some embed tags contain style rules that may need to be removed or edited to render properly.')
->columnSpanFull(),
Forms\Components\Textarea::make('embed')
->label('Embed (HTML)')
->rows(4)
->helperText('Some embed tags contain style rules that may need to be removed or edited to render properly.')
->columnSpanFull(),
Forms\Components\RichEditor::make('content')
->label('Content')
->toolbarButtons([
Expand All @@ -106,7 +108,7 @@ public static function form(Schema $schema): Schema
'attachFiles',
])
->extraInputAttributes([
'style' => 'min-height: 200px;'
'style' => 'min-height: 200px;',
]),
]);
}
Expand Down Expand Up @@ -173,16 +175,15 @@ public static function getPages(): array
];
}

public static function getEloquentQuery(): \Illuminate\Database\Eloquent\Builder
public static function getEloquentQuery(): Builder
{
$query = parent::getEloquentQuery();

// Apply tenant scoping if tenancy is enabled
if (config('filament-help.tenancy.enabled', false) && config('filament-help.tenancy.scoping.admin', true)) {
$tenant = \Filament\Facades\Filament::getTenant();
if (Tenancy::hasTenantColumn(static::getModel()) && config('filament-help.tenancy.scoping.admin', true)) {
$tenant = Filament::getTenant();
if ($tenant) {
$tenantColumn = config('filament-help.tenancy.column') ?? 'team_id';
$query->where($tenantColumn, $tenant->id);
$query->where(Tenancy::column(), $tenant->id);
}
}

Expand Down
41 changes: 41 additions & 0 deletions src/Support/Tenancy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace Tapp\FilamentHelp\Support;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Schema;
use Tapp\FilamentHelp\Models\HelpArticle;

class Tenancy
{
public static function isEnabled(): bool
{
return (bool) config('filament-help.tenancy.enabled', false);
}

public static function column(): string
{
$column = config('filament-help.tenancy.column', 'team_id');

return is_string($column) && $column !== '' ? $column : 'team_id';
}

public static function hasTenantColumn(?string $modelClass = null): bool
{
if (! static::isEnabled()) {
return false;
}

$modelClass ??= config('filament-help.model', HelpArticle::class);

if (! is_string($modelClass) || ! is_subclass_of($modelClass, Model::class)) {
$modelClass = HelpArticle::class;
}

/** @var Model $model */
$model = new $modelClass;

return Schema::hasTable($model->getTable())
&& Schema::hasColumn($model->getTable(), static::column());
}
}
18 changes: 18 additions & 0 deletions tests/Unit/TenancyTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

use Tapp\FilamentHelp\Models\HelpArticle;
use Tapp\FilamentHelp\Support\Tenancy;

it('does not apply tenant scope when tenancy is enabled but the tenant column is missing', function () {
config()->set('filament-help.tenancy.enabled', true);

HelpArticle::factory()->public()->create(['name' => 'Shared Article']);

$articles = HelpArticle::query()
->forTenant((object) ['id' => 1])
->get();

expect(Tenancy::hasTenantColumn())->toBeFalse()
->and($articles)->toHaveCount(1)
->and($articles->first()->name)->toBe('Shared Article');
});
Loading