get_version("forum_version") < 1) {
$database->create_table("forum_threads", "
id SCORE_AIPK,
sticky BOOLEAN NOT NULL DEFAULT FALSE,
title VARCHAR(255) NOT NULL,
user_id INTEGER NOT NULL,
date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
uptodate TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE RESTRICT
");
$database->execute("CREATE INDEX forum_threads_date_idx ON forum_threads(date)", []);
$database->create_table("forum_posts", "
id SCORE_AIPK,
thread_id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
date TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
message TEXT,
FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE RESTRICT,
FOREIGN KEY (thread_id) REFERENCES forum_threads (id) ON UPDATE CASCADE ON DELETE CASCADE
");
$database->execute("CREATE INDEX forum_posts_date_idx ON forum_posts(date)", []);
$config->set_int("forumTitleSubString", 25);
$config->set_int("forumThreadsPerPage", 15);
$config->set_int("forumPostsPerPage", 15);
$config->set_int("forumMaxCharsPerPost", 512);
$this->set_version("forum_version", 3);
}
if ($this->get_version("forum_version") < 2) {
$database->execute("ALTER TABLE forum_threads ADD FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE RESTRICT");
$database->execute("ALTER TABLE forum_posts ADD FOREIGN KEY (user_id) REFERENCES users(id) ON UPDATE CASCADE ON DELETE RESTRICT");
$this->set_version("forum_version", 2);
}
if ($this->get_version("forum_version") < 3) {
$database->standardise_boolean("forum_threads", "sticky");
$this->set_version("forum_version", 3);
}
}
public function onSetupBuilding(SetupBuildingEvent $event)
{
$sb = $event->panel->create_new_block("Forum");
$sb->add_int_option("forumTitleSubString", "Title max long: ");
$sb->add_int_option("forumThreadsPerPage", "
Threads per page: ");
$sb->add_int_option("forumPostsPerPage", "
Posts per page: ");
$sb->add_int_option("forumMaxCharsPerPost", "
Max chars per post: ");
}
public function onUserPageBuilding(UserPageBuildingEvent $event)
{
global $database;
$threads_count = $database->get_one("SELECT COUNT(*) FROM forum_threads WHERE user_id=:user_id", ['user_id'=>$event->display_user->id]);
$posts_count = $database->get_one("SELECT COUNT(*) FROM forum_posts WHERE user_id=:user_id", ['user_id'=>$event->display_user->id]);
$days_old = ((time() - strtotime($event->display_user->join_date)) / 86400) + 1;
$threads_rate = sprintf("%.1f", ($threads_count / $days_old));
$posts_rate = sprintf("%.1f", ($posts_count / $days_old));
$event->add_stats("Forum threads: $threads_count, $threads_rate per day");
$event->add_stats("Forum posts: $posts_count, $posts_rate per day");
}
public function onPageNavBuilding(PageNavBuildingEvent $event)
{
$event->add_nav_link("forum", new Link('forum/index'), "Forum");
}
public function onPageRequest(PageRequestEvent $event)
{
global $page, $user;
if ($event->page_matches("forum")) {
switch ($event->get_arg(0)) {
case "index":
$this->show_last_threads($page, $event, $user->can(Permissions::FORUM_ADMIN));
if (!$user->is_anonymous()) {
$this->theme->display_new_thread_composer($page);
}
break;
case "view":
$threadID = int_escape($event->get_arg(1));
// $pageNumber = int_escape($event->get_arg(2));
list($errors) = $this->sanity_check_viewed_thread($threadID);
if ($errors!=null) {
$this->theme->display_error(500, "Error", $errors);
break;
}
$this->show_posts($event, $user->can(Permissions::FORUM_ADMIN));
if ($user->can(Permissions::FORUM_ADMIN)) {
$this->theme->add_actions_block($page, $threadID);
}
if (!$user->is_anonymous()) {
$this->theme->display_new_post_composer($page, $threadID);
}
break;
case "new":
global $page;
$this->theme->display_new_thread_composer($page);
break;
case "create":
$redirectTo = "forum/index";
if (!$user->is_anonymous()) {
list($errors) = $this->sanity_check_new_thread();
if ($errors!=null) {
$this->theme->display_error(500, "Error", $errors);
break;
}
$newThreadID = $this->save_new_thread($user);
$this->save_new_post($newThreadID, $user);
$redirectTo = "forum/view/".$newThreadID."/1";
}
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link($redirectTo));
break;
case "delete":
$threadID = int_escape($event->get_arg(1));
$postID = int_escape($event->get_arg(2));
if ($user->can(Permissions::FORUM_ADMIN)) {
$this->delete_post($postID);
}
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("forum/view/".$threadID));
break;
case "nuke":
$threadID = int_escape($event->get_arg(1));
if ($user->can(Permissions::FORUM_ADMIN)) {
$this->delete_thread($threadID);
}
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("forum/index"));
break;
case "answer":
$threadID = int_escape($_POST["threadID"]);
$total_pages = $this->get_total_pages_for_thread($threadID);
if (!$user->is_anonymous()) {
list($errors) = $this->sanity_check_new_post();
if ($errors!=null) {
$this->theme->display_error(500, "Error", $errors);
break;
}
$this->save_new_post($threadID, $user);
}
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("forum/view/".$threadID."/".$total_pages));
break;
default:
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("forum/index"));
//$this->theme->display_error(400, "Invalid action", "You should check forum/index.");
break;
}
}
}
private function get_total_pages_for_thread(int $threadID): int
{
global $database, $config;
$result = $database->get_row("SELECT COUNT(1) AS count FROM forum_posts WHERE thread_id = :thread_id", ['thread_id'=>$threadID]);
return (int)ceil($result["count"] / $config->get_int("forumPostsPerPage"));
}
private function sanity_check_new_thread(): array
{
$errors = null;
if (!array_key_exists("title", $_POST)) {
$errors .= "