*/ protected array $selectedPermissions = []; /** * Expand the role's flat permission set into the form's grouped shape. * * @param array $data * @return array */ protected function mutateFormDataBeforeFill(array $data): array { $held = $this->getRecord()->permissions->pluck('name')->all(); foreach (Permissions::grouped() as $group => $permissions) { $data['permission_groups'][$group] = array_values(array_intersect($permissions, $held)); } return $data; } /** * @param array $data * @return array */ protected function mutateFormDataBeforeSave(array $data): array { return $this->extractPermissions($data); } /** * @param array $data * @return array */ protected function mutateFormDataBeforeCreate(array $data): array { return $this->extractPermissions($data); } protected function afterSave(): void { $this->syncSelectedPermissions(); } protected function afterCreate(): void { $this->syncSelectedPermissions(); } /** * @param array $data * @return array */ protected function extractPermissions(array $data): array { $groups = $data['permission_groups'] ?? []; unset($data['permission_groups']); // Intersecting with the catalogue means a stale or hand-crafted value // in the payload cannot grant a permission the app does not define. $this->selectedPermissions = array_values(array_intersect( array_merge(...array_values(array_map(fn ($v) => (array) $v, $groups)) ?: [[]]), Permissions::all(), )); return $data; } protected function syncSelectedPermissions(): void { $this->getRecord()->syncPermissions($this->selectedPermissions); // spatie caches the permission map; without this the change would not // take effect until the cache expired. app(PermissionRegistrar::class)->forgetCachedPermissions(); } }