BioTorrents.de’s version of Gazelle
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

forums.class.php 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. <?php
  2. class Forums
  3. {
  4. /**
  5. * Get information on a thread.
  6. *
  7. * @param int $ThreadID the thread ID.
  8. * @param boolean $Return indicates whether thread info should be returned.
  9. * @param Boolean $SelectiveCache cache thread info.
  10. * @return array holding thread information.
  11. */
  12. public static function get_thread_info($ThreadID, $Return = true, $SelectiveCache = false)
  13. {
  14. if ((!$ThreadInfo = G::$Cache->get_value('thread_' . $ThreadID . '_info')) || !isset($ThreadInfo['Ranking'])) {
  15. $QueryID = G::$DB->get_query_id();
  16. G::$DB->query("
  17. SELECT
  18. t.Title,
  19. t.ForumID,
  20. t.IsLocked,
  21. t.IsSticky,
  22. COUNT(fp.id) AS Posts,
  23. t.LastPostAuthorID,
  24. ISNULL(p.TopicID) AS NoPoll,
  25. t.StickyPostID,
  26. t.AuthorID as OP,
  27. t.Ranking
  28. FROM forums_topics AS t
  29. JOIN forums_posts AS fp ON fp.TopicID = t.ID
  30. LEFT JOIN forums_polls AS p ON p.TopicID = t.ID
  31. WHERE t.ID = ?
  32. GROUP BY fp.TopicID", $ThreadID);
  33. if (!G::$DB->has_results()) {
  34. G::$DB->set_query_id($QueryID);
  35. return null;
  36. }
  37. $ThreadInfo = G::$DB->next_record(MYSQLI_ASSOC, false);
  38. if ($ThreadInfo['StickyPostID']) {
  39. $ThreadInfo['Posts']--;
  40. G::$DB->query(
  41. "
  42. SELECT
  43. p.ID,
  44. p.AuthorID,
  45. p.AddedTime,
  46. p.Body,
  47. p.EditedUserID,
  48. p.EditedTime,
  49. ed.Username
  50. FROM forums_posts AS p
  51. LEFT JOIN users_main AS ed ON ed.ID = p.EditedUserID
  52. WHERE p.TopicID = ?
  53. AND p.ID = ?",
  54. $ThreadID,
  55. $ThreadInfo['StickyPostID']
  56. );
  57. list($ThreadInfo['StickyPost']) = G::$DB->to_array(false, MYSQLI_ASSOC);
  58. }
  59. G::$DB->set_query_id($QueryID);
  60. if (!$SelectiveCache || !$ThreadInfo['IsLocked'] || $ThreadInfo['IsSticky']) {
  61. G::$Cache->cache_value('thread_' . $ThreadID . '_info', $ThreadInfo, 0);
  62. }
  63. }
  64. if ($Return) {
  65. return $ThreadInfo;
  66. }
  67. }
  68. /**
  69. * Checks whether user has permissions on a forum.
  70. *
  71. * @param int $ForumID the forum ID.
  72. * @param string $Perm the permissision to check, defaults to 'Read'
  73. * @return boolean true if user has permission
  74. */
  75. public static function check_forumperm($ForumID, $Perm = 'Read')
  76. {
  77. $Forums = self::get_forums();
  78. if (isset(G::$LoggedUser['CustomForums'][$ForumID]) && G::$LoggedUser['CustomForums'][$ForumID] == 1) {
  79. return true;
  80. }
  81. if ($ForumID == DONOR_FORUM && Donations::has_donor_forum(G::$LoggedUser['ID'])) {
  82. return true;
  83. }
  84. if ($Forums[$ForumID]['MinClass' . $Perm] > G::$LoggedUser['Class'] && (!isset(G::$LoggedUser['CustomForums'][$ForumID]) || G::$LoggedUser['CustomForums'][$ForumID] == 0)) {
  85. return false;
  86. }
  87. if (isset(G::$LoggedUser['CustomForums'][$ForumID]) && G::$LoggedUser['CustomForums'][$ForumID] == 0) {
  88. return false;
  89. }
  90. return true;
  91. }
  92. /**
  93. * Gets basic info on a forum.
  94. *
  95. * @param int $ForumID the forum ID.
  96. */
  97. public static function get_forum_info($ForumID)
  98. {
  99. $Forum = G::$Cache->get_value("ForumInfo_$ForumID");
  100. if (!$Forum) {
  101. $QueryID = G::$DB->get_query_id();
  102. G::$DB->query("
  103. SELECT
  104. Name,
  105. MinClassRead,
  106. MinClassWrite,
  107. MinClassCreate,
  108. COUNT(forums_topics.ID) AS Topics
  109. FROM forums
  110. LEFT JOIN forums_topics ON forums_topics.ForumID = forums.ID
  111. WHERE forums.ID = ?
  112. GROUP BY ForumID", $ForumID);
  113. if (!G::$DB->has_results()) {
  114. return false;
  115. }
  116. // Makes an array, with $Forum['Name'], etc.
  117. $Forum = G::$DB->next_record(MYSQLI_ASSOC);
  118. G::$DB->set_query_id($QueryID);
  119. G::$Cache->cache_value("ForumInfo_$ForumID", $Forum, 86400);
  120. }
  121. return $Forum;
  122. }
  123. /**
  124. * Get the forum categories
  125. * @return array ForumCategoryID => Name
  126. */
  127. public static function get_forum_categories()
  128. {
  129. $ForumCats = G::$Cache->get_value('forums_categories');
  130. if ($ForumCats === false) {
  131. $QueryID = G::$DB->get_query_id();
  132. G::$DB->query("
  133. SELECT ID, Name
  134. FROM forums_categories");
  135. $ForumCats = [];
  136. while (list($ID, $Name) = G::$DB->next_record()) {
  137. $ForumCats[$ID] = $Name;
  138. }
  139. G::$DB->set_query_id($QueryID);
  140. G::$Cache->cache_value('forums_categories', $ForumCats, 0);
  141. }
  142. return $ForumCats;
  143. }
  144. /**
  145. * Get the forums
  146. * @return array ForumID => (various information about the forum)
  147. */
  148. public static function get_forums()
  149. {
  150. if (!$Forums = G::$Cache->get_value('forums_list')) {
  151. $QueryID = G::$DB->get_query_id();
  152. G::$DB->query("
  153. SELECT
  154. f.ID,
  155. f.CategoryID,
  156. f.Name,
  157. f.Description,
  158. f.MinClassRead AS MinClassRead,
  159. f.MinClassWrite AS MinClassWrite,
  160. f.MinClassCreate AS MinClassCreate,
  161. f.NumTopics,
  162. f.NumPosts,
  163. f.LastPostID,
  164. f.LastPostAuthorID,
  165. f.LastPostTopicID,
  166. f.LastPostTime,
  167. 0 AS SpecificRules,
  168. t.Title,
  169. t.IsLocked AS Locked,
  170. t.IsSticky AS Sticky
  171. FROM forums AS f
  172. JOIN forums_categories AS fc ON fc.ID = f.CategoryID
  173. LEFT JOIN forums_topics AS t ON t.ID = f.LastPostTopicID
  174. GROUP BY f.ID
  175. ORDER BY fc.Sort, fc.Name, f.CategoryID, f.Sort");
  176. $Forums = G::$DB->to_array('ID', MYSQLI_ASSOC, false);
  177. G::$DB->query("
  178. SELECT ForumID, ThreadID
  179. FROM forums_specific_rules");
  180. $SpecificRules = [];
  181. while (list($ForumID, $ThreadID) = G::$DB->next_record(MYSQLI_NUM, false)) {
  182. $SpecificRules[$ForumID][] = $ThreadID;
  183. }
  184. G::$DB->set_query_id($QueryID);
  185. foreach ($Forums as $ForumID => &$Forum) {
  186. if (isset($SpecificRules[$ForumID])) {
  187. $Forum['SpecificRules'] = $SpecificRules[$ForumID];
  188. } else {
  189. $Forum['SpecificRules'] = [];
  190. }
  191. }
  192. G::$Cache->cache_value('forums_list', $Forums, 0);
  193. }
  194. return $Forums;
  195. }
  196. /**
  197. * Get all forums that the current user has special access to ("Extra forums" in the profile)
  198. * @return array Array of ForumIDs
  199. */
  200. public static function get_permitted_forums()
  201. {
  202. if (isset(G::$LoggedUser['CustomForums'])) {
  203. return (array)array_keys(G::$LoggedUser['CustomForums'], 1);
  204. } else {
  205. return [];
  206. }
  207. }
  208. /**
  209. * Get all forums that the current user does not have access to ("Restricted forums" in the profile)
  210. * @return array Array of ForumIDs
  211. */
  212. public static function get_restricted_forums()
  213. {
  214. if (isset(G::$LoggedUser['CustomForums'])) {
  215. return (array)array_keys(G::$LoggedUser['CustomForums'], 0);
  216. } else {
  217. return [];
  218. }
  219. }
  220. /**
  221. * Get the last read posts for the current user
  222. * @param array $Forums Array of forums as returned by self::get_forums()
  223. * @return array TopicID => array(TopicID, PostID, Page) where PostID is the ID of the last read post and Page is the page on which that post is
  224. */
  225. public static function get_last_read($Forums)
  226. {
  227. if (isset(G::$LoggedUser['PostsPerPage'])) {
  228. $PerPage = G::$LoggedUser['PostsPerPage'];
  229. } else {
  230. $PerPage = POSTS_PER_PAGE;
  231. }
  232. $TopicIDs = [];
  233. foreach ($Forums as $Forum) {
  234. if (!empty($Forum['LastPostTopicID'])) {
  235. $TopicIDs[] = $Forum['LastPostTopicID'];
  236. }
  237. }
  238. if (!empty($TopicIDs)) {
  239. $QueryID = G::$DB->get_query_id();
  240. G::$DB->query("
  241. SELECT
  242. l.TopicID,
  243. l.PostID,
  244. CEIL(
  245. (
  246. SELECT
  247. COUNT(p.ID)
  248. FROM forums_posts AS p
  249. WHERE p.TopicID = l.TopicID
  250. AND p.ID <= l.PostID
  251. ) / ?
  252. ) AS Page
  253. FROM forums_last_read_topics AS l
  254. WHERE l.TopicID IN(" . implode(',', $TopicIDs) . ") AND
  255. l.UserID = ?", $PerPage, G::$LoggedUser['ID']);
  256. $LastRead = G::$DB->to_array('TopicID', MYSQLI_ASSOC);
  257. G::$DB->set_query_id($QueryID);
  258. } else {
  259. $LastRead = [];
  260. }
  261. return $LastRead;
  262. }
  263. /**
  264. * Add a note to a topic.
  265. * @param int $TopicID
  266. * @param string $Note
  267. * @param int|null $UserID
  268. * @return boolean
  269. */
  270. public static function add_topic_note($TopicID, $Note, $UserID = null)
  271. {
  272. if ($UserID === null) {
  273. $UserID = G::$LoggedUser['ID'];
  274. }
  275. $QueryID = G::$DB->get_query_id();
  276. G::$DB->query("
  277. INSERT INTO forums_topic_notes
  278. (TopicID, AuthorID, AddedTime, Body)
  279. VALUES
  280. (?, ?, NOW(), ?)", $TopicID, $UserID, $Note);
  281. G::$DB->set_query_id($QueryID);
  282. return (bool)G::$DB->affected_rows();
  283. }
  284. /**
  285. * Determine if a thread is unread
  286. * @param bool $Locked
  287. * @param bool $Sticky
  288. * @param int $LastPostID
  289. * @param array $LastRead An array as returned by self::get_last_read
  290. * @param int $LastTopicID TopicID of the thread where the most recent post was made
  291. * @param string $LastTime Datetime of the last post
  292. * @return bool
  293. */
  294. public static function is_unread($Locked, $Sticky, $LastPostID, $LastRead, $LastTopicID, $LastTime)
  295. {
  296. return (!$Locked || $Sticky) && $LastPostID != 0 && ((empty($LastRead[$LastTopicID]) || $LastRead[$LastTopicID]['PostID'] < $LastPostID) && strtotime($LastTime) > G::$LoggedUser['CatchupTime']);
  297. }
  298. /**
  299. * Create the part of WHERE in the sql queries used to filter forums for a
  300. * specific user (MinClassRead, restricted and permitted forums).
  301. * @return string
  302. */
  303. public static function user_forums_sql()
  304. {
  305. // I couldn't come up with a good name, please rename this if you can. -- Y
  306. $RestrictedForums = self::get_restricted_forums();
  307. $PermittedForums = self::get_permitted_forums();
  308. if (Donations::has_donor_forum(G::$LoggedUser['ID']) && !in_array(DONOR_FORUM, $PermittedForums)) {
  309. $PermittedForums[] = DONOR_FORUM;
  310. }
  311. $SQL = "((f.MinClassRead <= '" . G::$LoggedUser['Class'] . "'";
  312. if (count($RestrictedForums)) {
  313. $SQL .= " AND f.ID NOT IN ('" . implode("', '", $RestrictedForums) . "')";
  314. }
  315. $SQL .= ')';
  316. if (count($PermittedForums)) {
  317. $SQL .= " OR f.ID IN ('" . implode("', '", $PermittedForums) . "')";
  318. }
  319. $SQL .= ')';
  320. return $SQL;
  321. }
  322. }