Files
forum/Sources/SplitTopics.php

1038 lines
38 KiB
PHP

<?php
/******************************************************************************
* SplitTopics.php *
*******************************************************************************
* SMF: Simple Machines Forum *
* Open-Source Project Inspired by Zef Hemel (zef@zefhemel.com) *
* =========================================================================== *
* Software Version: SMF 1.0 *
* Software by: Simple Machines (http://www.simplemachines.org) *
* Copyright 2001-2004 by: Lewis Media (http://www.lewismedia.com) *
* Support, News, Updates at: http://www.simplemachines.org *
*******************************************************************************
* This program is free software; you may redistribute it and/or modify it *
* under the terms of the provided license as published by Lewis Media. *
* *
* This program is distributed in the hope that it is and will be useful, *
* but WITHOUT ANY WARRANTIES; without even any implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* *
* See the "license.txt" file for details of the Simple Machines license. *
* The latest version can always be found at http://www.simplemachines.org. *
******************************************************************************/
/* Original module by Mach8 - We'll never forget you. */
/*****************************************************************************/
if (!defined('SMF'))
die('Hacking attempt...');
/* This file handles merging and splitting topics...
*/
// Split a topic into two separate topics... in case it got offtopic, etc.
function SplitTopics()
{
global $topic, $sourcedir;
// And... which topic were you splitting, again?
if (empty($topic))
fatal_lang_error(337, false);
// Are you allowed to split topics?
isAllowedTo('split_any');
// Load up the "dependencies" - the template, getMsgMemberID(), and sendNotifications().
loadTemplate('SplitTopics');
require_once($sourcedir . '/Subs-Boards.php');
require_once($sourcedir . '/Subs-Post.php');
// ?action=splittopics;sa=LETSBREAKIT won't work, sorry.
if (!isset($_REQUEST['sa']) || !is_numeric($_REQUEST['sa']) || $_REQUEST['sa'] < 1 || $_REQUEST['sa'] > 4)
$subAction = 'SplitTopics1';
else
$subAction = 'SplitTopics' . (int) $_REQUEST['sa'];
$subAction();
}
// Part 1: General stuff.
function SplitTopics1()
{
global $txt, $topic, $db_prefix, $context;
// Validate "at".
if (empty($_GET['at']))
fatal_lang_error(337, false);
$_GET['at'] = (int) $_GET['at'];
// Retrieve the subject and stuff of the specific topic/message.
$request = db_query("
SELECT m.subject, t.numReplies, t.ID_FIRST_MSG
FROM {$db_prefix}messages AS m, {$db_prefix}topics AS t
WHERE m.ID_MSG = $_GET[at]
AND m.ID_TOPIC = $topic
AND t.ID_TOPIC = $topic
LIMIT 1", __FILE__, __LINE__);
if (mysql_num_rows($request) == 0)
fatal_lang_error('smf272');
list ($_REQUEST['subname'], $numReplies, $ID_FIRST_MSG) = mysql_fetch_row($request);
mysql_free_result($request);
// Check if there is more than one message in the topic. (there should be.)
if ($numReplies < 1)
fatal_lang_error('smf270', false);
// Check if this is the first message in the topic (if so, the first and second option won't be available)
if ($ID_FIRST_MSG == $_GET['at'])
return SplitTopics3();
// Basic template information....
$context['message'] = array(
'id' => $_GET['at'],
'subject' => $_REQUEST['subname']
);
$context['sub_template'] = 'ask';
$context['page_title'] = $txt['smf251'];
}
// Alright, you've decided what you want to do with it.... now to do it.
function SplitTopics2()
{
global $txt, $board, $topic, $db_prefix, $context, $ID_MEMBER;
// Check the session to make sure they meant to do this.
checkSession();
// They blanked the subject name.
if (!isset($_POST['subname']) || $_POST['subname'] == '')
$_POST['subname'] = $txt['smf258'];
// Redirect to the selector if they chose selective.
if ($_POST['step2'] == 'selective')
{
$_REQUEST['subname'] = $_POST['subname'];
return SplitTopics3();
}
// The old topic...
$split1_ID_TOPIC = $topic;
/// The new first message and member.
$split2_firstMsg = $_POST['at'];
$split2_firstMem = getMsgMemberID($split2_firstMsg);
// Find the old first, original last, and original number of replies.
$tresult = db_query("
SELECT MIN(m.ID_MSG) AS myID_FIRST_MSG, MAX(m.ID_MSG) AS myID_LAST_MSG, COUNT(m.ID_MSG) - 1 AS myNumReplies, t.isSticky
FROM {$db_prefix}topics AS t, {$db_prefix}messages AS m
WHERE m.ID_TOPIC = $split1_ID_TOPIC
AND t.ID_TOPIC = $split1_ID_TOPIC
GROUP BY t.ID_TOPIC", __FILE__, __LINE__);
list ($split1_firstMsg, $orig_lastMsg, $orig_replies, $isSticky) = mysql_fetch_row($tresult);
mysql_free_result($tresult);
$split1_firstMem = getMsgMemberID($split1_firstMsg);
$orig_lastMem = getMsgMemberID($orig_lastMsg);
// If you're not trying to do a selective on the first message.. what are you doing?
if ($_POST['at'] == $split1_firstMsg)
fatal_lang_error('smf268');
// If you are splitting all those after, or "onlythis" and this is the last post...
if ($_POST['step2'] == 'afterthis' || $orig_lastMsg == $split2_firstMsg)
{
// By logic, the new last message/member is the original last message/member.
$split2_lastMsg = $orig_lastMsg;
$split2_lastMem = $orig_lastMem;
// Find the last message and member of the old topic.
$request = db_query("
SELECT m.ID_MSG, IFNULL(mem.ID_MEMBER, 0) AS myID_MEMBER
FROM {$db_prefix}messages AS m
LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = m.ID_MEMBER)
WHERE ID_TOPIC = $split1_ID_TOPIC
AND ID_MSG < $_POST[at]
ORDER BY ID_MSG DESC
LIMIT 1", __FILE__, __LINE__);
list ($split1_lastMsg, $split1_lastMem) = mysql_fetch_row($request);
mysql_free_result($request);
// Find the number of replies for the new topic - thus finding the old as well.
$request = db_query("
SELECT COUNT(ID_MSG) - 1 AS numReplies
FROM {$db_prefix}messages
WHERE ID_TOPIC = $split1_ID_TOPIC
AND ID_MSG >= $_POST[at]", __FILE__, __LINE__);
list ($split2_replies) = mysql_fetch_row($request);
mysql_free_result($request);
$split1_replies = $orig_replies - $split2_replies - 1;
}
elseif ($_POST['step2'] == 'onlythis')
{
// If you're only splitting off this message, things are simple.
$split1_lastMsg = $orig_lastMsg;
$split1_lastMem = $orig_lastMem;
// Only one message - no replies.
$split2_lastMsg = $split2_firstMsg;
$split2_lastMem = $split2_firstMem;
$split2_replies = 0;
$split1_replies = $orig_replies - 1;
}
// There's another action?!
else
fatal_lang_error(1, false);
// No db changes yet, so let's double check to see if something got messed up.
if ($split1_firstMsg <= 0 || $split1_lastMsg <= 0 || $split2_firstMsg <= 0 || $split2_lastMsg <= 0 || $split1_replies < 0 || $split2_replies < 0)
fatal_lang_error('smf272');
// Make the new topic, but use 0 for the last and first ID_MSG to avoid UNIQUE errors. (fix 'em at the end!)
db_query("
INSERT INTO {$db_prefix}topics
(ID_BOARD, ID_MEMBER_STARTED, ID_MEMBER_UPDATED, ID_FIRST_MSG, ID_LAST_MSG, numReplies, isSticky)
VALUES ($board, $split2_firstMem, $split2_firstMem, 0, 0, $split2_replies, $isSticky)", __FILE__, __LINE__);
$split2_ID_TOPIC = db_insert_id();
if ($split2_ID_TOPIC <= 0)
fatal_lang_error('smf273');
// 'Move' the messages.
db_query("
UPDATE {$db_prefix}messages
SET ID_TOPIC = $split2_ID_TOPIC
WHERE ID_TOPIC = $split1_ID_TOPIC
AND (ID_MSG BETWEEN $split2_firstMsg AND $split2_lastMsg)
LIMIT " . ($split2_lastMsg - $split2_firstMsg + 1), __FILE__, __LINE__);
// Set the subject of the first message of the new topic.
db_query("
UPDATE {$db_prefix}messages
SET subject = '" . preg_replace('~&amp;#(\d{4,5}|[3-9]\d{2,4}|2[6-9]\d);~', '&#$1;', htmlspecialchars($_POST['subname'])) . "'
WHERE ID_MSG = $_POST[at]
LIMIT 1", __FILE__, __LINE__);
// Mess with the new first message, etc.
db_query("
UPDATE {$db_prefix}topics
SET ID_FIRST_MSG = $split1_firstMsg, ID_LAST_MSG = $split1_lastMsg, numReplies = $split1_replies,
ID_MEMBER_STARTED = $split1_firstMem, ID_MEMBER_UPDATED = $split1_lastMem
WHERE ID_TOPIC = $split1_ID_TOPIC
LIMIT 1", __FILE__, __LINE__);
// Now, put the first/last message back to what they should be.
db_query("
UPDATE {$db_prefix}topics
SET ID_FIRST_MSG = $split2_firstMsg, ID_LAST_MSG = $split2_lastMsg
WHERE ID_TOPIC = $split2_ID_TOPIC
LIMIT 1", __FILE__, __LINE__);
// The board has more topics now.
db_query("
UPDATE {$db_prefix}boards
SET numTopics = numTopics + 1
WHERE ID_BOARD = $board
LIMIT 1", __FILE__, __LINE__);
// The user has to have read it, hopefully, because they split it!
db_query("
REPLACE INTO {$db_prefix}log_topics
(logTime, ID_MEMBER, ID_TOPIC)
VALUES (" . time() . ", $ID_MEMBER, $split2_ID_TOPIC)", __FILE__, __LINE__);
// Clean up.
updateStats('topic');
updateLastMessages($board);
$context['old_topic'] = $split1_ID_TOPIC;
$context['new_topic'] = $split2_ID_TOPIC;
$context['page_title'] = $txt['smf251'];
logAction('split', array('topic' => $topic, 'new_topic' => $split2_ID_TOPIC));
// Notify people that this topic has been split?
sendNotifications($topic, 'split');
}
// Get a selective list of topics...
function SplitTopics3()
{
global $txt, $scripturl, $topic, $db_prefix, $context, $modSettings;
$context['page_title'] = $txt['smf251'] . ' - ' . $txt['smf257'];
// Some stuff for our favorite template.
$context['new_subject'] = stripslashes($_REQUEST['subname']);
// Get the maximum number of messages.
$result = db_query("
SELECT COUNT(ID_MSG)
FROM {$db_prefix}messages
WHERE ID_TOPIC = $topic", __FILE__, __LINE__);
list ($maxmessages) = mysql_fetch_row($result);
mysql_free_result($result);
// Build a page list.
$context['page_index'] = constructPageIndex($scripturl . '?action=splittopics;sa=3;subname=' . urlencode($_REQUEST['subname']) . ';topic=' . $topic, $_REQUEST['start'], $maxmessages, $modSettings['defaultMaxMessages'], true);
// Get the messages and stick them into an array.
$tresult = db_query("
SELECT m.subject, IFNULL(mem.realName, m.posterName) AS realName, m.body, m.ID_MSG
FROM {$db_prefix}messages AS m
LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = m.ID_MEMBER)
WHERE m.ID_TOPIC = $topic
ORDER BY m.ID_MSG DESC
LIMIT $_REQUEST[start], $modSettings[defaultMaxMessages]", __FILE__, __LINE__);
$context['messages'] = array();
while ($row = mysql_fetch_assoc($tresult))
{
$row['body'] = doUBBC($row['body']);
$context['messages'][] = array(
'subject' => $row['subject'],
'body' => $row['body'],
'id' => $row['ID_MSG'],
'poster' => $row['realName']
);
}
mysql_free_result($tresult);
// Using the "select" sub template.
$context['sub_template'] = 'select';
}
// Actually and selectively split the topics out.
function SplitTopics4()
{
global $txt, $board, $topic, $db_prefix, $context, $ID_MEMBER;
// Make sure the session id was passed with post.
checkSession();
// Default the subject in case it's blank.
if (!isset($_POST['subname']) || $_POST['subname'] == '')
$_POST['subname'] = $txt['smf258'];
// The old topic's ID is the current one.
$split1_ID_TOPIC = $topic;
// You must've selected some messages! Can't split out none!
if (empty($_POST['selpost']))
fatal_lang_error('smf271', false);
// No sense in imploding it over and over again.
$postList = implode(',', array_keys($_POST['selpost']));
// Find the new first and last not in the list. (old topic)
$result = db_query("
SELECT MIN(m.ID_MSG) AS myID_FIRST_MSG, MAX(m.ID_MSG) AS myID_LAST_MSG, COUNT(m.ID_MSG) - 1 AS myNumReplies, t.isSticky
FROM {$db_prefix}messages AS m, {$db_prefix}topics AS t
WHERE m.ID_MSG NOT IN ($postList)
AND m.ID_TOPIC = $split1_ID_TOPIC
AND t.ID_TOPIC = $split1_ID_TOPIC
GROUP BY m.ID_TOPIC
LIMIT 1", __FILE__, __LINE__);
// You can't select ALL the messages!
if (mysql_num_rows($result) == 0)
fatal_lang_error('smf271b', false);
list ($split1_firstMsg, $split1_lastMsg, $split1_replies, $isSticky) = mysql_fetch_row($result);
mysql_free_result($result);
$split1_firstMem = getMsgMemberID($split1_firstMsg);
$split1_lastMem = getMsgMemberID($split1_lastMsg);
// Find the first and last in the list. (new topic)
$result = db_query("
SELECT MIN(ID_MSG) AS myID_FIRST_MSG, MAX(ID_MSG) AS myID_LAST_MSG, COUNT(ID_MSG) - 1 AS myNumReplies
FROM {$db_prefix}messages
WHERE ID_MSG IN ($postList)
AND ID_TOPIC = $split1_ID_TOPIC
GROUP BY ID_TOPIC
LIMIT 1", __FILE__, __LINE__);
list ($split2_firstMsg, $split2_lastMsg, $split2_replies) = mysql_fetch_row($result);
mysql_free_result($result);
$split2_firstMem = getMsgMemberID($split2_firstMsg);
$split2_lastMem = getMsgMemberID($split2_lastMsg);
// No database changes yet, so let's double check to see if everything makes at least a little sense.
if ($split1_firstMsg <= 0 || $split1_lastMsg <= 0 || $split2_firstMsg <= 0 || $split2_lastMsg <= 0 || $split1_replies < 0 || $split2_replies < 0)
fatal_lang_error('smf272');
// We're off to insert the new topic! Use 0 for now to avoid UNIQUE errors.
db_query("
INSERT INTO {$db_prefix}topics
(ID_BOARD, ID_MEMBER_STARTED, ID_MEMBER_UPDATED, ID_FIRST_MSG, ID_LAST_MSG, numReplies, isSticky)
VALUES ($board, $split2_firstMem, $split2_lastMem, 0, 0, $split2_replies, $isSticky)", __FILE__, __LINE__);
$split2_ID_TOPIC = db_insert_id();
if ($split2_ID_TOPIC <= 0)
fatal_lang_error('smf273');
// Move the messages over to the other topic.
db_query("
UPDATE {$db_prefix}messages
SET ID_TOPIC = $split2_ID_TOPIC, subject = '" . preg_replace('~&amp;#(\d{4,5}|[3-9]\d{2,4}|2[6-9]\d);~', '&#$1;', htmlspecialchars($_POST['subname'])) . "'
WHERE ID_MSG IN ($postList)
LIMIT " . count($_POST['selpost']), __FILE__, __LINE__);
// Mess with the old topic's first, last, and number of messages.
db_query("
UPDATE {$db_prefix}topics
SET numReplies = $split1_replies, ID_FIRST_MSG = $split1_firstMsg, ID_LAST_MSG = $split1_lastMsg,
ID_MEMBER_STARTED = $split1_firstMem, ID_MEMBER_UPDATED = $split1_lastMem
WHERE ID_TOPIC = $split1_ID_TOPIC
LIMIT 1", __FILE__, __LINE__);
// Now, put the first/last message back to what they should be.
db_query("
UPDATE {$db_prefix}topics
SET ID_FIRST_MSG = $split2_firstMsg, ID_LAST_MSG = $split2_lastMsg
WHERE ID_TOPIC = $split2_ID_TOPIC
LIMIT 1", __FILE__, __LINE__);
// The board has more topics now.
db_query("
UPDATE {$db_prefix}boards
SET numTopics = numTopics + 1
WHERE ID_BOARD = $board
LIMIT 1", __FILE__, __LINE__);
// The user has to have read it, hopefully, because they split it!
db_query("
REPLACE INTO {$db_prefix}log_topics
(logTime, ID_MEMBER, ID_TOPIC)
VALUES (" . time() . ", $ID_MEMBER, $split2_ID_TOPIC)", __FILE__, __LINE__);
// Housekeeping.
updateStats('topic');
updateLastMessages($board);
$context['old_topic'] = $split1_ID_TOPIC;
$context['new_topic'] = $split2_ID_TOPIC;
$context['page_title'] = $txt['smf251'];
logAction('split', array('topic' => $topic, 'new_topic' => $split2_ID_TOPIC));
// Notify people that this topic has been split?
sendNotifications($topic, 'split');
}
// Merge two topics into one topic... useful if they have the same basic subject.
function MergeTopics()
{
// Load the template....
loadTemplate('SplitTopics');
// ?action=splittopics;sa=LETSBREAKIT won't work, sorry.
if (!isset($_REQUEST['sa']) || !is_numeric($_REQUEST['sa']) || $_REQUEST['sa'] < 1 || $_REQUEST['sa'] > 4)
$subAction = 'MergeTopics1';
else
$subAction = 'MergeTopics' . (int) $_REQUEST['sa'];
$subAction();
}
// Merge two topics together.
function MergeTopics1()
{
global $txt, $board, $context;
global $scripturl, $topic, $db_prefix, $user_info, $modSettings;
$_REQUEST['targetboard'] = isset($_REQUEST['targetboard']) ? (int) $_REQUEST['targetboard'] : $board;
$context['target_board'] = $_REQUEST['targetboard'];
// How many topics are on this board? (used for paging.)
$request = db_query("
SELECT COUNT(ID_TOPIC)
FROM {$db_prefix}topics
WHERE ID_BOARD = $_REQUEST[targetboard]", __FILE__, __LINE__);
list ($topiccount) = mysql_fetch_row($request);
mysql_free_result($request);
// Make the page list.
$context['page_index'] = constructPageIndex($scripturl . '?action=mergetopics;from=' . $_GET['from'] . ';targetboard=' . $_REQUEST['targetboard'] . ';board=' . $board, $_REQUEST['start'], $topiccount, $modSettings['defaultMaxTopics'], true);
// Get the topic's subject.
$request = db_query("
SELECT m.subject
FROM {$db_prefix}messages AS m, {$db_prefix}topics AS t
WHERE m.ID_MSG = t.ID_FIRST_MSG
AND t.ID_TOPIC = $_GET[from]
AND t.ID_BOARD = $board
LIMIT 1", __FILE__, __LINE__);
if (mysql_num_rows($request) == 0)
fatal_lang_error('smf232');
list ($subject) = mysql_fetch_row($request);
mysql_free_result($request);
// Tell the template a few things..
$context['origin_topic'] = $_GET['from'];
$context['origin_subject'] = $subject;
$context['origin_js_subject'] = addcslashes(addslashes($subject), '/');
$context['page_title'] = $txt['smf252'];
// Check which boards you have merge permissions on.
$merge_boards = boardsAllowedTo('merge_any');
if (empty($merge_boards))
fatal_lang_error('cannot_merge_any');
// Get a list of boards they can navigate to to merge.
$request = db_query("
SELECT b.ID_BOARD, b.name AS bName, c.name AS cName
FROM {$db_prefix}boards AS b, {$db_prefix}categories AS c
WHERE b.ID_CAT = c.ID_CAT
AND $user_info[query_see_board]" . (!in_array(0, $merge_boards) ? "
AND b.ID_BOARD IN (" . implode(', ', $merge_boards) . ")" : '') . "
ORDER BY c.catOrder, b.boardOrder", __FILE__, __LINE__);
$context['boards'] = array();
while ($row = mysql_fetch_assoc($request))
$context['boards'][] = array(
'id' => $row['ID_BOARD'],
'name' => $row['bName'],
'category' => $row['cName']
);
mysql_free_result($request);
// Get some topics to merge it with.
$request = db_query("
SELECT t.ID_TOPIC, m.subject, m.ID_MEMBER, IFNULL(mem.realName, m.posterName) AS posterName
FROM ({$db_prefix}topics AS t, {$db_prefix}messages AS m, {$db_prefix}messages AS m2)
LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = m.ID_MEMBER)
WHERE m.ID_MSG = t.ID_FIRST_MSG
AND m2.ID_MSG = t.ID_LAST_MSG
AND t.ID_BOARD = $_REQUEST[targetboard]
AND t.ID_TOPIC != $_GET[from]
ORDER BY " . (!empty($modSettings['enableStickyTopics']) ? 't.isSticky DESC, ' : '') . "m2.posterTime DESC
LIMIT $_REQUEST[start], $modSettings[defaultMaxTopics]", __FILE__, __LINE__);
$context['topics'] = array();
while ($row = mysql_fetch_assoc($request))
{
censorText($row['subject']);
$context['topics'][] = array(
'id' => $row['ID_TOPIC'],
'poster' => array(
'id' => $row['ID_MEMBER'],
'name' => $row['posterName'],
'href' => empty($row['ID_MEMBER']) ? '' : $scripturl . '?action=profile;u=' . $row['ID_MEMBER'],
'link' => empty($row['ID_MEMBER']) ? $row['posterName'] : '<a href="' . $scripturl . '?action=profile;u=' . $row['ID_MEMBER'] . '" target="_blank">' . $row['posterName'] . '</a>'
),
'subject' => $row['subject'],
'js_subject' => addcslashes(addslashes($row['subject']), '/')
);
}
$context['sub_template'] = 'merge';
}
// Now that the topic IDs are known, do the proper merging.
function MergeTopics2($topics = array())
{
global $db_prefix, $user_info, $txt, $context, $scripturl, $sourcedir;
// The parameters of MergeTopics2 were set, so this must've been an internal call.
if (!empty($topics))
{
isAllowedTo('merge_any');
loadTemplate('SplitTopics');
}
// Handle URLs from MergeTopics1.
if (!empty($_GET['from']) && !empty($_GET['to']))
$topics = array($_GET['from'], $_GET['to']);
// If we came from a form, the topic IDs came by post.
if (!empty($_POST['topics']) && is_array($_POST['topics']))
$topics = $_POST['topics'];
// There's nothing to merge with just one topic...
if (empty($topics) || !is_array($topics) || count($topics) == 1)
fatal_lang_error('merge_need_more_topics');
// Make sure every topic is numeric, or some nasty things could be done with the DB.
foreach ($topics as $id => $topic)
$topics[$id] = (int) $topic;
// Get info about the topics and polls that will be merged.
$request = db_query("
SELECT
t.ID_TOPIC, t.ID_BOARD, t.ID_POLL, t.numViews, t.isSticky,
m1.subject, m1.posterTime AS time_started, IFNULL(mem1.ID_MEMBER, 0) AS ID_MEMBER_STARTED, IFNULL(mem1.realName, m1.posterName) AS name_started,
m2.posterTime AS time_updated, IFNULL(mem2.ID_MEMBER, 0) AS ID_MEMBER_UPDATED, IFNULL(mem2.realName, m2.posterName) AS name_updated
FROM ({$db_prefix}topics AS t, {$db_prefix}messages AS m1, {$db_prefix}messages AS m2)
LEFT JOIN {$db_prefix}members AS mem1 ON (mem1.ID_MEMBER = m1.ID_MEMBER)
LEFT JOIN {$db_prefix}members AS mem2 ON (mem2.ID_MEMBER = m2.ID_MEMBER)
WHERE t.ID_TOPIC IN (" . implode(', ', $topics) . ")
AND m1.ID_MSG = t.ID_FIRST_MSG
AND m2.ID_MSG = t.ID_LAST_MSG
ORDER BY t.ID_FIRST_MSG
LIMIT " . count($topics), __FILE__, __LINE__);
if (mysql_num_rows($request) < 2)
fatal_lang_error('smf263');
$num_views = 0;
$isSticky = 0;
$boards = array();
$polls = array();
while ($row = mysql_fetch_assoc($request))
{
$topic_data[$row['ID_TOPIC']] = array(
'id' => $row['ID_TOPIC'],
'board' => $row['ID_BOARD'],
'poll' => $row['ID_POLL'],
'numViews' => $row['numViews'],
'subject' => $row['subject'],
'started' => array(
'time' => timeformat($row['time_started']),
'timestamp' => $row['time_started'],
'href' => empty($row['ID_MEMBER_STARTED']) ? '' : $scripturl . '?action=profile;u=' . $row['ID_MEMBER_STARTED'],
'link' => empty($row['ID_MEMBER_STARTED']) ? $row['name_started'] : '<a href="' . $scripturl . '?action=profile;u=' . $row['ID_MEMBER_STARTED'] . '">' . $row['name_started'] . '</a>'
),
'updated' => array(
'time' => timeformat($row['time_updated']),
'timestamp' => $row['time_updated'],
'href' => empty($row['ID_MEMBER_UPDATED']) ? '' : $scripturl . '?action=profile;u=' . $row['ID_MEMBER_UPDATED'],
'link' => empty($row['ID_MEMBER_UPDATED']) ? $row['name_updated'] : '<a href="' . $scripturl . '?action=profile;u=' . $row['ID_MEMBER_UPDATED'] . '">' . $row['name_updated'] . '</a>'
)
);
$num_views += $row['numViews'];
$boards[] = $row['ID_BOARD'];
// If there's no poll, ID_POLL == 0.
if ($row['ID_POLL'] > 0)
$polls[] = $row['ID_POLL'];
// Store the ID_TOPIC with the lowest ID_FIRST_MSG.
if (empty($firstTopic))
$firstTopic = $row['ID_TOPIC'];
$isSticky = max($isSticky, $row['isSticky']);
}
mysql_free_result($request);
$boards = array_values(array_unique($boards));
// Get the boards a user is allowed to merge in.
$merge_boards = boardsAllowedTo('merge_any');
if (empty($merge_boards))
fatal_lang_error('cannot_merge_any');
// Make sure they can see all boards....
$request = db_query("
SELECT b.ID_BOARD
FROM {$db_prefix}boards AS b
WHERE b.ID_BOARD IN (" . implode(', ', $boards) . ")
AND $user_info[query_see_board]" . (!in_array(0, $merge_boards) ? "
AND b.ID_BOARD IN (" . implode(', ', $merge_boards) . ")" : '') . "
LIMIT " . count($boards), __FILE__, __LINE__);
// If the number of boards that's in the output isn't exactly the same as we've put in there, you're in trouble.
if (mysql_num_rows($request) != count($boards))
fatal_lang_error('smf232');
mysql_free_result($request);
if (empty($_POST['sa']) || (int) $_POST['sa'] != 2)
{
if (count($polls) > 1)
{
$request = db_query("
SELECT t.ID_TOPIC, t.ID_POLL, m.subject, p.question
FROM {$db_prefix}polls AS p, {$db_prefix}topics AS t, {$db_prefix}messages AS m
WHERE p.ID_POLL IN (" . implode(', ', $polls) . ")
AND t.ID_POLL = p.ID_POLL
AND m.ID_MSG = t.ID_FIRST_MSG
LIMIT " . count($polls), __FILE__, __LINE__);
while ($row = mysql_fetch_assoc($request))
$context['polls'][] = array(
'id' => $row['ID_POLL'],
'topic' => array(
'id' => $row['ID_TOPIC'],
'subject' => $row['subject']
),
'question' => $row['question'],
'selected' => $row['ID_TOPIC'] == $firstTopic
);
mysql_free_result($request);
}
if (count($boards) > 1)
{
$request = db_query("
SELECT ID_BOARD, name
FROM {$db_prefix}boards
WHERE ID_BOARD IN (" . implode(', ', $boards) . ")
ORDER BY name
LIMIT " . count($boards), __FILE__, __LINE__);
while ($row = mysql_fetch_assoc($request))
$context['boards'][] = array(
'id' => $row['ID_BOARD'],
'name' => $row['name'],
'selected' => $row['ID_BOARD'] == $topic_data[$firstTopic]['board']
);
}
$context['topics'] = $topic_data;
foreach ($topic_data as $id => $topic)
$context['topics'][$id]['selected'] = $topic['id'] == $firstTopic;
$context['page_title'] = $txt['smf252'];
$context['sub_template'] = 'merge_extra_options';
return;
}
// Determine target board.
$target_board = count($boards) > 1 ? (int) $_POST['board'] : $boards[0];
if (!in_array($target_board, $boards))
fatal_lang_error('smf232');
// Determine which poll will survive and which polls won't.
$target_poll = count($polls) > 1 ? (int) $_POST['poll'] : (count($polls) == 1 ? $polls[0] : -1);
if ($target_poll > 0 && !in_array($target_poll, $polls))
fatal_lang_error(1, false);
$deleted_polls = empty($target_poll) ? $polls : array_diff($polls, array($target_poll));
// Determine the subject of the newly merged topic - was a custom subject was filled in?
if (empty($_POST['subject']) && isset($_POST['custom_subject']) && $_POST['custom_subject'] != '')
$target_subject = preg_replace('~&amp;#(\d{4,5}|[3-9]\d{2,4}|2[6-9]\d);~', '&#$1;', htmlspecialchars($_POST['custom_subject']));
// A subject was selected...
elseif (!empty($topic_data[(int) $_POST['subject']]['subject']))
$target_subject = addslashes($topic_data[(int) $_POST['subject']]['subject']);
// Nothing worked? Just take the subject of the first message.
else
$target_subject = addslashes($topic_data[$firstTopic]['subject']);
// Get the first and last message and the number of messages....
$request = db_query("
SELECT MIN(ID_MSG), MAX(ID_MSG), COUNT(ID_MSG) - 1
FROM {$db_prefix}messages
WHERE ID_TOPIC IN (" . implode(', ', $topics) . ")", __FILE__, __LINE__);
list ($first_msg, $last_msg, $num_replies) = mysql_fetch_row($request);
mysql_free_result($request);
// Get the member ID of the first and last message.
$request = db_query("
SELECT ID_MEMBER
FROM {$db_prefix}messages
WHERE ID_MSG IN ($first_msg, $last_msg)
ORDER BY ID_MSG
LIMIT 2", __FILE__, __LINE__);
list ($member_started) = mysql_fetch_row($request);
list ($member_updated) = mysql_fetch_row($request);
mysql_free_result($request);
// Delete the old topics....
db_query("
DELETE FROM {$db_prefix}topics
WHERE ID_TOPIC IN (" . implode(', ', $topics) . ")
LIMIT " . count($topics), __FILE__, __LINE__);
// Insert a new topic.
db_query("
INSERT INTO {$db_prefix}topics
(ID_BOARD, ID_MEMBER_STARTED, ID_MEMBER_UPDATED, ID_FIRST_MSG, ID_LAST_MSG, ID_POLL, numReplies, numViews, isSticky)
VALUES ($target_board, $member_started, $member_updated, $first_msg, $last_msg, $target_poll, $num_replies, $num_views, $isSticky)", __FILE__, __LINE__);
$ID_TOPIC = db_insert_id();
// Something went wrong creating the new topic.
if (empty($ID_TOPIC))
fatal_lang_error('merge_create_topic_failed');
// Change the topic IDs of all messages that will be merged. Also adjust subjects if 'enforce subject' was checked.
db_query("
UPDATE {$db_prefix}messages
SET ID_TOPIC = $ID_TOPIC, ID_BOARD = $target_board" . (!empty($_POST['enforce_subject']) ? ", subject = '$txt[response_prefix]$target_subject'" : '') . "
WHERE ID_TOPIC IN (" . implode(', ', $topics) . ")", __FILE__, __LINE__);
// Change the subject of the first message.
db_query("
UPDATE {$db_prefix}messages
SET subject = '$target_subject'
WHERE ID_MSG = $first_msg
LIMIT 1", __FILE__, __LINE__);
// Adjust all calendar events to point to the new topic.
db_query("
UPDATE {$db_prefix}calendar
SET ID_TOPIC = $ID_TOPIC, ID_BOARD = $target_board
WHERE ID_TOPIC IN (" . implode(', ', $topics) . ")", __FILE__, __LINE__);
// Merge log topic entries.
$request = db_query("
SELECT ID_MEMBER, MIN(logTime) AS newLogTime
FROM {$db_prefix}log_topics
WHERE ID_TOPIC IN (" . implode(', ', $topics) . ")
GROUP BY ID_MEMBER", __FILE__, __LINE__);
if (mysql_num_rows($request) > 0)
{
$insertEntries = array();
while ($row = mysql_fetch_assoc($request))
$insertEntries[] = "($row[ID_MEMBER], $ID_TOPIC, $row[newLogTime])";
db_query("
REPLACE INTO {$db_prefix}log_topics
(ID_MEMBER, ID_TOPIC, logTime)
VALUES " . implode(', ', $insertEntries), __FILE__, __LINE__);
unset($insertEntries);
// Get rid of the old log entries.
db_query("
DELETE FROM {$db_prefix}log_topics
WHERE ID_TOPIC IN (" . implode(', ', $topics) . ")", __FILE__, __LINE__);
}
mysql_free_result($request);
// Merge topic notifications.
if (!empty($_POST['notifications']) && is_array($_POST['notifications']))
{
// Check if the notification array contains valid topics.
if (count(array_diff($_POST['notifications'], $topics)) > 0)
fatal_lang_error('smf232');
$request = db_query("
SELECT ID_MEMBER, MAX(sent) AS sent
FROM {$db_prefix}log_notify
WHERE ID_TOPIC IN (" . implode(', ', $_POST['notifications']) . ")
GROUP BY ID_MEMBER", __FILE__, __LINE__);
if (mysql_num_rows($request) > 0)
{
$insertEntries = array();
while ($row = mysql_fetch_assoc($request))
$insertEntries[] = "($row[ID_MEMBER], $ID_TOPIC, 0, $row[sent])";
db_query("
INSERT INTO {$db_prefix}log_notify
(ID_MEMBER, ID_TOPIC, ID_BOARD, sent)
VALUES " . implode(', ', $insertEntries), __FILE__, __LINE__);
unset($insertEntries);
db_query("
DELETE FROM {$db_prefix}log_topics
WHERE ID_TOPIC IN (" . implode(', ', $topics) . ")", __FILE__, __LINE__);
}
mysql_free_result($request);
}
// Get rid of the redundant polls.
if (!empty($deleted_polls))
{
db_query("
DELETE FROM {$db_prefix}polls
WHERE ID_POLL IN (" . implode(', ', $deleted_polls) . ")
LIMIT 1", __FILE__, __LINE__);
db_query("
DELETE FROM {$db_prefix}poll_choices
WHERE ID_POLL IN (" . implode(', ', $deleted_polls) . ")", __FILE__, __LINE__);
db_query("
DELETE FROM {$db_prefix}log_polls
WHERE ID_POLL IN (" . implode(', ', $deleted_polls) . ")", __FILE__, __LINE__);
}
// Fix the board totals.
if (count($boards) > 1)
{
$request = db_query("
SELECT ID_BOARD, COUNT(ID_TOPIC) AS numTopics, SUM(numReplies) + COUNT(ID_TOPIC) AS numPosts
FROM {$db_prefix}topics
WHERE ID_BOARD IN (" . implode(', ', $boards) . ")
GROUP BY ID_BOARD
LIMIT " . count($boards), __FILE__, __LINE__);
while ($row = mysql_fetch_assoc($request))
db_query("
UPDATE {$db_prefix}boards
SET numPosts = $row[numPosts], numTopics = $row[numTopics]
WHERE ID_BOARD = $row[ID_BOARD]
LIMIT 1", __FILE__, __LINE__);
mysql_free_result($request);
}
else
db_query("
UPDATE {$db_prefix}boards
SET numTopics = numTopics - " . (count($topics) - 1) . "
WHERE ID_BOARD = $target_board
LIMIT 1", __FILE__, __LINE__);
// Update all the statistics.
updateStats('topic');
updateLastMessages($boards);
logAction('merge', array('topic' => $ID_TOPIC));
// Notify people that these topics have been merged?
require_once($sourcedir . '/Subs-Post.php');
sendNotifications($ID_TOPIC, 'merge');
// Send them to the all done page.
redirectexit('action=mergetopics;sa=3;to=' . $ID_TOPIC . ';targetboard=' . $target_board);
}
// Tell the user the move was done properly.
function MergeTopics3()
{
global $txt, $context;
// Make sure the template knows everything...
$context['target_board'] = $_GET['targetboard'];
$context['target_topic'] = $_GET['to'];
$context['page_title'] = $txt['smf252'];
$context['sub_template'] = 'merge_done';
}
// "link" topics: make one related to another, so users will get a number of
// "Related topics" links
function LinkTopics()
{
// Load the template....
loadTemplate('SplitTopics');
// ?action=splittopics;sa=LETSBREAKIT won't work, sorry.
if (!isset($_REQUEST['sa']) || !is_numeric($_REQUEST['sa']) || $_REQUEST['sa'] < 1 || $_REQUEST['sa'] > 4)
$subAction = 'LinkTopics1';
else
$subAction = 'LinkTopics' . (int) $_REQUEST['sa'];
$subAction();
}
//
function LinkTopics1()
{
global $txt, $board, $context;
global $scripturl, $topic, $db_prefix, $user_info, $modSettings;
$_REQUEST['targetboard'] = isset($_REQUEST['targetboard']) ? (int) $_REQUEST['targetboard'] : $board;
$context['target_board'] = $_REQUEST['targetboard'];
// How many topics are on this board? (used for paging.)
$request = db_query("
SELECT COUNT(ID_TOPIC)
FROM {$db_prefix}topics
WHERE ID_BOARD = $_REQUEST[targetboard]", __FILE__, __LINE__);
list ($topiccount) = mysql_fetch_row($request);
mysql_free_result($request);
// Make the page list.
$context['page_index'] = constructPageIndex($scripturl . '?action=linktopics;from=' . $_GET['from'] . ';targetboard=' . $_REQUEST['targetboard'] . ';board=' . $board, $_REQUEST['start'], $topiccount, $modSettings['defaultMaxTopics'], true);
// Get the topic's subject.
$request = db_query("
SELECT m.subject
FROM {$db_prefix}messages AS m, {$db_prefix}topics AS t
WHERE m.ID_MSG = t.ID_FIRST_MSG
AND t.ID_TOPIC = $_GET[from]
AND t.ID_BOARD = $board
LIMIT 1", __FILE__, __LINE__);
if (mysql_num_rows($request) == 0)
fatal_lang_error('smf232');
list ($subject) = mysql_fetch_row($request);
mysql_free_result($request);
// Tell the template a few things..
$context['origin_topic'] = $_GET['from'];
$context['origin_subject'] = $subject;
$context['origin_js_subject'] = addcslashes(addslashes($subject), '/');
$context['page_title'] = $txt['smf252'];
// Check which boards you have merge permissions on.
$merge_boards = boardsAllowedTo('merge_any');
if (empty($merge_boards))
fatal_lang_error('cannot_merge_any');
// Get a list of boards they can navigate to to merge.
$request = db_query("
SELECT b.ID_BOARD, b.name AS bName, c.name AS cName
FROM {$db_prefix}boards AS b, {$db_prefix}categories AS c
WHERE b.ID_CAT = c.ID_CAT
AND $user_info[query_see_board]" . (!in_array(0, $merge_boards) ? "
AND b.ID_BOARD IN (" . implode(', ', $merge_boards) . ")" : '') . "
ORDER BY c.catOrder, b.boardOrder", __FILE__, __LINE__);
$context['boards'] = array();
while ($row = mysql_fetch_assoc($request))
$context['boards'][] = array(
'id' => $row['ID_BOARD'],
'name' => $row['bName'],
'category' => $row['cName']
);
mysql_free_result($request);
// Get some topics to merge it with.
$request = db_query("
SELECT t.ID_TOPIC, m.subject, m.ID_MEMBER, IFNULL(mem.realName, m.posterName) AS posterName
FROM ({$db_prefix}topics AS t, {$db_prefix}messages AS m, {$db_prefix}messages AS m2)
LEFT JOIN {$db_prefix}members AS mem ON (mem.ID_MEMBER = m.ID_MEMBER)
WHERE m.ID_MSG = t.ID_FIRST_MSG
AND m2.ID_MSG = t.ID_LAST_MSG
AND t.ID_BOARD = $_REQUEST[targetboard]
AND t.ID_TOPIC != $_GET[from]
ORDER BY " . (!empty($modSettings['enableStickyTopics']) ? 't.isSticky DESC, ' : '') . "m2.posterTime DESC
LIMIT $_REQUEST[start], $modSettings[defaultMaxTopics]", __FILE__, __LINE__);
$context['topics'] = array();
while ($row = mysql_fetch_assoc($request))
{
censorText($row['subject']);
$context['topics'][] = array(
'id' => $row['ID_TOPIC'],
'poster' => array(
'id' => $row['ID_MEMBER'],
'name' => $row['posterName'],
'href' => empty($row['ID_MEMBER']) ? '' : $scripturl . '?action=profile;u=' . $row['ID_MEMBER'],
'link' => empty($row['ID_MEMBER']) ? $row['posterName'] : '<a href="' . $scripturl . '?action=profile;u=' . $row['ID_MEMBER'] . '" target="_blank">' . $row['posterName'] . '</a>'
),
'subject' => $row['subject'],
'js_subject' => addcslashes(addslashes($row['subject']), '/')
);
}
$context['sub_template'] = 'link';
}
// Now that the topic IDs are known, do the proper linking.
function LinkTopics2($topics = array())
{
global $db_prefix, $user_info, $txt, $context, $scripturl, $sourcedir;
// The parameters of MergeTopics2 were set, so this must've been an internal call.
if (!empty($topics))
{
isAllowedTo('merge_any');
loadTemplate('SplitTopics');
}
// Handle URLs from MergeTopics1.
if (!empty($_GET['from']) && !empty($_GET['to']))
$topics = array($_GET['from'], $_GET['to']);
// If we came from a form, the topic IDs came by post.
if (!empty($_POST['topics']) && is_array($_POST['topics']))
$topics = $_POST['topics'];
// There's nothing to merge with just one topic...
if (empty($topics) || !is_array($topics) || count($topics) == 1)
fatal_lang_error('merge_need_more_topics');
// Make sure every topic is numeric, or some nasty things could be done with the DB.
foreach ($topics as $id => $topic)
$topics[$id] = (int) $topic;
$request=db_query("
SELECT ID_TOPIC FROM {$db_prefix}topics
WHERE ID_TOPIC IN (". implode(",",$topics).")"
,__FILE__, __LINE__);
if(mysql_num_rows($request)!=2)
fatal_lang_error('merge_need_more_topics');
db_query("
INSERT INTO {$db_prefix}related_topics
VALUES({$topics[0]}, {$topics[1]})",
__FILE__, __LINE__);
logAction('link', array('topic' => $ID_TOPIC));
// Send them to the all done page.
redirectexit('action=linktopics;sa=3;to=' . $topics[0] . ';targetboard=' . $_GET['targetboard']);
}
// Tell the user the move was done properly.
function LinkTopics3()
{
global $txt, $context;
// Make sure the template knows everything...
$context['target_board'] = $_GET['targetboard'];
$context['target_topic'] = $_GET['to'];
$context['page_title'] = $txt['smf252'];
$context['sub_template'] = 'merge_done';
}
?>