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.

take_reply.php 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. <?
  2. authorize();
  3. //TODO: Remove all the stupid queries that could get their information just as easily from the cache
  4. /*********************************************************************\
  5. //--------------Take Post--------------------------------------------//
  6. This page takes a forum post submission, validates it, and
  7. enters it into the database. The user is then redirected to their
  8. post.
  9. $_POST['action'] is what the user is trying to do. It can be:
  10. 'reply' if the user is replying to a thread
  11. It will be accompanied with:
  12. $_POST['thread']
  13. $_POST['body']
  14. \*********************************************************************/
  15. // If you're not sending anything, go back
  16. if ($_POST['body'] === '' || !isset($_POST['body'])) {
  17. header('Location: '.$_SERVER['HTTP_REFERER']);
  18. die();
  19. }
  20. if (!empty($LoggedUser['DisablePosting'])) {
  21. error('Your posting privileges have been removed.');
  22. }
  23. $PerPage = $LoggedUser['PostsPerPage'] ?? POSTS_PER_PAGE;
  24. $Body = $_POST['body'];
  25. $TopicID = $_POST['thread'];
  26. $ThreadInfo = Forums::get_thread_info($TopicID);
  27. if ($ThreadInfo === null) {
  28. error(404);
  29. }
  30. $ForumID = $ThreadInfo['ForumID'];
  31. $SQLTime = sqltime();
  32. if (!Forums::check_forumperm($ForumID)) {
  33. error(403);
  34. }
  35. if (!Forums::check_forumperm($ForumID, 'Write') || $LoggedUser['DisablePosting'] || $ThreadInfo['IsLocked'] == '1' && !check_perms('site_moderate_forums')) {
  36. error(403);
  37. }
  38. if (strlen($Body) > 500000) {
  39. error('Your post is too large');
  40. }
  41. if (isset($_POST['subscribe']) && Subscriptions::has_subscribed($TopicID) === false) {
  42. Subscriptions::subscribe($TopicID);
  43. }
  44. //Now lets handle the special case of merging posts, we can skip bumping the thread and all that fun
  45. if ($ThreadInfo['LastPostAuthorID'] == $LoggedUser['ID'] && ((!check_perms('site_forums_double_post') && !in_array($ForumID, FORUMS_TO_ALLOW_DOUBLE_POST)) || isset($_POST['merge']))) {
  46. //Get the id for this post in the database to append
  47. $DB->query("
  48. SELECT ID, Body
  49. FROM forums_posts
  50. WHERE TopicID = ?
  51. AND AuthorID = ?
  52. ORDER BY ID DESC
  53. LIMIT 1", $TopicID, $LoggedUser['ID']);
  54. list($PostID, $OldBody) = $DB->next_record(MYSQLI_NUM, false);
  55. //Edit the post
  56. $DB->query("
  57. UPDATE forums_posts
  58. SET
  59. Body = CONCAT(Body, '\n\n', ?),
  60. EditedUserID = ?,
  61. EditedTime = ?
  62. WHERE ID = ?", $Body, $LoggedUser['ID'], $SQLTime, $PostID);
  63. //Store edit history
  64. $DB->query("
  65. INSERT INTO comments_edits
  66. (Page, PostID, EditUser, EditTime, Body)
  67. VALUES
  68. ('forums', ?, ?, ?, ?)", $PostID, $LoggedUser['ID'], $SQLTime, $OldBody);
  69. $Cache->delete_value("forums_edits_$PostID");
  70. //Get the catalogue it is in
  71. $CatalogueID = floor((POSTS_PER_PAGE * ceil($ThreadInfo['Posts'] / POSTS_PER_PAGE) - POSTS_PER_PAGE) / THREAD_CATALOGUE);
  72. //Get the catalogue value for the post we're appending to
  73. if ($ThreadInfo['Posts'] % THREAD_CATALOGUE == 0) {
  74. $Key = THREAD_CATALOGUE - 1;
  75. } else {
  76. $Key = ($ThreadInfo['Posts'] % THREAD_CATALOGUE) - 1;
  77. }
  78. if ($ThreadInfo['StickyPostID'] == $PostID) {
  79. $ThreadInfo['StickyPost']['Body'] .= "\n\n".$Body;
  80. $ThreadInfo['StickyPost']['EditedUserID'] = $LoggedUser['ID'];
  81. $ThreadInfo['StickyPost']['EditedTime'] = $SQLTime;
  82. $Cache->cache_value("thread_$TopicID".'_info', $ThreadInfo, 0);
  83. }
  84. //Edit the post in the cache
  85. $Cache->begin_transaction("thread_$TopicID"."_catalogue_$CatalogueID");
  86. $Cache->update_row($Key, [
  87. 'Body' => $Cache->MemcacheDBArray[$Key]['Body']."\n\n$Body",
  88. 'EditedUserID' => $LoggedUser['ID'],
  89. 'EditedTime' => $SQLTime,
  90. 'Username' => $LoggedUser['Username']
  91. ]);
  92. $Cache->commit_transaction(0);
  93. //Now we're dealing with a normal post
  94. } else {
  95. //Insert the post into the posts database
  96. $DB->query("
  97. INSERT INTO forums_posts (TopicID, AuthorID, AddedTime, Body)
  98. VALUES (?, ?, ?, ?)",
  99. $TopicID, $LoggedUser['ID'], $SQLTime, $Body);
  100. $PostID = $DB->inserted_id();
  101. //This updates the root index
  102. $DB->query("
  103. UPDATE forums
  104. SET
  105. NumPosts = NumPosts + 1,
  106. LastPostID = ?,
  107. LastPostAuthorID = ?,
  108. LastPostTopicID = ?,
  109. LastPostTime = ?
  110. WHERE ID = ?", $PostID, $LoggedUser['ID'], $TopicID, $SQLTime, $ForumID);
  111. //Update the topic
  112. $DB->query("
  113. UPDATE forums_topics
  114. SET
  115. NumPosts = NumPosts + 1,
  116. LastPostID = ?,
  117. LastPostAuthorID = ?,
  118. LastPostTime = ?
  119. WHERE ID = ?", $PostID, $LoggedUser['ID'], $SQLTime, $TopicID);
  120. // if cache exists modify it, if not, then it will be correct when selected next, and we can skip this block
  121. if ($Forum = $Cache->get_value("forums_$ForumID")) {
  122. list($Forum,,,$Stickies) = $Forum;
  123. // if the topic is already on this page
  124. if (array_key_exists($TopicID, $Forum)) {
  125. $Thread = $Forum[$TopicID];
  126. unset($Forum[$TopicID]);
  127. $Thread['NumPosts'] = $Thread['NumPosts'] + 1; // Increment post count
  128. $Thread['LastPostID'] = $PostID; // Set post ID for read/unread
  129. $Thread['LastPostTime'] = $SQLTime; // Time of last post
  130. $Thread['LastPostAuthorID'] = $LoggedUser['ID']; // Last poster ID
  131. $Part2 = [$TopicID => $Thread]; // Bumped thread
  132. // if we're bumping from an older page
  133. } else {
  134. // Remove the last thread from the index
  135. if (count($Forum) == TOPICS_PER_PAGE && $Stickies < TOPICS_PER_PAGE) {
  136. array_pop($Forum);
  137. }
  138. // Never know if we get a page full of stickies...
  139. if ($Stickies < TOPICS_PER_PAGE || $ThreadInfo['IsSticky'] == 1) {
  140. //Pull the data for the thread we're bumping
  141. $DB->query("
  142. SELECT
  143. f.AuthorID,
  144. f.IsLocked,
  145. f.IsSticky,
  146. f.NumPosts,
  147. ISNULL(p.TopicID) AS NoPoll
  148. FROM forums_topics AS f
  149. LEFT JOIN forums_polls AS p ON p.TopicID = f.ID
  150. WHERE f.ID = ?", $TopicID);
  151. list($AuthorID, $IsLocked, $IsSticky, $NumPosts, $NoPoll) = $DB->next_record();
  152. $Part2 = [
  153. $TopicID => [
  154. 'ID' => $TopicID,
  155. 'Title' => $ThreadInfo['Title'],
  156. 'AuthorID' => $AuthorID,
  157. 'IsLocked' => $IsLocked,
  158. 'IsSticky' => $IsSticky,
  159. 'NumPosts' => $NumPosts,
  160. 'LastPostID' => $PostID,
  161. 'LastPostTime' => $SQLTime,
  162. 'LastPostAuthorID' => $LoggedUser['ID'],
  163. 'NoPoll' => $NoPoll
  164. ]
  165. ]; //Bumped
  166. } else {
  167. $Part2 = [];
  168. }
  169. }
  170. if ($Stickies > 0) {
  171. $Part1 = array_slice($Forum, 0, $Stickies, true); //Stickies
  172. $Part3 = array_slice($Forum, $Stickies, TOPICS_PER_PAGE - $Stickies - 1, true); //Rest of page
  173. } else {
  174. $Part1 = [];
  175. $Part3 = $Forum;
  176. }
  177. if (is_null($Part1)) {
  178. $Part1 = [];
  179. }
  180. if (is_null($Part3)) {
  181. $Part3 = [];
  182. }
  183. if ($ThreadInfo['IsSticky'] == 1) {
  184. $Forum = $Part2 + $Part1 + $Part3; //Merge it
  185. } else {
  186. $Forum = $Part1 + $Part2 + $Part3; //Merge it
  187. }
  188. $Cache->cache_value("forums_$ForumID", [$Forum, '', 0, $Stickies], 0);
  189. //Update the forum root
  190. $Cache->begin_transaction('forums_list');
  191. $Cache->update_row($ForumID, [
  192. 'NumPosts' => '+1',
  193. 'LastPostID' => $PostID,
  194. 'LastPostAuthorID' => $LoggedUser['ID'],
  195. 'LastPostTopicID' => $TopicID,
  196. 'LastPostTime' => $SQLTime,
  197. 'Title' => $ThreadInfo['Title'],
  198. 'IsLocked' => $ThreadInfo['IsLocked'],
  199. 'IsSticky' => $ThreadInfo['IsSticky']
  200. ]);
  201. $Cache->commit_transaction(0);
  202. } else {
  203. //If there's no cache, we have no data, and if there's no data
  204. $Cache->delete_value('forums_list');
  205. }
  206. //This calculates the block of 500 posts that this one will fall under
  207. $CatalogueID = floor((POSTS_PER_PAGE * ceil($ThreadInfo['Posts'] / POSTS_PER_PAGE) - POSTS_PER_PAGE) / THREAD_CATALOGUE);
  208. //Insert the post into the thread catalogue (block of 500 posts)
  209. $Cache->begin_transaction("thread_$TopicID"."_catalogue_$CatalogueID");
  210. $Cache->insert('', [
  211. 'ID' => $PostID,
  212. 'AuthorID' => $LoggedUser['ID'],
  213. 'AddedTime' => $SQLTime,
  214. 'Body' => $Body,
  215. 'EditedUserID' => 0,
  216. 'EditedTime' => NULL,
  217. 'Username' => $LoggedUser['Username'] //TODO: Remove, it's never used?
  218. ]);
  219. $Cache->commit_transaction(0);
  220. //Update the thread info
  221. $Cache->begin_transaction("thread_$TopicID".'_info');
  222. $Cache->update_row(false, ['Posts' => '+1', 'LastPostAuthorID' => $LoggedUser['ID']]);
  223. $Cache->commit_transaction(0);
  224. //Increment this now to make sure we redirect to the correct page
  225. $ThreadInfo['Posts']++;
  226. //Award a badge if necessary
  227. $DB->query("
  228. SELECT COUNT(ID)
  229. FROM forums_posts
  230. WHERE AuthorID = '$LoggedUser[ID]'");
  231. list($UserPosts) = $DB->next_record(MYSQLI_NUM, false);
  232. foreach (AUTOMATED_BADGE_IDS['Posts'] AS $Count => $Badge) {
  233. if ((int) $UserPosts >= $Count) {
  234. $Success = Badges::award_badge($LoggedUser['ID'], $Badge);
  235. if ($Success) {
  236. Misc::send_pm($LoggedUser['ID'], 0, 'You have received a badge!', "You have received a badge for making ".$Count." forum posts.\n\nIt can be enabled from your user settings.");
  237. }
  238. }
  239. }
  240. }
  241. Subscriptions::flush_subscriptions('forums', $TopicID);
  242. Subscriptions::quote_notify($Body, $PostID, 'forums', $TopicID);
  243. header("Location: forums.php?action=viewthread&threadid=$TopicID&page=".ceil($ThreadInfo['Posts'] / $PerPage));
  244. die();