Refactor database handling to require PostgreSQL connection, removing fallback to JSON. Implement error handling for database unavailability in key files. Update .env.example to reflect mandatory DATABASE_URL for local development. Remove Firebase configuration and related code from the project.

This commit is contained in:
2026-05-23 10:23:28 +02:00
parent 547778bba5
commit 6577db475a
20 changed files with 823 additions and 789 deletions
+16 -93
View File
@@ -49,7 +49,11 @@ if (!$authed) {
exit;
}
$allRecipes = load_recipes();
try {
$allRecipes = load_recipes();
} catch (DatabaseUnavailableException $e) {
handle_database_unavailable($e);
}
$siteSettings = load_site_settings();
$message = null;
$errors = [];
@@ -165,12 +169,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'save_
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'delete') {
$slugDel = trim($_POST['slug'] ?? '');
$before = count($allRecipes);
$allRecipes = array_values(array_filter($allRecipes, fn($r) => ($r['slug'] ?? '') !== $slugDel));
if ($before !== count($allRecipes) && save_recipes($allRecipes)) {
if ($slugDel !== '' && delete_recipe($slugDel)) {
$message = 'Recipe deleted.';
$allRecipes = load_recipes();
} else {
$message = 'Could not delete. Check permissions.';
$message = 'Could not delete recipe.';
}
$editing = null;
$editIndex = null;
@@ -259,13 +262,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'delet
}
}
if ($featured) {
foreach ($allRecipes as &$r) {
$r['featured'] = false;
}
unset($r);
}
$record = [
'slug' => $slug,
'hero' => $hero,
@@ -309,16 +305,18 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'delet
],
];
if ($slugOriginal && $editIndex !== null) {
$allRecipes[$editIndex] = $record;
} else {
$allRecipes[] = $record;
if ($featured) {
clear_featured_recipes();
}
if ($slugOriginal && $slugOriginal !== $slug) {
delete_recipe($slugOriginal);
}
if (save_recipes($allRecipes)) {
if (save_recipe($record)) {
$message = $slugOriginal ? 'Saved changes.' : 'Saved! New recipe added.';
$allRecipes = load_recipes();
} else {
$message = 'Could not save the file. Check permissions on data/recipes.json.';
$message = 'Could not save to database.';
}
}
}
@@ -367,18 +365,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'delet
.list-item { padding: 12px 0; border-bottom: 1px solid rgba(255,255,255,0.08); display: flex; justify-content: space-between; align-items: center; }
.pill { background: rgba(255,255,255,0.06); color: var(--ink); }
</style>
<!-- Firebase v10 compat SDKs -->
<script src="https://www.gstatic.com/firebasejs/10.8.0/firebase-app-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/10.8.0/firebase-auth-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/10.8.0/firebase-firestore-compat.js"></script>
<script>
(function() {
var config = <?php echo json_encode(get_firebase_config()); ?>;
firebase.initializeApp(config);
window.auth = firebase.auth();
window.db = firebase.firestore();
})();
</script>
</head>
<body>
<div class="admin-header">
@@ -388,9 +374,6 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'delet
<a href="/admin.php" class="<?php echo $view === 'recipes' ? 'active' : ''; ?>">Recipes</a>
<a href="/admin.php?view=settings" class="<?php echo $view === 'settings' ? 'active' : ''; ?>">Site settings</a>
</div>
<?php if ($view === 'recipes' && !$editing): ?>
<button id="btn-seed-firestore" class="button" style="background: var(--accent-gold, #c5a880); color: #000; font-weight: 700; border: none; padding: 10px 14px; border-radius: 10px; cursor: pointer;">Seed Firestore</button>
<?php endif; ?>
<a class="button" href="/index.php" style="padding:10px 14px;">View site</a>
<?php if ($editing): ?>
<a class="button" href="/admin.php" style="padding:10px 14px;">Back</a>
@@ -654,65 +637,5 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'delet
</form>
<?php endif; ?>
<script>
// Firestore Seeder Logic
document.addEventListener('DOMContentLoaded', () => {
const btnSeed = document.getElementById('btn-seed-firestore');
if (btnSeed) {
btnSeed.addEventListener('click', async () => {
if (!confirm('Bist du sicher, dass du alle Rezepte nach Firestore importieren möchtest? Bestehende Dokumente mit identischem Slug werden überschrieben.')) return;
btnSeed.disabled = true;
btnSeed.innerText = 'Seeding...';
try {
const recipes = <?php echo json_encode($allRecipes); ?>;
let count = 0;
for (const recipe of recipes) {
await window.db.collection('recipes').doc(recipe.slug).set(recipe);
console.log('Seeded to Firestore:', recipe.slug);
count++;
}
alert(`Erfolgreich ${count} Rezepte nach Firestore migriert!`);
} catch (err) {
console.error('Seeding Fehler:', err);
alert('Fehler beim Seeding: ' + err.message);
} finally {
btnSeed.disabled = false;
btnSeed.innerText = 'Seed Firestore';
}
});
}
});
</script>
<!-- Auto-Sync after PHP Save -->
<?php if (isset($record) && str_contains($message ?? '', 'Saved')): ?>
<script>
document.addEventListener('DOMContentLoaded', async () => {
const recipe = <?php echo json_encode($record); ?>;
try {
await window.db.collection('recipes').doc(recipe.slug).set(recipe);
console.log('Successfully synced saved recipe to Firestore:', recipe.slug);
} catch (err) {
console.error('Error syncing saved recipe to Firestore:', err);
}
});
</script>
<?php endif; ?>
<!-- Auto-Sync after PHP Delete -->
<?php if (isset($slugDel) && ($message ?? '') === 'Recipe deleted.'): ?>
<script>
document.addEventListener('DOMContentLoaded', async () => {
const slugDel = <?php echo json_encode($slugDel); ?>;
try {
await window.db.collection('recipes').doc(slugDel).delete();
console.log('Successfully deleted recipe from Firestore:', slugDel);
} catch (err) {
console.error('Error deleting recipe from Firestore:', err);
}
});
</script>
<?php endif; ?>
</body>
</html>