feat(wiki): Beitragsliste für Betriebsrat-Nutzer auf zugängliche Kategorien filtern
BR-Nutzer (r-wiki-br ohne r-wiki) sehen in der Beitragsliste und im Kategorie-Dropdown nur Beiträge und Kategorien, die ihren freigegebenen Kategorien (betriebsrat_editable=1 + alle Nachfahren per BFS) zugeordnet sind. Der Filter wird server-seitig in post_listform.php berechnet und als Parameter an den Ajax-Endpunkt übergeben, da get_permission_state() im Ajax-Kontext nicht verfügbar ist. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -62,6 +62,39 @@ function ajax_is_category_editable_for_br(int $categoryId): bool
|
||||
return false;
|
||||
}
|
||||
|
||||
// Alle Kategorie-IDs, die für Betriebsrat zugänglich sind (direkt betriebsrat_editable=1
|
||||
// plus alle Nachfahren im Baum – BFS nach unten).
|
||||
function ajax_get_all_betriebsrat_accessible_category_ids(): array
|
||||
{
|
||||
$seeds = [];
|
||||
$res = mysqli_query($GLOBALS['mysql_con'],
|
||||
"SELECT id FROM knowledgecenter_categories_update WHERE betriebsrat_editable = 1");
|
||||
while ($row = mysqli_fetch_assoc($res)) {
|
||||
$seeds[] = (int)$row['id'];
|
||||
}
|
||||
if (empty($seeds)) {
|
||||
return [];
|
||||
}
|
||||
$visited = [];
|
||||
$queue = $seeds;
|
||||
while (!empty($queue)) {
|
||||
$current = array_shift($queue);
|
||||
if (isset($visited[$current])) {
|
||||
continue;
|
||||
}
|
||||
$visited[$current] = true;
|
||||
$cRes = mysqli_query($GLOBALS['mysql_con'],
|
||||
"SELECT child_category_id FROM knowledgecenter_category_links WHERE parent_category_id = $current");
|
||||
while ($cRow = mysqli_fetch_assoc($cRes)) {
|
||||
$cid = (int)$cRow['child_category_id'];
|
||||
if (!isset($visited[$cid])) {
|
||||
$queue[] = $cid;
|
||||
}
|
||||
}
|
||||
}
|
||||
return array_keys($visited);
|
||||
}
|
||||
|
||||
// Betriebsrat darf einen Post nur bearbeiten, wenn er in einer freigegebenen
|
||||
// Kategorie (oder Unterkategorie einer freigegebenen Kategorie) liegt.
|
||||
function ajax_can_edit_post(int $postId): bool
|
||||
@@ -1428,6 +1461,24 @@ function get_post_list()
|
||||
$categoryCondition = "";
|
||||
}
|
||||
|
||||
// Betriebsrat darf nur Posts sehen, die in einer freigegebenen Kategorie liegen.
|
||||
// Die erlaubten Kategorie-IDs werden von post_listform.php berechnet und übergeben,
|
||||
// da get_permission_state() im Ajax-Kontext nicht verfügbar ist.
|
||||
$brCategoryCondition = "";
|
||||
$rawBrIds = isset($_POST['br_category_ids']) && $_POST['br_category_ids'] !== 'null'
|
||||
? json_decode($_POST['br_category_ids'], true)
|
||||
: null;
|
||||
if (is_array($rawBrIds)) {
|
||||
if (count($rawBrIds) === 0) {
|
||||
$brCategoryCondition = "AND 1=0";
|
||||
} else {
|
||||
$brCatIdList = implode(',', array_map('intval', $rawBrIds));
|
||||
$brCategoryCondition = "AND EXISTS (
|
||||
SELECT 1 FROM knowledgecenter_category_post AS cp_br
|
||||
WHERE cp_br.post_id = kp.id AND cp_br.category_id IN ($brCatIdList)
|
||||
)";
|
||||
}
|
||||
}
|
||||
|
||||
// Beiträge abfragen (nur Post‑ID und Titel der aktuellen Version)
|
||||
$sqlPosts = "
|
||||
@@ -1442,6 +1493,7 @@ function get_post_list()
|
||||
WHERE 1=1
|
||||
$searchCondition
|
||||
$categoryCondition
|
||||
$brCategoryCondition
|
||||
GROUP BY kp.id
|
||||
ORDER BY kp.modified_at DESC
|
||||
";
|
||||
|
||||
@@ -867,6 +867,39 @@ function require_wiki_edit_permission(): void
|
||||
}
|
||||
}
|
||||
|
||||
// Gibt alle Kategorie-IDs zurück, auf die Betriebsrat Zugriff hat:
|
||||
// direkt betriebsrat_editable=1 sowie alle ihre Nachfahren im Baum (BFS nach unten).
|
||||
function get_all_betriebsrat_accessible_category_ids(): array
|
||||
{
|
||||
$seeds = [];
|
||||
$res = mysqli_query($GLOBALS['mysql_con'],
|
||||
"SELECT id FROM knowledgecenter_categories_update WHERE betriebsrat_editable = 1");
|
||||
while ($row = mysqli_fetch_assoc($res)) {
|
||||
$seeds[] = (int)$row['id'];
|
||||
}
|
||||
if (empty($seeds)) {
|
||||
return [];
|
||||
}
|
||||
$visited = [];
|
||||
$queue = $seeds;
|
||||
while (!empty($queue)) {
|
||||
$current = array_shift($queue);
|
||||
if (isset($visited[$current])) {
|
||||
continue;
|
||||
}
|
||||
$visited[$current] = true;
|
||||
$cRes = mysqli_query($GLOBALS['mysql_con'],
|
||||
"SELECT child_category_id FROM knowledgecenter_category_links WHERE parent_category_id = $current");
|
||||
while ($cRow = mysqli_fetch_assoc($cRes)) {
|
||||
$cid = (int)$cRow['child_category_id'];
|
||||
if (!isset($visited[$cid])) {
|
||||
$queue[] = $cid;
|
||||
}
|
||||
}
|
||||
}
|
||||
return array_keys($visited);
|
||||
}
|
||||
|
||||
// Prüft ob eine Kategorie (oder irgendein Vorfahre über knowledgecenter_category_links)
|
||||
// betriebsrat_editable=1 hat. Läuft den Baum nach oben durch.
|
||||
function is_category_betriebsrat_editable(int $categoryId): bool
|
||||
|
||||
@@ -186,6 +186,21 @@ $_kcBrOnly = !is_wiki_redakteur() && is_wiki_betriebsrat();
|
||||
* gefiltert, sodass in den Bereichen (Abteilung, Mandant, Rolle) entweder kein Eintrag vorliegt
|
||||
* oder der Eintrag mit den erlaubten Werten übereinstimmt.
|
||||
*/
|
||||
// Für Betriebsrat: nur Beiträge zeigen, die mindestens einer freigegebenen Kategorie zugeordnet sind
|
||||
$brCategoryFilter = '';
|
||||
if ($_kcBrOnly) {
|
||||
$brCatIds = get_all_betriebsrat_accessible_category_ids();
|
||||
if (empty($brCatIds)) {
|
||||
$brCategoryFilter = 'AND 1=0'; // kein Zugriff
|
||||
} else {
|
||||
$brCatIdList = implode(',', $brCatIds);
|
||||
$brCategoryFilter = "AND EXISTS (
|
||||
SELECT 1 FROM knowledgecenter_category_post kcp_br
|
||||
WHERE kcp_br.post_id = kp.id AND kcp_br.category_id IN ($brCatIdList)
|
||||
)";
|
||||
}
|
||||
}
|
||||
|
||||
$sqlPosts = "
|
||||
SELECT
|
||||
kp.id,
|
||||
@@ -232,6 +247,7 @@ $_kcBrOnly = !is_wiki_redakteur() && is_wiki_betriebsrat();
|
||||
AND ( pr.role_id IS NULL OR pr.role_id IN ($allowedRoles) )
|
||||
AND ( pe.einricht_id IS NULL OR pe.einricht_id IN ($allowedEinrichts) )
|
||||
AND ( pfb.fachbereich_id IS NULL OR pfb.fachbereich_id IN ($allowedFachbereiche) )
|
||||
$brCategoryFilter
|
||||
GROUP BY
|
||||
kp.id
|
||||
ORDER BY
|
||||
|
||||
@@ -3,7 +3,24 @@
|
||||
|
||||
// Redirect-URL für den Zurück-Button bzw. Navigation
|
||||
$redirectURL = isset($_GET['redirectURL']) ? $_GET['redirectURL'] : '?action=Category';
|
||||
// Kategorien für das Dropdown holen (state = 1)
|
||||
// Kategorien für das Dropdown holen
|
||||
$_isBrOnly = !is_wiki_redakteur() && is_wiki_betriebsrat();
|
||||
if ($_isBrOnly) {
|
||||
$_brCatIds = get_all_betriebsrat_accessible_category_ids();
|
||||
if (empty($_brCatIds)) {
|
||||
$catsQuery = "SELECT NULL LIMIT 0";
|
||||
} else {
|
||||
$_brCatIdList = implode(',', $_brCatIds);
|
||||
$catsQuery = "
|
||||
SELECT c.id, t.title
|
||||
FROM knowledgecenter_categories_update AS c
|
||||
LEFT JOIN knowledgecenter_category_translations AS t
|
||||
ON t.category_id = c.id AND t.language_id = $languageId
|
||||
WHERE c.id IN ($_brCatIdList)
|
||||
ORDER BY t.title ASC
|
||||
";
|
||||
}
|
||||
} else {
|
||||
$catsQuery = "
|
||||
SELECT c.id, t.title
|
||||
FROM knowledgecenter_categories_update AS c
|
||||
@@ -11,6 +28,7 @@ $catsQuery = "
|
||||
ON t.category_id = c.id AND t.language_id = $languageId
|
||||
ORDER BY t.title ASC
|
||||
";
|
||||
}
|
||||
$catsResult = mysqli_query($GLOBALS['mysql_con'], $catsQuery);
|
||||
$allCategories = [];
|
||||
while ($r = mysqli_fetch_assoc($catsResult)) {
|
||||
@@ -44,9 +62,14 @@ while ($r = mysqli_fetch_assoc($catsResult)) {
|
||||
</div>
|
||||
|
||||
|
||||
<?php
|
||||
$_brCategoryIds = $_isBrOnly ? ($_brCatIds ?? []) : null;
|
||||
$_brCategoryIdsJson = json_encode($_brCategoryIds);
|
||||
?>
|
||||
<script>
|
||||
var myRedirectURL = window.location.href;
|
||||
var debounceTimer;
|
||||
var brCategoryIds = <?= $_brCategoryIdsJson ?>;
|
||||
|
||||
function loadPostList() {
|
||||
var searchQuery = $('#searchQuery').val();
|
||||
@@ -61,7 +84,8 @@ while ($r = mysqli_fetch_assoc($catsResult)) {
|
||||
language_id: '<?= $languageId ?>',
|
||||
redirectURL: myRedirectURL,
|
||||
query: searchQuery,
|
||||
category_id: categoryId // hier mitgeben
|
||||
category_id: categoryId,
|
||||
br_category_ids: brCategoryIds !== null ? JSON.stringify(brCategoryIds) : null
|
||||
},
|
||||
dataType: 'json',
|
||||
beforeSend: function () { $('#overlayLoader').show(); },
|
||||
|
||||
Reference in New Issue
Block a user