query($sql)->fetchAll(PDO::FETCH_ASSOC); } public static function findBySlug(string $slug, bool $enabledOnly = true): ?array { $slug = self::normalizeSlug($slug); if ($slug === '') return null; $stmt = DB::pdo()->prepare( 'SELECT * FROM public_site_pages WHERE slug=:slug' . ($enabledOnly ? ' AND enabled=1' : '') . ' LIMIT 1', ); $stmt->execute([':slug' => $slug]); return $stmt->fetch(PDO::FETCH_ASSOC) ?: null; } public static function saveAll(array $pages): void { $db = DB::pdo(); $pages = array_values(array_filter($pages, 'is_array')); usort($pages, static fn (array $a, array $b): int => (int) ($a['position'] ?? 0) <=> (int) ($b['position'] ?? 0)); $seenSlugs = []; $position = 0; foreach ($pages as $page) { if (!is_array($page)) continue; $id = max(0, (int) ($page['id'] ?? 0)); if (!empty($page['delete'])) { if ($id > 0) $db->prepare('DELETE FROM public_site_pages WHERE id=?')->execute([$id]); continue; } $title = mb_substr(trim((string) ($page['title'] ?? '')), 0, 150); $slug = self::normalizeSlug((string) ($page['slug'] ?? '')); if ($slug === '') $slug = self::normalizeSlug($title); if ($title === '' && $slug === '' && trim((string) ($page['content'] ?? '')) === '') continue; if ($title === '' || $slug === '' || in_array($slug, self::RESERVED, true)) { throw new InvalidArgumentException(t('public_site.page_invalid')); } if (isset($seenSlugs[$slug])) throw new InvalidArgumentException(t('public_site.page_slug_duplicate')); $seenSlugs[$slug] = true; $duplicate = $db->prepare('SELECT id FROM public_site_pages WHERE slug=:slug AND id<>:id LIMIT 1'); $duplicate->execute([':slug' => $slug, ':id' => $id]); if ($duplicate->fetchColumn()) throw new InvalidArgumentException(t('public_site.page_slug_duplicate')); $content = trim((string) ($page['content'] ?? '')); $enabled = !empty($page['enabled']) ? 1 : 0; if ($id > 0) { $check = $db->prepare('SELECT 1 FROM public_site_pages WHERE id=?'); $check->execute([$id]); if (!$check->fetchColumn()) throw new InvalidArgumentException(t('public_site.page_invalid')); $stmt = $db->prepare('UPDATE public_site_pages SET slug=:slug,title=:title,content=:content,enabled=:enabled,sort_order=:sort,updated_at=CURRENT_TIMESTAMP WHERE id=:id'); $stmt->execute([':slug'=>$slug,':title'=>$title,':content'=>$content,':enabled'=>$enabled,':sort'=>$position,':id'=>$id]); } else { $stmt = $db->prepare('INSERT INTO public_site_pages(slug,title,content,enabled,sort_order) VALUES(:slug,:title,:content,:enabled,:sort)'); $stmt->execute([':slug'=>$slug,':title'=>$title,':content'=>$content,':enabled'=>$enabled,':sort'=>$position]); } $position++; } } public static function normalizeSlug(string $value): string { $value = mb_strtolower(trim($value), 'UTF-8'); $ascii = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $value); $value = $ascii === false ? $value : $ascii; $value = preg_replace('/[^a-z0-9]+/', '-', strtolower($value)) ?? ''; return mb_substr(trim($value, '-'), 0, 80); } }