mc-cms-namelessmc/modules/Forum/classes/Forum.php
Sam ab325f1e67
Merge commit from fork
Co-authored-by: Sam <samerton@users.noreply.github.com>
2026-04-02 18:11:40 +01:00

897 lines
35 KiB
PHP

<?php
/**
* Forum class
*
* @package Modules\Forum
* @author Samerton
* @version 2.0.0-pr13
* @license MIT
*/
class Forum {
private DB $_db;
private static array $_permission_cache = [];
private static array $_count_cache = [];
public function __construct() {
$this->_db = DB::getInstance();
}
/**
* Get an array of forums a user can access, including topic information
*
* @param array $groups Users groups
* @param int $user_id User ID
* @return array Array of forums a user can access
*/
public function listAllForums(array $groups = [0], int $user_id = 0): array {
if (in_array(0, $groups)) {
$user_id = 0;
}
if (!$user_id) {
$user_id = 0;
}
$groups_in = implode(',', $groups);
// Get a list of parent forums
$parent_forums = $this->_db->query(
<<<SQL
SELECT *
FROM `nl2_forums`
WHERE `parent` = 0
AND `id` IN
(SELECT `forum_id`
FROM nl2_forums_permissions
WHERE `group_id` IN ($groups_in)
AND `view` = 1
)
ORDER BY `forum_order` ASC
SQL
);
$return = [];
if ($parent_forums->count()) {
foreach ($parent_forums->results() as $forum) {
$return[$forum->id]['description'] = Output::getClean($forum->forum_description);
$return[$forum->id]['title'] = Output::getClean($forum->forum_title);
$return[$forum->id]['icon'] = Output::getPurified($forum->icon);
// Get discussion forums
$forums = $this->_db->query(
<<<SQL
SELECT
f.*,
EXISTS (
SELECT p.ID
FROM nl2_forums_permissions p
WHERE p.group_id IN ($groups_in)
AND p.forum_id = f.id
AND p.view_other_topics = 1
) view_other_topics
FROM nl2_forums AS f
WHERE f.parent = ?
AND f.id IN
(SELECT fp.forum_id
FROM nl2_forums_permissions AS fp
WHERE fp.group_id IN ($groups_in)
AND fp.view = 1
)
ORDER BY f.forum_order ASC
SQL,
[$forum->id]
);
if ($forums->count()) {
foreach ($forums->results() as $item) {
$return[$forum->id]['subforums'][$item->id] = $item;
$return[$forum->id]['subforums'][$item->id]->forum_title = Output::getClean($item->forum_title);
$return[$forum->id]['subforums'][$item->id]->forum_description = Output::getClean($item->forum_description);
$return[$forum->id]['subforums'][$item->id]->icon = Output::getPurified($item->icon);
$return[$forum->id]['subforums'][$item->id]->link = URL::build('/forum/view/' . urlencode($item->id) . '-' . $this->titleToURL($item->forum_title));
$return[$forum->id]['subforums'][$item->id]->redirect_to = Output::getClean($item->redirect_url);
// Get latest post from any sub-subforums
$subforums = $this->getAnySubforums($item->id, $groups, 0, true, $user_id);
if ($item->view_other_topics) {
$latest_post = [$item->last_post_date, $item->last_user_posted, $item->last_topic_posted];
} else {
$latest_post = $this->getLatestPostInOwnTopicForum($item->id, $user_id);
}
if (count($subforums)) {
$return[$forum->id]['subforums'][$item->id]->subforums = [];
foreach ($subforums as $subforum) {
if (isset($subforum->last_post_date) && $subforum->last_post_date > $latest_post[0]) {
$latest_post = [$subforum->last_post_date, $subforum->last_user_posted, $subforum->last_topic_posted];
}
$return[$forum->id]['subforums'][$item->id]->subforums[$subforum->id] = new stdClass();
$return[$forum->id]['subforums'][$item->id]->subforums[$subforum->id]->title = $subforum->forum_title;
$return[$forum->id]['subforums'][$item->id]->subforums[$subforum->id]->link = URL::build('/forum/view/' . urlencode($subforum->id) . '-' . $this->titleToURL($subforum->forum_title));
$return[$forum->id]['subforums'][$item->id]->subforums[$subforum->id]->icon = $subforum->icon;
}
}
// Can the user view other topics?
if ($this->canViewOtherTopics($item->id, $groups)) {
$topics = $this->_db->query(
<<<SQL
SELECT COUNT(*) AS `count`
FROM nl2_topics
WHERE
`forum_id` = ?
AND `deleted` = 0
SQL,
[$item->id]
)->first()->count;
$posts = $this->_db->query(
<<<SQL
SELECT COUNT(*) AS `count`
FROM nl2_posts
WHERE `forum_id` = ?
AND `deleted` = 0
SQL,
[$item->id]
)->first()->count;
} else {
$topics = $this->_db->query(
<<<SQL
SELECT COUNT(*) AS `count`
FROM nl2_topics
WHERE `forum_id` = ?
AND (`topic_creator` = ? OR `sticky` = 1)
AND `deleted` = 0
SQL,
[$item->id, $user_id],
)->first()->count;
$posts = $this->_db->query(
<<<SQL
SELECT COUNT(*) AS `count`
FROM nl2_posts
WHERE `topic_id` IN
(SELECT `id`
FROM nl2_topics
WHERE `forum_id` = ?
AND (`topic_creator` = ? OR `sticky` = 1)
)
AND `deleted` = 0
SQL,
[$item->id, $user_id]
)->first()->count;
}
$return[$forum->id]['subforums'][$item->id]->topics = $topics;
$return[$forum->id]['subforums'][$item->id]->posts = $posts;
// Get latest topic info
if ($latest_post[0]) {
$latest_topic = $this->_db->query(
<<<SQL
SELECT t.*,
p.id as pid,
p.post_creator,
p.created
FROM nl2_topics t
RIGHT JOIN nl2_posts p
ON p.id =
(SELECT ps.id
FROM nl2_posts ps
WHERE ps.topic_id = ?
AND ps.deleted = 0
ORDER BY ps.created DESC LIMIT 1
)
WHERE t.id = ?
SQL,
[$latest_post[2], $latest_post[2]]
);
if ($latest_topic->count() && $latest_topic = $latest_topic->first()) {
$return[$forum->id]['subforums'][$item->id]->last_post = $latest_topic;
$return[$forum->id]['subforums'][$item->id]->last_post->title = Output::getClean($latest_topic->topic_title);
$return[$forum->id]['subforums'][$item->id]->last_post->link = URL::build('/forum/topic/' . urlencode($latest_post[2]) . '-' . $this->titleToURL($latest_topic->topic_title), 'pid=' . $latest_topic->pid);
}
}
}
}
}
}
return $return;
}
/**
* Determine if a forum exists (in the context of a specific user)
*
* @param int $forum_id ID of the forum
* @param array $groups Array of groups the user is in
* @return bool Whether the forum exists or not
*/
public function forumExist(int $forum_id, array $groups = [0]): bool {
$exists = $this->_db->get('forums', ['id', $forum_id])->results();
if (count($exists)) {
return $this->hasPermission($forum_id, 'view', $groups);
}
return false;
}
/**
* Determines if any groups have permission to do a certain action on a forum
*
* @param int $forum_id ID of the forum
* @param string $required_permission Required permission
* @param array $groups Array of groups the user is in
* @return bool Whether the groups have permission or not
*/
private function hasPermission(int $forum_id, string $required_permission, array $groups): bool {
$cache_key = 'forum_permissions_' . $forum_id . '_' . $required_permission . '_' . implode('_', $groups);
if (isset(self::$_permission_cache[$cache_key])) {
return true;
}
$permissions = $this->_db->get('forums_permissions', ['forum_id', $forum_id])->results();
foreach ($permissions as $permission) {
if (in_array($permission->group_id, $groups)) {
if ($permission->{$required_permission} == 1) {
self::$_permission_cache[$cache_key] = true;
return true;
}
}
}
return false;
}
public function titleToURL(string $topic = null): string {
return URL::urlSafe($topic ?? '');
}
// Returns true/false depending on whether the current user can view a forum
// Params: $forum_id (integer) - forum id to check, $groups (array) - user groups
public function canViewOtherTopics(int $forum_id, array $groups = [0]): bool {
$cache_key = 'topics_view_' . $forum_id . '_' . implode('_', $groups);
if (isset(self::$_permission_cache[$cache_key])) {
return true;
}
// Does the forum exist?
$exists = $this->_db->get('forums', ['id', $forum_id])->results();
if (count($exists)) {
// Can the user view other topics?
$access = $this->_db->get('forums_permissions', ['forum_id', $forum_id])->results();
foreach ($access as $item) {
if (in_array($item->group_id, $groups)) {
if ($item->view_other_topics == 1) {
self::$_permission_cache[$cache_key] = true;
return true;
}
}
}
}
return false;
}
/**
* Get the newest x topics this user/group can view
*
* @param array $groups Array of groups the user is in
* @param int $user_id User ID
* @param int $limit Limit of topics to return, default 50
* @return array Latest topics
*/
public function getLatestDiscussions(array $groups = [0], int $user_id = 0, int $limit = 50): array {
if (!$user_id) {
$user_id = 0;
}
$all_topics_forums = DB::getInstance()->query('SELECT forum_id FROM nl2_forums_permissions WHERE group_id IN (' . rtrim(implode(',', $groups), ',') . ') AND `view` = 1 AND view_other_topics = 1')->results();
$own_topics_forums = [];
if ($user_id > 0) {
$own_topics_forums = DB::getInstance()->query('SELECT forum_id FROM nl2_forums_permissions WHERE group_id IN (' . rtrim(implode(',', $groups), ',') . ') AND `view` = 1 AND view_other_topics = 0')->results();
}
if (!count($all_topics_forums) && !count($own_topics_forums)) {
return [];
}
$all_topics_forums_string = '';
foreach ($all_topics_forums as $forum) {
$all_topics_forums_string .= $forum->forum_id . ',';
}
$all_topics_forums_string = rtrim($all_topics_forums_string, ',');
if (count($own_topics_forums)) {
$own_topics_forums_string = '';
foreach ($own_topics_forums as $forum) {
$own_topics_forums_string .= $forum->forum_id . ',';
}
$own_topics_forums_string = rtrim($own_topics_forums_string, ',');
return DB::getInstance()->query(
"(SELECT topics.id as id, topics.forum_id as forum_id, topics.topic_title as topic_title, topics.topic_creator as topic_creator, topics.topic_last_user as topic_last_user, topics.topic_date as topic_date, topics.topic_reply_date as topic_reply_date, topics.topic_views as topic_views, topics.locked as locked, topics.sticky as sticky, topics.label as label, topics.deleted as deleted, posts.id as last_post_id FROM nl2_topics topics LEFT JOIN nl2_posts posts ON topics.id = posts.topic_id AND posts.id = (SELECT MAX(id) FROM nl2_posts p WHERE p.topic_id = topics.id AND p.deleted = 0) WHERE topics.deleted = 0 AND topics.forum_id IN ($all_topics_forums_string) ORDER BY topics.topic_reply_date DESC LIMIT $limit)
UNION
(SELECT topics.id as id, topics.forum_id as forum_id, topics.topic_title as topic_title, topics.topic_creator as topic_creator, topics.topic_last_user as topic_last_user, topics.topic_date as topic_date, topics.topic_reply_date as topic_reply_date, topics.topic_views as topic_views, topics.locked as locked, topics.sticky as sticky, topics.label as label, topics.deleted as deleted, posts.id as last_post_id FROM nl2_topics topics LEFT JOIN nl2_posts posts ON topics.id = posts.topic_id AND posts.id = (SELECT MAX(id) FROM nl2_posts p WHERE p.topic_id = topics.id AND p.deleted = 0) WHERE topics.deleted = 0 AND ((topics.forum_id IN ($own_topics_forums_string) AND topics.topic_creator = ?) OR topics.sticky = 1) ORDER BY topics.topic_reply_date DESC LIMIT $limit)
ORDER BY topic_reply_date DESC LIMIT $limit",
[$user_id],
true
)->results();
}
return DB::getInstance()->query(
"SELECT topics.id as id, topics.forum_id as forum_id, topics.topic_title as topic_title, topics.topic_creator as topic_creator, topics.topic_last_user as topic_last_user, topics.topic_date as topic_date, topics.topic_reply_date as topic_reply_date, topics.topic_views as topic_views, topics.locked as locked, topics.sticky as sticky, topics.label as label, topics.deleted as deleted, posts.id as last_post_id
FROM nl2_topics topics
LEFT JOIN nl2_posts posts ON topics.id = posts.topic_id AND posts.id = (SELECT MAX(id) FROM nl2_posts p WHERE p.topic_id = topics.id AND p.deleted = 0)
WHERE topics.deleted = 0 AND topics.forum_id IN ($all_topics_forums_string) ORDER BY topics.topic_reply_date DESC LIMIT $limit",
)->results();
}
/**
* Determine if a topic exists or not.
*
* @param int $topic_id The topic ID
* @return bool Whether the topic exists or not
*/
public function topicExist(int $topic_id): bool {
// Does the topic exist?
$exists = $this->_db->get('topics', ['id', $topic_id])->results();
return count($exists) > 0;
}
/**
* Determine if the groups can view the forum or not.
*
* @param int $forum_id The forum ID
* @param array $groups The user's groups
* @return bool Whether the groups can view the forum or not
*/
public function canViewForum(int $forum_id, array $groups = [0]): bool {
return $this->hasPermission($forum_id, 'view', $groups);
}
/**
* Determine if the groups can post topics in the forum or not.
*
* @param int $forum_id The forum ID
* @param array $groups The user's groups
* @return bool Whether the groups can post topics in the forum or not
*/
public function canPostTopic(int $forum_id, array $groups = [0]): bool {
return $this->hasPermission($forum_id, 'create_topic', $groups);
}
/**
* Determine if the user can view a topic in a forum
*
* @param int $forum_id The forum ID for the topic
* @param int $author_id The topic author ID
* @param bool $is_topic_sticky Whether the topic is sticky or not
* @param ?User $user The user
* @return bool Whether the user can view the topic
*/
public function canViewTopicInForum(int $forum_id, int $author_id, bool $is_topic_sticky, ?User $user): bool {
if ($user) {
$groups = $user->getAllGroupIds();
$userId = $user->data()->id;
} else {
$groups = [0];
$userId = 0;
}
return
$this->canViewForum($forum_id, $groups) &&
($is_topic_sticky || $this->canViewOtherTopics($forum_id, $groups) || $author_id === $userId);
}
/**
* Determine if the groups can post replies in the forum or not.
*
* @param int $forum_id The forum ID
* @param array $groups The user's groups
* @return bool Whether the groups can post replies in the forum or not
*/
public function canPostReply(int $forum_id, array $groups = [0]): bool {
return $this->hasPermission($forum_id, 'create_post', $groups);
}
/**
* Determine if the groups can edit [psts] in the forum or not.
*
* @param int $forum_id The forum ID
* @param array $groups The user's groups
* @return bool Whether the groups can edit posts in the forum or not
*/
public function canEditTopic(int $forum_id, array $groups = [0]): bool {
return $this->hasPermission($forum_id, 'edit_topic', $groups);
}
/**
* Update the database with the new latest forum posts.
*
* @param int $forum_id The forum ID to update
*/
public function updateForumLatestPosts(int $forum_id): void {
$latest_post = $this->_db->query(
<<<SQL
SELECT `created`,
`post_date`,
`post_creator`,
`topic_id`
FROM nl2_posts
WHERE `forum_id` = ?
AND `deleted` = 0
ORDER BY `created` DESC LIMIT 1
SQL,
[$forum_id]
);
if ($latest_post->count() && $latest_post = $latest_post->first()) {
$this->_db->update('forums', $forum_id, [
'last_post_date' => $latest_post->created ?? strtotime($latest_post->post_date),
'last_user_posted' => $latest_post->post_creator,
'last_topic_posted' => $latest_post->topic_id,
]);
} else {
$this->_db->update('forums', $forum_id, [
'last_post_date' => null,
'last_user_posted' => null,
'last_topic_posted' => null,
]);
}
}
/**
* Update the database with the new latest forum topic posts.
*
* @param int $topic_id The topic ID to update
* @param int|null $forum_id The forum ID to update if topic does not exist
*/
public function updateTopicLatestPosts(int $topic_id, ?int $forum_id): void {
$latest_post = $this->_db->query(
<<<SQL
SELECT `created`,
`post_date`,
`post_creator`
FROM nl2_posts
WHERE `topic_id` = ?
AND `deleted` = 0
ORDER BY `created` DESC LIMIT 1
SQL,
[$topic_id]
);
if ($latest_post->count() && $latest_post = $latest_post->first()) {
$this->_db->update('topics', $topic_id, [
'topic_reply_date' => $latest_post->created ?? strtotime($latest_post->post_date),
'topic_last_user' => $latest_post->post_creator,
]);
} else if ($forum_id !== null) {
$this->_db->update('forums', $forum_id, [
'last_post_date' => null,
'last_user_posted' => null,
'last_topic_posted' => null,
]);
}
}
/**
* Get the title of a specific forum.
*
* @param int $forum_id The forum ID to get the title of.
* @return string The forum title.
*/
public function getForumTitle(int $forum_id): string {
$data = $this->_db->get('forums', ['id', $forum_id])->results();
return $data[0]->forum_title;
}
/**
* Get data of a specific post.
*
* @param int $post_id The post ID to data about.
* @return array|false The post data or false on failure.
*/
public function getIndividualPost(int $post_id) {
$data = $this->_db->query(
<<<SQL
SELECT p.post_creator,
p.post_content,
p.post_date,
p.forum_id,
p.topic_id,
t.sticky
FROM nl2_posts p
RIGHT JOIN nl2_topics t
ON p.topic_id = t.id
WHERE p.id = ? AND p.deleted = 0
SQL,
[$post_id]
);
if ($data->count()) {
$data = $data->first();
return [
'creator' => $data->post_creator,
'content' => $data->post_content,
'date' => $data->post_date,
'forum_id' => $data->forum_id,
'topic_id' => $data->topic_id,
'topic_sticky' => $data->sticky,
];
}
return false;
}
/**
* Get the latest news posts to display on homepage.
*
* TODO: can be optimised by including posts in the initial query?
*
* @param int $number The number of posts to get.
* @param array $groups Array containing user's group IDs, default [0] for guests
* @return array The latest news posts.
*/
public function getLatestNews(int $number = 5, array $groups = [0]): array {
$return = []; // Array to return containing news
$labels_cache = []; // Array to contain labels
$groups_in = implode(',', array_map(static fn () => '?', $groups));
$news_items = $this->_db->query(
<<<SQL
SELECT
id,
labels,
topic_creator,
topic_title,
topic_views
FROM nl2_topics
WHERE
forum_id IN (
SELECT
id
FROM nl2_forums
WHERE news = 1
AND id IN (
SELECT p.forum_id
FROM nl2_forums_permissions p
WHERE p.group_id IN ($groups_in)
AND p.view = 1
)
)
AND deleted = 0
ORDER BY topic_date
DESC LIMIT ?
SQL,
[...$groups, $number]
)->results();
foreach ($news_items as $item) {
$news_post = $this->_db->get('posts', ['topic_id', $item->id]);
$posts = $news_post->count();
$news_post = $news_post->first();
if (is_null($news_post->created)) {
$post_date = date(DATE_FORMAT, strtotime($news_post->post_date));
} else {
$post_date = date(DATE_FORMAT, $news_post->created);
}
$labels = [];
if ($item->labels) {
// Get label
$label_ids = explode(',', $item->labels);
if ($label_ids !== false) {
foreach ($label_ids as $label_id) {
if (isset($labels_cache[$label_id])) {
$labels[] = $labels_cache[$label_id];
} else {
$label = $this->_db->get('forums_topic_labels', ['id', $label_id]);
if ($label->count()) {
$label = $label->first();
$label_html = $this->_db->get('forums_labels', ['id', $label->label]);
if ($label_html->count()) {
$label_html = $label_html->first()->html;
$label = str_replace('{x}', Output::getClean($label->name), Output::getPurified($label_html));
} else {
$label = '';
}
} else {
$label = '';
}
$labels_cache[$label_id] = $label;
$labels[] = $label;
}
}
}
}
$post = $news_post->post_content;
$return[] = [
'topic_id' => $item->id,
'topic_date' => $post_date,
'topic_title' => $item->topic_title,
'topic_views' => $item->topic_views,
'author' => $item->topic_creator,
'content' => Text::truncate($post),
'replies' => $posts,
'label' => count($labels) ? $labels[0] : null,
'labels' => $labels
];
}
return $return;
}
/**
* Determine if groups have permission to moderate a forum.
*
* @param int|null $forum_id The forum ID to check.
* @param array $groups The groups to check.
* @return bool Whether the groups can moderate the forum.
*/
public function canModerateForum(int $forum_id = null, array $groups = [0]): bool {
if (!$forum_id || in_array(0, $groups)) {
return false;
}
$cache_key = 'moderate_' . $forum_id . '_' . implode('_', $groups);
if (isset(self::$_permission_cache[$cache_key])) {
return true;
}
$permissions = $this->_db->get('forums_permissions', ['forum_id', $forum_id])->results();
// Check the forum
foreach ($permissions as $permission) {
if (in_array($permission->group_id, $groups)) {
if ($permission->moderate == 1) {
self::$_permission_cache[$cache_key] = true;
return true;
}
}
}
return false;
}
/**
* Get a user's post count
*
* @param int|null $user_id User ID to check
* @return int Number of posts
*/
public function getPostCount(int $user_id = null): int {
if ($user_id) {
if (isset(self::$_count_cache["posts_$user_id"])) {
return self::$_count_cache["posts_$user_id"];
}
$count = $this->_db->query('SELECT COUNT(*) AS c FROM nl2_posts WHERE deleted = 0 AND post_creator = ?', [$user_id])->first()->c;
self::$_count_cache["posts_$user_id"] = $count;
return $count;
}
return 0;
}
/**
* Get a user's topic count
*
* @param int|null $user_id User ID to check
* @return int Number of topics
*/
public function getTopicCount(int $user_id = null): int {
if ($user_id) {
if (isset(self::$_count_cache["topics_$user_id"])) {
return self::$_count_cache["topics_$user_id"];
}
$count = $this->_db->query('SELECT COUNT(*) AS c FROM nl2_topics WHERE deleted = 0 AND topic_creator = ?', [$user_id])->first()->c;
self::$_count_cache["topics_$user_id"] = $count;
return $count;
}
return 0;
}
/**
* Get posts on a specific topic.
*
* @param int|null $tid The topic ID to check.
* @return array|false Array of topics or false on failure.
*/
public function getPosts(int $tid = null) {
if ($tid) {
// Get posts from database
$posts = $this->_db->get('posts', ['topic_id', $tid]);
if ($posts->count()) {
$posts = $posts->results();
// Remove deleted posts
foreach ($posts as $key => $post) {
if ($post->deleted == 1) {
unset($posts[$key]);
}
}
return array_values($posts);
}
}
return false;
}
/**
* Get any subforums at any level for a forum
*
* @param int $forum_id The forum ID
* @param array $groups The user groups
* @param int $depth The depth of the subforums to get
* @param ?bool $onlyOwnTopics Whether to only get forums in which the user can only view their own topics (default false)
* @param ?int $user_id Current user ID (default 0) - only used if $onlyOwnTopics is true
* @return array Subforums at any level for a forum
*/
public function getAnySubforums(
int $forum_id,
array $groups = [0],
int $depth = 0,
?bool $onlyOwnTopics = false,
?int $user_id = 0
): array {
if ($depth == 10) {
return [];
}
$ret = [];
$groups_in = implode(',', $groups);
$subforums_query = $this->_db->query(
<<<SQL
SELECT
f.*,
EXISTS (
SELECT p.ID
FROM nl2_forums_permissions p
WHERE p.group_id IN ($groups_in)
AND p.forum_id = f.id
AND p.view_other_topics = 1
) view_other_topics
FROM nl2_forums f
WHERE f.parent = ?
AND f.id IN
(SELECT sp.forum_id
FROM nl2_forums_permissions sp
WHERE sp.group_id IN ($groups_in)
AND sp.view = 1
)
SQL,
[$forum_id]
);
if (!$subforums_query->count()) {
return $ret;
}
foreach ($subforums_query->results() as $result) {
$to_add = new stdClass();
$to_add->id = $result->id;
$to_add->forum_title = Output::getClean($result->forum_title);
$to_add->icon = Output::getPurified($result->icon);
$to_add->category = false;
// Latest post
if ($onlyOwnTopics && $result->view_other_topics !== 1) {
[
$to_add->last_post_date,
$to_add->last_user_posted,
$to_add->last_topic_posted,
] = $this->getLatestPostInOwnTopicForum($result->id, $user_id);
} else {
$to_add->last_post_date = $result->last_post_date;
$to_add->last_user_posted = $result->last_user_posted;
$to_add->last_topic_posted = $result->last_topic_posted;
}
$ret[] = $to_add;
$subforums = $this->getAnySubforums($result->id, $groups, ++$depth, $onlyOwnTopics, $user_id);
if (count($subforums)) {
foreach ($subforums as $subforum) {
$ret[] = $subforum;
}
}
}
return $ret;
}
/**
* Get an array returned of accessible labels when providing group ids
*
* @param array $labels of label ids
* @param array $user_groups array of a user their group ids
* @return array An array of the ids of the labels the user has access to
*/
public static function getAccessibleLabels(array $labels, array $user_groups): array {
return array_reduce($labels, function(&$prev, $topic_label) use ($user_groups) {
$label = DB::getInstance()->get('forums_topic_labels', ['id', $topic_label])->first();
if ($label) {
$label_group_ids = explode(',', $label->gids);
$hasPerm = array_reduce($user_groups, fn($prev, $group_id) => $prev || in_array($group_id, $label_group_ids));
if ($hasPerm) {
$prev[] = $label->id;
}
}
return $prev;
}, []);
}
/**
* Get banned terms from the Forum module
*
* @return array Array of banned terms
*/
public static function getBannedTerms(): array {
$terms = Settings::get('banned_terms', null, 'forum');
if (!$terms) {
return [];
}
return explode("\n", $terms);
}
/**
* Get the latest post in a "View own topic" forum
* This could be a topic created by the user, or a sticky topic
*
* @param int $forumId
* @param int $userId
* @return array|null Time of latest post, post creator ID, topic ID
*/
private function getLatestPostInOwnTopicForum(int $forumId, int $userId): ?array {
$latest_post = $this->_db->query(
<<<SQL
SELECT
p.topic_id,
p.created,
p.post_date,
p.post_creator
FROM nl2_topics t
LEFT JOIN nl2_posts p
ON p.id = (
SELECT id
FROM nl2_posts sp
WHERE sp.topic_id = t.id
AND sp.deleted = 0
ORDER BY sp.created DESC LIMIT 1
)
WHERE t.forum_id = ?
AND (t.topic_creator = ? OR t.sticky = 1)
ORDER BY p.created, p.post_date DESC LIMIT 1
SQL,
[$forumId, $userId]
);
if ($latest_post->count() && $latest_post = $latest_post->first()) {
return [
$latest_post->created ?? strtotime($latest_post->post_date),
$latest_post->post_creator,
$latest_post->topic_id,
];
}
return null;
}
}