normalizePayload($payload); try { return DB::transaction(function () use ($data) { return Role::query()->create($data); }); } catch (\Throwable $e) { Log::error('Role create failed: ' . $e->getMessage()); throw $e; } } public function update(Role $role, array $payload): Role { $data = $this->normalizePayload($payload, $role->id, $role->slug ?? null); try { return DB::transaction(function () use ($role, $data) { $role->fill($data); $role->save(); return $role; }); } catch (\Throwable $e) { Log::error('Role update failed: ' . $e->getMessage()); throw $e; } } public function delete(Role $role): void { try { DB::transaction(function () use ($role) { $role->delete(); }); } catch (\Throwable $e) { Log::error('Role delete failed: ' . $e->getMessage()); throw $e; } } private function normalizePayload(array $payload, ?int $ignoreId = null, ?string $currentSlug = null): array { $rawName = trim((string) ($payload['name'] ?? '')); $rawSlug = trim((string) ($payload['slug'] ?? '')); $route = trim((string) ($payload['dashboard_route'] ?? '')); $desc = trim((string) ($payload['description'] ?? '')); $priority = (int) ($payload['priority'] ?? 0); $isActive = !empty($payload['is_active']) ? 1 : 0; $name = strtolower($rawName); $dashboardRoute = strtolower($route); $description = strtolower($desc); $slug = $rawSlug !== '' ? $rawSlug : $name; $slug = strtolower(preg_replace('/[^a-z0-9]+/i', '_', $slug)); $slug = trim($slug, '_'); if ($slug !== $currentSlug) { $slug = $this->ensureUniqueSlug($slug, $ignoreId); } return [ 'name' => $name, 'slug' => $slug, 'description' => $description, 'dashboard_route' => $dashboardRoute, 'priority' => $priority, 'is_active' => $isActive, ]; } private function ensureUniqueSlug(string $baseSlug, ?int $ignoreId = null): string { $slug = $baseSlug; $i = 2; while (true) { $query = Role::query()->where('slug', $slug); if ($ignoreId !== null) { $query->where('id', '!=', $ignoreId); } if (!$query->exists()) { return $slug; } $slug = $baseSlug . '_' . $i; $i++; if ($i > 100000) { return $slug; } } } }