schema([ Forms\Components\Grid::make() ->schema([ Forms\Components\Section::make() ->schema([ Forms\Components\TextInput::make('name') ->label(__('filament-shield::filament-shield.field.name')) ->unique(ignoreRecord: true) ->required() ->maxLength(255), Forms\Components\TextInput::make('guard_name') ->label(__('filament-shield::filament-shield.field.guard_name')) ->default(Utils::getFilamentAuthGuard()) ->nullable() ->maxLength(255), ShieldSelectAllToggle::make('select_all') ->onIcon('heroicon-s-shield-check') ->offIcon('heroicon-s-shield-exclamation') ->label(__('filament-shield::filament-shield.field.select_all.name')) ->helperText(fn (): HtmlString => new HtmlString(__('filament-shield::filament-shield.field.select_all.message'))) ->dehydrated(fn ($state): bool => $state), ]) ->columns([ 'sm' => 2, 'lg' => 3, ]), ]), Forms\Components\Tabs::make('Permissions') ->contained() ->tabs([ static::getTabFormComponentForResources(), static::getTabFormComponentForPage(), static::getTabFormComponentForWidget(), static::getTabFormComponentForCustomPermissions(), ]) ->columnSpan('full'), ]); } public static function table(Table $table): Table { return $table ->columns([ Tables\Columns\TextColumn::make('name') ->badge() ->label(__('filament-shield::filament-shield.column.name')) ->formatStateUsing(fn ($state): string => Str::headline($state)) ->colors(['primary']) ->searchable(), Tables\Columns\TextColumn::make('guard_name') ->badge() ->label(__('filament-shield::filament-shield.column.guard_name')), Tables\Columns\TextColumn::make('permissions_count') ->badge() ->label(__('filament-shield::filament-shield.column.permissions')) ->counts('permissions') ->colors(['success']), Tables\Columns\TextColumn::make('updated_at') ->label(__('filament-shield::filament-shield.column.updated_at')) ->dateTime(), ]) ->filters([ // ]) ->actions([ Tables\Actions\EditAction::make(), Tables\Actions\DeleteAction::make(), ]) ->bulkActions([ Tables\Actions\DeleteBulkAction::make(), ]); } public static function getRelations(): array { return [ // ]; } public static function getPages(): array { return [ 'index' => Pages\ListRoles::route('/'), 'create' => Pages\CreateRole::route('/create'), 'view' => Pages\ViewRole::route('/{record}'), 'edit' => Pages\EditRole::route('/{record}/edit'), ]; } public static function getCluster(): ?string { return Utils::getResourceCluster() ?? static::$cluster; } public static function getModel(): string { return Utils::getRoleModel(); } public static function getModelLabel(): string { return __('filament-shield::filament-shield.resource.label.role'); } public static function getPluralModelLabel(): string { return __('filament-shield::filament-shield.resource.label.roles'); } public static function shouldRegisterNavigation(): bool { return Utils::isResourceNavigationRegistered(); } public static function getNavigationGroup(): ?string { return 'Security Settings'; } public static function getNavigationLabel(): string { return __('filament-shield::filament-shield.nav.role.label'); } public static function getNavigationIcon(): string { return __('filament-shield::filament-shield.nav.role.icon'); } public static function getNavigationSort(): ?int { return Utils::getResourceNavigationSort(); } public static function getSlug(): string { return Utils::getResourceSlug(); } public static function getNavigationBadge(): ?string { return Utils::isResourceNavigationBadgeEnabled() ? strval(static::getEloquentQuery()->count()) : null; } public static function isScopedToTenant(): bool { return Utils::isScopedToTenant(); } public static function canGloballySearch(): bool { return Utils::isResourceGloballySearchable() && count(static::getGloballySearchableAttributes()) && static::canViewAny(); } public static function getResourceEntitiesSchema(): ?array { return collect(FilamentShield::getResources()) ->sortKeys() ->map(function ($entity) { $sectionLabel = strval( static::shield()->hasLocalizedPermissionLabels() ? FilamentShield::getLocalizedResourceLabel($entity['fqcn']) : $entity['model'] ); return Forms\Components\Section::make($sectionLabel) ->description(fn () => new HtmlString('' . Utils::showModelPath($entity['fqcn']) . '')) ->compact() ->schema([ static::getCheckBoxListComponentForResource($entity), ]) ->columnSpan(static::shield()->getSectionColumnSpan()) ->collapsible(); }) ->toArray(); } public static function getResourceTabBadgeCount(): ?int { return collect(FilamentShield::getResources()) ->map(fn ($resource) => count(static::getResourcePermissionOptions($resource))) ->sum(); } public static function getResourcePermissionOptions(array $entity): array { return collect(Utils::getResourcePermissionPrefixes($entity['fqcn'])) ->flatMap(function ($permission) use ($entity) { $name = $permission . '_' . $entity['resource']; $label = static::shield()->hasLocalizedPermissionLabels() ? FilamentShield::getLocalizedResourcePermissionLabel($permission) : $name; return [ $name => $label, ]; }) ->toArray(); } public static function setPermissionStateForRecordPermissions(Component $component, string $operation, array $permissions, ?Model $record): void { if (in_array($operation, ['edit', 'view'])) { if (blank($record)) { return; } if ($component->isVisible() && count($permissions) > 0) { $component->state( collect($permissions) /** @phpstan-ignore-next-line */ ->filter(fn ($value, $key) => $record->checkPermissionTo($key)) ->keys() ->toArray() ); } } } public static function getPageOptions(): array { return collect(FilamentShield::getPages()) ->flatMap(fn ($page) => [ $page['permission'] => static::shield()->hasLocalizedPermissionLabels() ? FilamentShield::getLocalizedPageLabel($page['class']) : $page['permission'], ]) ->toArray(); } public static function getWidgetOptions(): array { return collect(FilamentShield::getWidgets()) ->flatMap(fn ($widget) => [ $widget['permission'] => static::shield()->hasLocalizedPermissionLabels() ? FilamentShield::getLocalizedWidgetLabel($widget['class']) : $widget['permission'], ]) ->toArray(); } public static function getCustomPermissionOptions(): ?array { return FilamentShield::getCustomPermissions() ->mapWithKeys(fn ($customPermission) => [ $customPermission => static::shield()->hasLocalizedPermissionLabels() ? str($customPermission)->headline()->toString() : $customPermission, ]) ->toArray(); } public static function getTabFormComponentForResources(): Component { return static::shield()->hasSimpleResourcePermissionView() ? static::getTabFormComponentForSimpleResourcePermissionsView() : Forms\Components\Tabs\Tab::make('resources') ->label(__('filament-shield::filament-shield.resources')) ->visible(fn (): bool => (bool) Utils::isResourceEntityEnabled()) ->badge(static::getResourceTabBadgeCount()) ->schema([ Forms\Components\Grid::make() ->schema(static::getResourceEntitiesSchema()) ->columns(static::shield()->getGridColumns()), ]); } public static function getCheckBoxListComponentForResource(array $entity): Component { $permissionsArray = static::getResourcePermissionOptions($entity); return static::getCheckboxListFormComponent($entity['resource'], $permissionsArray, false); } public static function getTabFormComponentForPage(): Component { $options = static::getPageOptions(); $count = count($options); return Forms\Components\Tabs\Tab::make('pages') ->label(__('filament-shield::filament-shield.pages')) ->visible(fn (): bool => (bool) Utils::isPageEntityEnabled() && $count > 0) ->badge($count) ->schema([ static::getCheckboxListFormComponent('pages_tab', $options), ]); } public static function getTabFormComponentForWidget(): Component { $options = static::getWidgetOptions(); $count = count($options); return Forms\Components\Tabs\Tab::make('widgets') ->label(__('filament-shield::filament-shield.widgets')) ->visible(fn (): bool => (bool) Utils::isWidgetEntityEnabled() && $count > 0) ->badge($count) ->schema([ static::getCheckboxListFormComponent('widgets_tab', $options), ]); } public static function getTabFormComponentForCustomPermissions(): Component { $options = static::getCustomPermissionOptions(); $count = count($options); return Forms\Components\Tabs\Tab::make('custom') ->label(__('filament-shield::filament-shield.custom')) ->visible(fn (): bool => (bool) Utils::isCustomPermissionEntityEnabled() && $count > 0) ->badge($count) ->schema([ static::getCheckboxListFormComponent('custom_permissions', $options), ]); } public static function getTabFormComponentForSimpleResourcePermissionsView(): Component { $options = FilamentShield::getAllResourcePermissions(); $count = count($options); return Forms\Components\Tabs\Tab::make('resources') ->label(__('filament-shield::filament-shield.resources')) ->visible(fn (): bool => (bool) Utils::isResourceEntityEnabled() && $count > 0) ->badge($count) ->schema([ static::getCheckboxListFormComponent('resources_tab', $options), ]); } public static function getCheckboxListFormComponent(string $name, array $options, bool $searchable = true): Component { return Forms\Components\CheckboxList::make($name) ->label('') ->options(fn (): array => $options) ->searchable($searchable) ->afterStateHydrated( fn (Component $component, string $operation, ?Model $record) => static::setPermissionStateForRecordPermissions( component: $component, operation: $operation, permissions: $options, record: $record ) ) ->dehydrated(fn ($state) => ! blank($state)) ->bulkToggleable() ->gridDirection('row') ->columns(static::shield()->getCheckboxListColumns()) ->columnSpan(static::shield()->getCheckboxListColumnSpan()); } public static function shield(): FilamentShieldPlugin { return FilamentShieldPlugin::get(); } }