diff --git a/gazelle.sql b/gazelle.sql
index 40b96a24..f8f2e185 100644
--- a/gazelle.sql
+++ b/gazelle.sql
@@ -964,12 +964,6 @@ CREATE TABLE `stylesheets` (
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
-CREATE TABLE `subscribed_forums` (
- `ForumID` int(10) NOT NULL,
- `UserID` int(10) NOT NULL,
- PRIMARY KEY (`ForumID`,`UserID`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
-
CREATE TABLE `subscribed_users` (
`UserID` int(10) NOT NULL,
`SubscriberID` int(10) NOT NULL,
@@ -1619,6 +1613,12 @@ CREATE TABLE `users_sessions` (
KEY `ActiveAgeKeep` (`Active`,`LastUpdate`,`KeepLogged`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+CREATE TABLE `users_subscribed_forums` (
+ `UserID` int(10) NOT NULL,
+ `ForumID` int(10) NOT NULL,
+ PRIMARY KEY (`UserID`,`ForumID`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+
CREATE TABLE `users_subscriptions` (
`UserID` int(10) NOT NULL,
`TopicID` int(10) NOT NULL,
diff --git a/sections/forums/forum.php b/sections/forums/forum.php
index 5482f2b1..7a4aa75c 100644
--- a/sections/forums/forum.php
+++ b/sections/forums/forum.php
@@ -84,6 +84,11 @@
if (check_forumperm($ForumID, 'Write') && check_forumperm($ForumID, 'Create')) { ?>
New thread
+ } ?>
+ if (!check_user_forum_subscription($UserID, $ForumID)) { ?>
+
Subscribe
+ } else { ?>
+
Unsubscribe
} ?>
Search this forum
diff --git a/sections/forums/functions.php b/sections/forums/functions.php
index 3b8e0bbe..f6de1173 100644
--- a/sections/forums/functions.php
+++ b/sections/forums/functions.php
@@ -23,7 +23,7 @@ function get_thread_info($ThreadID, $Return = true, $SelectiveCache = false, $Ap
if (!$ApiCall) {
error(404);
} else {
- return NULL;
+ return null;
}
}
$ThreadInfo = $DB->next_record(MYSQLI_ASSOC, false);
@@ -139,3 +139,196 @@ function get_forums() {
}
return $Forums;
}
+
+/**
+ * Add a forum subscription for the provided user id
+ *
+ * @param $UserID
+ * @param $ForumID
+ */
+function add_subscribed_forum($UserID, $ForumID) {
+ global $DB;
+
+ $UserID = (int)$DB->escape_str($UserID);
+ $Subscriptions = get_subscribed_forums($UserID);
+ if (!in_array($ForumID, $Subscriptions)) {
+ $Subscriptions[] = $ForumID;
+ $DB->query("INSERT INTO users_subscribed_forums (UserID, ForumID) VALUES ({$UserID}, $ForumID)");
+ cache_forum_subscriptions($UserID, $Subscriptions);
+ }
+
+ // Populate the aggregate forum subscription cache
+ $ForumSubscriptions = get_subscriptions_for_forum($ForumID);
+ if (!in_array($UserID, $ForumSubscriptions)) {
+ $ForumSubscriptions[] = $UserID;
+ cache_aggregate_forum_subscriptions($ForumID, $ForumSubscriptions);
+ }
+}
+
+/**
+ * Remove a forum subscription from the specified user id
+ *
+ * @param $UserID
+ * @param $ForumID
+ */
+function remove_subscribed_forum($UserID, $ForumID) {
+ global $DB;
+
+ $UserID = (int)$DB->escape_str($UserID);
+ $Subscriptions = get_subscribed_forums($UserID);
+ if (($key = array_search($ForumID, $Subscriptions)) !== false) {
+ $DB->query("DELETE FROM users_subscribed_forums WHERE ForumID = $ForumID AND UserID = {$UserID}");
+ unset($Subscriptions[$key]);
+ cache_forum_subscriptions($UserID, $Subscriptions);
+ }
+
+ $ForumSubscriptions = get_subscriptions_for_forum($ForumID);
+ if (($key = array_search($UserID, $ForumSubscriptions)) !== false) {
+ unset($ForumSubscriptions[$key]);
+ cache_aggregate_forum_subscriptions($ForumID, $ForumSubscriptions);
+ }
+}
+
+/**
+ * Get a list of forum subscriptions for the given user id
+ *
+ * @param $UserID
+ *
+ * @return array|int List of forum ids the user has subscribed to
+ */
+function get_subscribed_forums($UserID) {
+ global $Cache, $DB;
+
+ if (!$Subscriptions = $Cache->get_value("forum_subscriptions_{$UserID}")) {
+
+ $UserID = (int)$DB->escape_str($UserID);
+ $DB->query("SELECT * FROM users_subscribed_forums WHERE UserID = $UserID");
+ $ResultSet = $DB->to_array();
+
+ $Subscriptions = array();
+ foreach ($ResultSet as $Subscription) {
+ $Subscriptions[] = $Subscription['ForumID'];
+ }
+
+ cache_forum_subscriptions($UserID, $Subscriptions);
+
+ }
+
+ return $Subscriptions;
+}
+
+/**
+ * Wrapper method to pull the global requirement on $Cache out of above methods which should
+ * enable simpler unit testing
+ *
+ * @param $UserID
+ * @param $Subscriptions
+ */
+function cache_forum_subscriptions($UserID, $Subscriptions) {
+ global $Cache;
+
+ $Cache->set("forum_subscriptions_{$UserID}", $Subscriptions);
+}
+
+/**
+ * Returns true if the user is subscribed to the given forum id; otherwise false
+ *
+ * @param $UserID
+ * @param $ForumID
+ *
+ * @return bool
+ */
+function check_user_forum_subscription($UserID, $ForumID) {
+ $Subscriptions = get_subscribed_forums($UserID);
+ if (in_array($ForumID, $Subscriptions)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/**
+ * Returns a list of users subscribed to the given forum id
+ *
+ * @param $ForumID
+ *
+ * @return array|int List of user ids subscribed to the forum
+ */
+function get_subscriptions_for_forum($ForumID) {
+ global $Cache, $DB;
+
+ if (!$Subscriptions = $Cache->get_value("forum_subscriptions_forum_{$ForumID}")) {
+ $DB->query("SELECT * FROM users_subscribed_forums WHERE ForumID = $ForumID");
+ $ResultSet = $DB->to_array();
+
+ $Subscriptions = array();
+ foreach ($ResultSet as $Subscription) {
+ $Subscriptions[] = $Subscription['UserID'];
+ }
+ cache_aggregate_forum_subscriptions($ForumID, $Subscriptions);
+ } else {
+ $Subscriptions = $Subscriptions;
+ }
+
+ return $Subscriptions;
+}
+
+/**
+ * Wrapper method to pull the global requirement on $Cache out of above methods which should
+ * enable simpler unit testing
+ * @param $ForumID
+ * @param $Subscriptions
+ */
+function cache_aggregate_forum_subscriptions($ForumID, $Subscriptions) {
+ global $Cache;
+
+ $Cache->set("forum_subscriptions_forum_{$ForumID}", $Subscriptions);
+}
+
+/**
+ * Updates the subscriptions_user_* cache entry to add the given topic ID
+ * for the specified user
+ * @param $UserID
+ * @param $TopicID
+ */
+function add_topic_subscription_for_user($UserID, $TopicID) {
+ global $Cache;
+
+ $Subscriptions = get_topic_subscriptions_for_user($UserID);
+ if (!in_array($TopicID, $Subscriptions)) {
+ $Subscriptions[] = $TopicID;
+ }
+
+ cache_topic_subscriptions_for_user($UserID, $Subscriptions);
+}
+
+/**
+ * Returns a list of topic ids the user is subscribed to
+ * @param $UserID
+ *
+ * @return array|int
+ */
+function get_topic_subscriptions_for_user($UserID) {
+ global $Cache, $DB;
+
+ if (!$Subscriptions = $Cache->get_value("subscriptions_user_$UserID")) {
+ $DB->query("SELECT TopicID FROM users_subscriptions WHERE UserID = $UserID");
+ $ResultSet = $DB->to_array();
+
+ $Subscriptions = array();
+ foreach ($ResultSet as $TopicID) {
+ $Subscriptions[] = $TopicID;
+ }
+
+ cache_topic_subscriptions_for_user($UserID, $Subscriptions);
+
+ }
+
+ return $Subscriptions;
+}
+
+function cache_topic_subscriptions_for_user($UserID, $Subscriptions) {
+ global $Cache;
+
+ $Cache->set("subscriptions_user_$UserID", $Subscriptions);
+}
\ No newline at end of file
diff --git a/sections/forums/index.php b/sections/forums/index.php
index 71260d54..af9bd1f0 100644
--- a/sections/forums/index.php
+++ b/sections/forums/index.php
@@ -108,8 +108,8 @@
case 'warn':
require(SERVER_ROOT.'/sections/forums/warn.php');
break;
- case 'forum_subscribe':
- include('subscribe.php');
+ case 'forum_subscription':
+ include('subscription.php');
break;
default:
error(404);
diff --git a/sections/forums/subscribe.php b/sections/forums/subscribe.php
deleted file mode 100644
index 7c471809..00000000
--- a/sections/forums/subscribe.php
+++ /dev/null
@@ -1,14 +0,0 @@
-query("INSERT IGNORE INTO subscribed_forums (ForumID, SubscriberID) VALUES ('$ForumID', '$LoggedUser[ID]')");
-} elseif ($_GET['perform'] == 'remove') {
- $DB->query("DELETE FROM subscribed_forums WHERE ForumID = '$ForumID' AND SubscriberID = '$LoggedUser[ID]'");
-}
-header('Location: forums.php?action=viewforum&forumid=' . $ForumID);
-?>
-
diff --git a/sections/forums/subscription.php b/sections/forums/subscription.php
new file mode 100644
index 00000000..fb5e46b0
--- /dev/null
+++ b/sections/forums/subscription.php
@@ -0,0 +1,16 @@
+
+
diff --git a/sections/forums/take_new_thread.php b/sections/forums/take_new_thread.php
index bdd4e50d..ada36e04 100644
--- a/sections/forums/take_new_thread.php
+++ b/sections/forums/take_new_thread.php
@@ -90,31 +90,28 @@
LastPostTime = '".sqltime()."'
WHERE ID = '$TopicID'");
-if (isset($_POST['subscribe'])) {
- $DB->query("
- INSERT INTO users_subscriptions
- VALUES ($LoggedUser[ID], $TopicID)");
- $Cache->delete_value('subscriptions_user_'.$LoggedUser['ID']);
+// Do a bulk insert into the users_subscriptions table for all users
+// subscribed to this forum
+$Subscribers = get_subscriptions_for_forum($ForumID);
+if (count($Subscribers) > 0) {
+ $SubscribersValueString = '(';
+ $SubscribersValueString .= implode(", $TopicID), (", $Subscribers);
+ $SubscribersValueString .= ", $TopicID)";
+ $DB->query("INSERT INTO users_subscriptions (UserID, TopicID) VALUES $SubscribersValueString");
}
-//auto subscribe
-/*
-if (check_perms('users_mod')) {
+// Loop through all the users that got subscribed to the thread and
+// update the cache entries
+foreach($Subscribers as $Subscriber) {
+ add_topic_subscription_for_user($Subscriber, $TopicID);
+}
+
+if (isset($_POST['subscribe']) && !in_array($LoggedUser['ID'], $Subscribers)) {
$DB->query("
- SELECT SubscriberID
- FROM subscribed_forums
- WHERE ForumID = '$ForumID'
- AND SubscriberID != '$LoggedUser[ID]'");
- while (list($SubscriberID) = $DB->next_record()) {
- $DB->query("INSERT INTO users_subscriptions VALUES ($SubscriberID, $TopicID)");
- // $DB->query("INSERT INTO forums_last_read_topics
- // (UserID, TopicID, PostID) VALUES
- // ('$SubscriberID', '".$TopicID ."', '".db_string($PostID)."')
- // ON DUPLICATE KEY UPDATE PostID='$LastPost'");
- $Cache->delete_value('subscriptions_user_'.$SubscriberID);
- }
+ INSERT INTO users_subscriptions
+ VALUES ($LoggedUser[ID], $TopicID)");
+ add_topic_subscription_for_user($LoggedUser['ID'], $TopicID);
}
-*/
if (empty($_POST['question']) || empty($_POST['answers']) || !check_perms('forums_polls_create')) {
$NoPoll = 1;