forum->categories->getCategories(hidden: false, asTree: true); // Filtering! This really needs cleaning up... foreach($cats as $catId => $category) { $perms = $this->authInfo->getPerms('forum', $category->info); // Check if we're allowed to list this category, separate from viewing for some reason... if(!$perms->check(Perm::F_CATEGORY_LIST)) { unset($cats[$catId]); continue; } $unread = false; // This is not fully recursive, idk why... probably shove this into ForumContext? if($category->info->mayHaveChildren && !$unread) foreach($category->children as $childId => $child) { $childPerms = $this->authInfo->getPerms('forum', $child->info); if(!$childPerms->check(Perm::F_CATEGORY_LIST)) { unset($category->children[$childId]); continue; } $childUnread = false; if($category->info->isListing) { if($child->info->mayHaveChildren) { foreach($child->children as $grandChildId => $grandChild) { $grandChildPerms = $this->authInfo->getPerms('forum', $grandChild->info); if(!$grandChildPerms->check(Perm::F_CATEGORY_LIST)) { unset($child->children[$grandChildId]); continue; } $grandChildUnread = false; if($grandChild->info->mayHaveTopics) { $catIds = [$grandChild->info->id]; foreach($grandChild->childIds as $greatGrandChildId) { $greatGrandChildPerms = $this->authInfo->getPerms('forum', $greatGrandChildId); if($greatGrandChildPerms->check(Perm::F_CATEGORY_LIST)) $catIds[] = $greatGrandChildId; } $grandChildUnread = $this->forum->categories->checkCategoryUnread($catIds, $this->authInfo->userInfo); if($grandChildUnread) $childUnread = true; } $grandChild->perms = $grandChildPerms; $grandChild->unread = $grandChildUnread; } } if($child->info->mayHaveChildren || $child->info->mayHaveTopics) { $catIds = [$child->info->id]; foreach($child->childIds as $grandChildId) { $grandChildPerms = $this->authInfo->getPerms('forum', $grandChildId); if($grandChildPerms->check(Perm::F_CATEGORY_LIST)) $catIds[] = $grandChildId; } try { $lastPostInfo = $this->forum->posts->getPost(categoryInfos: $catIds, getLast: true, deleted: false); } catch(RuntimeException $ex) { $lastPostInfo = null; } if($lastPostInfo !== null) { $child->lastPost = new stdClass; $child->lastPost->info = $lastPostInfo; $child->lastPost->topicInfo = $this->forum->topics->getTopic(postInfo: $lastPostInfo); if($lastPostInfo->userId !== null) { $child->lastPost->user = $this->usersCtx->getUserInfo($lastPostInfo->userId); $child->lastPost->colour = $this->usersCtx->getUserColour($child->lastPost->user); } } } } if($child->info->mayHaveTopics && !$childUnread) { $childUnread = $this->forum->categories->checkCategoryUnread($child->info, $this->authInfo->userInfo); if($childUnread) $unread = true; } $child->perms = $childPerms; $child->unread = $childUnread; } // This is listed second despite being less expensive because the subcategories listed also need to show unread :sob: if($category->info->mayHaveTopics) $unread = $this->forum->categories->checkCategoryUnread($category->info, $this->authInfo->userInfo); // Create virtual root category if we need to list non-listing categories in root if(!$category->info->isListing) { if(!array_key_exists('0', $cats)) { $cats['0'] = $root = new stdClass; $root->info = null; $root->perms = 0; $root->unread = false; $root->colour = null; $root->children = []; } $cats['0']->children[$categoryId] = $category; unset($cats[$categoryId]); if($category->info->mayHaveChildren || $category->info->mayHaveTopics) { $catIds = [$category->info->id]; foreach($category->childIds as $childId) { $childPerms = $this->authInfo->getPerms('forum', $childId); if($childPerms->check(Perm::F_CATEGORY_LIST)) $catIds[] = $childId; } try { $lastPostInfo = $this->forum->posts->getPost(categoryInfos: $catIds, getLast: true, deleted: false); } catch(RuntimeException $ex) { $lastPostInfo = null; } if($lastPostInfo !== null) { $category->lastPost = new stdClass; $category->lastPost->info = $lastPostInfo; $category->lastPost->topicInfo = $this->forum->topics->getTopic(postInfo: $lastPostInfo); if($lastPostInfo->userId !== null) { $category->lastPost->user = $this->usersCtx->getUserInfo($lastPostInfo->userId); $category->lastPost->colour = $this->usersCtx->getUserColour($category->lastPost->user); } } } } $category->perms = $perms; $category->unread = $unread; } return Template::renderRaw('forum.index', [ 'forum_categories' => $cats, 'forum_empty' => empty($cats), 'forum_show_mark_as_read' => $this->authInfo->isLoggedIn, ]); } #[HttpPost('/forum/mark-as-read')] #[UrlFormat('forum-mark-as-read', '/forum/mark-as-read', ['cat' => '', 'rec' => ''])] public function postMarkAsRead(HttpResponseBuilder $response, HttpRequest $request) { if(!$this->authInfo->isLoggedIn) return 401; if(!CSRF::validate($request->getHeaderLine('X-CSRF-token'))) return 403; $response->setHeader('X-CSRF-Token', CSRF::token()); $catId = (string)$request->getParam('cat', FILTER_SANITIZE_NUMBER_INT); $recursive = !empty($request->getParam('rec')); // root category purge must be recursive if($categoryId === '') return 400; if($catId === '') $cats = $this->forum->categories->getCategories(); elseif($recursive) $cats = $this->forum->categories->getCategoryChildren(parentInfo: $catId, includeSelf: true); else try { $cats = [$this->forum->categories->getCategory(categoryId: $catId)]; } catch(RuntimeException $ex) { $cats = []; } if(empty($cats)) { $response->setStatusCode(404); return [ 'error' => [ 'name' => 'forum:category:none', 'text' => "Couldn't find that forum category.", ], ]; } $success = false; foreach($cats as $category) { $perms = $this->authInfo->getPerms('forum', $category); if($perms->check(Perm::F_CATEGORY_LIST)) { $this->forum->categories->updateUserReadCategory($this->authInfo->userInfo, $category); $success = true; } } if(!$success) { $response->setStatusCode(403); return [ 'error' => [ 'name' => 'forum:category:access', 'text' => "You're not allowed to access this forum category.", ], ]; } return 204; } }