>}> */ public function pages(): array { $rows = CmsContent::query() ->get(['id', 'group', 'key']) ->keyBy(fn (CmsContent $row) => $row->group.'/'.$row->key); $pages = []; foreach (config('cms_pages.pages', []) as $pageKey => $page) { $sections = []; foreach ($page['sections'] ?? [] as $section) { $id = $section['group'].'/'.$section['key']; $sections[] = array_merge($section, [ 'page' => $pageKey, 'path' => $section['path'] ?? $page['path'] ?? null, 'anchor' => $section['anchor'] ?? null, 'content_id' => $rows[$id]->id ?? null, 'theme_key' => $this->themeKey($section['group'], $section['key']), ]); } $pages[$pageKey] = [ 'title' => $page['title'], 'path' => $page['path'] ?? null, 'sections' => $sections, ]; } $unlisted = $this->unlistedSections($rows->keys()->all(), $rows); if ($unlisted !== []) { $pages[self::UNLISTED] = [ 'title' => config('cms_pages.unlisted.title', 'Nicht mehr verwendet'), 'path' => null, 'sections' => $unlisted, ]; } return $pages; } /** * Eine Sektion aus der Registry samt Datenbankbezug, oder null. * * @return array|null */ public function section(string $group, string $key): ?array { foreach ($this->pages() as $page) { foreach ($page['sections'] as $section) { if ($section['group'] === $group && $section['key'] === $key) { return $section; } } } return null; } /** * Klartext-Beschriftung eines Feldes: Sektions-Override, dann Wörterbuch, sonst lesbar gemacht. */ public function fieldLabel(string $field, ?string $group = null, ?string $key = null): string { if ($group !== null && $key !== null) { foreach (config('cms_pages.pages', []) as $page) { foreach ($page['sections'] ?? [] as $section) { if ($section['group'] === $group && $section['key'] === $key && isset($section['fields'][$field])) { return $section['fields'][$field]; } } } } $labels = config('cms_pages.field_labels', []); if (isset($labels[$field])) { return $labels[$field]; } return Str::ucfirst(str_replace('_', ' ', $field)); } /** * Adresse der Vorschau für eine Sektion: Frontend-Domain, Pfad, Cache-Brecher und Sprungmarke. */ public function previewUrl(?array $section, int $version = 0): ?string { $path = $section['path'] ?? null; if ($path === null) { return null; } $url = rtrim(config('domains.protocol', 'https://').config('domains.domain_b2in'), '/') .'/'.ltrim($path, '/') .'?cms-preview='.$version; if (! empty($section['anchor'])) { $url .= '#'.$section['anchor']; } return $url; } /** * Theme-Section-Schlüssel (Lang-Datei) zu Gruppe/Key, für „Aus Vorlage anlegen“. */ public function themeKey(string $group, string $key): ?string { foreach (config('cms_section_map.sections', []) as $themeKey => $target) { if ($target === [$group, $key]) { return $themeKey; } } return null; } /** * @param list $ids * @param \Illuminate\Support\Collection $rows * @return list> */ private function unlistedSections(array $ids, $rows): array { $listed = []; foreach (config('cms_pages.pages', []) as $page) { foreach ($page['sections'] ?? [] as $section) { $listed[$section['group'].'/'.$section['key']] = true; } } $out = []; foreach ($ids as $id) { if (isset($listed[$id])) { continue; } $row = $rows[$id]; $out[] = [ 'group' => $row->group, 'key' => $row->key, 'page' => self::UNLISTED, 'path' => null, 'anchor' => null, 'title' => $row->group.' / '.$row->key, 'description' => null, 'content_id' => $row->id, 'theme_key' => null, ]; } usort($out, fn (array $a, array $b) => [$a['group'], $a['key']] <=> [$b['group'], $b['key']]); return $out; } }