Oppaitime'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 11KB

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