246 lines
9.7 KiB
PHP
246 lines
9.7 KiB
PHP
<?php
|
|
if (session_status() === PHP_SESSION_NONE) {
|
|
session_start();
|
|
}
|
|
|
|
require_once '../model/LocalArticleManager.php';
|
|
require_once '../model/ArticleManager.php';
|
|
require_once '../model/Article.php';
|
|
require_once '../validator/article-validator.php';
|
|
|
|
if (!isset($_SESSION["user_email"])) {
|
|
header("Location: index.php?pfad=login");
|
|
exit();
|
|
}
|
|
|
|
/**
|
|
* Baut die Blockliste aus den POST-Daten (blocks[i][type], blocks[i][text],
|
|
* blocks[i][existing_image]) und ggf. hochgeladenen Dateien (blocks[i][image])
|
|
* zusammen. Läuft bei JEDEM Submit (Zwischen-Schritt "Block hinzufügen/löschen"
|
|
* UND finales Speichern), damit neu ausgewählte Bilder in jedem Fall persistiert
|
|
* werden, bevor PHP die temporäre Upload-Datei nach Request-Ende verwirft.
|
|
*
|
|
* @param array $postBlocks $_POST['blocks'] ?? []
|
|
* @param array $fileBlocks $_FILES['blocks'] ?? []
|
|
* @param string $uploadDir absoluter Pfad zum uploads-Verzeichnis (mit trailing slash)
|
|
* @return array Liste von ['type' => 'text'|'image', 'value' => string]
|
|
*/
|
|
function rebuildBlocksFromPost(array $postBlocks, array $fileBlocks, string $uploadDir): array {
|
|
$allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
|
|
|
|
$keys = array_keys($postBlocks);
|
|
if (isset($fileBlocks['name']) && is_array($fileBlocks['name'])) {
|
|
$keys = array_unique(array_merge($keys, array_keys($fileBlocks['name'])));
|
|
}
|
|
sort($keys, SORT_NUMERIC);
|
|
|
|
$blocks = [];
|
|
|
|
foreach ($keys as $key) {
|
|
$type = $postBlocks[$key]['type'] ?? null;
|
|
|
|
if ($type === 'text') {
|
|
$blocks[] = [
|
|
'type' => 'text',
|
|
'value' => $postBlocks[$key]['text'] ?? '',
|
|
];
|
|
} elseif ($type === 'image') {
|
|
// Vorbelegung: bereits vorhandenes Server-Bild (falls Datei nicht ersetzt wird)
|
|
$value = $postBlocks[$key]['existing_image'] ?? '';
|
|
|
|
$hasUpload = isset($fileBlocks['error'][$key]['image'])
|
|
&& $fileBlocks['error'][$key]['image'] === UPLOAD_ERR_OK;
|
|
|
|
if ($hasUpload) {
|
|
$tmpName = $fileBlocks['tmp_name'][$key]['image'];
|
|
$originalName = $fileBlocks['name'][$key]['image'];
|
|
$extension = strtolower(pathinfo($originalName, PATHINFO_EXTENSION));
|
|
if (!in_array($extension, $allowedExtensions, true)) {
|
|
$extension = 'jpg';
|
|
}
|
|
|
|
$fileName = 'img_' . uniqid() . '.' . $extension;
|
|
$destination = $uploadDir . $fileName;
|
|
|
|
if (move_uploaded_file($tmpName, $destination)) {
|
|
$value = 'uploads/' . $fileName;
|
|
}
|
|
// Bei Fehler: alter Wert (falls vorhanden) bleibt erhalten, Block wird nicht verworfen
|
|
}
|
|
|
|
$blocks[] = [
|
|
'type' => 'image',
|
|
'value' => $value,
|
|
];
|
|
}
|
|
// unbekannter/fehlender type -> Block wird ignoriert
|
|
}
|
|
|
|
return $blocks;
|
|
}
|
|
|
|
if ($_SERVER["REQUEST_METHOD"] === "POST") {
|
|
|
|
if (isset($_GET["id"]) && !empty($_GET["id"])) {
|
|
$id = $_GET["id"];
|
|
} else {
|
|
$_SESSION["message"] = "missing_id";
|
|
header("location: ../../index.php?pfad=updateArticle");
|
|
exit();
|
|
}
|
|
|
|
try {
|
|
$articleManager = ArticleManager::getInstance();
|
|
$article = $articleManager->getArticle($id);
|
|
if ($article->getAuthor() != $_SESSION["user_email"]) {
|
|
$_SESSION["message"] = "unauthorized_access";
|
|
header("location: ../../index.php");
|
|
exit();
|
|
}
|
|
} catch (Exception $e) {
|
|
$_SESSION["message"] = $e->getMessage();
|
|
header("location: ../../index.php?pfad=updateArticle&id=$id");
|
|
exit();
|
|
}
|
|
|
|
$uploadDir = __DIR__ . '/../../uploads/';
|
|
if (!file_exists($uploadDir)) {
|
|
mkdir($uploadDir, 0755, true);
|
|
}
|
|
|
|
// Formularzustand (Titel/Tags/Kategorie/Blöcke) immer sichern, damit er nach einem
|
|
// Redirect (PRG-Pattern oder Validierungsfehler) wieder angezeigt werden kann.
|
|
$_SESSION["old_title"] = $_POST["title"] ?? '';
|
|
$_SESSION["old_tags"] = $_POST["tags"] ?? '';
|
|
$_SESSION["old_category"] = $_POST["category"] ?? '';
|
|
|
|
$blocks = rebuildBlocksFromPost($_POST['blocks'] ?? [], $_FILES['blocks'] ?? [], $uploadDir);
|
|
$_SESSION["old_content"] = json_encode($blocks, JSON_UNESCAPED_UNICODE);
|
|
|
|
// ---------------------------------------------------------------------
|
|
// Zwischenspeichern
|
|
// ---------------------------------------------------------------------
|
|
if (isset($_POST['editor_action']) && $_POST['editor_action'] !== '') {
|
|
$action = $_POST['editor_action'];
|
|
|
|
if ($action === 'add_text') {
|
|
$blocks[] = ['type' => 'text', 'value' => ''];
|
|
} elseif ($action === 'add_image') {
|
|
$blocks[] = ['type' => 'image', 'value' => ''];
|
|
} elseif (str_starts_with($action, 'delete_block:')) {
|
|
$deleteIndex = (int) substr($action, strlen('delete_block:'));
|
|
unset($blocks[$deleteIndex]);
|
|
$blocks = array_values($blocks);
|
|
}
|
|
|
|
$_SESSION["old_content"] = json_encode($blocks, JSON_UNESCAPED_UNICODE);
|
|
header("location: ../../content/updateArticle.php?id=$id");
|
|
exit();
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// Echtes Speichern
|
|
// ---------------------------------------------------------------------
|
|
if (!isset($_POST["title"]) || !isset($_POST["category"])) {
|
|
$_SESSION["message"] = "missing_parameters";
|
|
header("location: ../../index.php?pfad=updateArticle&id=$id");
|
|
exit();
|
|
} else {
|
|
$title = $_POST["title"];
|
|
$content = json_encode($blocks, JSON_UNESCAPED_UNICODE);
|
|
$author = $_SESSION["user_email"];
|
|
$category = $_POST["category"];
|
|
$tags = $_POST['tags'] ?? '';
|
|
|
|
// -------------------------------- Validierung der Daten: -------------------------
|
|
if (!articleTitleValidator($title)) {
|
|
$_SESSION["message"] = "invalid_title";
|
|
header("location: ../../index.php?pfad=updateArticle&id=$id");
|
|
exit();
|
|
}
|
|
|
|
if (!articleContentValidator($content)) {
|
|
$_SESSION["message"] = "invalid_content";
|
|
header("location: ../../index.php?pfad=updateArticle&id=$id");
|
|
exit();
|
|
}
|
|
|
|
if (!articleCategoryValidator($category)) {
|
|
$_SESSION["message"] = "invalid_category";
|
|
header("location: ../../index.php?pfad=updateArticle&id=$id");
|
|
exit();
|
|
}
|
|
|
|
if (!articleTagValidator($tags)) {
|
|
$_SESSION["message"] = "invalid_tags";
|
|
header("location: ../../index.php?pfad=updateArticle&id=$id");
|
|
exit();
|
|
} else {
|
|
$cleanedTags = [];
|
|
$rawTags = explode(',', $tags);
|
|
foreach ($rawTags as $rawTag) {
|
|
// Leerzeichen am Anfang/Ende des einzelnen Tags entfernen:
|
|
$tag = trim($rawTag);
|
|
$cleanedTags[] = $tag;
|
|
}
|
|
// Duplikate entfernen:
|
|
$cleanedTags = array_unique($cleanedTags);
|
|
$cleanedTags = implode(',', $cleanedTags);
|
|
}
|
|
|
|
// ----------------- Verwaiste Bilder aufräumen -----------------
|
|
// Bilder, die im alten (gespeicherten) Content vorkamen, im neuen aber nicht
|
|
// mehr referenziert werden, wurden vom Nutzer entfernt oder ersetzt -> löschen.
|
|
// TODO: Bilder, die innerhalb derselben Bearbeitungs-Sitzung neu hochgeladen und noch vor dem finalen Speichern wieder entfernt wurden, werden hierüber nicht erfasst (sie tauchten nie im alten Content auf) und bleiben als Datei liegen. Für eine vollständige Bereinigung würde sich ein
|
|
$oldBlocks = json_decode($article->getContent(), true);
|
|
$oldImagePaths = [];
|
|
if (is_array($oldBlocks)) {
|
|
foreach ($oldBlocks as $oldBlock) {
|
|
if (($oldBlock['type'] ?? '') === 'image'
|
|
&& !empty($oldBlock['value'])
|
|
&& is_string($oldBlock['value'])
|
|
&& str_starts_with($oldBlock['value'], 'uploads/')) {
|
|
$oldImagePaths[] = $oldBlock['value'];
|
|
}
|
|
}
|
|
}
|
|
|
|
$newImagePaths = [];
|
|
foreach ($blocks as $block) {
|
|
if (($block['type'] ?? '') === 'image' && !empty($block['value'])) {
|
|
$newImagePaths[] = $block['value'];
|
|
}
|
|
}
|
|
|
|
$orphanedImages = array_diff($oldImagePaths, $newImagePaths);
|
|
foreach ($orphanedImages as $orphanedImage) {
|
|
$absolutePath = __DIR__ . '/../../' . $orphanedImage;
|
|
if (is_file($absolutePath)) {
|
|
@unlink($absolutePath);
|
|
}
|
|
}
|
|
|
|
// ----------------- Übertragung der validierten Daten in ArticleManager: ---------------------------
|
|
try {
|
|
$articleManager = ArticleManager::getInstance();
|
|
$article = $articleManager->getArticle($id);
|
|
$article->setTitle($title);
|
|
$article->setContent($content);
|
|
$article->setCategory($category);
|
|
$article->setTags($cleanedTags);
|
|
$articleManager->updateArticle($id, $article, $author);
|
|
|
|
unset($_SESSION["old_title"], $_SESSION["old_content"], $_SESSION["old_category"], $_SESSION["old_tags"]);
|
|
|
|
} catch (\Throwable $e) {
|
|
$_SESSION["message"] = $e->getMessage();
|
|
header("location: ../../index.php?pfad=updateArticle&id=$id");
|
|
exit();
|
|
}
|
|
$_SESSION["message"] = "article_updated";
|
|
// Weiterleitung zur Homepage
|
|
header("location: ../../index.php?pfad=showArticle&id=$id");
|
|
}
|
|
}
|
|
|
|
?>
|