From 3378427e073442bf35c6596379d4fe7efd38fa11 Mon Sep 17 00:00:00 2001 From: LordSchmackes Date: Tue, 24 Mar 2026 15:57:37 +0100 Subject: [PATCH] Add minimalist editable CMS content section --- admin.php | 128 +++++++++++++++++++++++++++++++++++++++++++- helpers.php | 34 ++++++++++++ index.php | 50 +++++++---------- partials/footer.php | 7 ++- 4 files changed, 185 insertions(+), 34 deletions(-) diff --git a/admin.php b/admin.php index 584f48d..559c425 100644 --- a/admin.php +++ b/admin.php @@ -57,7 +57,9 @@ $editing = null; $editIndex = null; $editingEn = []; $editingDe = []; -$view = (isset($_GET['view']) && $_GET['view'] === 'settings') ? 'settings' : 'recipes'; +$allowedViews = ['recipes', 'settings', 'content']; +$view = $_GET['view'] ?? 'recipes'; +$view = in_array($view, $allowedViews, true) ? $view : 'recipes'; if (empty($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(16)); @@ -163,6 +165,59 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'save_ } } +if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'save_content') { + if (!hash_equals($_SESSION['csrf_token'] ?? '', $_POST['token'] ?? '')) { + $errors[] = 'Invalid form token, please retry.'; + } else { + $cms = $siteSettings['cms'] ?? ['de' => [], 'en' => []]; + $contentKeys = [ + 'landing_eyebrow', + 'landing_line_1', + 'landing_line_2', + 'landing_line_3', + 'landing_cta', + 'coming_soon_badge', + 'coming_soon_suffix', + 'footer_designed_by', + 'footer_contact_label', + 'home_title', + 'home_description', + 'coming_feature_1', + 'coming_feature_2', + 'coming_feature_3', + ]; + + foreach (['de', 'en'] as $langKey) { + foreach ($contentKeys as $field) { + $postKey = $field . '_' . $langKey; + $cms[$langKey][$field] = trim((string) ($_POST[$postKey] ?? ($cms[$langKey][$field] ?? ''))); + } + } + + $requiredCms = ['landing_line_1', 'landing_line_2', 'landing_line_3', 'landing_cta', 'home_title', 'home_description']; + foreach ($requiredCms as $field) { + if (($cms['de'][$field] ?? '') === '' && ($cms['en'][$field] ?? '') === '') { + $errors[] = "Content field \"$field\" needs DE or EN value."; + } + if (($cms['de'][$field] ?? '') === '') { + $cms['de'][$field] = $cms['en'][$field] ?? ''; + } + if (($cms['en'][$field] ?? '') === '') { + $cms['en'][$field] = $cms['de'][$field] ?? ''; + } + } + + if (empty($errors)) { + $siteSettings['cms'] = $cms; + if (save_site_settings($siteSettings)) { + $message = 'Content saved.'; + } else { + $errors[] = 'Could not save CMS content. Check permissions on data/site.json.'; + } + } + } +} + if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'delete') { $slugDel = trim($_POST['slug'] ?? ''); $before = count($allRecipes); @@ -350,6 +405,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'delet
View site @@ -368,7 +424,75 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'delet
- + + +
+ + +

Homepage Content (DE)

+ + +
+
+
+
+
+
+
+
+
+
+
+
+ + + + +

Coming soon feature bullets

+
+
+
+
+
+
+
+
+
+ +
+

Homepage Content (EN)

+ + +
+
+
+
+
+
+
+
+
+
+
+
+ + + + +

Coming soon feature bullets

+
+
+
+
+
+
+
+
+
+ + +
+
diff --git a/helpers.php b/helpers.php index c0a3f4d..892cb10 100644 --- a/helpers.php +++ b/helpers.php @@ -34,6 +34,40 @@ function save_recipes(array $recipes): bool { function default_site_settings(): array { $today = date('Y-m-d'); return [ + 'cms' => [ + 'en' => [ + 'landing_eyebrow' => 'Seasonal · Unfussy · Ridiculously tasty', + 'landing_line_1' => 'Cook better', + 'landing_line_2' => 'weeknights.', + 'landing_line_3' => 'Brighter weekends.', + 'landing_cta' => 'Explore recipes', + 'coming_soon_badge' => 'Coming soon', + 'coming_soon_suffix' => 'in progress', + 'footer_designed_by' => 'Website designed by Felix Brockers', + 'footer_contact_label' => 'Contact me', + 'home_title' => 'FlixCooks | Modern food blog for busy home cooks', + 'home_description' => 'Fresh, fast recipes with clear steps, smart prep notes, and big flavor. Built for Hetzner web hosting in plain PHP.', + 'coming_feature_1' => 'Nutrition info & recipe suggestions tailored to your goals', + 'coming_feature_2' => 'Send your grocery list straight to your phone', + 'coming_feature_3' => 'Step-by-step recipe assistant with videos', + ], + 'de' => [ + 'landing_eyebrow' => 'Saisonal · Unkompliziert · Richtig lecker', + 'landing_line_1' => 'Besser kochen', + 'landing_line_2' => 'unter der Woche.', + 'landing_line_3' => 'Glänzen am Wochenende.', + 'landing_cta' => 'Rezepte entdecken', + 'coming_soon_badge' => 'Bald verfügbar', + 'coming_soon_suffix' => 'in Arbeit', + 'footer_designed_by' => 'Website designed by Felix Brockers', + 'footer_contact_label' => 'Kontakt', + 'home_title' => 'FlixCooks | Moderner Foodblog für schnelle Alltagsküche', + 'home_description' => 'Frische, schnelle Rezepte mit klaren Schritten und großem Geschmack. Gebaut für Hetzner Webhosting in einfachem PHP.', + 'coming_feature_1' => 'Nährwerte & Rezepte Vorschlag individuell angepasst auf Ernährungsziel', + 'coming_feature_2' => 'Einkaufsliste ans Handy senden', + 'coming_feature_3' => 'Step-by-Step Rezepte Assistent mit Videos', + ], + ], 'imprint' => [ 'de' => [ 'owner_name' => 'FlixCooks (bitte anpassen)', diff --git a/index.php b/index.php index 7bd3a4d..22d3608 100644 --- a/index.php +++ b/index.php @@ -54,6 +54,8 @@ $copy = [ $t = $copy[$lang]; $allRecipes = load_recipes(); +$siteSettings = load_site_settings(); +$cms = $siteSettings['cms'][$lang] ?? []; $localizedAll = localize_recipes($allRecipes, $lang); $recipes = filter_recipes($allRecipes, $q ?: null, $tag ?: null, $lang); $recipes = array_values(array_filter($recipes, fn($r) => empty($r['coming_soon']))); // hide coming soon from main list @@ -84,24 +86,18 @@ foreach ($localizedAll as $recipe) { } $allTags = array_values(array_unique($allTags)); -$comingFeatures = $lang === 'de' - ? [ - 'Nährwerte & Rezepte Vorschlag individuell angepasst auf Ernährungsziel', - 'Einkaufsliste ans Handy senden', - 'Step-by-Step Rezepte Assistent mit Videos', - ] - : [ - 'Nutrition info & recipe suggestions tailored to your goals', - 'Send your grocery list straight to your phone', - 'Step-by-step recipe assistant with videos', - ]; +$comingFeatures = array_values(array_filter([ + trim((string) ($cms['coming_feature_1'] ?? '')), + trim((string) ($cms['coming_feature_2'] ?? '')), + trim((string) ($cms['coming_feature_3'] ?? '')), +], 'strlen')); -$pageTitle = $lang === 'de' +$pageTitle = trim((string) ($cms['home_title'] ?? '')) ?: ($lang === 'de' ? 'FlixCooks | Moderner Foodblog für schnelle Alltagsküche' - : 'FlixCooks | Modern food blog for busy home cooks'; -$description = $lang === 'de' + : 'FlixCooks | Modern food blog for busy home cooks'); +$description = trim((string) ($cms['home_description'] ?? '')) ?: ($lang === 'de' ? 'Frische, schnelle Rezepte mit klaren Schritten und großem Geschmack. Gebaut für Hetzner Webhosting in einfachem PHP.' - : 'Fresh, fast recipes with clear steps, smart prep notes, and big flavor. Built for Hetzner web hosting in plain PHP.'; + : 'Fresh, fast recipes with clear steps, smart prep notes, and big flavor. Built for Hetzner web hosting in plain PHP.'); $langSwitchLabel = $lang === 'de' ? 'DE' : 'EN'; $langSwitchHref = lang_url($lang === 'de' ? 'en' : 'de'); $navHome = $t['home']; @@ -183,24 +179,18 @@ include __DIR__ . '/partials/head.php';

- +

- - Besser kochen - unter der Woche. - Glänzen am Wochenende. - - Cook better - weeknights. - Brighter weekends. - + + +

- +
@@ -221,8 +211,8 @@ document.getElementById('landingCta').addEventListener('click', function(e){
-

- +

+
diff --git a/partials/footer.php b/partials/footer.php index a607ef5..f3e3316 100644 --- a/partials/footer.php +++ b/partials/footer.php @@ -3,11 +3,14 @@ $langSuffix = $langCode === 'de' ? '?lang=de' : ''; $settings = function_exists('load_site_settings') ? load_site_settings() : null; $contactEmail = $settings['imprint'][$langCode]['email'] ?? 'contact@flixcooks.at'; + $cms = $settings['cms'][$langCode] ?? []; + $footerByline = trim((string) ($cms['footer_designed_by'] ?? '')) ?: 'Website designed by Felix Brockers'; + $footerContact = trim((string) ($cms['footer_contact_label'] ?? '')) ?: ($langCode === 'de' ? 'Kontakt' : 'Contact me'); ?>