Files
awo-hamburg-intranet/module/knowledgecenter_update/Views/post_cardform.php

1035 lines
44 KiB
PHP
Raw Normal View History

<?php
// post_cardform.php
// ini_set('display_errors', 1);
// error_reporting(E_ALL);
// Aktueller Nutzer (z.B. via Session, hier exemplarisch aus den Globals)
$currentUserId = $GLOBALS["main_contact"]["id"] ?? 0;
// Lade die Berechtigungseinträge (Mandanten, Departments, Rollen) des aktuellen Nutzers
$userMandants = [];
$userDepartments = [];
$userRoles = [];
if ($currentUserId) {
$query = "SELECT main_mandant_id, main_department_id, main_role_id
FROM main_contact_department
WHERE main_contact_id = $currentUserId AND active = 1";
$result = mysqli_query($GLOBALS['mysql_con'], $query);
while ($row = mysqli_fetch_assoc($result)) {
if (!in_array($row['main_mandant_id'], $userMandants)) {
$userMandants[] = $row['main_mandant_id'];
}
if (!in_array($row['main_department_id'], $userDepartments)) {
$userDepartments[] = $row['main_department_id'];
}
if (!in_array($row['main_role_id'], $userRoles)) {
$userRoles[] = $row['main_role_id'];
}
}
}
$saveIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-check" viewBox="0 0 16 16">
<path d="M10.97 4.97a.75.75 0 0 1 1.07 1.05l-3.99 4.99a.75.75 0 0 1-1.08.02L4.324 8.384a.75.75 0 1 1 1.06-1.06l2.094 2.093 3.473-4.425z"/>
</svg>';
/**
* Prüft, ob der aktuelle User auf den Beitrag zugreifen darf
* basierend auf den Berechtigungstabellen für Mandanten, Abteilungen und Rollen.
* Der LEFT JOIN-Ansatz überprüft, ob in jedem Bereich (department, mandant, role)
* entweder keine Verknüpfung existiert oder, falls Verknüpfungen vorhanden sind,
* mindestens eine Übereinstimmung mit den erlaubten Werten vorliegt.
*
* @param int $postId Die ID des Beitrags, für den die Berechtigungsprüfung erfolgen soll.
* @return bool True, wenn der User in allen relevanten Bereichen mindestens einen Match hat oder die Einschränkung fehlt; ansonsten false.
*/
function userHasAccessForPost($postId)
{
// Superuser-Bypass: Hat der Nutzer die Berechtigung "super user", darf er den Artikel immer sehen
$mandantId = isset($GLOBALS['main_contact']['master_mandant_id']) ? (int) $GLOBALS['main_contact']['master_mandant_id'] : 0;
$userId = isset($GLOBALS['main_contact']['id']) ? (int) $GLOBALS['main_contact']['id'] : 0;
if (function_exists('get_permission_state')) {
$isSuperUser = get_permission_state('r-wiki', $mandantId, $userId);
if ($isSuperUser == 1) {
return true;
}
}
global $allowedMandants, $allowedDepartments, $allowedRoles;
// Baue den Query, der per LEFT JOIN die Verknüpfungen berücksichtigt.
// Für jeden Bereich wird ermittelt:
// - cntX: Gesamtzahl der Verknüpfungen in diesem Bereich für diesen Post.
// - matchX: Anzahl der Verknüpfungen, die in der erlaubten Liste liegen.
// Wenn cnt > 0 und match = 0, dann hat der User in diesem Bereich keinen Zugriff.
// Existieren keine Verknüpfungen (cnt = 0), gilt der Bereich als unbeschränkt.
$sql = "
SELECT
COUNT(DISTINCT pd.department_id) AS cntDept,
SUM(IF(pd.department_id IN (" . ($allowedDepartments ? $allowedDepartments : 'NULL') . "), 1, 0)) AS matchDept,
COUNT(DISTINCT pm.mandant_id) AS cntMand,
SUM(IF(pm.mandant_id IN (" . ($allowedMandants ? $allowedMandants : 'NULL') . "), 1, 0)) AS matchMand,
COUNT(DISTINCT pr.role_id) AS cntRole,
SUM(IF(pr.role_id IN (" . ($allowedRoles ? $allowedRoles : 'NULL') . "), 1, 0)) AS matchRole
FROM knowledgecenter_posts AS p
LEFT JOIN knowledgecenter_post_department AS pd ON p.id = pd.post_id
LEFT JOIN knowledgecenter_post_mandant AS pm ON p.id = pm.post_id
LEFT JOIN knowledgecenter_post_role AS pr ON p.id = pr.post_id
WHERE p.id = $postId
GROUP BY p.id
";
$res = mysqli_query($GLOBALS['mysql_con'], $sql);
if (!$res || mysqli_num_rows($res) === 0) {
// Falls keine Verknüpfungen in allen Bereichen vorhanden sind, wird oft kein Datensatz zurückgegeben
// das bedeutet, dass es keine Einschränkungen gibt, also Zugriff.
return true;
}
$row = mysqli_fetch_assoc($res);
$access = true;
if ($row['cntDept'] > 0 && $row['matchDept'] == 0) {
$access = false;
}
if ($row['cntMand'] > 0 && $row['matchMand'] == 0) {
$access = false;
}
if ($row['cntRole'] > 0 && $row['matchRole'] == 0) {
$access = false;
}
return $access;
}
// Hole alle Sprachen aus der Datenbank:
$allLanguages = [];
$sqlLang = "SELECT id, code, name FROM main_language";
$resLang = mysqli_query($GLOBALS['mysql_con'], $sqlLang);
while ($lang = mysqli_fetch_assoc($resLang)) {
$allLanguages[] = $lang;
}
$initialRedirectCategoryId = 0;
// akzeptiere beide Namen, falls du sie mal unterschiedlich geschickt hast
if (isset($_GET['initial_category_id'])) {
$initialRedirectCategoryId = (int)$_GET['initial_category_id'];
} elseif (isset($_GET['initial_category'])) {
$initialRedirectCategoryId = (int)$_GET['initial_category'];
}
if ($initialRedirectCategoryId > 0) {
// Ziel: /intranet/de/wiki/?detail=CATEGORYID&route=CATEGORYID
$redirectURL = '/intranet/de/wiki/?detail=' . $initialRedirectCategoryId . '&route=' . $initialRedirectCategoryId;
} elseif (!empty($_GET['redirectURL'])) {
// optional: hier könntest du noch erlaubte Domains/Prefixes whitelisten
$redirectURL = (string)$_GET['redirectURL'];
} else {
$redirectURL = '/';
}
// Prüfe, ob ein neuer Beitrag erstellt werden soll (Parameter new=1)
$isNew = isset($_GET['new']) && $_GET['new'] == 1;
// Initiale Kategorie aus der URL übernehmen (bei Neuerstellung)
$initialCategoryId = isset($_GET['InitialCategory']) ? (int) $_GET['InitialCategory'] : 0;
$InitialProduct = isset($_GET['InitialProduct']) ? (int) $_GET['InitialProduct'] : 0;
if ($isNew) {
require_permission('r-wiki');
// Neuer Beitrag: Lege leere bzw. Standardwerte an
$postId = 0;
$post = [
'id' => 0,
// Weitere Felder kannst du hier ggf. ergänzen
];
$commentCount = 0;
$versionCount = 0;
$currentVersion = [
'id' => 0,
'title' => '',
'image' => '',
'teaser' => '',
'content' => '',
'version_number' => 0,
'created_at' => date("Y-m-d H:i:s")
];
} else {
// Ermitteln der Post-ID aus dem Query-String
if (!isset($_GET['id'])) {
echo "<p>Kein Beitrag ausgewählt.</p>";
exit;
}
$postId = (int) $_GET['id'];
// Sicherheitscheck: Prüfe, ob der Nutzer auf diesen Beitrag zugreifen darf
if (!userHasAccessForPost($postId)) {
echo "<p>Sie haben nicht die notwendigen Berechtigungen.</p>";
exit;
}
// Beitrag aus der Haupttabelle abrufen
$sqlPost = "SELECT * FROM knowledgecenter_posts WHERE id = $postId LIMIT 1";
$resPost = mysqli_query($GLOBALS['mysql_con'], $sqlPost);
if (!$resPost || mysqli_num_rows($resPost) == 0) {
echo "<p>Beitrag nicht gefunden.</p>";
exit;
}
$post = mysqli_fetch_assoc($resPost);
// Anzahl Dateien ermitteln
$sqlCountFiles = "SELECT COUNT(*) AS fileCount FROM knowledgecenter_post_files WHERE post_id = $postId";
$resCountFiles = mysqli_query($GLOBALS['mysql_con'], $sqlCountFiles);
if ($resCountFiles && mysqli_num_rows($resCountFiles) > 0) {
$row = mysqli_fetch_assoc($resCountFiles);
$fileCount = (int) $row['fileCount'];
} else {
$fileCount = 0;
}
// Anzahl Kommentare ermitteln
$sqlCountComments = "SELECT COUNT(*) AS commentCount FROM topic WHERE knowledgecenter_post_id = $postId";
$resCountComments = mysqli_query($GLOBALS['mysql_con'], $sqlCountComments);
if ($resCountComments && mysqli_num_rows($resCountComments) > 0) {
$rowCount = mysqli_fetch_assoc($resCountComments);
$commentCount = (int) $rowCount['commentCount'];
} else {
$commentCount = 0;
}
// Anzahl Versionen für die aktuell ausgewählte Sprache ermitteln
$sqlCountVersions = "SELECT COUNT(*) AS versionCount FROM knowledgecenter_post_versions WHERE post_id = $postId AND language_id = $languageId";
$resCountVersions = mysqli_query($GLOBALS['mysql_con'], $sqlCountVersions);
if ($resCountVersions && mysqli_num_rows($resCountVersions) > 0) {
$rowCountVersions = mysqli_fetch_assoc($resCountVersions);
$versionCount = (int) $rowCountVersions['versionCount'];
} else {
$versionCount = 0;
}
// Anzahl Ansprechpartner ermitteln
$sqlCountContacts = "SELECT COUNT(*) AS contactCount FROM knowledgecenter_post_contacts WHERE post_id = $postId";
$resCountContacts = mysqli_query($GLOBALS['mysql_con'], $sqlCountContacts);
if ($resCountContacts && mysqli_num_rows($resCountContacts) > 0) {
$row = mysqli_fetch_assoc($resCountContacts);
$contactCount = (int) $row['contactCount'];
} else {
$contactCount = 0;
}
// Prüfe, ob ein spezieller Versionsparameter übergeben wurde
if (isset($_GET['version']) && !empty($_GET['version'])) {
$versionId = (int) $_GET['version'];
// Versuche, die angeforderte Version zu laden aber nur, wenn sie aktuell gültig ist:
$sqlVersion = "SELECT kpv.*, mc.name AS author
FROM knowledgecenter_post_versions AS kpv
LEFT JOIN main_contact AS mc ON kpv.author_id = mc.id
WHERE kpv.post_id = $postId
AND kpv.language_id = $languageId
AND kpv.id = $versionId
LIMIT 1";
// var_dump($sqlVersion);
$resVersion = mysqli_query($GLOBALS['mysql_con'], $sqlVersion);
if ($resVersion && mysqli_num_rows($resVersion) > 0) {
// Die angeforderte Version existiert und ist aktuell gültig
$currentVersion = mysqli_fetch_assoc($resVersion);
} else {
// Die angeforderte Version ist entweder ungültig (z. B. noch in der Zukunft) oder existiert nicht
// => Ladevorgang: Suche nach der neuesten gültigen Version
$sqlVersion = "SELECT kpv.*, mc.name AS author
FROM knowledgecenter_post_versions AS kpv
LEFT JOIN main_contact AS mc ON kpv.author_id = mc.id
WHERE kpv.post_id = $postId
AND kpv.language_id = $languageId
AND kpv.state = 1
AND (kpv.valid_from IS NULL OR kpv.valid_from <= NOW())
AND (kpv.valid_until IS NULL OR kpv.valid_until >= NOW())
ORDER BY kpv.version_number DESC
LIMIT 1";
// var_dump($sqlVersion);
$resVersion = mysqli_query($GLOBALS['mysql_con'], $sqlVersion);
if ($resVersion && mysqli_num_rows($resVersion) > 0) {
$currentVersion = mysqli_fetch_assoc($resVersion);
} else {
// Es gibt überhaupt keine aktuell gültige Version, also setze einen Standard-Platzhalter
$currentVersion = [
'id' => 0,
'title' => 'Keine gültige Version vorhanden',
'image' => '',
'teaser' => '',
'content' => '',
'version_number' => 0,
'created_at' => date("Y-m-d H:i:s"),
'author' => ''
];
}
}
} else {
// Kein spezieller Versionsparameter übergeben lade die neueste gültige Version
$sqlVersion = "SELECT kpv.*, mc.name AS author
FROM knowledgecenter_post_versions AS kpv
LEFT JOIN main_contact AS mc ON kpv.author_id = mc.id
WHERE kpv.post_id = $postId
AND kpv.language_id = $languageId
AND kpv.state = 1
AND (kpv.valid_from IS NULL OR kpv.valid_from <= NOW())
AND (kpv.valid_until IS NULL OR kpv.valid_until >= NOW())
ORDER BY kpv.version_number DESC
LIMIT 1";
// var_dump($sqlVersion);
$resVersion = mysqli_query($GLOBALS['mysql_con'], $sqlVersion);
if ($resVersion && mysqli_num_rows($resVersion) > 0) {
$currentVersion = mysqli_fetch_assoc($resVersion);
} else {
// Fallback: Falls keine aktuell gültige Version existiert, wird kein Draft geladen
// (Alternativ kannst du hier einen Hinweis ausgeben)
$currentVersion = [
'id' => 0,
'title' => 'Keine gültige Version vorhanden',
'image' => '',
'teaser' => '',
'content' => '',
'version_number' => 0,
'created_at' => date("Y-m-d H:i:s"),
'author' => ''
];
}
}
}
// Expose current post title to JS for setting the page H1
echo "<script>window.kcPostTitle = " . json_encode(isset($currentVersion['title']) ? $currentVersion['title'] : null) . ";</script>";
// Alle Versionen für diesen Beitrag (absteigend sortiert) für die aktuell gewählte Sprache abrufen
$sqlAllVersions = "SELECT kpv.*, mc.name AS author
FROM knowledgecenter_post_versions AS kpv
LEFT JOIN main_contact AS mc ON kpv.author_id = mc.id
WHERE kpv.post_id = $postId
AND kpv.language_id = $languageId
ORDER BY kpv.version_number DESC";
$resAllVersions = mysqli_query($GLOBALS['mysql_con'], $sqlAllVersions);
$versions = [];
while ($v = mysqli_fetch_assoc($resAllVersions)) {
$versions[] = $v;
}
// Lade translations für alle Sprachen: Für jede Sprache wird die neueste Version für diesen Beitrag geladen
$translations = [];
foreach ($allLanguages as $lang) {
$langId = (int) $lang['id'];
$sqlTrans = "SELECT * FROM knowledgecenter_post_versions
WHERE post_id = $postId
AND language_id = $langId
ORDER BY version_number DESC
LIMIT 1";
$resTrans = mysqli_query($GLOBALS['mysql_con'], $sqlTrans);
if ($resTrans && mysqli_num_rows($resTrans) > 0) {
$translations[$langId] = mysqli_fetch_assoc($resTrans);
} else {
$translations[$langId] = [
'id' => 0,
'title' => '',
'image' => '',
'teaser' => '',
'content' => '',
'version_number' => 0,
'created_at' => ''
];
}
}
$linkedFormId = null;
$sqlLinkedForm = "SELECT form_id
FROM knowledgecenter_post_form
WHERE post_id = $postId
LIMIT 1";
$resLinkedForm = mysqli_query($GLOBALS['mysql_con'], $sqlLinkedForm);
if ($resLinkedForm && mysqli_num_rows($resLinkedForm) > 0) {
$rowLinkedForm = mysqli_fetch_assoc($resLinkedForm);
$linkedFormId = (int) $rowLinkedForm['form_id'];
}
?>
<div class="post-detail-container">
<!-- Tabbar -->
<div class="post-detail-header">
<!-- <a href="<?php echo htmlspecialchars($redirectURL); ?>&embedded=<?= $isEmbedded ?>" class="back-link"></a> -->
<a href="<?php echo htmlspecialchars($redirectURL); ?>" class="back-link"></a>
<div class="tab-bar">
<a href="#tab-article" class="active"><?= $translation->get("wiki_post") ?></a>
<a href="#tab-files"><?= $translation->get("files") ?> (<?php echo $fileCount; ?>)</a>
<a href="#tab-contacts"><?= $translation->get("Ansprechpartner") ?> (<?php echo $contactCount; ?>)</a>
<a href="#tab-discussion"><?= $translation->get("Forum") ?> (<?php echo $commentCount; ?>)</a>
<a href="#tab-versions"><?= $translation->get("version_history") ?> (<?php echo $versionCount; ?>)</a>
<?php if (get_permission_state('r-wiki', $GLOBALS['main_contact']['master_mandant_id'], $GLOBALS['main_contact']['id']) == 1) { ?>
<a href="#tab-settings"><?= $translation->get("settings") ?></a>
<?php } ?>
</div>
</div>
<!-- Tab Content: Artikel (initial sichtbar) -->
<div id="tab-article" class="tab-content active">
<?php
require_once 'post_cardform_article.php';
if (!empty($linkedFormId)) {
// (Optional) read form title/description for display
$formRes = mysqli_query(
$GLOBALS['mysql_con'],
"SELECT description
FROM contactform_header
WHERE id = $linkedFormId
LIMIT 1"
);
$formRow = mysqli_fetch_assoc($formRes);
echo '<hr>';
echo '<div class="linked-contactform-wrapper">';
// Provide form id to the contactform module
$sitepart_id = $linkedFormId;
// Render the linked contact form
require MODULE_PATH . 'contactform/show_contactform.inc.php';
echo '</div>';
}
?>
<script>
document.addEventListener("DOMContentLoaded", function () {
const formBlock = document.querySelector('.linked-contactform-wrapper');
const previewBlock = document.querySelector('.post-preview-embed');
const contentBlock = document.querySelector('#displayContent');
if (formBlock) {
if (previewBlock && previewBlock.parentNode) {
previewBlock.parentNode.insertBefore(formBlock, previewBlock.nextSibling);
} else if (contentBlock && contentBlock.parentNode) {
contentBlock.parentNode.insertBefore(formBlock, contentBlock.nextSibling);
}
}
});
</script>
</div>
<!-- Tab Content: Diskussion -->
<div id="tab-files" class="tab-content">
<?php
require_once 'post_cardform_files.php';
?>
</div>
<div id="tab-contacts" class="tab-content">
<?php
require_once 'post_cardform_contacts.php';
?>
</div>
<div id="tab-discussion" class="tab-content forum">
<?php
// require_once 'post_cardform_discussion.php';
?>
<?php $knowledgecenter_post_id = $_GET['id']; ?>
<?php require_once(__DIR__ . '/../../forum/Views/topic_listform.php'); ?>
</div>
<!-- Tab Content: Versionsgeschichte -->
<div id="tab-versions" class="tab-content">
<?php
require_once 'post_cardform_version_history.php';
?>
</div>
<?php if (get_permission_state('r-wiki', $GLOBALS['main_contact']['master_mandant_id'], $GLOBALS['main_contact']['id']) == 1) { ?>
<div id="tab-settings" class="tab-content">
<?php
require_once 'post_cardform_settings.php';
?>
</div>
<?php } ?>
</div>
<!-- Aside-Bereich zum Bearbeiten / Erstellen des Beitrags (initial versteckt) -->
<aside class="post-edit-aside" id="editArea" style="display:none;">
<?php
require_once 'post_cardform_edit_aside.php';
?>
</aside>
<script>
// Stelle sicher, dass jQuery geladen ist
$(document).ready(function () {
// Setze H1-Titel (#intranetTitle) anhand des Post-Titels mit jQuery; Fallback "Wiki"
(function setPostTitle() {
var $h1 = $('#intranetTitle');
if (!$h1.length) return;
var t = (typeof window.kcPostTitle !== 'undefined' && window.kcPostTitle) ? String(window.kcPostTitle) : '';
$h1.text(t && $.trim(t) !== '' ? t : 'Wiki');
})();
// InitialCategory aus PHP übernehmen
var initialCategoryId = <?= $initialCategoryId ?>;
var InitialProduct = <?= $InitialProduct ?>;
var isNewPost = <?= $isNew ? 'true' : 'false' ?>;
var draftInitRequestRunning = false;
var mode = ""; // "update" oder "create"
// Für bestehende Beiträge ist der Zielordner direkt bekannt.
window.kcPostGalleryPath = <?= json_encode((!$isNew && $postId > 0) ? ('knowledgecenter_update/posts/' . substr(sha1('kc_post_' . $postId), 0, 24)) : '') ?>;
function ensureExistingPostGalleryFolder() {
if (isNewPost) {
return;
}
var currentPostId = parseInt($("#editVersionForm input[name='post_id']").val(), 10) || 0;
if (currentPostId <= 0) {
return;
}
$.ajax({
type: "POST",
url: "/module/knowledgecenter_update/Ajax/Ajax.php",
dataType: "json",
data: {
action: "ensure_post_gallery_folder",
post_id: currentPostId
},
success: function (response) {
if (response && response.success && typeof response.gallery_start_path === "string" && response.gallery_start_path.length > 0) {
window.kcPostGalleryPath = response.gallery_start_path;
}
},
error: function (jqXHR, textStatus, errorThrown) {
console.error("ensure_post_gallery_folder AJAX Fehler", textStatus, errorThrown);
}
});
}
function initializeDraftPost() {
if (!isNewPost || draftInitRequestRunning) {
return;
}
var $postIdInput = $("#editVersionForm input[name='post_id']");
if (!$postIdInput.length) {
return;
}
var currentPostId = parseInt($postIdInput.val(), 10) || 0;
if (currentPostId > 0) {
return;
}
draftInitRequestRunning = true;
$.ajax({
type: "POST",
url: "/module/knowledgecenter_update/Ajax/Ajax.php",
dataType: "json",
data: {
action: "create_post_draft"
},
success: function (response) {
if (response && response.success && response.new_post_id > 0) {
$postIdInput.val(response.new_post_id);
if (typeof response.gallery_start_path === "string" && response.gallery_start_path.length > 0) {
window.kcPostGalleryPath = response.gallery_start_path;
}
} else {
console.error("create_post_draft fehlgeschlagen", response);
}
},
error: function (jqXHR, textStatus, errorThrown) {
console.error("create_post_draft AJAX Fehler", textStatus, errorThrown);
},
complete: function () {
draftInitRequestRunning = false;
}
});
}
<?php if ($isNew): ?>
// Setze den Modus auf "create" und passe ggf. den Titel des Editierbereichs an
mode = "create";
$("#editAreaTitle").text("Erstellen");
// Blende den Editierbereich ein und füge den Blur-Effekt hinzu
$("#editArea").appendTo("body").show(function () {
$(".post-detail-container").addClass("blurred");
});
initializeDraftPost();
<?php endif; ?>
ensureExistingPostGalleryFolder();
// Event-Handler für die Sprache-Tabs im Bearbeitungsbereich
$(".language-tabs div").on("click", function () {
$(".language-tabs div").removeClass("active");
$(this).addClass("active");
var langId = $(this).data("lang");
// Alle sprachspezifischen Bereiche ausblenden und nur den angeklickten anzeigen
$(".lang-form").hide();
$("#lang_" + langId).show();
// Sidebar-Meta ebenfalls umschalten
$(".lang-form-meta").hide();
$(".lang-form-meta[data-lang='" + langId + "']").show();
});
// Funktion zum Aktualisieren des URL-Query-Parameters "version"
function updateVersionParamInURL(versionId) {
var currentUrl = window.location.href;
var newUrl;
if (currentUrl.indexOf('version=') !== -1) {
newUrl = currentUrl.replace(/(version=)[^\&]+/, '$1' + versionId);
} else {
newUrl = currentUrl + "&version=" + versionId;
}
history.pushState(null, '', newUrl);
}
// Tab-Wechsel in der Hauptnavigation
$(".tab-bar a").on("click", function (e) {
e.preventDefault();
var target = $(this).attr("href"); // z.B. "#tab-files"
// Aktualisiere das visuelle Tab-Layout
$(".tab-bar a").removeClass("active");
$(this).addClass("active");
$(".tab-content").removeClass("active");
$(target).addClass("active");
// Entferne das führende '#' aus dem Ziel (z. B. "tab-files")
var tabParam = target.substring(1);
// Aktualisiere den URL-Parameter "tab-content" mithilfe der History-API
var url = new URL(window.location);
url.searchParams.set("tab-content", tabParam);
window.history.pushState(null, "", url.toString());
});
var urlParams = new URLSearchParams(window.location.search);
var tabContent = urlParams.get("tab-content");
// console.log("URL-Parameter tab-content:", tabContent);
var selector = ".tab-bar a[href='#" + tabContent + "']";
// console.log("Selektor für Tab:", selector);
if ($(selector).length > 0) {
$(selector).trigger("click");
} else {
console.warn("Kein Tab gefunden für den Selektor: " + selector);
}
// Speichere alle Versionen in einer JS-Variablen (nur für Anzeige und Editierung)
var versionsData = <?php echo json_encode($versions); ?>;
// Klick auf ein Listenelement in der Versionsliste: Anzeige aktualisieren und URL anpassen
$("#versionList div").on("click", function () {
$("#versionList div").removeClass("version_selected");
$(this).addClass("version_selected");
var selectedId = $(this).data("id");
var selectedVersion = versionsData.find(function (ver) {
return ver.id == selectedId;
});
if (selectedVersion) {
$("#displayTitle").text(selectedVersion.title);
if (selectedVersion.image) {
$("#displayImage").attr("src", "/userdata/" + selectedVersion.image).show();
} else {
$("#displayImage").hide();
}
$("#displayTeaser").html(selectedVersion.teaser ? nl2br(selectedVersion.teaser) : "");
$("#displayContent").html(selectedVersion.content);
// Aktualisiere die URL, sodass ?version= gesetzt wird
updateVersionParamInURL(selectedId);
}
// Setze den Artikel-Tab aktiv:
$(".tab-bar a[href='#tab-article']").trigger("click");
});
// Hilfsfunktion, um Zeilenumbrüche in <br> umzuwandeln
function nl2br(str) {
return str.replace(/\n/g, "<br>");
}
// Klick auf Edit-Button: Update-Modus
$("#editBtn").on("click", function () {
mode = "update";
$("#editAreaTitle").text("Version bearbeiten");
$("#keep_modified_at").prop("checked", false);
// Ermitteln der aktiven Sprache (z.B. Sprache mit ID)
var activeLang = $(".language-tabs div.active").data("lang");
// Finde die aktuell ausgewählte Version
var currentId = $("#versionList div.version_selected").data("id");
var currentVersion = versionsData.find(function (ver) {
return ver.id == currentId;
});
if (currentVersion) {
// Setze den Hidden-Wert für die Version-ID im aktiven Sprachbereich
$("#lang_" + activeLang + " input[name='version_id[" + activeLang + "]']").val(currentVersion.id);
// Befülle die textbasierten Felder
$("#title_" + activeLang).val(currentVersion.title);
$("#image_" + activeLang).val(currentVersion.image);
$(".preview").attr("src", "/userdata/" + currentVersion.image);
$("#teaser_" + activeLang).val(currentVersion.teaser);
// Falls du einen Quill-Editor verwendest, setze den Inhalt über seine API:
if (quillEditors[activeLang]) {
// dangerouslyPasteHTML statt innerHTML=, damit Quill 2.x
// alte Listen-Inhalte beim Re-Normalisieren nicht droppt.
quillEditors[activeLang].setContents([], 'silent');
quillEditors[activeLang].clipboard.dangerouslyPasteHTML(0, currentVersion.content || '', 'silent');
}
}
$("#editArea").appendTo("body").show(function () {
$(".post-detail-container").addClass("blurred");
});
});
// Klick auf Create-Button: Create-Modus
$("#createBtn").on("click", function () {
mode = "create";
$("#editAreaTitle").text("Erstellen");
$("#keep_modified_at").prop("checked", false);
// Ermitteln der aktiven Sprache (z.B. Sprache mit ID)
var activeLang = $(".language-tabs div.active").data("lang");
// Aktuell angezeigte Version in der Versionsliste abrufen
var currentId = $("#versionList div.version_selected").data("id");
var currentVersion = versionsData.find(function (ver) {
return ver.id == currentId;
});
// Wenn es eine aktuell angezeigte Version gibt, diese vorbefüllen, ansonsten leere Felder setzen
if (currentVersion) {
// Im Create-Modus setzen wir die version_id auf leer, da eine neue Version erstellt wird.
$("#lang_" + activeLang + " input[name='version_id[" + activeLang + "]']").val("");
$("#title_" + activeLang).val(currentVersion.title);
$("#image_" + activeLang).val(currentVersion.image);
$(".preview").attr("src", "/userdata/" + currentVersion.image);
$("#teaser_" + activeLang).val(currentVersion.teaser);
if (quillEditors[activeLang]) {
// dangerouslyPasteHTML statt innerHTML=, damit Quill 2.x
// alte Listen-Inhalte beim Re-Normalisieren nicht droppt.
quillEditors[activeLang].setContents([], 'silent');
quillEditors[activeLang].clipboard.dangerouslyPasteHTML(0, currentVersion.content || '', 'silent');
}
} else {
$("#lang_" + activeLang + " input[name='version_id[" + activeLang + "]']").val("");
$("#title_" + activeLang).val("");
$("#image_" + activeLang).val("");
$("#teaser_" + activeLang).val("");
if (quillEditors[activeLang]) {
quillEditors[activeLang].setContents([], 'silent');
}
}
// Editierbereich anzeigen und ggf. den Blur-Effekt hinzufügen
$("#editArea").appendTo("body").show(function () {
$(".post-detail-container").addClass("blurred");
});
});
// Klick auf Abbrechen (Cancel) im Bearbeitungsbereich: Edit-Bereich schließen und Events reaktivieren
$("#cancelEditBtn").on("click", function () {
$("#editArea").hide(function () {
// Entferne den Blur-Effekt, wenn das Aside geschlossen wurde
$(".post-detail-container").removeClass("blurred");
});
});
$("#versionList div").on("click", function () {
$("#versionList div").removeClass("version_selected");
$(this).addClass("version_selected");
var selectedId = $(this).data("id");
var selectedVersion = versionsData.find(function (ver) {
return ver.id == selectedId;
});
if (!selectedVersion) return;
// 1) Title, Image, Teaser, Content wie gehabt
$("#displayTitle").text(selectedVersion.title);
if (selectedVersion.image) {
$("#displayImage").attr("src", "/userdata/" + selectedVersion.image).show();
} else {
$("#displayImage").hide();
}
$("#displayTeaser").html(selectedVersion.teaser ? nl2br(selectedVersion.teaser) : "");
$("#displayContent").html(selectedVersion.content);
// 2) Meta (Datum + Autor) aktualisieren
// a) in JS formatieren wir auf Deutsch:
var dt = new Date(selectedVersion.modified_at);
var formattedDate = dt.toLocaleString('de-DE', {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
// b) in ein und denselben Container schreiben:
$(".post-meta-item").text(formattedDate + " - " + selectedVersion.author);
});
// 1) BetterTablePlugin vor allen Instanzen registrieren
Quill.register({
'modules/better-table': quillBetterTable
}, true);
var quillEditors = {};
// 2) imageHandler: Datei-Upload statt Base64-Embed.
// Lädt das Bild via AJAX in den Post-Ordner und fügt nur die URL als <img src> ein.
function imageHandler() {
var quill = this.quill;
var range = quill.getSelection(true);
var fileInput = this.container.querySelector('input.ql-image[type=file]');
if (!fileInput) {
fileInput = document.createElement('input');
fileInput.setAttribute('type', 'file');
fileInput.setAttribute('accept', 'image/jpeg,image/png,image/gif,image/webp');
fileInput.style.display = 'none';
fileInput.addEventListener('change', function () {
var file = fileInput.files[0];
fileInput.value = '';
if (!file) return;
uploadInlineImage(quill, range, file);
});
this.container.appendChild(fileInput);
}
fileInput.click();
}
function getCurrentPostIdForUpload() {
var id = parseInt($("#editVersionForm input[name='post_id']").val(), 10) || 0;
return id;
}
// Stellt sicher, dass für einen neuen Entwurf eine Post-ID + Ordner existiert,
// bevor wir hochladen. Resolved mit einer post_id > 0 oder rejected.
function ensurePostIdReady() {
return new Promise(function (resolve, reject) {
var current = getCurrentPostIdForUpload();
if (current > 0) { resolve(current); return; }
if (!isNewPost) { reject(new Error('Keine Post-ID verfügbar.')); return; }
$.ajax({
type: "POST",
url: "/module/knowledgecenter_update/Ajax/Ajax.php",
dataType: "json",
data: { action: "create_post_draft" }
}).done(function (response) {
if (response && response.success && response.new_post_id > 0) {
$("#editVersionForm input[name='post_id']").val(response.new_post_id);
if (typeof response.gallery_start_path === "string" && response.gallery_start_path.length > 0) {
window.kcPostGalleryPath = response.gallery_start_path;
}
resolve(response.new_post_id);
} else {
reject(new Error((response && response.error) || 'Entwurf konnte nicht angelegt werden.'));
}
}).fail(function () {
reject(new Error('Netzwerkfehler beim Anlegen des Entwurfs.'));
});
});
}
function uploadInlineImage(quill, range, file) {
ensurePostIdReady().then(function (postId) {
var fd = new FormData();
fd.append('post_id', postId);
fd.append('file', file);
var insertIndex = (range && typeof range.index === 'number') ? range.index : quill.getLength();
quill.insertText(insertIndex, '⏳', 'silent');
$.ajax({
type: "POST",
url: "/module/knowledgecenter_update/Ajax/endpoints/upload_inline_image.php",
data: fd,
dataType: "json",
processData: false,
contentType: false
}).done(function (response) {
quill.deleteText(insertIndex, 1, 'silent');
if (response && response.success && response.url) {
quill.insertEmbed(insertIndex, 'image', response.url, 'user');
quill.setSelection(insertIndex + 1, 0, 'silent');
} else {
alert("Bild-Upload fehlgeschlagen: " + ((response && response.error) || 'unbekannter Fehler'));
}
}).fail(function (jqXHR) {
quill.deleteText(insertIndex, 1, 'silent');
var msg = 'Upload fehlgeschlagen.';
try {
var j = JSON.parse(jqXHR.responseText);
if (j && j.error) msg = j.error;
} catch (e) {}
alert("Bild-Upload fehlgeschlagen: " + msg);
});
}).catch(function (err) {
alert("Bild-Upload fehlgeschlagen: " + err.message);
});
}
// 3) Pro SprachForm genau eine QuillInstanz
$('.lang-form').each(function () {
var $form = $(this);
var langId = $form.data('lang');
var $editor = $form.find('.editor');
var editorId = $editor.attr('id');
var quill = new Quill('#' + editorId, {
theme: 'snow',
modules: {
// a) Toolbar = Goldstandard-Preset aus shared_components/quill/toolbar_presets.js
toolbar: {
container: window.QuillToolbarPresets.full(),
handlers: {
image: imageHandler,
table: function () {
// 'this' ist der ToolbarHandler, 'this.quill' Deine Instanz
const tableModule = this.quill.getModule('better-table');
tableModule.insertTable(3, 3); // hier beliebige Größe
}
}
},
// b) BetterTable
table: false,
'better-table': window.QuillToolbarPresets.betterTableConfig(),
// c) Wichtige KeyboardBindings für BetterTable
keyboard: {
bindings: quillBetterTable.keyboardBindings
},
// d) Drag-Resize für Bilder (shared module aus /module/shared_components/quill/)
imageResize: true
}
});
quillEditors[langId] = quill;
});
// AJAX-Funktion zum Speichern der Versionen
window.saveVersionAjax = function () {
// HTML-Inhalt aus jedem Editor in das zugehörige hidden-Feld übernehmen
for (var lang in quillEditors) {
if (quillEditors.hasOwnProperty(lang)) {
var htmlContent = quillEditors[lang].root.innerHTML;
$("#hiddenContent_" + lang).val(htmlContent);
}
}
// Formularserialisierung
var formData = $("#editVersionForm").serialize();
var postBackgroundColor = $("#postBackgroundColor").val();
var postTextColor = $("#postTextColor").val();
if (postBackgroundColor) {
formData += "&background_color=" + encodeURIComponent(postBackgroundColor);
}
if (postTextColor) {
formData += "&text_color=" + encodeURIComponent(postTextColor);
}
// InitialCategory zum POST-Daten hinzufügen
if (typeof initialCategoryId !== 'undefined' && initialCategoryId > 0) {
formData += "&initial_category_id=" + initialCategoryId;
}
if (typeof InitialProduct !== 'undefined' && InitialProduct > 0) {
formData += "&InitialProduct=" + InitialProduct;
}
// Modusabhängige Aktion anhängen (update oder create)
if (mode === "update") {
formData += "&action=update_post_version";
} else if (mode === "create") {
formData += "&action=insert_post_version";
}
// AJAX-Request über jQuery
$.ajax({
type: "POST",
url: "/module/knowledgecenter_update/Ajax/Ajax.php",
data: formData,
dataType: "json",
success: function (response) {
if (response.success) {
// Wenn ein neuer Beitrag erstellt wurde, leite weiter, ansonsten Seite neu laden
if (typeof response.new_post_id !== "undefined" && response.new_post_id > 0) {
// Übergibt den Redirect-Parameter aus PHP in JS
var redirectURL = "<?php echo htmlspecialchars($redirectURL, ENT_QUOTES, 'UTF-8'); ?>";
// Falls redirectURL nicht leer sein sollte, anhängen
var newUrl = "?action=Post&id=" + encodeURIComponent(response.new_post_id)
+ "&embedded=<?= rawurlencode((string) $isEmbedded) ?>";
if (typeof initialCategoryId !== 'undefined' && initialCategoryId > 0) {
newUrl += "&initial_category_id=" + encodeURIComponent(initialCategoryId);
}
if (typeof InitialProduct !== 'undefined' && InitialProduct > 0) {
newUrl += "&InitialProduct=" + encodeURIComponent(InitialProduct);
}
window.location.href = newUrl;
} else {
location.reload();
}
} else {
alert("Fehler: " + response.error);
}
},
error: function (jqXHR, textStatus, errorThrown) {
console.error("AJAX Fehler: ", textStatus, errorThrown);
}
});
}
// Ersetze den bisherigen Click-Handler vom Button "saveVersionBtn" durch den direkten Aufruf der AJAX-Funktion
$("#saveVersionBtn").on("click", function (e) {
e.preventDefault();
saveVersionAjax();
});
// In Deinem $(document).ready()-Block:
$(".deleteVersionBtn").on("click", function () {
var versionId = $(this).data("id"); // eventuell nicht mehr benötigt
var versionNumber = $(this).data("version-number");
// Stelle sicher, dass Du auch die Post-ID übergeben kannst entweder aus einem versteckten Feld oder als globale Variable:
var postId = <?php echo json_encode($postId); ?>;
if (confirm("Wollen Sie diese Version wirklich löschen?")) {
$.post("/module/knowledgecenter_update/Ajax/Ajax.php", {
action: "delete_post_version",
post_id: postId,
embedded: <?= $isEmbedded ?>,
version_number: versionNumber
}, function (response) {
if (response.success) {
if (response.redirect) {
window.location.href = response.redirect;
} else {
location.reload();
}
} else {
alert("Fehler beim Löschen: " + response.error);
}
}, "json");
}
});
});
</script>