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 13KB

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