PageRenderTime 70ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/moderate.php

https://github.com/gencer/fluxbb
PHP | 1331 lines | 926 code | 320 blank | 85 comment | 151 complexity | ecbeb8b0322d5a7161201182d22f343c MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. /**
  3. * Copyright (C) 2008-2012 FluxBB
  4. * based on code by Rickard Andersson copyright (C) 2002-2008 PunBB
  5. * License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher
  6. */
  7. define('PUN_ROOT', dirname(__FILE__).'/');
  8. require PUN_ROOT.'include/common.php';
  9. // This particular function doesn't require forum-based moderator access. It can be used
  10. // by all moderators and admins
  11. if (isset($_GET['get_host']))
  12. {
  13. if (!$pun_user['is_admmod'])
  14. message($lang->t('No permission'));
  15. // Is get_host an IP address or a post ID?
  16. if (@preg_match('%^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$%', $_GET['get_host']) || @preg_match('%^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b)\.){3}(\b((25[0-5])|(1\d{2})|(2[0-4]\d)|(\d{1,2}))\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))$%', $_GET['get_host']))
  17. $ip = $_GET['get_host'];
  18. else
  19. {
  20. $get_host = intval($_GET['get_host']);
  21. if ($get_host < 1)
  22. message($lang->t('Bad request'));
  23. $query = $db->select(array('poster_ip' => 'p.poster_ip'), 'posts AS p');
  24. $query->where = 'id = :pid';
  25. $params = array(':pid' => $get_host);
  26. $result = $query->run($params);
  27. if (empty($result))
  28. message($lang->t('Bad request'));
  29. $ip = $result[0]['poster_ip'];
  30. unset ($result, $query, $params);
  31. }
  32. // Load the misc.php language file
  33. $lang->load('misc');
  34. message($lang->t('Host info 1', $ip).'<br />'.$lang->t('Host info 2', @gethostbyaddr($ip)).'<br /><br /><a href="admin_users.php?show_users='.$ip.'">'.$lang->t('Show more users').'</a>');
  35. }
  36. // All other functions require moderator/admin access
  37. $fid = isset($_GET['fid']) ? intval($_GET['fid']) : 0;
  38. if ($fid < 1)
  39. message($lang->t('Bad request'));
  40. $query = $db->select(array('moderators' => 'f.moderators'), 'forums AS f');
  41. $query->where = 'f.id = :forum_id';
  42. $params = array(':forum_id' => $fid);
  43. $result = $query->run($params);
  44. $mods_array = empty($result[0]['moderators']) ? array() : unserialize($result[0]['moderators']);
  45. unset ($result, $query, $params);
  46. if ($pun_user['g_id'] != PUN_ADMIN && ($pun_user['g_moderator'] == '0' || !array_key_exists($pun_user['username'], $mods_array)))
  47. message($lang->t('No permission'));
  48. // Get topic/forum tracking data
  49. if (!$pun_user['is_guest'])
  50. $tracked_topics = get_tracked_topics();
  51. // Load the misc.php language file
  52. $lang->load('misc');
  53. // All other topic moderation features require a topic ID in GET
  54. if (isset($_GET['tid']))
  55. {
  56. $tid = intval($_GET['tid']);
  57. if ($tid < 1)
  58. message($lang->t('Bad request'));
  59. // Fetch some info about the topic
  60. $query = $db->select(array('subject' => 't.subject', 'num_replies' => 't.num_replies', 'first_post_id' => 't.first_post_id', 'forum_id' => 'f.id AS forum_id', 'forum_name' => 'forum_name'), 'topics AS t');
  61. $query->innerJoin('f', 'forums AS f', 'f.id = t.forum_id');
  62. $query->leftJoin('fp', 'forum_perms AS fp', 'fp.forum_id = f.id AND fp.group_id = :group_id');
  63. $query->where = '(fp.read_forum IS NULL OR fp.read_forum = 1) AND f.id = :forum_id AND t.id = :topic_id AND t.moved_to IS NULL';
  64. $params = array(':group_id' => $pun_user['g_id'], ':forum_id' => $fid, ':topic_id' => $tid);
  65. $result = $query->run($params);
  66. if (empty($result))
  67. message($lang->t('Bad request'));
  68. $cur_topic = $result[0];
  69. unset ($result, $query, $params);
  70. // Delete one or more posts
  71. if (isset($_POST['delete_posts']) || isset($_POST['delete_posts_comply']))
  72. {
  73. if (isset($_POST['delete_posts_comply']))
  74. {
  75. confirm_referrer('moderate.php');
  76. if (@preg_match('%[^0-9,]%', $_POST['posts']))
  77. message($lang->t('Bad request'));
  78. $posts = explode(',', $_POST['posts']);
  79. if (empty($posts))
  80. message($lang->t('No posts selected'));
  81. // How many posts did we just delete?
  82. $num_posts_deleted = count($posts);
  83. // Verify that the post IDs are valid
  84. $query = $db->select(array('num_posts' => 'COUNT(p.id) AS num_posts'), 'posts AS p');
  85. $query->where = 'p.id IN :pids AND p.topic_id = :topic_id';
  86. $params = array(':pids' => $posts, ':topic_id' => $tid);
  87. $result = $query->run($params);
  88. if ($result[0]['num_posts'] != $num_posts_deleted)
  89. message($lang->t('Bad request'));
  90. unset ($result, $query, $params);
  91. // Delete the posts
  92. $query = $db->delete('posts');
  93. $query->where = 'id IN :pids';
  94. $params = array(':pids' => $posts);
  95. $query->run($params);
  96. unset ($query, $params);
  97. require PUN_ROOT.'include/search_idx.php';
  98. strip_search_index($posts);
  99. // Get last_post, last_post_id, and last_poster for the topic after deletion
  100. $query = $db->select(array('id' => 'p.id', 'poster' => 'p.poster', 'posted' => 'p.posted'), 'posts AS p');
  101. $query->where = 'p.topic_id = :topic_id';
  102. $query->order = array('id' => 'p.id DESC');
  103. $query->limit = 1;
  104. $params = array(':topic_id' => $tid);
  105. $result = $query->run($params);
  106. $last_post = $result[0];
  107. unset ($result, $query, $params);
  108. // Update the topic
  109. $query = $db->update(array('last_post' => ':last_post', 'last_post_id' => ':last_post_id', 'last_poster' => ':last_poster', 'num_replies' => 'num_replies - :num_deleted'), 'topics');
  110. $query->where = 'id = :topic_id';
  111. $params = array(':last_post' => $last_post['posted'], ':last_post_id' => $last_post['id'], ':last_poster' => $last_post['poster'], ':num_deleted' => $num_posts_deleted, ':topic_id' => $tid);
  112. $query->run($params);
  113. unset ($query, $params);
  114. update_forum($fid);
  115. redirect('viewtopic.php?id='.$tid, $lang->t('Delete posts redirect'));
  116. }
  117. $posts = isset($_POST['posts']) ? $_POST['posts'] : array();
  118. if (empty($posts))
  119. message($lang->t('No posts selected'));
  120. $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang->t('Moderate'));
  121. define('PUN_ACTIVE_PAGE', 'index');
  122. require PUN_ROOT.'header.php';
  123. ?>
  124. <div class="blockform">
  125. <h2><span><?php echo $lang->t('Delete posts') ?></span></h2>
  126. <div class="box">
  127. <form method="post" action="moderate.php?fid=<?php echo $fid ?>&amp;tid=<?php echo $tid ?>">
  128. <div class="inform">
  129. <fieldset>
  130. <legend><?php echo $lang->t('Confirm delete legend') ?></legend>
  131. <div class="infldset">
  132. <input type="hidden" name="posts" value="<?php echo implode(',', array_map('intval', array_keys($posts))) ?>" />
  133. <p><?php echo $lang->t('Delete posts comply') ?></p>
  134. </div>
  135. </fieldset>
  136. </div>
  137. <p class="buttons"><input type="submit" name="delete_posts_comply" value="<?php echo $lang->t('Delete') ?>" /> <a href="javascript:history.go(-1)"><?php echo $lang->t('Go back') ?></a></p>
  138. </form>
  139. </div>
  140. </div>
  141. <?php
  142. require PUN_ROOT.'footer.php';
  143. }
  144. else if (isset($_POST['split_posts']) || isset($_POST['split_posts_comply']))
  145. {
  146. if (isset($_POST['split_posts_comply']))
  147. {
  148. confirm_referrer('moderate.php');
  149. if (@preg_match('%[^0-9,]%', $_POST['posts']))
  150. message($lang->t('Bad request'));
  151. $posts = explode(',', $_POST['posts']);
  152. if (empty($posts))
  153. message($lang->t('No posts selected'));
  154. $move_to_forum = isset($_POST['move_to_forum']) ? intval($_POST['move_to_forum']) : 0;
  155. if ($move_to_forum < 1)
  156. message($lang->t('Bad request'));
  157. // How many posts did we just split off?
  158. $num_posts_splitted = count($posts);
  159. // Verify that the post IDs are valid
  160. $query = $db->select(array('num_posts' => 'COUNT(p.id) AS num_posts'), 'posts AS p');
  161. $query->where = 'p.id IN :pids AND p.topic_id = :topic_id';
  162. $params = array(':pids' => $posts, ':topic_id' => $tid);
  163. $result = $query->run($params);
  164. if ($result[0]['num_posts'] != $num_posts_splitted)
  165. message($lang->t('Bad request'));
  166. unset ($result, $query, $params);
  167. // Verify that the move to forum ID is valid
  168. $query = $db->select(array('one' => '1'), 'forums AS f');
  169. $query->leftJoin('fp', 'forum_perms AS fp', 'fp.group_id = :group_id AND fp.forum_id = :forum_id');
  170. $query->where = 'f.redirect_url IS NULL AND (fp.post_topics IS NULL OR fp.post_topics = 1)';
  171. $params = array(':group_id' => $pun_user['g_id'], ':forum_id' => $move_to_forum);
  172. $result = $query->run($params);
  173. if (empty($result))
  174. message($lang->t('Bad request'));
  175. unset ($result, $query, $params);
  176. // Load the post.php language file
  177. $lang->load('post');
  178. // Check subject
  179. $new_subject = isset($_POST['new_subject']) ? pun_trim($_POST['new_subject']) : '';
  180. if ($new_subject == '')
  181. message($lang->t('No subject'));
  182. else if (pun_strlen($new_subject) > 70)
  183. message($lang->t('Too long subject'));
  184. // Get data from the new first post
  185. $query = $db->select(array('id' => 'p.id', 'poster' => 'p.poster', 'posted' => 'p.posted'), 'posts AS p');
  186. $query->where = 'p.id IN :pids';
  187. $query->order = array('id' => 'o.id ASC');
  188. $query->limit = 1;
  189. $params = array(':pids' => $posts);
  190. $result = $query->run($params);
  191. $first_post = $result[0];
  192. unset ($result, $query, $params);
  193. // Create the new topic
  194. $query = $db->insert(array('poster' => ':poster', 'subject' => ':subject', 'posted' => ':posted', 'first_post_id' => ':first_post_id', 'forum_id' => ':forum_id'), 'topics');
  195. $params = array(':poster' => $first_post['poster'], ':subject' => $new_subject, ':posted' => $first_post['posted'], ':first_post_id' => $first_post['id'], ':forum_id' => $move_to_forum);
  196. $query->run($params);
  197. $new_tid = $db->insertId();
  198. unset ($query, $params);
  199. // Move the posts to the new topic
  200. $query = $db->update(array('topic_id' => ':topic_id'), 'posts');
  201. $query->where = 'id IN :pids';
  202. $params = array(':topic_id' => $new_tid, ':pids' => $posts);
  203. $query->run($params);
  204. unset ($query, $params);
  205. // Get last_post, last_post_id, and last_poster from the topic and update it
  206. $query = $db->select(array('id' => 'p.id', 'poster' => 'p.poster', 'posted' => 'p.posted'), 'posts AS p');
  207. $query->where = 'p.topic_id = :topic_id';
  208. $query->order = array('id' => 'p.id DESC');
  209. $query->limit = 1;
  210. $params = array(':topic_id' => $tid);
  211. $result = $query->run($params);
  212. $last_post = $result[0];
  213. unset ($result, $query, $params);
  214. $query = $db->update(array('last_post' => ':last_post', 'last_post_id' => ':last_post_id', 'last_poster' => ':last_poster', 'num_replies' => 'num_replies - :num_splitted'), 'topics');
  215. $query->where = 'id = :topic_id';
  216. $params = array(':last_post' => $last_post['posted'], ':last_post_id' => $last_post['id'], ':last_poster' => $last_post['poster'], ':num_splitted' => $num_posts_splitted, ':topic_id' => $tid);
  217. $query->run($params);
  218. unset ($query, $params);
  219. // Get last_post, last_post_id, and last_poster from the new topic and update it
  220. $query = $db->select(array('id' => 'p.id', 'poster' => 'p.poster', 'posted' => 'p.posted'), 'posts AS p');
  221. $query->where = 'p.topic_id = :topic_id';
  222. $query->order = array('id' => 'p.id DESC');
  223. $query->limit = 1;
  224. $params = array(':topic_id' => $new_tid);
  225. $result = $query->run($params);
  226. $last_post = $result[0];
  227. unset ($result, $query, $params);
  228. $query = $db->update(array('last_post' => ':last_post', 'last_post_id' => ':last_post_id', 'last_poster' => ':last_poster', 'num_replies' => ':num_replies'), 'topics');
  229. $query->where = 'id = :topic_id';
  230. $params = array(':last_post' => $last_post['posted'], ':last_post_id' => $last_post['id'], ':last_poster' => $last_post['poster'], ':num_replies' => $num_posts_splitted - 1, ':topic_id' => $new_tid);
  231. $query->run($params);
  232. unset ($query, $params);
  233. update_forum($fid);
  234. update_forum($move_to_forum);
  235. redirect('viewtopic.php?id='.$new_tid, $lang->t('Split posts redirect'));
  236. }
  237. $query = $db->select(array('cid' => 'c.id AS cid', 'cat_name' => 'c.cat_name', 'fid' => 'f.id AS fid', 'forum_name' => 'f.forum_name'), 'categories AS c');
  238. $query->innerJoin('f', 'forums AS f', 'c.id = f.cat_id');
  239. $query->leftJoin('fp', 'forum_perms AS fp', 'fp.forum_id = f.id AND fp.group_id = :group_id');
  240. $query->where = '(fp.post_topics IS NULL OR fp.post_topics = 1) AND f.redirect_url IS NULL';
  241. $query->order = array('cposition' => 'c.disp_position ASC', 'cid' => 'c.id ASC', 'fposition' => 'f.disp_position ASC');
  242. $params = array(':group_id' => $pun_user['g_id']);
  243. $result = $query->run($params);
  244. $posts = isset($_POST['posts']) ? $_POST['posts'] : array();
  245. if (empty($posts))
  246. message($lang->t('No posts selected'));
  247. $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang->t('Moderate'));
  248. $focus_element = array('subject','new_subject');
  249. define('PUN_ACTIVE_PAGE', 'index');
  250. require PUN_ROOT.'header.php';
  251. ?>
  252. <div class="blockform">
  253. <h2><span><?php echo $lang->t('Split posts') ?></span></h2>
  254. <div class="box">
  255. <form id="subject" method="post" action="moderate.php?fid=<?php echo $fid ?>&amp;tid=<?php echo $tid ?>">
  256. <div class="inform">
  257. <fieldset>
  258. <legend><?php echo $lang->t('Confirm split legend') ?></legend>
  259. <div class="infldset">
  260. <input type="hidden" name="posts" value="<?php echo implode(',', array_map('intval', array_keys($posts))) ?>" />
  261. <label class="required"><strong><?php echo $lang->t('New subject') ?> <span><?php echo $lang->t('Required') ?></span></strong><br /><input type="text" name="new_subject" size="80" maxlength="70" /><br /></label>
  262. <label><?php echo $lang->t('Move to') ?>
  263. <br /><select name="move_to_forum">
  264. <?php
  265. $cur_category = 0;
  266. foreach ($result as $cur_forum)
  267. {
  268. if ($cur_forum['cid'] != $cur_category) // A new category since last iteration?
  269. {
  270. if ($cur_category)
  271. echo "\t\t\t\t\t\t\t".'</optgroup>'."\n";
  272. echo "\t\t\t\t\t\t\t".'<optgroup label="'.pun_htmlspecialchars($cur_forum['cat_name']).'">'."\n";
  273. $cur_category = $cur_forum['cid'];
  274. }
  275. echo "\t\t\t\t\t\t\t\t".'<option value="'.$cur_forum['fid'].'"'.($fid == $cur_forum['fid'] ? ' selected="selected"' : '').'>'.pun_htmlspecialchars($cur_forum['forum_name']).'</option>'."\n";
  276. }
  277. unset ($result, $query, $params);
  278. ?>
  279. </optgroup>
  280. </select>
  281. <br /></label>
  282. <p><?php echo $lang->t('Split posts comply') ?></p>
  283. </div>
  284. </fieldset>
  285. </div>
  286. <p class="buttons"><input type="submit" name="split_posts_comply" value="<?php echo $lang->t('Split') ?>" /> <a href="javascript:history.go(-1)"><?php echo $lang->t('Go back') ?></a></p>
  287. </form>
  288. </div>
  289. </div>
  290. <?php
  291. require PUN_ROOT.'footer.php';
  292. }
  293. // Show the moderate posts view
  294. // Load the viewtopic.php language file
  295. $lang->load('topic');
  296. // Used to disable the Move and Delete buttons if there are no replies to this topic
  297. $button_status = ($cur_topic['num_replies'] == 0) ? ' disabled="disabled"' : '';
  298. // Determine the post offset (based on $_GET['p'])
  299. $num_pages = ceil(($cur_topic['num_replies'] + 1) / $pun_user['disp_posts']);
  300. $p = (!isset($_GET['p']) || $_GET['p'] <= 1 || $_GET['p'] > $num_pages) ? 1 : intval($_GET['p']);
  301. $start_from = $pun_user['disp_posts'] * ($p - 1);
  302. // Generate paging links
  303. $paging_links = '<span class="pages-label">'.$lang->t('Pages').' </span>'.paginate($num_pages, $p, 'moderate.php?fid='.$fid.'&amp;tid='.$tid);
  304. if ($pun_config['o_censoring'] == '1')
  305. $cur_topic['subject'] = censor_words($cur_topic['subject']);
  306. $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), pun_htmlspecialchars($cur_topic['forum_name']), pun_htmlspecialchars($cur_topic['subject']));
  307. define('PUN_ACTIVE_PAGE', 'index');
  308. require PUN_ROOT.'header.php';
  309. ?>
  310. <div class="linkst">
  311. <div class="inbox crumbsplus">
  312. <ul class="crumbs">
  313. <li><a href="index.php"><?php echo $lang->t('Index') ?></a></li>
  314. <li><span>»&#160;</span><a href="viewforum.php?id=<?php echo $fid ?>"><?php echo pun_htmlspecialchars($cur_topic['forum_name']) ?></a></li>
  315. <li><span>»&#160;</span><a href="viewtopic.php?id=<?php echo $tid ?>"><?php echo pun_htmlspecialchars($cur_topic['subject']) ?></a></li>
  316. <li><span>»&#160;</span><strong><?php echo $lang->t('Moderate') ?></strong></li>
  317. </ul>
  318. <div class="pagepost">
  319. <p class="pagelink conl"><?php echo $paging_links ?></p>
  320. </div>
  321. <div class="clearer"></div>
  322. </div>
  323. </div>
  324. <form method="post" action="moderate.php?fid=<?php echo $fid ?>&amp;tid=<?php echo $tid ?>">
  325. <?php
  326. require PUN_ROOT.'include/parser.php';
  327. $post_count = 0; // Keep track of post numbers
  328. // Retrieve a list of post IDs, LIMIT is (really) expensive so we only fetch the IDs here then later fetch the remaining data
  329. $query = $db->select(array('id' => 'p.id'), 'posts AS p');
  330. $query->where = 'p.topic_id = :topic_id';
  331. $query->order = array('id' => 'p.id ASC');
  332. $query->offset = $start_from;
  333. $query->limit = $pun_user['disp_posts'];
  334. $params = array(':topic_id' => $tid);
  335. $post_ids = $query->run($params);
  336. unset ($query, $params);
  337. // If there are posts in this topic
  338. if (empty($post_ids))
  339. error('The post table and topic table seem to be out of sync!', __FILE__, __LINE__);
  340. // Translate from a 3d array into 2d array: $post_ids[0]['id'] -> $post_ids[0]
  341. foreach ($post_ids as $key => $value)
  342. $post_ids[$key] = $value['id'];
  343. // Retrieve the posts (and their respective poster)
  344. $query = $db->select(array('title' => 'u.title', 'num_posts' => 'u.num_posts', 'g_id' => 'g.g_id', 'g_user_title' => 'g.g_user_title', 'id' => 'p.id', 'poster' => 'p.poster', 'poster_id' => 'p.poster_id', 'message' => 'p.message', 'hide_smilies' => 'p.hide_smilies', 'posted' => 'p.posted', 'edited' => 'p.edited', 'edited_by' => 'p.edited_by'), 'posts AS p');
  345. $query->innerJoin('u', 'users AS u', 'u.id = p.poster_id');
  346. $query->Innerjoin('g', 'groups AS g', 'g.g_id = u.group_id');
  347. $query->where = 'p.id IN :pids';
  348. $query->order = array('id' => 'p.id ASC');
  349. $params = array(':pids' => $post_ids);
  350. $result = $query->run($params);
  351. foreach ($result as $cur_post)
  352. {
  353. $post_count++;
  354. // If the poster is a registered user
  355. if ($cur_post['poster_id'] > 1)
  356. {
  357. if ($pun_user['g_view_users'] == '1')
  358. $poster = '<a href="profile.php?id='.$cur_post['poster_id'].'">'.pun_htmlspecialchars($cur_post['poster']).'</a>';
  359. else
  360. $poster = pun_htmlspecialchars($cur_post['poster']);
  361. // get_title() requires that an element 'username' be present in the array
  362. $cur_post['username'] = $cur_post['poster'];
  363. $user_title = get_title($cur_post);
  364. if ($pun_config['o_censoring'] == '1')
  365. $user_title = censor_words($user_title);
  366. }
  367. // If the poster is a guest (or a user that has been deleted)
  368. else
  369. {
  370. $poster = pun_htmlspecialchars($cur_post['poster']);
  371. $user_title = $lang->t('Guest');
  372. }
  373. // Perform the main parsing of the message (BBCode, smilies, censor words etc)
  374. $cur_post['message'] = parse_message($cur_post['message'], $cur_post['hide_smilies']);
  375. ?>
  376. <div id="p<?php echo $cur_post['id'] ?>" class="blockpost<?php if($cur_post['id'] == $cur_topic['first_post_id']) echo ' firstpost' ?><?php echo ($post_count % 2 == 0) ? ' roweven' : ' rowodd' ?><?php if ($post_count == 1) echo ' blockpost1' ?>">
  377. <h2><span><span class="conr">#<?php echo ($start_from + $post_count) ?></span> <a href="viewtopic.php?pid=<?php echo $cur_post['id'].'#p'.$cur_post['id'] ?>"><?php echo format_time($cur_post['posted']) ?></a></span></h2>
  378. <div class="box">
  379. <div class="inbox">
  380. <div class="postbody">
  381. <div class="postleft">
  382. <dl>
  383. <dt><strong><?php echo $poster ?></strong></dt>
  384. <dd class="usertitle"><strong><?php echo $user_title ?></strong></dd>
  385. </dl>
  386. </div>
  387. <div class="postright">
  388. <h3 class="nosize"><?php echo $lang->t('Message') ?></h3>
  389. <div class="postmsg">
  390. <?php echo $cur_post['message']."\n" ?>
  391. <?php if ($cur_post['edited'] != '') echo "\t\t\t\t\t\t".'<p class="postedit"><em>'.$lang->t('Last edit').' '.pun_htmlspecialchars($cur_post['edited_by']).' ('.format_time($cur_post['edited']).')</em></p>'."\n"; ?>
  392. </div>
  393. </div>
  394. </div>
  395. </div>
  396. <div class="inbox">
  397. <div class="postfoot clearb">
  398. <div class="postfootright"><?php echo ($cur_post['id'] != $cur_topic['first_post_id']) ? '<p class="multidelete"><label><strong>'.$lang->t('Select').'</strong>&#160;<input type="checkbox" name="posts['.$cur_post['id'].']" value="1" /></label></p>' : '<p>'.$lang->t('Cannot select first').'</p>' ?></div>
  399. </div>
  400. </div>
  401. </div>
  402. </div>
  403. <?php
  404. }
  405. unset ($result, $query, $params);
  406. ?>
  407. <div class="postlinksb">
  408. <div class="inbox crumbsplus">
  409. <div class="pagepost">
  410. <p class="pagelink conl"><?php echo $paging_links ?></p>
  411. <p class="conr modbuttons"><input type="submit" name="split_posts" value="<?php echo $lang->t('Split') ?>"<?php echo $button_status ?> /> <input type="submit" name="delete_posts" value="<?php echo $lang->t('Delete') ?>"<?php echo $button_status ?> /></p>
  412. <div class="clearer"></div>
  413. </div>
  414. <ul class="crumbs">
  415. <li><a href="index.php"><?php echo $lang->t('Index') ?></a></li>
  416. <li><span>»&#160;</span><a href="viewforum.php?id=<?php echo $fid ?>"><?php echo pun_htmlspecialchars($cur_topic['forum_name']) ?></a></li>
  417. <li><span>»&#160;</span><a href="viewtopic.php?id=<?php echo $tid ?>"><?php echo pun_htmlspecialchars($cur_topic['subject']) ?></a></li>
  418. <li><span>»&#160;</span><strong><?php echo $lang->t('Moderate') ?></strong></li>
  419. </ul>
  420. <div class="clearer"></div>
  421. </div>
  422. </div>
  423. </form>
  424. <?php
  425. require PUN_ROOT.'footer.php';
  426. }
  427. // Move one or more topics
  428. if (isset($_REQUEST['move_topics']) || isset($_POST['move_topics_to']))
  429. {
  430. if (isset($_POST['move_topics_to']))
  431. {
  432. confirm_referrer('moderate.php');
  433. if (@preg_match('%[^0-9,]%', $_POST['topics']))
  434. message($lang->t('Bad request'));
  435. $topics = explode(',', $_POST['topics']);
  436. $move_to_forum = isset($_POST['move_to_forum']) ? intval($_POST['move_to_forum']) : 0;
  437. if (empty($topics) || $move_to_forum < 1)
  438. message($lang->t('Bad request'));
  439. // Verify that the topic IDs are valid
  440. $query = $db->select(array('num_topics' => 'COUNT(t.id) AS num_topics'), 'topics AS t');
  441. $query->where = 't.id IN :tids AND t.forum_id = :forum_id';
  442. $params = array(':tids' => $topics, ':forum_id' => $fid);
  443. $result = $query->run($params);
  444. if ($result[0]['num_topics'] != count($topics))
  445. message($lang->t('Bad request'));
  446. unset ($result, $query, $params);
  447. // Verify that the move to forum ID is valid
  448. $query = $db->select(array('one' => '1'), 'forums AS f');
  449. $query->leftJoin('fp', 'forum_perms AS fp', 'fp.group_id = :group_id AND fp.forum_id = :forum_id');
  450. $query->where = 'f.redirect_url IS NULL AND (fp.post_topics IS NULL OR fp.post_topics = 1)';
  451. $params = array(':group_id' => $pun_user['g_id'], ':forum_id' => $move_to_forum);
  452. if (empty($result))
  453. message($lang->t('Bad request'));
  454. unset ($result, $query, $params);
  455. // Delete any redirect topics if there are any (only if we moved/copied the topic back to where it was once moved from)
  456. $query = $db->delete('topics');
  457. $query->where = 'forum_id = :forum_id AND moved_to IN :tids';
  458. $params = array(':forum_id' => $move_to_forum, ':tids' => $topics);
  459. $query->run($params);
  460. unset ($query, $params);
  461. // Move the topic(s)
  462. $query = $db->update(array('forum_id' => ':forum_id'), 'topics');
  463. $query->where = 'id IN :tids';
  464. $params = array(':forum_id' => $move_to_forum, ':tids' => $topics);
  465. $query->run($params);
  466. unset ($query, $params);
  467. // Should we create redirect topics?
  468. if (isset($_POST['with_redirect']))
  469. {
  470. $query = $db->select(array('poster' => 't.poster', 'subject' => 't.subject', 'posted' => 't.posted', 'last_post' => 't.last_post'), 'topics AS t');
  471. $query->where = 't.id IN :tids';
  472. $params = array(':tids' => $topics);
  473. $result = $query->run($params);
  474. unset ($query, $params);
  475. $insert_query = $db->insert(array('poster' => ':poster', 'subject' => ':subject', 'posted' => ':posted', 'last_post' => ':last_post', 'moved_to' => ':moved_to', 'forum_id' => ':forum_id'), 'topics');
  476. foreach ($result as $cur_topic)
  477. {
  478. $params = array(':poster' => $cur_topic['poster'], ':subject' => $cur_topic['subject'], ':posted' => $cur_topic['posted'], ':last_post' => $cur_topic['last_post'], ':moved_to' => $cur_topic,':forum_id' => $fid);
  479. $insert_query->run($params);
  480. unset ($params);
  481. }
  482. unset ($result, $insert_query);
  483. }
  484. update_forum($fid); // Update the forum FROM which the topic was moved
  485. update_forum($move_to_forum); // Update the forum TO which the topic was moved
  486. $redirect_msg = (count($topics) > 1) ? $lang->t('Move topics redirect') : $lang->t('Move topic redirect');
  487. redirect('viewforum.php?id='.$move_to_forum, $redirect_msg);
  488. }
  489. if (isset($_POST['move_topics']))
  490. {
  491. $topics = isset($_POST['topics']) ? $_POST['topics'] : array();
  492. if (empty($topics))
  493. message($lang->t('No topics selected'));
  494. $topics = implode(',', array_map('intval', array_keys($topics)));
  495. $action = 'multi';
  496. }
  497. else
  498. {
  499. $topics = intval($_GET['move_topics']);
  500. if ($topics < 1)
  501. message($lang->t('Bad request'));
  502. $action = 'single';
  503. }
  504. $query = $db->select(array('cid' => 'c.id AS cid', 'cat_name' => 'c.cat_name', 'fid' => 'f.id AS fid', 'forum_name' => 'f.forum_name'), 'categories AS c');
  505. $query->innerJoin('f', 'forums AS f', 'c.id = f.cat_id');
  506. $query->leftJoin('fp', 'forum_perms AS fp', 'fp.forum_id = f.id AND fp.group_id = :group_id');
  507. $query->where = '(fp.post_topics IS NULL OR fp.post_topics = 1) AND f.redirect_url IS NULL';
  508. $query->order = array('cposition' => 'c.disp_position ASC', 'cid' => 'c.id ASC', 'fposition' => 'f.disp_position ASC');
  509. $params = array(':group_id' => $pun_user['g_id']);
  510. $result = $query->run($params);
  511. unset ($query, $params);
  512. if (count($result) < 2)
  513. message($lang->t('Nowhere to move'));
  514. $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang->t('Moderate'));
  515. define('PUN_ACTIVE_PAGE', 'index');
  516. require PUN_ROOT.'header.php';
  517. ?>
  518. <div class="blockform">
  519. <h2><span><?php echo ($action == 'single') ? $lang->t('Move topic') : $lang->t('Move topics') ?></span></h2>
  520. <div class="box">
  521. <form method="post" action="moderate.php?fid=<?php echo $fid ?>">
  522. <div class="inform">
  523. <input type="hidden" name="topics" value="<?php echo $topics ?>" />
  524. <fieldset>
  525. <legend><?php echo $lang->t('Move legend') ?></legend>
  526. <div class="infldset">
  527. <label><?php echo $lang->t('Move to') ?>
  528. <br /><select name="move_to_forum">
  529. <?php
  530. $cur_category = 0;
  531. foreach ($result as $cur_forum)
  532. {
  533. if ($cur_forum['cid'] != $cur_category) // A new category since last iteration?
  534. {
  535. if ($cur_category)
  536. echo "\t\t\t\t\t\t\t".'</optgroup>'."\n";
  537. echo "\t\t\t\t\t\t\t".'<optgroup label="'.pun_htmlspecialchars($cur_forum['cat_name']).'">'."\n";
  538. $cur_category = $cur_forum['cid'];
  539. }
  540. if ($cur_forum['fid'] != $fid)
  541. echo "\t\t\t\t\t\t\t\t".'<option value="'.$cur_forum['fid'].'">'.pun_htmlspecialchars($cur_forum['forum_name']).'</option>'."\n";
  542. }
  543. unset ($result);
  544. ?>
  545. </optgroup>
  546. </select>
  547. <br /></label>
  548. <div class="rbox">
  549. <label><input type="checkbox" name="with_redirect" value="1"<?php if ($action == 'single') echo ' checked="checked"' ?> /><?php echo $lang->t('Leave redirect') ?><br /></label>
  550. </div>
  551. </div>
  552. </fieldset>
  553. </div>
  554. <p class="buttons"><input type="submit" name="move_topics_to" value="<?php echo $lang->t('Move') ?>" /> <a href="javascript:history.go(-1)"><?php echo $lang->t('Go back') ?></a></p>
  555. </form>
  556. </div>
  557. </div>
  558. <?php
  559. require PUN_ROOT.'footer.php';
  560. }
  561. // Merge two or more topics
  562. else if (isset($_POST['merge_topics']) || isset($_POST['merge_topics_comply']))
  563. {
  564. if (isset($_POST['merge_topics_comply']))
  565. {
  566. confirm_referrer('moderate.php');
  567. if (@preg_match('%[^0-9,]%', $_POST['topics']))
  568. message($lang->t('Bad request'));
  569. $topics = explode(',', $_POST['topics']);
  570. if (count($topics) < 2)
  571. message($lang->t('Not enough topics selected'));
  572. // Verify that the topic IDs are valid (redirect links will point to the merged topic after the merge)
  573. $query = $db->select(array('id' => 't.id'), 'topics AS t');
  574. $query->where = 't.id IN :tids AND t.forum_id = :forum_id';
  575. $query->order = array('id' => 't.id ASC');
  576. $params = array(':tids' => $topics, ':forum_id' => $fid);
  577. $result = $query->run($params);
  578. if (count($result[0]) != count($topics))
  579. message($lang->t('Bad request'));
  580. // The topic that we are merging into is the one with the smallest ID
  581. $merge_to_tid = $result[0]['id'];
  582. unset ($result, $query, $params);
  583. // Make any redirect topics point to our new, merged topic
  584. $query = $db->update(array('moved_to' => ':merge_id'), 'topics');
  585. $query->where = 'moved_to IN :tids';
  586. $params = array(':merge_id' => $merge_to_tid, ':tids' => $topics);
  587. // Should we create redirect topics?
  588. if (isset($_POST['with_redirect']))
  589. $query->where .= ' OR (id IN :tids AND id != :merge_id)';
  590. $query->run($params);
  591. unset ($query, $params);
  592. // Merge the posts into the topic
  593. $query = $db->update(array('topic_id' => ':merge_id'), 'posts');
  594. $query->where = 'topic_id IN :tids';
  595. $params = array(':merge_id' => $merge_to_tid, ':tids' => $topics);
  596. $query->run($params);
  597. unset ($query, $params);
  598. // Delete any subscriptions
  599. $query = $db->delete('topic_subscriptions');
  600. $query->where = 'topic_id IN :tids AND topic_id != :merge_id';
  601. $params = array(':merge_id' => $merge_to_tid, ':tids' => $topics);
  602. $query->run($params);
  603. unset ($query, $params);
  604. // Without redirection the old topics are removed
  605. if (!isset($_POST['with_redirect']))
  606. {
  607. $query = $db->delete('topics');
  608. $query->where = 'id IN :tids AND id != :merge_id';
  609. $params = array(':merge_id' => $merge_to_tid, ':tids' => $topics);
  610. $query->run($params);
  611. unset ($query, $params);
  612. }
  613. // Count number of replies in the topic
  614. $query = $db->select(array('num_replies' => '(COUNT(p.id) - 1) AS num_replies'), 'posts AS p');
  615. $query->where = 'p.topic_id = :merge_to';
  616. $params = array(':merge_to' => $merge_to_tid);
  617. $result = $query->run($params);
  618. $num_replies = $result[0]['num_replies'];
  619. unset ($result, $query, $params);
  620. // Get last_post, last_post_id and last_poster
  621. $query = $db->select(array('posted' => 'p.posted', 'id' => 'p.id', 'poster' => 'p.poster'), 'posts AS p');
  622. $query->where = 'p.topic_id = :merge_to';
  623. $query->order = array('id' => 'p.id DESC');
  624. $query->limit = 1;
  625. $result = $query->run($params);
  626. $last_post = $result[0];
  627. unset ($result, $query, $params);
  628. // Update topic
  629. $query = $db->update(array('num_replies' => ':num_replies', 'last_post' => ':last_post', 'last_post_id' => ':last_post_id', 'last_poster' => ':last_poster'), 'topics');
  630. $query->where = 'id = :merge_to';
  631. $params = array(':num_replies' => $num_replies, ':last_post' => $last_post['posted'], ':last_post_id' => $last_post['id'], ':last_poster' => $last_post['poster'], ':merge_to' => $merge_to_tid);
  632. $query->run($params);
  633. unset ($query, $params);
  634. // Update the forum FROM which the topic was moved and redirect
  635. update_forum($fid);
  636. redirect('viewforum.php?id='.$fid, $lang->t('Merge topics redirect'));
  637. }
  638. $topics = isset($_POST['topics']) ? $_POST['topics'] : array();
  639. if (count($topics) < 2)
  640. message($lang->t('Not enough topics selected'));
  641. $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang->t('Moderate'));
  642. define('PUN_ACTIVE_PAGE', 'index');
  643. require PUN_ROOT.'header.php';
  644. ?>
  645. <div class="blockform">
  646. <h2><span><?php echo $lang->t('Merge topics') ?></span></h2>
  647. <div class="box">
  648. <form method="post" action="moderate.php?fid=<?php echo $fid ?>">
  649. <input type="hidden" name="topics" value="<?php echo implode(',', array_map('intval', array_keys($topics))) ?>" />
  650. <div class="inform">
  651. <fieldset>
  652. <legend><?php echo $lang->t('Confirm merge legend') ?></legend>
  653. <div class="infldset">
  654. <div class="rbox">
  655. <label><input type="checkbox" name="with_redirect" value="1" /><?php echo $lang->t('Leave redirect') ?><br /></label>
  656. </div>
  657. </div>
  658. </fieldset>
  659. </div>
  660. <p class="buttons"><input type="submit" name="merge_topics_comply" value="<?php echo $lang->t('Merge') ?>" /> <a href="javascript:history.go(-1)"><?php echo $lang->t('Go back') ?></a></p>
  661. </form>
  662. </div>
  663. </div>
  664. <?php
  665. require PUN_ROOT.'footer.php';
  666. }
  667. // Delete one or more topics
  668. else if (isset($_POST['delete_topics']) || isset($_POST['delete_topics_comply']))
  669. {
  670. if (isset($_POST['delete_topics_comply']))
  671. {
  672. confirm_referrer('moderate.php');
  673. if (@preg_match('%[^0-9,]%', $_POST['topics']))
  674. message($lang->t('Bad request'));
  675. $topics = explode(',', $_POST['topics']);
  676. if (empty($topics))
  677. message($lang->t('No topics selected'));
  678. require PUN_ROOT.'include/search_idx.php';
  679. // Verify that the topic IDs are valid
  680. $query = $db->select(array('num_topics' => 'COUNT(t.id) AS num_topics'), 'topics AS t');
  681. $query->where = 'id IN :tids AND forum_id = :forum_id';
  682. $params = array(':tids' => $topics, ':forum_id' => $fid);
  683. $result = $query->run($params);
  684. if ($result[0]['num_topics'] != count($topics))
  685. message($lang->t('Bad request'));
  686. unset ($result, $query, $params);
  687. // Delete the topics and any redirect topics
  688. $query = $db->delete('topics');
  689. $query->where = 'id IN :tids OR moved_to IN :tids';
  690. $params = array(':tids' => $topics);
  691. $query->run($params);
  692. unset ($query, $params);
  693. // Delete any subscriptions
  694. $query = $db->delete('topic_subscriptions');
  695. $query->where = 'topic_id IN :tids';
  696. $params = array(':tids' => $topics);
  697. $query->run($params);
  698. unset ($query, $params);
  699. // Create a list of the post IDs in this topic and then strip the search index
  700. $query = $db->select(array('id' => 'p.id'), 'posts AS p');
  701. $query->where = 'p.topic_id IN :tids';
  702. $params = array(':tids' => $topics);
  703. $result = $query->run($params);
  704. $post_ids = array();
  705. foreach ($result as $cur_post)
  706. $post_ids[] = $cur_post['id'];
  707. unset ($result, $query, $params);
  708. // We have to check that we actually have a list of post IDs since we could be deleting just a redirect topic
  709. if (!empty($post_ids))
  710. strip_search_index($post_ids);
  711. // Delete posts
  712. $query = $db->delete('posts');
  713. $query->where = 'topic_id IN :tids';
  714. $params = array(':tids' => $topics);
  715. $query->run($params);
  716. unset ($query, $params);
  717. update_forum($fid);
  718. redirect('viewforum.php?id='.$fid, $lang->t('Delete topics redirect'));
  719. }
  720. $topics = isset($_POST['topics']) ? $_POST['topics'] : array();
  721. if (empty($topics))
  722. message($lang->t('No topics selected'));
  723. $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), $lang->t('Moderate'));
  724. define('PUN_ACTIVE_PAGE', 'index');
  725. require PUN_ROOT.'header.php';
  726. ?>
  727. <div class="blockform">
  728. <h2><span><?php echo $lang->t('Delete topics') ?></span></h2>
  729. <div class="box">
  730. <form method="post" action="moderate.php?fid=<?php echo $fid ?>">
  731. <input type="hidden" name="topics" value="<?php echo implode(',', array_map('intval', array_keys($topics))) ?>" />
  732. <div class="inform">
  733. <fieldset>
  734. <legend><?php echo $lang->t('Confirm delete legend') ?></legend>
  735. <div class="infldset">
  736. <p><?php echo $lang->t('Delete topics comply') ?></p>
  737. </div>
  738. </fieldset>
  739. </div>
  740. <p class="buttons"><input type="submit" name="delete_topics_comply" value="<?php echo $lang->t('Delete') ?>" /><a href="javascript:history.go(-1)"><?php echo $lang->t('Go back') ?></a></p>
  741. </form>
  742. </div>
  743. </div>
  744. <?php
  745. require PUN_ROOT.'footer.php';
  746. }
  747. // Open or close one or more topics
  748. else if (isset($_REQUEST['open']) || isset($_REQUEST['close']))
  749. {
  750. $action = (isset($_REQUEST['open'])) ? 0 : 1;
  751. // There could be an array of topic IDs in $_POST
  752. if (isset($_POST['open']) || isset($_POST['close']))
  753. {
  754. confirm_referrer('moderate.php');
  755. $topics = isset($_POST['topics']) ? @array_map('intval', @array_keys($_POST['topics'])) : array();
  756. if (empty($topics))
  757. message($lang->t('No topics selected'));
  758. $query = $db->update(array('closed' => ':closed'), 'topics');
  759. $query->where = 'id IN :tids AND forum_id = :forum_id';
  760. $params = array(':closed' => $action, ':tids' => $topics, ':forum_id' => $fid);
  761. $query->run($params);
  762. unset ($query, $params);
  763. $redirect_msg = ($action) ? $lang->t('Close topics redirect') : $lang->t('Open topics redirect');
  764. redirect('moderate.php?fid='.$fid, $redirect_msg);
  765. }
  766. // Or just one in $_GET
  767. else
  768. {
  769. confirm_referrer('viewtopic.php');
  770. $topic_id = ($action) ? intval($_GET['close']) : intval($_GET['open']);
  771. if ($topic_id < 1)
  772. message($lang->t('Bad request'));
  773. $query = $db->update(array('closed' => ':closed'), 'topics');
  774. $query->where = 'id = :topic_id AND forum_id = :forum_id';
  775. $params = array(':closed' => $action, ':topic_id' => $topic_id, ':forum_id' => $fid);
  776. $query->run($params);
  777. unset ($query, $params);
  778. $redirect_msg = ($action) ? $lang->t('Close topic redirect') : $lang->t('Open topic redirect');
  779. redirect('viewtopic.php?id='.$topic_id, $redirect_msg);
  780. }
  781. }
  782. // Stick a topic
  783. else if (isset($_GET['stick']))
  784. {
  785. confirm_referrer('viewtopic.php');
  786. $stick = intval($_GET['stick']);
  787. if ($stick < 1)
  788. message($lang->t('Bad request'));
  789. $query = $db->update(array('sticky' => '1'), 'topics');
  790. $query->where = 'id = :topic_id AND forum_id = :forum_id';
  791. $params = array(':topic_id' => $stick, ':forum_id' => $fid);
  792. $query->run($params);
  793. unset ($query, $params);
  794. redirect('viewtopic.php?id='.$stick, $lang->t('Stick topic redirect'));
  795. }
  796. // Unstick a topic
  797. else if (isset($_GET['unstick']))
  798. {
  799. confirm_referrer('viewtopic.php');
  800. $unstick = intval($_GET['unstick']);
  801. if ($unstick < 1)
  802. message($lang->t('Bad request'));
  803. $query = $db->update(array('sticky' => '0'), 'topics');
  804. $query->where = 'id = :topic_id AND forum_id = :forum_id';
  805. $params = array(':topic_id' => $unstick, ':forum_id' => $fid);
  806. $query->run($params);
  807. unset ($query, $params);
  808. redirect('viewtopic.php?id='.$unstick, $lang->t('Unstick topic redirect'));
  809. }
  810. // No specific forum moderation action was specified in the query string, so we'll display the moderator forum
  811. // Load the viewforum.php language file
  812. $lang->load('forum');
  813. // Fetch some info about the forum
  814. $query = $db->select(array('forum_name' => 'f.forum_name', 'redirect_url' => 'f.redirect_url', 'num_topics' => 'f.num_topics', 'sort_by' => 'f.sort_by'), 'forums AS f');
  815. $query->leftJoin('fp', 'forum_perms AS fp', 'fp.forum_id = f.id AND fp.group_id = :group_id');
  816. $query->where = '(fp.read_forum IS NULL OR fp.read_forum = 1) AND f.id = :forum_id';
  817. $params = array(':group_id' => $pun_user['g_id'], ':forum_id' => $fid);
  818. $result = $query->run($params);
  819. if (empty($result))
  820. message($lang->t('Bad request'));
  821. $cur_forum = $result[0];
  822. unset ($result, $query, $params);
  823. // Is this a redirect forum? In that case, abort!
  824. if ($cur_forum['redirect_url'] != '')
  825. message($lang->t('Bad request'));
  826. switch ($cur_forum['sort_by'])
  827. {
  828. case 0:
  829. $sort_by = 't.last_post DESC';
  830. break;
  831. case 1:
  832. $sort_by = 't.posted DESC';
  833. break;
  834. case 2:
  835. $sort_by = 't.subject ASC';
  836. break;
  837. default:
  838. $sort_by = 't.last_post DESC';
  839. break;
  840. }
  841. // Determine the topic offset (based on $_GET['p'])
  842. $num_pages = ceil($cur_forum['num_topics'] / $pun_user['disp_topics']);
  843. $p = (!isset($_GET['p']) || $_GET['p'] <= 1 || $_GET['p'] > $num_pages) ? 1 : intval($_GET['p']);
  844. $start_from = $pun_user['disp_topics'] * ($p - 1);
  845. // Generate paging links
  846. $paging_links = '<span class="pages-label">'.$lang->t('Pages').' </span>'.paginate($num_pages, $p, 'moderate.php?fid='.$fid);
  847. $page_title = array(pun_htmlspecialchars($pun_config['o_board_title']), pun_htmlspecialchars($cur_forum['forum_name']));
  848. define('PUN_ACTIVE_PAGE', 'index');
  849. require PUN_ROOT.'header.php';
  850. ?>
  851. <div class="linkst">
  852. <div class="inbox crumbsplus">
  853. <ul class="crumbs">
  854. <li><a href="index.php"><?php echo $lang->t('Index') ?></a></li>
  855. <li><span>»&#160;</span><a href="viewforum.php?id=<?php echo $fid ?>"><?php echo pun_htmlspecialchars($cur_forum['forum_name']) ?></a></li>
  856. <li><span>»&#160;</span><strong><?php echo $lang->t('Moderate') ?></strong></li>
  857. </ul>
  858. <div class="pagepost">
  859. <p class="pagelink conl"><?php echo $paging_links ?></p>
  860. </div>
  861. <div class="clearer"></div>
  862. </div>
  863. </div>
  864. <form method="post" action="moderate.php?fid=<?php echo $fid ?>">
  865. <div id="vf" class="blocktable">
  866. <h2><span><?php echo pun_htmlspecialchars($cur_forum['forum_name']) ?></span></h2>
  867. <div class="box">
  868. <div class="inbox">
  869. <table cellspacing="0">
  870. <thead>
  871. <tr>
  872. <th class="tcl" scope="col"><?php echo $lang->t('Topic') ?></th>
  873. <th class="tc2" scope="col"><?php echo $lang->t('Replies') ?></th>
  874. <?php if ($pun_config['o_topic_views'] == '1'): ?> <th class="tc3" scope="col"><?php echo $lang->t('Views') ?></th>
  875. <?php endif; ?> <th class="tcr"><?php echo $lang->t('Last post') ?></th>
  876. <th class="tcmod" scope="col"><?php echo $lang->t('Select') ?></th>
  877. </tr>
  878. </thead>
  879. <tbody>
  880. <?php
  881. // Retrieve a list of topic IDs, LIMIT is (really) expensive so we only fetch the IDs here then later fetch the remaining data
  882. $query = $db->select(array('id' => 't.id'), 'topics AS t');
  883. $query->where = 't.forum_id = :forum_id';
  884. $query->order = array('sticky' => 't.sticky DESC', 'sort' => $sort_by, 'id' => 't.id DESC');
  885. $query->limit = $pun_user['disp_topics'];
  886. $query->offset = $start_from;
  887. $params = array(':forum_id' => $fid);
  888. $topic_ids = $query->run($params);
  889. unset ($query, $params);
  890. // If there are topics in this forum
  891. if (!empty($topic_ids))
  892. {
  893. // Translate from a 3d array into 2d array: $topics_ids[0]['id'] -> $topics_ids[0]
  894. foreach ($topic_ids as $key => $value)
  895. $topic_ids[$key] = $value['id'];
  896. // Select topics
  897. $query = $db->select(array('id' => 'id', 'poster' => 'poster', 'subject' => 'subject', 'posted' => 'posted', 'last_post' => 'last_post', 'last_post_id' => 'last_post_id', 'last_poster' => 'last_poster', 'num_views' => 'num_views', 'num_replies' => 'num_replies', 'closed' => 'closed', 'sticky' => 'sticky', 'moved_to' => 'moved_to'), 'topics AS t');
  898. $query->where = 't.id IN :tids';
  899. $query->order = array('sticky' => 't.sticky DESC', 'sort' => $sort_by, 'id' => 't.id DESC');
  900. $params = array(':tids' => $topic_ids);
  901. $button_status = '';
  902. $topic_count = 0;
  903. $result = $query->run($params);
  904. foreach ($result as $cur_topic)
  905. {
  906. ++$topic_count;
  907. $status_text = array();
  908. $item_status = ($topic_count % 2 == 0) ? 'roweven' : 'rowodd';
  909. $icon_type = 'icon';
  910. if ($cur_topic['moved_to'] == null)
  911. {
  912. $last_post = '<a href="viewtopic.php?pid='.$cur_topic['last_post_id'].'#p'.$cur_topic['last_post_id'].'">'.format_time($cur_topic['last_post']).'</a> <span class="byuser">'.$lang->t('by').' '.pun_htmlspecialchars($cur_topic['last_poster']).'</span>';
  913. $ghost_topic = false;
  914. }
  915. else
  916. {
  917. $last_post = '- - -';
  918. $ghost_topic = true;
  919. }
  920. if ($pun_config['o_censoring'] == '1')
  921. $cur_topic['subject'] = censor_words($cur_topic['subject']);
  922. if ($cur_topic['sticky'] == '1')
  923. {
  924. $item_status .= ' isticky';
  925. $status_text[] = '<span class="stickytext">'.$lang->t('Sticky').'</span>';
  926. }
  927. if ($cur_topic['moved_to'] != 0)
  928. {
  929. $subject = '<a href="viewtopic.php?id='.$cur_topic['moved_to'].'">'.pun_htmlspecialchars($cur_topic['subject']).'</a> <span class="byuser">'.$lang->t('by').' '.pun_htmlspecialchars($cur_topic['poster']).'</span>';
  930. $status_text[] = '<span class="movedtext">'.$lang->t('Moved').'</span>';
  931. $item_status .= ' imoved';
  932. }
  933. else if ($cur_topic['closed'] == '0')
  934. $subject = '<a href="viewtopic.php?id='.$cur_topic['id'].'">'.pun_htmlspecialchars($cur_topic['subject']).'</a> <span class="byuser">'.$lang->t('by').' '.pun_htmlspecialchars($cur_topic['poster']).'</span>';
  935. else
  936. {
  937. $subject = '<a href="viewtopic.php?id='.$cur_topic['id'].'">'.pun_htmlspecialchars($cur_topic['subject']).'</a> <span class="byuser">'.$lang->t('by').' '.pun_htmlspecialchars($cur_topic['poster']).'</span>';
  938. $status_text[] = '<span class="closedtext">'.$lang->t('Closed').'</span>';
  939. $item_status .= ' iclosed';
  940. }
  941. if (!$ghost_topic && $cur_topic['last_post'] > $pun_user['last_visit'] && (!isset($tracked_topics['topics'][$cur_topic['id']]) || $tracked_topics['topics'][$cur_topic['id']] < $cur_topic['last_post']) && (!isset($tracked_topics['forums'][$fid]) || $tracked_topics['forums'][$fid] < $cur_topic['last_post']))
  942. {
  943. $item_status .= ' inew';
  944. $icon_type = 'icon icon-new';
  945. $subject = '<strong>'.$subject.'</strong>';
  946. $subject_new_posts = '<span class="newtext">[ <a href="viewtopic.php?id='.$cur_topic['id'].'&amp;action=new" title="'.$lang->t('New posts info').'">'.$lang->t('New posts').'</a> ]</span>';
  947. }
  948. else
  949. $subject_new_posts = null;
  950. // Insert the status text before the subject
  951. $subject = implode(' ', $status_text).' '.$subject;
  952. $num_pages_topic = ceil(($cur_topic['num_replies'] + 1) / $pun_user['disp_posts']);
  953. if ($num_pages_topic > 1)
  954. $subject_multipage = '<span class="pagestext">[ '.paginate($num_pages_topic, -1, 'viewtopic.php?id='.$cur_topic['id']).' ]</span>';
  955. else
  956. $subject_multipage = null;
  957. // Should we show the "New posts" and/or the multipage links?
  958. if (!empty($subject_new_posts) || !empty($subject_multipage))
  959. {
  960. $subject .= !empty($subject_new_posts) ? ' '.$subject_new_posts : '';
  961. $subject .= !empty($subject_multipage) ? ' '.$subject_multipage : '';
  962. }
  963. ?>
  964. <tr class="<?php echo $item_status ?>">
  965. <td class="tcl">
  966. <div class="<?php echo $icon_type ?>"><div class="nosize"><?php echo forum_number_format($topic_count + $start_from) ?></div></div>
  967. <div class="tclcon">
  968. <div>
  969. <?php echo $subject."\n" ?>
  970. </div>
  971. </div>
  972. </td>
  973. <td class="tc2"><?php echo (!$ghost_topic) ? forum_number_format($cur_topic['num_replies']) : '-' ?></td>
  974. <?php if ($pun_config['o_topic_views'] == '1'): ?> <td class="tc3"><?php echo (!$ghost_topic) ? forum_number_format($cur_topic['num_views']) : '-' ?></td>
  975. <?php endif; ?> <td class="tcr"><?php echo $last_post ?></td>
  976. <td class="tcmod"><input type="checkbox" name="topics[<?php echo $cur_topic['id'] ?>]" value="1" /></td>
  977. </tr>
  978. <?php
  979. }
  980. unset ($result, $query, $params);
  981. }
  982. else
  983. {
  984. $colspan = ($pun_config['o_topic_views'] == '1') ? 5 : 4;
  985. $button_status = ' disabled="disabled"';
  986. echo "\t\t\t\t\t".'<tr><td class="tcl" colspan="'.$colspan.'">'.$lang->t('Empty forum').'</td></tr>'."\n";
  987. }
  988. ?>
  989. </tbody>
  990. </table>
  991. </div>
  992. </div>
  993. </div>
  994. <div class="linksb">
  995. <div class="inbox crumbsplus">
  996. <div class="pagepost">
  997. <p class="pagelink conl"><?php echo $paging_links ?></p>
  998. <p class="conr modbuttons"><input type="submit" name="move_topics" value="<?php echo $lang->t('Move') ?>"<?php echo $button_status ?> /> <input type="submit" name="delete_topics" value="<?php echo $lang->t('Delete') ?>"<?php echo $button_status ?> /> <input type="submit" name="merge_topics" value="<?php echo $lang->t('Merge') ?>"<?php echo $button_status ?> /> <input type="submit" name="open" value="<?php echo $lang->t('Open') ?>"<?php echo $button_status ?> /> <input type="submit" name="close" value="<?php echo $lang->t('Close') ?>"<?php echo $button_status ?> /></p>
  999. <div class="clearer"></div>
  1000. </div>
  1001. <ul class="crumbs">
  1002. <li><a href="index.php"><?php echo $lang->t('Index') ?></a></li>
  1003. <li><span>»&#160;</span><a href="viewforum.php?id=<?php echo $fid ?>"><?php echo pun_htmlspecialchars($cur_forum['forum_name']) ?></a></li>
  1004. <li><span>»&#160;</span><strong><?php echo $lang->t('Moderate') ?></strong></li>
  1005. </ul>
  1006. <div class="clearer"></div>
  1007. </div>
  1008. </div>
  1009. </form>
  1010. <?php
  1011. require PUN_ROOT.'footer.php';