81 lines
4.1 KiB
PHP
81 lines
4.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
final class PublicPageService
|
|
{
|
|
private const RESERVED = [
|
|
'site','animaux','adoption','presentation','dons','contact','mentions-legales','confidentialite',
|
|
'logo-association','login','logout','setup','dashboard','statistics','agenda','directory','settings','admin',
|
|
'accounting','inventory','care-round','animal','litter','documents','media','assets','api',
|
|
];
|
|
|
|
public static function all(bool $enabledOnly = false): array
|
|
{
|
|
$sql = 'SELECT * FROM public_site_pages' . ($enabledOnly ? ' WHERE enabled=1' : '') .
|
|
' ORDER BY sort_order,id';
|
|
return DB::pdo()->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);
|
|
}
|
|
}
|