mirror of
https://github.com/phpbb/phpbb.git
synced 2025-05-09 17:15:19 +02:00
Rewrote this stuff so that it is all multiple object oriented instead of looping single objects... The way it is written, there should be no speed decrease (and in some places, a speed increase) and maybe a miniscule amount of extra memory used in the move_topics function... Everything in there should be O(n) where n is the number of topics or posts being delete or moved or whatever. Multiple topic insertions are not supported as I cannot forsee where one would like to insert multiple topics into the same forum. Different forums I can understand but there is no way to optimize that _at all_. More work to come...
git-svn-id: file:///svn/phpbb/trunk@8625 89ea8834-ac86-4346-8a33-228a782c2dd0
This commit is contained in:
parent
1aa40171e0
commit
fc126eec66
@ -8,7 +8,6 @@ include(PHPBB_ROOT_PATH . 'common.' . PHP_EXT);
|
||||
|
||||
class posting_api
|
||||
{
|
||||
// ideas on global topics? I am stuck here :'-(
|
||||
/*
|
||||
topic table:
|
||||
topic_id
|
||||
@ -380,235 +379,94 @@ class posting_api
|
||||
}
|
||||
|
||||
static function delete_topic($data)
|
||||
{
|
||||
// just call the more powerful variant with just one topic :)
|
||||
self::delete_topics(array('topic_ids' => array($data['topic_id'])));
|
||||
}
|
||||
|
||||
static function delete_topics($data)
|
||||
{
|
||||
global $db;
|
||||
|
||||
// lets get this party started
|
||||
$db->sql_transaction('begin');
|
||||
|
||||
$topic_id = (int) $data['topic_id'];
|
||||
$topic_ids = array_map('intval', $data['topic_ids']);
|
||||
|
||||
// what kind of topic is this? lets find out how much we must tamper with the forum table...
|
||||
$sql = 'SELECT topic_posts, topic_shadow_posts, topic_deleted_posts, topic_unapproved_posts, topic_shadow_id, forum_id
|
||||
// TODO: investigate how aggregate functions can speed this up/reduce the number of results returned/misc. other benefits
|
||||
$sql = 'SELECT topic_posts, topic_shadow_posts, topic_deleted_posts, topic_unapproved_posts, topic_shadow_id, forum_id, topic_status
|
||||
FROM ' . TOPICS_TABLE . '
|
||||
WHERE topic_id = ' . $topic_id;
|
||||
WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
|
||||
$result = $db->sql_query($sql);
|
||||
$topic_row = $db->sql_fetchrow($result);
|
||||
// the following in an array, key'd by forum id that refers to topic rows
|
||||
$forum_lookup = array();
|
||||
while ($topic_row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$forum_id = (int) $topic_row['forum_id'];
|
||||
|
||||
// deal with posts
|
||||
$forum_lookup[$forum_id]['forum_posts'] += $topic_row['topic_posts'];
|
||||
$forum_lookup[$forum_id]['forum_shadow_posts'] += $topic_row['topic_shadow_posts'];
|
||||
$forum_lookup[$forum_id]['forum_deleted_posts'] += $topic_row['topic_deleted_posts'];
|
||||
$forum_lookup[$forum_id]['forum_unapproved_posts'] += $topic_row['topic_unapproved_posts'];
|
||||
|
||||
// deal with topics
|
||||
$topic_status = (int) $topic_row['topic_status'];
|
||||
$forum_lookup[$forum_id]['forum_topics']++; // a topic is a topic
|
||||
$forum_lookup[$forum_id]['forum_shadow_topics'] += ($topic_row['topic_shadow_id'] != 0);
|
||||
$forum_lookup[$forum_id]['forum_deleted_topics'] += ($topic_status & self::DELETED);
|
||||
$forum_lookup[$forum_id]['forum_unapproved_topics'] += ($topic_status & self::UNAPPROVED);
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
// goodnight topic
|
||||
$db->sql_query('DELETE FROM ' . TOPICS_TABLE . ' WHERE topic_id = ' . $topic_id);
|
||||
// goodnight, topics
|
||||
$db->sql_query('DELETE FROM ' . TOPICS_TABLE . ' WHERE ' . $db->sql_in_set('topic_id', $topic_ids));
|
||||
|
||||
// goodnight post
|
||||
$db->sql_query('DELETE FROM ' . POSTS_TABLE . ' WHERE topic_id = ' . $topic_id);
|
||||
// goodnight, posts
|
||||
$db->sql_query('DELETE FROM ' . POSTS_TABLE . ' WHERE ' . $db->sql_in_set('topic_id', $topic_ids));
|
||||
|
||||
$forum_id = (int) $topic_row['forum_id'];
|
||||
$forum_ids = array_keys($forum_lookup);
|
||||
|
||||
// what kind of topic is this? lets find out how much we must tamper with the forum table...
|
||||
$sql = 'SELECT forum_posts, forum_shadow_posts, forum_deleted_posts, forum_unapproved_posts
|
||||
$sql = 'SELECT forum_posts, forum_shadow_posts, forum_deleted_posts, forum_unapproved_posts, forum_id
|
||||
FROM ' . FORUMS_TABLE . '
|
||||
WHERE forum_id = ' . $forum_id;
|
||||
WHERE ' . $db->sql_in_set('forum_id', $forum_ids);
|
||||
$result = $db->sql_query($sql);
|
||||
$forum_row = $db->sql_fetchrow($result);
|
||||
|
||||
$forum_array = array(
|
||||
'forum_posts' => max($forum_row['forum_posts'] - $topic_id['forum_posts'], 0),
|
||||
'forum_shadow_posts' => max($forum_row['forum_shadow_posts'] - $topic_id['forum_shadow_posts'], 0),
|
||||
'forum_deleted_posts' => max($forum_row['forum_deleted_posts'] - $topic_id['forum_deleted_posts'], 0),
|
||||
'forum_unapproved_posts' => max($forum_row['forum_unapproved_posts'] - $topic_id['forum_unapproved_posts'], 0),
|
||||
|
||||
'forum_topics' => max($forum_row['forum_topics'] - 1, 0),
|
||||
'forum_shadow_topics' => max($forum_row['forum_shadow_topics'] - (($topic_type == self::SHADOW) ? 1 : 0), 0),
|
||||
'forum_deleted_topics' => max($forum_row['forum_deleted_topics'] - (($topic_status == self::DELETED) ? 1 : 0), 0),
|
||||
'forum_unapproved_topics' => max($forum_row['forum_unapproved_topics'] - (($topic_row['topic_shadow_id'] != 0) ? 1 : 0), 0),
|
||||
);
|
||||
|
||||
// get the last "normal" post in the forum, we _must_ update it
|
||||
$sql = 'SELECT MAX(post_id) as max_post_id
|
||||
FROM ' . POSTS_TABLE . '
|
||||
WHERE post_status = ' . self::NORMAL . '
|
||||
AND forum_id = ' . $forum_id;
|
||||
$result = $db->sql_query($sql);
|
||||
$row = $db->sql_fetchrow($result);
|
||||
$forum_rows = array();
|
||||
while ($forum_row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$forum_id = (int) $forum_row['forum_id'];
|
||||
$forum_rows[$forum_id] = $forum_row;
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
// anything left?
|
||||
if ($row)
|
||||
$shadow_topic_ids = array();
|
||||
foreach ($forum_rows as $forum_id => $forum_row)
|
||||
{
|
||||
// OK, lets go do some magick
|
||||
$sql = 'SELECT post_username, poster_id, post_subject, post_time
|
||||
FROM '. POSTS_TABLE . '
|
||||
WHERE post_id = ' . (int) $row['max_post_id'];
|
||||
$result = $db->sql_query($sql);
|
||||
$last_post = $db->sql_fetchrow($result);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$forum_array['forum_last_user_id'] = (int) $last_post['poster_id'];
|
||||
$forum_array['forum_last_poster_name'] = $last_post['post_username'];
|
||||
$forum_array['forum_last_post_title'] = $last_post['post_subject'];
|
||||
$forum_array['forum_last_post_time'] = (int) $last_post['post_time'];
|
||||
}
|
||||
else
|
||||
{
|
||||
// reset forum state
|
||||
$forum_array['forum_last_user_id'] = 0;
|
||||
$forum_array['forum_last_poster_name'] = '';
|
||||
$forum_array['forum_last_post_title'] = '';
|
||||
$forum_array['forum_last_post_time'] = 0;
|
||||
}
|
||||
|
||||
$db->sql_handle_data('UPDATE', FORUMS_TABLE, $forum_data, "forum_id = $forum_id");
|
||||
|
||||
// lastly, kill off all the unbelievers... erm, I mean shadow topics...
|
||||
$sql = 'SELECT topic_id, forum_id
|
||||
FROM ' . TOPICS_TABLE . '
|
||||
WHERE topic_shadow_id = ' . $topic_id;
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$data['topic_id'] = (int) $topic_id;
|
||||
self::delete_topic($data);
|
||||
}
|
||||
|
||||
// goodnight, moon
|
||||
$db->transaction('COMMIT');
|
||||
}
|
||||
|
||||
static function move_topic($data)
|
||||
{
|
||||
global $db;
|
||||
|
||||
// lets get this party started
|
||||
$db->transaction('BEGIN');
|
||||
|
||||
$topic_id = (int) $data['topic_id'];
|
||||
$to_forum_id = (int) $data['forum_id'];
|
||||
$make_shadow = (bool) $data['make_shadow'];
|
||||
|
||||
// let us first determine how many items we are removing from the pool
|
||||
$sql = 'SELECT topic_posts, topic_shadow_posts, topic_deleted_posts, topic_unapproved_posts, forum_id as from_forum_id, topic_status, topic_type, topic_shadow_id
|
||||
FROM ' . TOPICS_TABLE . '
|
||||
WHERE topic_id = ' . $topic_id;
|
||||
$result = $db->sql_query($sql);
|
||||
$row = $db->sql_fetchrow($result);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$topic_status = (int) $row['topic_status'];
|
||||
$topic_type = (int) $row['topic_type'];
|
||||
$from_forum_id = (int) $row['from_forum_id'];
|
||||
|
||||
$topic_row['topic_posts'] = (int) $row['topic_posts'];
|
||||
$topic_row['topic_shadow_posts'] = (int) $row['topic_shadow_posts'];
|
||||
$topic_row['topic_deleted_posts'] = (int) $row['topic_deleted_posts'];
|
||||
$topic_row['topic_unapproved_posts'] = (int) $row['topic_unapproved_posts'];
|
||||
|
||||
// let us first determine how many items we are removing from the pool
|
||||
$sql = 'SELECT forum_posts, forum_shadow_posts, forum_deleted_posts, forum_unapproved_posts, forum_id, forum_topics, forum_deleted_topics, forum_unapproved_topics
|
||||
FROM ' . FORUMS_TABLE . '
|
||||
WHERE ' . $db->sql_in_set('forum_id', array($to_forum_id, $from_forum_id));
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
$forum_row = array();
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$forum_id = (int) $row['forum_id'];
|
||||
|
||||
$forum_row[$forum_id]['forum_posts'] = (int) $row['forum_posts'];
|
||||
$forum_row[$forum_id]['forum_shadow_posts'] = (int) $row['forum_shadow_posts'];
|
||||
$forum_row[$forum_id]['forum_deleted_posts'] = (int) $row['forum_deleted_posts'];
|
||||
$forum_row[$forum_id]['forum_unapproved_posts'] = (int) $row['forum_unapproved_posts'];
|
||||
|
||||
$forum_row[$forum_id]['forum_topics'] = (int) $row['forum_topics'];
|
||||
$forum_row[$forum_id]['forum_shadow_topics'] = (int) $row['forum_shadow_topics'];
|
||||
$forum_row[$forum_id]['forum_deleted_topics'] = (int) $row['forum_deleted_topics'];
|
||||
$forum_row[$forum_id]['forum_unapproved_topics'] = (int) $row['forum_unapproved_topics'];
|
||||
}
|
||||
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
// update the topic itself
|
||||
$db->sql_handle_data('UPDATE', TOPICS_TABLE, array('forum_id' => $to_forum_id), "topic_id = $topic_id");
|
||||
|
||||
// update the posts now
|
||||
$db->sql_handle_data('UPDATE', POSTS_TABLE, array('forum_id' => $to_forum_id), "topic_id = $topic_id");
|
||||
|
||||
// remove the numbers from the old forum row
|
||||
$from_forum_array = array(
|
||||
'forum_posts' => max($forum_row[$from_forum_id]['forum_posts'] - $topic_row['forum_posts'], 0),
|
||||
'forum_shadow_posts' => max($forum_row[$from_forum_id]['forum_shadow_posts'] - $topic_row['forum_shadow_posts'], 0),
|
||||
'forum_deleted_posts' => max($forum_row[$from_forum_id]['forum_deleted_posts'] - $topic_row['forum_deleted_posts'], 0),
|
||||
'forum_unapproved_posts' => max($forum_row[$from_forum_id]['forum_unapproved_posts'] - $topic_row['forum_unapproved_posts'], 0),
|
||||
|
||||
'forum_topics' => max($forum_row[$from_forum_id]['forum_topics'] - 1, 0),
|
||||
'forum_shadow_topics' => max($forum_row[$from_forum_id]['forum_shadow_topics'] - (($topic_row['topic_shadow_id'] != 0) ? 1 : 0), 0),
|
||||
'forum_deleted_topics' => max($forum_row[$from_forum_id]['forum_deleted_topics'] - (($topic_status == self::DELETED) ? 1 : 0), 0),
|
||||
'forum_unapproved_topics' => max($forum_row[$from_forum_id]['forum_unapproved_topics'] - (($topic_status == self::UNAPPROVED) ? 1 : 0), 0),
|
||||
);
|
||||
|
||||
// get the last "normal" post in the old forum, we _must_ update it
|
||||
$sql = 'SELECT MAX(post_id) as max_post_id
|
||||
FROM ' . POSTS_TABLE . '
|
||||
WHERE post_status = ' . self::NORMAL . '
|
||||
AND forum_id = ' . $from_forum_id;
|
||||
$result = $db->sql_query($sql);
|
||||
$row = $db->sql_fetchrow($result);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
// anything left?
|
||||
if ($row)
|
||||
{
|
||||
// OK, lets go do some magick
|
||||
$sql = 'SELECT post_username, poster_id, post_subject, post_time
|
||||
FROM '. POSTS_TABLE . '
|
||||
WHERE post_id = ' . (int) $row['max_post_id'];
|
||||
$result = $db->sql_query($sql);
|
||||
$last_post = $db->sql_fetchrow($result);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$from_forum_array['forum_last_user_id'] = (int) $last_post['poster_id'];
|
||||
$from_forum_array['forum_last_poster_name'] = $last_post['post_username'];
|
||||
$from_forum_array['forum_last_post_title'] = $last_post['post_subject'];
|
||||
$from_forum_array['forum_last_post_time'] = (int) $last_post['post_time'];
|
||||
}
|
||||
else
|
||||
{
|
||||
// reset forum state
|
||||
$from_forum_array['forum_last_user_id'] = 0;
|
||||
$from_forum_array['forum_last_poster_name'] = '';
|
||||
$from_forum_array['forum_last_post_title'] = '';
|
||||
$from_forum_array['forum_last_post_time'] = 0;
|
||||
}
|
||||
|
||||
// update the old forum
|
||||
$db->sql_handle_data('UPDATE', FORUMS_TABLE, $from_forum_array, "forum_id = $from_forum_id");
|
||||
|
||||
// add the numbers to the new forum row
|
||||
$to_forum_array = array(
|
||||
'forum_posts' => $forum_row[$to_forum_id]['forum_posts'] + $topic_row['forum_posts'],
|
||||
'forum_shadow_posts' => $forum_row[$to_forum_id]['forum_shadow_posts'] + $topic_row['forum_shadow_posts'],
|
||||
'forum_deleted_posts' => $forum_row[$to_forum_id]['forum_deleted_posts'] + $topic_row['forum_deleted_posts'],
|
||||
'forum_unapproved_posts'=> $forum_row[$to_forum_id]['forum_unapproved_posts'] + $topic_row['forum_unapproved_posts'],
|
||||
|
||||
'forum_topics' => $forum_row[$from_forum_id]['forum_topics'] + 1,
|
||||
'forum_shadow_topics' => $forum_row[$from_forum_id]['forum_shadow_topics'] + (($topic_row['topic_shadow_id'] != 0) ? 1 : 0),
|
||||
'forum_deleted_topics' => $forum_row[$from_forum_id]['forum_deleted_topics'] + (($topic_status === self::DELETED) ? 1 : 0),
|
||||
'forum_unapproved_topics' => $forum_row[$from_forum_id]['forum_unapproved_topics'] + (($topic_status === self::UNAPPROVED) ? 1 : 0),
|
||||
);
|
||||
|
||||
// the new topic is approved and is not soft deleted and is not unapproved, go and sync some status
|
||||
if ($topic_status === self::NORMAL)
|
||||
{
|
||||
// get the lastest "normal" post in the new forum, we _must_ update it
|
||||
$topic_row = $forum_lookup[$forum_id];
|
||||
$forum_array = array(
|
||||
'forum_posts' => max($forum_row['forum_posts'] - $topic_row['forum_posts'], 0),
|
||||
'forum_shadow_posts' => max($forum_row['forum_shadow_posts'] - $topic_row['forum_shadow_posts'], 0),
|
||||
'forum_deleted_posts' => max($forum_row['forum_deleted_posts'] - $topic_row['forum_deleted_posts'], 0),
|
||||
'forum_unapproved_posts' => max($forum_row['forum_unapproved_posts'] - $topic_row['forum_unapproved_posts'], 0),
|
||||
|
||||
'forum_topics' => max($forum_row['forum_topics'] - $topic_row['forum_topics'], 0),
|
||||
'forum_shadow_topics' => max($forum_row['forum_shadow_topics'] - $topic_row['forum_shadow_topics'], 0),
|
||||
'forum_deleted_topics' => max($forum_row['forum_deleted_topics'] - $topic_row['forum_deleted_topics'], 0),
|
||||
'forum_unapproved_topics' => max($forum_row['forum_unapproved_topics'] - $topic_row['forum_unapproved_topics'], 0),
|
||||
);
|
||||
|
||||
// get the last "normal" post in the forum, we _must_ update it
|
||||
$sql = 'SELECT MAX(post_id) as max_post_id
|
||||
FROM ' . POSTS_TABLE . '
|
||||
WHERE post_status = ' . self::NORMAL . '
|
||||
AND forum_id = ' . $to_forum_id;
|
||||
AND forum_id = ' . $forum_id;
|
||||
$result = $db->sql_query($sql);
|
||||
$row = $db->sql_fetchrow($result);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
// we better find something... after all, we just moved a topic here!
|
||||
// anything left?
|
||||
if ($row)
|
||||
{
|
||||
// OK, lets go do some magick
|
||||
@ -619,17 +477,382 @@ class posting_api
|
||||
$last_post = $db->sql_fetchrow($result);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$from_forum_array['forum_last_user_id'] = (int) $last_post['poster_id'];
|
||||
$from_forum_array['forum_last_poster_name'] = $last_post['post_username'];
|
||||
$from_forum_array['forum_last_post_title'] = $last_post['post_subject'];
|
||||
$from_forum_array['forum_last_post_time'] = (int) $last_post['post_time'];
|
||||
$forum_array['forum_last_user_id'] = (int) $last_post['poster_id'];
|
||||
$forum_array['forum_last_poster_name'] = $last_post['post_username'];
|
||||
$forum_array['forum_last_post_title'] = $last_post['post_subject'];
|
||||
$forum_array['forum_last_post_time'] = (int) $last_post['post_time'];
|
||||
}
|
||||
else
|
||||
{
|
||||
// reset forum state
|
||||
$forum_array['forum_last_user_id'] = 0;
|
||||
$forum_array['forum_last_poster_name'] = '';
|
||||
$forum_array['forum_last_post_title'] = '';
|
||||
$forum_array['forum_last_post_time'] = 0;
|
||||
}
|
||||
|
||||
$db->sql_handle_data('UPDATE', FORUMS_TABLE, $forum_data, "forum_id = $forum_id");
|
||||
}
|
||||
|
||||
// let's not get too hasty, we can kill off the shadows later,
|
||||
// instead we compose a list of all shadows and then efficiently kill them off :)
|
||||
$sql = 'SELECT topic_id
|
||||
FROM ' . TOPICS_TABLE . '
|
||||
WHERE ' . $db->sql_in_set('topic_shadow_id', $topic_ids);
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$shadow_topic_ids[] = $row['topic_id'];
|
||||
}
|
||||
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
// recursion, the other white meat.
|
||||
if (sizeof($shadow_topic_ids))
|
||||
{
|
||||
self::delete_topics(array('topic_ids' => $shadow_topic_ids));
|
||||
}
|
||||
|
||||
// goodnight, moon
|
||||
$db->transaction('commit');
|
||||
}
|
||||
|
||||
static function delete_post($data)
|
||||
{
|
||||
// just call the more powerful variant with just one post :)
|
||||
self::delete_posts(array('post_ids' => array($data['post_id'])));
|
||||
}
|
||||
|
||||
static function delete_posts($data)
|
||||
{
|
||||
global $db;
|
||||
|
||||
// lets get this party started
|
||||
$db->sql_transaction('begin');
|
||||
|
||||
$post_ids = array_map('intval', $data['post_ids']);
|
||||
|
||||
$sql = 'SELECT topic_id, post_status, post_id, post_shadow_id, forum_id
|
||||
FROM ' . POSTS_TABLE . '
|
||||
WHERE ' . $db->sql_in_set('post_id', $post_ids);
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
// the following arrays are designed to allow for much faster updates
|
||||
$topic_lookup = array();
|
||||
$forum_lookup = array();
|
||||
|
||||
while ($post_row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$topic_id = (int) $post_row['topic_id'];
|
||||
$forum_id = (int) $post_row['forum_id'];
|
||||
$post_status = (int) $post_row['post_status'];
|
||||
|
||||
$topic_lookup[$topic_id]['topic_posts']++; // we remove a post, go figure
|
||||
$topic_lookup[$topic_id]['topic_shadow_posts'] += ($post_row['post_shadow_id'] != 0); // did we just try to kill a shadow post?!
|
||||
$topic_lookup[$topic_id]['topic_deleted_posts'] += ($post_status & self::DELETED);
|
||||
$topic_lookup[$topic_id]['topic_unapproved_posts'] += ($post_status & self::UNAPPROVED);
|
||||
|
||||
$forum_lookup[$forum_id]['forum_posts']++;
|
||||
$forum_lookup[$topic_id]['forum_shadow_posts'] += ($post_row['post_shadow_id'] != 0); // did we just try to kill a shadow post?!
|
||||
$forum_lookup[$topic_id]['forum_deleted_posts'] += ($post_status & self::DELETED);
|
||||
$forum_lookup[$topic_id]['forum_unapproved_posts'] += ($post_status & self::UNAPPROVED);
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
// goodnight, posts
|
||||
$db->sql_query('DELETE FROM ' . POSTS_TABLE . ' WHERE ' . $db->sql_in_set('topic_id', $topic_ids));
|
||||
|
||||
// mangle the forums table
|
||||
$sql = 'SELECT forum_posts, forum_shadow_posts, forum_deleted_posts, forum_unapproved_posts, forum_id
|
||||
FROM ' . FORUMS_TABLE . '
|
||||
WHERE forum_id = ' . $forum_id;
|
||||
$result = $db->sql_query($sql);
|
||||
$forum_rows = array();
|
||||
while ($forum_row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$forum_id = (int) $forum_row['forum_id'];
|
||||
$forum_rows[$forum_id] = $forum_row;
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$shadow_topic_ids = array();
|
||||
foreach ($forum_rows as $forum_id => $forum_row)
|
||||
{
|
||||
$topic_row = $forum_lookup[$forum_id];
|
||||
$forum_array = array(
|
||||
'forum_posts' => max($forum_row['forum_posts'] - $topic_row['forum_posts'], 0),
|
||||
'forum_shadow_posts' => max($forum_row['forum_shadow_posts'] - $topic_row['forum_shadow_posts'], 0),
|
||||
'forum_deleted_posts' => max($forum_row['forum_deleted_posts'] - $topic_row['forum_deleted_posts'], 0),
|
||||
'forum_unapproved_posts' => max($forum_row['forum_unapproved_posts'] - $topic_row['forum_unapproved_posts'], 0),
|
||||
);
|
||||
|
||||
// get the last "normal" post in the forum, we _must_ update it
|
||||
$sql = 'SELECT MAX(post_id) as max_post_id
|
||||
FROM ' . POSTS_TABLE . '
|
||||
WHERE post_status = ' . self::NORMAL . '
|
||||
AND forum_id = ' . $forum_id;
|
||||
$result = $db->sql_query($sql);
|
||||
$row = $db->sql_fetchrow($result);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
// anything left?
|
||||
if ($row)
|
||||
{
|
||||
// OK, lets go do some magick
|
||||
$sql = 'SELECT post_username, poster_id, post_subject, post_time
|
||||
FROM '. POSTS_TABLE . '
|
||||
WHERE post_id = ' . (int) $row['max_post_id'];
|
||||
$result = $db->sql_query($sql);
|
||||
$last_post = $db->sql_fetchrow($result);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$forum_array['forum_last_user_id'] = (int) $last_post['poster_id'];
|
||||
$forum_array['forum_last_poster_name'] = $last_post['post_username'];
|
||||
$forum_array['forum_last_post_title'] = $last_post['post_subject'];
|
||||
$forum_array['forum_last_post_time'] = (int) $last_post['post_time'];
|
||||
}
|
||||
else
|
||||
{
|
||||
// reset forum state
|
||||
$forum_array['forum_last_user_id'] = 0;
|
||||
$forum_array['forum_last_poster_name'] = '';
|
||||
$forum_array['forum_last_post_title'] = '';
|
||||
$forum_array['forum_last_post_time'] = 0;
|
||||
}
|
||||
|
||||
$db->sql_handle_data('UPDATE', FORUMS_TABLE, $forum_data, "forum_id = $forum_id");
|
||||
}
|
||||
|
||||
// mangle the topics table now :)
|
||||
$sql = 'SELECT topic_posts, topic_shadow_posts, topic_deleted_posts, topic_unapproved_posts, topic_id
|
||||
FROM ' . TOPICS_TABLE . '
|
||||
WHERE forum_id = ' . $forum_id;
|
||||
$result = $db->sql_query($sql);
|
||||
$topic_rows = array();
|
||||
while ($topic_row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$topic_id = (int) $topic_row['topic_id'];
|
||||
$topic_rows[$topic_id] = $topic_row;
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$empty_topic_ids = array();
|
||||
|
||||
foreach ($topic_rows as $topic_id => $topic_row)
|
||||
{
|
||||
$post_row = $topic_lookup[$topic_id];
|
||||
$topic_array = array(
|
||||
'topic_posts' => max($topic_row['topic_posts'] - $post_row['topic_posts'], 0),
|
||||
'topic_shadow_posts' => max($topic_row['topic_shadow_posts'] - $post_row['topic_shadow_posts'], 0),
|
||||
'topic_deleted_posts' => max($topic_row['topic_deleted_posts'] - $post_row['topic_deleted_posts'], 0),
|
||||
'topic_unapproved_posts' => max($topic_row['topic_unapproved_posts'] - $post_row['topic_unapproved_posts'], 0),
|
||||
);
|
||||
|
||||
// get the last "normal" post in the topic, we _must_ update it
|
||||
$sql = 'SELECT MAX(post_id) as max_post_id
|
||||
FROM ' . POSTS_TABLE . '
|
||||
WHERE post_status = ' . self::NORMAL . '
|
||||
AND topic_id = ' . $topic_id;
|
||||
$result = $db->sql_query($sql);
|
||||
$row = $db->sql_fetchrow($result);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
// anything left?
|
||||
if ($row)
|
||||
{
|
||||
// OK, lets go do some magick
|
||||
$sql = 'SELECT post_username, poster_id, post_subject, post_time
|
||||
FROM '. POSTS_TABLE . '
|
||||
WHERE post_id = ' . (int) $row['max_post_id'];
|
||||
$result = $db->sql_query($sql);
|
||||
$last_post = $db->sql_fetchrow($result);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$topic_array['topic_last_user_id'] = (int) $last_post['poster_id'];
|
||||
$topic_array['topic_last_poster_name'] = $last_post['post_username'];
|
||||
$topic_array['topic_last_post_title'] = $last_post['post_subject'];
|
||||
$topic_array['topic_last_post_time'] = (int) $last_post['post_time'];
|
||||
}
|
||||
else
|
||||
{
|
||||
// mark this post for execution!
|
||||
$empty_topic_ids[] = $topic_id;
|
||||
}
|
||||
|
||||
$db->sql_handle_data('UPDATE', TOPICS_TABLE, $topic_array, "topic_id = $topic_id");
|
||||
}
|
||||
|
||||
$shadow_post_ids = array();
|
||||
|
||||
// let's not get too hasty, we can kill off the shadows later,
|
||||
// instead we compose a list of all shadows and then efficiently kill them off :)
|
||||
$sql = 'SELECT post_id
|
||||
FROM ' . POSTS_TABLE . '
|
||||
WHERE ' . $db->sql_in_set('post_shadow_id', $topic_ids);
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$shadow_post_ids[] = $row['post_id'];
|
||||
}
|
||||
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
// recursion, the other white meat.
|
||||
if (sizeof($shadow_topic_ids))
|
||||
{
|
||||
self::delete_posts(array('post_ids' => $shadow_post_ids));
|
||||
}
|
||||
|
||||
// we killed all the posts in a topic, time to kill the topics!
|
||||
if (sizeof($empty_topics))
|
||||
{
|
||||
self::delete_topics(array('topic_ids' => $empty_topic_ids));
|
||||
}
|
||||
|
||||
// goodnight, moon
|
||||
$db->transaction('commit');
|
||||
}
|
||||
|
||||
static function move_topic($data)
|
||||
{
|
||||
self::move_topics(array('topic_forum_mapping' => array(array('topic_id' => $data['topic_id'], 'forum_id' => $data['forum_id'], 'make_shadow' => $data['make_shadow']))));
|
||||
}
|
||||
|
||||
static function move_topics($data)
|
||||
{
|
||||
global $db;
|
||||
|
||||
// lets get this party started
|
||||
$db->transaction('begin');
|
||||
|
||||
// all of each are indexed by topic id
|
||||
$to_forum_ids = $shadow_topic_ids = array();
|
||||
|
||||
foreach ($data['topic_forum_mapping'] as $mapping)
|
||||
{
|
||||
$topic_id = (int) $mapping['topic_id'];
|
||||
$to_forum_ids[$topic_id] = (int) $mapping['forum_id'];
|
||||
if ($mapping['make_shadow'])
|
||||
{
|
||||
$shadow_topic_ids[] = $topic_id;
|
||||
}
|
||||
}
|
||||
|
||||
// update the new forum
|
||||
$db->sql_handle_data('UPDATE', FORUMS_TABLE, $to_forum_array, "forum_id = $to_forum_id");
|
||||
$forum_columns = array('forum_posts', 'forum_shadow_posts', 'forum_deleted_posts', 'forum_unapproved_posts', 'forum_topics', 'forum_shadow_topics', 'forum_deleted_topics', 'forum_unapproved_topics');
|
||||
|
||||
if ($make_shadow === true)
|
||||
$topic_ids = array_keys($to_forum_ids);
|
||||
|
||||
// let us first determine how many items we are removing from the pool
|
||||
$sql = 'SELECT topic_posts, topic_shadow_posts, topic_deleted_posts, topic_unapproved_posts, forum_id, topic_status, topic_type, topic_shadow_id, topic_id
|
||||
FROM ' . TOPICS_TABLE . '
|
||||
WHERE ' . $db->sql_in_set('topic_id', $topic_ids);
|
||||
$result = $db->sql_query($sql);
|
||||
$forum_lookup = array();
|
||||
while ($topic_row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$topic_id = $topic_row['topic_id'];
|
||||
$from_forum_id = (int) $topic_row['forum_id'];
|
||||
$topic_status = (int) $topic_row['topic_status'];
|
||||
|
||||
$from_forum_ids[$topic_id] = $from_forum_id;
|
||||
|
||||
$to_forum_id = $to_forum_ids[$topic_id];
|
||||
|
||||
// we are iterating one topic at a time...
|
||||
$forum_lookup[$from_forum_id]['forum_topics'] = $forum_lookup[$to_forum_id]['forum_topics'] = 1;
|
||||
|
||||
foreach ($forum_columns as $column)
|
||||
{
|
||||
$forum_lookup[$from_forum_id][$column] -= $topic_row['topic_posts'];
|
||||
$forum_lookup[$to_forum_id][$column] += $topic_row['topic_posts'];
|
||||
}
|
||||
}
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
// determine the totals
|
||||
$sql = 'SELECT forum_posts, forum_shadow_posts, forum_deleted_posts, forum_unapproved_posts, forum_id, forum_topics, forum_deleted_topics, forum_unapproved_topics
|
||||
FROM ' . FORUMS_TABLE . '
|
||||
WHERE ' . $db->sql_in_set('forum_id', array_keys($forum_lookup));
|
||||
$result = $db->sql_query($sql);
|
||||
|
||||
while ($row = $db->sql_fetchrow($result))
|
||||
{
|
||||
$forum_id = (int) $row['forum_id'];
|
||||
|
||||
foreach ($forum_columns as $column)
|
||||
{
|
||||
$forum_lookup[$forum_id][$column] += (int) $row[$column];
|
||||
}
|
||||
}
|
||||
|
||||
// create a listing of which topics are going in which forums
|
||||
$update_list = array();
|
||||
|
||||
foreach ($to_forum_ids as $topic_id => $forum_id)
|
||||
{
|
||||
$update_list[$forum_id][] = $topic_id;
|
||||
}
|
||||
|
||||
// we save as many queries as we can by updating all similar topics at once
|
||||
foreach ($update_list as $forum_id => $topic_ids)
|
||||
{
|
||||
// update the topic itself
|
||||
$db->sql_handle_data('UPDATE', TOPICS_TABLE, array('forum_id' => $to_forum_id), $db->sql_in_set('topic_id', $topic_ids));
|
||||
|
||||
// update the posts now
|
||||
$db->sql_handle_data('UPDATE', POSTS_TABLE, array('forum_id' => $to_forum_id), $db->sql_in_set('topic_id', $topic_ids));
|
||||
}
|
||||
|
||||
// start building the needed arrays for updating the forum data
|
||||
foreach ($forum_lookup as $forum_id => $forum_data)
|
||||
{
|
||||
foreach ($forum_columns as $column)
|
||||
{
|
||||
$forum_data[$column] = max($forum_data[$column], 0); // ensure the result is unsigned
|
||||
}
|
||||
|
||||
// get the last "normal" post in the old forum, we _must_ update it
|
||||
$sql = 'SELECT MAX(post_id) as max_post_id
|
||||
FROM ' . POSTS_TABLE . '
|
||||
WHERE post_status = ' . self::NORMAL . '
|
||||
AND forum_id = ' . $forum_id;
|
||||
$result = $db->sql_query($sql);
|
||||
$row = $db->sql_fetchrow($result);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
// anything left?
|
||||
if ($row)
|
||||
{
|
||||
// OK, lets go do some magick
|
||||
$sql = 'SELECT post_username, poster_id, post_subject, post_time
|
||||
FROM '. POSTS_TABLE . '
|
||||
WHERE post_id = ' . (int) $row['max_post_id'];
|
||||
$result = $db->sql_query($sql);
|
||||
$last_post = $db->sql_fetchrow($result);
|
||||
$db->sql_freeresult($result);
|
||||
|
||||
$forum_data['forum_last_user_id'] = (int) $last_post['poster_id'];
|
||||
$forum_data['forum_last_poster_name'] = $last_post['post_username'];
|
||||
$forum_data['forum_last_post_title'] = $last_post['post_subject'];
|
||||
$forum_data['forum_last_post_time'] = (int) $last_post['post_time'];
|
||||
}
|
||||
else
|
||||
{
|
||||
// reset forum state
|
||||
$forum_data['forum_last_user_id'] = 0;
|
||||
$forum_data['forum_last_poster_name'] = '';
|
||||
$forum_data['forum_last_post_title'] = '';
|
||||
$forum_data['forum_last_post_time'] = 0;
|
||||
}
|
||||
|
||||
// update the old forum
|
||||
$db->sql_handle_data('UPDATE', FORUMS_TABLE, $forum_data, "forum_id = $forum_id");
|
||||
}
|
||||
|
||||
// hooray for code reuse!
|
||||
foreach ($shadow_topic_ids as $topic_id)
|
||||
{
|
||||
$data['shadow_topic_id'] = $topic_id;
|
||||
$data['forum_id'] = $from_forum_id;
|
||||
@ -637,6 +860,7 @@ class posting_api
|
||||
}
|
||||
|
||||
$db->sql_transaction('commit');
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user