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

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